summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.tarball-version1
-rw-r--r--AUTHORS14
-rw-r--r--CONTRIBUTING.md164
-rw-r--r--COPYING675
-rw-r--r--COPYING.ASL2050
-rw-r--r--COPYING.LESSER166
-rw-r--r--ChangeLog16389
-rw-r--r--INSTALL368
-rw-r--r--Makefile.am634
-rw-r--r--Makefile.in1375
-rw-r--r--NEWS1
-rw-r--r--README1
-rw-r--r--README.md188
-rw-r--r--aclocal.m45982
-rw-r--r--action.c2398
-rw-r--r--action.h116
-rw-r--r--compat/Makefile.am6
-rw-r--r--compat/Makefile.in775
-rw-r--r--compat/asprintf.c53
-rwxr-xr-xcompat/getifaddrs.c543
-rwxr-xr-xcompat/ifaddrs.h100
-rw-r--r--compat/solaris_elf_fix.c28
-rw-r--r--compat/strndup.c49
-rwxr-xr-xcompile348
-rwxr-xr-xconfig.guess1480
-rw-r--r--config.h.in683
-rwxr-xr-xconfig.sub1801
-rwxr-xr-xconfigure33739
-rw-r--r--configure.ac3097
-rw-r--r--contrib/README12
-rw-r--r--contrib/ffaup/Makefile.am8
-rw-r--r--contrib/ffaup/Makefile.in801
-rw-r--r--contrib/ffaup/ffaup.c395
-rw-r--r--contrib/fmhash/Makefile.am8
-rw-r--r--contrib/fmhash/Makefile.in801
-rw-r--r--contrib/fmhash/fmhash.c384
-rw-r--r--contrib/fmunflatten/Makefile.am5
-rw-r--r--contrib/fmunflatten/Makefile.in797
-rw-r--r--contrib/fmunflatten/fmunflatten.c243
-rw-r--r--contrib/gnutls/ca.pem15
-rw-r--r--contrib/gnutls/cert.pem16
-rw-r--r--contrib/gnutls/key.pem15
-rw-r--r--contrib/imbatchreport/Makefile.am6
-rw-r--r--contrib/imbatchreport/Makefile.in797
-rw-r--r--contrib/imbatchreport/imbatchreport.c1033
-rw-r--r--contrib/imczmq/Makefile.am8
-rw-r--r--contrib/imczmq/Makefile.in798
-rw-r--r--contrib/imczmq/README39
-rw-r--r--contrib/imczmq/imczmq.c632
-rw-r--r--contrib/imdocker/Makefile.am6
-rw-r--r--contrib/imdocker/Makefile.in797
-rw-r--r--contrib/imdocker/imdocker.c1794
-rw-r--r--contrib/imhiredis/COPYING674
-rw-r--r--contrib/imhiredis/Makefile.am7
-rw-r--r--contrib/imhiredis/Makefile.in799
-rw-r--r--contrib/imhiredis/README81
-rw-r--r--contrib/imhiredis/imhiredis.c2298
-rw-r--r--contrib/imhttp/Makefile.am5
-rw-r--r--contrib/imhttp/Makefile.in795
-rw-r--r--contrib/imhttp/imhttp.c1326
-rw-r--r--contrib/imkmsg/Makefile.am8
-rw-r--r--contrib/imkmsg/Makefile.in807
-rw-r--r--contrib/imkmsg/imkmsg.c372
-rw-r--r--contrib/imkmsg/imkmsg.h78
-rw-r--r--contrib/imkmsg/kmsg.c327
-rw-r--r--contrib/impcap/Makefile.am22
-rw-r--r--contrib/impcap/Makefile.in949
-rw-r--r--contrib/impcap/arp_parser.c163
-rw-r--r--contrib/impcap/dns_parser.c372
-rw-r--r--contrib/impcap/eth_parser.c179
-rw-r--r--contrib/impcap/ftp_parser.c152
-rw-r--r--contrib/impcap/http_parser.c159
-rw-r--r--contrib/impcap/icmp_parser.c79
-rw-r--r--contrib/impcap/impcap.c748
-rw-r--r--contrib/impcap/ipv4_parser.c101
-rw-r--r--contrib/impcap/ipv6_parser.c305
-rw-r--r--contrib/impcap/ipx_parser.c97
-rw-r--r--contrib/impcap/llc_parser.c109
-rw-r--r--contrib/impcap/parsers.h189
-rw-r--r--contrib/impcap/smb_parser.c145
-rw-r--r--contrib/impcap/tcp_parser.c121
-rw-r--r--contrib/impcap/udp_parser.c90
-rw-r--r--contrib/improg/Makefile.am11
-rw-r--r--contrib/improg/Makefile.in799
-rw-r--r--contrib/improg/improg.c722
-rw-r--r--contrib/imtuxedoulog/Makefile.am13
-rw-r--r--contrib/imtuxedoulog/Makefile.in799
-rw-r--r--contrib/imtuxedoulog/imtuxedoulog.c860
-rw-r--r--contrib/mmcount/Makefile.am8
-rw-r--r--contrib/mmcount/Makefile.in797
-rw-r--r--contrib/mmcount/mmcount.c351
-rw-r--r--contrib/mmdarwin/Makefile.am8
-rw-r--r--contrib/mmdarwin/Makefile.in797
-rw-r--r--contrib/mmdarwin/mmdarwin.c953
-rw-r--r--contrib/mmdarwin/protocol.h70
-rw-r--r--contrib/mmgrok/Makefile.am8
-rw-r--r--contrib/mmgrok/Makefile.in798
-rw-r--r--contrib/mmgrok/README32
-rw-r--r--contrib/mmgrok/mmgrok.c418
-rw-r--r--contrib/mmkubernetes/Makefile.am8
-rw-r--r--contrib/mmkubernetes/Makefile.in800
-rw-r--r--contrib/mmkubernetes/k8s_container_name.rulebase3
-rw-r--r--contrib/mmkubernetes/k8s_filename.rulebase2
-rw-r--r--contrib/mmkubernetes/mmkubernetes.c2085
-rw-r--r--contrib/mmrfc5424addhmac/Makefile.am8
-rw-r--r--contrib/mmrfc5424addhmac/Makefile.in801
-rw-r--r--contrib/mmrfc5424addhmac/mmrfc5424addhmac.c382
-rw-r--r--contrib/mmsequence/Makefile.am8
-rw-r--r--contrib/mmsequence/Makefile.in797
-rw-r--r--contrib/mmsequence/mmsequence.c406
-rw-r--r--contrib/mmtaghostname/Makefile.am8
-rw-r--r--contrib/mmtaghostname/Makefile.in798
-rw-r--r--contrib/mmtaghostname/mmtaghostname.c205
-rw-r--r--contrib/omamqp1/Makefile.am8
-rw-r--r--contrib/omamqp1/Makefile.in798
-rw-r--r--contrib/omamqp1/omamqp1.c921
-rw-r--r--contrib/omczmq/Makefile.am8
-rw-r--r--contrib/omczmq/Makefile.in798
-rw-r--r--contrib/omczmq/README79
-rw-r--r--contrib/omczmq/omczmq.c652
-rw-r--r--contrib/omfile-hardened/Makefile.am8
-rw-r--r--contrib/omfile-hardened/Makefile.in799
-rw-r--r--contrib/omfile-hardened/omfile-hardened.c1654
-rw-r--r--contrib/omhiredis/COPYING674
-rw-r--r--contrib/omhiredis/Makefile.am7
-rw-r--r--contrib/omhiredis/Makefile.in799
-rw-r--r--contrib/omhiredis/README70
-rw-r--r--contrib/omhiredis/omhiredis.c753
-rw-r--r--contrib/omhttp/Makefile.am8
-rw-r--r--contrib/omhttp/Makefile.in798
-rw-r--r--contrib/omhttp/omhttp.c2212
-rw-r--r--contrib/omhttpfs/Makefile.am9
-rw-r--r--contrib/omhttpfs/Makefile.in798
-rw-r--r--contrib/omhttpfs/omhttpfs.c855
-rw-r--r--contrib/omrabbitmq/Makefile.am8
-rw-r--r--contrib/omrabbitmq/Makefile.in798
-rw-r--r--contrib/omrabbitmq/omrabbitmq.c1381
-rw-r--r--contrib/omtcl/Makefile.am8
-rw-r--r--contrib/omtcl/Makefile.in798
-rw-r--r--contrib/omtcl/omtcl.c164
-rw-r--r--contrib/pmaixforwardedfrom/Makefile.am8
-rw-r--r--contrib/pmaixforwardedfrom/Makefile.in800
-rw-r--r--contrib/pmaixforwardedfrom/pmaixforwardedfrom.c185
-rw-r--r--contrib/pmcisconames/Makefile.am8
-rw-r--r--contrib/pmcisconames/Makefile.in798
-rw-r--r--contrib/pmcisconames/pmcisconames.c185
-rw-r--r--contrib/pmdb2diag/Makefile.am8
-rw-r--r--contrib/pmdb2diag/Makefile.in797
-rw-r--r--contrib/pmdb2diag/pmdb2diag.c305
-rw-r--r--contrib/pmpanngfw/Makefile.am8
-rw-r--r--contrib/pmpanngfw/Makefile.in797
-rw-r--r--contrib/pmpanngfw/pmpanngfw.c296
-rw-r--r--contrib/pmsnare/Makefile.am8
-rw-r--r--contrib/pmsnare/Makefile.in797
-rw-r--r--contrib/pmsnare/pmsnare.c444
-rwxr-xr-xdepcomp791
-rwxr-xr-xdevtools/prep-mysql-db.sh5
-rwxr-xr-xdevtools/prepare_clickhouse.sh13
-rw-r--r--dirty.h49
-rw-r--r--grammar/Makefile.am20
-rw-r--r--grammar/Makefile.in810
-rw-r--r--grammar/grammar.c2342
-rw-r--r--grammar/grammar.h186
-rw-r--r--grammar/grammar.y243
-rw-r--r--grammar/lexer.c4150
-rw-r--r--grammar/lexer.l590
-rw-r--r--grammar/parserif.h44
-rw-r--r--grammar/rainerscript.c5806
-rw-r--r--grammar/rainerscript.h409
-rwxr-xr-xinstall-sh518
-rw-r--r--ltmain.sh11251
-rw-r--r--m4/ac_check_define.m442
-rw-r--r--m4/atomic_operations.m466
-rw-r--r--m4/atomic_operations_64bit.m453
-rw-r--r--m4/libtool.m48394
-rw-r--r--m4/ltoptions.m4437
-rw-r--r--m4/ltsugar.m4124
-rw-r--r--m4/ltversion.m423
-rw-r--r--m4/lt~obsolete.m499
-rwxr-xr-xmissing215
-rw-r--r--outchannel.c303
-rw-r--r--outchannel.h38
-rw-r--r--parse.c567
-rw-r--r--parse.h105
-rw-r--r--platform/README7
-rwxr-xr-xplatform/freebsd/rsyslogd83
-rw-r--r--platform/redhat/rsyslog.conf87
-rwxr-xr-xplatform/slackware/rc.rsyslogd68
-rw-r--r--plugins/fmhttp/Makefile.am6
-rw-r--r--plugins/fmhttp/Makefile.in797
-rw-r--r--plugins/fmhttp/fmhttp.c188
-rw-r--r--plugins/im3195/Makefile.am8
-rw-r--r--plugins/im3195/Makefile.in798
-rw-r--r--plugins/im3195/im3195.c216
-rw-r--r--plugins/imdiag/Makefile.am6
-rw-r--r--plugins/imdiag/Makefile.in796
-rw-r--r--plugins/imdiag/imdiag.c943
-rw-r--r--plugins/imdtls/Makefile.am6
-rw-r--r--plugins/imdtls/Makefile.in797
-rw-r--r--plugins/imdtls/imdtls.c1164
-rw-r--r--plugins/imfile/Makefile.am12
-rw-r--r--plugins/imfile/Makefile.in809
-rw-r--r--plugins/imfile/imfile.c2992
-rw-r--r--plugins/imfile/siphash.c185
-rw-r--r--plugins/imgssapi/Makefile.am6
-rw-r--r--plugins/imgssapi/Makefile.in797
-rw-r--r--plugins/imgssapi/imgssapi.c823
-rw-r--r--plugins/imjournal/Makefile.am12
-rw-r--r--plugins/imjournal/Makefile.in816
-rw-r--r--plugins/imjournal/dummy.c171
-rw-r--r--plugins/imjournal/imjournal.c1496
-rw-r--r--plugins/imkafka/Makefile.am19
-rw-r--r--plugins/imkafka/Makefile.in815
-rw-r--r--plugins/imkafka/dummy.c171
-rw-r--r--plugins/imkafka/imkafka.c904
-rw-r--r--plugins/imklog/Makefile.am20
-rw-r--r--plugins/imklog/Makefile.in818
-rw-r--r--plugins/imklog/bsd.c329
-rw-r--r--plugins/imklog/imklog.c549
-rw-r--r--plugins/imklog/imklog.h77
-rw-r--r--plugins/immark/Makefile.am11
-rw-r--r--plugins/immark/Makefile.in799
-rw-r--r--plugins/immark/immark.c337
-rw-r--r--plugins/immark/immark.h34
-rw-r--r--plugins/impstats/Makefile.am6
-rw-r--r--plugins/impstats/Makefile.in796
-rw-r--r--plugins/impstats/impstats.c635
-rw-r--r--plugins/imptcp/Makefile.am6
-rw-r--r--plugins/imptcp/Makefile.in796
-rw-r--r--plugins/imptcp/imptcp.c2676
-rw-r--r--plugins/imrelp/Makefile.am6
-rw-r--r--plugins/imrelp/Makefile.in797
-rw-r--r--plugins/imrelp/imrelp.c954
-rw-r--r--plugins/imsolaris/Makefile.am6
-rw-r--r--plugins/imsolaris/Makefile.in808
-rw-r--r--plugins/imsolaris/imsolaris.c437
-rw-r--r--plugins/imsolaris/imsolaris.h2
-rw-r--r--plugins/imsolaris/sun_cddl.c420
-rw-r--r--plugins/imsolaris/sun_cddl.h7
-rw-r--r--plugins/imtcp/Makefile.am11
-rw-r--r--plugins/imtcp/Makefile.in799
-rw-r--r--plugins/imtcp/imtcp.c1192
-rw-r--r--plugins/imudp/Makefile.am11
-rw-r--r--plugins/imudp/Makefile.in800
-rw-r--r--plugins/imudp/imudp.c1419
-rw-r--r--plugins/imuxsock/Makefile.am11
-rw-r--r--plugins/imuxsock/Makefile.in799
-rw-r--r--plugins/imuxsock/imuxsock.c1767
-rw-r--r--plugins/mmanon/Makefile.am8
-rw-r--r--plugins/mmanon/Makefile.in797
-rw-r--r--plugins/mmanon/mmanon.c1375
-rw-r--r--plugins/mmaudit/Makefile.am8
-rw-r--r--plugins/mmaudit/Makefile.in797
-rw-r--r--plugins/mmaudit/mmaudit.c344
-rw-r--r--plugins/mmdblookup/Makefile.am14
-rw-r--r--plugins/mmdblookup/Makefile.in814
-rw-r--r--plugins/mmdblookup/dummy.c172
-rw-r--r--plugins/mmdblookup/mmdblookup.c517
-rw-r--r--plugins/mmexternal/Makefile.am13
-rw-r--r--plugins/mmexternal/Makefile.in800
-rw-r--r--plugins/mmexternal/mmexternal.c611
-rw-r--r--plugins/mmfields/Makefile.am8
-rw-r--r--plugins/mmfields/Makefile.in797
-rw-r--r--plugins/mmfields/mmfields.c275
-rw-r--r--plugins/mmjsonparse/Makefile.am14
-rw-r--r--plugins/mmjsonparse/Makefile.in800
-rw-r--r--plugins/mmjsonparse/mmjsonparse.c403
-rw-r--r--plugins/mmnormalize/Makefile.am14
-rw-r--r--plugins/mmnormalize/Makefile.in800
-rw-r--r--plugins/mmnormalize/mmnormalize.c551
-rw-r--r--plugins/mmpstrucdata/Makefile.am8
-rw-r--r--plugins/mmpstrucdata/Makefile.in798
-rw-r--r--plugins/mmpstrucdata/mmpstrucdata.c399
-rw-r--r--plugins/mmrm1stspace/Makefile.am8
-rw-r--r--plugins/mmrm1stspace/Makefile.in798
-rw-r--r--plugins/mmrm1stspace/mmrm1stspace.c178
-rw-r--r--plugins/mmsnmptrapd/Makefile.am8
-rw-r--r--plugins/mmsnmptrapd/Makefile.in798
-rw-r--r--plugins/mmsnmptrapd/mmsnmptrapd.c438
-rw-r--r--plugins/mmutf8fix/Makefile.am8
-rw-r--r--plugins/mmutf8fix/Makefile.in797
-rw-r--r--plugins/mmutf8fix/mmutf8fix.c339
-rw-r--r--plugins/omazureeventhubs/Makefile.am13
-rw-r--r--plugins/omazureeventhubs/Makefile.in802
-rw-r--r--plugins/omazureeventhubs/omazureeventhubs.c1354
-rw-r--r--plugins/omclickhouse/Makefile.am8
-rw-r--r--plugins/omclickhouse/Makefile.in800
-rw-r--r--plugins/omclickhouse/omclickhouse.c1032
-rw-r--r--plugins/omdtls/Makefile.am6
-rw-r--r--plugins/omdtls/Makefile.in797
-rw-r--r--plugins/omdtls/omdtls.c853
-rw-r--r--plugins/omelasticsearch/Makefile.am8
-rw-r--r--plugins/omelasticsearch/Makefile.in801
-rw-r--r--plugins/omelasticsearch/README21
-rw-r--r--plugins/omelasticsearch/omelasticsearch.c2319
-rw-r--r--plugins/omgssapi/Makefile.am6
-rw-r--r--plugins/omgssapi/Makefile.in797
-rw-r--r--plugins/omgssapi/omgssapi.c720
-rw-r--r--plugins/omhdfs/Makefile.am6
-rw-r--r--plugins/omhdfs/Makefile.in797
-rw-r--r--plugins/omhdfs/omhdfs.c570
-rw-r--r--plugins/omjournal/Makefile.am8
-rw-r--r--plugins/omjournal/Makefile.in798
-rw-r--r--plugins/omjournal/omjournal.c323
-rw-r--r--plugins/omkafka/Makefile.am18
-rw-r--r--plugins/omkafka/Makefile.in815
-rw-r--r--plugins/omkafka/dummy.c171
-rw-r--r--plugins/omkafka/omkafka.c2141
-rw-r--r--plugins/omlibdbi/Makefile.am12
-rw-r--r--plugins/omlibdbi/Makefile.in815
-rw-r--r--plugins/omlibdbi/dummy.c171
-rw-r--r--plugins/omlibdbi/omlibdbi.c660
-rw-r--r--plugins/ommail/Makefile.am6
-rw-r--r--plugins/ommail/Makefile.in796
-rw-r--r--plugins/ommail/ommail.c902
-rw-r--r--plugins/ommongodb/Makefile.am7
-rw-r--r--plugins/ommongodb/Makefile.in798
-rw-r--r--plugins/ommongodb/README48
-rw-r--r--plugins/ommongodb/ommongodb.c786
-rw-r--r--plugins/ommysql/Makefile.am16
-rw-r--r--plugins/ommysql/Makefile.in806
-rw-r--r--plugins/ommysql/createDB.sql37
-rw-r--r--plugins/ommysql/ommysql.c599
-rw-r--r--plugins/ompgsql/Makefile.am8
-rw-r--r--plugins/ompgsql/Makefile.in798
-rw-r--r--plugins/ompgsql/createDB.sql37
-rw-r--r--plugins/ompgsql/ompgsql.c580
-rw-r--r--plugins/omprog/Makefile.am8
-rw-r--r--plugins/omprog/Makefile.in797
-rw-r--r--plugins/omprog/omprog.c1281
-rw-r--r--plugins/omrelp/Makefile.am6
-rw-r--r--plugins/omrelp/Makefile.in797
-rw-r--r--plugins/omrelp/omrelp.c826
-rw-r--r--plugins/omruleset/Makefile.am8
-rw-r--r--plugins/omruleset/Makefile.in797
-rw-r--r--plugins/omruleset/omruleset.c274
-rw-r--r--plugins/omsnmp/Makefile.am6
-rw-r--r--plugins/omsnmp/Makefile.in797
-rw-r--r--plugins/omsnmp/omsnmp.c658
-rw-r--r--plugins/omsnmp/omsnmp.h104
-rw-r--r--plugins/omstdout/Makefile.am8
-rw-r--r--plugins/omstdout/Makefile.in797
-rw-r--r--plugins/omstdout/omstdout.c372
-rw-r--r--plugins/omtesting/Makefile.am11
-rw-r--r--plugins/omtesting/Makefile.in799
-rw-r--r--plugins/omtesting/omtesting.c364
-rw-r--r--plugins/omudpspoof/Makefile.am8
-rw-r--r--plugins/omudpspoof/Makefile.in798
-rw-r--r--plugins/omudpspoof/omudpspoof.c819
-rw-r--r--plugins/omuxsock/Makefile.am8
-rw-r--r--plugins/omuxsock/Makefile.in797
-rw-r--r--plugins/omuxsock/omuxsock.c454
-rw-r--r--plugins/pmciscoios/Makefile.am8
-rw-r--r--plugins/pmciscoios/Makefile.in797
-rw-r--r--plugins/pmciscoios/pmciscoios.c294
-rw-r--r--plugins/pmlastmsg/Makefile.am8
-rw-r--r--plugins/pmlastmsg/Makefile.in797
-rw-r--r--plugins/pmlastmsg/pmlastmsg.c169
-rw-r--r--plugins/pmnormalize/Makefile.am8
-rw-r--r--plugins/pmnormalize/Makefile.in798
-rw-r--r--plugins/pmnormalize/pmnormalize.c270
-rw-r--r--plugins/pmnull/Makefile.am8
-rw-r--r--plugins/pmnull/Makefile.in797
-rw-r--r--plugins/pmnull/pmnull.c187
-rw-r--r--runtime/Makefile.am318
-rw-r--r--runtime/Makefile.in2110
-rw-r--r--runtime/atomic.h265
-rw-r--r--runtime/batch.h129
-rw-r--r--runtime/cfsysline.c1081
-rw-r--r--runtime/cfsysline.h62
-rw-r--r--runtime/conf.c640
-rw-r--r--runtime/conf.h73
-rw-r--r--runtime/cryprov.h48
-rw-r--r--runtime/datetime.c1413
-rw-r--r--runtime/datetime.h100
-rw-r--r--runtime/debug.c478
-rw-r--r--runtime/debug.h78
-rw-r--r--runtime/dnscache.c472
-rw-r--r--runtime/dnscache.h31
-rw-r--r--runtime/dynstats.c622
-rw-r--r--runtime/dynstats.h83
-rw-r--r--runtime/errmsg.c288
-rw-r--r--runtime/errmsg.h38
-rw-r--r--runtime/glbl.c1523
-rw-r--r--runtime/glbl.h159
-rw-r--r--runtime/gss-misc.c315
-rw-r--r--runtime/gss-misc.h44
-rw-r--r--runtime/hashtable.c341
-rw-r--r--runtime/hashtable.h202
-rw-r--r--runtime/hashtable_itr.c189
-rw-r--r--runtime/hashtable_itr.h103
-rw-r--r--runtime/hashtable_private.h75
-rw-r--r--runtime/im-helper.h62
-rw-r--r--runtime/janitor.c103
-rw-r--r--runtime/janitor.h35
-rw-r--r--runtime/lib_ksi_queue.c220
-rw-r--r--runtime/lib_ksi_queue.h53
-rw-r--r--runtime/lib_ksils12.c2173
-rw-r--r--runtime/lib_ksils12.h250
-rw-r--r--runtime/libgcry.c765
-rw-r--r--runtime/libgcry.h87
-rw-r--r--runtime/libgcry_common.c200
-rw-r--r--runtime/linkedlist.c415
-rw-r--r--runtime/linkedlist.h71
-rw-r--r--runtime/lmcry_gcry.c339
-rw-r--r--runtime/lmcry_gcry.h39
-rw-r--r--runtime/lmsig_ksi-ls12.c346
-rw-r--r--runtime/lmsig_ksi-ls12.h40
-rw-r--r--runtime/lookup.c1093
-rw-r--r--runtime/lookup.h116
-rw-r--r--runtime/module-template.h1250
-rw-r--r--runtime/modules.c1488
-rw-r--r--runtime/modules.h213
-rw-r--r--runtime/msg.c5476
-rw-r--r--runtime/msg.h281
-rw-r--r--runtime/net.c1741
-rw-r--r--runtime/net.h180
-rw-r--r--runtime/net_ossl.c1217
-rw-r--r--runtime/net_ossl.h173
-rw-r--r--runtime/netstrm.c508
-rw-r--r--runtime/netstrm.h114
-rw-r--r--runtime/netstrms.c553
-rw-r--r--runtime/netstrms.h94
-rw-r--r--runtime/nsd.h134
-rw-r--r--runtime/nsd_gtls.c2451
-rw-r--r--runtime/nsd_gtls.h123
-rw-r--r--runtime/nsd_ossl.c1510
-rw-r--r--runtime/nsd_ossl.h85
-rw-r--r--runtime/nsd_ptcp.c1153
-rw-r--r--runtime/nsd_ptcp.h52
-rw-r--r--runtime/nsdpoll_ptcp.c320
-rw-r--r--runtime/nsdpoll_ptcp.h61
-rw-r--r--runtime/nsdsel_gtls.c317
-rw-r--r--runtime/nsdsel_gtls.h41
-rw-r--r--runtime/nsdsel_ossl.c290
-rw-r--r--runtime/nsdsel_ossl.h42
-rw-r--r--runtime/nsdsel_ptcp.c221
-rw-r--r--runtime/nsdsel_ptcp.h45
-rw-r--r--runtime/nspoll.c218
-rw-r--r--runtime/nspoll.h66
-rw-r--r--runtime/nssel.c254
-rw-r--r--runtime/nssel.h57
-rw-r--r--runtime/obj-types.h444
-rw-r--r--runtime/obj.c1409
-rw-r--r--runtime/obj.h132
-rw-r--r--runtime/objomsr.c158
-rw-r--r--runtime/objomsr.h51
-rw-r--r--runtime/operatingstate.c177
-rw-r--r--runtime/operatingstate.h32
-rw-r--r--runtime/parser.c742
-rw-r--r--runtime/parser.h77
-rw-r--r--runtime/perctile_ringbuf.c360
-rw-r--r--runtime/perctile_ringbuf.h34
-rw-r--r--runtime/perctile_stats.c695
-rw-r--r--runtime/perctile_stats.h89
-rw-r--r--runtime/prop.c262
-rw-r--r--runtime/prop.h73
-rw-r--r--runtime/queue.c3609
-rw-r--r--runtime/queue.h247
-rw-r--r--runtime/ratelimit.c436
-rw-r--r--runtime/ratelimit.h55
-rw-r--r--runtime/regexp.c384
-rw-r--r--runtime/regexp.h44
-rw-r--r--runtime/rsconf.c1601
-rw-r--r--runtime/rsconf.h299
-rw-r--r--runtime/rsyslog.c298
-rw-r--r--runtime/rsyslog.h814
-rw-r--r--runtime/ruleset.c1194
-rw-r--r--runtime/ruleset.h106
-rw-r--r--runtime/sigprov.h37
-rw-r--r--runtime/srUtils.h106
-rw-r--r--runtime/srutils.c868
-rw-r--r--runtime/statsobj.c761
-rw-r--r--runtime/statsobj.h203
-rw-r--r--runtime/stream.c2533
-rw-r--r--runtime/stream.h254
-rw-r--r--runtime/strgen.c278
-rw-r--r--runtime/strgen.h60
-rw-r--r--runtime/stringbuf.c777
-rw-r--r--runtime/stringbuf.h157
-rw-r--r--runtime/syslogd-types.h114
-rw-r--r--runtime/tcpclt.c525
-rw-r--r--runtime/tcpclt.h76
-rw-r--r--runtime/tcps_sess.c625
-rw-r--r--runtime/tcps_sess.h90
-rw-r--r--runtime/tcpsrv.c1799
-rw-r--r--runtime/tcpsrv.h233
-rw-r--r--runtime/timezones.c205
-rw-r--r--runtime/timezones.h38
-rw-r--r--runtime/typedefs.h314
-rw-r--r--runtime/unicode-helper.h44
-rw-r--r--runtime/unlimited_select.h45
-rw-r--r--runtime/var.c131
-rw-r--r--runtime/var.h62
-rw-r--r--runtime/wti.c573
-rw-r--r--runtime/wti.h144
-rw-r--r--runtime/wtp.c650
-rw-r--r--runtime/wtp.h108
-rw-r--r--runtime/zlibw.c239
-rw-r--r--runtime/zlibw.h51
-rw-r--r--runtime/zstdw.c191
-rw-r--r--runtime/zstdw.h43
-rw-r--r--template.c2449
-rw-r--r--template.h188
-rwxr-xr-xtest-driver148
-rw-r--r--tests/1.rstest26
-rw-r--r--tests/2.rstest10
-rw-r--r--tests/3.rstest21
-rw-r--r--tests/CI/centos6-9.supp32
-rw-r--r--tests/CI/centos7.supp9
-rw-r--r--tests/CI/gcov.supp6
-rw-r--r--tests/CI/ubuntu20.04.supp42
-rw-r--r--tests/DevNull.cfgtest2
-rw-r--r--tests/Makefile.am3148
-rw-r--r--tests/Makefile.in4452
-rw-r--r--tests/NoExistFile.cfgtest2
-rw-r--r--tests/README102
-rwxr-xr-xtests/abort-uncleancfg-badcfg-check.sh13
-rwxr-xr-xtests/abort-uncleancfg-badcfg-check_1.sh15
-rwxr-xr-xtests/abort-uncleancfg-goodcfg-check.sh13
-rwxr-xr-xtests/abort-uncleancfg-goodcfg.sh27
-rwxr-xr-xtests/action-tx-errfile-maxsize.sh35
-rwxr-xr-xtests/action-tx-errfile.sh40
-rwxr-xr-xtests/action-tx-single-processing.sh38
-rwxr-xr-xtests/allowed-sender-tcp-fail.sh26
-rwxr-xr-xtests/allowed-sender-tcp-hostname-fail.sh31
-rwxr-xr-xtests/allowed-sender-tcp-hostname-ok.sh23
-rwxr-xr-xtests/allowed-sender-tcp-ok.sh22
-rwxr-xr-xtests/array_lookup_table-vg.sh5
-rwxr-xr-xtests/array_lookup_table.sh53
-rwxr-xr-xtests/array_lookup_table_misuse-vg.sh45
-rwxr-xr-xtests/arrayqueue.sh21
-rwxr-xr-xtests/asynwr_deadlock.sh40
-rwxr-xr-xtests/asynwr_deadlock2.sh85
-rwxr-xr-xtests/asynwr_deadlock4.sh40
-rwxr-xr-xtests/asynwr_deadlock_2.sh32
-rwxr-xr-xtests/asynwr_dynfile_flushtxend-off.sh38
-rwxr-xr-xtests/asynwr_simple.sh26
-rwxr-xr-xtests/asynwr_simple_2.sh22
-rwxr-xr-xtests/asynwr_small.sh38
-rwxr-xr-xtests/asynwr_timeout.sh34
-rwxr-xr-xtests/asynwr_timeout_2.sh37
-rwxr-xr-xtests/asynwr_tinybuf.sh36
-rw-r--r--tests/bad_qi/dbq.qi29
-rwxr-xr-xtests/badqi.sh31
-rwxr-xr-xtests/cee_diskqueue.sh23
-rwxr-xr-xtests/cee_simple.sh23
-rwxr-xr-xtests/cfg.sh140
-rw-r--r--tests/cfg1.cfgtest3
-rw-r--r--tests/cfg1.testin2
-rw-r--r--tests/cfg2.cfgtest3
-rw-r--r--tests/cfg2.testin1
-rw-r--r--tests/cfg3.cfgtest5
-rw-r--r--tests/cfg3.testin1
-rw-r--r--tests/cfg4.cfgtest1
-rw-r--r--tests/cfg4.testin31
-rw-r--r--tests/check_relpEngineVersion.c66
-rw-r--r--tests/chkseq.c249
-rwxr-xr-xtests/clickhouse-basic-vg.sh3
-rwxr-xr-xtests/clickhouse-basic.sh30
-rwxr-xr-xtests/clickhouse-bulk-load-vg.sh3
-rwxr-xr-xtests/clickhouse-bulk-load.sh30
-rwxr-xr-xtests/clickhouse-bulk-vg.sh3
-rwxr-xr-xtests/clickhouse-bulk.sh39
-rwxr-xr-xtests/clickhouse-dflt-tpl.sh24
-rwxr-xr-xtests/clickhouse-errorfile.sh32
-rwxr-xr-xtests/clickhouse-limited-batch.sh31
-rwxr-xr-xtests/clickhouse-load-vg.sh3
-rwxr-xr-xtests/clickhouse-load.sh31
-rwxr-xr-xtests/clickhouse-retry-error.sh27
-rwxr-xr-xtests/clickhouse-select.sh28
-rwxr-xr-xtests/clickhouse-start.sh31
-rwxr-xr-xtests/clickhouse-stop.sh19
-rwxr-xr-xtests/clickhouse-wrong-insert-syntax.sh30
-rwxr-xr-xtests/clickhouse-wrong-quotation-marks.sh33
-rwxr-xr-xtests/clickhouse-wrong-template-option.sh31
-rwxr-xr-xtests/complex1.sh132
-rwxr-xr-xtests/compresssp-stringtpl.sh26
-rwxr-xr-xtests/compresssp.sh29
-rwxr-xr-xtests/config_enabled-off.sh18
-rwxr-xr-xtests/config_enabled-on.sh19
-rwxr-xr-xtests/config_multiple_include.sh32
-rwxr-xr-xtests/config_output-o-option.sh18
-rwxr-xr-xtests/da-mainmsg-q.sh49
-rwxr-xr-xtests/da-queue-persist.sh47
-rwxr-xr-xtests/daqueue-dirty-shutdown.sh116
-rwxr-xr-xtests/daqueue-invld-qi.sh51
-rwxr-xr-xtests/daqueue-persist-drvr.sh54
-rwxr-xr-xtests/daqueue-persist.sh19
-rwxr-xr-xtests/diag.sh2946
-rw-r--r--tests/diagtalker.c165
-rwxr-xr-xtests/dircreate_dflt.sh27
-rwxr-xr-xtests/dircreate_off.sh28
-rwxr-xr-xtests/discard-allmark-vg.sh35
-rwxr-xr-xtests/discard-allmark.sh25
-rwxr-xr-xtests/discard-rptdmsg-vg.sh4
-rwxr-xr-xtests/discard-rptdmsg.sh20
-rwxr-xr-xtests/discard.sh23
-rwxr-xr-xtests/diskq-rfc5424.sh42
-rwxr-xr-xtests/diskqueue-fail.sh35
-rwxr-xr-xtests/diskqueue-fsync.sh35
-rwxr-xr-xtests/diskqueue-full.sh32
-rwxr-xr-xtests/diskqueue-multithread-es.sh52
-rwxr-xr-xtests/diskqueue-non-unique-prefix.sh29
-rwxr-xr-xtests/diskqueue.sh31
-rwxr-xr-xtests/dnscache-TTL-0-vg.sh4
-rwxr-xr-xtests/dnscache-TTL-0.sh21
-rwxr-xr-xtests/dynfile_invalid2.sh42
-rwxr-xr-xtests/dynfile_invld_async.sh42
-rwxr-xr-xtests/dynfile_invld_sync.sh42
-rwxr-xr-xtests/dynstats-json-vg.sh41
-rwxr-xr-xtests/dynstats-json.sh40
-rwxr-xr-xtests/dynstats-vg.sh45
-rwxr-xr-xtests/dynstats.sh42
-rwxr-xr-xtests/dynstats_ctr_reset.sh51
-rwxr-xr-xtests/dynstats_nometric.sh44
-rwxr-xr-xtests/dynstats_overflow-vg.sh102
-rwxr-xr-xtests/dynstats_overflow.sh102
-rwxr-xr-xtests/dynstats_prevent_premature_eviction-vg.sh58
-rwxr-xr-xtests/dynstats_prevent_premature_eviction.sh53
-rwxr-xr-xtests/dynstats_reset-vg.sh57
-rwxr-xr-xtests/dynstats_reset.sh56
-rwxr-xr-xtests/dynstats_reset_without_pstats_reset.sh53
-rw-r--r--tests/elasticsearch-error-format-check.py137
-rwxr-xr-xtests/elasticsearch-stop.sh7
-rwxr-xr-xtests/empty-app-name.sh19
-rwxr-xr-xtests/empty-hostname.sh29
-rwxr-xr-xtests/empty-prop-comparison.sh25
-rwxr-xr-xtests/empty-ruleset.sh34
-rw-r--r--tests/err1.rstest7
-rwxr-xr-xtests/es-basic-bulk-vg.sh3
-rwxr-xr-xtests/es-basic-bulk.sh30
-rwxr-xr-xtests/es-basic-errfile-empty.sh34
-rwxr-xr-xtests/es-basic-errfile-popul.sh48
-rwxr-xr-xtests/es-basic-es6.0.sh29
-rwxr-xr-xtests/es-basic-es7.14.sh29
-rwxr-xr-xtests/es-basic-ha-vg.sh29
-rwxr-xr-xtests/es-basic-ha.sh34
-rwxr-xr-xtests/es-basic-server.sh27
-rwxr-xr-xtests/es-basic-vg.sh3
-rwxr-xr-xtests/es-basic-vgthread.sh32
-rwxr-xr-xtests/es-basic.sh73
-rwxr-xr-xtests/es-bulk-errfile-empty.sh37
-rwxr-xr-xtests/es-bulk-errfile-popul-def-format.sh52
-rwxr-xr-xtests/es-bulk-errfile-popul-def-interleaved.sh55
-rwxr-xr-xtests/es-bulk-errfile-popul-erronly-interleaved.sh56
-rwxr-xr-xtests/es-bulk-errfile-popul-erronly.sh55
-rwxr-xr-xtests/es-bulk-errfile-popul.sh45
-rwxr-xr-xtests/es-bulk-retry.sh298
-rwxr-xr-xtests/es-duplicated-ruleset-vg.sh6
-rwxr-xr-xtests/es-duplicated-ruleset.sh44
-rwxr-xr-xtests/es-execOnlyWhenPreviousSuspended.sh50
-rwxr-xr-xtests/es-maxbytes-bulk.sh30
-rwxr-xr-xtests/es-searchType-empty.sh35
-rwxr-xr-xtests/es-writeoperation.sh118
-rw-r--r--tests/es_response_get_msgnum.py8
-rwxr-xr-xtests/exec_tpl-concurrency.sh34
-rwxr-xr-xtests/execonlyonce.sh34
-rwxr-xr-xtests/execonlywhenprevsuspended-nonsusp-queue.sh40
-rwxr-xr-xtests/execonlywhenprevsuspended-nonsusp.sh36
-rwxr-xr-xtests/execonlywhenprevsuspended-queue.sh36
-rwxr-xr-xtests/execonlywhenprevsuspended.sh28
-rwxr-xr-xtests/execonlywhenprevsuspended2.sh36
-rwxr-xr-xtests/execonlywhenprevsuspended3.sh35
-rwxr-xr-xtests/execonlywhenprevsuspended4.sh31
-rwxr-xr-xtests/execonlywhenprevsuspended_multiwrkr.sh29
-rwxr-xr-xtests/externalstate-failed-rcvr.sh31
-rwxr-xr-xtests/fac_authpriv.sh22
-rwxr-xr-xtests/fac_ftp.sh19
-rwxr-xr-xtests/fac_invld1.sh21
-rwxr-xr-xtests/fac_invld2.sh21
-rwxr-xr-xtests/fac_invld3.sh21
-rwxr-xr-xtests/fac_invld4_rfc5424.sh21
-rwxr-xr-xtests/fac_local0-vg.sh4
-rwxr-xr-xtests/fac_local0.sh22
-rwxr-xr-xtests/fac_local7.sh21
-rwxr-xr-xtests/fac_mail.sh20
-rwxr-xr-xtests/fac_news.sh21
-rwxr-xr-xtests/fac_ntp.sh19
-rwxr-xr-xtests/fac_uucp.sh21
-rwxr-xr-xtests/failover-async.sh29
-rwxr-xr-xtests/failover-basic-vg.sh29
-rwxr-xr-xtests/failover-basic.sh21
-rwxr-xr-xtests/failover-double.sh20
-rwxr-xr-xtests/failover-no-basic-vg.sh37
-rwxr-xr-xtests/failover-no-basic.sh29
-rwxr-xr-xtests/failover-no-rptd-vg.sh26
-rwxr-xr-xtests/failover-no-rptd.sh29
-rwxr-xr-xtests/failover-rptd-vg.sh31
-rwxr-xr-xtests/failover-rptd.sh21
-rw-r--r--tests/faketime_common.sh60
-rwxr-xr-xtests/fieldtest-udp.sh29
-rwxr-xr-xtests/fieldtest.sh29
-rwxr-xr-xtests/func-substring-invld-startpos-vg.sh3
-rwxr-xr-xtests/func-substring-invld-startpos.sh17
-rwxr-xr-xtests/func-substring-large-endpos.sh17
-rwxr-xr-xtests/func-substring-large-neg-endpos.sh17
-rwxr-xr-xtests/func-substring-relative-endpos.sh17
-rwxr-xr-xtests/glbl-internalmsg_severity-debug-not_shown.sh16
-rwxr-xr-xtests/glbl-internalmsg_severity-debug-shown.sh17
-rwxr-xr-xtests/glbl-internalmsg_severity-info-shown.sh17
-rwxr-xr-xtests/glbl-invld-param.sh18
-rwxr-xr-xtests/glbl-oversizeMsg-log-vg.sh37
-rwxr-xr-xtests/glbl-oversizeMsg-log.sh37
-rwxr-xr-xtests/glbl-oversizeMsg-split.sh56
-rwxr-xr-xtests/glbl-oversizeMsg-truncate-imfile.sh47
-rwxr-xr-xtests/glbl-oversizeMsg-truncate.sh46
-rwxr-xr-xtests/glbl-ruleset-queue-defaults.sh21
-rwxr-xr-xtests/glbl-umask.sh29
-rwxr-xr-xtests/glbl-unloadmodules.sh27
-rwxr-xr-xtests/glbl_setenv.sh26
-rwxr-xr-xtests/glbl_setenv_2_vars.sh28
-rwxr-xr-xtests/glbl_setenv_err.sh25
-rwxr-xr-xtests/glbl_setenv_err_too_long.sh25
-rwxr-xr-xtests/global_vars.sh34
-rwxr-xr-xtests/gzipwr_flushInterval.sh28
-rwxr-xr-xtests/gzipwr_flushOnTXEnd.sh32
-rwxr-xr-xtests/gzipwr_hup-vg.sh4
-rwxr-xr-xtests/gzipwr_hup.sh35
-rwxr-xr-xtests/gzipwr_hup_multi_file.sh46
-rwxr-xr-xtests/gzipwr_hup_single_file.sh40
-rwxr-xr-xtests/gzipwr_large.sh35
-rwxr-xr-xtests/gzipwr_large_dynfile.sh52
-rwxr-xr-xtests/gzipwr_rscript.sh21
-rw-r--r--tests/have_relpEngineSetTLSLibByName.c10
-rw-r--r--tests/have_relpSrvSetOversizeMode.c10
-rw-r--r--tests/have_relpSrvSetTlsConfigCmd.c10
-rwxr-xr-xtests/hostname-with-slash-dflt-invld.sh28
-rwxr-xr-xtests/hostname-with-slash-dflt-slash-valid.sh26
-rwxr-xr-xtests/hostname-with-slash-pmrfc3164.sh25
-rwxr-xr-xtests/hostname-with-slash-pmrfc5424.sh25
-rwxr-xr-xtests/imbatchreport_delete_structdata.sh42
-rwxr-xr-xtests/imbatchreport_delete_success.sh48
-rwxr-xr-xtests/imbatchreport_delete_toolarge.sh48
-rwxr-xr-xtests/imbatchreport_errmsg_delete_params.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_glob_dir_fake.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_glob_dir_not_dir.sh15
-rwxr-xr-xtests/imbatchreport_errmsg_glob_not_regular.sh15
-rwxr-xr-xtests/imbatchreport_errmsg_no_params-vg.sh4
-rwxr-xr-xtests/imbatchreport_errmsg_no_params.sh17
-rwxr-xr-xtests/imbatchreport_errmsg_not_supported1.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_not_supported2.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_not_supported3.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_regex.match.reject.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_regex.match.rename.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_regex.nomatch.sh16
-rwxr-xr-xtests/imbatchreport_errmsg_rename_params.sh16
-rwxr-xr-xtests/imbatchreport_rename_success.sh48
-rwxr-xr-xtests/imbatchreport_rename_toolarge.sh48
-rwxr-xr-xtests/imdocker-basic-vg.sh3
-rwxr-xr-xtests/imdocker-basic.sh37
-rwxr-xr-xtests/imdocker-long-logline-vg.sh6
-rwxr-xr-xtests/imdocker-long-logline.sh43
-rwxr-xr-xtests/imdocker-multi-line-vg.sh6
-rwxr-xr-xtests/imdocker-multi-line.sh47
-rwxr-xr-xtests/imdocker-new-logs-from-start-vg.sh3
-rwxr-xr-xtests/imdocker-new-logs-from-start.sh53
-rwxr-xr-xtests/imdtls-basic-timeout45
-rwxr-xr-xtests/imdtls-basic-tlscommands.sh46
-rwxr-xr-xtests/imdtls-basic-vg.sh9
-rwxr-xr-xtests/imdtls-basic.sh37
-rwxr-xr-xtests/imdtls-error-cert.sh28
-rwxr-xr-xtests/imdtls-sessionbreak-vg.sh9
-rwxr-xr-xtests/imdtls-sessionbreak.sh75
-rwxr-xr-xtests/imfile-basic-2GB-file.sh48
-rwxr-xr-xtests/imfile-basic-legacy.sh29
-rwxr-xr-xtests/imfile-basic-vg.sh3
-rwxr-xr-xtests/imfile-basic-vgthread.sh39
-rwxr-xr-xtests/imfile-basic.sh26
-rwxr-xr-xtests/imfile-discard-truncated-line.sh72
-rwxr-xr-xtests/imfile-endmsg.regex-vg.sh111
-rwxr-xr-xtests/imfile-endmsg.regex-with-example-vg.sh147
-rwxr-xr-xtests/imfile-endmsg.regex-with-example.sh157
-rw-r--r--tests/imfile-endmsg.regex.crio.rulebase15
-rw-r--r--tests/imfile-endmsg.regex.json.rulebase9
-rwxr-xr-xtests/imfile-endmsg.regex.sh110
-rwxr-xr-xtests/imfile-endregex-save-lf-persist.sh59
-rwxr-xr-xtests/imfile-endregex-save-lf.sh53
-rwxr-xr-xtests/imfile-endregex-timeout-none-polling.sh59
-rwxr-xr-xtests/imfile-endregex-timeout-none.sh54
-rwxr-xr-xtests/imfile-endregex-timeout-polling.sh61
-rwxr-xr-xtests/imfile-endregex-timeout-with-shutdown-polling.sh64
-rwxr-xr-xtests/imfile-endregex-timeout-with-shutdown.sh66
-rwxr-xr-xtests/imfile-endregex-timeout.sh46
-rwxr-xr-xtests/imfile-endregex-vg.sh73
-rwxr-xr-xtests/imfile-endregex.sh86
-rwxr-xr-xtests/imfile-error-not-repeated.sh51
-rwxr-xr-xtests/imfile-escapelf.replacement-empty.sh30
-rwxr-xr-xtests/imfile-escapelf.replacement.sh30
-rwxr-xr-xtests/imfile-file-not-found-error.sh45
-rwxr-xr-xtests/imfile-fileNotFoundError-parameter.sh26
-rwxr-xr-xtests/imfile-freshStartTail1.sh34
-rwxr-xr-xtests/imfile-freshStartTail2.sh29
-rwxr-xr-xtests/imfile-freshStartTail3.sh33
-rwxr-xr-xtests/imfile-growing-file-id.sh79
-rwxr-xr-xtests/imfile-ignore-old-file-1.sh37
-rwxr-xr-xtests/imfile-ignore-old-file-2.sh43
-rwxr-xr-xtests/imfile-ignore-old-file-3.sh34
-rwxr-xr-xtests/imfile-ignore-old-file-4.sh31
-rwxr-xr-xtests/imfile-ignore-old-file-5.sh47
-rwxr-xr-xtests/imfile-ignore-old-file-6.sh42
-rwxr-xr-xtests/imfile-ignore-old-file-7.sh56
-rwxr-xr-xtests/imfile-logrotate-async.sh108
-rwxr-xr-xtests/imfile-logrotate-copytruncate.sh79
-rwxr-xr-xtests/imfile-logrotate-multiple.sh85
-rwxr-xr-xtests/imfile-logrotate-nocopytruncate.sh78
-rwxr-xr-xtests/imfile-logrotate.sh77
-rwxr-xr-xtests/imfile-old-state-file.sh87
-rwxr-xr-xtests/imfile-persist-state-1.sh30
-rwxr-xr-xtests/imfile-readmode0-vg.sh63
-rwxr-xr-xtests/imfile-readmode2-polling.sh75
-rwxr-xr-xtests/imfile-readmode2-vg.sh72
-rwxr-xr-xtests/imfile-readmode2-with-persists-data-during-stop.sh102
-rwxr-xr-xtests/imfile-readmode2-with-persists.sh97
-rwxr-xr-xtests/imfile-readmode2.sh74
-rwxr-xr-xtests/imfile-rename-while-stopped.sh70
-rwxr-xr-xtests/imfile-rename.sh91
-rwxr-xr-xtests/imfile-statefile-delete.sh44
-rwxr-xr-xtests/imfile-statefile-directory.sh32
-rwxr-xr-xtests/imfile-statefile-no-delete.sh36
-rwxr-xr-xtests/imfile-statefile-no-file_id-TO-file_id.sh49
-rwxr-xr-xtests/imfile-statefile-no-file_id.sh45
-rwxr-xr-xtests/imfile-symlink-ext-tmp-dir-tree.sh80
-rwxr-xr-xtests/imfile-symlink-multi.sh70
-rwxr-xr-xtests/imfile-symlink.sh68
-rwxr-xr-xtests/imfile-truncate-2GB-file.sh48
-rwxr-xr-xtests/imfile-truncate-line.sh75
-rwxr-xr-xtests/imfile-truncate-multiple.sh52
-rwxr-xr-xtests/imfile-truncate.sh41
-rwxr-xr-xtests/imfile-wildcards-dirs-multi.sh91
-rwxr-xr-xtests/imfile-wildcards-dirs-multi2.sh91
-rwxr-xr-xtests/imfile-wildcards-dirs-multi3.sh96
-rwxr-xr-xtests/imfile-wildcards-dirs-multi4.sh95
-rwxr-xr-xtests/imfile-wildcards-dirs-multi5-polling.sh74
-rwxr-xr-xtests/imfile-wildcards-dirs-multi5.sh87
-rwxr-xr-xtests/imfile-wildcards-dirs.sh70
-rwxr-xr-xtests/imfile-wildcards-dirs2.sh91
-rwxr-xr-xtests/imfile-wildcards.sh92
-rwxr-xr-xtests/imhiredis-queue-lpop-vg.sh7
-rwxr-xr-xtests/imhiredis-queue-lpop.sh52
-rwxr-xr-xtests/imhiredis-queue-vg.sh7
-rwxr-xr-xtests/imhiredis-queue.sh51
-rwxr-xr-xtests/imhiredis-redis-restart-vg.sh7
-rwxr-xr-xtests/imhiredis-redis-restart.sh69
-rwxr-xr-xtests/imhiredis-redis-start-after-vg.sh7
-rwxr-xr-xtests/imhiredis-redis-start-after.sh55
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-ack-vg.sh7
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-ack.sh67
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-noack-vg.sh7
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-noack.sh68
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-reclaim-vg.sh7
-rwxr-xr-xtests/imhiredis-stream-consumerGroup-reclaim.sh83
-rwxr-xr-xtests/imhiredis-stream-from-beginning-vg.sh7
-rwxr-xr-xtests/imhiredis-stream-from-beginning.sh60
-rwxr-xr-xtests/imhiredis-stream-vg.sh7
-rwxr-xr-xtests/imhiredis-stream.sh60
-rwxr-xr-xtests/imhiredis-subscribe-vg.sh7
-rwxr-xr-xtests/imhiredis-subscribe.sh60
-rwxr-xr-xtests/imhttp-getrequest-file-vg.sh4
-rwxr-xr-xtests/imhttp-getrequest-file.sh18
-rwxr-xr-xtests/imhttp-post-payload-basic-auth-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-basic-auth.sh62
-rwxr-xr-xtests/imhttp-post-payload-compress-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-compress.sh30
-rwxr-xr-xtests/imhttp-post-payload-large-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-large.sh52
-rwxr-xr-xtests/imhttp-post-payload-multi-lf-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-multi-lf.sh29
-rwxr-xr-xtests/imhttp-post-payload-multi-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-multi.sh27
-rwxr-xr-xtests/imhttp-post-payload-query-params-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload-query-params.sh48
-rwxr-xr-xtests/imhttp-post-payload-vg.sh4
-rwxr-xr-xtests/imhttp-post-payload.sh38
-rwxr-xr-xtests/imjournal-basic-vg.sh3
-rwxr-xr-xtests/imjournal-basic.sh47
-rwxr-xr-xtests/imjournal-statefile-vg.sh3
-rwxr-xr-xtests/imjournal-statefile.sh69
-rwxr-xr-xtests/imkafka-backgrounded.sh61
-rwxr-xr-xtests/imkafka-config-err-param.sh57
-rwxr-xr-xtests/imkafka-config-err-ruleset.sh58
-rwxr-xr-xtests/imkafka-hang-on-no-kafka.sh35
-rwxr-xr-xtests/imkafka-hang-other-action-on-no-kafka.sh39
-rwxr-xr-xtests/imkafka-vg.sh3
-rwxr-xr-xtests/imkafka.sh57
-rwxr-xr-xtests/imkafka_multi_group.sh112
-rwxr-xr-xtests/imkafka_multi_single.sh151
-rwxr-xr-xtests/imklog_permitnonkernelfacility_root.sh32
-rwxr-xr-xtests/immark-inputname.sh18
-rwxr-xr-xtests/immark-ruleset-custom-msg.sh22
-rwxr-xr-xtests/immark-ruleset.sh22
-rwxr-xr-xtests/immark.sh19
-rwxr-xr-xtests/improg-multiline-test.py6
-rwxr-xr-xtests/improg-simul.sh70
-rwxr-xr-xtests/improg_errmsg_no_params-vg.sh4
-rwxr-xr-xtests/improg_errmsg_no_params.sh17
-rwxr-xr-xtests/improg_prog_confirm.sh27
-rwxr-xr-xtests/improg_prog_confirm_killonclose.sh28
-rwxr-xr-xtests/improg_prog_killonclose.sh25
-rwxr-xr-xtests/improg_prog_simple-vg.sh4
-rwxr-xr-xtests/improg_prog_simple.sh24
-rwxr-xr-xtests/improg_simple_multi.sh23
-rwxr-xr-xtests/impstats-hup.sh26
-rwxr-xr-xtests/imptcp-NUL-rawmsg.sh27
-rwxr-xr-xtests/imptcp-NUL.sh21
-rwxr-xr-xtests/imptcp-basic-hup.sh22
-rwxr-xr-xtests/imptcp-connection-msg-disabled.sh39
-rwxr-xr-xtests/imptcp-connection-msg-received.sh40
-rwxr-xr-xtests/imptcp-discard-truncated-msg.sh32
-rwxr-xr-xtests/imptcp-maxFrameSize-parameter.sh28
-rwxr-xr-xtests/imptcp-msg-truncation-on-number.sh38
-rwxr-xr-xtests/imptcp-msg-truncation-on-number2.sh46
-rwxr-xr-xtests/imptcp-octet-framing-too-long-vg.sh23
-rwxr-xr-xtests/imptcp-oversize-message-display.sh43
-rwxr-xr-xtests/imptcp_addtlframedelim.sh22
-rwxr-xr-xtests/imptcp_conndrop-vg.sh6
-rwxr-xr-xtests/imptcp_conndrop.sh30
-rwxr-xr-xtests/imptcp_framing_regex-oversize.sh45
-rwxr-xr-xtests/imptcp_framing_regex.sh39
-rwxr-xr-xtests/imptcp_large.sh27
-rwxr-xr-xtests/imptcp_maxsessions.sh47
-rwxr-xr-xtests/imptcp_multi_line.sh27
-rwxr-xr-xtests/imptcp_no_octet_counted.sh21
-rwxr-xr-xtests/imptcp_nonProcessingPoller.sh25
-rwxr-xr-xtests/imptcp_spframingfix.sh21
-rwxr-xr-xtests/imptcp_veryLargeOctateCountedMessages.sh26
-rwxr-xr-xtests/imrelp-basic-hup.sh21
-rwxr-xr-xtests/imrelp-basic-oldstyle.sh19
-rwxr-xr-xtests/imrelp-basic-vg.sh3
-rwxr-xr-xtests/imrelp-basic.sh19
-rwxr-xr-xtests/imrelp-bigmessage.sh79
-rwxr-xr-xtests/imrelp-invld-tlslib.sh16
-rwxr-xr-xtests/imrelp-long-msg.sh19
-rwxr-xr-xtests/imrelp-manyconn-vg.sh9
-rwxr-xr-xtests/imrelp-manyconn.sh21
-rwxr-xr-xtests/imrelp-maxDataSize-error.sh31
-rwxr-xr-xtests/imrelp-oversizeMode-accept.sh33
-rwxr-xr-xtests/imrelp-oversizeMode-truncate.sh36
-rwxr-xr-xtests/imrelp-sessionbreak-vg.sh74
-rwxr-xr-xtests/imrelp-tls-cfgcmd.sh57
-rwxr-xr-xtests/imrelp-tls-chainedcert.sh47
-rwxr-xr-xtests/imrelp-tls-mixed-chainedcert.sh54
-rwxr-xr-xtests/imrelp-tls-mixed-chainedcert2.sh54
-rwxr-xr-xtests/imrelp-tls.sh36
-rwxr-xr-xtests/imtcp-NUL-rawmsg.sh27
-rwxr-xr-xtests/imtcp-NUL.sh21
-rwxr-xr-xtests/imtcp-basic-hup.sh22
-rwxr-xr-xtests/imtcp-basic.sh20
-rwxr-xr-xtests/imtcp-bigmessage-octetcounting.sh65
-rwxr-xr-xtests/imtcp-bigmessage-octetstuffing.sh65
-rwxr-xr-xtests/imtcp-connection-msg-recieved.sh24
-rwxr-xr-xtests/imtcp-discard-truncated-msg.sh26
-rwxr-xr-xtests/imtcp-drvr-in-input-basic.sh28
-rwxr-xr-xtests/imtcp-listen-port-file-2.sh38
-rwxr-xr-xtests/imtcp-maxFrameSize.sh27
-rwxr-xr-xtests/imtcp-msg-truncation-on-number.sh37
-rwxr-xr-xtests/imtcp-msg-truncation-on-number2.sh44
-rwxr-xr-xtests/imtcp-multi-drvr-basic-parallel.sh38
-rwxr-xr-xtests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh45
-rwxr-xr-xtests/imtcp-multi-drvr-basic.sh34
-rwxr-xr-xtests/imtcp-multiport.sh29
-rwxr-xr-xtests/imtcp-octet-framing-too-long-vg.sh23
-rwxr-xr-xtests/imtcp-tls-basic-verifydepth.sh30
-rwxr-xr-xtests/imtcp-tls-basic-vg.sh3
-rwxr-xr-xtests/imtcp-tls-basic.sh32
-rwxr-xr-xtests/imtcp-tls-gtls-x509fingerprint-invld.sh31
-rwxr-xr-xtests/imtcp-tls-gtls-x509fingerprint.sh34
-rwxr-xr-xtests/imtcp-tls-gtls-x509name-invld.sh28
-rwxr-xr-xtests/imtcp-tls-gtls-x509name-legacy.sh35
-rwxr-xr-xtests/imtcp-tls-gtls-x509name.sh32
-rwxr-xr-xtests/imtcp-tls-input-2certs.sh36
-rwxr-xr-xtests/imtcp-tls-input-basic.sh28
-rwxr-xr-xtests/imtcp-tls-no-lstn-startup.sh26
-rwxr-xr-xtests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh40
-rwxr-xr-xtests/imtcp-tls-ossl-basic-tlscommands.sh53
-rwxr-xr-xtests/imtcp-tls-ossl-basic-verifydepth.sh30
-rwxr-xr-xtests/imtcp-tls-ossl-basic-vg.sh9
-rwxr-xr-xtests/imtcp-tls-ossl-basic.sh33
-rwxr-xr-xtests/imtcp-tls-ossl-error-ca.sh23
-rwxr-xr-xtests/imtcp-tls-ossl-error-cert.sh24
-rwxr-xr-xtests/imtcp-tls-ossl-error-key.sh24
-rwxr-xr-xtests/imtcp-tls-ossl-error-key2.sh23
-rwxr-xr-xtests/imtcp-tls-ossl-input-2certs.sh36
-rwxr-xr-xtests/imtcp-tls-ossl-input-basic.sh33
-rwxr-xr-xtests/imtcp-tls-ossl-invalid-verifydepth.sh20
-rwxr-xr-xtests/imtcp-tls-ossl-x509fingerprint.sh34
-rwxr-xr-xtests/imtcp-tls-ossl-x509name.sh34
-rwxr-xr-xtests/imtcp-tls-ossl-x509valid.sh33
-rwxr-xr-xtests/imtcp_addtlframedelim.sh21
-rwxr-xr-xtests/imtcp_addtlframedelim_on_input.sh21
-rwxr-xr-xtests/imtcp_conndrop.sh30
-rwxr-xr-xtests/imtcp_conndrop_tls-vg.sh6
-rwxr-xr-xtests/imtcp_conndrop_tls.sh34
-rwxr-xr-xtests/imtcp_incomplete_frame_at_end.sh27
-rwxr-xr-xtests/imtcp_no_octet_counted.sh21
-rwxr-xr-xtests/imtcp_spframingfix.sh21
-rwxr-xr-xtests/imtuxedoulog_data.sh40
-rwxr-xr-xtests/imtuxedoulog_errmsg_no_params-vg.sh4
-rwxr-xr-xtests/imtuxedoulog_errmsg_no_params.sh17
-rwxr-xr-xtests/imudp_thread_hang.sh20
-rwxr-xr-xtests/imuxsock_ccmiddle.sh28
-rwxr-xr-xtests/imuxsock_ccmiddle_root.sh32
-rwxr-xr-xtests/imuxsock_ccmiddle_syssock.sh35
-rwxr-xr-xtests/imuxsock_hostname.sh32
-rwxr-xr-xtests/imuxsock_legacy.sh23
-rwxr-xr-xtests/imuxsock_logger.sh20
-rwxr-xr-xtests/imuxsock_logger_err.sh29
-rwxr-xr-xtests/imuxsock_logger_parserchain.sh26
-rwxr-xr-xtests/imuxsock_logger_ratelimit.sh47
-rwxr-xr-xtests/imuxsock_logger_root.sh29
-rwxr-xr-xtests/imuxsock_logger_ruleset.sh28
-rwxr-xr-xtests/imuxsock_logger_ruleset_ratelimit.sh35
-rwxr-xr-xtests/imuxsock_logger_syssock.sh24
-rwxr-xr-xtests/imuxsock_traillf.sh25
-rwxr-xr-xtests/imuxsock_traillf_root.sh35
-rwxr-xr-xtests/imuxsock_traillf_syssock.sh27
-rwxr-xr-xtests/incltest.sh12
-rwxr-xr-xtests/incltest_dir.sh24
-rwxr-xr-xtests/incltest_dir_empty_wildcard.sh17
-rwxr-xr-xtests/incltest_dir_wildcard.sh12
-rwxr-xr-xtests/include-obj-in-if-vg.sh19
-rwxr-xr-xtests/include-obj-outside-control-flow-vg.sh23
-rwxr-xr-xtests/include-obj-text-from-file-noexist.sh15
-rwxr-xr-xtests/include-obj-text-from-file.sh18
-rwxr-xr-xtests/include-obj-text-vg.sh21
-rw-r--r--tests/inputfilegen.c234
-rwxr-xr-xtests/inputname-imtcp.sh32
-rwxr-xr-xtests/internal-errmsg-memleak-vg.sh37
-rwxr-xr-xtests/invalid_nested_include.sh28
-rw-r--r--tests/journal_print.c68
-rwxr-xr-xtests/json-nonstring.sh36
-rwxr-xr-xtests/json-onempty-at-end.sh23
-rwxr-xr-xtests/json_array_looping-vg.sh61
-rwxr-xr-xtests/json_array_looping.sh52
-rwxr-xr-xtests/json_array_subscripting.sh28
-rwxr-xr-xtests/json_nonarray_looping.sh42
-rwxr-xr-xtests/json_null-vg.sh38
-rwxr-xr-xtests/json_null.sh31
-rwxr-xr-xtests/json_null_array-vg.sh35
-rwxr-xr-xtests/json_null_array.sh28
-rwxr-xr-xtests/json_object_looping-vg.sh71
-rwxr-xr-xtests/json_object_looping.sh63
-rwxr-xr-xtests/json_object_suicide_in_loop-vg.sh53
-rwxr-xr-xtests/json_var_case.sh32
-rwxr-xr-xtests/json_var_cmpr.sh38
-rwxr-xr-xtests/kafka-selftest.sh60
-rwxr-xr-xtests/key_dereference_on_uninitialized_variable_space.sh31
-rwxr-xr-xtests/killrsyslog.sh16
-rw-r--r--tests/known_issues.supp62
-rwxr-xr-xtests/libdbi-asyn.sh30
-rwxr-xr-xtests/libdbi-basic-vg.sh6
-rwxr-xr-xtests/libdbi-basic.sh23
-rw-r--r--tests/libmaxmindb.supp57
-rwxr-xr-xtests/linkedlistqueue.sh22
-rw-r--r--tests/linux_localtime_r.supp126
-rwxr-xr-xtests/loadbalance.sh44
-rwxr-xr-xtests/localvar-concurrency.sh39
-rwxr-xr-xtests/lookup_table-hup-backgrounded.sh51
-rwxr-xr-xtests/lookup_table-vg.sh5
-rwxr-xr-xtests/lookup_table.sh49
-rwxr-xr-xtests/lookup_table_bad_configs-vg.sh5
-rwxr-xr-xtests/lookup_table_bad_configs.sh160
-rwxr-xr-xtests/lookup_table_no_hup_reload-vg.sh5
-rwxr-xr-xtests/lookup_table_no_hup_reload.sh34
-rwxr-xr-xtests/lookup_table_rscript_reload-vg.sh5
-rwxr-xr-xtests/lookup_table_rscript_reload.sh53
-rwxr-xr-xtests/lookup_table_rscript_reload_without_stub-vg.sh5
-rwxr-xr-xtests/lookup_table_rscript_reload_without_stub.sh51
-rwxr-xr-xtests/mainq_actq_DA.sh24
-rw-r--r--tests/mangle_qi.c113
-rwxr-xr-xtests/mangle_qi_usage_output.sh14
-rwxr-xr-xtests/manyptcp.sh22
-rwxr-xr-xtests/manytcp-too-few-tls-vg.sh42
-rwxr-xr-xtests/manytcp.sh27
-rw-r--r--tests/miniamqpsrvr.c658
-rwxr-xr-xtests/minitcpsrv_usage_output.sh14
-rw-r--r--tests/minitcpsrvr.c131
-rwxr-xr-xtests/mmanon_both_modes_compatible.sh31
-rwxr-xr-xtests/mmanon_ipv6_port.sh46
-rwxr-xr-xtests/mmanon_random_128_ipv6.sh65
-rwxr-xr-xtests/mmanon_random_32_ipv4.sh65
-rwxr-xr-xtests/mmanon_random_cons_128_ipembedded.sh82
-rwxr-xr-xtests/mmanon_random_cons_128_ipv6.sh82
-rwxr-xr-xtests/mmanon_random_cons_32_ipv4.sh92
-rwxr-xr-xtests/mmanon_recognize_ipembedded.sh63
-rwxr-xr-xtests/mmanon_recognize_ipv4.sh79
-rwxr-xr-xtests/mmanon_recognize_ipv6.sh55
-rwxr-xr-xtests/mmanon_simple_12_ipv4.sh44
-rwxr-xr-xtests/mmanon_simple_33_ipv4.sh84
-rwxr-xr-xtests/mmanon_simple_8_ipv4.sh31
-rwxr-xr-xtests/mmanon_simple_mallformed_ipv4.sh37
-rwxr-xr-xtests/mmanon_with_debug.sh82
-rwxr-xr-xtests/mmanon_zero_128_ipv6.sh46
-rwxr-xr-xtests/mmanon_zero_12_ipv4.sh31
-rwxr-xr-xtests/mmanon_zero_33_ipv4.sh42
-rwxr-xr-xtests/mmanon_zero_50_ipv6.sh38
-rwxr-xr-xtests/mmanon_zero_64_ipv6.sh37
-rwxr-xr-xtests/mmanon_zero_8_ipv4.sh31
-rwxr-xr-xtests/mmanon_zero_96_ipv6.sh38
-rwxr-xr-xtests/mmdarwin_errmsg_no_params.sh16
-rwxr-xr-xtests/mmdarwin_errmsg_no_sock-vg.sh4
-rwxr-xr-xtests/mmdarwin_errmsg_no_sock.sh16
-rwxr-xr-xtests/mmdb-container-empty.sh23
-rwxr-xr-xtests/mmdb-container.sh23
-rwxr-xr-xtests/mmdb-multilevel-vg.sh30
-rwxr-xr-xtests/mmdb-space.sh29
-rwxr-xr-xtests/mmdb-vg.sh27
-rw-r--r--tests/mmdb.rb3
-rwxr-xr-xtests/mmdb.sh29
-rwxr-xr-xtests/mmexternal-InvldProg-vg.sh33
-rwxr-xr-xtests/mmexternal-SegFault-empty-jroot-vg.sh23
-rwxr-xr-xtests/mmexternal-SegFault.sh25
-rwxr-xr-xtests/mmjsonparse-invalid-containerName.sh32
-rwxr-xr-xtests/mmjsonparse-w-o-cookie-multi-spaces.sh25
-rwxr-xr-xtests/mmjsonparse-w-o-cookie.sh25
-rwxr-xr-xtests/mmjsonparse_cim.sh26
-rwxr-xr-xtests/mmjsonparse_cim2.sh25
-rwxr-xr-xtests/mmjsonparse_extra_data-vg.sh31
-rwxr-xr-xtests/mmjsonparse_localvar.sh25
-rwxr-xr-xtests/mmjsonparse_simple.sh26
-rwxr-xr-xtests/mmkubernetes-basic-vg.sh187
-rw-r--r--tests/mmkubernetes-basic.out.json376
-rwxr-xr-xtests/mmkubernetes-basic.sh187
-rwxr-xr-xtests/mmkubernetes-cache-expire-vg.sh12
-rw-r--r--tests/mmkubernetes-cache-expire.out.expected109
-rwxr-xr-xtests/mmkubernetes-cache-expire.sh167
-rw-r--r--tests/mmkubernetes.supp16
-rw-r--r--tests/mmkubernetes_test_server.py165
-rwxr-xr-xtests/mmnormalize_parsesuccess-vg.sh4
-rwxr-xr-xtests/mmnormalize_parsesuccess.sh27
-rwxr-xr-xtests/mmnormalize_processing_test1.sh70
-rwxr-xr-xtests/mmnormalize_processing_test2.sh70
-rwxr-xr-xtests/mmnormalize_processing_test3.sh70
-rwxr-xr-xtests/mmnormalize_processing_test4.sh39
-rwxr-xr-xtests/mmnormalize_regex.sh28
-rwxr-xr-xtests/mmnormalize_regex_defaulted.sh28
-rwxr-xr-xtests/mmnormalize_regex_disabled.sh28
-rwxr-xr-xtests/mmnormalize_rule_from_array.sh33
-rwxr-xr-xtests/mmnormalize_rule_from_string.sh33
-rwxr-xr-xtests/mmnormalize_tokenized.sh46
-rwxr-xr-xtests/mmnormalize_variable.sh31
-rwxr-xr-xtests/mmpstrucdata-case.sh26
-rwxr-xr-xtests/mmpstrucdata-escaping.sh21
-rwxr-xr-xtests/mmpstrucdata-invalid-vg.sh33
-rwxr-xr-xtests/mmpstrucdata-vg.sh34
-rwxr-xr-xtests/mmpstrucdata.sh23
-rwxr-xr-xtests/mmrm1stspace-basic.sh32
-rwxr-xr-xtests/mmtaghostname_server.sh28
-rwxr-xr-xtests/mmtaghostname_tag.sh27
-rwxr-xr-xtests/mmutf8fix_no_error.sh96
-rwxr-xr-xtests/msg-deadlock-headerless-noappname.sh20
-rwxr-xr-xtests/msgdup.sh32
-rwxr-xr-xtests/msgdup_props.sh64
-rwxr-xr-xtests/msgvar-concurrency-array-event.tags.sh34
-rwxr-xr-xtests/msgvar-concurrency-array.sh34
-rwxr-xr-xtests/msgvar-concurrency.sh35
-rw-r--r--tests/msleep.c58
-rwxr-xr-xtests/msleep_usage_output.sh14
-rwxr-xr-xtests/multiple_lookup_tables-vg.sh5
-rwxr-xr-xtests/multiple_lookup_tables.sh46
-rwxr-xr-xtests/mysql-actq-mt-withpause-vg.sh4
-rwxr-xr-xtests/mysql-actq-mt-withpause.sh37
-rwxr-xr-xtests/mysql-actq-mt.sh30
-rwxr-xr-xtests/mysql-asyn-vg.sh4
-rwxr-xr-xtests/mysql-asyn.sh21
-rwxr-xr-xtests/mysql-basic-cnf6.sh21
-rwxr-xr-xtests/mysql-basic-vg.sh4
-rwxr-xr-xtests/mysql-basic.sh23
-rwxr-xr-xtests/mysqld-start.sh28
-rwxr-xr-xtests/mysqld-stop.sh14
-rwxr-xr-xtests/nested-call-shutdown.sh35
-rwxr-xr-xtests/no-dynstats-json.sh24
-rwxr-xr-xtests/no-dynstats.sh24
-rwxr-xr-xtests/no-parser-errmsg.sh25
-rwxr-xr-xtests/no-parser-vg.sh26
-rwxr-xr-xtests/now-unixtimestamp.sh32
-rwxr-xr-xtests/now-utc-casecmp.sh36
-rwxr-xr-xtests/now-utc-ymd.sh29
-rwxr-xr-xtests/now-utc.sh30
-rwxr-xr-xtests/now_family_utc.sh32
-rwxr-xr-xtests/omamqp1-basic-vg.sh3
-rwxr-xr-xtests/omamqp1-basic.sh70
-rw-r--r--tests/omamqp1-common.sh50
-rwxr-xr-xtests/omazureeventhubs-basic-vg.sh6
-rwxr-xr-xtests/omazureeventhubs-basic.sh123
-rwxr-xr-xtests/omazureeventhubs-interrupt-vg.sh5
-rwxr-xr-xtests/omazureeventhubs-interrupt.sh165
-rwxr-xr-xtests/omazureeventhubs-list.sh137
-rwxr-xr-xtests/omazureeventhubs-stress.sh137
-rwxr-xr-xtests/omfile-module-params.sh19
-rwxr-xr-xtests/omfile-null-filename.sh22
-rwxr-xr-xtests/omfile-outchannel-many.sh54
-rwxr-xr-xtests/omfile-outchannel.sh23
-rwxr-xr-xtests/omfile-read-only-errmsg.sh33
-rwxr-xr-xtests/omfile-read-only.sh35
-rwxr-xr-xtests/omfile-sizelimitcmd-many.sh36
-rwxr-xr-xtests/omfile-whitespace-filename.sh21
-rwxr-xr-xtests/omfile_both_files_set.sh45
-rwxr-xr-xtests/omfile_hup-vg.sh4
-rwxr-xr-xtests/omfile_hup.sh29
-rwxr-xr-xtests/omfwd-errfile-maxsize-filled.sh18
-rwxr-xr-xtests/omfwd-errfile-maxsize.sh17
-rwxr-xr-xtests/omfwd-keepalive.sh36
-rwxr-xr-xtests/omfwd-tls-invalid-permitExpiredCerts.sh13
-rwxr-xr-xtests/omfwd_fast_imuxsock.sh94
-rwxr-xr-xtests/omfwd_impstats-tcp.sh41
-rwxr-xr-xtests/omfwd_impstats-udp.sh35
-rwxr-xr-xtests/omhttp-auth-vg.sh3
-rwxr-xr-xtests/omhttp-auth.sh44
-rwxr-xr-xtests/omhttp-basic-vg.sh3
-rwxr-xr-xtests/omhttp-basic.sh42
-rwxr-xr-xtests/omhttp-batch-dynrestpath.sh49
-rwxr-xr-xtests/omhttp-batch-fail-with-400.sh51
-rwxr-xr-xtests/omhttp-batch-jsonarray-compress-vg.sh3
-rwxr-xr-xtests/omhttp-batch-jsonarray-compress.sh47
-rwxr-xr-xtests/omhttp-batch-jsonarray-retry-vg.sh3
-rwxr-xr-xtests/omhttp-batch-jsonarray-retry.sh77
-rwxr-xr-xtests/omhttp-batch-jsonarray-vg.sh3
-rwxr-xr-xtests/omhttp-batch-jsonarray.sh45
-rwxr-xr-xtests/omhttp-batch-kafkarest-retry-vg.sh3
-rwxr-xr-xtests/omhttp-batch-kafkarest-retry.sh77
-rwxr-xr-xtests/omhttp-batch-kafkarest.sh46
-rwxr-xr-xtests/omhttp-batch-lokirest-retry-vg.sh3
-rwxr-xr-xtests/omhttp-batch-lokirest-retry.sh77
-rwxr-xr-xtests/omhttp-batch-lokirest-vg.sh5
-rwxr-xr-xtests/omhttp-batch-lokirest.sh46
-rwxr-xr-xtests/omhttp-batch-newline.sh46
-rwxr-xr-xtests/omhttp-dynrestpath.sh46
-rwxr-xr-xtests/omhttp-httpheaderkey.sh43
-rwxr-xr-xtests/omhttp-multiplehttpheaders.sh45
-rwxr-xr-xtests/omhttp-retry-vg.sh3
-rwxr-xr-xtests/omhttp-retry.sh46
-rw-r--r--tests/omhttp_server.py135
-rwxr-xr-xtests/omjournal-abort-no-template.sh20
-rwxr-xr-xtests/omjournal-abort-template.sh21
-rwxr-xr-xtests/omjournal-basic-no-template.sh26
-rwxr-xr-xtests/omjournal-basic-template.sh32
-rwxr-xr-xtests/omkafka-vg.sh3
-rwxr-xr-xtests/omkafka.sh129
-rwxr-xr-xtests/omkafkadynakey.sh154
-rwxr-xr-xtests/ommail_errmsg_no_params.sh20
-rwxr-xr-xtests/omod-if-array-udp.sh29
-rwxr-xr-xtests/omod-if-array.sh29
-rwxr-xr-xtests/omprog-close-unresponsive-noterm.sh53
-rwxr-xr-xtests/omprog-close-unresponsive-vg.sh38
-rwxr-xr-xtests/omprog-close-unresponsive.sh55
-rwxr-xr-xtests/omprog-defaults-vg.sh29
-rwxr-xr-xtests/omprog-defaults.sh55
-rwxr-xr-xtests/omprog-feedback-mt.sh53
-rwxr-xr-xtests/omprog-feedback-timeout.sh63
-rwxr-xr-xtests/omprog-feedback-vg.sh32
-rwxr-xr-xtests/omprog-feedback.sh67
-rwxr-xr-xtests/omprog-if-error.sh41
-rwxr-xr-xtests/omprog-output-capture-mt.sh98
-rwxr-xr-xtests/omprog-output-capture-vg.sh5
-rwxr-xr-xtests/omprog-output-capture.sh57
-rwxr-xr-xtests/omprog-restart-terminated-outfile.sh135
-rwxr-xr-xtests/omprog-restart-terminated-vg.sh4
-rwxr-xr-xtests/omprog-restart-terminated.sh155
-rwxr-xr-xtests/omprog-single-instance-outfile.sh71
-rwxr-xr-xtests/omprog-single-instance-vg.sh4
-rwxr-xr-xtests/omprog-single-instance.sh63
-rwxr-xr-xtests/omprog-transactions-failed-commits.sh158
-rwxr-xr-xtests/omprog-transactions-failed-messages.sh159
-rwxr-xr-xtests/omprog-transactions-vg.sh37
-rwxr-xr-xtests/omprog-transactions.sh140
-rwxr-xr-xtests/omrabbitmq_data_1server-vg.sh4
-rwxr-xr-xtests/omrabbitmq_data_1server.sh48
-rwxr-xr-xtests/omrabbitmq_data_2servers.sh50
-rwxr-xr-xtests/omrabbitmq_error_server0.sh42
-rwxr-xr-xtests/omrabbitmq_error_server1.sh42
-rwxr-xr-xtests/omrabbitmq_error_server2.sh42
-rwxr-xr-xtests/omrabbitmq_error_server3.sh41
-rwxr-xr-xtests/omrabbitmq_json.sh45
-rwxr-xr-xtests/omrabbitmq_no_params.sh16
-rwxr-xr-xtests/omrabbitmq_params_invalid0.sh16
-rwxr-xr-xtests/omrabbitmq_params_invalid1.sh16
-rwxr-xr-xtests/omrabbitmq_params_invalid2.sh16
-rwxr-xr-xtests/omrabbitmq_params_invalid3.sh16
-rwxr-xr-xtests/omrabbitmq_params_missing0.sh16
-rwxr-xr-xtests/omrabbitmq_params_missing1.sh16
-rwxr-xr-xtests/omrabbitmq_params_missing2.sh16
-rwxr-xr-xtests/omrabbitmq_raw.sh40
-rwxr-xr-xtests/omrelp-invld-tlslib.sh15
-rw-r--r--tests/omrelp_dflt_port.c9
-rwxr-xr-xtests/omrelp_errmsg_no_connect.sh17
-rwxr-xr-xtests/omrelp_wrong_authmode.sh21
-rwxr-xr-xtests/omruleset-queue.sh45
-rwxr-xr-xtests/omruleset.sh34
-rwxr-xr-xtests/omsnmp_errmsg_no_params.sh20
-rwxr-xr-xtests/omstdout-basic.sh27
-rwxr-xr-xtests/omtcl.sh19
-rw-r--r--tests/omtcl.tcl9
-rwxr-xr-xtests/omudpspoof_errmsg_no_params.sh16
-rwxr-xr-xtests/omusrmsg-errmsg-no-params.sh14
-rwxr-xr-xtests/omusrmsg-noabort-vg.sh4
-rwxr-xr-xtests/omusrmsg-noabort.sh23
-rwxr-xr-xtests/operatingstate-basic.sh19
-rwxr-xr-xtests/operatingstate-empty.sh22
-rwxr-xr-xtests/operatingstate-unclean.sh25
-rw-r--r--tests/ourtail.c46
-rw-r--r--tests/override_getaddrinfo.c28
-rw-r--r--tests/override_gethostname.c22
-rw-r--r--tests/override_gethostname_nonfqdn.c14
-rwxr-xr-xtests/parsertest-parse-3164-buggyday-udp.sh32
-rwxr-xr-xtests/parsertest-parse-3164-buggyday.sh32
-rwxr-xr-xtests/parsertest-parse-nodate-udp.sh28
-rwxr-xr-xtests/parsertest-parse-nodate.sh27
-rwxr-xr-xtests/parsertest-parse1-udp.sh83
-rwxr-xr-xtests/parsertest-parse1.sh82
-rwxr-xr-xtests/parsertest-parse2-udp.sh31
-rwxr-xr-xtests/parsertest-parse2.sh31
-rwxr-xr-xtests/parsertest-parse3-udp.sh32
-rwxr-xr-xtests/parsertest-parse3.sh32
-rwxr-xr-xtests/parsertest-parse_8bit_escape-udp.sh31
-rwxr-xr-xtests/parsertest-parse_8bit_escape.sh31
-rwxr-xr-xtests/parsertest-parse_invld_regex-udp.sh30
-rwxr-xr-xtests/parsertest-parse_invld_regex.sh30
-rwxr-xr-xtests/parsertest-snare_ccoff_udp.sh28
-rwxr-xr-xtests/parsertest-snare_ccoff_udp2.sh32
-rwxr-xr-xtests/perctile-simple-vg.sh3
-rwxr-xr-xtests/perctile-simple.sh62
-rwxr-xr-xtests/pgsql-actq-mt-withpause-vg.sh40
-rwxr-xr-xtests/pgsql-actq-mt-withpause.sh39
-rwxr-xr-xtests/pgsql-basic-cnf6-vg.sh27
-rwxr-xr-xtests/pgsql-basic-cnf6.sh28
-rwxr-xr-xtests/pgsql-basic-threads-cnf6.sh30
-rwxr-xr-xtests/pgsql-basic-vg.sh25
-rwxr-xr-xtests/pgsql-basic.sh24
-rwxr-xr-xtests/pgsql-template-cnf6-vg.sh38
-rwxr-xr-xtests/pgsql-template-cnf6.sh37
-rwxr-xr-xtests/pgsql-template-threads-cnf6.sh36
-rwxr-xr-xtests/pgsql-template-vg.sh30
-rwxr-xr-xtests/pgsql-template.sh32
-rwxr-xr-xtests/pipe_noreader.sh36
-rwxr-xr-xtests/pipeaction.sh46
-rwxr-xr-xtests/pmdb2diag_parse.sh65
-rwxr-xr-xtests/pmlastmsg-udp.sh44
-rwxr-xr-xtests/pmlastmsg.sh44
-rwxr-xr-xtests/pmnormalize-basic-vg.sh4
-rwxr-xr-xtests/pmnormalize-basic.sh29
-rwxr-xr-xtests/pmnormalize-invld-rulebase-vg.sh4
-rwxr-xr-xtests/pmnormalize-invld-rulebase.sh15
-rwxr-xr-xtests/pmnormalize-neither_rule_rulebase-vg.sh4
-rwxr-xr-xtests/pmnormalize-neither_rule_rulebase.sh15
-rwxr-xr-xtests/pmnormalize-rule-vg.sh4
-rwxr-xr-xtests/pmnormalize-rule.sh29
-rwxr-xr-xtests/pmnormalize-rule_and_rulebase-vg.sh4
-rwxr-xr-xtests/pmnormalize-rule_and_rulebase.sh15
-rwxr-xr-xtests/pmnormalize-rule_invld-data-vg.sh4
-rwxr-xr-xtests/pmnormalize-rule_invld-data.sh28
-rwxr-xr-xtests/pmnull-basic.sh26
-rwxr-xr-xtests/pmnull-withparams.sh26
-rwxr-xr-xtests/pmrfc3164-AtSignsInHostname.sh28
-rwxr-xr-xtests/pmrfc3164-AtSignsInHostname_off.sh30
-rwxr-xr-xtests/pmrfc3164-defaultTag.sh29
-rwxr-xr-xtests/pmrfc3164-json.sh32
-rwxr-xr-xtests/pmrfc3164-msgFirstSpace.sh32
-rwxr-xr-xtests/pmrfc3164-tagEndingByColon.sh32
-rwxr-xr-xtests/pmsnare-ccbackslash-udp.sh38
-rwxr-xr-xtests/pmsnare-ccbackslash.sh39
-rwxr-xr-xtests/pmsnare-cccstyle-udp.sh41
-rwxr-xr-xtests/pmsnare-cccstyle.sh43
-rwxr-xr-xtests/pmsnare-ccdefault-udp.sh42
-rwxr-xr-xtests/pmsnare-ccdefault.sh42
-rwxr-xr-xtests/pmsnare-ccoff-udp.sh36
-rwxr-xr-xtests/pmsnare-ccoff.sh36
-rwxr-xr-xtests/pmsnare-default-udp.sh45
-rwxr-xr-xtests/pmsnare-default.sh45
-rwxr-xr-xtests/pmsnare-modoverride-udp.sh47
-rwxr-xr-xtests/pmsnare-modoverride.sh48
-rwxr-xr-xtests/privdrop_common.sh110
-rwxr-xr-xtests/privdropabortonidfail.sh41
-rwxr-xr-xtests/privdropabortonidfaillegacy.sh38
-rwxr-xr-xtests/privdropgroup.sh28
-rwxr-xr-xtests/privdropgroupid.sh22
-rwxr-xr-xtests/privdropuser.sh21
-rwxr-xr-xtests/privdropuserid.sh21
-rwxr-xr-xtests/prop-all-json-concurrency.sh34
-rwxr-xr-xtests/prop-jsonmesg-vg.sh23
-rwxr-xr-xtests/prop-programname-with-slashes.sh27
-rwxr-xr-xtests/prop-programname.sh20
-rwxr-xr-xtests/proprepltest-nolimittag-udp.sh34
-rwxr-xr-xtests/proprepltest-nolimittag.sh34
-rwxr-xr-xtests/proprepltest-rfctag-udp.sh34
-rwxr-xr-xtests/proprepltest-rfctag.sh34
-rwxr-xr-xtests/queue-direct-with-no-params.sh12
-rwxr-xr-xtests/queue-direct-with-params-given.sh12
-rwxr-xr-xtests/queue-encryption-da.sh34
-rwxr-xr-xtests/queue-encryption-disk.sh34
-rwxr-xr-xtests/queue-encryption-disk_keyfile-vg.sh37
-rwxr-xr-xtests/queue-encryption-disk_keyfile.sh35
-rwxr-xr-xtests/queue-encryption-disk_keyprog.sh39
-rwxr-xr-xtests/queue-minbatch-queuefull.sh22
-rwxr-xr-xtests/queue-minbatch.sh42
-rwxr-xr-xtests/queue-persist-drvr.sh54
-rwxr-xr-xtests/queue-persist.sh13
-rwxr-xr-xtests/queue_warnmsg-oversize.sh15
-rwxr-xr-xtests/random.sh30
-rw-r--r--tests/randomgen.c130
-rwxr-xr-xtests/rawmsg-after-pri.sh31
-rwxr-xr-xtests/rcvr_fail_restore.sh168
-rwxr-xr-xtests/relp_tls_certificate_not_found.sh30
-rwxr-xr-xtests/rfc5424parser-sp_at_msg_start.sh25
-rwxr-xr-xtests/rfc5424parser.sh24
-rwxr-xr-xtests/rs-cnum.sh26
-rwxr-xr-xtests/rs-int2hex.sh27
-rwxr-xr-xtests/rs-substring.sh26
-rwxr-xr-xtests/rs_optimizer_pri.sh28
-rwxr-xr-xtests/rscript-config_enable-off-vg.sh22
-rwxr-xr-xtests/rscript-config_enable-on.sh24
-rwxr-xr-xtests/rscript_backticks-vg.sh17
-rwxr-xr-xtests/rscript_backticks_empty_envvar-vg.sh16
-rwxr-xr-xtests/rscript_bare_var_root-empty.sh31
-rwxr-xr-xtests/rscript_bare_var_root.sh32
-rwxr-xr-xtests/rscript_compare-common.sh53
-rwxr-xr-xtests/rscript_compare_num-num-vg.sh5
-rwxr-xr-xtests/rscript_compare_num-num.sh4
-rwxr-xr-xtests/rscript_compare_num-numstr-vg.sh5
-rwxr-xr-xtests/rscript_compare_num-numstr.sh4
-rwxr-xr-xtests/rscript_compare_num-str-vg.sh5
-rwxr-xr-xtests/rscript_compare_num-str.sh4
-rwxr-xr-xtests/rscript_compare_numstr-num-vg.sh5
-rwxr-xr-xtests/rscript_compare_numstr-num.sh4
-rwxr-xr-xtests/rscript_compare_numstr-numstr-vg.sh5
-rwxr-xr-xtests/rscript_compare_numstr-numstr.sh4
-rwxr-xr-xtests/rscript_compare_numstr-str-vg.sh5
-rwxr-xr-xtests/rscript_compare_numstr-str.sh4
-rwxr-xr-xtests/rscript_compare_str-num-vg.sh5
-rwxr-xr-xtests/rscript_compare_str-num.sh4
-rwxr-xr-xtests/rscript_compare_str-numstr-vg.sh5
-rwxr-xr-xtests/rscript_compare_str-numstr.sh4
-rwxr-xr-xtests/rscript_compare_str-str-vg.sh5
-rwxr-xr-xtests/rscript_compare_str-str.sh4
-rwxr-xr-xtests/rscript_contains.sh17
-rwxr-xr-xtests/rscript_eq.sh29
-rwxr-xr-xtests/rscript_eq_var.sh72
-rwxr-xr-xtests/rscript_exists-not1.sh22
-rwxr-xr-xtests/rscript_exists-not2.sh22
-rwxr-xr-xtests/rscript_exists-not3.sh22
-rwxr-xr-xtests/rscript_exists-not4.sh22
-rwxr-xr-xtests/rscript_exists-yes.sh22
-rwxr-xr-xtests/rscript_exists-yes2.sh22
-rwxr-xr-xtests/rscript_field-vg.sh34
-rwxr-xr-xtests/rscript_field.sh26
-rwxr-xr-xtests/rscript_format_time.sh45
-rwxr-xr-xtests/rscript_ge.sh28
-rwxr-xr-xtests/rscript_ge_var.sh75
-rwxr-xr-xtests/rscript_get_property-vg.sh4
-rwxr-xr-xtests/rscript_get_property.sh70
-rwxr-xr-xtests/rscript_gt.sh27
-rwxr-xr-xtests/rscript_gt_var.sh69
-rwxr-xr-xtests/rscript_hash32-vg.sh28
-rwxr-xr-xtests/rscript_hash32.sh27
-rwxr-xr-xtests/rscript_hash64-vg.sh28
-rwxr-xr-xtests/rscript_hash64.sh27
-rwxr-xr-xtests/rscript_http_request-vg.sh4
-rwxr-xr-xtests/rscript_http_request.sh47
-rwxr-xr-xtests/rscript_int2Hex.sh27
-rwxr-xr-xtests/rscript_ipv42num.sh51
-rwxr-xr-xtests/rscript_is_time.sh81
-rwxr-xr-xtests/rscript_le.sh27
-rwxr-xr-xtests/rscript_le_var.sh75
-rwxr-xr-xtests/rscript_lt.sh27
-rwxr-xr-xtests/rscript_lt_var.sh69
-rwxr-xr-xtests/rscript_ne.sh33
-rwxr-xr-xtests/rscript_ne_var.sh75
-rwxr-xr-xtests/rscript_num2ipv4.sh42
-rwxr-xr-xtests/rscript_number_comparison_LE-vg.sh3
-rwxr-xr-xtests/rscript_number_comparison_LE.sh24
-rwxr-xr-xtests/rscript_number_comparison_LT.sh24
-rwxr-xr-xtests/rscript_optimizer1.sh27
-rwxr-xr-xtests/rscript_parse_json-vg.sh25
-rwxr-xr-xtests/rscript_parse_json.sh24
-rwxr-xr-xtests/rscript_parse_time.sh122
-rw-r--r--tests/rscript_parse_time_get-ts.py152
-rwxr-xr-xtests/rscript_previous_action_suspended.sh27
-rwxr-xr-xtests/rscript_prifilt.sh25
-rwxr-xr-xtests/rscript_privdropgroup.sh21
-rwxr-xr-xtests/rscript_privdropgroupid.sh21
-rwxr-xr-xtests/rscript_privdropuser.sh21
-rwxr-xr-xtests/rscript_privdropuserid.sh21
-rwxr-xr-xtests/rscript_random.sh25
-rwxr-xr-xtests/rscript_re_extract.sh25
-rwxr-xr-xtests/rscript_re_extract_i.sh21
-rwxr-xr-xtests/rscript_re_match-dbl_quotes.sh16
-rwxr-xr-xtests/rscript_re_match.sh21
-rwxr-xr-xtests/rscript_re_match_i.sh21
-rwxr-xr-xtests/rscript_replace.sh29
-rwxr-xr-xtests/rscript_replace_complex.sh31
-rwxr-xr-xtests/rscript_ruleset_call.sh37
-rwxr-xr-xtests/rscript_ruleset_call_indirect-basic.sh23
-rwxr-xr-xtests/rscript_ruleset_call_indirect-invld.sh32
-rwxr-xr-xtests/rscript_ruleset_call_indirect-var.sh25
-rwxr-xr-xtests/rscript_script_error.sh30
-rwxr-xr-xtests/rscript_set_memleak-vg.sh34
-rwxr-xr-xtests/rscript_set_modify.sh26
-rwxr-xr-xtests/rscript_set_unset_invalid_var.sh41
-rwxr-xr-xtests/rscript_stop.sh28
-rwxr-xr-xtests/rscript_stop2.sh33
-rwxr-xr-xtests/rscript_str2num_negative.sh25
-rwxr-xr-xtests/rscript_substring.sh32
-rwxr-xr-xtests/rscript_trim-vg.sh89
-rwxr-xr-xtests/rscript_trim.sh88
-rwxr-xr-xtests/rscript_unaffected_reset.sh27
-rwxr-xr-xtests/rscript_unflatten_arg1_unsuitable-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_arg1_unsuitable.sh30
-rwxr-xr-xtests/rscript_unflatten_arg2_invalid-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_arg2_invalid.sh31
-rwxr-xr-xtests/rscript_unflatten_conflict1-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_conflict1.sh43
-rwxr-xr-xtests/rscript_unflatten_conflict2-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_conflict2.sh44
-rwxr-xr-xtests/rscript_unflatten_conflict3-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_conflict3.sh43
-rwxr-xr-xtests/rscript_unflatten_key_truncated-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_key_truncated.sh42
-rwxr-xr-xtests/rscript_unflatten_non_object-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_non_object.sh37
-rwxr-xr-xtests/rscript_unflatten_object-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_object.sh39
-rwxr-xr-xtests/rscript_unflatten_object_exclamation-vg.sh3
-rwxr-xr-xtests/rscript_unflatten_object_exclamation.sh34
-rwxr-xr-xtests/rscript_wrap2.sh25
-rwxr-xr-xtests/rscript_wrap3.sh25
-rwxr-xr-xtests/rsf_getenv.sh23
-rwxr-xr-xtests/ruleset-direct-queue.sh27
-rwxr-xr-xtests/rulesetmultiqueue-v6.sh62
-rwxr-xr-xtests/rulesetmultiqueue.sh77
-rw-r--r--tests/set-envvars.in1
-rwxr-xr-xtests/smtradfile-vg.sh4
-rwxr-xr-xtests/smtradfile.sh14
-rwxr-xr-xtests/sndrcv.sh49
-rwxr-xr-xtests/sndrcv_drvr.sh2
-rwxr-xr-xtests/sndrcv_drvr_noexit.sh49
-rwxr-xr-xtests/sndrcv_dtls_anon_ciphers.sh67
-rwxr-xr-xtests/sndrcv_dtls_certvalid-vg.sh9
-rwxr-xr-xtests/sndrcv_dtls_certvalid.sh91
-rwxr-xr-xtests/sndrcv_dtls_certvalid_ciphers.sh74
-rwxr-xr-xtests/sndrcv_dtls_certvalid_missing.sh82
-rwxr-xr-xtests/sndrcv_dtls_certvalid_permitted.sh94
-rwxr-xr-xtests/sndrcv_failover.sh67
-rwxr-xr-xtests/sndrcv_gzip.sh44
-rwxr-xr-xtests/sndrcv_kafka.sh125
-rwxr-xr-xtests/sndrcv_kafka_multi_topics.sh171
-rwxr-xr-xtests/sndrcv_omsnmpv1_udp.sh46
-rwxr-xr-xtests/sndrcv_omsnmpv1_udp_dynsource.sh55
-rwxr-xr-xtests/sndrcv_omsnmpv1_udp_invalidoid.sh46
-rwxr-xr-xtests/sndrcv_omudpspoof-bigmsg.sh83
-rwxr-xr-xtests/sndrcv_omudpspoof.sh65
-rwxr-xr-xtests/sndrcv_omudpspoof_nonstdpt.sh66
-rwxr-xr-xtests/sndrcv_ossl_cert_chain.sh76
-rwxr-xr-xtests/sndrcv_relp-vg-rcvr.sh59
-rwxr-xr-xtests/sndrcv_relp-vg-sender.sh60
-rwxr-xr-xtests/sndrcv_relp.sh43
-rwxr-xr-xtests/sndrcv_relp_dflt_pt.sh54
-rwxr-xr-xtests/sndrcv_relp_rebind.sh48
-rwxr-xr-xtests/sndrcv_relp_tls-cfgcmd.sh70
-rwxr-xr-xtests/sndrcv_relp_tls.sh45
-rwxr-xr-xtests/sndrcv_relp_tls_certvalid.sh65
-rwxr-xr-xtests/sndrcv_relp_tls_chainedcert.sh70
-rwxr-xr-xtests/sndrcv_relp_tls_prio.sh44
-rwxr-xr-xtests/sndrcv_tls_anon_hostname.sh62
-rwxr-xr-xtests/sndrcv_tls_anon_ipv4.sh65
-rwxr-xr-xtests/sndrcv_tls_anon_ipv6.sh67
-rwxr-xr-xtests/sndrcv_tls_anon_rebind.sh64
-rwxr-xr-xtests/sndrcv_tls_certless_clientonly.sh61
-rwxr-xr-xtests/sndrcv_tls_certvalid.sh60
-rwxr-xr-xtests/sndrcv_tls_certvalid_action_level.sh63
-rwxr-xr-xtests/sndrcv_tls_certvalid_expired.sh63
-rwxr-xr-xtests/sndrcv_tls_certvalid_expired_defaultmode.sh61
-rwxr-xr-xtests/sndrcv_tls_certvalid_revoked.sh67
-rwxr-xr-xtests/sndrcv_tls_client_missing_cert.sh65
-rwxr-xr-xtests/sndrcv_tls_gtls_serveranon_gtls_clientanon.sh48
-rwxr-xr-xtests/sndrcv_tls_gtls_serveranon_ossl_clientanon.sh66
-rwxr-xr-xtests/sndrcv_tls_gtls_servercert_gtls_clientanon.sh56
-rwxr-xr-xtests/sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh65
-rwxr-xr-xtests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh65
-rwxr-xr-xtests/sndrcv_tls_ossl_anon_ciphers.sh72
-rwxr-xr-xtests/sndrcv_tls_ossl_anon_ipv4.sh66
-rwxr-xr-xtests/sndrcv_tls_ossl_anon_ipv6.sh4
-rwxr-xr-xtests/sndrcv_tls_ossl_anon_rebind.sh78
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid.sh4
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid_action_level.sh4
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid_ciphers.sh75
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid_expired.sh61
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid_revoked.sh6
-rwxr-xr-xtests/sndrcv_tls_ossl_certvalid_tlscommand.sh81
-rwxr-xr-xtests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh66
-rwxr-xr-xtests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh57
-rwxr-xr-xtests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh66
-rwxr-xr-xtests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh66
-rwxr-xr-xtests/sndrcv_tls_priorityString.sh68
-rwxr-xr-xtests/sndrcv_udp.sh61
-rwxr-xr-xtests/sndrcv_udp_nonstdpt.sh48
-rwxr-xr-xtests/sndrcv_udp_nonstdpt_v6.sh53
-rwxr-xr-xtests/snmptrapreceiver.py104
-rwxr-xr-xtests/sparse_array_lookup_table-vg.sh5
-rwxr-xr-xtests/sparse_array_lookup_table.sh64
-rwxr-xr-xtests/stats-cee-vg.sh36
-rwxr-xr-xtests/stats-cee.sh28
-rwxr-xr-xtests/stats-json-es.sh29
-rwxr-xr-xtests/stats-json-vg.sh37
-rwxr-xr-xtests/stats-json.sh28
-rwxr-xr-xtests/stop-localvar.sh30
-rwxr-xr-xtests/stop-msgvar.sh30
-rwxr-xr-xtests/stop.sh25
-rwxr-xr-xtests/stop_when_array_has_element.sh31
-rwxr-xr-xtests/suspend-omfwd-via-file.sh51
-rwxr-xr-xtests/suspend-via-file.sh68
-rw-r--r--tests/syslog_caller.c151
-rwxr-xr-xtests/tabescape_dflt-udp.sh29
-rwxr-xr-xtests/tabescape_dflt.sh29
-rwxr-xr-xtests/tabescape_off-udp.sh32
-rwxr-xr-xtests/tabescape_off.sh28
-rwxr-xr-xtests/tabescape_on.sh28
-rwxr-xr-xtests/tcp-msgreduc-vg.sh28
-rwxr-xr-xtests/tcp_forwarding_dflt_tpl.sh40
-rwxr-xr-xtests/tcp_forwarding_ns_tpl.sh52
-rwxr-xr-xtests/tcp_forwarding_retries.sh41
-rwxr-xr-xtests/tcp_forwarding_tpl.sh38
-rw-r--r--tests/tcpflood.c2108
-rwxr-xr-xtests/tcpflood_wrong_option_output.sh18
-rwxr-xr-xtests/template-const-jsonf.sh19
-rwxr-xr-xtests/template-json.sh30
-rwxr-xr-xtests/template-pos-from-to-lowercase.sh19
-rwxr-xr-xtests/template-pos-from-to-missing-jsonvar.sh26
-rwxr-xr-xtests/template-pos-from-to-oversize-lowercase.sh26
-rwxr-xr-xtests/template-pos-from-to-oversize.sh56
-rwxr-xr-xtests/template-pos-from-to.sh19
-rwxr-xr-xtests/template-pure-json.sh19
-rwxr-xr-xtests/template-topos-neg.sh19
-rw-r--r--tests/test.mmdbbin0 -> 432 bytes
-rw-r--r--tests/test_id.c39
-rwxr-xr-xtests/test_id_usage_output.sh14
-rwxr-xr-xtests/testsuites/abort-uncleancfg-goodcfg.conf9
-rw-r--r--tests/testsuites/action-tx-errfile.result25
-rw-r--r--tests/testsuites/complex_replace_input4
-rw-r--r--tests/testsuites/date_time_msg2
-rw-r--r--tests/testsuites/docroot/file.txt1
-rw-r--r--tests/testsuites/dynstats_empty_input7
-rw-r--r--tests/testsuites/dynstats_input6
-rw-r--r--tests/testsuites/dynstats_input_12
-rw-r--r--tests/testsuites/dynstats_input_22
-rw-r--r--tests/testsuites/dynstats_input_32
-rw-r--r--tests/testsuites/dynstats_input_more_010
-rw-r--r--tests/testsuites/dynstats_input_more_13
-rw-r--r--tests/testsuites/dynstats_input_more_25
-rw-r--r--tests/testsuites/es.yml95
-rw-r--r--tests/testsuites/htpasswd1
-rw-r--r--tests/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input15
-rw-r--r--tests/testsuites/imhttp-large-data.txt250
-rw-r--r--tests/testsuites/imptcp_framing_regex-oversize.testdata22
-rw-r--r--tests/testsuites/imptcp_framing_regex.testdata18
-rw-r--r--tests/testsuites/imptcp_multi_line.testdata16
-rw-r--r--tests/testsuites/incltest.d/include.conf2
-rw-r--r--tests/testsuites/include-std-omfile-action.conf3
-rw-r--r--tests/testsuites/include-std1-omfile-action.conf5
-rw-r--r--tests/testsuites/include-std2-omfile-action.conf2
-rw-r--r--tests/testsuites/invalid.conf3
-rw-r--r--tests/testsuites/json_array_input1
-rw-r--r--tests/testsuites/json_nonarray_input3
-rw-r--r--tests/testsuites/json_object_input1
-rw-r--r--tests/testsuites/kafka-server.dep_wrk1.properties69
-rw-r--r--tests/testsuites/kafka-server.dep_wrk2.properties69
-rw-r--r--tests/testsuites/kafka-server.dep_wrk3.properties69
-rw-r--r--tests/testsuites/kafka-server.properties69
-rwxr-xr-xtests/testsuites/mmexternal-SegFault-mm-python.py84
-rw-r--r--tests/testsuites/mmnormalize_processing_tests.rulebase14
-rw-r--r--tests/testsuites/mmnormalize_regex.rulebase1
-rw-r--r--tests/testsuites/mmnormalize_tokenized.rulebase5
-rw-r--r--tests/testsuites/mmnormalize_variable.rulebase1
-rw-r--r--tests/testsuites/msgvar-concurrency-array-event.tags.rulebase11
-rw-r--r--tests/testsuites/msgvar-concurrency-array.rulebase11
-rw-r--r--tests/testsuites/mysql-select-msg.sql2
-rw-r--r--tests/testsuites/mysql-truncate.sql2
-rw-r--r--tests/testsuites/no_octet_counted.testdata20
-rwxr-xr-xtests/testsuites/omprog-close-unresponsive-bin.sh32
-rwxr-xr-xtests/testsuites/omprog-defaults-bin.sh14
-rwxr-xr-xtests/testsuites/omprog-feedback-bin.sh33
-rwxr-xr-xtests/testsuites/omprog-feedback-mt-bin.sh31
-rwxr-xr-xtests/testsuites/omprog-feedback-timeout-bin.sh49
-rwxr-xr-xtests/testsuites/omprog-output-capture-bin.sh16
-rwxr-xr-xtests/testsuites/omprog-output-capture-mt-bin.py35
-rwxr-xr-xtests/testsuites/omprog-restart-terminated-bin.sh49
-rwxr-xr-xtests/testsuites/omprog-single-instance-bin.sh25
-rwxr-xr-xtests/testsuites/omprog-transactions-bin.sh60
-rw-r--r--tests/testsuites/pgsql-basic.sql30
-rw-r--r--tests/testsuites/pgsql-select-msg.sql1
-rw-r--r--tests/testsuites/pgsql-select-syslogtag.sql1
-rw-r--r--tests/testsuites/pmnormalize_basic.rulebase1
-rw-r--r--tests/testsuites/regex_input1
-rw-r--r--tests/testsuites/spframingfix.testdata20
-rw-r--r--tests/testsuites/stop_when_array_has_elem_input3
-rw-r--r--tests/testsuites/tokenized_input5
-rw-r--r--tests/testsuites/valid.conf3
-rw-r--r--tests/testsuites/variable_leading_underscore.conf2
-rw-r--r--tests/testsuites/wrap3_input1
-rw-r--r--tests/testsuites/x.509/ca-key.pem182
-rw-r--r--tests/testsuites/x.509/ca.pem27
-rw-r--r--tests/testsuites/x.509/ca.srl1
-rw-r--r--tests/testsuites/x.509/client-cert-new.pem102
-rw-r--r--tests/testsuites/x.509/client-cert.pem27
-rw-r--r--tests/testsuites/x.509/client-expired-cert.pem25
-rw-r--r--tests/testsuites/x.509/client-expired-key.pem134
-rw-r--r--tests/testsuites/x.509/client-key.pem182
-rw-r--r--tests/testsuites/x.509/client-new.csr23
-rw-r--r--tests/testsuites/x.509/client-revoked-key.pem28
-rw-r--r--tests/testsuites/x.509/client-revoked-valid.pem92
-rw-r--r--tests/testsuites/x.509/client-revoked.csr18
-rw-r--r--tests/testsuites/x.509/client-revoked.pem92
-rw-r--r--tests/testsuites/x.509/crl.pem14
-rw-r--r--tests/testsuites/x.509/index.txt3
-rw-r--r--tests/testsuites/x.509/index.txt.attr1
-rw-r--r--tests/testsuites/x.509/machine-cert.pem27
-rw-r--r--tests/testsuites/x.509/machine-key.pem182
-rw-r--r--tests/testsuites/x.509/newcerts/01.pem92
-rw-r--r--tests/testsuites/x.509/newcerts/02.pem92
-rw-r--r--tests/testsuites/x.509/newcerts/03.pem92
-rw-r--r--tests/testsuites/x.509/newcerts/04.pem102
-rw-r--r--tests/testsuites/x.509/openssl-cmds.sh11
-rw-r--r--tests/testsuites/x.509/openssl.cnf41
-rw-r--r--tests/testsuites/x.509/serial1
-rw-r--r--tests/testsuites/xlate.lkp_tbl5
-rw-r--r--tests/testsuites/xlate_array.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_array_empty_table.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_array_misuse.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_array_more.lkp_tbl7
-rw-r--r--tests/testsuites/xlate_array_more_misuse.lkp_tbl7
-rw-r--r--tests/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl13
-rw-r--r--tests/testsuites/xlate_array_no_index.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_array_no_table.lkp_tbl5
-rw-r--r--tests/testsuites/xlate_array_no_value.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_empty_file.lkp_tbl0
-rw-r--r--tests/testsuites/xlate_incorrect_type.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_incorrect_version.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_invalid_json.lkp_tbl4
-rw-r--r--tests/testsuites/xlate_more.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl12
-rw-r--r--tests/testsuites/xlate_sparseArray_empty_table.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_sparseArray_no_index.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_sparseArray_no_table.lkp_tbl5
-rw-r--r--tests/testsuites/xlate_sparseArray_no_value.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_sparse_array.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_sparse_array_more.lkp_tbl7
-rw-r--r--tests/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl12
-rw-r--r--tests/testsuites/xlate_string_empty_table.lkp_tbl6
-rw-r--r--tests/testsuites/xlate_string_no_index.lkp_tbl8
-rw-r--r--tests/testsuites/xlate_string_no_table.lkp_tbl5
-rw-r--r--tests/testsuites/xlate_string_no_value.lkp_tbl8
-rw-r--r--tests/testsuites/zoo.cfg5
-rw-r--r--tests/testsuites/zoo.dep_wrk1.cfg5
-rw-r--r--tests/testsuites/zoo.dep_wrk2.cfg5
-rw-r--r--tests/testsuites/zoo.dep_wrk3.cfg5
-rwxr-xr-xtests/threadingmq.sh35
-rwxr-xr-xtests/threadingmqaq.sh47
-rwxr-xr-xtests/timegenerated-dateordinal-invld.sh62
-rwxr-xr-xtests/timegenerated-dateordinal.sh168
-rwxr-xr-xtests/timegenerated-utc-legacy.sh36
-rwxr-xr-xtests/timegenerated-utc.sh42
-rwxr-xr-xtests/timegenerated-uxtimestamp-invld.sh65
-rwxr-xr-xtests/timegenerated-uxtimestamp.sh207
-rwxr-xr-xtests/timegenerated-ymd.sh32
-rwxr-xr-xtests/timereported-utc-legacy.sh24
-rwxr-xr-xtests/timereported-utc-vg.sh4
-rwxr-xr-xtests/timereported-utc.sh27
-rwxr-xr-xtests/timestamp-3164.sh51
-rwxr-xr-xtests/timestamp-3339.sh33
-rwxr-xr-xtests/timestamp-isoweek.sh24
-rwxr-xr-xtests/timestamp-mysql.sh19
-rwxr-xr-xtests/timestamp-pgsql.sh20
-rwxr-xr-xtests/timestamp-subseconds.sh24
-rw-r--r--tests/tls-certs/ca-fail.pem3
-rw-r--r--tests/tls-certs/ca-key.pem190
-rw-r--r--tests/tls-certs/ca.pem29
-rw-r--r--tests/tls-certs/cert-fail.pem3
-rw-r--r--tests/tls-certs/cert.pem31
-rw-r--r--tests/tls-certs/certchained.pem60
-rw-r--r--tests/tls-certs/key-fail.pem40
-rw-r--r--tests/tls-certs/key.pem190
-rw-r--r--tests/travis/trusty.supp10
-rwxr-xr-xtests/udp-msgreduc-orgmsg-vg.sh35
-rwxr-xr-xtests/udp-msgreduc-vg.sh35
-rwxr-xr-xtests/unused_lookup_table-vg.sh27
-rwxr-xr-xtests/urlencode.py14
-rwxr-xr-xtests/uxsock_simple.sh46
-rw-r--r--tests/uxsockrcvr.c192
-rwxr-xr-xtests/validation-run.sh29
-rwxr-xr-xtests/variable_leading_underscore.sh13
-rw-r--r--tests/with_space.mmdbbin0 -> 432 bytes
-rwxr-xr-xtests/wr_large_async.sh31
-rwxr-xr-xtests/wr_large_sync.sh31
-rwxr-xr-xtests/wtpShutdownAll-assertionFailure.sh29
-rwxr-xr-xtests/zstd-vg.sh4
-rwxr-xr-xtests/zstd.sh38
-rw-r--r--threads.c322
-rw-r--r--threads.h47
-rw-r--r--tools/Makefile.am118
-rw-r--r--tools/Makefile.in1447
-rw-r--r--tools/gethostn.c46
-rw-r--r--tools/iminternal.c182
-rw-r--r--tools/iminternal.h45
-rw-r--r--tools/logctl.c486
-rw-r--r--tools/msggen.c36
-rw-r--r--tools/omdiscard.c158
-rw-r--r--tools/omdiscard.h33
-rw-r--r--tools/omfile.c1644
-rw-r--r--tools/omfile.h38
-rw-r--r--tools/omfwd.c1778
-rw-r--r--tools/omfwd.h34
-rw-r--r--tools/ompipe.c448
-rw-r--r--tools/ompipe.h31
-rw-r--r--tools/omshell.c163
-rw-r--r--tools/omshell.h34
-rw-r--r--tools/omusrmsg.c551
-rw-r--r--tools/omusrmsg.h33
-rw-r--r--tools/pmrfc3164.c419
-rw-r--r--tools/pmrfc3164.h33
-rw-r--r--tools/pmrfc5424.c329
-rw-r--r--tools/pmrfc5424.h33
-rwxr-xr-xtools/recover_qi.pl207
-rw-r--r--tools/rscryutil.c552
-rw-r--r--tools/rscryutil.rst199
-rw-r--r--tools/rsyslog.conf.5815
-rw-r--r--tools/rsyslogd.8320
-rw-r--r--tools/rsyslogd.c2362
-rw-r--r--tools/smfile.c137
-rw-r--r--tools/smfile.h31
-rw-r--r--tools/smfwd.c145
-rw-r--r--tools/smfwd.h30
-rw-r--r--tools/smtradfile.c130
-rw-r--r--tools/smtradfile.h31
-rw-r--r--tools/smtradfwd.c142
-rw-r--r--tools/smtradfwd.h30
-rw-r--r--tools/syslogd.c136
-rw-r--r--tools/syslogd.h38
-rwxr-xr-xylwrap247
1837 files changed, 396462 insertions, 0 deletions
diff --git a/.tarball-version b/.tarball-version
new file mode 100644
index 0000000..6d5cf31
--- /dev/null
+++ b/.tarball-version
@@ -0,0 +1 @@
+8.2402.0
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..8a3b556
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,14 @@
+Thankfully, we have had so many contributions that maintaining the
+AUTHORS file would be a big task in itself. On the other hand, we
+now use git and I make sure that each author receives proper credit
+for patches I receive.
+
+So rather than trying to reproduce the git author log here (and
+often making mistakes in that), I invite you to check the git logs.
+You can also do this online at
+
+http://git.adiscon.com/?p=rsyslog.git;a=summary
+
+Rainer Gerhards
+<rgerhards@adiscon.com>
+lead rsyslog developer
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..13239f6
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,164 @@
+# How to Contribute
+
+Rsyslog is a real open source project and open to contributions.
+By contributing, you help improve the state of logging as well as improve
+your own professional profile. Contributing is easy, and there are options
+for everyone - you do not need to be a developer.
+
+These are many ways to contribute to the project:
+ * become a rsyslog ambassador and let other people know about rsyslog and how to utilize it for best results. Help rsyslog getting backlinks, be present on Internet news sites or at meetings you attend.
+ * help others by offering support on
+ * the rsyslog's github home at https://github.com/rsyslog/rsyslog
+ * the rsyslog mailing list at http://lists.adiscon.net/mailman/listinfo/rsyslog
+ * help with the documentation; you can either contribute
+ * to the [rsyslog doc directory](https://github.com/rsyslog/rsyslog-doc), which is shown on http://rsyslog.com/doc
+ * to the rsyslog project web site -- just ask us for account creation
+ * become a bug-hunter and help with testing rsyslog development releases
+ * help driving the rsyslog infrastructure with its web sites and the like
+ * help creating packages
+ * or, obviously, help with rsyslog code development
+
+This list is not conclusive. There for sure are many more ways to contribute and if you find one, just let us know. We are very open to new suggestions and like to try out new things.
+
+## When to submit Pull Requests?
+
+It is OK to submit PRs that are not yet fully ready for merging. You want to
+do this in order to get early CI system coverage for your patch. However,
+all patches should be reasonably complete and "work" in a sense.
+
+If you submit such PRs, please flag them as "work in progress" by adding
+"WiP:" in front of the title. We will NOT merge these PRs before you tell us
+they are now ready for merging.
+
+If you just want/need to do a temporary experiment, you may open a PR, flag it
+as "EXPERIMENT - DO NOT MERGE", let the CI tests run, check results and close
+the PR thereafter. This prevents unnecessary cluttering of the open PR list.
+We will take the liberty to close such PRs if they are left open for an
+extended period of time.
+
+Please note, though, that the rsyslog repo is fully set up to use Travis CI.
+Travis covers about 95% of all essential testing. So we highly recommend
+that you use Travis to do initial checks on your work and create the PR
+only after this looks good. That saves both you and us some time.
+
+## Requirements for patches
+
+In order to ensure good code quality, after applying the path the code must
+
+- no legacy configuration statements ($someSetting) must be added,
+ all configuration must be in v6+ style (RainerScript)
+- compile cleanly without WARNING messages under both gcc and clang
+- pass clang static analyzer without any report
+- pass all CI tests
+- new functionality must have associated
+ * testbench tests
+ * doc additions in the rsyslog-doc sister project
+- be [sufficiently squashed](https://rainer.gerhards.net/2019/03/squash-your-pull-requests.html)
+
+### Testbench Coverage
+
+If you fix a bug that is not detected by the current testbench, it is
+appreciated if you also add testbench test to make sure the problem does
+not re-occur in the future.
+
+In contrast to new feature PRs, this is not a hard requirement, but it
+helps to speed up merging. If there is no testbench test added, the
+core rsyslog developers will try to add one based on the patch. That
+means merging needs to wait until we have time to do this.
+
+### Compiler Diagnostics
+
+Note that both warning messages and static analyzer warnings may be false
+positives. We have decided to accept that fate and work around it (e.g. by
+re-arranging the code, etc). Otherwise, we cannot use these useful features.
+
+As a last resort, compiler warnings can be turned off via
+ #pragma diagnostic
+directives. This should really only be done if there is no other known
+way around it. If so, it should be applied to a single function, only and
+not to full source file. Be sure to re-enable the warning after the function
+in question. We have done this in some few cases ourselves, and if someone
+can fix the root cause, we would appreciate help. But, again, this is a
+last resort which should normally not be used.
+
+Please read [on the importance of static analysis and why we request you to work around false positives](https://rainer.gerhards.net/2018/06/why-static-code-analysis.html).
+
+### Continuous Integration Testing
+
+All patches are run though our continuous integration system, which ensures
+no regressions are inside the code as well as rsyslog project policies are
+followed (as far as we can check in an automated way).
+
+For pull requests submitted via github, these two conditions are
+verified automatically. See the PR for potential failures. For patches
+submitted otherwise, they will be verified semi-manually.
+
+Also, patches are requested to not break the testbench. Unfortunately, the
+current testbench has some racy tests, which are still useful enough so that
+we do not want to disable them until the root cause has been found. If your
+PR runs into something that you think is not related to your code, just sit
+back and relax. The rsyslog core developer team reviews PRs regularly and
+restarts tests which we know to look racy. If the problem persists, we will
+contact you.
+
+All PRs will be tested on a variety of systems, with the help of both Travis
+CI and buildbot. The core goal of this multi-platform testing is to find
+issues that surface only on some systems (e.g. 32bit related issues, etc).
+We continuously strive to update the CI system coverage. If you can provide
+a buildbot slave for a not-yet-supported test platform, please let us know.
+We will gladly add it.
+
+Note that test coverage differs between platforms. For example, not all
+databases etc. are tested on each platform. Also note that due to resource
+constraints some very lengthy tests are only execute on some (maybe only
+a single) platform.
+
+Note that we always try to merge with the most recent master branch and
+try a build from that version (if automatic merging is possible). If this
+test fails but no other, chances are good that there is an inter-PR issue.
+If this happens, it is suggested to rebase to git master branch and update
+the PR.
+
+## Note to developers
+
+Please address pull requests against the master branch.
+
+
+## Testbench coding Tips
+
+- look for similar tests and use them as copy template. Be sure to update
+ comments as well.
+- see ./tests/diag.sh -- this is the base testing framework and it contains
+ many functions you can use inside your tests
+- keep test cases simple and focussed on one topic. Otherwise it is hard to
+ address test failures when they happen in the future.
+
+-------------------------------------------------------------------------------------
+LEGAL GDPR NOTICE:
+According to the European data protection laws (GDPR), we would like to make you
+aware that contributing to rsyslog via git will permanently store the
+name and email address you provide as well as the actual commit and the
+time and date you made it inside git's version history. This is inevitable,
+because it is a main feature git. If you are concerned about your
+privacy, we strongly recommend to use
+
+--author "anonymous <gdpr@example.com>"
+
+together with your commit. Also please do NOT sign your commit in this case,
+as that potentially could lead back to you. Please note that if you use your
+real identity, the GDPR grants you the right to have this information removed
+later. However, we have valid reasons why we cannot remove that information
+later on. The reasons are:
+
+* this would break git history and make future merges unworkable
+* the rsyslog projects has legitimate interest to keep a permanent record of the
+ contributor identity, once given, for
+ - copyright verification
+ - being able to provide proof should a malicious commit be made
+
+Please also note that your commit is public and as such will potentially be
+processed by many third-parties. Git's distributed nature makes it impossible
+to track where exactly your commit, and thus your personal data, will be stored
+and be processed. If you would not like to accept this risk, please do either
+commit anonymously or refrain from contributing to the rsyslog project.
+-------------------------------------------------------------------------------------
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..804eb5c
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,675 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/COPYING.ASL20 b/COPYING.ASL20
new file mode 100644
index 0000000..9d78c8b
--- /dev/null
+++ b/COPYING.ASL20
@@ -0,0 +1,50 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
+ 2. You must cause any modified files to carry prominent notices stating that You changed the files; and
+ 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+ 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
diff --git a/COPYING.LESSER b/COPYING.LESSER
new file mode 100644
index 0000000..34b8ea7
--- /dev/null
+++ b/COPYING.LESSER
@@ -0,0 +1,166 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ 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 that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU 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 as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..f4d9a77
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,16389 @@
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2402.0 (aka 2024.02) 2024-02-27
+- 2024-02-26: add DTLS support
+ This version comes with the initial implementation of imdtls and omdtls.
+ These modules permit secure message exchange over UDP.
+- 2024-02-26: testbench: make omusrmsg-noabort test more reliable
+ The previous test did not always detect an abort of rsyslog/omusrmsg.
+ The detection method has now been improved, so it is far more
+ probable that an abort is detected.
+ While doing this, we noticed that the omusrmsg-noabort-legacy test was
+ now a 100% duplicate. There is no need any longer to check pure legacy
+ syntax, and so that test has been removed.
+ We also added a valgrind-based test ofr omusrmsg-noabort, which furthers
+ strengthens bug detection. Most importantly, it helps us to detect
+ potentially new memory leaks on all CI platforms (in case the lib
+ behaves differently depending on os/distro).
+ see also https://github.com/rsyslog/rsyslog/issues/5294
+- 2024-02-26: omusrmsg bugfix: potential double free, which can cause segfault
+ omusrmsg frees a string which points to OS/system library memory. When
+ the os/libs clean up, it frees the memory as well. This results in a
+ double free. This bug interestingly seems to go unnoticed in many cases.
+ But it can cause a segfault or hard-to-trace memory corruptions which
+ could lead to other problems later on. The outcome of this bug most
+ probably depdns on os/library versions.
+ closes https://github.com/rsyslog/rsyslog/issues/5294
+- 2024-02-26: ommysql bugfix: potential segfault on database error
+ Due to an invalid code path, ommysql may cause a segfault if database
+ transactions fail into a specific way. The main trigger is a totally
+ irrecoverrable database error which can lead to premature connection
+ close, which is not checked for in all recover code.
+ This was detected in a setting where a stored procedure is called that
+ rolls back a transaction in itself.
+ This patch fixes the issue.
+ closes https://github.com/rsyslog/rsyslog/issues/5288
+- 2024-02-26: omfile: do not carry out actual action when writing to /dev/null
+ In some use cases omfile is configured to write to /dev/null. This seems
+ primarily be done because of statistics gathering but maybe some other
+ scenarios. We now add conditional logic to not do any actual omfile
+ action when the target file is /dev/null.
+ Note: this check only works on static file names. When /dev/null is
+ evaluated as part of dynafile, it will be handled just in the regular
+ case like before this patch.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2312.0 (aka 2023.12) 2023-12-12
+- 2023-12-11: imjournal: Add new input module parameter 'defaulttag'
+ The DefaultTag option specifies the default value for the tag field.
+ In imjournal, this can happen when one of the following is missing:
+ * identifier string provided by the application (SYSLOG_IDENTIFIER)
+ * name of the process the journal entry originates from (_COMM)
+ Thanks to Attila Lakatos for the patch.
+- 2023-12-08: core bugfix: rsyslog messages may not always have FQDN
+ Even if hostname FQDN is configured, rsyslog internal messages generated
+ after rsyslog startup and before the first HUP will not necessarily have
+ FQDN but instead only the shortname of the local host. This commit
+ fixes the situation.
+ Special thanks to github user eciii for doing a great bug analysis
+ and helping us considerably to fix the issue.
+ closes https://github.com/rsyslog/rsyslog/issues/5218
+- 2023-12-08: omlibdbi regression fix: database path was not properly used
+ Commit 4a072d6c93015a63716c49a6c7756df22750086a caused a regression that made
+ the database path unreliable to use. Depending on platform/libc version the
+ basename was improperly extracted, which made access to the database of sqllite
+ impossible.
+ Thanks to Flávio Tapajós for the patch.
+ closes: https://github.com/rsyslog/rsyslog/issues/5282
+- 2023-12-06: mazureeventhubs: Corrected handling of transport closed failures
+ - Added test for connection interrupts (requires root)
+ - Corrected handling of PN_TRANSPORT_CLOSED.
+ - Make sure Connection is being reestablished trough tryResume
+ - Enhanced Debug log output
+ closes: https://github.com/rsyslog/rsyslog/issues/5269
+- 2023-11-24: imkmsg: add params "readMode" and "expectedBootCompleteSeconds"
+ These parameters permit to control when imkmsg reads the full
+ kernel log upon startup.
+ Parameter "readMode" provides the following options:
+ * full-boot - (default) read full klog, but only "immediately" after
+ boot. "Immediately" is hereby meant in seconds of system
+ uptime given in "expectedBootCompleteSeconds"
+ * full-always - read full klog on every rsyslog startup. Most
+ probably causes messag duplication
+ * new-only - never emit existing kernel log message, read only
+ new ones.
+ Note that some message loss can happen if rsyslog is stopped
+ in "full-boot" and "new-only" read mode. The longer rsyslog is
+ inactive, the higher the message loss probability and potential
+ number of messages lost. For typical restart scenarios, this
+ should be minimal. On HUP, no message loss occurs as rsyslog
+ is not actually stopped.
+ The default value for "expectedBootCompleteSeconds" is 90.
+ see also https://github.com/rsyslog/rsyslog/issues/5161
+- 2023-11-10: imkmsg: add module param parseKernelTimestamp
+ The parameter permits to select whether or not and when kernel
+ timestamps shall parsed, that is be used as the actual time a
+ log message occurs.
+ This permits to work around problems with the way kernel
+ timestamps are represented. The reasoning is given in a sysklogd
+ commit by Joachim Wiberg, which we reproduce below ("QUOTE") to
+ have a stable reference.
+ The commit itself can be found for example at:
+ https://github.com/troglobit/sysklogd/commit/9f6fbb3301e571d8af95f8d771469291384e9e95
+ The new parameter parseKernelTimestamp has three possible modes:
+ "startup" - uses the kernel time stamp during the initial read
+ loop of /dev/kmsg, but replaced it later ignores it for later reads.
+ This is the DEFAULT setting.
+ "on" - kernel timestamps are always used and no correction is tried
+ "off" - kernel timestamps are never used, system time is used instead
+ Note that there this is a slightly breaking change. Previously, imkmsg
+ reported similar to "off" mode, now it reports by default in "startup"
+ mode. We consider this acceptable, as "off" mode timestamps are not
+ correct for startup. After startup, the behaviour is correct. All in
+ all, the new default is kind of a bugfix.
+ ============== QUOTE ===============
+ The spec[1] says the /dev/kmsg timestamp is a monotonic clock and in
+ microseconds. After a while you realize it's also relative to the boot
+ of the system, that fact was probably too obvious to be put in the spec.
+ However, what's *not* in the spec, and what takes a while to realize, is
+ that this monotonic time is *not* adjusted for suspend/resume cycles ...
+ On a frequently used laptop this can manifest itself as follows. The
+ kernel is stuck on Nov 15, and for the life of me I cannot find any to
+ adjust for this offset:
+ $ dmesg -T |tail -1; date
+ [Mon Nov 15 01:42:08 2021] wlan0: Limiting TX power to 23 (23 - 0) dBm as advertised by 18:e8:29:55:b0:62
+ Tue 23 Nov 2021 05:20:53 PM CET
+ Hence this patch. After initial "emptying" of /dev/kmsg when syslogd
+ starts up, we raise a flag (denoting done with backlog), and after this
+ point we ignore the kernel's idea of time and replace it with the actual
+ time we have now, the same that userspace messages are logged with.
+ Sure, there will be occasions where there's a LOT of kernel messages to
+ read and we won't be able to keep track. Yet, this patch is better than
+ the current state (where we log Nov 15).
+ [1]: https://www.kernel.org/doc/Documentation/ABI/testing/dev-kmsg
+ ===========END QUOTE ===============
+ closes https://github.com/rsyslog/rsyslog/issues/4561
+ closes https://github.com/rsyslog/rsyslog/issues/5161
+- 2023-11-07: imfile bugfix: remove state file on file delete
+ The state file would remain in the working directory
+ after shutdown, even though deleteStateOnfileDelete is
+ set to "on" and the monitored file was removed.
+ closes https://github.com/rsyslog/rsyslog/issues/5258
+ Thanks to Attila Lakatos for the patch.
+- 2023-10-31: TLS subsystem: fix small memory leak on startup
+ This was a one-time leak of the file name that hapened if a certificate file
+ was not accessible. It had no operational issues, but could confuse automatted
+ testing. As not only a side-effect, certificate load failures are now somewhat
+ more verbosely reported, which we consider helpful to the user.
+ Thanks to Attila Lakatos for the patch.
+- 2023-10-31: imklog bugfix: keepKernelTimestamp=off config param did not work
+ ... at least not as expected. It was only honored for kernel-level
+ messages and only when parseKernelTimestamp was "on". Otherwise, the
+ kernel timestamp was always kept inside the message.
+ closes https://github.com/rsyslog/rsyslog/issues/5160
+- 2023-10-26: TLS subsystem: add remote hostname to error reporting
+ This provides richer and easier to process logs for error and warning
+ cases. One goal is to enable automatic operations without the need
+ to consolidate multiple message to a single information.
+ This improves one situation in gtls driver and provides a more
+ generic approach in ossl driver for OpenSSL error reporting.
+ There is probably still room for improvement, however this patch
+ is at least a good starting point for further work. Please
+ provide feedback if you need more!
+ closes https://github.com/rsyslog/rsyslog/issues/5244
+- 2023-10-24: imjournal: add the ability to run multiple journal inputs
+ This may be useful to de-couple journal processing.
+ Thanks to Willy Tu for the patch.
+- 2023-10-24: regression fix: forking rsyslogd on BSD did not work
+ Actually, this was an issue for all platforms that do not provide open file handle
+ detection via the /proc file system.
+ Tech details: After fork if the child process uses close_range to close open file
+ descriptors it has no way to exempt the parentPipeFD causing a failure to signal
+ successful startup to the parent process. This causes failures on all systems that
+ aren't Linux that implement close_range.
+ Thanks to Nathan Huff for the patch.
+- 2023-10-24: omusrmsg: use logind instead of utmp for wall messages with systemd
+ Future SUSE versions will get rid of utmp due to a 32bit time_t counter
+ overflow in 2038.
+ See details at:
+ https://github.com/thkukuk/utmpx/blob/main/Y2038.md
+ On systemd based systems logind is an alternative to utmp.
+ Thanks to github user tblume for the patch.
+- 2023-10-24: cleanup: rm no longer used --with-systemdsystemunitdir configure switch
+ This is a clean up following the removal of the service unit in
+ cfd07503ba055100a84d75d1a78a5c6cceb9fdab
+- 2023-10-23: testbench: bump zookeeper version to match current offering
+ Older version can no longer be downloaded. It also makes sense to
+ test with mainstream version.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2310.0 (aka 2023.10) 2023-10-10
+- 2023-10-04: Add CAP_NET_RAW capability due to the omudpspoof module
+ The CAP_NET_RAW ensures the use of RAW and PACKET sockets,
+ which is utilized by the omudpspoof module, more precisely
+ the libnet_init function.
+ Thanks to Attila Lakatos for the patch.
+- 2023-10-04: Add new global config option "libcapng.enable"
+ Defines whether rsyslog should drop capabilities at startup or not.
+ By default, it is set to "on". Until this point, if the project was
+ compiled with --enable-libcap-ng option, capabilities were
+ automatically dropped. This is configurable now.
+ Thanks to Attila Lakatos for the patch.
+- 2023-10-04: tcp net subsystem: handle data race gracefully
+ It may happen that a socket file descriptor has been closed either
+ while setting up poll() et al or while being inside the system call.
+ This was previously treated as error and caused abort in debug
+ builds. However, it was essentially ignored in production builds.
+ This has now been fixed and now is always gracefully ignored. This
+ most importantly fixes some flakes in CI runs (which were caused
+ by this situation).
+- 2023-09-29: imrelp bufgifx: avoid crash on restart in imrelp SIGTTIN handler
+ While existing, if at specific time rsyslog receives a SIGTTIN, it
+ crashes due to 2 issues.
+ 1. debug.unloadModules="off" a double free of pRelpEngine
+ 2. debug.unloadModules="on" it crashes because the signal handler has
+ been unmapped from memory.
+ This patch covers both issues.
+ Thanks to Ali Abdallah for the patch.
+- 2023-09-28: fix startup issue on modern systemd systems
+ When we startup AND are told to auto-background ourselfs, we must
+ close all unneeded file descriptors. Not doing this has some
+ security implications. Traditionally, we do this by iterating
+ over all possible file descriptor values. This is fairly compatible,
+ because we need no OS-specific method. However, modern systemd configs
+ tend to not limit the number of fds, so there are potentially 2^30(*)
+ fds to close. While this is OKish, it takes some time and makes
+ systemd think that rsyslog did not properly start up.
+ We have now solved this by using the /proc filesystem to obtain our
+ currently open fds. This works for Linux, as well as Cygwin, NetBSD,
+ FreeBDS and MacOS. Where not available,and close_range() is available
+ on the (build) platform, we try to use it. If that fails as well, we
+ fall back to the traditional method. In our opionion, this fallback
+ is unproblematic, as on these platforms there is no systemd and in
+ almost all cases a decent number of fds to close.
+ Very special thanks go out to Brennan Kinney, who clearly described
+ the issue to us on github and also provided ample ways to solve it.
+ What we did is just implement what we think is the best fit from
+ rsyslog's PoV.
+ (*) Some details below on the number of potentially to close fds.
+ This is directly from a github posting from Brennan Kinney.
+ Just to clarify, by default since systemd v240 (2018Q4), that
+ should be `1024:524288` limit. As in the soft limit is the expected
+ `1024`.
+ The problem is other software shipping misconfiguration in systemd
+ services that overrides this to something silly like
+ `LimitNOFILE=infinity`.
+ - Which will map to the sysctl `fs.nr_open` (_a value systemd
+ v240 also raises from `2^20` to 2^30`, some distro like Debian are
+ known to opt-out via patch for the `fs.nr_open` change_).
+ - With the biggest issue there being that the soft limit was also
+ set to `infinity` instead of their software requesting to raise
+ the soft limit to a higher value that the hard limit permits.
+ `infinity` isn't at all sane though.
+ - The known source of this misconfiguration is container software such
+ as Docker and `containerd` (_which would often sync with the
+ systemd `.service` config from the Docker daemon `dockerd.service`_).
+ closes https://github.com/rsyslog/rsyslog/issues/5158
+- 2023-09-13: Add the 'batchsize' parameter to imhiredis
+ Parameter set to allow configuring the amount of entries imhiredis debatches at once.
+ Default value of '10' has been kept to avoid any side effect on existing
+ configurations.
+ Thanks to Jérémie Jourdin for the patch.
+- 2023-09-13: omprog bugfix: Add CAP_DAC_OVERRIDE to the bounding set
+ The omprog module uses the execve() function to execute
+ a third party program. Some required capabilities were not
+ preserved in the bounding set [1]. This caused problems, e.g.
+ the program could not write to files even if rsyslog was
+ executed as root and privileges were not dropped. As of now,
+ only the CAP_DAC_OVERRIDE capability is added to the bounding
+ set. Others could be added later, if there is justification
+ behind that.
+ [1] The capability bounding set is a security mechanism that
+ can be used to limit the capabilities that can be gained
+ during an execve(2). During an execve, the capability
+ bounding set is ANDed with the file permitted capability
+ set, and the result of this operation is assigned to the
+ thread's permitted capability set. The capability
+ bounding set thus places a limit on the permitted
+ capabilities that may be granted by an executable file.
+ Thanks to Attila Lakatos for the patch.
+- 2023-09-13: tcpflood bugfix: plain tcp send error not properly reported
+ The error code when plain tcp sending failed was improperly returned,
+ resulting in no meaningful error message.
+ Note: tcpflood is a testbench tool, not part of production rsyslog.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2308.0 (aka 2023.08) 2023-08-15
+- 2023-08-07: crypto subsystem bugfix: potential undefined behaviour
+ The is some potential undefined behaviour when initializting the IV for locally
+ encrypting log files. The issue cancels itself out, but at least causes
+ some confusion when using undefined behaviour sanitizer (UBSAN). However,
+ UBSAN seems not to detect the issue on all platforms and/or in all versions
+ (we were not able to reproduce this issue in our CI).
+ Please also note that the functionality where this can happen is extremely
+ rarely being used.
+ Thanks to Jeffrey Walton for providing the patch.
+- 2023-08-02: lookup tables: fix static analyzer issue
+ If something goes really wrong, a lookup table's name would not
+ be set. That could lead to a NULL pointer access. HOWEVER, this
+ would require serious bugs in config parameter parsing, as the
+ lookup table name is a required parameter and the parser will
+ error out if not set.
+ So the bug is mostly cosmetic - but it does not hurt to handle
+ this case, of course.
+- 2023-08-02: lookup tables bugfix: reload on HUP did not work when backgrounded
+ Lookup tables were only reloaded on HUP if the -n option was given
+ and rsyslog no backgrounded. This patch fixes the issue.
+ closes: https://github.com/rsyslog/rsyslog/issues/4813
+- 2023-07-30: testbench: make test more reliable
+ There was a race between tcpflood and rsyslog in imptpc_maxsessions.sh.
+ We now use the new -A tcpflood option to make the timing more
+ predictable, hopefully fixing test flakiness.
+ Note: if that does not help, we need to introduce a wait on the number
+ of error messages and maybe a delay before tcpflood termination. The
+ theory behind the latter is that rsyslog possibly does not fully
+ iniaitlize session which are quickly aborted before rsyslog receives
+ the related OS notification! We just record this info in case we
+ need it and are positive that this change will fix the situation.
+- 2023-07-28: openssl: make connection setup more reliable by use of newer lib feature
+ Replaced depreceated method SSLv23_method with TLS_method.
+ In OpenSSL 1.1.0 and higher, SSLv23_method causes some errors
+ in TLS handshake from time to time. As this method is depreceated
+ since 1.1.0, I have replaced it with the follow up method
+ TLS_method which is the most generic one.
+ It fixes the random test failures in tests like
+ - sndrcv_tls_ossl_anon_rebind.sh
+ Also added some debug output in OpenSSL error handling, which is
+ useful when analysing debug files.
+ closes: https://github.com/rsyslog/rsyslog/issues/5201
+- 2023-07-28: testbench improvement: define state file directories for imfile tests
+ Not all imfile tests have state file directories or a global working
+ directory defined. This results in usage of the default location.
+ While state file names should be sufficiently different, there is still
+ some riks of using the same name in different tests. That becomes
+ problematic if tests are run in parallel (and they are run in
+ parallel inside the regular CI).
+ NOTE: NOT YET COMPLETED FOR ALL TESTS! We are considering if it makes
+ sense to deliberately keep some as-is.
+- 2023-07-28: tcpflood bugfix: TCP sending was not implemented properly
+ Note: tcpflood is a testbench tool. This bug could lead to testbench
+ false positives. No way it can affect production deployments.
+ The tcpflood tool did improperly assume that a TCP sendto() call
+ would send messages of any size in a single shot. This is not the
+ case. It has now been corrected to proper behavior.
+ As a side-activity, some int variables which acutally needed to be
+ size_t have been fixed as well.
+- 2023-07-28: testbench: make waiting for HUP processing more reliable
+ The previous approach was more or less delay based. We have now
+ changed the code to enable imdiag to detect if HUP is underway
+ and wait until it is completed. The new method still employs some
+ kind of timeout, but is now quite reliable. Most importantly,
+ it works great with long-running HUP processing, which can happen
+ e.g. when querying the system name takes long or some actions need
+ longer time to persist their HUP processing.
+ The new approach will most likely reduce CI flakes and also speed
+ up testbench runs. The speedup happens from not having to wait a
+ full delay in cases where we detect HUP is completed (plus reduced
+ timeout when we cannot clearly detect this - see code comments why
+ the new method is still considered more reliable than the old one).
+ Code note: we needed to slightly re-structure the way actual HUP
+ processing and the "HUP mutex" is handled. After best analysis,
+ this does not affect the reliability or speed in production
+ settings.
+ closes https://github.com/rsyslog/rsyslog/issues/5192
+- 2023-07-27: build system: make rsyslogd execute when --disable-inet is configured
+ This option is mostly useless, as network functionality depends on the
+ modules loaded by the config. The only real, and important, effect it
+ has is to control auto-load of omfwd - a feature almost all installations
+ depend in (backward compatibility).
+ This has been clarified in ./configure -help
+ Also, when --disable-inet is given, rsyslog now executes successfully.
+ The reason for the abort was that previously building of the lmnet
+ component was prevented, but that component is also needed by rsyslog
+ startup itself to query its own (correct) hostname.
+ Note that --disable-inet still does not compile some networking
+ libraries. So do not use it if you intend to load standard networking
+ modules like omfwd, imtcp or imudp.
+ closes https://github.com/rsyslog/rsyslog/issues/5188
+- 2023-07-26: testbench/CI: update zookeper download to newer version
+ Old version is no longer available.
+- 2023-07-24: openssl: add support for new-version init function
+- 2023-07-07: add CRL support for network (TLS) drivers
+ Thanks to Darren J Moffat for implementing the OpenSSL part.
+- 2023-07-07: omazureeventhubs: Initial implementation of new output module
+ The output module uses Apache "Qpid Proton C API" which is a solid
+ AMQP protocol library implementation that can be integrated
+ very well into the rsyslog dev environment.
+ - Implemented Delivery with submitted and accepted state checking
+ - saving of failed messages in a failed list with support of saving
+ and restoring.
+ - Add testcases (requires ENV variables) to testbench
+ - Using application/octect-stream (binary) to send messages based on
+ Microsoft Code Sample:
+ https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-c-getstarted-send
+ * Note original Microsoft Samplecode is not working anymore, we are using
+ * QPID Proton Proactor based on
+ https://github.com/apache/qpid-proton/blob/main/c/examples/send.c
+ - requires QPID-PROTON Version 0.13 or higher because of the proactor API
+ - Add EventProperties configuration parameters
+ - Slow down when sender credit reaches zero (10ns).
+ - Add support for static library linking of qpid-proton
+ This is needed to build the module from source and remove
+ library package dependencies.
+ - adjusted valgrind suppressions
+- 2023-07-04: core bugfix: action.resumeintervalmax parameter was not respected
+ Unfortunately, defining action.resumeintervalmax in the configration
+ did not have any effect at all. Instead, the default value was used,
+ which is 1800. This was caused by not having all the letters in
+ lower-case.
+ Fixes https://github.com/rsyslog/rsyslog/issues/5132
+ Thanks to Attila Lakatos for the patch.
+- 2023-06-29: core bugfix: do not try to drop capabilities when we don't have any
+ In case the process does not have any capabilities, e.g. running as regular user then
+ we do not have to force capability dropping. The capng_have_capabilities() returns
+ none if that's the case.
+ Fixes https://github.com/rsyslog/rsyslog/issues/5091
+ Thanks to Attila Lakatos for the patch.
+- 2023-06-29: imhiredis bugfix: Restore compatiblity with hiredis < v1.0.0
+ RESP3 protocol wasn't implemented yet, some types weren't
+ available (REDIS_REPLY_DOUBLE)
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2023-06-23: testbench: use newer zookeeper version in tests
+- 2023-06-23: build system: more precise error message on too-old lib
+ When libcap-ng was enabled, the lib was present but did not meet the minimum version
+ dependency during configure, it was reported as "missing". We now emit a message
+ telling that it is present, but the version too old.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2306.0 (aka 2023.06) 2023-06-20
+- 2023-06-19: mmnormalize bugfix: if msg cannot be parsed, parser chain is stopped
+ When an parser is not able to parse a message, it should indicate this
+ to rsyslog core, which then activates the next parser(s) inside the
+ configured parser chain.
+ Unfortunatley, mmnormalize always tells core "success", and so no
+ other parsers are activated.
+ closes https://github.com/rsyslog/rsyslog/issues/5148
+- 2023-06-19: [i/o]mhiredis: various fixes and enhancements
+ please see the change log for details. Among others, suspending of the modules
+ has been fixed. Also a new "stream" mode has been added.
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2023-06-19: testbench/bug: mmexternal-SegFault-empty-jroot-vg.sh fails due to typo
+ Fix the typo that makes the test fail.
+ Thanks to Paul Fertser for the patch.
+- 2023-06-16: imjournal: Add FileCreateMode module parameter
+ FileCreateMode allows to set the default file mode bits
+ when creating new files. As of now, it has only impact on the state file.
+ Add test suite as well.
+ Minor indentation fix in run_journal.yml
+ Thanks to Attila Lakatos for the patch.
+- 2023-06-16: core bugfix: potential segfault on busy systems
+ This was discovered by Konstantin J. Chernov in a practicaly deployment.
+ Here, msg object tag processing caused sporadic segfaults. We did not
+ hear from similiar cases, but there clearly is potential for problems
+ because a mutex lock had insufficient range, thus leading to a potential
+ race.
+ The patch is directly from Konstantin J. Chernov, thanks for that.
+ Please note that the mutex lock could be minimized as it is not strictly
+ needed for the pM == NULL case, but this cause is extremely exotic
+ and the resulting code would be harder to understand. Thus we opt
+ to do the locking on funtion level (as usual).
+ Descriptiond edited by Rainer Gerhards
+ closes: https://github.com/rsyslog/rsyslog/issues/5110
+- 2023-06-16: Add new global config option "libcapng.default"
+ Defines how rsyslog should behave in case something went wrong
+ when capabilities were to be dropped. Default value is "on",
+ in which case rsyslog exits on a libcapng related error.
+ Thanks to Attila Lakatos for the patch.
+ Closes https://github.com/rsyslog/rsyslog/issues/5096
+- 2023-06-05: imfile bugfix: file handle leak, primarily in kubernetes context
+ At this point there is a code imfile.c#L919 that adds an inotify observer to the
+ parent of the symbolic link target. But there is no such code that removes this
+ observer in the case when inotify events do not occur in the directory tree above.
+ This may be if the directory tree of the symbolic link target and the directory tree
+ of the symbolic link itself are divided into different subtrees somewhere at the levels
+ above.
+ For example, in the rsyslog configuration, an imfile with the
+ template /var/log/containers/*.log is configured and there is the following directory
+ tree:
+ /var/log/pods/pod-1/a/0.log
+ /var/log/containers/pod-1-a-0.log -> /var/log/pods/pod-1/a/0.log
+ In this example, kubernetes cron jobs will permanently delete directories at the
+ /var/log/pods/pod-* level. And thus, inotify observer on the parent object of the
+ symbolic link target (/var/log/pods/pod-1/a/0.log) looking at the directory
+ /var/log/pods/pod-1/a will constantly leak.
+ This is due to the fact that the list of active objects in the edge with path
+ /var/log/containers, where the parent object of the target symbolic link is added,
+ is not checked. Verification and deletion will occur only in the case of an inotify
+ event in the upper nodes of the directory tree, in /var/log and above.
+ Thanks to Sergey Kacheev for the patch!
+- 2023-06-05: GNUTls Driver: Fix memory leaks in gtlsInitCred
+ Missing CA Certificate or multiple Connections caused
+ a memory leak in pThis->xcred as it was allocated each time in
+ gtlsInitCred by gnutls_certificate_allocate_credentials
+ closes: https://github.com/rsyslog/rsyslog/issues/5135
+- 2023-05-24: CI: update base ubuntu image for github actions
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2304.0 (aka 2023.04) 2023-04-18
+- 2023-04-17: imptcp bugfix: spam log on oversize message
+ If an oversize message was received by imptcp, imptcp reported
+ one error message for EACH oversize character. This could
+ result in a potentially very large number of similar (and
+ useless) messages.
+ This is a regression from commit f052717178.
+ closes https://github.com/rsyslog/rsyslog/issues/5078
+- 2023-04-17: core/bugfix: using $uuid msg prop can deadlock rsyslog on shutdown
+ This problem can occur if a large number of threads is used and rsyslog
+ cannot shut down all queues etc within the regular time interval. In this
+ case, it cancels some threads. That can leave the mutex guarding libuuid
+ calls locked and thus prevents other, not yet cancelled threads from
+ progressing. Assuming pthread_mutex_lock() is not a cancellation point,
+ this will case these other threads to hang forever and thus create a
+ deadlock situation.
+ closes https://github.com/rsyslog/rsyslog/issues/5104
+- 2023-04-17: Do not preserve capabilities when changing credentials
+ In configurations where $PrivDropToGroup or $PrivDropToUser are used,
+ rsyslogd changes uid/gid to a non-privileged user. As part of that
+ change, all capabilities should be lost. However, if rsyslog is
+ compiled with --enable-libcap-ng option, some capabilities are
+ preserved due to using capng_change_id() instead of setgid()and
+ setuid(). https://linux.die.net/man/3/capng_change_id:
+ This function preserves capabilities while changing uid/gid, causing
+ rsyslogd to run as non-root user, but with some root capabilities.
+ Unfortunately, rsyslogd will run with higher privileges than before.
+ The patch also removes CAP_SETPCAP, because the capability set does
+ not need to be altered at a later phase.
+ Thanks to Attila Lakatos for the patch.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2302.0 (aka 2023.02) 2023-02-21
+- 2023-01-27: core/template: implement negative position.to
+ This will easily permit to drop the last n characters from a property
+ without the need to know the exact length of the string. This is
+ especially useful as the exact length is most often not known
+ beforehand.
+- 2023-01-18: Introduce --enable-libcap-ng configure option
+ The option allows to drop the capabilities to only
+ the necessary set, to minimize security exposure in
+ case there was ever a mistake in a networking
+ plugin or some other input resource. Moreover, it adds
+ ability to change uid and gid while retaining the
+ previously specified capabilities.
+ Add ability to change uid and gid while retaining the
+ capabilities previously specified.
+ closes https://github.com/rsyslog/rsyslog/issues/4986
+ Thanks to Attila Lakatos for the patch.
+- 2023-01-16:
+ - omfile: add action parameters "rotation.*"
+ Add new action parameters
+ - rotation.sizeLimit
+ - rotation.sizeLimitCommand
+ provide automatic output file rotation functionality feature-wise
+ equivalent to legacy $outchannel. This finally permits to use
+ this feature set in rscript.
+ - core substring function: enhancement and hardening
+ Now, length can have a negative value -n to denote that the
+ substring should be build between startpos and the character
+ -n chars from the end. This is a shortcut for stripping charactes
+ on "both ends" of the string. See doc for details on the enhanced
+ semantics.
+ Also, some hardening against invalid startpos and length has
+ been added.
+ - core bugfix: wrong type conversion in internal string class could lead to segfault
+ This could only happen with very unusually large strings
+ Thanks to Flos Lonicerae for the patch.
+ - QA: changed to CodeQL scanning on github as LGTM replacement
+ - bugfix: wrong version number on daily stable builds
+ - CI: use newer version of zookeeper (needed modernization)
+ - ffaup bugfix : memory corruption with concurrent workers
+ The ffaup function fails to work properly when it is used with multiple workers.
+ The faup_handler_t struct is not supposed to be shared between threads.
+ This may have caused memory corruptions and race conditions when used
+ inside of actions.
+ Thanks to Thibaud Cartegnie for the fix.
+ - openssl bugfix: undefined reference error on OpenSSL 1.1 or higher.
+ This could have prevented ossl components from being loaded/used.
+- 2023-01-02: core bugfix: template system may generate invalid json
+ When
+ - a list template
+ - is created with option.jsonf="on"
+ - and the last list element is a property with onEmpty="skip"
+ - and that property is actually empty
+ invalid JSON is generated.
+ The JSON string in this case ends with ", " instead of "}\n". This
+ patch fixes the issue.
+ closes https://github.com/rsyslog/rsyslog/issues/5050
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2212.0 (aka 2022.12) 2022-12-06
+- 2022-12-05: testbench: make python http server based tests more reliable
+ Harden them against races during server port assignment. Prevents
+ testbench flakes.
+- 2022-12-05: omprog bugfix: invalid status handling at called program startup
+ There is a bug when external program *startup* does not return "OK". This
+ can also lead to a misadressing with potentially a segfault (very unlikely).
+ Note that no problem exists once the initializiation phase of the external
+ program is finished and regular message transfer runs.
+ The problem basically is that for a startup failure, the control data for
+ that external program instance is freed on error. Unfortunately, that state
+ data is needed later on to detect a suspended instance. We now keep the control
+ data even on init failure (as we then need to do normal control options).
+ closes https://github.com/rsyslog/rsyslog/issues/4967
+- 2022-11-29: testbench bugfix: wrong message injection object of instance 1
+ In some client-server test cases, messages are supposed to be injected into
+ the instance 2(client), but they are actually injected into instance 1(server),
+ which may lead to false negative results. This patch fixed it by replacing
+ 'injectmsg' with 'injectmsg2', and dealt with some minor issues.
+ Thanks to Guodong Zhu for the patch.
+- 2022-11-21: rsyslog.conf man page bugfix: description of selectors
+ Document historic difference to BSD syslog selectors.
+- 2022-11-18: imtcp bugfix: legacy config directives did no longer work
+ Many "$InputTCPServer..." config directives did no longer work
+ and were completely ignored (e.g. "$InputTCPServerStreamDriverMode").
+ This was a regression from a08591be5d9 (May, 5th 2021).
+ closes https://github.com/rsyslog/rsyslog/issues/5021
+- 2022-11-16: ksi bugfix: sending of too many signing requests fixed.
+ As there is a bug in libksi where too many signing requests may have bene sent
+ out the amount of signing requests will be limited by KSI module until the fix
+ is implemented.
+ Thanks to Taavi Valjaots for the patch.
+- 2022-11-14: bugfix: prevent potential segfault when switchung to queue emergency mode
+ When switching to Disk queue emergency mode, we destructed the in-memory
+ queue object. Practice has shown that this MAY cause races during
+ destruction which themselfs can lead to segfault. For that reason, we
+ now keep the disk queueu object. This will keep some ressources,
+ including disk space, allocated. But we prefer that over a segfault.
+ After all, it only happens after a serious queue error when we are
+ already at the edge of hard problems.
+ see also: https://github.com/rsyslog/rsyslog/issues/4963
+- 2022-11-08: ksi bugfix: Segmentation fault in async mode fixed
+ Thanks to Taavi Valjaots for the patch.
+- 2022-11-02: imjournal: add second fallback to _COMM
+ If SYSLOG_IDENTIFIER is not present in the journal message,
+ then lookup the _COMM field, which stands for the name
+ of the process the journal entry originates from. This is
+ needed in order to be in compliance with the journalctl
+ output.
+ Thanks to Attila Lakatos for the patch.
+- 2022-10-25: core bugfix: local hostname invalid if no global() config object given
+ The local hostname is invalidly set to "[localhost]" on rsyslog startup
+ if no global() config object is present in rsyslog.conf. Sending a HUP
+ corrects the hostname.
+ This is a regression from ba00a9f25293f
+ closes https://github.com/rsyslog/rsyslog/issues/4975
+ closes https://github.com/rsyslog/rsyslog/issues/4825
+- 2022-10-25: testbench bugfix: fixed timing issue that sometimes lead to test failure
+ Timing caused a race in test tool sync and could lead to premature termination of
+ tools, which in turn caused test failure
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2210.0 (aka 2022.10) 2022-10-18
+- 2022-10-13: fix NetBSD build issue
+ On NetBSD, time_t has for a long time now been __int64_t.
+ On 32-bit CPUs, the compiler is not obliged to define
+ __sync_bool_compare_and_swap_8, so instead this ends up
+ as an undefined symbol when linking rsyslog. This makes
+ the code fall back to the pthread / locking method on these
+ systems, but at least lets the program build.
+ Thanks to Havard Eidnes for the patch.
+- 2022-10-12: omrabbitmq: Add TLS support
+ Thanks to github user 21stcavenan for the patch.
+- 2022-09-14: config: add "abortOnFailedQueueStartup" global config parameter
+ similiar to "abortONUncleanConfig", this parameter aborts rsyslog
+ when a queue has problems during startup. Some users perfer rsyslog
+ to terminate in this case. By default, nothing changes.
+ closes https://github.com/rsyslog/rsyslog/issues/4902
+- 2022-09-07: cor bugfix: leak in helper function SetString
+ A part of rsyslog runtime, SetString(), had a small memory leak when a value was
+ assigned multiple times. While this could potentially consume larger amounts of
+ memory, this did not happen in practice. The reason is that multiple assignments
+ to the same object occur very seldom.
+ Thanks to github user seuzw930 for the patch.
+ closes: https://github.com/rsyslog/rsyslog/issues/4961
+- 2022-09-07: core bugfix: correct local host name after config processing
+ rsyslog.conf may affect the host's local name. These changes were
+ so far only activated after the first HUP. This patch now ensures
+ that the configured local host name is applied correctly throughout
+ all processing, including early startup.
+ This patch causes a slight change of behaviour. However, the behaviour
+ was inconsitent before. Now it is consistent and according to the config.
+ Please note: this patch also exposes a global entry point via "regular"
+ dynamic loading as this makes things much easier to do. This is in-line
+ with ongoing simplification effort.
+ Finally, we also remove a CI test that we do no longer need because
+ the problem covered is now addressed differently and the original issue
+ can no longer occur.
+ closes https://github.com/rsyslog/rsyslog/issues/4975
+- 2022-08-31: imtcp: add option notifyonconnectionopen
+ Add this both as module an input parameter. Complements already-existing
+ config param notifyonconnectionclose and mirrors the similar feature from
+ imptcp.
+ The module parameter acts as default, similarly to notifyonconnectionclose.
+ Note that in contrast to imptcp, we emit IP addresses and not host
+ names. This sticks with the traditional semantics of imtcp.
+ Note that we also fixed a mislading error message in the case when a
+ disallowed sender tried to connect.
+ Thanks to John Chivian for suggesting the addition.
+- 2022-08-26: openssl TLS driver: add mechanism to include extra CA files parameter
+ This change allows to include extra CA files so that no "unable to get issuer
+ certificates" issue is obtained when using chained cert files. New parameter name is
+ "NetstreamDriverCAExtraFiles".
+ Thanks to Sergio Arroutbi for the patch.
+ closes: https://github.com/rsyslog/rsyslog/issues/4851
+- 2022-08-19: fix compile issue with older gcc compilers
+ Thanks to Julien Thomas for the contribution.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2208.0 (aka 2022.08) 2022-08-09
+- 2022-08-09: ksi bugfix: request cache size and send timeout issue fixed.
+ Async service send timeout is not configurable and request cache size is too
+ small to handle large amount of signing requests with small amount of permitted
+ requests per aggregation round. For example user with max_requests = 4 results
+ cache size 5 * max_requests or at least 256. When signing 300 log files cache
+ will be too small resulting several unsigned blocks. When signing 200 log file
+ cache will be adequate, but with rate of 4 signatures per second, it is only
+ possible to sign 4 * 10 blocks before all requests that are not sent out will
+ timeout.
+ Fix for the issue is to make send timeout configurable and make the size of the
+ cache depend on the value of send timeout. New configuration value
+ sig.block.signtimeout="time, s" introduced that defines the time window wherein
+ the block has to be signed. The size of the request cache is increased to
+ 3 * max_requests * sign_timeout or at least 256.
+ Thanks to Taavi Valjaots for the patch.
+- 2022-08-09: imjournal bugfix: segmentation fault in close journal
+ Thanks to github user t-feng for the patch.
+- 2022-08-09: net subsystem: support sha256 for StreamDriverAuthMode="x509/fingerprint"
+ Thanks to github user codemaker219 for the patch.
+- 2022-08-05: imfile bugfix: message loss/duplication when monitored file is rotated
+ When a to-be-monitored file is being rotated, some messages may be lost or
+ duplicated. In case of duplication, many file lines may be duplicated
+ depending on actual timing. The whole bug was primarily timing depenedent
+ in general. It most often was visible in practice when the monitored
+ file was very frequently rotated (we had some report with every few
+ seconds).
+ Note that while we try hard to not lose any messages, input file
+ rotation always has some loss potential. This is inevitable if
+ the monitored file is being truncated.
+ Also note that this bugfix affects imfile, only. It has nothing to do
+ and no relation to rsyslog output files being rotated on HUP.
+ closes: https://github.com/rsyslog/rsyslog/issues/4797
+- 2022-08-05: ksi bugfix: optimize processing of signer queue to fix delays.
+ There is a worker queue where rsyslog KSI module collects events and signing
+ requests. When queue is processed thread is periodically put to sleep. Previous
+ implementation handles signature requests well but sleeps every time after
+ handling new file open / close event. When several log files are opened or
+ closed simultaneously process is significantly slowed down. Another issue is
+ that thread always sleeps 1000ms that may be 2x longer than aggregation round.
+ This slows down overall signing process.
+ Fix for the issue is to simply not sleep after file open / close event if there
+ are next items to be processed. To speed up the signing process, rsyslog uses
+ KSI aggregator conf. to obtain the aggregation period that is used for the sleep
+ time configuration.
+ Thanks to Taavi Valjaots for the patch.
+- 2022-08-04: ksi bugfix: possible crash fixed when several log files are opened.
+ KSI module in async mode used to request aggregator conf. every time a log
+ file was opened. When several log files were opened simultaneously
+ corresponding amount of pointless concurrent conf. requests were posted.
+ Concurrent conf. requests lead to a bug in libksi, where internal count of
+ pending requests was not decremented correctly causing system to crash.
+ Fix for the issue is to optimize the frequency of conf. requests so that only
+ one conf. requests is handled at once. Instead of checking conf. every time
+ log file is opened, conf is requested periodically after conf timeout. This will
+ affect both sync and async mode.
+ New option for KSI module introduced - sig.confinterval="time, s".
+ Thanks to Taavi Valjaots for the patch.
+- 2022-08-04: openssl: add support to split tls commands by semicolon
+ - Add support to split tls commands by semicolon.
+ - Changed one test with multiple tls commands to use semicolon as
+ separator instead of newline.
+ closes: https://github.com/rsyslog/rsyslog/issues/4852
+- 2022-08-04: openssl subsystem bugfix: build issue on Solaris
+ Needed header file was added. Platforms other than Solaris did not actually need it,
+ so this bug was discovered late.
+ Thanks to Jakub Kulík for the patch.
+ Import <strings.h> when index() is used.
+- 2022-08-04: openssl: add more details to error messages
+ - Avoid LogMsg outputs osslEndSess on successfull terminated
+ connection. Only LogMsg if the connection was terminated
+ unsuccessfully.
+ - Handle SSL_ERROR_SYSCALL in both Send / osslRecordRecv,
+ do not log as error if underlaying socket was terminated
+ (ECONNRESET). Log as information instead.
+ closes: https://github.com/rsyslog/rsyslog/issues/4946
+- 2022-08-04: omclickhouse: capture additional exceptions
+ - DB::NetException
+ - DB::ParsingExceptions
+ Thanks to Victor Kustov for the patch.
+- 2022-08-04: mmanon bugfix: Simplified and fixed IPv4 digit detection.
+ - Fixed an issue with numbers above int64 in syntax_ipv4.
+ Numbers that were up to 256 above the max of an int64
+ could incorrectly be detected as valid ipv4 digit.
+ - Simplified the IPv4 digit detection function and renamed
+ to isPosByte.
+ - added testcasse for malformed IPvc4 addresses
+ closes: https://github.com/rsyslog/rsyslog/issues/4940
+- 2022-07-21: imptcp: slight tuning
+ - reduce indirect addressing to obtain more speed
+ - also a fix for an annoying typo
+ - minor other optimizations
+ - modernization of one test
+- 2022-07-20: template procesing/json: performance optimization
+- 2022-07-19: core bugfix: memory leak when free action worker data table
+ During free action worker data table when action destruct, worker instance in worker
+ data table were not null. It resulted in memory leak.
+ Thanks to github user seuzw930 for the patch.
+- 2022-07-13: omfile: support for zstd compression
+ The zstd library provides better and faster compression than zlib.
+ This patch integrates zstd as a dynamically-loadable functionality.
+ As such, no further dependencies need to be added to the rsyslog
+ base package.
+ Due to the increased performance, usage of zstd is highly recommended
+ for high-volume use cases.
+ This patch also refactor zlib compression in order to unify handling
+ in both compression cases.
+- 2022-07-07: stream cleanup: move error message to debug log, only
+ This error message is most probably rooted in a kernel problem. At
+ least knowbody knows how it can happen. It's definitely not a
+ rsyslog issue. We also can recover from it for a long time now
+ so there is no reason to irritate users by emitteing this
+ "error" message.
+- 2022-07-04: mmdblookup bugfix: Don't crash Rsyslog on mmdb file errors
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2022-06-28: build error fix: libbson requires out-of-date language constructs
+- 2022-06-27: OpenSSL: fix depreacted API issues for OpenSSL 3.x
+ - OpenSSL error strings are loaded automatically now
+ - Debug Callback has changed
+ - See for more:
+ https://www.openssl.org/docs/manmaster/man7/migration_guide.html
+ closes: https://github.com/rsyslog/rsyslog/issues/4912
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2206.0 (aka 2022.06) 2022-06-14
+- 2022-05-25: omelastisearch: allow omitting _type field
+ Allow omitting the _type field by setting it to an empty string.
+ Setting this field has been deprecated since 6.0, and support will
+ be removed in 8.0
+ Also add testbench test for empty searchType with ES 7.0
+ This checks for messages in the deprecation log and also provides
+ avoids deprecation messages from usage of transport.tcp.port in the
+ test configuration
+ Thanks to Jarkko Oranen for the patch.
+- 2022-05-18: tcpsrv/imtcp: slight performance improvements
+ This change slightly improves performance for tcpsrv-based servers.
+ This affects imtcp and imgssapi as well as some helpers.
+ No other functional change is included in this change.
+- 2022-05-12: imptcp bugfix: worker thread starvation on extreme traffic
+ When connectes were totally busy, without any pause, the assigened worker
+ did never terminate its reading loop. As such, it could not service any
+ other conenctions. If this happened multiple time and to all configured
+ workers, all other connections could not be processed at all. This extreme
+ scenario is very unlikely, as the whole issue is relatively unlikely.
+ In practice, the issue could lead to somewhat degraded performance and
+ resolved itself after some time (in practice no connection is 100% busy
+ for an extended period of time).
+ Note that this patch sets a fixed limit of 16 iterations for very busy
+ connections. This sounds like a good compromise between non-starvation
+ and performance. The exact number may be made configurable if there
+ is really need to.
+- 2022-05-11: omelasticsearch: several support option for ElasticSearch 8
+ - config params searchIndex and documentType can be empty
+ - support for Data Stream API
+ Thanks to github user EHerzog76 for these changes.
+ - new config param esVersion.major
+- 2022-05-09: tcp receiver bugfix: delay/potential hang on some error conditions
+ Error were not correctly handled in some cases for imtcp and imgssapi. This could
+ lead to a temporary stall of some connections. For ultry-low traffic systems, this
+ stall could stay for a long period of time. In most cases, it was resolved very quickly.
+ Note that imptcp was not affected.
+ Thanks to Iwan Timmer for the fix.
+- 2022-05-05: net bugfix: potential buffer overrun
+ there is heap buffer overflow vulnerability in rsyslog tcp reception components.
+ This can only happen in octet-counted mode, which is enabled by default.
+ Affected components: imtcp, imptcp, imhttp, imgssapi, imdiag when octet-counted
+ framing was enabled.
+ If the receiver ports are exposed to the public Internet AND are used
+ without authentication, this can lead to remote DoS and potentially to
+ remote code execution. It is unclear if remote code execution is
+ actually possible. If so, it needs a very sophisticated attack.
+ When syslog best practices with proper firewalling and authentication
+ is used, thean attack can only be carried out from within the Intranet
+ and authorized systems. This limits the severity of the vulnerability
+ considerably (it would obviously require an attacker already to be
+ present inside the internal network).
+ Credits to Peter Agten for initially reporting the issue and working
+ with us on the resolution.
+ fixes CVE-2022-24903
+ Advisory:
+ https://github.com/rsyslog/rsyslog/security/advisories/GHSA-ggw7-xr6h-mmr8#advisory-comment-72243
+- 2022-05-05: imptcp: set OS worker thread name
+ We now set the worker thread names to "imptcp/<thrd nbr>" where
+ <thrd nbr> is the numerical index (0, 1, ...) of the worker thread.
+ This enables to distinguish individual worker threads in OS tools like
+ htop. That is useful for performance testing and system monitoring.
+ The choosen name format is consistant with other similar thread
+ names inside rsyslog. For imptcp, worker threads were not yet
+ given individual names.
+ Note: "in:imptcp" is imptcp's "main" thread, which also is used
+ as a worker in some scenarios. This name was not modified.
+- 2022-04-26: mmanon bugfix: shortened IPv6 form not always anonymized
+ If the IPv6 is in non-recommended form followed by a 5 digit port number, it
+ is not anonymized.
+ A reproducer for this is: 1a00:c820:1180:c84c::ad3f:d991:ec2e:49255
+ closes https://github.com/rsyslog/rsyslog/issues/4856
+- 2022-04-22: mmdblookup fix: wrong copy of buffer
+ ...following parse of libmaxminddb's return after a successful search sometimes
+ failed to return specific field from data.
+ Thanks to Théo Bertin for the patch.
+- 2022-04-22: mmdblookup: several enhancements
+ - support arrays in MMDB entry
+ - support escaped quotes '"' in MMDB entry
+ - support '<' characters in MMDB entry, when in a field
+ - support '}' characters in MMDB entry, when in a field
+ Thanks to Théo Bertin for the patch.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2204.1 (aka 2022.04) 2021-05-05
+- security bugfix: potential buffer overrun in imptcp, imtcp, imgssapi and others
+ This addresses CVE-2022-24903
+ see also https://github.com/rsyslog/rsyslog/security/advisories/GHSA-ggw7-xr6h-mmr8
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2204.0 (aka 2022.04) 2021-04-19
+- 2022-04-18: gnutls bugfix: possibility of infinite loop
+ There was a rare possibility that the E_AGAIN/E_INTERRUPT handling
+ could cause an infinite loop (100% CPU Usage), for example when a TLS
+ handshake is interrupted at a certain stage.
+ * After gnutls_record_recv is called, and E_AGAIN/E_INTERRUPT error
+ occurs, we need to do additional read/write direction handling
+ with gnutls_record_get_direction.
+ * After the second call of gnutls_record_recv (Expand buffer)
+ we needed to also check the eror codes for E_AGAIN/E_INTERRUPT
+ to do propper errorhandling.
+ * Add extra debug output based on ossl driver.
+ * Potential fix for 100% CPU Loop Receiveloop after gtlsRecordRecv
+ in doRetry call.
+ closes https://github.com/rsyslog/rsyslog/issues/4834
+ closes https://github.com/rsyslog/rsyslog/issues/4818
+ closes https://github.com/rsyslog/rsyslog/issues/4638
+- 2022-04-17: core/bugfix: errorfile could grow over max configures size
+ When action.errorfile.maxsize configuration option is enabled and error file
+ already has a certain size smaller than max size configured, it is increasing
+ higher than configured max size as the error file is considered to be zero in code.
+ This fix reads current error file size and limits the size to the maximum
+ size configured.
+ Thanks to Sergio Arroutbi for the patch.
+ fixes https://github.com/rsyslog/rsyslog/issues/4821
+- 2022-04-17: omkafka bugfix: potential misadressing
+ The `failedmsg_entry` expects a null-terminated string in `key`, but
+ here we allocate with malloc and copy a string-with-length-n into only
+ the first n bytes. If the final byte is null, this is by coincidence
+ only.
+ This was observed by means of seeing random binary data appended to
+ keys submitted to kafka apparently at random. This could also result
+ in more severe problems, inclusing a segfault.
+ Thanks to David Buckley for the patch.
+- 2022-04-06: added new "FullJSONFmt" standard template (with addtl fields)
+ This comes handy for a number of use cases, especially with ElasticSearch.
+ Thanks to Art O Cathain for the patch.
+- 2022-04-04: imfile: potential processing delay
+ This was mentioned by Mikko Kortelainen without exact details on what exactly
+ this could cause in practice. But we were confident enough that it is worth
+ merging (though it does not look like something that brought real problems in
+ practice, as we do not know any related reports).
+ see also: https://github.com/rsyslog/rsyslog/pull/4445
+ Thanks to Mikko Kortelainen for the patch.
+- 2022-04-04: bugfix: cosmetic data races
+ there was a more or less cosmetic data race which could happen when children
+ processes died in quick sequence. Even then, no real harm happened, as all
+ children were reaped eventually.
+ A similar data race exists for HUP processing.
+ However, these races polluted TSAN test runs, and so we fixed them
+- 2022-04-01: add property options to support ISO week/year number
+ Thanks to Mattia Barbon for the patch.
+- 2022-04-01: core bugfix: "action suspended" message was emitted even when turned off
+ Most messages were diasabled, but there was one part of the code that ignored the
+ user configuration.
+ Thanks to Deyneko Aleksey for the patch.
+- 2022-03-31: testbench: add more tests for rscript comparison operations
+- 2022-03-31: core bugfix: make internal logs emitted during HUP procesing appear quicker
+ After call doHUP(), probably there is a internal log in the list. However, it
+ will not be wrote out immediately, because the mainloop will be blocked at
+ pselect in wait_timeout() until a long timeout or next message occur.
+ More deadly, the log may be lost if the deamon exits unexpectedly.
+ We might as well put processImInternal() after doHUP(), so that the message
+ will be flushed out immediately.
+ Fixes: 723f6fdfa6(rsyslogd: Fix race between signals and main loop timeout)
+ Thanks to Yun Zhou for the patch.
+- 2022-03-20: refactor: Move the parser directive to the main config
+ Thanks to Attila Lakatos for the patch.
+- 2022-03-16: refactor: ake the main message queue part of the config
+ The intent of this patch is to make the main message queue part of the main config.
+ It will help us to proceed towards dynamic configuration reload.
+- regression bugfix: rsyslog may segfault during startup
+ glblGetMaxLine() might be called even before the main configuration file exists
+ resulting unexpected behavior, most probably segmentation fault. This is addressed
+ by re-introducing the old default of 8KiB. The problem was introduced earlier in
+ 2022.
+- regression fix: script string comparison did not work correctly
+ In rscript, comparison operations on strings did not work correctly
+ and returned false results. This is cause by a regression in commit
+ 5cec5dd634e0. While it fixed number comparisons, it introduced new
+ problems in string comparisons, which were not present before. Note
+ that most items in rsyslog are strings, so this can actually cause
+ some problems.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2202.0 (aka 2022.02) 2022-02-15
+- 2022-02-14: imfile bugfix: remove cause for "internal error message" (not causing harm)
+ When any message is output into a renamed input file, rsyslogd output the following:
+ message.
+ imfile: internal error? inotify provided watch descriptor 7 which we could not find
+ in our tables - ignored
+ When rsyslogd detects the inode change, it deletes the entry from wdmap[]. But,
+ the watch descriptor is not removed. Some application like sssd outputs some messages
+ (like "HUP signal was received!!") after HUP signal is received and before switching
+ into the new log file. And, the above messages can be output every log rotation.
+ This situation is now resolved.
+ Thanks to Masahiro Matsuya for the patch.
+- 2022-02-04: rscript bugfix: literal numbers were not compared correctly
+ This problem occurred when numbers were used in rsyslog.conf in
+ the set statement, e.g.
+ set $nbr = 1234;
+ In this case, during comparisons, the number was actually interpreted
+ as a string with digits. Thus numerical comparisons lead to unexpected
+ results. Even more so, as in other places of the code they were
+ treated as native numbers.
+ This is now fixed. We cannot outrule that this causes, in border cases,
+ change of behavior to existing configs. But it is unlikely and the
+ previous behaviour was a clear bug and very unintuitive. This in our
+ opinion it is justified to risk a breaking change for an expected
+ very minor subset of installations, if any such exists at all.
+ closes https://github.com/rsyslog/rsyslog/issues/4770
+- 2022-02-04: omelasticsearch bugfix: indexSuccess impstats counter in bulkmode wrong
+ When bulkmode is enabled, and a batch was processed without any
+ failures (errors is false), the code that increments the indexSuccess
+ impstats counter was never reached.
+ closes: https://github.com/rsyslog/rsyslog/issues/4794
+- 2022-01-17: imkmsg bugfix: effectively disabled input on error reading kmsg
+ Due to a program bug, imkmsg could not recover from an kmsg read error.
+ Note that recovering is possible and was intended.
+ Thanks to Kailash Sethuraman for the patch.
+- 2022-01-17: imtcp bugfix: worker threads were not properly terminated
+ Graceful shutdown of Rsyslog could lead to segmentation faults when
+ multiple imtcp inputs were being used. That is because the rest of the
+ tcpsrv threads are left behind running, while their underlying objects
+ are being disposed by the main thread as part of the module
+ de-initialization.
+ closes: https://github.com/rsyslog/rsyslog/issues/4776
+ Thanks to Gabor Orosz <goro@goro.io> for the analysis and patch.
+- 2022-01-07: omlibdbi bugfix: use-after-free bug
+ This occurred in when sqllite driver was used. Depending on circumstances, this had
+ no visible issues (often) up to rsyslog segfault. The busier rsyslog is, the more
+ likely a bad outcome.
+- 2022-01-06: omhttp bugfix: memory leak in lokirest batchmode
+ A JSON object was created (valueObj) but not used and also not released causing a
+ memory leak. Over time, this could lead to memory overcomittent.
+ closes: https://github.com/rsyslog/rsyslog/issues/4766
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2112.0 (aka 2021.12) 2021-12-16
+- 2021-12-14: refactor:Deallocate outchannel resources in rsconf destructor
+ Thanks to Attila Lakatos for the patch.
+- 2021-12-14: refactor: use runConf instead of loadConf in ratelimiting during runtime
+ Thanks to Attila Lakatos for the patch.
+- 2021-11-22: new contribtion: URL parser module function using libfa
+ Thanks to Théo Bertin for the patch.
+- 2021-11-18: mmanon: relax IPv6 detection - improve anonymization
+ We so far tried to ensure a value is really an IPv6 address, in order
+ to avoid to mangle with just similar-looking information elements.
+ However, this lead to misdetection for unusual formats, e.g. when a
+ port is appended to a numerical IPv6 adress given without braces [].
+ This has been changed now. In a sense, we now prefer to err on the
+ side of privacy.
+ BEHAVIOR CHANGE:
+ Previously, a suspect value was not anonymized, and thus some other
+ elements (like some MAC addresses) preserved. Now the opposite is
+ true, and we anonymize anything that looks close enough to be an
+ IPv6 address. This improves anonymization.
+ closes https://github.com/rsyslog/rsyslog/issues/4725
+- 2021-11-10: ruleset bugfix: ruleset queue was incorrectly named
+ The ruleset was incorrectly and unusably named. This was a regeression
+ from 4a63f8e9629c3c9481a8b6f9d7787e3b3304320b.
+ Many thanks to github user digirati82 for alerting us.
+ closes https://github.com/rsyslog/rsyslog/issues/4730
+- 2021-11-10: omsnmp: update module to current IP best practices
+ The omsnmp module uses the inet_addr() function to convert the Internet host address
+ from IPv4 numbers-and-dots notation into binary data in network byte order. If the input
+ is invalid, INADDR_NONE (usually -1) is returned. Use of this function is problematic
+ because -1 is a valid address (255.255.255.255). We should avoid its use in favor of
+ inet_aton(), inet_pton(3), or getaddrinfo(3), which provide a cleaner way to indicate
+ error return [1].
+ This is just a request to satisfy covscan, so no error is reported at all.
+ Thanks to Attila Lakatos for the patch.
+- 2021-10-27: ommysql: fix threading bug
+ When the MariaDB connection was (re)established, old or NULL handle
+ could be used. This is fixed now.
+ We need to synchronize access to the mysql handle, because multiple threads
+ use it and we may need to (re)init it during processing. This could lead to
+ races with potentially wrong addresses or NULL accesses. If this really
+ matters mostly depends on the MariaDB/MySQL client library. It looks like
+ they guard against fatal failuers. Anyhow, logging errors inside rsyslog
+ could happen in any case.
+- 2021-10-25: testbench: false positive when impstats was not built
+ Test omfwd_fast_imuxsock failed when impstats was not built. This
+ has been corrected, test is now only executed when impstats is
+ present.
+- 2021-10-25: imtcp: add support for permittedPeers setting at input() level
+ The permittedPeers settig was actually forgotten during the refactoring
+ of TLS input() level settings. This functionality is now added.
+ closes: https://github.com/rsyslog/rsyslog/issues/4706
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2110.0 (aka 2021.10) 2021-10-19
+- 2021-10-13: config bugfix: global(security.abortonidresolutionfail=) did not work
+ when used with rscript based configuration, it was not checked.
+- 2021-10-13: config bugfix: global param $privDropToUser did not work correctly
+ The parameter was not implemented for rscript based configuration and
+ did not properly apply to legacy configuration. In essence, it almost always
+ did not work as expected.
+ see also: https://github.com/rsyslog/rsyslog/issues/4642
+ see also: https://github.com/rsyslog/rsyslog/commit/cbcaf2c7e5b67e5465e47bc7cc67af2eae47bd31
+- 2021-10-12: rscript bugfix: ruleset called async when ruleset had queue.type="direct"
+ The call rscript statement is able to call a rule set either synchronously or
+ asynchronously. We did this, because practice showed that both modes
+ are needed. For various reasons we decided to make async
+ calls if the ruleset has a queue assigned and sync if not.
+ To know if a "queue is assigned" we just checked if queue parameters were
+ given. It was overlookeded the case of someone explicitly specifying a
+ "direct queue", aka "no queue". As such, queue="direct" triggered async
+ calls. That in turn meant that when a write operation to a variable was
+ made inside that rule set, other rulesets could or could not see the
+ write. While if was often not seen, this was a data race where the
+ change could also be seen by the outside.
+ This is now fixed. No matter if queue.type="direct" is specified or
+ left out, the call will always by synchronous. Any values written to
+ variables will also be seen by the "outside world" in later processing
+ stages.
+ Note that this has some potential to BREAK EXISTING CONFIGURATIONS.
+ We deem this acceptable because:
+ 1. this was racy at all, so unexpected behaviour could alwas occur
+ 2. it is actually unlikely that someone used the triggering conditions
+ in practice. But we can not outrule this, especially when the
+ configuration was auto-generated.
+ Potential compatibility issues can be solved by defining a small
+ array-memory queue on the ruleset in question instead of specifying
+ direct type.
+ Again, we expect that almost all users will never experience any
+ problems. If you do, however, please let us know: we may add an
+ option to re-enable the bug.
+- 2021-10-12: ksi bugfix: locking bug fixed in rsksiCtxOpenFile
+ Thanks to Taavi Valjaots for the patch.
+- 2021-10-11: core bugfix: fix typo in error message
+ Thanks to github user jkschulz for the patch.
+- 2021-10-11: tcpsrv bugfix: compilation without exceptions
+ tcpsrv.c:992:1: error: label at end of compound statement
+ finalize_it:
+ ^~~~~~~~~~~
+ Quoting from pthread.h:
+ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+ be used in matching pairs at the same nesting level of braces.
+ Amends commit bcdd220142ec9eb106550195ba331fd114adb0bd.
+ Thanks to Orgad Shaneh for the patch.
+- 2021-10-11: mkubernetes bugfix: no connection retry to kubernetes APP
+ When connection to the kubernates API was not possible, mmkubernetes
+ did not retry. This does now happen via regular rsyslog retry
+ mechanism.
+ Thanks to github user jayme-github for the analysis and patch.
+ closes https://github.com/rsyslog/rsyslog/issues/4669
+- 2021-10-11: openssl bugfix: Correct gnutlsPriorityString (custom ciphers) behaviour
+ - Only apply default anon ciphers if gnutlsPriorityString is NULL and
+ Authentication Mode is set to anon. Otherwise we do not set them
+ as they overwrite custom Ciphers.
+ - Added two tests for custom cipher configuration (anon/certvalid mode).
+ - Add call for applyGnutlsPriorityString if gnutlsPriorityString changes.
+ - Merged openssl init code from Connect into osslInitSession
+ closes: https://github.com/rsyslog/rsyslog/issues/4686
+- 2021-10-11: build issue: handle undefined MAXPATHLEN, PATH_MAX
+ While we handled missing PATH_MAX, we did not handle missing MAXPATHLEN.
+ This happens under GNU/Hurd, because there is no official limit. However,
+ extremely long pathes are extremely uncommon, so we do not want to
+ use slow dynamic alloc each time we need to build pathes. So we
+ impose a limit of 4KiB, which should be fairly enough. Note that
+ this obviously increases stack requirements in GNU/Hurd.
+ As suggested by Michael Biebl, we have now implemented a generic
+ approach to handle this via autoconf.
+- 2021-09-12: openssl: extended output information on connection failure
+ Now includes the remote client/server IP address in the log output.
+- 2021-09-12: imhttp enhancements - query parameter ingestion & basic auth support
+ - Basic Authentication support & tests
+ * configured via imhttp option "basicAuthFile". This option should be configured
+ to point to your htpasswd file generated via a standard htpasswd tool.
+ tests:
+ * imhttp-post-payload-basic-auth.sh
+ * imhttp-post-payload-basic-auth-vg.sh
+ - Query parameter ingestion capability & tests
+ use t `addmetadata` option to inject query parameters into
+ metadata for imhttp input.
+ DISTRO PACKAGERS BEWARE: NEW DEPENDENCY FOR IMHTTP:
+ libaprutil (libaprutil1-dev on debian'ish, apr-util-devel on Red Hat)
+ Thanks to Nelson Yen for the patch.
+- 2021-09-07: testbench bugfix: privdrop tests under root user did not work
+ When running under root, the privdrop tests did not properly work. This
+ patch fixes the issue and skips test where necessary.
+ This also includes some modernization of the related tests.
+ closes https://github.com/rsyslog/rsyslog/issues/4619
+- 2021-09-07: core/ratelimiting: fix rate limiting for already parsed messages
+ Rate limiting may not have worked if the considered message had already
+ been parsed (not having NEEDS_PARSING in msgFlags).
+ This affects also imuxsock in its default configuration
+ (useSpecialParser="true" and ratelimit.severity="1")
+- 2021-09-07: core bugfix: use of property $wday terminates string
+ When $wday is used inside a template, all template parts after it
+ are ignored. For exmaple:
+ template(name="json_filename" type="string" string="/var/log/%$wday%.log")
+ would generate something like "/var/log/0" - the ".log" part would be
+ missing. For the same reason, $wday can not reliably checked in script
+ filters.
+ Thanks to Alain Thivillon for reporting the bug and providing an
+ excellent analysis, which essentiellay was exactly this fix here.
+ closes https://github.com/rsyslog/rsyslog/issues/4670
+- 2021-09-07: core/queue bugfix: potential misadressing when queue discarded messages
+ When a discard mark was set, the queue was very busy and discarded messages, a
+ NULL pointer access could happen. Depending on circumstances, several problems
+ could occur, including a SEGFAULT. This is now fixed.
+ closes: https://github.com/rsyslog/rsyslog/issues/4437
+- 2021-09-07: imdiga bugfix: iOverallQueueSize calculation could be incorrect
+ This issue only affects testbench and rsyslog development debugging. The active
+ messages counter, used for synchronizing test steps, went wrong when the queue
+ discarded messages on it's consumer thread. Now fixed.
+- 2021-09-06: gnutls driver: SAN priority did not work correctly on server side
+ PrioritizeSAN was not propagated when accepting a new connection, this is now fixed.
+ Thanks to Attila Lakatos for the patch.
+- 2021-08-24: config: implement script-equavalent for $PrivDrop* statements
+ closes https://github.com/rsyslog/rsyslog/issues/891
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2108.0 (aka 2021.08) 2021-08-17
+- 2021-08-16: openssl tls: Improved error message output on tls failures.
+ closes: https://github.com/rsyslog/rsyslog/issues/4645
+- 2021-08-16: impstats: add percentile metrics tracking functionality
+ Brief overview:
+ TO configure tracking percentile metrics in rainerscript:
+ User would need to define:
+ - which percentile to track, such as [p50, p99, etc.]
+ - window size - note, this correlates directly with memory usage to
+ track the percentiles.
+ To track a value, user would call built-in function `percentile_observe()` in their configurations to
+ record an integer value, and percentile metrics would be emitted every
+ impstats interval.
+ Thanks to Nelson Yen for the patch.
+- 2021-08-12: imfile: add parameter "ignoreolderthanoption"
+ instructs imfile not to ingest a file that has not been modified in the
+ specified number of seconds.
+ Thanks to github user yanjunli76 for the patch (submitted from Nelson Yen)
+- 2021-08-10: imklog bugfix: invalid memory adressing, could cause abort
+ This is a regeression from commit 94c4a87. It introduced a free() call
+ using an object that was no longer valid (the main pointer to the
+ to-be-freed object) was already freed at time of use. This could
+ cause various issues, including a segfault.
+ Note: this bug was triggerred only during late phase of rsyslog
+ shutdown, so it did not affect regular operation.
+ Special thanks to github user wxiaoguang for analyzing the issue
+ and providing a draft fix proposal, on which this patch builds.
+ see also https://github.com/rsyslog/rsyslog/pull/4629
+ closes https://github.com/rsyslog/rsyslog/issues/4625
+- 2021-08-09: imfile bugfix: deleteStateOnFileDelete missed some state files
+ When the log file is deleted, imfile would attempt to delete the statefile but it
+ was missing the file_id part of the statefile name. This means the statefiles were
+ only removed in the log file was less than 512 characters, because for very small
+ files the file ID hash is not created. This lead to some state files not being
+ deleted.
+ Thanks to pearseimperva for the patch.
+- 2021-08-09: imfile bugfix: hash char invalidly added in readmode != 0
+ If imfile is ingesting log files with readMode set to 2 or 1, the resulting
+ messages all have a '#' character at the end. This patch corrects the behaviour.
+ Note: if some external script "supported" the bug of extra hash character at
+ the end of line, it may be necessary to update them.
+ closes https://github.com/rsyslog/rsyslog/issues/4491
+- 2021-08-09: omelasticsearch bugfix: errorFile mutex was not consistently locked
+ Lock the file during SIGHUPs to avoid issues with concurrent accesses by
+ writeDataError().
+ Thanks to François Poirotte for the patch.
+- 2021-08-09: imudp: add socket type (IPv4 vs. 6) to input name
+ Most importantly, the input name is used for stats counter names as
+ well. Previously, the same name was used for IPv4 and IPv6, so we had
+ two counters with an equal name. That left users puzzled.
+ Unfortunately, this change can potentially require changes to existing
+ analysis scripts, as the name is now slightly different.
+ closes https://github.com/rsyslog/rsyslog/issues/4364
+- 2021-08-06: omfwd: add capability for action-specific TLS certificate settings
+ This permits to override the global definitions for TLS certificates
+ at the action() level.
+- 2021-08-06: imfile bugfix: file handle leak if "freshStartTail" was turned on
+- 2021-08-05: imtcp: permit to use different certificate files per input/action
+ This completes the ability to override global/default TLS settings at the imtcp
+ input() level. Support for using multiple CAs/Certs per Connection is now provided.
+- 2021-08-04: imptcp bugfix: keep alive interval was incorrectly set
+ The interval was accidentally set to keep alive interval. This has been
+ corrected.
+ closes https://github.com/rsyslog/rsyslog/issues/4609
+- 2021-07-08: openssl network driver bugfix: small memory leak
+ Fixes a static, non-growing memory leak which existed when parameter
+ "GnutTLSPriorityString" was used. This was primarily a cosmetic issue,
+ but caused some grief during development in regard to memory leak
+ detectors.
+ Note: yes, this is for openssl -- the parameter name is historical.
+- 2021-07-07: psrv bugfix: abort if no listener could be started
+ Modules (like imtcp and imdiag) which use tcpsrv could abort or
+ otherwise malfunction if no listener for a specific input could
+ be started.
+ Found during implementing a new feature, no report from practice.
+ But could very well happen.
+- 2021-07-07: mmkubernetes bugfix: apiserver error handling
+ - Added graceful handling of apiserver errors with unexpected responses,
+ i.e., anything other than 200, 404, or 429. Idea is that apiserver
+ transient error state will recover. We don't want mmkubernetes to miss
+ metadata resolution for containers that don't have cached metadata.
+ During these transient error states, mmkubernetes will provide basic
+ container file path based resolution of namespace and pod metadata for
+ new pods whose metadata is not yet cached. After this error state
+ recovers, mmkubernetes is expected to resume its metadata resolution as
+ expected.
+ - Added a unit test case for apiserver return 500 with changes to mock server
+ - Fixed existing unit test that was failing due to missing expected results file
+ - Added mmkubernetes unit tests to testbench
+ Thanks to Abdul Waheed for the patch (submitted from Nelson Yen).
+- 2021-07-07: ommongodb bugfixes
+ - Fix Segmentation fault when server is down
+ - Add server connexion check while resuming
+ Thanks to Kevin Guillemot for the patch.
+- 2021-06-28: omkafka improvements
+ - drain librdkafka queues and retry later during rsyslog restart or hup. This
+ re-injects messages into rsyslog's native queues.
+ - add statsname on per kafka instance for better visibility
+ - omkafka - count errors related ssl as "errors_ssl"
+ Thanks to Nelson Yen for the patch.
+- 2021-06-23: some CI/QA improvements, Travis-CI disabled
+ For the time being, Travis CI is disabled because it was outdated and Travis also
+ changed their system. We will re-evaluate if we re-enable it. Since quite a while
+ the Travits tests were redundant with the rest of CI, so this does not reduce
+ coverage.
+- 2021-06-23: omhttp bugfix: dynrestpath param in batch mode invalid
+ When batchmode was used, the templates could not be used to
+ expand dynrestpath. We are now storing the restpath param
+ within the batch data if we are in batch mode.
+ When we are in batch mode, and the restpath value changes, the
+ batch is submitted and reinitialized
+ closes: https://github.com/rsyslog/rsyslog/issues/4567
+- 2021-06-17: add predefined template RSYSLOG_SyslogRFC5424Format
+ This is essentially the same as RSYSLOG_SyslogProtocol23Format with
+ a better name and a fix to remove the unnecessary LF at the end of
+ the message.
+ The different name also enables us to fix the LF issue without
+ any concern about backwards compatibility.
+ closes https://github.com/rsyslog/rsyslog/issues/4384
+- 2021-06-17: impstats/bugfix: _sender_stats reports integer counter as string
+ Note that this introduces a small backwards incompatibility: in previous output
+ the field was of string type, now it is integer (as intended). We discussed this
+ on the mailing list and the overwhelming thought was that this is not a problem
+ because almost all analysis backends are able to cover that format change. This made
+ the bugfix essentially costmetic.
+ HOWEVER, if you still experience issues, please let us know. We can add an option
+ to provide the previous format, and just spared to do so because there was no
+ evidence it was needed.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2106.0 (aka 2021.06) 2021-06-15
+NOTE: the prime new feature is support for TLS and non-TLS connections
+via imtcp in parallel. Furthermore, most TLS parameters can now be overriden
+at the input() level. The notable exceptions are certificate files, something
+that is due to be implemented as next step.
+- 2021-06-14: new global option "parser.supportCompressionExtension"
+ This permits to turn off rsyslog's single-message compression extension
+ when it interferes with non-syslog message processing (the parser
+ subsystem expects syslog messages, not generic text)
+ closes https://github.com/rsyslog/rsyslog/issues/4598
+- 2021-05-12: imtcp: add more override config params to input()
+ It is now possible to override all module parameters at the input() level. Module
+ parameters serve as defaults. Existing configs need no modification.
+- 2021-05-06: imtcp: add stream driver parameter to input() configuration
+ This permits to have different inputs use different stream drivers
+ and stream driver parameters.
+ closes https://github.com/rsyslog/rsyslog/issues/3727
+- 2021-04-29: imtcp: permit to run multiple inputs in parallel
+ Previously, a single server was used to run all imtcp inputs. This
+ had a couple of drawsbacks. First and foremost, we could not use
+ different stream drivers in the varios inputs. This patch now
+ provides a baseline to do that, but does still not implement the
+ capability (in this sense it is a staging patch).
+ Secondly, we now ensure that each input has at least one exclusive
+ thread for processing, untangling the performance of multiple
+ inputs from each other.
+ see also: https://github.com/rsyslog/rsyslog/issues/3727
+- 2021-04-27: tcpsrv bugfix: potential sluggishnes and hang on shutdown
+ tcpsrv is used by multiple other modules (imtcp, imdiag, imgssapi, and,
+ in theory, also others - even ones we do not know about). However, the
+ internal synchornization did not properly take multiple tcpsrv users
+ in consideration.
+ As such, a single user could hang under some circumstances. This was
+ caused by improperly awaking all users from a pthread condition wait.
+ That in turn could lead to some sluggish behaviour and, in rare cases,
+ a hang at shutdown.
+ Note: it was highly unlikely to experience real problems with the
+ officially provided modules.
+- 2021-04-22: refactoring of syslog/tcp driver parameter passing
+ This has now been generalized to a parameter block, which makes it much cleaner and
+ also easier to add new parameters in the future.
+- 2021-04-22: config script: add re_match_i() and re_extract_i() functions
+ This provides case-insensitive regex functionality.
+ closes https://github.com/rsyslog/rsyslog/issues/4429
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2104.0 (aka 2021.04) 2021-04-20
+- 2021-04-19: new contributed module imhiredis
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2021-04-19: new built-in function get_property() to access property vars
+ Provides ability to evaluate a rsyslog variable using dynamically
+ evaluated parameters.
+ 1st param is the rsyslog param, 2nd param is a key, can be an array
+ index or key string.
+ Useful for accessing json sub-objects, where a key
+ needs to be evaluated at runtime. Can be used to access arrays as well.
+ Thanks to Nelson Yen for contributing this module.
+- 2021-04-19: mmdblookup: add support for mmdb DB reload on HUP
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2021-04-19: script bugfix: empty array in foreach() improperly handled
+ When running a foreach() loop inside a ruleset, if the json array/object iterated
+ over is empty but valid, the foreach will make the message processing in the
+ ruleset abort operation, no following operation (such as actions) will be
+ executed after this.
+ Thanks to Théo Bertin (frikilax) for the patch.
+- 2021-04-19: imjournal bugfixes (handle leak, empty file)
+ Flush the FILE* buffer before rename & fsync in order
+ to not end up syncing an empty file.
+ Also, close WorkDir on fsync in order to prevent
+ file descriptor leakage.
+ Thanks to github user gerd-rausch for the fix.
+- 2021-04-06: new contributed function module fmunflatten
+ This commit adds a new rainerscript function to unflatten keys in a JSON tree. It
+ provides a way to expand dot separated fields.
+ <result> = unflatten(<source-tree>, <key-separator-character>);
+ It allows for instance to produce this: { "source": { "ip": "1.2.3.4", "port": 443 } }
+ from this source data: { "source.ip": "1.2.3.4", "source.port": 443 }
+ Thanks to Julien Thomas for the contribution.
+- 2021-02-22: test bugfix: some tests did not work with newer TLS library versions
+ Newer versions provide TLS versions that cannot be disabled in older versions as they
+ are unknown there. This is solved by setting restrictions in multiple steps. For
+ older library versions, the final step will error out, but the other one be applied.
+ This permits to achieve proper test results.
+ closes: https://github.com/rsyslog/rsyslog/issues/4534
+- some improvements to project CI
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2102.0 (aka 2021.02) 2021-02-16
+- 2021-02-15: omfwd: add stats counter for sent bytes
+ Thanks to John Chivian for suggesting this feature.
+- 2021-02-15: omfwd: add error reporting configuration option
+ RSyslog on a plain TCP cannot guarantee the message delivery
+ without using RELP protocol. Besides that the logs may be
+ flooded with connection errors making the rest of messages
+ difficult to find. To alleviate the problem (see issue 3910),
+ this patch adds a configuration option that enables to reduce
+ the number of network errors logged and reported.
+ For example, if each 10th network error message should be logged,
+ the rsyslog configuration has to be updated as follows.
+ action(type="omfwd" Target="<IP_ADDR>" Port="<PORT>" Protocol="tcp" ConErrSkip="10")
+ Thanks to Libor Bukata for the patch.
+- 2021-02-15: action stats counter bugfix: failure count was not properly incremented
+ In some cases the counter was not incremented, most notably with transaction-enabled
+ actions.
+ Thanks to github user thinkst-marco for the patch.
+- 2021-02-15: action stats counter bugfix: resume count was not incremented
+ And so it always stayed at zero.
+ Thanks to github user thinkst-marco for the patch.
+- 2021-02-15: omfwd bugfix: segfault or error if port not given
+ If omfwd is configured via RainerScript config format and the "port"
+ parameter is not given, a segfault will most likely happen on
+ connection establishment for TCP connections. For UDP, this is
+ usually not the case.
+ Alternatively, in any case, errors may happen.
+ Note that the segfault will usually happen right on restart so this
+ was easy to detect.
+ We did not receive reports from practice. Instead, we found the bug
+ while conducting other work.
+- 2021-01-29: lookup table bugfix: data race on lookup table reload
+ A data race could happen when a lookup table was reloaded. We found
+ this while moving to newer version of TSAN, but have no matching
+ report from practice. However, there is a potential for this to cause
+ a segfault under "bad circumstances".
+- 2021-01-18: testbench modernization
+ Bump dependency versions, use newer distro versions for some tests.
+ Make kafka distcheck separate to help diagnose flaky kafka tests.
+- 2021-01-16: testbench: fix invalid sequence of kafka tests runs
+ kafka tests can not run well in parallel (mostly due to ressource
+ constraints on CI machines). Accidentally, this was not enforced for
+ one of the tests. That could lead to random failures and false positives.
+- 2021-01-14: testbench: fix kafkacat issues
+ The kafkacat tool has an upper limit of how many messages it can send
+ at once. Going over that limit causes messages loss. The exact limit
+ seems to depend on the environment. This causes testbench false positives.
+ This commit fixes two related issues:
+ - errors during kafkacat run were not detected - this has been added
+ - we now have a "max messages at once" setting, after which kafkacat
+ is restarted for the next batch of messages. It currently is set
+ to 25,000 msgs per incarnation. All tests loop now to send the
+ required number of messages. This has been fixed at the testbench
+ framework level, so no need to adjust individual tests.
+- 2021-01-14: testbench: fix year-dependendt clickhouse test
+ A test had the year value hardcoded and as such failed whenever the
+ year changed. This patch corrects that.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2012.0 (aka 2020.12) 2020-12-08
+- 2020-12-07: testbench bugfix: some tests did not work in make distcheck
+ - certificate file missing in dist tarball
+ - some test cases did not properly specify path to cert file
+ Thanks to Michael Biebl for alerting us and providing part of
+ the fix.
+ closes https://github.com/rsyslog/rsyslog/issues/4446
+- 2020-12-07: immark: rewrite with many improvements
+ - mark message text can now be specified
+ - support for rulesets
+ - support for using syslog API vs. regular internal interface
+ - support for output template system
+ - ability to specify is mark message flag can be set
+ - minor changes and improvements
+- 2020-11-30: usability: re-phrase error message to help users better understand cause
+ see also https://github.com/rsyslog/rsyslog/issues/3910
+- 2020-11-10: add new system property $now-unixtimestamp
+ Among others, this may be used as a monotonic counter
+ for doing load-balancing and other things.
+ Thanks to Nicholas Brown for suggesting this feature.
+- 2020-11-04: omfwd: add new rate limit option
+ Adding new rate limit option to omfwd for rate limiting
+ syslog messages sent to the remote server
+ ratelimit.interval:
+ Specifies the rate-limiting interval in seconds.
+ Default value is 0, which turns off rate limiting.
+ ratelimit.burst
+ Specifies the rate-limiting burst in number of messages.
+ closes https://github.com/rsyslog/rsyslog/issues/4423
+ Thanks to Dinesh-Ramakrishnan for the patch.
+- 2020-11-03: omfwd bug: param "StreamDriver.PermitExpiredCerts" is not "off" by default
+ The default behaviour of expired certificates of stream driver in TLS mode, should
+ have been that the see tcp transmission is closed due to expired certificates, and
+ error messages emited in rsyslog status. This was not the case. That in turn could
+ lead to permitting sessions which should not be permitted.
+ Thanks to Vincent Zhu for alerting us and providing a great problem analysis
+ closes: https://github.com/rsyslog/rsyslog/issues/4425
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2010.0 (aka 2020.10) 2020-10-20
+- 2020-10-13: gnutls TLS subsystem bugfix: handshake error handling
+ If the tls handshake does not immediatelly finish, gnutls_handShake is called in
+ doRetry handler again. However the error handling was not
+ complete in the doRetry handler. A failed gnutls_handShake call
+ did not abort the connection and properly caused unexpected
+ problems like in issues:
+ https://github.com/rsyslog/rsyslog/issues/4270
+ https://github.com/rsyslog/rsyslog/issues/4288
+- 2020-10-13: core/msg bugfix: memory leak
+ There is a missing call to json_object_put(json) if the call to
+ jsonPathFindParent() failed. It's leaking memory. Depending on workload and config,
+ this leak can potentially grow large (albeit we did not see reports from practice).
+ Thanks to Julien Thomas for the patch.
+- 2020-10-13: core/msg bugfix: segfault in jsonPathFindNext() when <root> not an object
+ The segfault gets happens when <bCreate> is 1 and when the <root>
+ container where to insert the <namebuf> key is not an object.
+ Here is simple reproducible test case:
+ // ensure we start fresh
+ // unnecessary if there was no previous set
+ unset $!;
+ set $! = "";
+ set $!event!created = 123;
+ Thanks to Julien Thomas for the patch.
+- 2020-10-13: openssl TLS subsystem: improvments of error and status messages
+ Adding error logs at the ssl handshake failure scenarios.
+ Adding the header "nsd_ossl:" tag to these logs to identify
+ the origin module from which logs are generated.
+ Thanks to Anusha Pai G for the patch.
+- 2020-10-06: add 'exists()' script function to check if variable exists
+ This implements a way to check if rsyslog variables (e.g. '$!path!var') is
+ currently set of not.
+ Sample: if exists($!somevar) then ...
+ closes https://github.com/rsyslog/rsyslog/issues/4385
+- 2020-10-03: core bugfix: do not create empty JSON objects on non-existent key access
+ Performing a condition (eg: check for an empty string) on a subtree key that do not
+ exists (depth > 1 from the root container), creates an empty "parent" object.
+ Depending on your context, you may end up with (kind of...) annoying garbage when
+ producing object documents (for instance to index in ES).
+ Also fixes a hypothetical hang condition with an almost (?) unused plugin parameter
+ passing mode, for details see
+ https://github.com/rsyslog/rsyslog/issues/4436
+ closes https://github.com/rsyslog/rsyslog/issues/4430
+ Thanks to Julien Thomas for the patch.
+- 2020-09-28: gnutls subsysem bugfix: potential hang on session closure
+ Some TLS servers don't reply to graceful shutdown requests "for
+ optimization". This results in rsyslog's omfwd+gtls client to wait
+ forever for a reply of the TLS server which never comes, due to shutting
+ down the connection with gnutls_bye(GNUTLS_SHUT_RDWR).
+ On systemd systems, commands such as "systemctl restart rsyslog" just
+ hang for 1m30 and rsyslogd gets killed upon timeout by systemd.
+ This is fixed by replacing the call to gnutls_bye(GNUTLS_SHUT_RDWR) by calls to
+ gnutls_bye(GNUTLS_SHUT_WR) which is sufficient and doesn't wait for a
+ server reply.
+ As an example, Kiwi Syslog server is known to cause this issue.
+ Thanks to Renaud Métrich for the patch.
+- 2020-09-23: core/network bugfix: obey net.enableDNS=off when querying local hostname
+ Local hostname resolution used DNS queries even if the enableDNS was set to off, and
+ this could cause unexpected delays in the HUP signal handling if the DNS server was
+ not responsive.
+ Thanks to Samu Nuutamo for the fix.
+- 2020-09-14: core bugfix: potential segfault on query of PROGRAMNAME property
+ A data race can happen on variable iLenProgram as it is not guarded
+ by the message mutex at time of query. This can lead to it being
+ non -1 while the buffer has not yet properly set up.
+ Thanks to Leo Fang for alerting us and a related
+ patch proposal.
+ replaces https://github.com/rsyslog/rsyslog/pull/4300
+- 2020-09-14: imtcp bugfix: broken connection not necessariy detected
+ Due to an invalid return code check, broken TCP sessions could not
+ necessarily be detected "right in time". This can result is the loss
+ of one message.
+ closes https://github.com/rsyslog/rsyslog/issues/4227
+ Thanks to Leo Fang for the patch.
+- 2020-09-14: new module: imhttp - http input
+ permits to receive log data via HTTP.
+ uses http library to provide http input.
+ user would need to configure an 'endpoint' as input, along
+ with a ruleset, defining how the input should be routed in
+ rsyslog.
+ Thanks to Nelson Yen for contributing this module.
+- 2020-09-11: mmdarwin bugfix: potential zero uuid when reusing existing one
+ - fix a use-after-free variable during darwin uuid message extraction
+ - improve debug/output by logging uuid parse errors
+ Thanks to github user frikilax for the patch.
+- 2020-09-10: imdocker bugfix: build issue on some platforms
+ An invalid variable type was used, leading to compile errors at least on
+ all platform that use gcc 10 and above. Otherwise, however, it looks like the
+ issue caused no real harm.
+- 2020-09-07: omudpspoof bugfix: make compatbile with Solaris build
+ Thanks to Dagobert Michelsen for the patch.
+- 2020-09-03: testbench fix: python 3 incompatibility
+- 2020-09-02: core bugfix: segfault if disk-queue file cannot be created
+ When using Disk Queue and a queue.filename that can not be created
+ by rsyslog, the service does not switch to another queue type as
+ supposed to and crashes at a later step.
+ closes: https://github.com/rsyslog/rsyslog/issues/4282
+- 2020-08-26: cosmetic: fix dummy module name in debug output
+ When we have optional components (like imjournal) a dummy module
+ is used. It's sole purpose is to emit "this module is not available".
+ During init, the module emitted an invalid module name into the debug
+ log. This has now been replaced by the generic term "dummy".
+ Note: it is highly unlikely that someone will ever see that message
+ at all, as it is unlikely for the dummy modules to be build.
+ see also: https://github.com/rsyslog/rsyslog/commit/84a7e3d80b80106dcc86c273ed8cf78a6c11c722#r41782830
+ Thanks to Thomas D. (whissi) for the patch.
+- 2020-08-26: config bugfix: intended warning emitted as error
+ When there are actions configured after a STOP, a warning should be
+ emitted. In fact, an error message is generated. This prevents the
+ construct, which may have some legit uses in exotic settings. It
+ may also break older configs, but as the message is an error
+ for so long now, this should be no longer of concern.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2008.0 (aka 2020.08) 2020-08-25
+- 2020-08-25: imdocker bugfix: error reporting not always correct
+ A wrong function to obtain the error code was used. This
+ could lead to invalid error messages.
+ Thanks to Steve Grubb for the bug report and fix proposal.
+ closes https://github.com/rsyslog/rsyslog/issues/4381
+- 2020-08-25: imptcp: add max sessions config parameter
+ The max is per-instance, not global across all instances.
+ There is also a bugfix where if epoll failed I think we could leave a
+ session linked in the list of sessions, this code unlinks it.
+ Thank to Alfred Perlstein for the patch.
+- 2020-08-24: omelasticsearch bugfix: reply buffer reset after health check
+ The issue happens when more than one server is defined on the
+ action. On that condition a health check is made through
+ checkConn() before sending the POST. The replyLen should be
+ set back to 0 after the health check, otherwise the response
+ data received from the POST gets appended to the end of the
+ last health check.
+ Thanks to Julien Thomas for the patch.
+- 2020-08-14: omfile: do no longer limit dynafile cache size in legacy format
+ When using obsolete legacy config format, omfile had a hard limit of
+ 1,000 dynafile cache entries. This does not play well with very
+ large installation. This limit is now removed and converted into
+ a warning if cache size > 25,000 is specified.
+ Note: the problem can easily be worked-around by using modern
+ config format (RainerScript).
+ closes: https://github.com/rsyslog/rsyslog/issues/4241
+- 2020-08-13: imudp: fix very small, static memory leak
+ When ruleset support was used, the ruleset name was not freed upon rsyslog
+ termination. While this has no consequences for regular runs, it generates
+ leak errors under memory debuggers and as such makes debugging harder than
+ necessary.
+ Thanks to github user frikilax for the patch.
+- 2020-08-13: omelasticsearch: add parameter skipPipelineIfEmpty
+ When POST'ing a document, Elasticsearch does not allow an empty pipeline
+ parameter value. This patch introduces boolean option skipPipelineIfEmpty
+ to the omelasticsearch action. When set to true, the pipeline parameter
+ won't be posted. Default is false so we do not modify current behavior.
+ Thanks to Julien Thomas for the patch.
+- 2020-08-12: systemd service file removed from project
+ This was done as distros nowadays have very different service files and it no
+ longer is useful to provide a "generic" (sic) example.
+ see also: https://github.com/rsyslog/rsyslog/issues/4333
+- 2020-08-11: gnutls TLS driver bugfix: EKU check not done properly
+ When the server accepted a new connection, it did not properly set the
+ dataTypeCheck field based on the listening socket. That resulted in
+ skipping ExtendedKeyUsage (EKU) check on the client.
+ Thanks to Daiki Ueno for the patch.
+- 2020-08-06: MMDARWIN:: improve configuration flexibility and UUID fix
+ -t pu now able to get fields from local variables ($.)
+ - now able to configure a custom root container for mmdarwin fields
+ - now able to put nested keys ($!key1!key2)
+ - don't regenerate a UUID each time, but instead check if one exists before
+ creating it (allow successive calls without losing previous UUID)
+ Thanks to github user frikilax for the contribution.
+- 2020-08-06: add --enable-imjournal=optional ./configure option
+- 2020-08-06: IMPCAP::Fixes: segfault, memory and build corrections
+ * fix bug in ethernet packets parsing
+ * fix removes build error with gcc10: 'multiple definition of...'
+ * resolve memory leak during interface init failure (device not freed after post-create error)
+ * add test 'impcap_bug_ether' to prove ethernet parser fix is working
+ Thanks to github user frikilax for the contribution.
+ closes https://github.com/rsyslog/rsyslog/issues/4332
+- 2020-07-14: CI: add support for github actions
+- 2020-07-14: imklog: add ruleset support
+ see also: https://github.com/rsyslog/rsyslog/issues/4344#issuecomment-658001854
+ see also: https://github.com/rsyslog/rsyslog/issues/106
+- 2020-07-06: config system fix: ChkDisabled method to make config.enabled work
+ There was wrong negation in the method so it returned 0/1 in reverse
+ and also it did not mark the node to not be reported as unknown at all
+ times which is needed after all.
+ Thanks to Jiri Vymazal for the patch.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2006.0 (aka 2020.06) 2020-06-23
+- 2020-06-22: queue: permit ability to double size at shutdown
+ This prevents message loss due to "queue full" when re-enqueueing data
+ under quite exotic settings.
+ see also https://github.com/rsyslog/rsyslog/issues/3941#issuecomment-549765813
+ closes https://github.com/rsyslog/rsyslog/issues/4020
+- 2020-06-22:Fixing imfile segfaulting on selinux denial
+ If imfile is denied access to file watched trough symlink there is
+ unchecked condition resulting in access to not initialized memory.
+- 2020-06-22: openssl: Fixed memory leak when tls handshake failed.
+ closes: https://github.com/rsyslog/rsyslog/issues/4319
+- 2020-06-22: change systemd service file to wait for network
+ now that rsyslog is usually only installed for real syslog servers,
+ we should assume that some network listening or forwarding happens
+ on start. As such we need to start a bit later, after the network.
+ This poses no problem as systemd nowadays comes with journal which
+ is in almost all cases configured to buffer log data while
+ rsyslog is not yet running.
+ see also https://github.com/rsyslog/rsyslog-pkg-rhel-centos/issues/72
+- 2020-06-22: NEW INPUT MODULE:: impcap, network packets input parser
+ Thanks to github user frikilax for the contribution.
+- 2020-06-22: ksi bugfix: Optimized code in KSI module initialization fixed.
+ KSI module initialization will not stuck in infinite loop when code is
+ built with optimization -O2.
+- 2020-06-05: operatingstatefile bugfix: month was given too low
+ The month was printed with the range 0 (January) to 11 (December).
+ This has now been corrected.
+ closes https://github.com/rsyslog/rsyslog/issues/4292
+- 2020-06-05: build system: add "optional" build functionality to some components
+ Nameley:
+ --enable-libdbi=optional
+ --enable-mmdblookup=optional
+ --enable-imkafka=optional
+ --enable-omkafka=optional
+ If used, builds a dummy module which just emits a "module not supported
+ on this platform" error message when loaded.
+ Primary use case for this system is Debian-ish builds on SUSE OBS,
+ where we prefer to have a single package definition for all versions
+ (else things get much more complicated).
+- 2020-05-23: config system bugfix: backticks cat segfault if file cannot be opened
+ when a `cat <filename>` construct is used in rsyslog.conf and <filename> can not
+ be accessed (does not exist, no permissions, ...), rsyslog segfaults.
+ Thanks to Michael Skeffington for notifying us and providing root cause analysis.
+ closes https://github.com/rsyslog/rsyslog/issues/4290
+- 2020-05-15: imtcp bugfix: octet framing/stuffing problem with discardTruncatedMsg on
+ When "discardTruncatedMsg" was enabled in imtcp, messages were incorrectly
+ skipped if the last character before the truncation was the LFdelimiter.
+ Also adds two testbench tests for this case.
+ closes: https://github.com/rsyslog/rsyslog/issues/4281
+- 2020-05-12: ompipe bugfix: race during HUP
+ When HUP was received, the write mutex was not acquired. This could
+ lead to unexpected invalidation of the output file descriptor.
+ Thanks to Julien Thomas for alerting us on this issue.
+ see also https://github.com/rsyslog/rsyslog/pull/4136#issuecomment-578326278
+- 2020-05-12: ompipe: add action parameter tryResumeReopen
+ Sometimes we need to reopen a pipe after an ompipe action gets
+ suspended. Sending an HUP signal to rsyslog does the job but requires
+ an interraction with rsyslog. The patch adds support for a new boolean
+ option, tryResumeReopen, for the ompipe action. It mimics what an HUP
+ signal would do.
+ Thanks to Julien Thomas for the patch.
+- 2020-05-12: imjournal: remove strcat call
+ Thanks to Jeff Marckel for the patch.
+- 2020-05-12: build system: libzcmq version requirement needs to be bumped
+ Thanks to Thomas Deutschmann for pointing this out.
+ closes https://github.com/rsyslog/rsyslog/issues/3957
+- 2020-05-12: testbench: download ElasticSearch binaries from rsyslog.com
+ The official ElasticSearch download site sometimes denies the download.
+- 2020-05-11: openssl netstream driver bugfix: context leak
+ The context object was not properly freed.
+ Thanks to Michael Zimmermann for the fix.
+- 2020-05-11: omhttp: Add support for multiple http headers
+ Allows the inclusion of multiple http headers on the REST call.
+ Thanks to callmegar for the patch.
+- 2020-04-29: core bugfix: group id could not be obtained for very large groups
+ Thanks to github user emilbart for the patch.
+- 2020-04-29: testbench additions (relp broken connection test)
+- 2020-04-29: omudpspoof bugfix: issues with oversized messages
+ First issue was an incorrect packet length in UDP Header. It has to be the FULL UDP Packet
+ regardless of the MTU Setting. As a result regardless of IP fragmentation, the MTU setting
+ also limited the siizmax size of the UDP message.
+ The second issue was incorrect calculation of the UDP Checksum with libnet if
+ IP fragmentation was used (Based on MTU Setting). As a result, the network packets were
+ dropped by the tcp stack before they even could reach there target. The workarround for this
+ problem is, that we set the UDP Checksum to 0x0000 which allows skipping of the checksum
+ test. Fixing the problem by calculating the correct UDP Checksum would require some
+ code changes in the libnet.
+ Also fixed the omudpspoof bigmsg test and increased the testing size to 16KB.
+- 2020-04-29: omprog: fix assert failed on HUP with output flag
+ If the 'output' setting of omprog was used and rsyslog received a HUP
+ signal just after starting (and before the omprog action received the
+ first log to process), an internal assertion could fail, causing
+ rsyslog to terminate. The failure message was "rsyslogd: omprog.c:660:
+ closeOutputFile: Assertion `pCtx->bIsRunning' failed."
+ The failure could also occur if rsyslog received a HUP signal during
+ the shutdown sequence.
+ This bug was introduced in v8.2004 by PR https://github.com/rsyslog/rsyslog/pull/4255
+ Although a test already existed that checked the interaction of HUPs
+ with the 'output' setting, it didn't always fail in this particular case
+ due to timing conditions. The test has been improved to cover this case
+ more reliably.
+ Thanks to Joan Sala Isern for the patch.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2004.0 (aka 2020.04) 2020-04-28
+- 2020-04-28: ksi bugfix: When KSI module is suddenly closed, files are finalized
+ In async. mode all pending signature requests are closed immediately and
+ unsigned block marker is attached with message about sudden closure.
+ Similar approach is used for blocks that already contain some records.
+ Empty blocks are just closed without any metadata.
+ Thanks to Taavi Väljaots for the patch.
+- 2020-04-28: ksi bugfix: Signer thread initialization is verified before usage.
+ When signer thread is created in rsksiInitModule thread successful
+ initialization is verified before returning the function. This will
+ prevent adding records to not initialized module and in case of an
+ error signature files opened will contain only magic bytes.
+ Thread flags replaced with thread state.
+ When init module fails, module is disabled.
+ Thanks to Taavi Väljaots for the patch.
+- 2020-04-28: ksi bugfix: Hardcoded default hash algorithm replaced with 'default'
+ Instead of hardcoded SHA-256 KSI_getHashAlgorithmByName("default")
+ is used to get default hash function.
+ Function rsksiSetHashFunction and SetCnfParam updated.
+ Thanks to Taavi Väljaots for the patch.
+- 2020-04-28: imfile bugfix: poential segfault in stream object on file read
+ - if cstrLen(pThis->prevMsgSegment) > maxMsgSize then len calculation
+ become negative if cstrLen(thisLine) < cstrLen(pThis->prevMsgSegment)
+ This causes illegal access to memory location and thus causing segfault.
+ - assigning len = 0 if cstrLen(pThis->prevMsgSegment) > maxMsgSize so that
+ it access the correct memory location.
+ Thanks to github user jaankit
+- 2020-04-28: openssl TLS drivers: made more reliable for older openssl versions
+ OpenSSL can retry some failed operations, but older versions need an explicit
+ opt-in to do so. This is now done.
+- 2020-04-28: omprog: fix bad fd errors in daemon mode
+ When omprog was used with the 'forceSingleInstance=on' option, and/or
+ the 'output' setting, "bad file descriptor" errors occurred, which
+ prevented the external program to be executed and/or the program output
+ to be correctly captured. The bug could also manifest as "resource
+ temporarily unavailable" errors, or other errors related to the use of
+ invalid/reassigned file descriptors. These errors only happened when
+ rsyslog ran in daemon mode (i.e. they didn't happen if rsyslogd was
+ run with the '-n' option).
+ The cause of the bug was that omprog opened the pipe fds needed by
+ these flags during the configuration load phase (in the 'newActInst'
+ module entrypoint). This is a bad place since the fork of the daemon
+ occurs after this phase, and all fds are closed when the daemon process
+ is started (see 'initAll' in rsyslogd.c), hence invalidating the
+ previously opened fds.
+ To correct this, the single child process and the output capture thread
+ are now started later, when the first log message is received by the
+ first worker thread. (Note: the 'activateCnf' module entrypoint, despite
+ being invoked after the fork, cannot be used for this purpose, since it
+ is invoked per module, not per action instance.)
+ Currently no automated test exists for this use case since the testbench
+ always runs rsyslog in non-daemon mode.
+ Affected versions: v8.38 and later
+ closes: https://github.com/rsyslog/rsyslog/issues/4247
+ Thanks to Joan Sala Isern for the patch.
+- 2020-04-28: omfile bugfix: $outchannel split log lines at rotation time
+- 2020-04-17: openssl: add support for libreSSL
+ Disable use of "@SECLEVEL" in default cipher string and
+ avoid SSL_CONF_CTX_set_flags() API when LIBRESSL is used.
+ This means tlscommands will not work.
+ closes: https://github.com/rsyslog/rsyslog/issues/4210
+- 2020-03-04: imudp bugfix: build problems on some Linux kernel versions
+ Thanks to Wen Yang for the patch.
+- 2020-03-02: conf output bugfix: -o produces missing space between call and rulename
+ Thanks to Tetiana Ohnieva for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/3761
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2002.0 (aka 2020.02) 2020-02-25
+- 2020-02-25: imfile: add per minute rate limiting
+ Add MaxBytesPerMinute and MaxLinesPerMinute options.
+ These take integer values and, respectively, limit the number
+ of bytes or lines that may be sent in a minute.
+ This can be used to put a limit on the count or volume of logs
+ that may be sent for an imfile.
+ Thanks to Greg Farrell for the patch.
+- 2020-02-24: core: add global parameter "security.abortOnIDResolutionFail"
+ This parameter controls whether or not rsyslog aborts when a name ID
+ lookup fails (for user and group names). This is necessary as a security
+ measure, as otherwise the wrong permissions can be assigned or privileges
+ are not dropped.
+ CHANGE OF BEHAVIOR
+ The default for this parameter is "on". In previous versions, the default
+ was "off" (by virtue of this parameter not existing). As such, existing
+ configurations may now error out.
+ We have decided to accept this change of behavior because of the potential
+ security implications.
+ closes https://github.com/rsyslog/rsyslog/issues/4164
+- 2020-02-24: openssl TLS driver bugfix: chained certificates were not accepted
+ This was supported since always inside GnuTLS driver, but was missing for openssl one.
+- 2020-02-24: core bugfix: too early parsing of incoming messages
+ In theory, rsyslog should call parsers on the queue worker threads whenever
+ possible. This enables the parsers to be executed in parallel. There are
+ some cases where parsers needs to be called earlier, namely when parsed
+ data is needed for rate-limiting.
+ The logic to do this previously did not work correctly and was fixed six
+ years ago (!) by b51dd22. Unfortunately, b51dd22 was overly agressive:
+ it actually makes the early parser call now mandatory, effectively moving
+ parsing to the input side where there is no to little concurrency.
+ We still do not need to call the parser when all messages, regardless of
+ severity, need to be rate-limited. This is the default and very frequent
+ case. This patch introduces support for this and as such makes parsers
+ able to run in parallel in the frequent case again.
+ closes https://github.com/rsyslog/rsyslog/issues/4187
+- 2020-02-20: testbench bugfix: two minor issues in omkafkadynakey.sh test
+ lead to false positives during test runs (depending on circumstances)
+ closes: https://github.com/rsyslog/rsyslog/issues/4134
+- 2020-02-20: testbench: set max extra data length for tcpflood from 200 to 512KiB
+ Added a imrelp test for big messages (256KB).
+ closes: https://github.com/rsyslog/rsyslog/issues/4158
+- 2020-02-20: config system bugfix: 'config.enabled' directive oddities
+ Previously the directive was processed way too late which caused false
+ errors whenever it was set to 'off' and possibly other problems.
+ Thanks to Jiri Vymazal for the patch.
+- 2020-02-09: imfile bugfix: timeout did not work on very busy system
+ The timeout feature was soley based on timeouts of the poll()
+ system call. On a very busy system, this would probably happen
+ very seldomly. Moreover, the timeout could occur later than
+ expected on any system with high load.
+ The issue was not reported from practice but discovered during
+ CI system improvements.
+- 2020-01-30: build system: change --enable-imfile-tests default to "yes"
+ This was accidentally set to "no" some time ago (actual commit unknown). Tests for
+ imfile should by default run when imfile is enabled.
+ see also https://github.com/rsyslog/rsyslog/issues/4120
+- 2020-01-27: build system: add option --enable-gnutls-tests
+ This enables us to build GNUtls support but not necessarily
+ test it in CI. This is useful for some specialised subcomponent
+ test. The default is enabled if gnutls is enabled and disabled if not.
+- 2020-01-26: testbench: new test for loadbalancing via global vars
+ This is a popular functionality which had not been routinely tested
+ in the past.
+- 2020-01-26: mmdblookup bugfix: invalid data returned when no entry found
+ Since the upgrade of the package libmaxminddb on FreeBSD (1.3.2_2 -> 1.4.2),
+ the module mmdblookup returns the first entry of the mmdb database even if the entry
+ is not found. After some debug, I found the solution in the official maxminddb
+ repository : to check if the entry is in database, we must check the found_entry
+ attribute, otherwise the function MMDB_get_entry_data_list will return the first
+ entry of the database if the entry is not found in it.
+ Thanks to Kevin Guillemot for the patch.
+- 2020-01-23: oversize message log bugfix: do not close fd -1
+ The oversize message log fd is always closed on HUP, even if it never
+ was opened (and thus has -1 value). This patch corrects the issue.
+ The bug had no know-bad effect in practice other than getting an
+ (ignored) error status from close(). However, it introduced warnings
+ in test runs (e.g. when running under valgrind).
+- 2020-01-22: imfile bugfix: saving of old file_id for statefiles
+ Previously we saved old file_id unconditionally, which led to not
+ deleting old statefiles if files changes without rsyslog running.
+ Now it should work correctly.
+ Thanks to Jiri Vymazal for the patch.
+- 2020-01-22: imfile bugfix: misadressing and potential segfault
+ Commit 3f72e8c introduced an invalid memory allocation size. This lead to
+ too-short alloc and thus to overwrite of non-owned memory. That in turn
+ could lead to segfaults or other hard to find problems.
+ The issue was detected by our upgraded CI system. We did not receive
+ any problem reports in practice. Nevertheless, the problem is real and
+ people should update affected versions to patched ones.
+ The bug was present in scheduled stable release 8.1911.0 and 8.2001.0.
+ see also: https://github.com/rsyslog/rsyslog/issues/4120
+ see also: https://github.com/rsyslog/rsyslog/pull/4141
+- 2020-01-20: core bugfix: potential race during HUP
+ when rsyslog is HUPed immediately after startup and before it is fully
+ initialized, there is a potential race with the list of loaded modules.
+ This patch ensures no bad things can happen in that case.
+ Detected by LLVM TSAN, not seen in practice.
+- 2020-01-20: testbench improvements and fixes
+ modernize tests, reduce robustness against slow machines, provide some
+ test framework functional enhancements, and optimize some tests.
+ Also includes some code changes to C testing components. Among others,
+ tests have slightly been speeded up by reducing the wait time at queue
+ shutdown. This is possible because of better overall completion checks.
+----------------------------------------------------------------------------------------
+Scheduled Release 8.2001.0 (aka 2020.01) 2020-01-14
+- 2020-01-12: core bugfix: race condition related to libfastjson when using DA queue
+ Rsyslogd aborts when writing to disk queue from multiple workers simultaneously.
+ It is assumed that libfastjson is not thread-safe.
+ Resolve libfastjson race condition when writing to disk queue.
+ see also https://github.com/rsyslog/rsyslog/issues/4041
+ Thanks to MIZUTA Takeshi for the fix.
+- 2020-01-12: omfwd bugfix: parameter streamdriver.permitexpiredcerts did not work
+ closes https://github.com/rsyslog/rsyslog/issues/4098
+- 2020-01-11: Bugfix: KSI module + dynafile in asynchronous mode fixed
+ Thanks to Taavi Valjaots for the patch
+- 2020-01-08: tls driver: add support to configure certificate verify depth
+ Support added in omfwd as instance parameter:
+ streamdriver.TlsVerifyDepth
+ Support added in imtcp as module parameter:
+ streamdriver.TlsVerifyDepth
+ Can be 2 or higher.
+ Support added into ossl driver
+ Support added into gtls driver
+ Added testcases for both drivers.
+ closes: https://github.com/rsyslog/rsyslog/issues/4035
+- 2020-01-08: modernization of testbench
+ moved some tests to newer standards, hardened them against slow testbench machines,
+ kafka component download improvements, and prevent dangling left-over test tool
+ instances from aborted tests
+- 2020-01-07: tls subsystem bugfix: default for permitExpiredCerts was invalidly "on"
+ The problem occurred with commit 3d9b8df in December 2018 and went into
+ scheduled stable 8.1901.0. Unfortunately, the change in default was not detected
+ until a year later. This commit re-enables the previous default ("off"), which is
+ also the only sensible default from a security PoV. Unfortunately, new 2019
+ deployments may begin to see connection rejection when usin expired certs. As
+ expired certs should not be used, this hopefully will not cause problems in
+ practice.
+ Thanks to Jiri Vymazal for the patch.
+- 2020-01-01: testbench: improve ElasticSearch test speed
+ We now support re-using suitable running ES instances, which reduces the
+ number of restarts.
+- 2019-12-31: omelasticsearch: improve curl reply buffer handling
+ The curl reply buffer (pWrkrData->reply) was allocated, realloced and freed with
+ each request. This has now been reduced to once per module, slightly increasing
+ overall performance.
+ closes https://github.com/rsyslog/rsyslog/issues/1964
+- 2019-12-31: config system: emit proper error message on $ in double-quoted string
+ closes https://github.com/rsyslog/rsyslog/issues/2869
+- 2019-12-30: core bugfix: rsyslog aborts when config parse error is detected
+ In defaut settings, rsyslog tries to continue to run, but some data
+ structures are not properly initialized due to the config parsing error.
+ This causes a segfault.
+ In the following tracker, this is the root cause of the abort:
+ see also https://github.com/rsyslog/rsyslog/issues/2869
+- 2019-12-30: fix some alignment issues
+ So far, this worked everywhere (for years). But it may still have
+ caused issues on some platforms.
+ closes https://github.com/rsyslog/rsyslog/issues/2608
+- 2019-12-27: core bugfix: APP-NAME fields could become empty
+ RFC 5424 specifies that an empty APP-NAME needs to be indicated by
+ "-". Instead, the field could become empty under certain conditions.
+ If so, outgoing 5424 messages were invalidly formatted.
+ This happened under quite unusual conditions, but could be seen
+ in practice.
+ closes https://github.com/rsyslog/rsyslog/issues/4043
+- 2019-12-27: core bugfix: reopen /dev/urandom file descriptor after fork on Linux
+ This patch updates prepareBackground() in tools/rsyslogd.c to reopen any file
+ descriptors used for random number generation in the child process. This fixes
+ an issue on Linux systems where the file descriptor obtained for /dev/urandom
+ by seedRandomNumber() in runtime/srutils.c was left closed after the fork. This
+ could be observed in procfs, where /proc/fd/ would show no open descriptors to
+ /dev/urandom in the forked process. /dev/urandom is reopened as the child may be
+ be operating in a jail, and so should not continue to use file descriptors from
+ outside the jail (i.e. inherited from the parent process).
+ I found that this issue led to rsyslog intermittently hanging during seedIV()
+ in runtime/libgcry.c. After the fork, the closed file descriptor number tended
+ to get re-assigned. randomNumber() would then read from an incorrect (although
+ still valid) file descriptor, and could block (depending on the state of that
+ file descriptor). This gave rise to the intermittent hang that I observed.
+ Thanks to Simon Haggett for the patch.
+- 2019-12-20: imdocker bugfix: did not compile without atomic operations
+- 2019-12-20: omclickhouse: new parameter "timeout"
+ Thanks to Pavlo Bashynskiy for the patch.
+- 2019-12-20: omhiredis: add 'set' mode plus some fixes
+ - new mode 'set' to send SET/SETEX commands
+ - new parameter 'expiration' to send SETEX instead of SET commands (only applicable to 'set' mode)
+ - fixes to missing frees
+ Thanks to github user frikilax for the patch.
+- 2019-12-18: relp: Add support setting openssl configuration commands.
+ Add new configuration parameter tls.tlscfgcmd to omrelp and imrelp.
+ (Using relpSrvSetTlsConfigCmd and relpCltSetTlsConfigCmd)
+ OpenSSL Version 1.0.2 or higher is required for this feature.
+ A list of possible commands and their valid values can be found in the
+ documentation: https://www.openssl.org/docs/man1.0.2/man3/SSL_CONF_cmd.html
+ The setting can be single or multiline, each configuration command is
+ separated by linefeed (n). Command and value are separated by
+ equal sign (=). Here are a few samples:
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2"
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1
+ MinProtocol=TLSv1.2"
+ Add to new testcases for librelp and tlscfgcmd.
+ closes https://github.com/rsyslog/rsyslog/issues/3959
+- 2019-12-18: bugfix core: potential segfault in template engine
+ under some circumstances (not entirely clear right now), memory
+ was freed but later re-used as state-tracking structures were not
+ properly maintained. Github issue mentioned below has full details.
+ Thanks to github user snaix for analyzing this issue and providing
+ a patch. I am committing as myself as snaix did not disclose his or
+ her identity.
+ closes https://github.com/rsyslog/rsyslog/issues/3019
+ closes https://github.com/rsyslog/rsyslog/issues/4040
+- 2019-12-18: fixed some minor issues detected by clang static analyzer 9
+- 2019-12-10: core/config bugfix: false error msg when config.enabled="on" is used
+ When the 'config.enabled="on"' config parameter an invalid error message
+ was emitted that this parameter is not supported. However, it was still
+ applied properly. This commit removes the invalid error message.
+ closes https://github.com/rsyslog/rsyslog/issues/4011
+- 2019-12-03: omsnmp bugfix: "traptype" parameter invalidly rejected value 6
+ "Traptype" needs to support values 0 to 6.
+ However, if value 6(ENTERPRISESPECIFIC) was set, an invalid error message
+ was emitted. Otherwise processing was correct.
+ This could lead to problems with automatic config deployment,
+ as valid configurations were invalidly reported as incorrect.
+ That in turn could make a deployment fail.
+ closes https://github.com/rsyslog/rsyslog/issues/3973
+- 2019-12-03: omsnmp: add new parameter "snmpv1dynsource"
+ If set, the source field from SNMPv1 trap can be overwritten
+ with a template, default is "%fromhost-ip%". The content should be a
+ valid IPv4 Address that can be passed to inet_addr(). If the content
+ is not a valid IPv4 Address, the source will not be set.
+ closes: https://github.com/rsyslog/rsyslog/issues/3991
+- 2019-12-02: imfile bugfix: state file renaming sometimes did not work properly
+ Now checking if file-id changes and renaming - cleaning state file
+ accordingly and always checking and cleaning old inode-only style
+ state files.
+ Thanks to Jiri Vymazal for the patch.
+- 2019-12-02: ratelimit: increase rate limit interval parameter max value
+ The burst parameter in the ratelimit was increased to an unsigned int
+ but the interval remained an unsigned short. While it may be unusual,
+ there is possibly a chance to need to represent an interval longer than
+ about 3/4 of a day.
+ While here, go through and normalize all the various incarnations of
+ rate limiting to be explicitly unsigned int for the burst and interval.
+ Thanks to github user frikilax for the patch.
+- 2019-12-02: ommongodb: Add other supported formats for 'time' and 'date' fields
+ Thanks to github user frikilax for the patch.
+- 2019-12-02: imjournal bugfix: too many messages in error case
+ Under certain error conditions, `ignorePreviousMessages="on"` could be ignored
+ an existing messages be processed.
+ Thanks to github user 3chas3 for the patch.
+- 2019-11-27: core bugfix: action on retry mangles messages
+ When a failed action goes into retry, template content is rendered
+ invalid if the action uses more than 1 template.
+ closes https://github.com/rsyslog/rsyslog/issues/3898
+ Thanks to Mikko Kortelainen for the patch.
+- 2019-11-27: testbench: improve mysql testing support
+ tests can now run in parallel and are hardened against several glitches
+- 2019-11-22: omhttp: add basic support for Loki Rest
+ Loki is a new message indexer and querier from Grafana Labs. See
+ https://github.com/grafana/loki for details on Loki.
+ This change provides the initial message structure to send bulk message
+ payloads to the Loki Rest endpoint. omhttp, received a new bulk message
+ format called lokirest. Additionally, the plugin relies on the user to
+ provide the correct "stream" read message format.
+ A loki template must be json compatible and include a "stream" key of
+ key value tags, and a values key of an array of 2 element arrays, where
+ each 2 element array is the unix epoch in nanoseconds followed by an
+ unstructured message.
+ An example:
+ template(name="array_loki" type="string" string="{\"stream\":{\"host\":\"%HOSTNAME%\",\"facility\":\"%syslogfacility-text%\",\"priority\":\"%syslogpriority-text%\",\"syslogtag\":\"%syslogtag%\"},\"values\": [[ \"%timegenerated:::date-unixtimestamp%000000000\", \"%msg%\" ]]}")
+- 2019-11-22: testbench: obtain python binary path via AM_PATH_PYTHON
+ see also https://github.com/rsyslog/rsyslog/issues/3853
+- 2019-11-22: omprog: detect violation of interface protocol
+ The spec for the omprog interaction with the program it calls specifies
+ that the program receives one message via one line. In other words:
+ it must be a string terminated by LF.
+ However, omprog does currently rely on a proper template to fulfill this
+ requirement, If the template does not provide for the LF, it is never
+ written. For the called program, this looks like it does not receive any
+ input at all. Even if it finally reads data (e.g. due to full buffer),
+ it will not properly be able to discern the messages.
+ This handling is improved with this commit.
+ We cannot just check the template, because at the end of the template
+ may by a non-constant value. As such, we do not know at config load
+ time if there is this problem or not.
+ So the correct approach is to, during runtime, check if each message
+ is properly terminated. For those that are not:
+ * we append a LF, because anything else makes matters worse
+ * log a warning message, at least for a sample of the messages
+ The warning is useful in the (expected most often) case that the template
+ is simply missing the LF. While appending works, it slows down processing.
+ As such the user should be given a chance to correct the config bug.
+ To avoid clutter, the warning is emitted at most once every 30 seconds.
+ This value is hardcoded as we do not envision a need to adjust it. Usually
+ users should quickly fix the template.
+ closes https://github.com/rsyslog/rsyslog/issues/3975
+- 2019-11-19: core queue: emit warning if parameters are set for direct queue
+ Direct queues do not apply queue parameters because they are actually
+ no physical queue. As such, any parameter set is ignored. This can
+ lead to unintentional results.
+ The new code detects this case and warns the user.
+ closes https://github.com/rsyslog/rsyslog/issues/77
+- 2019-11-19: imjournal bugfix: do not wait too long on recovery try
+ When trying to recover journal errors, imjournal waited a hardcoded
+ period of 10s between tries. This was pretty long and could lead to
+ loss of journal data.
+ This commit adjust it to 100ms, which should still be fully sufficient
+ to prevent the journal from "hammering" the CPU.
+ It may be worth considering to make this setting configurable - but
+ let's first see if there is real demand to actually do that.
+ closes https://github.com/rsyslog/rsyslog/issues/3969
+- 2019-11-19: mmutf8fix: enhance handling of incorrect UTF-8 sequences
+ 1. Invalid utf8 detection didn't handle 3 and 4-byte overlong encodings (2
+ byte overlong encodings were handled explicitly by rejection E0 and E1
+ start bytes). Unified checks for overlong encodings.
+ 2. Surrogates U+D800..U+DFFF are not valid codepoints (Unicode Standard, D92)
+ 3. Replacement of characters in invalid 3 or 4-bytes encodings was too
+ eager. It must not replace bytes which are valid UTF-8 sequences. For
+ example, in [0xE0 0xC2 0xA7] sequence the 0xC2 is invalid as a continuation
+ byte, but it starts a valid UTF8 symbol [0xC2 0xA7]. That is, with current
+ code processing the sequence will result in "???" but the correct result is "?§"
+ (provided that the replacement character is "?").
+ 4. Various tests for UTF-8 invalid/valid sequences.
+ Thanks to Sergei Turchanov for the patch.
+- 2019-11-14: imfile: add new input parameter escapeLF.replacement
+ The new parameter permits to specify a replacement to be configured
+ when "escapeLF" is set to "on". Previously, a fixed replacement string
+ was used ("#012"/"\n") depending on circumstances. If the parameter is
+ set to an empty string, the LF is simply discarded.
+ closes https://github.com/rsyslog/rsyslog/issues/3889
+----------------------------------------------------------------------------------------
+Scheduled Release 8.1911.0 (aka 2019.11) 2019-11-12
+- 2019-11-12: core queue: add config param "queue.takeFlowCtlFromMsg"
+ This is a fine-tuning option which permits to control whether or not
+ rsyslog shall alays take the flow control setting from the message. If
+ so, non-primary queues may also block when reaching high water mark.
+ This permits to add some synchronous processing to rsyslog core engine.
+ However, it is dangerous, as improper use may make the core engine
+ stall. As such, enabling this option requires very careful planning
+ of the rsyslog configuration and deep understanding of the consequences.
+ Note that the option is applied to individual queues, so a configuration
+ with a large number of queues can (and must if use) be fine-tuned to
+ the exact use case.
+ The rsyslog team strongly recommends to let the option turned off,
+ which is the default setting.
+ see also https://github.com/rsyslog/rsyslog/issues/3941
+- 2019-11-12: imrelp: add new config parameter "flowcontrol"
+ This permits to fine-tune the flowControl parameter. Possible values are
+ "no", "light", and "full". With light being the default and previously
+ only value.
+ Changing the flow control setting may be useful for some rare applications,
+ but be sure to know exactly what you are doing when changing this setting.
+ Most importantly, whole rsyslog may block and become unresponsive if you
+ change flowcontrol to "full". While this may be a desired effect when
+ intentionally trying to make it most unlikely that rsyslog needs to
+ lose/discard messages, usually this is not what you want.
+ see also https://github.com/rsyslog/rsyslog/issues/3941
+- 2019-11-11: imrelp: remove unsafe debug instrumentation
+ dbgprintf, which is not signal safe, was called from a signal handler
+ to get better understanding during debugging. While this usually works,
+ it can occasionally (5%) lead to a hang during shutdown. We have now
+ removed that debug info as it is no longer vital.
+ Note: this could only happen during debug runs. Production mode was
+ not affected. As such, this fix is only relevant to developers.
+ However, it caused some confusion in the following issue tracker.
+ see also https://github.com/rsyslog/rsyslog/issues/3941
+- 2019-11-06: ossl driver bugfix: fix wrong OpenSSL Version check
+ Fix OpenSSL Version check in:
+ - SetGnutlsPriorityString function in nsd_ossl.c
+ - initTLS() function tcpflood.c
+ See https://www.openssl.org/docs/man1.1.0/man3/OPENSSL_VERSION_NUMBER.html
+ for more.
+ This bug lead to not enabling some functionality correctly.
+ Removed "MinProtocol=TLSv1.1" from two testcases because MinProtocol
+ is only supported by OpenSSl 1.1.0 or higher and was not really
+ necessary for the testcases.
+ closes https://github.com/rsyslog/rsyslog/issues/3939
+- 2019-11-05: mmdarwin: Optimizations, new parameters, update to protocol header
+ - use permanent worker-dependent buffers to avoid malloc/free for each entry
+ - move socket structures to worker data, remove global mutex
+ - add log lines for parameters and general workflow
+ - don't send body if empty/incomplete (see new parameters)
+ - don't close/reopen socket every time -> let session open or create new every X
+ entry (see new parameters)
+ - clean up code
+ - added 'send_partial', to let mmdarwin send body if not all fields were
+ retrieved, or not; default false = only send complete bodies
+ - added 'socket_max_use' to open new session every X packet, useful for
+ some versions of Darwin (prior to 1.1)
+ default is 0 = do not open new session/keep only one
+ - added 'evt_id' to the darwin header (Darwin v1+ compatibility)
+ Note: mmdarwin is a contributed module
+ Thanks to github user frikilax for the patch.
+- 2019-11-01: mmkubernetes bugfix: improper use of realloc()
+ could cause problems under extreme memory shortage - very unlikely
+ credits to LGTM.COM for detecting this
+- 2019-10-31: imjournal: set the journal data threshold to MaxMessageSize
+ When data is read from the journal using sd_journal_get_data it may be
+ truncated to a certain threshold (64K by default).
+ If the rsyslog MaxMessageSize is larger than the threshold, there is a
+ chance rsyslog will receive incomplete messages from the journal.
+ Empirically, this appears to happen reliably when XZ compression is
+ used by journald. Systems where journald uses LZ4 compression do not
+ appear to suffer this issue reliably--if at all.
+ This change sets the threshold to the MaxMessageSize when the
+ journal is opened.
+ Thanks to Robert Winslow Dalpe for the patch.
+- 2019-10-30: improg bugfix: allow improg to handle multi-line inputs
+ miscellaneous bug fixes in improg:
+ * properly truncate string after an input event is submitted
+ * set msgoffset to 0.
+ * tests added to check above fixes
+ Thanks to Nelson Yen for the fix.
+- 2019-10-30: mmdblookup bugfix: missing space in city name
+ This fixes the issue that spaces in city names are dropped. However, the
+ fix is more or less a work-around. As it turns out, the libmaxminddb API
+ is not correctly used. In the somewhat longer term, we should fix this.
+ see also https://github.com/maxmind/libmaxminddb/issues/218
+ closes https://github.com/rsyslog/rsyslog/issues/1650
+- 2019-10-30: core/queue: provide ability to run diskqueue on multiple threads
+ Up until this release, disk queues could only use a single thread,
+ what limited their performance with outputs like ElasticSearch.
+ Now disk queues can utilize multiple threads just like any other
+ queue type. Most importantly, the disk queue part of a DA queue
+ now inherits the max number of threads from its memory queue
+ counterpart.
+ NOTE: the new multi-threaded DA disk queue is actually a change of
+ behavior. We have not guarded it by a new config switch as we
+ assume the new behavior is most often exactly within user
+ expectations. In any case, we cannot see any harm from running
+ the disk queue on multiple threads.
+ see also https://github.com/rsyslog/rsyslog/issues/3543
+ closes https://github.com/rsyslog/rsyslog/issues/3833
+- 2019-10-25: omfile bugfix: file handle leak
+ The stream class does not close re-opened file descriptors.
+ This lead to leaking file handles and ultimately to the inability
+ to open any files/sockets/etc as rsyslog ran out of handles.
+ The bug was depending on timing. This involved different OS
+ thread scheduler timing as well as workload. The bug was more
+ common under the following conditions:
+ - async writing of files
+ - dynafiles
+ - not committing file data at end of transaction
+ However it could be triggered under other conditions as well.
+ The refactoring done in 8.1908 increased the likelihood of
+ experiencing this bug. But it was not a real regression, the new
+ code was valid, but changed the timing so that the race was more
+ likely.
+ Thanks to Michael Biebl for reporting this bug and helping to
+ analyze it.
+ closes https://github.com/rsyslog/rsyslog/issues/3885
+- 2019-10-22: imfile bugfix: improper use of calloc()
+ could cause problems under extreme memory shortage - very unlikely
+ credits to LGTM.COM for detecting this
+- 2019-10-22: TLS driver bugfix: improper use of calloc()
+ can cause problems under extreme memory shortage - very unlikely
+ credits to LGTM.COM for detecting this
+- 2019-10-22: imuxsock bugfix: improper use of calloc()
+ can cause problems under extreme memory shortage - very unlikely
+ credits to LGTM.COM for detecting this
+- 2019-10-17: build system bugfix: incorrect default in ./configure help text
+ closes https://github.com/rsyslog/rsyslog/issues/3904
+ Thanks to Michael Biebl for pointing this out.
+- 2019-10-17: mmkubernetes bugfix: improper use of calloc()
+ can cause problems under extreme memory shortage - very unlikely
+ credits to LGTM.COM for detecting this
+- 2019-10-16: core queue bugfix: propagate batch size to DA queue
+ This was a long-standing bug where the DA queue always had a fixed small batch
+ size because the setting was not propagated from the memory queue. This also
+ removes a needless and counter-productive "debug aid" which seemed to be in
+ the code for quite some while. It did not cause harm because of the batch
+ size issue.
+- 2019-10-16: testbench: fix unreliable gzipwrite test
+ The test was timing-sensitive as we did not properly check all data
+ was output to the output file - we just relied on sleep periods.
+ This has been changed. Also, we made some changes to the testing
+ framework to fully support sequence checking of multiple ZIP files.
+- 2019-10-16: core queue bugfix: handle multi-queue-file delete correctly
+ Rsyslog may leave some dangling disk queue files under the following
+ conditions:
+ - batch sizes and/or messages are large
+ - queue files are comparatively small
+ - a batch spans more than two queue files (from n to n+m with m>1)
+ In this case, queue files n+1 to (n+m-1) are not deleted. This can
+ lead to problems when the queue is re-opened again. In extreme cases
+ this can also lead to stalled processing when the max disk space is
+ used up by such left-over queue files.
+ Using defaults this scenario is very unlikely, but it can happen,
+ especially when large messages are being processed.
+- 2019-10-16: imjournal: fix regression from yesterday's patch
+ commit 78976a9bc059 introduced a regression that caused writing
+ the journal state file to fail. This happens when the state file
+ is given as relative file name and the working directory is also
+ a relative path. This situation is very uncommon. So most deployments
+ will never experience it. We discovered the issue during CI runs
+ where the trigger condition is given. Note that it also takes
+ multiple times of loading the journal to actually see the bug.
+ see also https://github.com/rsyslog/rsyslog/pull/3878
+- 2019-10-15: imjournal plugin code restructuring, added remote option
+ Decomposed ReadJournal() a bit, also now coupling journald
+ variables in one struct, added few warning messages and debug
+ prints to help with bug hunts in future, also got rid of two
+ needless journald calls. WorkAroundJournalBug now deprecated.
+ Added option to pull journald records from outside local machine.
+ Thanks to Jiri Vymazal for the patch.
+- 2019-10-11: core bugfix: potential abort on very long action name
+ The action name is stored in modified form for the debug header and
+ some messages. If it is extremely long, a buffer can be overrun,
+ resulting in misaddressing and potential segfault for rsyslog. This
+ can also happen if the action is NOT named, but a custom path to
+ the output module is given and that path is very long. This triggers
+ the same issue because by default the module load path is included
+ in the action name.
+ This patch corrects the problem and truncates overly long names
+ when being used for name generation.
+ The problem was detected during testbench work. We did never receive
+ a bug report from practice.
+- 2019-10-10: testbench: add test for mmpstrucdata with RFC5424 escape sequences
+----------------------------------------------------------------------------------------
+Scheduled Release 8.1910.0 (aka 2019.10) 2019-10-01
+- 2019-10-01: core bugfix: incorrect error message on duplicate module load
+ A Null-pointer was passed to printf instead of the module name.
+ On some platforms this may lead to a segfault. On most platforms
+ printf check's for NULL pointers and uses the string "(null)"
+ instead. In any case, the module name is missing from the error message.
+- 2019-10-01: imczmq nitfix: potential NULL ptr in printf on out-of-memory condition
+ very unlikely to happen but if it does without any real issue on most platforms.
+- 2019-10-01: work around some compiler warning messages induced by pthreads API
+- 2019-10-01: core ratelimiting: more verbose message when rate-limiting happens
+ When messages are rate-limited, the error message now also contains the
+ rate limiter setting. This enables the user to more quickly understand what
+ the problem is (especially if default values apply).
+ Thanks to Jiri Vymazal for the patch.
+- 2019-10-01: openssl TLS driver: do not emit unnecessary error message
+ On older openssl versions, an API was missing to set user-defined parameters. If we
+ had such an older version, rsyslog emitted an error message even if the user did
+ not configure such parameters. This has been corrected, so that a message is only
+ emitted if there really is a problem. Based on user feedback the severity has also
+ been downgraded to "warning".
+- 2019-10-01: pmcisconames (contributed module) bugfix: potential misaddressing
+- 2019-09-30: pmaixforwardedfrom (contributed module) bugfix: potential misaddressing
+- 2019-09-30: pmdb2diag (contributed module) bugfix: Out of bounds issue
+ Add a new sanity check after determining the level len.
+ Thanks to Philippe Duveau for the patch.
+ see also: https://nvd.nist.gov/vuln/detail/CVE-2019-17040
+- 2019-09-02: ability to set stricter TLS operation modes
+ - checking of extendedKeyUsage certificate field
+ - stricter checking of certificate name/addresses
+ Thanks to Jiri Vymazal for the patch.
+- 2019-08-21: testbench: add basic test for immark
+- 2019-08-20: core: do not unnecessarily set hostname on each HUP
+- 2019-08-20: build system: support cross-platform build for mysql/mariadb
+ rsyslog fails to cross build from source, because it uses mysql_config
+ and mysql_config is unfixably broken for cross compilation. It would be
+ better to use pkg-config. The attached patch makes rsyslog try
+ pkg-config first and fall back to mysql_config.
+ Thanks to Helmut Grohne for providing a base patch.
+- 2019-08-20: core/tcpsrv: potential race on startup/shutdown
+ if the tcpsrv component is started and quickly terminated, it may hang
+ for a short period of time. Also a very small amount of memory is leaked
+ immediately before shutdown. While this leak is irrelevant in practice
+ (the OS clean up the process anyways), it leads to CI failures. The hang,
+ however, can lead to longer than expected shutdown times for rsyslog.
+ The problem can be experienced via imtcp, imgssapi and imdiag (users
+ of affected core component).
+----------------------------------------------------------------------------------------
+Scheduled Release 8.1908.0 (aka 2019.08) 2019-08-20
+- 2019-08-19: testbench: add test for $allowedSender functionality
+- 2019-08-19: testbench: harden some tests against very slow CI machines
+- 2019-08-16: testbench: make most tests use a port file and assign listen port 0
+ This makes the test much more robust against heavily loaded test systems.
+- 2019-08-16: core/action: guard action.externalstate.file content against whitespace
+ remove trailing whitespace before checking the status string. This is
+ most important as a line usually ends with \n, which is considered
+ trailing whitespace. Accepting this increases usability.
+- 2019-08-16: imtcp bugfix: multiple listenerPortFile parameter did not work
+ ... because they were treated as module-global. If we had multiple imtcp
+ listeners with multiple port files, only the last filename was always used.
+ closes https://github.com/rsyslog/rsyslog/issues/3817
+- 2019-08-16: testbench: improve testbench plumbing for gzip and fail cases
+ We have added new capabilities to the testbench plumbing to automatically
+ deal with gzip-compressed files. This also permits to use the wait_seq_check
+ function to work for gzip tests as well. The known-timing-sensitive
+ gzipwr_large test now makes use of the new capabilities. This enables us
+ to more reliably detect when we can savely shutdown the tested instance.
+ This commit also adds an ability to "abort" the full testbench run on
+ first test failure. This is especially useful during CI.
+- 2019-08-13: testbench: add test for imuxsock legacy format
+ This was never tested. Ensures we don't accidentally break existing
+ configurations.
+- 2019-08-13: omelasticsearch bugfix: segfault on unknown retryRuleset
+ omelasticsearch does some "interesting tricks" for an output module.
+ This causes a segfault if the retryRuleset is now known.
+ The action module interface currently expects that all config errors
+ be detected during instance creation. Instead omelasticsearch defers
+ the retry ruleset check to a later state. The reason is that it wants
+ to support the use the same rulesetname it is defined in - and this
+ is not yet available at action parsing.
+ We fix this by ensuring that any deleted instance is properly unlinked
+ from the instance list. One may argue the module interface should get
+ upgrade for such cases, but this is a longer-term approach.
+ closes https://github.com/rsyslog/rsyslog/pull/3796
+- 2019-08-12: imptcp bugfix: port="0" parameter did not work as expected
+ when multiple interfaces and/or protocols could be bound, each of
+ them used a different listener ports were assigned. While this is
+ basically correct, it makes things unusable, especially as
+ listenPortFileName will only contain the port number used for
+ the latest listener.
+ This patch now follows the model of nsd_ptcp.c to assign only
+ the first port randomly and then use that port consistently.
+- 2019-08-10: omelasticsearch bugfix: potential resource leak with "rebindinterval"
+ If the "rebindInterval" parameter was used connections could be linked. This
+ was especially the case with small intervals (such as "2"). This is fixed by
+ forcing libcurl to close the connection on rebind.
+ Thanks to Noriko Hosoi for providing the patch.
+- 2019-08-10: imjournal bugfix: state file close with fsync() was incorrect
+ This lead to fsync() now always applied where expected.
+ Thanks to Jiri Vymazal for the patch.
+- 2019-08-10: testbench: add addtl test for multithreading and HUP
+- 2019-08-10: imptcp bugfix: received bytes counter improperly maintained
+ imptcp counts the number of bytes received. However, receives
+ happen on different worker thread. The access to the counter
+ was not synchronized, which can cause loss of updates. Also,
+ thread debuggers validly flag this as an error, which creates
+ problems under CI.
+ This commit fixes the situation via atomic operations and
+ falls back to mutex calls if they are not available.
+ Detected by LLVM thread sanitizer.
+ closes https://github.com/rsyslog/rsyslog/issues/3798
+- 2019-08-07: testbench: add basic tests for omusrmsg
+- 2019-08-05: omhttp bugfix: enable checkpath configuration parameter
+ omhttp, 'checkpath' option, was not configurable in the past.
+ - add 'checkpath' to the cnfparamdescr table.
+ - fix issue with checkpath passing extra garbage characters in string.
+ - add 'checkpath' into unit test - omhttp-retry.sh
+ Thanks to Nelson Yen for the fix.
+- 2019-08-05: testbench bugfix: some tests were executed when req module was missing
+ In actual case if --enable-impstats was not given some other tests failed.
+- 2019-08-03: iminternal bugfix: race on termination
+ This could in theory lead to loss of shutdown messages, but was mostly a
+ cosmetic issues. We primarily fixed it to get TSAN-clean so that we can
+ utilize LLVM TSAN in CI.
+- 2019-08-02: testbench: new test for omfile outchannel functionality
+- 2019-08-02: core/janitor bugfix: properly maintain dynafile cache
+ When the janitor cleans out timed-out files, it does not
+ properly indicate the entry is gone. Especially when running
+ in async mode this can lead to use-after-free and thus
+ memory corruption or segfault.
+ see also https://github.com/rsyslog/rsyslog/issues/3756
+- 2019-08-01: omfile bugfix: race file when async writing is enabled
+ This seems to be a long-standing bug, introduced around 7 years ago.
+ It became more visible by properly closing files during HUP, which
+ was done in 8.1905.0 (and was another bugfix). Note that due to this
+ race a memory corruption can occur under bad circumstances. As such,
+ this may have also caused segfaults or system hangs (mutexes could
+ have been affected).
+ closes https://github.com/rsyslog/rsyslog/issues/3772
+- 2019-08-01: testbench: additional tests for HUP
+- 2019-07-31: imrelp bugfix: hang after HUP
+ termination condition was not properly checked; this lead to
+ premature termination after patch 1c8712415b9 was applied.
+ It is open to debate if patch 1c8712415b9 changed the module
+ interface. Actually it looks like this was previously not
+ well thought out.
+ closes https://github.com/rsyslog/rsyslog/issues/3760
+- 2019-07-24: mmdarwin: add new module
+ This is a contributed module. For details see doc.
+ Thanks to the Advens team for contributing it.
+- 2019-07-23 iminternal bugfix: suppress mutex double-unlock
+ If there is a burst of log messages during a time when rsyslog is unable
+ to output (either during log rotation, an out-of-space condition, or
+ some other similar condition), rsyslog can SEGFAULT due to a mutex
+ double-unlock.
+- 2019-07-23 imtcp: enable listenPortFileName parameter
+ this parameter was added, but it had no effect as it was not
+ passed down to the driver layer. This has been fixed. That also
+ now enables us to use dynamically-assigned port, which are
+ very useful for further testbench stabilization. Quite some
+ false positives occurred because the pre-selected port was
+ already in use again when rsyslog started.
+- 2019-07-19 imtcp: enable listenPortFileName parameter
+ this parameter was added, but it had no effect as it was not
+ passed down to the driver layer. This has been fixed. That also
+ now enables us to use dynamically-assigned port, which are
+ very useful for further testbench stabilization. Quite some
+ false positives occurred because the pre-selected port was
+ already in use again when rsyslog started.
+- 2019-07-18 core/action: no error file written if act suspended on TX commit
+ when an action was already disabled while the action was tried to be
+ committed, no error file was written. Note that this state is highly
+ unlikely to happen. Most probably, it can only happen if parameter
+ action.externalstate.file is used.
+----------------------------------------------------------------------------------------
+Version 8.1907.0 (aka 2019.07) 2019-07-09
+NOTE TO MAINTAINERS: libee is not used by rsyslog for quite some while.
+However, we never included this info into the changelog. So if you still
+make rsyslog depend on libee (some do this), you should stop doing so now.
+Libee is dead and no longer been maintained nor hosted by us. Old versions
+can still be found at github for those in need.
+
+GENERAL NOTE: during 8.1907 scheduled release timeframe we changed the ChangeLog
+format to include the date a change went into master branch. This is to provide
+an easy way to identify which changes went into the respective daily stable.
+
+- 2019-07-05 imuxsock: support FreeBSD 12 out of the box
+ FreeBSD 12 uses RFC5424 on the system log socket by default. This
+ format is not supported by the special parser used in imuxsock.
+ Thus for FreeBSD the default needs to be changed to use the
+ regular parser chain by default. That is all this commit does.
+ closes https://github.com/rsyslog/rsyslog/issues/3694
+- 2019-07-05 function bugfix: "ipv42num" misspelled as "ip42mum" (without "v")
+ To fix the issue but keep compatible with existing deployments
+ both function names are now supported.
+ closes https://github.com/rsyslog/rsyslog/issues/3676
+- 2019-07-04 fix leading double space in rsyslog startup messages
+ see also https://github.com/rsyslog/rsyslog/issues/2979
+- omamqp1: port to latest api, add tests
+ This brings omamqp1 up-to-date with the latest qpid-proton-c
+ api version. This also adds a test for the plugin, to test
+ the basic functionality. The test requires the user to
+ install qdrouterd and the python qpid-proton library in order
+ to use the simple_recv.py test program.
+ Thanks to Richard Megginson for the patch.
+- omclickhouse bugfix: potential segfault on omclickhouse batchmode
+ segfault happened when the template did not contain the string
+ "VALUES".
+ Thanks to github user wdjwxh for the fix.
+- core bugfix: message duplication copied incorrect timestamp
+ MsgDup() placed timereported into timegenerated property, resulting
+ in invalid property values. Original timegenerated was lost. This
+ occurred always when a message needed to be duplicated. Most
+ importantly this is the case when queues are used.
+ closes https://github.com/rsyslog/rsyslog/issues/3716
+- core bugfix: segfault on startup depending on queue file names
+ rsyslog will segfault on startup when a main queue file name has
+ been set and at least on other queue contains a file name. This
+ was cased by too-early freeing config error-detection data
+ structures. It is a regression caused by commit e22fb205a3.
+ Thanks to Wade Simmons for reporting this issue and providing
+ detailed analysis. That greatly helps fixing it quickly.
+ closes https://github.com/rsyslog/rsyslog/issues/3681
+- core "bugfix": alignment issue
+ This was not a hard error on current platforms, but a
+ to-be-considered compiler warning regarding invalid alignment.
+ While it works well on current platforms, alignment issues may
+ turn into real issues in future platforms. So we try to fix them
+ if possible. As not only a side-effect this resolves compiler
+ warnings even on current platforms.
+ This fix has some regression potential. If so, the problems
+ may occur during IP address resolution.
+ see also https://github.com/rsyslog/rsyslog/issues/2608
+- omfile bugfix: potential hang/segfault on HUP of dynafile action
+ when omfile was HUPed it did not sufficiently clear all dynafile
+ cache maintenance data structures. This usually lead to misaddressing
+ and could result in various issues, including a hang of rsyslog
+ processing or segfaults. It could also have "no effect" by pure
+ luck of not hitting anything important. This actually seems to
+ have been the most frequent case.
+ This seems to be a long-standing bug, but the likelihood of its
+ appearance seems to have been increased by commit 62fbef7
+ introduced in 8.1905. Note: the commit itself has no regression,
+ just increases the likelihood to trigger the pre-existing bug.
+ special thanks to Alexandre Guédon for his help in analyzing
+ the issue - without him, we would probably still not know
+ what actually went wrong.
+ closes https://github.com/rsyslog/rsyslog/issues/3686
+- imjournal bugfix: potential message duplication
+ When journal was preloaded from previously saved cursor it was not advanced
+ to next entry so reading begun from last message which was therefore
+ duplicated.
+ Thanks to Jiri Vymazal for the patch.
+- rfc5424 parser bugfix: leading space sometimes lost
+ if structured data is present a leading space in MSG field is lost
+- queue subsystem bugfix: oversize queue warning message shown as error
+ The warning message was emitted as an error message, which is misleading
+ and may also break some automated procedures.
+- core bugfix: HUP did not work reliable on all platforms
+ most notably not on FreeBSD, maybe others. The reason was obviously
+ different handling of signals in respect to multiple threads.
+- build system bugfix: missing files in distribution tarball
+- testbench
+ * fixed "make distcheck" settings which were missing some modules
+ This lead to incomplete "make distcheck" run; some errors were not
+ detected due to that.
+ * testbench framework: use ip tool instead of outdated ifconfig
+ The framework now first checks if "ip" is available and falls back
+ to "ifconfig" only if this is not the case.
+ Thanks to Michael Biebl for the suggestion.
+ closes https://github.com/rsyslog/rsyslog/issues/3682
+------------------------------------------------------------------------------
+Version 8.1905.0 (aka 2019.05) 2019-05-28
+- templates: add datatype template option for JSON generation
+ The new "datatype" and "onEmpty" template options permits to
+ generate non-string data rather easily. It works together with
+ jsonf formatting, which is what people should use nowadays.
+ closes https://github.com/rsyslog/rsyslog/issues/2827
+- config processing: check disk queue file is unique
+ If the same name is specified for multiple queues, the queue files
+ will become corrupted. This commit adds a check during config parsing.
+ If duplicate names are detected the config parser errors out and the
+ related object is not created.
+ Note: this may look to a change-of-behavior to some users. However,
+ this never worked and it was pure luck that these users did not run
+ into big problems (e.g. DA queues were never going to disk at the
+ same time). So it is acceptable to error out in this hard error case.
+ closes https://github.com/rsyslog/rsyslog/issues/1385
+- global config: new parameters for ruleset queue defaults
+ specifically:
+ * default.ruleset.queue.timeoutshutdown
+ * default.ruleset.queue.timeoutactioncompletion
+ * default.ruleset.queue.timeoutenqueue
+ * default.ruleset.queue.timeoutworkerthreadshutdown
+ closes https://github.com/rsyslog/rsyslog/issues/3656
+- add capability to write full config file (-o cmdline option)
+ Introduces the capability to create an output config file that explodes
+ all "includes" into a single file. This provides a much better overview
+ of how exactly the configuration is crafted. That could often be a great
+ troubleshooting aid.
+ This commit also contains some slight not-really-related cleanup.
+ closes https://github.com/rsyslog/rsyslog/issues/3634
+- queue subsystem: permit to disable "light delay mark"
+ New semantic: if lightDelayMark is 0, it is set to the max queue
+ size, effectively disabling the "light delay" functionality.
+ Thanks to Yury Bushmelev to mentioning issues related to light
+ delay mark and proposing the solution (which actually is what
+ this commit does).
+ closes https://github.com/rsyslog/rsyslog/issues/1778
+- queue subsystem: provide better user status messages
+ The queue subsystem now provides additional information messages which
+ may help a regular user to maintain system health. Most importantly,
+ DA queues now output when they persist queue data at end of run and
+ when they restart the queue based on persisted data.
+- core: emit a warning message for ultra-large queue size definitions
+ We see error reports from users who have configured excessively large queues
+ and receive an OOM condition or other problems.
+ With that patch we generate a warning message if a queue is configured very
+ large. "Very large" is defined to be in excess of 500000 messages.
+ see also https://github.com/rsyslog/rsyslog/issues/3314
+ closes https://github.com/rsyslog/rsyslog/issues/3334
+- new global config parameter "internalmsg.severity"
+ permits to specify a severity filter for internal message. Only
+ messages with this severity level or more severe are logged.
+ Originally this was done in rsyslog.conf as usual: you can filter
+ rsyslog messages on severity, just like any other. But with systemd,
+ we now emit primarily to the journal, and this is outside of rsyslog's
+ rule engine and so regular filters do not apply (at least in regard
+ to the journal). Logging to journal is good, because finally
+ folks begin to see the messages (traditional distro configs discard
+ them, for whatever is the reason).
+ This commit implements a global setting for a severity-based filter
+ for internal messages, before submitted to journal. So it's not 100%
+ of what rsyslog can do, but at least some way to customize.
+ see also https://github.com/rsyslog/rsyslog/issues/3639
+- config processing bugfix: error messages if config.enabled="off" is used
+ Using config.enabled="off" could lead to error messages on
+ "parameter xxx not known", which were invalid. They occurred
+ because the config handler expected them to be used, which
+ was not the case due to being disabled.
+ This commit fixes that issue.
+ closes https://github.com/rsyslog/rsyslog/issues/2520
+- core portability bugfix: harden shutdown processing on FreeBSD
+ On FreeBSD, rsyslog does not always terminate immediately on SIGTERM.
+ Root cause seems to be that SIGTERM is delivered differently under
+ FreeBSD. This causes the main thread to not be awaken, and so it
+ takes until the next janitor interval to come back to life - which
+ can be far too long. Fixed this bug explicitly awaking the main
+ thread.
+- imtcp bugfix: oversize message truncation causes log to be garbled
+ The actual problem is in the tcpserver component. However, the prime user
+ is imtcp and so users will likely experience this as imtcp problem.
+ When a too-long message is truncated, the byte after the truncation
+ position becomes the first byte of the next message. This will garble
+ the next messages and in almost all cases render it is syslog-noncompliant.
+ The same problem does NOT occur when the message is split.
+ This commit fixes the issue. It also includes a testbench fix.
+ Unfortunately the test for exactly this feature was not properly
+ crafted and so could not detect the problem.
+ closes https://github.com/rsyslog/rsyslog/issues/3580
+- omfile bugfix: FlushOnTXEnd does not work reliably with dynafiles
+ The flush was only done to the last dynafile in use at end of
+ transactions. Dynafiles that were also modified during the
+ transaction were not flushed.
+ Special thanks to Duy Nguyen for pointing us to the bug and
+ suggesting a solution.
+ This commit also contains a bit of cosmetic cleanup inside
+ the file stream class.
+ closes https://github.com/rsyslog/rsyslog/issues/2502
+- lmcry_gcry build bugfix: was not always properly build
+ Due to an invalid definition in build system this seems to have not
+ been correctly build on at least some platforms (but it worked on
+ others as it passed CI testing). This has now been corrected.
+ Thanks to Remi Locherer for the patch.
+- dnscache bugfix: very unlikely memory leak
+ This fixes a memory leak that can only occur under OOM conditions.
+ Detected by Coverity Scan, CID 203717
+- testbench bugfix: wrong parameter check in diag.sh (tcpflood())
+ When first parameter is check_only, the tcpflood funtion shall not
+ abort the test itself (The fail is intended if this option is set).
+ closes issue #3625
+- testbench bugfix: imfile-symlink test failed w/ parallel test run
+ The test sometimes failed. It used a symlink to a hardcoded name
+ rsyslog-link.*.log. This symlink was created but then disappears.
+ The reason is that upon (every!) test exit, rsyslog-link.*.log is
+ deleted. So a parallel test running the exit procedure just at the
+ "right" time can removed that file.
+ The bug is that the file name should be created using the tests's
+ dynamic name. This is done now.
+ closes https://github.com/rsyslog/rsyslog/issues/3550
+------------------------------------------------------------------------------
+Version 8.1904.0 (aka 2019.04) 2019-04-16
+- omfile: provide more helpful error message on file write errors
+ now contains actual file name plus a link to probable causes for this type
+ of problem
+- imfile: emit error on startup if no working directory is set
+ When the work directory has not been set or is invalid, state files
+ are created in the root of the file system. This is neither expected
+ nor desirable. We now complain loudly about this fact. For backwards
+ compatibility reasons, we still need to support running imfile in
+ this case.
+ closes https://github.com/rsyslog/rsyslog/issues/1296
+- dnscache: add global parameter dnscache.default.ttl
+ This permits to control default TTL for cache entries. If set
+ to 0, the DNS cache is effectively disabled.
+ closes https://github.com/rsyslog/rsyslog/issues/49
+ closes https://github.com/rsyslog/rsyslog/issues/1487
+- omelasticsearch: new parameter rebindinterval
+ Thanks to Richard Megginson for the patch.
+- omelasticsearch: new parameter skipverifyhost
+ Add ability to specify the libcurl CURLOPT_SSL_VERIFYHOST
+ option to skip verification of the hostname in the peer cert.
+ WARNING: This option is insecure, and should only be used
+ for testing. The default value is off, meaning, the hostname
+ will be verified by default.
+ Thanks to Richard Megginson for the patch.
+- omelasticsearch: set rawmsg to data from original request
+ Previously, when constructing the message to submit for a retry
+ for an original request, if the original request did not contain
+ the field `message`, the system property `rawmsg` was set to
+ the entire metadata + data from the original request. This was
+ causing problems with Elasticsearch. This patch changes
+ the code so that the `rawmsg` will be set to only the data part
+ of the original request if there is no `message` field.
+ closes https://github.com/rsyslog/rsyslog/issues/3573
+ Thanks to Richard Megginson for the patch.
+- mmkubernetes - support for metadata cache expiration
+ New parameters for mmkubernetes (module and action):
+ * `cacheexpireinterval`
+ If `cacheexpireinterval` is -1, then do not check for cache expiration.
+ If `cacheexpireinterval` is 0, then check for cache expiration.
+ If `cacheexpireinterval` is greater than 0, check for cache expiration
+ if the last time we checked was more than this many seconds ago.
+ * `cacheentryttl` - maximum age in seconds for cache entries
+ New statistics counters:
+ * `podcachenumentries` - the number of entries in the pod metadata cache.
+ * `namespacecachenumentries` - the number of entries in the namespace
+ metadata cache.
+ * `podcachehits` - the number of times a requested entry was found in the
+ pod metadata cache.
+ * `namespacecachehits` - the number of times a requested entry was found
+ in the namespace metadata cache.
+ * `podcachemisses` - the number of times a requested entry was not found
+ in the pod metadata cache, and had to be requested from Kubernetes.
+ * `namespacecachemisses` - the number of times a requested entry was not
+ found in the namespace metadata cache, and had to be requested from
+ Kubernetes.
+- imdocker: new contributed module
+ imdocker will get (docker) container logs from a host as well as filling
+ out some basic container metadata as id, name, image, labels.
+ Thanks to Nelson Yen for the contribution.
+- mmtaghostname: new contributed module
+ This module allows one to force hostname after parsing to the localhostname of
+ rsyslog and/or add a tag to messages received from input modules without
+ tag parameter.
+ Thanks to Philippe Duveau for the contribution.
+- imbatchreport: new contributed input module
+ This input module manage batches' reports : complete file as a single log.
+ Thanks to Philippe Duveau for the contribution.
+- imtuxedolog: new contributed input module for Tuxedo ULOG
+ Thanks to Philippe Duveau for the contribution.
+- openssl network driver: Added support setting openssl configcommands
+ We are using the gnutlsPriorityString setting variable, to pass
+ configuration commands to openssl.
+ closes: https://github.com/rsyslog/rsyslog/issues/3605
+- omkafka: drop messages rejected due to being too large
+ Drop messages that were rejected due to
+ 'RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE' error
+ Thanks to Nelson Yen for the patch
+- core/action: implement capability to resume/suspend via external file
+ It has been reported that some TCP receivers exists that accept syslog tcp
+ messages at any rate, even if they do not manage to actually process them.
+ Instead, they silently drop the message. This behavior is not configurable.
+ All in all, it can lead to considerate message loss.
+ To support such use cases, we need to provide an ability to externally
+ trigger actions suspension and resumption.
+ We do this via a configured file which contains the status of the action.
+ Rsyslog periodically reads the file and if it contains "SUSPEND", it
+ suspend the action (and likewise for resume).
+ closes https://github.com/rsyslog/rsyslog/issues/2924
+- improg bugfix: some memory leaks
+ Thanks to Philippe Duveau for the contribution.
+- msg object bugfix: regression from 1255a67
+ closes https://github.com/rsyslog/rsyslog/issues/3570
+- pmnormalize: fix memory leaks, improve tests
+ This patch fixes a set of problems plus provides more and enhanced
+ tests for the module.
+ Most important problem was a memory leak that occurred when a message
+ could not be passed at all. For each message that could not be parsed
+ memory of at least the size the message is leaked. Depending on
+ traffic pattern this can quickly lead to OOM. Note, however, that
+ this leak was never reported - it was discovered as part of code
+ review.
+ closes https://github.com/rsyslog/rsyslog/issues/2007
+- omkafka bugfix: build failure due to inconsistent type
+ fails depending on platform and settings; was somehow undetected by CI
+- imjournal bugfix: potential segfault on some API failure returns
+ In one case there was possibility of free()'d value of journal
+ cursor not being reset, causing double-free and crash later on.
+ closes https://github.com/rsyslog/rsyslog/issues/3537
+- openssl subsystem bugfix: better error handling
+ Handling of SSL_ERROR_SYSCALL has been hardened.
+ Handling for SSL_Shutdown errors has been corrected.
+ Also fixed SSL Shutdown handling in tcpflood (openssl code).
+ If SSL_Shutdown returns error, we call SSL_read as described in
+ the documentation to do a bidirectional shutdown.
+ Closes https://github.com/rsyslog/rsyslog/issues/3561
+- imjournal bugfix: Fetching journal cursor only for valid journal
+ The sd_journal_get_cursor() got called regardless of previous
+ retcodes from other journal calls which flooded logs with journald
+ errors. Now skipping the call in case of previous journal call
+ non-zero result. Fixed success checking of get_cursor() call
+ to eliminate double-free possibility.
+ Also, making WorkAroundJournalBug true by default, as there were no
+ confirmed performance regressions for a quite long time.
+ Thanks to Jiri Vymazal for the patch.
+- omamqp: fix build errors
+ They occur on some, newer, platforms. We do not really fix them, but rather
+ make the compiler ignore them. This is not really good, but the module is
+ contributed and so that's for now the best thing we can do.
+- testbench: change manytcp.sh to use a larger connection count again
+ not sure why it was reduced, maybe related to
+ https://github.com/rsyslog/rsyslog/issues/1108
+ also, modernize this and another test
+- tcpflood bugfix: make soft connection limit work again
+ It looks like the soft limit became defunct when tcpflood was enhanced to
+ request more open file handles from OS.
+ closes https://github.com/rsyslog/rsyslog/issues/1108
+- testbench bugfix: omhttp tests were not run during "make distcheck"
+- build system bugfix: omhttp test files were not included in dist tarball
+ Thanks to Thomas D. (whissi) for the patch.
+------------------------------------------------------------------------------
+Version 8.1903.0 (aka 2019.03) 2019-03-05
+- omrabbitmq: add features (RabbitMQ HA management, templatize routing_key,
+ populate amqp message headers, delivery_mode and expiration parameters)
+- improg: create input module to use external program as input datas
+- imtuxedoulog: create input module to consume Tuxedo ULOG files
+- omhttp: rewritten with large feature enhancements
+ Many thanks to Gabriel Intrator for this work. Gabriel also has adopted the
+ module and plans to support it in the future.
+- pmdb2diag: create parser module for DB2 diag logs
+- TLS subsystem: add support for certless communication
+ both openssl and GnuTLS drivers have been updated to support certless
+ communications. In this case e.g. Diffie-Helman is used.
+ NOTE: this is an insecure mode, as it does NOT guard against
+ man-in-the-middle attacks. We implemented it because of the large demand,
+ not because we think it makes sense to use this mode. We strongly recommend
+ against it.
+ closes https://github.com/rsyslog/rsyslog/issues/1068
+- imrelp/omrelp: add capability to specify tlslib for librelp
+ closes https://github.com/rsyslog/rsyslog/issues/3451
+- build system: introduce a better way to handle compiler pragmas
+ we now use macros and _Pragma(). This requires less code lines and is more
+ portable.
+- omkafka: add support for dynamic keys
+ A new configuration property "dynaKey" is added that, when "on", changes the
+ value of property "key" to a template names instead of a constant value.
+ This is similar in approach to the DynaTopic implementation.
+ Thanks to Ludo Brands for the patch.
+- AIX port: add AIX linking extensions on many plugins and contributions to
+ allow building them on this os.
+- template: add Time-Related System Property $wday which is the day of week
+ This allows one to get a week based rotation of log as AIX does.
+- ksi subsystem: add high availability mode
+ Note: ksi subsystem now REQUIRES libksi 3.19.0 or above
+ Thanks to Allan Park for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/3338
+- imfile bugfix: file reader could get stuck
+ State file handling was invalid. When a file was moved and re-created
+ rsyslog could use the file_id if the new file to write the old files'
+ state file. This could make the file reader stuck until it reached the
+ previous offset. Depending on file sizes this could never happen AND
+ would cause large message loss. This situation was timing dependent
+ (a race) and most frequently occurred under log rotation. In polling
+ mode the bug was less likely, but could also occur.
+ closes: https://github.com/rsyslog/rsyslog/issues/3465
+ closes: https://github.com/rsyslog/rsyslog/issues/3468
+- imfile bugfix: potential segfault when working with directories or symlinks
+ see also https://github.com/rsyslog/rsyslog/pull/3496
+ Thanks to Nelson Yen for the patch
+- omhttp bugfix: header items could not have spaces in them
+ Thanks to Nathan Brown for the patch.
+- core bugfix: enlarged msg offset types for bigger structured messages
+ using a large enough (dozens of kBs) structured message
+ it is possible to overflow the signed short type which leads
+ to rsyslog crash. (applies to msg.c, the message object)
+ Thanks to Jiri Vymazal for the patch.
+- core bugfix for AIX: timeval2syslogTime now handle the bias according to
+ local time zone as documented by IBM.
+- imfile feature: add configuration parameter to force parsing of read logs
+- imczmq bugfix:
+ Release zframe following read from socket
+ Make the 0MQ frame pointer local to the receive loop and destroy the
+ frame as soon as the contents have been copied. This avoids:
+ * a memory leak should the receive loop execute more than once
+ * referencing an un-initialized value during cleanup (finalize_it)
+ Thanks to Mark Gillott for the patch.
+- omclickhouse bugfix: default template unusable
+ STDSQL option added to the default template used in output module of clickhouse
+ Thanks to gagandeep trivedi for the patch.
+- omclickhouse "bugfix": work-around failed error detection
+ omclickhouse uses a questionable method to check if a request generated
+ an error. We have seen the method to fail when we slightly upgraded clickhouse
+ server in CI testing.
+ This commit makes the method a bit more reliable without really fixing it.
+ But it's at least a short-term solution.
+ This should be changed to a proper status check. I assume such is possible.
+ see also https://github.com/rsyslog/rsyslog/issues/3485
+- imptcp bugfix: overly long socket bind path can lead to segfault
+ if the `path` input parameter is overly long (e.g. more than 108
+ characters on some platforms) a non-terminated string is generated
+ and then passed to OS API. This can lead to all sorts of problems
+ including segfault.
+ We detected that based on gcc-8 warnings during code inspection.
+ No real-world problem case is known.
+- ommongodb bugfix: improper stpncpy() calls
+- testbench tcpflood: add new transport option relp-tls
+ Tcpflood can now send messages via relp with tls support.
+ closes https://github.com/rsyslog/rsyslog/issues/3448
+- testbench: mmdb valgrind tests failed is srcdir env was not set
+- testbench: add omclickhouse tests
+- testbench bugfix: some long-running tests had too low runtime allowance
+ closes https://github.com/rsyslog/rsyslog/issues/3493
+- testbench bugfix: daqueue-dirty-shutdown test
+ This test occasionally failed with left-over spool files. As far as we
+ have analyzed, this is due to the use of an invalid shutdown timeout
+ (very short) in the second phase of the test. It looks like this is
+ actually a copy&paste error from phase one. Behavior of rsyslog was
+ correct, but the test itself created a false positive.
+ We have corrected the timeout now and also modernized the test
+ a bit.
+ closes https://github.com/rsyslog/rsyslog/issues/2122
+- testbench bugfix: some omhttp tests had compatibility issues with Python 3
+ Thanks to Thomas D. (whissi) for the patch.
+------------------------------------------------------------------------------
+Version 8.1901.0 (aka 2019.01) 2019-01-22
+- new version scheme: 8.yymm.0 - version now depends on release date
+ see also https://rainer.gerhards.net/2018/12/rsyslog-version-numbering-change.html
+- queue: add support for minimum batch sizes
+ closes https://github.com/rsyslog/rsyslog/issues/495
+- change queue.timeoutshutdown default to 10 for action queues
+ The previous default of 0 gave action queues no real chance to
+ shutdown - at the time they were applied, they were usually already
+ expired (computing the absolute timeout took a small amount of time).
+ So we change this now to 10ms, which still is very quick but gives
+ the queue at least a chance to shutdown itself. That in turn
+ smoothes the whole shutdown process.
+ If a very large number of action queues is used this may lead
+ to a very slightly longer shutdown time, albeit this is very
+ improbable.
+- omclickhouse: new output module for clickhouse
+ This output module adds the possibility to send
+ INSERT querys to a Clickhouse database. See doc for details.
+ The messages are sent via a REST interface.
+ This commit also adds support of the testbench
+ for clickhouse tests, as well as various tests.
+ Closes https://github.com/rsyslog/rsyslog/issues/2272
+- omkafka: Add ability to dump librdkafka statistics to a file
+ Use statsFile to specify statistics output file; also requires
+ setting statistics.interval.ms confparam to a non-zero value.
+ Thanks to github user pcullen65 for the contribution.
+- tls(ossl/gtls): add new Option "StreamDriver.PermitExpiredCerts"
+ The new Option can have one of the following values:
+ on = Expired certificates are allowed
+ off = Expired certificates are not allowed
+ warn = Expired certificates are allowed but warning will be logged (Default)
+ Includes necessary tests to validate new code.
+ closes https://github.com/rsyslog/rsyslog/issues/3364
+- action: add "action.resumeIntervalMax" parameter
+ This parameter permits to set an upper limit on the growth of the
+ retry interval. This is most useful when a target has extended
+ outage, in which case retries can happen very infrequently.
+ closes https://github.com/rsyslog/rsyslog/issues/3401
+- report child process exit status according to config parameter
+ Add new global setting 'reportChildProcessExits' with possible values
+ 'none|errors|all' (default 'errors'), and new global function
+ 'glblReportChildProcessExit' to report the exit status of a child
+ process according to the setting.
+ Invoke the report function whenever rsyslog reaps a child, namely in:
+ - rsyslogd.c (SIGCHLD signal handler)
+ - omprog
+ - mmexternal
+ - srutils.c (execProg function, invoked from stream.c and omshell)
+ Remove redundant "reaped by main loop" info log in omprog.
+ Promote debug message in mmexternal indicating that the child has
+ terminated prematurely to a warning log, like in omprog.
+ closes https://github.com/rsyslog/rsyslog/issues/3281
+ Thanks to Joan Sala for contributing this.
+- build system: add capability to turn off helgrind tests
+ we add configure switch --enable-helgrind. We need to turn helgrind off
+ when we use clang coverage instrumentation. The instrumentation injects
+ mt-unsafe counter updates which we seem to be unable to suppress.
+ Note: for gcc this was possible, because they all occurred in a utility
+ function. For clang, they are inlined so we get many -and changing- violations.
+ see also https://github.com/rsyslog/rsyslog/issues/3361#issuecomment-450502569
+- imzmq3/omzmq3: remove modules
+ according to @brianknox (their author) these modules are outdated:
+ https://twitter.com/taotetek/status/931860786959540224
+ They are replaced by imczmq/omczmq and are no longer maintained. We put a
+ depreciation notice into the modules a year ago, and now it finally is time
+ to remove them. They do NOT build in any case, except if very old versions
+ of the 0mq ecosystem are used.
+ see also https://github.com/rsyslog/rsyslog/issues/2100
+ closes https://github.com/rsyslog/rsyslog/issues/2103
+- bugfix omusrmsg: don't overwrite previous set _PATH_DEV value
+ Since commit 56ace5e418d149af27586c7c1264fccfbc6badf1, omusrmsg was broken
+ because "memcpy()" is not a suitable substitute for "strncat()" in this
+ context, it is actually replacing the previous added content.
+ Bug: https://bugs.gentoo.org/673004
+ Closes: https://github.com/rsyslog/rsyslog/issues/3346
+ Thanks to Thomas D. (whissi) for the patch.
+- bugfix ossl TLS driver: fixed authentication mode anon
+ authentication mode "anon" was not properly supported in ossl TLS
+ driver; if selected, did still require a full certificate.
+ closes: https://github.com/rsyslog/rsyslog/issues/3037
+- bugfix tls subsystem: Receiver hang due to insufficient TLS buffersize.
+ gtls and ossl driver used a default buffersize of 8KiB to store received
+ TLS packets. When tls read returned more than buffersize, the additional
+ buffer was not processed until new data arrived on the socket again.
+ TLS RFCs require up to 16KiB+1 buffer size for a single TLS record.
+ closes https://github.com/rsyslog/rsyslog/issues/3325
+- bugfix pmpanngfw: build issue due to non-matching data types in comparison
+ Thanks to Narasimha Datta for the patch.
+- omfile: work-around for "Bad file descriptor" errors
+ This works-around an issue we can reproduce e.g. via the
+ imtcp-tls-ossl-x509fingerprint.sh test. Here, omfile gets a write
+ error with reason EBADF. So far, I was not able to see an actual
+ coding error. However I traced this down to a multithreaded race
+ on open and close calls. I am very surprised to see this type
+ of issue, as I think the kernel guarantees that it does not happen.
+ Here is what I see in strace -f:
+ openssl accepts a socket:
+ [pid 66386] accept(4, {sa_family=AF_INET, sin_port=htons(59054), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 10
+ then, it works a bit with that socket, detects a failure and shuts it down. Sometimes, at the very same instant omfile on another thread tries to open on output file. Then the following happens:
+ [pid 66386] close(10) = 0
+ [pid 66389] openat(AT_FDCWD, "./rstb_356100_31fa9d20.out.log", O_WRONLY|O_CREAT|O_NOCTTY|O_APPEND|O_CLOEXEC, 0644 <unfinished ...>
+ [pid 66386] close(10 <unfinished ...>
+ [pid 66389] <... openat resumed> ) = 10
+ [pid 66386] <... close resumed> ) = 0
+ [pid 66386] poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN}], 2, -1 <unfinished ...>
+ [pid 66389] write(2, "file './rstb_356100_31fa9d20.out"..., 66file './rstb_356100_31fa9d20.out.log' opened as #10 with mode 420
+ ) = 66
+ [pid 66389] ioctl(10, TCGETS, 0x7f59aeb89540) = -1 EBADF (Bad file descriptor)
+ This is **literally** from the log, without deleting or reordering
+ lines. I read it so that there is a race between `open` and `close`
+ where fd 10 is reused, but seemingly closed - resulting in the `EBADF`
+ While it smells like a kernel issue, it may be a well-hidden program
+ bug - if so, one I currently do not find. HOWEVER, this commit
+ works around the issue by reopening the file when we receive EBADF.
+ That's the best thing to do in that case, especially if it really is
+ a kernel bug. Data loss should not occur, as the previous writes
+ succeeded in that case.
+ The backdraw of this work-around is that it only "fixes" omfile. In
+ theory every part of rsyslog can be affected by this issues (queue
+ files, for example). So this is not to be considered a final solution
+ of the root issues (but a big step forward for known problem cases).
+ see also https://github.com/rsyslog/rsyslog/issues/3404
+- omhttp bugfix: segfault due to NULL pointer access
+ many thanks to Gerardo Puerta for the patch
+- omkafka bugfix: segfault when running in debug mode using dynamic topics
+ This should only affect test environments, as debug mode is not
+ suitable for production (and really does not work when running for
+ extended period of time).
+- testbench bugfix: TLS syslog tests for "anon" mode were broken
+ They did not detect when "anon" mode was not properly supported by the
+ drivers.
+- test tooling bugfix: correct tcpflood error messages
+ it looks like tcpflood's openssl code stems partly back to tcpdump, at
+ least the error messages indicate this. Thankfully tcpdump is BSD licensed,
+ so this should not be a big issue. Nevertheless, the incorrect program name
+ in error messages needs to be corrected, and this is what this commit does.
+- tcpflood bugfix: tool did not terminate on certificate error
+ when tcpflood detected a certificate error, it reported an
+ error message but did not abort. This could make errors undetectable
+ during CI runs.
+ also fix tests which did not properly provide CA cert (which than
+ caused the error).
+- testbench: fix issues with journal testing
+ The configure/Makefile checks were not correct, leading to the
+ build of journal components when not necessary, even if not
+ supported by the platform. Thus lead to invalid build and test
+ failures.
+- testbench: add tests for "certless" tcp/tls
+ This adds a test to ensure that a client without certificate can
+ connect to a server with certificates. So it is not exactly
+ "certless".
+ The prime intent of this test is to match config suggestions given
+ by log hosting companies (like loggly) and so ensure that we do
+ not accidentally break them. This is especially important as the
+ capability for certless clients was not properly documented and
+ also become forgotten by the rsyslog team.
+ see also https://github.com/rsyslog/rsyslog/issues/3413
+- CI
+ - further improve testbench robustness against slow machines
+ - testbench: add tests for parser.EscapeControlCharacterTab global option
+ - testbench: Updated all expired x.509 certs
+ Closes https://github.com/rsyslog/rsyslog/issues/3348
+ - fix a potential race in CI debug mode which can lead to segfault
+ only when instructed to do so, rsyslog may emit a "final worker thread shutdown"
+ messages. This is usually only enabled in CI and/or other testing. If enabled,
+ the code has a race on the pWti object which can lead to segfault or abort.
+ Only system which explicitly enable this CI aid are affected (running in debug
+ mode alone is NOT sufficient).
+ This is a regression from 8.40.0.
+ - testbench: improve robustness against slow CI, gen. improvements
+ * add an overall timeout value for tests - if running longer,
+ testbench framework tries to FAIL and end test. Note that
+ this is not bullet-proof and not intended to be so.
+ * guard against hanging rsyslog instances via a new imdiag
+ feature to abort after n number of seconds; among others,
+ this guards as against timeout-cancel in CI, which is always
+ pretty hard to diagnose - now we see these errors in test-suite.log
+ * fix a bug in tcp zip test, which actually did not use zip mode
+ * experimentally add debug output to better understand
+ shutdown_when_empty operation; goal is to improve understanding
+ and then remove that code again.
+ * improve shutdown predicate for a couple of tests
+ * made travis run make check with two parallel threads, for which
+ we seem ready now. Nevertheless, it's still experimental and we
+ may roll this back if required.
+ * testbench: disable omprog tests that hang under coverage instrumentation
+ When gcc coverage instrumentation is used, these tests hang. They work
+ with clang coverage instrumentation, but for some reason clang does not
+ give us full reports (at least not when used together with CodeCov.io).
+ We have tried to troubleshoot this for hours and hours - now is time to
+ give up until someone comes up with a bright idea. So we make the affected
+ tests skip themselves when they detect gcc with coverage instrumentation.
+ * testbench: add new test for imfile and logrotate in copytruncate mode
+ * testbench: add new omkafka tests for dynamic topics
+ * travis: do no longer run 0mq tests
+ This often causes trouble when the packages are rebuild by the 0mq project
+ (which happens frequently). We already do intensive testing of the 0mq
+ components in the buildbot infrastructure, where we use dedicated containers.
+ This is reliable, as the containers already contain everything needed and so
+ do not need to reach out to the 0mq package archives. In the light of this,
+ let's save us the trouble of Travis failures. The only downside is that
+ users cannot pre-test with their local Travis when modifying 0mq modules,
+ which is quite acceptable.
+------------------------------------------------------------------------------
+Version 8.40.0 [v8-stable] 2018-12-11
+- mmkubernetes: add support for sslpartialchain for openssl
+ If `"on"`, this will set the OpenSSL certificate store flag
+ `X509_V_FLAG_PARTIAL_CHAIN`. This will allow you to verify the Kubernetes API
+ server cert with only an intermediate CA cert in your local trust store, rather
+ than having to have the entire intermediate CA + root CA chain in your local
+ trust store. See also `man s_client` - the `-partial_chain` flag.
+ This option is only available if rsyslog was built with support for OpenSSL and
+ only if the `X509_V_FLAG_PARTIAL_CHAIN` flag is available. If you attempt to
+ set this parameter on other platforms, you will get an `INFO` level log
+ message. This was done so that you could use the same configuration on
+ different platforms.
+- openssl driver: improved error messages
+ also fixes misleading wording of some error messages
+ closes https://github.com/rsyslog/rsyslog/issues/3238
+- imfile: disable file vs directory error on symlinks
+ The file/directory node-object alignment now ignores symlinks. Previously
+ it reported error on each directory symlink spamming user error logs.
+ Thanks to Jiri Vymazal for the patch.
+- cleanup: remove no longer needed --enable-rtinst code
+ configure option --enable-rtinst is gone-away since a while, but there were
+ still some supporting code left. It required careful analysis what could
+ actually be removed. This is now done and the code fully cleaned up. This
+ greatly simplifies the code and also makes it better readable for
+ developers which are not deep inside the rsyslog code base.
+ As a positive side effect, we could eliminate mutex calls inside
+ the debug system. This means we are more likely to reproduce race
+ conditions in runs with debugging enabled.
+ closes https://github.com/rsyslog/rsyslog/issues/2211
+- bugfix imfile: rsyslog re-sends data for files larger 2GiB
+ This occurs always if and only if
+ - reopenOnTruncate="on" is set
+ - file grows over 2GiB in size
+ Then, the data is continuously re-sent until the file becomes smaller
+ 2GiB (due to truncation) or is deleted.
+ It is a regression introduced by 2d15cbc8221e385c5aa821e4a851d7498ed81850
+ closes https://github.com/rsyslog/rsyslog/issues/3249
+- config: fix segfault in backticks "echo" expansion of undefined variables
+ The bug was introduced in commit abe0434 (config: enhance backticks "echo"
+ capability). The getenv() result passed to strlen() and es_addBuf() may be
+ NULL if the environment variable does not exist, resulting in a segfault.
+ Thanks to Julien Thomas for the patch.
+ fixes https://github.com/rsyslog/rsyslog/issues/3006
+- bugfix imsolaris: message timestamps on Solaris
+ On Solaris messages don't have their time directly in the raw body but in
+ a separate log_ctl structure which is currently not used.
+ When message is logged and processed, rsyslogd gives it current time because
+ it ignores the actual one. That means that old messages (e.g. from system
+ reboot) get timestamp of processing instead of the reboot itself (it is
+ not a problem for live logging where now is used anyway).
+ Thanks to Jakub Kulik for the patch.
+- bugfix build system: "make distcheck" did not work for mysql tests
+- bugfix build system: don't link liblogging-stdlog when available but not enabled
+ When liblogging-stdlog was available but configure option "--disable-liblogging-stdlog"
+ was set, rsyslog was still linking against liblogging-stdlog.
+ This commit will ensure that rsyslog will only link against liblogging-stdlog when
+ "--enable-liblogging-stdlog" was set.
+ see also: https://bugs.gentoo.org/667836
+- bugfix RainerScript: abs() could return negative value, now in range [0..max]
+ Thanks to Harshvardhan Shrivastava for providing the patch
+- bugfix debug output: date property options output wrongly
+ inside debug logging, the date property options were not all
+ properly converted into strings. Some of the newer ones were
+ invalidly flagged as "UNKNOWN". This is primarily a cosmetic
+ problem and has no effect other than puzzling folks looking at
+ the debug log.
+- bugfix omhttp: did not compile on some platforms
+- CI
+ * made mysql-based tests (ommysql and omlibdbi) work inside containers
+ * bugfix testbench: do not execute libgcrypt tests if disabled
+ closes https://github.com/rsyslog/rsyslog/issues/3228
+ * testbench: grep failed when string starting with "-" was used
+ The search term was mistakenly interpreted as an option.
+ * testbench: support auto-start/-stop of mysqld
+ This is required to run mysql/mariadb tests inside containers.
+ closes https://github.com/rsyslog/rsyslog/issues/3223
+ * improve bash coding style and fix a some bug in testbench
+ - duplicate diag.sh init call was not detected due to typo
+ - queue-persists test did not work correctly
+ - some general testbench framework improvements
+ issues found be shellcheck, fixes brought up other work to do
+ * testbench: improve journal tests and testbench framework
+ improving both style and reliability of journal tests; along that way
+ also improve testbench framework:
+ - do cleanup on error_exit and skip
+ - explicit skip handler (vs exit 77)
+ this permits us to do better cleanup
+ - new testbench functions for journal-specific functionality
+ reduce code duplication and make things easier to maintain in the
+ future
+ - provide a way to do valgrind and non-valgrind tests with a single
+ test file
+ see also https://github.com/rsyslog/rsyslog/issues/2564
+ * testbench: improve framework, harden rscript http test
+ - the test now tries to detect unavailable http server, which
+ should not result in test failure
+ - equivalent valgrind test changed to new method, removing code
+ duplication
+ - testbench supports
+ * new exit code 177, which indicates environment error, makes
+ test SKIP but still reports the failure
+ * new exitcode, logurl stats reporting fields
+ * report buildbot builder (if provided) in failure report
+ * testbench: add test for mmjsonparse with unparsable data
+ * testbench: make es-bulk-retry test more reliable
+ We now no longer depend on a fixed 'sleep' command but rather
+ check the output file for what we expect. This is much more
+ robust on slow test machines.
+ We believe this closes the below-mentioned issue. If not, it
+ should be re-opened.
+ closes https://github.com/rsyslog/rsyslog/issues/3104
+ * testbench: suppress valgrind error caused by pthreads lib
+ finally I give up and honestly think this is a problem in pthreads and
+ not in rsyslog code. See issue below and previous commit for more
+ information.
+ Unfortunately, this will also mask off cases where we do not properly
+ call pthread_join() albeit it is needed. Nevertheless, this bug is
+ causing so much CI grief that it is definitely worth it.
+ closes https://github.com/rsyslog/rsyslog/issues/2902
+ * testbench: made a couple of (unnamed due to too many) test more robust
+ against slow (CI) machines
+------------------------------------------------------------------------------
+Version 8.39.0 [v8-stable] 2018-10-30
+- imfile: improve truncation detection
+ previously, truncation was only detected at end of file. Especially with
+ busy files that could cause loss of data and possibly also stall imfile
+ reading. The new code now also checks during each read. Obviously, there
+ is some additional overhead associated with that, but this is unavoidable.
+ It still is highly recommended NOT to turn on "reopenOnTruncate" in imfile.
+ Note that there are also inherent reliability issues. There is no way to
+ "fix" these, as they are caused by races between the process(es) who truncate
+ and rsyslog reading the file. But with the new code, the "problem window"
+ should be much smaller and, more importantly, imfile should not stall.
+ see also https://github.com/rsyslog/rsyslog/issues/2659
+ see also https://github.com/rsyslog/rsyslog/issues/1605
+- imjournal: work around journald excessive reloading behavior
+ This is workaround for possible imjournal interaction with systemd
+ where journal invalidate fix is not present. The code tries to
+ detect SD_JOURNAL_INVALIDATE loop and not reload after each call.
+ Thanks to Jiri Vymazal for the patch.
+- errmsg: remove no longer needed code
+ refactored code (over a long time) so that object-ish style is no longer
+ needed and could now finally be removed; We also refactored the last
+ component (omhttp contrib module) that used the old interface.
+ closes https://github.com/rsyslog/rsyslog/issues/1684
+- queue bugfix: invalid error message on queue startup
+ due to some old regression (commit not exactly identified, but for
+ sure a regression, 9 years ago it was correct) an error message
+ is emitted when no .qi file exists on startup of the queue, which
+ is a normal condition.
+ Actually, the code should not have tried to open the .qi file in
+ the first place because it detected that it did not exist. That
+ (necessary) shortcut had been removed a while ago.
+ closes https://github.com/rsyslog/rsyslog/issues/3117
+- bugfix imrelp: regression with legacy configuration startup fail
+ Startup of a relp listener failed if legacy configuration was used.
+ caused by commit: 32b71daa8aadb8f16fe0ca2945e54d593f47a824
+ closes https://github.com/rsyslog/rsyslog/issues/3106
+- bugfix imudp: stall of connection and/or potential segfault
+ There was a regression in 493279b790a8cdace8ccbc2c5136985e820dd2fa.
+ This regression may cause stop (or delay) of reception from some systems
+ and may also cause a segfault. Triggering condition is that at least
+ one listener could not be created.
+ Thanks to Jens Låås for the patch.
+- bugfix gcry crypto driver: small memleak
+ If a crypto key is specified directly via the key="" parameter,
+ the storage for that key is not freed, causing a small memleak.
+ Note that the problem occurs only once per context, so this
+ should not cause real issues. Even more so, as specifying a
+ key directly is meant only for testing purposes and is strongly
+ discouraged for production use.
+ Detected by internal testing, no actual fail case known.
+- fix potential misaddressing in encryption subsystem
+ could happen if e.g. disk queues were encrypted
+ not seen in practice but caught by testbench test
+- ksi subsystem changes
+ * enhance debug logging
+ * disable unsafe SHA1 algorithm
+ Thanks to Allan Park for the patch.
+- bugfix core: regex compile error messages could be incorrect
+- bugfix core: potential hang on rsyslog termination
+ The root cause was a deadlock during worker startup. This could
+ happen for example when a DA queue needed to persist data during
+ shutdown.
+ Fail condition:
+ * startup request for a new worker
+ * initialization of that worker
+ * immediate detection that the worker can or must shutdown
+ * main thread waiting for worker running state, which it skips,
+ and so the main thread hangs inside a loop
+ closes https://github.com/rsyslog/rsyslog/issues/3094
+- bugfix imkafka: system hang when backgrounded
+ imkafka initializes librdkafka too early (before the fork). This leads
+ to hangs in various parts of the system - not only im imkafka but
+ other functions as well (e.g. getaddrinfo() calls).
+ closes https://github.com/rsyslog/rsyslog/issues/3180
+- bugfix imfile: file change was not reliably detected
+ A change in the inode was not detected under all circumstances,
+ most importantly not in some logrotate cases.
+ Includes new tests made by Andre Lorbach. They now use the
+ logrotate tool natively to reproduce the issue.
+ closes https://github.com/rsyslog/rsyslog/issues/2659
+ closes https://github.com/rsyslog/rsyslog/issues/1605
+- bugfix imrelp: do not fail build if librelp does not have relpSrvSetLstnAddr
+ closes https://github.com/rsyslog/rsyslog/issues/2938
+- bugfix queue subsystem: DA queue did ignore encryption settings
+ closes https://github.com/rsyslog/rsyslog/issues/3066
+ closes https://github.com/rsyslog/rsyslog/issues/2575
+- bugfix KSI: lmsig-ksils12 module skips signing the last block
+ Thanks to Allan Park for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/3105
+- bugfix fmhash: function hash64mod sometimes returned wrong result
+ Thanks to Harshvardhan Shrivastava for providing the patch
+ closes https://github.com/rsyslog/rsyslog/issues/3025
+- bugfix core/debug: data written to random fd 2 under some debug settings
+ This happens only during auto-backgrounding, where we cannot any longer
+ access stderr. Whatever is opened with fd2 receives some debug messages.
+ Note that the specific feature is usually turned on only in CI runs.
+- cleanup: removed no longer needed code
+ Code that was unused for quite a while or did not really belong to the
+ project identified and removed.
+- overall code cleanup
+ e.g. remove unused code, replace bad bash constructs, etc...
+- CI:
+ * some small improvements in testbench plumbing
+ e.g. (`cmd` replaced by $(cmd), removed useless use of cat, ...)
+ * testbench: improve plumbing for kafka tests
+ - Removed all sleeps where possible.
+ - Moved all kafka start/stop/download logic into functions.
+ - Moved kafka/zookeeper stop into error_exit and exit_test.
+ - Kafka/Zookeeper cleanup only done on success now.
+ - Kafka/Zookeeper logfiles automatically dumped on error_exit only now.
+ - Added cleanup for Kafka/Zookeeper instances into CI/buildbot_cleanup.sh
+ - added new tests
+ * testbench: fix incompatibility of one omprog test with Python3
+ Python3 writes to stderr immediately, and this caused the
+ captured output to differ with respect to Python2. Simplified
+ the test to do a single write to stderr. Also a cast to int
+ was needed when calculating 'numRepeats'.
+ closes https://github.com/rsyslog/rsyslog/issues/3030
+ * testbench: fixed imfile parallel issues
+ - Fixed timing issues in some imfile wildcard/regex tests
+ - Added touch command in imfile wildcard tests to make sure directories
+ exist before files are created in it if IO is under stress.
+ - changed content checking in some tests to use "content_check_with_count"
+ with check timeouts instead of using fixed sleeptimes.
+ * testbench: new basic tests
+ These ensure that for some modules that did not have any tests at all
+ we have at least a minimal coverage (module loads, activates, is able
+ to emit error messages). Of course, further improvements would make
+ much sense. Modules:
+ - ommail
+ - testbench: new tests for disk queue encryption
+ - testbench: improved auto-diagnostics for hanging instance
+ - testbench: hardened kafka test against failing kafka subsystem,
+ not in 100% of the cases, but at least in some that frequently occur
+ - failing tests now report failure status so that we can get stats
+ on unreliable tests
+ - testbench tooling: fix incorrect tcpflood TLS parameter check
+ could lead to segfault when started
+ - bugfix testbench tooling: tcpflood invalid type in calloc (openssl mode)
+ It is unlikely that this has caused a real issue, as long as pointers
+ are all of the same size (what is highly probable).
+ detected by cppcheck via Codacy.com
+------------------------------------------------------------------------------
+Version 8.38.0 [v8-stable] 2018-09-18
+- AIX: make basic modules work again
+- make rsyslog build on AIX again
+ ... at least for a limited set of default modules
+- imfile: support for endmsg.regex
+ This adds support for endmsg.regex. It is similar to
+ startmsg.regex except that it matches the line that denotes
+ the end of the message, rather than the start of the next message.
+ This is primarily for container log file use cases such as this:
+ date stdout P start of message
+ date stdout P middle of message
+ date stdout F end of message
+ The `F` means this is the line which contains the final part of
+ the message. The fully assembled message should be
+ `start of message middle of message end of message`.
+ `startmsg.regex="^[^ ]+ stdout F "` will match.
+ Thanks to Richard Megginson for the patch.
+- imkafka: add parameter "parseHostName"
+ This enables imkafka to parse the hostname from log message.
+ Previously that was not possible. It was most likely a bug, but
+ one that users may count on. The new parameter "ParseHostName"
+ (default is off) controls this behavior. Default is to NOT
+ parse the hostname.
+ Thanks to github user snaix for the contribution.
+- im[p]tcp: improve error message on connect failure
+ Now a message with the actual OS error is emitted, making things far
+ easier to troubleshoot.
+- imkafka: implement multithreading support for kafka consumers.
+ Each consumer runs in it's own consumer thread now. New tests have also
+ been added for this.
+- omelasticsearch: write all header metadata to $.omes for retries
+ Write all of the original request metadata fields to $.omes for
+ the retry, if present. This may include all of the following:
+ _index, _type, _id, _parent, pipeline
+ This is in addition to the fields from the response. If the same
+ field name exists in the request metadata and the response, the
+ field from the request will be used, in order to facilitate
+ retrying the exact same request.
+ Thanks to Richard Megginson for the patch.
+- core: improve error message on module load fail
+ The error message now lists all dlopen() errors in depth. This is
+ especially useful if the error is due to missing symbols or file
+ format errors.
+- core/queue: add error message if queue file cannot be accessed
+ When having a disk-assisted queue without permission to write to the specified
+ queue file an error will now be generated.
+ closes https://github.com/rsyslog/rsyslog/issues/323
+- imtcp/imudp: new option preservecase for managing the case of FROMHOST value
+ default is left at current behavior
+ see also https://github.com/rsyslog/rsyslog/pull/2774
+ see also https://bugzilla.redhat.com/show_bug.cgi?id=1309698
+- omprog: add feedback timeout and keep-alive feature
+ - Restart the program if it does not respond within timeout.
+ - New setting 'confirmTimeout' (default 10 seconds).
+ - Allow the program to provide keep-alive feedback when a
+ message requires long-running processing.
+ - Improve efficiency when reading feedback line (use buffer).
+ Retry interrupted writes/reads to/from pipe.
+ - New setting 'reportFailures' for reporting error messages
+ from the program.
+ - Report child termination when writing to pipe.
+ - Minor refactor: renamed writePipe function to sendMessage,
+ renamed readPipe to readStatus.
+ Thanks to Joan Sala for contributing this.
+- omprog: fix forceSingleInstance configuration option
+ The forceSingleInstance option did not work as intended. Even
+ if set multiple instances were spawned. This most probably
+ was a regression from 0453b1670fc34c96d31ee7c9a370f0f5ec24744a
+ The code was broken roughly 3.5yrs ago, so it looks like the
+ issue was little-noticed. This also means that potentially some users
+ may see the bugfix as change of behavior. If so, just remove
+ the option.
+ closes https://github.com/rsyslog/rsyslog/issues/2813
+ closes https://github.com/rsyslog/rsyslog/issues/2468
+ Thanks to Joan Sala for contributing this.
+- imfile: implement file-id, used in state file
+ This ensures that files with the same inodes are not accidentally treated
+ as equal, at least within the limits of the file id hash (see doc for
+ details).
+ We use the siphash reference implementation to generate our non-cryptographic
+ hash.
+ closes https://github.com/rsyslog/rsyslog/issues/2530
+ closes https://github.com/rsyslog/rsyslog/issues/2231
+- imfile: experimental input throttling feature
+ The new input parameter delay.message has been added. It specifies
+ a delay in microseconds after each line read.
+ closes https://github.com/rsyslog/rsyslog/issues/2960
+- core: emit TZ warning on startup not on Linux non-container
+ On Linux it seems common that the TZ variable is NOT properly set.
+ There are some concerns that the warning related to rsyslog correcting
+ this confuses users. It also seems that the corrective action rsyslog
+ takes is right, and so there is no hard need to inform users on that.
+ In Linux containers, however, the warning seems to be useful as the
+ timezone setup there seems to be frequently-enough different and
+ rsyslog's corrective action may not be correct.
+ So we now check if we are running under Linux and not within a container.
+ If so, we do not emit the warning. In all other case, we do. This is
+ based on the assumption that other unixoid systems still should have
+ TZ properly set.
+ closes https://github.com/rsyslog/rsyslog/issues/2994
+- omkafka:
+ * better debug information
+ * Fixed minor issue in omkafka producing wrong kafka timestamps when
+ msgTimestamp was NULL.
+ * Setting RD_KAFKA_V_KEY(NULL, 0) in rd_kafka_producev now when KEY is not
+ configured.
+ * Fixed minor issue when rsyslog is compiled with --enable-debug and
+ librdkafka is too old.
+- omfile bugfix: errant error message when dynafile param needed
+ also fixes related message in contributed module omfile-hardened
+ closes https://github.com/rsyslog/rsyslog/issues/2975
+ Thanks to Frank Bicknell for the patch
+- omhttp: new contributed module
+ Thanks to Christian Tramnitz for contributing it.
+ Some more info at https://github.com/rsyslog/rsyslog/pull/2782
+- mmkubernetes: action fails preparation cycle if kubernetes API ...
+ ... destroys resource during bootup sequence
+ The plugin was not handling 404 Not Found correctly when looking
+ up pods and namespaces. In this case, we assume the pod/namespace
+ was deleted, annotate the record with whatever metadata we have,
+ and cache the fact that the pod/namespace is missing so we don't
+ attempt to look it up again.
+ In addition, the plugin was not handling error 429 Busy correctly.
+ In this case, it should also annotate the record with whatever
+ metadata it has, and _not_ cache anything. By default the plugin
+ will retry every 5 seconds to connect to Kubernetes. This
+ behavior is controlled by the new config param `busyretryinterval`.
+ This commit also adds impstats counters so that admins can
+ view the state of the plugin to see if the lookups are working
+ or are returning errors. The stats are reported per-instance
+ or per-action to facilitate using multiple different actions
+ for different Kubernetes servers.
+ This commit also adds support for client cert auth to
+ Kubernetes via the two new config params `tls.mycert` and
+ `tls.myprivkey`.
+ Thanks to Richard Megginson for the patch.
+- bugfix pmnormalize/core: several memory leaks, invld property handling
+ - major memory leak which occurred once per message processed
+ So this could lead to OOM. Caused by improper free of json
+ structure
+ - another two major leaks of similar magnitude could occur if
+ "fromhost-ip" and/or "fromhost" properties were set
+ - minor leaks upon termination. these were unproblematic as
+ static and only occurred immediately before shutdown.
+ But they triggered memory debugger errors.
+ - fixed test which did not check for mem leaks albeit it should
+ - core invalid handling of the "fromhost" property, if set via
+ the MsgSetPropsViaJSON() call. This was primarily of concern
+ for pmnormalize and mmexternal, and only if these properties
+ were used by either the rulebase or the external program
+ response.
+ Actually, most of the leaks go back to rsyslog core, but that
+ core functionality was not used by other modules in the same
+ way. But if some other would have used it, the effects would
+ have been the same (so be aware if you wrote custom modules).
+- bugfix imptcp: fixed pointers for session counting
+ imptcp open, failedopen, and closed pstats counters were assigned the wrong
+ name, thus pstats values did provide a totally wrong picture of what was
+ going on.
+ Thanks to github user jeverakes for the patch.
+- bugfix omprog: invalid memory access on partial writes to pipe
+ When sending logs to the program, in case of a partial write to the pipe,
+ invalid data was sent, or an invalid memory access could occur. (A
+ partial write can occur if the syscall is interrupted or the pipe is full.)
+ Thanks to Joan Sala for contributing this.
+- bugfix omprog: rsyslog's environment was not passed to script
+ closes https://github.com/rsyslog/rsyslog/issues/2921
+- bugfix omprog: severity of some log messages in waitForChild corrected
+ Log some messages related to child process termination as info/warn
+ instead of error.
+- bugfix imfile: files which were loaded via symlink were not always followed
+ They were stopped watching after being rotated.
+ closes https://github.com/rsyslog/rsyslog/issues/2229
+ Thanks to Jiri Vymazal for the patch.
+- bugfix imfile: potential misaddressing when processing symlinks
+ Fixed parent name when processing symlinks. Detected during code review.
+ There was a garbage byte left before which could cause errors down the
+ road.
+ Thanks to Jiri Vymazal for the patch.
+- bugfix ommongodb: build issue if mongo-c-driver is not compiled with TLS
+ Let ommongodb module works even if mongo-c-driver is not compiled with SSL support.
+ Thanks to Jérémie Jourdin for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/2907
+- CI:
+ * many changes with the goal to support parallel test execution, e.g.
+ use dynamic ports and file names, changes to testing tools, etc.
+ * kafka tests re-enabled, as they should now no longer be racy. However,
+ this has yet to be proven in practice.
+ * upgrading kafka server version to current
+ * Fixed server configuration issues holding the kafka tests back from working
+ * Fixed some config issues in all sndrcv kafka tests.
+ * Generating dynamically kafka topics now for each kafka test.
+ * Reenabled kafka_multi test which runs a test on 3 kafka/zookeeper instances
+------------------------------------------------------------------------------
+Version 8.37.0 [v8-stable] 2018-08-07
+- build system: add --enable-default-tests ./configure option
+ This permits to control the "default tests" in testbench runs. These
+ are those tests that do not need a special configure option. There are
+ some situations where we really want to turn them of so that we can
+ run tests only for a specific component (e.g. ElasticSearch).
+ This commit also removes the --enable-testbench[12] configure switches,
+ which were introduced just to work-around travis runtime restrictions.
+ With the new CI setup and new options we could reduce the Travis runtime
+ dramatically and so we do not need them any longer.
+- overall adaptation to gcc 8 which emits new warnings
+- fix some build warnings on 32bit systems, namely armhf architecture
+- ommail change of behavior: "enable.body" default now "on"
+ This was always documented to be "on", but actually was "off". Usually, we
+ fix the doc, but after long discussion the agreement was that in this
+ specific case it was actually better to change the default.
+ see also: https://github.com/rsyslog/rsyslog/pull/2791
+- core/omfile: race in async writing mode
+ mutex was not properly locked at all times when the async writing buffer
+ was flushed
+ Thanks to Radovan Sroka for the patch.
+- core: provide a somewhat better default action name
+ We now include the module name (e.g. "omelasticsearch" or "builtin:omfile")
+ as part of the name. This is still not perfect, but hopefully a bit
+ easier to grasp.
+ see also https://github.com/rsyslog/rsyslog/issues/342
+- new global() parameter "abortOnUncleanConfig"
+ This provides a new-style alternative to $AbortOnUncleanConfig.
+ closes https://github.com/rsyslog/rsyslog/issues/2744
+- tcpflood no longer links with -lgrcypt
+ as this is no longer necessary for GnuTLS
+ Thanks to Michael Biebl for the patch.
+- imjournal: add journal-specific impstats counters
+ these provide some additional insight into journal operations
+ Thanks to Abdul Waheed for the patch.
+- imjournal: fixed startup on missing state file
+ When starting rsyslog with imjournal for first time it outputs
+ an error and plugin does not run because no state file exists yet.
+ Now it skips the loading and creates state file on first persist.
+ Thanks to Jiri Vymazal for the patch.
+- imjournal: fetching cursor on readJournal() and simplified pollJournal()
+ Fetching journal cursor in persistJournal could cause us to save
+ invalid cursor leading to duplicating messages further on, when new
+ WorkAroundJournalBug option is set we are saving it on each
+ readJournal() where we now that the state is good.
+ pollJournal() is now cleaner and faster, correctly handles INVALIDATE
+ status from journald and is able to continue polling after journal
+ flush. Also reduced POLL_TIMEOUT a bit as it caused rsyslog to exit
+ with error in corner cases for some ppc when left at full second.
+ re-factored imjournal CI tests with journal_print tool to have more
+ detailed error reporting.
+ Thanks to Jiri Vymazal for the patch.
+- config: enhance backticks "echo" capability
+ This is now more along the lines of what bash does. We now support
+ multiple environment variable expansions as well as constant text
+ between them.
+ example:
+ env SOMEPATH is set to "/var/log/custompath"
+ config is: param=`echo $SOMEPATH/myfile`
+ param than is expanded to "/var/log/custompath/myfile"
+ among others, this is also needed inside the testbench to properly
+ support "make distcheck".
+ Note: testbench tests follows via separate commit. There will be
+ no special test, as the testbench itself requires the functionality
+ at several places, so the coverage will be very good even without
+ a dedicated test.
+- imrelp: add support for setting address to bind to (#894)
+ This adds a new optional `address` parameter to `imrelp` inputs in order
+ to specify an address to bind to.
+ Based on support added by rsyslog/librelp@96eb5be
+ Thanks to Simon Wachter for the patch.
+- omrelp: permit all authmodes; updated tests
+ omrelp for some time limited authentication modes to those
+ that were known. While this was OK, it prevented the easy
+ introduction of new auth modes into librel.
+ This has now been changed; omrelp now checks the validity of
+ the authmode directly via librelp by doing some librelp calls
+ upon processing the configuration.
+ Also, some tests have been updated to check this feature and
+ also ensure that the new librelp mode "certvalid" works
+ (if it is available).
+- regexp.c: reduce lock contention when using glibc.
+ When using glibc, we enable per-thread regex to avoid lock contention.
+ See:
+ - https://github.com/rsyslog/rsyslog/issues/2759
+ - https://github.com/rsyslog/rsyslog/pull/2786
+ - https://sourceware.org/bugzilla/show_bug.cgi?id=11159
+ This should not affect BSD as they don't seem to take a lock in regexec.
+ NOTE: it is assumed that we can craft an even better solution than
+ this patch, but it improves the situation and we do not have time to
+ craft more. So we decided to merge. For details see
+ https://github.com/rsyslog/rsyslog/pull/2786
+- mmpstrucdata: better error message, support $! in var names
+ see also https://github.com/rsyslog/rsyslog/issues/1262#issuecomment-404773495
+- more explicit error msg with message modification mod on queue
+ Message modification modules do not work if used with a non-direct queue.
+ We now make this more explicit in the config parsing error message.
+ closes https://github.com/rsyslog/rsyslog/issues/1323
+- omrabbitmq: improve high-load performance
+ A different pthread mutex is created for each connection (action)
+ instead of a single one shared by all connections. This will
+ improve performance when using multiple concurrent connections
+ to a single (or multiple) RabbitMQ instance(s) (e.g. for load balancing)
+ Thanks to github user micoq for contributing the patch.
+- imudp: replace select() calls by poll()
+ This improves reliability in extreme cases (more than 1024 fds open when
+ imudp begins to listen) and potentially improves performance a little.
+- ommysql: support mysql unix domain socket:
+ via action(.. socket="/tmp/mysqld.sock" ..)
+ Thanks to JoungKyun Kim for contributing this.
+- impstats: emit warning if log.syslog="off" and ruleset name given
+ With this config, "ruleset" is silently ignored, what probably is
+ not obvious to a user.
+ closes https://github.com/rsyslog/rsyslog/issues/2821
+- build system cleanup: remove no longer needed --enable-memcheck
+ This was used for a very old testing capability, no longer functional but
+ causes build to fail if enabled. Replaced by ASAN/valgrind.
+ Issue detected while testing some other CI settings.
+- tools: Updated python based statslog analyzer sample scripts
+- developer tools: make devcontainer tool more developer friendly
+ slight improvement for easy interactive use
+- enable better testing via "make distcheck"
+ Also a couple of changes to testbench worth mentioning:
+ * use cp -f to ensure files can be overwritten in VBUILD
+ * fix issue of missing include test file in EXTRA_DIST
+ * new suppressions
+ * testbench: try to use local system dependency cache
+ avoid going to Internet repos if not absolutely necessary. For
+ development containers, they should be pre-populated with the
+ important dependencies.
+ * do not enable libfaketime if ASAN is selected
+ unfortunately, libfaketime does not work in that case
+ Note: for modules with non-standard dependencies (e.g. databases),
+ "make distcheck" only enables what on the original ./configure line
+ was enabled. This is done in order to ensure that "distcheck" adapts
+ to what is actually available on the system in question. Rsyslog's
+ own CI system installs the maximum set of possible dependencies and
+ so tries the maximum set "make distcheck" can support on a platform.
+ see also https://github.com/rsyslog/rsyslog/issues/174
+- add new global config parameter "inputs.timeout.shutdown"
+- omusrmsg: do not fall back to max username length of 8
+ This happens if utmp.h and friends are not available and stems back to
+ the original syslogd. Nowadas, 32 is more appropriate and now being used
+ in that (now very unlikely) case. The detection logic for UT_NAMESIZE has
+ also been streamlined.
+ closes https://github.com/rsyslog/rsyslog/issues/2834
+- bugfix build system: fix race in parallel builds
+ If libgcry.la is built later than lmcry_gcry.la, there is a failure:
+ [snip]
+ |../aarch64-wrs-linux-libtool --tag=CC --mode=link aarch64-wrs-linux-gcc
+ -o lmcry_gcry.la lmcry_gcry_la-lmcry_gcry.lo libgcry.la -lgcrypt
+ |aarch64-wrs-linux-libtool: error: cannot find the library 'libgcry.la'
+ or unhandled argument 'libgcry.la'
+ |Makefile:1049: recipe for target 'lmcry_gcry.la' failed
+ |make[2]: *** [lmcry_gcry.la] Error 1
+ [snip]
+ The LIBADD of lmcry_gcry.la contains libgcry.la, we should also add libgcry.la
+ to lmcry_gcry.la's DEPENDENCIES.
+ Thanks to Hongxu Jia for the patch.
+- bugfix imfile: memory leak upon shutdown (cosmetic)
+ When rsyslog shuts down and imfile is inside a change polling loop,
+ it does not properly free memory returned by glob(). This is a cosmetic
+ bug as the process terminates within the next few milliseconds. However,
+ it causes memory analyzer reports and thus makes CI fail.
+- bugfix core msg: potential deadlock (and rsyslog hang)
+ can happen e.g. with headerless messages when app-name
+ property is used
+ closes https://github.com/rsyslog/rsyslog/issues/3135
+- bugfix core: do not abort startup on problems setting scheduling policy
+ rsyslog creates a default scheduling policy on startup. This code
+ invalidly used CHKiRet (our exception handler) to check pthreads
+ return codes, what this macro cannot do. This lead to hard to
+ diagnose startup problems in cases where there were problems
+ setting the scheduling defaults (e.g. when rsyslog is set to run
+ at idle priority). Even more so, this blocked startup altogether,
+ which is not the right thing to do. Actually, this can be considered
+ a regression from commit 7742b21. That commit was 8 years ago, so
+ in general this cannot be a big issues ;-)
+ The code now emits proper error messages (to stderr, as at this point
+ no other output is available as it is during the initial state of
+ rsyslog initialization) and continues the startup.
+ closes https://github.com/rsyslog/rsyslog/issues/2855
+- bugfix core: input shutdown timeout not properly applied
+ The timeout could be reduced by mutex wait time, which was not the
+ intended behavior and could lead the the input thread being
+ cancelled while it would have been perfectly legal to shut it down
+ cleanly.
+ Noticed during working on the CI system. May explain some testbench
+ instability and may have caused trouble with state files (not)
+ properly being written by inputs.
+- bugfix config optimizer: error in constant folding
+ did not work properly if a string and a number were to be folded.
+ Detected by gcc 8.
+- build: fix improper function casts
+ no real issue, but generated warnings under gcc 8 and thus
+ broke CI
+- bugfix omlibdbi: fix potential small memory leak
+ detected by clang static analyzer
+- bugfix ommysql: unsafe use of strncpy()
+ also now reports oversize names as user error vs. silent truncation
+ overly long names only could affect config load phase
+- bugfix omhttpfs: fix insecure usage if strncmp()
+ consequences not evaluated as this is a contributed module.
+ Detected by gcc 8.
+- bugfix mmgrok: cosmetic build issue - compiler warnings
+ caused build under gcc 7 to fail with warning
+- bugfix mmkubernetes: stops working with non-kubernetes container names
+ When mmkubernetes encounters a record with a CONTAINER_NAME field,
+ but the value does not match the rulebase, mmkubernetes returns
+ an error, and mmkubernetes does not do any further processing
+ of any records.
+ The fix is to check the return value of ln_normalize to see if
+ it is a "hard" error or a "does not match" error.
+ This also adds a test for pod names with dots in them.
+ Thanks to Richard Megginson for the patch.
+- bugfix mmkubernetes: potential NULL pointer access
+ If token file could not be opened, fclose() was passed a NULL pointer.
+ Thanks to github user jvymazal for finding and Richard Megginson
+ for fixing the issue.
+- bugfix omsnmp: invalid traptype was not detected
+ this could leave config errors unreported and cause unexpected
+ behavior
+- bugfix mmkubernetes: default rules use container_name_and_id
+ also include rulebase files in dist and fix rule so that dot inside
+ pod name is supported.
+ Thanks to Richard Megginson for fixing the issue.
+- bugfix omelasticsearch: build regression
+ Commit 6d4635efbb13907bf651b1a6e5a545effe84d9d9 introduced some compile
+ problems, which were only detected on CentOS6, which unfortunately did
+ not compile omelasticsearch during CI runs
+- bugfix ommongodb: do not force MongoDB to use "PLAIN" auth mechanism
+ ... which also seems not to be handled by current MongoDB.
+ Remove ?authMechanism=PLAIN URI part to let the mongo library chooses the
+ default mechanism. One can force a specific authentication mechanism by
+ adding ?authMechanism=XXX into the uristr argument of the module
+ Thanks to Jérémie Jourdin for the fix.
+ closes https://github.com/rsyslog/rsyslog/issues/2753
+- build system: do not disable tests via --disable-liblogging-stdlog
+ This setting controlled both the actual rsyslog functionality as well
+ as some testbench tests, which use liblogging-stdlog to provide some
+ specific functionality. This meant those tests were not run since
+ changing the default. Now untangling the dependency.
+- CI:
+ * most test refactored to use newer testbench plumbing
+ while no functional change, this permits further enhancements
+ * ElasticSearch startup timeout in tests increased to care for
+ slower test systems
+ * imjournal: fixed tests to actually test plugin functionality
+ Thanks to Jiri Vymazal for the patch.
+ * new test for gnutls priority string in librelp
+ Thanks to github user jvymazal for the patch
+ * testbench: relax hanging instance detection
+ This does not work reliably if multiple instances of rsyslog
+ builds run on a single machine. We need to improve, but this
+ commit makes conflict less likely and provides some diagnostic
+ info to help guide us towards a final solution.
+ * testbench: fix tests that look awfully wrong
+ These tests indicated they terminate rsyslog forcefully without
+ draining the queues, but then checked if they were drained (all
+ messages processed). That does not make sense, and we cannot
+ envision why this was written the first place. So we assume some
+ copy&paste problem was the root of that.
+ * testbench: refactor tests which used "nettester" tool
+ Some old tests are carried out via the nettester tool. This was
+ our initial shot at a testbench a couple of years ago. While it
+ worked back then, the testbench framework has been much enhanced.
+ These old tests are nowadays very hard to handle, as they miss
+ debug support etc. So it is time to refactor them to new style.
+ As a side-activity, the testbench plumbing has been enhanced to
+ support some operations commonly needed by these tests. Contrary
+ to pre-existing plumbing, these new operations are now crafted
+ using bash functions, which we consider superior to the current
+ method. So this is also the start of converting the older-style
+ functionality into bash functions. We just did this now because
+ it was required and we entangled it into the test refactoring
+ because it was really needed. Else we had to write old-style
+ operations and convert them in another commit, which would
+ have been a waste of time.
+ Special thanks to Pascal Withopf for the initial step of taking
+ old tests and putting config as well as test data together into
+ the refactored tests, on which Rainer Gerhards than could build
+ to create the new tests and update testbench plumbing.
+ * testbench: ensure uxsock test leaves no dangling listener instances
+ ..in case the test aborts. We utilize the timeout utility for now
+ to prevent this.
+ * testbench: make port for imdiag dynamic
+ This is prep work to support parallel test runs
+------------------------------------------------------------------------------
+Version 8.36.0 [v8-stable] 2018-06-26
+- build system change:
+ Liblogging-stdlog was introduced to provide a broader ability to send rsyslog
+ internal logs to different sources. However, most distros did not pick up
+ that capability and so instead we do a regular syslog() call. We assume that
+ the actual functionality is never used in practice, so we plan to retire it.
+ That makes building rsyslog from source easier.
+ The plan is to disable use of liblogging-stdlog by default during
+ configure. So users (and distros!) can still opt-in to have it enabled if
+ they desire.
+ A couple of releases later, we want to completely remove the functionality,
+ except if there has desire been shown in the meantime which justifies to keep
+ liblogging-stdlog.
+ This version disabled liblogging-stdlog by default. We now also
+ emit a warning message ("liblogging-stdlog will go away") so that users
+ know what is going on and my react.
+ closes https://github.com/rsyslog/rsyslog/issues/2705
+ see also https://github.com/rsyslog/rsyslog/issues/2706
+- add openssl driver alongside GnuTLS one for TLS communication
+ The openssl driver is currently experimental. It will become the new preferred
+ driver as it permits us to provide much better end-user error message than
+ we could provide with GnuTLS. It is also less picky with certificate files
+ and provides specific error messages if there are certificate problems.
+ closes: https://github.com/rsyslog/rsyslog/issues/1390
+ closes: https://github.com/rsyslog/rsyslog/issues/1840
+ closes: https://github.com/rsyslog/rsyslog/issues/1352
+ closes: https://github.com/rsyslog/rsyslog/issues/1702
+ closes: https://github.com/rsyslog/rsyslog/issues/2547
+- GnuTLS TLS driver: support intermediate certificates
+ this is necessary for certificate chains
+ Thanks to Arne Nordmark for providing the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/2762
+- omelasticsearch: write op types; bulk rejection retries
+ * Add support for a 'create' write operation type in addition to
+ the default 'index'. Using create allows specifying a unique id
+ for each record, and allows duplicate document detection.
+ * Add support for checking each record returned in a bulk index
+ request response. Allow specifying a ruleset to send each failed
+ record to. Add a local variable `omes` which contains the
+ information in the error response, so that users can control how
+ to handle responses e.g. retry, or send to an error file.
+ * Add support for response stats - count successes, duplicates, and
+ different types of failures.
+ * Add testing for bulk index rejections.
+ Thanks to Richard Megginson for the patch.
+- lookup tables: reload message now with "info" severity (was "error")
+ thanks to Adam Chalkley for the patch
+- imptcp: add support for regex-based framing
+ for complex multi-line messages (XML in particular), the multiLine method
+ does not work well. We now have a capability to specify via a regex when
+ a frame starts (and the previous thus ends).
+ adds imptcp input parameter "framing.delimiter.regex"
+- imjournal: add statistics counter
+ following statistics counter are now supported by imjournal
+ - submitted = total number of messages submitted for processing
+ closes https://github.com/rsyslog/rsyslog/issues/2549
+- config: permit 4-digit file creation modes
+ permit 4-digit file creation modes (actually 5 with the leading zero) so
+ that the setgid bit can also be set (and anything else on that position.
+ closes https://github.com/rsyslog/rsyslog/issues/1092
+- ommongodb: add possibility to ignore some insertion error code
+ new config parameter "allowed_error_codes", which will be ignored if
+ they happen. For example, 11000 DuplicateKey in case of collection
+ containing a unique field.
+ Thanks to Hugo Soszynski for contributing this work
+- omprog: simplify 'plugin-with-feedback.py' example
+ Make the skeleton easier to understand by removing transaction support.
+ Also, transaction failures did not work as explained in the skeleton,
+ because of issue #2420. In the future, a 'plugin-with-transactions.py'
+ example can be added, ideally once the issue is solved.
+ Thanks to Joan Sala for contributing this.
+- core: misaddressing when writing disk queue files
+ when writing disk queue files during shutdown, access to freed
+ memory can occur under these circumstances:
+ - action A is processing data, but could not complete it
+ most importantly, the current in-process batch needs not to
+ be totally completed. Most probable cause for this scenario
+ is a suspended action in retry mode.
+ - action A is called from a ruleset RA which
+ - does not have a queue assigned
+ - where RA is called from a ruleset RO which is bound
+ to the input from which the message originated
+ - RO must be defined before RA inside the expanded config
+ - Disk queues (or the disk part of a DA queue) must be utilized by A
+ When re-injecting the unprocessed messages from A into the disk queue, the
+ name of ruleset RO is accessed (for persisting to disk). However, RO is
+ already destructed at this point in time.
+ The patch changes the shutdown processing of rulesets, so that all
+ shutdown processing is done before any ruleset data is destructed. This
+ ensures that all data items which potentially need to be accessed
+ remain valid as long as some part may potentially try to access them.
+ This follows a the approach used in
+ https://github.com/rsyslog/rsyslog/pull/1857
+ where obviously that part of the problem was not noticed.
+ see also https://github.com/rsyslog/rsyslog/issues/1122
+ closes https://github.com/rsyslog/rsyslog/issues/2742
+- core: fix message loss on target unavailability during shutdown
+ Triggering condition:
+ - action queue in disk mode (or DA)
+ - batch is being processed by failed action in retry mode
+ - rsyslog is shut down without resuming action
+ In these cases messages may be lost by not properly writing them
+ back to the disk queue.
+ closes https://github.com/rsyslog/rsyslog/issues/2760
+- imrelp bugfix: error message "librelp too old" is always emitted ...
+ ... even if librelp is current. The condition check was actually missing.
+ This commit adds it.
+ closes https://github.com/rsyslog/rsyslog/issues/2712
+- imrelp: segfault on startup when cert without priv key is configured
+ closes https://github.com/rsyslog/rsyslog/issues/2747
+- omrelp bugfix: segfault on first message sent when authmode was wrong
+ A segfault could occur if the authmode was configured to an invalid value.
+ This is now caught during config processing and an error is reported.
+ closes https://github.com/rsyslog/rsyslog/issues/2743
+- imfile bugfix: double-free on module shutdown
+ detected by code review, not seen in practice
+- imfile/core bugfix: potential misaddressing in string copy routine
+ This can be exposed via imfile, as follows:
+ - use a regex to process multiline messages
+ - configure timeouts
+ - make sure imfile reads a partial message
+ - wait so that at least one timeout occurs
+ - add the message termination sequence
+ This leads to a misaddressing, which may have no obvious effects potentially
+ up to a segfault.
+ closes https://github.com/rsyslog/rsyslog/issues/2661
+- imfile bugfix: if freshStartTail is set some initial file lines missing
+ When the option is set and a new file is created after rsyslog startup,
+ freshStartTail is also applied to it. That is data written quickly to it
+ (before rsyslog can process it) will potentially be discarded. If so,
+ and how much, depends on the timing between rsyslog and the logging process.
+ This problem is most likely to be seen in polling mode, where a relatively
+ long time may be required for rsyslog to find the new file.
+ This is changed so that now freshStartTail only applies to files that
+ are already-existing during rsyslog's initial processing of the file
+ monitors. HOWEVER, depending on the number and location (network?) of
+ existing files, this initial startup processing may take some time as
+ well. If another process creates a new file at exactly the time of
+ startup processing and writes data to it, rsyslog might detect this
+ file and it's data as prexisting and may skip it. This race is inevitable.
+ So when freshStartTail is used, some risk of data loss exists. The same
+ holds true if between the last shutdown of rsyslog and its restart log
+ file content has been added. This is no rsyslog bug if it occurs.
+ As such, the rsyslog team advises against activating the freshStartTail
+ option.
+ closes https://github.com/rsyslog/rsyslog/issues/2464
+- core: fix undefined behavior (unsigned computation may lead to value < 0)
+ This was detected by LLVM UBSAN. On some platforms re-setting the rawmsg
+ inside the message object could lead to invalid computation due to the
+ fact the the computation was carried out as unsigned and only then
+ converted to integer.
+ No known problem in practice.
+- CI/QA:
+ - improved Elasticsearch tests so they can now be run without system-
+ installed ES service; also enables us to specify specific ES versions
+ and should now make the tests executable inside a container
+------------------------------------------------------------------------------
+Version 8.35.0 [v8-stable] 2018-05-15
+- imptcp: add ability to configure socket backlog
+ this can be useful under heavy load.
+ For a detailed discussion see https://github.com/rsyslog/rsyslog/pull/2561
+ Thanks to Maxime Graff for implementing this.
+- omfile: do not permit filename that only consists of whitespace
+- fmhash: new hash function module
+ implements hash32() and hash64() functions
+ Thanks to Harshvardhan Shrivastava for implementing these
+- some better error messages
+- imklog: add ratelimiting capability
+ On Linux kernel logs are ratelimited only for messages using
+ printk_ratelimit(). Some logs do not use this facility, so
+ we ratelimit kernel ourselves.
+ Thanks to Berend De Schouwer for the patch.
+- omkafka: added impstats counters for librdkafka returned statistics
+ Adds:
+ * statscallback counters
+ * librdkafka failure and error counters
+ * acked message counter
+ Thanks to Abdul Waheed for implementing this.
+- imudp
+ * use rsyslog message rate-limiter instead of home-grown one
+ imudp introduced it's own (feature-limited) rate-limiting capability for
+ message on disallowed senders before we had central rate-limiters
+ inside rsyslog. Also, that code evolved from running on a single
+ thread to running on multiple threads, which introduced data races
+ and so made unreliable.
+ Now we removed the old rate-limiting capability and depend on the
+ system rate limiter for internal rsyslog messages.
+ closes https://github.com/rsyslog/rsyslog/issues/2467
+ * add stats counter "disallowed"
+ counts the number of messages discarded due to being received from
+ disallowed senders
+ see also https://github.com/rsyslog/rsyslog/issues/2467
+- imrelp: add parameter "oversizeMode"
+ Permits to instruct librelp how to handle oversize messages. The new default
+ is to truncate messages. Previously, the connection was aborted, what often
+ lead to stuck messages at the sender side. Now, there are three options passed
+ down to librelp:
+ * abort - same behavior as previously, connection is aborted on error
+ * truncate - do not abort but instead truncate oversize message to
+ configured max size
+ * accept - accept all oversize messages (note: this can cause security issues,
+ see doc for details)
+ see also https://github.com/rsyslog/rsyslog/pull/1525#issuecomment-384179393
+ see also https://github.com/rsyslog/rsyslog/issues/2190
+ closes https://github.com/rsyslog/rsyslog/issues/2633
+ closes https://github.com/rsyslog/rsyslog/issues/1741
+ closes https://github.com/rsyslog/rsyslog/issues/1782
+ closes https://github.com/rsyslog/rsyslog/issues/2496
+- core: consistent handling of oversize input messages
+ In the community we frequently discuss handling of oversize messages.
+ David Lang rightfully suggested to create a central capability inside
+ rsyslog core to handle them.
+ We need to make a distinction between input and output messages. Also,
+ input messages frequently need to have some size restrictions done at
+ a lower layer (e.g. protocol layer) for security reasons. Nevertheless,
+ we should have a central capability
+ * for cases where it need not be handled at a lower level
+ * as a safeguard when a module invalidly emits it (imfile is an example,
+ see https://github.com/rsyslog/rsyslog/pull/2632 for a try to fix it
+ on the module level - we will replace that with the new capability
+ described here).
+ The central capability works on message submission, and so cannot be
+ circumvented. It has these capabilities:
+ * oversize message handling modes:
+ - truncate message
+ - split message
+ this is of questionable use, but also often requested. In that mode,
+ the oversize message content is split into multiple messages. Usually,
+ this ends up with message segments where all but the first is lost
+ anyhow as the regular filter rules do not match the other fragments.
+ As it is requested, we still implemented it.
+ - accept message as is, even if oversize
+ This may be required for some cases. Most importantly, it makes
+ quite some sense when writing messages to file, where oversize
+ does not matter (accept from a DoS PoV).
+ * report message to a special "oversize message log file" (not via the
+ regular engine, as that would obviously cause another oversize message)
+ This commit, as the title says, handles oversize INPUT messages.
+ see also https://github.com/rsyslog/rsyslog/issues/2190
+ closes https://github.com/rsyslog/rsyslog/issues/2681
+ closes https://github.com/rsyslog/rsyslog/issues/498
+ Note: this commit adds global parameters:
+ * "oversizemsg.errorfile",
+ is used to specify the location of the oversize message log file.
+ * "oversizemsg.report",
+ is used to control if an error shall be reported when an oversize
+ message is seen. The default it "on".
+ * add global parameter "oversizemsg.input.mode"
+ is used to specify the mode with which oversized messages will
+ be handled.
+- omfwd: add support for bind-to-address for UDP
+ To allow the same source address to be used regardless of the egress
+ interface taken, an option is added for an address to bind the datagram
+ socket to. Similarly to imudp, it is necessary to add an ipfreebind
+ option which is set by default, so as to avoid an excess of errors at
+ startup before the network interface has come up. This enhancement
+ allows a usecase on networking devices, by which a source interface
+ that is typically a loopback is specified, on which an address to bind
+ to is configured. This is so that the same source address is used for
+ all packets from rsyslog.
+ Thanks to Mike Manning for the patch.
+- template systemd service file proposes higher permitted file handle limit
+ Especially on busy systems the default are too low. Please keep in mind
+ that on a very busy system even the now-proposed setting may be too low.
+ Thanks to github user jvymazal for the patch.
+- imuxsock: replace select() call by poll()
+ While extremely unlikely, imuxsock could abort if a file descriptor
+ > 1024 was received during the startup phase (never occurred in
+ practice, but theoretically could if imfile monitored a large number
+ of files and were loaded before imuxsock - and maybe other
+ strange cases).
+ see also https://github.com/rsyslog/rsyslog/issues/2615
+- nsdsel_ptcp: replace select() by poll()
+ This removes us of problems with fds > 1024. The performance will
+ probably also increase in most cases.
+ Note this is not a replacement for the epoll drivers, but a general
+ stability improvement when epoll() is not available for some reason.
+ see also https://github.com/rsyslog/rsyslog/issues/2615
+ closes https://github.com/rsyslog/rsyslog/issues/1728
+ closes https://github.com/rsyslog/rsyslog/issues/1459
+- omprog: refactor tests, fix child closing issues
+ Refactor omprog tests. Fix sync issues in these tests by
+ using the feedback mode (confirmMessages=on) to synchronize
+ the test with the external program. Closes #2403 (I hope)
+ Fix omprog not properly closing child process when
+ signalOnClose=on. Needed for the new tests. Closes #2599
+ Fix omprog not waiting for the child process to terminate
+ when signalOnClose=off. Needed for the new tests. Closes #2600
+ Close all fds before executing the child even when valgrind
+ is enabled (--enable-valgrind). Needed for the new tests.
+ Fix memory leak when the xxxTransactionMark parameters were
+ used.
+ Thanks to Joan Sala for the patch.
+- core: config optimizer did not handle call_indirect
+ This also caused the emission of an "internal error" error message
+ closes https://github.com/rsyslog/rsyslog/issues/2665
+- debug support: add capability to print testbench-specific timeout reports
+ done by setting RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR to "on"
+ this is by default activated inside the testbench
+- mmgrok: fix potential segfault
+ The modules used strtok(), which is not thread-safe. So it will potentially
+ segfault when multiple instances are spawned (what e.g. happens on busy
+ systems).
+ This patch replaces strtok() with its thread-safe counterpart
+ strtok_r().
+ see also https://github.com/rsyslog/rsyslog/issues/1359
+- imrelp bugfix: maxDataSize could be set lower than maxMessageSize
+ maxDataSize specifies the length which will still be accepted
+ It previously could be set to any value, including values lower than the
+ configured rsyslog max message size, which makes no sense. Now this is
+ checked an error message is emitted if the size is set too low.
+- build system bugfix: build broken if liblogging-stdlog installed in custom path
+ Thanks to Dirk Hörner for the patch.
+- core bugfix: segfault on queue shutdown
+ if a ruleset queue is in direct mode, a segfault can occur during
+ rsyslog shutdown. The root cause is that a direct queue does not
+ have an associated worker thread pool, but the ruleset destructor
+ does not anticipate that and tries to destruct the worker thread
+ pool. It needs to do this itself, as otherwise we get a race
+ between rulesets on shutdown.
+ This was a regression from
+ https://github.com/rsyslog/rsyslog/commit/3fbd901b3e6300010
+ closes https://github.com/rsyslog/rsyslog/issues/2480
+- imfile bugfix: statefiles contain invalid JSON
+ When imfile rewrites state files, it does not truncate previous
+ content. If the new content is smaller than the existing one, the
+ existing part will not be overwritten, resulting in invalid json.
+ That in turn can lead to some other failures.
+ closes https://github.com/rsyslog/rsyslog/issues/2662
+- omfile bugfix: segfault if empty filename was given
+ closes https://github.com/rsyslog/rsyslog/issues/2417
+- fix build issues when atomic operations are not present
+ for details, see https://github.com/rsyslog/rsyslog/pull/2604
+- lmsig_ksils12 bugfix: build and static analyzer issues
+ The module had a couple of problems building as well as some potential
+ errors detected by clang static analyzer. These have been fixed.
+ Thanks to Allan Park for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/2517
+- impstats bugfix: segfault if bound to non-existing ruleset
+ segfault happens during shutdown; up until unload of impstats,
+ rsyslog works correctly, except that no pstats are emitted. This
+ can be considered to be expected, because the error message
+ indicates the default ruleset is used instead. This is what
+ now actually happens.
+ closes https://github.com/rsyslog/rsyslog/issues/2645
+- mmjsonparse bugfix: invalid container name was not detected
+ in debug builds, this will trigger an assertion. In production
+ builds, an rsyslog internal error is logged, but rsyslog
+ continues to run.
+ closes https://github.com/rsyslog/rsyslog/issues/2584
+- mmkubernetes bugfixes: fix lnrules, add defaults, add test
+ - Fix lnrules for CONTAINER_NAME
+ - Add pkg check for lognorm >= 2.0.3 so we can set the macro
+ to enable ln_loadSamplesFromString
+ - Add some reasonable default values for parameters, such as
+ kubernetesurl https://kubernetes.default.svc.cluster.local:443
+ - Clean up sample.conf configuration file
+ Thanks to Richard Megginson for the patch set.
+- build system bugfix: --enable-atomic-operations did not work
+ closes https://github.com/rsyslog/rsyslog/pull/2604
+- bugfix: rsyslog aborts on startup when specific config errors are made
+ The following errors must be made in rsyslog.conf:
+ * no action present
+ * a call statement is used on an undefined ruleset
+ In this case, rsyslog emits an error message on the missing actions and
+ then segfaults. Depending on memory layout, it may also continue to run
+ but do nothing except accepting messages as no action is configured.
+ This patch make rsyslog properly terminate after the error message. It
+ is a change in behavior, but there really is no reason why a defunct
+ instance should be kept running.
+ closes https://github.com/rsyslog/rsyslog/issues/2399
+- build system: remove no longer needed --enable-libcurl configure switch
+ The --enable-libcurl switch was added to be able to disable libcurl
+ functionality inside the rsyslog core, see 46f4f43. As libcurl is no
+ longer used inside the core (due to introducing function modules),
+ --enable-libcurl needs to be removed.
+ closes https://github.com/rsyslog/rsyslog/issues/2628
+- QA/CI
+ * fixed races in some tests; root cause was that default enq timeout was too
+ low - we may also see in the future that other tests also need adjustment
+ (note that this is not a code problem but rather slow CI environments,
+ so increasing the timeout to get to a stable test state is the absolutely
+ correct thing to do)
+ * enabled some additional useful compiler warnings
+ * new test for diskqueue hitting configured disk space limit
+ * new tests for omfile
+ * added tests for mmkubernetes
+ * added tests for some script functions that were missing them
+ * made far more test compatible with FreeBSD, so that we now have fuller
+ coverage there
+------------------------------------------------------------------------------
+Version 8.34.0 [v8-stable] 2018-04-03
+- mmkubernetes: new module
+ Thanks to Richard Megginson and Peter Portante for contributing the module.
+- rsyslog script: introduce loadable function modules
+ rsyslog scripting can now also be extended via loadable modules - they
+ provides functions (just like loadable input, output, ... modules)
+ see also http://jan.gerhards.net/2018/03/loadable-rainerscript-functions.html
+- imfile: large refactoring of complete module
+ This commit greatly refactors imfile internal workings. It changes the
+ handling of inotify, FEN, and polling modes. Mostly unchanged is the
+ processing of the way a file is read and state files are kept.
+ This is about a 50% rewrite of the module.
+ Polling, inotify, and FEN modes now use greatly unified code. Some
+ differences still exists and may be changed with further commits. The
+ internal handling of wildcards and file detection has been completely
+ re-written from scratch. For example, previously when multi-level
+ wildcards were used these were not reliably detected. The code also
+ now provides much of the same functionality in all modes, most importantly
+ wildcards are now also supported in polling mode.
+ The refactoring sets ground for further enhancements and smaller
+ refactorings. This commit provides the same feature set that imfile
+ had previously and all existing CI tests pass, as do some newly
+ created tests.
+ Some specific changes:
+ - bugfix: module parameter "sortfiles" ignored
+ This parameter only works in Solaris FEN mode, but is otherwise
+ ignored. Most importantly it is ignored under Linux.
+ fixes https://github.com/rsyslog/rsyslog/issues/2528
+ - bugfix: imfile did not pick up all files when not present
+ at startup
+ fixes https://github.com/rsyslog/rsyslog/issues/2241
+ fixes https://github.com/rsyslog/rsyslog/issues/2230
+ fixes https://github.com/rsyslog/rsyslog/issues/2354
+ fixes https://github.com/rsyslog/rsyslog/issues/1716
+ - bugfix: directories only support "*" wildcard, no others
+ fixes https://github.com/rsyslog/rsyslog/issues/2303
+ - bugfix: parameter "sortfiles" did only work in FEN mode
+ fixes https://github.com/rsyslog/rsyslog/issues/2528
+ - provides the ability to dynamically add and remove files via
+ multi-level wildcards
+ see also https://github.com/rsyslog/rsyslog/issues/1280
+ - the state file name currently has been changed to inode number
+ This will further be worked on in upcoming PRs
+ see also https://github.com/rsyslog/rsyslog/issues/2231
+ - some enhancements were also done to CI tests, most importantly
+ they were made more compatible with BSD
+ Note that most of the mentioned bug fixes cannot be applied to older
+ versions, as they fix design issues which are solved by the refactoring.
+ Thus there are not separate commits for them.
+ There are probably also a number of different issues fixed, which have
+ not yet been full confirmed. Especially anyone having troubles with imfile
+ and wildcards will benefit from the refactoring.
+ closes https://github.com/rsyslog/rsyslog/issues/2359
+- omelasticsearch: add support for CA cert, client cert auth
+ This allows omelasticsearch to perform client cert based authentication
+ to Elasticsearch.
+ adds parameters: tls.cacert, tls.mycert, tls.myprivkey
+ Thanks to Richard Megginson for the patch.
+- omfile-hardening: new contributed module for "omfile hardened operations"
+ This extends omfile with features considered useful for hardening. Comes
+ at the expense of performance loss and changed semantics.
+ Thanks to Mikko Kortelainen for contributing this work.
+- stream/bugfix: memory leak on stream open if filename as already generated
+ this can happen if imfile reads a state file. On each open, memory for the
+ file name can be lost.
+ We detected this while working on imfile refactoring, so there is no related
+ bug report. No specific test has been crafted, as the refactored imfile
+ tests catch it (as soon as they are merged).
+- bugfix/omkafka: did not build on platforms without atomic operations
+ Thanks to github user bruce87en for the patch
+- bugfix/core/ratelimiting: SystemLogRateLimitBurst was limited to 65535
+ rsyslog uses unsigned short for configuration setting SystemLogRateLimitBurst.
+ Being just 16 bits, unsigned short cannot hold values bigger than 65535. in a
+ practical setting rsyslog misbehaved with SystemLogRateLimitBurst being bigger
+ than 65535.
+ Thanks to github user KaleviKolttonen for the patch.
+- bugfix imfile: memory leak in readMode 0
+ closes https://github.com/rsyslog/rsyslog/issues/2421
+- bugfix omfile: some error messages had parameters in wrong order
+ which made the message look strange, but still readable
+ Thanks to Hans Rakers for the patch.
+- bugfix omprog: file handle leak
+ There was a fd leak in the feedback feature added in v8.31.0 (github PR #1753).
+ The leak occurred when omprog was used with the confirmMessages=on setting
+ and no output setting. One fd was leaked every time the external program was
+ started.
+ Thanks to Joan Sala for the patch.
+- bugfix imuxsock: data alignment problems
+ gcc did rightly complain that the cred and ts pointers would cause
+ alignment problems, so they were converted to structs and the necessary
+ data was memcpy()'ed to them.
+ the aux[] buffer was also potentially misaligned, so making a union
+ out of it and struct cmsghdr insured it was properly aligned.
+ The problems were especially visible on alpha and ia64 machines.
+ Thanks to Jason Duerstock for the fix.
+- bugfix testbench: some test were accidentally not executed
+ Thanks to Kasumi Hanazuki for the patch.
+- bugfix tcp subsystem: keepalive settings mixed up
+ TCPKeepAliveIntvl and TPCKeepAliveTime were switched. This is now correct and
+ thus causes a CHANGE OF BeHAVIOR of these settings. We applied this change only
+ after careful consideration of the effect. The contributor Alexandre Pierret
+ explained the situation as such:
+ "From my side, I work with thousands of servers centralizing logs to rsyslog
+ servers in tcp. All of them are running RHEL 6 and 7. The default rsyslog settings
+ in RHEL is TCPKeepAlive off. Since there are thousands of connections on the
+ rsyslog servers, I had to turn the TCPKeepAlive on to setup an aggressive policy
+ regarding ghost connections (following firewall tcp-timeout issue). Basically,
+ I set up: intvl=10 - probe=5 - time=2 If intvl and time are switched, it won't
+ break anything. It will just send 5 more empty tcp packets for 10 seconds (5
+ probe x 2 seconds), which is painless (any professional grade 100€ router can
+ send more than 1.000.000 PPS). For 3000 servers, it means 3000 pps for 5
+ seconds (3000 servers x 2 back-and-forth / 2 seconds). Let's take another worst
+ example: intvl=3600 - probe=5 - time=1. It means one keepalive every hour and
+ a 5 retry every 1s after a network issue. If the time and intvl values are
+ switched, it will generate 1 keepalive every seconds, It's a LOT more, but
+ after 5 probe or packet, it will stop. To summarize, I think it won't
+ break anything:
+ * Keepalive is off by default is many linux distribution
+ * When we enable it, it's to set up an aggressive policy. And setting up a
+ 10-5-1, 60-5-2, 2-5-60 or 1-20-1 policy is almost the same.
+ Bonus: For people setting up their rsyslog from the documentation, it will
+ now work as expected."
+ This was convincing, and we actually think that the fast majority of users set
+ up keepalive based on the doc and did never verify it actually worked as
+ expected. So we think that in all those cases, rsyslog will finally work as
+ intended. So we consider it justified to "change the behavior" here.
+ full discussion in PR: https://github.com/rsyslog/rsyslog/pull/2367
+ Thanks to Alexandre Pierret for analyzing the situation and providing the
+ patch.
+- fix some cosmetic issues found by lgtm.com static code analyzer
+ e.g. header file guard not correctly set - if you really are interested in
+ details, check git log
+- CI
+ * add build test without atomic operations - now catches missing mutex macros
+ * add lgtm.com static analyzer (automatically called via GitHub PR)
+ * improved stability of global-umask.sh test, which unnecessarily used
+ wildcards for test output file checking.
+ Thanks to Kasumi Hanazuki for the patch.
+ * added some test for omprog with transactional interface
+ Thanks to Joan Sala for the new tests.
+ * fixed some omjournal tests which did not properly check result
+------------------------------------------------------------------------------
+Version 8.33.1 [v8-stable] 2018-03-06
+- 8.33.0 tarball release was actually pre-8.33.0
+ ... and so did not contain all features. This alone made a re-release
+ necessary, which is what now happens with 8.33.1.
+ Note: the git 8.33.0 label was correctly applied, "just" the tarball
+ was wrong.
+- devcontainer: use some more sensible defaults
+ and add ability to specify generic docker run options
+ this makes integration into CI (and other scripting) easier
+- fix problems with make dist
+ make dist did not package everything that was needed for CI, thus
+ resulting in make check failures if build from tarball.
+ Thanks to Thomas D. (whissi), and Michael Biebl for alerting us on the
+ problem, providing advise and some of the patches. We also added addt'l
+ patches ourselves. The problem occurred as the CI check for tarball
+ completeness was more or less disabled a couple of weeks ago, which
+ unfortunately went unnoticed. We have also applied some more safeguards
+ to detect such problems in the future.
+------------------------------------------------------------------------------
+Version 8.33.0 [v8-stable] 2018-02-20
+- auto-detect if running inside a container (as pid 1)
+ adjust defaults in this case to be more container-friendly
+- config: add include() script object
+ This permits to include files (like legacy $IncludeConfig) via a
+ script object. Needless to say, the script object offers more
+ features:
+ - include files can now be
+ - required, with rsyslog aborting when not present
+ - required, with rsyslog emitting an error message but otherwise
+ continuing when not present
+ - optional, which means non-present include files will be
+ skipped without notice
+ This is controlled by the "mode" parameter.
+ - text can be included form e.g. an environment variable
+ --> ex: include(text=`echo $ENVVAR`)
+ This finally really obsoletes $IncludeConfig.
+ closes https://github.com/rsyslog/rsyslog/issues/2151
+- template: add option to generate json "container"
+ This enables easy JSON generation via template.
+ This commit also corrects an issue with the constant "jsonf"
+ format. That was recently added, and the implementation problem
+ only became visible when used inside a larger json object. No
+ officially released code is affected, thought - so it really
+ is just a side-note.
+ closes https://github.com/rsyslog/rsyslog/issues/2347
+- core/template: add format jsonf to constant template entries
+ closes https://github.com/rsyslog/rsyslog/issues/2348
+- config: add ability to disable config parameter ("config.enabled")
+ For auto-generated configs, it is useful to have the ability to disable some
+ config constructs even though they may be specified inside the config. This
+ can now be done via the ```config.enabled``` parameter, applicable to all
+ script objects. If set to ```on``` or not specified, the construct will be
+ used, if set to any other value, it will be ignored. This can be used
+ together with the backtick functionality to configure enable and disable
+ from either a file or environment variable.
+ closes https://github.com/rsyslog/rsyslog/issues/2431
+- script: permit to use environment variables during configuration
+ new constant string type "backticks", inspired by sh
+ (sample: `echo $VARNAME`).
+- new global config parameter "shutdown.enable.ctlc"
+ permits to shutdown rsyslog via ctl-c; useful e.g. in containers
+- config optimizer: detect totally empty "if" statements and optimize
+ them out
+- template: constant entry can now also be formatted as json field
+ This enhancements permits to craft clean templates that generate JSON,
+ e.g. for ElasticSearch consumption (or any other REST API)
+- omstdout: support for new-style configuration parameters added
+- core: set TZ on startup if not already set
+ In theory, TZ should be set by the OS. Unfortunately, this seems
+ to be not the case any longer on many Linux distros. We now check
+ it and set it appropriate if not already given.
+ Thanks to github user JPvRiel for providing an excellent explanation
+ of the reasoning for this and how to work around it.
+ closes https://github.com/rsyslog/rsyslog/issues/2054
+- imjournal bugfix: file handle leak during journal rotation
+ Thanks to Peter Portante for the patch
+ see also: https://github.com/rsyslog/rsyslog/pull/2437
+- lmsig_ksils12 bugfix: dirOwner and dirGroup config was not respected
+- script bugfix: replace() function worked incorrectly in some cases
+ If the end of the message was similar to the replacement string, parts
+ of the string could (not always) be missing.
+ Thanks to Yaroslav Bo for the patch.
+- build system bugfix: --disable-libcurl did not work
+ Thanks to Dan Molik, Thomas D. (whissi), and Michael Biebl for the patches.
+- fixed build issues on Alpine Linux
+- core bugfix: misaddressing in external command parser
+ This parser is used whenever a module (e.g. omprog) needs to process
+ command lines. If command parameters were given, memory misaddressing
+ occurred. This could lead to a segfault.
+ This is a regression in 8.32.0.
+ closes https://github.com/rsyslog/rsyslog/issues/2408
+- core bugfix: small memory leak in external command parser
+ This parser is used whenever a module (e.g. omprog) needs to process
+ command lines. On each action definitions for actions that use the
+ parser a small amount of memory was leaked. It is an uncritical leak
+ as it only occurs during config parsing. So it leaks a couple of
+ KiB during startup but does not grow during actual message processing.
+ This is a regression in 8.32.0.
+- core bugfix: string not properly terminated when RFC5424 MSGID is used
+ This could lead to misaddressing when the jsonmesg property was used.
+ closes https://github.com/rsyslog/rsyslog/issues/2396
+- bugfix: strndup() compatibility layer func copies too much
+ The function did not obey the upper limit, effectively becoming
+ a strdup(). This was only noticed when the compatibility layer
+ was required, most importantly on Solaris 10.
+- CI system
+ - we now use well-defined containers for parts of the CI runs
+ - now also build test under Alpine Linux
+ - test added for omprog feedback feature
+------------------------------------------------------------------------------
+Version 8.32.0 [v8-stable] 2018-01-09
+- NEW BUILD REQUIREMENTs:
+ * libfastjson 0.99.8 is now required; older versions lead to bugs in rsyslog
+ * libczmq >= 3.0.2 is now required for omczmq
+ This was actually required for quite some while, but not properly checked
+ during configure run. If the lib was older, build failed. Now configure
+ detects this and emits the appropriate error message.
+ * libcurl is now needed for rsyslog core
+ due to new script function http_request(). This can be turned off by the
+ new configure option --disable-libcurl. If so, http_request() is not
+ available.
+- rsyslogd: add capability to specify that no pid file shall be written
+ Command line option -iNONE provides this capability. This utilizes the
+ pre-existing -i option, but uses the special name "NONE" to turn of the
+ pid file check feature. Turning off is useful for systems where this no
+ longer is needed (e.g. systemd based).
+ closes https://github.com/rsyslog/rsyslog/issues/2143
+- ompgsql: considerable enhancements
+ The PostgreSQL output module was woefully out-of-date the following
+ list is changes made to update the module to current Rsyslog standards.
+ * allow for v6 configuration syntax
+ * configurable ports
+ * support transactional interface
+ * push db connection into workers (libpq is threadsafe)
+ * enable module testing on travis
+ * ensure configuration syntax backwards compatibility
+ * formatting around postgres core templating
+ * use new test conventions
+ * add new configuration syntax test
+ * add valgrind tests for new and old syntax
+ * add threading tests
+ * add action queue long running tests
+ * add action queue valgrind test
+ Thanks to Dan Molik for contributing this great enhancement!
+- build system: removed --enable-rtinst configure option
+ This was a historic debugging option which has been superseded by
+ newer tools like valgrind, helgrind, ASAN, TSAN, etc...
+- pmrfc3164: support for headerless messages
+ pmrfc3164 now detects if the first non-SP, non-HT character is either
+ '{' or '[' and if so assume that no header (TAG, HOSTNAME, DATE) is
+ given. If so, it uses defaults for these values. The full message is
+ used as the MSG part in that case. Note that an initial PRI may still
+ be specified.
+ This follows the trend to send JSON messages via syslog without any
+ header. We use default header values in this case.
+ This right now is a bit experimental; we may roll it back if
+ problems show up in practice.
+ closes https://github.com/rsyslog/rsyslog/issues/2030
+- omhiredis: add option to use RPUSH instead of LPUSH
+ see also https://github.com/rsyslog/rsyslog/issues/1625
+- mmexternal improvements
+ * better error reporting if to-be-executed script cannot be executed
+ * some general cleanup
+ * better redirection of stdin/out/err for the executed script
+ * bugfix: argv[0] of the script was missing if command line parameters
+ were not specified
+- omprog: refactored, code shared with mmexternal moved to common object
+- logctl tool: refactor to support newer rsyslog standards
+ * Made the logctl usertool ISO C90 compliant.
+ * Made the logctl usertool use a homogeneous coding style.
+ Thanks to Hugo Soszynski for contributing this work (as well as
+ suggesting some workarounds related to libmongoc/libbson).
+- imfile: added support for Solaris File Event notification (FEN)
+ also improves performance under Solaris, with FEN imfile provides
+ features equivalent to inotify mode
+- core/action: new parameter "action.errorfile"
+ permits to write failed messages to an "error file" so that they
+ can be reviewed and potentially be reprocessed
+- imfile: added new module parameter "sortFiles"
+ This permits to process newly created files in sorted order.
+- imuxsock: improved status reporting: socket name received from systemd
+ Providing an indication of what we got from systemd facilitates problem
+ analysis.
+- build system: added new testbench configure switches
+ now --enable-testbench1 and --enable-testbench2 exists which permit
+ to enable/disable parts of the testbench. By default, both are on
+ when --enable-testbench is given. For full testbench coverage, both
+ options must be given. These options are necessary because under
+ Travis we hit the max runtime for tests and needed to split tests
+ over multiple incarnations.
+- mmpstrucdata: new parameter "sd_name.lowercase"
+ to permit preserving case for structured data identifiers
+ Special thanks to github user alanrobson for the initial commit that
+ preserves case (on which we based other work).
+- omfile: add module-global option "dynafile.donotsuspend"
+ this permits to enable SUSPENDing dynafile actions. Traditionally,
+ SUSPEND mode was never entered for dynafiles as it would have blocked
+ overall processing flow. Default is not to suspend (and thus block).
+ closes https://github.com/rsyslog/rsyslog/issues/2236
+- testbench: add a capability to turn off libfaketime tests via configure
+ Unfortunately, libfaketime becomes more and more problematic in newer
+ versions and causes aborts on some platforms. This provides the ability
+ to turn it off via --disable-libfaketime.
+ In the longer term, we should consider writing our own replacement.
+- testbench: name valgrind tests consistently
+ all valgrind tests now end in -vg.sh
+- RainerScript: add function parse_json()
+- RainerScript: add function substring()
+- RainerScript: add function http_request()
+- RainerScript: add function previous_is_suspended()
+ This function returns a boolean indicating if the previous action is
+ suspended (0 - no, 1 - yes). This is useful if arbitrary processing
+ (other than calling actions) should be made depending on that state.
+ A prime example for this is probably calling a ruleset.
+ closes https://github.com/rsyslog/rsyslog/issues/1939
+- Patches from BSD projects have been imported
+ ... as far as they still apply. Some patches that patched BSD-specific
+ code were broadened to be more generic.
+- script bugfix: invalid function names were silently ignored
+ no error message was produced
+ thanks to Matt Ezell for providing the patch.
+- rainerscript: add int2hex() function
+- rainerscript: add is_time() function
+ Thanks to Stephen Workman for implementing this.
+- RainerScript: add function script_error() and error-reporting support
+ This permits script functions that could fail to report errors back, so
+ that the user can handle them if desired. We use an errno-style of
+ interface. That means script_error() needs to be called after functions
+ that supports it. It will return either 0 (all OK) or something else
+ (an error condition).
+ The commit also modifies the parse_time() function to use the new
+ interface. First of all, this is useful for users, and secondly we
+ needed a capability to craft a testbench test.
+ closes https://github.com/rsyslog/rsyslog/issues/1978
+- testbench: fixed build problem of testbench tools under Alpine Linux
+- added --enable-libsystemd configure option to enforce use of libsystemd
+ so we can fail the build on platforms where this is required
+- core/glbl: remove long-unused option $optimizeforuniprocessor
+ This was still available, but had no effect (for ~10 years or so). The
+ plumbing is now removed. If someone tries to use the option, an
+ error message is generated.
+ closes https://github.com/rsyslog/rsyslog/issues/2280
+- core/queue: emit better status messages at rsyslog shutdown
+ this helps to diagnose issue - unfortunately we need more work to ensure
+ that the messages always make it to the user. This is a start and
+ hopefully useful at least for the testbench, possibly more.
+- fixed a couple of build issues with gcc-7 (in less frequently used modules)
+- fixed a couple of build issues on the arm platform (actually raspbian)
+- impstats: fix invalid counter definitions for getrusage() reporting
+ some of the counters were defined as int (32 bit) vs. intctr_t (64 bit).
+ On some platforms "long" seems to be 64bit, and getrusage() provides
+ what we store as int via long. So this caused truncation and/or overflow.
+ This had undefined effects. Most often, everything worked fine
+ for values smaller than 2^31 but sometimes we got negative values.
+ closes https://github.com/rsyslog/rsyslog/issues/1517
+- imudp bugfix: potential segfault in ratelimiting
+ The rate-limiter inside imudp was not set to be thread safe, but was
+ used across multiple threads. This worked in default configuration,
+ but failed when RepeatedMsgReduction was set to "on".
+ Note that it in general is a bug to use a rate-limiter in
+ non-threadsafe mode across multiple threads. This also causes invalid
+ rate limiting counts in the default case.
+ closes https://github.com/rsyslog/rsyslog/issues/441
+ fixes https://github.com/rsyslog/rsyslog/issues/2132
+- imptcp bugfix: access to free'ed memory
+ When notifyconnectionclose was on, a string buffer was accessed immediately
+ after it was freed (as part of the connection close operation).
+ Detected by LLVM ASAN.
+- mmanon bugfix: fix wrong ipv6 embedded recognition
+ mmanon recognized IPv6 with embedded IPv4 that have too few (16 bit) fields.
+ example: 13:abd:45:0.0.0.0
+ closes https://github.com/rsyslog/rsyslog/issues/2357
+- imfile bugfix: not detecting files in directory when wildcards are used.
+ When directories and files are created at the same time,
+ imfile may missed subdirs or file if the machine is on high load.
+ The handling has been enhanced to scan newly created directories ALWAYS for
+ matching files.
+ fixes https://github.com/rsyslog/rsyslog/issues/2271
+ However there still exist problems with multilevel directory configurations.
+ Details are discussed in https://github.com/rsyslog/rsyslog/issues/2354
+ Fixes for the remaining issues are expected for 8.33.0.
+- script bugfix: improper string-to-number conversion for negative numbers
+- core/action bugfix: 100% CPU utilization on suspension of output module
+ Triggering condition:
+ * output module using the legacy transaction interface
+ (e.g. omelasticsearch, omlibdbi)
+ * output module needs to suspend itself
+ In these cases, rsyslog enters a busy loop trying to resolve the
+ suspend condition. The bug is rooted in rsyslog core action code.
+ This patch fixes it by inserting a 1-second sleep during calls
+ to the resume handler.
+ Note: we cannot sleep exactly as long as tryResume needs. This
+ would require larger refactoring, which probably is not worth for
+ the legacy interface. The current solution is almost as good, as
+ the one second sleep has very little overhead on a real system.
+ Thus we have chosen that approach.
+ This patch now also ensures that failed messages are properly
+ handled and do not cause eternal hang.
+ closes https://github.com/rsyslog/rsyslog/issues/2113
+- core/variables bugfix: bare $! cannot be used in set statement
+ fixes https://github.com/rsyslog/rsyslog/issues/326
+- core bugfix: auto commit of actions improperly handled
+ The internal state variable bHadAutoCommit was handled in thread-unsafe way
+ and most probably caused (hard to see) issues when action instances were
+ run on multiple worker threads. It looks like the state variable was
+ forgotten to move over to worker state when action workers were introduced.
+ closes https://github.com/rsyslog/rsyslog/issues/2046
+- core bugfix: filename length limitation of 199 bytes
+ file names (including path names) longer than 199 bytes could not be
+ handled at many places. This has now been uplifted to 4KiB after careful
+ review for the largest size supported among all relevant platforms.
+- core bugfix: undefined behavior due to integer overflow
+ when searching strings, we may have an (unsigned) integer overflow
+ which can lead to misaddressing.
+ Detected by clang ubsan.
+- core bugfix: race on LocalHostIP property during startup
+ The way the default was set could lead to a race if e.g. two internal
+ messages were emitted at startup when the property was not yet set. This
+ has been seen to happen in practice. It had no bad effect except a very
+ small stationary memory leak, but made using thread analyzers unreliable
+ (as it was rightfully detected as a problem).
+ closes https://github.com/rsyslog/rsyslog/issues/2012
+- bugfix: potential segfault on startup
+ timezone info table was "sorted" even though it may be NULL. There is
+ no practical case known where this lead to an actual abort, but in
+ theory it would be possible. If so, it would happen immediately on
+ startup.
+ Detected by clang ubsan.
+- omhiredis bugfix: rsyslog segfault on startup if no template is specified
+- omprog bugfix: argv[0] not set when using binary without arguments
+ When using the omprog plugin with a binary without arguments, argv[0] (the
+ name of the binary) is not set, causing binaries that depend on this value
+ being set to crash or misbehave.
+ This patch also mildly refactors omprog argv[] creations, albeit some more
+ refactoring would be useful.
+ closes https://github.com/rsyslog/rsyslog/issues/1858
+- core: refactoring of rsyslog's cstr "class"
+ Function cstrGetSzStrNoNULL shall modified the string buffer on each call,
+ albeit it is considered a "read-only" function. It currently adds a '\0'
+ at the end. This is bad, especially when multiple threads access the same
+ string. As always the same data is written, it was not causing real issues
+ (except unnecessary cache writes), but it polluted the thread debugger and
+ as such prevent more elaborate automated tests.
+- parent directory creation function refactored
+ This should not cause any change of behavior, but is worth noting in case
+ we see a regression not caught by the CI system.
+- mmsnmptrapd bugfix: potential misaddressing
+ This only occurred in situations when the system was totally out of memory.
+- imkafka: fix potential small resource leak
+ If rdkafka handle cannot fully populated, cleanup is added. Previously, we
+ could leak a handle if e.g. no brokers were available. Note that this was
+ a cosmetic leak, as proper processing is not possible in any case and the
+ leak is once per listener, so not growing. But we now also ensure that
+ proper error reporting and handling is done in any case. Previously, we
+ may have some misleading error messages if the defunct kafka handle was
+ used.
+ closes https://github.com/rsyslog/rsyslog/issues/2084
+- imkafka bugfix: do not emit error message on regular state
+ This was misunderstood as an error state and could spam the system
+ log considerably. Regression from 8.31.0.
+- omkafka: expose operational status to user where useful
+ omkafka emits many useful operational status messages only to the debug
+ log. After careful review, we have exposed many of these as user error
+ and warning message (ex: librdkafka queue full, so user knows why we
+ suspend the plugin temporarily). This may have made the module too
+ chatty. If so, one can always filter out messages via configuration. And
+ if we really went overboard, we can undo those parts with the next
+ release. So it's better to give a bit more than less, as this definitely
+ eases troubleshooting for users.
+ closes https://github.com/rsyslog/rsyslog/pull/2334
+- omkafka bugfix: potential message duplication
+ If a message that already failed in librdkafka was resubmitted and that
+ resubmit also failed, it got duplicated.
+- omkafka: fix multithreading
+ omkafka has several issue if multiple worker instances are used. This commit
+ actually make the module use a single worker thread at max. Reasoning:
+ Librdkafka creates background threads itself. So omkafka basically needs to move
+ memory buffers over to librdkafka, which then does the heavy hauling. As such, we
+ think that it is best to run max one wrkr instance of omkafka -- otherwise we just
+ get additional locking (contention) overhead without any real gain. As such,
+ we use a global mutex for doAction which ensures only one worker can be active
+ at any given time. That mutex is also used to guard utility functions (like
+ tryResume) which may also be accessed by multiple workers in parallel.
+ Note: shall this method be changed, the kafka connection/suspension handling needs
+ to be refactored. The current code assumes that all workers share state information
+ including librdkafka handles.
+ closes https://github.com/rsyslog/rsyslog/issues/2313
+- omkafka bugfix: potential misaddressing
+ The failed message list is improperly cleaned. This is a regression
+ from recent commit 4eae19e089b5a83da679fe29398c6b2c10003793, which
+ was introduced in 8.31.0.
+ This problem is more likely to happen under heavy load or bad
+ connectivity, when the local librdkafka queue overruns or message
+ delivery times out.
+ closes https://github.com/rsyslog/rsyslog/issues/2184
+ closes https://github.com/rsyslog/rsyslog/issues/2067
+- omkafka bugfix: build fails with older versions of librdkafka
+ closes https://github.com/rsyslog/rsyslog/issues/2168
+- omgssapi bugfix: fix compiler warnings with gcc-7
+ closes https://github.com/rsyslog/rsyslog/issues/2097
+- dnscache bugfix: entries were cached based on IP AND port number
+ That hash key which is used to find out already cached dns entry gets
+ incorrectly computed from the whole sockaddr_storage
+ (sockaddr_in/sockaddr_in6) structure including a sin_port (which doesn't
+ have a static value) instead of only an address, thus creating redundant
+ dns cache entries/consuming more space. This lead to potentially high memory
+ usage and ineffectiveness of the case. It could be considered a memory leak.
+ Thanks to Martin Osvald for the patch.
+ see also: https://github.com/rsyslog/rsyslog/pull/2160
+- omkafka bugfix: fixed memory leak
+ a memory leak occurred when librdkafka communicated error/status information
+ to omkafka. this seems to happen relatively frequently, so this leak
+ could be pretty problematic.
+- mmdblookup bugfix: replace thread-unsafe strtok() by thread-safe counterpart
+ Many thanks to Will Storey (github user @horgh) for mentioning this and
+ his phantastic help in debugging this rsyslog problem!
+- pmnormalize bugfix: remove unsave "strcat" implementation
+- rainerscript bugfix: ltrim() and rtrim function misaddressing
+ This could lead to a segfault and was triggered by certain input data
+ schemes. For example, a ltrim(" a") could lead to the fault.
+- imklog bugfix: local host IP was hardcoded to 127.0.0.1
+ This is now taken from the global localHostIP setting, which is used
+ consistent across all modules.
+ Also, the removed (2012?) directive $klogLocalIPIF has been added
+ again but directly marked as removed. That way, an informative error
+ message is generated if someone tries to use it.
+ closes https://github.com/rsyslog/rsyslog/issues/2276
+- cleanup: remove obsolete pre-KSI GuardTime signature interface
+ this is no longer functional starting Jan 2018 as it reached end of life
+ closes https://github.com/rsyslog/rsyslog/issues/2128
+- cleanup: obsolete definition SOL_TCP replaced by newer IPPROTO_TCP
+ this should not have any effect at all except better portability, but is
+ worth mentioning in the ChangeLog nevertheless.
+- lookup tables: fixed undefined behavior detected by UBSan
+- CI testing
+ - ARM (via Raspberry PI) added to CI system
+ - Debian 9 added to CI system
+ - omgssapi and usertools components are now also tested in Travis
+ - test coverage on BSD has been enhanced
+------------------------------------------------------------------------------
+Version 8.31.0 [v8-stable] 2017-11-28
+- NEW BUILD DEPENDENCY: ommongodb now requires libmongo-c
+ instead of deprecated libmongo-client.
+- remove systemd embedded code, use libsystemd instead
+ Since the early days rsyslog used the original systemd embedded
+ interface code. This version now uses libsystemd where available.
+ If we do not find libsystemd, we assume the system does not use
+ systemd, which is a safe assumption nowadays. This ensures we use the
+ fresh interface code and also removes bloat from our project.
+ closes https://github.com/rsyslog/rsyslog/issues/1933
+- mmanon: add support for IPv6 addresses with embedded IPv4 address
+ While this format is uncommon, it may still be present in logs and as
+ such should be supported. It is configurable via individual settings,
+ though. Especially the number of bits to anonymize may be desired to
+ be different than in pure IPv6.
+- ommongodb: big refactoring, more or less a feature-enhanced rewrite
+ New features are :
+ * Handle TLS connection to mongodb
+ * Handle MongoDB Replicasets
+ * Added the 'ssl_ca' and 'ssl_cert' directives to configure tls connection
+ * Added 'uristr' directive to configure the connection uri in the form
+ of 'mongodb://...'
+ Now uses the official mongo-c-driver library instead of the deprecated
+ mongo-client library
+ Special thanks to Hugo Soszynski and Jérémie Jourdin for there hard work
+ to make this a reality!
+ See also: https://github.com/rsyslog/rsyslog/pull/1917
+- rainerscript: add parse_time() function
+ Thanks to Stephen Workman for implementing this.
+- omelasticsearch: add LF to every elastic response for error file
+ error file content was written without LF after each message, making
+ it hard to work with and monitor.
+ Thanks to Yaroslav Bo for the patch.
+- omelasticsearch: add pipeline support
+ supports static and dynamic ElasticSearch pipeline parameter.
+ closes https://github.com/rsyslog/rsyslog/issues/1411
+ Thanks to github users scibi and WaeCo for the implementation.
+- lmsig_ksi_ls12: support asynchronous mode of libksi
+- omprog: added error handling and transaction support for external plugins
+ This permits much better integration of external output modules.
+ Special thanks to Joan Sala for providing this work!
+- imzmq3/omzmq3: marked as deprecated, modules will be remove in v8.41
+ see also: https://github.com/rsyslog/rsyslog/issues/2100
+- imzmq3/omzmq3: fixed build issues with gcc-7
+- core: emit error message on abnormal input thread termination
+ This indicates a serious issue of which the user should be notified.
+ Was not done so far and caused grief when troubleshooting issues.
+- core: refactored locking for json variable access
+ refactored the method so that it consistent in all functions and easier
+ to follow. Most importantly, now an as simple as possible locking paradigm
+ of lock ... unlock within the function. Hopefully easier to understand
+ both for humans and static code analyzers.
+- core: refactored creation of UDP sockets
+ was very old, hard to follow code; streamlined that a bit
+- core/dnscache: refactor locking
+ keep a simple lock ... unlock scheme within the function. That is
+ easier to follow for both humans as well as static analyzers.
+ Also removes Coverity scan CID 185419
+- rainerscript: use crypto-grade random number generator for random() function
+ We now use /dev/urandom if available. If not, we fall back to the weak PRNG.
+- imkafka: improve error reporting and cleanup refactoring
+- imkafka bugfix: segfault if "broker" parameter is not specified
+ Now emits warning message instead and uses hardcoded default
+ (which usually matches where the kafka broker can be found).
+ fixes https://github.com/rsyslog/rsyslog/issues/2085
+- omkafka: improve error reporting
+- omkafka: slight speedup do to refactoring of LIST class
+ double-linked list was used for temporarily undeliverable message tracking
+ where singly-linked list was sufficient. Changed that.
+- TCP syslog: support SNI when connecting as a client
+ This is done if a hostname is configured and turned off if an IP is used.
+ Thanks to Art O Cathain for the patch.
+ see also https://github.com/rsyslog/rsyslog/pull/1393
+- msg variable bugfix: potential segfault on variable access
+ A segfault is likely to happen if during processing a variable with
+ more than one path component is accessed (e.g. $!path!var) and NO
+ variables oft hat kind (local, message, global) are defined at all.
+ closes https://github.com/rsyslog/rsyslog/issues/1920
+- ratelimiting bugfix: data race in Linux-like ratelimiter
+ access to the Linux-like ratelimiter was not properly synchronized, and
+ the system rate-limiter was not using it in any case.
+ This could lead to the rate-limit settings not being properly
+ respected, but no "hard error".
+- core/template bugfix: potential NULL pointer access at config load
+ could happen if the config was loaded and the parameters could not properly
+ be processed. If so, this occurred only during the startup phase.
+ Detected by Coverity scan, CID 185318
+- core/json var subsystem bugfix: segfault in MsgSetPropsViaJSON
+ Invalid libfastjson API use lead to double-free. This was most importantly
+ triggered by mmexternal (but could potentially be triggered by other
+ uses as well)
+ closes https://github.com/rsyslog/rsyslog/issues/1822
+- core/wrkr threads bugfix: race condition
+ During e.g. shutdown it could happen that a worker thread was started
+ and immediately be requested to terminate. In such situations there was
+ a race the prevented proper initialization. This could lead to follow-on
+ problems.
+ We believe (but could not proof) that this also could lead to a hang of
+ the termination process. Thus we claim to close an issue tracker down
+ here below, but are not 100% certain it really closes it (we hope for
+ user feedback on this). In any case, the thread debugger showed invalid
+ operations and this has been fixed, so it is useful in any case.
+ closes https://github.com/rsyslog/rsyslog/issues/1959
+- core/wtp: potential hang during shutdown
+ when the wtp worker is cancelled in the final stage of shutting down
+ while the mutex is locked and there is one worker left, the system
+ will hang. The reason is that the cancelled thread could not free the
+ mutex that the other needs in order to shut down orderly.
+ Detected with clang thread sanitizer.
+- omfwd bugfix: generate error message on connection failure
+- imtcp bugfix: "streamdriver.mode" parameter could not be set to 0
+- imjournal bugfix: module was defunctional
+ The open function was broken by commit 92ac801, resulting in
+ no data being ever read from the journal.
+ patch bases on the idea of Radovan Sroka given here:
+ https://github.com/rsyslog/rsyslog/issues/1895#issuecomment-339017357
+ but follows the current imjournal-paradigm of having the journal
+ handle inside a global variable.
+ see also https://github.com/rsyslog/rsyslog/issues/1895
+ closes https://github.com/rsyslog/rsyslog/issues/1897
+- imjournal: refactor error handling, fix error messages
+ imjournal did not try to recover from errors and used the error state
+ returned by journal functions incorrectly, resulting in misleading
+ error messages. Fixed this and also increased the number of error
+ messages so that it now is easier to diagnose problems with this module.
+ Also a little bit of internal brush-up.
+ -mmdblookup bugfix: fix potential segfault due to threading issues
+ libmaxminddb seems to have issues when running under multiple threads. As
+ a first measure, we prevent mmdblookup now from running on more than one
+ thread concurrently.
+ see also: https://github.com/rsyslog/rsyslog/issues/1885#issuecomment-344882616
+- omelasticsearch bugfix: operational error messages not passed to user
+ This lead to sometimes hard to diagnose problem. Note that for obvious
+ reasons the amount of messages from omelasticsearch has increased; this
+ is not a sign of a problem in itself -- but it may reveal problems that
+ existed before and went unnoticed. Also note that too-verbose messages
+ can be filtered out via regular rsyslog methods (e.g. message discarding
+ based on content).
+- omkafka bugfixes
+ * statistics counter maxoutqsize could not be reset
+ Thanks to github user flisky for the patch.
+ * potential hang condition
+ omkafka did not release a mutex under some error conditions (most
+ notably out of memory on specific alloc calls). This lead to a hang
+ during actively processing messages or during shutdown (at latest).
+ This could happen only if dynamic topics were configured.
+ Detected by Coverity Scan, CID 185781 (originally 185721, detected
+ as a different issue by Coverity after code refactoring done in regard
+ to 185721 -- then the problem became more obvious).
+ * file handle leak, which could occur when local buffering
+ of messages was needed
+ * invalid load of failedmsg file on startup if disabled
+ error "rsyslogd: omkafka: could not load failed messages from "
+ "file (null) error -2027 - failed messages will not be resend."
+ occurs because, despite `keepFailedMessages="off"` as a default,
+ omkafka still tries to check for and load a `(none)` file which
+ triggers an IO error of sorts according to the 2027 link above.
+ Obviously, it probably shouldn't try load the file if
+ `keepFailedMessages` is not enabled.
+ Thanks to github user JPvRiel for a very good error report and
+ analysis.
+ closes https://github.com/rsyslog/rsyslog/issues/1765
+ * various config parameters did not work
+ These were not even recognized when used and lead to a config startup
+ error message:
+ ~ closeTimeout
+ ~ reopenOnHup
+ ~ resubmitOnFailure
+ ~ keepFailedMessages
+ ~ failedMsgFile
+ closes https://github.com/rsyslog/rsyslog/issues/2052
+ * considerable memory leak
+ Whenever a message could (temporarily) not be delivered to kafka,
+ a non-trivial amount of memory was leaked. This could sum up to
+ quite a big memory leak.
+ fixes https://github.com/rsyslog/rsyslog/issues/1991
+ * some small memory leaks fixed
+ most of them cosmetic or a few bytes statically (not growing as
+ omkafka was used) -- thus we do not mention each one explicitly.
+ For more details, see git commit log or this pull request:
+ https://github.com/rsyslog/rsyslog/pull/2051
+- kafka bugfix: problem on invalid kafka configuration values
+ omkafka ended up in an endless loop and high cpu.
+ imkafka tried to subscribe to a not connected kafka server.
+ closes https://github.com/rsyslog/rsyslog/issues/1806
+- [io]mgssapi: fix build problems (regression from 8.30.0)
+- [io]czmq: fix build problems on some platforms (namely gcc 7, clang 5)
+- tcpsrv bugfix: potential hang during shutdown
+- queue bugfix: potential hang during shutdown
+- queue bugfix: NULL pointer dereference during config processing
+ If the queue parameters were incorrectly given, a NULL pointer dereference
+ could happen during config parsing. Once post that stage, no problem could
+ occur.
+ Detected by Coverity scan, CID 185339
+- imczmq bugfix: segfault
+ happened in a call to
+ 371: zcert_destroy(&serverCert) called from rcvData().
+ Thanks to ~achiketa Prachanda for the patch.
+- imfile: some small performance enhancements
+ Thanks to Peter Portante for the patch
+- omfile: handle file open error via SUSPEND mode
+ For a while, an open file error lead to suspension as the error was
+ not detected by the rule engine. This has changed with fixes
+ in 8.30.0. I asked users what they prefer (and expect) and
+ everyone meant it should still be handled via suspension. See
+ github tracker below for more details.
+ closes https://github.com/rsyslog/rsyslog/issues/1832
+- omfile bugfix: race during directory creation can lead to loop
+ There was a race where two threads were competing for directory creation
+ which could lead to none succeeding and a flood of error message like this
+ "error during config processing: omfile: creating parent directories for
+ file". This has been solved.
+ Thanks to Niko Kortström for the patch.
+- imudp: improve error reporting
+ When udp listener cannot be created, an error message containing
+ the ip-address and port is put out.
+ closes https://github.com/rsyslog/rsyslog/issues/1899
+- omrelp bugfix: incorrect error handling
+ if librelp with TLS but without Authentication was included, librelp
+ did not emit the correct error message due to invalid error code
+ check. It also did not err-out but instead suspended itself.
+ Detected by Coverity scan, CID 185362
+- [io]mrelp bugfix: segfault on startup if configured cert not readable
+ When the certificate file specified in the omrelp/imrelp configuration
+ can't be accessed, e.g. because it doesn't exist or you don't have
+ permission to do so, a Segmentation Fault will appear when you start
+ Rsyslog. This commit fixes that problem.
+ closes https://github.com/rsyslog/rsyslog/issues/1869
+- mmanon fix: make build under gcc 7
+ Thanks to William Dauchy for the patch
+- mmpstrucdata bugfix: formatting error of ']' char
+ This was invalidly formatted as '"'. Thanks to github user
+ wu3396 for the error report including the patch idea.
+ closes https://github.com/rsyslog/rsyslog/issues/1826
+- mmexternalb bugfix: memory leak
+- core/stats bugfix: memory leak if sender stats or tracking are enabled
+- core bugfix: potential segfault during startup
+ A NULL pointer could be accessed if there was a problem with the
+ timezone parameters. Affects only startup, once started, no problem
+ existed.
+ Detected by Coverity scan; CID 185414
+- core bugfix: potential race in variable handling
+ Root of variable tree is accessed prior to locking access to it.
+ This introduces a race that may result in various kinds of
+ misaddressing.
+ Found while reviewing code, no bug report exists.
+- core bugfix: potential segfault when shutting down rsyslog
+ when rulesets are nested a segfault can occur when shutting down
+ rsyslog. the reason is that rule sets are destructed in load order,
+ which means a "later" ruleset may still be active when an "earlier"
+ one was already destructed. In these cases, a "call" can invalidly
+ call into the earlier ruleset, which is destructed and so leads to
+ invalid memory access. If a segfault actually happens depends on the
+ OS, but it is highly probable.
+ The cure is to split the queue shutdown sequence. In a first step,
+ all worker threads are terminated and the queue set to enqOnly.
+ While some are terminated, it is still possible that the others
+ enqueue messages into the queue (which are then just placed into the
+ queue, not processed). After this happens, a call can no longer
+ be issued (as there are no more workers). So then we can destruct
+ the rulesets in any order.
+ closes https://github.com/rsyslog/rsyslog/issues/1122
+- core/action bugfix: potential misaddressing when processing hard errors
+ For batches that did fail in an output module, the rsyslog core
+ tries to find offending messages that generate hard (non-recoverable)
+ errors. During this process, the action templates for each message
+ are copied into a temporary buffer. That copy was invalidly sized,
+ actually copying only the first template string. As such, outputs
+ that requested more template strings AND had errors in batch submission
+ received uninitialized pointers. This could lead to all sorts of
+ problems.
+ see also https://github.com/rsyslog/rsyslog/issues/1885
+ closes https://github.com/rsyslog/rsyslog/issues/1906
+- template object bugfix: NULL pointer access on invalid parameters
+ could happen only during startup
+ Detected by Coverity scan, CID 185376
+- omjournal bugfix: NULL pointer access on invalid parameters
+ could happen only during startup
+- omelasticsearch bugfix: configured credentials not used during health check
+ Authentication credentials were not applied during health check,
+ permission to use unsigned CERTS was not applied to regular data post.
+ closes https://github.com/rsyslog/rsyslog/issues/1949
+- omelasticsearch bugfix: abort on unavailable ES server
+ Depending on the state of unavailability (libcurl return code),
+ omelasticsearch tries to process a NULL return message, what
+ leads to a segfault.
+ This fixes the problem and introduces better error handling and
+ better error messages.
+ see also https://github.com/rsyslog/rsyslog/issues/1885
+- omelasticsearch: fix memory leak and potential misaddressing
+ Commit 96b5fce introduced regressions, leading to potential misaddressing
+ and a very probable memory leak. This commit fixes the issues and
+ hardens the module to better detect some error cases in the
+ future.
+ It also adds valgrind-based testbench tests which ensure that no
+ pointer errors exist. If they had been in place, the regressions
+ would never have been undetected.
+ Note that commit 96b5fce was introduced in 8.23.0 on Nov, 15th 2016.
+ Many thanks to Yaroslav Bo for alerting me on the root problem and
+ providing a very good analysis and guidance.
+ see also https://github.com/rsyslog/rsyslog/issues/1906
+ see also https://github.com/rsyslog/rsyslog/issues/1964
+ closes https://github.com/rsyslog/rsyslog/issues/1962
+- omelasticsearch bugfix: output from libcurl to stdout
+ omelasticsearch made libcurl output messages to stdout. This
+ commit fixes that. It also automatically enables libcurl verbose
+ mode during debug runs - it needs to be seen if this is smart or
+ not (previously, code needed to be commented in).
+ closes https://github.com/rsyslog/rsyslog/issues/1909
+- iczmq bugfix: potential memory leak
+- imptcp bugfix: potential misaddressing
+ When during a connection request the remote peer could not be
+ identified, imptcp could misaddress memory if it is configured
+ to emit messages on connection open.
+ Detected by clang 5.0 static analyzer.
+- imptcp: potential buffer overflow
+ if the local hostname or IP is larger than NI_MAXHOST-1, an internal
+ buffer is overflowed. This is irrespective of any input data.
+ Detected by Coverity scan, CID 185390
+- core/nsd_gtls: fix potential uninitialized data access
+ could occur during certificate check
+ found by clang 5.0 static analyzer
+- stats bugfix: potential program hang
+ due to missing unlock. This could only occur if pstats was set to
+ CEE-format logging (very uncommon) AND if the system runs out of
+ memory (in which case other things go pretty bad as well).
+ found by Coverity scan
+- omfwd bugfix: memory leak if network namespaces are used
+ very seldom used feature, occurs only during error case
+ found by Coverity scan.
+- core: potential misaddressing when accessing JSON properties
+ When a JSON property is accessed in template processing, memory may
+ have been misaddressed or a double-free may occur while obtaining the
+ property.
+ This was detected by a Coverity scan.
+- gcry crypto provider bugfixes: potential misaddressing and memory leak
+ If the config parameters were invalid, a misaddressing could occur. If so,
+ this happens only during startup.
+ Also, a memory leak existed when the crypto provider errored out. This could
+ build up if it were used in frequently-changing dynafiles. This was
+ detected by Coverity scan, CID 185360.
+- core/file stream object bugfix: memory leak
+ If a multiline read errored out, a line buffer could be leaked.
+ Detected by Coverity scan, CID 185328
+- imdiag bugfix: double mutex unlock when working with stats
+ Note: while this could potentially lead to a program hang, it affected
+ only testbench execution as imdiag is a testbench-only tool.
+ Detected by Coverity scan, CID 185348 and 185350
+- fixed several minor and cosmetic issues found by Coverity scan
+ including false positives. For details see "$ git log". All noteworthy
+ issues are separately mentioned in this ChangeLog. The ones not mentioned
+ are for example problems that can only occur during out of memory
+ conditions, under which it is extremely likely tha the rsyslog process
+ will be killed in any case
+- testbench:
+ * added compile-check for [io]mgssapi, mmcount
+ * harden tests against hanging previous instances
+ * re-enable RELP tests on Solaris
+ * added basic test for imjournal
+ * added threading tests via valgrind's helgrind tool
+ * added valgrind test for kafka modules
+ * added capability to run elasticsearch tests with
+ a) different ElasticSearch versions
+ b) independently from OS-installed version
+ This also sets base to enable more elaborate ES tests
+ * further relaxed timing of dynstats tests, as they tend to create
+ false positives on slow machines
+- CI: improved test coverage on FreeBSD
+- Travis: clang static analyzer 5.0 now run over all source files
+- build: make compile warning-free under gcc 7
+------------------------------------------------------------------------------
+Version 8.30.0 [v8-stable] 2017-10-17
+- NEW BUILD REQUIREMENTS
+ * libfastjson 0.99.7 is now mandatory
+ the new version is required to support case-insensitive variable
+ comparisons, which are now the default
+ * when building imjournal, libsystemd-journal >= 234 is now recommended
+ This is to support the imjournal enhancement. Note that it is possible
+ to build with lower version, but this will degrade imjournal functionality.
+- CHANGE OF BEHAVIOR: all variables are now case-insensitive by default
+ Formerly, JSON based variables ($!, $., $/) were case-sensitive.
+ Turn old default back on: global(variables.casesensitive="on")
+ See ChangeLog entry below for more details.
+- core: handle (JSON) variables in case-insensitive way
+ The variable system inside rsyslog is JSON based (for easy consumption
+ of JSON input, the prime source of structured data). In JSON, keys
+ ("variable names") are case-sensitive. This causes constant problems
+ inside rsyslog configurations. A major nit is that case-insensitivity
+ option inside templates (even if turned on) does not work with JSON
+ keys because they of inner workings*1.
+ It is much more natural to treat keys in a case-INsensitive way (e.g.
+ "$!Key" and "$!key" are the same). We do not expect any real problems
+ out of this, as key names only differing in case is highly unlikely.
+ However, as it is possible we provide a way to enable case-sensitivity
+ via the global(variables.casesensitive="on") global config object.
+ Note that the default is to do case-insensitive matches. The reason
+ is that this is the right thing to do in almost all cases, and we do
+ not envision any problems at all in existing deployments.
+ *1 Note: case-insensitivity in rsyslog is achieved by converting all
+ names to lower case. So that the higher speed of strcmp() can be used.
+ The template option does actually that, convert the template keys to
+ lower case. Unfortunately, this does not work with JSON, as JSON keys
+ are NOT converted to lower case.
+ closes https://github.com/rsyslog/rsyslog/issues/1805
+- imjournal: made switching to persistent journal in runtime possible
+ with this patch imjournal can continue logging after switch to
+ persistent journal without need to restart rsyslog service
+ Thanks to github user jvymazal for the patch
+- mmanon: complete refactor and enhancements
+ - add pseudonymization mode
+ - add address randomization mode
+ - add support for IPv6 (this also supports various replacement modes)
+ closes https://github.com/rsyslog/rsyslog/issues/1614
+ also fixes bugs
+ - in IPv4 address recognition
+ closes https://github.com/rsyslog/rsyslog/issues/1720
+ - in IPv4 simple mode to-be-anonymized bits can get wrong
+ closes https://github.com/rsyslog/rsyslog/issues/1717
+- imfile: add "fileoffset" metadata
+ This permits to send the offset from which the message was read together
+ with the message text.
+ Thanks to github user derekjsonar for the initial implementation which
+ we extended to use the message start offset.
+- RainerScript: add ltrim and rtrim functions
+ closes https://github.com/rsyslog/rsyslog/issues/1711
+- core: report module name when suspending action
+ Thanks to Orion Poplawski for the patch.
+- core: add ability to limit number of error messages going to stderr
+ This permits to put a hard limit on the number of messages that can
+ go to stderr. If for nothing else, this capability is helpful for the
+ testbench. It permits to reduce spamming the test log while still
+ providing the ability to see initial error messages. Might also be
+ useful for some practical deployments.
+ global parameter: global(errorMessagesToStderr.maxNumber)
+- tcpsrv subsystem: improve clarity of some error messages
+ operating system error message are added to some messages, providing
+ better advise of what actually is the error cause
+- imptcp: include module name in error msg
+- imtcp: include module name in error msg
+- tls improvement: better error message if certificate file cannot be read
+- omfwd: slightly improved error messages during config parsing
+ They now contain config file/line number information where this was missing.
+- ommysql improvements
+ * Return specific code for unrecoverable errors. This makes retry processing
+ more performant and robust.
+ * error messages improved
+ * Update to utilize native v8 transactional interface. Previously, it used
+ the v7 interface with v8 emulation.
+ * treat server and client-generated messages differently
+ Server-generated error messages are considered non-recoverable, while
+ client generated once point into connection problems (which simply can
+ be retried). This is part of the improvements towards better
+ message-induced errors. Previous commits did only handle SQL parsing
+ errors, now we aim to address all of the message-induced error. We assume
+ that all server-generated errors are such - mysql API unfortunately does
+ not provide a clear indication of what type if error this is and it is
+ out of question to check for hundreds of error codes.
+ closes https://github.com/rsyslog/rsyslog/issues/1830
+- ommysql bugfix: do not duplicate entries on failed transaction
+ If a multi-message batch contains data errors, messages may be
+ duplicated as connection close is implicit commit (not rollback).
+ This patch introduces a specific rollback request in those cases.
+ closes https://github.com/rsyslog/rsyslog/issues/1829
+- imtcp bugfix: parameter priorityString was ignored
+ defaults were always used
+- template/bugfix: invalid template option conflict detection
+ This prevented "option.casesensitive" to be used with the SQL and JSON
+ options.
+- core/actions: fix handling of data-induced errors
+ Rsyslog core should try to detect data-induced (unrecoverable) errors
+ during action processing. An example of such is invalid SQL statements.
+ If the action returns a data error, rsyslog shall retry individual
+ messages from a batch in an effort to log those without errors. The others
+ shall be dropped.
+ This logic was temporarily disabled after the switch to the new v8
+ transaction interface. Now this bug is fixed and the testbench has been
+ amended to detect problems in the future.
+ closes https://github.com/rsyslog/rsyslog/issues/974
+- core/action bugfix: no "action suspended" message during retry processing
+ The action engine does not emit "action suspended" messages but "resumed"
+ ones in retry processing. This is wrong, as they are a strong indication
+ that something does not work correctly. Nevertheless, "resumed" messages
+ were emitted, which was very puzzling for the user.
+ This patch fixes it so that "suspend" messages are given during retry
+ processing. These do not contain a retry timestamp, providing evidence
+ that a retry is currently being tried.
+ closes https://github.com/rsyslog/rsyslog/issues/1069
+- core/ratelimit bugfix: race can lead to segfault
+ There was a race in iminternalAddMsg(), where the mutex is
+ released and after that the passed message object is accessed.
+ If the mainloop iterates in between, the msg may have already
+ been deleted by this time, resulting in a segfault.
+ Most importantly, there is no need to release the mutex lock
+ early, as suggested by current code. Inside mainloop the mutex
+ is acquired when it is time to do so, so at worst we'll have a
+ very slight wait there (which really does not matter at all).
+ This only happens if a large number of internal messages are emitted.
+ closes https://github.com/rsyslog/rsyslog/issues/1828
+- core bugfix: rsyslog aborts if errmsg is generated in early startup
+ Note that the segfault can occur only during early startup. Once
+ rsyslog has started, everything works reliably. This condition can
+ especially be triggered by specifying invalid TLS default certificates.
+ closes https://github.com/rsyslog/rsyslog/issues/1783
+ closes https://github.com/rsyslog/rsyslog/issues/1786
+- core bugfix: informational messages was logged with error severity
+ When the main loop reaped a child process (a normal action), this was
+ reported as an error. This caused user confusion. Now it is reported as
+ an informational message.
+- core bugfix: --enable-debugless build was broken
+ This was a regression from the v8.29.0 debug enhancements
+ Thanks to Stephen Workman for the patch.
+- queue bugfix: file write error message was incorrect
+ when a queue was restarted from disk file, it almost always
+ emitted a message claiming
+ "file opened for non-append write, but already contains xxx bytes"
+ This message was wrong and did not indicate a real error condition.
+ The predicate check was incorrect.
+ closes https://github.com/rsyslog/rsyslog/issues/170 (kind of)
+- omrelp bugfix: segfault when rebindinterval parameter is used
+- imudp bugfix: UDP oversize message not properly handled
+ When a message larger than supported by the UDP stack is to be sent,
+ EMSGSIZE is returned, but not specifically handled. That in turn
+ will lead to action suspension. However, this does not make sense
+ because messages over the UDP max message size simply cannot be sent.
+ closes https://github.com/rsyslog/rsyslog/issues/1654
+- core bugfix: memory corruption during configuration parsing
+ when omfwd is used with the $streamdriverpermittedpeers legacy
+ parameter, a memory corruption can occur. This depends on the
+ length of the provided strings and probably the malloc subsystem.
+ Once config parsing succeeds, no problem can happen.
+ Thanks to Brent Douglas for initially reporting this issue and
+ providing great analysis.
+ Thanks to github user bwdoll for analyzing this bug and providing
+ a suggested fix (which is almost what this commit includes).
+ closes https://github.com/rsyslog/rsyslog/issues/1408
+ closes https://github.com/rsyslog/rsyslog/issues/1474
+- core bugfix: race on worker thread termination during shutdown
+ The testbench got some occasionally failing tests. Review of
+ them brought up the idea that there is a race during worker
+ threat termination. Further investigation showed that this
+ might be a long-standing issue, but so far did not really
+ surface as the timing was almost always correct. However,
+ with the new functionality to emit a message on worker
+ shutdown (v8.29), the timing got more complex and now this
+ seemed to occasionally surface.
+ closes https://github.com/rsyslog/rsyslog/issues/1754
+- omelasticsearch: avoid ES5 warnings while sending json in bulkmode
+ do this by adding proper content type header to ES request
+ Thanks to William Dauchy for the patch
+- omelasticsearch bugfix: incompatibility with newer ElasticSearch version
+ ElasticSearch changed its API in newer versions. When "bulkmode" is enabled
+ in omelasticsearch, rsyslog seems to consider all responses from Elasticsearch
+ as errors, even the successful ones. As a consequence, every single request
+ ends up being logged into the error file.
+ closes https://github.com/rsyslog/rsyslog/issues/1731
+ Thanks to Vincent Quéméner for the patch.
+- imptcp bugfix: invalid mutex addressing on some platforms
+ code did not compile on platforms without atomic instructions
+ Thanks to github user petiepooo for the patch
+- imptcp bugfix: do not accept missing port in legacy listener definition
+ If legacy listener definition was used, a missing port was accepted during
+ the config read phase but errored out upon listener activation. This now
+ errors out directly when processing the config directive.
+------------------------------------------------------------------------------
+Version 8.29.0 [v8-stable] 2017-08-08
+- imptcp: add experimental parameter "multiline"
+ This enables a heuristic to support multiline messages on raw tcp syslog
+ connections.
+- imptcp: framing-related error messages now also indicate remote peer
+ This is the case e.g. for oversize messages.
+- imtcp: framing-related error messages now also indicate remote peer
+ This is the case e.g. for oversize messages.
+- imptcp: add session statistics counter
+ - session.opened
+ - session.openfailed
+ - session.closed
+- imtcp: add ability to specify GnuTLS priority string
+ This permits to set cipher details on a very low level.
+- impstats: add new resource counter "openfiles"
+- pmnormalize: new parser module
+ Parser module that uses liblognorm to parse incoming messages.
+- core/queue: provide informational messages on thread startup and shutdown
+ This provides better insight into operational state of rsyslog and is useful
+ in monitoring system health. Note that this causes the emission of messages
+ not previously seen. They are of syslog.informational priority.
+- omfwd/udp: improve error reporting, deprecate maxerrormessages parameter
+ Generally improved udp-related error messages (e.g. they now contain the
+ socket number, which makes it easier to related them to errors reported by
+ net.c subsystem).
+ We also deprecated (removed) the "maxerrormessages" configuration parameters.
+ It provided some very rough rate-limiting capabilities and was introduced
+ before we had native rate-limiters. The default was that only the first 5
+ error messages were actually reported. For long-running instances, that
+ meant that in many cases no errors were ever reported. We now use the default
+ internal message rate limiter, which works far better and ensures that also
+ long-running instances will be able to emit error messages after prolonged
+ runtime. In contrast, this also means that users will see more error
+ messages from rsyslog, but that should actually improve the end user
+ experience.
+- core: add parameters debug.file and debug.whitelist
+ allows one to generate debug log output only of specific files
+ Background information available at:
+ https://www.linkedin.com/pulse/improving-rsyslog-debug-output-jan-gerhards
+- core/net.c: improve UDP socket creation error messages
+- omfwd/udp: add "udp.sendbuf" parameter
+- core: make rsyslog internal message rate-limiter configurable
+ New parameters "internalmsg.ratelimit.interval" and "internalmsg.ratelimit.burst"
+ have been added.
+- omelasticsearch bugfixes and changed ES5 API support:
+ * avoid 404 during health check
+ Omelasticsearch responds differently to HTTP HEAD and GET requests and
+ returns correct state only on GET requests. This patch works around
+ that ES bug and always does a GET request even when technically a HEAD
+ request would be sufficient.
+ * avoid ES5 warnings while sending json
+ ES5 is generating warnings when sending json without the proper header:
+ $ curl -i -H "Content-Type: text/json" -XGET 'http://elasticsearch5:9200/' \
+ -d '{}\n'
+ HTTP/1.1 200 OK
+ Warning: 299 Elasticsearch-5.4.3-eed30a8 "Content type detection for rest
+ requests is deprecated. Specify the content type using the [Content-Type]
+ header." "Wed, 26 Jul 2017 14:33:28 GMT"
+ no issue on previous version.
+ Now, the header is set as application/json. It works for all versions
+ (tested on ES2 and ES5) we also handle the bulkmode where it should be
+ set to application/x-ndjson
+ closes https://github.com/rsyslog/rsyslog/issues/1546
+ * bugfix for memory leak while writing error file
+ Thanks to William Dauchy for providing the patches
+- imfile bugfix: wildcard detection issue on path wildcards
+ Wildcards mode was not properly detected when wildcards
+ were only used in a directory name on startup.
+ This caused imfile not to create a proper dynamic filewatch.
+ closes: https://github.com/rsyslog/rsyslog/issues/1672
+- omfwd bugfix: always give reason for suspension
+ In many cases, no error message were emitted when omfwd
+ went into action suspension, which was confusing for end
+ users. This patch enables explicit error messages in all
+ those cases.
+ closes https://github.com/rsyslog/rsyslog/issues/782
+- omfwd bugfix: configured compression level was not properly used
+ Thanks to Harshvardhan Shrivastava for the patch.
+- imptcp bugfix: potential socket leak on session shutdown
+ imptcp first tries to remove a to-be-shut-down socket from the
+ epoll set, and errors out if that does not work. In that case, the
+ underlying socket will be leaked.
+ This patch refactors the code; most importantly, it is not necessary
+ to remove the socket from the epoll set, as this happens automatically
+ on close. As such, we simply remove that part of the code, which
+ also removes the root cause of the socket leak.
+- omfwd/omudpspoof bugfix: switch udp client sockets to nonblocking mode
+ On very busy systems, we see "udp send error 11" inside the logs, and the requesting
+ action is being suspended (and later resumed). During the suspension period (in
+ default configuration), messages are lost. Error 11 translates to EAGAIN and the
+ cause of this problem is that the system is running out of UDP buffer space. This
+ can happen on very busy systems (with busy networks).
+ It is not an error per se. Doing a short wait will resolve the issue. The real root
+ cause of the issue is that omfwd uses a nonblocking socket for sending. If it were
+ blocking, the OS would block until the situation is resolved. The need for a
+ non-blocking sockets is a purely historical one. In the days of single-threaded
+ processing (pre v3), everything needed to be done by multiplexing, and blocking was
+ not permitted. Since then, the engine has dramatically changed. Actions now run on
+ their own thread(s). As such, there is no longer a hard need to use non-blocking i/o
+ for sending data. Many other output plugins also do blocking wait (e.g. omelasticsearch).
+ As such, the real root cause of the trouble is unnecessarily using non-blocking mode,
+ and consequently the right solution is to change that.
+ Note that using blocking i/o might change some timing inside rsyslog, especially
+ during shutdown. So theoretical there is regression potential in that area. However,
+ the core is designed to handle that situation (e.g. there is special shutdown code to
+ handle the blocking case), so this does not stand against the "proper" solution.
+ This patch applies the change on the rsyslog core level, within net.c. The only
+ users of the changed functionality are omfwd and omudpspoof. Imudp is unaffected as
+ it requests server sockets.
+ Note that according to the sendto() man page, there is a second cause for the EAGAIN
+ error, this is when the system temporarily runs out of ephemeral ports. It is not
+ 100% clear if this can also happen in the blocking case. However, if so, we can argue
+ this is a case where we really want the default retry logic. So for the time being,
+ it is appropriate to not handle EAGAIN in a special case any longer.
+ closes https://github.com/rsyslog/rsyslog/issues/1665
+- imklog: fix permitnonkernelfacility not working
+- impstats bugfix: impstats does not handle HUP
+ If the parameter "log.file" is specified, impstats writes its own
+ log file. However, HUP is not handled for this file, which makes
+ the functionality unusable with log rotation. It is also counter-
+ intuitive for users.
+ This patch enables correct HUP processing. As a sideline, it also
+ introduces a generic HUP processing framework for non-action type
+ of loadable modules.
+ closes https://github.com/rsyslog/rsyslog/issues/1662
+ closes https://github.com/rsyslog/rsyslog/issues/1663
+- core bugfix: segfault after configuration errors
+- core/queue bugfixes:
+ * Fix behavior of PersistStateInterval
+ If PersistStateInterval=1, then each log line read should cause the state file
+ to be updated, but this was not happening because nRecords was being post-increment.
+ Thanks to Anthony Howe for the patch.
+ * potential problem during deserialization
+ if queue object deserialization fails, invalid memory blocks might be
+ free'ed.
+ For more information see https://github.com/rsyslog/rsyslog/pull/1647
+ Thanks to Derek Smith for the patch.
+- core bugfix: message garbled after message modification
+ The MsgDup() function will return a garbled message object under these
+ conditions: The message was originally created with message length equal or
+ larger to CONF_RAWMSG_BUFSIZE. This makes rsyslog store the message in
+ dynamically allocated buffer space. Then, a component reduces the message
+ size to a size lower than CONGF_RAWMSG_BUFSIZE. A frequent sample is the
+ parser removing a known-bad LF at the end of the messages. Then, MsgDup is
+ executed. It checks the message size and finds that it is below
+ CONF_RAWMSG_BUFSIZE, which make it copy the msg object internal buffer
+ instead of the dynamically allocated one. That buffer was not written to in
+ the first place, so uninitialized data is copied. Note that no segfault can
+ happen, as the copied location was properly allocated, just not used in
+ this processing flow. In the end result, the new message object contains
+ garbage data. Whenever the new object is used (e.g. in a async ruleset or
+ action) that garbage will be used. Whenever the old object is accessed,
+ correct data will be used. Both types of access can happen inside the
+ same processing flow, which makes the problem appear to be random.
+ closes https://github.com/rsyslog/rsyslog/issues/1658
+- lmsig_ksi: removed pre-KSI_LS12 components
+ As of GuardTime, the provider, these no longer work due to backend
+ changes. The lmsig_ksi_ls12 module shall be used instead. This is
+ available since 8.27.0.
+- testbench bugfix: hang in tests if omstdout is not present
+ Many tests depend on omstdout. Given the fact that omstdout
+ is really only useful for the testbench (at least that's the intent),
+ we now require --enable-omstdout if --enable-testbench is given.
+ The alternative would have been to disable all those tests that
+ need it, which would have lead to considerable less testbench
+ coverage.
+ closes https://github.com/rsyslog/rsyslog/issues/1649
+------------------------------------------------------------------------------
+Version 8.28.0 [v8-stable] 2017-06-27
+- NEW BUILD REQUIREMENT: librelp 1.2.14 (to build relp components)
+ This was necessary because imrelp requires an API introduced in 1.2.14.
+- omfwd: add parameter "tcp_frameDelimiter"
+- omkafka: large refactor of kafka subsystem
+ This offers improvements and greatly increases reliability.
+ Closes https://github.com/rsyslog/rsyslog/issues/1559
+ Closes https://github.com/rsyslog/rsyslog/issues/1584
+ Closes https://github.com/rsyslog/rsyslog/issues/1515
+ Closes https://github.com/rsyslog/rsyslog/issues/1052
+ May fix https://github.com/rsyslog/rsyslog/issues/1230
+- imfile: improved handling of atomically renamed file (w/ wildcards)
+ if a file is atomically renamed, the state file is also being renamed,
+ so processing continues as if the original name were kept.
+ see also: https://github.com/rsyslog/rsyslog/issues/1417
+- imfile: add capability to truncate oversize messages or split into multiple
+ also in this case an error message is emitted. Both of these actions are
+ configurable. This also solves memory issues when an endregex does not
+ match for prolonged time. In that case, large parts of the file were
+ previously buffered, which could cause big problems in case e.g. the
+ endregex was simply wrong and never matched. For the later, see also
+ https://github.com/rsyslog/rsyslog/issues/1552
+- mmdblookup
+ * upgraded from "contrib" to "fully supported" state
+ * refactored and simplified code
+ * added ability to specify custom names for extracted fields
+ * added ability to specify container name for extracted fields
+ * bugfix: fixed multiple memory leaks
+- imptcp: add new parameter "flowControl"
+- imrelp: add "maxDataSize" config parameter
+ Thanks to Nathan Brown for the patch.
+- multiple modules: gtls: improve error if certificate file can't be opened
+- omsnare: allow different tab escapes
+ Thanks to Shane P. Lawrence for the patch.
+- omelasticsearch: converted to use libfastjson instead of json-c
+ json-c was used for historical purposes, and it's source included
+ within the rsyslog source tree. We now use libfastjson inside all
+ components.
+- imjournal: _PID fallback
+ * added fallback for _PID property when SYSLOG_PID is not available
+ * introduced new option "usepid" which sets which property should
+ rsyslog use, it has 3 states system|syslog|both, default is both
+ * deprecated "usepidfromsystem" option, still can be used
+ and override the "usepid"
+ * it is possible to revert previous default with usepid="syslog"
+ Thanks to Radovan Sroka for the patch
+- multiple modules: add better error messages when regcomp is failing
+- omhiredis: fix build warnings
+ Thanks to Brian Knox for the fix.
+- imfile bugfix: files mv-ed in into directory were not handled
+ Thanks to Zachary M. Zhao for the patch.
+ see also https://github.com/rsyslog/rsyslog/issues/1588
+- omprog bugfix: execve() incorrectly called
+ this caused failures on some but not all platforms
+ Thanks to å¼µå›å¤©(Chun-Tien Chang) and Matthew Seaman for the patch.
+- imfile bugfix: multiline timeout did not work if state file exists
+ The timeout feature for multiline reads does not correctly work for
+ files for which a state file existed. This is usually the case for files
+ that had been processed by a previous run and that still exist on the
+ new start. For all other files, especially those monitored by a
+ wildcard and newly created after the rsyslog start, timeout worked as
+ expected.
+ closes https://github.com/rsyslog/rsyslog/issues/1445
+- lmsig_ksi-ls12 bugfix: build problems on some platforms
+- core bugfix: invalid object type assertion
+ This lead to aborts due to failing assertion. Note that this could only
+ happen during debugging runs which includes runtime instrumentation,
+ something that never should be done in a stable production build.
+ So this did not affect ordinary users, only developers in with
+ deep debugging settings.
+- regression fix: local hostname was not always detected properly...
+ ... on early start (w/o network). Introduced in 8.27.0.
+ Thanks to github user jvymazal for the patch and whissi for
+ reporting and helping with the analysis.
+- bugfix: format security issues in zmq3 modules
+ see also: https://github.com/rsyslog/rsyslog/pull/1565
+ Thanks to Thomas D. (whissi) for the patch.
+- bugfix build system: add libksi only to those binaries that need it
+ Thanks to Allan Park for the patch.
+- bugfix KSI ls12 components: invalid tree height calculation
+ Thanks to Allan Park for the patch.
+- testbench/CI enhancements
+ * re-enable and add kafka tests
+ Kafka tests were disabled in 8.27.0 (a regression from imkafka).
+ * better testbench coverage for mmdblookup
+ * lmsig_ksi-ls12 is now being built at least on Centos7
+------------------------------------------------------------------------------
+Version 8.27.0 [v8-stable] 2017-05-16
+- imkafka: add module
+- imptcp enhancements:
+ * optionally emit an error message if incoming messages are truncated
+ * optionally emit connection tracking message (on connection create and
+ close)
+ * add "maxFrameSize" parameter to specify the maximum size permitted
+ in octet-counted mode
+ * add parameter "discardTruncatedMsg" to permit truncation of
+ oversize messages
+ * improve octect-counted mode detection: if the octet count is larger
+ then the set frame size (or overly large in general), it is now
+ assumed that octet-stuffing mode is used. This probably solves a
+ number of issues seen in real deployments.
+- imtcp enhancements:
+ * add parameter "discardTruncatedMsg" to permit truncation of
+ oversize messages
+ * add "maxFrameSize" parameter to specify the maximum size permitted
+ in octet-counted mode
+- imfile bugfix: "file not found error" repeatedly being reported
+ for configured non-existing file. In polling mode, this message
+ appeared once in each polling cycle, causing a potentially very large
+ amount of error messages. Note that they were usually emitted too
+ infrequently to trigger the error message rate limiter, albeit often
+ enough to be a major annoyance.
+- imfile: in inotify mode, add error message if configured file cannot
+ be found
+- imfile: add parameter "fileNotFoundError" to optionally disable
+ "file not found" error messages
+- core: replaced gethostbyname() with getaddrinfo() call
+ Gethostbyname() is generally considered obsolete, is not reentrant and
+ cannot really work with IPv6. Changed the only place in rsyslog where
+ this call remained.
+ Thanks to github user jvymazal for the patch
+- omkafka: add "origin" field to stats output
+ See also https://github.com/rsyslog/rsyslog/issues/1508
+ Thanks to Yury Bushmelev for providing the patch.
+- imuxsock: rate-limiting also uses process name
+ both for the actual limit processing as well as warning messages emitted
+ see also https://github.com/rsyslog/rsyslog/pull/1520
+ Thanks to github user jvymazal for the patch
+- Added new module: KSI log signing ver. 1.2 (lmsig_ksi_ls12)
+- rsyslog base functionality now builds on osx (Mac)
+ Thanks to github user hdatma for his help in getting this done.
+- build now works on solaris again
+- imfile: fix cross-platform build issue
+ see also https://github.com/rsyslog/rsyslog/issues/1494
+ Thanks to Felix Janda for bug report and solution suggestion.
+- bugfix core: segfault when no parser could parse message
+ This could happen if the default parser chain was changed and the
+ RFC3164 parser was not included. Never seen in practice, just by
+ experimenting in lab.
+- bugfix core: rate-limit internal messages when going to external log system
+ Rate-limiting was only applied to messages processed internally.
+ While the external logging system probably also applies rate-limiting,
+ it would be preferable that rsyslog applies the same policies on
+ internal messages, no matter where they go. This is now the case.
+- bugfix core: when obtaining local hostname, a NULL pointer could be
+ accessed. This depends on many factors, among them that no local host
+ name is configured in rsyslog.conf AND the local system configuration
+ also is set to an empty hostname.
+ Thanks to github user jvymazal for the patch.
+- bugfix core: on shutdown, stderr was written to, even if already closed
+ This lead to messages going to whatever was associated with file
+ descriptor two.
+ Thanks to Allan Park for the patch.
+- bugfix core: perform MainqObj destruction only when not NULL already
+ This affects the config object; in theory may lead to misaddressing during
+ config parsing.
+ Thanks to github user jvymazal for the patch
+- bugfix core: memory leak when internal messages not processed internally
+ In this case, the message object is not destructed, resulting in
+ a memory leak. Usually, this is no problem due to the low number
+ of internal message, but it can become an issue if a large number
+ of messages is emitted.
+ closes https://github.com/rsyslog/rsyslog/issues/1548
+ closes https://github.com/rsyslog/rsyslog/issues/1531
+- bugfix imptcp: potential overflow in octet count computation
+ when a very large octet count was specified, the counter could overflow
+------------------------------------------------------------------------------
+Version 8.26.0 [v8-stable] 2017-04-04
+- NEW BUILD REQUIREMENT: liblognorm 2.0.3 is required for mmnormalize
+ If mmnormalize is not built, the build requirements are unchanged.
+ The new version is necessary because it contains an enhanced API for a
+ new mmnormalize feature.
+- enable internal error messages at all times
+ This is an important change to the design of the rsyslog core internal
+ error message system. Previous code could deadlock if internal messages were
+ issued inside queue processing code, which effectively limited error-reporting
+ capabilities. This change makes it possible to call error messages from any
+ part of the code at any time.
+ As a side-effect, this also fixes an issue where rsyslog could deadlock if
+ imuxsock submited messages to the system log socket when that socket blocked.
+ This was a rare race, albeit consistently reproducible and also seen in
+ practice. The work-around for this issue was to set
+ global(processInternalMessages="on")
+ in rsyslog.conf. With the new code, this race can never happen again. The new
+ code also sets stage for emitting better error messages, especially in places
+ where we previously refrained from doing so and messages went only to the
+ debug log. For some file output and queue subsystem related messages, this
+ is already done, but there is still further work required.
+ Note well: this is a redesign of an important core component. While intensely
+ tested, this may still have some larger regression potential than usual code
+ changes.
+- core: added logging name of source of rate-limited messages
+ This adds the name to the rate-limiting message itself, making it easier
+ to identify the actual source of "spam" messages.
+ Thanks to github user jvymazal for the patch.
+- omfwd: omfwd: add support for network namespaces
+ Thanks to Bastian Stender for the patch.
+- imrelp: honor input name if provided when submitting to impstats
+ Thanks to Jon Henry for the patch.
+- imptcp: add ability to set owner/group/access perms for uds
+ Thanks to Nathan Brown for implementing this feature.
+- mmnormalize: add ability to load a rulebase from action() parameter
+ This is especially useful for small rulebases, as it avoids having
+ a separate rulebase file.
+ closes https://github.com/rsyslog/rsyslog/issues/625
+- pmrfc3164 improvements
+ - permit to ignore leading space in MSG
+ - permit to use at-sign in host names
+ - permit to require tag to end in colon
+ Thanks to github user bdolez for the contribution
+- add new global parameter "umask"
+ This is equivalent to "$umask" and permits to convert that construct
+ to new-style config format.
+ closes https://github.com/rsyslog/rsyslog/issues/1382
+- core: make use of -T command line option more secure
+ When the -T option is used, a chdir is now done right after chroot. It must
+ be noted, though, that -T is a testing option and has no intent to provide
+ real security. So this change does not mean it actually is sufficiently
+ secure.
+ Thanks to github user jvymazal for the patch.
+- omfile: add error if both file and dynafile are set
+- bugfix: build problem on MacOS (not a supported platform)
+ Thanks to FX Coudert for the fix.
+- regression fix: in 8.25, str2num() returned error on empty string
+ past behavior was to return 0 in this case; past behavior was reinstantiated
+ Thanks to github user jvymazal for the patch.
+- bugfix omsnmp: improper handling of new-style configuration parameters
+ Thanks to Radovan Sroka for the patch.
+- bugfix: rsyslog identifies itself as "liblogging-stdlog" in internal messages
+ This occurred when liblogging-stdlog was used, and was used by default (without
+ explicit configuration). This is a regression of the new default, which does
+ not correctly call stdlog_open() in the default case.
+ closes https://github.com/rsyslog/rsyslog/issues/1442
+- bugfix imfile: wrong files were monitored when using multiple imfile inputs
+ The bug was introduced by the changes for the multilevel wildcard feature
+ in 8.25.0. We have to handle FileCreate events different if the directory
+ watch is configured or added dynamically.
+ closes https://github.com/rsyslog/rsyslog/issues/1452
+- bugfix: setting net.aclResolveHostname/net.acladdhostnameonfail segfaults
+ When compiling using hardened gcc (gentoo), specifying net.aclResolveHostname
+ or net.acladdhostnameonfail results in rsyslogd segfaulting on startup.
+ Thanks to Radovan Sroka for the patch.
+- bugfix: immark emitted error messages with text "imuxsock"
+ Thanks to Chris Pilkington for the patch.
+- bugfix tcpflood: build failed if RELP was disabled
+- fix gcc6 compiler warnings
+ This also fixes a small bug with incorrectly working deprecated -u
+ command line option.
+ Thanks to Nikola Pajkovsky for the patch.
+- the output module array passing interface has been removed
+ It wasn't functional since the v8 update, and the only user was omoracle,
+ which is a contributed module that is no longer maintained. So we
+ removed that interface to streamline the code. Should it ever be needed
+ again, we could check the 8.25 code base. Note, though, that that code
+ still needs to be adjusted to the v8 engine.
+- testbench:
+ * tcpflood now automatically enters silent mode during Travis CI testing
+ This reduces testbench output, which is limited under Travis.
+ * the libqpid-proton package is no longer available for Ubuntu trusty. As
+ such, we disabled its use in Travis on this platform. Right now, this
+ means omamqp1 module is no longer tested on trusty.
+------------------------------------------------------------------------------
+Version 8.25.0 [v8-stable] 2017-02-21
+- imfile: add support for wildcards in directory names
+ This now permits to monitor newly created directories without altering
+ the configuration.
+- add new global option "parser.PermitSlashInProgramname"
+- mmdblookup: fix build issues, code cleanup
+ Thanks to Dan Molik for the patch.
+- improved debug output for queue corruption cases
+- an error message is now displayed when a directory owner cannot be set
+ This mostly happens with omfile and dynafile. The new messages
+ facilitates troubleshooting.
+- rainerscript:
+ * add new function ipv42num
+ * add new function num2ipv4
+- bugfix: ratelimiter does not work correctly is time is set back
+ Thanks to github user hese10 for the patch.
+ see also https://github.com/rsyslog/rsyslog/issues/1354
+- core: fix potential message loss in old-style transactional interface
+ This was experienced for example by omrelp. Could loose one message per
+ broken connection, iff that message did not make it to the unacked list.
+- bugfix queue subsystem: queue corrupted if certain msg props are used
+ The core issues was in the msg object deserializer, which had the wrong
+ deserialization sequence. That in turn lead to queue corruption issues.
+ Corruption of disk queue (or disk part of DA queue) always happens if
+ the "json" property (message variables) is present and "structured-data"
+ property is also present. This causes rsyslog to serialize to the
+ queue in wrong property sequence, which will lead to error -2308 on
+ deserialization.
+ Seems to be a long-standing bug. Depending on version used, some or
+ all messages in disk queue may be lost.
+ closes https://github.com/rsyslog/rsyslog/issues/1404
+- bugfix imjournal: fixed situation when time goes backwards
+ This is resolving the situation when system is after reboot and
+ boot_id doesn't match so cursor pointing into "future".
+ Usually sd_journal_next jump to head of journal due to journal
+ approximation, but when system time goes backwards and cursor is
+ still invalid, rsyslog stops logging.
+ We use sd_journal_get_cursor to validate our cursor.
+ When cursor is invalid we are trying to jump to the head of journal
+ This problem with time should not affect persistent journal,
+ but if cursor has been intentionally compromised it could stop
+ logging even with persistent journal.
+- bugfix: bFlushOnTxEnd == 0 not honored when writing w/o async writer
+ If bFlushOnTXEnd is set, we need to flush on transaction end - in
+ any case. It is not relevant if this is using background writes
+ (which then become pretty slow) or not. And, similarly, no flush
+ happens when it is not set.
+ see also https://github.com/rsyslog/rsyslog/issues/1297
+- bugfix core: str2num mishandling empty strings
+ If str2num() receives an empty string, misaddressing happens.
+ This theoretically can lead to a segfault if a RainerScript function
+ is used inside the configuration which calls code that could trigger
+ this bug.
+ closes https://github.com/rsyslog/rsyslog/issues/1412
+- bugfix rainerscript: set/unset statement do not check variable name validity
+ Only JSON-based variables can be use with set and unset. Unfortunately,
+ this restriction is not checked. If an invalid variable is given
+ (e.g. $invalid), this is not detected upon config processing on
+ startup. During execution phase, this can lead to a segfault, a
+ memory leak or other types of problems.
+ Thanks to github user mostolog for reporting and helping to analyze
+ this issue.
+ see also https://github.com/rsyslog/rsyslog/issues/1376
+ closes https://github.com/rsyslog/rsyslog/issues/1377
+- bugfix mmrm1stspace: last character of rawmsg property was doubled
+- bugfix: rsyslog loops on freebsd when trying to write /dev/console
+ Rsyslog 8.23.0 loops on FreeBSD when trying to access a (now revoked)
+ /dev/console file descriptor, as per Alexandre's original bug report [1].
+ The original patch fixes the problem when tryTTYRecover() sees errno 6 ENXIO.
+ Running FreeBSD 10-stable here and getting errno 5 EIO, same as Xavier gets
+ in his 2016 bug report [2].
+ New patch [3] includes errno 5 to tryTTYRecover() in runtime/stream.c and
+ fixes the problem for me, on multiple machines.
+ [1] https://github.com/rsyslog/rsyslog/issues/371
+ [2] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211033
+ [3] https://bz-attachments.freebsd.org/attachment.cgi?id=178452
+ closes https://github.com/rsyslog/rsyslog/issues/1351
+ Thanks to Damien Fleuriot for the patch.
+- bugfix imtcp: fix very small (cosmetic) memory leak
+ For each listener, the name of an assigned ruleset is not freed. This
+ is cosmetic, because it is a very small static leak AND it needs to
+ be kept until end of run anyways (and at end of run the OS frees it).
+ However, the leak breaks memleak checks in the testbench.
+- fix build issues on some platforms (detected on newer Fedora)
+------------------------------------------------------------------------------
+Version 8.24.0 [v8-stable] 2017-01-10
+- rsyslog now builds on AIX
+ see also: https://github.com/rsyslog/rsyslog/pull/1247
+ Thanks to github user purnimam1 and the team at IBM
+ Note: the rsyslog project has no AIX platform to ensure that future versions
+ will remain buildable on AIX. If you would like to contribute resources,
+ please contact the rsyslog team.
+- mmdblookup: new maxminddb lookup message modify plugin
+ Thanks to 饶ç›ç³ (github user chenryn) for the contribution
+- mmrm1stspace: new module; removes first space in MSG if present
+- KSI signature provider: file permissions can now be specified
+ This happens via parameters equal to those used by omfile itself.
+ Note that KSI files can have different permissions/owner than the log
+ files themself.
+ Thanks to Allan Park for the patch.
+- omzmq: new features
+ Thanks to Brian Knox for the patch.
+- change: when the hostname is empty, we now use "localhost-empty-hostname"
+ In 8.23.0, "localhost" was used in this case, but that could be misleading.
+ The new name makes the error condition (gethostname() should always return
+ a non-empty name) more obvious.
+- omelasticsearch: remove "asyncrepl" config parameter
+ The _bulk index endpoint on ElasticSearch 5.0 no longer
+ ignores the ?replication=async query parameter. It was deprecated
+ since 1.5 and silently ignored in 2.x but passing it to a 5.x
+ instance breaks omelasticsearch with a 400 response.
+ closes https://github.com/rsyslog/rsyslog/issues/1250
+- omfwd: Add support for bind-to-device (see below on same for imudp)
+- imudp: Add support for bind-to-device
+ Add support for bind-to-device option to omfwd and imudp modules.
+ Configured using device="name". Only new syntax format is supported.
+ e.g.,
+ input(type="imudp" port=["10514"] device="eth0" name="udp")
+ Action(type="omfwd" Target="192.168.1.23" Port="10514" Device="eth0")
+ see also https://github.com/rsyslog/rsyslog/pull/1261
+ Thanks to David Ahern for the patch.
+- imudp: limit rcvbufsize parameter to max 1GiB
+- rainerscript: implement new "call_indirect" statement
+- bugfix imjournal: make state file handling more robust
+ There is a bug in rsyslog which is caused by not very atomic writes of
+ imjournal statefile. It's hardly reproducible but there is a way.
+ fscanf error appears only when rsyslog reads an empty statefile which
+ causes that imjournal is stopped so no logging from journal is
+ performed. When the statefile contains random bytes error appears
+ again but from journal and imjournal is stopped too.
+ In this patch Rsyslog writes imjournal statefile more atomically and
+ secure. Reading the statefile is more robust and doesn't affect
+ imjournal module so when corrupted statefile is read imjournal
+ ignores statefile, continues with logging and it doesn't stop. Logger
+ can be used as a test if it's logging or not.
+ Patch introduces a new option with both old and new config format
+ "IgnoreNonValidStateFile" which is "on" by default and it can turn
+ off ignorance of non valid statefile.
+ Thanks to github user tomassykora for the patch.
+- bugfix core: lookup table reload was not properly integrated
+ The opcode was not handled, what lead to misleading messages
+ in debug log. Since we run debug builds more strictly, it also
+ causes an assertion to trigger, thus aborting the test
+- bugfix core: potential deadlock on shutdown
+ could happen when rsyslog was started and quickly shut down OR when
+ coincidentally a new thread was spawend "with bad timing" around the time
+ of shutdown.
+ See also https://github.com/rsyslog/rsyslog/pull/1274
+ Thanks to github user tomassykora for the final patch and Rado Sroka for
+ the analysis and an initial patch.
+- bugfix ommongodb: did not work in v8 due to invalid indirection
+ Thanks to Benoit Dolez for the patch.
+- bugfix ommongodb: fix tryResume handling
+ To make tryResume working, the connection to mongodb need to be closed.
+ Thus close it on "insert error".
+ Thanks to Benoit Dolez for the patch.
+- bugfix omfwd: retry processing was not done correctly, could stall
+ see also https://github.com/rsyslog/rsyslog/pull/1261
+ Thanks to David Ahern for the patch.
+- bugfix imuxsock: segfault non shutdown when $OmitLocalLogging is on
+ Imuxsock tries to close socket on index 0 which ends with segfault.
+ Thanks to Tomas Sykora for the patch.
+- testbench:
+ * empty-hostname test did not work correctly
+ * improve debugging by better output
+------------------------------------------------------------------------------
+Version 8.23.0 [v8-stable] 2016-11-15
+- NEW BUILD REQUIREMENT: libfastjson 0.99.3
+ This was introduced in 8.20.0 as a suggestion and has now become a hard
+ requirement. See 8.20.0 ChangeLog entry for more details.
+- KSI signatures: removed SHA2-224 hash algorithm
+ This is considered insecure and no longer supported by the underlying
+ KSI library. If still used within a configuration, a descriptive error
+ message is emitted during config processing.
+ Thanks to Henri Lakk for the initial patch.
+- imfile: new timeout feature for multi-line reads
+ When using startmsg.regex, messages are held until the next one is written.
+ We now provide a "readTimeout" parameter family (see doc) to timeout such
+ reads and ensure messages are not held for a very long time.
+ see also https://github.com/rsyslog/rsyslog/issues/1133
+- omfile: improve robustness against network file system failures
+ in case of failure, a close and re-open is tried, which often solves the
+ issue (and wasn't handle before this patch).
+ see also https://github.com/rsyslog/rsyslog/pull/1161
+ Thanks to github user hese10 for the patch.
+- pmaixforwardedfrom: support for AIX syslogd -s option
+ if syslog in AIX started with "-s" option, AIX syslog adds only "From "
+ instead of "Message forwarded from ". With this patch, both are now
+ detected.
+ Thanks to github user patelritesh for the patch.
+- omelasticsearch: add ability to specify max http request size
+ This permits to keep batches below ES-configured limits.
+ Thanks to github user barakshechter for the patch.
+- omelasticsearch: high availability addressing of ElasticSearch cluster
+ allow one to specify an array of servers, which is tried until a working
+ one is found (and given up only if none works).
+ Thanks to github user barakshechter for the patch.
+- omelasticsearch: make compatible with ElasticSearch 2.x and 5.x
+ fixes omelasticsearch logs response from ElasticSearch 5.0 _bulk
+ endpoint as error
+ See also https://github.com/rsyslog/rsyslog/pull/1253
+ Thanks to Christian Rodemeyer for the patch.
+- omhiredis: add dynakey attribute.
+ If set to on, this causes omhiredis to treat the key attribute as the
+ name of a template so that you can build a dynamic redis queue name
+ or list key.
+ see also: https://github.com/rsyslog/rsyslog/pull/1218
+ Thanks to github user bobthemighty for the patch
+- omtcl: new contributed module
+ see also https://github.com/rsyslog/rsyslog/pull/1041
+ Please note: contributed modules are not directly supported by the
+ project. You might want to contact the author for questions.
+ Thanks to Francisco Castro for contributing it.
+- RainerScript: provide a capability to set environment variables
+ via 'global(environment="var=val")' config statement.
+ This is most importantly for things like HTTP_PROXY.
+ see also https://github.com/rsyslog/rsyslog/issues/1209
+- lookup tables: improved error checking
+ Thanks to Janmejay Singh for the patch.
+- queue subsystem: add configuration parameter "queue.samplinginterval"
+ Supports sampling of messages (as often used in data transmission).
+ Thanks to Zachary M. Zhao for the patch.
+- bugfix core: errmsg.LogError now switches to dfltErrLogger just before shutdown
+ Thanks to Janmejay Singh for the patches.
+- bugfix core: fixed un-freed memory in non-transactional action using string-passing
+ closes https://github.com/rsyslog/rsyslog/issues/968
+ Thanks to Janmejay Singh for the patches.
+- rsgtutil: option to specify KSI publications file certificate constraints
+ see also https://github.com/rsyslog/rsyslog/issues/1207
+- omprog: bugfixes and enhancements
+ - omprog resource leak fix (fd leak)
+ - omprog got ability to force-kill process if it doesn't die in 5 seconds
+ (linux specific)
+ - child-process lifecycle debugging aid (in form of logs) (mainLoop and
+ omprog cleanup both log pid at child-death, mainLoop reaping is now
+ visible to user, as opposed to being a mystery, because omprog didn't
+ seem to anticipate it in terms of code)
+ Thanks to Janmejay Singh for the patches.
+ see also https://github.com/rsyslog/rsyslog/pull/1155
+- bugfix imfile: ReopenOnTruncate processing, file open processing
+ This fixes
+ * ReopenOnTruncate was only honored when a state file existed
+ see https://github.com/rsyslog/rsyslog/issues/1090
+ * open processing could run into a loop
+ see https://github.com/rsyslog/rsyslog/issues/1174
+ This is done via refactoring the open file handling, which provides
+ overall cleaner and easier-to-follow code.
+ Thanks to Owen Smith for analyzing the problem and providing a
+ prototype PR which greatly helped towards the final solution.
+- bugfix omlibdbi: libdbi-driver-sqlite3/2 requires to provide a path to
+ database split into two strings:
+ * absolute path, where the database file sits
+ * database filename itself.
+ This was previously not done.
+ Thanks to github user aleek for the patch.
+- bugfix RainerScript: issue in prifilt() function
+ Initialize func-data(and to-be-freed flag) correctly for prifilt
+ function-node
+ Thanks to Janmejay Singh for the patch.
+- bugfix omrelp: invalid module name imrelp was used in some error messages
+ Thanks to Chris Pilkington for the patch.
+- bugfix core: abort when persisting object state
+ This causes a segfault. It happens whenever an object state larger
+ than 4095 byte is persisted. Then, incorrectly a try to rollover to
+ a new state file is tried, which will lead to a division by zero
+ as the necessary variables for this operation are not set because we
+ are NOT in circular mode.
+ This problem can happen wherever state files are written. It has been
+ experienced with imfile and queue files.
+ Many thanks to github user mostolog for his help in reproducing the issue,
+ which was very important to finally nail down this long-standing bug.
+ closes https://github.com/rsyslog/rsyslog/issues/1239
+ closes https://github.com/rsyslog/rsyslog/issues/1162
+ closes https://github.com/rsyslog/rsyslog/issues/1074
+- bugfix: segfault if hostname is unset on system
+ happens when gethostname() returns empty string. This will cause
+ the createon of the localhostname prop_t to fail, which in turn
+ leads to a NULL pointer dereference when emitting local messages.
+ As we emit a startup message by default, this had usually lead
+ to a segfault on startup.
+ Thanks to Erik Potter and github user mostolog for their help
+ in analyzing this problem.
+ closes https://github.com/rsyslog/rsyslog/issues/1040
+ closes https://github.com/rsyslog/rsyslog/issues/335
+- bugfix external module perl skeleton: did not work properly
+ Thanks to github user Igorjan666 for the patch.
+- bugfix build system: Fix detection of pthread_setschedparam() on platforms
+ such as FreeBSD
+ see also https://github.com/rsyslog/rsyslog/pull/1147
+ Thanks to Matthew Seaman for the patch.
+- bugfix omelasticsearch: modifies constant memory under some circumstances
+ Function computeBaseUrl may modify its serverParam parameter, but
+ this may contain the constant string "localhost". Depending on the
+ platform, this can lead to a segfault.
+ Noticed while working on compiler warnings, not seen in practice.
+- "bugfix": theoretical queue file corruption when more than MAX_INT files
+ closes https://github.com/rsyslog/rsyslog/issues/1202
+- bug fix/KSI: LOGSIG11 missing in the beginning of KSI log signature file
+ When logging with KSI is not working properly for whatever reason, an
+ empty .ksisig file is created (which by itself is not an issue). However,
+ later it looks like this file is re-used, but it is not checked whether it
+ already contains the magic LOGSIG11 in the beginning of the file. This leads
+ to a log signature file which has correct content but is missing the
+ LOGSIG11 magic in the beginning.
+- bugfix template processor: missing escaping of backslash in json mode
+ Thanks to github user mostolog for providing the patch.
+- build environment: --enable-debug now defaults to new "auto" mode
+ previously, DEBUG mode (and thus assert() macros) was disabled by default
+ and explicitly needed to be enabled by providing the --enable-debug
+ ./configure switch. Now, a new --enable-debug=auto mode has been added
+ and made the default. It enables DEBUG mode if we build from git and only
+ disables it when a release build is done (from the release tarball). This
+ aims at better error checking during testbench runs and developer testing.
+- testbench improvements
+ * improved testbench file generation tool
+ Thanks to Pascal Withopf for the patch.
+ * added some plumbing for extended tests which work by overriding OS APIs
+ * imfile ReopenOnTruncate option is now being tested
+ * the CI environment now runs most tests in debug mode, but some in
+ release mode to cover potential release-mode races
+ * template json option is now being tested
+ * object state persisting received a basic test
+ * added test for empty hostnames
+ * added tests for omprog
+------------------------------------------------------------------------------
+Version 8.22.0 [v8-stable] 2016-10-04
+- ompgsql: add template support
+ Thanks to Radu Gheorghe for implementing this.
+- generate somewhat better error message on config file syntax error
+ a common case (object at invalid location) has received it's own error
+ message; for the rest we still rely on the generic flex/bison handler
+- bugfix:omhiredis reconnects after failure
+ previously it could loose messages under such conditions.
+ Thanks to Bob Gregory for the patch.
+- general cleanup and code improvement
+ mostly guided by compiler warnings induced by newer opensuse buildbot
+ environment
+------------------------------------------------------------------------------
+Version 8.21.0 [v8-stable] 2016-08-23
+- CHANGE OF BEHAVIOR:
+ by default, internal messages are no longer logged via the internal
+ bridge to rsyslog but via the syslog() API call [either directly or
+ via liblogging). For the typical single-rsyslogd-instance installation this
+ is mostly unnoticeable (except for some additional latency). If multiple
+ instances are run, only the "main" (the one processing system log messages)
+ will see all messages. To return to the old behavior, do either of those
+ two:
+ 1) add in rsyslog.conf:
+ global(processInternalMessages="on")
+ 2) export the environment variable RSYSLOG_DFLT_LOG_INTERNAL=1
+ This will set a new default - the value can still be overwritten via
+ rsyslog.conf (method 1). Note that the environment variable must be
+ set in your **startup script**.
+ For more information, please visit
+ https://www.rsyslog.com/rsyslog-error-reporting-improved/
+- slightly improved TLS syslog error messages
+- queue subsystem: improved robustness
+ The .qi file is now persisted whenever an existing queue file is fully
+ written and a new file is begun. This helps with rsyslog aborts, including
+ the common case where the OS issues kill -9 because of insufficiently
+ configured termination timeout (this is an OS config error, but a frequent
+ one). Also, a situation where an orphaned empty file could be left in the
+ queue work directory has been fixed. We expect that this change causes
+ fewer permanent queue failures.
+- bugfix: build failed on some platforms due to missing include files
+------------------------------------------------------------------------------
+Version 8.20.0 [v8-stable] 2016-07-12
+- NEW BUILD REQUIREMENT: librelp, was 1.2.5, now is 1.2.12
+ This is only needed if --enable-relp is used. The new version is needed
+ to support the new timeout parameter in omrelp.
+- NEW BUILD SUGGESTION: libfastjson 0.99.3
+ while not strictly necessary, previous versions of libfastjson have a bug
+ in unicode processing that can result in non US-ASCII characters to be
+ improperly encoded and may (very unlikely) also cause a segfault.
+ This version will become mandatory in rsyslog 8.23.0
+- omrelp: add configurable connection timeout
+ Thanks to Nathan Brown for implementing this feature.
+- pmrfc3164: add support for slashes in hostname
+ added parameter "permit.slashesinhostname" to support this, off by default
+ [Note that the RFC5424 always supported this, as 5424 is a different
+ standard]
+- bugfix omfile: handle chown() failure correctly
+ If the file creation succeeds, but chown() failed, the file was
+ still writen, even if the user requested that this should be treated
+ as a failure case. This is corrected now.
+ Also, some refactoring was done to create better error messages.
+- omfile now better conveys status of unwritable files back to core
+- config files recursively including themselves are now detected
+ and an error message is emitted in that case; Previously, this
+ misconfiguration resulted in rsyslog loop and abort during startup.
+ closes https://github.com/rsyslog/rsyslog/issues/1058
+- refactored code to not emit compiler warnings in "strict mode"
+ We changed the compiler warning settings to be rather strict and cleaned up
+ the code to work without generating any warning messages.
+ This results in an overall even more improved code quality, which will now
+ also be enforced via our CI systems.
+- bugfix: fix some issues with action CommitTransaction() handling
+ An action that returns an error from CommitTransaction() caused a
+ loop in rsyslog action processing. Similarly, retry processing was not
+ properly handled in regard to CommitTransaction().
+ This is a first shot at fixing the situation. It solves the
+ immediate problems, but does not implement the full desired
+ functionality (like error file).
+ see also https://github.com/rsyslog/rsyslog/issues/974
+ see also https://github.com/rsyslog/rsyslog/issues/500
+- bugfix omqmqp1: connecting to the message bus fails on nonstandard port
+ Thanks to Ken Giusti for the patch.
+ see also: https://github.com/rsyslog/rsyslog/pull/1064
+- testbench/CI enhancements
+ * new tests for RELP components
+ * new tests for core action processing and retry
+ * travis tests now also run against all unstable versions of supporting
+ libraries. This helps to track interdependency problems early.
+ * new tests for hostname parsing
+ * new tests for RainerScript comparisons
+------------------------------------------------------------------------------
+Version 8.19.0 [v8-stable] 2016-05-31
+- NEW BUILD REQUIREMENT: autoconf-archive
+- omelasticsearch: add option to permit unsigned certs (experimentally)
+ This adds plumbing as suggested by Joerg Heinemann and Radu Gheorghe,
+ but is otherwise untested. Chances are good it works. If you use it,
+ please let us know your experience and most importantly any bug
+ reports you may have.
+ closes https://github.com/rsyslog/rsyslog/issues/89
+- imrelp: better error codes on unavailability of TLS options
+ Most importantly, we will tell the user in clear words if specific TLS
+ options are not available due to too-old GnuTLS.
+ closes https://github.com/rsyslog/rsyslog/issues/1019
+- default stack size for inputs has been explicitly set to 4MiB
+ for most platforms, this means a reduction from the default of 10MiB, however
+ it may mean an increase for micro-libc's (some may have as low as 80KiB by
+ default).
+- testbench: We are now using libfaketime instead of faketime command line
+ tool. Make sure you have installed the library and not just the binary!
+- refactor stringbuf
+ * use only a single string buffer
+ ... both for the internal representation as well as the C-String one.
+ The module originally tried to support embedded NUL characters, which
+ over time has proven to be not necessary. Rsyslog always encodes
+ NUL into escape sequences.
+ Also, the dual buffers were used inconsistently, which could lead to
+ subtle bugs. With the single buffer, this does no longer happen and
+ we also get some improved performance (should be noticeable)
+ and reduced memory use (a bit).
+ closes https://github.com/rsyslog/rsyslog/issues/1033
+ * removed no longer used code
+ * internal API changes to reflect new needs
+ * performance improvements
+ * miscellaneous minor cleanup
+- fix: potential misaddressing in template config processing
+ This could cause segfault on startup. Happens when template name shorter
+ than two chars and outname is not set. Once we are over startup, things
+ work reliably.
+- bugfix omfile: async output file writing does not respect flushing
+ neither parameter flushInterval nor flushOnTXEnd="on" was respected.
+ closes https://github.com/rsyslog/rsyslog/issues/1054
+- bugfix imfile: corrupted multi-line message when state data was persisted
+ see also https://github.com/rsyslog/rsyslog/issues/874
+ Thanks to Magnus Hyllander for the analysis and a patch suggestion.
+- bugfix imfile: missing newline after first line of multiline message
+ see also https://github.com/rsyslog/rsyslog/issues/843
+ Thanks to Magnus Hyllander for the patch.
+- bugfix: dynstats unusedMetricTtl bug
+ Thanks to Janmejay Singh for fixing this.
+- bugfix build system: build was broken on SunOS
+ Thanks to Filip Hajny for the patch.
+- bugfix: afterRun entry point not correctly called
+ The entry point was called at the wrong spot, only when the thread
+ had not already terminated by itself. This could cause various
+ cleanup to not be done. This affected e.g. imjournal.
+ closes https://github.com/rsyslog/rsyslog/issues/882
+- bugfix dynstats: do not leak file handles
+ Thanks to Janmejay Singh for the patch.
+- bugfix omelasticsearch: disable libCURL signal handling
+ previously, this could lead to segfaults on connection timeout
+ see also https://github.com/rsyslog/rsyslog/pull/1007
+ Thanks to Sai Ke WANG for the patch.
+- bugfix omelasticsearch: some regressions were fixed
+ * error file was no longer written
+ * fix for some potential misaddressings
+- improved wording: gnutls error message points to potential cause
+ What GnutTLS returns us is very unspecific and somewhat misleading, so
+ we point to what it most probably is (broken connect).
+ see also https://github.com/rsyslog/rsyslog/issues/846
+- some general code improvements
+ * "fixed" cosmetic memory leaks at shutdown
+- build system bugfix: configure can't find gss_acquire_cred on Solaris
+ Thanks to github user vlmarek for the patch.
+- improvements to the CI environment
+ * improvements on the non-raciness of some tests
+ * imdiag: avoid races in detecting queue empty status
+ This resolves cases where the testbench terminated rsyslog too early,
+ resulting in potential message loss and test failure.
+ * omkafka has now dynamic tests
+ Thanks to Janmejay Singh for implementing them.
+ * try to merge PR to master and run tests; this guards against cross-PR
+ regressions and wasn't caught previously. Note that we skip this test
+ if we cannot successfully merge. So this is not a replacement for a
+ daily full "all-project integration test run".
+ * travis has finally enabled elasticsearch tests
+ ES was unfortunately not being regularly tested for quite a while due to
+ missing environment. This lead to some regressions becoming undetected.
+ These were now discovered thanks to the new support on travis. Also, this
+ guards against future regressions.
+ * imfile has now additional tests and overall better coverage
+ * omfile has now additional tests
+------------------------------------------------------------------------------
+Version 8.18.0 [v8-stable] 2016-04-19
+- testbench: When running privdrop tests testbench tries to drop
+ user to "rsyslog", "syslog" or "daemon" when running as root and
+ you don't explicit set RSYSLOG_TESTUSER environment variable.
+ Make sure the unprivileged testuser can write into tests/ dir!
+- templates: add option to convert timestamps to UTC
+ closes https://github.com/rsyslog/rsyslog/issues/730
+- omjournal: fix segfault (regression in 8.17.0)
+- imptcp: added AF_UNIX support
+ Thanks to Nathan Brown for implementing this feature.
+- new template options
+ * compressSpace
+ * date-utc
+- redis: support for authentication
+ Thanks to Manohar Ht for the patch
+- omkafka: makes kafka-producer on-HUP restart optional
+ As of now, omkafka kills and re-creates kafka-producer on HUP. This
+ is not always desirable. This change introduces an action param
+ (reopenOnHup="on|off") which allows user to control re-cycling of
+ kafka-producer.
+ It defaults to on (for backward compatibility). Off allows user to
+ ignore HUP as far as kafka-producer is concerned.
+ Thanks to Janmejay Singh for implementing this feature
+- imfile: new "FreshStartTail" input parameter
+ Thanks to Curu Wong for implementing this.
+- omjournal: fix libfastjson API issues
+ This module accessed private data members of libfastjson
+- ommongodb: fix json API issues
+ This module accessed private data members of libfastjson
+- testbench improvements (more tests and more thorough tests)
+ among others:
+ - tests for omjournal added
+ - tests for KSI subsystem
+ - tests for privilege drop statements
+ - basic test for RELP with TLS
+ - some previously disabled tests have been re-enabled
+- dynamic stats subsystem: a couple of smaller changes
+ they also involve the format, which is slightly incompatible to
+ previous version. As this was out only very recently (last version),
+ we considered this as acceptable.
+ Thanks to Janmejay Singh for developing this.
+- foreach loop: now also iterates over objects (not just arrays)
+ Thanks to Janmejay Singh for developing this.
+- improvements to the CI environment
+- enhancement: queue subsystem is more robst in regard to some corruptions
+ It is now detected if a .qi file states that the queue contains more
+ records than there are actually inside the queue files. Previously this
+ resulted in an emergency switch to direct mode, now the problem is only
+ reported but processing continues.
+- enhancement: Allow rsyslog to bind UDP ports even w/out specific
+ interface being up at the moment.
+ Alternatively, rsyslog could be ordered after networking, however,
+ that might have some negative side effects. Also IP_FREEBIND is
+ recommended by systemd documentation.
+ Thanks to Nirmoy Das and Marius Tomaschewski for the patch.
+- cleanup: removed no longer needed json-c compatibility layer
+ as we now always use libfastjson, we do not need to support old
+ versions of json-c (libfastjson was based on the newest json-c
+ version at the time of the fork, which is the newest in regard
+ to the compatibility layer)
+- new External plugin for sending metrics to SPM Monitoring SaaS
+ Thanks to Radu Gheorghe for the patch.
+- bugfix imfile: fix memory corruption bug when appending @cee
+ Thanks to Brian Knox for the patch.
+- bugfix: memory misallocation if position.from and position.to is used
+ a negative amount of memory is tried to be allocated if position.from
+ is smaller than the buffer size (at least with json variables). This
+ usually leads to a segfault.
+ closes https://github.com/rsyslog/rsyslog/issues/915
+- bugfix: fix potential memleak in TCP allowed sender definition
+ depending on circumstances, a very small leak could happen on each
+ HUP. This was caused by an invalid macro definition which did not rule
+ out side effects.
+- bugfix: $PrivDropToGroupID actually did a name lookup
+ ... instead of using the provided ID
+- bugfix: small memory leak in imfile
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: double free in jsonmesg template
+ There has to be actual json data in the message (from mmjsonparse,
+ mmnormalize, imjournal, ...) to trigger the crash.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: incorrect formatting of stats when CEE/Json format is used
+ This lead to ill-formed json being generated
+- bugfix omfwd: new-style keepalive action parameters did not work
+ due to being inconsistently spelled inside the code. Note that legacy
+ parameters $keepalive... always worked
+ see also: https://github.com/rsyslog/rsyslog/issues/916
+ Thanks to Devin Christensen for alerting us and an analysis of the
+ root cause.
+- bugfix: memory leaks in logctl utility
+ Detected by clang static analyzer. Note that these leaks CAN happen in
+ practice and may even be pretty large. This was probably never detected
+ because the tool is not often used.
+- bugfix omrelp: fix segfault if no port action parameter was given
+ closes https://github.com/rsyslog/rsyslog/issues/911
+- bugfix imtcp: Messages not terminated by a NL were discarded
+ ... upon connection termination.
+ Thanks to Tomas Heinrich for the patch.
+------------------------------------------------------------------------------
+Version 8.17.0 [v8-stable] 2016-03-08
+- NEW REQUIREMENT: libfastjson
+ see also:
+ http://blog.gerhards.net/2015/12/rsyslog-and-liblognorm-will-switch-to.html
+- new testbench requirement: faketime command line tool
+ This is used to generate a controlled environment for time-based tests; if
+ not available, tests will gracefully be skipped.
+- improve json variable performance
+ We use libfastjson's alternative hash function, which has been
+ proven to be much faster than the default one (which stems
+ back to libjson-c). This should bring an overall performance
+ improvement for all operations involving variable processing.
+ closes https://github.com/rsyslog/rsyslog/issues/848
+- new experimental feature: lookup table support
+ Note that at this time, this is an experimental feature which is not yet
+ fully supported by the rsyslog team. It is introduced in order to gain
+ more feedback and to make it available as early as possible because many
+ people consider it useful.
+ Thanks to Janmejay Singh for implementing this feature
+- new feature: dynamic statistics counters
+ which may be changed during rule processing
+ Thanks to Janmejay Singh for suggesting and implementing this feature
+- new contributed plugin: omamqp1 for AMQP 1.0-compliant brokers
+ Thanks to Ken Giusti for this module
+- new set of UTC-based $now family of variables ($now-utc, $year-utc, ...)
+- simplified locking when accessing message and local variables
+ this simplifies the code and slightly increases performance if such
+ variables are heavily accessed.
+- new global parameter "debug.unloadModules"
+ This permits to disable unloading of modules, e.g. to make valgrind
+ reports more useful (without a need to recompile).
+- timestamp handling: guard against invalid dates
+ We do not permit dates outside of the year 1970..2100
+ interval. Note that network-receivers do already guard
+ against this, so the new guard only guards against invalid
+ system time.
+- imfile: add "trimlineoverbytes" input parameter
+ Thanks to github user JindongChen for the patch.
+- ommongodb: add support for extended json format for dates
+ Thanks to Florian Bücklers for the patch.
+- omjournal: add support for templates
+ see also: https://github.com/rsyslog/rsyslog/pull/770
+ Thanks to github user bobthemighty for the patch
+- imuxsock: add "ruleset" input parameter
+- testbench: framework improvement: configs can be included in test file
+ they do no longer need to be in a separate file, which saves a bit
+ of work when working with them. This is supported for simple tests with
+ a single running rsyslog instance
+ Thanks to Janmejay Singh for inspiring me with a similar method in
+ liblognorm testbench.
+- imptcp: performance improvements
+ Thanks to Janmejay Singh for implementing this improvement
+- made build compile (almost) without warnings
+ still some warnings are suppressed where this is currently required
+- improve interface definition in some modules, e.g. mmanon, mmsequence
+ This is more an internal cleanup and should have no actual affect to
+ the end user.
+- solaris build: MAXHOSTNAMELEN properly detected
+- build system improvement: ability to detect old hiredis libs
+ This permits to automatically build omhiredis on systems where the
+ hiredis libs do not provide a pkgconfig file. Previously, this
+ required manual configuration.
+ Thanks to github user jaymell for the patch.
+- rsgtutil: dump mode improvements
+ * auto-detect signature file type
+ * ability to dump hash chains for log extraction files
+- build system: fix build issues with clang
+ clang builds often failed with a missing external symbol
+ "rpl_malloc". This was caused by checks in configure.ac,
+ which checked for specific GNU semantics. As we do not need
+ them (we never ask malloc for zero bytes), we can safely
+ remove the macros.
+ Note that we routinely run clang static analyzer in CI and
+ it also detects such calls as invalid.
+ closes https://github.com/rsyslog/rsyslog/issues/834
+- bugfix: unixtimestamp date format was incorrectly computed
+ The problem happened in leap year from March til then end
+ of year and healed itself at the beginning of the next year.
+ During the problem period, the timestamp was 24 hours too low.
+ fixes https://github.com/rsyslog/rsyslog/issues/830
+- bugfix: date-ordinal date format was incorrectly computed
+ same root cause aus for unixtimestamp and same triggering
+ condition. During the affected perido, the ordinal was one
+ too less.
+- bugfix: some race when shutting down input module threads
+ this had little, if at all, effect on real deployments as it resulted
+ in a small leak right before rsyslog termination. However, it caused
+ trouble with the testbench (and other QA tools).
+ Thanks to Peter Portante for the patch and both Peter and Janmejay
+ Singh for helping to analyze what was going on.
+- bugfix tcpflood: did not handle connection drops correct in TLS case
+ note that tcpflood is a testbench too. The bug caused some testbench
+ instability, but had no effect on deployments.
+- bugfix: abort if global parameter value was wrong
+ If so, the abort happened during startup. Once started,
+ all was stable.
+- bugfix omkafka: fix potential NULL pointer addressing
+ this happened when the topic cache was full and an entry
+ needed to be evicted
+- bugfix impstats: @cee cookie was prefixed to wrong format (json vs. cee)
+ Thanks to Volker Fröhlich for the fix.
+- bugfix imfile: fix race during startup that could lead to some duplication
+ If a to-be-monitored file was created after inotify was initialized
+ but before startup was completed, the first chunk of data from this
+ file could be duplicated. This should have happened very rarely in
+ practice, but caused occasional testbench failures.
+ see also: https://github.com/rsyslog/rsyslog/issues/791
+- bugfix: potential loss of single message at queue shutdown
+ see also: https://github.com/rsyslog/rsyslog/issues/262
+- bugfix: potential deadlock with heavy variable access
+ When making heavy use of global, local and message variables, a deadlock
+ could occur. While it is extremely unlikely to happen, we have at least
+ seen one incarnation of this problem in practice.
+- bugfix ommysql: on some platforms, serverport parameter had no effect
+ This was caused by an invalid code sequence which's outcome depends on
+ compiler settings.
+- bugfix omelasticsearch: invalid pointer dereference
+ The actual practical impact is not clear. This came up when working
+ on compiler warnings.
+ Thanks to David Lang for the patch.
+- bugfix omhiredis: serverport config parameter did not reliably work
+ depended on environment/compiler used to build
+- bugfix rsgtutil: -h command line option did not work
+ Thanks to Henri Lakk for the patch.
+- bugfix lexer: hex numbers were not properly represented
+ see: https://github.com/rsyslog/rsyslog/pull/771
+ Thanks to Sam Hanes for the patch.
+- bugfix TLS syslog: intermittent errors while sending data
+ Regression from commit 1394e0b. A symptom often seen was the message
+ "unexpected GnuTLS error -50 in nsd_gtls.c:530"
+- bugfix imfile: abort on startup if no slash was present in file name param
+ Thanks to Brian Knox for the patch.
+- bugfix rsgtutil: fixed abort when using short command line options
+ Thanks to Henri Lakk
+- bugfix rsgtutil: invalid computation of log record extraction file
+ This caused verification to fail because the hash chain was actually
+ incorrect. Depended on the input data set.
+ closes https://github.com/rsyslog/rsyslog/issues/832
+- bugfix build system: KSI components could only be build if in default path
+------------------------------------------------------------------------------
+Version 8.16.0 [v8-stable] 2016-01-26
+- rsgtutil: Added extraction support including loglines and hash chains.
+ More details on how to extract loglines can be found in the rsgtutil
+ manpage. See also: https://github.com/rsyslog/rsyslog/issues/561
+- clean up doAction output module interface
+ We started with char * pointers, but used different types of pointers
+ over time. This lead to alignment warnings. In practice, I think this
+ should never cause any problems (at least there have been no reports
+ in the 7 or so years we do this), but it is not clean. The interface is
+ now cleaned up. We do this in a way that does not require modifications
+ to modules that just use string parameters. For those with message
+ parameters, have a look at e.g. mmutf8fix to see how easy the
+ required change is.
+- new system properties for $NOW properties based on UTC
+ This permits to express current system time in UTC.
+ See also https://github.com/rsyslog/rsyslog/issues/729
+- impstats: support broken ElasticSearch JSON implementation
+ ES 2.0 no longer supports valid JSON and disallows dots inside names.
+ This adds a new "json-elasticsearch" format option which replaces
+ those dots by the bang ("!") character. So "discarded.full" becomes
+ "discarded!full".
+ This is a workaround. A method that will provide more control over
+ replacements will be implemented some time in the future. For
+ details, see below-quoted issue tracker.
+ closes https://github.com/rsyslog/rsyslog/issues/713
+- omelasticsearch: craft better URLs
+ Elasticsearch is confused by url's ending in a bare '?' or '&'. While
+ this is valid, those are no longer produced.
+ Thanks to Benno Evers for the patch.
+- imfile: add experimental "reopenOnTruncate" parameter
+ Thanks to Matthew Wang for the patch.
+- bugfix imfile: proper handling of inotify initialization failure
+ Thanks to Zachary Zhao for the patch.
+- bugfix imfile: potential segfault due to improper handling of ev var
+ This occurs in inotify mode, only.
+ Thanks to Zachary Zhao and Peter Portante for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/718
+- bugfix imfile: potential segfault under heavy load.
+ This occurs in inotify mode when using wildcards, only.
+ The root cause is dropped IN_IGNORED inotify events which be dropped
+ in circumstance of high input pressure and frequent rotation, and
+ according to wikipeida, they can also be dropped in other conditions.
+ Thanks to Zachary Zhao for the patch.
+ closes https://github.com/rsyslog/rsyslog/issues/723
+- bugfix ommail: invalid handling of server response
+ if that response was split into different read calls. Could lead to
+ error-termination of send operation. Problem is pretty unlikely to
+ occur in standard setups (requires slow connection to SMTP server).
+ Thank to github user haixingood for the patch.
+- bugfix omelasticsearch: custom serverport was ignored on some platforms
+ Thanks to Benno Evers for the patch.
+- bugfix: tarball did not include some testbench files
+ Thanks to Thomas D. (whissi) for the patch.
+- bugfix: memory misaddressing during config parsing string template
+ This occurred if an (invalid) template option larger than 63 characters
+ was given.
+ Thanks to git hub user c6226 for the patch.
+- bugfix imzmq: memory leak
+ Thanks to Jeremy Liang for the patch.
+- bugfix imzmq: memory leak
+ Thanks to github user xushengping for the patch.
+- bugfix omzmq: memory leak
+ Thanks to Jack Lin for the patch.
+- some code improvement and cleanup
+------------------------------------------------------------------------------
+Version 8.15.0 [v8-stable] 2015-12-15
+- KSI Lib: Updated code to run with libksi 3.4.0.5
+ Also libksi 3.4.0.x is required to build rsyslog if ksi support
+ is enabled. New libpackages have been build as well.
+- KSI utilities: Added option to ser publication url.
+ Since libksi 3.4.0.x, there is no default publication url anymore.
+ The publication url has to be set using the --publications-server
+ Parameter, otherwise the ksi signature cannot be verified. UserID
+ and UserKey can also be set by parameter now.
+ Closes https://github.com/rsyslog/rsyslog/issues/581
+- KSI Lib: Fixed wrong TLV container for KSI signatures from 0905 to 0906.
+ closes https://github.com/rsyslog/rsyslog/issues/587
+- KSI/GT Lib: Fixed multiple issues found using static analyzer
+- performance improvement for configs with heavy use of JSON variables
+ Depending on the config, this can be a very big gain in performance.
+- added pmpanngfw: contributed module for translating Palo Alto Networks logs.
+ see also: https://github.com/rsyslog/rsyslog/pull/573
+ Thanks to Luigi Mori for the contribution.
+- testbench: Changed valgrind option for imtcp-tls-basic-vg.sh
+ For details see: https://github.com/rsyslog/rsyslog/pull/569
+- pmciscoios: support for asterisk before timestamp added
+ thanks to github user c0by for the patch
+ see also: https://github.com/rsyslog/rsyslog/pull/583
+- solr external output plugin much enhanced
+ see also: https://github.com/rsyslog/rsyslog/pull/529
+ Thanks to Radu Gheorghe for the patch.
+- omrabbitmq: improvements
+ thanks to Luigi Mori for the patch
+ see also: https://github.com/rsyslog/rsyslog/pull/580
+- add support for libfastjson (as a replacement for json-c)
+- KSI utilities: somewhat improved error messages
+ Thanks to Henri Lakk for the patch.
+ see also: https://github.com/rsyslog/rsyslog/pull/588
+- pmciscoios: support for some format variations
+ Thanks to github user c0by for the patch
+- support grok via new contributed module mmgrok
+ Thanks to 饶ç›ç³ (github user chenryn) for the contribution.
+- omkafka: new statistics counter "maxoutqsize"
+ Thanks to 饶ç›ç³ (github user chenryn) for the contribution.
+- improvements for 0mq modules:
+ * omczmq - suspend / Retry handling - the output plugin can now recover
+ from some error states due to issues with plugin startup or message sending
+ * omczmq - refactored topic handling code for ZMQ_PUB output to be a little
+ more efficient
+ * omczmq - added ability to set a timeout for sends
+ * omczmq - set topics can be in separate frame (default) or part of message
+ frame (configurable)
+ * omczmq - code cleanup
+ * imczmq - code cleanup
+ * imczmq - fixed a couple of cases where vars could be used uninitialized
+ * imczmq - ZMQ_ROUTER support
+ * imczmq - Fix small memory leak from not freeing sockets when done with them
+ * allow creation of on demand ephemeral CurveZMQ certs for encryption.
+ Clients may specify clientcertpath="*" to indicate they want an on
+ demand generated cert.
+ Thanks to Brian Knox for the contributions.
+- cleanup on code to unset a variable
+ under extreme cases (very, very unlikely), the old code could also lead
+ to erroneous processing
+- omelasticsearch: build on FreeBSD
+ Thanks to github user c0by for the patch
+- pmciscoios: fix some small issues clang static analyzer detected
+- testbench: many improvements and some new tests
+ note that there still is a number of tests which are somewhat racy
+- overall code improvements thanks to clang static analyzer
+- gnutls fix: Added possible fix for gnutls issue #575
+ see also: https://github.com/rsyslog/rsyslog/issues/575
+ Thanks to Charles Southerland for the patch
+- bugfix omkafka: restore ability to build on all platforms
+ Undo commit aea09800643343ab8b6aa205b0f10a4be676643b
+ because that lead to build failures on various important platforms.
+ This means it currently is not possible to configure the location
+ of librdkafka, but that will affect far fewer people.
+ closes: https://github.com/rsyslog/rsyslog/issues/596
+- bugfix omkafka: fix potentially negative partition number
+ Thanks to Tait Clarridge for providing a patch.
+- bugfix: solve potential race in creation of additional action workers
+ Under extreme circumstances, this could lead to segfault. Note that we
+ detected this problem thanks to ASAN address sanitizer in combination
+ with a very extreme testbench test. We do not think that this issue
+ was ever reported in practice.
+- bugfix: potential memory leak in config parsing
+ Thanks to github user linmujia for the patch
+- bugfix: small memory leak in loading template config
+ This happened when a plugin was used inside the template. Then, the
+ memory for the template name was never freed.
+ Thanks to github user xushengping for the fix.
+- bugfix: fix extra whitespace in property expansions
+ Address off-by-one issues introduced in f3bd7a2 resulting in extra
+ whitespace in property expansions
+ Thanks to Matthew Gabeler-Lee for the patch.
+- bugfix: mmfields leaked memory if very large messages were processed
+ detected by clang static analyzer
+- bugfix: mmfields could add garbage data to field
+ this happened when very large fields were to be processed.
+ Thanks to Peter Portante for reporting this.
+- bugfix: omhttpfs now also compiles with older json-c lib
+- bugfix: memory leak in (contributed) module omhttpfs
+ Thanks to git hub user c6226 for the patch.
+- bugfix: parameter mismatch in error message for wrap() function
+- bugfix: parameter mismatch in error message for random() function
+- bugfix: divide by zero if max() function was provided zero
+- bugfix: invalid mutex handling in omfile async write mode
+ could lead to segfault, even though highly unlikely (caught by
+ testbench on a single platform)
+- bugfix: fix inconsistent number processing
+ Unfortunately, previous versions of the rule engine tried to
+ support oct and hex, but that wasn't really the case.
+ Everything based on JSON was just dec-converted. As this was/is
+ the norm, we fix that inconsistency by always using dec.
+ Luckily, oct and hex support was never documented and could
+ probably only have been activated by constant numbers.
+- bugfix: timezone() object: fix NULL pointer dereference
+ This happened during startup when the offset or id parameter was not
+ given. Could lead to a segfault at startup.
+ Detected by clang static analyzer.
+- bugfix omfile: memory addressing error if very long outchannel name used
+ Thanks to github user c6226 for the patch.
+------------------------------------------------------------------------------
+Version 8.14.0 [v8-stable] 2015-11-03
+- Added possibility to customize librdkafka location
+ see also: https://github.com/rsyslog/rsyslog/pull/502
+ Thanks to Matthew Wang for the patch.
+- add property "rawmsg-after-pri"
+- bugfix: potential misaddresseing in imfile
+ Could happen when wildcards were used.
+ see also https://github.com/rsyslog/rsyslog/issues/532
+ see also https://github.com/rsyslog/rsyslog/issues/534
+ Thanks to zhangdaoling for the bugfix.
+- bugfix: re_extract RainerScript function did not work
+ Thanks to Janmejay Singh for the patch
+------------------------------------------------------------------------------
+Version 8.13.0 [v8-stable] 2015-09-22
+- ZeroMQ enhancements:
+ * Added the ability to set a static publishing topic per action as an
+ alternative to constructing topics with templates
+ Contributor: Luca Bocassi
+ * ZMQ_PUB socket now defaults to bind and ZMQ_SUB socket now defaults to
+ connect - Contributor: Luca Bocassi
+- Redis enhancements:
+ * Can now LPUSH to a Redis list in "queue" mode - Contributor: Brian Knox
+ * Can now PUBLISH to a Redis channel in "publish" mode
+ Contributor: Brian Knox
+- build requirement for rsyslog/mmnormalize is now liblognorm 1.1.2 or above
+- mmnormalize: liblognorm error messages are now emitted via regular
+ rsyslog error reporting mechanism (aka "are now logged")
+ This is possible due to a new API in liblognorm 1.1.2;
+ Note that the amount of error messages depends on the version of
+ liblognorm used.
+- add support for TCP client side keep-alives
+ Thanks to github user tinselcity for the patch.
+- bugfix: imtcp/TLS hangs on dropped packets
+ see also https://github.com/rsyslog/rsyslog/issues/318
+ Thanks to github user tinselcity for the patch.
+- bugfix testbench: some tests using imptcp are run if module is disabled
+ Thanks to Michael Biebl for reporting this
+ see also https://github.com/rsyslog/rsyslog/issues/524
+- bugfix omkafka: Fixes a bug not accepting new messages anymore.
+ see also: https://github.com/rsyslog/rsyslog/pull/472
+ Thanks to Janmejay Singh
+- bugfix: Parallel build issue "cannot find ../runtime/.libs/librsyslog.a:
+ No such file or directory" (#479) fixed.
+ Thanks to Thomas D. (Whissi) for the patch.
+- bugfix: Added missing mmpstrucdata testfiles into makefile.
+ see also: https://github.com/rsyslog/rsyslog/issues/484
+- bugfix: Reverted FIX for issue #392 as it had unexpected side effects.
+ The new fix duplicates the Listener object for static files (like
+ done for dynamic files already), resolving issue #392 and #490.
+ see also https://github.com/rsyslog/rsyslog/pull/490
+- bugfix: issues in queue subsystem if syncqueuefiles was enabled
+ * Error 14 was generated on the .qi file directory handle.
+ As the .qi filestream does not have a directory set, fsync
+ was called on an empty directory causing a error 14 in debug log.
+ * When queue files existed on startup, the bSyncQueueFiles
+ strm property was not set to 1. This is now done in the
+ qqueueLoadPersStrmInfoFixup function.
+- bugfix/testbench: tcpflood tool could abort when random data was added
+ see also: https://github.com/rsyslog/rsyslog/issues/506
+ Thanks to Louis Bouchard for the fix
+- rscryutil: Added support to decrypt a not closed log file.
+ Thanks to wizard1024 for the patch.
+------------------------------------------------------------------------------
+Version 8.12.0 [v8-stable] 2015-08-11
+- Harmonize resetConfigVariables values and defaults
+ see also https://github.com/rsyslog/rsyslog/pull/413
+ Thanks to Tomas Heinrich for the patch.
+- GT/KSI: fix some issues in signature file format and add conversion tool
+ The file format is incompatible to previous format, but tools have been
+ upgraded to handle both and also an option been added to convert from
+ old to new format.
+- bugfix: ommysql did not work when gnutls was enabled
+ as it turned out, this was due to a check for GnuTLS functions
+ with the side-effect that
+ AC_CHECK_LIB, by default, adds the lib to LIBS, if there is no
+ explicit action, what was the case here. So everything was now
+ linked against GnuTLS, which in turn made ommysql fail.
+ Thanks to Thomas D. (whissi) for the analysis of the ommysql/gnutls
+ problem and Thomas Heinrich for pointing out that AC_CHECK_LIB might
+ be the culprit.
+- bugfix omfile: potential memory leak on file close
+ see also: https://github.com/rsyslog/rsyslog/pull/423
+ Thanks to Robert Schiele for the patch.
+- bugfix omfile: potential race in dynafile detection/creation
+ This could lead to a segfault.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix omfile: Fix race-condition detection in path-creation code
+ The affected code is used to detect a race condition in between
+ testing for the existence of a directory and creating it if it didn't
+ exist. The variable tracking the number of attempts wasn't reset for
+ subsequent elements in the path, thus limiting the number of
+ reattempts to one per the whole path, instead of one per each path
+ element.
+ This solution was provided by Martin Poole.
+- bugfix parser subsystem: potential misaddressing in SanitizeMsg()
+ could lead to a segfault
+ Thanks to Tomas Heinrich for the patch.
+- imfile: files moved outside of directory are now (properly) handled
+- bugfix: imfile: segfault when using startmsg.regex if first log line
+ doesn't match
+ Thanks to Ciprian Hacman for the patch.
+- bugfix imfile: file table was corrupted when on file deletion
+ This could happen when a file that was statically configured (not via an
+ wildcard) was deleted.
+- bugfix ompgsql: transaction were improperly handled
+ now transaction support is solidly disabled until we have enough requests
+ to implement it again. Module still works fine in single insert mode.
+ closes https://github.com/rsyslog/rsyslog/issues/399
+- bugfix mmjsonparse: memory leak if non-cee-json message is processed
+ see also https://github.com/rsyslog/rsyslog/pull/383
+ Thanks to Anton Matveenko for the patch
+- testbench: remove raciness from UDP based tests
+- testbench: added bash into all scripts making it mandatory
+- bugfix testbench: Fixed problem building syslog_caller util when
+ liblogging-stdlog is not available.
+ Thanks to Louis Bouchard for the patch
+- bugfix rscryutil.1: Added fix checking for generate_man_pages condition
+ Thanks to Radovan Sroka for the patch
+- bugfix freebsd console: \n (NL) is prepended with \r (CR) in console
+ output on freebsd only. For more details see here:
+ https://github.com/rsyslog/rsyslog/issues/372
+ Thanks to AlexandreFenyo for the patch
+------------------------------------------------------------------------------
+Version 8.11.0 [v8-stable] 2015-06-30
+- new signature provider for Keyless Signature Infrastructure (KSI) added
+- build system: re-enable use of "make distcheck"
+- add new signature provider for Kesless Signature Infrastructure (KSI)
+ This has also been added to existing tooling; KSI is kind of v2 of
+ the Guardtime functionality and has been added in the appropriate
+ places.
+- bugfix imfile: regex multiline mode ignored escapeLF option
+ Thanks to Ciprian Hacman for reporting the problem
+ closes https://github.com/rsyslog/rsyslog/issues/370
+- bugfix omkafka: fixed several concurrency issues, most of them related
+ to dynamic topics.
+ Thanks to Janmejay Singh for the patch.
+- bugfix: execonlywhenpreviousissuspended did not work correctly
+ This especially caused problems when an action with this attribute was
+ configured with an action queue.
+- bugfix core engine: ensured global variable atomicity
+ This could lead to problems in RainerScript, as well as probably in other
+ areas where global variables are used inside rsyslog. I wouldn't outrule
+ it could lead to segfaults.
+ Thanks to Janmejay Singh for the patch.
+- bugfix imfile: segfault when using startmsg.regex because of empty log line
+ closes https://github.com/rsyslog/rsyslog/issues/357
+ Thanks to Ciprian Hacman for the patch.
+- bugfix: build problem on Solaris
+ Thanks to Dagobert Michelsen for reporting this and getting us up to
+ speed on the openCWS build farm.
+- bugfix: build system strndup was used even if not present
+ now added compatibility function. This came up on Solaris builds.
+ Thanks to Dagobert Michelsen for reporting the problem.
+ closes https://github.com/rsyslog/rsyslog/issues/347
+- bugfix imjournal: do not pass empty messages to rsyslog core
+ this causes a crash of the daemon
+ see also https://github.com/rsyslog/rsyslog/pull/412
+ Thanks to Tomas Heinrich for the patch.
+- bugfix imjournal: cosmetic memory leak
+ very small and an shutdown only, so did not affect operations
+ see also https://github.com/rsyslog/rsyslog/pull/411
+ Thanks to Tomas Heinrich for the patch.
+------------------------------------------------------------------------------
+Version 8.10.0 [v8-stable] 2015-05-19
+- imfile: add capability to process multi-line messages based on regex
+ input parameter "endmsg.regex" was added for that purpose. The new
+ mode provides much more power in processing different multiline-formats.
+- pmrfc3164: add new parameters
+ * "detect.yearAfterTimestamp"
+ This supports timestamps as generated e.g. by some Aruba Networks
+ equipment.
+ * "permit.squareBracesInHostname"
+ Permits to use "hostnames" in the form of "[127.0.0.1]"; also seen in
+ Aruba Networks equipment, but we strongly assume this can also happen
+ in other cases, especially with IPv6.
+- supplementary groups are now set when dropping privileges
+ closes https://github.com/rsyslog/rsyslog/issues/296
+ Thanks to Zach Lisinski for the patch.
+- imfile: added brace glob expansion to wildcard
+ Thanks to Zach Lisinski for the patch.
+- zmq: add the ability for zeromq input and outputs to advertise their
+ presence on UDP via the zbeacon API.
+ Thanks to Brian Knox for the contribution.
+- added omhttpfs: contributed module for writing to HDFS via HTTP
+ Thanks to sskaje for the contribution.
+- Configure option "--disable-debug-symbols" added which is disabled per
+ default. If you set the new option, configure won't set the appropriate
+ compiler flag to generate debug symbols anymore.
+- When building from git source we now require rst2man and yacc (or a
+ replacement like bison).
+ That isn't any new requirement, we only added missing configure checks.
+- Configure option "--enable-generate-man-pages" is now disabled for non git
+ source builds per default but enforced when building from git source.
+- mmpstrucdata: some code cleanup
+ removed lots of early development debug outputs
+- bugfix imuxsock: fix a memory leak that happened with large messages
+ ... when annotation was enabled.
+ Thanks to github user c6226 for the patch
+- bugfix omhttpfs: memory leak
+ Thanks to github user c6226 for the patch
+- bugfix imuxsock: fix a crash when setting a hostname
+ Setting a hostname via the legacy directive would lead to a crash
+ during shutdown caused by a double-free.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: memory leak in mmpstrucdata
+ Thanks to Grégoire Seux for reporting this issue.
+ closes https://github.com/rsyslog/rsyslog/issues/310
+- bugfix (minor): default action name: assigned number was one off
+ see also https://github.com/rsyslog/rsyslog/pull/340
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: memory leak in imfile
+ A small leak happened each time a new file was monitored based on
+ a wildcard. Depending on the rate of file creation, this could result
+ in a serious memory leak.
+------------------------------------------------------------------------------
+Version 8.9.0 [v8-stable] 2015-04-07
+- omprog: add option "hup.forward" to forwards HUP to external plugins
+ This was suggested by David Lang so that external plugins (and other
+ programs) can also do HUP-specific processing. The default is not
+ to forward HUP, so no change of behavior by default.
+- imuxsock: added capability to use regular parser chain
+ Previously, this was a fixed format, that was known to be spoken on
+ the system log socket. This also adds new parameters:
+ - sysSock.useSpecialParser module parameter
+ - sysSock.parseHostname module parameter
+ - useSpecialParser input parameter
+ - parseHostname input parameter
+- 0mq: improvements in input and output modules
+ See module READMEs, part is to be considered experimental.
+ Thanks to Brian Knox for the contribution.
+- imtcp: add support for ip based bind for imtcp -> param "address"
+ Thanks to github user crackytsi for the patch.
+- bugfix: MsgDeserialize out of sync with MsgSerialize for StrucData
+ This lead to failure of disk queue processing when structured data was
+ present. Thanks to github user adrush for the fix.
+- bugfix imfile: partial data loss, especially in readMode != 0
+ closes https://github.com/rsyslog/rsyslog/issues/144
+- bugfix: potential large memory consumption with failed actions
+ see also https://github.com/rsyslog/rsyslog/issues/253
+- bugfix: omudpspoof: invalid default send template in RainerScript format
+ The file format template was used, which obviously does not work for
+ forwarding. Thanks to Christopher Racky for alerting us.
+ closes https://github.com/rsyslog/rsyslog/issues/268
+- bugfix: size-based legacy config statements did not work properly
+ on some platforms, they were incorrectly handled, resulting in all
+ sorts of "interesting" effects (up to segfault on startup)
+- build system: added option --without-valgrind-testbench
+ ... which provides the capability to either enforce or turn off
+ valgrind use inside the testbench. Thanks to whissi for the patch.
+- rsyslogd: fix misleading typos in error messages
+ Thanks to Ansgar Püster for the fixes.
+------------------------------------------------------------------------------
+Version 8.8.0 [v8-stable] 2015-02-24
+- omkafka: add support for dynamic topics and auto partitioning
+ Thanks to Tait Clarridge for the patches.
+- imtcp/imptcp: support for broken Cisco ASA TCP syslog framing
+- omfwd: more detailed error messages in case of UDP send error
+- TLS syslog: enable capability to turn on GnuTLS debug logging
+ This provides better diagnostics in hard-to-diagnose cases,
+ especially when GnuTLS is extra-picky about certificates.
+- bugfix: $AbortOnUncleanConfig did not work
+- improve rsyslogd -v output and error message with meta information
+ version number is now contained in error message and build platform in
+ version output. This helps to gets rid of the usual "which version"
+ question on mailing list, support forums, etc...
+- bugfix imtcp: octet-counted framing cannot be turned off
+- bugfix: build problems on Illuminos
+ Thanks to Andrew Stormont for the patch
+- bugfix: invalid data size for iMaxLine global property
+ It was defined as int, but inside the config system it was declared as
+ size type, which uses int64_t. With legacy config statements, this could
+ lead to misaddressing, which usually meant the another config variable was
+ overwritten (depending on memory layout).
+ closes https://github.com/rsyslog/rsyslog/issues/205
+- bugfix: negative values for maxMessageSize global parameter were permitted
+------------------------------------------------------------------------------
+Version 8.7.0 [v8-stable] 2015-01-13
+- add message metadata "system" to msg object
+ this permits to store metadata alongside the message
+- imfile: add support for "filename" metadata
+ this is useful in cases where wildcards are used
+- imptcp: make stats counter names consistent with what imudp, imtcp uses
+- added new module "omkafka" to support writing to Apache Kafka
+- omfwd: add new "udp.senddelay" parameter
+- mmnormalize enhancements
+ Thanks to Janmejay Singh for the patch.
+- RainerScript "foreach" iterator and array reading support
+ Thanks to Janmejay Singh for the patch.
+- now requires liblognorm >= 1.0.2
+- add support for systemd >= 209 library names
+- BSD "ntp" facility (value 12) is now also supported in filter
+ Thanks to Douglas K. Rand of Iteris, Inc. for the patch.
+ Note: this patch was released under ASL 2.0 (see email-conversation).
+- bugfix: global(localHostName="xxx") was not respected in all modules
+- bugfix: emit correct error message on config-file-not-found
+ closes https://github.com/rsyslog/rsyslog/issues/173
+- bugfix: impstats emitted invalid JSON format (if JSON was selected)
+- bugfix: (small) memory leak in omfile's outchannel code
+ Thanks to Koral Ilgun for reporting this issue.
+- bugfix: imuxsock did not deactivate some code not supported by platform
+ Among potential other problems, this caused build failure under Solaris.
+ Note that this build problem just made a broader problem appear that so
+ far always existed but was not visible.
+ closes https://github.com/rsyslog/rsyslog/issues/185
+------------------------------------------------------------------------------
+Version 8.6.0 [v8-stable] 2014-12-02
+NOTE: This version also incorporates all changes and enhancements made for
+v8.5.0, but in a stable release. For details see immediately below.
+- configuration-setting rsyslogd command line options deprecated
+ For most of them, there are now proper configuration objects. Some few
+ will be completely dropped if nobody insists on them. Additional info at
+ http://blog.gerhards.net/2014/11/phasing-out-legacy-command-line-options.html
+- new and enhanced plugins for 0mq. These are currently experimental.
+ Thanks to Brian Knox who contributed the modules and is their author.
+- empty rulesets have been permitted. They no longer raise a syntax error.
+- add parameter -N3 to enable config check of partial config file
+ Use for config include files. Disables checking if any action exists at
+ all.
+- rsyslogd -e option has finally been removed
+ It is deprecated since many years.
+- testbench improvements
+ Testbench is now more robust and has additional tests.
+- testbench is now by default disabled
+ To enable it, use --enable-testbench. This was done as the testbench now
+ does better checking if required modules are present and this in turn
+ would lead to configure error messages where non previously were if we
+ would leave --enable-testbench on by default. Thus we have turned it off.
+ This should not be an issue for those few testbench users.
+- add new RainerScript functions warp() and replace()
+ Thanks to Singh Janmejay for the patch.
+- mmnormalize can now also work on a variable
+ Thanks to Singh Janmejay for the patch.
+- new property date options for day ordinal and week number
+ Thanks to github user arrjay for the patch
+- remove --enable-zlib configure option, we always require it
+ It's hard to envision a system without zlib, so we turn this off
+ closes https://github.com/rsyslog/rsyslog/issues/76
+- slight source-tree restructuring: contributed modules are now in their
+ own ./contrib directory. The idea is to make it clearer to the end user
+ which plugins are supported by the rsyslog project (those in ./plugins).
+- bugfix: imudp makes rsyslog hang on shutdown when more than 1 thread used
+ closes https://github.com/rsyslog/rsyslog/issues/126
+- bugfix: not all files closed on auto-backgrounding startup
+ This could happen when not running under systemd. Some low-numbered
+ fds were not closed in that case.
+- bugfix: typo in queue configuration parameter
+ made parameter unusable
+ Thanks to Bojan Smojver for the patch.
+- bugfix: uninitialized buffer off-by-one error in hostname generation
+ The DNS cache used uninitialized memory, which could lead to
+ invalid hostname generation.
+ Thanks to Jarrod Sayers for alerting us and providing analysis and
+ patch recommendations.
+- bugfix imuxsock: possible segfault when SysSock.Use="off"
+ Thanks to alexjfisher for reporting this issue.
+ closes https://github.com/rsyslog/rsyslog/issues/140
+- bugfix: RainerScript: invalid ruleset names were accepted
+ during ruleset definition, but could of course not be used when
+ e.g. calling a ruleset.
+ IMPORTANT: this may cause existing configurations to error out on start,
+ as they invalid names could also be used e.g. when assigning rulesets.
+- bugfix: some module entry points were not called for all modules
+ callbacks like endCnfLoad() were primarily being called for input
+ modules. This has been corrected. Note that this bugfix has some
+ regression potential.
+- bugfix omlibdbi: connection was taken down in wrong thread
+ this could have consequences depending on the driver being used. In
+ general, it looks more like a cosmetic issue. For example, with
+ MySQL it lead to a small memory but also an annoying message about
+ a thread not properly torn down.
+- imttcp was removed because it was an incomplete experimental module
+- pmrfc3164sd because it was a custom module nobody used
+ We used to keep this as a sample inside the tree, but whoever wants
+ to look at it can check in older versions inside git.
+- omoracle was removed because it was orphaned and did not build/work
+ for quite some years and nobody was interested in fixing it
+---------------------------------------------------------------------------
+Version 8.5.0 [v8-stable] 2014-10-24
+- imfile greatly refactored and support for wildcards added
+- PRI-handling code refactored for more clarity and robustness
+- ommail: add support for RainerScript config system [action() object]
+ This finally adds support for the new config style. Also, we now permit
+ to set a constant subject text without the need to create a template for
+ it.
+- refactored the auto-backgrounding method
+ The code is now more robust and also offers possibilities for enhanced
+ error reporting in the future. This is also assumed to fix some races
+ where a system startup script hang due to "hanging" rsyslogd.
+- make gntls tcp syslog driver emit more error messages
+ Messages previously emitted only to the debug log are now emitted as
+ syslog error messages. It has shown that they contain information
+ helpful to the user for troubleshooting config issues. Note that this
+ change is a bit experimental, as we are not sure if there are situations
+ where large amounts of error messages may be emitted.
+- bugfix: imfile did not complain if configured file did not exist
+ closes https://github.com/rsyslog/rsyslog/issues/137
+- bugfix: build failure on systems which don't have json_tokener_errors
+ Older versions of json-c need to use a different API (which don't exists
+ on newer versions, unfortunately...)
+ Thanks to Thomas D. for reporting this problem.
+- imgssapi: log remote peer address in some error messages
+ Thanks to Bodik for the patch.
+---------------------------------------------------------------------------
+Version 8.4.3 [v8-stable] 2014-10-??
+- ommail: minor bugfixes & improvements
+ * timestamps were 1 hour out when using daylight saving times when
+ viewing emails in most email clients due to incorrect date format
+ * X-Mailer header had a typo in it
+ * To: header was duplicated once per recipient (this is permitted,
+ but an address list is a better choice nowadays)
+ Thanks to github user cacheus for the patches.
+- bugfix imkmsg: infinite loop on OpenVZ VMs
+ Thanks to github user PaulSD for the patch
+ closes https://github.com/rsyslog/rsyslog/pull/138
+- bugfix: typo in queue configuration parameter made parameter unusable
+ Thanks to Bojan Smojver for the patch.
+- bugfix: uninitialized buffer off-by-one error in hostname generation
+ The DNS cache used uninitialized memory, which could lead to
+ invalid hostname generation.
+ Thanks to Jarrod Sayers for alerting us and providing analysis and
+ patch recommendations.
+- bugfix imfile: segfault on startup in "inotify" mode
+ A segfault happened when more than one file was monitored.
+- bugfix imfile: could make rsyslog exit in inotify mode
+- bugfix: rsgtutil sometimes crashed in verify mode if file did not exist
+- bugfix imklog: pri was miscalculated
+ actually, the pri was totally off the real value for PRIs > 9
+- bugfix imfile:file processing in inotify mode was stalled sometimes
+ closes https://github.com/rsyslog/rsyslog/issues/134
+- bugfix: imjournal did not build properly
+ The build succeeded, but the module did not load due to a type in
+ a support function name, which kept unresolved during load.
+- bugfix: mmcount did no longer build
+ note that this is untested -- users of this module should file a bug if
+ the new (trivial) code is broken [if there are any users, thus I did not
+ invest time in testing...]
+ closes https://github.com/rsyslog/rsyslog/issues/129
+- bugfix imuxsock: possible segfault when SysSock.Use="off"
+ Thanks to alexjfisher for reporting this issue.
+ closes https://github.com/rsyslog/rsyslog/issues/140
+---------------------------------------------------------------------------
+Version 8.4.2 [v8-stable] 2014-10-02
+- bugfix: the fix for CVE-2014-3634 did not handle all cases
+ This is corrected now.
+ see also: CVE-2014-3683
+- fixed a build problem on some platforms
+ Thanks to Olaf for the patch
+- behavior change: "msg" of messages with invalid PRI set to "rawmsg"
+ When the PRI is invalid, the rest of the header cannot be valid. So
+ we move all of it to MSG and do not try to parse it out. Note that
+ this is not directly related to the security issue but rather done
+ because it makes most sense.
+---------------------------------------------------------------------------
+Version 8.4.1 [v8-stable] 2014-09-30
+- imudp: add for bracketing mode, which makes parsing stats easier
+- permit at-sign in variable names
+ closes: https://github.com/rsyslog/rsyslog/issues/110
+- bugfix: fix syntax error in anon_cc_numbers.py script
+ Thanks to github user anthcourtney for the patch.
+ closes: https://github.com/rsyslog/rsyslog/issues/109
+- bugfix: ompgsql: don't loose uncommitted data on retry
+ Thanks to Jared Johnson and Axel Rau for the patch.
+- bugfix: imfile: if a state file for a different file name was set,
+ that different file (name) was monitored instead of the configured
+ one. Now, the state file is deleted and the correct file monitored.
+ closes: https://github.com/rsyslog/rsyslog/issues/103
+- bugfix: omudpspoof: source port was invalid
+ Thanks to Pavel Levshin for the patch
+- bugfix: build failure on systems which don't have json_tokener_errors
+ Older versions of json-c need to use a different API (which don't exists
+ on newer versions, unfortunately...)
+ Thanks to Thomas D. for reporting this problem.
+- bugfix: omelasticsearch does not work with broken/changed ES 1.0+ API
+ closes: https://github.com/rsyslog/rsyslog/issues/104
+- bugfix: mmanon did not properly anonymize IP addresses starting with '9'
+ Thanks to defa-at-so36.net for reporting this problem.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=529
+- bugfix: build problems on SuSe Linux
+ Thanks Andreas Stieger for the patch
+- bugfix: omelasticsearch error file did not work correctly on ES 1.0+
+ due to a breaking change in the ElasticSearch API.
+ see also: https://github.com/rsyslog/rsyslog/issues/104
+- bugfix: potential abort when a message with PRI > 191 was processed
+ if the "pri-text" property was used in active templates, this could
+ be abused to a remote denial of service from permitted senders
+ see also: CVE-2014-3634
+---------------------------------------------------------------------------
+Version 8.4.0 [v8-stable] 2014-08-18
+- this is the new stable branch, which incorporates all enhancements of
+ rsyslog 8.3.
+---------------------------------------------------------------------------
+Version 8.3.5 [v8-devel] 2014-08-05
+- mmjsonparse: support selectable cookie and target containers
+ This permits to put different meanings into a json formatted syslog
+ message, e.g. the "traditional" cee or cim data.
+- bugfix: mmjsonparse did not build with json-c < 0.10
+ This was a regression introduced some time in the past in order to
+ support API changes in json-c. Now we check for the version and use
+ proper code.
+- omprog: emit error message via syslog() if loading binary fails
+ This happens after forking, so omprog has no longer access to rsyslog's
+ regular error reporting functions. Previously, this meant any error
+ message was lost. Now it is emitted via regular syslog (which may end up
+ in a different instance, if multiple instances run...)
+- couple of patches imported from v7-stable (7.6.4)
+---------------------------------------------------------------------------
+Version 8.3.4 [v8-devel] 2014-07-11
+- new pmciscoios parser supporting various Cisco IOS formats
+- RFC3164 timestamp parser now accepts timezones and subsecond resolution
+ ... at least for some common formats and where we could do so without
+ running risk of breaking proper formats (or introducing regressions)
+- new parser config object -- permits to define custom parser definitions
+- new tzinfo config object -- permits to define time zone offsets
+ This is a utility object that currently is being used by some parsers.
+- bugfix: mishandling of input modules not supporting new input instances
+ If they did not support this, accidentally the output module part of the
+ module union was written, leading to unpredictable results. Note: all
+ core modules do support this interface, but some contributed or very
+ old ones do not.
+- bugfix: double-free when ruleset() parser parameters were used
+ While unlikely, this could cause stability issues even after the
+ config phase.
+---------------------------------------------------------------------------
+Version 8.3.3 [v8-devel] 2014-06-26
+- unify input object naming
+ imudp now supports "name" parameter, as other inputs do. "inputname" has
+ been deprecated, but can still be used. Same applies to "appendport"
+ subparameter". Thanks to "Nick Syslog" for the suggestion.
+- made the missing (contributed) modules build under v8 [import from 8.2.2]
+ Modules:
+ * mmrfc5424addhmac
+ * omrabbitmq
+ * omgssapi
+ * omhdfs
+ * omzmq3
+- added a cleanup process (janitor); permits to close omfile files after a
+ timeout
+- make omgssapi build under v8.3 [import vom v8.2]
+ note that we could do this to the stable, because there is NO regression
+ chance at all: only omgssapi was changed, and this module did NOT work
+ previously.
+- removed obsolete --disable-fsstnd configure option
+ Thanks to Thomas D. for alerting us.
+ Closes: https://github.com/rsyslog/rsyslog/issues/72
+---------------------------------------------------------------------------
+Version 8.3.2 [v8-devel] 2014-05-02
+- new template options for date extraction:
+ - year
+ - month
+ - day
+ - wday
+ - hour
+ - minute
+ - second
+ - tzoffshour
+ - tzoffsmin
+ - tzoffsdirection
+ - wdayname
+ For string templates, these are property options and they are
+ prefixed with "date-" (e.g. "date-year", "date-month", ...)
+ see also: https://github.com/rsyslog/rsyslog/issues/65
+- bugfix: mmexternal remove framing char before processing JSON reply
+ This did not have any real bad effects, but caused unnecessary
+ processing, as empty replies were not properly detected. Otherwise,
+ the bug was not noticeable from the user's PoV.
+- bugfix: mmexternal segfault due to invalid free in non-json input mode
+ closes: https://github.com/rsyslog/rsyslog/issues/70
+- bugfix: mmexternal segfault when external plugin sent invalid reply
+ ... or no reply at all. This happened if the reply was improper JSON.
+ Now, we emit an error message in those cases.
+ see also: https://github.com/rsyslog/rsyslog/issues/69
+- bugfix: mmexternal did potentially pass incomplete data to restarted
+ external plugin
+ This could happen if EPIPE was returned "too late", in which case the
+ beginning of the data could be lost.
+- bugfix: mmexternal did not properly process messages over 4KiB
+ The data to be passed to the external plugin was truncated after 4KiB.
+ see: https://github.com/rsyslog/rsyslog/issues/64
+- imrelp: added support for per-listener ruleset and inputname
+ see: https://github.com/rsyslog/rsyslog/pull/63
+ Thanks to bobthesecurityguy github user for the patch
+---------------------------------------------------------------------------
+Version 8.3.1 [v8-devel] 2014-04-24
+- external message modification interface now support modifying message PRI
+- "jsonmesg" property will include uuid only if one was previously generated
+ This is primarily a performance optimization. Whenever the message uuid
+ is gotten, it is generated when not already present. As we used the
+ regular setter, this means that always the uuid was generated, which is
+ quite time-consuming. This has now been changed so that it only is
+ generated if it already exists. That also matches more closely the
+ semantics, as "jsonmesg" should not make modifications to the message.
+ Note that the same applies to "fulljson" passing mode for external
+ plugins.
+- added plugin to rewrite message facility and/or severity
+ Name: fac-sever-rewrite.py
+- permits to build against json-c 0.12
+ Unfortunately, json-c had an ABI breakage, so this is necessary. Note
+ that versions prior to 0.12 had security issues (CVE-2013-6370,
+ CVE-2013-6371) and so it is desirable to link against the new version.
+ Thanks to Thomas D. for the patch. Note that at least some distros
+ have fixed the security issue in older versions of json-c, so this
+ seems to apply mostly when building from sources.
+- bugfix: using UUID property could cause segfault
+- bugfix/mmexternal: memory leak
+- bugfix: memory leak when using "jsonmesg" property
+- bugfix: mmutf8fix did not detect two invalid sequences
+ Thanks to Axel Rau for the patch.
+- bugfix: build problems with lexer.l on some platforms
+ For some reason, the strdup() prototype and others are missing. I admit
+ that I don't know why, as this happens only in 8.3.0+ and there is no
+ indication of changes to the affected files. In any case, we need to
+ fix this, and the current solution works at least as an interim one.
+---------------------------------------------------------------------------
+Version 8.3.0 [v8-devel] 2014-04-10
+- new plugin for anonymizing credit card numbers
+ Thanks to Peter Slavov for providing the code.
+- external message modification modules are now supported
+ They are bound via the new native module "mmexternal". Also, a sample
+ skeleton for an external python message modification module has been
+ added.
+- new $jsonmesg property with JSON representation of whole message object
+ closes: https://github.com/rsyslog/rsyslog/issues/19
+- improved error message for invalid field extraction in string template
+ see also:
+ http://kb.monitorware.com/problem-with-field-based-extraction-t12299.html
+- fix build problems on Solaris
+- NOTE: a json-c API that we begun to use requires the compiler to be in
+ c99 mode. By default, we select it automatically. If you modify this and
+ use gcc, be sure to include "-std=c99" in your compiler flags. This seems
+ to be necessary only for older versions of gcc.
+---------------------------------------------------------------------------
+Version 8.2.3 [v8-stable] 2014-??-??
+- bugfix: ommysql: handle/mem leak upon termination of worker thread
+ This could become bad if the (instance) worker threads are often
+ started and terminated. But it takes quite a while to show effect.
+---------------------------------------------------------------------------
+Version 8.2.2 [v8-stable] 2014-06-02
+- made the missing (contributed) modules build under v8
+ Note that we could do this to the stable, because there is NO regression
+ chance at all: only the modules themselves were changed, and they did
+ NOT work at all previously. Please also note that most of these modules
+ did not yet receive real testing. As we don't have the necessary
+ environments (easily enough available), we depend on users submitting
+ error reports and helping to iron out any issues that may arise.
+ Modules:
+ * mmrfc5424addhmac
+ * omrabbitmq
+ * omgssapi
+ * omhdfs
+ * omzmq3
+---------------------------------------------------------------------------
+Version 8.2.1 [v8-stable] 2014-04-17
+- permits to build against json-c 0.12
+ Unfortunately, json-c had an ABI breakage, so this is necessary. Note
+ that versions prior to 0.12 had security issues (CVE-2013-6370,
+ CVE-2013-6371) and so it is desirable to link against the new version.
+ Thanks to Thomas D. for the patch. Note that at least some distros
+ have fixed the security issue in older versions of json-c, so this
+ seems to apply mostly when building from sources.
+- doc is no longer shipped as part of the rsyslog tarball
+ Instead, the rsyslog-doc project creates its own tarball. This is the
+ result of a mailing list discussion after the 8.2.0 release with a
+ tarball-in-tarball approach, which was disliked by almost all distro
+ maintainers. This move also has the advantage of de-coupling the
+ release cycles of both projects a bit (which turned out to be a bit
+ problematic in practice).
+- bugfix: mmutf8fix did not detect two invalid sequences
+ Thanks to Axel Rau for the patch.
+---------------------------------------------------------------------------
+Version 8.2.0 [v8-stable] 2014-04-02
+This starts a new stable branch based on 8.1.6 plus the following changes:
+- we now use doc from the rsyslog-doc project
+ As such, the ./doc subtree has been removed. Instead, a cache of the
+ rsyslog-doc project's files has been included in ./rsyslog-doc.tar.gz.
+ Note that the exact distribution mode for the doc is still under
+ discussion and may change in future releases.
+ This was agreed upon on the rsyslog mailing list. For doc issues
+ and corrections, be sure to work with the rsyslog-doc project. It is
+ currently hosted at https://github.com/rsyslog/rsyslog-doc
+- add support for specifying the liblogging-stdlog channel spec
+ new global parameter "stdlog.channelspec"
+- add "defaultnetstreamdrivercertfile" global variable to set a default
+ for the certfile.
+ Thanks to Radu Gheorghe for the patch.
+- omelasticsearch: add new "usehttps" parameter for secured connections
+ Thanks to Radu Gheorghe for the patch.
+- "action resumed" message now also specifies module type
+ which makes troubleshooting a bit easier. Note that we cannot output all
+ the config details (like destination etc) as this would require much more
+ elaborate code changes, which we at least do not like to do in the
+ stable version.
+- add capability to override GnuTLS path in build process
+ Thanks to Clayton Shotwell for the patch
+- better and more consistent action naming, action queues now always
+ contain the word "queue" after the action name
+- bugfix: ompipe did resume itself even when it was still in error
+ See: https://github.com/rsyslog/rsyslog/issues/35
+ Thanks to github user schplat for reporting
+- bugfix: ompipe used invalid default template
+ This is a regression from an old change (didn't track it down precisely,
+ but over a year ago). It used the Forwarding template instead of
+ the file template (so we have a full syslog header). This fix corrects
+ it back to previous behavior, but new scripts that used the wrong
+ format may now need to have the RSYSLOG_ForwardingFormat template
+ explicitly be applied.
+ closes: https://github.com/rsyslog/rsyslog/issues/50
+---------------------------------------------------------------------------
+Version 8.1.6 [release candidate] 2014-02-20
+- omfile: permit to set global defaults for action parameters
+ Thanks to Nathan Brown for the patch.
+ See also: https://github.com/rsyslog/rsyslog/pull/23
+- add capability to escape control characters in the C way of doing it
+ adds new global parameter "parser.escapeControlCharactersCStyle"
+ Thanks to Nathan Brown for the patch.
+ See also: https://github.com/rsyslog/rsyslog/pull/13
+- parser global parameters can now be set using RainerScript global()
+ Thanks to Nathan Brown for the patch.
+ See also: https://github.com/rsyslog/rsyslog/pull/23
+- omprog: guard program-to-be-executed against CTL-C
+ This can frequently happen in debug mode, where rsyslog is terminated
+ by ctl-c. In any case, SIGINT is not meant to control the child process,
+ so it should be blocked.
+- omprog bugfix: parameter "forceSingleInstance" is NOT mandatory
+- add new jsonr property replacer option
+ Thanks to Nathan Brown for the patch.
+- added external plugin interface
+- ommongodb: add authentication support (untested)
+ Thanks to JT for the patch.
+ See also: https://github.com/rsyslog/rsyslog/pull/17
+- bugfix: json templates are improperly created
+ Strings miss the terminating NUL character, which obviously can lead
+ to all sorts of problems.
+ See also: https://github.com/rsyslog/rsyslog/issues/27
+ Thanks to Alain for the analysis and the patch.
+- ompgsql bugfix: improper handling of auto-backgrounding mode
+ If rsyslog was set to auto-background itself (default code behavior, but
+ many distros now turn it off for good reason), ompgsql could not
+ properly connect. This could even lead to a segfault. The core reason
+ was that a PG session handle was kept open over a fork, something that
+ is explicitly forbidden in the PG API.
+ Thanks to Alain for the analysis and the patch.
+- bugfix: ommongodb's template parameter was mandatory but should have
+ been optional
+ Thanks to Alain for the analysis and the patch.
+- bugfix: end of batch processing was not 100% correct. Could lead to
+ outputs not properly writing messages. At least omelasticsearch did not
+ write anything to the database due to this bug.
+ See: https://github.com/rsyslog/rsyslog/issues/10
+ Thanks to Radu Gheorghe for reporting the issue.
+---------------------------------------------------------------------------
+Version 8.1.5 [devel] 2014-01-24
+- omprog: ability to execute multiple program instances per action
+ It can now execute one program instance per worker thread. This is
+ generally a very good thing the have performance wise. Usually, this
+ should cause no problems with the invoked program. For that reason,
+ we have decided to make this the default mode of operation. If not
+ desired, it can be turned off via the 'forceSingleInstance="on"'
+ action parameter.
+ CHANGE OF BEHAVIOR: previous versions did always execute only one
+ instance per action, no matter how many workers were active. If
+ your program has special needs, you need to change your configuration.
+- imfile now supports inotify (but must be explicitly turned on)
+- imfile no longer has a limit on number of monitored files
+- added ProcessInternalMessages global system parameter
+ This permits to inject rsyslog status messages into *another* main
+ syslogd or the journal.
+- new dependency: liblogging-stdlog (for submitting to external logger)
+- bugfix: imuxsock input parameters were not accepted
+ due to copy&paste error. Thanks to Andy Goldstein for the fix.
+---------------------------------------------------------------------------
+Version 8.1.4 [devel] 2014-01-10
+- add exec_template() RainerScript function
+- imrelp: support for TCP KEEPALIVE added
+- bumped librelp dependency to 1.2.2 to support new KEEPALIVE feature
+- Add directives for numerically specifying GIDs/UIDs
+ The already present directives (FileOwner, FileGroup, DirOwner,
+ DirGroup) translate names to numerical IDs, which depends on the user
+ information being available during rsyslog's startup. This can fail if
+ the information is obtained over a network or from a service such as
+ SSSD. The new directives provide a way to specify the numerical IDs
+ directly and bypass the lookup.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: action commitTransaction() processing did not properly handle
+ suspended actions
+- bugfix: omelasticsearch fail.es stats counter was improperly maintained
+---------------------------------------------------------------------------
+Version 8.1.3 [devel] 2013-12-06
+
+THIS VERSION CAN BE CONSIDERED A "NORMAL" DEVEL RELEASE. It's no longer
+highly experimental. This assertion is based on real-world feedback.
+
+- changes to the strgen module interface
+- new output module interface for transactional modules
+- performance improvements
+ * reduced number of malloc/frees due to further changes to the
+ output module interface
+ * reduced number of malloc/frees during string template processing
+ We now re-use once allocated string template memory for as long
+ as the worker thread exists. This saves us from doing new memory
+ allocs (and their free counterpart) when the next message is
+ processed. The drawback is that the cache always is the size of
+ the so-far largest message processed. This is not considered a
+ problem, as in any case a single messages' memory footprint should
+ be far lower than that of a whole set of messages (especially on
+ busy servers).
+ * used variable qualifiers (const, __restrict__) to hopefully help
+ the compiler generate somewhat faster code
+- failed action detection more precisely for a number of actions
+ If an action uses string parameter passing but is non-transactional
+ it can be executed immediately, giving a quicker indication of
+ action failure.
+- bugfix: limiting queue disk space did not work properly
+ * queue.maxdiskspace actually initializes queue.maxfilesize
+ * total size of queue files was not checked against
+ queue.maxdiskspace for disk assisted queues.
+ Thanks to Karol Jurak for the patch.
+---------------------------------------------------------------------------
+Version 8.1.2 [experimental] 2013-11-28
+- support for liblognorm1 added - results in performance improvements
+ Thanks to Pavel Levshin for his work in this regard.
+- support for jemalloc added via --enable-jemalloc
+ Thanks to Pavel Levshin for suggesting jemalloc
+ Note that build system is experimental at this stage.
+- queue defaults have changed
+ * high water mark is now dynamically 90% of queue size
+ * low water makr is now dynamically 70% of queue size
+ * queue.discardMark is now dynamically 98% of queue size
+ * queue.workerThreadMinimumMessage set to queue.size / num workers
+ For queues with very low queue.maxSize (< 100), "emergency" defaults
+ will be used.
+- bugfix: disk queues created files in wrong working directory
+ if the $WorkDirectory was changed multiple times, all queues only
+ used the last value set.
+- bugfix: legacy directive $ActionQueueWorkerThreads was not honored
+- bugfix: mmrfc5424addhmac: "key" parameter was not properly processed
+---------------------------------------------------------------------------
+Version 8.1.1 [experimental] 2013-11-19
+- bugfix: STOP/discard(~) was mostly NOT honored
+ This lead to execution of config code that was not meant to be executed.
+- bugfix: memory leak on worker thread termination
+- bugfix: potential segfault in omfile under heavy load
+ Thanks to Pavel Levshin for alerting us.
+- bugfix: mmsequence: instance mode did not work
+ Thanks to Pavel Levshin for the patch
+- bugfix: segfault on startup when certain script constructs are used
+ e.g. "if not $msg ..."
+- omhiredis: now supports v8 output module interface and works again
+ Thanks to Pavel Levshin for the patch
+- mmaudit: now supports v8 output module interface and work again
+- bugfix: potential abort on startup in debug mode
+ This depends on template type being used. The root cause was a
+ non-necessary debug output, which were at the wrong spot (leftover from
+ initial testing).
+ Thanks to Pavel Levshin for alerting us and providing a patch
+ proposal.
+---------------------------------------------------------------------------
+Version 8.1.0 [experimental] 2013-11-15
+- rewritten core engine for higher performance and new features
+ In detail:
+ * completely rewritten rule execution engine
+ * completely changed output module interface
+ * remodelled output module interface
+ * enabled important output modules to support full concurrent
+ operation
+ The core engine has been considerably changed and must be considered
+ experimental at this stage. Note that it does not yet include all
+ features planned for v8, but is close to this goal. In theory, the
+ engine should perform much better, especially on complex configurations
+ and busy servers. Most importantly, actions instances can now be called
+ concurrently from worker threads and many important output modules
+ support multiple concurrent action instances natively.
+- module omruleset is no longer enabled by default.
+ Note that it has been deprecated in v7 and been replaced by the "call"
+ statement. Also, it can still be build without problems, the option must
+ just explicitly be given.
+---------------------------------------------------------------------------
+Version 7.6.8 [v7.6-stable] 2014-10-??
+- bugfix: typo in queue configuration parameter made parameter unusable
+ Thanks to Bojan Smojver for the patch.
+- bugfix imuxsock: possible segfault when SysSock.Use="off"
+ Thanks to alexjfisher for reporting this issue.
+ closes https://github.com/rsyslog/rsyslog/issues/140
+- bugfix: uninitialized buffer off-by-one error in hostname generation
+ The DNS cache used uninitialized memory, which could lead to
+ invalid hostname generation.
+ Thanks to Jarrod Sayers for alerting us and providing analysis and
+ patch recommendations.
+- remove zpipe (a testing tool) from --enable-diagtools
+ This tool is no longer maintained and currently not used inside the
+ testbench. We keep it in the source tree for the time being in case that
+ it may be used in the future.
+- bugfix: imjournal did not build properly
+ The build succeeded, but the module did not load due to a type in
+ a support function name, which kept unresolved during load.
+- bugfix imklog: pri was miscalculated
+ actually, the pri was totally off the real value for PRIs > 9
+- bugfix rsgtutil: sometimes crashed in verify mode if file did not exist
+- bugfix rsgtutil: some errors/problems at end of file were not reported
+ * The verification function in rsgtutil tool did not report deletion of
+ whole signed blocks of lines from the end of the log file.
+ * The verification function in rsgtutil tool did not report extra
+ (unsigned) lines at the end of the log file.
+ Thanks to Henri Lakk for the patch.
+- bugfix: error: json_tokener_errors undeclared when overriding PKGCONFIG
+ If PKGCONFIG settings for json-c were overridden, presence of
+ json_tokener_errors was not properly detected.
+ closes: https://github.com/rsyslog/rsyslog/issues/143
+ Thanks to Alex Fisher for alerting us and the patch.
+---------------------------------------------------------------------------
+Version 7.6.7 [v7.6-stable] 2014-10-02
+- bugfix: the fix for CVE-2014-3634 did not handle all cases
+ This is corrected now.
+ see also: CVE-2014-3683
+- fixed a build problem on some platforms
+ Thanks to Olaf for the patch
+- behavior change: "msg" of messages with invalid PRI set to "rawmsg"
+ When the PRI is invalid, the rest of the header cannot be valid. So
+ we move all of it to MSG and do not try to parse it out. Note that
+ this is not directly related to the security issue but rather done
+ because it makes most sense.
+---------------------------------------------------------------------------
+Version 7.6.6 [v7.6-stable] 2014-09-30
+- bugfix: potential abort when a message with PRI > 191 was processed
+ if the "pri-text" property was used in active templates, this could
+ be abused to a remote denial of service from permitted senders
+ see also: CVE-2014-3634
+- bugfix: potential segfault on startup on 64 bit systems
+ This happened immediately on startup during config processing. Once
+ rsyslog got past this stage, it could not happen.
+- bugfix: build problems on SuSe Linux
+ Thanks Andreas Stieger for the patch
+---------------------------------------------------------------------------
+Version 7.6.5 [v7.6-stable] 2014-09-17
+- bugfix: in 7.6.4, pri-based filters did not work correctly
+ messages were distributed to the wrong bins.
+- bugfix: build problems on systems without atomic instructions
+ e.g. RHEL 5; backport from v8
+---------------------------------------------------------------------------
+Version 7.6.4 [v7.6-stable] 2014-09-12
+- add --enable-generate-man-pages configure switch (default: enabled)
+ This forces generation of man pages, even if cached ones exists. This
+ "fixes" a typical release tarball nit. While it is hackish, the
+ benefit is clear given the history of failed tarball releases since
+ we changed the cached man page handling. It was just too easy to get
+ that wrong.
+- removed obsolete --disable-fsstnd configure option
+ Thanks to Thomas D. for alerting us.
+ Closes: https://github.com/rsyslog/rsyslog/issues/72
+- permits to build against json-c 0.12
+ Unfortunately, json-c had an ABI breakage, so this is necessary. Note
+ that versions prior to 0.12 had security issues (CVE-2013-6370,
+ CVE-2013-6371) and so it is desirable to link against the new version.
+ Thanks to Thomas D. for the patch. Note that at least some distros
+ have fixed the security issue in older versions of json-c, so this
+ seems to apply mostly when building from sources.
+- new omfile default module parameters
+ * filecreatemode
+ * fileowner
+ * fileownernum
+ * filegroup
+ * filegroupnum
+ * dirowner
+ * dirownernum
+ * dirgroup
+ * dirgroupnum
+ Thanks to Karol Jurak for the patch.
+- bugfix: memory leak in TCP TLS mode
+- bugfix: imfile: if a state file for a different file name was set,
+ that different file (name) was monitored instead of the configured
+ one. Now, the state file is deleted and the correct file monitored.
+ closes: https://github.com/rsyslog/rsyslog/issues/103
+- bugfix: using UUID property could cause segfault
+- bugfix: mmutf8fix did not detect two invalid sequences
+ Thanks to Axel Rau for the patch.
+- bugfix: file descriptor leak with Guardtime signatures
+ When a .gtstate file is opened it is never closed. This is especially
+ bad when dynafiles frequently get evicted from dynafile cache and be
+ re-opened again.
+- bugfix: busy loop in tcp listener when running out of file descriptors
+ Thanks to Susant Sahani for the patch.
+- bugfix: mishandling of input modules not supporting new input instances
+ If they did not support this, accidentally the output module part of the
+ module union was written, leading to unpredictable results. Note: all
+ core modules do support this interface, but some contributed or very
+ old ones do not.
+- bugfix: double-free when ruleset() parser parameters were used
+ While unlikely, this could cause stability issues even after the
+ config phase.
+- bugfix: output modules with parameters with multiple passing modes
+ could caused strange behavior including aborts
+ This was due to the fact that the action module only preserved and
+ processed the last set passing mode. Note that this was not a problem
+ for the plugins provided by the rsyslog git: none of them uses different
+ passing modes.
+ Thanks to Tomas Heinrich for providing a very detailed bug report.
+- various fixes after coverity scan
+ These do not address issues seen in practice but those seen by the tool.
+ Some of them may affect practical deployments.
+ Thanks to Tomas Heinrich for the patches.
+- bugfix imuxsock: "Last message repeated..." was not emitted at shutdown
+ The "Last message repeated..." notice didn't get printed if rsyslog was
+ shut down before the repetition was broken.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: make dist failed when GUARDTIME or LIBGCRYPT feature was disabled
+- bugfix: mmjsonparse did not build with json-c < 0.10
+ This was a regression introduced some time in the past in order to
+ support API changes in json-c. Now we check for the version and use
+ proper code.
+- bugfix: mmanon did not properly anonymize IP addresses starting with '9'
+ Thanks to defa-at-so36.net for reporting this problem.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=529
+---------------------------------------------------------------------------
+Version 7.6.3 [v7.6-stable] 2014-03-27
+- add capability to override GnuTLS path in build process
+ Thanks to Clayton Shotwell for the patch
+- support for librelp 1.2.5
+ Support new return states of librelp 1.2.5 to emit better error messages
+ For obvious reasons, librelp 1.2.5 is now required.
+- bugfix: ompipe used invalid default template
+ This is a regression from an old change (didn't track it down precisely,
+ but over a year ago). It used the Forwarding template instead of
+ the file template (so we have a full syslog header). This fix corrects
+ it back to previous behavior, but new scripts that used the wrong
+ format may now need to have the RSYSLOG_ForwardingFormat template
+ explicitly be applied.
+ closes: https://github.com/rsyslog/rsyslog/issues/50
+- bugfix: ompipe did emit many suspension messages for /dev/xconsole
+ (hopefully now) closes: https://github.com/rsyslog/rsyslog/issues/35
+ When it was present, but nobody reading from it. The problem
+ is the way the rsyslog v7 engine tries to resolve failures in outputs.
+ It does some retries, and along those lines some state information gets
+ lost and it is close to impossible to retain it. However, the actual
+ root problem is that ompipe does not reliably detect if it is able to
+ recover. The problem here is that it actually does not know this
+ before it does an actual write. These two things together mess up the
+ logic that suppresses invalid resumption/suspension messages
+ (actually, the plugin switches state really that often).
+ Nevertheless, the prime problem with /dev/xconsole (and probably
+ most other pipes as well) is that it gets full. So I have now added
+ code that checks, during resume processing, if the pipe is writable.
+ If it is not, resume is deferred. That should address the case.
+---------------------------------------------------------------------------
+Version 7.6.2 [v7.6-stable] 2014-03-17
+- support for librelp 1.2.4
+ This was necessary due to the problems with librelp 1.2.3 API stability.
+ We now use the new native 1.2.4 APIs to learn about the state of
+ librelp's TLS support.
+ For obvious reasons, librelp 1.2.4 is now required.
+---------------------------------------------------------------------------
+Version 7.6.1 [v7.6-stable] 2014-03-13
+- added "action.reportSuspension" action parameter
+ This now permits to control handling on a per-action basis rather to
+ the previous "global setting only".
+- "action resumed" message now also specifies module type
+ which makes troubleshooting a bit easier. Note that we cannot output all
+ the config details (like destination etc) as this would require much more
+ elaborate code changes, which we at least do not like to do in the
+ stable version.
+- better and more consistent action naming, action queues now always
+ contain the word "queue" after the action name
+- add support for "tls-less" librelp
+ we now require librelp 1.2.3, as we need the new error code definition
+ See also: https://github.com/rsyslog/librelp/issues/1
+- build system improvements
+ * autoconf subdir option
+ * support for newer json-c packages
+ Thanks to Michael Biebl for the patches.
+- imjournal enhancements:
+ * log entries with empty message field are no longer ignored
+ * invalid facility and severity values are replaced by defaults
+ * new config parameters to set default facility and severity
+ Thanks to Tomas Heinrich for implementing this
+- bugfix: ompipe did resume itself even when it was still in error
+ See: https://github.com/rsyslog/rsyslog/issues/35
+ Thanks to github user schplat for reporting
+- bugfix: "action xxx suspended" did report incorrect error code
+- bugfix: ommongodb's template parameter was mandatory but should have
+ been optional
+ Thanks to Alain for the analysis and the patch.
+- bugfix: only partial doc was put into distribution tarball
+ Thanks to Michael Biebl for alerting us.
+ see also: https://github.com/rsyslog/rsyslog/issues/31
+- bugfix: async ruleset did process already-deleted messages
+ Thanks to John Novotny for the patch.
+---------------------------------------------------------------------------
+Version 7.6.0 [v7.6-stable] 2014-02-12
+This starts a new stable branch based on 7.5.8 plus the following changes:
+- bugfix: imuxsock input parameters were not accepted
+ due to copy&paste error. Thanks to Andy Goldstein for the fix.
+- added ProcessInternalMessages global system parameter
+ This permits to inject rsyslog status messages into *another* main
+ syslogd or the journal.
+- new dependency: liblogging-stdlog (for submitting to external logger)
+- bugfix: json templates are improperly created
+ Strings miss the terminating NUL character, which obviously can lead
+ to all sorts of problems.
+ See also: https://github.com/rsyslog/rsyslog/issues/27
+ Thanks to Alain for the analysis and the patch.
+- ompgsql bugfix: improper handling of auto-backgrounding mode
+ If rsyslog was set to auto-background itself (default code behavior, but
+ many distros now turn it off for good reason), ompgsql could not
+ properly connect. This could even lead to a segfault. The core reason
+ was that a PG session handle was kept open over a fork, something that
+ is explicitly forbidden in the PG API.
+ Thanks to Alain for the analysis and the patch.
+---------------------------------------------------------------------------
+Version 7.5.8 [v7-release candidate] 2014-01-09
+- add exec_template() RainerScript function
+- add debug.onShutdown and debug.logFile global parameters
+ These enable the new "debug on shutdown" mode, which can be used to
+ track hard to find problems that occur during system shutdown.
+- Add directives for numerically specifying GIDs/UIDs
+ The already present directives (FileOwner, FileGroup, DirOwner,
+ DirGroup) translate names to numerical IDs, which depends on the user
+ information being available during rsyslog's startup. This can fail if
+ the information is obtained over a network or from a service such as
+ SSSD. The new directives provide a way to specify the numerical IDs
+ directly and bypass the lookup.
+ Thanks to Tomas Heinrich for the patch.
+- actions now report if they suspend and resume themselves
+ this is by default on and controllable by the action.reportSuspension
+ global parameter
+- bugfix: omelasticsearch fail.es stats counter was improperly maintained
+- bugfix: mmrfc5424addhmac: "key" parameter was not properly processed
+- add new impstats action counters:
+ * suspended
+ * suspended.duration
+ * resumed
+---------------------------------------------------------------------------
+Version 7.5.7 [v7-devel] 2013-11-25
+- queue defaults have changed
+ * high water mark is now dynamically 90% of queue size
+ * low water makr is now dynamically 70% of queue size
+ * queue.discardMark is now dynamically 98% of queue size
+ * queue.workerThreadMinimumMessage set to queue.size / num workers
+ For queues with very low queue.maxSize (< 100), "emergency" defaults
+ will be used.
+- worker thread pool handling has been improved
+ Among others, permits pool to actually shrink (was quite hard with
+ previous implementation. This will also improve performance and/or
+ lower system overhead on busy systems.
+ Thanks to Pavel Levshin for the enhancement.
+- bugfix: mmpstrucdata generated inaccessible properties
+- bugfix: RainerScript optimizer did not optimize PRI filters
+ things like "if $syslogfacility-text == "local3"" were not converted
+ to PRIFILT. This was a regression introduced in 7.5.6.
+- bugfix: legacy directive $ActionQueueWorkerThreads was not honored
+- bugfix: segfault on startup when certain script constructs are used
+ e.g. "if not $msg ..."
+- bugfix: ommysql lost configfile/section parameters after first close
+ This means that when a connection was broken, it was probably
+ re-instantiated with different parameters than configured.
+- bugfix: regression in template processing with subtrees in templates
+ Thanks to Pavel Levshin for the fix
+- bugfix: regular worker threads are not properly (re)started if DA
+ mode is active.
+ This occurs only under rare conditions, but definitely is a bug that
+ needed to be addressed. It probably is present since version 4.
+ Note that this patch has not been applied to v7.4-stable, as it
+ is very unlikely to happen and the fix itself has some regression
+ potential (the fix looks very solid, but it addresses a core component).
+ Thanks to Pavel Levshin for the fix
+- now emit warning message if om with msg passing mode uses action queue
+ These can modify the message, and this causes races.
+- bugfix: $SystemLogUseSysTimeStamp/$SystemLogUsePIDFromSystem did not work
+ Thanks to Tomas Heinrich for the patch.
+---------------------------------------------------------------------------
+Version 7.5.6 [devel] 2013-10-29
+- impstats: add capability to bind to a ruleset
+- improved performance of RainerScript variable access
+ by refactoring the whole body of variable handling code. This also
+ solves some of the anomalies experienced in some versions of rsyslog.
+ All variable types are now handled in unified code, including
+ access via templates.
+- RainerScript: make use of 64 bit for numbers where available
+ Thanks to Pavel Levshin for enhancement.
+- slight performance optimization if GCC is used
+ We give branch prediction hints for the frequent RETiRet macro which is
+ used for error handling. Some slight performance gain is to be expected
+ from that.
+- removed global variable support
+ The original idea was not well thought out and global variables, as
+ implemented, worked far different from what anybody would expect. As
+ such, we consider the current approach as an experiment that did not
+ work out and opt to removing it, clearing the way for a better future
+ solution. Note: global vars were introduced in 7.5.3 on Sept, 11th 2013.
+- new module mmsequence, primarily used for action load balancing
+ Thanks to Pavel Levshin for contributing this module.
+- bugfix: unset statement always worked on message var, even if local
+ var was given
+- imudp: support for binding to ruleset added
+- bugfix: segfault if variable was assigned to non-container subtree
+ Thanks to Pavel Levshin for the fix
+- bugfix: imuxsock did not support addtl sockets if syssock was disabled
+ Thanks to Pavel Levshin for the fix
+- bugfix: running imupd on multiple threads lead to segfault if recvmmsg
+ is available
+- bugfix: imudp when using recvmmsg could report wrong sender IP
+- bugfix: segfault if re_extract() function was used and no match found
+- bugfix: omelasticsearch did not compile on platforms without atomic
+ instructions
+- bugfix: potential misaddressing on startup if property-filter was used
+ This could happen if the property name was longer than 127 chars, a case
+ that would not happen in practice.
+- bugfix: invalid property filter was not properly disabled in ruleset
+ Note: the cosmetic memory leak introduced with that patch in 7.4.5 is
+ now also fixed.
+- imported bugfixes from 7.4.6 stable release
+---------------------------------------------------------------------------
+Version 7.5.5 [devel] 2013-10-16
+- imfile: permit to monitor an unlimited number of files
+- imptcp: add "defaultTZ" input parameter
+- imudp: support for multiple receiver threads added
+- imudp: add "dfltTZ" input config parameter
+- bugfix: memory leak in mmnormalize
+- bugfix: mmutf8fix did not properly handle invalid UTF-8 at END of message
+ if the very last character sequence was too long, this was not detected
+ Thanks to Risto Vaarandi for reporting this problem.
+- mmanon: removed the check for specific "terminator characters" after
+ last octet. As it turned out, this didn't work in practice as there
+ was an enormous set of potential terminator chars -- so removing
+ them was the best thing to do. Note that this may change behavior of
+ existing installations. Yet, we still consider this an important
+ bugfix, that should be applied to the stable branch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=477
+ Thanks to Muri Cicanor for initiating the discussion
+- now requires libestr 0.1.7 as early versions had a nasty bug in
+ string comparisons
+- bugfix: mmanon did not detect all IP addresses in rewrite mode
+ The problem occurred if two IPs were close to each other and the first one
+ was shrunk.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=485
+ Thanks to micah-at-riseup.net for reporting this bug
+- bugfix: mmanon sometimes used invalid replacement char in simple mode
+ depending on configuration sequence, the replacement character was set
+ to 's' instead of the correct value. Most importantly, it was set to
+ 's' if simple mode was selected and no replacement char set.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=484
+ Thanks to micah-at-riseup.net for reporting this bug
+- bugfix: memory leak in mmnormalize
+- bugfix: array-based ==/!= comparisons lead to invalid results
+ This was a regression introduced in 7.3.5 bei the PRI optimizer
+---------------------------------------------------------------------------
+Version 7.5.4 [devel] 2013-10-07
+- mmpstrucdata: new module to parse RFC5424 structured data into json
+ message properties
+- change main/ruleset queue defaults to be more enterprise-like
+ new defaults are queue.size 100,000 max workers 2, worker
+ activation after 40,000 msgs are queued, batch size 256. These settings
+ are much more useful for enterprises and will not hurt low-end systems
+ that much. This is part of our re-focus on enterprise needs.
+- omfwd: new action parameter "maxErrorMessages" added
+- omfile: new module parameters to set action defaults added
+ * dirCreateMode
+ * fileCreateMode
+- mmutf8fix: new module to fix invalid UTF-8 sequences
+- imuxsock: handle unlimited number of additional listen sockets
+- doc: improve usability by linking to relevant web resources
+ The idea is to enable users to quickly find additional information,
+ samples, HOWTOs and the like on the main site.
+ At the same time, (very) slightly remove memory footprint when
+ few listeners are monitored.
+- bugfix: omfwd parameter streamdrivermode was not properly handled
+ it was always overwritten by whatever value was set via the
+ legacy directive $ActionSendStreamDriverMode
+- imtcp: add streamdriver.name module parameter
+ permits overriding the system default stream driver (gtls, ptcp)
+- bugfix: build system: libgcrypt.h needed even if libgrcypt was disabled
+ Thanks to Jonny Törnbom for reporting this problem
+- imported bugfixes from 7.4.4
+---------------------------------------------------------------------------
+Version 7.5.3 [devel] 2013-09-11
+- imfile: support for escaping LF characters added
+ embedded LF in syslog messages cause a lot of trouble. imfile now has
+ the capability to escape them to "#012" (just like the regular control
+ character escape option). This requires new-style input statements to be
+ used. If legacy configuration statements are used, LF escaping is always
+ turned off to preserve compatibility.
+ NOTE: if input() statements were already used, there is a CHANGE OF
+ BEHAVIOR: starting with this version, escaping is enabled by
+ default. So if you do not want it, you need to add
+ escapeLF="off"
+ to the input statement. Given the trouble LFs cause and the fact
+ that the majority of installations still use legacy config, we
+ considered this behavior change acceptable and useful.
+ see also: http://blog.gerhards.net/2013/09/imfile-multi-line-messages.html
+- add support for global and local variables
+- bugfix: queue file size was not correctly processed
+ this could lead to using one queue file per message for sizes >2GiB
+ Thanks to Tomas Heinrich for the patch.
+- add main_queue() configuration object to configure main message queue
+- bugfix: stream compression in imptcp caused timestamp to be corrupted
+- imudp: add ability to specify SO_RCVBUF size (rcvbufSize parameter)
+- imudp: use inputname for statistics, if configured
+- impstats: add process resource usage counters [via getrusage()]
+- impstats: add parameter "resetCounters" to report delta values
+ possible for most, but not all, counters. See doc for details.
+- librelp 1.2.0 is now required
+- make use of new librelp generic error reporting facility
+ This leads to more error messages being passed to the user and
+ thus simplified troubleshooting.
+- bugfix: very small memory leak in imrelp
+ more or less cosmetic, a single memory block was not freed, but this
+ only happens immediately before termination (when the OS automatically
+ frees all memory). Still an annoyance e.g. in valgrind.
+- fix compile problem in debug build
+- imported fixes from 7.4.4
+---------------------------------------------------------------------------
+Version 7.5.2 [devel] 2013-07-04
+- librelp 1.1.4 is now required
+ We use API extensions for better error reporting and higher performance.
+- omrelp: use transactional mode to make imrelp emit bulk sends
+- omrelp: add "windowSize" parameter to set custom RELP window size
+- bugfix: double-free in omelasticsearch
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=461
+ a security advisory for this bug is available at:
+ http://www.lsexperts.de/advisories/lse-2013-07-03.txt
+ CVE: CVE-2013-4758
+ PLEASE NOTE: This issue only existed if omelasticsearch was used
+ in a non-default configuration, where the "errorfile" parameter
+ was specified. Without that parameter set, the bug could not
+ be triggered.
+ Thanks to Markus Vervier and Marius Ionescu for providing a detailed
+ bug report. Special thanks to Markus for coordinating his security
+ advisory with us.
+- doc: fixed various typos
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=391
+ Thanks to Georgi Georgiev for the patch.
+---------------------------------------------------------------------------
+Version 7.5.1 [devel] 2013-06-26
+- librelp 1.1.3 is required - older versions can lead to a segfault
+- add mmfields, which among others supports easy parsing of CEF messages
+- omrelp:
+ * new parameter "compression.prioritystring" to control encryption
+ parameters used by GnuTLS
+- imrelp:
+ * new parameter "compression.dhbits" to control the number of
+ bits being used for Diffie-Hellman key generation
+ * new parameter "compression.prioritystring" to control encryption
+ parameters used by GnuTLS
+ * support for impstats added
+ * support for setting permitted peers (client authentication) added
+ * bugfix: potential segfault at startup on invalid config parameters
+- imjournal: imported patches from 7.4.1
+- omprog: add support for command line parameters
+- added experimental TCP stream compression (imptcp only, currently)
+- added BSD-specific syslog facilities
+ * "console"
+ * "bsd_security" - this is called "security" under BSD, but that name
+ was unfortunately already taken by some standard facility. So I
+ did the (hopefully) second-best thing and renamed it a little.
+- imported fixes from 7.4.2 (especially build problems on FreeBSD)
+- bugfix: imptcp did not properly initialize compression status variable
+ could lead to segfault if stream:always compression mode was selected
+---------------------------------------------------------------------------
+Version 7.5.0 [devel] 2013-06-11
+- imrelp: implement "ruleset" module parameter
+- imrelp/omrelp: add TLS & compression (zip) support
+- omrelp: add "rebindInterval" parameter
+- add -S command line option to specify IP address to use for RELP client
+ connections
+ Thanks to Axel Rau for the patch.
+---------------------------------------------------------------------------
+Version 7.4.11 [v7.4-stable] *never released*
+- imjournal enhancements:
+ * log entries with empty message field are no longer ignored
+ * invalid facility and severity values are replaced by defaults
+ * new config parameters to set default facility and severity
+ Thanks to Tomas Heinrich for implementing this
+---------------------------------------------------------------------------
+Version 7.4.10 [v7.4-stable] 2014-02-12
+- bugfix: json templates are improperly created
+ Strings miss the terminating NUL character, which obviously can lead
+ to all sorts of problems.
+ See also: https://github.com/rsyslog/rsyslog/issues/27
+ Thanks to Alain for the analysis and the patch.
+- ompgsql bugfix: improper handling of auto-backgrounding mode
+ If rsyslog was set to auto-background itself (default code behavior, but
+ many distros now turn it off for good reason), ompgsql could not
+ properly connect. This could even lead to a segfault. The core reason
+ was that a PG session handle was kept open over a fork, something that
+ is explicitly forbidden in the PG API.
+ Thanks to Alain for the analysis and the patch.
+---------------------------------------------------------------------------
+Version 7.4.9 [v7.4-stable] 2014-01-22
+- added ProcessInternalMessages global system parameter
+ This permits to inject rsyslog status messages into *another* main
+ syslogd or the journal.
+- new dependency: liblogging-stdlog (for submitting to external logger)
+- bugfix: imuxsock input parameters were not accepted
+ due to copy&paste error. Thanks to Andy Goldstein for the fix.
+- bugfix: potential double-free in RainerScript equal comparison
+ happens if the left-hand operand is JSON object and the right-hand
+ operand is a non-string that does not convert to a number (for
+ example, it can be another JSON object, probably the only case that
+ could happen in practice). This is very unlikely to be triggered.
+- bugfix: some RainerScript Json(Variable)/string comparisons were wrong
+---------------------------------------------------------------------------
+Version 7.4.8 [v7.4-stable] 2014-01-08
+- rsgtutil provides better error messages on unfinished signature blocks
+- bugfix: guard against control characters in internal (error) messages
+ Thanks to Ahto Truu for alerting us.
+- bugfix: immark did emit messages under kern.=info instead of syslog.=info
+ Note that his can potentially break existing configurations that
+ rely on immark sending as kern.=info. Unfortunately, we cannot leave
+ this unfixed as we never should emit messages under the kern facility.
+---------------------------------------------------------------------------
+Version 7.4.7 [v7.4-stable] 2013-12-10
+- bugfix: limiting queue disk space did not work properly
+ * queue.maxdiskspace actually initializes queue.maxfilesize
+ * total size of queue files was not checked against
+ queue.maxdiskspace for disk assisted queues.
+ Thanks to Karol Jurak for the patch.
+- bugfix: linux kernel-like ratelimiter did not work properly with all
+ inputs (for example, it did not work with imdup). The reason was that
+ the PRI value was used, but that needed parsing of the message, which
+ was done too late.
+- bugfix: disk queues created files in wrong working directory
+ if the $WorkDirectory was changed multiple times, all queues only
+ used the last value set.
+- bugfix: legacy directive $ActionQueueWorkerThreads was not honored
+- bugfix: segfault on startup when certain script constructs are used
+ e.g. "if not $msg ..."
+- bugfix: imuxsock: UseSysTimeStamp config parameter did not work correctly
+ Thanks to Tomas Heinrich for alerting us and providing a solution
+ suggestion.
+- bugfix: $SystemLogUseSysTimeStamp/$SystemLogUsePIDFromSystem did not work
+ Thanks to Tomas Heinrich for the patch.
+- improved checking of queue config parameters on startup
+- bugfix: call to ruleset with async queue did not use the queue
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=443
+- bugfix: if imtcp is loaded and no listeners are configured (which is
+ uncommon), rsyslog crashes during shutdown.
+---------------------------------------------------------------------------
+Version 7.4.6 [v7.4-stable] 2013-10-31
+- bugfix: potential abort during HUP
+ This could happen when one of imklog, imzmq3, imkmsg, impstats,
+ imjournal, or imuxsock were under heavy load during a HUP.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=489
+ Thanks to Guy Rozendorn for reporting the problem and Peval Levshin for
+ his analysis.
+- bugfix: imtcp flowControl parameter incorrectly defaulted to "off"
+ This could cause message loss on systems under heavy load and was
+ a change-of-behavior to previous version. This is a regression
+ most probably introduced in 5.9.0 (but did not try hard to find the
+ exact point of its introduction).
+- now requires libestr 0.1.9 as earlier versions lead to problems with
+ number handling in RainerScript
+- bugfix: memory leak in strlen() RainerScript function
+ Thanks to Gregoire Seux for reporting this bug.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=486
+- bugfix: buffer overrun if re_extract function was called for submatch 50
+ Thanks to Pavel Levshin for reporting the problem and its location.
+- bugfix: memleak in re_extract() function
+ Thanks to Pavel Levshin for reporting this problem.
+- bugfix: potential abort in RainerScript optimizer
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=488
+ Thanks to Thomas Doll for reporting the problem and Pavel Levshin for
+ fixing it.
+- bugfix: memory leak in omhiredis
+ Thanks to Pavel Levshin for the fix
+- bugfix: segfault if variable was assigned to non-container subtree
+ Thanks to Pavel Levshin for the fix
+---------------------------------------------------------------------------
+Version 7.4.5 [v7.4-stable] 2013-10-22
+- mmanon: removed the check for specific "terminator characters" after
+ last octet. As it turned out, this didn't work in practice as there
+ was an enormous set of potential terminator chars -- so removing
+ them was the best thing to do. Note that this may change behavior of
+ existing installations. Yet, we still consider this an important
+ bugfix, that should be applied to the stable branch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=477
+ Thanks to Muri Cicanor for initiating the discussion
+- now requires libestr 0.1.8 as early versions had a nasty bug in
+ string comparisons
+- omelasticsearch: add failed.httprequests stats counter
+- bugfix: invalid property filter was not properly disabled in ruleset
+ Note that this bugfix introduces a very slight memory leak, which is
+ cosmetic, as it just holds data until termination that is no longer
+ needed. It is just the part of the config that was invalid. We will
+ "fix" this "issue" in the devel version first, as the fix is a bit
+ too intrusive to do without hard need in the stable version.
+- bugfix: segfault if re_extract() function was used and no match found
+- bugfix: potential misaddressing on startup if property-filter was used
+ This could happen if the property name was longer than 127 chars, a case
+ that would not happen in practice.
+- bugfix: omelasticsearch: correct failed.http stats counter
+- bugfix: omelasticsearch: did not correctly initialize stats counters
+- bugfix: omelasticsearch: failed.es counter was only maintained in bulk mode
+ This usually did not lead to any problems, because they are in static
+ memory, which is initialized to zero by the OS when the plugin is
+ loaded. But it may cause problems especially on systems that do not
+ support atomic instructions - in this case the associated mutexes also
+ did not get properly initialized.
+- bugfix: mmanon did not detect all IP addresses in rewrite mode
+ The problem occurred if two IPs were close to each other and the first one
+ was shrunk.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=485
+ Thanks to micah-at-riseup.net for reporting this bug
+- bugfix: mmanon sometimes used invalid replacement char in simple mode
+ depending on configuration sequence, the replacement character was set
+ to 's' instead of the correct value. Most importantly, it was set to
+ 's' if simple mode was selected and no replacement char set.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=484
+ Thanks to micah-at-riseup.net for reporting this bug
+- bugfix: memory leak in mmnormalize
+- bugfix: array-based ==/!= comparisons lead to invalid results
+ This was a regression introduced in 7.3.5 bei the PRI optimizer
+- bugfix: omprog blocked signals to executed programs
+ The made it impossible to send signals to programs executed via
+ omprog.
+ Thanks to Risto Vaarandi for the analysis and a patch.
+- bugfix: doc: imuxsock legacy param $SystemLogSocketParseTrusted was
+ misspelled
+ Thanks to David Lang for alerting us
+- bugfix: imfile "facility" input parameter improperly handled
+ caused facility not to be set, and severity to be overwritten with
+ the facility value.
+ Thanks to forum user dmunny for reporting this bug.
+- bugfix: small memory leak in imfile when $ResetConfigVariables was used
+ Thanks to Grégory Nuyttens for reporting this bug and providing a fix
+- bugfix: segfault on startup if TLS was used but no CA cert set
+- bugfix: segfault on startup if TCP TLS was used but no cert or key set
+- bugfix: some more build problems with newer json-c versions
+ Thanks to Michael Biebl for mentioning the problem.
+- bugfix: build system: libgcrypt.h needed even if libgrcypt was disabled
+ Thanks to Jonny Törnbom for reporting this problem
+---------------------------------------------------------------------------
+Version 7.4.4 [v7.4-stable] 2013-09-03
+- better error messages in GuardTime signature provider
+ Thanks to Ahto Truu for providing the patch.
+- make rsyslog use the new json-c pkgconfig file if available
+ Thanks to the Gentoo team for the patches.
+- bugfix: imfile parameter "persistStateInterval" was unusable
+ due to a case typo in imfile; work-around was to use legacy config
+ Thanks to Brandon Murphy for reporting this bug.
+- bugfix: TLV16 flag encoding error in signature files from GT provider
+ This fixes a problem where the TLV16 flag was improperly encoded.
+ Unfortunately, existing files already have the bug and may not properly
+ be processed. The fix uses constants from the GuardTime API lib to
+ prevent such problems in the future.
+ Thanks to Ahto Truu for providing the patch.
+- bugfix: slightly malformed SMTP handling in ommail
+- bugfix: segfault in omprog if no template was provided (now dflt is used)
+- bugfix: segfault in ompipe if no template was provided (now dflt is used)
+- bugfix: segfault in omsnmp if no template was provided (now dflt is used)
+- bugfix: some omsnmp optional config params were flagged as mandatory
+- bugfix: segfault in omelasticsearch when resuming queued messages
+ after restarting Elasticsearch
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=464
+- bugfix: imtcp addtlframedelimiter could not be set to zero
+ Thanks to Chris Norton for alerting us.
+- doc bugfix: remove no-longer existing omtemplate from developer doc
+ was specifically mentioned as a sample for creating new plugins
+ Thanks to Yannick Brosseau for alerting us of this problem.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=473
+---------------------------------------------------------------------------
+Version 7.4.3 [v7.4-stable] 2013-07-18
+- bugfix: queue file size was not correctly processed
+ this could lead to using one queue file per message for sizes >2GiB
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: $QHOUR/$HHOUR were always "00" or "01"
+ regression some time between v5 and here
+ Thanks to forum user rjmcinty for reporting this bug
+- bugfix: testbench tool chkseq did improperly report invalid file
+ This happened when permitted duplicate values existed in the very
+ last lines, right before end-of-file.
+ Thanks to Radu Gheorghe for reporting this bug.
+---------------------------------------------------------------------------
+Version 7.4.3 [v7.4-stable] 2013-07-18
+- bugfix: memory leak if disk queues were used and json data present
+- bugfix: CEE/json data was lost during disk queue operation
+- bugfix: potential segfault during startup on invalid config
+ could happen if invalid actions were present, which could lead
+ to improper handling in optimizer.
+- bugfix: 100% CPU utilization when DA queue became full
+- bugfix: omlibdbi did not properly close connection on some errors
+ This happened to errors occurring in Begin/End Transaction entry
+ points.
+- cosmetic bugfix: file name buffer was not freed on disk queue destruction
+ This was an extremely small one-time per run memleak, so nothing of
+ concern. However, it bugs under valgrind and similar memory debuggers.
+- fix build on FreeBSD
+ Thanks to Christiano Rolim for the patch
+---------------------------------------------------------------------------
+Version 7.4.2 [v7.4-stable] 2013-07-04
+- bugfix: in RFC5425 TLS, multiple wildcards in auth could cause segfault
+- bugfix: RainerScript object required parameters were not properly
+ checked - this could result to segfaults on startup if parameters
+ were missing.
+- bugfix: double-free in omelasticsearch
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=461
+ a security advisory for this bug is available at:
+ http://www.lsexperts.de/advisories/lse-2013-07-03.txt
+ CVE: CVE-2013-4758
+ PLEASE NOTE: This issue only existed if omelasticsearch was used
+ in a non-default configuration, where the "errorfile" parameter
+ was specified. Without that parameter set, the bug could not
+ be triggered.
+ Thanks to Markus Vervier and Marius Ionescu for providing a detailed
+ bug report. Special thanks to Markus for coordinating his security
+ advisory with us.
+- bugfix: omrelp potential segfault at startup on invalid config parameters
+- bugfix: small memory leak when $uptime property was used
+- bugfix: potential segfault on rsyslog termination in imudp
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=456
+- bugfix: lmsig_gt abort on invalid configuration parameters
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=448
+ Thanks to Risto Laanoja for the patch.
+- imtcp: fix typo in "listner" parameter, which is "listener"
+ Currently, both names are accepted.
+- solved build problems on FreeBSD
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=457
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=458
+ Thanks to Christiano for reporting and suggesting patches
+- solved build problems on CENTOS5
+---------------------------------------------------------------------------
+Version 7.4.1 [v7.4-stable] 2013-06-17
+- imjournal: add ratelimiting capability
+ The original imjournal code did not support ratelimiting at all. We
+ now have our own ratelimiter. This can mitigate against journal
+ database corruption, when the journal re-sends old data. This is a
+ current bug in systemd journal, but we won't outrule this to happen
+ in the future again. So it is better to have a safeguard in place.
+ By default, we permit 20,000 messages within 10 minutes. This may
+ be a bit restrictive, but given the risk potential it seems reasonable.
+ Users requiring larger traffic flows can always adjust the value.
+- bugfix: potential loop in rate limiting
+ if the message that tells about rate-limiting gets rate-limited itself,
+ it will potentially create and endless loop
+- bugfix: potential segfault in imjournal if journal DB is corrupted
+- bugfix: prevent a segfault in imjournal if state file is not defined
+- bugfix imzmq3: potential segfault on startup
+ if no problem happened at startup, everything went fine
+ Thanks to Hongfei Cheng and Brian Knox for the patch
+---------------------------------------------------------------------------
+Version 7.4.0 [v7.4-stable] 2013-06-06
+This starts a new stable branch based on 7.3.15 plus the following changes:
+- add --enable-cached-man-pages ./configure option
+ permits to build rsyslog on a system where rst2man is not installed. In
+ that case, cached versions of the man pages are used (they were built
+ during "make dist", so they should be current for the version in
+ question.
+- doc bugfix: ReadMode wrong in imfile doc, two values were swapped
+ Thanks to jokajak@gmail.com for mentioning this
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=450
+- imjournal: no longer do periodic wakeup
+- bugfix: potential hang *in debug mode* on rsyslogd termination
+ This ONLY affected rsyslogd if it were running with debug output
+ enabled.
+- bugfix: $template statement with multiple spaces lead to invalid tpl name
+ If multiple spaces were used in front of the template name, all but one
+ of them became actually part of the template name. So
+ $template a,"..." would be name " a", and as such "a" was not
+ available, e.g. in
+ *.* /var/log/file;a
+ This is a legacy config problem. As it was unreported for many years,
+ no backport of the fix to old versions will happen.
+ This is a long-standing bug that was only recently reported by forum
+ user mc-sim.
+ Reference: http://kb.monitorware.com/post23448.html
+- 0mq fixes; credits to Hongfei Cheng and Brian Knox
+---------------------------------------------------------------------------
+Version 7.3.15 [beta] 2013-05-15
+- bugfix: problem in build system (especially when cross-compiling)
+ Thanks to Tomas Heinrich and winfried_mb2@xmsnet.nl for the patch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=445
+- bugfix: imjournal had problem with systemd journal API change
+- imjournal: now obtain and include PID
+- bugfix: .logsig files had tlv16 indicator bit at wrong offset
+- bugfix: omrelp legacy config parameters set a timeout of zero
+ which lead the legacy config to be unusable.
+- bugfix: segfault on startup if a disk queue was configure without file
+ name
+ Now this triggers an error message and the queue is changed to
+ linkedList type.
+- bugfix: invalid addressing in string class (recent regression)
+---------------------------------------------------------------------------
+Version 7.3.14 [beta] 2013-05-06
+- bugfix: some man pages were not properly installed
+ either rscryutil or rsgtutil man was installed, but not both
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: potential segfault on startup when builtin module was specified
+ in module() statement.
+ Thanks to Marius Tomaschewski for reporting the bug.
+- bugfix: segfault due to invalid dynafile cache handling
+ Accidentally, the old-style cache size parameter was used when the
+ dynafile cache was created in a RainerScript action. If the old-style
+ size was lower than the one actually set, this lead to misaddressing
+ when the size was overrun, and that could lead to all kinds of
+ "interesting things", often in segfaults.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=440
+---------------------------------------------------------------------------
+Version 7.3.13 [beta] 2013-04-29
+- added omrabbitmq module (contributed, untested)
+ Note: this is unsupported and as such was moved immediately into the
+ beta version.
+ Thanks to Vaclav Tomec for providing this module.
+- bugfix: build problem when --enable-encryption was not selected
+ Thanks to Michael Biebl for fixing this.
+- doc bugfix: omfile parameter "VeryRobustZip" was documented as
+ "VeryReliableZip"
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=437
+ Thanks to Thomas Doll for reporting this.
+---------------------------------------------------------------------------
+Version 7.3.12 [devel] 2013-04-25
+- added doc for omelasticsearch
+ Thanks to Radu Gheorghe for the doc contribution.
+- omelasticsearch: _id field support for bulk operations
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=392
+ Thanks to Jérôme Renard for the idea and patches.
+- max number of templates for plugin use has been increased to five
+- platform compatibility enhancement: solve compile issue with libgcrypt
+ do not use GCRY_CIPHER_MODE_AESWRAP where not available
+- fix compile on Solaris
+ Thanks to Martin Carpenter for the patch.
+- bugfix: off-by-one error in handling local FQDN name (regression)
+ A temporary buffer was allocated one byte too small. Did only
+ affect startup, not actual operations. Came up during routine tests,
+ and can have no effect once the engine runs. Bug was introduced in
+ 7.3.11.
+- bugfix: build problems on Solaris
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=436
+- bugfix: block size limit was not properly honored
+- bugfix: potential segfault in guardtime signature provider
+ it could segfault if an error was reported by the GuardTime API, because
+ an invalid free could happen then
+---------------------------------------------------------------------------
+Version 7.3.11 [devel] 2013-04-23
+- added support for encrypting log files
+- omhiredis: added support for redis pipeline support
+ Thanks to Brian Knox for the patch.
+- bugfix: $PreserveFQDN is not properly working
+ Thanks to Louis Bouchard for the patch
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=426
+- bugfix: imuxsock aborted due to problem in ratelimiting code
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: imuxsock aborted under some conditions
+ regression from ratelimiting enhancements - this was a different one
+ to the one Tomas Heinrich patched.
+- bugfix: timestamp problems in imkmsg
+---------------------------------------------------------------------------
+Version 7.3.10 [devel] 2013-04-10
+- added RainerScript re_extract() function
+- omrelp: added support for RainerScript-based configuration
+- omrelp: added ability to specify session timeout
+- templates now permit substring extraction relative to end-of-string
+- bugfix: failover/action suspend did not work correctly
+ This was experienced if the retry action took more than one second
+ to complete. For suspending, a cached timestamp was used, and if the
+ retry took longer, that timestamp was already in the past. As a
+ result, the action never was kept in suspended state, and as such
+ no failover happened. The suspend functionality now does no longer use
+ the cached timestamp (should not have any performance implication, as
+ action suspend occurs very infrequently).
+- bugfix: gnutls RFC5425 driver had some undersized buffers
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: nested if/prifilt conditions did not work properly
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=415
+- bugfix: imuxsock aborted under some conditions
+ regression from ratelimiting enhancements
+- bugfix: build problems on Solaris
+ Thanks to Martin Carpenter for the patches.
+---------------------------------------------------------------------------
+Version 7.3.9 [devel] 2013-03-27
+- support for signing logs added
+- imudp: now supports user-selectable inputname
+- omlibdbi: now supports transaction interface
+ if recent enough lbdbi is present
+- imuxsock: add ability to NOT create/delete sockets during startup and
+ shutdown
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=259
+- imfile: errors persisting state file are now reported
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=292
+- imfile: now detects file change when rsyslog was inactive
+ Previously, this case could not be detected, so if a file was overwritten
+ or rotated away while rsyslog was stopped, some data was missing. This
+ is now detected and the new file being forwarded right from the
+ beginning.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=228
+- updated systemd files to match current systemd source
+- bugfix: imudp scheduling parameters did affect main thread, not imudp
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=409
+- bugfix: build problem on platforms without GLOB_NOMAGIC
+- bugfix: build problems on non-Linux platforms
+- bugfix: stdout/stderr were not closed on forking
+ but were closed when running in the foreground - this was just reversed
+ of what it should be. This is a regression of a recent change.
+---------------------------------------------------------------------------
+Version 7.3.8 [devel] 2013-03-18
+- imrelp: now supports listening to IPv4/v6 only instead of always both
+ build now requires librelp 1.0.2
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=378
+- bugfix: mmanon did not build on some platforms (e.g. Ubuntu)
+- bugfix: segfault in expression optimizer
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=423
+- bugfix: imuxsock was missing SysSock.ParseTrusted module parameter
+ To use that functionality, legacy rsyslog.conf syntax had to be used.
+ Also, the doc was missing information on the "ParseTrusted" set of
+ config directives.
+- bugfix: include files got included in the wrong order
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=411
+ This happens if an $IncludeConfig directive was done on multiple
+ files (e.g. the distro default of $IncludeConfig /etc/rsyslog.d/*.conf).
+ In that case, the order of include file processing is reversed, which
+ could lead to all sorts of problems.
+ Thanks to Nathan Stratton Treadway for his great analysis of the problem,
+ which made bug fixing really easy.
+---------------------------------------------------------------------------
+Version 7.3.7 [devel] 2013-03-12
+- add support for anonymizing IPv4 addresses
+- add support for writing to the Linux Journal (omjournal)
+- imuxsock: add capability to ignore messages from ourselves
+ This helps prevent message routing loops, and is vital to have
+ if omjournal is used together with traditional syslog.
+- field() function now supports a string as field delimiter
+- added ability to configure debug system via rsyslog.conf
+- bugfix: imuxsock segfault when system log socket was used
+- bugfix: mmjsonparse segfault if new-style config was used
+- bugfix: script == comparison did not work properly on JSON objects
+- bugfix: field() function did never return "***FIELD NOT FOUND***"
+ instead it returned "***ERROR in field() FUNCTION***" in that case
+---------------------------------------------------------------------------
+Version 7.3.6 [devel] 2013-01-28
+- greatly improved speed of large-array [N]EQ RainerScript comparisons
+ Thanks to David Lang for a related discussion that inspired the idea
+ to do this with a much simpler (yet sufficient) approach than originally
+ planned for.
+- greatly improved speed of DNS cache for large cache sizes
+- general performance improvements
+- omfile: added stats counters for dynafile caches
+- omfile: improved async writing, finally enabled full async write
+ also fixed a couple of smaller issues along that way
+- impstats: added ability to write stats records to local file
+ and avoid going through the syslog log stream. syslog logging can now
+ also be turned off (see doc for details).
+- bugfix: imklog issued wrong facility in error messages
+ ...what could lead to problems in other parts of the code
+- fix compile problem in imklog
+- added capability to output thread-id-to-function debug info
+ This is a useful debug aid, but nothing of concern for regular users.
+---------------------------------------------------------------------------
+Version 7.3.5 [devel] 2012-12-19
+- ommysql: addded batching/transaction support
+- enhanced script optimizer to optimize common PRI-based comparisons
+ These constructs are especially used in SUSE default config files,
+ but also by many users (as they are more readable than the equivalent
+ PRI-based filter).
+- omudpspoof: add support for new config system
+- omudpspoof: add support for packets larger than 1472 bytes
+ On Ethernet, they need to be transmitted in multiple fragments. While
+ it is known that fragmentation can cause issues, it is the best choice
+ to be made in that case. Also improved debug output.
+- bugfix: omudpspoof failed depending on the execution environment
+ The v7 engine closes fds, and closed some of libnet's fds as well, what
+ lead to problems (unfortunately, at least some libnet versions do not
+ report a proper error state but still "success"...). The order of libnet
+ calls has been adjusted to by in sync with what the core engine does.
+- bugfix: segfault on imuxsock startup if system log socket is used
+ and no ratelimiting supported. Happens only during initial config
+ read phase, once this is over, everything works stable.
+- bugfix: mmnormalize build problems
+- bugfix: mmnormalize could abort rsyslog if config parameter was in error
+- bugfix: no error message for invalid string template parameters
+ rather a malformed template was generated, and error information emitted
+ at runtime. However, this could be quite confusing. Note that with this
+ "bugfix" user experience changes: formerly, rsyslog and the affected
+ actions properly started up, but the actions did not produce proper
+ data. Now, there are startup error messages and the actions are NOT
+ executed (due to missing template due to template error).
+- bugfix[minor]: invalid error code when mmnormalize could not access
+ rulebase
+- bugfix(kind of): script optimizer did not work for complex boolean
+ expressions
+- doc bugfix: corrections and improvements in mmnormalize html doc page
+- bugfix: some message properties could be garbled due to race condition
+ This happened only on very high volume systems, if the same message was
+ being processed by two different actions. This was a regression caused
+ by the new config processor, which did no longer properly enable msg
+ locking in multithreaded cases. The bugfix is actually a refactoring of
+ the msg locking code - we no longer do unlocked operations, as the use
+ case for it has mostly gone away. It is potentially possible only at
+ very low-end systems, and there the small additional overhead of doing
+ the locking does not really hurt. Instead, the removal of that
+ capability can actually slightly improve performance in common cases,
+ as the code path is smaller and requires slightly less memory writes.
+ That probably outperforms the extra locking overhead (which in the
+ low-end case always happens in user space, without need for kernel
+ support as we can always directly acquire the lock - there is no
+ contention at all).
+- build system cleanup (thanks to Michael Biebl for this!)
+- bugfix: omelasticsearch did not properly compile on some platforms
+ due to missing libmath. Thanks to Michael Biebl for the fix
+---------------------------------------------------------------------------
+Version 7.3.4 [devel] 2012-11-23
+- further (and rather drastically) improved disk queue performance
+ we now save one third of the IO calls
+- imklog: added ParseKernelTimestamp parameter (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the patch.
+- imklog: added KeepKernelTimestamp parameter (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: improper handling of backslash in string-type template()s
+- bugfix: leading quote (") in string-type template() lead to tight loop
+ on startup
+- bugfix: no error msg on invalid field option in legacy/string template
+- bugfix: imklog mistakenly took kernel timestamp subseconds as nanoseconds
+ ... actually, they are microseconds. So the fractional part of the
+ timestamp was not properly formatted. (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the bug report and the patch idea.
+---------------------------------------------------------------------------
+Version 7.3.3 [devel] 2012-11-07
+- improved disk queue performance
+- bugfix: dynafile zip files could be corrupted
+ This could happen if a dynafile was destructed before the first write.
+ In practice, this could happen if few lines were written to a file and
+ it then became evicted from the dynafile cache. This would probably
+ look very random, because it depended on the timing in regard to
+ message volume and dynafile cache size.
+---------------------------------------------------------------------------
+Version 7.3.2 [devel] 2012-10-30
+- mmnormalize: support for v6+ config interface added
+- mmjsonparse: support for v6+ config interface added
+---------------------------------------------------------------------------
+Version 7.3.2 [devel] 2012-10-30
+- totally reworked ratelimiting and "last message repeated n times"
+ all over rsyslog code. Each of the supported inputs now supports
+ linux-like ratelimiting (formerly only imuxsock did). Also, the
+ "last message repeated n times" is now processed at the input side
+ and no longer at the output side of rsyslog processing. This
+ provides the basis for new future additions as well as usually more
+ performance and a much simpler output part (which can be even further
+ refactored).
+- imtcp: support for Linux-Type ratelimiting added
+- imptcp: support for Linux-Type ratelimiting added
+- imudp enhancements:
+ * support for input batching added (performance improvement)
+ * support for Linux-Type ratelimiting added
+- permited action-like statements (stop, call, ...) in action lists
+- bugfix: segfault on startup when modules using MSG_PASSING mode are used
+- omelasticsearch: support for writing data errors to local file added
+- omelasticsearch: fix check for bulk processing status response
+---------------------------------------------------------------------------
+Version 7.3.1 [devel] 2012-10-19
+- optimized template processing performance, especially for $NOW family
+ of properties
+- change lumberjack cookie to "@cee:" from "@cee: "
+ CEE originally specified the cookie with SP, whereas other lumberjack
+ tools used it without space. In order to keep interop with lumberjack,
+ we now use the cookie without space as well. I hope this can be changed
+ in CEE as well when it is released at a later time.
+ Thanks to Miloslav TrmaÄ for pointing this out and a similar v7 patch.
+- bugfix: imuxsock and imklog truncated head of received message
+ This happened only under some circumstances. Thanks to Marius
+ Tomaschewski, Florian Piekert and Milan Bartos for their help in
+ solving this issue.
+- bugfix: imuxsock did not properly honor $LocalHostIPIF
+---------------------------------------------------------------------------
+Version 7.3.0 [devel] 2012-10-09
+- omlibdbi improvements, added
+ * support for config load phases & module() parameters
+ * support for default templates
+ * driverdirectory is now cleanly a global parameter, but can no longer
+ be specified as an action parameter. Note that in previous versions
+ this parameter was ignored in all but the first action definition
+- improved omfile zip writer to increase compression
+ This was achieved by somewhat reducing the robustness of the zip archive.
+ This is controlled by the new action parameter "VeryReliableZip".
+----------------------------------------------------------------------------
+Version 7.2.8 [v7-stable] 2013-0?-??
+- bugfix: potential segfault on startup when builtin module was specified
+ in module() statement.
+ Thanks to Marius Tomaschewski for reporting the bug.
+- bugfix: segfault due to invalid dynafile cache handling
+ Accidentally, the old-style cache size parameter was used when the
+ dynafile cache was created in a RainerScript action. If the old-style
+ size was lower than the one actually set, this lead to misaddressing
+ when the size was overrun, and that could lead to all kinds of
+ "interesting things", often in segfaults.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=440
+----------------------------------------------------------------------------
+Version 7.2.7 [v7-stable] 2013-04-17
+- rsyslogd startup information is now properly conveyed back to init
+ when privileges are being dropped
+ Actually, we have moved termination of the parent in front of the
+ priv drop. So it shall work now in all cases. See code comments in
+ commit for more details.
+- If forking, the parent now waits for a maximum of 60 seconds for
+ termination by the child
+- improved debugging support in forked (auto-backgrounding) mode
+ The rsyslog debug log file is now continued to be written across the
+ fork.
+- updated systemd files to match current systemd source
+- bugfix: failover/action suspend did not work correctly
+ This was experienced if the retry action took more than one second
+ to complete. For suspending, a cached timestamp was used, and if the
+ retry took longer, that timestamp was already in the past. As a
+ result, the action never was kept in suspended state, and as such
+ no failover happened. The suspend functionality now does no longer use
+ the cached timestamp (should not have any performance implication, as
+ action suspend occurs very infrequently).
+- bugfix: nested if/prifilt conditions did not work properly
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=415
+- bugfix: script == comparison did not work properly on JSON objects
+ [backport from 7.3 branch]
+- bugfix: imudp scheduling parameters did affect main thread, not imudp
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=409
+- bugfix: imuxsock rate-limiting could not be configured via legacy conf
+ Rate-limiting for the system socket could not be configured via legacy
+ configuration directives. However, the new-style RainerScript config
+ options worked.
+ Thanks to Milan Bartos for the patch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=390
+- bugfix: using group resolution could lead to endless loop
+ Thanks to Tomas Heinrich for the patch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=310
+- bugfix: $mmnormalizeuseramsg parameter was specified with wrong type
+ Thank to Renzhong Zhang for alerting us of the problem.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=420
+- bugfix: RainerScript getenv() function caused segfault when var was
+ not found.
+ Thanks to Philippe Muller for the patch.
+- bugfix: several issues in imkmsg
+ see bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=421#c8
+- bugfix: imuxsock was missing SysSock.ParseTrusted module parameter
+ To use that functionality, legacy rsyslog.conf syntax had to be used.
+ Also, the doc was missing information on the "ParseTrusted" set of
+ config directives.
+- bugfix: parameter action.execOnlyWhenPreviousIsSuspended was accidentally
+ of integer-type. For obvious reasons, it needs to be boolean. Note
+ that this change can break existing configurations if they circumvented
+ the problem by using 0/1 values.
+- doc bugfix: rsyslog.conf man page had invalid file format info
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=418
+----------------------------------------------------------------------------
+Version 7.2.6 [v7-stable] 2013-03-05
+- slightly improved config parser error messages when invalid escapes happen
+- bugfix: include files got included in the wrong order
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=411
+ This happens if an $IncludeConfig directive was done on multiple
+ files (e.g. the distro default of $IncludeConfig /etc/rsyslog.d/*.conf).
+ In that case, the order of include file processing is reversed, which
+ could lead to all sorts of problems.
+ Thanks to Nathan Stratton Treadway for his great analysis of the problem,
+ which made bug fixing really easy.
+- bugfix: omelasticsearch failed when authentication data was provided
+ ... at least in most cases it emitted an error message:
+ "snprintf failed when trying to build auth string"
+ Thanks to Joerg Heinemann for alerting us.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=404
+- bugfix: some property-based filter were incorrectly parsed
+ This usually lead to a syntax error on startup and rsyslogd not actually
+ starting up. The problem was the regex, which did not care for double
+ quote characters to follow in the action part - unfortunately something
+ that can frequently happen with v6+ format. An example:
+ :programname, isequal, "as" {action(type="omfile" ...) }
+ Here, the part
+ :programname, isequal, "as" {action(type="omfile"
+ was treated as the property filter, and the rest as action part.
+ Obviously, this did not work out. Unfortunately, such situations usually
+ resulted in very hard to understand error messages.
+----------------------------------------------------------------------------
+Version 7.2.5 [v7-stable] 2013-01-08
+- build system cleanup (thanks to Michael Biebl for this!)
+- bugfix: omelasticsearch did not properly compile on some platforms
+ due to missing libmath. Thanks to Michael Biebl for the fix
+- bugfix: invalid DST handling under Solaris
+ Thanks to Scott Severtson for the patch.
+- bugfix: on termination, actions were incorrectly called
+ The problem was that incomplete fiter evaluation was done *during the
+ shutdown phase*. This affected only the LAST batches being processed. No
+ problem existed during the regular run. Could usually only happen on
+ very busy systems, which were still busy during shutdown.
+- bugfix: very large memory consumption (and probably out of memory) when
+ FromPos was specified in template, but ToPos not.
+ Thanks to Radu Gheorghe for alerting us of this bug.
+- bugfix: timeval2syslogTime cause problems on some platforms
+ due to invalid assumption on structure data types.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=394
+ Thanks to David Hill for the patch [under ASL2.0 as per email conversation
+ 2013-01-03].
+- bugfix: compile errors in im3195
+ Thanks to Martin Körper for the patch
+- bugfix: doGetFileCreateMode() had invalid validity check ;)
+ Thanks to Chandler Latour for the patch.
+- bugfix: mmjsonparse erroneously returned action error when no CEE cookie
+ was present.
+----------------------------------------------------------------------------
+Version 7.2.4 [v7-stable] 2012-12-07
+- enhance: permit RFC3339 timestamp in local log socket messages
+ Thanks to Sebastien Ponce for the patch.
+- imklog: added ParseKernelTimestamp parameter (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the patch.
+- fix missing functionality: ruleset(){} could not specify ruleset queue
+ The "queue.xxx" parameter set was not supported, and legacy ruleset
+ config statements did not work (by intention). The fix introduces the
+ "queue.xxx" parameter set. It has some regression potential, but only
+ for the new functionality. Note that using that interface it is possible
+ to specify duplicate queue file names, which will cause trouble. This
+ will be solved in v7.3, because there is a too-large regression
+ potential for the v7.2 stable branch.
+- imklog: added KeepKernelTimestamp parameter (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: imklog mistakenly took kernel timestamp subseconds as nanoseconds
+ ... actually, they are microseconds. So the fractional part of the
+ timestamp was not properly formatted. (import from 5.10.2)
+ Thanks to Marius Tomaschewski for the bug report and the patch idea.
+- bugfix: supportoctetcountedframing parameter did not work in imptcp
+- bugfix: modules not (yet) supporting new conf format were not properly
+ registered. This lead to a "module not found" error message instead of
+ the to-be-expected "module does not support new style" error message.
+ That invalid error message could be quite misleading and actually stop
+ people from addressing the real problem (aka "go nuts" ;))
+- bugfix: template "type" parameter is mandatory (but was not)
+- bugfix: some message properties could be garbled due to race condition
+ This happened only on very high volume systems, if the same message was
+ being processed by two different actions. This was a regression caused
+ by the new config processor, which did no longer properly enable msg
+ locking in multithreaded cases. The bugfix is actually a refactoring of
+ the msg locking code - we no longer do unlocked operations, as the use
+ case for it has mostly gone away. It is potentially possible only at
+ very low-end systems, and there the small additional overhead of doing
+ the locking does not really hurt. Instead, the removal of that
+ capability can actually slightly improve performance in common cases,
+ as the code path is smaller and requires slightly less memory writes.
+ That probably outperforms the extra locking overhead (which in the
+ low-end case always happens in user space, without need for kernel
+ support as we can always directly acquire the lock - there is no
+ contention at all).
+----------------------------------------------------------------------------
+Version 7.2.3 [v7-stable] 2012-10-21
+- regression fix: rsyslogd terminated when wild-card $IncludeConfig did not
+ find actual include files. For example, if this directive is present:
+ $IncludeConfig /etc/rsyslog.d/*.conf
+ and there are no *.conf files in /etc/rsyslog.d (but rsyslog.d exists),
+ rsyslogd will emit an error message and terminate. Previous (and expected)
+ behavior is that an empty file set is no problem. HOWEVER, if the
+ directory itself does not exist, this is flagged as an error and will
+ load to termination (no startup).
+ Unfortunately, this is often the case by default in many distros, so this
+ actually prevents rsyslog startup.
+----------------------------------------------------------------------------
+Version 7.2.2 [v7-stable] 2012-10-16
+- doc improvements
+- enabled to build without libuuid, at loss of uuid functionality
+ this enables smoother builds on older systems that do not support
+ libuuid. Loss of functionality should usually not matter too much as
+ uuid support has only recently been added and is very seldom used.
+- bugfix: omfwd did not properly support "template" parameter
+- bugfix: potential segfault when re_match() function was used
+ Thanks to oxpa for the patch.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=371
+- bugfix: potential abort of imtcp on rsyslogd shutdown
+- bugfix: imzmq3 segfault with PULL subscription
+ Thanks to Martin Nilsson for the patch.
+- bugfix: improper handling of backslash in string-type template()s
+- bugfix: leading quote (") in string-type template() lead to tight loop
+ on startup
+- bugfix: no error msg on invalid field option in legacy/string template
+- bugfix: potential segfault due to invalid param handling in comparisons
+ This could happen in RainerScript comparisons (like contains); in some
+ cases an uninitialized variable was accessed, which could lead to an
+ invalid free and in turn to a segfault.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=372
+ Thanks to Georgi Georgiev for reporting this bug and his great help
+ in solving it.
+- bugfix: no error msg on unreadable $IncludeConfig path
+- bugfix: $IncludeConfig did not correctly process directories
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=376
+ The testbench was also enhanced to check for these cases.
+ Thanks to Georgi Georgiev for the bug report.
+- bugfix: make rsyslog compile on kfreebsd again
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=380
+ Thanks to Guillem Jover for the patch.
+- bugfix: garbled message if field name was used with jsonf property option
+ The length for the field name was invalidly computed, resulting in either
+ truncated field names or including extra random data. If the random data
+ contained NULs, the rest of the message became unreadable.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=374
+- bugfix: potential segfault at startup with property-based filter
+ If the property name was followed by a space before the comma, rsyslogd
+ aborted on startup. Note that no segfault could happen if the initial
+ startup went well (this was a problem with the config parser).
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=381
+- bugfix: imfile discarded some file parts
+ File lines that were incomplete (LF missing) *at the time imfile polled
+ the file* were partially discarded. That part of the line that was read
+ without the LF was discarded, and the rest of the line was submitted in
+ the next polling cycle. This is now changed so that the partial content
+ is saved until the complete line is read. Note that the patch affects
+ only read mode 0.
+ Thanks to Milan Bartos for providing the base idea for the solution.
+----------------------------------------------------------------------------
+Version 7.2.1 [v7-stable] 2012-10-29
+- bugfix: ruleset()-object did only support a single statement
+- added -D rsyslogd option to enable config parser debug mode
+- improved syntax error messages by outputting the error token
+- the rsyslog core now suspends actions after 10 failures in a row
+ This was former the case after 1,000 failures and could cause rsyslog
+ to be spammed/resources misused. See the v6 compatibility doc for more
+ details.
+- ommongodb rate-limits error messages to prevent spamming the syslog
+ closes (for v7.2): http://bugzilla.adiscon.com/show_bug.cgi?id=366
+----------------------------------------------------------------------------
+Version 7.2.0 [v7-stable] 2012-10-22
+This starts a new stable branch based on 7.1.12 plus the following changes:
+- bugfix: imuxsock did not properly honor $LocalHostIPIF
+- omruleset/omdiscard do no longer issue "deprecated" warnings, as 7.1
+ grammar does not permit to use the replacements under all circumstances
+----------------------------------------------------------------------------
+Version 7.1.12 [beta] 2012-10-18
+- minor updates to better support newer systemd developments
+ Thanks to Michael Biebl for the patches.
+- build system cleanup
+ Thanks to Michael Biebl for the patch series.
+- cleanup: removed remains of -c option (compatibility mode)
+ both from code & doc and emitted warning message if still used
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=361
+ Thanks to Michael Biebl for reporting & suggestions
+- bugfix: imklog truncated head of received message
+ This happened only under some circumstances. Thanks to Marius
+ Tomaschewski and Florian Piekert for their help in solving this issue.
+----------------------------------------------------------------------------
+Version 7.1.11 [beta] 2012-10-16
+- bugfix: imuxsock truncated head of received message
+ This happened only under some circumstances. Thanks to Marius
+ Tomaschewski, Florian Piekert and Milan Bartos for their help in
+ solving this issue.
+- bugfix: do not crash if set statement is used with date field
+ Thanks to Miloslav TrmaÄ for the patch.
+- change lumberjack cookie to "@cee:" from "@cee: "
+ CEE originally specified the cookie with SP, whereas other lumberjack
+ tools used it without space. In order to keep interop with lumberjack,
+ we now use the cookie without space as well. I hope this can be changed
+ in CEE as well when it is released at a later time.
+ Thanks to Miloslav TrmaÄ for pointing this out and a similar v7 patch.
+- added deprecated note to omruleset (plus clue to use "call")
+- added deprecated note to discard action (plus clue to use "stop")
+---------------------------------------------------------------------------
+Version 7.1.10 [beta] 2012-10-11
+ - bugfix: m4 directory was not present in release tarball
+ - bugfix: small memory leak with string-type templates
+ - bugfix: small memory leak when template was specified in omfile
+ - bugfix: some config processing warning messages were treated as errors
+ - bugfix: small memory leak when processing action() statements
+ - bugfix: unknown action() parameters were not reported
+---------------------------------------------------------------------------
+Version 7.1.9 [beta] 2012-10-09
+- bugfix: comments inside objects (e.g. action()) were not properly handled
+- bugfix: in (non)equal comparisons the position of arrays influenced result
+ This behavior is OK for "contains"-type of comparisons (which have quite
+ different semantics), but not for == and <>, which shall be commutative.
+ This has been fixed now, so there is no difference any longer if the
+ constant string array is the left or right hand operand. We solved this
+ via the optimizer, as it keeps the actual script execution code small.
+---------------------------------------------------------------------------
+Version 7.1.8 [beta] 2012-10-02
+- bugfix: ruleset(){} directive erroneously changed default ruleset
+ much like the $ruleset legacy conf statement. This potentially lead
+ to statements being assigned to the wrong ruleset.
+- improved module doc
+- added "parser" parameter to ruleset(), so that parser chain can be
+ configured
+- implemented "continue" RainerScript statement
+---------------------------------------------------------------------------
+Version 7.1.7 [devel] 2012-10-01
+- implemented RainerScript "call" statement
+- implemented RainerScript array-based string comparison operations
+- implemented imtcp "permittedPeers" module-global parameter
+- imudp: support for specifying multiple ports via array added
+---------------------------------------------------------------------------
+Version 7.1.6 [devel] 2012-09-28
+- implemented RainerScript input() statement, including support for it
+ in major input plugins
+- implemented RainerScript ruleset() statement
+---------------------------------------------------------------------------
+Version 7.1.5 [devel] 2012-09-25
+- implemented RainerScript prifield() function
+- implemented RainerScript field() function
+- added new module imkmsg to process structured kernel log
+ Thanks to Milan Bartos for contributing this module
+- implemented basic RainerScript optimizer, which will speed up script
+ operations
+- bugfix: invalid free if function re_match() was incorrectly used
+ if the config file parser detected that param 2 was not constant, some
+ data fields were not initialized. The destructor did not care about that.
+ This bug happened only if rsyslog startup was unclean.
+---------------------------------------------------------------------------
+Version 7.1.4 [devel] 2012-09-19
+- implemented ability for CEE-based properties to be stored in disk queues
+- implemented string concatenation in expressions via &-operator
+- implemented json subtree copy in variable assignment
+- implemented full JSON support for variable manipulation
+- introduced "subtree"-type templates
+- bugfix: omfile action did not respect "template" parameter
+ ... and used default template in all cases
+- bugfix: MsgDup() did not copy CEE structure
+ This function was called at various places, most importantly during
+ "last messages repeated n times" processing and omruleset. If CEE(JSON)
+ data was present, it was lost as part of the copy process.
+- bugfix: debug output indicated improper queue type
+---------------------------------------------------------------------------
+Version 7.1.3 [devel] 2012-09-17
+- introduced "set" and "unset" config statements
+- bugfix: missing support for escape sequences in RainerScript
+ only \' was supported. Now the usual set is supported. Note that v5
+ used \x as escape where x was any character (e.g. "\n" meant "n" and NOT
+ LF). This also means there is some incompatibility to v5 for well-know
+ sequences. Better break it now than later.
+- bugfix: invalid property name in property-filter could cause abort
+ if action chaining (& operator) was used
+ http://bugzilla.adiscon.com/show_bug.cgi?id=355
+ Thanks to pilou@gmx.com for the bug report
+---------------------------------------------------------------------------
+Version 7.1.2 [devel] 2012-09-12
+- bugfix: messages were duplicated, sometimes massively
+ regression from new code in 7.1.1 and reason for early release
+- bugfix: remove invalid socket option call from imuxsock
+ Thanks to Cristian Ionescu-Idbohrn and Jonny Törnbom
+- bugfix: abort when invalid property name was configured
+ in property-based filter
+- bugfix: multiple rulesets did no longer work correctly (7.1.1 regression)
+---------------------------------------------------------------------------
+Version 7.1.1 [devel] 2012-09-11
+- MAJOR NEW FEATURE: ruleengine now fully supports nesting
+ including if ... then ... else ... constructs. This is a big change
+ and it obviously has a lot of bug potential.
+- BSD-style (filter) blocks are no longer supported
+ see https://www.rsyslog.com/g/BSD for details and solution
+- imuxsock now stores trusted properties by default in the CEE root
+ This was done in order to keep compatible with other implementations of
+ the lumberjack schema
+ Thanks to Miloslav TrmaÄ for pointing to this.
+- bugfix: string-generating templates caused abort if CEE field could not
+ be found
+---------------------------------------------------------------------------
+Version 7.1.0 [devel] 2012-09-06
+- added support for hierarchical properties (CEE/lumberjack)
+- added pure JSON output plugin parameter passing mode
+- ommongodb now supports templates
+- bugfix: imtcp could abort on exit due to invalid free()
+- imported bugfixes from 6.4.1
+---------------------------------------------------------------------------
+Version 6.6.1 [v6-stable] 2012-10-??
+- bugfix: build problems on some platforms
+- bugfix: misaddressing of $mmnormalizeuserawmsg parameter
+ On many platforms, this has no effect at all. At some, it may cause
+ a segfault. The problem occurs only during config phase, no segfault
+ happens when rsyslog has fully started.
+- fix API "glitch" in some plugins
+ This did not affect users, but could have caused trouble in the future
+ for developers.
+- bugfix: no error msg on invalid field option in legacy/string template
+- bugfix: no error msg on unreadable $IncludeConfig path
+- bugfix: $IncludeConfig did not correctly process directories
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=376
+ The testbench was also enhanced to check for these cases.
+ Thanks to Georgi Georgiev for the bug report.
+- bugfix: spurios error messages from imuxsock about (non-error) EAGAIN
+ Thanks to Marius Tomaschewski for the patch.
+- imklog: added $klogParseKernelTimestamp option
+ When enabled, kernel message [timestamp] is converted for message time.
+ Default is to use receive time as in 5.8.x and before, because the clock
+ used to create the timestamp is not supposed to be as accurate as the
+ monotonic clock (depends on hardware and kernel) resulting in differences
+ between kernel and system messages which occurred at same time.
+ Thanks to Marius Tomaschewski for the patch.
+- imklog: added $klogKeepKernelTimestamp option
+ When enabled, the kernel [timestamp] remains at begin of
+ each message, even it is used for the message time too.
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: imklog mistakenly took kernel timestamp subseconds as nanoseconds
+ ... actually, they are microseconds. So the fractional part of the
+ timestamp was not properly formatted.
+ Thanks to Marius Tomaschewski for the bug report and the patch idea.
+- bugfix: hostname set in rsyslog.conf was not picked up until HUP
+ which could also mean "never" or "not for a very long time".
+ Thanks to oxpa for providing analysis and a patch
+- bugfix: some message properties could be garbled due to race condition
+ This happened only on very high volume systems, if the same message was
+ being processed by two different actions. This was a regression caused
+ by the new config processor, which did no longer properly enable msg
+ locking in multithreaded cases. The bugfix is actually a refactoring of
+ the msg locking code - we no longer do unlocked operations, as the use
+ case for it has mostly gone away. It is potentially possible only at
+ very low-end systems, and there the small additional overhead of doing
+ the locking does not really hurt. Instead, the removal of that
+ capability can actually slightly improve performance in common cases,
+ as the code path is smaller and requires slightly less memory writes.
+ That probably outperforms the extra locking overhead (which in the
+ low-end case always happens in user space, without need for kernel
+ support as we can always directly acquire the lock - there is no
+ contention at all).
+- bugfix: invalid DST handling under Solaris
+ Thanks to Scott Severtson for the patch.
+---------------------------------------------------------------------------
+Version 6.6.0 [v6-stable] 2012-10-22
+This starts a new stable branch, based on the 6.5.x series, plus:
+- bugfix: imuxsock did not properly honor $LocalHostIPIF
+---------------------------------------------------------------------------
+Version 6.5.1 [beta] 2012-10-11
+- added tool "logctl" to handle lumberjack logs in MongoDB
+- imfile ported to new v6 config interface
+- imfile now supports config parameter for maximum number of submits
+ which is a fine-tuning parameter in regard to input batching
+- added pure JSON output plugin parameter passing mode
+- ommongodb now supports templates
+- bugfix: imtcp could abort on exit due to invalid free()
+- bugfix: remove invalid socket option call from imuxsock
+ Thanks to Cristian Ionescu-Idbohrn and Jonny Törnbom
+- added pure JSON output plugin parameter passing mode
+- ommongodb now supports templates
+- bugfix: imtcp could abort on exit due to invalid free()
+- bugfix: missing support for escape sequences in RainerScript
+ only \' was supported. Now the usual set is supported. Note that v5
+ used \x as escape where x was any character (e.g. "\n" meant "n" and NOT
+ LF). This also means there is some incompatibility to v5 for well-know
+ sequences. Better break it now than later.
+- bugfix: small memory leaks in template() statements
+ these were one-time memory leaks during startup, so they did NOT grow
+ during runtime
+- bugfix: config validation run did not always return correct return state
+- bugfix: config errors did not always cause statement to fail
+ This could lead to startup with invalid parameters.
+---------------------------------------------------------------------------
+Version 6.5.0 [devel] 2012-08-28
+- imrelp now supports non-cancel thread termination
+ (but now requires at least librelp 1.0.1)
+- implemented freeCnf() module interface
+ This was actually not present in older versions, even though some modules
+ already used it. The implementation was now done, and not in 6.3/6.4
+ because the resulting memory leak was ultra-slim and the new interface
+ handling has some potential to seriously break things. Not the kind of
+ thing you want to add in late beta state, if avoidable.
+- added --enable-debugless configure option for very high demanding envs
+ This actually at compile time disables a lot of debug code, resulting
+ in some speedup (but serious loss of debugging capabilities)
+- added new 0mq plugins (via czmq lib)
+ Thanks to David Kelly for contributing these modules
+- bugfix: omhdfs did no longer compile
+- bugfix: SystemLogSocketAnnotate did not work correctly
+ Thanks to Miloslav TrmaÄ for the patch
+- $SystemLogParseTrusted config file option
+ Thanks to Milan Bartos for the patch
+- added template config directive
+- added new uuid message property
+ Thanks to Jérôme Renard for the idea and patches.
+ Note: patches were released under ASL 2.0, see
+ http://bugzilla.adiscon.com/show_bug.cgi?id=353
+---------------------------------------------------------------------------
+Version 6.4.3 [V6-STABLE/NEVER RELEASED] 2012-??-??
+This version was never released as 6.6.0 came quickly enough. Note that
+all these patches here are present in 6.6.0.
+- cleanup: removed remains of -c option (compatibility mode)
+ both from code & doc and emitted warning message if still used
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=361
+ Thanks to Michael Biebl for reporting & suggestions
+- bugfix: imuxsock and imklog truncated head of received message
+ This happened only under some circumstances. Thanks to Marius
+ Tomaschewski, Florian Piekert and Milan Bartos for their help in
+ solving this issue.
+- change lumberjack cookie to "@cee:" from "@cee: "
+ CEE originally specified the cookie with SP, whereas other lumberjack
+ tools used it without space. In order to keep interop with lumberjack,
+ we now use the cookie without space as well. I hope this can be changed
+ in CEE as well when it is released at a later time.
+ Thanks to Miloslav TrmaÄ for pointing this out and a similar v7 patch.
+- bugfix: comments inside objects (e.g. action()) were not properly handled
+- bugfix: sysklogd-emulating standard template was no longer present in v6
+ This was obviously lost during the transition to the new config format.
+ Thanks to Milan Bartos for alerting us and a patch!
+- bugfix: some valid legacy PRI filters were flagged as erroneous
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=358
+ This happened to filters of the style "local0,local1.*", where the
+ multiple facilities were comma-separated.
+- bugfix: imuxsock did not properly honor $LocalHostIPIF
+---------------------------------------------------------------------------
+Version 6.4.2 [V6-STABLE] 2012-09-20
+- bugfix: potential abort, if action queue could not be properly started
+ This most importantly could happen due to configuration errors.
+- bugfix: remove invalid socket option call from imuxsock
+ Thanks to Cristian Ionescu-Idbohrn and Jonny Törnbom
+- bugfix: missing support for escape sequences in RainerScript
+ only \' was supported. Now the usual set is supported. Note that v5
+ used \x as escape where x was any character (e.g. "\n" meant "n" and NOT
+ LF). This also means there is some incompatibility to v5 for well-know
+ sequences. Better break it now than later.
+- bugfix: config validation run did not always return correct return state
+---------------------------------------------------------------------------
+Version 6.4.1 [V6-STABLE] 2012-09-06
+- bugfix: multiple main queues with same queue file name were not detected
+ This lead to queue file corruption. While the root cause is a config
+ error, it is a bug that this important and hard to find config error
+ was not detected by rsyslog.
+- bugfix: "jsonf" property replacer option did generate invalid JSON
+ in JSON, we have "fieldname":"value", but the option emitted
+ "fieldname"="value". Interestingly, this was accepted by a couple
+ of sinks, most importantly elasticsearch. Now the correct format is
+ emitted, which causes a remote chance that some things that relied on
+ the wrong format will break.
+ Thanks to Miloslav TrmaÄ for the patch
+- change $!all-json did emit an empty (thus non-JSON) string if no libee
+ data was present. It now emits {} and thus valid JSON. There is a
+ small risk that this may break some things that relied on the previous
+ inconsistency.
+ Thanks to Miloslav TrmaÄ for the patch
+- bugfix: omusrmsg incorrect return state & config warning handling
+ During config file processing, Omusrmsg often incorrectly returned a
+ warning status, even when no warning was present (caused by
+ uninitialized variable). Also, the core handled warning messages
+ incorrectly, and treated them as errors. As a result, omusrmsg
+ (most often) could not properly be loaded. Note that this only
+ occurs with legacy config action syntax. This was a regression
+ caused by an incorrect merge in to the 6.3.x codebase.
+ Thanks to Stefano Mason for alerting us of this bug.
+- bugfix: Fixed TCP CheckConnection handling in omfwd.c. Interface needed
+ to be changed in lower stream classes. Syslog TCP Sending is now resumed
+ properly. Unfixed, that lead to non-detection of downstate of remote
+ hosts.
+---------------------------------------------------------------------------
+Version 6.4.0 [V6-STABLE] 2012-08-20
+- THIS IS THE FIRST VERSION OF THE 6.4.x STABLE BRANCH
+ It includes all enhancements made in 6.3.x plus what is written in the
+ ChangeLog below.
+- omelasticsearch: support for parameters parent & dynparent added
+- bugfix: imtcp aborted when more than 2 connections were used.
+ Incremented pthread stack size to 4MB for imtcp, imptcp and imttcp
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=342
+- bugfix: imptcp aborted when $InputPTCPServerBindRuleset was used
+- bugfix: problem with cutting first 16 characters from message with
+ bAnnotate
+ Thanks to Milan Bartos for the patch.
+---------------------------------------------------------------------------
+Version 6.3.12 [BETA] 2012-07-02
+- support for elasticsearch via omelasticsearch added
+ Note that this module has been tested quite well by a number of folks,
+ and this is why we merge in new functionality in a late beta stage.
+ Even if problems would exist, only users of omelasticsearch would
+ experience them, making it a pretty safe addition.
+- bugfix: $ActionName was not properly honored
+ Thanks to Abby Edwards for alerting us
+---------------------------------------------------------------------------
+Version 6.3.11 [BETA] 2012-06-18
+- bugfix: expression-based filters with AND/OR could segfault
+ due to a problem with boolean shortcut operations. From the user's
+ perspective, the segfault is almost non-deterministic (it occurs when
+ a shortcut is used).
+ Thanks to Lars Peterson for providing the initial bug report and his
+ support in solving it.
+- bugfix: "last message repeated n times" message was missing hostname
+ Thanks to Zdenek Salvet for finding this bug and to Bodik for reporting
+---------------------------------------------------------------------------
+Version 6.3.10 [BETA] 2012-06-04
+- bugfix: delayable source could block action queue, even if there was
+ a disk queue associated with it. The root cause of this problem was
+ that it makes no sense to delay messages once they arrive in the
+ action queue - the "input" that is being held in that case is the main
+ queue worker, what makes no sense.
+ Thanks to Marcin for alerting us on this problem and providing
+ instructions to reproduce it.
+- bugfix: invalid free in imptcp could lead to abort during startup
+- bugfix: if debug message could end up in log file when forking
+ if rsyslog was set to auto-background (thus fork, the default) and debug
+ mode to stdout was enabled, debug messages ended up in the first log file
+ opened. Currently, stdout logging is completely disabled in forking mode
+ (but writing to the debug log file is still possible). This is a change
+ in behavior, which is under review. If it causes problems to you,
+ please let us know.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: --enable-smcustbindcdr configure directive did not work
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=330
+ Thanks to Ultrabug for the patch.
+- bugfix: made rsyslog compile when libestr ist not installed in /usr
+ Thanks to Miloslav TrmaÄ for providing patches and suggestions
+---------------------------------------------------------------------------
+Version 6.3.9 [BETA] 2012-05-22
+- bugfix: imtcp could cause hang during reception
+ this also applied to other users of core file tcpsrv.c, but imtcp was
+ by far the most prominent and widely-used, the rest rather exotic
+ (like imdiag)
+- added capability to specify substrings for field extraction mode
+- added the "jsonf" property replacer option (and fieldname)
+- bugfix: omudpspoof did not work correctly if no spoof hostname was
+ configured
+- bugfix: property replacer option "json" could lead to content loss
+ message was truncated if escaping was necessary
+- bugfix: assigned ruleset was lost when using disk queues
+ This looked quite hard to diagnose for disk-assisted queues, as the
+ pure memory part worked well, but ruleset info was lost for messages
+ stored inside the disk queue.
+- bugfix/imuxsock: solving abort if hostname was not set; configured
+ hostname was not used (both merge regressions)
+ -bugfix/omfile: template action parameter was not accepted
+ (and template name set to "??" if the parameter was used)
+ Thanks to Brian Knox for alerting us on this bug.
+- bugfix: ommysql did not properly init/exit the mysql runtime library
+ this could lead to segfaults. Triggering condition: multiple action
+ instances using ommysql. Thanks to Tomas Heinrich for reporting this
+ problem and providing an initial patch (which my solution is based on,
+ I need to add more code to clean the mess up).
+- bugfix: rsyslog did not terminate when delayable inputs were blocked
+ due to unavailable sources. Fixes:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ Thanks to Marcin M for bringing up this problem and Andre Lorbach
+ for helping to reproduce and fix it.
+- added capability to specify substrings for field extraction mode
+- bugfix: disk queue was not persisted on shutdown, regression of fix to
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ The new code also handles the case of shutdown of blocking light and
+ full delayable sources somewhat smarter and permits, assuming sufficient
+ timeouts, to persist message up to the max queue capacity. Also some nits
+ in debug instrumentation have been fixed.
+---------------------------------------------------------------------------
+Version 6.3.8 [DEVEL] 2012-04-16
+- added $PStatJSON directive to permit stats records in JSON format
+- added "date-unixtimestamp" property replacer option to format as a
+ unix timestamp (seconds since epoch)
+- added "json" property replacer option to support JSON encoding on a
+ per-property basis
+- added omhiredis (contributed module)
+- added mmjsonparse to support recognizing and parsing JSON enhanced syslog
+ messages
+- upgraded more plugins to support the new v6 config format:
+ - ommysql
+ - omlibdbi
+ - omsnmp
+- added configuration directives to customize queue light delay marks
+ $MainMsgQueueLightDelayMark, $ActionQueueLightDelayMark; both
+ specify number of messages starting at which a delay happens.
+- added message property parsesuccess to indicate if the last run
+ higher-level parser could successfully parse the message or not
+ (see property replacer html doc for details)
+- bugfix: abort during startup when rsyslog.conf v6+ format was used in
+ a certain way
+- bugfix: property $!all-json made rsyslog abort if no normalized data
+ was available
+- bugfix: memory leak in array passing output module mode
+- added configuration directives to customize queue light delay marks
+- permit size modifiers (k,m,g,...) in integer config parameters
+ Thanks to Jo Rhett for the suggestion.
+- bugfix: hostname was not requeried on HUP
+ Thanks to Per Jessen for reporting this bug and Marius Tomaschewski for
+ his help in testing the fix.
+- bugfix: imklog invalidly computed facility and severity
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=313
+- added configuration directive to disable octet-counted framing
+ for imtcp, directive is $InputTCPServerSupportOctetCountedFraming
+ for imptcp, directive is $InputPTCPServerSupportOctetCountedFraming
+- added capability to use a local interface IP address as fromhost-ip for
+ locally originating messages. New directive $LocalHostIPIF
+---------------------------------------------------------------------------
+Version 6.3.7 [DEVEL] 2012-02-02
+- imported refactored v5.9.6 imklog linux driver, now combined with BSD
+ driver
+- removed imtemplate/omtemplate template modules, as this was waste of time
+ The actual input/output modules are better copy templates. Instead, the
+ now-removed modules cost time for maintenance AND often caused confusion
+ on what their role was.
+- added a couple of new stats objects
+- improved support for new v6 config system. The build-in output modules
+ now all support the new config language
+- bugfix: facility local<x> was not correctly interpreted in legacy filters
+ Was only accepted if it was the first PRI in a multi-filter PRI.
+ Thanks to forum user Mark for bringing this to our attention.
+- bugfix: potential abort after reading invalid X.509 certificate
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=290
+ Thanks to Tomas Heinrich for the patch
+- bugfix: legacy parsing of some filters did not work correctly
+- bugfix: rsyslog aborted during startup if there is an error in loading
+ an action and legacy configuration mode is used
+- bugfix: bsd klog driver did no longer compile
+- relicensed larger parts of the code under Apache (ASL) 2.0
+---------------------------------------------------------------------------
+Version 6.3.6 [DEVEL] 2011-09-19
+- added $InputRELPServerBindRuleset directive to specify rulesets for RELP
+- bugfix: config parser did not support properties with dashes in them
+ inside property-based filters. Thanks to Gerrit Seré for reporting this.
+---------------------------------------------------------------------------
+Version 6.3.5 [DEVEL] (rgerhards/al), 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: mark message processing did not work correctly
+- imudp&imtcp now report error if no listener at all was defined
+ Thanks to Marcin for suggesting this error message.
+- bugfix: potential misaddressing in property replacer
+---------------------------------------------------------------------------
+Version 6.3.4 [DEVEL] (rgerhards), 2011-08-02
+- added support for action() config object
+ * in rsyslog core engine
+ * in omfile
+ * in omusrmsg
+- bugfix: omusrmsg format usr1,usr2 was no longer supported
+- bugfix: misaddressing in config handler
+ In theory, can cause segfault, in practice this is extremely unlikely
+ Thanks to Marcin for alerting me.
+---------------------------------------------------------------------------
+Version 6.3.3 [DEVEL] (rgerhards), 2011-07-13
+- rsyslog.conf format: now parsed by RainerScript parser
+ this provides the necessary base for future enhancements as well as some
+ minor immediate ones. For details see:
+ http://blog.gerhards.net/2011/07/rsyslog-633-config-format-improvements.html
+- performance of script-based filters notably increased
+- removed compatibility mode as we expect people have adjusted their
+ confs by now
+- added support for the ":omfile:" syntax for actions
+---------------------------------------------------------------------------
+Version 6.3.2 [DEVEL] (rgerhards), 2011-07-06
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- systemd support: set stdout/stderr to null - thx to Lennart for the patch
+- added support for obtaining timestamp for kernel message from message
+ If the kernel time-stamps messages, time is now take from that
+ timestamp instead of the system time when the message was read. This
+ provides much better accuracy. Thanks to Lennart Poettering for
+ suggesting this feature and his help during implementation.
+- added support for obtaining timestamp from system for imuxsock
+ This permits to read the time a message was submitted to the system
+ log socket. Most importantly, this is provided in microsecond resolution.
+ So we are able to obtain high precision timestampis even for messages
+ that were - as is usual - not formatted with them. This also simplifies
+ things in regard to local time calculation in chroot environments.
+ Many thanks to Lennart Poettering for suggesting this feature,
+ providing some guidance on implementing it and coordinating getting the
+ necessary support into the Linux kernel.
+- bugfix: timestamp was incorrectly calculated for timezones with minute
+ offset
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=271
+- bugfix: memory leak in imtcp & subsystems under some circumstances
+ This leak is tied to error conditions which lead to incorrect cleanup
+ of some data structures.
+---------------------------------------------------------------------------
+Version 6.3.1 [DEVEL] (rgerhards), 2011-06-07
+- added a first implementation of a DNS name cache
+ this still has a couple of weaknesses, like no expiration of entries,
+ suboptimal algorithms -- but it should perform much better than
+ what we had previously. Implementation will be improved based on
+ feedback during the next couple of releases
+---------------------------------------------------------------------------
+Version 6.3.0 [DEVEL] (rgerhards), 2011-06-01
+- introduced new config system
+ http://blog.gerhards.net/2011/06/new-rsyslog-config-system-materializes.html
+---------------------------------------------------------------------------
+Version 6.2.2 [v6-stable], 2012-06-13
+- build system improvements and spec file templates
+ Thanks to Abby Edwards for providing these enhancements
+- bugfix: disk queue was not persisted on shutdown, regression of fix to
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ The new code also handles the case of shutdown of blocking light and
+ full delayable sources somewhat smarter and permits, assuming sufficient
+ timeouts, to persist message up to the max queue capacity. Also some nits
+ in debug instrumentation have been fixed.
+- bugfix: --enable-smcustbindcdr configure directive did not work
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=330
+ Thanks to Ultrabug for the patch.
+- add small delay (50ms) after sending shutdown message
+ There seem to be cases where the shutdown message is otherwise not
+ processed, not even on an idle system. Thanks to Marcin for
+ bringing this problem up.
+- support for resolving huge groups
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=310
+ Thanks to Alec Warner for the patch
+- bugfix: potential hang due to mutex deadlock
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=316
+ Thanks to Andreas Piesk for reporting&analyzing this bug as well as
+ providing patches and other help in resolving it.
+- bugfix: property PROCID empty instead of proper nilvalue if not present
+ If it is not present, it must have the nilvalue "-" as of RFC5424
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=332
+ Thanks to John N for reporting this issue.
+- bugfix: did not compile under solaris due to $uptime property code
+ For the time being, $uptime is not supported on Solaris
+- bugfix: "last message repeated n times" message was missing hostname
+ Thanks to Zdenek Salvet for finding this bug and to Bodik for reporting
+---------------------------------------------------------------------------
+Version 6.2.1 [v6-stable], 2012-05-10
+- change plugin config interface to be compatible with pre-v6.2 system
+ The functionality was already removed (because it is superseded by the
+ v6.3+ config language), but code was still present. I have now removed
+ those parts that affect interface. Full removal will happen in v6.3, in
+ order to limit potential regressions. However, it was considered useful
+ enough to do the interface change in v6-stable; this also eases merging
+ branches!
+- re-licensed larger parts of the codebase under the Apache license 2.0
+- bugfix: omprog made rsyslog abort on startup if not binary to
+ execute was configured
+- bugfix: imklog invalidly computed facility and severity
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=313
+- bugfix: stopped DA queue was never processed after a restart due to a
+ regression from statistics module
+- bugfix: memory leak in array passing output module mode
+- bugfix: ommysql did not properly init/exit the mysql runtime library
+ this could lead to segfaults. Triggering condition: multiple action
+ instances using ommysql. Thanks to Tomas Heinrich for reporting this
+ problem and providing an initial patch (which my solution is based on,
+ I need to add more code to clean the mess up).
+- bugfix: rsyslog did not terminate when delayable inputs were blocked
+ due to unavailable sources. Fixes:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ Thanks to Marcin M for bringing up this problem and Andre Lorbach
+ for helping to reproduce and fix it.
+- bugfix/tcpflood: sending small test files did not work correctly
+---------------------------------------------------------------------------
+Version 6.2.0 [v6-stable], 2012-01-09
+- bugfix (kind of): removed numerical part from pri-text
+ see v6 compatibility document for reasons
+- bugfix: race condition when extracting program name, APPNAME, structured
+ data and PROCID (RFC5424 fields) could lead to invalid characters e.g.
+ in dynamic file names or during forwarding (general malfunction of these
+ fields in templates, mostly under heavy load)
+- bugfix: imuxsock did no longer ignore message-provided timestamp, if
+ so configured (the *default*). Lead to no longer sub-second timestamps.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=281
+- bugfix: omfile returns fatal error code for things that go really wrong
+ previously, RS_RET_RESUME was returned, which lead to a loop inside the
+ rule engine as omfile could not really recover.
+- bugfix: potential abort after reading invalid X.509 certificate
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=290
+ Thanks to Tomas Heinrich for the patch
+- enhanced module loader to not rely on PATH_MAX
+- imuxsock: added capability to "annotate" messages with "trusted
+ information", which contains some properties obtained from the system
+ and as such sure to not be faked. This is inspired by the similar idea
+ introduced in systemd.
+---------------------------------------------------------------------------
+Version 6.1.12 [BETA], 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: mark message processing did not work correctly
+- bugfix: potential misaddressing in property replacer
+- bugfix: memcpy overflow can occur in allowed sender checking
+ if a name is resolved to IPv4-mapped-on-IPv6 address
+ Found by Ismail Dönmez at suse
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+- bugfix: fixed incorrect state handling for Discard Action (transactions)
+ Note: This caused all messages in a batch to be set to COMMITTED,
+ even if they were discarded.
+---------------------------------------------------------------------------
+Version 6.1.11 [BETA] (rgerhards), 2011-07-11
+- systemd support: set stdout/stderr to null - thx to Lennart for the patch
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- added support for the ":omfile:" syntax in configuring user messages
+---------------------------------------------------------------------------
+Version 6.1.10 [BETA] (rgerhards), 2011-06-22
+- bugfix: problems in failover action handling
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=270
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=254
+- bugfix: mutex was invalidly left unlocked during action processing
+ At least one case where this can occur is during thread shutdown, which
+ may be initiated by lower activity. In most cases, this is quite
+ unlikely to happen. However, if it does, data structures may be
+ corrupted which could lead to fatal failure and segfault. I detected
+ this via a testbench test, not a user report. But I assume that some
+ users may have had unreproducable aborts that were cause by this bug.
+---------------------------------------------------------------------------
+Version 6.1.9 [BETA] (rgerhards), 2011-06-14
+- bugfix: problems in failover action handling
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=270
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=254
+- bugfix: mutex was invalidly left unlocked during action processing
+ At least one case where this can occur is during thread shutdown, which
+ may be initiated by lower activity. In most cases, this is quite
+ unlikely to happen. However, if it does, data structures may be
+ corrupted which could lead to fatal failure and segfault. I detected
+ this via a testbench test, not a user report. But I assume that some
+ users may have had unreproducable aborts that were cause by this bug.
+- bugfix/improvement:$WorkDirectory now gracefully handles trailing slashes
+- bugfix: memory leak in imtcp & subsystems under some circumstances
+ This leak is tied to error conditions which lead to incorrect cleanup
+ of some data structures. [backport from v6.3]
+- bugfix: $ActionFileDefaultTemplate did not work
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=262
+---------------------------------------------------------------------------
+Version 6.1.8 [BETA] (rgerhards), 2011-05-20
+- official new beta version (note that in a sense 6.1.7 was already beta,
+ so we may release the first stable v6 earlier than usual)
+- new module mmsnmptrapd, a sample message modification module
+- import of minor bug fixes from v4 & v5
+---------------------------------------------------------------------------
+Version 6.1.7 [DEVEL] (rgerhards), 2011-04-15
+- added log classification capabilities (via mmnormalize & tags)
+- speeded up tcp forwarding by reducing number of API calls
+ this especially speeds up TLS processing
+- somewhat improved documentation index
+- bugfix: enhanced imudp config processing code disabled due to wrong
+ merge (affected UDP realtime capabilities)
+- bugfix (kind of): memory leak with tcp reception epoll handler
+ This was an extremely unlikely leak and, if it happened, quite small.
+ Still it is better to handle this border case.
+- bugfix: IPv6-address could not be specified in omrelp
+ this was due to improper parsing of ":"
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=250
+- bugfix: do not open files with full privileges, if privs will be dropped
+ This make the privilege drop code more bulletproof, but breaks Ubuntu's
+ work-around for log files created by external programs with the wrong
+ user and/or group. Note that it was long said that this "functionality"
+ would break once we go for serious privilege drop code, so hopefully
+ nobody still depends on it (and, if so, they lost...).
+- bugfix: pipes not opened in full priv mode when privs are to be dropped
+---------------------------------------------------------------------------
+Version 6.1.6 [DEVEL] (rgerhards), 2011-03-14
+- enhanced omhdfs to support batching mode. This permits to increase
+ performance, as we now call the HDFS API with much larger message
+ sizes and far more infrequently
+- improved testbench
+ among others, life tests for ommysql (against a test database) have
+ been added, valgrind-based testing enhanced, ...
+- bugfix: minor memory leak in omlibdbi (< 1k per instance and run)
+- bugfix: (regression) omhdfs did no longer compile
+- bugfix: omlibdbi did not use password from rsyslog.con
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=203
+- systemd support somewhat improved (can now take over existing log sockt)
+- bugfix: discard action did not work under some circumstances
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=217
+- bugfix: file descriptor leak in gnutls netstream driver
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=222
+- fixed compile problem in imtemplate
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=235
+---------------------------------------------------------------------------
+Version 6.1.5 [DEVEL] (rgerhards), 2011-03-04
+- improved testbench
+- enhanced imtcp to use a pool of worker threads to process incoming
+ messages. This enables higher processing rates, especially in the TLS
+ case (where more CPU is needed for the crypto functions)
+- added support for TLS (in anon mode) to tcpflood
+- improved TLS error reporting
+- improved TLS startup (Diffie-Hellman bits do not need to be generated,
+ as we do not support full anon key exchange -- we always need certs)
+- bugfix: fixed a memory leak and potential abort condition
+ this could happen if multiple rulesets were used and some output batches
+ contained messages belonging to more than one ruleset.
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=226
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=218
+- bugfix: memory leak when $RepeatedMsgReduction on was used
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=225
+- bugfix: potential abort condition when $RepeatedMsgReduction set to on
+ as well as potentially in a number of other places where MsgDup() was
+ used. This only happened when the imudp input module was used and it
+ depended on name resolution not yet had taken place. In other words,
+ this was a strange problem that could lead to hard to diagnose
+ instability. So if you experience instability, chances are good that
+ this fix will help.
+---------------------------------------------------------------------------
+Version 6.1.4 [DEVEL] (rgerhards), 2011-02-18
+- bugfix/omhdfs: directive $OMHDFSFileName rendered unusable
+ due to a search and replace-induced bug ;)
+- bugfix: minor race condition in action.c - considered cosmetic
+ This is considered cosmetic as multiple threads tried to write exactly
+ the same value into the same memory location without sync. The method
+ has been changed so this can no longer happen.
+- added pmsnare parser module (written by David Lang)
+- enhanced imfile to support non-cancel input termination
+- improved systemd socket activation thanks to Marius Tomaschewski
+- improved error reporting for $WorkDirectory
+ non-existence and other detectable problems are now reported,
+ and the work directory is NOT set in this case
+- bugfix: pmsnare caused abort under some conditions
+- bugfix: abort if imfile reads file line of more than 64KiB
+ Thanks to Peter Eisentraut for reporting and analyzing this problem.
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=221
+- bugfix: queue engine did not properly slow down inputs in FULL_DELAY mode
+ when in disk-assisted mode. This especially affected imfile, which
+ created unnecessarily queue files if a large set of input file data was
+ to process.
+- bugfix: very long running actions could prevent shutdown under some
+ circumstances. This has now been solved, at least for common
+ situations.
+- bugfix: fixed compile problem due to empty structs
+ this occurred only on some platforms/compilers. thanks to Dražen KaÄar
+ for the fix
+---------------------------------------------------------------------------
+Version 6.1.3 [DEVEL] (rgerhards), 2011-02-01
+- experimental support for mongodb added
+- added $IMUDPSchedulingPolicy and $IMUDPSchedulingPriority config settings
+- added $LocalHostName config directive
+- improved tcpsrv performance by enabling multiple-entry epoll
+ so far, we always pulled a single event from the epoll interface.
+ Now 128, what should result in performance improvement (less API
+ calls) on busy systems. Most importantly affects imtcp.
+- imptcp now supports non-cancel termination mode, a plus in stability
+- imptcp speedup: multiple worker threads can now be used to read data
+- new directive $InputIMPTcpHelperThreads added
+- bugfix: fixed build problems on some platforms
+ namely those that have 32bit atomic operations but not 64 bit ones
+- bugfix: local hostname was pulled too-early, so that some config
+ directives (namely FQDN settings) did not have any effect
+- enhanced tcpflood to support multiple sender threads
+ this is required for some high-throughput scenarios (and necessary to
+ run some performance tests, because otherwise the sender is too slow).
+- added some new custom parsers (snare, aix, some Cisco "specialities")
+ thanks to David Lang
+---------------------------------------------------------------------------
+Version 6.1.2 [DEVEL] (rgerhards), 2010-12-16
+- added experimental support for log normalization (via liblognorm)
+ support for normalizing log messages has been added in the form of
+ mmnormalize. The core engine (property replacer, filter engine) has
+ been enhanced to support properties from normalized events.
+ Note: this is EXPERIMENTAL code. It is currently know that
+ there are issues if the functionality is used with
+ - disk-based queues
+ - asynchronous action queues
+ You can not use the new functionality together with these features.
+ This limitation will be removed in later releases. However, we
+ preferred to release early, so that one can experiment with the new
+ feature set and accepted the price that this means the full set of
+ functionality is not yet available. If not used together with
+ these features, log normalizing should be pretty stable.
+- enhanced testing tool tcpflood
+ now supports sending via UDP and the capability to run multiple
+ iterations and generate statistics data records
+- bugfix: potential abort when output modules with different parameter
+ passing modes were used in configured output modules
+---------------------------------------------------------------------------
+Version 6.1.1 [DEVEL] (rgerhards), 2010-11-30
+- bugfix(important): problem in TLS handling could cause rsyslog to loop
+ in a tight loop, effectively disabling functionality and bearing the
+ risk of unresponsiveness of the whole system.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=194
+- support for omhdfs officially added (import from 5.7.1)
+- merged imuxsock improvements from 5.7.1 (see there)
+- support for systemd officially added (import from 5.7.0)
+- bugfix: a couple of problems that imfile had on some platforms, namely
+ Ubuntu (not their fault, but occurred there)
+- bugfix: imfile utilizes 32 bit to track offset. Most importantly,
+ this problem can not experienced on Fedora 64 bit OS (which has
+ 64 bit long's!)
+- a number of other bugfixes from older versions imported
+---------------------------------------------------------------------------
+Version 6.1.0 [DEVEL] (rgerhards), 2010-08-12
+
+*********************************** NOTE **********************************
+The v6 versions of rsyslog feature a greatly redesigned config system
+which, among others, supports scoping. However, the initial version does
+not contain the whole new system. Rather it will evolve. So it is
+expected that interfaces, even new ones, break during the initial
+6.x.y releases.
+*********************************** NOTE **********************************
+
+- added $Begin, $End and $ScriptScoping config scope statements
+ (at this time for actions only).
+- added imptcp, a simplified, Linux-specific and potentially fast
+ syslog plain tcp input plugin (NOT supporting TLS!)
+ [ported from v4]
+---------------------------------------------------------------------------
+Version 5.10.2 [V5-STABLE], 201?-??-??
+- bugfix: queue file size was not correctly processed
+ this could lead to using one queue file per message for sizes >2GiB
+ Thanks to Tomas Heinrich for the patch.
+- updated systemd files to match current systemd source
+- bugfix: spurios error messages from imuxsock about (non-error) EAGAIN
+ Thanks to Marius Tomaschewski for the patch.
+- imklog: added $klogParseKernelTimestamp option
+ When enabled, kernel message [timestamp] is converted for message time.
+ Default is to use receive time as in 5.8.x and before, because the clock
+ used to create the timestamp is not supposed to be as accurate as the
+ monotonic clock (depends on hardware and kernel) resulting in differences
+ between kernel and system messages which occurred at same time.
+ Thanks to Marius Tomaschewski for the patch.
+- imklog: added $klogKeepKernelTimestamp option
+ When enabled, the kernel [timestamp] remains at begin of
+ each message, even it is used for the message time too.
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: imklog mistakenly took kernel timestamp subseconds as nanoseconds
+ ... actually, they are microseconds. So the fractional part of the
+ timestamp was not properly formatted.
+ Thanks to Marius Tomaschewski for the bug report and the patch idea.
+- imklog: added $klogKeepKernelTimestamp option
+ When enabled, the kernel [timestamp] remains at begin of
+ each message, even it is used for the message time too.
+ Thanks to Marius Tomaschewski for the patch.
+- bugfix: imklog mistakenly took kernel timestamp subseconds as nanoseconds
+ ... actually, they are microseconds. So the fractional part of the
+ timestamp was not properly formatted.
+ Thanks to Marius Tomaschewski for the bug report and the patch idea.
+- bugfix: invalid DST handling under Solaris
+ Thanks to Scott Severtson for the patch.
+- bugfix: invalid decrement in pm5424 could lead to log truncation
+ Thanks to Tomas Heinrich for the patch.
+- bugfix[kind of]: omudpspoof discarded messages >1472 bytes (MTU size)
+ it now truncates these message, but ensures they are sent. Note that
+ 7.3.5+ will switch to fragmented UDP messages instead (up to 64K)
+---------------------------------------------------------------------------
+Version 5.10.1 [V5-STABLE], 2012-10-17
+- bugfix: imuxsock and imklog truncated head of received message
+ This happened only under some circumstances. Thanks to Marius
+ Tomaschewski, Florian Piekert and Milan Bartos for their help in
+ solving this issue.
+- enable DNS resolution in imrelp
+ Thanks to Apollon Oikonomopoulos for the patch
+- bugfix: invalid property name in property-filter could cause abort
+ if action chaining (& operator) was used
+ http://bugzilla.adiscon.com/show_bug.cgi?id=355
+ Thanks to pilou@gmx.com for the bug report
+- bugfix: remove invalid socket option call from imuxsock
+ Thanks to Cristian Ionescu-Idbohrn and Jonny Törnbom
+- bugfix: fixed wrong bufferlength for snprintf in tcpflood.c when using
+ the -f (dynafiles) option.
+- fixed issues in build system (namely related to cust1 dummy plugin)
+---------------------------------------------------------------------------
+Version 5.10.0 [V5-STABLE], 2012-08-23
+
+NOTE: this is the new rsyslog v5-stable, incorporating all changes from the
+ 5.9.x series. In addition to that, it contains the fixes and
+ enhancements listed below in this entry.
+
+- bugfix: delayable source could block action queue, even if there was
+ a disk queue associated with it. The root cause of this problem was
+ that it makes no sense to delay messages once they arrive in the
+ action queue - the "input" that is being held in that case is the main
+ queue worker, what makes no sense.
+ Thanks to Marcin for alerting us on this problem and providing
+ instructions to reproduce it.
+- bugfix: disk queue was not persisted on shutdown, regression of fix to
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ The new code also handles the case of shutdown of blocking light and
+ full delayable sources somewhat smarter and permits, assuming sufficient
+ timeouts, to persist message up to the max queue capacity. Also some nits
+ in debug instrumentation have been fixed.
+- add small delay (50ms) after sending shutdown message
+ There seem to be cases where the shutdown message is otherwise not
+ processed, not even on an idle system. Thanks to Marcin for
+ bringing this problem up.
+- support for resolving huge groups
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=310
+ Thanks to Alec Warner for the patch
+- bugfix: potential hang due to mutex deadlock
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=316
+ Thanks to Andreas Piesk for reporting&analyzing this bug as well as
+ providing patches and other help in resolving it.
+- bugfix: property PROCID empty instead of proper nilvalue if not present
+ If it is not present, it must have the nilvalue "-" as of RFC5424
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=332
+ Thanks to John N for reporting this issue.
+- bugfix: "last message repeated n times" message was missing hostname
+ Thanks to Zdenek Salvet for finding this bug and to Bodik for reporting
+- bugfix: multiple main queues with same queue file name was not detected
+ This lead to queue file corruption. While the root cause is a config
+ error, it is a bug that this important and hard to find config error
+ was not detected by rsyslog.
+---------------------------------------------------------------------------
+Version 5.9.7 [V5-BETA], 2012-05-10
+- added capability to specify substrings for field extraction mode
+- bugfix: ommysql did not properly init/exit the mysql runtime library
+ this could lead to segfaults. Triggering condition: multiple action
+ instances using ommysql. Thanks to Tomas Heinrich for reporting this
+ problem and providing an initial patch (which my solution is based on,
+ I need to add more code to clean the mess up).
+- bugfix: rsyslog did not terminate when delayable inputs were blocked
+ due to unavailable sources. Fixes:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ Thanks to Marcin M for bringing up this problem and Andre Lorbach
+ for helping to reproduce and fix it.
+- bugfix/tcpflood: sending small test files did not work correctly
+---------------------------------------------------------------------------
+Version 5.9.6 [V5-BETA], 2012-04-12
+- added configuration directives to customize queue light delay marks
+- permit size modifiers (k,m,g,...) in integer config parameters
+ Thanks to Jo Rhett for the suggestion.
+- bugfix: hostname was not requeried on HUP
+ Thanks to Per Jessen for reporting this bug and Marius Tomaschewski for
+ his help in testing the fix.
+- bugfix: imklog invalidly computed facility and severity
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=313
+- bugfix: imptcp input name could not be set
+ config directive was accepted, but had no effect
+- added configuration directive to disable octet-counted framing
+ for imtcp, directive is $InputTCPServerSupportOctetCountedFraming
+ for imptcp, directive is $InputPTCPServerSupportOctetCountedFraming
+- added capability to use a local interface IP address as fromhost-ip for
+ locally originating messages. New directive $LocalHostIPIF
+- added configuration directives to customize queue light delay marks
+ $MainMsgQueueLightDelayMark, $ActionQueueLightDelayMark; both
+ specify number of messages starting at which a delay happens.
+---------------------------------------------------------------------------
+Version 5.9.5 [V5-DEVEL], 2012-01-27
+- improved impstats subsystem, added many new counters
+- enhanced module loader to not rely on PATH_MAX
+- refactored imklog linux driver, now combined with BSD driver
+ The Linux driver no longer supports outdated kernel symbol resolution,
+ which was disabled by default for very long. Also overall cleanup,
+ resulting in much smaller code. Linux and BSD are now covered by a
+ single small driver.
+- $IMUXSockRateLimitInterval DEFAULT CHANGED, was 5, now 0
+ The new default turns off rate limiting. This was chosen as people
+ experienced problems with rate-limiting activated by default. Now it
+ needs an explicit opt-in by setting this parameter.
+ Thanks to Chris Gaffney for suggesting to make it opt-in; thanks to
+ many unnamed others who already had complained at the time Chris made
+ the suggestion ;-)
+---------------------------------------------------------------------------
+Version 5.9.4 [V5-DEVEL], 2011-11-29
+- imuxsock: added capability to "annotate" messages with "trusted
+ information", which contains some properties obtained from the system
+ and as such sure to not be faked. This is inspired by the similar idea
+ introduced in systemd.
+- removed dependency on gcrypt for recently-enough GnuTLS
+ see: http://bugzilla.adiscon.com/show_bug.cgi?id=289
+- bugfix: imuxsock did no longer ignore message-provided timestamp, if
+ so configured (the *default*). Lead to no longer sub-second timestamps.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=281
+- bugfix: omfile returns fatal error code for things that go really wrong
+ previously, RS_RET_RESUME was returned, which lead to a loop inside the
+ rule engine as omfile could not really recover.
+- bugfix: rsyslogd -v always said 64 atomics were not present
+ thanks to mono_matsuko for the patch
+---------------------------------------------------------------------------
+Version 5.9.3 [V5-DEVEL], 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: mark message processing did not work correctly
+- added capability to emit config error location info for warnings
+ otherwise, omusrmsg's warning about new config format was not
+ accompanied by problem location.
+- bugfix: potential misaddressing in property replacer
+- bugfix: MSGID corruption in RFC5424 parser under some circumstances
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=275
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+---------------------------------------------------------------------------
+Version 5.9.2 [V5-DEVEL] (rgerhards), 2011-07-11
+- systemd support: set stdout/stderr to null - thx to Lennart for the patch
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- added support for the ":omfile:" syntax for actions
+---------------------------------------------------------------------------
+Version 5.9.1 [V5-DEVEL] (rgerhards), 2011-06-30
+- added support for obtaining timestamp for kernel message from message
+ If the kernel time-stamps messages, time is now take from that
+ timestamp instead of the system time when the message was read. This
+ provides much better accuracy. Thanks to Lennart Poettering for
+ suggesting this feature and his help during implementation.
+- added support for obtaining timestamp from system for imuxsock
+ This permits to read the time a message was submitted to the system
+ log socket. Most importantly, this is provided in microsecond resolution.
+ So we are able to obtain high precision timestampis even for messages
+ that were - as is usual - not formatted with them. This also simplifies
+ things in regard to local time calculation in chroot environments.
+ Many thanks to Lennart Poettering for suggesting this feature,
+ providing some guidance on implementing it and coordinating getting the
+ necessary support into the Linux kernel.
+- bugfix: timestamp was incorrectly calculated for timezones with minute
+ offset
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=271
+- bugfix: problems in failover action handling
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=270
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=254
+- bugfix: mutex was invalidly left unlocked during action processing
+ At least one case where this can occur is during thread shutdown, which
+ may be initiated by lower activity. In most cases, this is quite
+ unlikely to happen. However, if it does, data structures may be
+ corrupted which could lead to fatal failure and segfault. I detected
+ this via a testbench test, not a user report. But I assume that some
+ users may have had unreproducable aborts that were cause by this bug.
+- bugfix: memory leak in imtcp & subsystems under some circumstances
+ This leak is tied to error conditions which lead to incorrect cleanup
+ of some data structures. [backport from v6]
+- bugfix/improvement:$WorkDirectory now gracefully handles trailing slashes
+---------------------------------------------------------------------------
+Version 5.9.0 [V5-DEVEL] (rgerhards), 2011-06-08
+- imfile: added $InputFileMaxLinesAtOnce directive
+- enhanced imfile to support input batching
+- added capability for imtcp and imptcp to activate keep-alive packets
+ at the socket layer. This has not been added to imttcp, as the latter is
+ only an experimental module, and one which did not prove to be useful.
+ reference: http://kb.monitorware.com/post20791.html
+- added support to control KEEPALIVE settings in imptcp
+ this has not yet been added to imtcp, but could be done on request.
+- $ActionName is now also used for naming of queues in impstats
+ as well as in the debug output
+- bugfix: do not open files with full privileges, if privs will be dropped
+ This make the privilege drop code more bulletproof, but breaks Ubuntu's
+ work-around for log files created by external programs with the wrong
+ user and/or group. Note that it was long said that this "functionality"
+ would break once we go for serious privilege drop code, so hopefully
+ nobody still depends on it (and, if so, they lost...).
+- bugfix: pipes not opened in full priv mode when privs are to be dropped
+- this begins a new devel branch for v5
+- better handling of queue i/o errors in disk queues. This is kind of a
+ bugfix, but a very intrusive one, this it goes into the devel version
+ first. Right now, "file not found" is handled and leads to the new
+ emergency mode, in which disk action is stopped and the queue run
+ in direct mode. An error message is emited if this happens.
+- added support for user-level PRI provided via systemd
+- added new config directive $InputTCPFlowControl to select if tcp
+ received messages shall be flagged as light delayable or not.
+- enhanced omhdfs to support batching mode. This permits to increase
+ performance, as we now call the HDFS API with much larger message
+ sizes and far more infrequently
+- bugfix: failover did not work correctly if repeated msg reduction was on
+ affected directive was: $ActionExecOnlyWhenPreviousIsSuspended on
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=236
+---------------------------------------------------------------------------
+Version 5.8.13 [V5-stable] 2012-08-22
+- bugfix: DA queue could cause abort
+- bugfix: "last message repeated n times" message was missing hostname
+ Thanks to Zdenek Salvet for finding this bug and to Bodik for reporting
+- bugfix "$PreserveFQDN on" was not honored in some modules
+ Thanks to bodik for reporting this bug.
+- bugfix: randomized IP option header in omudpspoof caused problems
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=327
+ Thanks to Rick Brown for helping to test out the patch.
+- bugfix: potential abort if output plugin logged message during shutdown
+ note that none of the rsyslog-provided plugins does this
+ Thanks to bodik and Rohit Prasad for alerting us on this bug and
+ analyzing it.
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=347
+- bugfix: multiple main queues with same queue file name was not detected
+ This lead to queue file corruption. While the root cause is a config
+ error, it is a bug that this important and hard to find config error
+ was not detected by rsyslog.
+---------------------------------------------------------------------------
+Version 5.8.12 [V5-stable] 2012-06-06
+- add small delay (50ms) after sending shutdown message
+ There seem to be cases where the shutdown message is otherwise not
+ processed, not even on an idle system. Thanks to Marcin for
+ bringing this problem up.
+- support for resolving huge groups
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=310
+ Thanks to Alec Warner for the patch
+- bugfix: delayable source could block action queue, even if there was
+ a disk queue associated with it. The root cause of this problem was
+ that it makes no sense to delay messages once they arrive in the
+ action queue - the "input" that is being held in that case is the main
+ queue worker, what makes no sense.
+ Thanks to Marcin for alerting us on this problem and providing
+ instructions to reproduce it.
+- bugfix: disk queue was not persisted on shutdown, regression of fix to
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ The new code also handles the case of shutdown of blocking light and
+ full delayable sources somewhat smarter and permits, assuming sufficient
+ timeouts, to persist message up to the max queue capacity. Also some nits
+ in debug instrumentation have been fixed.
+- bugfix/omudpspoof: problems, including abort, happened when run on
+ multiple threads. Root cause is that libnet is not thread-safe.
+ omudpspoof now guards libnet calls with their own mutex.
+- bugfix: if debug message could end up in log file when forking
+ if rsyslog was set to auto-background (thus fork, the default) and debug
+ mode to stdout was enabled, debug messages ended up in the first log file
+ opened. Currently, stdout logging is completely disabled in forking mode
+ (but writing to the debug log file is still possible). This is a change
+ in behavior, which is under review. If it causes problems to you,
+ please let us know.
+ Thanks to Tomas Heinrich for the patch.
+- bugfix/tcpflood: sending small test files did not work correctly
+- bugfix: potential hang due to mutex deadlock
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=316
+ Thanks to Andreas Piesk for reporting&analyzing this bug as well as
+ providing patches and other help in resolving it.
+- bugfix: property PROCID empty instead of proper nilvalue if not present
+ If it is not present, it must have the nilvalue "-" as of RFC5424
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=332
+ Thanks to John N for reporting this issue.
+---------------------------------------------------------------------------
+Version 5.8.11 [V5-stable] 2012-05-03
+- bugfix: ommysql did not properly init/exit the mysql runtime library
+ this could lead to segfaults. Triggering condition: multiple action
+ instances using ommysql. Thanks to Tomas Heinrich for reporting this
+ problem and providing an initial patch (which my solution is based on,
+ I need to add more code to clean the mess up).
+- bugfix: rsyslog did not terminate when delayable inputs were blocked
+ due to unavailable sources. Fixes:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=299
+ Thanks to Marcin M for bringing up this problem and Andre Lorbach
+ for helping to reproduce and fix it.
+- bugfix: active input in "light delay state" could block rsyslog
+ termination, at least for prolonged period of time
+- bugfix: imptcp input name could not be set
+ config directive was accepted, but had no effect
+- bugfix: assigned ruleset was lost when using disk queues
+ This looked quite hard to diagnose for disk-assisted queues, as the
+ pure memory part worked well, but ruleset info was lost for messages
+ stored inside the disk queue.
+- bugfix: hostname was not requeried on HUP
+ Thanks to Per Jessen for reporting this bug and Marius Tomaschewski for
+ his help in testing the fix.
+- bugfix: inside queue.c, some thread cancel states were not correctly
+ reset. While this is a bug, we assume it did have no practical effect
+ because the reset as it was done was set to the state the code actually
+ had at this point. But better fix this...
+---------------------------------------------------------------------------
+Version 5.8.10 [V5-stable] 2012-04-05
+- bugfix: segfault on startup if $actionqueuefilename was missing for disk
+ queue config
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: segfault if disk-queue was started up with old queue file
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: memory leak in array passing output module mode
+---------------------------------------------------------------------------
+Version 5.8.9 [V5-stable] 2012-03-15
+- added tool to recover disk queue if .qi file is missing (recover_qi.pl)
+ Thanks to Kaiwang Chen for contributing this tool
+- bugfix: stopped DA queue was never processed after a restart due to a
+ regression from statistics module
+- added better doc for statsobj interface
+ Thanks to Kaiwang Chen for his suggestions and analysis in regard to the
+ stats subsystem.
+---------------------------------------------------------------------------
+Version 5.8.8 [V5-stable] 2012-03-05
+- added capability to use a local interface IP address as fromhost-ip for
+ imuxsock imklog
+ new config directives: $IMUXSockLocalIPIF, $klogLocalIPIF
+- added configuration directives to customize queue light delay marks
+ $MainMsgQueueLightDelayMark, $ActionQueueLightDelayMark; both
+ specify number of messages starting at which a delay happens.
+- bugfix: omprog made rsyslog abort on startup if not binary to
+ execute was configured
+- bugfix: imklog invalidly computed facility and severity
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=313
+---------------------------------------------------------------------------
+Version 5.8.7 [V5-stable] 2012-01-17
+- bugfix: instabilities when using RFC5424 header fields
+ Thanks to Kaiwang Chen for the patch
+- bugfix: imuxsock did truncate part of received message if it did not
+ contain a proper date. The truncation occurred because we removed that
+ part of the messages that was expected to be the date.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=295
+- bugfix: potential abort after reading invalid X.509 certificate
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=290
+ Thanks to Tomas Heinrich for the patch
+- bugfix: stats counter were not properly initialized on creation
+- FQDN hostname for multihomed host was not always set to the correct name
+ if multiple aliases existed. Thanks to Tomas Heinreich for the patch.
+- re-licensed larger parts of the codebase under the Apache license 2.0
+---------------------------------------------------------------------------
+Version 5.8.6 [V5-stable] 2011-10-21
+- bugfix: missing whitespace after property-based filter was not detected
+- bugfix: $OMFileFlushInterval period was doubled - now using correct value
+- bugfix: ActionQueue could malfunction due to index error
+ Thanks to Vlad Grigorescu for the patch
+- bugfix: $ActionExecOnlyOnce interval did not work properly
+ Thanks to Tomas Heinrich for the patch
+- bugfix: race condition when extracting program name, APPNAME, structured
+ data and PROCID (RFC5424 fields) could lead to invalid characters e.g.
+ in dynamic file names or during forwarding (general malfunction of these
+ fields in templates, mostly under heavy load)
+- bugfix: imuxsock did no longer ignore message-provided timestamp, if
+ so configured (the *default*). Lead to no longer sub-second timestamps.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=281
+- bugfix: omfile returns fatal error code for things that go really wrong
+ previously, RS_RET_RESUME was returned, which lead to a loop inside the
+ rule engine as omfile could not really recover.
+- bugfix: imfile did invalid system call under some circumstances
+ when a file that was to be monitored did not exist BUT the state file
+ actually existed. Mostly a cosmetic issue. Root cause was incomplete
+ error checking in stream.c; so patch may affect other code areas.
+- bugfix: rsyslogd -v always said 64 atomics were not present
+ thanks to mono_matsuko for the patch
+---------------------------------------------------------------------------
+Version 5.8.5 [V5-stable] (rgerhards/al), 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: mark message processing did not work correctly
+- bugfix: potential hang condition during tag emulation
+- bugfix: too-early string termination during tag emulation
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+- bugfix: fixed incorrect state handling for Discard Action (transactions)
+ Note: This caused all messages in a batch to be set to COMMITTED,
+ even if they were discarded.
+---------------------------------------------------------------------------
+Version 5.8.4 [V5-stable] (al), 2011-08-10
+- bugfix: potential misaddressing in property replacer
+- bugfix: memcpy overflow can occur in allowed sender checking
+ if a name is resolved to IPv4-mapped-on-IPv6 address
+ Found by Ismail Dönmez at suse
+- bugfix: potential misaddressing in property replacer
+- bugfix: MSGID corruption in RFC5424 parser under some circumstances
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=275
+---------------------------------------------------------------------------
+Version 5.8.3 [V5-stable] (rgerhards), 2011-07-11
+- systemd support: set stdout/stderr to null - thx to Lennart for the patch
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- added support for the ":omfile:" syntax for actions
+ Note: previous outchannel syntax will generate a warning message. This
+ may be surprising to some users, but it is quite urgent to alert them
+ of the new syntax as v6 can no longer support the previous one.
+---------------------------------------------------------------------------
+Version 5.8.2 [V5-stable] (rgerhards), 2011-06-21
+- bugfix: problems in failover action handling
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=270
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=254
+- bugfix: mutex was invalidly left unlocked during action processing
+ At least one case where this can occur is during thread shutdown, which
+ may be initiated by lower activity. In most cases, this is quite
+ unlikely to happen. However, if it does, data structures may be
+ corrupted which could lead to fatal failure and segfault. I detected
+ this via a testbench test, not a user report. But I assume that some
+ users may have had unreproducable aborts that were cause by this bug.
+- bugfix: memory leak in imtcp & subsystems under some circumstances
+ This leak is tied to error conditions which lead to incorrect cleanup
+ of some data structures. [backport from v6]
+- bugfix/improvement:$WorkDirectory now gracefully handles trailing slashes
+---------------------------------------------------------------------------
+Version 5.8.1 [V5-stable] (rgerhards), 2011-05-19
+- bugfix: invalid processing in QUEUE_FULL condition
+ If the the multi-submit interface was used and a QUEUE_FULL condition
+ occurred, the failed message was properly destructed. However, the
+ rest of the input batch, if it existed, was not processed. So this
+ lead to potential loss of messages and a memory leak. The potential
+ loss of messages was IMHO minor, because they would have been dropped
+ in most cases due to the queue remaining full, but very few lucky ones
+ from the batch may have made it. Anyhow, this has now been changed so
+ that the rest of the batch is properly tried to be enqueued and, if
+ not possible, destructed.
+- new module mmsnmptrapd, a sample message modification module
+ This can be useful to reformat snmptrapd messages and also serves as
+ a sample for how to write message modification modules using the
+ output module interface. Note that we introduced this new
+ functionality directly into the stable release, as it does not
+ modify the core and as such cannot have any side-effects if it is
+ not used (and thus the risk is solely on users requiring that
+ functionality).
+- bugfix: rate-limiting inside imuxsock did not work 100% correct
+ reason was that a global config variable was invalidly accessed where a
+ listener variable should have been used.
+ Also performance-improved the case when rate limiting is turned off (this
+ is a very unintrusive change, thus done directly to the stable version).
+- bugfix: $myhostname not available in RainerScript (and no error message)
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=233
+- bugfix: memory and file descriptor leak in stream processing
+ Leaks could occur under some circumstances if the file stream handler
+ errored out during the open call. Among others, this could cause very
+ big memory leaks if there were a problem with unreadable disk queue
+ files. In regard to the memory leak, this
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=256
+- bugfix: doc for impstats had wrong config statements
+ also, config statements were named a bit inconsistent, resolved that
+ problem by introducing an alias and only documenting the consistent
+ statements
+ Thanks to Marcin for bringing up this problem.
+- bugfix: IPv6-address could not be specified in omrelp
+ this was due to improper parsing of ":"
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=250
+- bugfix: TCP connection invalidly aborted when messages needed to be
+ discarded (due to QUEUE_FULL or similar problem)
+- bugfix: $LocalHostName was not honored under all circumstances
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=258
+- bugfix(minor): improper template function call in syslogd.c
+---------------------------------------------------------------------------
+Version 5.8.0 [V5-stable] (rgerhards), 2011-04-12
+
+This is the new v5-stable branch, importing all feature from the 5.7.x
+versions. To see what has changed in regard to the previous v5-stable,
+check the Changelog for 5.7.x below.
+
+- bugfix: race condition in deferred name resolution
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=238
+ Special thanks to Marcin for his persistence in helping to solve this
+ bug.
+- bugfix: DA queue was never shutdown once it was started
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=241
+---------------------------------------------------------------------------
+Version 5.7.10 [V5-BETA] (rgerhards), 2011-03-29
+- bugfix: ompgsql did not work properly with ANSI SQL strings
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=229
+- bugfix: rsyslog did not build with --disable-regexp configure option
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=243
+- bugfix: PRI was invalid on Solaris for message from local log socket
+- enhance: added $BOM system property to ease writing byte order masks
+- bugfix: RFC5424 parser confused by empty structured data
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=237
+- bugfix: error return from strgen caused abort, now causes action to be
+ ignored (just like a failed filter)
+- new sample plugin for a strgen to generate sql statement consumable
+ by a database plugin
+- bugfix: strgen could not be used together with database outputs
+ because the sql/stdsql option could not be specified. This has been
+ solved by permitting the strgen to include the opton inside its name.
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=195
+---------------------------------------------------------------------------
+Version 5.7.9 [V5-BETA] (rgerhards), 2011-03-16
+- improved testbench
+ among others, life tests for ommysql (against a test database) have
+ been added, valgrind-based testing enhanced, ...
+- enhance: fallback *at runtime* to epoll_create if epoll_create1 is not
+ available. Thanks to Michael Biebl for analysis and patch!
+- bugfix: failover did not work correctly if repeated msg reduction was on
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=236
+ affected directive was: $ActionExecOnlyWhenPreviousIsSuspended on
+- bugfix: minor memory leak in omlibdbi (< 1k per instance and run)
+- bugfix: (regression) omhdfs did no longer compile
+- bugfix: omlibdbi did not use password from rsyslog.conf
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=203
+---------------------------------------------------------------------------
+Version 5.7.8 [V5-BETA] (rgerhards), 2011-03-09
+- systemd support somewhat improved (can now take over existing log sockt)
+- bugfix: discard action did not work under some circumstances
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=217
+- bugfix: file descriptor leak in gnutls netstream driver
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=222
+---------------------------------------------------------------------------
+Version 5.7.7 [V5-BETA] (rgerhards), 2011-03-02
+- bugfix: potential abort condition when $RepeatedMsgReduction set to on
+ as well as potentially in a number of other places where MsgDup() was
+ used. This only happened when the imudp input module was used and it
+ depended on name resolution not yet had taken place. In other words,
+ this was a strange problem that could lead to hard to diagnose
+ instability. So if you experience instability, chances are good that
+ this fix will help.
+---------------------------------------------------------------------------
+Version 5.7.6 [V5-BETA] (rgerhards), 2011-02-25
+- bugfix: fixed a memory leak and potential abort condition
+ this could happen if multiple rulesets were used and some output batches
+ contained messages belonging to more than one ruleset.
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=226
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=218
+- bugfix: memory leak when $RepeatedMsgReduction on was used
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=225
+---------------------------------------------------------------------------
+Version 5.7.5 [V5-BETA] (rgerhards), 2011-02-23
+- enhance: imfile did not yet support multiple rulesets, now added
+ we do this directly in the beta because a) it does not affect existing
+ functionality and b) one may argue that this missing functionality is
+ close to a bug.
+- improved testbench, added tests for imuxsock
+- bugfix: imuxsock did no longer sanitize received messages
+ This was a regression from the imuxsock partial rewrite. Happened
+ because the message is no longer run through the standard parsers.
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=224
+- bugfix: minor race condition in action.c - considered cosmetic
+ This is considered cosmetic as multiple threads tried to write exactly
+ the same value into the same memory location without sync. The method
+ has been changed so this can no longer happen.
+---------------------------------------------------------------------------
+Version 5.7.4 [V5-BETA] (rgerhards), 2011-02-17
+- added pmsnare parser module (written by David Lang)
+- enhanced imfile to support non-cancel input termination
+- improved systemd socket activation thanks to Marius Tomaschewski
+- improved error reporting for $WorkDirectory
+ non-existence and other detectable problems are now reported,
+ and the work directory is NOT set in this case
+- bugfix: pmsnare caused abort under some conditions
+- bugfix: abort if imfile reads file line of more than 64KiB
+ Thanks to Peter Eisentraut for reporting and analyzing this problem.
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=221
+- bugfix: queue engine did not properly slow down inputs in FULL_DELAY mode
+ when in disk-assisted mode. This especially affected imfile, which
+ created unnecessarily queue files if a large set of input file data was
+ to process.
+- bugfix: very long running actions could prevent shutdown under some
+ circumstances. This has now been solved, at least for common
+ situations.
+- bugfix: fixed compile problem due to empty structs
+ this occurred only on some platforms/compilers. thanks to Dražen KaÄar
+ for the fix
+---------------------------------------------------------------------------
+Version 5.7.3 [V5-BETA] (rgerhards), 2011-02-07
+- added support for processing multi-line messages in imfile
+- added $IMUDPSchedulingPolicy and $IMUDPSchedulingPriority config settings
+- added $LocalHostName config directive
+- bugfix: fixed build problems on some platforms
+ namely those that have 32bit atomic operations but not 64 bit ones
+- bugfix: local hostname was pulled too-early, so that some config
+ directives (namely FQDN settings) did not have any effect
+- bugfix: imfile did duplicate messages under some circumstances
+- added $OMMySQLConfigFile config directive
+- added $OMMySQLConfigSection config directive
+---------------------------------------------------------------------------
+Version 5.7.2 [V5-DEVEL] (rgerhards), 2010-11-26
+- bugfix(important): problem in TLS handling could cause rsyslog to loop
+ in a tight loop, effectively disabling functionality and bearing the
+ risk of unresponsiveness of the whole system.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=194
+- bugfix: imfile state file was not written when relative file name
+ for it was specified
+- bugfix: compile failed on systems without epoll_create1()
+ Thanks to David Hill for providing a fix.
+- bugfix: atomic increment for msg object may not work correct on all
+ platforms. Thanks to Chris Metcalf for the patch
+- bugfix: replacements for atomic operations for non-int sized types had
+ problems. At least one instance of that problem could potentially lead
+ to abort (inside omfile).
+---------------------------------------------------------------------------
+Version 5.7.1 [V5-DEVEL] (rgerhards), 2010-10-05
+- support for Hadoop's HDFS added (via omhdfs)
+- imuxsock now optionally use SCM_CREDENTIALS to pull the pid from the log
+ socket itself
+ (thanks to Lennart Poettering for the suggesting this feature)
+- imuxsock now optionally uses per-process input rate limiting, guarding the
+ user against processes spamming the system log
+ (thanks to Lennart Poettering for suggesting this feature)
+- added new config statements
+ * $InputUnixListenSocketUsePIDFromSystem
+ * $SystemLogUsePIDFromSystem
+ * $SystemLogRateLimitInterval
+ * $SystemLogRateLimitBurst
+ * $SystemLogRateLimitSeverity
+ * $IMUxSockRateLimitInterval
+ * $IMUxSockRateLimitBurst
+ * $IMUxSockRateLimitSeverity
+- imuxsock now supports up to 50 different sockets for input
+- some code cleanup in imuxsock (consider this a release a major
+ modification, especially if problems show up)
+- bugfix: /dev/log was unlinked even when passed in from systemd
+ in which case it should be preserved as systemd owns it
+---------------------------------------------------------------------------
+Version 5.7.0 [V5-DEVEL] (rgerhards), 2010-09-16
+- added module impstat to emit periodic statistics on rsyslog counters
+- support for systemd officially added
+ * acquire /dev/log socket optionally from systemd
+ thanks to Lennart Poettering for this patch
+ * sd-systemd API added as part of rsyslog runtime library
+---------------------------------------------------------------------------
+Version 5.6.5 [V5-STABLE] (rgerhards), 2011-03-22
+- bugfix: failover did not work correctly if repeated msg reduction was on
+ affected directive was: $ActionExecOnlyWhenPreviousIsSuspended on
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=236
+- bugfix: omlibdbi did not use password from rsyslog.con
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=203
+- bugfix(kind of): tell users that config graph can currently not be
+ generated
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=232
+- bugfix: discard action did not work under some circumstances
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=217
+ (backport from 5.7.8)
+---------------------------------------------------------------------------
+Version 5.6.4 [V5-STABLE] (rgerhards), 2011-03-03
+- bugfix: potential abort condition when $RepeatedMsgReduction set to on
+ as well as potentially in a number of other places where MsgDup() was
+ used. This only happened when the imudp input module was used and it
+ depended on name resolution not yet had taken place. In other words,
+ this was a strange problem that could lead to hard to diagnose
+ instability. So if you experience instability, chances are good that
+ this fix will help.
+- bugfix: fixed a memory leak and potential abort condition
+ this could happen if multiple rulesets were used and some output batches
+ contained messages belonging to more than one ruleset.
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=226
+ fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=218
+- bugfix: memory leak when $RepeatedMsgReduction on was used
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=225
+---------------------------------------------------------------------------
+Version 5.6.3 [V5-STABLE] (rgerhards), 2011-01-26
+- bugfix: action processor released memory too early, resulting in
+ potential issue in retry cases (but very unlikely due to another
+ bug, which I also fixed -- only after the fix this problem here
+ became actually visible).
+- bugfix: batch processing flagged invalid message as "bad" under some
+ circumstances
+- bugfix: uninitialized variable could cause issues under extreme conditions
+ plus some minor nits. This was found after a clang static code analyzer
+ analysis (great tool, and special thanks to Marcin for telling me about
+ it!)
+- bugfix: batches which had actions in error were not properly retried in
+ all cases
+- bugfix: imfile did duplicate messages under some circumstances
+- bugfix: testbench was not activated if no Java was present on system
+ ... what actually was a left-over. Java is no longer required.
+---------------------------------------------------------------------------
+Version 5.6.2 [V5-STABLE] (rgerhards), 2010-11-30
+- bugfix: compile failed on systems without epoll_create1()
+ Thanks to David Hill for providing a fix.
+- bugfix: atomic increment for msg object may not work correct on all
+ platforms. Thanks to Chris Metcalf for the patch
+- bugfix: replacements for atomic operations for non-int sized types had
+ problems. At least one instance of that problem could potentially lead
+ to abort (inside omfile).
+- added the $InputFilePersistStateInterval config directive to imfile
+- changed imfile so that the state file is never deleted (makes imfile
+ more robust in regard to fatal failures)
+- bugfix: a slightly more informative error message when a TCP
+ connections is aborted
+---------------------------------------------------------------------------
+Version 5.6.1 [V5-STABLE] (rgerhards), 2010-11-24
+- bugfix(important): problem in TLS handling could cause rsyslog to loop
+ in a tight loop, effectively disabling functionality and bearing the
+ risk of unresponsiveness of the whole system.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=194
+- permitted imptcp to work on systems which support epoll(), but not
+ epoll_create().
+ Bug: http://bugzilla.adiscon.com/show_bug.cgi?id=204
+ Thanks to Nicholas Brink for reporting this problem.
+- bugfix: testbench failed if imptcp was not enabled
+- bugfix: segfault when an *empty* template was used
+ Bug: http://bugzilla.adiscon.com/show_bug.cgi?id=206
+ Thanks to David Hill for alerting us.
+- bugfix: compile failed with --enable-unlimited-select
+ thanks varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 5.6.0 [V5-STABLE] (rgerhards), 2010-10-19
+
+This release brings all changes and enhancements of the 5.5.x series
+to the v5-stable branch.
+
+- bugfix: a couple of problems that imfile had on some platforms, namely
+ Ubuntu (not their fault, but occurred there)
+- bugfix: imfile utilizes 32 bit to track offset. Most importantly,
+ this problem can not experienced on Fedora 64 bit OS (which has
+ 64 bit long's!)
+---------------------------------------------------------------------------
+Version 5.5.7 [V5-BETA] (rgerhards), 2010-08-09
+- changed omudpspoof default spoof address to simplify typical use case
+ thanks to David Lang for suggesting this
+- doc bugfix: pmlastmsg doc samples had errors
+- bugfix[minor]: pmrfc3164sd had invalid name (resided in rsyslog name
+ space, what should not be the case for a contributed module)
+- added omuxsock, which permits to write message to local Unix sockets
+ this is the counterpart to imuxsock, enabling fast local forwarding
+---------------------------------------------------------------------------
+Version 5.5.6 [DEVEL] (rgerhards), 2010-07-21
+- added parser modules
+ * pmlastmsg, which supports the notoriously malformed "last message
+ repeated n times" messages from some syslogd's (namely sysklogd)
+ * pmrfc3164sd (contributed), supports RFC5424 structured data in
+ RFC3164 messages [untested]
+- added new module type "string generator", used to speed up output
+ processing. Expected speedup for (typical) rsyslog processing is
+ roughly 5 to 6 percent compared to using string-based templates.
+ They may also be used to do more complex formatting with custom
+ C code, what provided greater flexibility and probably far higher
+ speed, for example if using multiple regular expressions within a
+ template.
+- added 4 string generators for
+ * RSYSLOG_FileFormat
+ * RSYSLOG_TraditionalFileFormat
+ * RSYSLOG_ForwardFormat
+ * RSYSLOG_TraditionalForwardFormat
+- bugfix: mutexes used to simulate atomic instructions were not destructed
+- bugfix: regression caused more locking action in msg.c than necessary
+- bugfix: "$ActionExecOnlyWhenPreviousIsSuspended on" was broken
+- bugfix: segfault on HUP when "HUPIsRestart" was set to "on"
+ thanks varmojfekoj for the patch
+- bugfix: default for $OMFileFlushOnTXEnd was wrong ("off").
+ This, in default mode, caused buffered writing to be used, what
+ means that it looked like no output were written or partial
+ lines. Thanks to Michael Biebl for pointing out this bug.
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
+---------------------------------------------------------------------------
+Version 5.5.5 [DEVEL] (rgerhards), 2010-05-20
+- added new cancel-reduced action thread termination method
+ We now manage to cancel threads that block inside a retry loop to
+ terminate without the need to cancel the thread. Avoiding cancellation
+ helps keep the system complexity minimal and thus provides for better
+ stability. This also solves some issues with improper shutdown when
+ inside an action retry loop.
+---------------------------------------------------------------------------
+Version 5.5.4 [DEVEL] (rgerhards), 2010-05-03
+- This version offers full support for Solaris on Intel and Sparc
+- bugfix: problems with atomic operations emulation
+ replaced atomic operation emulation with new code. The previous code
+ seemed to have some issue and also limited concurrency severely. The
+ whole atomic operation emulation has been rewritten.
+- bugfix: netstream ptcp support class was not correctly build on systems
+ without epoll() support
+- bugfix: segfault on Solaris/Sparc
+---------------------------------------------------------------------------
+Version 5.5.3 [DEVEL] (rgerhards), 2010-04-09
+- added basic but functional support for Solaris
+- imported many bugfixes from 3.6.2/4.6.1 (see ChangeLog below!)
+- added new property replacer option "date-rfc3164-buggyday" primarily
+ to ease migration from syslog-ng. See property replacer doc for
+ details.
+- added capability to turn off standard LF delimiter in TCP server
+ via new directive "$InputTCPServerDisableLFDelimiter on"
+- bugfix: failed to compile on systems without epoll support
+- bugfix: comment char ('#') in literal terminated script parsing
+ and thus could not be used.
+ but tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=119
+ [merged in from v3.22.2]
+- imported patches from 4.6.0:
+ * improved testbench to contain samples for totally malformed messages
+ which miss parts of the message content
+ * bugfix: some malformed messages could lead to a missing LF inside files
+ or some other missing parts of the template content.
+ * bugfix: if a message ended immediately with a hostname, the hostname
+ was mistakenly interpreted as TAG, and localhost be used as hostname
+---------------------------------------------------------------------------
+Version 5.5.2 [DEVEL] (rgerhards), 2010-02-05
+- applied patches that make rsyslog compile under Apple OS X.
+ Thanks to trey for providing these.
+- replaced data type "bool" by "sbool" because this created some
+ portability issues.
+- added $Escape8BitCharactersOnReceive directive
+ Thanks to David Lang for suggesting it.
+- worked around an issue where omfile failed to compile on 32 bit platforms
+ under some circumstances (this smells like a gcc problem, but a simple
+ solution was available). Thanks to Kenneth Marshall for some advice.
+- extended testbench
+---------------------------------------------------------------------------
+Version 5.5.1 [DEVEL] (rgerhards), 2009-11-27
+- introduced the ability for netstream drivers to utilize an epoll interface
+ This offers increased performance and removes the select() FDSET size
+ limit from imtcp. Note that we fall back to select() if there is no
+ epoll netstream drivers. So far, an epoll driver has only been
+ implemented for plain tcp syslog, the rest will follow once the code
+ proves well in practice AND there is demand.
+- re-implemented $EscapeControlCharacterTab config directive
+ Based on Jonathan Bond-Caron's patch for v4. This now also includes some
+ automated tests.
+- bugfix: enabling GSSServer crashes rsyslog startup
+ Thanks to Tomas Kubina for the patch [imgssapi]
+- bugfix (kind of): check if TCP connection is still alive if using TLS
+ Thanks to Jonathan Bond-Caron for the patch.
+---------------------------------------------------------------------------
+Version 5.5.0 [DEVEL] (rgerhards), 2009-11-18
+- moved DNS resolution code out of imudp and into the backend processing
+ Most importantly, DNS resolution now never happens if the resolved name
+ is not required. Note that this applies to imudp - for the other inputs,
+ DNS resolution almost comes for free, so we do not do it there. However,
+ the new method has been implemented in a generic way and as such may
+ also be used by other modules in the future.
+- added option to use unlimited-size select() calls
+ Thanks to varmojfekoj for the patch
+ This is not done in imudp, as it natively supports epoll().
+- doc: improved description of what loadable modules can do
+---------------------------------------------------------------------------
+Version 5.4.2 [v5-stable] (rgerhards), 2010-03-??
+- bugfix(kind of): output plugin retry behavior could cause engine to loop
+ The rsyslog engine did not guard itself against output modules that do
+ not properly convey back the tryResume() behavior. This then leads to
+ what looks like an endless loop. I consider this to be a bug of the
+ engine not only because it should be hardened against plugin misbehavior,
+ but also because plugins may not be totally able to avoid this situation
+ (depending on the type of and processing done by the plugin).
+- bugfix: testbench failed when not executed in UTC+1 timezone
+ accidentally, the time zone information was kept inside some
+ to-be-checked-for responses
+- temporary bugfix replaced by permanent one for
+ message-induced off-by-one error (potential segfault) (see 4.6.2)
+ The analysis has been completed and a better fix been crafted and
+ integrated.
+- bugfix(minor): status variable was uninitialized
+ However, this would have caused harm only if NO parser modules at
+ all were loaded, which would lead to a defunctional configuration
+ at all. And, even more important, this is impossible as two parser
+ modules are built-in and thus can not be "not loaded", so we always
+ have a minimum of two.
+---------------------------------------------------------------------------
+Version 5.4.1 [v5-stable] (rgerhards), 2010-03-??
+- added new property replacer option "date-rfc3164-buggyday" primarily
+ to ease migration from syslog-ng. See property replacer doc for
+ details. [backport from 5.5.3 because urgently needed by some]
+- imported all bugfixes vom 4.6.2 (see below)
+---------------------------------------------------------------------------
+Version 5.4.0 [v5-stable] (rgerhards), 2010-03-08
+***************************************************************************
+* This is a new stable v5 version. It contains all fixes and enhancements *
+* made during the 5.3.x phase as well as those listed below. *
+* Note that the 5.2.x series was quite buggy and as such all users are *
+* strongly advised to upgrade to 5.4.0. *
+***************************************************************************
+- bugfix: omruleset failed to work in many cases
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=179
+ Thanks to Ryan B. Lynch for reporting this issue.
+- bugfix: comment char ('#') in literal terminated script parsing
+ and thus could not be used.
+ but tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=119
+ [merged in from v3.22.2]
+---------------------------------------------------------------------------
+Version 5.3.7 [BETA] (rgerhards), 2010-01-27
+- bugfix: queues in direct mode could case a segfault, especially if an
+ action failed for action queues. The issue was an invalid increment of
+ a stack-based pointer which lead to destruction of the stack frame and
+ thus a segfault on function return.
+ Thanks to Michael Biebl for alerting us on this problem.
+- bugfix: hostname accidentally set to IP address for some message sources,
+ for example imudp. Thanks to Anton for reporting this bug. [imported v4]
+- bugfix: ompgsql had problems with transaction support, what actually
+ rendered it unusable. Thanks to forum user "horhe" for alerting me
+ on this bug and helping to debug/fix it! [imported from 5.3.6]
+- bugfix: $CreateDirs variable not properly initialized, default thus
+ was random (but most often "on") [imported from v3]
+- bugfix: potential segfaults during queue shutdown
+ (bugs require certain non-standard settings to appear)
+ Thanks to varmojfekoj for the patch [imported from 4.5.8]
+ [backport from 5.5.2]
+- bugfix: wrong memory assignment for a config variable (probably
+ without causing any harm) [backport from 5.2.2]
+- bugfix: rsyslog hangs when writing to a named pipe which nobody was
+ reading. Thanks to Michael Biebl for reporting this bug.
+ Bugzilla entry: http://bugzilla.adiscon.com/show_bug.cgi?id=169
+ [imported from 4.5.8]
+---------------------------------------------------------------------------
+Version 5.3.6 [BETA] (rgerhards), 2010-01-13
+- bugfix: ompgsql did not properly check the server connection in
+ tryResume(), which could lead to rsyslog running in a tight loop
+- bugfix: suspension during beginTransaction() was not properly handled
+ by rsyslog core
+- bugfix: omfile output was only written when buffer was full, not at
+ end of transaction
+- bugfix: commit transaction was not properly conveyed to message layer,
+ potentially resulting in non-message destruction and thus hangs
+- bugfix: enabling GSSServer crashes rsyslog startup
+ Thanks to Tomas Kubina for the patch [imgssapi]
+- bugfix (kind of): check if TCP connection is still alive if using TLS
+ Thanks to Jonathan Bond-Caron for the patch.
+- bugfix: $CreateDirs variable not properly initialized, default thus
+ was random (but most often "on") [imported from v3]
+- bugfix: ompgsql had problems with transaction support, what actually
+ rendered it unusable. Thanks to forum user "horhe" for alerting me
+ on this bug and helping to debug/fix it!
+- bugfix: memory leak when sending messages in zip-compressed format
+ Thanks to Naoya Nakazawa for analyzing this issue and providing a patch.
+- worked around an issue where omfile failed to compile on 32 bit platforms
+ under some circumstances (this smells like a gcc problem, but a simple
+ solution was available). Thanks to Kenneth Marshall for some advice.
+ [backported from 5.5.x branch]
+---------------------------------------------------------------------------
+Version 5.3.5 [BETA] (rgerhards), 2009-11-13
+- some light performance enhancement by replacing time() call with much
+ faster (at least under linux) gettimeofday() calls.
+- some improvement of omfile performance with dynafiles
+ saved costly time() calls by employing a logical clock, which is
+ sufficient for the use case
+- bugfix: omudpspoof miscalculated source and destination ports
+ while this was probably not noticed for source ports, it resulted in
+ almost all destination ports being wrong, except for the default port
+ of 514, which by virtue of its binary representation was calculated
+ correct (and probably thus the bug not earlier detected).
+- bugfixes imported from earlier releases
+ * bugfix: named pipes did no longer work (they always got an open error)
+ this was a regression from the omfile rewrite in 4.5.0
+ * bugfix(testbench): sequence check was not always performed correctly,
+ that could result in tests reporting success when they actually failed
+- improved testbench: added tests for UDP forwarding and omudpspoof
+- doc bugfix: omudpspoof had wrong config command names ("om" missing)
+- bugfix [imported from 4.4.3]: $ActionExecOnlyOnceEveryInterval did
+ not work.
+- [inport v4] improved testbench, contains now tcp and gzip test cases
+- [import v4] added a so-called "On Demand Debug" mode, in which debug
+ output can be generated only after the process has started, but not right
+ from the beginning. This is assumed to be useful for hard-to-find bugs.
+ Also improved the doc on the debug system.
+- bugfix: segfault on startup when -q or -Q option was given
+ [imported from v3-stable]
+---------------------------------------------------------------------------
+Version 5.3.4 [DEVEL] (rgerhards), 2009-11-04
+- added the ability to create custom message parsers
+- added $RulesetParser config directive that permits to bind specific
+ parsers to specific rulesets
+- added omruleset output module, which provides great flexibility in
+ action processing. THIS IS A VERY IMPORTANT ADDITION, see its doc
+ for why.
+- added the capability to have ruleset-specific main message queues
+ This offers considerable additional flexibility AND superior performance
+ (in cases where multiple inputs now can avoid lock contention)
+- bugfix: correct default for escape ('#') character restored
+ This was accidentally changed to '\\', thanks to David Lang for reporting
+- bugfix(testbench): testcase did not properly wait for rsyslogd shutdown
+ thus some unpredictable behavior and a false negative test result
+ could occur.
+---------------------------------------------------------------------------
+Version 5.3.3 [DEVEL] (rgerhards), 2009-10-27
+- simplified and thus speeded up the queue engine, also fixed some
+ potential race conditions (in very unusual shutdown conditions)
+ along the way. The threading model has seriously changes, so there may
+ be some regressions.
+- enhanced test environment (including testbench): support for enhancing
+ probability of memory addressing failure by using non-NULL default
+ value for malloced memory (optional, only if requested by configure
+ option). This helps to track down some otherwise undetected issues
+ within the testbench.
+- bugfix: potential abort if inputname property was not set
+ primarily a problem of imdiag
+- bugfix: message processing states were not set correctly in all cases
+ however, this had no negative effect, as the message processing state
+ was not evaluated when a batch was deleted, and that was the only case
+ where the state could be wrong.
+---------------------------------------------------------------------------
+Version 5.3.2 [DEVEL] (rgerhards), 2009-10-21
+- enhanced omfile to support transactional interface. This will increase
+ performance in many cases.
+- added multi-ruleset support to imudp
+- re-enabled input thread termination handling that does avoid thread
+ cancellation where possible. This provides a more reliable mode of
+ rsyslogd termination (canceling threads my result in not properly
+ freed resources and potential later hangs, even though we perform
+ proper cancel handling in our code). This is part of an effort to
+ reduce thread cancellation as much as possible in rsyslog.
+ NOTE: the code previously written code for this functionality had a
+ subtle race condition. The new code solves that.
+- enhanced immark to support non-cancel input module termination
+- improved imudp so that epoll can be used in more environments,
+ fixed potential compile time problem if EPOLL_CLOEXEC is not available.
+- some cleanup/slight improvement:
+ * changed imuxsock to no longer use deprecated submitAndParseMsg() IF
+ * changed submitAndParseMsg() interface to be a wrapper around the new
+ way of message creation/submission. This enables older plugins to be
+ used together with the new interface. The removal also enables us to
+ drop a lot of duplicate code, reducing complexity and increasing
+ maintainability.
+- bugfix: segfault when starting up with an invalid .qi file for a disk queue
+ Failed for both pure disk as well as DA queues. Now, we emit an error
+ message and disable disk queueing facility.
+- bugfix: potential segfault on messages with empty MSG part. This was a
+ recently introduced regression.
+- bugfix: debug string larger than 1K were improperly displayed. Max size
+ is now 32K, and if a string is even longer it is meaningfully truncated.
+---------------------------------------------------------------------------
+Version 5.3.1 [DEVEL] (rgerhards), 2009-10-05
+- added $AbortOnUncleanConfig directive - permits to prevent startup when
+ there are problems with the configuration file. See it's doc for
+ details.
+- included some important fixes from v4-stable:
+ * bugfix: invalid handling of zero-sized messages
+ * bugfix: zero-sized UDP messages are no longer processed
+ * bugfix: random data could be appended to message
+ * bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+- bugfixes imported from 4.5.4:
+ * bugfix: potential segfault in stream writer on destruction
+ * bugfix: potential race in object loader (obj.c) during use/release
+ * bugfixes: potential problems in out file zip writer
+---------------------------------------------------------------------------
+Version 5.3.0 [DEVEL] (rgerhards), 2009-09-14
+- begun to add simple GUI programs to gain insight into running rsyslogd
+ instances and help setup and troubleshooting (active via the
+ --enable-gui ./configure switch)
+- changed imudp to utilize epoll(), where available. This shall provide
+ slightly better performance (just slightly because we called select()
+ rather infrequently on a busy system)
+---------------------------------------------------------------------------
+Version 5.2.2 [v5-stable] (rgerhards), 2009-11-??
+- bugfix: enabling GSSServer crashes rsyslog startup
+ Thanks to Tomas Kubina for the patch [imgssapi]
+---------------------------------------------------------------------------
+Version 5.2.1 [v5-stable] (rgerhards), 2009-11-02
+- bugfix [imported from 4.4.3]: $ActionExecOnlyOnceEveryInterval did
+ not work.
+- bugfix: segfault on startup when -q or -Q option was given
+ [imported from v3-stable]
+---------------------------------------------------------------------------
+Version 5.2.0 [v5-stable] (rgerhards), 2009-11-02
+This is a re-release of version 5.1.6 as stable after we did not get any bug
+reports during the whole beta phase. Still, this first v5-stable may not be
+as stable as one hopes for, I am not sure if we did not get bug reports
+just because nobody tried it. Anyhow, we need to go forward and so we
+have the initial v5-stable.
+---------------------------------------------------------------------------
+Version 5.1.6 [v5-beta] (rgerhards), 2009-10-15
+- feature imports from v4.5.6
+- bugfix: potential race condition when queue worker threads were
+ terminated
+- bugfix: solved potential (temporary) stall of messages when the queue was
+ almost empty and few new data added (caused testbench to sometimes hang!)
+- fixed some race condition in testbench
+- added more elaborate diagnostics to parts of the testbench
+- bugfixes imported from 4.5.4:
+ * bugfix: potential segfault in stream writer on destruction
+ * bugfix: potential race in object loader (obj.c) during use/release
+ * bugfixes: potential problems in out file zip writer
+- included some important fixes from 4.4.2:
+ * bugfix: invalid handling of zero-sized messages
+ * bugfix: zero-sized UDP messages are no longer processed
+ * bugfix: random data could be appended to message
+ * bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+---------------------------------------------------------------------------
+Version 5.1.5 [v5-beta] (rgerhards), 2009-09-11
+- added new config option $ActionWriteAllMarkMessages
+ this option permits to process mark messages under all circumstances,
+ even if an action was recently called. This can be useful to use mark
+ messages as a kind of heartbeat.
+- added new config option $InputUnixListenSocketCreatePath
+ to permit the auto-creation of paths to additional log sockets. This
+ turns out to be useful if they reside on temporary file systems and
+ rsyslogd starts up before the daemons that create these sockets
+ (rsyslogd always creates the socket itself if it does not exist).
+- added $LogRSyslogStatusMessages configuration directive
+ permitting to turn off rsyslog start/stop/HUP messages. See Debian
+ ticket http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463793
+- bugfix: hostnames with dashes in them were incorrectly treated as
+ malformed, thus causing them to be treated as TAG (this was a regression
+ introduced from the "rfc3164 strict" change in 4.5.0). Testbench has been
+ updated to include a sample message with a hostname containing a dash.
+- bugfix: strings improperly reused, resulting in some message properties
+ be populated with strings from previous messages. This was caused by
+ an improper predicate check.
+- added new config directive $omfileForceChown [import from 4.7.0]
+---------------------------------------------------------------------------
+Version 5.1.4 [DEVEL] (rgerhards), 2009-08-20
+- legacy syslog parser changed so that it now accepts date stamps in
+ wrong case. Some devices seem to create them and I do not see any harm
+ in supporting that.
+- added $InputTCPMaxListeners directive - permits to specify how many
+ TCP servers shall be possible (default is 20).
+- bugfix: memory leak with some input modules. Those inputs that
+ use parseAndSubmitMsg() leak two small memory blocks with every message.
+ Typically, those process only relatively few messages, so the issue
+ does most probably not have any effect in practice.
+- bugfix: if tcp listen port could not be created, no error message was
+ emitted
+- bugfix: discard action did not work (did not discard messages)
+- bugfix: discard action caused segfault
+- bugfix: potential segfault in output file writer (omfile)
+ In async write mode, we use modular arithmetic to index the output
+ buffer array. However, the counter variables accidentally were signed,
+ thus resulting in negative indices after integer overflow. That in turn
+ could lead to segfaults, but was depending on the memory layout of
+ the instance in question (which in turn depended on a number of
+ variables, like compile settings but also configuration). The counters
+ are now unsigned (as they always should have been) and so the dangling
+ mis-indexing does no longer happen. This bug potentially affected all
+ installations, even if only some may actually have seen a segfault.
+---------------------------------------------------------------------------
+Version 5.1.3 [DEVEL] (rgerhards), 2009-07-28
+- architecture change: queue now always has at least one worker thread
+ if not running in direct mode. Previous versions could run without
+ any active workers. This simplifies the code at a very small expense.
+ See v5 compatibility note document for more in-depth discussion.
+- enhance: UDP spoofing supported via new output module omudpspoof
+ See the omudpspoof documentation for details and samples
+- bugfix: message could be truncated after TAG, often when forwarding
+ This was a result of an internal processing error if maximum field
+ sizes had been specified in the property replacer.
+- bugfix: minor static memory leak while reading configuration
+ did NOT leak based on message volume
+- internal: added ability to terminate input modules not via pthread_cancel
+ but an alternate approach via pthread_kill. This is somewhat safer as we
+ do not need to think about the cancel-safeness of all libraries we use.
+ However, not all inputs can easily supported, so this now is a feature
+ that can be requested by the input module (the most important ones
+ request it).
+---------------------------------------------------------------------------
+Version 5.1.2 [DEVEL] (rgerhards), 2009-07-08
+- bugfix: properties inputname, fromhost, fromhost-ip, msg were lost when
+ working with disk queues
+- some performance enhancements
+- bugfix: abort condition when RecvFrom was not set and message reduction
+ was on. Happened e.g. with imuxsock.
+- added $klogConsoleLogLevel directive which permits to set a new
+ console log level while rsyslog is active
+- some internal code cleanup
+---------------------------------------------------------------------------
+Version 5.1.1 [DEVEL] (rgerhards), 2009-07-03
+- bugfix: huge memory leak in queue engine (made rsyslogd unusable in
+ production). Occurred if at least one queue was in direct mode
+ (the default for action queues)
+- imported many performance optimizations from v4-devel (4.5.0)
+- bugfix: subtle (and usually irrelevant) issue in timeout processing
+ timeout could be one second too early if nanoseconds wrapped
+- set a more sensible timeout for shutdown, now 1.5 seconds to complete
+ processing (this also removes those cases where the shutdown message
+ was not written because the termination happened before it)
+---------------------------------------------------------------------------
+Version 5.1.0 [DEVEL] (rgerhards), 2009-05-29
+
+*********************************** NOTE **********************************
+The v5 versions of rsyslog feature a greatly redesigned queue engine. The
+major theme for the v5 release is twofold:
+
+a) greatly improved performance
+b) enable audit-grade processing
+
+Here, audit-grade processing means that rsyslog, if used together with
+audit-grade transports and configured correctly, will never lose messages
+that already have been acknowledged, not even in fatal failure cases like
+sudden loss of power.
+
+Note that large parts of rsyslog's important core components have been
+restructured to support these design goals. As such, early versions of
+the engine will probably be less stable than the v3/v4 engine.
+
+Also note that the initial versions do not cover all and everything. As
+usual, the code will evolve toward the final goal as version numbers
+increase.
+*********************************** NOTE **********************************
+
+- redesigned queue engine so that it supports ultra-reliable operations
+ This resulted in a rewrite of large parts. The new capability can be
+ used to build audit-grade systems on the basis of rsyslog.
+- added $MainMsgQueueDequeueBatchSize and $ActionQueueDequeueBatchSize
+ configuration directives
+- implemented a new transactional output module interface which provides
+ superior performance (for databases potentially far superior performance)
+- increased ompgsql performance by adapting to new transactional
+ output module interface
+---------------------------------------------------------------------------
+Version 4.8.1 [v4-stable], 2011-09-??
+- increased max config file line size to 64k
+ We now also emit an error message if even 64k is not enough (not
+ doing so previously may rightfully be considered as a bug)
+- bugfix: omprog made rsyslog abort on startup if not binary to
+ execute was configured
+- bugfix: $ActionExecOnlyOnce interval did not work properly
+ Thanks to Tomas Heinrich for the patch
+- bugfix: potential abort if ultra-large file io buffers are used and
+ dynafile cache exhausts address space (primarily a problem on 32 bit
+ platforms)
+- bugfix: potential abort after reading invalid X.509 certificate
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=290
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: potential fatal abort in omgssapi
+ Thanks to Tomas Heinrich for the patch.
+- added doc for omprog
+- FQDN hostname for multihomed host was not always set to the correct name
+ if multiple aliases existed. Thanks to Tomas Heinreich for the patch.
+- re-licensed larger parts of the codebase under the Apache license 2.0
+---------------------------------------------------------------------------
+Version 4.8.0 [v4-stable] (rgerhards), 2011-09-07
+***************************************************************************
+* This is a new stable v4 version. It contains all fixes and enhancements *
+* made during the 4.7.x phase as well as those listed below. *
+* Note: major new development to v4 is concluded and will only be done *
+* for custom projects. *
+***************************************************************************
+There are no changes compared to 4.7.5, just a re-release with the new
+version number as new v4-stable. The most important new feature is Solaris
+support.
+---------------------------------------------------------------------------
+Version 4.7.5 [v4-beta], 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: potential misaddressing in property replacer
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+---------------------------------------------------------------------------
+Version 4.7.4 [v4-beta] (rgerhards), 2011-07-11
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- added support for the ":omfile:" syntax in configuring user messages
+- added $LocalHostName config directive
+- bugfix: PRI was invalid on Solaris for message from local log socket
+Version 4.7.3 [v4-devel] (rgerhards), 2010-11-25
+- added omuxsock, which permits to write message to local Unix sockets
+ this is the counterpart to imuxsock, enabling fast local forwarding
+- added imptcp, a simplified, Linux-specific and potentially fast
+ syslog plain tcp input plugin (NOT supporting TLS!)
+- bugfix: a couple of problems that imfile had on some platforms, namely
+ Ubuntu (not their fault, but occurred there)
+- bugfix: imfile utilizes 32 bit to track offset. Most importantly,
+ this problem can not experienced on Fedora 64 bit OS (which has
+ 64 bit long's!)
+- added the $InputFilePersistStateInterval config directive to imfile
+- changed imfile so that the state file is never deleted (makes imfile
+ more robust in regard to fatal failures)
+---------------------------------------------------------------------------
+Version 4.7.2 [v4-devel] (rgerhards), 2010-05-03
+- bugfix: problems with atomic operations emulation
+ replaced atomic operation emulation with new code. The previous code
+ seemed to have some issue and also limited concurrency severely. The
+ whole atomic operation emulation has been rewritten.
+- added new $Sleep directive to hold processing for a couple of seconds
+ during startup
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
+---------------------------------------------------------------------------
+Version 4.7.1 [v4-devel] (rgerhards), 2010-04-22
+- Solaris support much improved -- was not truly usable in 4.7.0
+ Solaris is no longer supported in imklog, but rather there is a new
+ plugin imsolaris, which is used to pull local log sources on a Solaris
+ machine.
+- testbench improvement: Java is no longer needed for testing tool creation
+---------------------------------------------------------------------------
+Version 4.7.0 [v4-devel] (rgerhards), 2010-04-14
+- new: support for Solaris added (but not yet the Solaris door API)
+- added function getenv() to RainerScript
+- added new config option $InputUnixListenSocketCreatePath
+ to permit the auto-creation of paths to additional log sockets. This
+ turns out to be useful if they reside on temporary file systems and
+ rsyslogd starts up before the daemons that create these sockets
+ (rsyslogd always creates the socket itself if it does not exist).
+- added $LogRSyslogStatusMessages configuration directive
+ permitting to turn off rsyslog start/stop/HUP messages. See Debian
+ ticket http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463793
+- added new config directive $omfileForceChown to (try to) fix some broken
+ system configs.
+ See ticket for details: http://bugzilla.adiscon.com/show_bug.cgi?id=150
+- added $EscapeControlCharacterTab config directive
+ Thanks to Jonathan Bond-Caron for the patch.
+- added option to use unlimited-size select() calls
+ Thanks to varmojfekoj for the patch
+- debugondemand mode caused backgrounding to fail - close to a bug, but I'd
+ consider the ability to background in this mode a new feature...
+- bugfix (kind of): check if TCP connection is still alive if using TLS
+ Thanks to Jonathan Bond-Caron for the patch.
+- imported changes from 4.5.7 and below
+- bugfix: potential segfault when -p command line option was used
+ Thanks for varmojfekoj for pointing me at this bug.
+- imported changes from 4.5.6 and below
+---------------------------------------------------------------------------
+Version 4.6.8 [v4-stable] (rgerhards), 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: potential misaddressing in property replacer
+- bugfix: memcpy overflow can occur in allowed sender checking
+ if a name is resolved to IPv4-mapped-on-IPv6 address
+ Found by Ismail Dönmez at suse
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+---------------------------------------------------------------------------
+Version 4.6.7 [v4-stable] (rgerhards), 2011-07-11
+- added support for the ":omusrmsg:" syntax in configuring user messages
+- added support for the ":omfile:" syntax for actions
+---------------------------------------------------------------------------
+Version 4.6.6 [v4-stable] (rgerhards), 2011-06-24
+- bugfix: memory leak in imtcp & subsystems under some circumstances
+ This leak is tied to error conditions which lead to incorrect cleanup
+ of some data structures. [backport from v6, limited testing under v4]
+- bugfix: invalid processing in QUEUE_FULL condition
+ If the the multi-submit interface was used and a QUEUE_FULL condition
+ occurred, the failed message was properly destructed. However, the
+ rest of the input batch, if it existed, was not processed. So this
+ lead to potential loss of messages and a memory leak. The potential
+ loss of messages was IMHO minor, because they would have been dropped
+ in most cases due to the queue remaining full, but very few lucky ones
+ from the batch may have made it. Anyhow, this has now been changed so
+ that the rest of the batch is properly tried to be enqueued and, if
+ not possible, destructed.
+- bugfix: invalid storage type for config variables
+- bugfix: stream driver mode was not correctly set on tcp output on big
+ endian systems.
+ thanks varmojfekoj for the patch
+- bugfix: IPv6-address could not be specified in omrelp
+ this was due to improper parsing of ":"
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=250
+- bugfix: memory and file descriptor leak in stream processing
+ Leaks could occur under some circumstances if the file stream handler
+ errored out during the open call. Among others, this could cause very
+ big memory leaks if there were a problem with unreadable disk queue
+ files. In regard to the memory leak, this
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=256
+- bugfix: imfile potentially duplicates lines
+ This can happen when 0 bytes are read from the input file, and some
+ writer appends data to the file BEFORE we check if a rollover happens.
+ The check for rollover uses the inode and size as a criterion. So far,
+ we checked for equality of sizes, which is not given in this scenario,
+ but that does not indicate a rollover. From the source code comments:
+ Note that when we check the size, we MUST NOT check for equality.
+ The reason is that the file may have been written right after we
+ did try to read (so the file size has increased). That is NOT in
+ indicator of a rollover (this is an actual bug scenario we
+ experienced). So we need to check if the new size is smaller than
+ what we already have seen!
+ Also, under some circumstances an invalid truncation was detected. This
+ code has now been removed, a file change (and thus resent) is only
+ detected if the inode number changes.
+- bugfix: a couple of problems that imfile had on some platforms, namely
+ Ubuntu (not their fault, but occurred there)
+- bugfix: imfile utilizes 32 bit to track offset. Most importantly,
+ this problem can not experienced on Fedora 64 bit OS (which has
+ 64 bit long's!)
+- bugfix: abort if imfile reads file line of more than 64KiB
+ Thanks to Peter Eisentraut for reporting and analyzing this problem.
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=221
+- bugfix: omlibdbi did not use password from rsyslog.con
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=203
+- bugfix: TCP connection invalidly aborted when messages needed to be
+ discarded (due to QUEUE_FULL or similar problem)
+- bugfix: a slightly more informative error message when a TCP
+ connections is aborted
+- bugfix: timestamp was incorrectly calculated for timezones with minute
+ offset
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=271
+- some improvements thanks to clang's static code analyzer
+ o overall cleanup (mostly unnecessary writes and otherwise unused stuff)
+ o bugfix: fixed a very remote problem in msg.c which could occur when
+ running under extremely low memory conditions
+---------------------------------------------------------------------------
+Version 4.6.5 [v4-stable] (rgerhards), 2010-11-24
+- bugfix(important): problem in TLS handling could cause rsyslog to loop
+ in a tight loop, effectively disabling functionality and bearing the
+ risk of unresponsiveness of the whole system.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=194
+---------------------------------------------------------------------------
+Version 4.6.4 [v4-stable] (rgerhards), 2010-08-05
+- bugfix: zero-sized (empty) messages were processed by imtcp
+ they are now dropped as they always should have been
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
+---------------------------------------------------------------------------
+Version 4.6.3 [v4-stable] (rgerhards), 2010-07-07
+- improved testbench
+ - added test with truly random data received via syslog to test
+ robustness
+ - added new configure option that permits to disable and enable an
+ extended testbench
+- bugfix: segfault on HUP when "HUPIsRestart" was set to "on"
+ thanks varmojfekoj for the patch
+- bugfix: default for $OMFileFlushOnTXEnd was wrong ("off").
+ This, in default mode, caused buffered writing to be used, what
+ means that it looked like no output were written or partial
+ lines. Thanks to Michael Biebl for pointing out this bug.
+- bugfix: testbench failed when not executed in UTC+1 timezone
+ accidentally, the time zone information was kept inside some
+ to-be-checked-for responses
+- temporary bugfix replaced by permanent one for
+ message-induced off-by-one error (potential segfault) (see 4.6.2)
+ The analysis has been completed and a better fix been crafted and
+ integrated.
+- bugfix: the T/P/E config size specifiers did not work properly under
+ all 32-bit platforms
+- bugfix: local unix system log socket was deleted even when it was
+ not configured
+- some doc fixes; incorrect config samples could cause confusion
+ thanks to Anthony Edwards for pointing the problems out
+---------------------------------------------------------------------------
+Version 4.6.2 [v4-stable] (rgerhards), 2010-03-26
+- new feature: "." action type added to support writing files to relative
+ paths (this is primarily meant as a debug aid)
+- added replacements for atomic instructions on systems that do not
+ support them. [backport of Stefen Sledz' patch for v5)
+- new feature: $OMFileAsyncWriting directive added
+ it permits to specify if asynchronous writing should be done or not
+- bugfix(temporary): message-induced off-by-one error (potential segfault)
+ Some types of malformed messages could trigger an off-by-one error
+ (for example, \0 or \n as the last character, and generally control
+ character escaption is questionable). This is due to not strictly
+ following a the \0 or string counted string paradigm (during the last
+ optimization on the cstring class). As a temporary fix, we have
+ introduced a proper recalculation of the size. However, a final
+ patch is expected in the future. See bug tracker for further details
+ and when the final patch will be available:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=184
+ Note that the current patch is considered sufficient to solve the
+ situation, but it requires a bit more runtime than desirable.
+- bugfix: potential segfault in dynafile cache
+ This bug was triggered by an open failure. The the cache was full and
+ a new entry needed to be placed inside it, a victim for eviction was
+ selected. That victim was freed, then the open of the new file tried. If
+ the open failed, the victim entry was still freed, and the function
+ exited. However, on next invocation and cache search, the victim entry
+ was used as if it were populated, most probably resulting in a segfault.
+- bugfix: race condition during directory creation
+ If multiple files try to create a directory at (almost) the same time,
+ some of them may fail. This is a data race and also exists with other
+ processes that may create the same directory. We do now check for this
+ condition and gracefully handle it.
+- bugfix: potential re-use of free()ed file stream object in omfile
+ when dynaCache is enabled, the cache is full, a new entry needs to
+ be allocated, thus the LRU discarded, then a new entry is opend and that
+ fails. In that case, it looks like the discarded stream may be reused
+ improperly (based on code analysis, test case and confirmation pending)
+- added new property replacer option "date-rfc3164-buggyday" primarily
+ to ease migration from syslog-ng. See property replacer doc for
+ details. [backport from 5.5.3 because urgently needed by some]
+- improved testbench
+- bugfix: invalid buffer write in (file) stream class
+ currently being accessed buffer could be overwritten with new data.
+ While this probably did not cause access violations, it could case loss
+ and/or duplication of some data (definitely a race with no deterministic
+ outcome)
+- bugfix: potential hang condition during filestream close
+ predicate was not properly checked when waiting for the background file
+ writer
+- bugfix: improper synchronization when "$OMFileFlushOnTXEnd on" was used
+ Internal data structures were not properly protected due to missing
+ mutex calls.
+- bugfix: potential data loss during file stream shutdown
+- bugfix: potential problems during file stream shutdown
+ The shutdown/close sequence was not clean, what potentially (but
+ unlikely) could lead to some issues. We have not been able to describe
+ any fatal cases, but there was some bug potential. Sequence has now
+ been straighted out.
+- bugfix: potential problem (loop, abort) when file write error occurred
+ When a write error occurred in stream.c, variable iWritten had the error
+ code but this was handled as if it were the actual number of bytes
+ written. That was used in pointer arithmetic later on, and thus could
+ lead to all sorts of problems. However, this could only happen if the
+ error was EINTR or the file in question was a tty. All other cases were
+ handled properly. Now, iWritten is reset to zero in such cases, resulting
+ in proper retries.
+- bugfix: $omfileFlushOnTXEnd was turned on when set to off and vice
+ versa due to an invalid check
+- bugfix: recent patch to fix small memory leak could cause invalid free.
+ This could only happen during config file parsing.
+- bugfix(minor): handling of extremely large strings in dbgprintf() fixed
+ Previously, it could lead to garbage output and, in extreme cases, also
+ to segfaults. Note: this was a problem only when debug output was
+ actually enabled, so it caused no problem in production use.
+- bugfix(minor): BSD_SO_COMPAT query function had some global vars not
+ properly initialized. However, in practice the loader initializes them
+ with zero, the desired value, so there were no actual issue in almost
+ all cases.
+---------------------------------------------------------------------------
+Version 4.6.1 [v4-stable] (rgerhards), 2010-03-04
+- re-enabled old pipe output (using new module ompipe, built-in) after
+ some problems with pipes (and especially in regard to xconsole) were
+ discovered. Thanks to Michael Biebl for reporting the issues.
+- bugfix: potential problems with large file support could cause segfault
+ ... and other weird problems. This seemed to affect 32bit-platforms
+ only, but I can not totally outrule there were issues on other
+ platforms as well. The previous code could cause system data types
+ to be defined inconsistently, and that could lead to various
+ troubles. Special thanks go to the Mandriva team for identifying
+ an initial problem, help discussing it and ultimately a fix they
+ contributed.
+- bugfix: fixed problem that caused compilation on FreeBSD 9.0 to fail.
+ bugtracker: http://bugzilla.adiscon.com/show_bug.cgi?id=181
+ Thanks to Christiano for reporting.
+- bugfix: potential segfault in omfile when a dynafile open failed
+ In that case, a partial cache entry was written, and some internal
+ pointers (iCurrElt) not correctly updated. In the next iteration, that
+ could lead to a segfault, especially if iCurrElt then points to the
+ then-partial record. Not very likely, but could happen in practice.
+- bugfix (theoretical): potential segfault in omfile under low memory
+ condition. This is only a theoretical bug, because it would only
+ happen when strdup() fails to allocate memory - which is highly
+ unlikely and will probably lead to all other sorts of errors.
+- bugfix: comment char ('#') in literal terminated script parsing
+ and thus could not be used.
+ but tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=119
+ [merged in from v3.22.2]
+---------------------------------------------------------------------------
+Version 4.6.0 [v4-stable] (rgerhards), 2010-02-24
+***************************************************************************
+* This is a new stable v4 version. It contains all fixes and enhancements *
+* made during the 4.5.x phase as well as those listed below. *
+* Note: this version is scheduled to conclude the v4 development process. *
+* Do not expect any more new developments in v4. The focus is now *
+* on v5 (what also means we have a single devel branch again). *
+* ("development" means new feature development, bug fixes are of *
+* course provided for v4-stable) *
+***************************************************************************
+- improved testbench to contain samples for totally malformed messages
+ which miss parts of the message content
+- bugfix: some malformed messages could lead to a missing LF inside files
+ or some other missing parts of the template content.
+- bugfix: if a message ended immediately with a hostname, the hostname
+ was mistakenly interpreted as TAG, and localhost be used as hostname
+- bugfix: message without MSG part could case a segfault
+ [backported from v5 commit 98d1ed504ec001728955a5bcd7916f64cd85f39f]
+ This actually was a "recent" regression, but I did not realize that it
+ was introduced by the performance optimization in v4-devel. Shame on
+ me for having two devel versions at the same time...
+---------------------------------------------------------------------------
+Version 4.5.8 [v4-beta] (rgerhards), 2010-02-10
+- enhanced doc for using PostgreSQL
+ Thanks to Marc Schiffbauer for the new/updated doc
+- bugfix: property replacer returned invalid parameters under some (unusual)
+ conditions. In extreme cases, this could lead to garbled logs and/or
+ a system failure.
+- bugfix: invalid length returned (often) when using regular expressions
+ inside the property replacer
+- bugfix: submatch regex in property replacer did not honor "return 0 on
+ no match" config case
+- bugfix: imuxsock incorrectly stated inputname "imudp"
+ Thanks to Ryan Lynch for reporting this.
+- (slightly) enhanced support for FreeBSD by setting _PATH_MODDIR to
+ the correct value on FreeBSD.
+ Thanks to Cristiano for the patch.
+- bugfix: -d did not enable display of debug messages
+ regression from introduction of "debug on demand" mode
+ Thanks to Michael Biebl for reporting this bug
+- bugfix: blanks inside file names did not terminate file name parsing.
+ This could result in the whole rest of a line (including comments)
+ to be treated as file name in "write to file" actions.
+ Thanks to Jack for reporting this issue.
+- bugfix: rsyslog hang when writing to a named pipe which nobody was
+ reading. Thanks to Michael Biebl for reporting this bug.
+ Bugzilla entry: http://bugzilla.adiscon.com/show_bug.cgi?id=169
+- bugfix: potential segfaults during queue shutdown
+ (bugs require certain non-standard settings to appear)
+ Thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 4.5.7 [v4-beta] (rgerhards), 2009-11-18
+- added a so-called "On Demand Debug" mode, in which debug output can
+ be generated only after the process has started, but not right from
+ the beginning. This is assumed to be useful for hard-to-find bugs.
+ Also improved the doc on the debug system.
+- bugfix (kind of): check if TCP connection is still alive if using TLS
+ Thanks to Jonathan Bond-Caron for the patch.
+- bugfix: hostname accidentally set to IP address for some message sources,
+ for example imudp. Thanks to Anton for reporting this bug.
+- bugfix [imported from 4.4.3]: $ActionExecOnlyOnceEveryInterval did
+ not work.
+---------------------------------------------------------------------------
+Version 4.5.6 [v4-beta] (rgerhards), 2009-11-05
+- bugfix: named pipes did no longer work (they always got an open error)
+ this was a regression from the omfile rewrite in 4.5.0
+- bugfix(minor): diag function returned wrong queue member count
+ for the main queue if an active DA queue existed. This had no relevance
+ to real deployments (assuming they are not running the debug/diagnostic
+ module...), but sometimes caused grief and false alerts in the
+ testbench.
+- included some important fixes from v4-stable:
+ * bugfix: invalid handling of zero-sized messages
+ * bugfix: zero-sized UDP messages are no longer processed
+ * bugfix: random data could be appended to message
+ * bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+- bugfix(testbench): testcase did not properly wait for rsyslog shutdown
+ thus some unpredictable behavior and a false negative test result
+ could occur. [BACKPORTED from v5]
+- bugfix(testbench): sequence check was not always performed correctly,
+ that could result in tests reporting success when they actually failed
+---------------------------------------------------------------------------
+Version 4.5.5 [v4-beta] (rgerhards), 2009-10-21
+- added $InputTCPServerNotifyOnConnectionClose config directive
+ see doc for details
+- bugfix: debug string larger than 1K were improperly displayed. Max size
+ is now 32K
+- bugfix: invalid storage class selected for some size config parameters.
+ This resulted in wrong values. The most prominent victim was the
+ directory creation mode, which was set to zero in some cases. For
+ details, see related blog post:
+ http://blog.gerhards.net/2009/10/another-note-on-hard-to-find-bugs.html
+---------------------------------------------------------------------------
+Version 4.5.4 [v4-beta] (rgerhards), 2009-09-29
+- bugfix: potential segfault in stream writer on destruction
+ Most severely affected omfile. The problem was that some buffers were
+ freed before the asynchronous writer thread was shut down. So the
+ writer thread accessed invalid data, which may even already be
+ overwritten. Symptoms (with omfile) were segfaults, garbled data
+ and files with random names placed around the file system (most
+ prominently into the root directory). Special thanks to Aaron for
+ helping to track this down.
+- bugfix: potential race in object loader (obj.c) during use/release
+ of object interface
+- bugfixes: potential problems in out file zip writer. Problems could
+ lead to abort and/or memory leak. The module is now hardened in a very
+ conservative way, which is sub-optimal from a performance point of view.
+ This should be improved if it has proven reliable in practice.
+---------------------------------------------------------------------------
+Version 4.5.3 [v4-beta] (rgerhards), 2009-09-17
+- bugfix: repeated messages were incorrectly processed
+ this could lead to loss of the repeated message content. As a side-
+ effect, it could probably also be possible that some segfault occurs
+ (quite unlikely). The root cause was that some counters introduced
+ during the malloc optimizations were not properly duplicated in
+ MsgDup(). Note that repeated message processing is not enabled
+ by default.
+- bugfix: message sanitation had some issues:
+ - control character DEL was not properly escaped
+ - NUL and LF characters were not properly stripped if no control
+ character replacement was to be done
+ - NUL characters in the message body were silently dropped (this was
+ a regression introduced by some of the recent optimizations)
+- bugfix: strings improperly reused, resulting in some message properties
+ be populated with strings from previous messages. This was caused by
+ an improper predicate check. [backported from v5]
+- fixed some minor portability issues
+- bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+ [imported from 4.4.2]
+---------------------------------------------------------------------------
+Version 4.5.2 [v4-beta] (rgerhards), 2009-08-21
+- legacy syslog parser changed so that it now accepts date stamps in
+ wrong case. Some devices seem to create them and I do not see any harm
+ in supporting that.
+- added $InputTCPMaxListeners directive - permits to specify how many
+ TCP servers shall be possible (default is 20).
+- bugfix: memory leak with some input modules. Those inputs that
+ use parseAndSubmitMsg() leak two small memory blocks with every message.
+ Typically, those process only relatively few messages, so the issue
+ does most probably not have any effect in practice.
+- bugfix: if tcp listen port could not be created, no error message was
+ emitted
+- bugfix: potential segfault in output file writer (omfile)
+ In async write mode, we use modular arithmetic to index the output
+ buffer array. However, the counter variables accidentally were signed,
+ thus resulting in negative indices after integer overflow. That in turn
+ could lead to segfaults, but was depending on the memory layout of
+ the instance in question (which in turn depended on a number of
+ variables, like compile settings but also configuration). The counters
+ are now unsigned (as they always should have been) and so the dangling
+ mis-indexing does no longer happen. This bug potentially affected all
+ installations, even if only some may actually have seen a segfault.
+- bugfix: hostnames with dashes in them were incorrectly treated as
+ malformed, thus causing them to be treated as TAG (this was a regression
+ introduced from the "rfc3164 strict" change in 4.5.0).
+---------------------------------------------------------------------------
+Version 4.5.1 [DEVEL] (rgerhards), 2009-07-15
+- CONFIG CHANGE: $HUPisRestart default is now "off". We are doing this
+ to support removal of restart-type HUP in v5.
+- bugfix: fromhost-ip was sometimes truncated
+- bugfix: potential segfault when zip-compressed syslog records were
+ received (double free)
+- bugfix: properties inputname, fromhost, fromhost-ip, msg were lost when
+ working with disk queues
+- performance enhancement: much faster, up to twice as fast (depending
+ on configuration)
+- bugfix: abort condition when RecvFrom was not set and message reduction
+ was on. Happened e.g. with imuxsock.
+- added $klogConsoleLogLevel directive which permits to set a new
+ console log level while rsyslog is active
+- bugfix: message could be truncated after TAG, often when forwarding
+ This was a result of an internal processing error if maximum field
+ sizes had been specified in the property replacer.
+- added ability for the TCP output action to "rebind" its send socket after
+ sending n messages (actually, it re-opens the connection, the name is
+ used because this is a concept very similar to $ActionUDPRebindInterval).
+ New config directive $ActionSendTCPRebindInterval added for the purpose.
+ By default, rebinding is disabled. This is considered useful for load
+ balancers.
+- testbench improvements
+---------------------------------------------------------------------------
+Version 4.5.0 [DEVEL] (rgerhards), 2009-07-02
+- activation order of inputs changed, they are now activated only after
+ privileges are dropped. Thanks to Michael Terry for the patch.
+- greatly improved performance
+- greatly reduced memory requirements of msg object
+ to around half of the previous demand. This means that more messages can
+ be stored in core! Due to fewer cache misses, this also means some
+ performance improvement.
+- improved config error messages: now contain a copy of the config line
+ that (most likely) caused the error
+- reduced max value for $DynaFileCacheSize to 1,000 (the former maximum
+ of 10,000 really made no sense, even 1,000 is very high, but we like
+ to keep the user in control ;)).
+- added capability to fsync() queue disk files for enhanced reliability
+ (also add's speed, because you do no longer need to run the whole file
+ system in sync mode)
+- more strict parsing of the hostname in rfc3164 mode, hopefully
+ removes false positives (but may cause some trouble with hostname
+ parsing). For details, see this bug tracker:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=126
+- omfile rewrite to natively support zip files (includes large extension
+ of the stream class)
+- added configuration commands (see doc for explanations)
+ * $OMFileZipLevel
+ * $OMFileIOBufferSize
+ * $OMFileFlushOnTXEnd
+ * $MainMsgQueueSyncQueueFiles
+ * $ActionQueueSyncQueueFiles
+- done some memory accesses explicitly atomic
+- bugfix: subtle (and usually irrelevant) issue in timeout processing
+ timeout could be one second too early if nanoseconds wrapped
+- set a more sensible timeout for shutdown, now 1.5 seconds to complete
+ processing (this also removes those cases where the shutdown message
+ was not written because the termination happened before it)
+- internal bugfix: object pointer was only reset to NULL when an object
+ was actually destructed. This most likely had no effect to existing code,
+ but it may also have caused trouble in remote cases. Similarly, the fix
+ may also cause trouble...
+- bugfix: missing initialization during timestamp creation
+ This could lead to timestamps written in the wrong format, but not to
+ an abort
+---------------------------------------------------------------------------
+Version 4.4.3 [v4-stable] (rgerhards), 2009-10-??
+- bugfix: several smaller bugs resolved after flexelint review
+ Thanks to varmojfekoj for the patch.
+- bugfix: $ActionExecOnlyOnceEveryInterval did not work.
+ This was a regression from the time() optimizations done in v4.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=143
+ Thanks to Klaus Tachtler for reporting this bug.
+- bugfix: potential segfault on queue shutdown
+ Thanks to varmojfekoj for the patch.
+- bugfix: potential hang condition on queue shutdown
+ [imported from v3-stable]
+- bugfix: segfault on startup when -q or -Q option was given
+ [imported from v3-stable]
+---------------------------------------------------------------------------
+Version 4.4.2 [v4-stable] (rgerhards), 2009-10-09
+- bugfix: invalid handling of zero-sized messages, could lead to mis-
+ addressing and potential memory corruption/segfault
+- bugfix: zero-sized UDP messages are no longer processed
+ until now, they were forwarded to processing, but this makes no sense
+ Also, it looks like the system seems to provide a zero return code
+ on a UDP recvfrom() from time to time for some internal reasons. These
+ "receives" are now silently ignored.
+- bugfix: random data could be appended to message, possibly causing
+ segfaults
+- bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+ A comparison was done between the current and the former source address.
+ However, this was done on the full sockaddr_storage structure and not
+ on the host address only. This has now been changed for IPv4 and IPv6.
+ The end result of this bug could be a higher UDP message loss rate than
+ necessary (note that UDP message loss can not totally be avoided due
+ to the UDP spec)
+---------------------------------------------------------------------------
+Version 4.4.1 [v4-stable] (rgerhards), 2009-09-02
+- features requiring Java are automatically disabled if Java is not
+ present (thanks to Michael Biebl for his help!)
+- bugfix: invalid double-quoted PRI, among others in outgoing messages
+ This causes grief with all receivers.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=147
+- bugfix: Java testing tools were required, even if testbench was disabled
+ This resulted in build errors if no Java was present on the build system,
+ even though none of the selected option actually required Java.
+ (I forgot to backport a similar fix to newer releases).
+- bugfix (backport): omfwd segfault
+ Note that the original (higher version) patch states this happens only
+ when debugging mode is turned on. That statement is wrong: if debug
+ mode is turned off, the message is not being emitted, but the division
+ by zero in the actual parameters still happens.
+---------------------------------------------------------------------------
+Version 4.4.0 [v4-stable] (rgerhards), 2009-08-21
+- bugfix: stderr/stdout were not closed to be able to emit error messages,
+ but this caused ssh sessions to hang. Now we close them after the
+ initial initialization. See forum thread:
+ http://kb.monitorware.com/controlling-terminal-issues-t9875.html
+- bugfix: sending syslog messages with zip compression did not work
+---------------------------------------------------------------------------
+Version 4.3.2 [v4-beta] (rgerhards), 2009-06-24
+- removed long-obsoleted property UxTradMsg
+- added a generic network stream server (in addition to rather specific
+ syslog tcp server)
+- added ability for the UDP output action to rebind its send socket after
+ sending n messages. New config directive $ActionSendUDPRebindInterval
+ added for the purpose. By default, rebinding is disabled. This is
+ considered useful for load balancers.
+- bugfix: imdiag/imtcp had a race condition
+- improved testbench (now much better code design and reuse)
+- added config switch --enable-testbench=no to turn off testbench
+---------------------------------------------------------------------------
+Version 4.3.1 [DEVEL] (rgerhards), 2009-05-25
+- added capability to run multiple tcp listeners (on different ports)
+- performance enhancement: imtcp calls parser no longer on input thread
+ but rather inside on of the potentially many main msg queue worker
+ threads (an enhancement scheduled for all input plugins where this is
+ possible)
+- added $GenerateConfigGraph configuration command which can be used
+ to generate nice-looking (and very informative) rsyslog configuration
+ graphs.
+- added $ActionName configuration directive (currently only used for
+ graph generation, but may find other uses)
+- improved doc
+ * added (hopefully) easier to grasp queue explanation
+- improved testbench
+ * added tests for queue disk-only mode (checks disk queue logic)
+- bugfix: light and full delay watermarks had invalid values, badly
+ affecting performance for delayable inputs
+- build system improvements - thanks to Michael Biebl
+- added new testing module imdiag, which enables to talk to the
+ rsyslog core at runtime. The current implementation is only a
+ beginning, but can be expanded over time
+---------------------------------------------------------------------------
+Version 4.3.0 [DEVEL] (rgerhards), 2009-04-17
+- new feature: new output plugin omprog, which permits to start program
+ and feed it (via its stdin) with syslog messages. If the program
+ terminates, it is restarted.
+- improved internal handling of RainerScript functions, building the
+ necessary plumbing to support more functions with decent runtime
+ performance. This is also necessary towards the long-term goal
+ of loadable library modules.
+- added new RainerScript function "tolower"
+- improved testbench
+ * added tests for tcp-based reception
+ * added tcp-load test (1000 connections, 20,000 messages)
+- added $MaxOpenFiles configuration directive
+- bugfix: solved potential memory leak in msg processing, could manifest
+ itself in imtcp
+- bugfix: ompgsql did not detect problems in sql command execution
+ this could cause loss of messages. The handling was correct if the
+ connection broke, but not if there was a problem with statement
+ execution. The most probable case for such a case would be invalid
+ sql inside the template, and this is now much easier to diagnose.
+---------------------------------------------------------------------------
+Version 4.2.0 [v4-stable] (rgerhards), 2009-06-23
+- bugfix: light and full delay watermarks had invalid values, badly
+ affecting performance for delayable inputs
+- imported all patches from 3.22.1 as of today (see below)
+- bugfix: compile problems in im3195
+---------------------------------------------------------------------------
+Version 4.1.7 [BETA] (rgerhards), 2009-04-22
+- bugfix: $InputTCPMaxSessions config directive was accepted, but not
+ honored. This resulted in a fixed upper limit of 200 connections.
+- bugfix: the default for $DirCreateMode was 0644, and as such wrong.
+ It has now been changed to 0700. For some background, please see
+ http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html
+- bugfix: ompgsql did not detect problems in sql command execution
+ this could cause loss of messages. The handling was correct if the
+ connection broke, but not if there was a problem with statement
+ execution. The most probable case for such a case would be invalid
+ sql inside the template, and this is now much easier to diagnose.
+---------------------------------------------------------------------------
+Version 4.1.6 [DEVEL] (rgerhards), 2009-04-07
+- added new "csv" property replacer options to enable simple creation
+ of CSV-formatted outputs (format from RFC4180 is used)
+- implemented function support in RainerScript. That means the engine
+ parses and compile functions, as well as executes a few build-in
+ ones. Dynamic loading and registration of functions is not yet
+ supported - but we now have a good foundation to do that later on.
+- implemented the strlen() RainerScript function
+- added a template output module
+- added -T rsyslogd command line option, enables to specify a directory
+ where to chroot() into on startup. This is NOT a security feature but
+ introduced to support testing. Thus, -T does not make sure chroot()
+ is used in a secure way. (may be removed later)
+- added omstdout module for testing purposes. Spits out all messages to
+ stdout - no config option, no other features
+- added a parser testing suite (still needs to be extended, but a good
+ start)
+- modified $ModLoad statement so that for modules whom's name starts with
+ a dot, no path is prepended (this enables relative-paths and should
+ not break any valid current config)
+- fixed a bug that caused action retries not to work correctly
+ situation was only cleared by a restart
+- bugfix: closed dynafile was potentially never written until another
+ dynafile name was generated - potential loss of messages
+- improved omfile so that it properly suspends itself if there is an
+ i/o or file name generation error. This enables it to be used with
+ the full high availability features of rsyslog's engine
+- bugfix: fixed some segfaults on Solaris, where vsprintf() does not
+ check for NULL pointers
+- improved performance of regexp-based filters
+ Thanks to Arnaud Cornet for providing the idea and initial patch.
+- added a new way how output plugins may be passed parameters. This is
+ more efficient for some outputs. They new can receive fields not only
+ as a single string but rather in an array where each string is separated.
+- added (some) developer documentation for output plugin interface
+- bugfix: potential abort with DA queue after high watermark is reached
+ There exists a race condition that can lead to a segfault. Thanks
+ go to vbernetr, who performed the analysis and provided patch, which
+ I only tweaked a very little bit.
+- bugfix: imtcp did incorrectly parse hostname/tag
+ Thanks to Luis Fernando Muñoz Mejías for the patch.
+---------------------------------------------------------------------------
+Version 4.1.5 [DEVEL] (rgerhards), 2009-03-11
+- bugfix: parser did not correctly parse fields in UDP-received messages
+- added ERE support in filter conditions
+ new comparison operation "ereregex"
+- added new config directive $RepeatedMsgContainsOriginalMsg so that the
+ "last message repeated n times" messages, if generated, may
+ have an alternate format that contains the message that is being repeated
+---------------------------------------------------------------------------
+Version 4.1.4 [DEVEL] (rgerhards), 2009-01-29
+- bugfix: inconsistent use of mutex/atomic operations could cause segfault
+ details are too many, for full analysis see blog post at:
+ http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html
+- bugfix: uninitialized mutex was used in msg.c:getPRI
+ This was subtle, because getPRI is called as part of the debugging code
+ (always executed) in syslogd.c:logmsg.
+- bugfix: $PreserveFQDN was not properly handled for locally emitted
+ messages
+---------------------------------------------------------------------------
+Version 4.1.3 [DEVEL] (rgerhards), 2008-12-17
+- added $InputTCPServerAddtlFrameDelimiter config directive, which
+ enables to specify an additional, non-standard message delimiter
+ for processing plain tcp syslog. This is primarily a fix for the invalid
+ framing used in Juniper's NetScreen products. Credit to forum user
+ Arv for suggesting this solution.
+- added $InputTCPServerInputName property, which enables a name to be
+ specified that will be available during message processing in the
+ inputname property. This is considered useful for logic that treats
+ messages differently depending on which input received them.
+- added $PreserveFQDN config file directive
+ Enables to use FQDNs in sender names where the legacy default
+ would have stripped the domain part.
+ Thanks to BlinkMind, Inc. http://www.blinkmind.com for sponsoring this
+ development.
+- bugfix: imudp went into an endless loop under some circumstances
+ (but could also leave it under some other circumstances...)
+ Thanks to David Lang and speedfox for reporting this issue.
+---------------------------------------------------------------------------
+Version 4.1.2 [DEVEL] (rgerhards), 2008-12-04
+- bugfix: code did not compile without zlib
+- security bugfix: $AllowedSender was not honored, all senders were
+ permitted instead (see https://www.rsyslog.com/Article322.phtml)
+- security fix: imudp emitted a message when a non-permitted sender
+ tried to send a message to it. This behavior is operator-configurable.
+ If enabled, a message was emitted each time. That way an attacker could
+ effectively fill the disk via this facility. The message is now
+ emitted only once in a minute (this currently is a hard-coded limit,
+ if someone comes up with a good reason to make it configurable, we
+ will probably do that).
+- doc bugfix: typo in v3 compatibility document directive syntax
+ thanks to Andrej for reporting
+- imported other changes from 3.21.8 and 3.20.1 (see there)
+---------------------------------------------------------------------------
+Version 4.1.1 [DEVEL] (rgerhards), 2008-11-26
+- added $PrivDropToGroup, $PrivDropToUser, $PrivDropToGroupID,
+ $PrivDropToUserID config directives to enable dropping privileges.
+ This is an effort to provide a security enhancement. For the limits of this
+ approach, see http://wiki.rsyslog.com/index.php/Security
+- re-enabled imklog to compile on FreeBSD (brought in from beta)
+---------------------------------------------------------------------------
+Version 4.1.0 [DEVEL] (rgerhards), 2008-11-18
+
+********************************* WARNING *********************************
+This version has a slightly different on-disk format for message entries.
+As a consequence, old queue files being read by this version may have
+an invalid output timestamp, which could result to some malfunction inside
+the output driver. It is recommended to drain queues with the previous
+version before switching to this one.
+********************************* WARNING *********************************
+
+- greatly enhanced performance when compared to v3.
+- added configuration directive "HUPisRestart" which enables to configure
+ HUP to be either a full restart or "just" a lightweight way to
+ close open files.
+- enhanced legacy syslog parser to detect year if part of the timestamp
+ the format is based on what Cisco devices seem to emit.
+- added a setting "$OptimizeForUniprocessor" to enable users to turn off
+ pthread_yield calls which are counter-productive on multiprocessor
+ machines (but have been shown to be useful on uniprocessors)
+- reordered imudp processing. Message parsing is now done as part of main
+ message queue worker processing (was part of the input thread)
+ This should also improve performance, as potentially more work is
+ done in parallel.
+- bugfix: compressed syslog messages could be slightly mis-uncompressed
+ if the last byte of the compressed record was a NUL
+- added $UDPServerTimeRequery option which enables to work with
+ less accurate timestamps in favor of performance. This enables querying
+ of the time only every n-th time if imudp is running in the tight
+ receive loop (aka receiving messages at a high rate)
+- doc bugfix: queue doc had wrong parameter name for setting controlling
+ worker thread shutdown period
+- restructured rsyslog.conf documentation
+- bugfix: memory leak in ompgsql
+ Thanks to Ken for providing the patch
+---------------------------------------------------------------------------
+Version 3.22.4 [v3-stable] (rgerhards), 2010-??-??
+- bugfix: action resume interval incorrectly handled, thus took longer to
+ resume
+- bugfix: cosmetic: proper constant used instead of number in open call
+- bugfix: timestamp was incorrectly calculated for timezones with minute
+ offset
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=271
+- improved some code based on clang static analyzer results
+- bugfix: potential misaddressing in property replacer
+- bugfix: improper handling of invalid PRI values
+ references: CVE-2014-3634
+---------------------------------------------------------------------------
+Version 3.22.3 [v3-stable] (rgerhards), 2010-11-24
+- bugfix(important): problem in TLS handling could cause rsyslog to loop
+ in a tight loop, effectively disabling functionality and bearing the
+ risk of unresponsiveness of the whole system.
+ Bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=194
+---------------------------------------------------------------------------
+Version 3.22.2 [v3-stable] (rgerhards), 2010-08-05
+- bugfix: comment char ('#') in literal terminated script parsing
+ and thus could not be used.
+ but tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=119
+- enhance: imrelp now also provides remote peer's IP address
+ [if librelp != 1.0.0 is used]
+- bugfix: sending syslog messages with zip compression did not work
+- bugfix: potential hang condition on queue shutdown
+- bugfix: segfault on startup when -q or -Q option was given
+ bug tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=157
+ Thanks to Jonas Nogueira for reporting this bug.
+- clarified use of $ActionsSendStreamDriver[AuthMode/PermittedPeers]
+ in doc set (require TLS drivers)
+- bugfix: $CreateDirs variable not properly initialized, default thus
+ was random (but most often "on")
+- bugfix: potential segfault when -p command line option was used
+ thanks to varmojfekoj for pointing me at this bug
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
+---------------------------------------------------------------------------
+Version 3.22.1 [v3-stable] (rgerhards), 2009-07-02
+- bugfix: invalid error message issued if $includeConfig was on an empty
+ set of files (e.g. *.conf, where none such files existed)
+ thanks to Michael Biebl for reporting this bug
+- bugfix: when run in foreground (but not in debug mode), a
+ debug message ("DoDie called") was emitted at shutdown. Removed.
+ thanks to Michael Biebl for reporting this bug
+- bugfix: some garbage was emitted to stderr on shutdown. This
+ garbage consisted of file names, which were written during
+ startup (key point: not a pointer error)
+ thanks to Michael Biebl for reporting this bug
+- bugfix: startup and shutdown message were emitted to stdout
+ thanks to Michael Biebl for reporting this bug
+- bugfix: error messages were not emitted to stderr in forked mode
+ (stderr and stdo are now kept open across forks)
+- bugfix: internal messages were emitted to whatever file had fd2 when
+ rsyslogd ran in forked mode (as usual!)
+ Thanks to varmojfekoj for the patch
+- small enhancement: config validation run now exits with code 1 if an
+ error is detected. This change is considered important but small enough
+ to apply it directly to the stable version. [But it is a border case,
+ the change requires more code than I had hoped. Thus I have NOT tried
+ to actually catch all cases, this is left for the current devel
+ releases, if necessary]
+- bugfix: light and full delay watermarks had invalid values, badly
+ affecting performance for delayable inputs
+- bugfix: potential segfault issue when multiple $UDPServerRun directives
+ are specified. Thanks to Michael Biebl for helping to debug this one.
+- relaxed GnuTLS version requirement to 1.4.0 after confirmation from the
+ field that this version is sufficient
+- bugfix: parser did not properly handle empty structured data
+- bugfix: invalid mutex release in msg.c (detected under thread debugger,
+ seems not to have any impact on actual deployments)
+---------------------------------------------------------------------------
+Version 3.22.0 [v3-stable] (rgerhards), 2009-04-21
+This is the first stable release that includes the full functionality
+of the 3.21.x version tree.
+- bugfix: $InputTCPMaxSessions config directive was accepted, but not
+ honored. This resulted in a fixed upper limit of 200 connections.
+- bugfix: the default for $DirCreateMode was 0644, and as such wrong.
+ It has now been changed to 0700. For some background, please see
+ http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html
+- bugfix: ompgsql did not detect problems in sql command execution
+ this could cause loss of messages. The handling was correct if the
+ connection broke, but not if there was a problem with statement
+ execution. The most probable case for such a case would be invalid
+ sql inside the template, and this is now much easier to diagnose.
+---------------------------------------------------------------------------
+Version 3.21.11 [BETA] (rgerhards), 2009-04-03
+- build system improvements contributed by Michael Biebl - thx!
+- all patches from 3.20.5 incorporated (see it's ChangeLog entry)
+---------------------------------------------------------------------------
+Version 3.21.10 [BETA] (rgerhards), 2009-02-02
+- bugfix: inconsistent use of mutex/atomic operations could cause segfault
+ details are too many, for full analysis see blog post at:
+ http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html
+- the string "Do Die" was accidentally emited upon exit in non-debug mode
+ This has now been corrected. Thanks to varmojfekoj for the patch.
+- some legacy options were not correctly processed.
+ Thanks to varmojfekoj for the patch.
+- doc bugfix: v3-compatibility document had typo in config directive
+ thanks to Andrej for reporting this
+---------------------------------------------------------------------------
+Version 3.21.9 [BETA] (rgerhards), 2008-12-04
+- re-release of 3.21.8 with an additional fix, that could also lead
+ to DoS; 3.21.8 has been removed from the official download archives
+- security fix: imudp emitted a message when a non-permitted sender
+ tried to send a message to it. This behavior is operator-configurable.
+ If enabled, a message was emitted each time. That way an attacker could
+ effectively fill the disk via this facility. The message is now
+ emitted only once in a minute (this currently is a hard-coded limit,
+ if someone comes up with a good reason to make it configurable, we
+ will probably do that).
+---------------------------------------------------------------------------
+Version 3.21.8 [BETA] (rgerhards), 2008-12-04
+- bugfix: imklog did not compile on FreeBSD
+- security bugfix: $AllowedSender was not honored, all senders were
+ permitted instead (see https://www.rsyslog.com/Article322.phtml)
+- merged in all other changes from 3.20.1 (see there)
+---------------------------------------------------------------------------
+Version 3.21.7 [BETA] (rgerhards), 2008-11-11
+- this is the new beta branch, based on the former 3.21.6 devel
+- new functionality: ZERO property replacer nomatch option (from v3-stable)
+---------------------------------------------------------------------------
+Version 3.21.6 [DEVEL] (rgerhards), 2008-10-22
+- consolidated time calls during msg object creation, improves performance
+ and consistency
+- bugfix: solved a segfault condition
+- bugfix: subsecond time properties generated by imfile, imklog and
+ internal messages could be slightly inconsistent
+- bugfix: (potentially big) memory leak on HUP if queues could not be
+ drained before timeout - thanks to David Lang for pointing this out
+- added capability to support multiple module search paths. Thank
+ to Marius Tomaschewski for providing the patch.
+- bugfix: im3195 did no longer compile
+- improved "make distcheck" by ensuring everything relevant is recompiled
+---------------------------------------------------------------------------
+Version 3.21.5 [DEVEL] (rgerhards), 2008-09-30
+- performance optimization: unnecessary time() calls during message
+ parsing removed - thanks to David Lang for his excellent performance
+ analysis
+- added new capability to property replacer: multiple immediately
+ successive field delimiters are treated as a single one.
+ Thanks to Zhuang Yuyao for the patch.
+- added message property "inputname", which contains the name of the
+ input (module) that generated it. Presence is depending on support in
+ each input module (else it is blank).
+- added system property "$myhostname", which contains the name of the
+ local host as it knows itself.
+- imported a number of fixes and enhancements from the stable and
+ devel branches, including a fix to a potential segfault on HUP
+ when using UDP listeners
+- re-enabled gcc builtin atomic operations and added a proper
+ ./configure check
+- bugfix: potential race condition when adding messages to queue
+ There was a wrong order of mutex lock operations. It is hard to
+ believe that really caused problems, but in theory it could and with
+ threading we often see that theory becomes practice if something is only
+ used long enough on a fast enough machine with enough CPUs ;)
+- cleaned up internal debug system code and made it behave better
+ in regard to multi-threading
+---------------------------------------------------------------------------
+Version 3.21.4 [DEVEL] (rgerhards), 2008-09-04
+- removed compile time fixed message size limit (was 2K), limit can now
+ be set via $MaxMessageSize global config directive (finally gotten rid
+ of MAXLINE ;))
+- enhanced doc for $ActionExecOnlyEveryNthTimeTimeout
+- integrated a number of patches from 3.18.4, namely
+ - bugfix: order-of magnitude issue with base-10 size definitions
+ in config file parser. Could lead to invalid sizes, constraints
+ etc for e.g. queue files and any other object whose size was specified
+ in base-10 entities. Did not apply to binary entities. Thanks to
+ RB for finding this bug and providing a patch.
+ - bugfix: action was not called when system time was set backwards
+ (until the previous time was reached again). There are still some
+ side-effects when time is rolled back (A time rollback is really a bad
+ thing to do, ideally the OS should issue pseudo time (like NetWare did)
+ when the user tries to roll back time). Thanks to varmojfekoj for this
+ patch.
+ - doc bugfix: rsyslog.conf man page improved and minor nit fixed
+ thanks to Lukas Kuklinek for the patch.
+---------------------------------------------------------------------------
+Version 3.21.3 [DEVEL] (rgerhards), 2008-08-13
+- added ability to specify flow control mode for imuxsock
+- added ability to execute actions only after the n-th call of the action
+ This also lead to the addition of two new config directives:
+ $ActionExecOnlyEveryNthTime and $ActionExecOnlyEveryNthTimeTimeout
+ This feature is useful, for example, for alerting: it permits you to
+ send an alert only after at least n occurrences of a specific message
+ have been seen by rsyslogd. This protects against false positives
+ due to waiting for additional confirmation.
+- bugfix: IPv6 addresses could not be specified in forwarding actions
+ New syntax @[addr]:port introduced to enable that. Root problem was IPv6
+ addresses contain colons.
+- somewhat enhanced debugging messages
+- imported from 3.18.3:
+ - enhanced ommysql to support custom port to connect to server
+ Port can be set via new $ActionOmmysqlServerPort config directive
+ Note: this was a very minor change and thus deemed appropriate to be
+ done in the stable release.
+ - bugfix: misspelled config directive, previously was
+ $MainMsgQueueWorkeTimeoutrThreadShutdown, is now
+ $MainMsgQueueWorkerTimeoutThreadShutdown. Note that the misspelled
+ directive is not preserved - if the misspelled directive was used
+ (which I consider highly unlikely), the config file must be changed.
+ Thanks to lperr for reporting the bug.
+---------------------------------------------------------------------------
+Version 3.21.2 [DEVEL] (rgerhards), 2008-08-04
+- added $InputUnixListenSocketHostName config directive, which permits to
+ override the hostname being used on a local unix socket. This is useful
+ for differentiating "hosts" running in several jails. Feature was
+ suggested by David Darville, thanks for the suggestion.
+- enhanced ommail to support multiple email recipients. This is done by
+ specifying $ActionMailTo multiple times. Note that this introduces a
+ small incompatibility to previous config file syntax: the recipient
+ list is now reset for each action (we honestly believe that will
+ not cause any problem - apologies if it does).
+- enhanced troubleshooting documentation
+---------------------------------------------------------------------------
+Version 3.21.1 [DEVEL] (rgerhards), 2008-07-30
+- bugfix: no error was reported if the target of a $IncludeConfig
+ could not be accessed.
+- added testbed for common config errors
+- added doc for -u option to rsyslogd man page
+- enhanced config file checking - no active actions are detected
+- added -N rsyslogd command line option for a config validation run
+ (which does not execute actual syslogd code and does not interfere
+ with a running instance)
+- somewhat improved emergency configuration. It is now also selected
+ if the config contains no active actions
+- rsyslogd error messages are now reported to stderr by default. can be
+ turned off by the new "$ErrorMessagesToStderr off" directive
+ Thanks to HKS for suggesting the new features.
+---------------------------------------------------------------------------
+Version 3.21.0 [DEVEL] (rgerhards), 2008-07-18
+- starts a new devel branch
+- added a generic test driver for RainerScript plus some test cases
+ to the testbench
+- added a small diagnostic tool to obtain result of gethostname() API
+- imported all changes from 3.18.1 until today (some quite important,
+ see below)
+---------------------------------------------------------------------------
+Version 3.20.6 [v3-stable] (rgerhards), 2009-04-16
+- this is the last v3-stable for the 3.20.x series
+- bugfix: $InputTCPMaxSessions config directive was accepted, but not
+ honored. This resulted in a fixed upper limit of 200 connections.
+- bugfix: the default for $DirCreateMode was 0644, and as such wrong.
+ It has now been changed to 0700. For some background, please see
+ http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html
+---------------------------------------------------------------------------
+Version 3.20.5 [v3-stable] (rgerhards), 2009-04-02
+- bugfix: potential abort with DA queue after high watermark is reached
+ There exists a race condition that can lead to a segfault. Thanks
+ go to vbernetr, who performed the analysis and provided patch, which
+ I only tweaked a very little bit.
+- fixed bugs in RainerScript:
+ o when converting a number and a string to a common type, both were
+ actually converted to the other variable's type.
+ o the value of rsCStrConvertToNumber() was miscalculated.
+ Thanks to varmojfekoj for the patch
+- fixed a bug in configure.ac which resulted in problems with
+ environment detection - thanks to Michael Biebl for the patch
+- fixed a potential segfault problem in gssapi code
+ thanks to varmojfekoj for the patch
+- doc enhance: provide standard template for MySQL module and instructions
+ on how to modify schema
+---------------------------------------------------------------------------
+Version 3.20.4 [v3-stable] (rgerhards), 2009-02-09
+- bugfix: inconsistent use of mutex/atomic operations could cause segfault
+ details are too many, for full analysis see blog post at:
+ http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html
+- bugfix: invalid ./configure settings for RFC3195
+ thanks to Michael Biebl for the patch
+- bugfix: invalid mutex access in msg.c
+- doc bugfix: dist tarball missed 2 files, had one extra file that no
+ longer belongs into it. Thanks to Michael Biebl for pointing this out.
+---------------------------------------------------------------------------
+Version 3.20.3 [v3-stable] (rgerhards), 2009-01-19
+- doc bugfix: v3-compatibility document had typo in config directive
+ thanks to Andrej for reporting this
+- fixed a potential segfault condition with $AllowedSender directive
+ On HUP, the root pointers were not properly cleaned up. Thanks to
+ Michael Biebl, olgoat, and Juha Koho for reporting and analyzing
+ the bug.
+---------------------------------------------------------------------------
+Version 3.20.2 [v3-stable] (rgerhards), 2008-12-04
+- re-release of 3.20.1 with an additional fix, that could also lead
+ to DoS; 3.20.1 has been removed from the official download archives
+- security fix: imudp emitted a message when a non-permitted sender
+ tried to send a message to it. This behavior is operator-configurable.
+ If enabled, a message was emitted each time. That way an attacker could
+ effectively fill the disk via this facility. The message is now
+ emitted only once in a minute (this currently is a hard-coded limit,
+ if someone comes up with a good reason to make it configurable, we
+ will probably do that).
+---------------------------------------------------------------------------
+Version 3.20.1 [v3-stable] (rgerhards), 2008-12-04
+- security bugfix: $AllowedSender was not honored, all senders were
+ permitted instead
+- enhance: regex nomatch option "ZERO" has been added
+ This allows one to return the string 0 if a regular expression is
+ not found. This is probably useful for storing numerical values into
+ database columns.
+- bugfix: memory leak in gtls netstream driver fixed
+ memory was lost each time a TLS session was torn down. This could
+ result in a considerable memory leak if it happened quite frequently
+ (potential system crash condition)
+- doc update: documented how to specify multiple property replacer
+ options + link to new online regex generator tool added
+- minor bugfix: very small memory leak in gtls netstream driver
+ around a handful of bytes (< 20) for each HUP
+- improved debug output for regular expressions inside property replacer
+ RE's seem to be a big trouble spot and I would like to have more
+ information inside the debug log. So I decided to add some additional
+ debug strings permanently.
+---------------------------------------------------------------------------
+Version 3.20.0 [v3-stable] (rgerhards), 2008-11-05
+- this is the initial release of the 3.19.x branch as a stable release
+- bugfix: double-free in pctp netstream driver. Thank to varmojfekoj
+ for the patch
+---------------------------------------------------------------------------
+Version 3.19.12 [BETA] (rgerhards), 2008-10-16
+- bugfix: subseconds where not correctly extracted from a timestamp
+ if that timestamp did not contain any subsecond information (the
+ resulting string was garbage but should have been "0", what it
+ now is).
+- increased maximum size of a configuration statement to 4K (was 1K)
+- imported all fixes from the stable branch (quite a lot)
+- bugfix: (potentially big) memory leak on HUP if queues could not be
+ drained before timeout - thanks to David Lang for pointing this out
+---------------------------------------------------------------------------
+Version 3.19.11 [BETA] (rgerhards), 2008-08-25
+This is a refresh of the beta. No beta-specific fixes have been added.
+- included fixes from v3-stable (most importantly 3.18.3)
+---------------------------------------------------------------------------
+Version 3.19.10 [BETA] (rgerhards), 2008-07-15
+- start of a new beta branch based on former 3.19 devel branch
+- bugfix: bad memory leak in disk-based queue modes
+- bugfix: UDP syslog forwarding did not work on all platforms
+ the ai_socktype was incorrectly set to 1. On some platforms, this
+ lead to failing name resolution (e.g. FreeBSD 7). Thanks to HKS for
+ reporting the bug.
+- bugfix: priority was incorrectly calculated on FreeBSD 7,
+ because the LOG_MAKEPRI() C macro has a different meaning there (it
+ is just a simple addition of facility and severity). I have changed
+ this to use own, consistent, code for PRI calculation. Thank to HKS
+ for reporting this bug.
+- bugfix (cosmetical): authorization was not checked when gtls handshake
+ completed immediately. While this sounds scary, the situation can not
+ happen in practice. We use non-blocking IO only for server-based gtls
+ session setup. As TLS requires the exchange of multiple frames before
+ the handshake completes, it simply is impossible to do this in one
+ step. However, it is useful to have the code path correct even for
+ this case - otherwise, we may run into problems if the code is changed
+ some time later (e.g. to use blocking sockets). Thanks to varmojfekoj
+ for providing the patch.
+- important queue bugfix from 3.18.1 imported (see below)
+- cleanup of some debug messages
+---------------------------------------------------------------------------
+Version 3.19.9 (rgerhards), 2008-07-07
+- added tutorial for creating a TLS-secured syslog infrastructure
+- rewritten omusrmsg to no longer fork() a new process for sending messages
+ this caused some problems with the threading model, e.g. zombies. Also,
+ it was far less optimal than it is now.
+- bugfix: machine certificate was required for client even in TLS anon mode
+ Reference: http://bugzilla.adiscon.com/show_bug.cgi?id=85
+ The fix also slightly improves performance by not storing certificates in
+ client sessions when there is no need to do so.
+- bugfix: RainerScript syntax error was not always detected
+---------------------------------------------------------------------------
+Version 3.19.8 (rgerhards), 2008-07-01
+- bugfix: gtls module did not correctly handle EGAIN (and similar) recv()
+ states. This has been fixed by introducing a new abstraction layer inside
+ gtls.
+- added (internal) error codes to error messages; added redirector to
+ web description of error codes
+ closes bug http://bugzilla.adiscon.com/show_bug.cgi?id=20
+- disabled compile warnings caused by third-party libraries
+- reduced number of compile warnings in gcc's -pedantic mode
+- some minor documentation improvements
+- included all fixes from beta 3.17.5
+---------------------------------------------------------------------------
+Version 3.19.7 (rgerhards), 2008-06-11
+- added new property replacer option "date-subseconds" that enables
+ to query just the subsecond part of a high-precision timestamp
+- somewhat improved plain tcp syslog reliability by doing a connection
+ check before sending. Credits to Martin Schuette for providing the
+ idea. Details are available at
+ http://blog.gerhards.net/2008/06/reliable-plain-tcp-syslog-once-again.html
+- made rsyslog tickless in the (usual and default) case that repeated
+ message reduction is turned off. More info:
+ http://blog.gerhards.net/2008/06/coding-to-save-environment.html
+- some build system cleanup, thanks to Michael Biebl
+- bugfix: compile under (Free)BSD failed due to some invalid library
+ definitions - this is fixed now. Thanks to Michael Biebl for the patch.
+---------------------------------------------------------------------------
+Version 3.19.6 (rgerhards), 2008-06-06
+- enhanced property replacer to support multiple regex matches
+- bugfix: part of permittedPeer structure was not correctly initialized
+ thanks to varmojfekoj for spotting this
+- bugfix: off-by-one bug during certificate check
+- bugfix: removed some memory leaks in TLS code
+---------------------------------------------------------------------------
+Version 3.19.5 (rgerhards), 2008-05-30
+- enabled Posix ERE expressions inside the property replacer
+ (previously BRE was permitted only)
+- provided ability to specify that a regular expression submatch shall
+ be used inside the property replacer
+- implemented in property replacer: if a regular expression does not match,
+ it can now either return "**NO MATCH** (default, as before), a blank
+ property or the full original property text
+- enhanced property replacer to support multiple regex matches
+---------------------------------------------------------------------------
+Version 3.19.4 (rgerhards), 2008-05-27
+- implemented x509/certvalid gtls auth mode
+- implemented x509/name gtls auth mode (including wildcards)
+- changed fingerprint gtls auth mode to new format fingerprint
+- protected gtls error string function by a mutex. Without it, we
+ could have a race condition in extreme cases. This was very remote,
+ but now can no longer happen.
+- changed config directive name to reflect different use
+ $ActionSendStreamDriverCertFingerprint is now
+ $ActionSendStreamDriverPermittedPeer and can be used both for
+ fingerprint and name authentication (similar to the input side)
+- bugfix: sender information (fromhost et al) was missing in imudp
+ thanks to sandiso for reporting this bug
+- this release fully implements IETF's syslog-transport-tls-12 plus
+ the latest text changes Joe Salowey provided via email. Not included
+ is ipAddress subjectAltName authentication, which I think will be
+ dropped from the draft. I don't think there is any real need for it.
+This release also includes all bug fix up to today from the beta
+and stable branches. Most importantly, this means the bugfix for
+100% CPU utilization by imklog.
+---------------------------------------------------------------------------
+Version 3.19.3 (rgerhards), 2008-05-21
+- added ability to authenticate the server against its certificate
+ fingerprint
+- added ability for client to provide its fingerprint
+- added ability for server to obtain client cert's fingerprint
+- bugfix: small mem leak in omfwd on exit (strmdriver name was not freed)
+- bugfix: $ActionSendStreamDriver had no effect
+- bugfix: default syslog port was no longer used if none was
+ configured. Thanks to varmojfekoj for the patch
+- bugfix: missing linker options caused build to fail on some
+ systems. Thanks to Tiziano Mueller for the patch.
+---------------------------------------------------------------------------
+Version 3.19.2 (rgerhards), 2008-05-16
+- bugfix: TCP input modules did incorrectly set fromhost property
+ (always blank)
+- bugfix: imklog did not set fromhost property
+- added "fromhost-ip" property
+ Note that adding this property changes the on-disk format for messages.
+ However, that should not have any bad effect on existing spool files.
+ But you will run into trouble if you create a spool file with this
+ version and then try to process it with an older one (after a downgrade).
+ Don't do that ;)
+- added "RSYSLOG_DebugFormat" canned template
+- bugfix: hostname and fromhost were swapped when a persisted message
+ (in queued mode) was read in
+- bugfix: lmtcpclt, lmtcpsrv and lmgssutil did all link to the static
+ runtime library, resulting in a large size increase (and potential
+ "interesting" effects). Thanks to Michael Biebl for reporting the size
+ issue.
+- bugfix: TLS server went into an endless loop in some situations.
+ Thanks to Michael Biebl for reporting the problem.
+- fixed potential segfault due to invalid call to cfsysline
+ thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 3.19.1 (rgerhards), 2008-05-07
+- configure help for --enable-gnutls wrong - said default is "yes" but
+ default actually is "no" - thanks to darix for pointing this out
+- file dirty.h was missing - thanks to darix for pointing this out
+- bugfix: man files were not properly distributed - thanks to
+ darix for reporting and to Michael Biebl for help with the fix
+- some minor cleanup
+---------------------------------------------------------------------------
+Version 3.19.0 (rgerhards), 2008-05-06
+- begins new devel branch version
+- implemented TLS for plain tcp syslog (this is also the world's first
+ implementation of IETF's upcoming syslog-transport-tls draft)
+- partly rewritten and improved omfwd among others, now loads TCP
+ code only if this is actually necessary
+- split of a "runtime library" for rsyslog - this is not yet a clean
+ model, because some modularization is still outstanding. In theory,
+ this shall enable other utilities but rsyslogd to use the same
+ runtime
+- implemented im3195, the RFC3195 input as a plugin
+- changed directory structure, files are now better organized
+- a lot of cleanup in regard to modularization
+- -c option no longer must be the first option - thanks to varmojfekoj
+ for the patch
+---------------------------------------------------------------------------
+Version 3.18.7 (rgerhards), 2008-12-??
+- bugfix: the default for $DirCreateMode was 0644, and as such wrong.
+ It has now been changed to 0700. For some background, please see
+ http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html
+- fixed a potential segfault condition with $AllowedSender directive
+ On HUP, the root pointers were not properly cleaned up. Thanks to
+ Michael Biebl, olgoat, and Juha Koho for reporting and analyzing
+ the bug.
+- some legacy options were not correctly processed.
+ Thanks to varmojfekoj for the patch.
+- doc bugfix: some spelling errors in man pages corrected. Thanks to
+ Geoff Simmons for the patch.
+---------------------------------------------------------------------------
+Version 3.18.6 (rgerhards), 2008-12-08
+- security bugfix: $AllowedSender was not honored, all senders were
+ permitted instead (see https://www.rsyslog.com/Article322.phtml)
+ (backport from v3-stable, v3.20.9)
+- minor bugfix: dual close() call on tcp session closure
+---------------------------------------------------------------------------
+Version 3.18.5 (rgerhards), 2008-10-09
+- bugfix: imudp input module could cause segfault on HUP
+ It did not properly de-init a variable acting as a linked list head.
+ That resulted in trying to access freed memory blocks after the HUP.
+- bugfix: rsyslogd could hang on HUP
+ because getnameinfo() is not cancel-safe, but was not guarded against
+ being cancelled. pthread_cancel() is routinely being called during
+ HUP processing.
+- bugfix[minor]: if queue size reached light_delay mark, enqueuing
+ could potentially be blocked for a longer period of time, which
+ was not the behavior desired.
+- doc bugfix: $ActionExecOnlyWhenPreviousIsSuspended was still misspelled
+ as $...OnlyIfPrev... in some parts of the documentation. Thanks to
+ Lorenzo M. Catucci for reporting this bug.
+- added doc on malformed messages, cause and how to work-around, to the
+ doc set
+- added doc on how to build from source repository
+---------------------------------------------------------------------------
+Version 3.18.4 (rgerhards), 2008-09-18
+- bugfix: order-of magnitude issue with base-10 size definitions
+ in config file parser. Could lead to invalid sizes, constraints
+ etc for e.g. queue files and any other object whose size was specified
+ in base-10 entities. Did not apply to binary entities. Thanks to
+ RB for finding this bug and providing a patch.
+- bugfix: action was not called when system time was set backwards
+ (until the previous time was reached again). There are still some
+ side-effects when time is rolled back (A time rollback is really a bad
+ thing to do, ideally the OS should issue pseudo time (like NetWare did)
+ when the user tries to roll back time). Thanks to varmojfekoj for this
+ patch.
+- doc bugfix: rsyslog.conf man page improved and minor nit fixed
+ thanks to Lukas Kuklinek for the patch.
+- bugfix: error code -2025 was used for two different errors. queue full
+ is now -2074 and -2025 is unique again. (did cause no real problem
+ except for troubleshooting)
+- bugfix: default discard severity was incorrectly set to 4, which lead
+ to discard-on-queue-full to be enabled by default. That could cause
+ message loss where non was expected. The default has now been changed
+ to the correct value of 8, which disables the functionality. This
+ problem applied both to the main message queue and the action queues.
+ Thanks to Raoul Bhatia for pointing out this problem.
+- bugfix: option value for legacy -a option could not be specified,
+ resulting in strange operations. Thanks to Marius Tomaschewski
+ for the patch.
+- bugfix: colon after date should be ignored, but was not. This has
+ now been corrected. Required change to the internal ParseTIMESTAMP3164()
+ interface.
+---------------------------------------------------------------------------
+Version 3.18.3 (rgerhards), 2008-08-18
+- bugfix: imfile could cause a segfault upon rsyslogd HUP and termination
+ Thanks to lperr for an excellent bug report that helped detect this
+ problem.
+- enhanced ommysql to support custom port to connect to server
+ Port can be set via new $ActionOmmysqlServerPort config directive
+ Note: this was a very minor change and thus deemed appropriate to be
+ done in the stable release.
+- bugfix: misspelled config directive, previously was
+ $MainMsgQueueWorkeTimeoutrThreadShutdown, is now
+ $MainMsgQueueWorkerTimeoutThreadShutdown. Note that the misspelled
+ directive is not preserved - if the misspelled directive was used
+ (which I consider highly unlikely), the config file must be changed.
+ Thanks to lperr for reporting the bug.
+- disabled flow control for imuxsock, as it could cause system hangs
+ under some circumstances. The devel (3.21.3 and above) will
+ re-enable it and provide enhanced configurability to overcome the
+ problems if they occur.
+---------------------------------------------------------------------------
+Version 3.18.2 (rgerhards), 2008-08-08
+- merged in IPv6 forwarding address bugfix from v2-stable
+---------------------------------------------------------------------------
+Version 3.18.1 (rgerhards), 2008-07-21
+- bugfix: potential segfault in creating message mutex in non-direct queue
+ mode. rsyslogd segfaults on freeBSD 7.0 (an potentially other platforms)
+ if an action queue is running in any other mode than non-direct. The
+ same problem can potentially be triggered by some main message queue
+ settings. In any case, it will manifest during rsyslog's startup. It is
+ unlikely to happen after a successful startup (the only window of
+ exposure may be a relatively seldom executed action running in queued
+ mode). This has been corrected. Thank to HKS for point out the problem.
+- bugfix: priority was incorrectly calculated on FreeBSD 7,
+ because the LOG_MAKEPRI() C macro has a different meaning there (it
+ is just a simple addition of facility and severity). I have changed
+ this to use own, consistent, code for PRI calculation. [Backport from
+ 3.19.10]
+- bugfix: remove PRI part from kernel message if it is present
+ Thanks to Michael Biebl for reporting this bug
+- bugfix: mark messages were not correctly written to text log files
+ the markmessageinterval was not correctly propagated to all places
+ where it was needed. This resulted in rsyslog using the default
+ (20 minutes) in some code paths, what looked to the user like mark
+ messages were never written.
+- added a new property replacer option "sp-if-no-1st-sp" to cover
+ a problem with RFC 3164 based interpretation of tag separation. While
+ it is a generic approach, it fixes a format problem introduced in
+ 3.18.0, where kernel messages no longer had a space after the tag.
+ This is done by a modification of the default templates.
+ Please note that this may affect some messages where there intentionally
+ is no space between the tag and the first character of the message
+ content. If so, this needs to be worked around via a specific
+ template. However, we consider this scenario to be quite remote and,
+ even if it exists, it is not expected that it will actually cause
+ problems with log parsers (instead, we assume the new default template
+ behavior may fix previous problems with log parsers due to the
+ missing space).
+- bugfix: imklog module was not correctly compiled for GNU/kFreeBSD.
+ Thanks to Petr Salinger for the patch
+- doc bugfix: property replacer options secpath-replace and
+ secpath-drop were not documented
+- doc bugfix: fixed some typos in rsyslog.conf man page
+- fixed typo in source comment - thanks to Rio Fujita
+- some general cleanup (thanks to Michael Biebl)
+---------------------------------------------------------------------------
+Version 3.18.0 (rgerhards), 2008-07-11
+- begun a new v3-stable based on former 3.17.4 beta plus patches to
+ previous v3-stable
+- bugfix in RainerScript: syntax error was not always detected
+---------------------------------------------------------------------------
+Version 3.17.5 (rgerhards), 2008-06-27
+- added doc: howto set up a reliable connection to remote server via
+ queued mode (and plain tcp protocol)
+- bugfix: comments after actions were not properly treated. For some
+ actions (e.g. forwarding), this could also lead to invalid configuration
+---------------------------------------------------------------------------
+Version 3.17.4 (rgerhards), 2008-06-16
+- changed default for $KlogSymbolLookup to "off". The directive is
+ also scheduled for removal in a later version. This was necessary
+ because on kernels >= 2.6, the kernel does the symbol lookup itself. The
+ imklog lookup logic then breaks the log message and makes it unusable.
+---------------------------------------------------------------------------
+Version 3.17.3 (rgerhards), 2008-05-28
+- bugfix: imklog went into an endless loop if a PRI value was inside
+ a kernel log message (unusual case under Linux, frequent under BSD)
+---------------------------------------------------------------------------
+Version 3.17.2 (rgerhards), 2008-05-04
+- this version is the new beta, based on 3.17.1 devel feature set
+- merged in imklog bug fix from v3-stable (3.16.1)
+---------------------------------------------------------------------------
+Version 3.17.1 (rgerhards), 2008-04-15
+- removed dependency on MAXHOSTNAMELEN as much as it made sense.
+ GNU/Hurd does not define it (because it has no limit), and we have taken
+ care for cases where it is undefined now. However, some very few places
+ remain where IMHO it currently is not worth fixing the code. If it is
+ not defined, we have used a generous value of 1K, which is above IETF
+ RFC's on hostname length at all. The memory consumption is no issue, as
+ there are only a handful of this buffers allocated *per run* -- that's
+ also the main reason why we consider it not worth to be fixed any further.
+- enhanced legacy syslog parser to handle slightly malformed messages
+ (with a space in front of the timestamp) - at least HP procurve is
+ known to do that and I won't outrule that others also do it. The
+ change looks quite unintrusive and so we added it to the parser.
+- implemented klogd functionality for BSD
+- implemented high precision timestamps for the kernel log. Thanks to
+ Michael Biebl for pointing out that the kernel log did not have them.
+- provided ability to discard non-kernel messages if they are present
+ in the kernel log (seems to happen on BSD)
+- implemented $KLogInternalMsgFacility config directive
+- implemented $KLogPermitNonKernelFacility config directive
+Plus a number of bugfixes that were applied to v3-stable and beta
+branches (not mentioned here in detail).
+---------------------------------------------------------------------------
+Version 3.17.0 (rgerhards), 2008-04-08
+- added native ability to send mail messages
+- removed no longer needed file relputil.c/.h
+- added $ActionExecOnlyOnceEveryInterval config directive
+- bugfix: memory leaks in script engine
+- bugfix: zero-length strings were not supported in object
+ deserializer
+- properties are now case-insensitive everywhere (script, filters,
+ templates)
+- added the capability to specify a processing (actually dequeue)
+ timeframe with queues - so things can be configured to be done
+ at off-peak hours
+- We have removed the 32 character size limit (from RFC3164) on the
+ tag. This had bad effects on existing environments, as sysklogd didn't
+ obey it either (probably another bug in RFC3164...). We now receive
+ the full size, but will modify the outputs so that only 32 characters
+ max are used by default. If you need large tags in the output, you need
+ to provide custom templates.
+- changed command line processing. -v, -M, -c options are now parsed
+ and processed before all other options. Inter-option dependencies
+ have been relieved. Among others, permits to specify initial module
+ load path via -M only (not the environment) which makes it much
+ easier to work with non-standard module library locations. Thanks
+ to varmojfekoj for suggesting this change. Matches bugzilla bug 55.
+- bugfix: some messages were emited without hostname
+Plus a number of bugfixes that were applied to v3-stable and beta
+branches (not mentioned here in detail).
+---------------------------------------------------------------------------
+Version 3.16.3 (rgerhards), 2008-07-11
+- updated information on rsyslog packages
+- bugfix: memory leak in disk-based queue modes
+---------------------------------------------------------------------------
+Version 3.16.2 (rgerhards), 2008-06-25
+- fixed potential segfault due to invalid call to cfsysline
+ thanks to varmojfekoj for the patch
+- bugfix: some whitespaces where incorrectly not ignored when parsing
+ the config file. This is now corrected. Thanks to Michael Biebl for
+ pointing out the problem.
+---------------------------------------------------------------------------
+Version 3.16.1 (rgerhards), 2008-05-02
+- fixed a bug in imklog which lead to startup problems (including
+ segfault) on some platforms under some circumstances. Thanks to
+ Vieri for reporting this bug and helping to troubleshoot it.
+---------------------------------------------------------------------------
+Version 3.16.0 (rgerhards), 2008-04-24
+- new v3-stable (3.16.x) based on beta 3.15.x (RELP support)
+- bugfix: omsnmp had a too-small sized buffer for hostname+port. This
+ could not lead to a segfault, as snprintf() was used, but could cause
+ some trouble with extensively long hostnames.
+- applied patch from Tiziano Müller to remove some compiler warnings
+- added gssapi overview/howto thanks to Peter Vrabec
+- changed some files to grant LGPLv3 extended permissions on top of GPLv3
+ this also is the first sign of something that will evolve into a
+ well-defined "rsyslog runtime library"
+---------------------------------------------------------------------------
+Version 3.15.1 (rgerhards), 2008-04-11
+- bugfix: some messages were emited without hostname
+- disabled atomic operations for the time being because they introduce some
+ cross-platform trouble - need to see how to fix this in the best
+ possible way
+- bugfix: zero-length strings were not supported in object
+ deserializer
+- added librelp check via PKG_CHECK thanks to Michael Biebl's patch
+- file relputil.c deleted, is not actually needed
+- added more meaningful error messages to rsyslogd (when some errors
+ happens during startup)
+- bugfix: memory leaks in script engine
+- bugfix: $hostname and $fromhost in RainerScript did not work
+This release also includes all changes applied to the stable versions
+up to today.
+---------------------------------------------------------------------------
+Version 3.15.0 (rgerhards), 2008-04-01
+- major new feature: imrelp/omrelp support reliable delivery of syslog
+ messages via the RELP protocol and librelp (http://www.librelp.com).
+ Plain tcp syslog, so far the best reliability solution, can lose
+ messages when something goes wrong or a peer goes down. With RELP,
+ this can no longer happen. See imrelp.html for more details.
+- bugfix: rsyslogd was no longer build by default; man pages are
+ only installed if corresponding option is selected. Thanks to
+ Michael Biebl for pointing these problems out.
+---------------------------------------------------------------------------
+Version 3.14.2 (rgerhards), 2008-04-09
+- bugfix: segfault with expression-based filters
+- bugfix: omsnmp did not deref errmsg object on exit (no bad effects caused)
+- some cleanup
+- bugfix: imklog did not work well with kernel 2.6+. Thanks to Peter
+ Vrabec for patching it based on the development in sysklogd - and thanks
+ to the sysklogd project for upgrading klogd to support the new
+ functionality
+- some cleanup in imklog
+- bugfix: potential segfault in imklog when kernel is compiled without
+ /proc/kallsyms and the file System.map is missing. Thanks to
+ Andrea Morandi for pointing it out and suggesting a fix.
+- bugfixes, credits to varmojfekoj:
+ * reset errno before printing a warning message
+ * misspelled directive name in code processing legacy options
+- bugfix: some legacy options not correctly interpreted - thanks to
+ varmojfekoj for the patch
+- improved detection of modules being loaded more than once
+ thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 3.14.1 (rgerhards), 2008-04-04
+- bugfix: some messages were emited without hostname
+- bugfix: rsyslogd was no longer build by default; man pages are
+ only installed if corresponding option is selected. Thanks to
+ Michael Biebl for pointing these problems out.
+- bugfix: zero-length strings were not supported in object
+ deserializer
+- disabled atomic operations for this stable build as it caused
+ platform problems
+- bugfix: memory leaks in script engine
+- bugfix: $hostname and $fromhost in RainerScript did not work
+- bugfix: some memory leak when queue is running in disk mode
+- man pages improved thanks to varmojfekoj and Peter Vrabec
+- We have removed the 32 character size limit (from RFC3164) on the
+ tag. This had bad effects on existing environments, as sysklogd didn't
+ obey it either (probably another bug in RFC3164...). We now receive
+ the full size, but will modify the outputs so that only 32 characters
+ max are used by default. If you need large tags in the output, you need
+ to provide custom templates.
+- bugfix: some memory leak when queue is running in disk mode
+---------------------------------------------------------------------------
+Version 3.14.0 (rgerhards), 2008-04-02
+An interim version was accidentally released to the web. It was named 3.14.0.
+To avoid confusion, we have not assigned this version number to any
+official release. If you happen to use 3.14.0, please update to 3.14.1.
+---------------------------------------------------------------------------
+Version 3.13.0-dev0 (rgerhards), 2008-03-31
+- bugfix: accidentally set debug option in 3.12.5 reset to production
+ This option prevented dlclose() to be called. It had no real bad effects,
+ as the modules were otherwise correctly deinitialized and dlopen()
+ supports multiple opens of the same module without any memory footprint.
+- removed --enable-mudflap, added --enable-valgrind ./configure setting
+- bugfix: tcp receiver could segfault due to uninitialized variable
+- docfix: queue doc had a wrong directive name that prevented max worker
+ threads to be correctly set
+- worked a bit on atomic memory operations to support problem-free
+ threading (only at non-intrusive places)
+- added a --enable/disable-rsyslogd configure option so that
+ source-based packaging systems can build plugins without the need
+ to compile rsyslogd
+- some cleanup
+- test of potential new version number scheme
+---------------------------------------------------------------------------
+Version 3.12.5 (rgerhards), 2008-03-28
+- changed default for "last message repeated n times", which is now
+ off by default
+- implemented backward compatibility commandline option parsing
+- automatically generated compatibility config lines are now also
+ logged so that a user can diagnose problems with them
+- added compatibility mode for -a, -o and -p options
+- compatibility mode processing finished
+- changed default file output format to include high-precision timestamps
+- added a built-in template for previous syslogd file format
+- added new $ActionFileDefaultTemplate directive
+- added support for high-precision timestamps when receiving legacy
+ syslog messages
+- added new $ActionForwardDefaultTemplate directive
+- added new $ActionGSSForwardDefaultTemplate directive
+- added build-in templates for easier configuration
+- bugfix: fixed small memory leak in tcpclt.c
+- bugfix: fixed small memory leak in template regular expressions
+- bugfix: regular expressions inside property replacer did not work
+ properly
+- bugfix: QHOUR and HHOUR properties were wrongly calculated
+- bugfix: fixed memory leaks in stream class and imfile
+- bugfix: $ModDir did invalid bounds checking, potential overflow in
+ dbgprintf() - thanks to varmojfekoj for the patch
+- bugfix: -t and -g legacy options max number of sessions had a wrong
+ and much too high value
+---------------------------------------------------------------------------
+Version 3.12.4 (rgerhards), 2008-03-25
+- Greatly enhanced rsyslogd's file write performance by disabling
+ file syncing capability of output modules by default. This
+ feature is usually not required, not useful and an extreme performance
+ hit (both to rsyslogd as well as the system at large). Unfortunately,
+ most users enable it by default, because it was most intuitive to enable
+ it in plain old sysklogd syslog.conf format. There is now the
+ $ActionFileEnableSync config setting which must be enabled in order to
+ support syncing. By default it is off. So even if the old-format config
+ lines request syncing, it is not done unless explicitly enabled. I am
+ sure this is a very useful change and not a risk at all. I need to think
+ if I undo it under compatibility mode, but currently this does not
+ happen (I fear a lot of lazy users will run rsyslogd in compatibility
+ mode, again bringing up this performance problem...).
+- added flow control options to other input sources
+- added $HHOUR and $QHOUR system properties - can be used for half- and
+ quarter-hour logfile rotation
+- changed queue's discard severities default value to 8 (do not discard)
+ to prevent unintentional message loss
+- removed a no-longer needed callback from the output module
+ interface. Results in reduced code complexity.
+- bugfix/doc: removed no longer supported -h option from man page
+- bugfix: imklog leaked several hundred KB on each HUP. Thanks to
+ varmojfekoj for the patch
+- bugfix: potential segfault on module unload. Thanks to varmojfekoj for
+ the patch
+- bugfix: fixed some minor memory leaks
+- bugfix: fixed some slightly invalid memory accesses
+- bugfix: internally generated messages had "FROMHOST" property not set
+---------------------------------------------------------------------------
+Version 3.12.3 (rgerhards), 2008-03-18
+- added advanced flow control for congestion cases (mode depending on message
+ source and its capability to be delayed without bad side effects)
+- bugfix: $ModDir should not be reset on $ResetConfig - this can cause a lot
+ of confusion and there is no real good reason to do so. Also conflicts with
+ the new -M option and environment setting.
+- bugfix: TCP and GSSAPI framing mode variable was uninitialized, leading to
+ wrong framing (caused, among others, interop problems)
+- bugfix: TCP (and GSSAPI) octet-counted frame did not work correctly in all
+ situations. If the header was split across two packet reads, it was invalidly
+ processed, causing loss or modification of messages.
+- bugfix: memory leak in imfile
+- bugfix: duplicate public symbol in omfwd and omgssapi could lead to
+ segfault. thanks to varmojfekoj for the patch.
+- bugfix: rsyslogd aborted on sighup - thanks to varmojfekoj for the patch
+- some more internal cleanup ;)
+- begun relp modules, but these are not functional yet
+- Greatly enhanced rsyslogd's file write performance by disabling
+ file syncing capability of output modules by default. This
+ feature is usually not required, not useful and an extreme performance
+ hit (both to rsyslogd as well as the system at large). Unfortunately,
+ most users enable it by default, because it was most intuitive to enable
+ it in plain old sysklogd syslog.conf format. There is now a new config
+ setting which must be enabled in order to support syncing. By default it
+ is off. So even if the old-format config lines request syncing, it is
+ not done unless explicitly enabled. I am sure this is a very useful
+ change and not a risk at all. I need to think if I undo it under
+ compatibility mode, but currently this does not happen (I fear a lot of
+ lazy users will run rsyslogd in compatibility mode, again bringing up
+ this performance problem...).
+---------------------------------------------------------------------------
+Version 3.12.2 (rgerhards), 2008-03-13
+- added RSYSLOGD_MODDIR environment variable
+- added -M rsyslogd option (allows one to specify module directory location)
+- converted net.c into a loadable library plugin
+- bugfix: debug module now survives unload of loadable module when
+ printing out function call data
+- bugfix: not properly initialized data could cause several segfaults if
+ there were errors in the config file - thanks to varmojfekoj for the patch
+- bugfix: rsyslogd segfaulted when imfile read an empty line - thanks
+ to Johnny Tan for an excellent bug report
+- implemented dynamic module unload capability (not visible to end user)
+- some more internal cleanup
+- bugfix: imgssapi segfaulted under some conditions; this fix is actually
+ not just a fix but a change in the object model. Thanks to varmojfekoj
+ for providing the bug report, an initial fix and lots of good discussion
+ that lead to where we finally ended up.
+- improved session recovery when outbound tcp connection breaks, reduces
+ probability of message loss at the price of a highly unlikely potential
+ (single) message duplication
+---------------------------------------------------------------------------
+Version 3.12.1 (rgerhards), 2008-03-06
+- added library plugins, which can be automatically loaded
+- bugfix: actions were not correctly retried; caused message loss
+- changed module loader to automatically add ".so" suffix if not
+ specified (over time, this shall also ease portability of config
+ files)
+- improved debugging support; debug runtime options can now be set via
+ an environment variable
+- bugfix: removed debugging code that I forgot to remove before releasing
+ 3.12.0 (does not cause harm and happened only during startup)
+- added support for the MonitorWare syslog MIB to omsnmp
+- internal code improvements (more code converted into classes)
+- internal code reworking of the imtcp/imgssapi module
+- added capability to ignore client-provided timestamp on unix sockets and
+ made this mode the default; this was needed, as some programs (e.g. sshd)
+ log with inconsistent timezone information, what messes up the local
+ logs (which by default don't even contain time zone information). This
+ seems to be consistent with what sysklogd did for the past four years.
+ Alternate behavior may be desirable if gateway-like processes send
+ messages via the local log slot - in this case, it can be enabled
+ via the $InputUnixListenSocketIgnoreMsgTimestamp and
+ $SystemLogSocketIgnoreMsgTimestamp config directives
+- added ability to compile on HP UX; verified that imudp worked on HP UX;
+ however, we are still in need of people trying out rsyslogd on HP UX,
+ so it can not yet be assumed it runs there
+- improved session recovery when outbound tcp connection breaks, reduces
+ probability of message loss at the price of a highly unlikely potential
+ (single) message duplication
+---------------------------------------------------------------------------
+Version 3.12.0 (rgerhards), 2008-02-28
+- added full expression support for filters; filters can now contain
+ arbitrary complex boolean, string and arithmetic expressions
+---------------------------------------------------------------------------
+Version 3.11.6 (rgerhards), 2008-02-27
+- bugfix: gssapi libraries were still linked to rsyslog core, what should
+ no longer be necessary. Applied fix by Michael Biebl to solve this.
+- enabled imgssapi to be loaded side-by-side with imtcp
+- added InputGSSServerPermitPlainTCP config directive
+- split imgssapi source code somewhat from imtcp
+- bugfix: queue cancel cleanup handler could be called with
+ invalid pointer if dequeue failed
+- bugfix: rsyslogd segfaulted on second SIGHUP
+ tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=38
+- improved stability of queue engine
+- bugfix: queue disk file were not properly persisted when
+ immediately after closing an output file rsyslog was stopped
+ or huped (the new output file open must NOT have happened at
+ that point) - this lead to a sparse and invalid queue file
+ which could cause several problems to the engine (unpredictable
+ results). This situation should have happened only in very
+ rare cases. tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=40
+- bugfix: during queue shutdown, an assert invalidly triggered when
+ the primary queue's DA worker was terminated while the DA queue's
+ regular worker was still executing. This could result in a segfault
+ during shutdown.
+ tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=41
+- bugfix: queue properties sizeOnDisk, bytesRead were persisted to
+ disk with wrong data type (long instead of int64) - could cause
+ problems on 32 bit machines
+- bugfix: queue aborted when it was shut down, DA-enabled, DA mode
+ was just initiated but not fully initialized (a race condition)
+- bugfix: imfile could abort under extreme stress conditions
+ (when it was terminated before it could open all of its
+ to be monitored files)
+- applied patch from varmojfekoj to fix an issue with compatibility
+ mode and default module directories (many thanks!):
+ I've also noticed a bug in the compatibility code; the problem is that
+ options are parsed before configuration file so options which need a
+ module to be loaded will currently ignore any $moddir directive. This
+ can be fixed by moving legacyOptsHook() after config file parsing.
+ (see the attached patch) This goes against the logical order of
+ processing, but the legacy options are only few and it doesn't seem to
+ be a problem.
+- bugfix: object property deserializer did not handle negative numbers
+---------------------------------------------------------------------------
+Version 3.11.5 (rgerhards), 2008-02-25
+- new imgssapi module, changed imtcp module - this enables to load/package
+ GSSAPI support separately - thanks to varmojfekoj for the patch
+- compatibility mode (the -c option series) is now at least partly
+ completed - thanks to varmojfekoj for the patch
+- documentation for imgssapi and imtcp added
+- duplicate $ModLoad's for the same module are now detected and
+ rejected -- thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 3.11.4 (rgerhards), 2008-02-21
+- bugfix: debug.html was missing from release tarball - thanks to Michael
+ Biebl for bringing this to my attention
+- some internal cleanup on the stringbuf object calling interface
+- general code cleanup and further modularization
+- $MainMessageQueueDiscardSeverity can now also handle textual severities
+ (previously only integers)
+- bugfix: message object was not properly synchronized when the
+ main queue had a single thread and non-direct action queues were used
+- some documentation improvements
+---------------------------------------------------------------------------
+Version 3.11.3 (rgerhards), 2008-02-18
+- fixed a bug in imklog which lead to duplicate message content in
+ kernel logs
+- added support for better plugin handling in libdbi (we contributed
+ a patch to do that, we just now need to wait for the next libdbi
+ version)
+- bugfix: fixed abort when invalid template was provided to an action
+ bug http://bugzilla.adiscon.com/show_bug.cgi?id=4
+- re-instantiated SIGUSR1 function; added SIGUSR2 to generate debug
+ status output
+- added some documentation on runtime-debug settings
+- slightly improved man pages for novice users
+---------------------------------------------------------------------------
+Version 3.11.2 (rgerhards), 2008-02-15
+- added the capability to monitor text files and process their content
+ as syslog messages (including forwarding)
+- added support for libdbi, a database abstraction layer. rsyslog now
+ also supports the following databases via dbi drivers:
+ * Firebird/Interbase
+ * FreeTDS (access to MS SQL Server and Sybase)
+ * SQLite/SQLite3
+ * Ingres (experimental)
+ * mSQL (experimental)
+ * Oracle (experimental)
+ Additional drivers may be provided by the libdbi-drivers project, which
+ can be used by rsyslog as soon as they become available.
+- removed some left-over unnecessary dbgprintf's (cluttered screen,
+ cosmetic)
+- doc bugfix: html documentation for omsnmp was missing
+---------------------------------------------------------------------------
+Version 3.11.1 (rgerhards), 2008-02-12
+- SNMP trap sender added thanks to Andre Lorbach (omsnmp)
+- added input-plugin interface specification in form of a (copy) template
+ input module
+- applied documentation fix by Michael Biebl -- many thanks!
+- bugfix: immark did not have MARK flags set...
+- added x-info field to rsyslogd startup/shutdown message. Hopefully
+ points users to right location for further info (many don't even know
+ they run rsyslog ;))
+- bugfix: trailing ":" of tag was lost while parsing legacy syslog messages
+ without timestamp - thanks to Anders Blomdell for providing a patch!
+- fixed a bug in stringbuf.c related to STRINGBUF_TRIM_ALLOCSIZE, which
+ wasn't supposed to be used with rsyslog. Put a warning message up that
+ tells this feature is not tested and probably not worth the effort.
+ Thanks to Anders Blomdell fro bringing this to our attention
+- somewhat improved performance of string buffers
+- fixed bug that caused invalid treatment of tabs (HT) in rsyslog.conf
+- bugfix: setting for $EscapeControlCharactersOnReceive was not
+ properly initialized
+- clarified usage of space-cc property replacer option
+- improved abort diagnostic handler
+- some initial effort for malloc/free runtime debugging support
+- bugfix: using dynafile actions caused rsyslogd abort
+- fixed minor man errors thanks to Michael Biebl
+---------------------------------------------------------------------------
+Version 3.11.0 (rgerhards), 2008-01-31
+- implemented queued actions
+- implemented simple rate limiting for actions
+- implemented deliberate discarding of lower priority messages over higher
+ priority ones when a queue runs out of space
+- implemented disk quotas for disk queues
+- implemented the $ActionResumeRetryCount config directive
+- added $ActionQueueFilename config directive
+- added $ActionQueueSize config directive
+- added $ActionQueueHighWaterMark config directive
+- added $ActionQueueLowWaterMark config directive
+- added $ActionQueueDiscardMark config directive
+- added $ActionQueueDiscardSeverity config directive
+- added $ActionQueueCheckpointInterval config directive
+- added $ActionQueueType config directive
+- added $ActionQueueWorkerThreads config directive
+- added $ActionQueueTimeoutshutdown config directive
+- added $ActionQueueTimeoutActionCompletion config directive
+- added $ActionQueueTimeoutenQueue config directive
+- added $ActionQueueTimeoutworkerThreadShutdown config directive
+- added $ActionQueueWorkerThreadMinimumMessages config directive
+- added $ActionQueueMaxFileSize config directive
+- added $ActionQueueSaveonShutdown config directive
+- addded $ActionQueueDequeueSlowdown config directive
+- addded $MainMsgQueueDequeueSlowdown config directive
+- bugfix: added forgotten docs to package
+- improved debugging support
+- fixed a bug that caused $MainMsgQueueCheckpointInterval to work incorrectly
+- when a long-running action needs to be cancelled on shutdown, the message
+ that was processed by it is now preserved. This finishes support for
+ guaranteed delivery of messages (if the output supports it, of course)
+- fixed bug in output module interface, see
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1881008&group_id=123448&atid=696552
+- changed the ommysql output plugin so that the (lengthy) connection
+ initialization now takes place in message processing. This works much
+ better with the new queued action mode (fast startup)
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+- bugfixed stream class offset handling on 32bit platforms
+---------------------------------------------------------------------------
+Version 3.10.3 (rgerhards), 2008-01-28
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- run-time instrumentation added
+- implemented disk-assisted queue mode, which enables on-demand disk
+ spooling if the queue's in-memory queue is exhausted
+- implemented a dynamic worker thread pool for processing incoming
+ messages; workers are started and shut down as need arises
+- implemented a run-time instrumentation debug package
+- implemented the $MainMsgQueueSaveOnShutdown config directive
+- implemented the $MainMsgQueueWorkerThreadMinimumMessages config directive
+- implemented the $MainMsgQueueTimeoutWorkerThreadShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.2 (rgerhards), 2008-01-14
+- added the ability to keep stop rsyslogd without the need to drain
+ the main message queue. In disk queue mode, rsyslog continues to
+ run from the point where it stopped. In case of a system failure, it
+ continues to process messages from the last checkpoint.
+- fixed a bug that caused a segfault on startup when no $WorkDir directive
+ was specified in rsyslog.conf
+- provided more fine-grain control over shutdown timeouts and added a
+ way to specify the enqueue timeout when the main message queue is full
+- implemented $MainMsgQueueCheckpointInterval config directive
+- implemented $MainMsgQueueTimeoutActionCompletion config directive
+- implemented $MainMsgQueueTimeoutEnqueue config directive
+- implemented $MainMsgQueueTimeoutShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.1 (rgerhards), 2008-01-10
+- implemented the "disk" queue mode. However, it currently is of very
+ limited use, because it does not support persistence over rsyslogd
+ runs. So when rsyslogd is stopped, the queue is drained just as with
+ the in-memory queue modes. Persistent queues will be a feature of
+ the next release.
+- performance-optimized string class, should bring an overall improvement
+- fixed a memory leak in imudp -- thanks to varmojfekoj for the patch
+- fixed a race condition that could lead to a rsyslogd hang when during
+ HUP or termination
+- done some doc updates
+- added $WorkDirectory config directive
+- added $MainMsgQueueFileName config directive
+- added $MainMsgQueueMaxFileSize config directive
+---------------------------------------------------------------------------
+Version 3.10.0 (rgerhards), 2008-01-07
+- implemented input module interface and initial input modules
+- enhanced threading for input modules (each on its own thread now)
+- ability to bind UDP listeners to specific local interfaces/ports and
+ ability to run multiple of them concurrently
+- added ability to specify listen IP address for UDP syslog server
+- license changed to GPLv3
+- mark messages are now provided by loadble module immark
+- rklogd is no longer provided. Its functionality has now been taken over
+ by imklog, a loadable input module. This offers a much better integration
+ into rsyslogd and makes sure that the kernel logger process is brought
+ up and down at the appropriate times
+- enhanced $IncludeConfig directive to support wildcard characters
+ (thanks to Michael Biebl)
+- all inputs are now implemented as loadable plugins
+- enhanced threading model: each input module now runs on its own thread
+- enhanced message queue which now supports different queueing methods
+ (among others, this can be used for performance fine-tuning)
+- added a large number of new configuration directives for the new
+ input modules
+- enhanced multi-threading utilizing a worker thread pool for the
+ main message queue
+- compilation without pthreads is no longer supported
+- much cleaner code due to new objects and removal of single-threading
+ mode
+---------------------------------------------------------------------------
+Version 2.0.8 V2-STABLE (rgerhards), 2008-??-??
+- bugfix: ompgsql did not detect problems in sql command execution
+ this could cause loss of messages. The handling was correct if the
+ connection broke, but not if there was a problem with statement
+ execution. The most probable case for such a case would be invalid
+ sql inside the template, and this is now much easier to diagnose.
+- doc bugfix: default for $DirCreateMode incorrectly stated
+---------------------------------------------------------------------------
+Version 2.0.7 V2-STABLE (rgerhards), 2008-04-14
+- bugfix: the default for $DirCreateMode was 0644, and as such wrong.
+ It has now been changed to 0700. For some background, please see
+ http://lists.adiscon.net/pipermail/rsyslog/2009-April/001986.html
+- bugfix: "$CreateDirs off" also disabled file creation
+ Thanks to William Tisater for analyzing this bug and providing a patch.
+ The actual code change is heavily based on William's patch.
+- bugfix: memory leak in ompgsql
+ Thanks to Ken for providing the patch
+- bugfix: potential memory leak in msg.c
+ This one did not surface yet and the issue was actually found due to
+ a problem in v4 - but better fix it here, too
+---------------------------------------------------------------------------
+Version 2.0.6 V2-STABLE (rgerhards), 2008-08-07
+- bugfix: memory leaks in rsyslogd, primarily in singlethread mode
+ Thanks to Frederico Nunez for providing the fix
+- bugfix: copy&paste error lead to dangling if - this caused a very minor
+ issue with re-formatting a RFC3164 date when the message was invalidly
+ formatted and had a colon immediately after the date. This was in the
+ code for some years (even v1 had it) and I think it never had any
+ effect at all in practice. Though, it should be fixed - but definitely
+ nothing to worry about.
+---------------------------------------------------------------------------
+Version 2.0.6 V2-STABLE (rgerhards), 2008-08-07
+- bugfix: IPv6 addresses could not be specified in forwarding actions
+ New syntax @[addr]:port introduced to enable that. Root problem was IPv6
+ addresses contain colons. (backport from 3.21.3)
+---------------------------------------------------------------------------
+Version 2.0.5 STABLE (rgerhards), 2008-05-15
+- bugfix: regular expressions inside property replacer did not work
+ properly
+- adapted to liblogging 0.7.1+
+---------------------------------------------------------------------------
+Version 2.0.4 STABLE (rgerhards), 2008-03-27
+- bugfix: internally generated messages had "FROMHOST" property not set
+- bugfix: continue parsing if tag is oversize (discard oversize part) - thanks
+ to mclaughlin77@gmail.com for the patch
+- added $HHOUR and $QHOUR system properties - can be used for half- and
+ quarter-hour logfile rotation
+---------------------------------------------------------------------------
+Version 2.0.3 STABLE (rgerhards), 2008-03-12
+- bugfix: setting for $EscapeControlCharactersOnReceive was not
+ properly initialized
+- bugfix: resolved potential segfault condition on HUP (extremely
+ unlikely to happen in practice), for details see tracker:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=38
+- improved the man pages a bit - thanks to Michael Biebl for the patch
+- bugfix: not properly initialized data could cause several segfaults if
+ there were errors in the config file - thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 2.0.2 STABLE (rgerhards), 2008-02-12
+- fixed a bug that could cause invalid string handling via strerror_r
+ varmojfekoj provided the patch - many thanks!
+- added x-info field to rsyslogd startup/shutdown message. Hopefully
+ points users to right location for further info (many don't even know
+ they run rsyslog ;))
+- bugfix: suspended actions were not always properly resumed
+ varmojfekoj provided the patch - many thanks!
+- bugfix: errno could be changed during mark processing, leading to
+ invalid error messages when processing inputs. Thank to varmojfekoj for
+ pointing out this problem.
+- bugfix: trailing ":" of tag was lost while parsing legacy syslog messages
+ without timestamp - thanks to Anders Blomdell for providing a patch!
+- bugfix (doc): misspelled config directive, invalid signal info
+- applied some doc fixes from Michel Biebl and cleaned up some no longer
+ needed files suggested by him
+- cleaned up stringbuf.c to fix an annoyance reported by Anders Blomdell
+- fixed bug that caused invalid treatment of tabs (HT) in rsyslog.conf
+---------------------------------------------------------------------------
+Version 2.0.1 STABLE (rgerhards), 2008-01-24
+- fixed a bug in integer conversion - but this function was never called,
+ so it is not really a useful bug fix ;)
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+---------------------------------------------------------------------------
+Version 2.0.0 STABLE (rgerhards), 2008-01-02
+- re-release of 1.21.2 as STABLE with no modifications except some
+ doc updates
+---------------------------------------------------------------------------
+Version 1.21.2 (rgerhards), 2007-12-28
+- created a gss-api output module. This keeps GSS-API code and
+ TCP/UDP code separated. It is also important for forward-
+ compatibility with v3. Please note that this change breaks compatibility
+ with config files created for 1.21.0 and 1.21.1 - this was considered
+ acceptable.
+- fixed an error in forwarding retry code (could lead to message corruption
+ but surfaced very seldom)
+- increased portability for older platforms (AI_NUMERICSERV moved)
+- removed socket leak in omfwd.c
+- cross-platform patch for GSS-API compile problem on some platforms
+ thanks to darix for the patch!
+---------------------------------------------------------------------------
+Version 1.21.1 (rgerhards), 2007-12-23
+- small doc fix for $IncludeConfig
+- fixed a bug in llDestroy()
+- bugfix: fixing memory leak when message queue is full and during
+ parsing. Thanks to varmojfekoj for the patch.
+- bugfix: when compiled without network support, unix sockets were
+ not properly closed
+- bugfix: memory leak in cfsysline.c/doGetWord() fixed
+---------------------------------------------------------------------------
+Version 1.21.0 (rgerhards), 2007-12-19
+- GSS-API support for syslog/TCP connections was added. Thanks to
+ varmojfekoj for providing the patch with this functionality
+- code cleanup
+- enhanced $IncludeConfig directive to support wildcard filenames
+- changed some multithreading synchronization
+---------------------------------------------------------------------------
+Version 1.20.1 (rgerhards), 2007-12-12
+- corrected a debug setting that survived release. Caused TCP connections
+ to be retried unnecessarily often.
+- When a hostname ACL was provided and DNS resolution for that name failed,
+ ACL processing was stopped at that point. Thanks to mildew for the patch.
+ Fedora Bugzilla: http://bugzilla.redhat.com/show_bug.cgi?id=395911
+- fixed a potential race condition, see link for details:
+ http://rgerhards.blogspot.com/2007/12/rsyslog-race-condition.html
+ Note that the probability of problems from this bug was very remote
+- fixed a memory leak that happened when PostgreSQL date formats were
+ used
+---------------------------------------------------------------------------
+Version 1.20.0 (rgerhards), 2007-12-07
+- an output module for postgres databases has been added. Thanks to
+ sur5r for contributing this code
+- unloading dynamic modules has been cleaned up, we now have a
+ real implementation and not just a dummy "good enough for the time
+ being".
+- enhanced platform independence - thanks to Bartosz Kuzma and Michael
+ Biebl for their very useful contributions
+- some general code cleanup (including warnings on 64 platforms, only)
+---------------------------------------------------------------------------
+Version 1.19.12 (rgerhards), 2007-12-03
+- cleaned up the build system (thanks to Michael Biebl for the patch)
+- fixed a bug where ommysql was still not compiled with -pthread option
+---------------------------------------------------------------------------
+Version 1.19.11 (rgerhards), 2007-11-29
+- applied -pthread option to build when building for multi-threading mode
+ hopefully solves an issue with segfaulting
+---------------------------------------------------------------------------
+Version 1.19.10 (rgerhards), 2007-10-19
+- introduced the new ":modulename:" syntax for calling module actions
+ in selector lines; modified ommysql to support it. This is primarily
+ an aid for further modules and a prerequisite to actually allow third
+ party modules to be created.
+- minor fix in slackware startup script, "-r 0" is now "-r0"
+- updated rsyslogd doc set man page; now in html format
+- undid creation of a separate thread for the main loop -- this did not
+ turn out to be needed or useful, so reduce complexity once again.
+- added doc fixes provided by Michael Biebl - thanks
+---------------------------------------------------------------------------
+Version 1.19.9 (rgerhards), 2007-10-12
+- now packaging system which again contains all components in a single
+ tarball
+- modularized main() a bit more, resulting in less complex code
+- experimentally added an additional thread - will see if that affects
+ the segfault bug we experience on some platforms. Note that this change
+ is scheduled to be removed again later.
+---------------------------------------------------------------------------
+Version 1.19.8 (rgerhards), 2007-09-27
+- improved repeated message processing
+- applied patch provided by varmojfekoj to support building ommysql
+ in its own way (now also resides in a plugin subdirectory);
+ ommysql is now a separate package
+- fixed a bug in cvthname() that lead to message loss if part
+ of the source hostname would have been dropped
+- created some support for distributing ommysql together with the
+ main rsyslog package. I need to re-think it in the future, but
+ for the time being the current mode is best. I now simply include
+ one additional tarball for ommysql inside the main distribution.
+ I look forward to user feedback on how this should be done best. In the
+ long term, a separate project should be spawend for ommysql, but I'd
+ like to do that only after the plugin interface is fully stable (what
+ it is not yet).
+---------------------------------------------------------------------------
+Version 1.19.7 (rgerhards), 2007-09-25
+- added code to handle situations where senders send us messages ending with
+ a NUL character. It is now simply removed. This also caused trailing LF
+ reduction to fail, when it was followed by such a NUL. This is now also
+ handled.
+- replaced some non-thread-safe function calls by their thread-safe
+ counterparts
+- fixed a minor memory leak that occurred when the %APPNAME% property was
+ used (I think nobody used that in practice)
+- fixed a bug that caused signal handlers in cvthname() not to be restored when
+ a malicious pointer record was detected and processing of the message been
+ stopped for that reason (this should be really rare and can not be related
+ to the segfault bug we are hunting).
+- fixed a bug in cvthname that lead to passing a wrong parameter - in
+ practice, this had no impact.
+- general code cleanup (e.g. compiler warnings, comments)
+---------------------------------------------------------------------------
+Version 1.19.6 (rgerhards), 2007-09-11
+- applied patch by varmojfekoj to change signal handling to the new
+ sigaction API set (replacing the depreciated signal() calls and its
+ friends.
+- fixed a bug that in --enable-debug mode caused an assertion when the
+ discard action was used
+- cleaned up compiler warnings
+- applied patch by varmojfekoj to FIX a bug that could cause
+ segfaults if empty properties were processed using modifying
+ options (e.g. space-cc, drop-cc)
+- fixed man bug: rsyslogd supports -l option
+---------------------------------------------------------------------------
+Version 1.19.5 (rgerhards), 2007-09-07
+- changed part of the CStr interface so that better error tracking
+ is provided and the calling sequence is more intuitive (there were
+ invalid calls based on a too-weird interface)
+- (hopefully) fixed some remaining bugs rooted in wrong use of
+ the CStr class. These could lead to program abort.
+- applied patch by varmojfekoj two fix two potential segfault situations
+- added $ModDir config directive
+- modified $ModLoad so that an absolute path may be specified as
+ module name (e.g. /rsyslog/ommysql.so)
+---------------------------------------------------------------------------
+Version 1.19.4 (rgerhards/varmojfekoj), 2007-09-04
+- fixed a number of small memory leaks - thanks varmojfekoj for patching
+- fixed an issue with CString class that could lead to rsyslog abort
+ in tplToString() - thanks varmojfekoj for patching
+- added a man-version of the config file documentation - thanks to Michel
+ Samia for providing the man file
+- fixed bug: a template like this causes an infinite loop:
+ $template opts,"%programname:::a,b%"
+ thanks varmojfekoj for the patch
+- fixed bug: case changing options crash freeing the string pointer
+ because they modify it: $template opts2,"%programname::1:lowercase%"
+ thanks varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 1.19.3 (mmeckelein/varmojfekoj), 2007-08-31
+- small mem leak fixed (after calling parseSelectorAct) - Thx varmojfekoj
+- documentation section "Regular File" und "Blocks" updated
+- solved an issue with dynamic file generation - Once again many thanks
+ to varmojfekoj
+- the negative selector for program name filter (Blocks) does not work as
+ expected - Thanks varmojfekoj for patching
+- added forwarding information to sysklogd (requires special template)
+ to config doc
+---------------------------------------------------------------------------
+Version 1.19.2 (mmeckelein/varmojfekoj), 2007-08-28
+- a specifically formed message caused a segfault - Many thanks varmojfekoj
+ for providing a patch
+- a typo and a weird condition are fixed in msg.c - Thanks again
+ varmojfekoj
+- on file creation the file was always owned by root:root. This is fixed
+ now - Thanks ypsa for solving this issue
+---------------------------------------------------------------------------
+Version 1.19.1 (mmeckelein), 2007-08-22
+- a bug that caused a high load when a TCP/UDP connection was closed is
+ fixed now - Thanks mildew for solving this issue
+- fixed a bug which caused a segfault on reinit - Thx varmojfekoj for the
+ patch
+- changed the hardcoded module path "/lib/rsyslog" to $(pkglibdir) in order
+ to avoid trouble e.g. on 64 bit platforms (/lib64) - many thanks Peter
+ Vrabec and darix, both provided a patch for solving this issue
+- enhanced the unloading of modules - thanks again varmojfekoj
+- applied a patch from varmojfekoj which fixes various little things in
+ MySQL output module
+---------------------------------------------------------------------------
+Version 1.19.0 (varmojfekoj/rgerhards), 2007-08-16
+- integrated patch from varmojfekoj to make the mysql module a loadable one
+ many thanks for the patch, MUCH appreciated
+---------------------------------------------------------------------------
+Version 1.18.2 (rgerhards), 2007-08-13
+- fixed a bug in outchannel code that caused templates to be incorrectly
+ parsed
+- fixed a bug in ommysql that caused a wrong ";template" missing message
+- added some code for unloading modules; not yet fully complete (and we do
+ not yet have loadable modules, so this is no problem)
+- removed debian subdirectory by request of a debian packager (this is a special
+ subdir for debian and there is also no point in maintaining it when there
+ is a debian package available - so I gladly did this) in some cases
+- improved overall doc quality (some pages were quite old) and linked to
+ more of the online resources.
+- improved /contrib/delete_mysql script by adding a host option and some
+ other minor modifications
+---------------------------------------------------------------------------
+Version 1.18.1 (rgerhards), 2007-08-08
+- applied a patch from varmojfekoj which solved a potential segfault
+ of rsyslogd on HUP
+- applied patch from Michel Samia to fix compilation when the pthreads
+ feature is disabled
+- some code cleanup (moved action object to its own file set)
+- add config directive $MainMsgQueueSize, which now allows one to configure the
+ queue size dynamically
+- all compile-time settings are now shown in rsyslogd -v, not just the
+ active ones
+- enhanced performance a little bit more
+- added config file directive $ActionResumeInterval
+- fixed a bug that prevented compilation under debian sid
+- added a contrib directory for user-contributed useful things
+---------------------------------------------------------------------------
+Version 1.18.0 (rgerhards), 2007-08-03
+- rsyslog now supports fallback actions when an action did not work. This
+ is a great feature e.g. for backup database servers or backup syslog
+ servers
+- modified rklogd to only change the console log level if -c is specified
+- added feature to use multiple actions inside a single selector
+- implemented $ActionExecOnlyWhenPreviousIsSuspended config directive
+- error messages during startup are now spit out to the configured log
+ destinations
+---------------------------------------------------------------------------
+Version 1.17.6 (rgerhards), 2007-08-01
+- continued to work on output module modularization - basic stage of
+ this work is now FINISHED
+- fixed bug in OMSRcreate() - always returned SR_RET_OK
+- fixed a bug that caused ommysql to always complain about missing
+ templates
+- fixed a mem leak in OMSRdestruct - freeing the object itself was
+ forgotten - thanks to varmojfekoj for the patch
+- fixed a memory leak in syslogd/init() that happened when the config
+ file could not be read - thanks to varmojfekoj for the patch
+- fixed insufficient memory allocation in addAction() and its helpers.
+ The initial fix and idea was developed by mildew, I fine-tuned
+ it a bit. Thanks a lot for the fix, I'd probably had pulled out my
+ hair to find the bug...
+- added output of config file line number when a parsing error occurred
+- fixed bug in objomsr.c that caused program to abort in debug mode with
+ an invalid assertion (in some cases)
+- fixed a typo that caused the default template for MySQL to be wrong.
+ thanks to mildew for catching this.
+- added configuration file command $DebugPrintModuleList and
+ $DebugPrintCfSysLineHandlerList
+- fixed an invalid value for the MARK timer - unfortunately, there was
+ a testing aid left in place. This resulted in quite frequent MARK messages
+- added $IncludeConfig config directive
+- applied a patch from mildew to prevent rsyslogd from freezing under heavy
+ load. This could happen when the queue was full. Now, we drop messages
+ but rsyslogd remains active.
+---------------------------------------------------------------------------
+Version 1.17.5 (rgerhards), 2007-07-30
+- continued to work on output module modularization
+- fixed a missing file bug - thanks to Andrea Montanari for reporting
+ this problem
+- fixed a problem with shutting down the worker thread and freeing the
+ selector_t list - this caused messages to be lost, because the
+ message queue was not properly drained before the selectors got
+ destroyed.
+---------------------------------------------------------------------------
+Version 1.17.4 (rgerhards), 2007-07-27
+- continued to work on output module modularization
+- fixed a situation where rsyslogd could create zombie processes
+ thanks to mildew for the patch
+- applied patch from Michel Samia to fix compilation when NOT
+ compiled for pthreads
+---------------------------------------------------------------------------
+Version 1.17.3 (rgerhards), 2007-07-25
+- continued working on output module modularization
+- fixed a bug that caused rsyslogd to segfault on exit (and
+ probably also on HUP), when there was an unsent message in a selector
+ that required forwarding and the dns lookup failed for that selector
+ (yes, it was pretty unlikely to happen;))
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed a memory leak in config file parsing and die()
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- rsyslogd now checks on startup if it is capable to perform any work
+ at all. If it cant, it complains and terminates
+ thanks to Michel Samia for providing the patch!
+- fixed a small memory leak when HUPing syslogd. The allowed sender
+ list now gets freed. thanks to mildew for the patch.
+- changed the way error messages in early startup are logged. They
+ now do no longer use the syslogd code directly but are rather
+ send to stderr.
+---------------------------------------------------------------------------
+Version 1.17.2 (rgerhards), 2007-07-23
+- made the port part of the -r option optional. Needed for backward
+ compatibility with sysklogd
+- replaced system() calls with something more reasonable. Please note that
+ this might break compatibility with some existing configuration files.
+ We accept this in favor of the gained security.
+- removed a memory leak that could occur if timegenerated was used in
+ RFC 3164 format in templates
+- did some preparation in msg.c for advanced multithreading - placed the
+ hooks, but not yet any active code
+- worked further on modularization
+- added $ModLoad MySQL (dummy) config directive
+- added DropTrailingLFOnReception config directive
+---------------------------------------------------------------------------
+Version 1.17.1 (rgerhards), 2007-07-20
+- fixed a bug that caused make install to install rsyslogd and rklogd under
+ the wrong names
+- fixed bug that caused $AllowedSenders to handle IPv6 scopes incorrectly;
+ also fixed but that could garble $AllowedSender wildcards. Thanks to
+ mildew@gmail.com for the patch
+- minor code cleanup - thanks to Peter Vrabec for the patch
+- fixed minimal memory leak on HUP (caused by templates)
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed another memory leak on HUPing and on exiting rsyslogd
+ again thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- code cleanup (removed compiler warnings)
+- fixed portability bug in configure.ac - thanks to Bartosz Kuźma for patch
+- moved msg object into its own file set
+- added the capability to continue trying to write log files when the
+ file system is full. Functionality based on patch by Martin Schulze
+ to sysklogd package.
+---------------------------------------------------------------------------
+Version 1.17.0 (RGer), 2007-07-17
+- added $RepeatedLineReduction config parameter
+- added $EscapeControlCharactersOnReceive config parameter
+- added $ControlCharacterEscapePrefix config parameter
+- added $DirCreateMode config parameter
+- added $CreateDirs config parameter
+- added $DebugPrintTemplateList config parameter
+- added $ResetConfigVariables config parameter
+- added $FileOwner config parameter
+- added $FileGroup config parameter
+- added $DirOwner config parameter
+- added $DirGroup config parameter
+- added $FailOnChownFailure config parameter
+- added regular expression support to the filter engine
+ thanks to Michel Samia for providing the patch!
+- enhanced $AllowedSender functionality. Credits to mildew@gmail.com for
+ the patch doing that
+ - added IPv6 support
+ - allowed DNS hostnames
+ - allowed DNS wildcard names
+- added new option $DropMsgsWithMaliciousDnsPTRRecords
+- added autoconf so that rfc3195d, rsyslogd and klogd are stored to /sbin
+- added capability to auto-create directories with dynaFiles
+---------------------------------------------------------------------------
+Version 1.16.0 (RGer/Peter Vrabec), 2007-07-13 - The Friday, 13th Release ;)
+- build system switched to autotools
+- removed SYSV preprocessor macro use, replaced with autotools equivalents
+- fixed a bug that caused rsyslogd to segfault when TCP listening was
+ disabled and it terminated
+- added new properties "syslogfacility-text" and "syslogseverity-text"
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- added the -x option to disable hostname dns resolution
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- begun to better modularize syslogd.c - this is an ongoing project; moved
+ type definitions to a separate file
+- removed some now-unused fields from struct filed
+- move file size limit fields in struct field to the "right spot" (the file
+ writing part of the union - f_un.f_file)
+- subdirectories linux and solaris are no longer part of the distribution
+ package. This is not because we cease support for them, but there are no
+ longer any files in them after the move to autotools
+---------------------------------------------------------------------------
+Version 1.15.1 (RGer), 2007-07-10
+- fixed a bug that caused a dynaFile selector to stall when there was
+ an open error with one file
+- improved template processing for dynaFiles; templates are now only
+ looked up during initialization - speeds up processing
+- optimized memory layout in struct filed when compiled with MySQL
+ support
+- fixed a bug that caused compilation without SYSLOG_INET to fail
+- re-enabled the "last message repeated n times" feature. This
+ feature was not taken care of while rsyslogd evolved from sysklogd
+ and it was more or less defunct. Now it is fully functional again.
+- added system properties: $NOW, $YEAR, $MONTH, $DAY, $HOUR, $MINUTE
+- fixed a bug in iovAsString() that caused a memory leak under stress
+ conditions (most probably memory shortage). This was unlikely to
+ ever happen, but it doesn't hurt doing it right
+- cosmetic: defined type "uchar", change all unsigned chars to uchar
+---------------------------------------------------------------------------
+Version 1.15.0 (RGer), 2007-07-05
+- added ability to dynamically generate file names based on templates
+ and thus properties. This was a much-requested feature. It makes
+ life easy when it e.g. comes to splitting files based on the sender
+ address.
+- added $umask and $FileCreateMode config file directives
+- applied a patch from Bartosz Kuzma to compile cleanly under NetBSD
+- checks for extra (unexpected) characters in system config file lines
+ have been added
+- added IPv6 documentation - was accidentally missing from CVS
+- begun to change char to unsigned char
+---------------------------------------------------------------------------
+Version 1.14.2 (RGer), 2007-07-03
+** this release fixes all known nits with IPv6 **
+- restored capability to do /etc/service lookup for "syslog"
+ service when -r 0 was given
+- documented IPv6 handling of syslog messages
+- integrate patch from Bartosz Kuźma to make rsyslog compile under
+ Solaris again (the patch replaced a strndup() call, which is not
+ available under Solaris
+- improved debug logging when waiting on select
+- updated rsyslogd man page with new options (-46A)
+---------------------------------------------------------------------------
+Version 1.14.1 (RGer/Peter Vrabec), 2007-06-29
+- added Peter Vrabec's patch for IPv6 TCP
+- prefixed all messages send to stderr in rsyslogd with "rsyslogd: "
+---------------------------------------------------------------------------
+Version 1.14.0 (RGer/Peter Vrabec), 2007-06-28
+- Peter Vrabec provided IPv6 for rsyslog, so we are now IPv6 enabled
+ IPv6 Support is currently for UDP only, TCP is to come soon.
+ AllowedSender configuration does not yet work for IPv6.
+- fixed code in iovCreate() that broke C's strict aliasing rules
+- fixed some char/unsigned char differences that forced the compiler
+ to spit out warning messages
+- updated the Red Hat init script to fix a known issue (thanks to
+ Peter Vrabec)
+---------------------------------------------------------------------------
+Version 1.13.5 (RGer), 2007-06-22
+- made the TCP session limit configurable via command line switch
+ now -t <port>,<max sessions>
+- added man page for rklogd(8) (basically a copy from klogd, but now
+ there is one...)
+- fixed a bug that caused internal messages (e.g. rsyslogd startup) to
+ appear without a tag.
+- removed a minor memory leak that occurred when TAG processing requalified
+ a HOSTNAME to be a TAG (and a TAG already was set).
+- removed potential small memory leaks in MsgSet***() functions. There
+ would be a leak if a property was re-set, something that happened
+ extremely seldom.
+---------------------------------------------------------------------------
+Version 1.13.4 (RGer), 2007-06-18
+- added a new property "PRI-text", which holds the PRI field in
+ textual form (e.g. "syslog.info")
+- added alias "syslogseverity" for "syslogpriority", which is a
+ misleading property name that needs to stay for historical
+ reasons (and backward-compatibility)
+- added doc on how to record PRI value in log file
+- enhanced signal handling in klogd, including removal of an unsafe
+ call to the logging system during signal handling
+---------------------------------------------------------------------------
+Version 1.13.3 (RGer), 2007-06-15
+- create a version of syslog.c from scratch. This is now
+ - highly optimized for rsyslog
+ - removes an incompatible license problem as the original
+ version had a BSD license with advertising clause
+ - fixed in the regard that rklogd will continue to work when
+ rsyslogd has been restarted (the original version, as well
+ as sysklogd, will remain silent then)
+ - solved an issue with an extra NUL char at message end that the
+ original version had
+- applied some changes to klogd to care for the new interface
+- fixed a bug in syslogd.c which prevented compiling under debian
+---------------------------------------------------------------------------
+Version 1.13.2 (RGer), 2007-06-13
+- lib order in makefile patched to facilitate static linking - thanks
+ to Bennett Todd for providing the patch
+- Integrated a patch from Peter Vrabec (pvrabec@redhat.com):
+ - added klogd under the name of rklogd (remove dependency on
+ original sysklogd package
+ - createDB.sql now in UTF
+ - added additional config files for use on Red Hat
+---------------------------------------------------------------------------
+Version 1.13.1 (RGer), 2007-02-05
+- changed the listen backlog limit to a more reasonable value based on
+ the maximum number of TCP connections configured (10% + 5) - thanks to Guy
+ Standen for the hint (actually, the limit was 5 and that was a
+ left-over from early testing).
+- fixed a bug in makefile which caused DB-support to be disabled when
+ NETZIP support was enabled
+- added the -e option to allow transmission of every message to remote
+ hosts (effectively turns off duplicate message suppression)
+- (somewhat) improved memory consumption when compiled with MySQL support
+- looks like we fixed an incompatibility with MySQL 5.x and above software
+ At least in one case, the remote server name was destroyed, leading to
+ a connection failure. The new, improved code does not have this issue and
+ so we see this as solved (the new code is generally somewhat better, so
+ there is a good chance we fixed this incompatibility).
+---------------------------------------------------------------------------
+Version 1.13.0 (RGer), 2006-12-19
+- added '$' as ToPos property replacer specifier - means "up to the
+ end of the string"
+- property replacer option "escape-cc", "drop-cc" and "space-cc" added
+- changed the handling of \0 characters inside syslog messages. We now
+ consistently escape them to "#000". This is somewhat recommended in
+ the draft-ietf-syslog-protocol-19 draft. While the real recommendation
+ is to not escape any characters at all, we can not do this without
+ considerable modification of the code. So we escape it to "#000", which
+ is consistent with a sample found in the Internet-draft.
+- removed message glue logic (see printchopped() comment for details)
+ Also caused removal of parts table and thus some improvements in
+ memory usage.
+- changed the default MAXLINE to 2048 to take care of recent syslog
+ standardization efforts (can easily be changed in syslogd.c)
+- added support for byte-counted TCP syslog messages (much like
+ syslog-transport-tls-05 Internet Draft). This was necessary to
+ support compression over TCP.
+- added support for receiving compressed syslog messages
+- added support for sending compressed syslog messages
+- fixed a bug where the last message in a syslog/tcp stream was
+ lost if it was not properly terminated by a LF character
+---------------------------------------------------------------------------
+Version 1.12.3 (RGer), 2006-10-04
+- implemented some changes to support Solaris (but support is not
+ yet complete)
+- commented out (via #if 0) some methods that are currently not being use
+ but should be kept for further us
+- added (interim) -u 1 option to turn off hostname and tag parsing
+- done some modifications to better support Fedora
+- made the field delimiter inside property replace configurable via
+ template
+- fixed a bug in property replacer: if fields were used, the delimitor
+ became part of the field. Up until now, this was barely noticeable as
+ the delimiter as TAB only and thus invisible to a human. With other
+ delimiters available now, it quickly showed up. This bug fix might cause
+ some grief to existing installations if they used the extra TAB for
+ whatever reasons - sorry folks... Anyhow, a solution is easy: just add
+ a TAB character constant into your template. Thus, there has no attempt
+ been made to do this in a backwards-compatible way.
+---------------------------------------------------------------------------
+Version 1.12.2 (RGer), 2006-02-15
+- fixed a bug in the RFC 3339 date formatter. An extra space was added
+ after the actual timestamp
+- added support for providing high-precision RFC3339 timestamps for
+ (rsyslogd-)internally-generated messages
+- very (!) experimental support for syslog-protocol internet draft
+ added (the draft is experimental, the code is solid ;))
+- added support for field-extracting in the property replacer
+- enhanced the legacy-syslog parser so that it can interpret messages
+ that do not contain a TIMESTAMP
+- fixed a bug that caused the default socket (usually /dev/log) to be
+ opened even when -o command line option was given
+- fixed a bug in the Debian sample startup script - it caused rsyslogd
+ to listen to remote requests, which it shouldn't by default
+---------------------------------------------------------------------------
+Version 1.12.1 (RGer), 2005-11-23
+- made multithreading work with BSD. Some signal-handling needed to be
+ restructured. Also, there might be a slight delay of up to 10 seconds
+ when huping and terminating rsyslogd under BSD
+- fixed a bug where a NULL-pointer was passed to printf() in logmsg().
+- fixed a bug during "make install" where rc3195d was not installed
+ Thanks to Bennett Todd for spotting this.
+- fixed a bug where rsyslogd dumped core when no TAG was found in the
+ received message
+- enhanced message parser so that it can deal with missing hostnames
+ in many cases (may not be totally fail-safe)
+- fixed a bug where internally-generated messages did not have the correct
+ TAG
+---------------------------------------------------------------------------
+Version 1.12.0 (RGer), 2005-10-26
+- moved to a multi-threaded design. single-threading is still optionally
+ available. Multi-threading is experimental!
+- fixed a potential race condition. In the original code, marking was done
+ by an alarm handler, which could lead to all sorts of bad things. This
+ has been changed now. See comments in syslogd.c/domark() for details.
+- improved debug output for property-based filters
+- not a code change, but: I have checked all exit()s to make sure that
+ none occurs once rsyslogd has started up. Even in unusual conditions
+ (like low-memory conditions) rsyslogd somehow remains active. Of course,
+ it might loose a message or two, but at least it does not abort and it
+ can also recover when the condition no longer persists.
+- fixed a bug that could cause loss of the last message received
+ immediately before rsyslogd was terminated.
+- added comments on thread-safety of global variables in syslogd.c
+- fixed a small bug: spurios printf() when TCP syslog was used
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug with regular expression support (thanks to Andres Riancho)
+- a little bit of code restructuring (especially main(), which was
+ horribly large)
+---------------------------------------------------------------------------
+Version 1.11.1 (RGer), 2005-10-19
+- support for BSD-style program name and host blocks
+- added a new property "programname" that can be used in templates
+- added ability to specify listen port for rfc3195d
+- fixed a bug that rendered the "startswith" comparison operation
+ unusable.
+- changed more functions to "static" storage class to help compiler
+ optimize (should have been static in the first place...)
+- fixed a potential memory leak in the string buffer class destructor.
+ As the destructor was previously never called, the leak did not actually
+ appear.
+- some internal restructuring in anticipation/preparation of minimal
+ multi-threading support
+- rsyslogd still shares some code with the sysklogd project. Some patches
+ for this shared code have been brought over from the sysklogd CVS.
+---------------------------------------------------------------------------
+Version 1.11.0 (RGer), 2005-10-12
+- support for receiving messages via RFC 3195; added rfc3195d for that
+ purpose
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+---------------------------------------------------------------------------
+Version 1.10.2 (RGer), 2005-09-27
+- added comparison operations in property-based filters:
+ * isequal
+ * startswith
+- added ability to negate all property-based filter comparison operations
+ by adding a !-sign right in front of the operation name
+- added the ability to specify remote senders for UDP and TCP
+ received messages. Allows to block all but well-known hosts
+- changed the $-config line directives to be case-INsensitive
+- new command line option -w added: "do not display warnings if messages
+ from disallowed senders are received"
+- fixed a bug that caused rsyslogd to dump core when the compare value
+ was not quoted in property-based filters
+- fixed a bug in the new CStr compare function which lead to invalid
+ results (fortunately, this function was not yet used widely)
+- added better support for "debugging" rsyslog.conf property filters
+ (only if -d switch is given)
+- changed some function definitions to static, which eventually enables
+ some compiler optimizations
+- fixed a bug in MySQL code; when a SQL error occurred, rsyslogd could
+ run in a tight loop. This was due to invalid sequence of error reporting
+ and is now fixed.
+---------------------------------------------------------------------------
+Version 1.10.1 (RGer), 2005-09-23
+- added the ability to execute a shell script as an action.
+ Thanks to Bjoern Kalkbrenner for providing the code!
+- fixed a bug in the MySQL code; due to the bug the automatic one-time
+ retry after an error did not happen - this lead to error message in
+ cases where none should be seen (e.g. after a MySQL restart)
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.10.0 (RGer), 2005-09-20
+ REMINDER: 1.10 is the first unstable version if the 1.x series!
+- added the capability to filter on any property in selector lines
+ (not just facility and priority)
+- changed stringbuf into a new counted string class
+- added support for a "discard" action. If a selector line with
+ discard (~ character) is found, no selector lines *after* that
+ line will be processed.
+- thanks to Andres Riancho, regular expression support has been
+ added to the template engine
+- added the FROMHOST property in the template processor, which could
+ previously not be obtained. Thanks to Cristian Testa for pointing
+ this out and even providing a fix.
+- added display of compile-time options to -v output
+- performance improvement for production build - made some checks
+ to happen only during debug mode
+- fixed a problem with compiling on SUSE and - while doing so - removed
+ the socket call to set SO_BSDCOMPAT in cases where it is obsolete.
+---------------------------------------------------------------------------
+Version 1.0.4 (RGer), 2006-02-01
+- a small but important fix: the tcp receiver had two forgotten printf's
+ in it that caused a lot of unnecessary output to stdout. This was
+ important enough to justify a new release
+---------------------------------------------------------------------------
+Version 1.0.3 (RGer), 2005-11-14
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+- applied some patches available from the sysklogd project to code
+ shared from there
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug in the TCP sender that caused the retry logic to fail
+ after an error or receiver overrun
+- fixed a bug in init() that could lead to dumping core
+- fixed a bug that could lead to dumping core when no HOSTNAME or no TAG
+ was present in the syslog message
+---------------------------------------------------------------------------
+Version 1.0.2 (RGer), 2005-10-05
+- fixed an issue with MySQL error reporting. When an error occurred,
+ the MySQL driver went into an endless loop (at least in most cases).
+---------------------------------------------------------------------------
+Version 1.0.1 (RGer), 2005-09-23
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.0.0 (RGer), 2005-09-12
+- changed install doc to cover daily cron scripts - a trouble source
+- added rc script for slackware (provided by Chris Elvidge - thanks!)
+- fixed a really minor bug in usage() - the -r option was still
+ reported as without the port parameter
+---------------------------------------------------------------------------
+Version 0.9.8 (RGer), 2005-09-05
+- made startup and shutdown message more consistent and included the
+ pid, so that they can be easier correlated. Used syslog-protocol
+ structured data format for this purpose.
+- improved config info in startup message, now tells not only
+ if it is listening remote on udp, but also for tcp. Also includes
+ the port numbers. The previous startup message was misleading, because
+ it did not say "remote reception" if rsyslogd was only listening via
+ tcp (but not via udp).
+- added a "how can you help" document to the doc set
+---------------------------------------------------------------------------
+Version 0.9.7 (RGer), 2005-08-15
+- some of the previous doc files (like INSTALL) did not properly
+ reflect the changes to the build process and the new doc. Fixed
+ that.
+- changed syslogd.c so that when compiled without database support,
+ an error message is displayed when a database action is detected
+ in the config file (previously this was used as an user rule ;))
+- fixed a bug in the os-specific Makefiles which caused MySQL
+ support to not be compiled, even if selected
+---------------------------------------------------------------------------
+Version 0.9.6 (RGer), 2005-08-09
+- greatly enhanced documentation. Now available in html format in
+ the "doc" folder and FreeBSD. Finally includes an install howto.
+- improved MySQL error messages a little - they now show up as log
+ messages, too (formerly only in debug mode)
+- added the ability to specify the listen port for udp syslog.
+ WARNING: This introduces an incompatibility. Formerly, udp
+ syslog was enabled by the -r command line option. Now, it is
+ "-r [port]", which is consistent with the tcp listener. However,
+ just -r will now return an error message.
+- added sample startup scripts for Debian and FreeBSD
+- added support for easy feature selection in the makefile. Un-
+ fortunately, this also means I needed to spilt the make file
+ for different OS and distros. There are some really bad syntax
+ differences between FreeBSD and Linux make.
+---------------------------------------------------------------------------
+Version 0.9.5 (RGer), 2005-08-01
+- the "semicolon bug" was actually not (fully) solved in 0.9.4. One
+ part of the bug was solved, but another still existed. This one
+ is fixed now, too.
+- the "semicolon bug" actually turned out to be a more generic bug.
+ It appeared whenever an invalid template name was given. With some
+ selector actions, rsyslogd dumped core, with other it "just" had
+ a small resource leak with others all worked well. These anomalies
+ are now fixed. Note that they only appeared during system initialization
+ once the system was running, nothing bad happened.
+- improved error reporting for template errors on startup. They are now
+ shown on the console and the start-up tty. Formerly, they were only
+ visible in debug mode.
+- support for multiple instances of rsyslogd on a single machine added
+- added new option "-o" --> omit local unix domain socket. This option
+ enables rsyslogd NOT to listen to the local socket. This is most
+ helpful when multiple instances of rsyslogd (or rsyslogd and another
+ syslogd) shall run on a single system.
+- added new option "-i <pidfile>" which allows one to specify the pidfile.
+ This is needed when multiple instances of rsyslogd are to be run.
+- the new project home page is now online at www.rsyslog.com
+---------------------------------------------------------------------------
+Version 0.9.4 (RGer), 2005-07-25
+- finally added the TCP sender. It now supports non-blocking mode, no
+ longer disabling message reception during connect. As it is now, it
+ is usable in production. The code could be more sophisticated, but
+ I've kept it short in anticipation of the move to liblogging, which
+ will lead to the removal of the code just written ;)
+- the "exiting on signal..." message still had the "syslogd" name in
+ it. Changed this to "rsyslogd", as we do not have a large user base
+ yet, this should pose no problem.
+- fixed "the semicolon" bug. rsyslogd dumped core if a write-db action
+ was specified but no semicolon was given after the password (an empty
+ template was ok, but the semicolon needed to be present).
+- changed a default for traditional output format. During testing, it
+ was seen that the timestamp written to file in default format was
+ the time of message reception, not the time specified in the TIMESTAMP
+ field of the message itself. Traditionally, the message TIMESTAMP is
+ used and this has been changed now.
+---------------------------------------------------------------------------
+Version 0.9.3 (RGer), 2005-07-19
+- fixed a bug in the message parser. In June, the RFC 3164 timestamp
+ was not correctly parsed (yes, only in June and some other months,
+ see the code comment to learn why...)
+- added the ability to specify the destination port when forwarding
+ syslog messages (both for TCP and UDP)
+- added an very experimental TCP sender (activated by
+ @@machine:port in config). This is not yet for production use. If
+ the receiver is not alive, rsyslogd will wait quite some time until
+ the connection request times out, which most probably leads to
+ loss of incoming messages.
+
+---------------------------------------------------------------------------
+Version 0.9.2 (RGer), around 2005-07-06
+- I intended to change the maxsupported message size to 32k to
+ support IHE - but given the memory inefficiency in the usual use
+ cases, I have not done this. I have, however, included very
+ specific instructions on how to do this in the source code. I have
+ also done some testing with 32k messages, so you can change the
+ max size without taking too much risk.
+- added a syslog/tcp receiver; we now can receive messages via
+ plain tcp, but we can still send only via UDP. The syslog/tcp
+ receiver is the primary enhancement of this release.
+- slightly changed some error messages that contained a spurios \n at
+ the end of the line (which gives empty lines in your log...)
+
+---------------------------------------------------------------------------
+Version 0.9.1 (RGer)
+- fixed code so that it compiles without errors under FreeBSD
+- removed now unused function "allocate_log()" from syslogd.c
+- changed the make file so that it contains more defines for
+ different environments (in the long term, we need a better
+ system for disabling/enabling features...)
+- changed some printf's printing off_t types to %lld and
+ explicit (long long) casts. I tried to figure out the exact type,
+ but did not succeed in this. In the worst case, ultra-large peta-
+ byte files will now display funny informational messages on rollover,
+ something I think we can live with for the neersion 3.11.2 (rgerhards), 2008-02-??
+---------------------------------------------------------------------------
+Version 3.11.1 (rgerhards), 2008-02-12
+- SNMP trap sender added thanks to Andre Lorbach (omsnmp)
+- added input-plugin interface specification in form of a (copy) template
+ input module
+- applied documentation fix by Michael Biebl -- many thanks!
+- bugfix: immark did not have MARK flags set...
+- added x-info field to rsyslogd startup/shutdown message. Hopefully
+ points users to right location for further info (many don't even know
+ they run rsyslog ;))
+- bugfix: trailing ":" of tag was lost while parsing legacy syslog messages
+ without timestamp - thanks to Anders Blomdell for providing a patch!
+- fixed a bug in stringbuf.c related to STRINGBUF_TRIM_ALLOCSIZE, which
+ wasn't supposed to be used with rsyslog. Put a warning message up that
+ tells this feature is not tested and probably not worth the effort.
+ Thanks to Anders Blomdell fro bringing this to our attention
+- somewhat improved performance of string buffers
+- fixed bug that caused invalid treatment of tabs (HT) in rsyslog.conf
+- bugfix: setting for $EscapeControlCharactersOnReceive was not
+ properly initialized
+- clarified usage of space-cc property replacer option
+- improved abort diagnostic handler
+- some initial effort for malloc/free runtime debugging support
+- bugfix: using dynafile actions caused rsyslogd abort
+- fixed minor man errors thanks to Michael Biebl
+---------------------------------------------------------------------------
+Version 3.11.0 (rgerhards), 2008-01-31
+- implemented queued actions
+- implemented simple rate limiting for actions
+- implemented deliberate discarding of lower priority messages over higher
+ priority ones when a queue runs out of space
+- implemented disk quotas for disk queues
+- implemented the $ActionResumeRetryCount config directive
+- added $ActionQueueFilename config directive
+- added $ActionQueueSize config directive
+- added $ActionQueueHighWaterMark config directive
+- added $ActionQueueLowWaterMark config directive
+- added $ActionQueueDiscardMark config directive
+- added $ActionQueueDiscardSeverity config directive
+- added $ActionQueueCheckpointInterval config directive
+- added $ActionQueueType config directive
+- added $ActionQueueWorkerThreads config directive
+- added $ActionQueueTimeoutshutdown config directive
+- added $ActionQueueTimeoutActionCompletion config directive
+- added $ActionQueueTimeoutenQueue config directive
+- added $ActionQueueTimeoutworkerThreadShutdown config directive
+- added $ActionQueueWorkerThreadMinimumMessages config directive
+- added $ActionQueueMaxFileSize config directive
+- added $ActionQueueSaveonShutdown config directive
+- addded $ActionQueueDequeueSlowdown config directive
+- addded $MainMsgQueueDequeueSlowdown config directive
+- bugfix: added forgotten docs to package
+- improved debugging support
+- fixed a bug that caused $MainMsgQueueCheckpointInterval to work incorrectly
+- when a long-running action needs to be cancelled on shutdown, the message
+ that was processed by it is now preserved. This finishes support for
+ guaranteed delivery of messages (if the output supports it, of course)
+- fixed bug in output module interface, see
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1881008&group_id=123448&atid=696552
+- changed the ommysql output plugin so that the (lengthy) connection
+ initialization now takes place in message processing. This works much
+ better with the new queued action mode (fast startup)
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+- bugfixed stream class offset handling on 32bit platforms
+---------------------------------------------------------------------------
+Version 3.10.3 (rgerhards), 2008-01-28
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- run-time instrumentation added
+- implemented disk-assisted queue mode, which enables on-demand disk
+ spooling if the queue's in-memory queue is exhausted
+- implemented a dynamic worker thread pool for processing incoming
+ messages; workers are started and shut down as need arises
+- implemented a run-time instrumentation debug package
+- implemented the $MainMsgQueueSaveOnShutdown config directive
+- implemented the $MainMsgQueueWorkerThreadMinimumMessages config directive
+- implemented the $MainMsgQueueTimeoutWorkerThreadShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.2 (rgerhards), 2008-01-14
+- added the ability to keep stop rsyslogd without the need to drain
+ the main message queue. In disk queue mode, rsyslog continues to
+ run from the point where it stopped. In case of a system failure, it
+ continues to process messages from the last checkpoint.
+- fixed a bug that caused a segfault on startup when no $WorkDir directive
+ was specified in rsyslog.conf
+- provided more fine-grain control over shutdown timeouts and added a
+ way to specify the enqueue timeout when the main message queue is full
+- implemented $MainMsgQueueCheckpointInterval config directive
+- implemented $MainMsgQueueTimeoutActionCompletion config directive
+- implemented $MainMsgQueueTimeoutEnqueue config directive
+- implemented $MainMsgQueueTimeoutShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.1 (rgerhards), 2008-01-10
+- implemented the "disk" queue mode. However, it currently is of very
+ limited use, because it does not support persistence over rsyslogd
+ runs. So when rsyslogd is stopped, the queue is drained just as with
+ the in-memory queue modes. Persistent queues will be a feature of
+ the next release.
+- performance-optimized string class, should bring an overall improvement
+- fixed a memory leak in imudp -- thanks to varmojfekoj for the patch
+- fixed a race condition that could lead to a rsyslogd hang when during
+ HUP or termination
+- done some doc updates
+- added $WorkDirectory config directive
+- added $MainMsgQueueFileName config directive
+- added $MainMsgQueueMaxFileSize config directive
+---------------------------------------------------------------------------
+Version 3.10.0 (rgerhards), 2008-01-07
+- implemented input module interface and initial input modules
+- enhanced threading for input modules (each on its own thread now)
+- ability to bind UDP listeners to specific local interfaces/ports and
+ ability to run multiple of them concurrently
+- added ability to specify listen IP address for UDP syslog server
+- license changed to GPLv3
+- mark messages are now provided by loadble module immark
+- rklogd is no longer provided. Its functionality has now been taken over
+ by imklog, a loadable input module. This offers a much better integration
+ into rsyslogd and makes sure that the kernel logger process is brought
+ up and down at the appropriate times
+- enhanced $IncludeConfig directive to support wildcard characters
+ (thanks to Michael Biebl)
+- all inputs are now implemented as loadable plugins
+- enhanced threading model: each input module now runs on its own thread
+- enhanced message queue which now supports different queueing methods
+ (among others, this can be used for performance fine-tuning)
+- added a large number of new configuration directives for the new
+ input modules
+- enhanced multi-threading utilizing a worker thread pool for the
+ main message queue
+- compilation without pthreads is no longer supported
+- much cleaner code due to new objects and removal of single-threading
+ mode
+---------------------------------------------------------------------------
+Version 2.0.1 STABLE (rgerhards), 2008-01-24
+- fixed a bug in integer conversion - but this function was never called,
+ so it is not really a useful bug fix ;)
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+---------------------------------------------------------------------------
+Version 2.0.0 STABLE (rgerhards), 2008-01-02
+- re-release of 1.21.2 as STABLE with no modifications except some
+ doc updates
+---------------------------------------------------------------------------
+Version 1.21.2 (rgerhards), 2007-12-28
+- created a gss-api output module. This keeps GSS-API code and
+ TCP/UDP code separated. It is also important for forward-
+ compatibility with v3. Please note that this change breaks compatibility
+ with config files created for 1.21.0 and 1.21.1 - this was considered
+ acceptable.
+- fixed an error in forwarding retry code (could lead to message corruption
+ but surfaced very seldom)
+- increased portability for older platforms (AI_NUMERICSERV moved)
+- removed socket leak in omfwd.c
+- cross-platform patch for GSS-API compile problem on some platforms
+ thanks to darix for the patch!
+---------------------------------------------------------------------------
+Version 1.21.1 (rgerhards), 2007-12-23
+- small doc fix for $IncludeConfig
+- fixed a bug in llDestroy()
+- bugfix: fixing memory leak when message queue is full and during
+ parsing. Thanks to varmojfekoj for the patch.
+- bugfix: when compiled without network support, unix sockets were
+ not properly closed
+- bugfix: memory leak in cfsysline.c/doGetWord() fixed
+---------------------------------------------------------------------------
+Version 1.21.0 (rgerhards), 2007-12-19
+- GSS-API support for syslog/TCP connections was added. Thanks to
+ varmojfekoj for providing the patch with this functionality
+- code cleanup
+- enhanced $IncludeConfig directive to support wildcard filenames
+- changed some multithreading synchronization
+---------------------------------------------------------------------------
+Version 1.20.1 (rgerhards), 2007-12-12
+- corrected a debug setting that survived release. Caused TCP connections
+ to be retried unnecessarily often.
+- When a hostname ACL was provided and DNS resolution for that name failed,
+ ACL processing was stopped at that point. Thanks to mildew for the patch.
+ Fedora Bugzilla: http://bugzilla.redhat.com/show_bug.cgi?id=395911
+- fixed a potential race condition, see link for details:
+ http://rgerhards.blogspot.com/2007/12/rsyslog-race-condition.html
+ Note that the probability of problems from this bug was very remote
+- fixed a memory leak that happened when PostgreSQL date formats were
+ used
+---------------------------------------------------------------------------
+Version 1.20.0 (rgerhards), 2007-12-07
+- an output module for postgres databases has been added. Thanks to
+ sur5r for contributing this code
+- unloading dynamic modules has been cleaned up, we now have a
+ real implementation and not just a dummy "good enough for the time
+ being".
+- enhanced platform independence - thanks to Bartosz Kuzma and Michael
+ Biebl for their very useful contributions
+- some general code cleanup (including warnings on 64 platforms, only)
+---------------------------------------------------------------------------
+Version 1.19.12 (rgerhards), 2007-12-03
+- cleaned up the build system (thanks to Michael Biebl for the patch)
+- fixed a bug where ommysql was still not compiled with -pthread option
+---------------------------------------------------------------------------
+Version 1.19.11 (rgerhards), 2007-11-29
+- applied -pthread option to build when building for multi-threading mode
+ hopefully solves an issue with segfaulting
+---------------------------------------------------------------------------
+Version 1.19.10 (rgerhards), 2007-10-19
+- introduced the new ":modulename:" syntax for calling module actions
+ in selector lines; modified ommysql to support it. This is primarily
+ an aid for further modules and a prerequisite to actually allow third
+ party modules to be created.
+- minor fix in slackware startup script, "-r 0" is now "-r0"
+- updated rsyslogd doc set man page; now in html format
+- undid creation of a separate thread for the main loop -- this did not
+ turn out to be needed or useful, so reduce complexity once again.
+- added doc fixes provided by Michael Biebl - thanks
+---------------------------------------------------------------------------
+Version 1.19.9 (rgerhards), 2007-10-12
+- now packaging system which again contains all components in a single
+ tarball
+- modularized main() a bit more, resulting in less complex code
+- experimentally added an additional thread - will see if that affects
+ the segfault bug we experience on some platforms. Note that this change
+ is scheduled to be removed again later.
+---------------------------------------------------------------------------
+Version 1.19.8 (rgerhards), 2007-09-27
+- improved repeated message processing
+- applied patch provided by varmojfekoj to support building ommysql
+ in its own way (now also resides in a plugin subdirectory);
+ ommysql is now a separate package
+- fixed a bug in cvthname() that lead to message loss if part
+ of the source hostname would have been dropped
+- created some support for distributing ommysql together with the
+ main rsyslog package. I need to re-think it in the future, but
+ for the time being the current mode is best. I now simply include
+ one additional tarball for ommysql inside the main distribution.
+ I look forward to user feedback on how this should be done best. In the
+ long term, a separate project should be spawend for ommysql, but I'd
+ like to do that only after the plugin interface is fully stable (what
+ it is not yet).
+---------------------------------------------------------------------------
+Version 1.19.7 (rgerhards), 2007-09-25
+- added code to handle situations where senders send us messages ending with
+ a NUL character. It is now simply removed. This also caused trailing LF
+ reduction to fail, when it was followed by such a NUL. This is now also
+ handled.
+- replaced some non-thread-safe function calls by their thread-safe
+ counterparts
+- fixed a minor memory leak that occurred when the %APPNAME% property was
+ used (I think nobody used that in practice)
+- fixed a bug that caused signal handlers in cvthname() not to be restored when
+ a malicious pointer record was detected and processing of the message been
+ stopped for that reason (this should be really rare and can not be related
+ to the segfault bug we are hunting).
+- fixed a bug in cvthname that lead to passing a wrong parameter - in
+ practice, this had no impact.
+- general code cleanup (e.g. compiler warnings, comments)
+---------------------------------------------------------------------------
+Version 1.19.6 (rgerhards), 2007-09-11
+- applied patch by varmojfekoj to change signal handling to the new
+ sigaction API set (replacing the depreciated signal() calls and its
+ friends.
+- fixed a bug that in --enable-debug mode caused an assertion when the
+ discard action was used
+- cleaned up compiler warnings
+- applied patch by varmojfekoj to FIX a bug that could cause
+ segfaults if empty properties were processed using modifying
+ options (e.g. space-cc, drop-cc)
+- fixed man bug: rsyslogd supports -l option
+---------------------------------------------------------------------------
+Version 1.19.5 (rgerhards), 2007-09-07
+- changed part of the CStr interface so that better error tracking
+ is provided and the calling sequence is more intuitive (there were
+ invalid calls based on a too-weird interface)
+- (hopefully) fixed some remaining bugs rooted in wrong use of
+ the CStr class. These could lead to program abort.
+- applied patch by varmojfekoj two fix two potential segfault situations
+- added $ModDir config directive
+- modified $ModLoad so that an absolute path may be specified as
+ module name (e.g. /rsyslog/ommysql.so)
+---------------------------------------------------------------------------
+Version 1.19.4 (rgerhards/varmojfekoj), 2007-09-04
+- fixed a number of small memory leaks - thanks varmojfekoj for patching
+- fixed an issue with CString class that could lead to rsyslog abort
+ in tplToString() - thanks varmojfekoj for patching
+- added a man-version of the config file documentation - thanks to Michel
+ Samia for providing the man file
+- fixed bug: a template like this causes an infinite loop:
+ $template opts,"%programname:::a,b%"
+ thanks varmojfekoj for the patch
+- fixed bug: case changing options crash freeing the string pointer
+ because they modify it: $template opts2,"%programname::1:lowercase%"
+ thanks varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 1.19.3 (mmeckelein/varmojfekoj), 2007-08-31
+- small mem leak fixed (after calling parseSelectorAct) - Thx varmojfekoj
+- documentation section "Regular File" und "Blocks" updated
+- solved an issue with dynamic file generation - Once again many thanks
+ to varmojfekoj
+- the negative selector for program name filter (Blocks) does not work as
+ expected - Thanks varmojfekoj for patching
+- added forwarding information to sysklogd (requires special template)
+ to config doc
+---------------------------------------------------------------------------
+Version 1.19.2 (mmeckelein/varmojfekoj), 2007-08-28
+- a specifically formed message caused a segfault - Many thanks varmojfekoj
+ for providing a patch
+- a typo and a weird condition are fixed in msg.c - Thanks again
+ varmojfekoj
+- on file creation the file was always owned by root:root. This is fixed
+ now - Thanks ypsa for solving this issue
+---------------------------------------------------------------------------
+Version 1.19.1 (mmeckelein), 2007-08-22
+- a bug that caused a high load when a TCP/UDP connection was closed is
+ fixed now - Thanks mildew for solving this issue
+- fixed a bug which caused a segfault on reinit - Thx varmojfekoj for the
+ patch
+- changed the hardcoded module path "/lib/rsyslog" to $(pkglibdir) in order
+ to avoid trouble e.g. on 64 bit platforms (/lib64) - many thanks Peter
+ Vrabec and darix, both provided a patch for solving this issue
+- enhanced the unloading of modules - thanks again varmojfekoj
+- applied a patch from varmojfekoj which fixes various little things in
+ MySQL output module
+---------------------------------------------------------------------------
+Version 1.19.0 (varmojfekoj/rgerhards), 2007-08-16
+- integrated patch from varmojfekoj to make the mysql module a loadable one
+ many thanks for the patch, MUCH appreciated
+---------------------------------------------------------------------------
+Version 1.18.2 (rgerhards), 2007-08-13
+- fixed a bug in outchannel code that caused templates to be incorrectly
+ parsed
+- fixed a bug in ommysql that caused a wrong ";template" missing message
+- added some code for unloading modules; not yet fully complete (and we do
+ not yet have loadable modules, so this is no problem)
+- removed debian subdirectory by request of a debian packager (this is a special
+ subdir for debian and there is also no point in maintaining it when there
+ is a debian package available - so I gladly did this) in some cases
+- improved overall doc quality (some pages were quite old) and linked to
+ more of the online resources.
+- improved /contrib/delete_mysql script by adding a host option and some
+ other minor modifications
+---------------------------------------------------------------------------
+Version 1.18.1 (rgerhards), 2007-08-08
+- applied a patch from varmojfekoj which solved a potential segfault
+ of rsyslogd on HUP
+- applied patch from Michel Samia to fix compilation when the pthreads
+ feature is disabled
+- some code cleanup (moved action object to its own file set)
+- add config directive $MainMsgQueueSize, which now allows one to configure the
+ queue size dynamically
+- all compile-time settings are now shown in rsyslogd -v, not just the
+ active ones
+- enhanced performance a little bit more
+- added config file directive $ActionResumeInterval
+- fixed a bug that prevented compilation under debian sid
+- added a contrib directory for user-contributed useful things
+---------------------------------------------------------------------------
+Version 1.18.0 (rgerhards), 2007-08-03
+- rsyslog now supports fallback actions when an action did not work. This
+ is a great feature e.g. for backup database servers or backup syslog
+ servers
+- modified rklogd to only change the console log level if -c is specified
+- added feature to use multiple actions inside a single selector
+- implemented $ActionExecOnlyWhenPreviousIsSuspended config directive
+- error messages during startup are now spit out to the configured log
+ destinations
+---------------------------------------------------------------------------
+Version 1.17.6 (rgerhards), 2007-08-01
+- continued to work on output module modularization - basic stage of
+ this work is now FINISHED
+- fixed bug in OMSRcreate() - always returned SR_RET_OK
+- fixed a bug that caused ommysql to always complain about missing
+ templates
+- fixed a mem leak in OMSRdestruct - freeing the object itself was
+ forgotten - thanks to varmojfekoj for the patch
+- fixed a memory leak in syslogd/init() that happened when the config
+ file could not be read - thanks to varmojfekoj for the patch
+- fixed insufficient memory allocation in addAction() and its helpers.
+ The initial fix and idea was developed by mildew, I fine-tuned
+ it a bit. Thanks a lot for the fix, I'd probably had pulled out my
+ hair to find the bug...
+- added output of config file line number when a parsing error occurred
+- fixed bug in objomsr.c that caused program to abort in debug mode with
+ an invalid assertion (in some cases)
+- fixed a typo that caused the default template for MySQL to be wrong.
+ thanks to mildew for catching this.
+- added configuration file command $DebugPrintModuleList and
+ $DebugPrintCfSysLineHandlerList
+- fixed an invalid value for the MARK timer - unfortunately, there was
+ a testing aid left in place. This resulted in quite frequent MARK messages
+- added $IncludeConfig config directive
+- applied a patch from mildew to prevent rsyslogd from freezing under heavy
+ load. This could happen when the queue was full. Now, we drop messages
+ but rsyslogd remains active.
+---------------------------------------------------------------------------
+Version 1.17.5 (rgerhards), 2007-07-30
+- continued to work on output module modularization
+- fixed a missing file bug - thanks to Andrea Montanari for reporting
+ this problem
+- fixed a problem with shutting down the worker thread and freeing the
+ selector_t list - this caused messages to be lost, because the
+ message queue was not properly drained before the selectors got
+ destroyed.
+---------------------------------------------------------------------------
+Version 1.17.4 (rgerhards), 2007-07-27
+- continued to work on output module modularization
+- fixed a situation where rsyslogd could create zombie processes
+ thanks to mildew for the patch
+- applied patch from Michel Samia to fix compilation when NOT
+ compiled for pthreads
+---------------------------------------------------------------------------
+Version 1.17.3 (rgerhards), 2007-07-25
+- continued working on output module modularization
+- fixed a bug that caused rsyslogd to segfault on exit (and
+ probably also on HUP), when there was an unsent message in a selector
+ that required forwarding and the dns lookup failed for that selector
+ (yes, it was pretty unlikely to happen;))
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed a memory leak in config file parsing and die()
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- rsyslogd now checks on startup if it is capable to perform any work
+ at all. If it cant, it complains and terminates
+ thanks to Michel Samia for providing the patch!
+- fixed a small memory leak when HUPing syslogd. The allowed sender
+ list now gets freed. thanks to mildew for the patch.
+- changed the way error messages in early startup are logged. They
+ now do no longer use the syslogd code directly but are rather
+ send to stderr.
+---------------------------------------------------------------------------
+Version 1.17.2 (rgerhards), 2007-07-23
+- made the port part of the -r option optional. Needed for backward
+ compatibility with sysklogd
+- replaced system() calls with something more reasonable. Please note that
+ this might break compatibility with some existing configuration files.
+ We accept this in favor of the gained security.
+- removed a memory leak that could occur if timegenerated was used in
+ RFC 3164 format in templates
+- did some preparation in msg.c for advanced multithreading - placed the
+ hooks, but not yet any active code
+- worked further on modularization
+- added $ModLoad MySQL (dummy) config directive
+- added DropTrailingLFOnReception config directive
+---------------------------------------------------------------------------
+Version 1.17.1 (rgerhards), 2007-07-20
+- fixed a bug that caused make install to install rsyslogd and rklogd under
+ the wrong names
+- fixed bug that caused $AllowedSenders to handle IPv6 scopes incorrectly;
+ also fixed but that could garble $AllowedSender wildcards. Thanks to
+ mildew@gmail.com for the patch
+- minor code cleanup - thanks to Peter Vrabec for the patch
+- fixed minimal memory leak on HUP (caused by templates)
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed another memory leak on HUPing and on exiting rsyslogd
+ again thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- code cleanup (removed compiler warnings)
+- fixed portability bug in configure.ac - thanks to Bartosz Kuźma for patch
+- moved msg object into its own file set
+- added the capability to continue trying to write log files when the
+ file system is full. Functionality based on patch by Martin Schulze
+ to sysklogd package.
+---------------------------------------------------------------------------
+Version 1.17.0 (RGer), 2007-07-17
+- added $RepeatedLineReduction config parameter
+- added $EscapeControlCharactersOnReceive config parameter
+- added $ControlCharacterEscapePrefix config parameter
+- added $DirCreateMode config parameter
+- added $CreateDirs config parameter
+- added $DebugPrintTemplateList config parameter
+- added $ResetConfigVariables config parameter
+- added $FileOwner config parameter
+- added $FileGroup config parameter
+- added $DirOwner config parameter
+- added $DirGroup config parameter
+- added $FailOnChownFailure config parameter
+- added regular expression support to the filter engine
+ thanks to Michel Samia for providing the patch!
+- enhanced $AllowedSender functionality. Credits to mildew@gmail.com for
+ the patch doing that
+ - added IPv6 support
+ - allowed DNS hostnames
+ - allowed DNS wildcard names
+- added new option $DropMsgsWithMaliciousDnsPTRRecords
+- added autoconf so that rfc3195d, rsyslogd and klogd are stored to /sbin
+- added capability to auto-create directories with dynaFiles
+---------------------------------------------------------------------------
+Version 1.16.0 (RGer/Peter Vrabec), 2007-07-13 - The Friday, 13th Release ;)
+- build system switched to autotools
+- removed SYSV preprocessor macro use, replaced with autotools equivalents
+- fixed a bug that caused rsyslogd to segfault when TCP listening was
+ disabled and it terminated
+- added new properties "syslogfacility-text" and "syslogseverity-text"
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- added the -x option to disable hostname dns resolution
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- begun to better modularize syslogd.c - this is an ongoing project; moved
+ type definitions to a separate file
+- removed some now-unused fields from struct filed
+- move file size limit fields in struct field to the "right spot" (the file
+ writing part of the union - f_un.f_file)
+- subdirectories linux and solaris are no longer part of the distribution
+ package. This is not because we cease support for them, but there are no
+ longer any files in them after the move to autotools
+---------------------------------------------------------------------------
+Version 1.15.1 (RGer), 2007-07-10
+- fixed a bug that caused a dynaFile selector to stall when there was
+ an open error with one file
+- improved template processing for dynaFiles; templates are now only
+ looked up during initialization - speeds up processing
+- optimized memory layout in struct filed when compiled with MySQL
+ support
+- fixed a bug that caused compilation without SYSLOG_INET to fail
+- re-enabled the "last message repeated n times" feature. This
+ feature was not taken care of while rsyslogd evolved from sysklogd
+ and it was more or less defunct. Now it is fully functional again.
+- added system properties: $NOW, $YEAR, $MONTH, $DAY, $HOUR, $MINUTE
+- fixed a bug in iovAsString() that caused a memory leak under stress
+ conditions (most probably memory shortage). This was unlikely to
+ ever happen, but it doesn't hurt doing it right
+- cosmetic: defined type "uchar", change all unsigned chars to uchar
+---------------------------------------------------------------------------
+Version 1.15.0 (RGer), 2007-07-05
+- added ability to dynamically generate file names based on templates
+ and thus properties. This was a much-requested feature. It makes
+ life easy when it e.g. comes to splitting files based on the sender
+ address.
+- added $umask and $FileCreateMode config file directives
+- applied a patch from Bartosz Kuzma to compile cleanly under NetBSD
+- checks for extra (unexpected) characters in system config file lines
+ have been added
+- added IPv6 documentation - was accidentally missing from CVS
+- begun to change char to unsigned char
+---------------------------------------------------------------------------
+Version 1.14.2 (RGer), 2007-07-03
+** this release fixes all known nits with IPv6 **
+- restored capability to do /etc/service lookup for "syslog"
+ service when -r 0 was given
+- documented IPv6 handling of syslog messages
+- integrate patch from Bartosz Kuźma to make rsyslog compile under
+ Solaris again (the patch replaced a strndup() call, which is not
+ available under Solaris
+- improved debug logging when waiting on select
+- updated rsyslogd man page with new options (-46A)
+---------------------------------------------------------------------------
+Version 1.14.1 (RGer/Peter Vrabec), 2007-06-29
+- added Peter Vrabec's patch for IPv6 TCP
+- prefixed all messages send to stderr in rsyslogd with "rsyslogd: "
+---------------------------------------------------------------------------
+Version 1.14.0 (RGer/Peter Vrabec), 2007-06-28
+- Peter Vrabec provided IPv6 for rsyslog, so we are now IPv6 enabled
+ IPv6 Support is currently for UDP only, TCP is to come soon.
+ AllowedSender configuration does not yet work for IPv6.
+- fixed code in iovCreate() that broke C's strict aliasing rules
+- fixed some char/unsigned char differences that forced the compiler
+ to spit out warning messages
+- updated the Red Hat init script to fix a known issue (thanks to
+ Peter Vrabec)
+---------------------------------------------------------------------------
+Version 1.13.5 (RGer), 2007-06-22
+- made the TCP session limit configurable via command line switch
+ now -t <port>,<max sessions>
+- added man page for rklogd(8) (basically a copy from klogd, but now
+ there is one...)
+- fixed a bug that caused internal messages (e.g. rsyslogd startup) to
+ appear without a tag.
+- removed a minor memory leak that occurred when TAG processing requalified
+ a HOSTNAME to be a TAG (and a TAG already was set).
+- removed potential small memory leaks in MsgSet***() functions. There
+ would be a leak if a property was re-set, something that happened
+ extremely seldom.
+---------------------------------------------------------------------------
+Version 1.13.4 (RGer), 2007-06-18
+- added a new property "PRI-text", which holds the PRI field in
+ textual form (e.g. "syslog.info")
+- added alias "syslogseverity" for "syslogpriority", which is a
+ misleading property name that needs to stay for historical
+ reasons (and backward-compatibility)
+- added doc on how to record PRI value in log file
+- enhanced signal handling in klogd, including removal of an unsafe
+ call to the logging system during signal handling
+---------------------------------------------------------------------------
+Version 1.13.3 (RGer), 2007-06-15
+- create a version of syslog.c from scratch. This is now
+ - highly optimized for rsyslog
+ - removes an incompatible license problem as the original
+ version had a BSD license with advertising clause
+ - fixed in the regard that rklogd will continue to work when
+ rsyslogd has been restarted (the original version, as well
+ as sysklogd, will remain silent then)
+ - solved an issue with an extra NUL char at message end that the
+ original version had
+- applied some changes to klogd to care for the new interface
+- fixed a bug in syslogd.c which prevented compiling under debian
+---------------------------------------------------------------------------
+Version 1.13.2 (RGer), 2007-06-13
+- lib order in makefile patched to facilitate static linking - thanks
+ to Bennett Todd for providing the patch
+- Integrated a patch from Peter Vrabec (pvrabec@redhat.com):
+ - added klogd under the name of rklogd (remove dependency on
+ original sysklogd package
+ - createDB.sql now in UTF
+ - added additional config files for use on Red Hat
+---------------------------------------------------------------------------
+Version 1.13.1 (RGer), 2007-02-05
+- changed the listen backlog limit to a more reasonable value based on
+ the maximum number of TCP connections configured (10% + 5) - thanks to Guy
+ Standen for the hint (actually, the limit was 5 and that was a
+ left-over from early testing).
+- fixed a bug in makefile which caused DB-support to be disabled when
+ NETZIP support was enabled
+- added the -e option to allow transmission of every message to remote
+ hosts (effectively turns off duplicate message suppression)
+- (somewhat) improved memory consumption when compiled with MySQL support
+- looks like we fixed an incompatibility with MySQL 5.x and above software
+ At least in one case, the remote server name was destroyed, leading to
+ a connection failure. The new, improved code does not have this issue and
+ so we see this as solved (the new code is generally somewhat better, so
+ there is a good chance we fixed this incompatibility).
+---------------------------------------------------------------------------
+Version 1.13.0 (RGer), 2006-12-19
+- added '$' as ToPos property replacer specifier - means "up to the
+ end of the string"
+- property replacer option "escape-cc", "drop-cc" and "space-cc" added
+- changed the handling of \0 characters inside syslog messages. We now
+ consistently escape them to "#000". This is somewhat recommended in
+ the draft-ietf-syslog-protocol-19 draft. While the real recommendation
+ is to not escape any characters at all, we can not do this without
+ considerable modification of the code. So we escape it to "#000", which
+ is consistent with a sample found in the Internet-draft.
+- removed message glue logic (see printchopped() comment for details)
+ Also caused removal of parts table and thus some improvements in
+ memory usage.
+- changed the default MAXLINE to 2048 to take care of recent syslog
+ standardization efforts (can easily be changed in syslogd.c)
+- added support for byte-counted TCP syslog messages (much like
+ syslog-transport-tls-05 Internet Draft). This was necessary to
+ support compression over TCP.
+- added support for receiving compressed syslog messages
+- added support for sending compressed syslog messages
+- fixed a bug where the last message in a syslog/tcp stream was
+ lost if it was not properly terminated by a LF character
+---------------------------------------------------------------------------
+Version 1.12.3 (RGer), 2006-10-04
+- implemented some changes to support Solaris (but support is not
+ yet complete)
+- commented out (via #if 0) some methods that are currently not being use
+ but should be kept for further us
+- added (interim) -u 1 option to turn off hostname and tag parsing
+- done some modifications to better support Fedora
+- made the field delimiter inside property replace configurable via
+ template
+- fixed a bug in property replacer: if fields were used, the delimitor
+ became part of the field. Up until now, this was barely noticeable as
+ the delimiter as TAB only and thus invisible to a human. With other
+ delimiters available now, it quickly showed up. This bug fix might cause
+ some grief to existing installations if they used the extra TAB for
+ whatever reasons - sorry folks... Anyhow, a solution is easy: just add
+ a TAB character constant into your template. Thus, there has no attempt
+ been made to do this in a backwards-compatible way.
+---------------------------------------------------------------------------
+Version 1.12.2 (RGer), 2006-02-15
+- fixed a bug in the RFC 3339 date formatter. An extra space was added
+ after the actual timestamp
+- added support for providing high-precision RFC3339 timestamps for
+ (rsyslogd-)internally-generated messages
+- very (!) experimental support for syslog-protocol internet draft
+ added (the draft is experimental, the code is solid ;))
+- added support for field-extracting in the property replacer
+- enhanced the legacy-syslog parser so that it can interpret messages
+ that do not contain a TIMESTAMP
+- fixed a bug that caused the default socket (usually /dev/log) to be
+ opened even when -o command line option was given
+- fixed a bug in the Debian sample startup script - it caused rsyslogd
+ to listen to remote requests, which it shouldn't by default
+---------------------------------------------------------------------------
+Version 1.12.1 (RGer), 2005-11-23
+- made multithreading work with BSD. Some signal-handling needed to be
+ restructured. Also, there might be a slight delay of up to 10 seconds
+ when huping and terminating rsyslogd under BSD
+- fixed a bug where a NULL-pointer was passed to printf() in logmsg().
+- fixed a bug during "make install" where rc3195d was not installed
+ Thanks to Bennett Todd for spotting this.
+- fixed a bug where rsyslogd dumped core when no TAG was found in the
+ received message
+- enhanced message parser so that it can deal with missing hostnames
+ in many cases (may not be totally fail-safe)
+- fixed a bug where internally-generated messages did not have the correct
+ TAG
+---------------------------------------------------------------------------
+Version 1.12.0 (RGer), 2005-10-26
+- moved to a multi-threaded design. single-threading is still optionally
+ available. Multi-threading is experimental!
+- fixed a potential race condition. In the original code, marking was done
+ by an alarm handler, which could lead to all sorts of bad things. This
+ has been changed now. See comments in syslogd.c/domark() for details.
+- improved debug output for property-based filters
+- not a code change, but: I have checked all exit()s to make sure that
+ none occurs once rsyslogd has started up. Even in unusual conditions
+ (like low-memory conditions) rsyslogd somehow remains active. Of course,
+ it might loose a message or two, but at least it does not abort and it
+ can also recover when the condition no longer persists.
+- fixed a bug that could cause loss of the last message received
+ immediately before rsyslogd was terminated.
+- added comments on thread-safety of global variables in syslogd.c
+- fixed a small bug: spurios printf() when TCP syslog was used
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug with regular expression support (thanks to Andres Riancho)
+- a little bit of code restructuring (especially main(), which was
+ horribly large)
+---------------------------------------------------------------------------
+Version 1.11.1 (RGer), 2005-10-19
+- support for BSD-style program name and host blocks
+- added a new property "programname" that can be used in templates
+- added ability to specify listen port for rfc3195d
+- fixed a bug that rendered the "startswith" comparison operation
+ unusable.
+- changed more functions to "static" storage class to help compiler
+ optimize (should have been static in the first place...)
+- fixed a potential memory leak in the string buffer class destructor.
+ As the destructor was previously never called, the leak did not actually
+ appear.
+- some internal restructuring in anticipation/preparation of minimal
+ multi-threading support
+- rsyslogd still shares some code with the sysklogd project. Some patches
+ for this shared code have been brought over from the sysklogd CVS.
+---------------------------------------------------------------------------
+Version 1.11.0 (RGer), 2005-10-12
+- support for receiving messages via RFC 3195; added rfc3195d for that
+ purpose
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+---------------------------------------------------------------------------
+Version 1.10.2 (RGer), 2005-09-27
+- added comparison operations in property-based filters:
+ * isequal
+ * startswith
+- added ability to negate all property-based filter comparison operations
+ by adding a !-sign right in front of the operation name
+- added the ability to specify remote senders for UDP and TCP
+ received messages. Allows to block all but well-known hosts
+- changed the $-config line directives to be case-INsensitive
+- new command line option -w added: "do not display warnings if messages
+ from disallowed senders are received"
+- fixed a bug that caused rsyslogd to dump core when the compare value
+ was not quoted in property-based filters
+- fixed a bug in the new CStr compare function which lead to invalid
+ results (fortunately, this function was not yet used widely)
+- added better support for "debugging" rsyslog.conf property filters
+ (only if -d switch is given)
+- changed some function definitions to static, which eventually enables
+ some compiler optimizations
+- fixed a bug in MySQL code; when a SQL error occurred, rsyslogd could
+ run in a tight loop. This was due to invalid sequence of error reporting
+ and is now fixed.
+---------------------------------------------------------------------------
+Version 1.10.1 (RGer), 2005-09-23
+- added the ability to execute a shell script as an action.
+ Thanks to Bjoern Kalkbrenner for providing the code!
+- fixed a bug in the MySQL code; due to the bug the automatic one-time
+ retry after an error did not happen - this lead to error message in
+ cases where none should be seen (e.g. after a MySQL restart)
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.10.0 (RGer), 2005-09-20
+ REMINDER: 1.10 is the first unstable version if the 1.x series!
+- added the capability to filter on any property in selector lines
+ (not just facility and priority)
+- changed stringbuf into a new counted string class
+- added support for a "discard" action. If a selector line with
+ discard (~ character) is found, no selector lines *after* that
+ line will be processed.
+- thanks to Andres Riancho, regular expression support has been
+ added to the template engine
+- added the FROMHOST property in the template processor, which could
+ previously not be obtained. Thanks to Cristian Testa for pointing
+ this out and even providing a fix.
+- added display of compile-time options to -v output
+- performance improvement for production build - made some checks
+ to happen only during debug mode
+- fixed a problem with compiling on SUSE and - while doing so - removed
+ the socket call to set SO_BSDCOMPAT in cases where it is obsolete.
+---------------------------------------------------------------------------
+Version 1.0.4 (RGer), 2006-02-01
+- a small but important fix: the tcp receiver had two forgotten printf's
+ in it that caused a lot of unnecessary output to stdout. This was
+ important enough to justify a new release
+---------------------------------------------------------------------------
+Version 1.0.3 (RGer), 2005-11-14
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+- applied some patches available from the sysklogd project to code
+ shared from there
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug in the TCP sender that caused the retry logic to fail
+ after an error or receiver overrun
+- fixed a bug in init() that could lead to dumping core
+- fixed a bug that could lead to dumping core when no HOSTNAME or no TAG
+ was present in the syslog message
+---------------------------------------------------------------------------
+Version 1.0.2 (RGer), 2005-10-05
+- fixed an issue with MySQL error reporting. When an error occurred,
+ the MySQL driver went into an endless loop (at least in most cases).
+---------------------------------------------------------------------------
+Version 1.0.1 (RGer), 2005-09-23
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.0.0 (RGer), 2005-09-12
+- changed install doc to cover daily cron scripts - a trouble source
+- added rc script for slackware (provided by Chris Elvidge - thanks!)
+- fixed a really minor bug in usage() - the -r option was still
+ reported as without the port parameter
+---------------------------------------------------------------------------
+Version 0.9.8 (RGer), 2005-09-05
+- made startup and shutdown message more consistent and included the
+ pid, so that they can be easier correlated. Used syslog-protocol
+ structured data format for this purpose.
+- improved config info in startup message, now tells not only
+ if it is listening remote on udp, but also for tcp. Also includes
+ the port numbers. The previous startup message was misleading, because
+ it did not say "remote reception" if rsyslogd was only listening via
+ tcp (but not via udp).
+- added a "how can you help" document to the doc set
+---------------------------------------------------------------------------
+Version 0.9.7 (RGer), 2005-08-15
+- some of the previous doc files (like INSTALL) did not properly
+ reflect the changes to the build process and the new doc. Fixed
+ that.
+- changed syslogd.c so that when compiled without database support,
+ an error message is displayed when a database action is detected
+ in the config file (previously this was used as an user rule ;))
+- fixed a bug in the os-specific Makefiles which caused MySQL
+ support to not be compiled, even if selected
+---------------------------------------------------------------------------
+Version 0.9.6 (RGer), 2005-08-09
+- greatly enhanced documentation. Now available in html format in
+ the "doc" folder and FreeBSD. Finally includes an install howto.
+- improved MySQL error messages a little - they now show up as log
+ messages, too (formerly only in debug mode)
+- added the ability to specify the listen port for udp syslog.
+ WARNING: This introduces an incompatibility. Formerly, udp
+ syslog was enabled by the -r command line option. Now, it is
+ "-r [port]", which is consistent with the tcp listener. However,
+ just -r will now return an error message.
+- added sample startup scripts for Debian and FreeBSD
+- added support for easy feature selection in the makefile. Un-
+ fortunately, this also means I needed to spilt the make file
+ for different OS and distros. There are some really bad syntax
+ differences between FreeBSD and Linux make.
+---------------------------------------------------------------------------
+Version 0.9.5 (RGer), 2005-08-01
+- the "semicolon bug" was actually not (fully) solved in 0.9.4. One
+ part of the bug was solved, but another still existed. This one
+ is fixed now, too.
+- the "semicolon bug" actually turned out to be a more generic bug.
+ It appeared whenever an invalid template name was given. With some
+ selector actions, rsyslogd dumped core, with other it "just" had
+ a small resource leak with others all worked well. These anomalies
+ are now fixed. Note that they only appeared during system initialization
+ once the system was running, nothing bad happened.
+- improved error reporting for template errors on startup. They are now
+ shown on the console and the start-up tty. Formerly, they were only
+ visible in debug mode.
+- support for multiple instances of rsyslogd on a single machine added
+- added new option "-o" --> omit local unix domain socket. This option
+ enables rsyslogd NOT to listen to the local socket. This is most
+ helpful when multiple instances of rsyslogd (or rsyslogd and another
+ syslogd) shall run on a single system.
+- added new option "-i <pidfile>" which allows one to specify the pidfile.
+ This is needed when multiple instances of rsyslogd are to be run.
+- the new project home page is now online at www.rsyslog.com
+---------------------------------------------------------------------------
+Version 0.9.4 (RGer), 2005-07-25
+- finally added the TCP sender. It now supports non-blocking mode, no
+ longer disabling message reception during connect. As it is now, it
+ is usable in production. The code could be more sophisticated, but
+ I've kept it short in anticipation of the move to liblogging, which
+ will lead to the removal of the code just written ;)
+- the "exiting on signal..." message still had the "syslogd" name in
+ it. Changed this to "rsyslogd", as we do not have a large user base
+ yet, this should pose no problem.
+- fixed "the semicolon" bug. rsyslogd dumped core if a write-db action
+ was specified but no semicolon was given after the password (an empty
+ template was ok, but the semicolon needed to be present).
+- changed a default for traditional output format. During testing, it
+ was seen that the timestamp written to file in default format was
+ the time of message reception, not the time specified in the TIMESTAMP
+ field of the message itself. Traditionally, the message TIMESTAMP is
+ used and this has been changed now.
+---------------------------------------------------------------------------
+Version 0.9.3 (RGer), 2005-07-19
+- fixed a bug in the message parser. In June, the RFC 3164 timestamp
+ was not correctly parsed (yes, only in June and some other months,
+ see the code comment to learn why...)
+- added the ability to specify the destination port when forwarding
+ syslog messages (both for TCP and UDP)
+- added an very experimental TCP sender (activated by
+ @@machine:port in config). This is not yet for production use. If
+ the receiver is not alive, rsyslogd will wait quite some time until
+ the connection request times out, which most probably leads to
+ loss of incoming messages.
+
+---------------------------------------------------------------------------
+Version 0.9.2 (RGer), around 2005-07-06
+- I intended to change the maxsupported message size to 32k to
+ support IHE - but given the memory inefficiency in the usual use
+ cases, I have not done this. I have, however, included very
+ specific instructions on how to do this in the source code. I have
+ also done some testing with 32k messages, so you can change the
+ max size without taking too much risk.
+- added a syslog/tcp receiver; we now can receive messages via
+ plain tcp, but we can still send only via UDP. The syslog/tcp
+ receiver is the primary enhancement of this release.
+- slightly changed some error messages that contained a spurios \n at
+ the end of the line (which gives empty lines in your log...)
+
+---------------------------------------------------------------------------
+Version 0.9.1 (RGer)
+- fixed code so that it compiles without errors under FreeBSD
+- removed now unused function "allocate_log()" from syslogd.c
+- changed the make file so that it contains more defines for
+ different environments (in the long term, we need a better
+ system for disabling/enabling features...)
+- changed some printf's printing off_t types to %lld and
+ explicit (long long) casts. I tried to figure out the exact type,
+ but did not succeed in this. In the worst case, ultra-large peta-
+ byte files will now display funny informational messages on rollover,
+ something I think we can live with for the neersion 3.11.2 (rgerhards), 2008-02-??
+---------------------------------------------------------------------------
+Version 3.11.1 (rgerhards), 2008-02-12
+- SNMP trap sender added thanks to Andre Lorbach (omsnmp)
+- added input-plugin interface specification in form of a (copy) template
+ input module
+- applied documentation fix by Michael Biebl -- many thanks!
+- bugfix: immark did not have MARK flags set...
+- added x-info field to rsyslogd startup/shutdown message. Hopefully
+ points users to right location for further info (many don't even know
+ they run rsyslog ;))
+- bugfix: trailing ":" of tag was lost while parsing legacy syslog messages
+ without timestamp - thanks to Anders Blomdell for providing a patch!
+- fixed a bug in stringbuf.c related to STRINGBUF_TRIM_ALLOCSIZE, which
+ wasn't supposed to be used with rsyslog. Put a warning message up that
+ tells this feature is not tested and probably not worth the effort.
+ Thanks to Anders Blomdell fro bringing this to our attention
+- somewhat improved performance of string buffers
+- fixed bug that caused invalid treatment of tabs (HT) in rsyslog.conf
+- bugfix: setting for $EscapeControlCharactersOnReceive was not
+ properly initialized
+- clarified usage of space-cc property replacer option
+- improved abort diagnostic handler
+- some initial effort for malloc/free runtime debugging support
+- bugfix: using dynafile actions caused rsyslogd abort
+- fixed minor man errors thanks to Michael Biebl
+---------------------------------------------------------------------------
+Version 3.11.0 (rgerhards), 2008-01-31
+- implemented queued actions
+- implemented simple rate limiting for actions
+- implemented deliberate discarding of lower priority messages over higher
+ priority ones when a queue runs out of space
+- implemented disk quotas for disk queues
+- implemented the $ActionResumeRetryCount config directive
+- added $ActionQueueFilename config directive
+- added $ActionQueueSize config directive
+- added $ActionQueueHighWaterMark config directive
+- added $ActionQueueLowWaterMark config directive
+- added $ActionQueueDiscardMark config directive
+- added $ActionQueueDiscardSeverity config directive
+- added $ActionQueueCheckpointInterval config directive
+- added $ActionQueueType config directive
+- added $ActionQueueWorkerThreads config directive
+- added $ActionQueueTimeoutshutdown config directive
+- added $ActionQueueTimeoutActionCompletion config directive
+- added $ActionQueueTimeoutenQueue config directive
+- added $ActionQueueTimeoutworkerThreadShutdown config directive
+- added $ActionQueueWorkerThreadMinimumMessages config directive
+- added $ActionQueueMaxFileSize config directive
+- added $ActionQueueSaveonShutdown config directive
+- addded $ActionQueueDequeueSlowdown config directive
+- addded $MainMsgQueueDequeueSlowdown config directive
+- bugfix: added forgotten docs to package
+- improved debugging support
+- fixed a bug that caused $MainMsgQueueCheckpointInterval to work incorrectly
+- when a long-running action needs to be cancelled on shutdown, the message
+ that was processed by it is now preserved. This finishes support for
+ guaranteed delivery of messages (if the output supports it, of course)
+- fixed bug in output module interface, see
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1881008&group_id=123448&atid=696552
+- changed the ommysql output plugin so that the (lengthy) connection
+ initialization now takes place in message processing. This works much
+ better with the new queued action mode (fast startup)
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+- bugfixed stream class offset handling on 32bit platforms
+---------------------------------------------------------------------------
+Version 3.10.3 (rgerhards), 2008-01-28
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- run-time instrumentation added
+- implemented disk-assisted queue mode, which enables on-demand disk
+ spooling if the queue's in-memory queue is exhausted
+- implemented a dynamic worker thread pool for processing incoming
+ messages; workers are started and shut down as need arises
+- implemented a run-time instrumentation debug package
+- implemented the $MainMsgQueueSaveOnShutdown config directive
+- implemented the $MainMsgQueueWorkerThreadMinimumMessages config directive
+- implemented the $MainMsgQueueTimeoutWorkerThreadShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.2 (rgerhards), 2008-01-14
+- added the ability to keep stop rsyslogd without the need to drain
+ the main message queue. In disk queue mode, rsyslog continues to
+ run from the point where it stopped. In case of a system failure, it
+ continues to process messages from the last checkpoint.
+- fixed a bug that caused a segfault on startup when no $WorkDir directive
+ was specified in rsyslog.conf
+- provided more fine-grain control over shutdown timeouts and added a
+ way to specify the enqueue timeout when the main message queue is full
+- implemented $MainMsgQueueCheckpointInterval config directive
+- implemented $MainMsgQueueTimeoutActionCompletion config directive
+- implemented $MainMsgQueueTimeoutEnqueue config directive
+- implemented $MainMsgQueueTimeoutShutdown config directive
+---------------------------------------------------------------------------
+Version 3.10.1 (rgerhards), 2008-01-10
+- implemented the "disk" queue mode. However, it currently is of very
+ limited use, because it does not support persistence over rsyslogd
+ runs. So when rsyslogd is stopped, the queue is drained just as with
+ the in-memory queue modes. Persistent queues will be a feature of
+ the next release.
+- performance-optimized string class, should bring an overall improvement
+- fixed a memory leak in imudp -- thanks to varmojfekoj for the patch
+- fixed a race condition that could lead to a rsyslogd hang when during
+ HUP or termination
+- done some doc updates
+- added $WorkDirectory config directive
+- added $MainMsgQueueFileName config directive
+- added $MainMsgQueueMaxFileSize config directive
+---------------------------------------------------------------------------
+Version 3.10.0 (rgerhards), 2008-01-07
+- implemented input module interface and initial input modules
+- enhanced threading for input modules (each on its own thread now)
+- ability to bind UDP listeners to specific local interfaces/ports and
+ ability to run multiple of them concurrently
+- added ability to specify listen IP address for UDP syslog server
+- license changed to GPLv3
+- mark messages are now provided by loadble module immark
+- rklogd is no longer provided. Its functionality has now been taken over
+ by imklog, a loadable input module. This offers a much better integration
+ into rsyslogd and makes sure that the kernel logger process is brought
+ up and down at the appropriate times
+- enhanced $IncludeConfig directive to support wildcard characters
+ (thanks to Michael Biebl)
+- all inputs are now implemented as loadable plugins
+- enhanced threading model: each input module now runs on its own thread
+- enhanced message queue which now supports different queueing methods
+ (among others, this can be used for performance fine-tuning)
+- added a large number of new configuration directives for the new
+ input modules
+- enhanced multi-threading utilizing a worker thread pool for the
+ main message queue
+- compilation without pthreads is no longer supported
+- much cleaner code due to new objects and removal of single-threading
+ mode
+---------------------------------------------------------------------------
+Version 2.0.1 STABLE (rgerhards), 2008-01-24
+- fixed a bug in integer conversion - but this function was never called,
+ so it is not really a useful bug fix ;)
+- fixed a bug with standard template definitions (not a big deal) - thanks
+ to varmojfekoj for spotting it
+- fixed a bug that caused a potential hang in file and fwd output module
+ varmojfekoj provided the patch - many thanks!
+---------------------------------------------------------------------------
+Version 2.0.0 STABLE (rgerhards), 2008-01-02
+- re-release of 1.21.2 as STABLE with no modifications except some
+ doc updates
+---------------------------------------------------------------------------
+Version 1.21.2 (rgerhards), 2007-12-28
+- created a gss-api output module. This keeps GSS-API code and
+ TCP/UDP code separated. It is also important for forward-
+ compatibility with v3. Please note that this change breaks compatibility
+ with config files created for 1.21.0 and 1.21.1 - this was considered
+ acceptable.
+- fixed an error in forwarding retry code (could lead to message corruption
+ but surfaced very seldom)
+- increased portability for older platforms (AI_NUMERICSERV moved)
+- removed socket leak in omfwd.c
+- cross-platform patch for GSS-API compile problem on some platforms
+ thanks to darix for the patch!
+---------------------------------------------------------------------------
+Version 1.21.1 (rgerhards), 2007-12-23
+- small doc fix for $IncludeConfig
+- fixed a bug in llDestroy()
+- bugfix: fixing memory leak when message queue is full and during
+ parsing. Thanks to varmojfekoj for the patch.
+- bugfix: when compiled without network support, unix sockets were
+ not properly closed
+- bugfix: memory leak in cfsysline.c/doGetWord() fixed
+---------------------------------------------------------------------------
+Version 1.21.0 (rgerhards), 2007-12-19
+- GSS-API support for syslog/TCP connections was added. Thanks to
+ varmojfekoj for providing the patch with this functionality
+- code cleanup
+- enhanced $IncludeConfig directive to support wildcard filenames
+- changed some multithreading synchronization
+---------------------------------------------------------------------------
+Version 1.20.1 (rgerhards), 2007-12-12
+- corrected a debug setting that survived release. Caused TCP connections
+ to be retried unnecessarily often.
+- When a hostname ACL was provided and DNS resolution for that name failed,
+ ACL processing was stopped at that point. Thanks to mildew for the patch.
+ Fedora Bugzilla: http://bugzilla.redhat.com/show_bug.cgi?id=395911
+- fixed a potential race condition, see link for details:
+ http://rgerhards.blogspot.com/2007/12/rsyslog-race-condition.html
+ Note that the probability of problems from this bug was very remote
+- fixed a memory leak that happened when PostgreSQL date formats were
+ used
+---------------------------------------------------------------------------
+Version 1.20.0 (rgerhards), 2007-12-07
+- an output module for postgres databases has been added. Thanks to
+ sur5r for contributing this code
+- unloading dynamic modules has been cleaned up, we now have a
+ real implementation and not just a dummy "good enough for the time
+ being".
+- enhanced platform independence - thanks to Bartosz Kuzma and Michael
+ Biebl for their very useful contributions
+- some general code cleanup (including warnings on 64 platforms, only)
+---------------------------------------------------------------------------
+Version 1.19.12 (rgerhards), 2007-12-03
+- cleaned up the build system (thanks to Michael Biebl for the patch)
+- fixed a bug where ommysql was still not compiled with -pthread option
+---------------------------------------------------------------------------
+Version 1.19.11 (rgerhards), 2007-11-29
+- applied -pthread option to build when building for multi-threading mode
+ hopefully solves an issue with segfaulting
+---------------------------------------------------------------------------
+Version 1.19.10 (rgerhards), 2007-10-19
+- introduced the new ":modulename:" syntax for calling module actions
+ in selector lines; modified ommysql to support it. This is primarily
+ an aid for further modules and a prerequisite to actually allow third
+ party modules to be created.
+- minor fix in slackware startup script, "-r 0" is now "-r0"
+- updated rsyslogd doc set man page; now in html format
+- undid creation of a separate thread for the main loop -- this did not
+ turn out to be needed or useful, so reduce complexity once again.
+- added doc fixes provided by Michael Biebl - thanks
+---------------------------------------------------------------------------
+Version 1.19.9 (rgerhards), 2007-10-12
+- now packaging system which again contains all components in a single
+ tarball
+- modularized main() a bit more, resulting in less complex code
+- experimentally added an additional thread - will see if that affects
+ the segfault bug we experience on some platforms. Note that this change
+ is scheduled to be removed again later.
+---------------------------------------------------------------------------
+Version 1.19.8 (rgerhards), 2007-09-27
+- improved repeated message processing
+- applied patch provided by varmojfekoj to support building ommysql
+ in its own way (now also resides in a plugin subdirectory);
+ ommysql is now a separate package
+- fixed a bug in cvthname() that lead to message loss if part
+ of the source hostname would have been dropped
+- created some support for distributing ommysql together with the
+ main rsyslog package. I need to re-think it in the future, but
+ for the time being the current mode is best. I now simply include
+ one additional tarball for ommysql inside the main distribution.
+ I look forward to user feedback on how this should be done best. In the
+ long term, a separate project should be spawend for ommysql, but I'd
+ like to do that only after the plugin interface is fully stable (what
+ it is not yet).
+---------------------------------------------------------------------------
+Version 1.19.7 (rgerhards), 2007-09-25
+- added code to handle situations where senders send us messages ending with
+ a NUL character. It is now simply removed. This also caused trailing LF
+ reduction to fail, when it was followed by such a NUL. This is now also
+ handled.
+- replaced some non-thread-safe function calls by their thread-safe
+ counterparts
+- fixed a minor memory leak that occurred when the %APPNAME% property was
+ used (I think nobody used that in practice)
+- fixed a bug that caused signal handlers in cvthname() not to be restored when
+ a malicious pointer record was detected and processing of the message been
+ stopped for that reason (this should be really rare and can not be related
+ to the segfault bug we are hunting).
+- fixed a bug in cvthname that lead to passing a wrong parameter - in
+ practice, this had no impact.
+- general code cleanup (e.g. compiler warnings, comments)
+---------------------------------------------------------------------------
+Version 1.19.6 (rgerhards), 2007-09-11
+- applied patch by varmojfekoj to change signal handling to the new
+ sigaction API set (replacing the depreciated signal() calls and its
+ friends.
+- fixed a bug that in --enable-debug mode caused an assertion when the
+ discard action was used
+- cleaned up compiler warnings
+- applied patch by varmojfekoj to FIX a bug that could cause
+ segfaults if empty properties were processed using modifying
+ options (e.g. space-cc, drop-cc)
+- fixed man bug: rsyslogd supports -l option
+---------------------------------------------------------------------------
+Version 1.19.5 (rgerhards), 2007-09-07
+- changed part of the CStr interface so that better error tracking
+ is provided and the calling sequence is more intuitive (there were
+ invalid calls based on a too-weird interface)
+- (hopefully) fixed some remaining bugs rooted in wrong use of
+ the CStr class. These could lead to program abort.
+- applied patch by varmojfekoj two fix two potential segfault situations
+- added $ModDir config directive
+- modified $ModLoad so that an absolute path may be specified as
+ module name (e.g. /rsyslog/ommysql.so)
+---------------------------------------------------------------------------
+Version 1.19.4 (rgerhards/varmojfekoj), 2007-09-04
+- fixed a number of small memory leaks - thanks varmojfekoj for patching
+- fixed an issue with CString class that could lead to rsyslog abort
+ in tplToString() - thanks varmojfekoj for patching
+- added a man-version of the config file documentation - thanks to Michel
+ Samia for providing the man file
+- fixed bug: a template like this causes an infinite loop:
+ $template opts,"%programname:::a,b%"
+ thanks varmojfekoj for the patch
+- fixed bug: case changing options crash freeing the string pointer
+ because they modify it: $template opts2,"%programname::1:lowercase%"
+ thanks varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 1.19.3 (mmeckelein/varmojfekoj), 2007-08-31
+- small mem leak fixed (after calling parseSelectorAct) - Thx varmojfekoj
+- documentation section "Regular File" und "Blocks" updated
+- solved an issue with dynamic file generation - Once again many thanks
+ to varmojfekoj
+- the negative selector for program name filter (Blocks) does not work as
+ expected - Thanks varmojfekoj for patching
+- added forwarding information to sysklogd (requires special template)
+ to config doc
+---------------------------------------------------------------------------
+Version 1.19.2 (mmeckelein/varmojfekoj), 2007-08-28
+- a specifically formed message caused a segfault - Many thanks varmojfekoj
+ for providing a patch
+- a typo and a weird condition are fixed in msg.c - Thanks again
+ varmojfekoj
+- on file creation the file was always owned by root:root. This is fixed
+ now - Thanks ypsa for solving this issue
+---------------------------------------------------------------------------
+Version 1.19.1 (mmeckelein), 2007-08-22
+- a bug that caused a high load when a TCP/UDP connection was closed is
+ fixed now - Thanks mildew for solving this issue
+- fixed a bug which caused a segfault on reinit - Thx varmojfekoj for the
+ patch
+- changed the hardcoded module path "/lib/rsyslog" to $(pkglibdir) in order
+ to avoid trouble e.g. on 64 bit platforms (/lib64) - many thanks Peter
+ Vrabec and darix, both provided a patch for solving this issue
+- enhanced the unloading of modules - thanks again varmojfekoj
+- applied a patch from varmojfekoj which fixes various little things in
+ MySQL output module
+---------------------------------------------------------------------------
+Version 1.19.0 (varmojfekoj/rgerhards), 2007-08-16
+- integrated patch from varmojfekoj to make the mysql module a loadable one
+ many thanks for the patch, MUCH appreciated
+---------------------------------------------------------------------------
+Version 1.18.2 (rgerhards), 2007-08-13
+- fixed a bug in outchannel code that caused templates to be incorrectly
+ parsed
+- fixed a bug in ommysql that caused a wrong ";template" missing message
+- added some code for unloading modules; not yet fully complete (and we do
+ not yet have loadable modules, so this is no problem)
+- removed debian subdirectory by request of a debian packager (this is a special
+ subdir for debian and there is also no point in maintaining it when there
+ is a debian package available - so I gladly did this) in some cases
+- improved overall doc quality (some pages were quite old) and linked to
+ more of the online resources.
+- improved /contrib/delete_mysql script by adding a host option and some
+ other minor modifications
+---------------------------------------------------------------------------
+Version 1.18.1 (rgerhards), 2007-08-08
+- applied a patch from varmojfekoj which solved a potential segfault
+ of rsyslogd on HUP
+- applied patch from Michel Samia to fix compilation when the pthreads
+ feature is disabled
+- some code cleanup (moved action object to its own file set)
+- add config directive $MainMsgQueueSize, which now allows one to configure the
+ queue size dynamically
+- all compile-time settings are now shown in rsyslogd -v, not just the
+ active ones
+- enhanced performance a little bit more
+- added config file directive $ActionResumeInterval
+- fixed a bug that prevented compilation under debian sid
+- added a contrib directory for user-contributed useful things
+---------------------------------------------------------------------------
+Version 1.18.0 (rgerhards), 2007-08-03
+- rsyslog now supports fallback actions when an action did not work. This
+ is a great feature e.g. for backup database servers or backup syslog
+ servers
+- modified rklogd to only change the console log level if -c is specified
+- added feature to use multiple actions inside a single selector
+- implemented $ActionExecOnlyWhenPreviousIsSuspended config directive
+- error messages during startup are now spit out to the configured log
+ destinations
+---------------------------------------------------------------------------
+Version 1.17.6 (rgerhards), 2007-08-01
+- continued to work on output module modularization - basic stage of
+ this work is now FINISHED
+- fixed bug in OMSRcreate() - always returned SR_RET_OK
+- fixed a bug that caused ommysql to always complain about missing
+ templates
+- fixed a mem leak in OMSRdestruct - freeing the object itself was
+ forgotten - thanks to varmojfekoj for the patch
+- fixed a memory leak in syslogd/init() that happened when the config
+ file could not be read - thanks to varmojfekoj for the patch
+- fixed insufficient memory allocation in addAction() and its helpers.
+ The initial fix and idea was developed by mildew, I fine-tuned
+ it a bit. Thanks a lot for the fix, I'd probably had pulled out my
+ hair to find the bug...
+- added output of config file line number when a parsing error occurred
+- fixed bug in objomsr.c that caused program to abort in debug mode with
+ an invalid assertion (in some cases)
+- fixed a typo that caused the default template for MySQL to be wrong.
+ thanks to mildew for catching this.
+- added configuration file command $DebugPrintModuleList and
+ $DebugPrintCfSysLineHandlerList
+- fixed an invalid value for the MARK timer - unfortunately, there was
+ a testing aid left in place. This resulted in quite frequent MARK messages
+- added $IncludeConfig config directive
+- applied a patch from mildew to prevent rsyslogd from freezing under heavy
+ load. This could happen when the queue was full. Now, we drop messages
+ but rsyslogd remains active.
+---------------------------------------------------------------------------
+Version 1.17.5 (rgerhards), 2007-07-30
+- continued to work on output module modularization
+- fixed a missing file bug - thanks to Andrea Montanari for reporting
+ this problem
+- fixed a problem with shutting down the worker thread and freeing the
+ selector_t list - this caused messages to be lost, because the
+ message queue was not properly drained before the selectors got
+ destroyed.
+---------------------------------------------------------------------------
+Version 1.17.4 (rgerhards), 2007-07-27
+- continued to work on output module modularization
+- fixed a situation where rsyslogd could create zombie processes
+ thanks to mildew for the patch
+- applied patch from Michel Samia to fix compilation when NOT
+ compiled for pthreads
+---------------------------------------------------------------------------
+Version 1.17.3 (rgerhards), 2007-07-25
+- continued working on output module modularization
+- fixed a bug that caused rsyslogd to segfault on exit (and
+ probably also on HUP), when there was an unsent message in a selector
+ that required forwarding and the dns lookup failed for that selector
+ (yes, it was pretty unlikely to happen;))
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed a memory leak in config file parsing and die()
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- rsyslogd now checks on startup if it is capable to perform any work
+ at all. If it cant, it complains and terminates
+ thanks to Michel Samia for providing the patch!
+- fixed a small memory leak when HUPing syslogd. The allowed sender
+ list now gets freed. thanks to mildew for the patch.
+- changed the way error messages in early startup are logged. They
+ now do no longer use the syslogd code directly but are rather
+ send to stderr.
+---------------------------------------------------------------------------
+Version 1.17.2 (rgerhards), 2007-07-23
+- made the port part of the -r option optional. Needed for backward
+ compatibility with sysklogd
+- replaced system() calls with something more reasonable. Please note that
+ this might break compatibility with some existing configuration files.
+ We accept this in favor of the gained security.
+- removed a memory leak that could occur if timegenerated was used in
+ RFC 3164 format in templates
+- did some preparation in msg.c for advanced multithreading - placed the
+ hooks, but not yet any active code
+- worked further on modularization
+- added $ModLoad MySQL (dummy) config directive
+- added DropTrailingLFOnReception config directive
+---------------------------------------------------------------------------
+Version 1.17.1 (rgerhards), 2007-07-20
+- fixed a bug that caused make install to install rsyslogd and rklogd under
+ the wrong names
+- fixed bug that caused $AllowedSenders to handle IPv6 scopes incorrectly;
+ also fixed but that could garble $AllowedSender wildcards. Thanks to
+ mildew@gmail.com for the patch
+- minor code cleanup - thanks to Peter Vrabec for the patch
+- fixed minimal memory leak on HUP (caused by templates)
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed another memory leak on HUPing and on exiting rsyslogd
+ again thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- code cleanup (removed compiler warnings)
+- fixed portability bug in configure.ac - thanks to Bartosz Kuźma for patch
+- moved msg object into its own file set
+- added the capability to continue trying to write log files when the
+ file system is full. Functionality based on patch by Martin Schulze
+ to sysklogd package.
+---------------------------------------------------------------------------
+Version 1.17.0 (RGer), 2007-07-17
+- added $RepeatedLineReduction config parameter
+- added $EscapeControlCharactersOnReceive config parameter
+- added $ControlCharacterEscapePrefix config parameter
+- added $DirCreateMode config parameter
+- added $CreateDirs config parameter
+- added $DebugPrintTemplateList config parameter
+- added $ResetConfigVariables config parameter
+- added $FileOwner config parameter
+- added $FileGroup config parameter
+- added $DirOwner config parameter
+- added $DirGroup config parameter
+- added $FailOnChownFailure config parameter
+- added regular expression support to the filter engine
+ thanks to Michel Samia for providing the patch!
+- enhanced $AllowedSender functionality. Credits to mildew@gmail.com for
+ the patch doing that
+ - added IPv6 support
+ - allowed DNS hostnames
+ - allowed DNS wildcard names
+- added new option $DropMsgsWithMaliciousDnsPTRRecords
+- added autoconf so that rfc3195d, rsyslogd and klogd are stored to /sbin
+- added capability to auto-create directories with dynaFiles
+---------------------------------------------------------------------------
+Version 1.16.0 (RGer/Peter Vrabec), 2007-07-13 - The Friday, 13th Release ;)
+- build system switched to autotools
+- removed SYSV preprocessor macro use, replaced with autotools equivalents
+- fixed a bug that caused rsyslogd to segfault when TCP listening was
+ disabled and it terminated
+- added new properties "syslogfacility-text" and "syslogseverity-text"
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- added the -x option to disable hostname dns resolution
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- begun to better modularize syslogd.c - this is an ongoing project; moved
+ type definitions to a separate file
+- removed some now-unused fields from struct filed
+- move file size limit fields in struct field to the "right spot" (the file
+ writing part of the union - f_un.f_file)
+- subdirectories linux and solaris are no longer part of the distribution
+ package. This is not because we cease support for them, but there are no
+ longer any files in them after the move to autotools
+---------------------------------------------------------------------------
+Version 1.15.1 (RGer), 2007-07-10
+- fixed a bug that caused a dynaFile selector to stall when there was
+ an open error with one file
+- improved template processing for dynaFiles; templates are now only
+ looked up during initialization - speeds up processing
+- optimized memory layout in struct filed when compiled with MySQL
+ support
+- fixed a bug that caused compilation without SYSLOG_INET to fail
+- re-enabled the "last message repeated n times" feature. This
+ feature was not taken care of while rsyslogd evolved from sysklogd
+ and it was more or less defunct. Now it is fully functional again.
+- added system properties: $NOW, $YEAR, $MONTH, $DAY, $HOUR, $MINUTE
+- fixed a bug in iovAsString() that caused a memory leak under stress
+ conditions (most probably memory shortage). This was unlikely to
+ ever happen, but it doesn't hurt doing it right
+- cosmetic: defined type "uchar", change all unsigned chars to uchar
+---------------------------------------------------------------------------
+Version 1.15.0 (RGer), 2007-07-05
+- added ability to dynamically generate file names based on templates
+ and thus properties. This was a much-requested feature. It makes
+ life easy when it e.g. comes to splitting files based on the sender
+ address.
+- added $umask and $FileCreateMode config file directives
+- applied a patch from Bartosz Kuzma to compile cleanly under NetBSD
+- checks for extra (unexpected) characters in system config file lines
+ have been added
+- added IPv6 documentation - was accidentally missing from CVS
+- begun to change char to unsigned char
+---------------------------------------------------------------------------
+Version 1.14.2 (RGer), 2007-07-03
+** this release fixes all known nits with IPv6 **
+- restored capability to do /etc/service lookup for "syslog"
+ service when -r 0 was given
+- documented IPv6 handling of syslog messages
+- integrate patch from Bartosz Kuźma to make rsyslog compile under
+ Solaris again (the patch replaced a strndup() call, which is not
+ available under Solaris
+- improved debug logging when waiting on select
+- updated rsyslogd man page with new options (-46A)
+---------------------------------------------------------------------------
+Version 1.14.1 (RGer/Peter Vrabec), 2007-06-29
+- added Peter Vrabec's patch for IPv6 TCP
+- prefixed all messages send to stderr in rsyslogd with "rsyslogd: "
+---------------------------------------------------------------------------
+Version 1.14.0 (RGer/Peter Vrabec), 2007-06-28
+- Peter Vrabec provided IPv6 for rsyslog, so we are now IPv6 enabled
+ IPv6 Support is currently for UDP only, TCP is to come soon.
+ AllowedSender configuration does not yet work for IPv6.
+- fixed code in iovCreate() that broke C's strict aliasing rules
+- fixed some char/unsigned char differences that forced the compiler
+ to spit out warning messages
+- updated the Red Hat init script to fix a known issue (thanks to
+ Peter Vrabec)
+---------------------------------------------------------------------------
+Version 1.13.5 (RGer), 2007-06-22
+- made the TCP session limit configurable via command line switch
+ now -t <port>,<max sessions>
+- added man page for rklogd(8) (basically a copy from klogd, but now
+ there is one...)
+- fixed a bug that caused internal messages (e.g. rsyslogd startup) to
+ appear without a tag.
+- removed a minor memory leak that occurred when TAG processing requalified
+ a HOSTNAME to be a TAG (and a TAG already was set).
+- removed potential small memory leaks in MsgSet***() functions. There
+ would be a leak if a property was re-set, something that happened
+ extremely seldom.
+---------------------------------------------------------------------------
+Version 1.13.4 (RGer), 2007-06-18
+- added a new property "PRI-text", which holds the PRI field in
+ textual form (e.g. "syslog.info")
+- added alias "syslogseverity" for "syslogpriority", which is a
+ misleading property name that needs to stay for historical
+ reasons (and backward-compatibility)
+- added doc on how to record PRI value in log file
+- enhanced signal handling in klogd, including removal of an unsafe
+ call to the logging system during signal handling
+---------------------------------------------------------------------------
+Version 1.13.3 (RGer), 2007-06-15
+- create a version of syslog.c from scratch. This is now
+ - highly optimized for rsyslog
+ - removes an incompatible license problem as the original
+ version had a BSD license with advertising clause
+ - fixed in the regard that rklogd will continue to work when
+ rsyslogd has been restarted (the original version, as well
+ as sysklogd, will remain silent then)
+ - solved an issue with an extra NUL char at message end that the
+ original version had
+- applied some changes to klogd to care for the new interface
+- fixed a bug in syslogd.c which prevented compiling under debian
+---------------------------------------------------------------------------
+Version 1.13.2 (RGer), 2007-06-13
+- lib order in makefile patched to facilitate static linking - thanks
+ to Bennett Todd for providing the patch
+- Integrated a patch from Peter Vrabec (pvrabec@redhat.com):
+ - added klogd under the name of rklogd (remove dependency on
+ original sysklogd package
+ - createDB.sql now in UTF
+ - added additional config files for use on Red Hat
+---------------------------------------------------------------------------
+Version 1.13.1 (RGer), 2007-02-05
+- changed the listen backlog limit to a more reasonable value based on
+ the maximum number of TCP connections configured (10% + 5) - thanks to Guy
+ Standen for the hint (actually, the limit was 5 and that was a
+ left-over from early testing).
+- fixed a bug in makefile which caused DB-support to be disabled when
+ NETZIP support was enabled
+- added the -e option to allow transmission of every message to remote
+ hosts (effectively turns off duplicate message suppression)
+- (somewhat) improved memory consumption when compiled with MySQL support
+- looks like we fixed an incompatibility with MySQL 5.x and above software
+ At least in one case, the remote server name was destroyed, leading to
+ a connection failure. The new, improved code does not have this issue and
+ so we see this as solved (the new code is generally somewhat better, so
+ there is a good chance we fixed this incompatibility).
+---------------------------------------------------------------------------
+Version 1.13.0 (RGer), 2006-12-19
+- added '$' as ToPos property replacer specifier - means "up to the
+ end of the string"
+- property replacer option "escape-cc", "drop-cc" and "space-cc" added
+- changed the handling of \0 characters inside syslog messages. We now
+ consistently escape them to "#000". This is somewhat recommended in
+ the draft-ietf-syslog-protocol-19 draft. While the real recommendation
+ is to not escape any characters at all, we can not do this without
+ considerable modification of the code. So we escape it to "#000", which
+ is consistent with a sample found in the Internet-draft.
+- removed message glue logic (see printchopped() comment for details)
+ Also caused removal of parts table and thus some improvements in
+ memory usage.
+- changed the default MAXLINE to 2048 to take care of recent syslog
+ standardization efforts (can easily be changed in syslogd.c)
+- added support for byte-counted TCP syslog messages (much like
+ syslog-transport-tls-05 Internet Draft). This was necessary to
+ support compression over TCP.
+- added support for receiving compressed syslog messages
+- added support for sending compressed syslog messages
+- fixed a bug where the last message in a syslog/tcp stream was
+ lost if it was not properly terminated by a LF character
+---------------------------------------------------------------------------
+Version 1.12.3 (RGer), 2006-10-04
+- implemented some changes to support Solaris (but support is not
+ yet complete)
+- commented out (via #if 0) some methods that are currently not being use
+ but should be kept for further us
+- added (interim) -u 1 option to turn off hostname and tag parsing
+- done some modifications to better support Fedora
+- made the field delimiter inside property replace configurable via
+ template
+- fixed a bug in property replacer: if fields were used, the delimitor
+ became part of the field. Up until now, this was barely noticeable as
+ the delimiter as TAB only and thus invisible to a human. With other
+ delimiters available now, it quickly showed up. This bug fix might cause
+ some grief to existing installations if they used the extra TAB for
+ whatever reasons - sorry folks... Anyhow, a solution is easy: just add
+ a TAB character constant into your template. Thus, there has no attempt
+ been made to do this in a backwards-compatible way.
+---------------------------------------------------------------------------
+Version 1.12.2 (RGer), 2006-02-15
+- fixed a bug in the RFC 3339 date formatter. An extra space was added
+ after the actual timestamp
+- added support for providing high-precision RFC3339 timestamps for
+ (rsyslogd-)internally-generated messages
+- very (!) experimental support for syslog-protocol internet draft
+ added (the draft is experimental, the code is solid ;))
+- added support for field-extracting in the property replacer
+- enhanced the legacy-syslog parser so that it can interpret messages
+ that do not contain a TIMESTAMP
+- fixed a bug that caused the default socket (usually /dev/log) to be
+ opened even when -o command line option was given
+- fixed a bug in the Debian sample startup script - it caused rsyslogd
+ to listen to remote requests, which it shouldn't by default
+---------------------------------------------------------------------------
+Version 1.12.1 (RGer), 2005-11-23
+- made multithreading work with BSD. Some signal-handling needed to be
+ restructured. Also, there might be a slight delay of up to 10 seconds
+ when huping and terminating rsyslogd under BSD
+- fixed a bug where a NULL-pointer was passed to printf() in logmsg().
+- fixed a bug during "make install" where rc3195d was not installed
+ Thanks to Bennett Todd for spotting this.
+- fixed a bug where rsyslogd dumped core when no TAG was found in the
+ received message
+- enhanced message parser so that it can deal with missing hostnames
+ in many cases (may not be totally fail-safe)
+- fixed a bug where internally-generated messages did not have the correct
+ TAG
+---------------------------------------------------------------------------
+Version 1.12.0 (RGer), 2005-10-26
+- moved to a multi-threaded design. single-threading is still optionally
+ available. Multi-threading is experimental!
+- fixed a potential race condition. In the original code, marking was done
+ by an alarm handler, which could lead to all sorts of bad things. This
+ has been changed now. See comments in syslogd.c/domark() for details.
+- improved debug output for property-based filters
+- not a code change, but: I have checked all exit()s to make sure that
+ none occurs once rsyslogd has started up. Even in unusual conditions
+ (like low-memory conditions) rsyslogd somehow remains active. Of course,
+ it might loose a message or two, but at least it does not abort and it
+ can also recover when the condition no longer persists.
+- fixed a bug that could cause loss of the last message received
+ immediately before rsyslogd was terminated.
+- added comments on thread-safety of global variables in syslogd.c
+- fixed a small bug: spurios printf() when TCP syslog was used
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug with regular expression support (thanks to Andres Riancho)
+- a little bit of code restructuring (especially main(), which was
+ horribly large)
+---------------------------------------------------------------------------
+Version 1.11.1 (RGer), 2005-10-19
+- support for BSD-style program name and host blocks
+- added a new property "programname" that can be used in templates
+- added ability to specify listen port for rfc3195d
+- fixed a bug that rendered the "startswith" comparison operation
+ unusable.
+- changed more functions to "static" storage class to help compiler
+ optimize (should have been static in the first place...)
+- fixed a potential memory leak in the string buffer class destructor.
+ As the destructor was previously never called, the leak did not actually
+ appear.
+- some internal restructuring in anticipation/preparation of minimal
+ multi-threading support
+- rsyslogd still shares some code with the sysklogd project. Some patches
+ for this shared code have been brought over from the sysklogd CVS.
+---------------------------------------------------------------------------
+Version 1.11.0 (RGer), 2005-10-12
+- support for receiving messages via RFC 3195; added rfc3195d for that
+ purpose
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+---------------------------------------------------------------------------
+Version 1.10.2 (RGer), 2005-09-27
+- added comparison operations in property-based filters:
+ * isequal
+ * startswith
+- added ability to negate all property-based filter comparison operations
+ by adding a !-sign right in front of the operation name
+- added the ability to specify remote senders for UDP and TCP
+ received messages. Allows to block all but well-known hosts
+- changed the $-config line directives to be case-INsensitive
+- new command line option -w added: "do not display warnings if messages
+ from disallowed senders are received"
+- fixed a bug that caused rsyslogd to dump core when the compare value
+ was not quoted in property-based filters
+- fixed a bug in the new CStr compare function which lead to invalid
+ results (fortunately, this function was not yet used widely)
+- added better support for "debugging" rsyslog.conf property filters
+ (only if -d switch is given)
+- changed some function definitions to static, which eventually enables
+ some compiler optimizations
+- fixed a bug in MySQL code; when a SQL error occurred, rsyslogd could
+ run in a tight loop. This was due to invalid sequence of error reporting
+ and is now fixed.
+---------------------------------------------------------------------------
+Version 1.10.1 (RGer), 2005-09-23
+- added the ability to execute a shell script as an action.
+ Thanks to Bjoern Kalkbrenner for providing the code!
+- fixed a bug in the MySQL code; due to the bug the automatic one-time
+ retry after an error did not happen - this lead to error message in
+ cases where none should be seen (e.g. after a MySQL restart)
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.10.0 (RGer), 2005-09-20
+ REMINDER: 1.10 is the first unstable version if the 1.x series!
+- added the capability to filter on any property in selector lines
+ (not just facility and priority)
+- changed stringbuf into a new counted string class
+- added support for a "discard" action. If a selector line with
+ discard (~ character) is found, no selector lines *after* that
+ line will be processed.
+- thanks to Andres Riancho, regular expression support has been
+ added to the template engine
+- added the FROMHOST property in the template processor, which could
+ previously not be obtained. Thanks to Cristian Testa for pointing
+ this out and even providing a fix.
+- added display of compile-time options to -v output
+- performance improvement for production build - made some checks
+ to happen only during debug mode
+- fixed a problem with compiling on SUSE and - while doing so - removed
+ the socket call to set SO_BSDCOMPAT in cases where it is obsolete.
+---------------------------------------------------------------------------
+Version 1.0.4 (RGer), 2006-02-01
+- a small but important fix: the tcp receiver had two forgotten printf's
+ in it that caused a lot of unnecessary output to stdout. This was
+ important enough to justify a new release
+---------------------------------------------------------------------------
+Version 1.0.3 (RGer), 2005-11-14
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+- applied some patches available from the sysklogd project to code
+ shared from there
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug in the TCP sender that caused the retry logic to fail
+ after an error or receiver overrun
+- fixed a bug in init() that could lead to dumping core
+- fixed a bug that could lead to dumping core when no HOSTNAME or no TAG
+ was present in the syslog message
+---------------------------------------------------------------------------
+Version 1.0.2 (RGer), 2005-10-05
+- fixed an issue with MySQL error reporting. When an error occurred,
+ the MySQL driver went into an endless loop (at least in most cases).
+---------------------------------------------------------------------------
+Version 1.0.1 (RGer), 2005-09-23
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.0.0 (RGer), 2005-09-12
+- changed install doc to cover daily cron scripts - a trouble source
+- added rc script for slackware (provided by Chris Elvidge - thanks!)
+- fixed a really minor bug in usage() - the -r option was still
+ reported as without the port parameter
+---------------------------------------------------------------------------
+Version 0.9.8 (RGer), 2005-09-05
+- made startup and shutdown message more consistent and included the
+ pid, so that they can be easier correlated. Used syslog-protocol
+ structured data format for this purpose.
+- improved config info in startup message, now tells not only
+ if it is listening remote on udp, but also for tcp. Also includes
+ the port numbers. The previous startup message was misleading, because
+ it did not say "remote reception" if rsyslogd was only listening via
+ tcp (but not via udp).
+- added a "how can you help" document to the doc set
+---------------------------------------------------------------------------
+Version 0.9.7 (RGer), 2005-08-15
+- some of the previous doc files (like INSTALL) did not properly
+ reflect the changes to the build process and the new doc. Fixed
+ that.
+- changed syslogd.c so that when compiled without database support,
+ an error message is displayed when a database action is detected
+ in the config file (previously this was used as an user rule ;))
+- fixed a bug in the os-specific Makefiles which caused MySQL
+ support to not be compiled, even if selected
+---------------------------------------------------------------------------
+Version 0.9.6 (RGer), 2005-08-09
+- greatly enhanced documentation. Now available in html format in
+ the "doc" folder and FreeBSD. Finally includes an install howto.
+- improved MySQL error messages a little - they now show up as log
+ messages, too (formerly only in debug mode)
+- added the ability to specify the listen port for udp syslog.
+ WARNING: This introduces an incompatibility. Formerly, udp
+ syslog was enabled by the -r command line option. Now, it is
+ "-r [port]", which is consistent with the tcp listener. However,
+ just -r will now return an error message.
+- added sample startup scripts for Debian and FreeBSD
+- added support for easy feature selection in the makefile. Un-
+ fortunately, this also means I needed to spilt the make file
+ for different OS and distros. There are some really bad syntax
+ differences between FreeBSD and Linux make.
+---------------------------------------------------------------------------
+Version 0.9.5 (RGer), 2005-08-01
+- the "semicolon bug" was actually not (fully) solved in 0.9.4. One
+ part of the bug was solved, but another still existed. This one
+ is fixed now, too.
+- the "semicolon bug" actually turned out to be a more generic bug.
+ It appeared whenever an invalid template name was given. With some
+ selector actions, rsyslogd dumped core, with other it "just" had
+ a small resource leak with others all worked well. These anomalies
+ are now fixed. Note that they only appeared during system initialization
+ once the system was running, nothing bad happened.
+- improved error reporting for template errors on startup. They are now
+ shown on the console and the start-up tty. Formerly, they were only
+ visible in debug mode.
+- support for multiple instances of rsyslogd on a single machine added
+- added new option "-o" --> omit local unix domain socket. This option
+ enables rsyslogd NOT to listen to the local socket. This is most
+ helpful when multiple instances of rsyslogd (or rsyslogd and another
+ syslogd) shall run on a single system.
+- added new option "-i <pidfile>" which allows one to specify the pidfile.
+ This is needed when multiple instances of rsyslogd are to be run.
+- the new project home page is now online at www.rsyslog.com
+---------------------------------------------------------------------------
+Version 0.9.4 (RGer), 2005-07-25
+- finally added the TCP sender. It now supports non-blocking mode, no
+ longer disabling message reception during connect. As it is now, it
+ is usable in production. The code could be more sophisticated, but
+ I've kept it short in anticipation of the move to liblogging, which
+ will lead to the removal of the code just written ;)
+- the "exiting on signal..." message still had the "syslogd" name in
+ it. Changed this to "rsyslogd", as we do not have a large user base
+ yet, this should pose no problem.
+- fixed "the semicolon" bug. rsyslogd dumped core if a write-db action
+ was specified but no semicolon was given after the password (an empty
+ template was ok, but the semicolon needed to be present).
+- changed a default for traditional output format. During testing, it
+ was seen that the timestamp written to file in default format was
+ the time of message reception, not the time specified in the TIMESTAMP
+ field of the message itself. Traditionally, the message TIMESTAMP is
+ used and this has been changed now.
+---------------------------------------------------------------------------
+Version 0.9.3 (RGer), 2005-07-19
+- fixed a bug in the message parser. In June, the RFC 3164 timestamp
+ was not correctly parsed (yes, only in June and some other months,
+ see the code comment to learn why...)
+- added the ability to specify the destination port when forwarding
+ syslog messages (both for TCP and UDP)
+- added an very experimental TCP sender (activated by
+ @@machine:port in config). This is not yet for production use. If
+ the receiver is not alive, rsyslogd will wait quite some time until
+ the connection request times out, which most probably leads to
+ loss of incoming messages.
+
+---------------------------------------------------------------------------
+Version 0.9.2 (RGer), around 2005-07-06
+- I intended to change the maxsupported message size to 32k to
+ support IHE - but given the memory inefficiency in the usual use
+ cases, I have not done this. I have, however, included very
+ specific instructions on how to do this in the source code. I have
+ also done some testing with 32k messages, so you can change the
+ max size without taking too much risk.
+- added a syslog/tcp receiver; we now can receive messages via
+ plain tcp, but we can still send only via UDP. The syslog/tcp
+ receiver is the primary enhancement of this release.
+- slightly changed some error messages that contained a spurios \n at
+ the end of the line (which gives empty lines in your log...)
+
+---------------------------------------------------------------------------
+Version 0.9.1 (RGer)
+- fixed code so that it compiles without errors under FreeBSD
+- removed now unused function "allocate_log()" from syslogd.c
+- changed the make file so that it contains more defines for
+ different environments (in the long term, we need a better
+ system for disabling/enabling features...)
+- changed some printf's printing off_t types to %lld and
+ explicit (long long) casts. I tried to figure out the exact type,
+ but did not succeed in this. In the worst case, ultra-large peta-
+ byte files will now display funny informational messages on rollover,
+ something I think we can live with for the next 10 years or so...
+
+---------------------------------------------------------------------------
+Version 0.9.0 (RGer)
+- changed the filed structure to be a linked list. Previously, it
+ was a table - well, for non-SYSV it was defined as linked list,
+ but from what I see that code did no longer work after my
+ modifications. I am now using a linked list in general because
+ that is needed for other upcoming modifications.
+- fixed a bug that caused rsyslogd not to listen to anything if
+ the configuration file could not be read
+- previous versions disabled network logging (send/receive) if
+ syslog/udp port was not in /etc/services. Now defaulting to
+ port 514 in this case.
+- internal error messages are now supported up to 256 bytes
+- error message seen during config file read are now also displayed
+ to the attached tty and not only the console
+- changed some error messages during init to be sent to the console
+ and/or emergency log. Previously, they were only seen if the
+ -d (debug) option was present on the command line.
+- fixed the "2gb file issue on 32bit systems". If a file grew to
+ more than 2gb, the syslogd was aborted with "file size exceeded".
+ Now, defines have been added according to
+ http://www.daimi.au.dk/~kasperd/comp.os.linux.development.faq.html#LARGEFILE
+ Testing revealed that they work ;)
+ HOWEVER, if your file system, glibc, kernel, whatever does not
+ support files larger 2gb, you need to set a file size limit with
+ the new output channel mechanism.
+- updated man pages to reflect the changes
+
+---------------------------------------------------------------------------
+Version 0.8.4
+
+- improved -d debug output (removed developer-only content)
+- now compiles under FreeBSD and NetBSD (only quick testing done on NetBSD)
+---------------------------------------------------------------------------
+Version 0.8.3
+
+- security model in "make install" changed
+- minor doc updates
+---------------------------------------------------------------------------
+Version 0.8.2
+
+- added man page for rsyslog.conf and rsyslogd
+- gave up on the concept of rsyslog being a "drop in" replacement
+ for syslogd. Now, the user installs rsyslogd and also needs to
+ adjust his system settings to this specifically. This also lead
+ to these changes:
+ * changed Makefile so that install now installs rsyslogd instead
+ of dealing with syslogd
+ * changed the default config file name to rsyslog.conf
+---------------------------------------------------------------------------
+Version 0.8.1
+
+- fixed a nasty memory leak (probably not the last one with this release)
+- some enhancements to Makefile as suggested by Bennett Todd
+- syslogd-internal messages (like restart) were missing the hostname
+ this has been corrected
+---------------------------------------------------------------------------
+Version 0.8.0
+
+Initial testing release. Based on the sysklogd package. Thanks to the
+sysklogd maintainers for all their good work!
+---------------------------------------------------------------------------
+
+----------------------------------------------------------------------
+The following comments were left in the syslogd source. While they provide
+not too much detail, the help to date when Rainer started work on the
+project (which was 2003, now even surprising for Rainer himself ;)).
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-10-17
+ * Some initial modifications on the sysklogd package to support
+ * liblogging. These have actually not yet been merged to the
+ * source you see currently (but they hopefully will)
+ *
+ * \date 2004-10-28
+ * Restarted the modifications of sysklogd. This time, we
+ * focus on a simpler approach first. The initial goal is to
+ * provide MySQL database support (so that syslogd can log
+ * to the database).
+----------------------------------------------------------------------
+The following comments are from the stock syslogd.c source. They provide
+some insight into what happened to the source before we forked
+rsyslogd. However, much of the code already has been replaced and more
+is to be replaced. So over time, these comments become less valuable.
+I have moved them out of the syslogd.c file to shrink it, especially
+as a lot of them do no longer apply. For historical reasons and
+understanding of how the daemon evolved, they are probably still
+helpful.
+ * Author: Eric Allman
+ * extensive changes by Ralph Campbell
+ * more extensive changes by Eric Allman (again)
+ *
+ * Steve Lord: Fix UNIX domain socket code, added linux kernel logging
+ * change defines to
+ * SYSLOG_INET - listen on a UDP socket
+ * SYSLOG_UNIXAF - listen on unix domain socket
+ * SYSLOG_KERNEL - listen to linux kernel
+ *
+ * Mon Feb 22 09:55:42 CST 1993: Dr. Wettstein
+ * Additional modifications to the source. Changed priority scheme
+ * to increase the level of configurability. In its stock configuration
+ * syslogd no longer logs all messages of a certain priority and above
+ * to a log file. The * wildcard is supported to specify all priorities.
+ * Note that this is a departure from the BSD standard.
+ *
+ * Syslogd will now listen to both the inetd and the unixd socket. The
+ * strategy is to allow all local programs to direct their output to
+ * syslogd through the unixd socket while the program listens to the
+ * inetd socket to get messages forwarded from other hosts.
+ *
+ * Fri Mar 12 16:55:33 CST 1993: Dr. Wettstein
+ * Thanks to Stephen Tweedie (dcs.ed.ac.uk!sct) for helpful bug-fixes
+ * and an enlightened commentary on the prioritization problem.
+ *
+ * Changed the priority scheme so that the default behavior mimics the
+ * standard BSD. In this scenario all messages of a specified priority
+ * and above are logged.
+ *
+ * Add the ability to specify a wildcard (=) as the first character
+ * of the priority name. Doing this specifies that ONLY messages with
+ * this level of priority are to be logged. For example:
+ *
+ * *.=debug /usr/adm/debug
+ *
+ * Would log only messages with a priority of debug to the /usr/adm/debug
+ * file.
+ *
+ * Providing an * as the priority specifies that all messages are to be
+ * logged. Note that this case is degenerate with specifying a priority
+ * level of debug. The wildcard * was retained because I believe that
+ * this is more intuitive.
+ *
+ * Thu Jun 24 11:34:13 CDT 1993: Dr. Wettstein
+ * Modified sources to incorporate changes in libc4.4. Messages from
+ * syslog are now null-terminated, syslogd code now parses messages
+ * based on this termination scheme. Linux as of libc4.4 supports the
+ * fsync system call. Modified code to fsync after all writes to
+ * log files.
+ *
+ * Sat Dec 11 11:59:43 CST 1993: Dr. Wettstein
+ * Extensive changes to the source code to allow compilation with no
+ * complaints with -Wall.
+ *
+ * Reorganized the facility and priority name arrays so that they
+ * compatible with the syslog.h source found in /usr/include/syslog.h.
+ * NOTE that this should really be changed. The reason I do not
+ * allow the use of the values defined in syslog.h is on account of
+ * the extensions made to allow the wildcard character in the
+ * priority field. To fix this properly one should malloc an array,
+ * copy the contents of the array defined by syslog.h and then
+ * make whatever modifications that are desired. Next round.
+ *
+ * Thu Jan 6 12:07:36 CST 1994: Dr. Wettstein
+ * Added support for proper decomposition and re-assembly of
+ * fragment messages on UNIX domain sockets. Lack of this capability
+ * was causing 'partial' messages to be output. Since facility and
+ * priority information is encoded as a leader on the messages this
+ * was causing lines to be placed in erroneous files.
+ *
+ * Also added a patch from Shane Alderton (shane@ion.apana.org.au) to
+ * correct a problem with syslogd dumping core when an attempt was made
+ * to write log messages to a logged-on user. Thank you.
+ *
+ * Many thanks to Juha Virtanen (jiivee@hut.fi) for a series of
+ * interchanges which lead to the fixing of problems with messages set
+ * to priorities of none and emerg. Also thanks to Juha for a patch
+ * to exclude users with a class of LOGIN from receiving messages.
+ *
+ * Shane Alderton provided an additional patch to fix zombies which
+ * were conceived when messages were written to multiple users.
+ *
+ * Mon Feb 6 09:57:10 CST 1995: Dr. Wettstein
+ * Patch to properly reset the single priority message flag. Thanks
+ * to Christopher Gori for spotting this bug and forwarding a patch.
+ *
+ * Wed Feb 22 15:38:31 CST 1995: Dr. Wettstein
+ * Added version information to startup messages.
+ *
+ * Added defines so that paths to important files are taken from
+ * the definitions in paths.h. Hopefully this will insure that
+ * everything follows the FSSTND standards. Thanks to Chris Metcalf
+ * for a set of patches to provide this functionality. Also thanks
+ * Elias Levy for prompting me to get these into the sources.
+ *
+ * Wed Jul 26 18:57:23 MET DST 1995: Martin Schulze
+ * Linux' gethostname only returns the hostname and not the fqdn as
+ * expected in the code. But if you call hostname with an fqdn then
+ * gethostname will return an fqdn, so we have to mention that. This
+ * has been changed.
+ *
+ * The 'LocalDomain' and the hostname of a remote machine is
+ * converted to lower case, because the original caused some
+ * inconsistency, because the (at least my) nameserver did respond an
+ * fqdn containing of upper- _and_ lowercase letters while
+ * 'LocalDomain' consisted only of lowercase letters and that didn't
+ * match.
+ *
+ * Sat Aug 5 18:59:15 MET DST 1995: Martin Schulze
+ * Now no messages that were received from any remote host are sent
+ * out to another. At my domain this missing feature caused ugly
+ * syslog-loops, sometimes.
+ *
+ * Remember that no message is sent out. I can't figure out any
+ * scenario where it might be useful to change this behavior and to
+ * send out messages to other hosts than the one from which we
+ * received the message, but I might be shortsighted. :-/
+ *
+ * Thu Aug 10 19:01:08 MET DST 1995: Martin Schulze
+ * Added my pidfile.[ch] to it to perform a better handling with
+ * pidfiles. Now both, syslogd and klogd, can only be started
+ * once. They check the pidfile.
+ *
+ * Sun Aug 13 19:01:41 MET DST 1995: Martin Schulze
+ * Add an addition to syslog.conf's interpretation. If a priority
+ * begins with an exclamation mark ('!') the normal interpretation
+ * of the priority is inverted: ".!*" is the same as ".none", ".!=info"
+ * don't logs the info priority, ".!crit" won't log any message with
+ * the priority crit or higher. For example:
+ *
+ * mail.*;mail.!=info /usr/adm/mail
+ *
+ * Would log all messages of the facility mail except those with
+ * the priority info to /usr/adm/mail. This makes the syslogd
+ * much more flexible.
+ *
+ * Defined TABLE_ALLPRI=255 and changed some occurrences.
+ *
+ * Sat Aug 19 21:40:13 MET DST 1995: Martin Schulze
+ * Making the table of facilities and priorities while in debug
+ * mode more readable.
+ *
+ * If debugging is turned on, printing the whole table of
+ * facilities and priorities every hexadecimal or 'X' entry is
+ * now 2 characters wide.
+ *
+ * The number of the entry is prepended to each line of
+ * facilities and priorities, and F_UNUSED lines are not shown
+ * anymore.
+ *
+ * Corrected some #ifdef SYSV's.
+ *
+ * Mon Aug 21 22:10:35 MET DST 1995: Martin Schulze
+ * Corrected a strange behavior during parsing of configuration
+ * file. The original BSD syslogd doesn't understand spaces as
+ * separators between specifier and action. This syslogd now
+ * understands them. The old behavior caused some confusion over
+ * the Linux community.
+ *
+ * Thu Oct 19 00:02:07 MET 1995: Martin Schulze
+ * The default behavior has changed for security reasons. The
+ * syslogd will not receive any remote message unless you turn
+ * reception on with the "-r" option.
+ *
+ * Not defining SYSLOG_INET will result in not doing any network
+ * activity, i.e. not sending or receiving messages. I changed
+ * this because the old idea is implemented with the "-r" option
+ * and the old thing didn't work anyway.
+ *
+ * Thu Oct 26 13:14:06 MET 1995: Martin Schulze
+ * Added another logfile type F_FORW_UNKN. The problem I ran into
+ * was a name server that runs on my machine and a forwarder of
+ * kern.crit to another host. The hosts address can only be
+ * fetched using the nameserver. But named is started after
+ * syslogd, so syslogd complained.
+ *
+ * This logfile type will retry to get the address of the
+ * hostname ten times and then complain. This should be enough to
+ * get the named up and running during boot sequence.
+ *
+ * Fri Oct 27 14:08:15 1995: Dr. Wettstein
+ * Changed static array of logfiles to a dynamic array. This
+ * can grow during process.
+ *
+ * Fri Nov 10 23:08:18 1995: Martin Schulze
+ * Inserted a new tabular sys_h_errlist that contains plain text
+ * for error codes that are returned from the net subsystem and
+ * stored in h_errno. I have also changed some wrong lookups to
+ * sys_errlist.
+ *
+ * Wed Nov 22 22:32:55 1995: Martin Schulze
+ * Added the fabulous strip-domain feature that allows us to
+ * strip off (several) domain names from the fqdn and only log
+ * the simple hostname. This is useful if you're in a LAN that
+ * has a central log server and also different domains.
+ *
+ * I have also also added the -l switch do define hosts as
+ * local. These will get logged with their simple hostname, too.
+ *
+ * Thu Nov 23 19:02:56 MET DST 1995: Martin Schulze
+ * Added the possibility to omit fsyncing of logfiles after every
+ * write. This will give some performance back if you have
+ * programs that log in a very verbose manner (like innd or
+ * smartlist). Thanks to Stephen R. van den Berg <srb@cuci.nl>
+ * for the idea.
+ *
+ * Thu Jan 18 11:14:36 CST 1996: Dr. Wettstein
+ * Added patch from beta-testers to stop compile error. Also
+ * added removal of pid file as part of termination cleanup.
+ *
+ * Wed Feb 14 12:42:09 CST 1996: Dr. Wettstein
+ * Allowed forwarding of messages received from remote hosts to
+ * be controlled by a command-line switch. Specifying -h allows
+ * forwarding. The default behavior is to disable forwarding of
+ * messages which were received from a remote host.
+ *
+ * Parent process of syslogd does not exit until child process has
+ * finished initialization process. This allows rc.* startup to
+ * pause until syslogd facility is up and operating.
+ *
+ * Re-arranged the select code to move UNIX domain socket accepts
+ * to be processed later. This was a contributed change which
+ * has been proposed to correct the delays sometimes encountered
+ * when syslogd starts up.
+ *
+ * Minor code cleanups.
+ *
+ * Thu May 2 15:15:33 CDT 1996: Dr. Wettstein
+ * Fixed bug in init function which resulted in file descriptors
+ * being orphaned when syslogd process was re-initialized with SIGHUP
+ * signal. Thanks to Edvard Tuinder
+ * (Edvard.Tuinder@praseodymium.cistron.nl) for putting me on the
+ * trail of this bug. I am amazed that we didn't catch this one
+ * before now.
+ *
+ * Tue May 14 00:03:35 MET DST 1996: Martin Schulze
+ * Corrected a mistake that causes the syslogd to stop logging at
+ * some virtual consoles under Linux. This was caused by checking
+ * the wrong error code. Thanks to Michael Nonweiler
+ * <mrn20@hermes.cam.ac.uk> for sending me a patch.
+ *
+ * Mon May 20 13:29:32 MET DST 1996: Miquel van Smoorenburg <miquels@cistron.nl>
+ * Added continuation line supported and fixed a bug in
+ * the init() code.
+ *
+ * Tue May 28 00:58:45 MET DST 1996: Martin Schulze
+ * Corrected behavior of blocking pipes - i.e. the whole system
+ * hung. Michael Nonweiler <mrn20@hermes.cam.ac.uk> has sent us
+ * a patch to correct this. A new logfile type F_PIPE has been
+ * introduced.
+ *
+ * Mon Feb 3 10:12:15 MET DST 1997: Martin Schulze
+ * Corrected behavior of logfiles if the file can't be opened.
+ * There was a bug that causes syslogd to try to log into non
+ * existing files which ate cpu power.
+ *
+ * Sun Feb 9 03:22:12 MET DST 1997: Martin Schulze
+ * Modified syslogd.c to not kill itself which confuses bash 2.0.
+ *
+ * Mon Feb 10 00:09:11 MET DST 1997: Martin Schulze
+ * Improved debug code to decode the numeric facility/priority
+ * pair into textual information.
+ *
+ * Tue Jun 10 12:35:10 MET DST 1997: Martin Schulze
+ * Corrected freeing of logfiles. Thanks to Jos Vos <jos@xos.nl>
+ * for reporting the bug and sending an idea to fix the problem.
+ *
+ * Tue Jun 10 12:51:41 MET DST 1997: Martin Schulze
+ * Removed sleep(10) from parent process. This has caused a slow
+ * startup in former times - and I don't see any reason for this.
+ *
+ * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
+ * Some more glibc patches made by <mdorman@debian.org>.
+ *
+ * Thu Jan 1 16:04:52 CET 1998: Martin Schulze <joey@infodrom.north.de
+ * Applied patch from Herbert Thielen <Herbert.Thielen@lpr.e-technik.tu-muenchen.de>.
+ * This included some balance parentheses for emacs and a bug in
+ * the exclamation mark handling.
+ *
+ * Fixed small bug which caused syslogd to write messages to the
+ * wrong logfile under some very rare conditions. Thanks to
+ * Herbert Xu <herbert@gondor.apana.org.au> for fiddling this out.
+ *
+ * Thu Jan 8 22:46:35 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Reworked one line of the above patch as it prevented syslogd
+ * from binding the socket with the result that no messages were
+ * forwarded to other hosts.
+ *
+ * Sat Jan 10 01:33:06 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed small bugs in F_FORW_UNKN mechanism. Thanks to Torsten
+ * Neumann <torsten@londo.rhein-main.de> for pointing me to it.
+ *
+ * Mon Jan 12 19:50:58 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified debug output concerning remote reception.
+ *
+ * Mon Feb 23 23:32:35 CET 1998: Topi Miettinen <Topi.Miettinen@ml.tele.fi>
+ * Re-worked handling of Unix and UDP sockets to support closing /
+ * opening of them in order to have it open only if it is needed
+ * either for forwarding to a remote host or by reception from
+ * the network.
+ *
+ * Wed Feb 25 10:54:09 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed little comparison mistake that prevented the MARK
+ * feature to work properly.
+ *
+ * Wed Feb 25 13:21:44 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Corrected Topi's patch as it prevented forwarding during
+ * startup due to an unknown LogPort.
+ *
+ * Sat Oct 10 20:01:48 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added support for TESTING define which will turn syslogd into
+ * stdio-mode used for debugging.
+ *
+ * Sun Oct 11 20:16:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Reworked the initialization/fork code. Now the parent
+ * process activates a signal handler which the daughter process
+ * will raise if it is initialized. Only after that one the
+ * parent process may exit. Otherwise klogd might try to flush
+ * its log cache while syslogd can't receive the messages yet.
+ *
+ * Mon Oct 12 13:30:35 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Redirected some error output with regard to argument parsing to
+ * stderr.
+ *
+ * Mon Oct 12 14:02:51 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Applied patch provided vom Topi Miettinen with regard to the
+ * people from OpenBSD. This provides the additional '-a'
+ * argument used for specifying additional UNIX domain sockets to
+ * listen to. This is been used with chroot()'ed named's for
+ * example. See for http://www.psionic.com/papers/dns.html
+ *
+ * Mon Oct 12 18:29:44 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added `ftp' facility which was introduced in glibc version 2.
+ * It's #ifdef'ed so won't harm with older libraries.
+ *
+ * Mon Oct 12 19:59:21 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Code cleanups with regard to bsd -> posix transition and
+ * stronger security (buffer length checking). Thanks to Topi
+ * Miettinen <tom@medialab.sonera.net>
+ * . index() --> strchr()
+ * . sprintf() --> snprintf()
+ * . bcopy() --> memcpy()
+ * . bzero() --> memset()
+ * . UNAMESZ --> UT_NAMESIZE
+ * . sys_errlist --> strerror()
+ *
+ * Mon Oct 12 20:22:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added support for setutent()/getutent()/endutent() instead of
+ * binary reading the UTMP file. This is the the most portable
+ * way. This allows /var/run/utmp format to change, even to a
+ * real database or utmp daemon. Also if utmp file locking is
+ * implemented in libc, syslog will use it immediately. Thanks
+ * to Topi Miettinen <tom@medialab.sonera.net>.
+ *
+ * Mon Oct 12 20:49:18 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Avoid logging of SIGCHLD when syslogd is in the process of
+ * exiting and closing its files. Again thanks to Topi.
+ *
+ * Mon Oct 12 22:18:34 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified printline() to support 8bit characters - such as
+ * russian letters. Thanks to Vladas Lapinskas <lapinskas@mail.iae.lt>.
+ *
+ * Sat Nov 14 02:29:37 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * ``-m 0'' now turns of MARK logging entirely.
+ *
+ * Tue Jan 19 01:04:18 MET 1999: Martin Schulze <joey@infodrom.north.de>
+ * Finally fixed an error with `-a' processing, thanks to Topi
+ * Miettinen <tom@medialab.sonera.net>.
+ *
+ * Sun May 23 10:08:53 CEST 1999: Martin Schulze <joey@infodrom.north.de>
+ * Removed superfluous call to utmpname(). The path to the utmp
+ * file is defined in the used libc and should not be hardcoded
+ * into the syslogd binary referring the system it was compiled on.
+ *
+ * Sun Sep 17 20:45:33 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Fixed some bugs in printline() code that did not escape
+ * control characters '\177' through '\237' and contained a
+ * single-byte buffer overflow. Thanks to Solar Designer
+ * <solar@false.com>.
+ *
+ * Sun Sep 17 21:26:16 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Don't close open sockets upon reload. Thanks to Bill
+ * Nottingham.
+ *
+ * Mon Sep 18 09:10:47 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Fixed bug in printchopped() that caused syslogd to emit
+ * kern.emerg messages when splitting long lines. Thanks to
+ * Daniel Jacobowitz <dan@debian.org> for the fix.
+ *
+ * Mon Sep 18 15:33:26 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Removed unixm/unix domain sockets and switch to Datagram Unix
+ * Sockets. This should remove one possibility to play DoS with
+ * syslogd. Thanks to Olaf Kirch <okir@caldera.de> for the patch.
+ *
+ * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de>
+ * Don't return a closed fd if `-a' is called with a wrong path.
+ * Thanks to Bill Nottingham <notting@redhat.com> for providing
+ * a patch.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..8865734
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,368 @@
+Installation Instructions
+*************************
+
+ Copyright (C) 1994-1996, 1999-2002, 2004-2016 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 command './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 limitation. Until the limitation is lifted, you can use this
+workaround:
+
+ CONFIG_SHELL=/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
index 0000000..3af31bc
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,634 @@
+sbin_PROGRAMS =
+pkglib_LTLIBRARIES =
+
+pkgconfigdir = $(libdir)/pkgconfig
+
+EXTRA_DIST = \
+ README.md \
+ platform/README \
+ platform/freebsd/rsyslogd \
+ platform/slackware/rc.rsyslogd \
+ platform/redhat/rsyslog.conf \
+ contrib/README \
+ CONTRIBUTING.md \
+ COPYING \
+ COPYING.LESSER \
+ COPYING.ASL20 \
+ contrib/gnutls/ca.pem \
+ contrib/gnutls/cert.pem \
+ contrib/gnutls/key.pem
+
+SUBDIRS = compat runtime grammar . plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting
+# external plugin driver is always enabled (core component)
+SUBDIRS += plugins/mmexternal
+
+if ENABLE_RSYSLOGD
+SUBDIRS += tools
+endif
+
+if ENABLE_IMKLOG
+SUBDIRS += plugins/imklog
+endif
+
+if ENABLE_IMKMSG
+SUBDIRS += contrib/imkmsg
+endif
+
+if ENABLE_IMPSTATS
+SUBDIRS += plugins/impstats
+endif
+
+if ENABLE_IMSOLARIS
+SUBDIRS += plugins/imsolaris
+endif
+
+if ENABLE_GSSAPI
+SUBDIRS += plugins/omgssapi plugins/imgssapi
+endif
+
+if ENABLE_RELP
+SUBDIRS += plugins/omrelp plugins/imrelp
+endif
+
+if ENABLE_OMFILE_HARDENED
+SUBDIRS += contrib/omfile-hardened
+endif
+
+if ENABLE_MYSQL
+SUBDIRS += plugins/ommysql
+endif
+
+if ENABLE_OMLIBDBI
+SUBDIRS += plugins/omlibdbi
+endif
+
+if ENABLE_PGSQL
+SUBDIRS += plugins/ompgsql
+endif
+
+if ENABLE_SNMP
+SUBDIRS += plugins/omsnmp
+endif
+
+if ENABLE_OMSTDOUT
+SUBDIRS += plugins/omstdout
+endif
+
+if ENABLE_PMCISCONAMES
+SUBDIRS += contrib/pmcisconames
+endif
+
+if ENABLE_PMCISCOIOS
+SUBDIRS += plugins/pmciscoios
+endif
+
+if ENABLE_PMNULL
+SUBDIRS += plugins/pmnull
+endif
+
+if ENABLE_PMNORMALIZE
+SUBDIRS += plugins/pmnormalize
+endif
+
+if ENABLE_PMAIXFORWARDEDFROM
+SUBDIRS += contrib/pmaixforwardedfrom
+endif
+
+if ENABLE_PMSNARE
+SUBDIRS += contrib/pmsnare
+endif
+
+if ENABLE_PMPANNGFW
+SUBDIRS += contrib/pmpanngfw
+endif
+
+if ENABLE_PMLASTMSG
+SUBDIRS += plugins/pmlastmsg
+endif
+
+if ENABLE_OMRULESET
+SUBDIRS += plugins/omruleset
+endif
+
+if ENABLE_OMUDPSPOOF
+SUBDIRS += plugins/omudpspoof
+endif
+
+if ENABLE_OMMONGODB
+SUBDIRS += plugins/ommongodb
+endif
+
+if ENABLE_OMHIREDIS
+SUBDIRS += contrib/omhiredis
+endif
+
+if ENABLE_OMCZMQ
+SUBDIRS += contrib/omczmq
+endif
+
+if ENABLE_OMRABBITMQ
+SUBDIRS += contrib/omrabbitmq
+endif
+
+if ENABLE_IMCZMQ
+SUBDIRS += contrib/imczmq
+endif
+
+if ENABLE_OMUXSOCK
+SUBDIRS += plugins/omuxsock
+endif
+
+if ENABLE_OMHDFS
+SUBDIRS += plugins/omhdfs
+endif
+
+if ENABLE_OMJOURNAL
+SUBDIRS += plugins/omjournal
+endif
+
+if ENABLE_IMJOURNAL
+SUBDIRS += plugins/imjournal
+endif
+
+if ENABLE_ELASTICSEARCH
+SUBDIRS += plugins/omelasticsearch
+endif
+
+if ENABLE_CLICKHOUSE
+SUBDIRS += plugins/omclickhouse
+endif
+
+if ENABLE_OMHTTP
+SUBDIRS += contrib/omhttp
+endif
+
+if ENABLE_SNMP
+SUBDIRS += plugins/omsnmp
+endif
+
+if ENABLE_MMSNMPTRAPD
+SUBDIRS += plugins/mmsnmptrapd
+endif
+
+if ENABLE_IMFILE
+SUBDIRS += plugins/imfile
+endif
+
+if ENABLE_IMDOCKER
+SUBDIRS += contrib/imdocker
+endif
+
+if ENABLE_IMPTCP
+SUBDIRS += plugins/imptcp
+endif
+
+if ENABLE_IMDIAG
+SUBDIRS += plugins/imdiag
+endif
+
+if ENABLE_MAIL
+SUBDIRS += plugins/ommail
+endif
+
+if ENABLE_FMHTTP
+SUBDIRS += plugins/fmhttp
+endif
+
+if ENABLE_FMHASH
+SUBDIRS += contrib/fmhash
+endif
+
+if ENABLE_FMUNFLATTEN
+SUBDIRS += contrib/fmunflatten
+endif
+
+if ENABLE_FFAUP
+SUBDIRS += contrib/ffaup
+endif
+
+if ENABLE_OMKAFKA
+SUBDIRS += plugins/omkafka
+endif
+
+if ENABLE_IMKAFKA
+SUBDIRS += plugins/imkafka
+endif
+
+if ENABLE_OMAZUREEVENTHUBS
+SUBDIRS += plugins/omazureeventhubs
+endif
+
+if ENABLE_IMDTLS
+SUBDIRS += plugins/imdtls
+endif
+
+if ENABLE_OMDTLS
+SUBDIRS += plugins/omdtls
+endif
+
+if ENABLE_OMPROG
+SUBDIRS += plugins/omprog
+endif
+
+if ENABLE_RFC3195
+SUBDIRS += plugins/im3195
+endif
+
+if ENABLE_MMNORMALIZE
+SUBDIRS += plugins/mmnormalize
+endif
+
+if ENABLE_MMJSONPARSE
+SUBDIRS += plugins/mmjsonparse
+endif
+
+if ENABLE_MMGROK
+SUBDIRS += contrib/mmgrok
+endif
+
+if ENABLE_MMAUDIT
+SUBDIRS += plugins/mmaudit
+endif
+
+if ENABLE_MMANON
+SUBDIRS += plugins/mmanon
+endif
+
+if ENABLE_MMRM1STSPACE
+SUBDIRS += plugins/mmrm1stspace
+endif
+
+if ENABLE_MMUTF8FIX
+SUBDIRS += plugins/mmutf8fix
+endif
+
+if ENABLE_MMCOUNT
+SUBDIRS += contrib/mmcount
+endif
+
+if ENABLE_MMSEQUENCE
+SUBDIRS += contrib/mmsequence
+endif
+
+if ENABLE_MMDBLOOKUP
+SUBDIRS += plugins/mmdblookup
+endif
+
+if ENABLE_MMDARWIN
+SUBDIRS += contrib/mmdarwin
+endif
+
+if ENABLE_MMFIELDS
+SUBDIRS += plugins/mmfields
+endif
+
+if ENABLE_MMPSTRUCDATA
+SUBDIRS += plugins/mmpstrucdata
+endif
+
+if ENABLE_MMRFC5424ADDHMAC
+SUBDIRS += contrib/mmrfc5424addhmac
+endif
+
+# omhttpfs
+if ENABLE_OMHTTPFS
+SUBDIRS += contrib/omhttpfs
+endif
+
+# omamqp1
+if ENABLE_OMAMQP1
+SUBDIRS += contrib/omamqp1
+endif
+
+# imbatchreport
+if ENABLE_IMBATCHREPORT
+SUBDIRS += contrib/imbatchreport
+endif
+
+# omtcl
+if ENABLE_OMTCL
+SUBDIRS += contrib/omtcl
+endif
+
+# mmkubernetes
+if ENABLE_MMKUBERNETES
+SUBDIRS += contrib/mmkubernetes
+endif
+
+# impcap
+if ENABLE_IMPCAP
+SUBDIRS += contrib/impcap
+endif
+
+# imtuxedoulog
+if ENABLE_IMTUXEDOULOG
+SUBDIRS += contrib/imtuxedoulog
+endif
+
+# improg
+if ENABLE_IMPROG
+SUBDIRS += contrib/improg
+endif
+
+# imhttp
+if ENABLE_IMHTTP
+SUBDIRS += contrib/imhttp
+endif
+
+# mmtaghostname
+if ENABLE_MMTAGHOSTNAME
+SUBDIRS += contrib/mmtaghostname
+endif
+
+# imdb2diag
+if ENABLE_PMDB2DIAG
+SUBDIRS += contrib/pmdb2diag
+endif
+
+# imhiredis
+if ENABLE_IMHIREDIS
+SUBDIRS += contrib/imhiredis
+endif
+
+# tests are added as last element, because tests may need different
+# modules that need to be generated first
+SUBDIRS += tests
+
+
+
+DISTCHECK_CONFIGURE_FLAGS=
+# make sure "make distcheck" tries to build all modules. This means that
+# a developer must always have an environment where every supporting library
+# is available. If that is not the case, the respective configure option may
+# temporarily be removed below. The intent behind forcing everthing to compile
+# in a make distcheck is so that we detect code that accidently was not updated
+# when some global update happened.
+DISTCHECK_CONFIGURE_FLAGS+= \
+ --enable-silent-rules \
+ --enable-rsyslogd \
+ --enable-omstdout \
+ --enable-imdiag \
+ --enable-testbench \
+ --enable-valgrind
+# currently not supported in make distcheck:
+# --enable-pgsql-tests
+# --enable-extended-tests --> should probably never be enabled due to runtime
+
+if ENABLE_DEFAULT_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= \
+ --enable-diagtools \
+ --enable-impstats \
+ --enable-imptcp \
+ --enable-klog \
+ --enable-mail \
+ --enable-mmanon \
+ --enable-mmaudit \
+ --enable-mmcount \
+ --enable-mmexternal \
+ --enable-mmfields \
+ --enable-mmjsonparse \
+ --enable-mmpstrucdata \
+ --enable-mmrm1stspace \
+ --enable-mmsequence \
+ --enable-mmutf8fix \
+ --enable-omruleset \
+ --enable-omuxsock \
+ --enable-pmaixforwardedfrom \
+ --enable-pmciscoios \
+ --enable-pmcisconames \
+ --enable-pmlastmsg \
+ --enable-pmnull \
+ --enable-pmsnare \
+ --enable-usertools
+
+else
+DISTCHECK_CONFIGURE_FLAGS+= \
+ --disable-default-tests
+endif # if ENABLE_DEFAULT_TESTS
+
+if ENABLE_IMPROG
+DISTCHECK_CONFIGURE_FLAGS+= --enable-improg
+endif
+
+if ENABLE_IMHTTP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imhttp
+endif
+
+if ENABLE_OMPROG
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omprog
+endif
+
+if ENABLE_GSSAPI
+DISTCHECK_CONFIGURE_FLAGS+= --enable-gssapi-krb5
+endif
+
+if ENABLE_PMNORMALIZE
+DISTCHECK_CONFIGURE_FLAGS+= --enable-pmnormalize
+endif
+
+if ENABLE_MMDBLOOKUP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmdblookup
+endif
+
+if ENABLE_MMDARWIN
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmdarwin
+endif
+
+if ENABLE_MMNORMALIZE
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmnormalize
+endif
+
+if ENABLE_OMMONGODB
+DISTCHECK_CONFIGURE_FLAGS+= --enable-ommongodb
+endif
+
+if ENABLE_OMHIREDIS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omhiredis
+endif
+
+if ENABLE_MMSNMPTRAPD
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmsnmptrapd
+endif
+
+if ENABLE_OMLIBDBI
+DISTCHECK_CONFIGURE_FLAGS+= --enable-libdbi
+endif
+
+if ENABLE_LIBGCRYPT
+DISTCHECK_CONFIGURE_FLAGS+= --enable-libgcrypt
+endif
+
+if ENABLE_OMHTTP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omhttp
+endif
+
+if ENABLE_OMHTTPFS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omhttpfs
+endif
+
+if ENABLE_OMTCL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omtcl
+endif
+
+if ENABLE_SNMP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-snmp
+endif
+
+if ENABLE_SNMP_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-snmp-tests
+endif
+
+if ENABLE_FMHTTP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-fmhttp
+endif
+
+if ENABLE_OMUDPSPOOF
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omudpspoof
+endif
+
+if ENABLE_PGSQL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-pgsql
+endif
+
+if ENABLE_GNUTLS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-gnutls
+endif
+
+if ENABLE_GNUTLS_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-gnutls-tests
+else
+DISTCHECK_CONFIGURE_FLAGS+= --disable-gnutls-tests
+endif
+
+if ENABLE_OPENSSL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-openssl
+endif
+
+if ENABLE_MYSQL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mysql
+endif
+if ENABLE_MYSQL_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mysql-tests
+endif
+
+if ENABLE_ELASTICSEARCH
+DISTCHECK_CONFIGURE_FLAGS+= --enable-elasticsearch
+endif
+if ENABLE_ELASTICSEARCH_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-elasticsearch-tests
+endif
+
+if ENABLE_CLICKHOUSE
+DISTCHECK_CONFIGURE_FLAGS+= --enable-clickhouse
+endif
+if ENABLE_CLICKHOUSE_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-clickhouse-tests
+endif
+
+if ENABLE_MMGROK
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmgrok
+endif
+
+if ENABLE_RELP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-relp --enable-omrelp-default-port=13515
+endif
+
+if ENABLE_IMKAFKA
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imkafka
+endif
+if ENABLE_OMKAFKA
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omkafka
+endif
+if ENABLE_KAFKA_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-kafka-tests
+endif
+
+if ENABLE_OMAZUREEVENTHUBS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omazureeventhubs
+endif
+
+if ENABLE_IMDTLS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imdtls
+endif
+
+if ENABLE_OMDTLS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omdtls
+endif
+
+if ENABLE_IMJOURNAL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imjournal
+endif
+if ENABLE_OMJOURNAL
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omjournal
+endif
+if ENABLE_JOURNAL_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-journal-tests
+endif
+
+if ENABLE_IMCZMQ
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imczmq
+endif
+if ENABLE_OMCZMQ
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omczmq
+endif
+
+if ENABLE_MMTAGHOSTNAME
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmtaghostname
+endif
+
+if ENABLE_IMTUXEDOULOG
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imtuxedolog
+endif
+
+if ENABLE_PMDB2DIAG
+DISTCHECK_CONFIGURE_FLAGS+= --enable-pmdb2diag
+endif
+
+if ENABLE_IMBATCHREPORT
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imbatchreport
+endif
+
+if ENABLE_IMFILE
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imfile
+endif
+
+if ENABLE_IMFILE_TESTS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imfile-tests
+else
+DISTCHECK_CONFIGURE_FLAGS+= --disable-imfile-tests
+endif
+
+if ENABLE_IMPCAP
+DISTCHECK_CONFIGURE_FLAGS+= --enable-impcap
+endif
+
+if ENABLE_IMDOCKER
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imdocker
+endif
+
+if ENABLE_OMRABBITMQ
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omrabbitmq
+endif
+
+if ENABLE_MMKUBERNETES
+DISTCHECK_CONFIGURE_FLAGS+= --enable-mmkubernetes
+endif
+
+if ENABLE_OMAMQP1
+DISTCHECK_CONFIGURE_FLAGS+= --enable-omamqp1
+endif
+
+if ENABLE_DISTCHECK_WORKAROUND
+DISTCHECK_CONFIGURE_FLAGS+= --disable-testbench
+else
+DISTCHECK_CONFIGURE_FLAGS+= --enable-testbench
+endif
+
+if ENABLE_IMHIREDIS
+DISTCHECK_CONFIGURE_FLAGS+= --enable-imhiredis
+endif
+
+dist-hook:
+ $(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
+
+ACLOCAL_AMFLAGS = -I m4
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..80682e2
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,1375 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+sbin_PROGRAMS =
+@ENABLE_RSYSLOGD_TRUE@am__append_1 = tools
+@ENABLE_IMKLOG_TRUE@am__append_2 = plugins/imklog
+@ENABLE_IMKMSG_TRUE@am__append_3 = contrib/imkmsg
+@ENABLE_IMPSTATS_TRUE@am__append_4 = plugins/impstats
+@ENABLE_IMSOLARIS_TRUE@am__append_5 = plugins/imsolaris
+@ENABLE_GSSAPI_TRUE@am__append_6 = plugins/omgssapi plugins/imgssapi
+@ENABLE_RELP_TRUE@am__append_7 = plugins/omrelp plugins/imrelp
+@ENABLE_OMFILE_HARDENED_TRUE@am__append_8 = contrib/omfile-hardened
+@ENABLE_MYSQL_TRUE@am__append_9 = plugins/ommysql
+@ENABLE_OMLIBDBI_TRUE@am__append_10 = plugins/omlibdbi
+@ENABLE_PGSQL_TRUE@am__append_11 = plugins/ompgsql
+@ENABLE_SNMP_TRUE@am__append_12 = plugins/omsnmp
+@ENABLE_OMSTDOUT_TRUE@am__append_13 = plugins/omstdout
+@ENABLE_PMCISCONAMES_TRUE@am__append_14 = contrib/pmcisconames
+@ENABLE_PMCISCOIOS_TRUE@am__append_15 = plugins/pmciscoios
+@ENABLE_PMNULL_TRUE@am__append_16 = plugins/pmnull
+@ENABLE_PMNORMALIZE_TRUE@am__append_17 = plugins/pmnormalize
+@ENABLE_PMAIXFORWARDEDFROM_TRUE@am__append_18 = contrib/pmaixforwardedfrom
+@ENABLE_PMSNARE_TRUE@am__append_19 = contrib/pmsnare
+@ENABLE_PMPANNGFW_TRUE@am__append_20 = contrib/pmpanngfw
+@ENABLE_PMLASTMSG_TRUE@am__append_21 = plugins/pmlastmsg
+@ENABLE_OMRULESET_TRUE@am__append_22 = plugins/omruleset
+@ENABLE_OMUDPSPOOF_TRUE@am__append_23 = plugins/omudpspoof
+@ENABLE_OMMONGODB_TRUE@am__append_24 = plugins/ommongodb
+@ENABLE_OMHIREDIS_TRUE@am__append_25 = contrib/omhiredis
+@ENABLE_OMCZMQ_TRUE@am__append_26 = contrib/omczmq
+@ENABLE_OMRABBITMQ_TRUE@am__append_27 = contrib/omrabbitmq
+@ENABLE_IMCZMQ_TRUE@am__append_28 = contrib/imczmq
+@ENABLE_OMUXSOCK_TRUE@am__append_29 = plugins/omuxsock
+@ENABLE_OMHDFS_TRUE@am__append_30 = plugins/omhdfs
+@ENABLE_OMJOURNAL_TRUE@am__append_31 = plugins/omjournal
+@ENABLE_IMJOURNAL_TRUE@am__append_32 = plugins/imjournal
+@ENABLE_ELASTICSEARCH_TRUE@am__append_33 = plugins/omelasticsearch
+@ENABLE_CLICKHOUSE_TRUE@am__append_34 = plugins/omclickhouse
+@ENABLE_OMHTTP_TRUE@am__append_35 = contrib/omhttp
+@ENABLE_SNMP_TRUE@am__append_36 = plugins/omsnmp
+@ENABLE_MMSNMPTRAPD_TRUE@am__append_37 = plugins/mmsnmptrapd
+@ENABLE_IMFILE_TRUE@am__append_38 = plugins/imfile
+@ENABLE_IMDOCKER_TRUE@am__append_39 = contrib/imdocker
+@ENABLE_IMPTCP_TRUE@am__append_40 = plugins/imptcp
+@ENABLE_IMDIAG_TRUE@am__append_41 = plugins/imdiag
+@ENABLE_MAIL_TRUE@am__append_42 = plugins/ommail
+@ENABLE_FMHTTP_TRUE@am__append_43 = plugins/fmhttp
+@ENABLE_FMHASH_TRUE@am__append_44 = contrib/fmhash
+@ENABLE_FMUNFLATTEN_TRUE@am__append_45 = contrib/fmunflatten
+@ENABLE_FFAUP_TRUE@am__append_46 = contrib/ffaup
+@ENABLE_OMKAFKA_TRUE@am__append_47 = plugins/omkafka
+@ENABLE_IMKAFKA_TRUE@am__append_48 = plugins/imkafka
+@ENABLE_OMAZUREEVENTHUBS_TRUE@am__append_49 = plugins/omazureeventhubs
+@ENABLE_IMDTLS_TRUE@am__append_50 = plugins/imdtls
+@ENABLE_OMDTLS_TRUE@am__append_51 = plugins/omdtls
+@ENABLE_OMPROG_TRUE@am__append_52 = plugins/omprog
+@ENABLE_RFC3195_TRUE@am__append_53 = plugins/im3195
+@ENABLE_MMNORMALIZE_TRUE@am__append_54 = plugins/mmnormalize
+@ENABLE_MMJSONPARSE_TRUE@am__append_55 = plugins/mmjsonparse
+@ENABLE_MMGROK_TRUE@am__append_56 = contrib/mmgrok
+@ENABLE_MMAUDIT_TRUE@am__append_57 = plugins/mmaudit
+@ENABLE_MMANON_TRUE@am__append_58 = plugins/mmanon
+@ENABLE_MMRM1STSPACE_TRUE@am__append_59 = plugins/mmrm1stspace
+@ENABLE_MMUTF8FIX_TRUE@am__append_60 = plugins/mmutf8fix
+@ENABLE_MMCOUNT_TRUE@am__append_61 = contrib/mmcount
+@ENABLE_MMSEQUENCE_TRUE@am__append_62 = contrib/mmsequence
+@ENABLE_MMDBLOOKUP_TRUE@am__append_63 = plugins/mmdblookup
+@ENABLE_MMDARWIN_TRUE@am__append_64 = contrib/mmdarwin
+@ENABLE_MMFIELDS_TRUE@am__append_65 = plugins/mmfields
+@ENABLE_MMPSTRUCDATA_TRUE@am__append_66 = plugins/mmpstrucdata
+@ENABLE_MMRFC5424ADDHMAC_TRUE@am__append_67 = contrib/mmrfc5424addhmac
+
+# omhttpfs
+@ENABLE_OMHTTPFS_TRUE@am__append_68 = contrib/omhttpfs
+
+# omamqp1
+@ENABLE_OMAMQP1_TRUE@am__append_69 = contrib/omamqp1
+
+# imbatchreport
+@ENABLE_IMBATCHREPORT_TRUE@am__append_70 = contrib/imbatchreport
+
+# omtcl
+@ENABLE_OMTCL_TRUE@am__append_71 = contrib/omtcl
+
+# mmkubernetes
+@ENABLE_MMKUBERNETES_TRUE@am__append_72 = contrib/mmkubernetes
+
+# impcap
+@ENABLE_IMPCAP_TRUE@am__append_73 = contrib/impcap
+
+# imtuxedoulog
+@ENABLE_IMTUXEDOULOG_TRUE@am__append_74 = contrib/imtuxedoulog
+
+# improg
+@ENABLE_IMPROG_TRUE@am__append_75 = contrib/improg
+
+# imhttp
+@ENABLE_IMHTTP_TRUE@am__append_76 = contrib/imhttp
+
+# mmtaghostname
+@ENABLE_MMTAGHOSTNAME_TRUE@am__append_77 = contrib/mmtaghostname
+
+# imdb2diag
+@ENABLE_PMDB2DIAG_TRUE@am__append_78 = contrib/pmdb2diag
+
+# imhiredis
+@ENABLE_IMHIREDIS_TRUE@am__append_79 = contrib/imhiredis
+# currently not supported in make distcheck:
+# --enable-pgsql-tests
+# --enable-extended-tests --> should probably never be enabled due to runtime
+@ENABLE_DEFAULT_TESTS_TRUE@am__append_80 = \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-diagtools \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-impstats \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-imptcp \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-klog \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mail \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmanon \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmaudit \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmcount \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmexternal \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmfields \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmjsonparse \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmpstrucdata \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmrm1stspace \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmsequence \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-mmutf8fix \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-omruleset \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-omuxsock \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmaixforwardedfrom \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmciscoios \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmcisconames \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmlastmsg \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmnull \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-pmsnare \
+@ENABLE_DEFAULT_TESTS_TRUE@ --enable-usertools
+
+@ENABLE_DEFAULT_TESTS_FALSE@am__append_81 = \
+@ENABLE_DEFAULT_TESTS_FALSE@ --disable-default-tests
+
+@ENABLE_IMPROG_TRUE@am__append_82 = --enable-improg
+@ENABLE_IMHTTP_TRUE@am__append_83 = --enable-imhttp
+@ENABLE_OMPROG_TRUE@am__append_84 = --enable-omprog
+@ENABLE_GSSAPI_TRUE@am__append_85 = --enable-gssapi-krb5
+@ENABLE_PMNORMALIZE_TRUE@am__append_86 = --enable-pmnormalize
+@ENABLE_MMDBLOOKUP_TRUE@am__append_87 = --enable-mmdblookup
+@ENABLE_MMDARWIN_TRUE@am__append_88 = --enable-mmdarwin
+@ENABLE_MMNORMALIZE_TRUE@am__append_89 = --enable-mmnormalize
+@ENABLE_OMMONGODB_TRUE@am__append_90 = --enable-ommongodb
+@ENABLE_OMHIREDIS_TRUE@am__append_91 = --enable-omhiredis
+@ENABLE_MMSNMPTRAPD_TRUE@am__append_92 = --enable-mmsnmptrapd
+@ENABLE_OMLIBDBI_TRUE@am__append_93 = --enable-libdbi
+@ENABLE_LIBGCRYPT_TRUE@am__append_94 = --enable-libgcrypt
+@ENABLE_OMHTTP_TRUE@am__append_95 = --enable-omhttp
+@ENABLE_OMHTTPFS_TRUE@am__append_96 = --enable-omhttpfs
+@ENABLE_OMTCL_TRUE@am__append_97 = --enable-omtcl
+@ENABLE_SNMP_TRUE@am__append_98 = --enable-snmp
+@ENABLE_SNMP_TESTS_TRUE@am__append_99 = --enable-snmp-tests
+@ENABLE_FMHTTP_TRUE@am__append_100 = --enable-fmhttp
+@ENABLE_OMUDPSPOOF_TRUE@am__append_101 = --enable-omudpspoof
+@ENABLE_PGSQL_TRUE@am__append_102 = --enable-pgsql
+@ENABLE_GNUTLS_TRUE@am__append_103 = --enable-gnutls
+@ENABLE_GNUTLS_TESTS_TRUE@am__append_104 = --enable-gnutls-tests
+@ENABLE_GNUTLS_TESTS_FALSE@am__append_105 = --disable-gnutls-tests
+@ENABLE_OPENSSL_TRUE@am__append_106 = --enable-openssl
+@ENABLE_MYSQL_TRUE@am__append_107 = --enable-mysql
+@ENABLE_MYSQL_TESTS_TRUE@am__append_108 = --enable-mysql-tests
+@ENABLE_ELASTICSEARCH_TRUE@am__append_109 = --enable-elasticsearch
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@am__append_110 = --enable-elasticsearch-tests
+@ENABLE_CLICKHOUSE_TRUE@am__append_111 = --enable-clickhouse
+@ENABLE_CLICKHOUSE_TESTS_TRUE@am__append_112 = --enable-clickhouse-tests
+@ENABLE_MMGROK_TRUE@am__append_113 = --enable-mmgrok
+@ENABLE_RELP_TRUE@am__append_114 = --enable-relp --enable-omrelp-default-port=13515
+@ENABLE_IMKAFKA_TRUE@am__append_115 = --enable-imkafka
+@ENABLE_OMKAFKA_TRUE@am__append_116 = --enable-omkafka
+@ENABLE_KAFKA_TESTS_TRUE@am__append_117 = --enable-kafka-tests
+@ENABLE_OMAZUREEVENTHUBS_TRUE@am__append_118 = --enable-omazureeventhubs
+@ENABLE_IMDTLS_TRUE@am__append_119 = --enable-imdtls
+@ENABLE_OMDTLS_TRUE@am__append_120 = --enable-omdtls
+@ENABLE_IMJOURNAL_TRUE@am__append_121 = --enable-imjournal
+@ENABLE_OMJOURNAL_TRUE@am__append_122 = --enable-omjournal
+@ENABLE_JOURNAL_TESTS_TRUE@am__append_123 = --enable-journal-tests
+@ENABLE_IMCZMQ_TRUE@am__append_124 = --enable-imczmq
+@ENABLE_OMCZMQ_TRUE@am__append_125 = --enable-omczmq
+@ENABLE_MMTAGHOSTNAME_TRUE@am__append_126 = --enable-mmtaghostname
+@ENABLE_IMTUXEDOULOG_TRUE@am__append_127 = --enable-imtuxedolog
+@ENABLE_PMDB2DIAG_TRUE@am__append_128 = --enable-pmdb2diag
+@ENABLE_IMBATCHREPORT_TRUE@am__append_129 = --enable-imbatchreport
+@ENABLE_IMFILE_TRUE@am__append_130 = --enable-imfile
+@ENABLE_IMFILE_TESTS_TRUE@am__append_131 = --enable-imfile-tests
+@ENABLE_IMFILE_TESTS_FALSE@am__append_132 = --disable-imfile-tests
+@ENABLE_IMPCAP_TRUE@am__append_133 = --enable-impcap
+@ENABLE_IMDOCKER_TRUE@am__append_134 = --enable-imdocker
+@ENABLE_OMRABBITMQ_TRUE@am__append_135 = --enable-omrabbitmq
+@ENABLE_MMKUBERNETES_TRUE@am__append_136 = --enable-mmkubernetes
+@ENABLE_OMAMQP1_TRUE@am__append_137 = --enable-omamqp1
+@ENABLE_DISTCHECK_WORKAROUND_TRUE@am__append_138 = --disable-testbench
+@ENABLE_DISTCHECK_WORKAROUND_FALSE@am__append_139 = --enable-testbench
+@ENABLE_IMHIREDIS_TRUE@am__append_140 = --enable-imhiredis
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+ $(am__configure_deps) $(am__DIST_COMMON)
+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__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)"
+PROGRAMS = $(sbin_PROGRAMS)
+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; }; \
+ }
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+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 distdir-am dist dist-all distcheck
+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
+DIST_SUBDIRS = compat runtime grammar . plugins/immark \
+ plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting \
+ plugins/mmexternal tools plugins/imklog contrib/imkmsg \
+ plugins/impstats plugins/imsolaris plugins/omgssapi \
+ plugins/imgssapi plugins/omrelp plugins/imrelp \
+ contrib/omfile-hardened plugins/ommysql plugins/omlibdbi \
+ plugins/ompgsql plugins/omsnmp plugins/omstdout \
+ contrib/pmcisconames plugins/pmciscoios plugins/pmnull \
+ plugins/pmnormalize contrib/pmaixforwardedfrom contrib/pmsnare \
+ contrib/pmpanngfw plugins/pmlastmsg plugins/omruleset \
+ plugins/omudpspoof plugins/ommongodb contrib/omhiredis \
+ contrib/omczmq contrib/omrabbitmq contrib/imczmq \
+ plugins/omuxsock plugins/omhdfs plugins/omjournal \
+ plugins/imjournal plugins/omelasticsearch plugins/omclickhouse \
+ contrib/omhttp plugins/mmsnmptrapd plugins/imfile \
+ contrib/imdocker plugins/imptcp plugins/imdiag plugins/ommail \
+ plugins/fmhttp contrib/fmhash contrib/fmunflatten \
+ contrib/ffaup plugins/omkafka plugins/imkafka \
+ plugins/omazureeventhubs plugins/imdtls plugins/omdtls \
+ plugins/omprog plugins/im3195 plugins/mmnormalize \
+ plugins/mmjsonparse contrib/mmgrok plugins/mmaudit \
+ plugins/mmanon plugins/mmrm1stspace plugins/mmutf8fix \
+ contrib/mmcount contrib/mmsequence plugins/mmdblookup \
+ contrib/mmdarwin plugins/mmfields plugins/mmpstrucdata \
+ contrib/mmrfc5424addhmac contrib/omhttpfs contrib/omamqp1 \
+ contrib/imbatchreport contrib/omtcl contrib/mmkubernetes \
+ contrib/impcap contrib/imtuxedoulog contrib/improg \
+ contrib/imhttp contrib/mmtaghostname contrib/pmdb2diag \
+ contrib/imhiredis tests
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \
+ COPYING COPYING.LESSER ChangeLog INSTALL NEWS README compile \
+ config.guess config.sub depcomp install-sh ltmain.sh missing \
+ ylwrap
+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
+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@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES =
+pkgconfigdir = $(libdir)/pkgconfig
+EXTRA_DIST = \
+ README.md \
+ platform/README \
+ platform/freebsd/rsyslogd \
+ platform/slackware/rc.rsyslogd \
+ platform/redhat/rsyslog.conf \
+ contrib/README \
+ CONTRIBUTING.md \
+ COPYING \
+ COPYING.LESSER \
+ COPYING.ASL20 \
+ contrib/gnutls/ca.pem \
+ contrib/gnutls/cert.pem \
+ contrib/gnutls/key.pem
+
+# external plugin driver is always enabled (core component)
+
+# tests are added as last element, because tests may need different
+# modules that need to be generated first
+SUBDIRS = compat runtime grammar . plugins/immark plugins/imuxsock \
+ plugins/imtcp plugins/imudp plugins/omtesting \
+ plugins/mmexternal $(am__append_1) $(am__append_2) \
+ $(am__append_3) $(am__append_4) $(am__append_5) \
+ $(am__append_6) $(am__append_7) $(am__append_8) \
+ $(am__append_9) $(am__append_10) $(am__append_11) \
+ $(am__append_12) $(am__append_13) $(am__append_14) \
+ $(am__append_15) $(am__append_16) $(am__append_17) \
+ $(am__append_18) $(am__append_19) $(am__append_20) \
+ $(am__append_21) $(am__append_22) $(am__append_23) \
+ $(am__append_24) $(am__append_25) $(am__append_26) \
+ $(am__append_27) $(am__append_28) $(am__append_29) \
+ $(am__append_30) $(am__append_31) $(am__append_32) \
+ $(am__append_33) $(am__append_34) $(am__append_35) \
+ $(am__append_36) $(am__append_37) $(am__append_38) \
+ $(am__append_39) $(am__append_40) $(am__append_41) \
+ $(am__append_42) $(am__append_43) $(am__append_44) \
+ $(am__append_45) $(am__append_46) $(am__append_47) \
+ $(am__append_48) $(am__append_49) $(am__append_50) \
+ $(am__append_51) $(am__append_52) $(am__append_53) \
+ $(am__append_54) $(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_65) \
+ $(am__append_66) $(am__append_67) $(am__append_68) \
+ $(am__append_69) $(am__append_70) $(am__append_71) \
+ $(am__append_72) $(am__append_73) $(am__append_74) \
+ $(am__append_75) $(am__append_76) $(am__append_77) \
+ $(am__append_78) $(am__append_79) tests
+# make sure "make distcheck" tries to build all modules. This means that
+# a developer must always have an environment where every supporting library
+# is available. If that is not the case, the respective configure option may
+# temporarily be removed below. The intent behind forcing everthing to compile
+# in a make distcheck is so that we detect code that accidently was not updated
+# when some global update happened.
+DISTCHECK_CONFIGURE_FLAGS = --enable-silent-rules --enable-rsyslogd \
+ --enable-omstdout --enable-imdiag --enable-testbench \
+ --enable-valgrind $(am__append_80) $(am__append_81) \
+ $(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_93) \
+ $(am__append_94) $(am__append_95) $(am__append_96) \
+ $(am__append_97) $(am__append_98) $(am__append_99) \
+ $(am__append_100) $(am__append_101) $(am__append_102) \
+ $(am__append_103) $(am__append_104) $(am__append_105) \
+ $(am__append_106) $(am__append_107) $(am__append_108) \
+ $(am__append_109) $(am__append_110) $(am__append_111) \
+ $(am__append_112) $(am__append_113) $(am__append_114) \
+ $(am__append_115) $(am__append_116) $(am__append_117) \
+ $(am__append_118) $(am__append_119) $(am__append_120) \
+ $(am__append_121) $(am__append_122) $(am__append_123) \
+ $(am__append_124) $(am__append_125) $(am__append_126) \
+ $(am__append_127) $(am__append_128) $(am__append_129) \
+ $(am__append_130) $(am__append_131) $(am__append_132) \
+ $(am__append_133) $(am__append_134) $(am__append_135) \
+ $(am__append_136) $(am__append_137) $(am__append_138) \
+ $(am__append_139) $(am__append_140)
+ACLOCAL_AMFLAGS = -I m4
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) 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) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu 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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+ 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-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
+
+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}; \
+ }
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+ -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) | eval GZIP= gzip $(GZIP_ENV) -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 distribution archives compressed with" \
+ "legacy program 'compress' 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 shar distribution archives is" \
+ "deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -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*) \
+ eval GZIP= gzip $(GZIP_ENV) -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*) \
+ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_build/sub $(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/sub \
+ && ../../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 $(PROGRAMS) $(LTLIBRARIES) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+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 clean-pkglibLTLIBRARIES \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+ 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: install-pkglibLTLIBRARIES install-sbinPROGRAMS
+
+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
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
+
+.MAKE: $(am__recursive_targets) all install-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 clean-pkglibLTLIBRARIES clean-sbinPROGRAMS \
+ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \
+ dist-zip distcheck distclean 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-info install-info-am install-man \
+ 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-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am \
+ uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+dist-hook:
+ $(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
+
+# 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
index 0000000..61bad1e
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+This file has been superseded by ChangeLog. Please see there.
diff --git a/README b/README
new file mode 100644
index 0000000..3a5ec95
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+see README.md -- this file here is just required for autotools
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cec64af
--- /dev/null
+++ b/README.md
@@ -0,0 +1,188 @@
+Rsyslog - what is it?
+=====================
+
+[![Help Contribute to Open Source](https://www.codetriage.com/rsyslog/rsyslog/badges/users.svg)](https://www.codetriage.com/rsyslog/rsyslog)
+
+Rsyslog is a **r**ocket-fast **sys**tem for **log** processing.
+
+It offers high-performance, great security features and a modular design.
+While it started as a regular syslogd, rsyslog has evolved into a kind of swiss
+army knife of logging, being able to accept inputs from a wide variety of sources,
+transform them, and output to the results to diverse destinations.
+
+Rsyslog can deliver over one million messages per second to local destinations
+when limited processing is applied (based on v7, December 2013). Even with
+remote destinations and more elaborate processing the performance is usually
+considered "stunning".
+
+Mailing List
+============
+http://lists.adiscon.net/mailman/listinfo/rsyslog
+
+Installing rsyslog
+==================
+Most distributions carry rsyslog in their repository. So you usually just need
+to use the package manager to install it. Note that on non-systemd systems (most
+notably Ubuntu), rsyslog usually is already installed.
+
+Project-Provided Packages
+----------------------------
+Unfortunately, distributions often do not catch up with the pace of rsyslog
+development and as such only offer old versions. To solve that problem, we have
+created packages for current versions ourselves.
+
+They are available for:
+ * RPM-based systems: https://www.rsyslog.com/rhelcentos-rpms/
+ * Ubuntu: https://www.rsyslog.com/ubuntu-repository/
+ * Debian: https://www.rsyslog.com/debian-repository/
+
+Building from Source
+--------------------
+Follow the instructions at: https://www.rsyslog.com/doc/v8-stable/installation/build_from_repo.html
+
+### Build Environment
+
+In general, you need
+
+* pkg-config
+* libestr
+* liblogging (stdlog component, for testbench)
+
+It is best to build these from source.
+
+#### CentOS 6 / RHEL
+
+For json-c, we need:
+```
+export PKG_CONFIG_PATH=/lib64/pkgconfig/
+```
+
+```
+sudo yum install git valgrind autoconf automake flex bison python-docutils python-sphinx json-c-devel libuuid-devel libgcrypt-devel zlib-devel openssl-devel libcurl-devel gnutls-devel mysql-devel postgresql-devel libdbi-dbd-mysql libdbi-devel net-snmp-devel
+```
+
+#### Ubuntu
+
+Add Adiscon repository:
+```
+apt-get update && apt-get install -y software-properties-common
+add-apt-repository -y ppa:adiscon/v8-stable
+```
+
+*Note:* if you are a developer who wants to work with git master branch,
+adding the Adiscon repository is probably not a good idea. It then
+is better to also compile the supporting libraries from source, because
+newer versions of rsyslog may need newer versions of the libraries than
+there are in the repositories.
+Libraries in question are at least: libestr, liblognorm, libfastjson.
+
+Needed packages to build with omhiredis support:
+```
+apt-get update && apt-get install -y build-essential pkg-config libestr-dev libfastjson-dev zlib1g-dev uuid-dev libgcrypt20-dev libhiredis-dev uuid-dev libgcrypt11-dev liblogging-stdlog-dev flex bison
+```
+
+Aditional packages for other modules:
+```
+libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev libmongo-client-dev
+```
+
+For KSI, from the Adiscon PPA:
+```
+sudo apt-get install libksi0 libksi-devel
+```
+
+#### Debian
+
+```
+sudo apt install build-essential pkg-config libestr-dev libfastjson-dev zlib1g-dev uuid-dev libgcrypt20-dev libcurl4-gnutls-dev zlib1g-dev liblogging-stdlog-dev flex bison
+```
+
+*Note:* For certain libraries version requirements might be higher,
+in that case adding debian backports repositories might help.
+For example installing with apt libfastjson-dev -t stretch-backports.
+
+
+Aditional packages for other modules:
+```
+libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev libmongo-client-dev
+```
+
+
+
+#### openSUSE 13
+
+```
+sudo zypper install gcc make autoconf automake libtool libcurl-devel flex bison valgrind python-docutils libjson-devel uuid-devel libgcrypt-devel libgnutls-devel libmysqlclient-devel libdbi-devel libnet-devel postgresql-devel net-snmp-devellibuuid-devel libdbi-drivers-dbd-mysql
+```
+
+For the testbench VMs:
+```
+sudo zypper install gvim mutt
+```
+
+#### SUSE LINUX Enterprise Server 11
+
+Available packages:
+```
+zypper install gcc make autoconf libtool flex bison
+```
+
+Missing packages:
+```
+libcurl-devel valgrind python-docutils uuid-devel libgcrypt-devel libgnutls-devel libmysqlclient-devel libdbi-devel postgresql-devel net-snmp-devel libdbi-drivers-dbd-mysql json-c zlib-dev libdbi
+```
+
+Reporting Bugs
+==============
+
+Talk to the mailing list if you think something is a bug. Often, it's just a
+matter of doing some config trickery.
+
+File bugs at: https://github.com/rsyslog/rsyslog/issues
+
+How to Contribute
+=================
+Contributions to rsyslog are very welcome. Fork and send us your Pull Requests.
+
+For more information about contributing, see the
+[CONTRIBUTING](CONTRIBUTING.md) file.
+
+Note that it is easy to add output plugins using languages like Python or
+Perl. So if you need to connect to a system which is not yet supported, you
+can easily do so via an external plugin. For more information see the
+[README](plugins/external/README.md) file in the external plugin directory.
+
+Documentation
+=============
+The main rsyslog documentation is available in HTML format. To read
+it, point your web browser to ./doc/manual.html. Alternatively,
+you can view the documentation for *the most recent rsyslog version*
+online at: https://www.rsyslog.com/doc/
+
+Project Philosophy
+==================
+We are an open source project in all aspects and very open to outside feedback
+and contribution. We base our work on standards and try to solve all real-world
+needs (of course, we occasionally fail tackling actually all needs ;)). While
+the project is primarily sponsored by Adiscon, technical development is
+independent from company goals and most decisions are solely based on mailing
+list discussion results. There is an active community around rsyslog.
+
+There is no such thing like being an official member of the rsyslog team. The
+closest to that is being subscribed to the mailing list:
+http://lists.adiscon.net/mailman/listinfo/rsyslog
+
+This method of open discussions is modelled after the IETF process, which is
+probably the best-known and most successive collaborative standards body.
+
+Project Funding
+===============
+Rsyslog's main sponsor Adiscon tries to fund rsyslog by selling custom
+development and support contracts. Adiscon does NOT license rsyslog under a
+commercial license (this is simply impossible for anyone due to rsyslog's
+license structure).
+
+Any third party is obviously also free to offer custom development, support
+and rsyslog consulting. We gladly merge results of such third-party work into
+the main repository (assuming it matches the few essential things written
+down in our contribution policy).
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..c65dfe1
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,5982 @@
+# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2018 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'.])])
+
+# ============================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# For every FLAG1, FLAG2 it is checked whether the compiler works with the
+# flag. If it does, the flag is added FLAGS-VARIABLE
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. During the check the flag is always added to the
+# current language's flags.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: This macro depends on the AX_APPEND_FLAG and
+# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
+# AX_APPEND_LINK_FLAGS.
+#
+# LICENSE
+#
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+ AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
+done
+])dnl AX_APPEND_COMPILE_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+# added in between.
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
+# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+# FLAG.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 any
+# warranty.
+
+#serial 8
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+ AS_CASE([" AS_VAR_GET(FLAGS) "],
+ [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+ [
+ AS_VAR_APPEND(FLAGS,[" $1"])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+ ],
+ [
+ AS_VAR_SET(FLAGS,[$1])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# For every FLAG1, FLAG2 it is checked whether the linker works with the
+# flag. If it does, the flag is added FLAGS-VARIABLE
+#
+# If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
+# used. During the check the flag is always added to the linker's flags.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
+# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
+#
+# LICENSE
+#
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_APPEND_LINK_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+ AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
+done
+])dnl AX_APPEND_LINK_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the linker or gives an error.
+# (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $4 $1"
+ AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_FLAGS([CFLAGS-VARIABLE], [LDFLAGS-VARIABLE], [IS-RELEASE], [EXTRA-BASE-CFLAGS], [EXTRA-YES-CFLAGS], [UNUSED], [UNUSED], [UNUSED], [EXTRA-BASE-LDFLAGS], [EXTRA-YES-LDFLAGS], [UNUSED], [UNUSED], [UNUSED])
+#
+# DESCRIPTION
+#
+# Check for the presence of an --enable-compile-warnings option to
+# configure, defaulting to "error" in normal operation, or "yes" if
+# IS-RELEASE is equal to "yes". Return the value in the variable
+# $ax_enable_compile_warnings.
+#
+# Depending on the value of --enable-compile-warnings, different compiler
+# warnings are checked to see if they work with the current compiler and,
+# if so, are appended to CFLAGS-VARIABLE and LDFLAGS-VARIABLE. This
+# allows a consistent set of baseline compiler warnings to be used across
+# a code base, irrespective of any warnings enabled locally by individual
+# developers. By standardising the warnings used by all developers of a
+# project, the project can commit to a zero-warnings policy, using -Werror
+# to prevent compilation if new warnings are introduced. This makes
+# catching bugs which are flagged by warnings a lot easier.
+#
+# By providing a consistent --enable-compile-warnings argument across all
+# projects using this macro, continuous integration systems can easily be
+# configured the same for all projects. Automated systems or build
+# systems aimed at beginners may want to pass the --disable-Werror
+# argument to unconditionally prevent warnings being fatal.
+#
+# --enable-compile-warnings can take the values:
+#
+# * no: Base compiler warnings only; not even -Wall.
+# * yes: The above, plus a broad range of useful warnings.
+# * error: The above, plus -Werror so that all warnings are fatal.
+# Use --disable-Werror to override this and disable fatal
+# warnings.
+#
+# The set of base and enabled flags can be augmented using the
+# EXTRA-*-CFLAGS and EXTRA-*-LDFLAGS variables, which are tested and
+# appended to the output variable if --enable-compile-warnings is not
+# "no". Flags should not be disabled using these arguments, as the entire
+# point of AX_COMPILER_FLAGS is to enforce a consistent set of useful
+# compiler warnings on code, using warnings which have been chosen for low
+# false positive rates. If a compiler emits false positives for a
+# warning, a #pragma should be used in the code to disable the warning
+# locally. See:
+#
+# https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
+#
+# The EXTRA-* variables should only be used to supply extra warning flags,
+# and not general purpose compiler flags, as they are controlled by
+# configure options such as --disable-Werror.
+#
+# IS-RELEASE can be used to disable -Werror when making a release, which
+# is useful for those hairy moments when you just want to get the release
+# done as quickly as possible. Set it to "yes" to disable -Werror. By
+# default, it uses the value of $ax_is_release, so if you are using the
+# AX_IS_RELEASE macro, there is no need to pass this parameter. For
+# example:
+#
+# AX_IS_RELEASE([git-directory])
+# AX_COMPILER_FLAGS()
+#
+# CFLAGS-VARIABLE defaults to WARN_CFLAGS, and LDFLAGS-VARIABLE defaults
+# to WARN_LDFLAGS. Both variables are AC_SUBST-ed by this macro, but must
+# be manually added to the CFLAGS and LDFLAGS variables for each target in
+# the code base.
+#
+# If C++ language support is enabled with AC_PROG_CXX, which must occur
+# before this macro in configure.ac, warning flags for the C++ compiler
+# are AC_SUBST-ed as WARN_CXXFLAGS, and must be manually added to the
+# CXXFLAGS variables for each target in the code base. EXTRA-*-CFLAGS can
+# be used to augment the base and enabled flags.
+#
+# Warning flags for g-ir-scanner (from GObject Introspection) are
+# AC_SUBST-ed as WARN_SCANNERFLAGS. This variable must be manually added
+# to the SCANNERFLAGS variable for each GIR target in the code base. If
+# extra g-ir-scanner flags need to be enabled, the AX_COMPILER_FLAGS_GIR
+# macro must be invoked manually.
+#
+# AX_COMPILER_FLAGS may add support for other tools in future, in addition
+# to the compiler and linker. No extra EXTRA-* variables will be added
+# for those tools, and all extra support will still use the single
+# --enable-compile-warnings configure option. For finer grained control
+# over the flags for individual tools, use AX_COMPILER_FLAGS_CFLAGS,
+# AX_COMPILER_FLAGS_LDFLAGS and AX_COMPILER_FLAGS_* for new tools.
+#
+# The UNUSED variables date from a previous version of this macro, and are
+# automatically appended to the preceding non-UNUSED variable. They should
+# be left empty in new uses of the macro.
+#
+# LICENSE
+#
+# Copyright (c) 2014, 2015 Philip Withnall <philip@tecnocode.co.uk>
+# Copyright (c) 2015 David King <amigadave@amigadave.com>
+#
+# 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 any
+# warranty.
+
+#serial 14
+
+# _AX_COMPILER_FLAGS_LANG([LANGNAME])
+m4_defun([_AX_COMPILER_FLAGS_LANG],
+[m4_ifdef([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [],
+ [m4_define([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [])dnl
+ AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_]$1[FLAGS])])dnl
+])
+
+AC_DEFUN([AX_COMPILER_FLAGS],[
+ # C support is enabled by default.
+ _AX_COMPILER_FLAGS_LANG([C])
+ # Only enable C++ support if AC_PROG_CXX is called. The redefinition of
+ # AC_PROG_CXX is so that a fatal error is emitted if this macro is called
+ # before AC_PROG_CXX, which would otherwise cause no C++ warnings to be
+ # checked.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AX_COMPILER_FLAGS_LANG([CXX])],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AX_COMPILER_FLAGS_LANG([CXX])])])
+ AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_LDFLAGS])
+
+ # Default value for IS-RELEASE is $ax_is_release
+ ax_compiler_flags_is_release=m4_tolower(m4_normalize(ifelse([$3],,
+ [$ax_is_release],
+ [$3])))
+
+ AC_ARG_ENABLE([compile-warnings],
+ AS_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@],
+ [Enable compiler warnings and errors]),,
+ [AS_IF([test "$ax_compiler_flags_is_release" = "yes"],
+ [enable_compile_warnings="yes"],
+ [enable_compile_warnings="error"])])
+ AC_ARG_ENABLE([Werror],
+ AS_HELP_STRING([--disable-Werror],
+ [Unconditionally make all compiler warnings non-fatal]),,
+ [enable_Werror=maybe])
+
+ # Return the user's chosen warning level
+ AS_IF([test "$enable_Werror" = "no" -a \
+ "$enable_compile_warnings" = "error"],[
+ enable_compile_warnings="yes"
+ ])
+
+ ax_enable_compile_warnings=$enable_compile_warnings
+
+ AX_COMPILER_FLAGS_CFLAGS([$1],[$ax_compiler_flags_is_release],
+ [$4],[$5 $6 $7 $8])
+ m4_ifdef([_AX_COMPILER_FLAGS_LANG_CXX_enabled],
+ [AX_COMPILER_FLAGS_CXXFLAGS([WARN_CXXFLAGS],
+ [$ax_compiler_flags_is_release],
+ [$4],[$5 $6 $7 $8])])
+ AX_COMPILER_FLAGS_LDFLAGS([$2],[$ax_compiler_flags_is_release],
+ [$9],[$10 $11 $12 $13])
+ AX_COMPILER_FLAGS_GIR([WARN_SCANNERFLAGS],[$ax_compiler_flags_is_release])
+])dnl AX_COMPILER_FLAGS
+
+# =============================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cflags.html
+# =============================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_FLAGS_CFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+# Add warning flags for the C compiler to VARIABLE, which defaults to
+# WARN_CFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be
+# manually added to the CFLAGS variable for each target in the code base.
+#
+# This macro depends on the environment set up by AX_COMPILER_FLAGS.
+# Specifically, it uses the value of $ax_enable_compile_warnings to decide
+# which flags to enable.
+#
+# LICENSE
+#
+# Copyright (c) 2014, 2015 Philip Withnall <philip@tecnocode.co.uk>
+# Copyright (c) 2017, 2018 Reini Urban <rurban@cpan.org>
+#
+# 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 any
+# warranty.
+
+#serial 17
+
+AC_DEFUN([AX_COMPILER_FLAGS_CFLAGS],[
+ AC_REQUIRE([AC_PROG_SED])
+ AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
+ AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+ AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+
+ # Variable names
+ m4_define([ax_warn_cflags_variable],
+ [m4_normalize(ifelse([$1],,[WARN_CFLAGS],[$1]))])
+
+ AC_LANG_PUSH([C])
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+ [#ifndef __cplusplus
+ #error "no C++"
+ #endif]])],
+ [ax_compiler_cxx=yes;],
+ [ax_compiler_cxx=no;])
+
+ # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+ # flags, otherwise they are always appended to the warn_cflags variable, and
+ # Clang warns on them for every compilation unit.
+ # If this is passed to GCC, it will explode, so the flag must be enabled
+ # conditionally.
+ AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+ ],[
+ ax_compiler_flags_test=""
+ ])
+
+ # Check that -Wno-suggest-attribute=format is supported
+ AX_CHECK_COMPILE_FLAG([-Wno-suggest-attribute=format],[
+ ax_compiler_no_suggest_attribute_flags="-Wno-suggest-attribute=format"
+ ],[
+ ax_compiler_no_suggest_attribute_flags=""
+ ])
+
+ # Base flags
+ AX_APPEND_COMPILE_FLAGS([ dnl
+ -fno-strict-aliasing dnl
+ $3 dnl
+ ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+
+ AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+ if test "$ax_compiler_cxx" = "no" ; then
+ # C-only flags. Warn in C++
+ AX_APPEND_COMPILE_FLAGS([ dnl
+ -Wnested-externs dnl
+ -Wmissing-prototypes dnl
+ -Wstrict-prototypes dnl
+ -Wdeclaration-after-statement dnl
+ -Wimplicit-function-declaration dnl
+ -Wold-style-definition dnl
+ -Wjump-misses-init dnl
+ ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+ fi
+
+ # "yes" flags
+ AX_APPEND_COMPILE_FLAGS([ dnl
+ -Wall dnl
+ -Wextra dnl
+ -Wundef dnl
+ -Wwrite-strings dnl
+ -Wpointer-arith dnl
+ -Wmissing-declarations dnl
+ -Wredundant-decls dnl
+ -Wno-unused-parameter dnl
+ -Wno-missing-field-initializers dnl
+ -Wformat=2 dnl
+ -Wcast-align dnl
+ -Wformat-nonliteral dnl
+ -Wformat-security dnl
+ -Wsign-compare dnl
+ -Wstrict-aliasing dnl
+ -Wshadow dnl
+ -Winline dnl
+ -Wpacked dnl
+ -Wmissing-format-attribute dnl
+ -Wmissing-noreturn dnl
+ -Winit-self dnl
+ -Wredundant-decls dnl
+ -Wmissing-include-dirs dnl
+ -Wunused-but-set-variable dnl
+ -Warray-bounds dnl
+ -Wreturn-type dnl
+ -Wswitch-enum dnl
+ -Wswitch-default dnl
+ -Wduplicated-cond dnl
+ -Wduplicated-branches dnl
+ -Wlogical-op dnl
+ -Wrestrict dnl
+ -Wnull-dereference dnl
+ -Wdouble-promotion dnl
+ $4 dnl
+ $5 dnl
+ $6 dnl
+ $7 dnl
+ ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+ ])
+ AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+ # "error" flags; -Werror has to be appended unconditionally because
+ # it's not possible to test for
+ #
+ # suggest-attribute=format is disabled because it gives too many false
+ # positives
+ AX_APPEND_FLAG([-Werror],ax_warn_cflags_variable)
+
+ AX_APPEND_COMPILE_FLAGS([ dnl
+ [$ax_compiler_no_suggest_attribute_flags] dnl
+ ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+ ])
+
+ # In the flags below, when disabling specific flags, always add *both*
+ # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example)
+ # we enable -Werror, disable a flag, and a build bot passes CFLAGS=-Wall,
+ # which effectively turns that flag back on again as an error.
+ for flag in $ax_warn_cflags_variable; do
+ AS_CASE([$flag],
+ [-Wno-*=*],[],
+ [-Wno-*],[
+ AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')],
+ ax_warn_cflags_variable,
+ [$ax_compiler_flags_test])
+ ])
+ done
+
+ AC_LANG_POP([C])
+
+ # Substitute the variables
+ AC_SUBST(ax_warn_cflags_variable)
+])dnl AX_COMPILER_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_gir.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_FLAGS_GIR([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+# Add warning flags for the g-ir-scanner (from GObject Introspection) to
+# VARIABLE, which defaults to WARN_SCANNERFLAGS. VARIABLE is AC_SUBST-ed
+# by this macro, but must be manually added to the SCANNERFLAGS variable
+# for each GIR target in the code base.
+#
+# This macro depends on the environment set up by AX_COMPILER_FLAGS.
+# Specifically, it uses the value of $ax_enable_compile_warnings to decide
+# which flags to enable.
+#
+# LICENSE
+#
+# Copyright (c) 2015 Philip Withnall <philip@tecnocode.co.uk>
+#
+# 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 any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_COMPILER_FLAGS_GIR],[
+ AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+
+ # Variable names
+ m4_define([ax_warn_scannerflags_variable],
+ [m4_normalize(ifelse([$1],,[WARN_SCANNERFLAGS],[$1]))])
+
+ # Base flags
+ AX_APPEND_FLAG([$3],ax_warn_scannerflags_variable)
+
+ AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+ # "yes" flags
+ AX_APPEND_FLAG([ dnl
+ --warn-all dnl
+ $4 dnl
+ $5 dnl
+ $6 dnl
+ $7 dnl
+ ],ax_warn_scannerflags_variable)
+ ])
+ AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+ # "error" flags
+ AX_APPEND_FLAG([ dnl
+ --warn-error dnl
+ ],ax_warn_scannerflags_variable)
+ ])
+
+ # Substitute the variables
+ AC_SUBST(ax_warn_scannerflags_variable)
+])dnl AX_COMPILER_FLAGS
+
+# ==============================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_ldflags.html
+# ==============================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_FLAGS_LDFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+# Add warning flags for the linker to VARIABLE, which defaults to
+# WARN_LDFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be
+# manually added to the LDFLAGS variable for each target in the code base.
+#
+# This macro depends on the environment set up by AX_COMPILER_FLAGS.
+# Specifically, it uses the value of $ax_enable_compile_warnings to decide
+# which flags to enable.
+#
+# LICENSE
+#
+# Copyright (c) 2014, 2015 Philip Withnall <philip@tecnocode.co.uk>
+# Copyright (c) 2017, 2018 Reini Urban <rurban@cpan.org>
+#
+# 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 any
+# warranty.
+
+#serial 9
+
+AC_DEFUN([AX_COMPILER_FLAGS_LDFLAGS],[
+ AX_REQUIRE_DEFINED([AX_APPEND_LINK_FLAGS])
+ AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+ AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+ AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+
+ # Variable names
+ m4_define([ax_warn_ldflags_variable],
+ [m4_normalize(ifelse([$1],,[WARN_LDFLAGS],[$1]))])
+
+ # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+ # flags, otherwise they are always appended to the warn_ldflags variable,
+ # and Clang warns on them for every compilation unit.
+ # If this is passed to GCC, it will explode, so the flag must be enabled
+ # conditionally.
+ AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+ ],[
+ ax_compiler_flags_test=""
+ ])
+
+ AX_CHECK_LINK_FLAG([-Wl,--as-needed], [
+ AX_APPEND_LINK_FLAGS([-Wl,--as-needed],
+ [AM_LDFLAGS],[$ax_compiler_flags_test])
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-z,relro], [
+ AX_APPEND_LINK_FLAGS([-Wl,-z,relro],
+ [AM_LDFLAGS],[$ax_compiler_flags_test])
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-z,now], [
+ AX_APPEND_LINK_FLAGS([-Wl,-z,now],
+ [AM_LDFLAGS],[$ax_compiler_flags_test])
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [
+ AX_APPEND_LINK_FLAGS([-Wl,-z,noexecstack],
+ [AM_LDFLAGS],[$ax_compiler_flags_test])
+ ])
+ # textonly, retpolineplt not yet
+
+ # macOS and cygwin linker do not have --as-needed
+ AX_CHECK_LINK_FLAG([-Wl,--no-as-needed], [
+ ax_compiler_flags_as_needed_option="-Wl,--no-as-needed"
+ ], [
+ ax_compiler_flags_as_needed_option=""
+ ])
+
+ # macOS linker speaks with a different accent
+ ax_compiler_flags_fatal_warnings_option=""
+ AX_CHECK_LINK_FLAG([-Wl,--fatal-warnings], [
+ ax_compiler_flags_fatal_warnings_option="-Wl,--fatal-warnings"
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-fatal_warnings], [
+ ax_compiler_flags_fatal_warnings_option="-Wl,-fatal_warnings"
+ ])
+
+ # Base flags
+ AX_APPEND_LINK_FLAGS([ dnl
+ $ax_compiler_flags_as_needed_option dnl
+ $3 dnl
+ ],ax_warn_ldflags_variable,[$ax_compiler_flags_test])
+
+ AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+ # "yes" flags
+ AX_APPEND_LINK_FLAGS([$4 $5 $6 $7],
+ ax_warn_ldflags_variable,
+ [$ax_compiler_flags_test])
+ ])
+ AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+ # "error" flags; -Werror has to be appended unconditionally because
+ # it's not possible to test for
+ #
+ # suggest-attribute=format is disabled because it gives too many false
+ # positives
+ AX_APPEND_LINK_FLAGS([ dnl
+ $ax_compiler_flags_fatal_warnings_option dnl
+ ],ax_warn_ldflags_variable,[$ax_compiler_flags_test])
+ ])
+
+ # Substitute the variables
+ AC_SUBST(ax_warn_ldflags_variable)
+])dnl AX_COMPILER_FLAGS
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_is_release.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_IS_RELEASE(POLICY)
+#
+# DESCRIPTION
+#
+# Determine whether the code is being configured as a release, or from
+# git. Set the ax_is_release variable to 'yes' or 'no'.
+#
+# If building a release version, it is recommended that the configure
+# script disable compiler errors and debug features, by conditionalising
+# them on the ax_is_release variable. If building from git, these
+# features should be enabled.
+#
+# The POLICY parameter specifies how ax_is_release is determined. It can
+# take the following values:
+#
+# * git-directory: ax_is_release will be 'no' if a '.git' directory exists
+# * minor-version: ax_is_release will be 'no' if the minor version number
+# in $PACKAGE_VERSION is odd; this assumes
+# $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+# * micro-version: ax_is_release will be 'no' if the micro version number
+# in $PACKAGE_VERSION is odd; this assumes
+# $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+# * dash-version: ax_is_release will be 'no' if there is a dash '-'
+# in $PACKAGE_VERSION, for example 1.2-pre3, 1.2.42-a8b9
+# or 2.0-dirty (in particular this is suitable for use
+# with git-version-gen)
+# * always: ax_is_release will always be 'yes'
+# * never: ax_is_release will always be 'no'
+#
+# Other policies may be added in future.
+#
+# LICENSE
+#
+# Copyright (c) 2015 Philip Withnall <philip@tecnocode.co.uk>
+# Copyright (c) 2016 Collabora Ltd.
+#
+# 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.
+
+#serial 7
+
+AC_DEFUN([AX_IS_RELEASE],[
+ AC_BEFORE([AC_INIT],[$0])
+
+ m4_case([$1],
+ [git-directory],[
+ # $is_release = (.git directory does not exist)
+ AS_IF([test -d ${srcdir}/.git],[ax_is_release=no],[ax_is_release=yes])
+ ],
+ [minor-version],[
+ # $is_release = ($minor_version is even)
+ minor_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'`
+ AS_IF([test "$(( $minor_version % 2 ))" -ne 0],
+ [ax_is_release=no],[ax_is_release=yes])
+ ],
+ [micro-version],[
+ # $is_release = ($micro_version is even)
+ micro_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]]*\.[[^.]]*\.\([[^.]]*\).*/\1/'`
+ AS_IF([test "$(( $micro_version % 2 ))" -ne 0],
+ [ax_is_release=no],[ax_is_release=yes])
+ ],
+ [dash-version],[
+ # $is_release = ($PACKAGE_VERSION has a dash)
+ AS_CASE([$PACKAGE_VERSION],
+ [*-*], [ax_is_release=no],
+ [*], [ax_is_release=yes])
+ ],
+ [always],[ax_is_release=yes],
+ [never],[ax_is_release=no],
+ [
+ AC_MSG_ERROR([Invalid policy. Valid policies: git-directory, minor-version, micro-version, dash-version, always, never.])
+ ])
+])
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_java.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_JAVA
+#
+# DESCRIPTION
+#
+# Here is a summary of the main macros:
+#
+# AX_PROG_JAVAC: finds a Java compiler.
+#
+# AX_PROG_JAVA: finds a Java virtual machine.
+#
+# AX_CHECK_CLASS: finds if we have the given class (beware of CLASSPATH!).
+#
+# AX_CHECK_RQRD_CLASS: finds if we have the given class and stops
+# otherwise.
+#
+# AX_TRY_COMPILE_JAVA: attempt to compile user given source.
+#
+# AX_TRY_RUN_JAVA: attempt to compile and run user given source.
+#
+# AX_JAVA_OPTIONS: adds Java configure options.
+#
+# AX_PROG_JAVA tests an existing Java virtual machine. It uses the
+# environment variable JAVA then tests in sequence various common Java
+# virtual machines. For political reasons, it starts with the free ones.
+# You *must* call [AX_PROG_JAVAC] before.
+#
+# If you want to force a specific VM:
+#
+# - at the configure.in level, set JAVA=yourvm before calling AX_PROG_JAVA
+#
+# (but after AC_INIT)
+#
+# - at the configure level, setenv JAVA
+#
+# You can use the JAVA variable in your Makefile.in, with @JAVA@.
+#
+# *Warning*: its success or failure can depend on a proper setting of the
+# CLASSPATH env. variable.
+#
+# TODO: allow to exclude virtual machines (rationale: most Java programs
+# cannot run with some VM like kaffe).
+#
+# Note: This is part of the set of autoconf M4 macros for Java programs.
+# It is VERY IMPORTANT that you download the whole set, some macros depend
+# on other. Unfortunately, the autoconf archive does not support the
+# concept of set of macros, so I had to break it for submission.
+#
+# A Web page, with a link to the latest CVS snapshot is at
+# <http://www.internatif.org/bortzmeyer/autoconf-Java/>.
+#
+# This is a sample configure.in Process this file with autoconf to produce
+# a configure script.
+#
+# AC_INIT(UnTag.java)
+#
+# dnl Checks for programs.
+# AC_CHECK_CLASSPATH
+# AX_PROG_JAVAC
+# AX_PROG_JAVA
+#
+# dnl Checks for classes
+# AX_CHECK_RQRD_CLASS(org.xml.sax.Parser)
+# AX_CHECK_RQRD_CLASS(com.jclark.xml.sax.Driver)
+#
+# AC_OUTPUT(Makefile)
+#
+# LICENSE
+#
+# Copyright (c) 2008 Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 10
+
+AU_ALIAS([AC_PROG_JAVA], [AX_PROG_JAVA])
+AC_DEFUN([AX_PROG_JAVA],[
+m4_define([m4_ax_prog_java_list], [kaffe java])dnl
+AS_IF([test "x$JAVAPREFIX" = x],
+ [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list])],
+ [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list], [], [$JAVAPREFIX/bin])])
+test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH])
+m4_undefine([m4_ax_prog_java_list])dnl
+AX_PROG_JAVA_WORKS
+AC_PROVIDE([$0])dnl
+])
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_java_works.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_JAVA_WORKS
+#
+# DESCRIPTION
+#
+# Internal use ONLY.
+#
+# Note: This is part of the set of autoconf M4 macros for Java programs.
+# It is VERY IMPORTANT that you download the whole set, some macros depend
+# on other. Unfortunately, the autoconf archive does not support the
+# concept of set of macros, so I had to break it for submission. The
+# general documentation, as well as the sample configure.in, is included
+# in the AX_PROG_JAVA macro.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 11
+
+AU_ALIAS([AC_PROG_JAVA_WORKS], [AX_PROG_JAVA_WORKS])
+AC_DEFUN([AX_PROG_JAVA_WORKS], [
+ if test x$ac_cv_prog_javac_works = xno; then
+ AC_MSG_ERROR([Cannot compile java source. $JAVAC does not work properly])
+ fi
+ if test x$ac_cv_prog_javac_works = x; then
+ AX_PROG_JAVAC
+ fi
+AC_CACHE_CHECK(if $JAVA works, ac_cv_prog_java_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+TEST=Test
+changequote(, )dnl
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+public static void main (String args[]) {
+ System.exit (0);
+} }
+EOF
+changequote([, ])dnl
+ if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) && test -s $CLASS_TEST; then
+ :
+ else
+ echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat $JAVA_TEST >&AS_MESSAGE_LOG_FD
+ AC_MSG_ERROR(The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?))
+ fi
+if AC_TRY_COMMAND($JAVA -classpath . $JAVAFLAGS $TEST) >/dev/null 2>&1; then
+ ac_cv_prog_java_works=yes
+else
+ echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat $JAVA_TEST >&AS_MESSAGE_LOG_FD
+ AC_MSG_ERROR(The Java VM $JAVA failed (see config.log, check the CLASSPATH?))
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+])
+AC_PROVIDE([$0])dnl
+]
+)
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_javac.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_JAVAC
+#
+# DESCRIPTION
+#
+# AX_PROG_JAVAC tests an existing Java compiler. It uses the environment
+# variable JAVAC then tests in sequence various common Java compilers. For
+# political reasons, it starts with the free ones.
+#
+# If you want to force a specific compiler:
+#
+# - at the configure.in level, set JAVAC=yourcompiler before calling
+# AX_PROG_JAVAC
+#
+# - at the configure level, setenv JAVAC
+#
+# You can use the JAVAC variable in your Makefile.in, with @JAVAC@.
+#
+# *Warning*: its success or failure can depend on a proper setting of the
+# CLASSPATH env. variable.
+#
+# TODO: allow to exclude compilers (rationale: most Java programs cannot
+# compile with some compilers like guavac).
+#
+# Note: This is part of the set of autoconf M4 macros for Java programs.
+# It is VERY IMPORTANT that you download the whole set, some macros depend
+# on other. Unfortunately, the autoconf archive does not support the
+# concept of set of macros, so I had to break it for submission. The
+# general documentation, as well as the sample configure.in, is included
+# in the AX_PROG_JAVA macro.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 8
+
+AU_ALIAS([AC_PROG_JAVAC], [AX_PROG_JAVAC])
+AC_DEFUN([AX_PROG_JAVAC],[
+m4_define([m4_ax_prog_javac_list],["gcj -C" guavac jikes javac])dnl
+AS_IF([test "x$JAVAPREFIX" = x],
+ [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list])],
+ [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list], [], [$JAVAPREFIX/bin])])
+m4_undefine([m4_ax_prog_javac_list])dnl
+test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH])
+AX_PROG_JAVAC_WORKS
+AC_PROVIDE([$0])dnl
+])
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_javac_works.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_JAVAC_WORKS
+#
+# DESCRIPTION
+#
+# Internal use ONLY.
+#
+# Note: This is part of the set of autoconf M4 macros for Java programs.
+# It is VERY IMPORTANT that you download the whole set, some macros depend
+# on other. Unfortunately, the autoconf archive does not support the
+# concept of set of macros, so I had to break it for submission. The
+# general documentation, as well as the sample configure.in, is included
+# in the AX_PROG_JAVA macro.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 7
+
+AU_ALIAS([AC_PROG_JAVAC_WORKS], [AX_PROG_JAVAC_WORKS])
+AC_DEFUN([AX_PROG_JAVAC_WORKS],[
+AC_CACHE_CHECK([if $JAVAC works], ac_cv_prog_javac_works, [
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+cat << \EOF > $JAVA_TEST
+/* [#]line __oline__ "configure" */
+public class Test {
+}
+EOF
+if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) >/dev/null 2>&1; then
+ ac_cv_prog_javac_works=yes
+else
+ AC_MSG_ERROR([The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)])
+ echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat $JAVA_TEST >&AS_MESSAGE_LOG_FD
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+])
+AC_PROVIDE([$0])dnl
+])
+
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+# been defined and thus are available for use. This avoids random issues
+# where a macro isn't expanded. Instead the configure script emits a
+# non-fatal:
+#
+# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+# It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+# Here's an example:
+#
+# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
+#
+# 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 any
+# warranty.
+
+#serial 2
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+ m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
+
+dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+dnl serial 11 (pkg-config-0.29.1)
+dnl
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+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
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl 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])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+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
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+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
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl 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
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+#------------------------------------------------------------------------
+# SC_PATH_TCLCONFIG --
+#
+# Locate the tclConfig.sh file and perform a sanity check on
+# the Tcl compile flags
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tcl=...
+#
+# Defines the following vars:
+# TCL_BIN_DIR Full path to the directory containing
+# the tclConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_PATH_TCLCONFIG], [
+ #
+ # Ok, lets find the tcl configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tcl
+ #
+
+ if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+ AC_ARG_WITH(tcl,
+ AC_HELP_STRING([--with-tcl],
+ [directory containing tcl configuration (tclConfig.sh)]),
+ with_tclconfig="${withval}")
+ AC_MSG_CHECKING([for Tcl configuration])
+ AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+ # First check to see if --with-tcl was specified.
+ if test x"${with_tclconfig}" != x ; then
+ case "${with_tclconfig}" in
+ */tclConfig.sh )
+ if test -f "${with_tclconfig}"; then
+ AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
+ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
+ else
+ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tcl.framework/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.6 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
+ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+ ])
+
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCL_BIN_DIR="# no Tcl configs found"
+ AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
+ else
+ no_tcl=
+ TCL_BIN_DIR="${ac_cv_c_tclconfig}"
+ AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_PATH_TKCONFIG --
+#
+# Locate the tkConfig.sh file
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tk=...
+#
+# Defines the following vars:
+# TK_BIN_DIR Full path to the directory containing
+# the tkConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_PATH_TKCONFIG], [
+ #
+ # Ok, lets find the tk configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tk
+ #
+
+ if test x"${no_tk}" = x ; then
+ # we reset no_tk in case something fails here
+ no_tk=true
+ AC_ARG_WITH(tk,
+ AC_HELP_STRING([--with-tk],
+ [directory containing tk configuration (tkConfig.sh)]),
+ with_tkconfig="${withval}")
+ AC_MSG_CHECKING([for Tk configuration])
+ AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+ # First check to see if --with-tkconfig was specified.
+ if test x"${with_tkconfig}" != x ; then
+ case "${with_tkconfig}" in
+ */tkConfig.sh )
+ if test -f "${with_tkconfig}"; then
+ AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
+ with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tkconfig}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
+ else
+ AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tk library
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tk.framework/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tk8.6 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ `ls -d /usr/local/lib/tk8.6 2>/dev/null` \
+ `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \
+ ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+ ])
+
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ TK_BIN_DIR="# no Tk configs found"
+ AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
+ else
+ no_tk=
+ TK_BIN_DIR="${ac_cv_c_tkconfig}"
+ AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_LOAD_TCLCONFIG --
+#
+# Load the tclConfig.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# TCL_BIN_DIR
+#
+# Results:
+#
+# Substitutes the following vars:
+# TCL_BIN_DIR
+# TCL_SRC_DIR
+# TCL_LIB_FILE
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_LOAD_TCLCONFIG], [
+ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])
+
+ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
+ AC_MSG_RESULT([loading])
+ . "${TCL_BIN_DIR}/tclConfig.sh"
+ else
+ AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+
+ # If the TCL_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TCL_LIB_SPEC will be set to the value
+ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+ # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
+ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
+ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tcl.framework installed in an arbitrary location.
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
+ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
+ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
+ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
+ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+
+ AC_SUBST(TCL_VERSION)
+ AC_SUBST(TCL_PATCH_LEVEL)
+ AC_SUBST(TCL_BIN_DIR)
+ AC_SUBST(TCL_SRC_DIR)
+
+ AC_SUBST(TCL_LIB_FILE)
+ AC_SUBST(TCL_LIB_FLAG)
+ AC_SUBST(TCL_LIB_SPEC)
+
+ AC_SUBST(TCL_STUB_LIB_FILE)
+ AC_SUBST(TCL_STUB_LIB_FLAG)
+ AC_SUBST(TCL_STUB_LIB_SPEC)
+])
+
+#------------------------------------------------------------------------
+# SC_LOAD_TKCONFIG --
+#
+# Load the tkConfig.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# TK_BIN_DIR
+#
+# Results:
+#
+# Sets the following vars that should be in tkConfig.sh:
+# TK_BIN_DIR
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_LOAD_TKCONFIG], [
+ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])
+
+ if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
+ AC_MSG_RESULT([loading])
+ . "${TK_BIN_DIR}/tkConfig.sh"
+ else
+ AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
+ eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
+
+ # If the TK_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TK_LIB_SPEC will be set to the value
+ # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
+ # instead of TK_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
+ TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
+ TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tk.framework installed in an arbitrary location.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
+ for i in "`cd "${TK_BIN_DIR}"; pwd`" \
+ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
+ TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
+ TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
+ TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
+ eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
+ eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
+ eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
+
+ AC_SUBST(TK_VERSION)
+ AC_SUBST(TK_BIN_DIR)
+ AC_SUBST(TK_SRC_DIR)
+
+ AC_SUBST(TK_LIB_FILE)
+ AC_SUBST(TK_LIB_FLAG)
+ AC_SUBST(TK_LIB_SPEC)
+
+ AC_SUBST(TK_STUB_LIB_FILE)
+ AC_SUBST(TK_STUB_LIB_FLAG)
+ AC_SUBST(TK_STUB_LIB_SPEC)
+])
+
+#------------------------------------------------------------------------
+# SC_PROG_TCLSH
+# Locate a tclsh shell installed on the system path. This macro
+# will only find a Tcl shell that already exists on the system.
+# It will not find a Tcl shell in the Tcl build directory or
+# a Tcl shell that has been installed from the Tcl build directory.
+# If a Tcl shell can't be located on the PATH, then TCLSH_PROG will
+# be set to "". Extensions should take care not to create Makefile
+# rules that are run by default and depend on TCLSH_PROG. An
+# extension can't assume that an executable Tcl shell exists at
+# build time.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following vars:
+# TCLSH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_PROG_TCLSH], [
+ AC_MSG_CHECKING([for tclsh])
+ AC_CACHE_VAL(ac_cv_path_tclsh, [
+ search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+ for dir in $search_path ; do
+ for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \
+ `ls -r $dir/tclsh* 2> /dev/null` ; do
+ if test x"$ac_cv_path_tclsh" = x ; then
+ if test -f "$j" ; then
+ ac_cv_path_tclsh=$j
+ break
+ fi
+ fi
+ done
+ done
+ ])
+
+ if test -f "$ac_cv_path_tclsh" ; then
+ TCLSH_PROG="$ac_cv_path_tclsh"
+ AC_MSG_RESULT([$TCLSH_PROG])
+ else
+ # It is not an error if an installed version of Tcl can't be located.
+ TCLSH_PROG=""
+ AC_MSG_RESULT([No tclsh found on PATH])
+ fi
+ AC_SUBST(TCLSH_PROG)
+])
+
+#------------------------------------------------------------------------
+# SC_BUILD_TCLSH
+# Determine the fully qualified path name of the tclsh executable
+# in the Tcl build directory. This macro will correctly determine
+# the name of the tclsh executable even if tclsh has not yet
+# been built in the build directory. The build tclsh must be used
+# when running tests from an extension build directory. It is not
+# correct to use the TCLSH_PROG in cases like this.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following values:
+# BUILD_TCLSH
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_BUILD_TCLSH], [
+ AC_MSG_CHECKING([for tclsh in Tcl build directory])
+ BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh
+ AC_MSG_RESULT([$BUILD_TCLSH])
+ AC_SUBST(BUILD_TCLSH)
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_SHARED --
+#
+# Allows the building of shared libraries
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-shared=yes|no
+#
+# Defines the following vars:
+# STATIC_BUILD Used for building import/export libraries
+# on Windows.
+#
+# Sets the following vars:
+# SHARED_BUILD Value of 1 or 0
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_SHARED], [
+ AC_MSG_CHECKING([how to build libraries])
+ AC_ARG_ENABLE(shared,
+ AC_HELP_STRING([--enable-shared],
+ [build and link with shared libraries (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+
+ if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" ; then
+ AC_MSG_RESULT([shared])
+ SHARED_BUILD=1
+ else
+ AC_MSG_RESULT([static])
+ SHARED_BUILD=0
+ AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_FRAMEWORK --
+#
+# Allows the building of shared libraries into frameworks
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-framework=yes|no
+#
+# Sets the following vars:
+# FRAMEWORK_BUILD Value of 1 or 0
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_FRAMEWORK], [
+ if test "`uname -s`" = "Darwin" ; then
+ AC_MSG_CHECKING([how to package libraries])
+ AC_ARG_ENABLE(framework,
+ AC_HELP_STRING([--enable-framework],
+ [package shared libraries in MacOSX frameworks (default: off)]),
+ [enable_framework=$enableval], [enable_framework=no])
+ if test $enable_framework = yes; then
+ if test $SHARED_BUILD = 0; then
+ AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
+ enable_framework=no
+ fi
+ if test $tcl_corefoundation = no; then
+ AC_MSG_WARN([Frameworks can only be used when CoreFoundation is available])
+ enable_framework=no
+ fi
+ fi
+ if test $enable_framework = yes; then
+ AC_MSG_RESULT([framework])
+ FRAMEWORK_BUILD=1
+ else
+ if test $SHARED_BUILD = 1; then
+ AC_MSG_RESULT([shared library])
+ else
+ AC_MSG_RESULT([static library])
+ fi
+ FRAMEWORK_BUILD=0
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_THREADS --
+#
+# Specify if thread support should be enabled
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-threads
+#
+# Sets the following vars:
+# THREADS_LIBS Thread library(s)
+#
+# Defines the following vars:
+# TCL_THREADS
+# _REENTRANT
+# _THREAD_SAFE
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_THREADS], [
+ AC_ARG_ENABLE(threads,
+ AC_HELP_STRING([--enable-threads],
+ [build with threads (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+
+ if test "${TCL_THREADS}" = 1; then
+ tcl_threaded_core=1;
+ fi
+
+ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+ TCL_THREADS=1
+ # USE_THREAD_ALLOC tells us to try the special thread-based
+ # allocator that significantly reduces lock contention
+ AC_DEFINE(USE_THREAD_ALLOC, 1,
+ [Do we want to use the threaded memory allocator?])
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ if test "`uname -s`" = "SunOS" ; then
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+ fi
+ AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
+ AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
+ if test "$tcl_ok" = "no"; then
+ # Check a little harder for __pthread_mutex_init in the same
+ # library, as some systems hide it there until pthread.h is
+ # defined. We could alternatively do an AC_TRY_COMPILE with
+ # pthread.h, but that will work with libpthread really doesn't
+ # exist, like AIX 4.2. [Bug: 4359]
+ AC_CHECK_LIB(pthread, __pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthread"
+ else
+ AC_CHECK_LIB(pthreads, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthreads"
+ else
+ AC_CHECK_LIB(c, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "no"; then
+ AC_CHECK_LIB(c_r, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -pthread"
+ else
+ TCL_THREADS=0
+ AC_MSG_WARN([Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...])
+ fi
+ fi
+ fi
+ fi
+
+ # Does the pthread-implementation provide
+ # 'pthread_attr_setstacksize' ?
+
+ ac_saved_libs=$LIBS
+ LIBS="$LIBS $THREADS_LIBS"
+ AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
+ LIBS=$ac_saved_libs
+ else
+ TCL_THREADS=0
+ fi
+ # Do checking message here to not mess up interleaved configure output
+ AC_MSG_CHECKING([for building with threads])
+ if test "${TCL_THREADS}" = 1; then
+ AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
+ if test "${tcl_threaded_core}" = 1; then
+ AC_MSG_RESULT([yes (threaded core)])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ AC_SUBST(TCL_THREADS)
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_SYMBOLS --
+#
+# Specify if debugging symbols should be used.
+# Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging
+# can also be enabled.
+#
+# Arguments:
+# none
+#
+# Requires the following vars to be set in the Makefile:
+# CFLAGS_DEBUG
+# CFLAGS_OPTIMIZE
+# LDFLAGS_DEBUG
+# LDFLAGS_OPTIMIZE
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-symbols
+#
+# Defines the following vars:
+# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true
+# Sets to $(CFLAGS_OPTIMIZE) if false
+# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true
+# Sets to $(LDFLAGS_OPTIMIZE) if false
+# DBGX Formerly used as debug library extension;
+# always blank now.
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_SYMBOLS], [
+ AC_MSG_CHECKING([for build with symbols])
+ AC_ARG_ENABLE(symbols,
+ AC_HELP_STRING([--enable-symbols],
+ [build with debugging symbols (default: off)]),
+ [tcl_ok=$enableval], [tcl_ok=no])
+# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
+ DBGX=""
+ if test "$tcl_ok" = "no"; then
+ CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
+ AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])
+ AC_MSG_RESULT([no])
+ AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])
+ else
+ CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
+ if test "$tcl_ok" = "yes"; then
+ AC_MSG_RESULT([yes (standard debugging)])
+ fi
+ fi
+ AC_SUBST(CFLAGS_DEFAULT)
+ AC_SUBST(LDFLAGS_DEFAULT)
+
+ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
+ AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
+ fi
+
+ ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself
+ if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
+ AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])
+ AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])
+ fi)
+
+ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+ if test "$tcl_ok" = "all"; then
+ AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging])
+ else
+ AC_MSG_RESULT([enabled $tcl_ok debugging])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_LANGINFO --
+#
+# Allows use of modern nl_langinfo check for better l10n.
+# This is only relevant for Unix.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-langinfo=yes|no (default is yes)
+#
+# Defines the following vars:
+# HAVE_LANGINFO Triggers use of nl_langinfo if defined.
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_LANGINFO], [
+ AC_ARG_ENABLE(langinfo,
+ AC_HELP_STRING([--enable-langinfo],
+ [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
+ [langinfo_ok=$enableval], [langinfo_ok=yes])
+
+ HAVE_LANGINFO=0
+ if test "$langinfo_ok" = "yes"; then
+ AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
+ fi
+ AC_MSG_CHECKING([whether to use nl_langinfo])
+ if test "$langinfo_ok" = "yes"; then
+ AC_CACHE_VAL(tcl_cv_langinfo_h, [
+ AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
+ [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
+ AC_MSG_RESULT([$tcl_cv_langinfo_h])
+ if test $tcl_cv_langinfo_h = yes; then
+ AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
+ fi
+ else
+ AC_MSG_RESULT([$langinfo_ok])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_CONFIG_MANPAGES
+#
+# Decide whether to use symlinks for linking the manpages,
+# whether to compress the manpages after installation, and
+# whether to add a package name suffix to the installed
+# manpages to avoidfile name clashes.
+# If compression is enabled also find out what file name suffix
+# the given compression program is using.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-man-symlinks
+# --enable-man-compression=PROG
+# --enable-man-suffix[=STRING]
+#
+# Defines the following variable:
+#
+# MAN_FLAGS - The apropriate flags for installManPage
+# according to the user's selection.
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_MANPAGES], [
+ AC_MSG_CHECKING([whether to use symlinks for manpages])
+ AC_ARG_ENABLE(man-symlinks,
+ AC_HELP_STRING([--enable-man-symlinks],
+ [use symlinks for the manpages (default: off)]),
+ test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+
+ AC_MSG_CHECKING([whether to compress the manpages])
+ AC_ARG_ENABLE(man-compression,
+ AC_HELP_STRING([--enable-man-compression=PROG],
+ [compress the manpages with PROG (default: off)]),
+ [case $enableval in
+ yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
+ esac],
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+ if test "$enableval" != "no"; then
+ AC_MSG_CHECKING([for compressed file suffix])
+ touch TeST
+ $enableval TeST
+ Z=`ls TeST* | sed 's/^....//'`
+ rm -f TeST*
+ MAN_FLAGS="$MAN_FLAGS --extension $Z"
+ AC_MSG_RESULT([$Z])
+ fi
+
+ AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
+ AC_ARG_ENABLE(man-suffix,
+ AC_HELP_STRING([--enable-man-suffix=STRING],
+ [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
+ [case $enableval in
+ yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ esac],
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+
+ AC_SUBST(MAN_FLAGS)
+])
+
+#--------------------------------------------------------------------
+# SC_CONFIG_SYSTEM
+#
+# Determine what the system is (some things cannot be easily checked
+# on a feature-driven basis, alas). This can usually be done via the
+# "uname" command, but there are a few systems, like Next, where
+# this doesn't work.
+#
+# Arguments:
+# none
+#
+# Results:
+# Defines the following var:
+#
+# system - System/platform/version identification code.
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_SYSTEM], [
+ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
+ if test -f /usr/lib/NextStep/software_version; then
+ tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ AC_MSG_WARN([can't find uname command])
+ tcl_cv_sys_version=unknown
+ else
+ # Special check for weird MP-RAS system (uname returns weird
+ # results, and the version is kept in special file).
+
+ if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
+ tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid`
+ fi
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
+ tcl_cv_sys_version=NetBSD-Debian
+ fi
+ fi
+ fi
+ ])
+ system=$tcl_cv_sys_version
+])
+
+#--------------------------------------------------------------------
+# SC_CONFIG_CFLAGS
+#
+# Try to determine the proper flags to pass to the compiler
+# for building shared libraries and other such nonsense.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines and substitutes the following vars:
+#
+# DL_OBJS - Name of the object file that implements dynamic
+# loading for Tcl on this system.
+# DL_LIBS - Library file(s) to include in tclsh and other base
+# applications in order for the "load" command to work.
+# LDFLAGS - Flags to pass to the compiler when linking object
+# files into an executable application binary such
+# as tclsh.
+# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
+# that tell the run-time dynamic linker where to look
+# for shared libraries such as libtcl.so. Depends on
+# the variable LIB_RUNTIME_DIR in the Makefile. Could
+# be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
+# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib",
+# that tell the run-time dynamic linker where to look
+# for shared libraries such as libtcl.so. Depends on
+# the variable LIB_RUNTIME_DIR in the Makefile.
+# MAKE_LIB - Command to execute to build the a library;
+# differs when building shared or static.
+# MAKE_STUB_LIB -
+# Command to execute to build a stub library.
+# INSTALL_LIB - Command to execute to install a library;
+# differs when building shared or static.
+# INSTALL_STUB_LIB -
+# Command to execute to install a stub library.
+# STLIB_LD - Base command to use for combining object files
+# into a static library.
+# SHLIB_CFLAGS - Flags to pass to cc when compiling the components
+# of a shared library (may request position-independent
+# code, among other things).
+# SHLIB_LD - Base command to use for combining object files
+# into a shared library.
+# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
+# creating shared libraries. This symbol typically
+# goes at the end of the "ld" commands that build
+# shared libraries. The value of the symbol defaults to
+# "${LIBS}" if all of the dependent libraries should
+# be specified when creating a shared library. If
+# dependent libraries should not be specified (as on
+# SunOS 4.x, where they cause the link to fail, or in
+# general if Tcl and Tk aren't themselves shared
+# libraries), then this symbol has an empty string
+# as its value.
+# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable
+# extensions. An empty string means we don't know how
+# to use shared libraries on this platform.
+# TCL_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS
+# TK_SHLIB_LD_EXTRAS for the build of Tcl and Tk, but not recorded in the
+# tclConfig.sh, since they are only used for the build
+# of Tcl and Tk.
+# Examples: MacOS X records the library version and
+# compatibility version in the shared library. But
+# of course the Tcl version of this is only used for Tcl.
+# LIB_SUFFIX - Specifies everything that comes after the "libfoo"
+# in a static or shared library name, using the $VERSION variable
+# to put the version in the right place. This is used
+# by platforms that need non-standard library names.
+# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs
+# to have a version after the .so, and ${VERSION}.a
+# on AIX, since a shared library needs to have
+# a .a extension whereas shared objects for loadable
+# extensions have a .so extension. Defaults to
+# ${VERSION}${SHLIB_SUFFIX}.
+# TCL_LIBS -
+# Libs to use when linking Tcl shell or some other
+# shell that includes Tcl libs.
+# CFLAGS_DEBUG -
+# Flags used when running the compiler in debug mode
+# CFLAGS_OPTIMIZE -
+# Flags used when running the compiler in optimize mode
+# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_CFLAGS], [
+
+ # Step 0.a: Enable 64 bit support?
+
+ AC_MSG_CHECKING([if 64bit support is requested])
+ AC_ARG_ENABLE(64bit,
+ AC_HELP_STRING([--enable-64bit],
+ [enable 64bit support (default: off)]),
+ [do64bit=$enableval], [do64bit=no])
+ AC_MSG_RESULT([$do64bit])
+
+ # Step 0.b: Enable Solaris 64 bit VIS support?
+
+ AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
+ AC_ARG_ENABLE(64bit-vis,
+ AC_HELP_STRING([--enable-64bit-vis],
+ [enable 64bit Sparc VIS support (default: off)]),
+ [do64bitVIS=$enableval], [do64bitVIS=no])
+ AC_MSG_RESULT([$do64bitVIS])
+ # Force 64bit on with VIS
+ AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ AC_CACHE_CHECK([if compiler supports visibility "hidden"],
+ tcl_cv_cc_visibility_hidden, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_LINK([
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
+ tcl_cv_cc_visibility_hidden=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
+ AC_DEFINE(MODULE_SCOPE,
+ [extern __attribute__((__visibility__("hidden")))],
+ [Compiler support for module scope symbols])
+ AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
+ ])
+
+ # Step 0.d: Disable -rpath support?
+
+ AC_MSG_CHECKING([if rpath support is requested])
+ AC_ARG_ENABLE(rpath,
+ AC_HELP_STRING([--disable-rpath],
+ [disable rpath support (default: on)]),
+ [doRpath=$enableval], [doRpath=yes])
+ AC_MSG_RESULT([$doRpath])
+
+ # Step 1: set the variable "system" to hold the name and version number
+ # for the system.
+
+ SC_CONFIG_SYSTEM
+
+ # Step 2: check for existence of -ldl library. This is needed because
+ # Linux can use either -ldl or -ldld for dynamic loading.
+
+ AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
+
+ # Require ranlib early so we can override it in special cases below.
+
+ AC_REQUIRE([AC_PROG_RANLIB])
+
+ # Step 3: set configuration options based on system name and version.
+
+ do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
+ LDFLAGS_ORIG="$LDFLAGS"
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
+ UNSHARED_LIB_SUFFIX=""
+ TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
+ ECHO_VERSION='`echo ${VERSION}`'
+ TCL_LIB_VERSIONS_OK=ok
+ CFLAGS_DEBUG=-g
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS_OPTIMIZE=-O2
+ CFLAGS_WARNING="-Wall"
+ ], [
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING=""
+ ])
+ AC_CHECK_TOOL(AR, ar)
+ STLIB_LD='${AR} cr'
+ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+ PLAT_OBJS=""
+ PLAT_SRCS=""
+ LDAIX_SRC=""
+ AS_IF([test "x${SHLIB_VERSION}" = x],[SHLIB_VERSION=".1.0"],[SHLIB_VERSION=".${SHLIB_VERSION}"])
+ case $system in
+ AIX-*)
+ AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
+ # AIX requires the _r compiler when gcc isn't being used
+ case "${CC}" in
+ *_r|*_r\ *)
+ # ok ...
+ ;;
+ *)
+ # Make sure only first arg gets _r
+ CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
+ ;;
+ esac
+ AC_MSG_RESULT([Using $CC for compiling with threads])
+ ])
+ LIBS="$LIBS -lc"
+ SHLIB_CFLAGS=""
+ SHLIB_SUFFIX=".so"
+
+ DL_OBJS="tclLoadDl.o"
+ LD_LIBRARY_PATH_VAR="LIBPATH"
+
+ # ldAix No longer needed with use of -bexpall/-brtl
+ # but some extensions may still reference it
+ LDAIX_SRC='$(UNIX_DIR)/ldAix'
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
+ RANLIB="${RANLIB} -X64"
+ AR="${AR} -X64"
+ SHLIB_LD_FLAGS="-b64"
+ ])
+ ])
+
+ AS_IF([test "`uname -m`" = ia64], [
+ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ # AIX-5 has dl* in libc.so
+ DL_LIBS=""
+ AS_IF([test "$GCC" = yes], [
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ ], [
+ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+ ])
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ], [
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+ ], [
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+ ])
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ BeOS*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -nostart'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+
+ #-----------------------------------------------------------
+ # Check for inet_ntoa in -lbind, for BeOS (which also needs
+ # -lsocket, even if the network functions are in -lnet which
+ # is always linked to, for compatibility.
+ #-----------------------------------------------------------
+ AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
+ ;;
+ BSD/OS-2.1*|BSD/OS-3*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="shlicc -r"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ BSD/OS-4.*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ CYGWIN_*|MINGW32*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".dll"
+ DL_OBJS="tclLoadDl.o"
+ PLAT_OBJS='${CYGWIN_OBJS}'
+ PLAT_SRCS='${CYGWIN_SRCS}'
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ TCL_NEEDS_EXP_FILE=1
+ TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
+ AC_CACHE_CHECK(for Cygwin version of gcc,
+ ac_cv_cygwin,
+ AC_TRY_COMPILE([
+ #ifdef __CYGWIN__
+ #error cygwin
+ #endif
+ ], [],
+ ac_cv_cygwin=no,
+ ac_cv_cygwin=yes)
+ )
+ if test "$ac_cv_cygwin" = "no"; then
+ AC_MSG_ERROR([${CC} is not a cygwin compiler.])
+ fi
+ if test "x${TCL_THREADS}" = "x0"; then
+ AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
+ fi
+ do64bit_ok=yes
+ if test "x${SHARED_BUILD}" = "x1"; then
+ echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
+ # The eval makes quoting arguments work.
+ if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
+ then :
+ else
+ { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
+ fi
+ fi
+ ;;
+ dgux*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-lroot"
+ AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
+ ;;
+ HP-UX-*.11.*)
+ # Use updated header definitions where possible
+ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
+ AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
+ LIBS="$LIBS -lxnet" # Use the XOPEN network library
+
+ AS_IF([test "`uname -m`" = ia64], [
+ SHLIB_SUFFIX=".so"
+ ], [
+ SHLIB_SUFFIX=".sl"
+ ])
+ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+ AS_IF([test "$tcl_ok" = yes], [
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ DL_OBJS="tclLoadShl.o"
+ DL_LIBS="-ldld"
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+ ])
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ CFLAGS="$CFLAGS -z"
+ ])
+
+ # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
+ #CFLAGS="$CFLAGS +DAportable"
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = "yes"], [
+ AS_IF([test "$GCC" = yes], [
+ case `${CC} -dumpmachine` in
+ hppa64*)
+ # 64-bit gcc in use. Fix flags for GNU ld.
+ do64bit_ok=yes
+ SHLIB_LD='${CC} -shared'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ;;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ;;
+ esac
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS +DD64"
+ LDFLAGS_ARCH="+DD64"
+ ])
+ ]) ;;
+ HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
+ SHLIB_SUFFIX=".sl"
+ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+ AS_IF([test "$tcl_ok" = yes], [
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ SHLIB_LD_LIBS=""
+ DL_OBJS="tclLoadShl.o"
+ DL_LIBS="-ldld"
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+ ]) ;;
+ IRIX-5.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ ;;
+ IRIX-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS="$CFLAGS -mabi=n32"
+ LDFLAGS="$LDFLAGS -mabi=n32"
+ ], [
+ case $system in
+ IRIX-6.3)
+ # Use to build 6.2 compatible binaries on 6.3.
+ CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
+ ;;
+ *)
+ CFLAGS="$CFLAGS -n32"
+ ;;
+ esac
+ LDFLAGS="$LDFLAGS -n32"
+ ])
+ ;;
+ IRIX64-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+
+ # Check to enable 64-bit flags for compiler/linker
+
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported by gcc])
+ ], [
+ do64bit_ok=yes
+ SHLIB_LD="ld -64 -shared -rdata_shared"
+ CFLAGS="$CFLAGS -64"
+ LDFLAGS_ARCH="-64"
+ ])
+ ])
+ ;;
+ Linux*|GNU*|NetBSD-Debian)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+
+ CFLAGS_OPTIMIZE="-O2"
+ # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
+ # when you inline the string and math operations. Turn this off to
+ # get rid of the warnings.
+ #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"
+
+ SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
+ AS_IF([test $do64bit = yes], [
+ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -m64"
+ AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_m64 = yes], [
+ CFLAGS="$CFLAGS -m64"
+ do64bit_ok=yes
+ ])
+ ])
+
+ # The combo of gcc + glibc has a bug related to inlining of
+ # functions like strtod(). The -fno-builtin flag should address
+ # this problem but it does not work. The -fno-inline flag is kind
+ # of overkill but it works. Disable inlining only when one of the
+ # files in compat/*.c is being linked in.
+
+ AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
+ ;;
+ Lynx*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ CFLAGS_OPTIMIZE=-02
+ SHLIB_LD='${CC} -shared'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-mshared -ldl"
+ LD_FLAGS="-Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ ;;
+ MP-RAS-02*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ MP-RAS-*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ OpenBSD-*)
+ arch=`arch -s`
+ case "$arch" in
+ alpha|sparc64)
+ SHLIB_CFLAGS="-fPIC"
+ ;;
+ *)
+ SHLIB_CFLAGS="-fpic"
+ ;;
+ esac
+ SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
+ LDFLAGS="-Wl,-export-dynamic"
+ CFLAGS_OPTIMIZE="-O2"
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+ ])
+ # OpenBSD doesn't do version numbers with dots.
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ NetBSD-*)
+ # NetBSD has ELF and can use 'cc -shared' to build shared libs
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the CFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ;;
+ DragonFly-*|FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
+ case $system in
+ FreeBSD-3.*)
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ esac
+ ;;
+ Darwin-*)
+ CFLAGS_OPTIMIZE="-Os"
+ SHLIB_CFLAGS="-fno-common"
+ # To avoid discrepancies between what headers configure sees during
+ # preprocessing tests and compiling tests, move any -isysroot and
+ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
+ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
+ CFLAGS="`echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
+ AS_IF([test $do64bit = yes], [
+ case `arch` in
+ ppc)
+ AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
+ tcl_cv_cc_arch_ppc64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
+ tcl_cv_cc_arch_ppc64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ do64bit_ok=yes
+ ]);;
+ i386)
+ AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
+ tcl_cv_cc_arch_x86_64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch x86_64"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
+ tcl_cv_cc_arch_x86_64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
+ CFLAGS="$CFLAGS -arch x86_64"
+ do64bit_ok=yes
+ ]);;
+ *)
+ AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
+ esac
+ ], [
+ # Check for combined 32-bit and 64-bit fat build
+ AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
+ fat_32_64=yes])
+ ])
+ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
+ AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_single_module = yes], [
+ SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+ ])
+ SHLIB_SUFFIX=".dylib"
+ DL_OBJS="tclLoadDyld.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS -headerpad_max_install_names"
+ AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
+ tcl_cv_ld_search_paths_first, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
+ tcl_cv_ld_search_paths_first=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ ])
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [__private_extern__],
+ [Compiler support for module scope symbols])
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+ AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
+ PLAT_OBJS='${MAC_OSX_OBJS}'
+ PLAT_SRCS='${MAC_OSX_SRCS}'
+ AC_MSG_CHECKING([whether to use CoreFoundation])
+ AC_ARG_ENABLE(corefoundation,
+ AC_HELP_STRING([--enable-corefoundation],
+ [use CoreFoundation API on MacOSX (default: on)]),
+ [tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
+ AC_MSG_RESULT([$tcl_corefoundation])
+ AS_IF([test $tcl_corefoundation = yes], [
+ AC_CACHE_CHECK([for CoreFoundation.framework],
+ tcl_cv_lib_corefoundation, [
+ hold_libs=$LIBS
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ # On Tiger there is no 64-bit CF, so remove 64-bit
+ # archs from CFLAGS et al. while testing for
+ # presence of CF. 64-bit CF is disabled in
+ # tclUnixPort.h if necessary.
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done])
+ LIBS="$LIBS -framework CoreFoundation"
+ AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
+ [CFBundleRef b = CFBundleGetMainBundle();],
+ tcl_cv_lib_corefoundation=yes,
+ tcl_cv_lib_corefoundation=no)
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ LIBS=$hold_libs])
+ AS_IF([test $tcl_cv_lib_corefoundation = yes], [
+ LIBS="$LIBS -framework CoreFoundation"
+ AC_DEFINE(HAVE_COREFOUNDATION, 1,
+ [Do we have access to Darwin CoreFoundation.framework?])
+ ], [tcl_corefoundation=no])
+ AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
+ AC_CACHE_CHECK([for 64-bit CoreFoundation],
+ tcl_cv_lib_corefoundation_64, [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
+ [CFBundleRef b = CFBundleGetMainBundle();],
+ tcl_cv_lib_corefoundation_64=yes,
+ tcl_cv_lib_corefoundation_64=no)
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
+ AC_DEFINE(NO_COREFOUNDATION_64, 1,
+ [Is Darwin CoreFoundation unavailable for 64-bit?])
+ LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
+ ])
+ ])
+ ])
+ ;;
+ NEXTSTEP-*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -nostdlib -r'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadNext.o"
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ OS/390-*)
+ SHLIB_LD_LIBS=""
+ CFLAGS_OPTIMIZE="" # Optimizer is buggy
+ AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h
+ [Should OS/390 do the right thing with sockets?])
+ ;;
+ OSF1-1.0|OSF1-1.1|OSF1-1.2)
+ # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1
+ SHLIB_CFLAGS=""
+ # Hack: make package name same as library name
+ SHLIB_LD='ld -R -export $@:'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadOSF.o"
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ OSF1-1.*)
+ # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
+ SHLIB_CFLAGS="-fPIC"
+ AS_IF([test "$SHARED_BUILD" = 1], [SHLIB_LD="ld -shared"], [
+ SHLIB_LD="ld -non_shared"
+ ])
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ OSF1-V*)
+ # Digital OSF/1
+ SHLIB_CFLAGS=""
+ AS_IF([test "$SHARED_BUILD" = 1], [
+ SHLIB_LD='ld -shared -expect_unresolved "*"'
+ ], [
+ SHLIB_LD='ld -non_shared -expect_unresolved "*"'
+ ])
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
+ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
+ # see pthread_intro(3) for pthread support on osf1, k.furukawa
+ AS_IF([test "${TCL_THREADS}" = 1], [
+ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
+ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
+ LIBS=`echo $LIBS | sed s/-lpthreads//`
+ AS_IF([test "$GCC" = yes], [
+ LIBS="$LIBS -lpthread -lmach -lexc"
+ ], [
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ])
+ ;;
+ QNX-6*)
+ # QNX RTP
+ # This may work for all QNX, but it was only reported for v6.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="ld -Bshareable -x"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ # dlopen is in -lc on QNX
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SCO_SV-3.2*)
+ # Note, dlopen is available only on SCO 3.2.5 and greater. However,
+ # this test works, since "uname -s" was non-standard in 3.2.4 and
+ # below.
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_CFLAGS="-fPIC -melf"
+ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
+ ], [
+ SHLIB_CFLAGS="-Kpic -belf"
+ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+ ])
+ SHLIB_LD="ld -G"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SINIX*5.4*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SunOS-4*)
+ SHLIB_CFLAGS="-PIC"
+ SHLIB_LD="ld"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+ # SunOS can't handle version numbers with dots in them in library
+ # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it
+ # requires an extra version number at the end of .so file names.
+ # So, the library has to have a name like libtcl75.so.1.0
+
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ SunOS-5.[[0-6]])
+ # Careful to not let 5.10+ fall into this case
+
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ SunOS-5*)
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+
+ SHLIB_CFLAGS="-KPIC"
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ arch=`isainfo`
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ AS_IF([test "$GCC" = yes], [
+ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
+ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+ ])
+ ], [
+ do64bit_ok=yes
+ AS_IF([test "$do64bitVIS" = yes], [
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+ ], [
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+ ])
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+ ])
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ AS_IF([test "$GCC" = yes], [
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
+ esac
+ ], [
+ do64bit_ok=yes
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ CFLAGS="$CFLAGS -xarch=amd64"
+ LDFLAGS="$LDFLAGS -xarch=amd64";;
+ esac
+ ])
+ ], [AC_MSG_WARN([64bit mode not supported for $arch])])])
+ ])
+
+ #--------------------------------------------------------------------
+ # On Solaris 5.x i386 with the sunpro compiler we need to link
+ # with sunmath to get floating point rounding control
+ #--------------------------------------------------------------------
+ AS_IF([test "$GCC" = yes],[use_sunmath=no],[
+ arch=`isainfo`
+ AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])
+ AS_IF([test "$arch" = "amd64 i386" -o "$arch" = "i386"], [
+ AC_MSG_RESULT([yes])
+ MATH_LIBS="-lsunmath $MATH_LIBS"
+ AC_CHECK_HEADER(sunmath.h)
+ use_sunmath=yes
+ ], [
+ AC_MSG_RESULT([no])
+ use_sunmath=no
+ ])
+ ])
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "$do64bit_ok" = yes], [
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ # We need to specify -static-libgcc or we need to
+ # add the path to the sparv9 libgcc.
+ SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
+ # for finding sparcv9 libgcc, get the regular libgcc
+ # path, remove so name and append 'sparcv9'
+ #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
+ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
+ ])])
+ ])
+ ], [
+ AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text])
+ case $system in
+ SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]])
+ SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
+ *)
+ SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
+ esac
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ])
+ ;;
+ UNIX_SV* | UnixWare-5*)
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
+ # that don't grok the -Bexport option. Test that it does.
+ AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_Bexport = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ esac
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
+ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
+ ])
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = yes], [
+ AC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?])
+ ])
+
+dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
+dnl # until the end of configure, as configure's compile and link tests use
+dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
+dnl # preprocessing tests use only CPPFLAGS.
+ AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
+
+ # Step 4: disable dynamic loading if requested via a command-line switch.
+
+ AC_ARG_ENABLE(load,
+ AC_HELP_STRING([--enable-load],
+ [allow dynamic loading and "load" command (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+ AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])
+
+ AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
+ AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
+ SHLIB_CFLAGS=""
+ SHLIB_LD=""
+ SHLIB_SUFFIX=""
+ DL_OBJS="tclLoadNone.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS_ORIG"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ BUILD_DLTEST=""
+ ])
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
+
+ # If we're running gcc, then change the C flags for compiling shared
+ # libraries to the right flags for gcc, instead of those for the
+ # standard manufacturer compiler.
+
+ AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*|MINGW32_*) ;;
+ IRIX*) ;;
+ NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac])
+
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [extern],
+ [No Compiler support for module scope symbols])
+ ])
+
+ AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
+ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
+ AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
+ UNSHARED_LIB_SUFFIX='${VERSION}.a'])
+ DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"
+
+ AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
+ LIB_SUFFIX=${SHARED_LIB_SUFFIX}
+ MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
+ AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
+ DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
+ ], [
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+ ])
+ ], [
+ LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
+
+ AS_IF([test "$RANLIB" = ""], [
+ MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'
+ ], [
+ MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'
+ ])
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+ ])
+
+ # Stub lib does not depend on shared/static configuration
+ AS_IF([test "$RANLIB" = ""], [
+ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'
+ ], [
+ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'
+ ])
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'
+
+ # Define TCL_LIBS now that we know what DL_LIBS is.
+ # The trick here is that we don't want to change the value of TCL_LIBS if
+ # it is already set when tclConfig.sh had been loaded by Tk.
+ AS_IF([test "x${TCL_LIBS}" = x], [
+ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"])
+ AC_SUBST(TCL_LIBS)
+
+ # See if the compiler supports casting to a union type.
+ # This is used to stop gcc from printing a compiler
+ # warning when initializing a union member.
+
+ AC_CACHE_CHECK(for cast to union support,
+ tcl_cv_cast_to_union,
+ AC_TRY_COMPILE([],
+ [
+ union foo { int i; double d; };
+ union foo f = (union foo) (int) 0;
+ ],
+ tcl_cv_cast_to_union=yes,
+ tcl_cv_cast_to_union=no)
+ )
+ if test "$tcl_cv_cast_to_union" = "yes"; then
+ AC_DEFINE(HAVE_CAST_TO_UNION, 1,
+ [Defined when compiler supports casting to union type.])
+ fi
+
+ # FIXME: This subst was left in only because the TCL_DL_LIBS
+ # entry in tclConfig.sh uses it. It is not clear why someone
+ # would use TCL_DL_LIBS instead of TCL_LIBS.
+ AC_SUBST(DL_LIBS)
+
+ AC_SUBST(DL_OBJS)
+ AC_SUBST(PLAT_OBJS)
+ AC_SUBST(PLAT_SRCS)
+ AC_SUBST(LDAIX_SRC)
+ AC_SUBST(CFLAGS)
+ AC_SUBST(CFLAGS_DEBUG)
+ AC_SUBST(CFLAGS_OPTIMIZE)
+ AC_SUBST(CFLAGS_WARNING)
+
+ AC_SUBST(LDFLAGS)
+ AC_SUBST(LDFLAGS_DEBUG)
+ AC_SUBST(LDFLAGS_OPTIMIZE)
+ AC_SUBST(CC_SEARCH_FLAGS)
+ AC_SUBST(LD_SEARCH_FLAGS)
+
+ AC_SUBST(STLIB_LD)
+ AC_SUBST(SHLIB_LD)
+ AC_SUBST(TCL_SHLIB_LD_EXTRAS)
+ AC_SUBST(TK_SHLIB_LD_EXTRAS)
+ AC_SUBST(SHLIB_LD_LIBS)
+ AC_SUBST(SHLIB_CFLAGS)
+ AC_SUBST(SHLIB_SUFFIX)
+ AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,"${SHLIB_SUFFIX}",
+ [What is the default extension for shared libraries?])
+
+ AC_SUBST(MAKE_LIB)
+ AC_SUBST(MAKE_STUB_LIB)
+ AC_SUBST(INSTALL_LIB)
+ AC_SUBST(DLL_INSTALL_DIR)
+ AC_SUBST(INSTALL_STUB_LIB)
+ AC_SUBST(RANLIB)
+])
+
+#--------------------------------------------------------------------
+# SC_MISSING_POSIX_HEADERS
+#
+# Supply substitutes for missing POSIX header files. Special
+# notes:
+# - stdlib.h doesn't define strtol, strtoul, or
+# strtod insome versions of SunOS
+# - some versions of string.h don't declare procedures such
+# as strstr
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# NO_DIRENT_H
+# NO_VALUES_H
+# NO_STDLIB_H
+# NO_STRING_H
+# NO_SYS_WAIT_H
+# NO_DLFCN_H
+# HAVE_SYS_PARAM_H
+#
+# HAVE_STRING_H ?
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
+ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
+ AC_TRY_LINK([#include <sys/types.h>
+#include <dirent.h>], [
+#ifndef _POSIX_SOURCE
+# ifdef __Lynx__
+ /*
+ * Generate compilation error to make the test fail: Lynx headers
+ * are only valid if really in the POSIX environment.
+ */
+
+ missing_procedure();
+# endif
+#endif
+DIR *d;
+struct dirent *entryPtr;
+char *p;
+d = opendir("foobar");
+entryPtr = readdir(d);
+p = entryPtr->d_name;
+closedir(d);
+], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])
+
+ if test $tcl_cv_dirent_h = no; then
+ AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
+ fi
+
+ AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
+ AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
+ AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
+ AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
+ if test $tcl_ok = 0; then
+ AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
+ fi
+ AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
+ AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)
+
+ # See also memmove check below for a place where NO_STRING_H can be
+ # set and why.
+
+ if test $tcl_ok = 0; then
+ AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
+ fi
+
+ AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
+ AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])
+
+ # OS/390 lacks sys/param.h (and doesn't need it, by chance).
+ AC_HAVE_HEADERS(sys/param.h)
+])
+
+#--------------------------------------------------------------------
+# SC_PATH_X
+#
+# Locate the X11 header files and the X11 library archive. Try
+# the ac_path_x macro first, but if it doesn't find the X stuff
+# (e.g. because there's no xmkmf program) then check through
+# a list of possible directories. Under some conditions the
+# autoconf macro will return an include directory that contains
+# no include files, so double-check its result just to be safe.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets the following vars:
+# XINCLUDES
+# XLIBSW
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_PATH_X], [
+ AC_PATH_X
+ not_really_there=""
+ if test "$no_x" = ""; then
+ if test "$x_includes" = ""; then
+ AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
+ else
+ if test ! -r $x_includes/X11/Xlib.h; then
+ not_really_there="yes"
+ fi
+ fi
+ fi
+ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
+ AC_MSG_CHECKING([for X11 header files])
+ found_xincludes="no"
+ AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
+ if test "$found_xincludes" = "no"; then
+ dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
+ for i in $dirs ; do
+ if test -r $i/X11/Xlib.h; then
+ AC_MSG_RESULT([$i])
+ XINCLUDES=" -I$i"
+ found_xincludes="yes"
+ break
+ fi
+ done
+ fi
+ else
+ if test "$x_includes" != ""; then
+ XINCLUDES="-I$x_includes"
+ found_xincludes="yes"
+ fi
+ fi
+ if test "$found_xincludes" = "no"; then
+ AC_MSG_RESULT([couldn't find any!])
+ fi
+
+ if test "$no_x" = yes; then
+ AC_MSG_CHECKING([for X11 libraries])
+ XLIBSW=nope
+ dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
+ for i in $dirs ; do
+ if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
+ AC_MSG_RESULT([$i])
+ XLIBSW="-L$i -lX11"
+ x_libraries="$i"
+ break
+ fi
+ done
+ else
+ if test "$x_libraries" = ""; then
+ XLIBSW=-lX11
+ else
+ XLIBSW="-L$x_libraries -lX11"
+ fi
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_MSG_RESULT([could not find any! Using -lX11.])
+ XLIBSW=-lX11
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_BLOCKING_STYLE
+#
+# The statements below check for systems where POSIX-style
+# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
+# On these systems (mostly older ones), use the old BSD-style
+# FIONBIO approach instead.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# HAVE_SYS_IOCTL_H
+# HAVE_SYS_FILIO_H
+# USE_FIONBIO
+# O_NONBLOCK
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_BLOCKING_STYLE], [
+ AC_CHECK_HEADERS(sys/ioctl.h)
+ AC_CHECK_HEADERS(sys/filio.h)
+ SC_CONFIG_SYSTEM
+ AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
+ case $system in
+ OSF*)
+ AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+ AC_MSG_RESULT([FIONBIO])
+ ;;
+ SunOS-4*)
+ AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+ AC_MSG_RESULT([FIONBIO])
+ ;;
+ *)
+ AC_MSG_RESULT([O_NONBLOCK])
+ ;;
+ esac
+])
+
+#--------------------------------------------------------------------
+# SC_TIME_HANLDER
+#
+# Checks how the system deals with time.h, what time structures
+# are used on the system, and what fields the structures have.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# USE_DELTA_FOR_TZ
+# HAVE_TM_GMTOFF
+# HAVE_TM_TZADJ
+# HAVE_TIMEZONE_VAR
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TIME_HANDLER], [
+ AC_CHECK_HEADERS(sys/time.h)
+ AC_HEADER_TIME
+
+ AC_CHECK_FUNCS(gmtime_r localtime_r mktime)
+
+ AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
+ tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
+ if test $tcl_cv_member_tm_tzadj = yes ; then
+ AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
+ fi
+
+ AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
+ tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
+ if test $tcl_cv_member_tm_gmtoff = yes ; then
+ AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
+ fi
+
+ #
+ # Its important to include time.h in this check, as some systems
+ # (like convex) have timezone functions, etc.
+ #
+ AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern long timezone;
+ timezone += 1;
+ exit (0);],
+ tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
+ if test $tcl_cv_timezone_long = yes ; then
+ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+ else
+ #
+ # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
+ #
+ AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern time_t timezone;
+ timezone += 1;
+ exit (0);],
+ tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
+ if test $tcl_cv_timezone_time = yes ; then
+ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_LINK_LIBS
+#
+# Search for the libraries needed to link the Tcl shell.
+# Things like the math library (-lm) and socket stuff (-lsocket vs.
+# -lnsl) are dealt with here.
+#
+# Arguments:
+# None.
+#
+# Results:
+#
+# Might append to the following vars:
+# LIBS
+# MATH_LIBS
+#
+# Might define the following vars:
+# HAVE_NET_ERRNO_H
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_LINK_LIBS], [
+ #--------------------------------------------------------------------
+ # On a few very rare systems, all of the libm.a stuff is
+ # already in libc.a. Set compiler flags accordingly.
+ #--------------------------------------------------------------------
+
+ AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
+
+ #--------------------------------------------------------------------
+ # Interactive UNIX requires -linet instead of -lsocket, plus it
+ # needs net/errno.h to define the socket-related error codes.
+ #--------------------------------------------------------------------
+
+ AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
+ AC_CHECK_HEADER(net/errno.h, [
+ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])
+
+ #--------------------------------------------------------------------
+ # Check for the existence of the -lsocket and -lnsl libraries.
+ # The order here is important, so that they end up in the right
+ # order in the command line generated by make. Here are some
+ # special considerations:
+ # 1. Use "connect" and "accept" to check for -lsocket, and
+ # "gethostbyname" to check for -lnsl.
+ # 2. Use each function name only once: can't redo a check because
+ # autoconf caches the results of the last check and won't redo it.
+ # 3. Use -lnsl and -lsocket only if they supply procedures that
+ # aren't already present in the normal libraries. This is because
+ # IRIX 5.2 has libraries, but they aren't needed and they're
+ # bogus: they goof up name resolution if used.
+ # 4. On some SVR4 systems, can't use -lsocket without -lnsl too.
+ # To get around this problem, check for both libraries together
+ # if -lsocket doesn't work by itself.
+ #--------------------------------------------------------------------
+
+ tcl_checkBoth=0
+ AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
+ if test "$tcl_checkSocket" = 1; then
+ AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
+ LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
+ fi
+ if test "$tcl_checkBoth" = 1; then
+ tk_oldLibs=$LIBS
+ LIBS="$LIBS -lsocket -lnsl"
+ AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
+ fi
+ AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
+ [LIBS="$LIBS -lnsl"])])
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_EARLY_FLAGS
+#
+# Check for what flags are needed to be passed so the correct OS
+# features are available.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# _ISOC99_SOURCE
+# _LARGEFILE64_SOURCE
+# _LARGEFILE_SOURCE64
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_EARLY_FLAG],[
+ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
+ AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
+ AC_TRY_COMPILE([[#define ]$1[ 1
+]$2], $3,
+ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
+ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
+ if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
+ AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
+ tcl_flags="$tcl_flags $1"
+ fi
+])
+
+AC_DEFUN([SC_TCL_EARLY_FLAGS],[
+ AC_MSG_CHECKING([for required early compiler flags])
+ tcl_flags=""
+ SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
+ [char *p = (char *)strtoll; char *q = (char *)strtoull;])
+ SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
+ [struct stat64 buf; int i = stat64("/", &buf);])
+ SC_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
+ [char *p = (char *)open64;])
+ if test "x${tcl_flags}" = "x" ; then
+ AC_MSG_RESULT([none])
+ else
+ AC_MSG_RESULT([${tcl_flags}])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_64BIT_FLAGS
+#
+# Check for what is defined in the way of 64-bit features.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# TCL_WIDE_INT_IS_LONG
+# TCL_WIDE_INT_TYPE
+# HAVE_STRUCT_DIRENT64, HAVE_DIR64
+# HAVE_STRUCT_STAT64
+# HAVE_TYPE_OFF64_T
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_64BIT_FLAGS], [
+ AC_MSG_CHECKING([for 64-bit integer type])
+ AC_CACHE_VAL(tcl_cv_type_64bit,[
+ tcl_cv_type_64bit=none
+ # See if the compiler knows natively about __int64
+ AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
+ tcl_type_64bit=__int64, tcl_type_64bit="long long")
+ # See if we should use long anyway Note that we substitute in the
+ # type that is our current guess for a 64-bit type inside this check
+ # program, so it should be modified only carefully...
+ AC_TRY_COMPILE(,[switch (0) {
+ case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
+ }],tcl_cv_type_64bit=${tcl_type_64bit})])
+ if test "${tcl_cv_type_64bit}" = none ; then
+ AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
+ AC_MSG_RESULT([using long])
+ else
+ AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
+ [What type should be used to define wide integers?])
+ AC_MSG_RESULT([${tcl_cv_type_64bit}])
+
+ # Now check for auxiliary declarations
+ AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <dirent.h>],[struct dirent64 p;],
+ tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
+ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
+ AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
+ fi
+
+ AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <dirent.h>],[struct dirent64 *p; DIR64 d = opendir64(".");
+ p = readdir64(d); rewinddir64(d); closedir64(d);],
+ tcl_cv_DIR64=yes,tcl_cv_DIR64=no)])
+ if test "x${tcl_cv_DIR64}" = "xyes" ; then
+ AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])
+ fi
+
+ AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
+ AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
+],
+ tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
+ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
+ AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
+ fi
+
+ AC_CHECK_FUNCS(open64 lseek64)
+ AC_MSG_CHECKING([for off64_t])
+ AC_CACHE_VAL(tcl_cv_type_off64_t,[
+ AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
+],
+ tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
+ dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
+ dnl functions lseek64 and open64 are defined.
+ if test "x${tcl_cv_type_off64_t}" = "xyes" && \
+ test "x${ac_cv_func_lseek64}" = "xyes" && \
+ test "x${ac_cv_func_open64}" = "xyes" ; then
+ AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_CFG_ENCODING TIP #59
+#
+# Declare the encoding to use for embedded configuration information.
+#
+# Arguments:
+# None.
+#
+# Results:
+# Might append to the following vars:
+# DEFS (implicit)
+#
+# Will define the following vars:
+# TCL_CFGVAL_ENCODING
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CFG_ENCODING], [
+ AC_ARG_WITH(encoding,
+ AC_HELP_STRING([--with-encoding],
+ [encoding for configuration values (default: iso8859-1)]),
+ with_tcencoding=${withval})
+
+ if test x"${with_tcencoding}" != x ; then
+ AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
+ [What encoding should be used for embedded configuration info?])
+ else
+ AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
+ [What encoding should be used for embedded configuration info?])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_CHECK_BROKEN_FUNC
+#
+# Check for broken function.
+#
+# Arguments:
+# funcName - function to test for
+# advancedTest - the advanced test to run if the function is present
+#
+# Results:
+# Might cause compatibility versions of the function to be used.
+# Might affect the following vars:
+# USE_COMPAT (implicit)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
+ AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
+ if test ["$tcl_ok"] = 1; then
+ AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
+ AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
+ [tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
+ if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test ["$tcl_ok"] = 0; then
+ AC_LIBOBJ($1)
+ USE_COMPAT=1
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETHOSTBYADDR_R
+#
+# Check if we have MT-safe variant of gethostbyaddr().
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETHOSTBYADDR_R
+# HAVE_GETHOSTBYADDR_R_7
+# HAVE_GETHOSTBYADDR_R_8
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [
+ # Avoids picking hidden internal symbol from libc
+ SC_TCL_GETHOSTBYADDR_R_DECL
+
+ if test "$tcl_cv_api_gethostbyaddr_r" = yes; then
+ SC_TCL_GETHOSTBYADDR_R_TYPE
+ fi
+])
+
+AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [
+ tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include <netdb.h>])
+])
+
+AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [
+ AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &h_errnop);
+ ], tcl_cv_api_gethostbyaddr_r_7=yes, tcl_cv_api_gethostbyaddr_r_7=no)])
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,
+ [Define to 1 if gethostbyaddr_r takes 7 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result, *resultp;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &resultp, &h_errnop);
+ ], tcl_cv_api_gethostbyaddr_r_8=yes, tcl_cv_api_gethostbyaddr_r_8=no)])
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,
+ [Define to 1 if gethostbyaddr_r takes 8 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R, 1,
+ [Define to 1 if gethostbyaddr_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETHOSTBYNAME_R
+#
+# Check to see what variant of gethostbyname_r() we have.
+# Based on David Arnold's example from the comp.programming.threads
+# FAQ Q213
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETHOSTBYNAME_R
+# HAVE_GETHOSTBYNAME_R_3
+# HAVE_GETHOSTBYNAME_R_5
+# HAVE_GETHOSTBYNAME_R_6
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [
+ # Avoids picking hidden internal symbol from libc
+ SC_TCL_GETHOSTBYNAME_R_DECL
+
+ if test "$tcl_cv_api_gethostbyname_r" = yes; then
+ SC_TCL_GETHOSTBYNAME_R_TYPE
+ fi
+])
+
+AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [
+ tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include <netdb.h>])
+])
+
+AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [
+ AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he, *res;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
+ ], tcl_cv_api_gethostbyname_r_6=yes, tcl_cv_api_gethostbyname_r_6=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_6
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,
+ [Define to 1 if gethostbyname_r takes 6 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
+ ], tcl_cv_api_gethostbyname_r_5=yes, tcl_cv_api_gethostbyname_r_5=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,
+ [Define to 1 if gethostbyname_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he;
+ struct hostent_data data;
+
+ (void) gethostbyname_r(name, he, &data);
+ ], tcl_cv_api_gethostbyname_r_3=yes, tcl_cv_api_gethostbyname_r_3=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_3
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,
+ [Define to 1 if gethostbyname_r takes 3 args.])
+ fi
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1,
+ [Define to 1 if gethostbyname_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETPWUID_R
+#
+# Check if we have MT-safe variant of getpwuid() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETPWUID_R
+# HAVE_GETPWUID_R_4
+# HAVE_GETPWUID_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [
+ AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ uid_t uid;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
+ ], tcl_cv_api_getpwuid_r_5=yes, tcl_cv_api_getpwuid_r_5=no)])
+ tcl_ok=$tcl_cv_api_getpwuid_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R_5, 1,
+ [Define to 1 if getpwuid_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ uid_t uid;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(uid, &pw, buf, buflen);
+ ], tcl_cv_api_getpwuid_r_4=yes, tcl_cv_api_getpwuid_r_4=no)])
+ tcl_ok=$tcl_cv_api_getpwuid_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R_4, 1,
+ [Define to 1 if getpwuid_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R, 1,
+ [Define to 1 if getpwuid_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETPWNAM_R
+#
+# Check if we have MT-safe variant of getpwnam() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETPWNAM_R
+# HAVE_GETPWNAM_R_4
+# HAVE_GETPWNAM_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [
+ AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ char *name;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwnam_r(name, &pw, buf, buflen, &pwp);
+ ], tcl_cv_api_getpwnam_r_5=yes, tcl_cv_api_getpwnam_r_5=no)])
+ tcl_ok=$tcl_cv_api_getpwnam_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R_5, 1,
+ [Define to 1 if getpwnam_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ char *name;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(name, &pw, buf, buflen);
+ ], tcl_cv_api_getpwnam_r_4=yes, tcl_cv_api_getpwnam_r_4=no)])
+ tcl_ok=$tcl_cv_api_getpwnam_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R_4, 1,
+ [Define to 1 if getpwnam_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R, 1,
+ [Define to 1 if getpwnam_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETGRGID_R
+#
+# Check if we have MT-safe variant of getgrgid() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETGRGID_R
+# HAVE_GETGRGID_R_4
+# HAVE_GETGRGID_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [
+ AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ gid_t gid;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrgid_r(gid, &gr, buf, buflen, &grp);
+ ], tcl_cv_api_getgrgid_r_5=yes, tcl_cv_api_getgrgid_r_5=no)])
+ tcl_ok=$tcl_cv_api_getgrgid_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R_5, 1,
+ [Define to 1 if getgrgid_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ gid_t gid;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrgid_r(gid, &gr, buf, buflen);
+ ], tcl_cv_api_getgrgid_r_4=yes, tcl_cv_api_getgrgid_r_4=no)])
+ tcl_ok=$tcl_cv_api_getgrgid_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R_4, 1,
+ [Define to 1 if getgrgid_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R, 1,
+ [Define to 1 if getgrgid_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETGRNAM_R
+#
+# Check if we have MT-safe variant of getgrnam() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETGRNAM_R
+# HAVE_GETGRNAM_R_4
+# HAVE_GETGRNAM_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
+ AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ char *name;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrnam_r(name, &gr, buf, buflen, &grp);
+ ], tcl_cv_api_getgrnam_r_5=yes, tcl_cv_api_getgrnam_r_5=no)])
+ tcl_ok=$tcl_cv_api_getgrnam_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R_5, 1,
+ [Define to 1 if getgrnam_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ char *name;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrnam_r(name, &gr, buf, buflen);
+ ], tcl_cv_api_getgrnam_r_4=yes, tcl_cv_api_getgrnam_r_4=no)])
+ tcl_ok=$tcl_cv_api_getgrnam_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R_4, 1,
+ [Define to 1 if getgrnam_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R, 1,
+ [Define to 1 if getgrnam_r is available.])
+ fi
+])])
+
+AC_DEFUN([SC_TCL_IPV6],[
+ NEED_FAKE_RFC2553=0
+ AC_CHECK_FUNCS(getnameinfo getaddrinfo freeaddrinfo gai_strerror,,[NEED_FAKE_RFC2553=1])
+ AC_CHECK_TYPES([
+ struct addrinfo,
+ struct in6_addr,
+ struct sockaddr_in6,
+ struct sockaddr_storage],,[NEED_FAKE_RFC2553=1],[[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+]])
+if test "x$NEED_FAKE_RFC2553" = "x1"; then
+ AC_DEFINE([NEED_FAKE_RFC2553], 1,
+ [Use compat implementation of getaddrinfo() and friends])
+ AC_LIBOBJ([fake-rfc2553])
+ AC_CHECK_FUNC(strlcpy)
+fi
+])
+# Local Variables:
+# mode: autoconf
+# End:
+
+# Copyright (C) 2002-2018 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.16'
+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.16.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.16.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-2018 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],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2018 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-2018 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-2018 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.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ AS_CASE([$CONFIG_FILES],
+ [*\'*], [eval set x "$CONFIG_FILES"],
+ [*], [set x $CONFIG_FILES])
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`AS_DIRNAME(["$am_mf"])`
+ am_filepart=`AS_BASENAME(["$am_mf"])`
+ AM_RUN_LOG([cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles]) || am_rc=$?
+ done
+ if test $am_rc -ne 0; then
+ AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. Try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).])
+ fi
+ AS_UNSET([am_dirpart])
+ AS_UNSET([am_filepart])
+ AS_UNSET([am_mf])
+ AS_UNSET([am_rc])
+ rm -f conftest-deps.mk
+}
+])# _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.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll 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" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2018 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:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver). 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: <https://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 The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+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-2018 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+set}" != 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-2018 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-2018 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 whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+ AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+ ['0:this is the am__doit target'],
+ [AS_CASE([$s],
+ [BSD], [am__include='.include' am__quote='"'],
+ [am__include='include' am__quote=''])])
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2018 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-2018 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-2018 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) 1999-2018 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# ---------------------------------------------------------------------------
+# Adds support for distributing Python modules and packages. To
+# install modules, copy them to $(pythondir), using the python_PYTHON
+# automake variable. To install a package with the same name as the
+# automake package, install to $(pkgpythondir), or use the
+# pkgpython_PYTHON automake variable.
+#
+# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
+# locations to install python extension modules (shared libraries).
+# Another macro is required to find the appropriate flags to compile
+# extension modules.
+#
+# If your package is configured with a different prefix to python,
+# users will have to add the install directory to the PYTHONPATH
+# environment variable, or create a .pth file (see the python
+# documentation for details).
+#
+# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
+# cause an error if the version of python installed on the system
+# doesn't meet the requirement. MINIMUM-VERSION should consist of
+# numbers and dots only.
+AC_DEFUN([AM_PATH_PYTHON],
+ [
+ dnl Find a Python interpreter. Python versions prior to 2.0 are not
+ dnl supported. (2.0 was released on October 16, 2000).
+ m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
+[python python2 python3 dnl
+ python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
+ python3.2 python3.1 python3.0 dnl
+ python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
+ python2.0])
+
+ AC_ARG_VAR([PYTHON], [the Python interpreter])
+
+ m4_if([$1],[],[
+ dnl No version check is needed.
+ # Find any Python interpreter.
+ if test -z "$PYTHON"; then
+ AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
+ fi
+ am_display_PYTHON=python
+ ], [
+ dnl A version check is needed.
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ AC_MSG_CHECKING([whether $PYTHON version is >= $1])
+ AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Python interpreter is too old])])
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ AC_CACHE_CHECK([for a Python interpreter with version >= $1],
+ [am_cv_pathless_PYTHON],[
+ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
+ done])
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+ ])
+
+ if test "$PYTHON" = :; then
+ dnl Run any user-specified action, or abort.
+ m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
+ else
+
+ dnl Query Python for its version number. Getting [:3] seems to be
+ dnl the best way to do this; it's what "site.py" does in the standard
+ dnl library.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
+ [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
+ AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
+
+ dnl Use the values of $prefix and $exec_prefix for the corresponding
+ dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
+ dnl distinct variables so they can be overridden if need be. However,
+ dnl general consensus is that you shouldn't need this ability.
+
+ AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
+ AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
+
+ dnl At times (like when building shared libraries) you may want
+ dnl to know which OS platform Python thinks this is.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
+ [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
+ AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+ dnl Set up 4 directories:
+
+ dnl pythondir -- where to install python scripts. This is the
+ dnl site-packages directory, not the python standard library
+ dnl directory like in previous automake betas. This behavior
+ dnl is more consistent with lispdir.m4 for example.
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON script directory],
+ [am_cv_python_pythondir],
+ [if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pythondir], [$am_cv_python_pythondir])
+
+ dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
+ dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
+ dnl more consistent with the rest of automake.
+
+ AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
+
+ dnl pyexecdir -- directory for installing python extension modules
+ dnl (shared libraries)
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
+ [am_cv_python_pyexecdir],
+ [if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
+
+ dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
+
+ AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
+
+ dnl Run any user-specified action.
+ $2
+ fi
+
+])
+
+
+# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# ---------------------------------------------------------------------------
+# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
+# Run ACTION-IF-FALSE otherwise.
+# This test uses sys.hexversion instead of the string equivalent (first
+# word of sys.version), in order to cope with versions such as 2.2c1.
+# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
+AC_DEFUN([AM_PYTHON_CHECK_VERSION],
+ [prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
+sys.exit(sys.hexversion < minverhex)"
+ AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
+
+# Copyright (C) 2001-2018 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-2018 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-2018 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-2018 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-2018 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-2018 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/ac_check_define.m4])
+m4_include([m4/atomic_operations.m4])
+m4_include([m4/atomic_operations_64bit.m4])
+m4_include([m4/libtool.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/action.c b/action.c
new file mode 100644
index 0000000..1f77529
--- /dev/null
+++ b/action.c
@@ -0,0 +1,2398 @@
+/* action.c
+ *
+ * Implementation of the action object.
+ *
+ * File begun on 2007-08-06 by RGerhards (extracted from syslogd.c)
+ *
+ * Some notes on processing (this hopefully makes it easier to find
+ * the right code in question): For performance reasons, this module
+ * uses different methods of message submission based on the user-selected
+ * configuration. This code is similar, but can not be abstracted because
+ * of the performance-affecting differences in it. As such, it is often
+ * necessary to triple-check that everything works well in *all* modes.
+ * The different modes (and calling sequence) are:
+ *
+ * if set iExecEveryNthOccur > 1 || iSecsExecOnceInterval
+ * - doSubmitToActionQComplex
+ * handles mark message reduction, but in essence calls
+ * - actionWriteToAction
+ * - doSubmitToActionQ
+ * (now queue engine processing)
+ * if(pThis->bWriteAllMarkMsgs == RSFALSE)
+ * - doSubmitToActionQNotAllMark
+ * - doSubmitToActionQ (and from here like in the else case below!)
+ * else
+ * - doSubmitToActionQ
+ * - qqueueEnqObj
+ * (now queue engine processing)
+ *
+ * Note that bWriteAllMakrMsgs on or off creates almost the same processing.
+ * The difference ist that if WriteAllMarkMsgs is not set, we need to
+ * preprocess the batch and drop mark messages which are not yet due for
+ * writing.
+ *
+ * After dequeue, processing is as follows:
+ * - processBatchMain
+ * - processMsgMain (direct entry for DIRECT queue!)
+ * - ...
+ *
+ * MORE ON PROCESSING, QUEUES and FILTERING
+ * All filtering needs to be done BEFORE messages are enqueued to an
+ * action. In previous code, part of the filtering was done at the
+ * "remote end" of the action queue, which lead to problems in
+ * non-direct mode (because then things run asynchronously). In order
+ * to solve this problem once and for all, I have changed the code so
+ * that all filtering is done before enq, and processing on the
+ * dequeue side of action processing now always executes whatever is
+ * enqueued. This is the only way to handle things consistently and
+ * (as much as possible) in a queue-type agnostic way. However, it is
+ * a rather radical change, which I unfortunately needed to make from
+ * stable version 5.8.1 to 5.8.2. If new problems pop up, you now know
+ * what may be their cause. In any case, the way it is done now is the
+ * only correct one.
+ * A problem is that, under fortunate conditions, we use the current
+ * batch for the output system as well. This is very good from a performance
+ * point of view, but makes the distinction between enq and deq side of
+ * the queue a bit hard. The current idea is that the filter condition
+ * alone is checked at the deq side of the queue (seems to be unavoidable
+ * to do it that way), but all other complex conditons (like failover
+ * handling) go into the computation of the filter condition. For
+ * non-direct queues, we still enqueue only what is acutally necessary.
+ * Note that in this case the rest of the code must ensure that the filter
+ * is set to "true". While this is not perfect and not as simple as
+ * we would like to see it, it looks like the best way to tackle that
+ * beast.
+ * rgerhards, 2011-06-15
+ *
+ * Copyright 2007-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <json.h>
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "template.h"
+#include "action.h"
+#include "modules.h"
+#include "cfsysline.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "batch.h"
+#include "wti.h"
+#include "rsconf.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "atomic.h"
+#include "ruleset.h"
+#include "parserif.h"
+#include "statsobj.h"
+
+/* AIXPORT : cs renamed to legacy_cs as clashes with libpthreads variable in complete file*/
+#ifdef _AIX
+#define cs legacy_cs
+#endif
+
+PRAGMA_INGORE_Wswitch_enum
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+#define NO_TIME_PROVIDED 0 /* indicate we do not provide any cached time */
+
+/* forward definitions */
+static rsRetVal ATTR_NONNULL() processBatchMain(void *pVoid, batch_t *pBatch, wti_t * const pWti);
+static rsRetVal doSubmitToActionQ(action_t * const pAction, wti_t * const pWti, smsg_t*);
+static rsRetVal doSubmitToActionQComplex(action_t * const pAction, wti_t * const pWti, smsg_t*);
+static rsRetVal doSubmitToActionQNotAllMark(action_t * const pAction, wti_t * const pWti, smsg_t*);
+static void ATTR_NONNULL() actionSuspend(action_t * const pThis, wti_t * const pWti);
+static void ATTR_NONNULL() actionRetry(action_t * const pThis, wti_t * const pWti);
+
+/* object static data (once for all instances) */
+DEFobjCurrIf(obj)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(module)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(ruleset)
+
+
+typedef struct configSettings_s {
+ int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
+ int bActionWriteAllMarkMsgs; /* should all mark messages be unconditionally written? */
+ int iActExecOnceInterval; /* execute action once every nn seconds */
+ int iActExecEveryNthOccur; /* execute action every n-th occurrence (0,1=always) */
+ time_t iActExecEveryNthOccurTO; /* timeout for n-occurrence setting (in seconds, 0=never) */
+ int glbliActionResumeInterval;
+ int glbliActionResumeRetryCount; /* how often should suspended actions be retried? */
+ int bActionRepMsgHasMsg; /* last messsage repeated... has msg fragment in it */
+ uchar *pszActionName; /* short name for the action */
+ /* action queue and its configuration parameters */
+ queueType_t ActionQueType; /* type of the main message queue above */
+ int iActionQueueSize; /* size of the main message queue above */
+ int iActionQueueDeqBatchSize; /* batch size for action queues */
+ int iActionQHighWtrMark; /* high water mark for disk-assisted queues */
+ int iActionQLowWtrMark; /* low water mark for disk-assisted queues */
+ int iActionQDiscardMark; /* begin to discard messages */
+ int iActionQDiscardSeverity;
+ /* by default, discard nothing to prevent unintentional loss */
+ int iActionQueueNumWorkers; /* number of worker threads for the mm queue above */
+ uchar *pszActionQFName; /* prefix for the main message queue file */
+ int64 iActionQueMaxFileSize;
+ int iActionQPersistUpdCnt; /* persist queue info every n updates */
+ int bActionQSyncQeueFiles; /* sync queue files */
+ int iActionQtoQShutdown; /* queue shutdown */
+ int iActionQtoActShutdown; /* action shutdown (in phase 2) */
+ int iActionQtoEnq; /* timeout for queue enque */
+ int iActionQtoWrkShutdown; /* timeout for worker thread shutdown */
+ int iActionQWrkMinMsgs; /* minimum messages per worker needed to start a new one */
+ int bActionQSaveOnShutdown; /* save queue on shutdown (when DA enabled)? */
+ int64 iActionQueMaxDiskSpace; /* max disk space allocated 0 ==> unlimited */
+ int iActionQueueDeqSlowdown; /* dequeue slowdown (simple rate limiting) */
+ int iActionQueueDeqtWinFromHr; /* hour begin of time frame when queue is to be dequeued */
+ int iActionQueueDeqtWinToHr; /* hour begin of time frame when queue is to be dequeued */
+} configSettings_t;
+
+
+static configSettings_t cs; /* our current config settings */
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfparamdescr[] = {
+ { "name", eCmdHdlrGetWord, 0 }, /* legacy: actionname */
+ { "type", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: actionname */
+ { "action.errorfile", eCmdHdlrString, 0 },
+ { "action.errorfile.maxsize", eCmdHdlrInt, 0 },
+ { "action.writeallmarkmessages", eCmdHdlrBinary, 0 }, /* legacy: actionwriteallmarkmessages */
+ { "action.execonlyeverynthtime", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtime */
+ { "action.execonlyeverynthtimetimeout", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtimetimeout */
+ { "action.execonlyonceeveryinterval", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyonceeveryinterval */
+ { "action.execonlywhenpreviousissuspended", eCmdHdlrBinary, 0 },
+ /* legacy: actionexeconlywhenpreviousissuspended */
+ { "action.repeatedmsgcontainsoriginalmsg", eCmdHdlrBinary, 0 }, /* legacy: repeatedmsgcontainsoriginalmsg */
+ { "action.resumeretrycount", eCmdHdlrInt, 0 }, /* legacy: actionresumeretrycount */
+ { "action.reportsuspension", eCmdHdlrBinary, 0 },
+ { "action.reportsuspensioncontinuation", eCmdHdlrBinary, 0 },
+ { "action.resumeintervalmax", eCmdHdlrPositiveInt, 0 },
+ { "action.resumeinterval", eCmdHdlrInt, 0 },
+ { "action.externalstate.file", eCmdHdlrString, 0 },
+ { "action.copymsg", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescr)/sizeof(struct cnfparamdescr),
+ cnfparamdescr
+ };
+
+
+/* primarily a helper for debug purposes, get human-readble name of state */
+/* currently not needed, but may be useful in the future! */
+#if 0
+static const char *
+batchState2String(const batch_state_t state)
+{
+ switch(state) {
+ case BATCH_STATE_RDY:
+ return "BATCH_STATE_RDY";
+ case BATCH_STATE_BAD:
+ return "BATCH_STATE_BAD";
+ case BATCH_STATE_SUB:
+ return "BATCH_STATE_SUB";
+ case BATCH_STATE_COMM:
+ return "BATCH_STATE_COMM";
+ case BATCH_STATE_DISC:
+ return "BATCH_STATE_DISC";
+ default:
+ return "ERROR, batch state not known!";
+ }
+}
+#endif // #if 0
+
+/* ------------------------------ methods ------------------------------ */
+
+/* This function returns the "current" time for this action. Current time
+ * is not necessarily real-time. In order to enhance performance, current
+ * system time is obtained the first time an action needs to know the time
+ * and then kept cached inside the action structure. Later requests will
+ * always return that very same time. Wile not totally accurate, it is far
+ * accurate in most cases and considered "acurate enough" for all cases.
+ * When changing the threading model, please keep in mind that this
+ * logic needs to be changed should we once allow more than one parallel
+ * call into the same action (object). As this is currently not supported,
+ * we simply cache the time inside the action object itself, after it
+ * is under mutex protection.
+ * Side-note: the value -1 is used as tActNow, because it also is the
+ * error return value of time(). So we would do a retry with the next
+ * invocation if time() failed. Then, of course, we would probably already
+ * be in trouble, but for the sake of performance we accept this very,
+ * very slight risk.
+ * This logic has been added as part of an overall performance improvment
+ * effort inspired by David Lang. -- rgerhards, 2008-09-16
+ * Note: this function does not use the usual iRet call conventions
+ * because that would provide little to no benefit but complicate things
+ * a lot. So we simply return the system time.
+ */
+static time_t
+getActNow(action_t * const pThis)
+{
+ assert(pThis != NULL);
+ if(pThis->tActNow == -1) {
+ pThis->tActNow = datetime.GetTime(NULL); /* good time call - the only one done */
+ if(pThis->tLastExec > pThis->tActNow) {
+ /* if we are traveling back in time, reset tLastExec */
+ pThis->tLastExec = (time_t) 0;
+ }
+ }
+
+ return pThis->tActNow;
+}
+
+
+/* resets action queue parameters to their default values. This happens
+ * after each action has been created in order to prevent any wild defaults
+ * to be used. It is somewhat against the original spirit of the config file
+ * reader, but I think it is a good thing to do.
+ * rgerhards, 2008-01-29
+ */
+static rsRetVal
+actionResetQueueParams(void)
+{
+ DEFiRet;
+
+ cs.ActionQueType = QUEUETYPE_DIRECT; /* type of the main message queue above */
+ cs.iActionQueueSize = 1000; /* size of the main message queue above */
+ cs.iActionQueueDeqBatchSize = 16; /* default batch size */
+ cs.iActionQHighWtrMark = -1; /* high water mark for disk-assisted queues */
+ cs.iActionQLowWtrMark = -1; /* low water mark for disk-assisted queues */
+ cs.iActionQDiscardMark = 980; /* begin to discard messages */
+ cs.iActionQDiscardSeverity = 8; /* discard warning and above */
+ cs.iActionQueueNumWorkers = 1; /* number of worker threads for the mm queue above */
+ cs.iActionQueMaxFileSize = 1024*1024;
+ cs.iActionQPersistUpdCnt = 0; /* persist queue info every n updates */
+ cs.bActionQSyncQeueFiles = 0;
+ cs.iActionQtoQShutdown = 0; /* queue shutdown */
+ cs.iActionQtoActShutdown = 1000; /* action shutdown (in phase 2) */
+ cs.iActionQtoEnq = 50; /* timeout for queue enque */
+ cs.iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
+ cs.iActionQWrkMinMsgs = -1; /* minimum messages per worker needed to start a new one */
+ cs.bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
+ cs.iActionQueMaxDiskSpace = 0;
+ cs.iActionQueueDeqSlowdown = 0;
+ cs.iActionQueueDeqtWinFromHr = 0;
+ cs.iActionQueueDeqtWinToHr = 25; /* 25 disables time windowed dequeuing */
+
+ cs.glbliActionResumeRetryCount = 0; /* I guess it is smart to reset this one, too */
+
+ free(cs.pszActionQFName);
+ cs.pszActionQFName = NULL; /* prefix for the main message queue file */
+
+ RETiRet;
+}
+
+/* free action worker data table
+*/
+static void freeWrkrDataTable(action_t * const pThis)
+{
+ int freeSpot;
+ for(freeSpot = 0; freeSpot < pThis->wrkrDataTableSize; ++freeSpot) {
+ if(pThis->wrkrDataTable[freeSpot] != NULL) {
+ pThis->pMod->mod.om.freeWrkrInstance(pThis->wrkrDataTable[freeSpot]);
+ pThis->wrkrDataTable[freeSpot] = NULL;
+ }
+ }
+ free(pThis->wrkrDataTable);
+ return;
+}
+
+/* destructs an action descriptor object
+ * rgerhards, 2007-08-01
+ */
+rsRetVal actionDestruct(action_t * const pThis)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+
+ if(!strcmp((char*)modGetName(pThis->pMod), "builtin:omdiscard")) {
+ /* discard actions will be optimized out */
+ FINALIZE;
+ }
+
+ if(pThis->pQueue != NULL) {
+ qqueueDestruct(&pThis->pQueue);
+ }
+
+ /* destroy stats object, if we have one (may not always be
+ * be the case, e.g. if turned off)
+ */
+ if(pThis->statsobj != NULL)
+ statsobj.Destruct(&pThis->statsobj);
+
+ if(pThis->pModData != NULL)
+ pThis->pMod->freeInstance(pThis->pModData);
+
+ if(pThis->fdErrFile != -1)
+ close(pThis->fdErrFile);
+ pthread_mutex_destroy(&pThis->mutErrFile);
+ pthread_mutex_destroy(&pThis->mutAction);
+ pthread_mutex_destroy(&pThis->mutWrkrDataTable);
+ free((void*)pThis->pszErrFile);
+ free((void*)pThis->pszExternalStateFile);
+ free(pThis->pszName);
+ free(pThis->ppTpl);
+ free(pThis->peParamPassing);
+ freeWrkrDataTable(pThis);
+
+finalize_it:
+ free(pThis);
+ RETiRet;
+}
+
+
+/* Disable action, this means it will never again be usable
+ * until rsyslog is reloaded. Use only as a last resort, but
+ * depends on output module.
+ * rgerhards, 2007-08-02
+ */
+static inline void
+actionDisable(action_t *__restrict__ const pThis)
+{
+ pThis->bDisabled = 1;
+}
+
+
+
+/* create a new action descriptor object
+ * rgerhards, 2007-08-01
+ * Note that it is vital to set proper initial values as the v6 config
+ * system depends on these!
+ */
+rsRetVal actionConstruct(action_t **ppThis)
+{
+ DEFiRet;
+ action_t *pThis;
+
+ assert(ppThis != NULL);
+
+ CHKmalloc(pThis = (action_t*) calloc(1, sizeof(action_t)));
+ pThis->iResumeInterval = 30;
+ pThis->iResumeIntervalMax = 1800; /* max interval default is half an hour */
+ pThis->iResumeRetryCount = 0;
+ pThis->pszName = NULL;
+ pThis->pszErrFile = NULL;
+ pThis->maxErrFileSize = 0;
+ pThis->currentErrFileSize = 0;
+ pThis->pszExternalStateFile = NULL;
+ pThis->fdErrFile = -1;
+ pThis->bWriteAllMarkMsgs = 1;
+ pThis->iExecEveryNthOccur = 0;
+ pThis->iExecEveryNthOccurTO = 0;
+ pThis->iSecsExecOnceInterval = 0;
+ pThis->bExecWhenPrevSusp = 0;
+ pThis->bRepMsgHasMsg = 0;
+ pThis->bDisabled = 0;
+ pThis->isTransactional = 0;
+ pThis->bReportSuspension = -1; /* indicate "not yet set" */
+ pThis->bReportSuspensionCont = -1; /* indicate "not yet set" */
+ pThis->bCopyMsg = 0;
+ pThis->tLastOccur = datetime.GetTime(NULL); /* done once per action on startup only */
+ pThis->iActionNbr = loadConf->actions.iActionNbr;
+ pthread_mutex_init(&pThis->mutErrFile, NULL);
+ pthread_mutex_init(&pThis->mutAction, NULL);
+ pthread_mutex_init(&pThis->mutWrkrDataTable, NULL);
+ INIT_ATOMIC_HELPER_MUT(pThis->mutCAS);
+
+ /* indicate we have a new action */
+ loadConf->actions.iActionNbr++;
+
+finalize_it:
+ *ppThis = pThis;
+ RETiRet;
+}
+
+
+/* action construction finalizer
+ */
+rsRetVal
+actionConstructFinalize(action_t *__restrict__ const pThis, struct nvlst *lst)
+{
+ DEFiRet;
+ uchar pszAName[64]; /* friendly name of our action */
+
+ if(!strcmp((char*)modGetName(pThis->pMod), "builtin:omdiscard")) {
+ /* discard actions will be optimized out */
+ FINALIZE;
+ }
+ /* generate a friendly name for us action stats */
+ if(pThis->pszName == NULL) {
+ snprintf((char*) pszAName, sizeof(pszAName), "action-%d-%s",
+ pThis->iActionNbr, pThis->pMod->pszName);
+ pThis->pszName = ustrdup(pszAName);
+ }
+
+ /* cache transactional attribute */
+ pThis->isTransactional = pThis->pMod->mod.om.supportsTX;
+ if(pThis->isTransactional) {
+ int i;
+ for(i = 0 ; i < pThis->iNumTpls ; ++i) {
+ if(pThis->peParamPassing[i] != ACT_STRING_PASSING) {
+ LogError(0, RS_RET_INVLD_OMOD, "action '%s'(%d) is transactional but "
+ "parameter %d "
+ "uses invalid parameter passing mode -- disabling "
+ "action. This is probably caused by a pre-v7 "
+ "output module that needs upgrade.",
+ pThis->pszName, pThis->iActionNbr, i);
+ actionDisable(pThis);
+ ABORT_FINALIZE(RS_RET_INVLD_OMOD);
+
+ }
+ }
+ }
+
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&pThis->statsobj));
+ CHKiRet(statsobj.SetName(pThis->statsobj, pThis->pszName));
+ CHKiRet(statsobj.SetOrigin(pThis->statsobj, (uchar*)"core.action"));
+
+ STATSCOUNTER_INIT(pThis->ctrProcessed, pThis->mutCtrProcessed);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("processed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrProcessed));
+
+ STATSCOUNTER_INIT(pThis->ctrFail, pThis->mutCtrFail);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("failed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFail));
+
+ STATSCOUNTER_INIT(pThis->ctrSuspend, pThis->mutCtrSuspend);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("suspended"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrSuspend));
+ STATSCOUNTER_INIT(pThis->ctrSuspendDuration, pThis->mutCtrSuspendDuration);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("suspended.duration"),
+ ctrType_IntCtr, 0, &pThis->ctrSuspendDuration));
+
+ STATSCOUNTER_INIT(pThis->ctrResume, pThis->mutCtrResume);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("resumed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrResume));
+
+ CHKiRet(statsobj.ConstructFinalize(pThis->statsobj));
+
+ /* create our queue */
+
+ /* generate a friendly name for the queue */
+ snprintf((char*) pszAName, sizeof(pszAName), "%s queue",
+ pThis->pszName);
+
+ /* now check if we can run the action in "firehose mode" during stage one of
+ * its processing (that is before messages are enqueued into the action q).
+ * This is only possible if some features, which require strict sequence, are
+ * not used. Thankfully, that is usually the case. The benefit of firehose
+ * mode is much faster processing (and simpler code) -- rgerhards, 2010-06-08
+ */
+ if( pThis->iExecEveryNthOccur > 1
+ || pThis->iSecsExecOnceInterval
+ ) {
+ DBGPRINTF("info: firehose mode disabled for action because "
+ "iExecEveryNthOccur=%d, iSecsExecOnceInterval=%d\n",
+ pThis->iExecEveryNthOccur, pThis->iSecsExecOnceInterval);
+ pThis->submitToActQ = doSubmitToActionQComplex;
+ } else if(pThis->bWriteAllMarkMsgs) {
+ /* full firehose submission mode, default case*/
+ pThis->submitToActQ = doSubmitToActionQ;
+ } else {
+ /* nearly full-speed submission mode */
+ pThis->submitToActQ = doSubmitToActionQNotAllMark;
+ }
+
+ /* create queue */
+ /* action queues always (for now) have just one worker. This may change when
+ * we begin to implement an interface the enable output modules to request
+ * to be run on multiple threads. So far, this is forbidden by the interface
+ * spec. -- rgerhards, 2008-01-30
+ */
+ CHKiRet(qqueueConstruct(&pThis->pQueue, cs.ActionQueType, 1, cs.iActionQueueSize,
+ processBatchMain));
+ obj.SetName((obj_t*) pThis->pQueue, pszAName);
+ qqueueSetpAction(pThis->pQueue, pThis);
+
+ if(lst == NULL) { /* use legacy params? */
+ /* ... set some properties ... */
+# define setQPROP(func, directive, data) \
+ CHKiRet_Hdlr(func(pThis->pQueue, data)) { \
+ LogError(0, NO_ERRCODE, "Invalid " #directive ", \
+ error %d. Ignored, running with default setting", iRet); \
+ }
+# define setQPROPstr(func, directive, data) \
+ CHKiRet_Hdlr(func(pThis->pQueue, data, (data == NULL)? 0 : strlen((char*) data))) { \
+ LogError(0, NO_ERRCODE, "Invalid " #directive ", \
+ error %d. Ignored, running with default setting", iRet); \
+ }
+ setQPROP(qqueueSetsizeOnDiskMax, "$ActionQueueMaxDiskSpace", cs.iActionQueMaxDiskSpace);
+ setQPROP(qqueueSetiDeqBatchSize, "$ActionQueueDequeueBatchSize", cs.iActionQueueDeqBatchSize);
+ setQPROP(qqueueSetMaxFileSize, "$ActionQueueFileSize", cs.iActionQueMaxFileSize);
+ setQPROPstr(qqueueSetFilePrefix, "$ActionQueueFileName", cs.pszActionQFName);
+ setQPROP(qqueueSetiPersistUpdCnt, "$ActionQueueCheckpointInterval", cs.iActionQPersistUpdCnt);
+ setQPROP(qqueueSetbSyncQueueFiles, "$ActionQueueSyncQueueFiles", cs.bActionQSyncQeueFiles);
+ setQPROP(qqueueSettoQShutdown, "$ActionQueueTimeoutShutdown", cs.iActionQtoQShutdown );
+ setQPROP(qqueueSettoActShutdown, "$ActionQueueTimeoutActionCompletion", cs.iActionQtoActShutdown);
+ setQPROP(qqueueSettoWrkShutdown, "$ActionQueueWorkerTimeoutThreadShutdown", cs.iActionQtoWrkShutdown);
+ setQPROP(qqueueSettoEnq, "$ActionQueueTimeoutEnqueue", cs.iActionQtoEnq);
+ setQPROP(qqueueSetiHighWtrMrk, "$ActionQueueHighWaterMark", cs.iActionQHighWtrMark);
+ setQPROP(qqueueSetiLowWtrMrk, "$ActionQueueLowWaterMark", cs.iActionQLowWtrMark);
+ setQPROP(qqueueSetiDiscardMrk, "$ActionQueueDiscardMark", cs.iActionQDiscardMark);
+ setQPROP(qqueueSetiDiscardSeverity, "$ActionQueueDiscardSeverity", cs.iActionQDiscardSeverity);
+ setQPROP(qqueueSetiMinMsgsPerWrkr, "$ActionQueueWorkerThreadMinimumMessages", cs.iActionQWrkMinMsgs);
+ setQPROP(qqueueSetiNumWorkerThreads, "$ActionQueueWorkerThreads", cs.iActionQueueNumWorkers);
+ setQPROP(qqueueSetbSaveOnShutdown, "$ActionQueueSaveOnShutdown", cs.bActionQSaveOnShutdown);
+ setQPROP(qqueueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", cs.iActionQueueDeqSlowdown);
+ setQPROP(qqueueSetiDeqtWinFromHr, "$ActionQueueDequeueTimeBegin", cs.iActionQueueDeqtWinFromHr);
+ setQPROP(qqueueSetiDeqtWinToHr, "$ActionQueueDequeueTimeEnd", cs.iActionQueueDeqtWinToHr);
+ } else {
+ /* we have v6-style config params */
+ qqueueSetDefaultsActionQueue(pThis->pQueue);
+ qqueueApplyCnfParam(pThis->pQueue, lst);
+ }
+ qqueueCorrectParams(pThis->pQueue);
+
+# undef setQPROP
+# undef setQPROPstr
+
+ qqueueDbgPrint(pThis->pQueue);
+
+ DBGPRINTF("Action %p: queue %p created\n", pThis, pThis->pQueue);
+
+ if(pThis->bUsesMsgPassingMode && pThis->pQueue->qType != QUEUETYPE_DIRECT) {
+ parser_warnmsg("module %s with message passing mode uses "
+ "non-direct queue. This most probably leads to undesired "
+ "results. For message modificaton modules (mm*), this means "
+ "that they will have no effect - "
+ "see https://www.rsyslog.com/mm-no-queue/", (char*)modGetName(pThis->pMod));
+ }
+
+ /* and now reset the queue params (see comment in its function header!) */
+ actionResetQueueParams();
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* set the global resume interval
+ */
+rsRetVal actionSetGlobalResumeInterval(int iNewVal)
+{
+ cs.glbliActionResumeInterval = iNewVal;
+ return RS_RET_OK;
+}
+
+
+/* returns the action state name in human-readable form
+ * returned string must not be modified.
+ * rgerhards, 2009-05-07
+ */
+static uchar *getActStateName(action_t * const pThis, wti_t * const pWti)
+{
+ switch(getActionState(pWti, pThis)) {
+ case ACT_STATE_RDY:
+ return (uchar*) "rdy";
+ case ACT_STATE_ITX:
+ return (uchar*) "itx";
+ case ACT_STATE_RTRY:
+ return (uchar*) "rtry";
+ case ACT_STATE_SUSP:
+ return (uchar*) "susp";
+ case ACT_STATE_DATAFAIL:
+ return (uchar*) "datafail";
+ default:
+ return (uchar*) "ERROR/UNKNWON";
+ }
+}
+
+
+/* returns a suitable return code based on action state
+ * rgerhards, 2009-05-07
+ */
+static rsRetVal getReturnCode(action_t * const pThis, wti_t * const pWti)
+{
+ DEFiRet;
+
+ switch(getActionState(pWti, pThis)) {
+ case ACT_STATE_RDY:
+ iRet = RS_RET_OK;
+ break;
+ case ACT_STATE_ITX:
+ if(pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit) {
+ pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 0; /* auto-reset */
+ iRet = RS_RET_PREVIOUS_COMMITTED;
+ } else {
+ iRet = RS_RET_DEFER_COMMIT;
+ }
+ break;
+ case ACT_STATE_RTRY:
+ iRet = RS_RET_SUSPENDED;
+ break;
+ case ACT_STATE_SUSP:
+ iRet = RS_RET_ACTION_FAILED;
+ break;
+ case ACT_STATE_DATAFAIL:
+ iRet = RS_RET_DATAFAIL;
+ break;
+ default:
+ DBGPRINTF("Invalid action engine state %u, program error\n",
+ getActionState(pWti, pThis));
+ iRet = RS_RET_ERR;
+ break;
+ }
+
+ RETiRet;
+}
+
+
+/* set the action to a new state
+ * rgerhards, 2007-08-02
+ */
+static void
+actionSetState(action_t * const pThis, wti_t * const pWti, uint8_t newState)
+{
+ setActionState(pWti, pThis, newState);
+ DBGPRINTF("action[%s] transitioned to state: %s\n",
+ pThis->pszName, getActStateName(pThis, pWti));
+}
+
+/* Handles the transient commit state. So far, this is
+ * mostly a dummy...
+ * rgerhards, 2007-08-02
+ */
+static void actionCommitted(action_t * const pThis, wti_t * const pWti)
+{
+ actionSetState(pThis, pWti, ACT_STATE_RDY);
+}
+
+
+/* set action state according to external state file (if configured)
+*/
+static rsRetVal ATTR_NONNULL()
+checkExternalStateFile(action_t *const pThis, wti_t *const pWti)
+{
+ char filebuf[1024];
+ int fd = -1;
+ int r;
+ DEFiRet;
+
+ DBGPRINTF("checking external state file\n");
+
+ if(pThis->pszExternalStateFile == NULL) {
+ FINALIZE;
+ }
+
+ fd = open(pThis->pszExternalStateFile, O_RDONLY|O_CLOEXEC);
+ if(fd == -1) {
+ dbgprintf("could not read external state file\n");
+ FINALIZE;
+ }
+
+ r = read(fd, filebuf, sizeof(filebuf) - 1);
+ if(r < 1) {
+ dbgprintf("checkExternalStateFile read() returned %d\n", r);
+ FINALIZE;
+ }
+
+ filebuf[r] = '\0';
+ dbgprintf("external state file content: '%s'\n", filebuf);
+ /* trim trailing whitespace */
+ for(int j = r-1 ; j > 0 ; --j) {
+ if(filebuf[j] == '\n' || filebuf[j] == '\t' || filebuf[j] == ' ') {
+ filebuf[j] = '\0';
+ } else {
+ break;
+ }
+ }
+ if(!strcmp(filebuf, "SUSPENDED")) {
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "action '%s' suspended (module '%s') by external state file",
+ pThis->pszName, pThis->pMod->pszName);
+ actionRetry(pThis, pWti);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+finalize_it:
+ if(fd != -1) {
+ close(fd);
+ }
+ DBGPRINTF("done checking external state file, iRet=%d\n", iRet);
+ RETiRet;
+}
+
+
+/* we need to defer setting the action's own bReportSuspension state until
+ * after the full config has been processed. So the most simple case to do
+ * that is here. It's not a performance problem, as it happens infrequently.
+ * it's not a threading race problem, as always the same value will be written.
+ * As we need to do this in several places, we have moved the code to its own
+ * helper function.
+ */
+static void
+setSuspendMessageConfVars(action_t *__restrict__ const pThis)
+{
+ if(pThis->bReportSuspension == -1)
+ pThis->bReportSuspension = runConf->globals.bActionReportSuspension;
+ if(pThis->bReportSuspensionCont == -1) {
+ pThis->bReportSuspensionCont = runConf->globals.bActionReportSuspensionCont;
+ if(pThis->bReportSuspensionCont == -1)
+ pThis->bReportSuspensionCont = 1;
+ }
+}
+
+
+/* set action to "rtry" state.
+ * rgerhards, 2007-08-02
+ */
+static void ATTR_NONNULL() actionRetry(action_t * const pThis, wti_t * const pWti)
+{
+ setSuspendMessageConfVars(pThis);
+ actionSetState(pThis, pWti, ACT_STATE_RTRY);
+ if(pThis->bReportSuspension) {
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "action '%s' suspended (module '%s'), retry %d. There should "
+ "be messages before this one giving the reason for suspension.",
+ pThis->pszName, pThis->pMod->pszName,
+ getActionNbrResRtry(pWti, pThis));
+ }
+ incActionResumeInRow(pWti, pThis);
+}
+
+/* Suspend action, this involves changing the action state as well
+ * as setting the next retry time.
+ * if we have more than 10 retries, we prolong the
+ * retry interval. If something is really stalled, it will
+ * get re-tried only very, very seldom - but that saves
+ * CPU time. TODO: maybe a config option for that?
+ * rgerhards, 2007-08-02
+ */
+static void ATTR_NONNULL()
+actionSuspend(action_t * const pThis, wti_t * const pWti)
+{
+ time_t ttNow;
+ int suspendDuration;
+ char timebuf[32];
+
+ setSuspendMessageConfVars(pThis);
+
+ /* note: we can NOT use a cached timestamp, as time may have evolved
+ * since caching, and this would break logic (and it actually did so!)
+ */
+ datetime.GetTime(&ttNow);
+ suspendDuration = pThis->iResumeInterval * (getActionNbrResRtry(pWti, pThis) / 10 + 1);
+ if(pThis->iResumeIntervalMax > 0 && suspendDuration > pThis->iResumeIntervalMax) {
+ suspendDuration = pThis->iResumeIntervalMax;
+ }
+ pThis->ttResumeRtry = ttNow + suspendDuration;
+ actionSetState(pThis, pWti, ACT_STATE_SUSP);
+ pThis->ctrSuspendDuration += suspendDuration;
+ if(getActionNbrResRtry(pWti, pThis) == 0) {
+ STATSCOUNTER_INC(pThis->ctrSuspend, pThis->mutCtrSuspend);
+ }
+
+ if( pThis->bReportSuspensionCont
+ || (pThis->bReportSuspension && getActionNbrResRtry(pWti, pThis) == 0) ) {
+ ctime_r(&pThis->ttResumeRtry, timebuf);
+ timebuf[strlen(timebuf)-1] = '\0'; /* strip LF */
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "action '%s' suspended (module '%s'), next retry is %s, retry nbr %d. "
+ "There should be messages before this one giving the reason for suspension.",
+ pThis->pszName, pThis->pMod->pszName, timebuf,
+ getActionNbrResRtry(pWti, pThis));
+ }
+ DBGPRINTF("action '%s' suspended, earliest retry=%lld (now %lld), iNbrResRtry %d, "
+ "duration %d\n",
+ pThis->pszName, (long long) pThis->ttResumeRtry, (long long) ttNow,
+ getActionNbrResRtry(pWti, pThis), suspendDuration);
+}
+
+
+/* actually do retry processing. Note that the function receives a timestamp so
+ * that we do not need to call the (expensive) time() API.
+ * Note that we do the full retry processing here, doing the configured number of
+ * iterations. -- rgerhards, 2009-05-07
+ * We need to guard against module which always return RS_RET_OK from their tryResume()
+ * entry point. This is invalid, but has harsh consequences: it will cause the rsyslog
+ * engine to go into a tight loop. That obviously is not acceptable. As such, we track the
+ * count of iterations that a tryResume returning RS_RET_OK is immediately followed by
+ * an unsuccessful call to doAction(). If that happens more than 10 times, we assume
+ * the return acutally is a RS_RET_SUSPENDED. In order to go through the various
+ * resumption stages, we do this for every 10 requests. This magic number 10 may
+ * not be the most appropriate, but it should be thought of a "if nothing else helps"
+ * kind of facility: in the first place, the module should return a proper indication
+ * of its inability to recover. -- rgerhards, 2010-04-26.
+ */
+static rsRetVal ATTR_NONNULL()
+actionDoRetry(action_t * const pThis, wti_t * const pWti)
+{
+ int iRetries;
+ int iSleepPeriod;
+ int bTreatOKasSusp;
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ iRetries = 0;
+ while((*pWti->pbShutdownImmediate == 0) && getActionState(pWti, pThis) == ACT_STATE_RTRY) {
+ DBGPRINTF("actionDoRetry: %s enter loop, iRetries=%d, ResumeInRow %d\n",
+ pThis->pszName, iRetries, getActionResumeInRow(pWti, pThis));
+ iRet = pThis->pMod->tryResume(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData);
+ DBGPRINTF("actionDoRetry: %s action->tryResume returned %d\n", pThis->pszName, iRet);
+ if((getActionResumeInRow(pWti, pThis) > 9) && (getActionResumeInRow(pWti, pThis) % 10 == 0)) {
+ bTreatOKasSusp = 1;
+ setActionResumeInRow(pWti, pThis, 0);
+ iRet = RS_RET_SUSPENDED;
+ } else {
+ bTreatOKasSusp = 0;
+ }
+ if((iRet == RS_RET_OK) && (!bTreatOKasSusp)) {
+ DBGPRINTF("actionDoRetry: %s had success RDY again (iRet=%d)\n",
+ pThis->pszName, iRet);
+ STATSCOUNTER_INC(pThis->ctrResume, pThis->mutCtrResume);
+ if(pThis->bReportSuspension) {
+ LogMsg(0, RS_RET_RESUMED, LOG_INFO, "action '%s' "
+ "resumed (module '%s')",
+ pThis->pszName, pThis->pMod->pszName);
+ }
+ actionSetState(pThis, pWti, ACT_STATE_RDY);
+ } else if(iRet == RS_RET_SUSPENDED || bTreatOKasSusp) {
+ /* max retries reached? */
+ DBGPRINTF("actionDoRetry: %s check for max retries, iResumeRetryCount "
+ "%d, iRetries %d\n",
+ pThis->pszName, pThis->iResumeRetryCount, iRetries);
+ if((pThis->iResumeRetryCount != -1 && iRetries >= pThis->iResumeRetryCount)) {
+ actionSuspend(pThis, pWti);
+ if(getActionNbrResRtry(pWti, pThis) < 20)
+ incActionNbrResRtry(pWti, pThis);
+ } else {
+ ++iRetries;
+ iSleepPeriod = pThis->iResumeInterval;
+ srSleep(iSleepPeriod, 0);
+ if(*pWti->pbShutdownImmediate) {
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ }
+ }
+ } else if(iRet == RS_RET_DISABLE_ACTION) {
+ actionDisable(pThis);
+ }
+ }
+
+ if(getActionState(pWti, pThis) == ACT_STATE_RDY) {
+ setActionNbrResRtry(pWti, pThis, 0);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* special retry handling if disabled via file: simply wait for the file
+ * to indicate whether or not it is ready again
+ */
+static rsRetVal ATTR_NONNULL()
+actionDoRetry_extFile(action_t *const pThis, wti_t *const pWti)
+{
+ int iRetries;
+ int iSleepPeriod;
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ DBGPRINTF("actionDoRetry_extFile: enter, actionState: %d\n",getActionState(pWti, pThis));
+ iRetries = 0;
+ while((*pWti->pbShutdownImmediate == 0) && getActionState(pWti, pThis) == ACT_STATE_RTRY) {
+ DBGPRINTF("actionDoRetry_extFile: %s enter loop, iRetries=%d, ResumeInRow %d\n",
+ pThis->pszName, iRetries, getActionResumeInRow(pWti, pThis));
+ iRet = checkExternalStateFile(pThis, pWti);
+ DBGPRINTF("actionDoRetry_extFile: %s checkExternalStateFile returned %d\n", pThis->pszName, iRet);
+ if(iRet == RS_RET_OK) {
+ DBGPRINTF("actionDoRetry_extFile: %s had success RDY again (iRet=%d)\n",
+ pThis->pszName, iRet);
+ if(pThis->bReportSuspension) {
+ LogMsg(0, RS_RET_RESUMED, LOG_INFO, "action '%s' "
+ "resumed (module '%s') via external state file",
+ pThis->pszName, pThis->pMod->pszName);
+ }
+ actionSetState(pThis, pWti, ACT_STATE_RDY);
+ } else if(iRet == RS_RET_SUSPENDED) {
+ /* max retries reached? */
+ DBGPRINTF("actionDoRetry_extFile: %s check for max retries, iResumeRetryCount "
+ "%d, iRetries %d\n",
+ pThis->pszName, pThis->iResumeRetryCount, iRetries);
+ if((pThis->iResumeRetryCount != -1 && iRetries >= pThis->iResumeRetryCount)) {
+ DBGPRINTF("actionDoRetry_extFile: did not work out, suspending\n");
+ actionSuspend(pThis, pWti);
+ pWti->execState.bPrevWasSuspended = 1;
+ if(getActionNbrResRtry(pWti, pThis) < 20)
+ incActionNbrResRtry(pWti, pThis);
+ } else {
+ ++iRetries;
+ iSleepPeriod = pThis->iResumeInterval;
+ srSleep(iSleepPeriod, 0);
+ if(*pWti->pbShutdownImmediate) {
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ }
+ }
+ } else if(iRet == RS_RET_DISABLE_ACTION) {
+ actionDisable(pThis);
+ }
+ }
+
+ if(getActionState(pWti, pThis) == ACT_STATE_RDY) {
+ setActionNbrResRtry(pWti, pThis, 0);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+actionCheckAndCreateWrkrInstance(action_t * const pThis, const wti_t *const pWti)
+{
+ int locked = 0;
+ DEFiRet;
+ if(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData == NULL) {
+ DBGPRINTF("wti %p: we need to create a new action worker instance for "
+ "action %d\n", pWti, pThis->iActionNbr);
+ CHKiRet(pThis->pMod->mod.om.createWrkrInstance(&(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData),
+ pThis->pModData));
+ pWti->actWrkrInfo[pThis->iActionNbr].pAction = pThis;
+ setActionState(pWti, pThis, ACT_STATE_RDY); /* action is enabled */
+
+ /* maintain worker data table -- only needed if wrkrHUP is requested! */
+
+ pthread_mutex_lock(&pThis->mutWrkrDataTable);
+ locked = 1;
+ int freeSpot;
+ for(freeSpot = 0 ; freeSpot < pThis->wrkrDataTableSize ; ++freeSpot)
+ if(pThis->wrkrDataTable[freeSpot] == NULL)
+ break;
+ if(pThis->nWrkr == pThis->wrkrDataTableSize) {
+ void *const newTable = realloc(pThis->wrkrDataTable,
+ (pThis->wrkrDataTableSize + 1) * sizeof(void*));
+ if(newTable == NULL) {
+ DBGPRINTF("actionCheckAndCreateWrkrInstance: out of "
+ "memory realloc wrkrDataTable\n")
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pThis->wrkrDataTable = newTable;
+ pThis->wrkrDataTableSize++;
+ }
+ pThis->wrkrDataTable[freeSpot] = pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData;
+ pThis->nWrkr++;
+ DBGPRINTF("wti %p: created action worker instance %d for "
+ "action %d\n", pWti, pThis->nWrkr, pThis->iActionNbr);
+ }
+finalize_it:
+ if(locked) {
+ pthread_mutex_unlock(&pThis->mutWrkrDataTable);
+ }
+ RETiRet;
+}
+
+/* try to resume an action -- rgerhards, 2007-08-02
+ * changed to new action state engine -- rgerhards, 2009-05-07
+ */
+static rsRetVal
+actionTryResume(action_t * const pThis, wti_t * const pWti)
+{
+ DEFiRet;
+ time_t ttNow = NO_TIME_PROVIDED;
+
+ if(getActionState(pWti, pThis) == ACT_STATE_SUSP) {
+ /* if we are suspended, we need to check if the timeout expired.
+ * for this handling, we must always obtain a fresh timestamp. We used
+ * to use the action timestamp, but in this case we will never reach a
+ * point where a resumption is actually tried, because the action timestamp
+ * is always in the past. So we can not avoid doing a fresh time() call
+ * here. -- rgerhards, 2009-03-18
+ */
+ datetime.GetTime(&ttNow); /* cache "now" */
+ if(ttNow >= pThis->ttResumeRtry) {
+ actionSetState(pThis, pWti, ACT_STATE_RTRY); /* back to retries */
+ }
+ }
+
+ if(getActionState(pWti, pThis) == ACT_STATE_RTRY) {
+ CHKiRet(actionDoRetry(pThis, pWti));
+ }
+
+ if(Debug && (getActionState(pWti, pThis) == ACT_STATE_RTRY ||
+ getActionState(pWti, pThis) == ACT_STATE_SUSP)) {
+ if(ttNow == NO_TIME_PROVIDED) /* use cached result if we have it */
+ datetime.GetTime(&ttNow);
+ dbgprintf("actionTryResume: action[%s] state: %s, next retry (if applicable): %u [now %u]\n",
+ pThis->pszName, getActStateName(pThis, pWti),
+ (unsigned) pThis->ttResumeRtry, (unsigned) ttNow);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* prepare an action for performing work. This involves trying to recover it,
+ * depending on its current state.
+ * rgerhards, 2009-05-07
+ */
+static rsRetVal ATTR_NONNULL()
+actionPrepare(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti)
+{
+ DEFiRet;
+
+DBGPRINTF("actionPrepare[%s]: enter\n", pThis->pszName);
+ CHKiRet(actionCheckAndCreateWrkrInstance(pThis, pWti));
+ CHKiRet(actionTryResume(pThis, pWti));
+
+ /* if we are now ready, we initialize the transaction and advance
+ * action state accordingly
+ */
+ if(getActionState(pWti, pThis) == ACT_STATE_RDY) {
+ iRet = checkExternalStateFile(pThis, pWti);
+ if(iRet == RS_RET_SUSPENDED) {
+ DBGPRINTF("actionPrepare[%s]: SUSPENDED via external state file, "
+ "doing retry processing\n", pThis->pszName);
+ CHKiRet(actionDoRetry_extFile(pThis, pWti));
+ }
+ iRet = pThis->pMod->mod.om.beginTransaction(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData);
+ switch(iRet) {
+ case RS_RET_OK:
+ actionSetState(pThis, pWti, ACT_STATE_ITX);
+ break;
+ case RS_RET_SUSPENDED:
+ actionRetry(pThis, pWti);
+ break;
+ case RS_RET_DISABLE_ACTION:
+ actionDisable(pThis);
+ break;
+ default:FINALIZE;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* prepare the calling parameters for doAction()
+ * rgerhards, 2009-05-07
+ */
+static rsRetVal
+prepareDoActionParams(action_t * __restrict__ const pAction,
+ wti_t * __restrict__ const pWti,
+ smsg_t *__restrict__ const pMsg,
+ struct syslogTime *ttNow)
+{
+ int i;
+ struct json_object *json;
+ actWrkrIParams_t *iparams;
+ actWrkrInfo_t *__restrict__ pWrkrInfo;
+ DEFiRet;
+
+ pWrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]);
+ if(pAction->isTransactional) {
+ CHKiRet(wtiNewIParam(pWti, pAction, &iparams));
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ CHKiRet(tplToString(pAction->ppTpl[i], pMsg,
+ &actParam(iparams, pAction->iNumTpls, 0, i),
+ ttNow));
+ }
+ } else {
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ switch(pAction->peParamPassing[i]) {
+ case ACT_STRING_PASSING:
+ CHKiRet(tplToString(pAction->ppTpl[i], pMsg,
+ &(pWrkrInfo->p.nontx.actParams[i]),
+ ttNow));
+ break;
+ /* note: ARRAY_PASSING mode has been removed in 8.26.0; if it
+ * is ever needed again, it can be found in 8.25.0.
+ * rgerhards 2017-03-06
+ */
+ case ACT_MSG_PASSING:
+ pWrkrInfo->p.nontx.actParams[i].param = (void*) pMsg;
+ break;
+ case ACT_JSON_PASSING:
+ CHKiRet(tplToJSON(pAction->ppTpl[i], pMsg, &json, ttNow));
+ pWrkrInfo->p.nontx.actParams[i].param = (void*) json;
+ break;
+ default:dbgprintf("software bug/error: unknown "
+ "pAction->peParamPassing[%d] %d in prepareDoActionParams\n",
+ i, (int) pAction->peParamPassing[i]);
+ break;
+ }
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+void
+releaseDoActionParams(action_t *__restrict__ const pAction, wti_t *__restrict__ const pWti, int action_destruct)
+{
+ int j;
+ actWrkrInfo_t *__restrict__ pWrkrInfo;
+
+ pWrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]);
+ for(j = 0 ; j < pAction->iNumTpls ; ++j) {
+ if (action_destruct) {
+ if (ACT_STRING_PASSING == pAction->peParamPassing[j]) {
+ free(pWrkrInfo->p.nontx.actParams[j].param);
+ pWrkrInfo->p.nontx.actParams[j].param = NULL;
+ pWrkrInfo->p.nontx.actParams[j].lenBuf = 0;
+ pWrkrInfo->p.nontx.actParams[j].lenStr = 0;
+ }
+ } else {
+ switch(pAction->peParamPassing[j]) {
+ case ACT_ARRAY_PASSING:
+ LogError(0, RS_RET_ERR, "plugin error: no longer supported "
+ "ARRAY_PASSING mode is used (see action.c)");
+ return;
+ case ACT_JSON_PASSING:
+ json_object_put((struct json_object*)
+ pWrkrInfo->p.nontx.actParams[j].param);
+ pWrkrInfo->p.nontx.actParams[j].param = NULL;
+ pWrkrInfo->p.nontx.actParams[j].lenBuf = 0;
+ pWrkrInfo->p.nontx.actParams[j].lenStr = 0;
+ break;
+ case ACT_STRING_PASSING:
+ case ACT_MSG_PASSING:
+ /* no need to do anything with these */
+ break;
+ }
+ }
+ }
+
+ return;
+}
+
+
+/* This is used in resume processing. We only finally know that a resume
+ * worked when we have been able to actually process a messages. As such,
+ * we need to do some cleanup and status tracking in that case.
+ */
+static void
+actionSetActionWorked(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti)
+{
+ setActionResumeInRow(pWti, pThis, 0);
+}
+
+static rsRetVal
+handleActionExecResult(action_t *__restrict__ const pThis,
+ wti_t *__restrict__ const pWti,
+ const rsRetVal ret)
+{
+ DEFiRet;
+ switch(ret) {
+ case RS_RET_OK:
+ actionCommitted(pThis, pWti);
+ actionSetActionWorked(pThis, pWti); /* we had a successful call! */
+ break;
+ case RS_RET_DEFER_COMMIT:
+ actionSetActionWorked(pThis, pWti); /* we had a successful call! */
+ /* we are done, action state remains the same */
+ break;
+ case RS_RET_PREVIOUS_COMMITTED:
+ /* action state remains the same, but we had a commit. */
+ pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 1;
+ actionSetActionWorked(pThis, pWti); /* we had a successful call! */
+ break;
+ case RS_RET_DISABLE_ACTION:
+ actionDisable(pThis);
+ break;
+ case RS_RET_SUSPENDED:
+ actionRetry(pThis, pWti);
+ break;
+ default:/* error happened - if it hits us here, we assume the message cannot
+ * be processed but an retry makes no sense. Usually, this should be
+ * return code RS_RET_DATAFAIL. -- rgerhards, 2017-10-06
+ */
+ LogError(0, ret, "action '%s' (module '%s') "
+ "message lost, could not be processed. Check for "
+ "additional error messages before this one.",
+ pThis->pszName, pThis->pMod->pszName);
+ actionSetState(pThis, pWti, ACT_STATE_DATAFAIL);
+ break;
+ }
+ iRet = getReturnCode(pThis, pWti);
+
+ RETiRet;
+}
+
+/* call the DoAction output plugin entry point
+ * rgerhards, 2008-01-28
+ */
+static rsRetVal
+actionCallDoAction(action_t *__restrict__ const pThis,
+ actWrkrIParams_t *__restrict__ const iparams,
+ wti_t *__restrict__ const pWti)
+{
+ void *param[CONF_OMOD_NUMSTRINGS_MAXSIZE];
+ int i;
+ DEFiRet;
+
+ DBGPRINTF("entering actionCalldoAction(), state: %s, actionNbr %d\n",
+ getActStateName(pThis, pWti), pThis->iActionNbr);
+
+ pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 0;
+ /* for this interface, we need to emulate the old style way
+ * of parameter passing.
+ */
+ for(i = 0 ; i < pThis->iNumTpls ; ++i) {
+ param[i] = actParam(iparams, pThis->iNumTpls, 0, i).param;
+ }
+
+ iRet = pThis->pMod->mod.om.doAction(param,
+ pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData);
+ iRet = handleActionExecResult(pThis, pWti, iRet);
+ RETiRet;
+}
+
+
+/* call the commitTransaction output plugin entry point */
+static rsRetVal ATTR_NONNULL()
+actionCallCommitTransaction(action_t * const pThis,
+ wti_t *const pWti,
+ actWrkrIParams_t *__restrict__ const iparams, const int nparams)
+{
+ DEFiRet;
+
+ DBGPRINTF("entering actionCallCommitTransaction[%s], state: %s, nMsgs %u\n",
+ pThis->pszName, getActStateName(pThis, pWti), nparams);
+
+ iRet = pThis->pMod->mod.om.commitTransaction(
+ pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData,
+ iparams, nparams);
+ DBGPRINTF("actionCallCommitTransaction[%s] state: %s "
+ "mod commitTransaction returned %d\n",
+ pThis->pszName, getActStateName(pThis, pWti), iRet);
+ iRet = handleActionExecResult(pThis, pWti, iRet);
+ RETiRet;
+}
+
+
+/* process a message
+ * this readies the action and then calls doAction()
+ * rgerhards, 2008-01-28
+ */
+static rsRetVal
+actionProcessMessage(action_t * const pThis, void *actParams, wti_t * const pWti)
+{
+ DEFiRet;
+
+ CHKiRet(actionPrepare(pThis, pWti));
+ if(pThis->pMod->mod.om.SetShutdownImmdtPtr != NULL)
+ pThis->pMod->mod.om.SetShutdownImmdtPtr(pThis->pModData, pWti->pbShutdownImmediate);
+ if(getActionState(pWti, pThis) == ACT_STATE_ITX)
+ CHKiRet(actionCallDoAction(pThis, actParams, pWti));
+
+ iRet = getReturnCode(pThis, pWti);
+finalize_it:
+ RETiRet;
+}
+
+
+/* the following function uses the new-style transactional interface */
+static rsRetVal
+doTransaction(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti,
+ actWrkrIParams_t *__restrict__ const iparams, const int nparams)
+{
+ actWrkrInfo_t *wrkrInfo;
+ int i;
+ DEFiRet;
+
+ wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]);
+ if(pThis->pMod->mod.om.commitTransaction != NULL) {
+ DBGPRINTF("doTransaction: have commitTransaction IF, using that, pWrkrInfo %p\n", wrkrInfo);
+ CHKiRet(actionCallCommitTransaction(pThis, pWti, iparams, nparams));
+ } else { /* note: this branch is for compatibility with old TX modules */
+ DBGPRINTF("doTransaction: action '%s', currIParam %d\n",
+ pThis->pszName, wrkrInfo->p.tx.currIParam);
+ for(i = 0 ; i < nparams ; ++i) {
+ /* Note: we provide the message's base iparam - actionProcessMessage()
+ * uses this as *base* address.
+ */
+ iRet = actionProcessMessage(pThis,
+ &actParam(iparams, pThis->iNumTpls, i, 0), pWti);
+ DBGPRINTF("doTransaction: action %d, processing msg %d, result %d\n",
+ pThis->iActionNbr, i,iRet);
+ if(iRet == RS_RET_SUSPENDED) {
+ --i; /* we need to re-submit */
+ /* note: we are suspended and need to retry. In order not to
+ * hammer the CPU, we now do a voluntarly wait of 1 second.
+ * The rest will be handled by the standard retry handler.
+ */
+ srSleep(1, 0);
+ } else if(iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED &&
+ iRet != RS_RET_OK) {
+ FINALIZE; /* let upper peer handle the error condition! */
+ }
+ }
+ }
+finalize_it:
+ if(iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED)
+ iRet = RS_RET_OK; /* this is expected for transactional action! */
+ RETiRet;
+}
+
+
+/* Commit try committing (do not handle retry processing and such) */
+static rsRetVal ATTR_NONNULL()
+actionTryCommit(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti,
+ actWrkrIParams_t *__restrict__ const iparams, const int nparams)
+{
+ DEFiRet;
+
+ DBGPRINTF("actionTryCommit[%s] enter\n", pThis->pszName);
+ CHKiRet(actionPrepare(pThis, pWti));
+
+ CHKiRet(doTransaction(pThis, pWti, iparams, nparams));
+
+ if(getActionState(pWti, pThis) == ACT_STATE_ITX) {
+ iRet = pThis->pMod->mod.om.endTransaction(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData);
+ switch(iRet) {
+ case RS_RET_OK:
+ actionCommitted(pThis, pWti);
+ break;
+ case RS_RET_SUSPENDED:
+ actionRetry(pThis, pWti);
+ break;
+ case RS_RET_DISABLE_ACTION:
+ actionDisable(pThis);
+ break;
+ case RS_RET_DEFER_COMMIT:
+ DBGPRINTF("output plugin error: endTransaction() returns RS_RET_DEFER_COMMIT "
+ "- ignored\n");
+ actionCommitted(pThis, pWti);
+ break;
+ case RS_RET_PREVIOUS_COMMITTED:
+ DBGPRINTF("output plugin error: endTransaction() returns RS_RET_PREVIOUS_COMMITTED "
+ "- ignored\n");
+ actionCommitted(pThis, pWti);
+ break;
+ default:/* permanent failure of this message - no sense in retrying. This is
+ * not yet handled (but easy TODO)
+ */
+ DBGPRINTF("action[%s]: actionTryCommit receveived iRet %d\n",
+ pThis->pszName, iRet);
+ FINALIZE;
+ }
+ }
+ iRet = getReturnCode(pThis, pWti);
+
+finalize_it:
+ RETiRet;
+}
+
+/* If a transcation failed, we write the error file (if configured).
+ */
+static void ATTR_NONNULL()
+actionWriteErrorFile(action_t *__restrict__ const pThis, const rsRetVal ret,
+ actWrkrIParams_t *__restrict__ const iparams, const int nparams)
+{
+ fjson_object *etry=NULL;
+ int bNeedUnlock = 0;
+
+ STATSCOUNTER_INC(pThis->ctrFail, pThis->mutCtrFail);
+
+ if(pThis->pszErrFile == NULL) {
+ DBGPRINTF("action %s: commit failed, no error file set, silently "
+ "discarding %d messages\n", pThis->pszName, nparams);
+ goto done;
+ }
+
+ DBGPRINTF("action %d commit failed, writing %u messages (%d tpls) to error file\n",
+ pThis->iActionNbr, nparams, pThis->iNumTpls);
+
+ pthread_mutex_lock(&pThis->mutErrFile);
+ bNeedUnlock = 1;
+
+ if(pThis->fdErrFile == -1) {
+ pThis->fdErrFile = open(pThis->pszErrFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pThis->fdErrFile == -1) {
+ LogError(errno, RS_RET_ERR, "action %s: error opening error file %s",
+ pThis->pszName, pThis->pszErrFile);
+ goto done;
+ }
+ if (pThis->maxErrFileSize > 0) {
+ struct stat statbuf;
+ if (fstat(pThis->fdErrFile, &statbuf) == -1) {
+ LogError(errno, RS_RET_ERR, "failed to fstat %s", pThis->pszErrFile);
+ goto done;
+ }
+ pThis->currentErrFileSize = statbuf.st_size;
+ }
+ }
+
+ for(int i = 0 ; i < nparams ; ++i) {
+ if((etry = fjson_object_new_object()) == NULL)
+ goto done;
+ fjson_object_object_add(etry, "action", fjson_object_new_string((char*)pThis->pszName));
+ fjson_object_object_add(etry, "status", fjson_object_new_int(ret));
+ for(int j = 0 ; j < pThis->iNumTpls ; ++j) {
+ char tplname[20];
+ snprintf(tplname, sizeof(tplname), "template%d", j);
+ tplname[sizeof(tplname)-1] = '\0';
+ fjson_object_object_add(etry, tplname,
+ fjson_object_new_string((char*)actParam(iparams, 1, i, j).param));
+ }
+
+ char *const rendered = strdup((char*)fjson_object_to_json_string(etry));
+ if(rendered == NULL)
+ goto done;
+
+ size_t toWrite = strlen(rendered) + 1;
+ // Check if need to truncate the amount of bytes to write
+ if (pThis->maxErrFileSize > 0) {
+ if (pThis->currentErrFileSize + toWrite > pThis->maxErrFileSize) {
+ // Truncate to the pending available
+ toWrite = pThis->maxErrFileSize - pThis->currentErrFileSize;
+ }
+ pThis->currentErrFileSize += toWrite;
+ }
+ if(toWrite > 0) {
+ /* note: we use the '\0' inside the string to store a LF - we do not
+ * otherwise need it and it safes us a copy/realloc.
+ */
+ rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+ const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite);
+ if(wrRet != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "action %s: error writing errorFile %s, write returned %lld",
+ pThis->pszName, pThis->pszErrFile, (long long) wrRet);
+ }
+ }
+ free(rendered);
+
+ fjson_object_put(etry);
+ etry = NULL;
+ }
+done:
+ if(bNeedUnlock) {
+ pthread_mutex_unlock(&pThis->mutErrFile);
+ }
+ fjson_object_put(etry);
+ return;
+}
+
+
+static rsRetVal
+actionTryRemoveHardErrorsFromBatch(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti,
+ actWrkrIParams_t *const new_iparams, unsigned *new_nMsgs)
+{
+ actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]);
+ const unsigned nMsgs = wrkrInfo->p.tx.currIParam;
+ actWrkrIParams_t oneParamSet[CONF_OMOD_NUMSTRINGS_MAXSIZE];
+ rsRetVal ret;
+ DEFiRet;
+
+ *new_nMsgs = 0;
+ for(unsigned i = 0 ; i < nMsgs ; ++i) {
+ setActionResumeInRow(pWti, pThis, 0); // make sure we do not trigger OK-as-SUSPEND handling
+ memcpy(&oneParamSet, &actParam(wrkrInfo->p.tx.iparams, pThis->iNumTpls, i, 0),
+ sizeof(actWrkrIParams_t) * pThis->iNumTpls);
+ ret = actionTryCommit(pThis, pWti, oneParamSet, 1);
+ if(ret == RS_RET_SUSPENDED) {
+ memcpy(new_iparams + (*new_nMsgs * pThis->iNumTpls), &oneParamSet,
+ sizeof(actWrkrIParams_t) * pThis->iNumTpls);
+ ++(*new_nMsgs);
+ } else if(ret != RS_RET_OK) {
+ actionWriteErrorFile(pThis, ret, oneParamSet, 1);
+ }
+ }
+ RETiRet;
+}
+
+/* Note: we currently need to return an iRet, as this is used in
+ * direct mode. TODO: However, it may be worth further investigating this,
+ * as it looks like there is no ultimate consumer of this code.
+ * rgerhards, 2013-11-06
+ */
+static rsRetVal ATTR_NONNULL()
+actionCommit(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti)
+{
+ actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]);
+ /* Variables that permit us to override the batch of messages */
+ unsigned nMsgs = 0;
+ actWrkrIParams_t *iparams = NULL;
+ int needfree_iparams = 0; // work-around for clang static analyzer false positive
+ DEFiRet;
+
+ DBGPRINTF("actionCommit[%s]: enter, %d msgs\n", pThis->pszName, wrkrInfo->p.tx.currIParam);
+ if(!pThis->isTransactional || pWti->actWrkrInfo[pThis->iActionNbr].p.tx.currIParam == 0) {
+ FINALIZE;
+ } else if(getActionState(pWti, pThis) == ACT_STATE_SUSP) {
+ /* if we are suspended, we already tried everything to recover the
+ * action - and failed. So all we can do here is write the error file.
+ */
+ actionWriteErrorFile(pThis, iRet, wrkrInfo->p.tx.iparams, wrkrInfo->p.tx.currIParam);
+ FINALIZE;
+ }
+ DBGPRINTF("actionCommit[%s]: processing...\n", pThis->pszName);
+
+ /* we now do one try at commiting the whole batch. Usually, this will
+ * succeed. If so, we are happy and done. If not, we dig into the details
+ * of finding out if we have a non-temporary error and try to handle this
+ * as well as retry processing. Due to this logic we do a bit more retries
+ * than configured (if temporary failure), but this unavoidable and should
+ * do no real harm. - rgerhards, 2017-10-06
+ */
+ iRet = actionTryCommit(pThis, pWti, wrkrInfo->p.tx.iparams, wrkrInfo->p.tx.currIParam);
+DBGPRINTF("actionCommit[%s]: return actionTryCommit %d\n", pThis->pszName, iRet);
+ if(iRet == RS_RET_OK) {
+ FINALIZE;
+ }
+
+ /* check if this was a single-message batch. If it had a datafail error, we
+ * are done. If it is a multi-message batch, we need to sort out the individual
+ * message states.
+ */
+ if(wrkrInfo->p.tx.currIParam == 1) {
+ needfree_iparams = 0;
+ iparams = wrkrInfo->p.tx.iparams;
+ nMsgs = wrkrInfo->p.tx.currIParam;
+ if(iRet == RS_RET_DATAFAIL) {
+ FINALIZE;
+ }
+ } else {
+ DBGPRINTF("actionCommit[%s]: somewhat unhappy, full batch of %d msgs returned "
+ "status %d. Trying messages as individual actions.\n",
+ pThis->pszName, wrkrInfo->p.tx.currIParam, iRet);
+ CHKmalloc(iparams = malloc(sizeof(actWrkrIParams_t) * pThis->iNumTpls
+ * wrkrInfo->p.tx.currIParam));
+ needfree_iparams = 1;
+ actionTryRemoveHardErrorsFromBatch(pThis, pWti, iparams, &nMsgs);
+ }
+
+ if(nMsgs == 0) {
+ ABORT_FINALIZE(RS_RET_OK); // here, we consider everyting OK
+ }
+
+ /* We still have some messages with suspend error. So now let's do our
+ * "regular" retry and suspend processing.
+ */
+ DBGPRINTF("actionCommit[%s]: unhappy, we still have %d uncommitted messages.\n",
+ pThis->pszName, nMsgs);
+ int bDone = 0;
+ do {
+ iRet = actionTryCommit(pThis, pWti, iparams, nMsgs);
+ DBGPRINTF("actionCommit[%s]: in retry loop, iRet %d\n",
+ pThis->pszName, iRet);
+ if(iRet == RS_RET_FORCE_TERM) {
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ } else if(iRet == RS_RET_SUSPENDED) {
+ iRet = actionDoRetry(pThis, pWti);
+ DBGPRINTF("actionCommit[%s]: actionDoRetry returned %d\n",
+ pThis->pszName, iRet);
+ if(iRet == RS_RET_FORCE_TERM) {
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ } else if(iRet != RS_RET_OK) {
+ actionWriteErrorFile(pThis, iRet, iparams, nMsgs);
+ bDone = 1;
+ }
+ continue;
+ } else if(iRet == RS_RET_OK ||
+ iRet == RS_RET_SUSPENDED ||
+ iRet == RS_RET_ACTION_FAILED) {
+ bDone = 1;
+ }
+ if(getActionState(pWti, pThis) == ACT_STATE_RDY ||
+ getActionState(pWti, pThis) == ACT_STATE_SUSP) {
+ bDone = 1;
+ }
+ } while(!bDone);
+finalize_it:
+ DBGPRINTF("actionCommit[%s]: done, iRet %d\n", pThis->pszName, iRet);
+ if(needfree_iparams) {
+ free(iparams);
+ }
+ wrkrInfo->p.tx.currIParam = 0; /* reset to beginning */
+ RETiRet;
+}
+
+/* Commit all active transactions in *DIRECT mode* */
+void ATTR_NONNULL()
+actionCommitAllDirect(wti_t *__restrict__ const pWti)
+{
+ int i;
+ action_t *pAction;
+
+ for(i = 0 ; i < runConf->actions.iActionNbr ; ++i) {
+ pAction = pWti->actWrkrInfo[i].pAction;
+ if(pAction == NULL)
+ continue;
+ DBGPRINTF("actionCommitAllDirect: action %d, state %u, nbr to commit %d "
+ "isTransactional %d\n",
+ i, getActionStateByNbr(pWti, i), pWti->actWrkrInfo->p.tx.currIParam,
+ pAction->isTransactional);
+ if(pAction->pQueue->qType == QUEUETYPE_DIRECT)
+ actionCommit(pAction, pWti);
+ }
+}
+
+/* process a single message. This is both called if we run from the
+ * consumer side of an action queue as well as directly from the main
+ * queue thread if the action queue is set to "direct".
+ */
+static rsRetVal
+processMsgMain(action_t *__restrict__ const pAction,
+ wti_t *__restrict__ const pWti,
+ smsg_t *__restrict__ const pMsg,
+ struct syslogTime *ttNow)
+{
+ DEFiRet;
+
+ CHKiRet(prepareDoActionParams(pAction, pWti, pMsg, ttNow));
+
+ if(pAction->isTransactional) {
+ pWti->actWrkrInfo[pAction->iActionNbr].pAction = pAction;
+ DBGPRINTF("action '%s': is transactional - executing in commit phase\n", pAction->pszName);
+ actionPrepare(pAction, pWti);
+ iRet = getReturnCode(pAction, pWti);
+ FINALIZE;
+ }
+
+ iRet = actionProcessMessage(pAction,
+ pWti->actWrkrInfo[pAction->iActionNbr].p.nontx.actParams,
+ pWti);
+ if(pAction->bNeedReleaseBatch)
+ releaseDoActionParams(pAction, pWti, 0);
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ if(pWti->execState.bDoAutoCommit)
+ iRet = actionCommit(pAction, pWti);
+ }
+ RETiRet;
+}
+
+/* This entry point is called by the ACTION queue (not main queue!)
+ */
+static rsRetVal ATTR_NONNULL()
+processBatchMain(void *__restrict__ const pVoid,
+ batch_t *__restrict__ const pBatch,
+ wti_t *__restrict__ const pWti)
+{
+ action_t *__restrict__ const pAction = (action_t*__restrict__ const) pVoid;
+ int i;
+ struct syslogTime ttNow;
+ DEFiRet;
+
+ wtiResetExecState(pWti, pBatch);
+ /* indicate we have not yet read the date */
+ ttNow.year = 0;
+
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*pWti->pbShutdownImmediate ; ++i) {
+ if(batchIsValidElem(pBatch, i)) {
+ /* we do not check error state below, because aborting would be
+ * more harmful than continuing.
+ */
+ rsRetVal localRet = processMsgMain(pAction, pWti, pBatch->pElem[i].pMsg, &ttNow);
+ DBGPRINTF("processBatchMain: i %d, processMsgMain iRet %d\n", i, localRet);
+ if( localRet == RS_RET_OK
+ || localRet == RS_RET_DEFER_COMMIT
+ || localRet == RS_RET_ACTION_FAILED
+ || localRet == RS_RET_PREVIOUS_COMMITTED ) {
+ batchSetElemState(pBatch, i, BATCH_STATE_COMM);
+ DBGPRINTF("processBatchMain: i %d, COMM state set\n", i);
+ }
+ }
+ }
+
+ iRet = actionCommit(pAction, pWti);
+ RETiRet;
+}
+
+
+/* remove an action worker instance from our table of
+ * workers. To be called from worker handler (wti).
+ */
+void
+actionRemoveWorker(action_t *const __restrict__ pAction,
+ void *const __restrict__ actWrkrData)
+{
+ pthread_mutex_lock(&pAction->mutWrkrDataTable);
+ pAction->nWrkr--;
+ for(int w = 0 ; w < pAction->wrkrDataTableSize ; ++w) {
+ if(pAction->wrkrDataTable[w] == actWrkrData) {
+ pAction->wrkrDataTable[w] = NULL;
+ break; /* done */
+ }
+ }
+ pthread_mutex_unlock(&pAction->mutWrkrDataTable);
+}
+
+
+/* call the HUP handler for a given action, if such a handler is defined.
+ * Note that the action must be able to service HUP requests concurrently
+ * to any current doAction() processing.
+ */
+rsRetVal
+actionCallHUPHdlr(action_t * const pAction)
+{
+ DEFiRet;
+
+ assert(pAction != NULL);
+ DBGPRINTF("Action %p checks HUP hdlr, act level: %p, wrkr level %p\n",
+ pAction, pAction->pMod->doHUP, pAction->pMod->doHUPWrkr);
+
+ if(pAction->pMod->doHUP != NULL) {
+ CHKiRet(pAction->pMod->doHUP(pAction->pModData));
+ }
+
+ if(pAction->pMod->doHUPWrkr != NULL) {
+ pthread_mutex_lock(&pAction->mutWrkrDataTable);
+ for(int i = 0 ; i < pAction->wrkrDataTableSize ; ++i) {
+ dbgprintf("HUP: table entry %d: %p %s\n", i,
+ pAction->wrkrDataTable[i],
+ pAction->wrkrDataTable[i] == NULL ? "[unused]" : "");
+ if(pAction->wrkrDataTable[i] != NULL) {
+ const rsRetVal localRet
+ = pAction->pMod->doHUPWrkr(pAction->wrkrDataTable[i]);
+ if(localRet != RS_RET_OK) {
+ DBGPRINTF("HUP handler returned error state %d - "
+ "ignored\n", localRet);
+ }
+ }
+ }
+ pthread_mutex_unlock(&pAction->mutWrkrDataTable);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the action message queue mode
+ * TODO: probably move this into queue object, merge with MainMsgQueue!
+ * rgerhards, 2008-01-28
+ */
+static rsRetVal setActionQueType(void __attribute__((unused)) *pVal, uchar *pszType)
+{
+ DEFiRet;
+
+ if (!strcasecmp((char *) pszType, "fixedarray")) {
+ cs.ActionQueType = QUEUETYPE_FIXED_ARRAY;
+ DBGPRINTF("action queue type set to FIXED_ARRAY\n");
+ } else if (!strcasecmp((char *) pszType, "linkedlist")) {
+ cs.ActionQueType = QUEUETYPE_LINKEDLIST;
+ DBGPRINTF("action queue type set to LINKEDLIST\n");
+ } else if (!strcasecmp((char *) pszType, "disk")) {
+ cs.ActionQueType = QUEUETYPE_DISK;
+ DBGPRINTF("action queue type set to DISK\n");
+ } else if (!strcasecmp((char *) pszType, "direct")) {
+ cs.ActionQueType = QUEUETYPE_DIRECT;
+ DBGPRINTF("action queue type set to DIRECT (no queueing at all)\n");
+ } else {
+ LogError(0, RS_RET_INVALID_PARAMS, "unknown actionqueue parameter: %s", (char *) pszType);
+ iRet = RS_RET_INVALID_PARAMS;
+ }
+ free(pszType); /* no longer needed */
+
+ RETiRet;
+}
+
+
+/* This submits the message to the action queue in case we do NOT need to handle repeat
+ * message processing. That case permits us to gain lots of freedom during processing
+ * and thus speed. This is also utilized to submit messages in more complex cases once
+ * the complex logic has been applied ;)
+ * rgerhards, 2010-06-08
+ */
+static rsRetVal ATTR_NONNULL()
+doSubmitToActionQ(action_t * const pAction, wti_t * const pWti, smsg_t *pMsg)
+{
+ struct syslogTime ttNow; // TODO: think if we can buffer this in pWti
+ DEFiRet;
+
+ DBGPRINTF("action '%s': called, logging to %s (susp %d/%d, direct q %d)\n",
+ pAction->pszName, module.GetStateName(pAction->pMod),
+ pAction->bExecWhenPrevSusp, pWti->execState.bPrevWasSuspended,
+ pAction->pQueue->qType == QUEUETYPE_DIRECT);
+
+ if( pAction->bExecWhenPrevSusp
+ && !pWti->execState.bPrevWasSuspended) {
+ DBGPRINTF("action '%s': NOT executing, as previous action was "
+ "not suspended\n", pAction->pszName);
+ FINALIZE;
+ }
+
+ STATSCOUNTER_INC(pAction->ctrProcessed, pAction->mutCtrProcessed);
+ if(pAction->pQueue->qType == QUEUETYPE_DIRECT) {
+ ttNow.year = 0;
+ iRet = processMsgMain(pAction, pWti, pMsg, &ttNow);
+ } else {/* in this case, we do single submits to the queue.
+ * TODO: optimize this, we may do at least a multi-submit!
+ */
+ iRet = qqueueEnqMsg(pAction->pQueue, eFLOWCTL_NO_DELAY,
+ pAction->bCopyMsg ? MsgDup(pMsg) : MsgAddRef(pMsg));
+ }
+ pWti->execState.bPrevWasSuspended =
+ (iRet == RS_RET_SUSPENDED || iRet == RS_RET_ACTION_FAILED);
+
+ if (iRet == RS_RET_ACTION_FAILED) /* Increment failed counter */
+ STATSCOUNTER_INC(pAction->ctrFail, pAction->mutCtrFail);
+
+ DBGPRINTF("action '%s': set suspended state to %d\n",
+ pAction->pszName, pWti->execState.bPrevWasSuspended);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function builds up a batch of messages to be (later)
+ * submitted to the action queue.
+ * Important: this function MUST not be called with messages that are to
+ * be discarded due to their "prevWasSuspended" state. It will not check for
+ * this and submit all messages to the queue for execution. So these must
+ * be filtered out before calling us (what is done currently!).
+ */
+rsRetVal
+actionWriteToAction(action_t * const pAction, smsg_t *pMsg, wti_t * const pWti)
+{
+ DEFiRet;
+
+ /* first, we check if the action should actually be called. The action-specific
+ * $ActionExecOnlyEveryNthTime permits us to execute an action only every Nth
+ * time. So we need to check if we need to drop the (otherwise perfectly executable)
+ * action for this reason. Note that in case we need to drop it, we return RS_RET_OK
+ * as the action was properly "passed to execution" from the upper layer's point
+ * of view. -- rgerhards, 2008-08-07.
+ */
+ if(pAction->iExecEveryNthOccur > 1) {
+ /* we need to care about multiple occurrences */
+ if( pAction->iExecEveryNthOccurTO > 0
+ && (getActNow(pAction) - pAction->tLastOccur) > pAction->iExecEveryNthOccurTO) {
+ DBGPRINTF("n-th occurrence handling timed out (%d sec), restarting from 0\n",
+ (int) (getActNow(pAction) - pAction->tLastOccur));
+ pAction->iNbrNoExec = 0;
+ pAction->tLastOccur = getActNow(pAction);
+ }
+ if(pAction->iNbrNoExec < pAction->iExecEveryNthOccur - 1) {
+ ++pAction->iNbrNoExec;
+ DBGPRINTF("action %p passed %d times to execution - less than configured - discarding\n",
+ pAction, pAction->iNbrNoExec);
+ FINALIZE;
+ } else {
+ pAction->iNbrNoExec = 0; /* we execute the action now, so the number of no execs is down to */
+ }
+ }
+
+ DBGPRINTF("Called action(complex case), logging to %s\n", module.GetStateName(pAction->pMod));
+
+ /* now check if we need to drop the message because otherwise the action would be too
+ * frequently called. -- rgerhards, 2008-04-08
+ * Note that the check for "pAction->iSecsExecOnceInterval > 0" is not necessary from
+ * a purely logical point of view. However, if safes us to check the system time in
+ * (those common) cases where ExecOnceInterval is not used. -- rgerhards, 2008-09-16
+ */
+ if(pAction->iSecsExecOnceInterval > 0 &&
+ pAction->iSecsExecOnceInterval + pAction->tLastExec > getActNow(pAction)) {
+ /* in this case we need to discard the message - its not yet time to exec the action */
+ DBGPRINTF("action not yet ready again to be executed, onceInterval %d, tCurr %d, tNext %d\n",
+ (int) pAction->iSecsExecOnceInterval, (int) getActNow(pAction),
+ (int) (pAction->iSecsExecOnceInterval + pAction->tLastExec));
+ FINALIZE;
+ }
+
+ /* we use reception time, not dequeue time - this is considered more appropriate and also faster ;)
+ * rgerhards, 2008-09-17 */
+ pAction->tLastExec = getActNow(pAction); /* re-init time flags */
+ pAction->f_time = pMsg->ttGenTime;
+
+ /* When we reach this point, we have a valid, non-disabled action.
+ * So let's enqueue our message for execution. -- rgerhards, 2007-07-24
+ */
+ iRet = doSubmitToActionQ(pAction, pWti, pMsg);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Call configured action, most complex case with all features supported (and thus slow).
+ * rgerhards, 2010-06-08
+ */
+
+PRAGMA_DIAGNOSTIC_PUSH;
+PRAGMA_IGNORE_Wempty_body;
+static rsRetVal
+doSubmitToActionQComplex(action_t * const pAction, wti_t * const pWti, smsg_t *pMsg)
+{
+ DEFiRet;
+
+ d_pthread_mutex_lock(&pAction->mutAction);
+ pthread_cleanup_push(mutexCancelCleanup, &pAction->mutAction);
+ DBGPRINTF("Called action %p (complex case), logging to %s\n",
+ pAction, module.GetStateName(pAction->pMod));
+
+ pAction->tActNow = -1; /* we do not yet know our current time (clear prev. value) */
+ // TODO: can we optimize the "now" handling again (was batch, I guess...)?
+
+ /* don't output marks to recently written outputs */
+ if(pAction->bWriteAllMarkMsgs == 0
+ && (pMsg->msgFlags & MARK) && (getActNow(pAction) - pAction->f_time) < MarkInterval / 2) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* call the output driver */
+ iRet = actionWriteToAction(pAction, pMsg, pWti);
+
+finalize_it:
+ d_pthread_mutex_unlock(&pAction->mutAction);
+ pthread_cleanup_pop(0); /* remove mutex cleanup handler */
+
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+
+/* helper to activateActions, it activates a specific action.
+ */
+DEFFUNC_llExecFunc(doActivateActions)
+{
+ rsRetVal localRet;
+ action_t * const pThis = (action_t*) pData;
+ localRet = qqueueStart(runConf, pThis->pQueue);
+ if(localRet != RS_RET_OK) {
+ if(runConf->globals.bAbortOnFailedQueueStartup) {
+ fprintf(stderr, "rsyslogd: error %d starting up action queue, "
+ "abortOnFailedQueueStartup is set, so we abort rsyslog now.", localRet);
+ fflush(stderr);
+ exit(1); /* "good" exit, this is intended here */
+ }
+ LogError(0, localRet, "error starting up action queue");
+ if(localRet == RS_RET_FILE_PREFIX_MISSING) {
+ LogError(0, localRet, "file prefix (work directory?) "
+ "is missing");
+ }
+ actionDisable(pThis);
+ }
+ DBGPRINTF("Action %s[%p]: queue %p started\n", modGetName(pThis->pMod),
+ pThis, pThis->pQueue);
+ return RS_RET_OK; /* we ignore errors, we can not do anything either way */
+}
+
+
+/* This function "activates" the action after privileges have been dropped. Currently,
+ * this means that the queues are started.
+ * rgerhards, 2011-05-02
+ */
+rsRetVal
+activateActions(void)
+{
+ DEFiRet;
+ iRet = ruleset.IterateAllActions(runConf, doActivateActions, NULL);
+ RETiRet;
+}
+
+
+
+/* This submits the message to the action queue in case where we need to handle
+ * bWriteAllMarkMessage == RSFALSE only. Note that we use a non-blocking CAS loop
+ * for the synchronization. Here, we just modify the filter condition to be false when
+ * a mark message must not be written. However, in this case we must save the previous
+ * filter as we may need it in the next action (potential future optimization: check if this is
+ * the last action TODO).
+ * rgerhards, 2010-06-08
+ */
+static rsRetVal
+doSubmitToActionQNotAllMark(action_t * const pAction, wti_t * const pWti, smsg_t * const pMsg)
+{
+ int doProcess = 1;
+ time_t lastAct;
+ DEFiRet;
+
+ /* TODO: think about the whole logic. If messages come in out of order, things
+ * tend to become a bit unreliable. On the other hand, this only happens if we have
+ * very high traffic, in which this use case here is not really affected (as the
+ * MarkInterval is pretty corase).
+ */
+ /* CAS loop, we write back a bit early, but that's OK... */
+ /* we use reception time, not dequeue time - this is considered more appropriate and
+ * also faster ;) -- rgerhards, 2008-09-17 */
+ do {
+ lastAct = pAction->f_time;
+ if(pMsg->msgFlags & MARK) {
+ if((pMsg->ttGenTime - lastAct) < MarkInterval / 2) {
+ doProcess = 0;
+ DBGPRINTF("action was recently called, ignoring mark message\n");
+ break; /* do not update timestamp for non-written mark messages */
+ }
+ }
+ } while(ATOMIC_CAS_time_t(&pAction->f_time, lastAct,
+ pMsg->ttGenTime, &pAction->mutCAS) == 0);
+
+ if(doProcess) {
+ DBGPRINTF("Called action(NotAllMark), processing via '%s'\n",
+ module.GetStateName(pAction->pMod));
+ iRet = doSubmitToActionQ(pAction, pWti, pMsg);
+ }
+
+ RETiRet;
+}
+
+
+/* apply all params from param block to action. This supports the v6 config system.
+ * Defaults must have been set appropriately during action construct!
+ * rgerhards, 2011-08-01
+ */
+static rsRetVal
+actionApplyCnfParam(action_t * const pAction, struct cnfparamvals * const pvals)
+{
+ int i;
+
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblk.descr[i].name, "name")) {
+ pAction->pszName = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "type")) {
+ continue; /* this is handled seperately during module select! */
+ } else if(!strcmp(pblk.descr[i].name, "action.errorfile")) {
+ pAction->pszErrFile = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "action.errorfile.maxsize")) {
+ pAction->maxErrFileSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.externalstate.file")) {
+ pAction->pszExternalStateFile = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "action.writeallmarkmessages")) {
+ pAction->bWriteAllMarkMsgs = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.execonlyeverynthtime")) {
+ pAction->iExecEveryNthOccur = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.execonlyeverynthtimetimeout")) {
+ pAction->iExecEveryNthOccurTO = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.execonlyonceeveryinterval")) {
+ pAction->iSecsExecOnceInterval = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.execonlywhenpreviousissuspended")) {
+ pAction->bExecWhenPrevSusp = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.repeatedmsgcontainsoriginalmsg")) {
+ pAction->bRepMsgHasMsg = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.resumeretrycount")) {
+ pAction->iResumeRetryCount = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.reportsuspension")) {
+ pAction->bReportSuspension = (int) pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.reportsuspensioncontinuation")) {
+ pAction->bReportSuspensionCont = (int) pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.copymsg")) {
+ pAction->bCopyMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.resumeinterval")) {
+ pAction->iResumeInterval = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "action.resumeintervalmax")) {
+ pAction->iResumeIntervalMax = pvals[i].val.d.n;
+ } else {
+ dbgprintf("action: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+ }
+ return RS_RET_OK;
+}
+
+
+/* add an Action to the current selector
+ * The pOMSR is freed, as it is not needed after this function.
+ * Note: this function pulls global data that specifies action config state.
+ * rgerhards, 2007-07-27
+ */
+rsRetVal
+addAction(action_t **ppAction, modInfo_t *pMod, void *pModData,
+ omodStringRequest_t *pOMSR, struct cnfparamvals *actParams,
+ struct nvlst * const lst)
+{
+ DEFiRet;
+ int i;
+ int iTplOpts;
+ uchar *pTplName;
+ action_t *pAction;
+ char errMsg[512];
+
+ assert(ppAction != NULL);
+ assert(pMod != NULL);
+ assert(pOMSR != NULL);
+ DBGPRINTF("Module %s processes this action.\n", module.GetName(pMod));
+
+ CHKiRet(actionConstruct(&pAction)); /* create action object first */
+ pAction->pMod = pMod;
+ pAction->pModData = pModData;
+ if(actParams == NULL) { /* use legacy systemn */
+ pAction->pszName = cs.pszActionName;
+ pAction->iResumeInterval = cs.glbliActionResumeInterval;
+ pAction->iResumeRetryCount = cs.glbliActionResumeRetryCount;
+ pAction->bWriteAllMarkMsgs = cs.bActionWriteAllMarkMsgs;
+ pAction->bExecWhenPrevSusp = cs.bActExecWhenPrevSusp;
+ pAction->iSecsExecOnceInterval = cs.iActExecOnceInterval;
+ pAction->iExecEveryNthOccur = cs.iActExecEveryNthOccur;
+ pAction->iExecEveryNthOccurTO = cs.iActExecEveryNthOccurTO;
+ pAction->bRepMsgHasMsg = cs.bActionRepMsgHasMsg;
+ cs.iActExecEveryNthOccur = 0; /* auto-reset */
+ cs.iActExecEveryNthOccurTO = 0; /* auto-reset */
+ cs.bActionWriteAllMarkMsgs = 1; /* auto-reset */
+ cs.pszActionName = NULL; /* free again! */
+ } else {
+ actionApplyCnfParam(pAction, actParams);
+ }
+
+ /* check if we can obtain the template pointers - TODO: move to separate function? */
+ pAction->iNumTpls = OMSRgetEntryCount(pOMSR);
+ assert(pAction->iNumTpls >= 0); /* only debug check because this "can not happen" */
+ /* please note: iNumTpls may validly be zero. This is the case if the module
+ * does not request any templates. This sounds unlikely, but an actual example is
+ * the discard action, which does not require a string. -- rgerhards, 2007-07-30
+ */
+ if(pAction->iNumTpls > 0) {
+ /* we first need to create the template arrays */
+ CHKmalloc(pAction->ppTpl = (struct template **)calloc(pAction->iNumTpls, sizeof(struct template *)));
+ CHKmalloc(pAction->peParamPassing = (paramPassing_t*)calloc(pAction->iNumTpls,
+ sizeof(paramPassing_t)));
+ }
+
+ pAction->bUsesMsgPassingMode = 0;
+ pAction->bNeedReleaseBatch = 0;
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ CHKiRet(OMSRgetEntry(pOMSR, i, &pTplName, &iTplOpts));
+ /* Ok, we got everything, so it now is time to look up the template
+ * (Hint: templates MUST be defined before they are used!)
+ */
+ if(!(iTplOpts & OMSR_TPL_AS_MSG)) {
+ if((pAction->ppTpl[i] =
+ tplFind(loadConf, (char*)pTplName, strlen((char*)pTplName))) == NULL) {
+ snprintf(errMsg, sizeof(errMsg),
+ " Could not find template %d '%s' - action disabled",
+ i, pTplName);
+ errno = 0;
+ LogError(0, RS_RET_NOT_FOUND, "%s", errMsg);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ /* check required template options */
+ if( (iTplOpts & OMSR_RQD_TPL_OPT_SQL)
+ && (pAction->ppTpl[i]->optFormatEscape == 0)) {
+ errno = 0;
+ LogError(0, RS_RET_RQD_TPLOPT_MISSING, "Action disabled."
+ " To use this action, you have to specify "
+ "the SQL or stdSQL option in your template!\n");
+ ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING);
+ }
+ }
+
+ /* set parameter-passing mode */
+ if(iTplOpts & OMSR_TPL_AS_ARRAY) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else if(iTplOpts & OMSR_TPL_AS_MSG) {
+ pAction->peParamPassing[i] = ACT_MSG_PASSING;
+ pAction->bUsesMsgPassingMode = 1;
+ } else if(iTplOpts & OMSR_TPL_AS_JSON) {
+ pAction->peParamPassing[i] = ACT_JSON_PASSING;
+ pAction->bNeedReleaseBatch = 1;
+ } else {
+ pAction->peParamPassing[i] = ACT_STRING_PASSING;
+ }
+
+ DBGPRINTF("template: '%s' assigned\n", pTplName);
+ }
+
+ pAction->pMod = pMod;
+ pAction->pModData = pModData;
+
+ CHKiRet(actionConstructFinalize(pAction, lst));
+
+ *ppAction = pAction; /* finally store the action pointer */
+
+finalize_it:
+ if(iRet == RS_RET_OK)
+ iRet = OMSRdestruct(pOMSR);
+ else {
+ /* do not overwrite error state! */
+ OMSRdestruct(pOMSR);
+ if(pAction != NULL)
+ actionDestruct(pAction);
+ }
+
+ RETiRet;
+}
+
+
+/* Reset config variables to default values.
+ * rgerhards, 2009-11-12
+ */
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.iActExecOnceInterval = 0;
+ cs.bActExecWhenPrevSusp = 0;
+ return RS_RET_OK;
+}
+
+
+/* initialize (current) config variables.
+ * Used at program start and when a new scope is created.
+ */
+static void
+initConfigVariables(void)
+{
+ cs.bActionWriteAllMarkMsgs = 1;
+ cs.glbliActionResumeRetryCount = 0;
+ cs.bActExecWhenPrevSusp = 0;
+ cs.iActExecOnceInterval = 0;
+ cs.iActExecEveryNthOccur = 0;
+ cs.iActExecEveryNthOccurTO = 0;
+ cs.glbliActionResumeInterval = 30;
+ cs.glbliActionResumeRetryCount = 0;
+ cs.bActionRepMsgHasMsg = 0;
+ if(cs.pszActionName != NULL) {
+ free(cs.pszActionName);
+ cs.pszActionName = NULL;
+ }
+ actionResetQueueParams();
+}
+
+
+rsRetVal
+actionNewInst(struct nvlst *lst, action_t **ppAction)
+{
+ struct cnfparamvals *paramvals;
+ modInfo_t *pMod;
+ uchar *cnfModName = NULL;
+ omodStringRequest_t *pOMSR;
+ void *pModData;
+ action_t *pAction;
+ DEFiRet;
+
+ paramvals = nvlstGetParams(lst, &pblk, NULL);
+ if(paramvals == NULL) {
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ dbgprintf("action param blk after actionNewInst:\n");
+ cnfparamsPrint(&pblk, paramvals);
+ cnfModName = (uchar*)es_str2cstr(paramvals[cnfparamGetIdx(&pblk, ("type"))].val.d.estr, NULL);
+ if((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_OUT)) == NULL) {
+ LogError(0, RS_RET_MOD_UNKNOWN, "module name '%s' is unknown", cnfModName);
+ ABORT_FINALIZE(RS_RET_MOD_UNKNOWN);
+ }
+ CHKiRet(pMod->mod.om.newActInst(cnfModName, lst, &pModData, &pOMSR));
+
+ if((iRet = addAction(&pAction, pMod, pModData, pOMSR, paramvals, lst)) == RS_RET_OK) {
+ /* check if the module is compatible with select features
+ * (currently no such features exist) */
+ loadConf->actions.nbrActions++; /* one more active action! */
+ *ppAction = pAction;
+ } else {
+ // TODO: cleanup
+ }
+
+finalize_it:
+ free(cnfModName);
+ cnfparamvalsDestruct(paramvals, &pblk);
+ RETiRet;
+}
+
+rsRetVal actionClassInit(void)
+{
+ DEFiRet;
+ /* request objects we use */
+ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(module, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionname", 0, eCmdHdlrGetWord, NULL, &cs.pszActionName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuefilename", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszActionQFName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesize", 0, eCmdHdlrInt, NULL, &cs.iActionQueueSize,
+ NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionwriteallmarkmessages", 0, eCmdHdlrBinary, NULL,
+ &cs.bActionWriteAllMarkMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuebatchsize", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQueueDeqBatchSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuemaxdiskspace", 0, eCmdHdlrSize, NULL,
+ &cs.iActionQueMaxDiskSpace, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuehighwatermark", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQHighWtrMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuelowwatermark", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQLowWtrMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuediscardmark", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQDiscardMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuediscardseverity", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQDiscardSeverity, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuecheckpointinterval", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQPersistUpdCnt, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesyncqueuefiles", 0, eCmdHdlrBinary, NULL,
+ &cs.bActionQSyncQeueFiles, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetype", 0, eCmdHdlrGetWord, setActionQueType, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkerthreads", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQueueNumWorkers, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQtoQShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQtoActShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQtoEnq, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQtoWrkShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQWrkMinMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuemaxfilesize", 0, eCmdHdlrSize, NULL,
+ &cs.iActionQueMaxFileSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL,
+ &cs.bActionQSaveOnShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeueslowdown", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQueueDeqSlowdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQueueDeqtWinFromHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimeend", 0, eCmdHdlrInt, NULL,
+ &cs.iActionQueueDeqtWinToHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyeverynthtime", 0, eCmdHdlrInt, NULL,
+ &cs.iActExecEveryNthOccur, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyeverynthtimetimeout", 0, eCmdHdlrInt, NULL,
+ &cs.iActExecEveryNthOccurTO, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyonceeveryinterval", 0, eCmdHdlrInt, NULL,
+ &cs.iActExecOnceInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgcontainsoriginalmsg", 0, eCmdHdlrBinary, NULL,
+ &cs.bActionRepMsgHasMsg, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL,
+ &cs.bActExecWhenPrevSusp, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL,
+ &cs.glbliActionResumeRetryCount, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, NULL));
+
+ initConfigVariables(); /* first-time init of config setings */
+
+finalize_it:
+ RETiRet;
+}
+
+/* vi:set ai:
+ */
diff --git a/action.h b/action.h
new file mode 100644
index 0000000..16da900
--- /dev/null
+++ b/action.h
@@ -0,0 +1,116 @@
+/* action.h
+ * Header file for the action object
+ *
+ * File begun on 2007-08-06 by RGerhards (extracted from syslogd.c, which
+ * was under BSD license at the time of rsyslog fork)
+ *
+ * Copyright 2007-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ACTION_H_INCLUDED
+#define ACTION_H_INCLUDED 1
+
+#include "syslogd-types.h"
+#include "queue.h"
+
+/* external data */
+extern int glbliActionResumeRetryCount;
+
+/* the following struct defines the action object data structure
+ */
+struct action_s {
+ time_t f_time; /* used for "max. n messages in m seconds" processing */
+ time_t tActNow; /* the current time for an action execution. Initially set to -1 and
+ populated on an as-needed basis. This is a performance optimization. */
+ time_t tLastExec; /* time this action was last executed */
+ int iActionNbr; /* this action's number (ID) */
+ sbool bExecWhenPrevSusp;/* execute only when previous action is suspended? */
+ sbool bWriteAllMarkMsgs;
+ /* should all mark msgs be written (not matter how recent the action was executed)? */
+ sbool bReportSuspension;/* should suspension (and reactivation) of the action reported */
+ sbool bReportSuspensionCont;
+ sbool bDisabled;
+ sbool isTransactional;
+ sbool bCopyMsg;
+ int iSecsExecOnceInterval; /* if non-zero, minimum seconds to wait until action is executed again */
+ time_t ttResumeRtry; /* when is it time to retry the resume? */
+ int iResumeInterval;/* resume interval for this action */
+ int iResumeIntervalMax;/* maximum resume interval for this action --> -1: unbounded */
+ int iResumeRetryCount;/* how often shall we retry a suspended action? (-1 --> eternal) */
+ int iNbrNoExec; /* number of matches that did not yet yield to an exec */
+ int iExecEveryNthOccur;/* execute this action only every n-th occurrence (with n=0,1 -> always) */
+ int iExecEveryNthOccurTO;/* timeout for n-th occurrence feature */
+ time_t tLastOccur; /* time last occurrence was seen (for timing them out) */
+ struct modInfo_s *pMod;/* pointer to output module handling this selector */
+ void *pModData; /* pointer to module data - content is module-specific */
+ sbool bRepMsgHasMsg; /* "message repeated..." has msg fragment in it (0-no, 1-yes) */
+ rsRetVal (*submitToActQ)(action_t *, wti_t*, smsg_t*);/* function submit message to action queue */
+ rsRetVal (*qConstruct)(struct queue_s *pThis);
+ sbool bUsesMsgPassingMode;
+ sbool bNeedReleaseBatch; /* do we need to release batch ressources? Depends on ParamPassig modes... */
+ int iNumTpls; /* number of array entries for template element below */
+ struct template **ppTpl;/* array of template to use - strings must be passed to doAction
+ * in this order. */
+ paramPassing_t *peParamPassing; /* mode of parameter passing to action for that template */
+ qqueue_t *pQueue; /* action queue */
+ pthread_mutex_t mutAction; /* primary action mutex */
+ uchar *pszName; /* action name */
+ DEF_ATOMIC_HELPER_MUT(mutCAS)
+ /* error file */
+ const char *pszErrFile;
+ int fdErrFile;
+ size_t maxErrFileSize;
+ size_t currentErrFileSize;
+ pthread_mutex_t mutErrFile;
+ /* external stat file system */
+ const char *pszExternalStateFile;
+ /* for per-worker HUP processing */
+ pthread_mutex_t mutWrkrDataTable; /* protects table structures */
+ void **wrkrDataTable;
+ int wrkrDataTableSize;
+ int nWrkr;
+ /* for statistics subsystem */
+ statsobj_t *statsobj;
+ STATSCOUNTER_DEF(ctrProcessed, mutCtrProcessed)
+ STATSCOUNTER_DEF(ctrFail, mutCtrFail)
+ STATSCOUNTER_DEF(ctrSuspend, mutCtrSuspend)
+ STATSCOUNTER_DEF(ctrSuspendDuration, mutCtrSuspendDuration)
+ STATSCOUNTER_DEF(ctrResume, mutCtrResume)
+};
+
+
+/* function prototypes
+ */
+rsRetVal actionConstruct(action_t **ppThis);
+rsRetVal actionConstructFinalize(action_t *pThis, struct nvlst *lst);
+rsRetVal actionDestruct(action_t *pThis);
+rsRetVal actionSetGlobalResumeInterval(int iNewVal);
+rsRetVal actionDoAction(action_t *pAction);
+rsRetVal actionWriteToAction(action_t *pAction, smsg_t *pMsg, wti_t*);
+rsRetVal actionCallHUPHdlr(action_t *pAction);
+rsRetVal actionClassInit(void);
+rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR,
+ struct cnfparamvals *actParams, struct nvlst *lst);
+rsRetVal activateActions(void);
+rsRetVal actionNewInst(struct nvlst *lst, action_t **ppAction);
+rsRetVal actionProcessCnf(struct cnfobj *o);
+void actionCommitAllDirect(wti_t *pWti);
+void actionRemoveWorker(action_t *const pAction, void *const actWrkrData);
+void releaseDoActionParams(action_t * const pAction, wti_t * const pWti, int action_destruct);
+
+#endif /* #ifndef ACTION_H_INCLUDED */
diff --git a/compat/Makefile.am b/compat/Makefile.am
new file mode 100644
index 0000000..03bc936
--- /dev/null
+++ b/compat/Makefile.am
@@ -0,0 +1,6 @@
+noinst_LTLIBRARIES = compat.la
+
+compat_la_SOURCES = getifaddrs.c ifaddrs.h strndup.c asprintf.c solaris_elf_fix.c
+compat_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+compat_la_LDFLAGS = -module -avoid-version
+compat_la_LIBADD = $(IMUDP_LIBS)
diff --git a/compat/Makefile.in b/compat/Makefile.in
new file mode 100644
index 0000000..92c7f31
--- /dev/null
+++ b/compat/Makefile.in
@@ -0,0 +1,775 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = compat
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+compat_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_compat_la_OBJECTS = compat_la-getifaddrs.lo compat_la-strndup.lo \
+ compat_la-asprintf.lo compat_la-solaris_elf_fix.lo
+compat_la_OBJECTS = $(am_compat_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 =
+compat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(compat_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/compat_la-asprintf.Plo \
+ ./$(DEPDIR)/compat_la-getifaddrs.Plo \
+ ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo \
+ ./$(DEPDIR)/compat_la-strndup.Plo
+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 = $(compat_la_SOURCES)
+DIST_SOURCES = $(compat_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = compat.la
+compat_la_SOURCES = getifaddrs.c ifaddrs.h strndup.c asprintf.c solaris_elf_fix.c
+compat_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+compat_la_LDFLAGS = -module -avoid-version
+compat_la_LIBADD = $(IMUDP_LIBS)
+all: 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) --gnu compat/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu compat/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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}; \
+ }
+
+compat.la: $(compat_la_OBJECTS) $(compat_la_DEPENDENCIES) $(EXTRA_compat_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(compat_la_LINK) $(compat_la_OBJECTS) $(compat_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-asprintf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-getifaddrs.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-solaris_elf_fix.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-strndup.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+compat_la-getifaddrs.lo: getifaddrs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-getifaddrs.lo -MD -MP -MF $(DEPDIR)/compat_la-getifaddrs.Tpo -c -o compat_la-getifaddrs.lo `test -f 'getifaddrs.c' || echo '$(srcdir)/'`getifaddrs.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-getifaddrs.Tpo $(DEPDIR)/compat_la-getifaddrs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getifaddrs.c' object='compat_la-getifaddrs.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) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-getifaddrs.lo `test -f 'getifaddrs.c' || echo '$(srcdir)/'`getifaddrs.c
+
+compat_la-strndup.lo: strndup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-strndup.lo -MD -MP -MF $(DEPDIR)/compat_la-strndup.Tpo -c -o compat_la-strndup.lo `test -f 'strndup.c' || echo '$(srcdir)/'`strndup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-strndup.Tpo $(DEPDIR)/compat_la-strndup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strndup.c' object='compat_la-strndup.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) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-strndup.lo `test -f 'strndup.c' || echo '$(srcdir)/'`strndup.c
+
+compat_la-asprintf.lo: asprintf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-asprintf.lo -MD -MP -MF $(DEPDIR)/compat_la-asprintf.Tpo -c -o compat_la-asprintf.lo `test -f 'asprintf.c' || echo '$(srcdir)/'`asprintf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-asprintf.Tpo $(DEPDIR)/compat_la-asprintf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asprintf.c' object='compat_la-asprintf.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) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-asprintf.lo `test -f 'asprintf.c' || echo '$(srcdir)/'`asprintf.c
+
+compat_la-solaris_elf_fix.lo: solaris_elf_fix.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-solaris_elf_fix.lo -MD -MP -MF $(DEPDIR)/compat_la-solaris_elf_fix.Tpo -c -o compat_la-solaris_elf_fix.lo `test -f 'solaris_elf_fix.c' || echo '$(srcdir)/'`solaris_elf_fix.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-solaris_elf_fix.Tpo $(DEPDIR)/compat_la-solaris_elf_fix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='solaris_elf_fix.c' object='compat_la-solaris_elf_fix.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) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-solaris_elf_fix.lo `test -f 'solaris_elf_fix.c' || echo '$(srcdir)/'`solaris_elf_fix.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+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-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/compat_la-asprintf.Plo
+ -rm -f ./$(DEPDIR)/compat_la-getifaddrs.Plo
+ -rm -f ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo
+ -rm -f ./$(DEPDIR)/compat_la-strndup.Plo
+ -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 ./$(DEPDIR)/compat_la-asprintf.Plo
+ -rm -f ./$(DEPDIR)/compat_la-getifaddrs.Plo
+ -rm -f ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo
+ -rm -f ./$(DEPDIR)/compat_la-strndup.Plo
+ -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: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles 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
+
+.PRECIOUS: Makefile
+
+
+# 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/compat/asprintf.c b/compat/asprintf.c
new file mode 100644
index 0000000..fcfb102
--- /dev/null
+++ b/compat/asprintf.c
@@ -0,0 +1,53 @@
+/* compatibility file for systems without asprintf.
+ *
+ * Copyright 2019 P Duveau
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#ifndef HAVE_ASPRINTF
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+int asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ *strp = malloc(len+1);
+ if (!*strp) {
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(*strp, len+1, fmt, ap);
+ va_end(ap);
+
+ (*strp)[len] = 0;
+ return len;
+}
+#else
+/* XLC needs at least one method in source file even static to compile */
+#ifdef __xlc__
+static void dummy() {}
+#endif
+#endif /* #ifndef HAVE_ASPRINTF */
diff --git a/compat/getifaddrs.c b/compat/getifaddrs.c
new file mode 100755
index 0000000..3973974
--- /dev/null
+++ b/compat/getifaddrs.c
@@ -0,0 +1,543 @@
+#include "config.h"
+#ifndef HAVE_GETIFADDRS
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <netdb.h>
+#if !defined (_AIX)
+#include <nss_dbdefs.h>
+#endif
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#if defined (_AIX)
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#if defined (_AIX)
+#include <netdb.h>
+#endif
+#if !defined (_AIX)
+#include <sys/sockio.h>
+#endif
+#include <sys/types.h>
+#include <stdlib.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#if defined (_AIX)
+#include <netinet/in6_var.h>
+#endif
+
+/* Normally this is defined in <net/if.h> but was new for Solaris 11 */
+#ifndef LIFC_ENABLED
+#define LIFC_ENABLED 0x20
+#endif
+
+#if defined (_AIX) /* Use ifaddrs_rsys instead of ifaddrs and ifreq instead of lifreq */
+int getallifaddrs(sa_family_t af, struct ifaddrs_rsys **ifap, int64_t flags);
+int getallifs(int s, sa_family_t af, struct ifreq **ifr, int *numifs,
+ int64_t ifc_flags);
+#else
+int getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags);
+int getallifs(int s, sa_family_t af, struct lifreq **lifr, int *numifs,
+ int64_t lifc_flags);
+#endif
+
+/*
+ * Create a linked list of `struct ifaddrs_rsys' structures, one for each
+ * address that is UP. If successful, store the list in *ifap and
+ * return 0. On errors, return -1 and set `errno'.
+ *
+ * The storage returned in *ifap is allocated dynamically and can
+ * only be properly freed by passing it to `freeifaddrs'.
+ */
+int
+#if defined (_AIX)
+getifaddrs(struct ifaddrs_rsys **ifap)
+#else
+getifaddrs(struct ifaddrs **ifap)
+#endif
+{
+ int err;
+ char *cp;
+#if defined (_AIX)
+ struct ifaddrs_rsys *curr;
+#else
+ struct ifaddrs *curr;
+#endif
+
+ if (ifap == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *ifap = NULL;
+ err = getallifaddrs(AF_UNSPEC, ifap, LIFC_ENABLED);
+ if (err == 0) {
+ for (curr = *ifap; curr != NULL; curr = curr->ifa_next) {
+ if ((cp = strchr(curr->ifa_name, ':')) != NULL)
+ *cp = '\0';
+ }
+ }
+ return (err);
+}
+
+void
+#if defined (_AIX)
+freeifaddrs(struct ifaddrs_rsys *ifa)
+#else
+freeifaddrs(struct ifaddrs *ifa)
+#endif
+{
+#if defined (_AIX)
+ struct ifaddrs_rsys *curr;
+#else
+ struct ifaddrs *curr;
+#endif
+
+ while (ifa != NULL) {
+ curr = ifa;
+ ifa = ifa->ifa_next;
+ free(curr->ifa_name);
+ free(curr->ifa_addr);
+ free(curr->ifa_netmask);
+ free(curr->ifa_dstaddr);
+ free(curr);
+ }
+}
+
+/*
+ * Returns all addresses configured on the system. If flags contain
+ * LIFC_ENABLED, only the addresses that are UP are returned.
+ * Address list that is returned by this function must be freed
+ * using freeifaddrs().
+ */
+#if defined (_AIX)
+int
+getallifaddrs(sa_family_t af, struct ifaddrs_rsys **ifap, int64_t flags)
+{
+ struct ifreq *buf = NULL;
+ struct ifreq *ifrp;
+ struct ifreq ifrl;
+ struct in6_ifreq ifrl6;
+ int ret;
+ int s, n, iflen;
+ struct ifaddrs_rsys *curr, *prev;
+ sa_family_t ifr_af;
+ int sock4;
+ int sock6;
+ int err;
+ int ifsize;
+ char *s_ifrp, *e_ifrp;
+ int flag;
+
+ if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (-1);
+ if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ err = errno;
+ close(sock4);
+ errno = err;
+ return (-1);
+ }
+
+retry:
+ /* Get all interfaces from SIOCGIFCONF */
+ ret = getallifs(sock4, af, &buf, &iflen, (flags & ~LIFC_ENABLED));
+ if (ret != 0)
+ goto fail;
+
+ /*
+ * Loop through the interfaces obtained from SIOCGIFCOMF
+ * and retrieve the addresses, netmask and flags.
+ */
+ prev = NULL;
+ s_ifrp = (char *)buf;
+ e_ifrp = (char *)buf + iflen;
+ *ifap = NULL;
+ while (s_ifrp < e_ifrp)
+ {
+ ifrp = (struct ifreq *)s_ifrp;
+ ifsize = sizeof(struct ifreq);
+
+ if (ifrp->ifr_addr.sa_len > sizeof(ifrp->ifr_ifru)) {
+ ifsize += ifrp->ifr_addr.sa_len - sizeof(ifrp->ifr_ifru);
+ }
+
+ /* Prepare for the ioctl call */
+ (void) strncpy(ifrl.ifr_name, ifrp->ifr_name,
+ sizeof (ifrl.ifr_name));
+ (void) strncpy(ifrl6.ifr_name, ifrp->ifr_name,
+ sizeof (ifrl.ifr_name));
+ ifr_af = ifrp->ifr_addr.sa_family;
+
+ if (ifr_af != AF_INET && ifr_af != AF_INET6)
+ goto next;
+
+ s = (ifr_af == AF_INET ? sock4 : sock6);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifrl) < 0)
+ goto fail;
+
+ if ((flags & LIFC_ENABLED) && !(ifrl.ifr_flags & IFF_UP)) {
+ goto next;
+ }
+
+ /*
+ * Allocate the current list node. Each node contains data
+ * for one ifaddrs structure.
+ */
+ curr = calloc(1, sizeof (struct ifaddrs_rsys));
+ if (curr == NULL)
+ goto fail;
+
+ if (prev != NULL) {
+ prev->ifa_next = curr;
+ } else {
+ /* First node in the linked list */
+ *ifap = curr;
+ }
+ prev = curr;
+
+/* AIXPORT : ifreq field names used instead of linux lifreq field names */
+ curr->ifa_flags = ifrl.ifr_flags;
+ if ((curr->ifa_name = strdup(ifrp->ifr_name)) == NULL)
+ goto fail;
+
+ curr->ifa_addr = malloc(sizeof (struct sockaddr_storage));
+ if (curr->ifa_addr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_addr, &ifrp->ifr_addr,
+ sizeof (struct sockaddr_storage));
+
+ /* Get the netmask */
+ if (ifr_af == AF_INET) {
+ if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifrl) < 0) {
+ goto fail;
+ }
+ curr->ifa_netmask = malloc(sizeof (struct sockaddr_storage));
+ if (curr->ifa_netmask == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_netmask, &ifrl.ifr_addr,
+ sizeof (struct sockaddr_storage));
+ } else {
+ if (ioctl(s, SIOCGIFNETMASK6, (caddr_t)&ifrl6) < 0) {
+ goto fail;
+ }
+ curr->ifa_netmask = malloc(sizeof (struct sockaddr_storage));
+ if (curr->ifa_netmask == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_netmask, &ifrl6.ifr_Addr,
+ sizeof (struct sockaddr_storage));
+ }
+
+ /* Get the destination for a pt-pt interface */
+ if (curr->ifa_flags & IFF_POINTOPOINT) {
+ if (ifr_af == AF_INET) {
+ if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifrl) < 0)
+ goto fail;
+ curr->ifa_dstaddr = malloc(
+ sizeof (struct sockaddr_storage));
+ if (curr->ifa_dstaddr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_dstaddr, &ifrl.ifr_addr,
+ sizeof (struct sockaddr_storage));
+ } else {
+ if (ioctl(s, SIOCGIFDSTADDR6, (caddr_t)&ifrl6) < 0)
+ goto fail;
+ curr->ifa_dstaddr = malloc(
+ sizeof (struct sockaddr_storage));
+ if (curr->ifa_dstaddr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_dstaddr, &ifrl6.ifr_Addr,
+ sizeof (struct sockaddr_storage));
+ }
+ /* Do not get broadcast address for IPv6 */
+ } else if ((curr->ifa_flags & IFF_BROADCAST) && (ifr_af == AF_INET)) {
+ if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifrl) < 0)
+ goto fail;
+ curr->ifa_broadaddr = malloc(
+ sizeof (struct sockaddr_storage));
+ if (curr->ifa_broadaddr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_broadaddr, &ifrl.ifr_addr,
+ sizeof (struct sockaddr_storage));
+ }
+next:
+ s_ifrp += ifsize;
+ }
+ free(buf);
+ close(sock4);
+ close(sock6);
+ return (0);
+fail:
+ err = errno;
+ free(buf);
+ freeifaddrs(*ifap);
+ *ifap = NULL;
+ if (err == ENXIO)
+ goto retry;
+ close(sock4);
+ close(sock6);
+ errno = err;
+ return (-1);
+}
+
+/*
+ * Do a SIOCGIFCONF and store all the interfaces in `buf'.
+ */
+int
+getallifs(int s, sa_family_t af, struct ifreq **ifr, int *iflen,
+ int64_t ifc_flags)
+{
+ int ifsize;
+ struct ifconf ifc;
+ size_t bufsize;
+ char *tmp;
+ caddr_t *buf = (caddr_t *)ifr;
+
+ *buf = NULL;
+retry:
+ if (ioctl(s, SIOCGSIZIFCONF, &ifsize) < 0)
+ goto fail;
+
+ /*
+ * When calculating the buffer size needed, add a small number
+ * of interfaces to those we counted. We do this to capture
+ * the interface status of potential interfaces which may have
+ * been plumbed between the SIOCGSIZIFCONF and the SIOCGIFCONF.
+ */
+ bufsize = ifsize + (4 * sizeof (struct in6_ifreq));
+
+ if ((tmp = realloc(*buf, bufsize)) == NULL)
+ goto fail;
+
+ *buf = tmp;
+ ifc.ifc_buf = *buf;
+ ifc.ifc_len = bufsize;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
+ goto fail;
+
+ *iflen = ifc.ifc_len;
+ if (*iflen >= bufsize) {
+ /*
+ * If every entry was filled, there are probably
+ * more interfaces than (ifn + 4)
+ * Redo the ioctls SIOCGSIZIFCONF and SIOCGIFCONF to
+ * get all the interfaces.
+ */
+ goto retry;
+ }
+ return (0);
+fail:
+ free(*buf);
+ *buf = NULL;
+ return (-1);
+}
+#else /* _AIX */
+int
+getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags)
+{
+ struct lifreq *buf = NULL;
+ struct lifreq *lifrp;
+ struct lifreq lifrl;
+ int ret;
+ int s, n, numifs;
+ struct ifaddrs *curr, *prev;
+ sa_family_t lifr_af;
+ int sock4;
+ int sock6;
+ int err;
+
+ if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (-1);
+ if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ err = errno;
+ close(sock4);
+ errno = err;
+ return (-1);
+ }
+
+retry:
+ /* Get all interfaces from SIOCGLIFCONF */
+ ret = getallifs(sock4, af, &buf, &numifs, (flags & ~LIFC_ENABLED));
+ if (ret != 0)
+ goto fail;
+
+ /*
+ * Loop through the interfaces obtained from SIOCGLIFCOMF
+ * and retrieve the addresses, netmask and flags.
+ */
+ prev = NULL;
+ lifrp = buf;
+ *ifap = NULL;
+ for (n = 0; n < numifs; n++, lifrp++) {
+
+ /* Prepare for the ioctl call */
+ (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
+ sizeof (lifrl.lifr_name));
+ lifr_af = lifrp->lifr_addr.ss_family;
+ if (af != AF_UNSPEC && lifr_af != af)
+ continue;
+
+ s = (lifr_af == AF_INET ? sock4 : sock6);
+
+ if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0)
+ goto fail;
+ if ((flags & LIFC_ENABLED) && !(lifrl.lifr_flags & IFF_UP))
+ continue;
+
+ /*
+ * Allocate the current list node. Each node contains data
+ * for one ifaddrs structure.
+ */
+ curr = calloc(1, sizeof (struct ifaddrs));
+ if (curr == NULL)
+ goto fail;
+
+ if (prev != NULL) {
+ prev->ifa_next = curr;
+ } else {
+ /* First node in the linked list */
+ *ifap = curr;
+ }
+ prev = curr;
+
+ curr->ifa_flags = lifrl.lifr_flags;
+ if ((curr->ifa_name = strdup(lifrp->lifr_name)) == NULL)
+ goto fail;
+
+ curr->ifa_addr = malloc(sizeof (struct sockaddr_storage));
+ if (curr->ifa_addr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_addr, &lifrp->lifr_addr,
+ sizeof (struct sockaddr_storage));
+
+ /* Get the netmask */
+ if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifrl) < 0)
+ goto fail;
+ curr->ifa_netmask = malloc(sizeof (struct sockaddr_storage));
+ if (curr->ifa_netmask == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_netmask, &lifrl.lifr_addr,
+ sizeof (struct sockaddr_storage));
+
+ /* Get the destination for a pt-pt interface */
+ if (curr->ifa_flags & IFF_POINTOPOINT) {
+ if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifrl) < 0)
+ goto fail;
+ curr->ifa_dstaddr = malloc(
+ sizeof (struct sockaddr_storage));
+ if (curr->ifa_dstaddr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_dstaddr, &lifrl.lifr_addr,
+ sizeof (struct sockaddr_storage));
+ } else if (curr->ifa_flags & IFF_BROADCAST) {
+ if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifrl) < 0)
+ goto fail;
+ curr->ifa_broadaddr = malloc(
+ sizeof (struct sockaddr_storage));
+ if (curr->ifa_broadaddr == NULL)
+ goto fail;
+ (void) memcpy(curr->ifa_broadaddr, &lifrl.lifr_addr,
+ sizeof (struct sockaddr_storage));
+ }
+
+ }
+ free(buf);
+ close(sock4);
+ close(sock6);
+ return (0);
+fail:
+ err = errno;
+ free(buf);
+ freeifaddrs(*ifap);
+ *ifap = NULL;
+ if (err == ENXIO)
+ goto retry;
+ close(sock4);
+ close(sock6);
+ errno = err;
+ return (-1);
+}
+
+/*
+ * Do a SIOCGLIFCONF and store all the interfaces in `buf'.
+ */
+int
+getallifs(int s, sa_family_t af, struct lifreq **lifr, int *numifs,
+ int64_t lifc_flags)
+{
+ struct lifnum lifn;
+ struct lifconf lifc;
+ size_t bufsize;
+ char *tmp;
+ caddr_t *buf = (caddr_t *)lifr;
+
+ lifn.lifn_family = af;
+ lifn.lifn_flags = lifc_flags;
+
+ *buf = NULL;
+retry:
+ if (ioctl(s, SIOCGLIFNUM, &lifn) < 0)
+ goto fail;
+
+ /*
+ * When calculating the buffer size needed, add a small number
+ * of interfaces to those we counted. We do this to capture
+ * the interface status of potential interfaces which may have
+ * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
+ */
+ bufsize = (lifn.lifn_count + 4) * sizeof (struct lifreq);
+
+ if ((tmp = realloc(*buf, bufsize)) == NULL)
+ goto fail;
+
+ *buf = tmp;
+ lifc.lifc_family = af;
+ lifc.lifc_flags = lifc_flags;
+ lifc.lifc_len = bufsize;
+ lifc.lifc_buf = *buf;
+ if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0)
+ goto fail;
+
+ *numifs = lifc.lifc_len / sizeof (struct lifreq);
+ if (*numifs >= (lifn.lifn_count + 4)) {
+ /*
+ * If every entry was filled, there are probably
+ * more interfaces than (lifn.lifn_count + 4).
+ * Redo the ioctls SIOCGLIFNUM and SIOCGLIFCONF to
+ * get all the interfaces.
+ */
+ goto retry;
+ }
+ return (0);
+fail:
+ free(*buf);
+ *buf = NULL;
+ return (-1);
+}
+#endif /* _AIX */
+#endif /* HAVE_GETIFADDRS */
diff --git a/compat/ifaddrs.h b/compat/ifaddrs.h
new file mode 100755
index 0000000..a643c62
--- /dev/null
+++ b/compat/ifaddrs.h
@@ -0,0 +1,100 @@
+#include "config.h"
+#ifndef HAVE_GETIFADDRS
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+#ifndef _IFADDRS_H
+#define _IFADDRS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/*
+ * The `getifaddrs' function generates a linked list of these structures.
+ * Each element of the list describes one network interface.
+ */
+#if defined(_AIX)
+struct ifaddrs_rsys {
+ struct ifaddrs_rsys *ifa_next; /* Pointer to the next structure. */
+#else
+struct ifaddrs {
+ struct ifaddrs *ifa_next; /* Pointer to the next structure. */
+#endif
+ char *ifa_name; /* Name of this network interface. */
+ uint64_t ifa_flags; /* Flags as from SIOCGLIFFLAGS ioctl. */
+ struct sockaddr *ifa_addr; /* Network address of this interface. */
+ struct sockaddr *ifa_netmask; /* Netmask of this interface. */
+ union {
+ /*
+ * At most one of the following two is valid. If the
+ * IFF_BROADCAST bit is set in `ifa_flags', then
+ * `ifa_broadaddr' is valid. If the IFF_POINTOPOINT bit is
+ * set, then `ifa_dstaddr' is valid. It is never the case that
+ * both these bits are set at once.
+ */
+ struct sockaddr *ifu_broadaddr;
+ struct sockaddr *ifu_dstaddr;
+ } ifa_ifu;
+ void *ifa_data; /* Address-specific data (may be unused). */
+/*
+ * This may have been defined in <net/if.h>.
+ */
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
+#endif
+#ifndef ifa_dstaddr
+#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of p-to-p link */
+#endif
+};
+
+/*
+ * Create a linked list of `struct ifaddrs' structures, one for each
+ * network interface on the host machine. If successful, store the
+ * list in *ifap and return 0. On errors, return -1 and set `errno'.
+ *
+ * The storage returned in *ifap is allocated dynamically and can
+ * only be properly freed by passing it to `freeifaddrs'.
+ */
+#if defined(_AIX)
+extern int getifaddrs(struct ifaddrs_rsys **);
+#else
+extern int getifaddrs(struct ifaddrs **);
+#endif
+
+/* Reclaim the storage allocated by a previous `getifaddrs' call. */
+#if defined(_AIX)
+extern void freeifaddrs(struct ifaddrs_rsys *);
+#else
+extern void freeifaddrs(struct ifaddrs *);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IFADDRS_H */
+#endif /* HAVE_GETIFADDRS */
diff --git a/compat/solaris_elf_fix.c b/compat/solaris_elf_fix.c
new file mode 100644
index 0000000..8ce6893
--- /dev/null
+++ b/compat/solaris_elf_fix.c
@@ -0,0 +1,28 @@
+/* This file ensure that is at least one symbol in our compat
+ * convenience library. Otherwise, at least the Solaris linker
+ * bails out with an error message like this:
+ *
+ * ld: elf error: file ../compat/.libs/compat.a: elf_getarsym
+ *
+ * Copyright 2016 Rainer Gerhards and Adiscon
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#if defined(OS_SOLARIS) || defined(__xlc__)
+int SOLARIS_and_XLC_wants_a_symbol_inside_the_lib;
+#endif
diff --git a/compat/strndup.c b/compat/strndup.c
new file mode 100644
index 0000000..e279f98
--- /dev/null
+++ b/compat/strndup.c
@@ -0,0 +1,49 @@
+/* compatibility file for systems without strndup.
+ *
+ * Copyright 2015 Rainer Gerhards and Adiscon
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#ifndef HAVE_STRNDUP
+
+
+#include <stdlib.h>
+#include <string.h>
+
+extern char *strndup(const char *s, size_t n);
+
+char *
+strndup(const char *s, size_t n)
+{
+ const size_t len = strlen(s);
+ char *new_s;
+ if(len <= n)
+ return strdup(s);
+ new_s = malloc(n+1);
+ if(new_s == NULL)
+ return NULL;
+ memcpy(new_s, s, n);
+ new_s[n] = '\0';
+ return new_s;
+}
+#else
+/* XLC needs at least one method in source file even static to compile */
+#ifdef __xlc__
+static void dummy() {}
+#endif
+#endif /* #ifndef HAVE_STRNDUP */
diff --git a/compile b/compile
new file mode 100755
index 0000000..99e5052
--- /dev/null
+++ b/compile
@@ -0,0 +1,348 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2018 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 <https://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 | \
+ icl | *[/\\]icl | icl.exe | *[/\\]icl.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 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..f50dcdb
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1480 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-02-24'
+
+# 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 <https://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; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches 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.
+
+Options:
+ -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-2018 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' | sed 's, ,,g'`"
+
+ # If ldd exists, use it to detect musl libc.
+ if command -v ldd >/dev/null && \
+ ldd --version 2>&1 | grep -q ^musl
+ then
+ LIBC=musl
+ fi
+ ;;
+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=`(uname -p 2>/dev/null || \
+ "/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 ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine="${arch}${endian}"-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) and ABI.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ os=netbsdelf
+ ;;
+ 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
+ # Determine ABI tags.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ 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/[-_].*//' | cut -d. -f1,2`
+ ;;
+ 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}${abi}"
+ 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 ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+ exit ;;
+ *:MidnightBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-midnightbsd"$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 ;;
+ *:Sortix:*:*)
+ echo "$UNAME_MACHINE"-unknown-sortix
+ exit ;;
+ *:Redox:*:*)
+ echo "$UNAME_MACHINE"-unknown-redox
+ exit ;;
+ mips:OSF1:*.*)
+ echo mips-dec-osf1
+ 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 ;;
+ 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/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ 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:4.4BSD:*)
+ 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)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ exit ;;
+ i*:CYGWIN*:*)
+ echo "$UNAME_MACHINE"-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo "$UNAME_MACHINE"-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo "$UNAME_MACHINE"-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo "$UNAME_MACHINE"-pc-msys
+ 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 ;;
+ i*:UWIN*:*)
+ echo "$UNAME_MACHINE"-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-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 "[:upper:]" "[:lower:]"``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 ;;
+ e2k:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-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 ;;
+ k1om: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; }
+ ;;
+ mips64el:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-"$LIBC"
+ exit ;;
+ or32:Linux:*:* | or1k*: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 ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo "$UNAME_MACHINE"-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:*:*)
+ if objdump -f /bin/sh | grep -q elf32-x86-64; then
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32
+ else
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ fi
+ 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.*:*)
+ 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 configure 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 ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-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 test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+ 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
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ 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 ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ echo nsv-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ echo nsx-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 ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+echo "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary 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-functions 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..2b7a5a8
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,683 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Defined if debug mode is enabled (its easier to check). */
+#undef DEBUG
+
+/* Defined if debugless mode is enabled. */
+#undef DEBUGLESS
+
+/* Indicator that GnuTLS is present */
+#undef ENABLE_GNUTLS
+
+/* Indicator that IMDIAG is present */
+#undef ENABLE_IMDIAG
+
+/* Indicator that we need to build a dummy imkafka module */
+#undef ENABLE_IMKAFKA_DUMMY
+
+/* Indicator that libcap-ng is present */
+#undef ENABLE_LIBCAPNG
+
+/* Indicator that libcap-ng is present */
+#undef ENABLE_LIBCAPNG_PRESENT
+
+/* Indicator that LIBGCRYPT is present */
+#undef ENABLE_LIBGCRYPT
+
+/* Indicator that we need to build a dummy module */
+#undef ENABLE_MMBDLOOKUP_DUMMY
+
+/* Indicator that we need to build a dummy omkafka module */
+#undef ENABLE_OMKAFKA_DUMMY
+
+/* Indicator that openssl is present */
+#undef ENABLE_OPENSSL
+
+/* Indicator that RELP is present */
+#undef ENABLE_RELP
+
+/* Regular expressions support enabled. */
+#undef FEATURE_REGEXP
+
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the <apr_base64.h> header file. */
+#undef HAVE_APR_BASE64_H
+
+/* Define to 1 if you have the <apr_md5.h> header file. */
+#undef HAVE_APR_MD5_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 `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define if compiler provides atomic builtins */
+#undef HAVE_ATOMIC_BUILTINS
+
+/* Define if compiler provides 64 bit atomic builtins */
+#undef HAVE_ATOMIC_BUILTINS64
+
+/* Define to 1 if you have the `basename' function. */
+#undef HAVE_BASENAME
+
+/* Define to 1 if compiler supports __builtin_expect */
+#undef HAVE_BUILTIN_EXPECT
+
+/* Define to 1 if your system has a working `chown' function. */
+#undef HAVE_CHOWN
+
+/* Define to 1 if you have the <civetweb.h> header file. */
+#undef HAVE_CIVETWEB_H
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the `close_range' function. */
+#undef HAVE_CLOSE_RANGE
+
+/* 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 libdbi supports the new plugin-safe interface */
+#undef HAVE_DBI_R
+
+/* Define to 1 if libdbi supports transactions */
+#undef HAVE_DBI_TXSUPP
+
+/* 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 <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `epoll_create' function. */
+#undef HAVE_EPOLL_CREATE
+
+/* Define to 1 if you have the `epoll_create1' function. */
+#undef HAVE_EPOLL_CREATE1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* set define */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the `getline' function. */
+#undef HAVE_GETLINE
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* set define */
+#undef HAVE_GLOB_NOMAGIC
+
+/* Define to 1 if you have the `gnutls_certificate_set_retrieve_function'
+ function. */
+#undef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
+
+/* Define to 1 if you have the `gnutls_certificate_type_set_priority'
+ function. */
+#undef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY
+
+/* Define to 1 if you have the <grok.h> header file. */
+#undef HAVE_GROK_H
+
+/* Define to 1 if you have the <hadoop/hdfs.h> header file. */
+#undef HAVE_HADOOP_HDFS_H
+
+/* Define to 1 if you have the <hdfs.h> header file. */
+#undef HAVE_HDFS_H
+
+/* Define to 1 if you have the `inotify_init' function. */
+#undef HAVE_INOTIFY_INIT
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* jemalloc support is integrated. */
+#undef HAVE_JEMALLOC
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if liblogging-stdlog is available. */
+#undef HAVE_LIBLOGGING_STDLOG
+
+/* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */
+#undef HAVE_LIBMYSQLCLIENT
+
+/* Define to 1 if you have the <libnet.h> header file. */
+#undef HAVE_LIBNET_H
+
+/* Define to 1 if you have the <librdkafka/rdkafka.h> header file. */
+#undef HAVE_LIBRDKAFKA_RDKAFKA_H
+
+/* libsystemd present */
+#undef HAVE_LIBSYSTEMD
+
+/* Define to 1 if you have the <linux/close_range.h> header file. */
+#undef HAVE_LINUX_CLOSE_RANGE_H
+
+/* Define if ln_loadSamplesFromString exists. */
+#undef HAVE_LOADSAMPLESFROMSTRING
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the `lseek64' function. */
+#undef HAVE_LSEEK64
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `malloc_trim' function. */
+#undef HAVE_MALLOC_TRIM
+
+/* Define to 1 if you have the <maxminddb.h> header file. */
+#undef HAVE_MAXMINDDB_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have the `mongoc_client_set_ssl_opts' function. */
+#undef HAVE_MONGOC_CLIENT_SET_SSL_OPTS
+
+/* mysql_library_init available */
+#undef HAVE_MYSQL_LIBRARY_INIT
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_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 <net-snmp/net-snmp-config.h> header file. */
+#undef HAVE_NET_SNMP_NET_SNMP_CONFIG_H
+
+/* Define to 1 if the system has the type `off64_t'. */
+#undef HAVE_OFF64_T
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the <pcap.h> header file. */
+#undef HAVE_PCAP_H
+
+/* PGsslInUse function available */
+#undef HAVE_PGSSLINUSE
+
+/* Define to 1 if you have the `port_create' function. */
+#undef HAVE_PORT_CREATE
+
+/* Enable FEN support for imfile */
+#undef HAVE_PORT_SOURCE_FILE
+
+/* Define to 1 if you have the `prctl' function. */
+#undef HAVE_PRCTL
+
+/* Define to 1 if you have the <protocol.h> header file. */
+#undef HAVE_PROTOCOL_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Set-kind available for rwlock attr. */
+#undef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
+
+/* Can set thread-name. */
+#undef HAVE_PTHREAD_SETNAME_NP
+
+/* Can set thread scheduling parameters */
+#undef HAVE_PTHREAD_SETSCHEDPARAM
+
+/* Define to 1 if you have the `recvmmsg' function. */
+#undef HAVE_RECVMMSG
+
+/* Define to 1 if you have the `regcomp' function. */
+#undef HAVE_REGCOMP
+
+/* Define if relpSrvSetTlsConfigCmd exists. */
+#undef HAVE_RELPENGINESETTLSCFGCMD
+
+/* Define if relpEngineSetTLSLibByName exists. */
+#undef HAVE_RELPENGINESETTLSLIBBYNAME
+
+/* Define if relpSrvSetLstnAddr exists. */
+#undef HAVE_RELPSRVSETLSTNADDR
+
+/* Define if relpSrvSetOversizeMode exists. */
+#undef HAVE_RELPSRVSETOVERSIZEMODE
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#undef HAVE_RESOLV_H
+
+/* Define to 1 if you have the `sched_get_priority_max' function. */
+#undef HAVE_SCHED_GET_PRIORITY_MAX
+
+/* Define to 1 if you have the <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* set define */
+#undef HAVE_SCM_CREDENTIALS
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the <semaphore.h> header file. */
+#undef HAVE_SEMAPHORE_H
+
+/* Define if setns exists. */
+#undef HAVE_SETNS
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* set define */
+#undef HAVE_SO_TIMESTAMP
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* 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 `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* 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 `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* 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 to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if you have the `syscall' function. */
+#undef HAVE_SYSCALL
+
+/* set define */
+#undef HAVE_SYSINFO_UPTIME
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/inotify.h> header file. */
+#undef HAVE_SYS_INOTIFY_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/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_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/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* set define */
+#undef HAVE_SYS_gettid
+
+/* Define to 1 if you have the `ttyname_r' function. */
+#undef HAVE_TTYNAME_R
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* 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
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* the host environment, can be queried via a system variable */
+#undef HOSTENV
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Define with a value if your <sys/param.h> does not define MAXHOSTNAMELEN */
+#undef MAXHOSTNAMELEN
+
+/* replacement for missing PATH_MAX */
+#undef MAXPATHLEN
+
+/* Defined if debug mode is disabled. */
+#undef NDEBUG
+
+/* new systemd present */
+#undef NEW_JOURNAL
+
+/* Define if ln_loadSamplesFromString does not exist. */
+#undef NO_LOADSAMPLESFROMSTRING
+
+/* Indicator for a AIX OS */
+#undef OS_AIX
+
+/* Indicator for APPLE OS */
+#undef OS_APPLE
+
+/* Indicator for a BSD OS */
+#undef OS_BSD
+
+/* Indicator for a Linux OS */
+#undef OS_LINUX
+
+/* Indicator for a Solaris OS */
+#undef OS_SOLARIS
+
+/* 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
+
+/* "Configuration file path (default : /etc/rsyslog.conf)" */
+#undef PATH_CONFFILE
+
+/* replacement for missing PATH_MAX */
+#undef PATH_MAX
+
+/* "Pid file path (default : /var/run/rsyslogd.pid)" */
+#undef PATH_PIDFILE
+
+/* platform id for display purposes */
+#undef PLATFORM_ID
+
+/* platform id for display purposes */
+#undef PLATFORM_ID_LSB
+
+/* default port for omrelp */
+#undef RELP_DFLT_PT
+
+/* Define version of librelp used. */
+#undef RELP_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* 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
+
+/* network support is integrated. */
+#undef SYSLOG_INET
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Define if you want to use GSSAPI */
+#undef USE_GSSAPI
+
+/* Using XXHASH for hash64. */
+#undef USE_HASH_XXHASH
+
+/* Define if you want to enable libuuid support */
+#undef USE_LIBUUID
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* If defined, the select() syscall won't be limited to a particular number of
+ file descriptors. */
+#undef USE_UNLIMITED_SELECT
+
+/* Defined if valgrind support settings are to be enabled (e.g. prevents
+ dlclose()). */
+#undef VALGRIND
+
+/* Version number of package */
+#undef VERSION
+
+/* month part of real rsyslog version */
+#undef VERSION_MONTH
+
+/* year part of real rsyslog version */
+#undef VERSION_YEAR
+
+/* 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 for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Use POSIX pthread semantics */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define for Solaris 2.5.1 so the uint8_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 _UINT8_T
+
+/* Use X/Open CAE Specification */
+#undef _XOPEN_SOURCE
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* 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 `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* 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 8 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..1d8e98b
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1801 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-02-22'
+
+# 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 <https://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 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:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# 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 or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -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-2018 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* | netbsd*-eabi* | \
+ kopensolaris*-gnu* | cloudabi*-eabi* | \
+ 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/'`
+ ;;
+ -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 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | 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 \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pru \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]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 \
+ | visium \
+ | wasm32 \
+ | 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
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+ ;;
+ 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-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | 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-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pru-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | 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-* \
+ | visium-* \
+ | wasm32-* \
+ | 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-pc
+ 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
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ 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*)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ 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
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ 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
+ ;;
+ nsv-tandem)
+ basic_machine=nsv-tandem
+ ;;
+ nsx-tandem)
+ basic_machine=nsx-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)
+ 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)
+ 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
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ 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
+ ;;
+ x64)
+ basic_machine=x86_64-pc
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # es1800 is here to avoid being matched by es* (a different OS)
+ -es1800*)
+ os=-ose
+ ;;
+ # Now 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* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -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* | -glidix* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
+ | -midnightbsd*)
+ # 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 | -xray | -os68k* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* \
+ | -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
+ ;;
+ -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
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $basic_machine in
+ arm*)
+ os=-eabi
+ ;;
+ *)
+ os=-elf
+ ;;
+ esac
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -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
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ pru-*)
+ os=-elf
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-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
+ ;;
+ *-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-functions '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
index 0000000..88c0490
--- /dev/null
+++ b/configure
@@ -0,0 +1,33739 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for rsyslog 8.2402.0.
+#
+# Report bugs to <rsyslog@lists.adiscon.com>.
+#
+#
+# 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 \$(( 1 + 1 )) = 2 || 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"
+ 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: rsyslog@lists.adiscon.com about your system, including
+$0: any error possibly output before this message. Then
+$0: install a modern shell, or manually run the script
+$0: 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'"
+
+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='rsyslog'
+PACKAGE_TARNAME='rsyslog'
+PACKAGE_VERSION='8.2402.0'
+PACKAGE_STRING='rsyslog 8.2402.0'
+PACKAGE_BUGREPORT='rsyslog@lists.adiscon.com'
+PACKAGE_URL=''
+
+ac_unique_file="ChangeLog"
+# 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
+RST2MAN
+ENABLE_GENERATE_MAN_PAGES_FALSE
+ENABLE_GENERATE_MAN_PAGES_TRUE
+YACC_FOUND
+ENABLE_DISTCHECK_WORKAROUND_FALSE
+ENABLE_DISTCHECK_WORKAROUND_TRUE
+ENABLE_MMTAGHOSTNAME_FALSE
+ENABLE_MMTAGHOSTNAME_TRUE
+ENABLE_MMKUBERNETES_FALSE
+ENABLE_MMKUBERNETES_TRUE
+ENABLE_OMTCL_FALSE
+ENABLE_OMTCL_TRUE
+TCL_INCLUDE_SPEC
+TCL_STUB_LIB_SPEC
+TCL_STUB_LIB_FLAG
+TCL_STUB_LIB_FILE
+TCL_LIB_SPEC
+TCL_LIB_FLAG
+TCL_LIB_FILE
+TCL_SRC_DIR
+TCL_BIN_DIR
+TCL_PATCH_LEVEL
+TCL_VERSION
+ENABLE_OMAMQP1_FALSE
+ENABLE_OMAMQP1_TRUE
+ENABLE_OMHTTPFS_FALSE
+ENABLE_OMHTTPFS_TRUE
+ENABLE_IMHIREDIS_FALSE
+ENABLE_IMHIREDIS_TRUE
+ENABLE_OMHIREDIS_FALSE
+ENABLE_OMHIREDIS_TRUE
+REDIS
+LIBEVENT_LIBS
+LIBEVENT_CFLAGS
+HIREDIS_LIBS
+HIREDIS_CFLAGS
+ENABLE_REDIS_TESTS_FALSE
+ENABLE_REDIS_TESTS_TRUE
+ENABLE_OMRABBITMQ_FALSE
+ENABLE_OMRABBITMQ_TRUE
+RABBITMQ_LIBS
+RABBITMQ_CFLAGS
+ENABLE_OMCZMQ_FALSE
+ENABLE_OMCZMQ_TRUE
+ENABLE_IMCZMQ_FALSE
+ENABLE_IMCZMQ_TRUE
+CZMQ_LIBS
+CZMQ_CFLAGS
+ENABLE_OMDTLS_FALSE
+ENABLE_OMDTLS_TRUE
+ENABLE_IMDTLS_FALSE
+ENABLE_IMDTLS_TRUE
+ENABLE_OMMONGODB_FALSE
+ENABLE_OMMONGODB_TRUE
+LIBMONGOC_LIBS
+LIBMONGOC_CFLAGS
+ENABLE_QPIDPROTON_STATIC_FALSE
+ENABLE_QPIDPROTON_STATIC_TRUE
+ENABLE_OMAZUREEVENTHUBS_FALSE
+ENABLE_OMAZUREEVENTHUBS_TRUE
+PROTON_PROACTOR_LIBS
+PROTON_PROACTOR_CFLAGS
+PROTON_LIBS
+PROTON_CFLAGS
+ENABLE_IMKAFKA_FALSE
+ENABLE_IMKAFKA_TRUE
+ENABLE_OMKAFKA_FALSE
+ENABLE_OMKAFKA_TRUE
+READLINK
+WGET
+JAVA
+JAVAC
+IMKAFKA_USE_DUMMY_FALSE
+IMKAFKA_USE_DUMMY_TRUE
+LIBLZ4_LIBS
+LIBLZ4_CFLAGS
+OMKAFKA_USE_DUMMY_FALSE
+OMKAFKA_USE_DUMMY_TRUE
+LIBRDKAFKA_LIBS
+LIBRDKAFKA_CFLAGS
+ENABLE_KAFKA_STATIC_FALSE
+ENABLE_KAFKA_STATIC_TRUE
+ENABLE_KAFKA_TESTS_FALSE
+ENABLE_KAFKA_TESTS_TRUE
+ENABLE_OMAZUREEVENTHUBS_TESTS_FALSE
+ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE
+ENABLE_OMHDFS_FALSE
+ENABLE_OMHDFS_TRUE
+ENABLE_MMSNMPTRAPD_FALSE
+ENABLE_MMSNMPTRAPD_TRUE
+ENABLE_OMUXSOCK_FALSE
+ENABLE_OMUXSOCK_TRUE
+ENABLE_OMRULESET_FALSE
+ENABLE_OMRULESET_TRUE
+ENABLE_PMPANNGFW_FALSE
+ENABLE_PMPANNGFW_TRUE
+ENABLE_PMSNARE_FALSE
+ENABLE_PMSNARE_TRUE
+ENABLE_PMAIXFORWARDEDFROM_FALSE
+ENABLE_PMAIXFORWARDEDFROM_TRUE
+ENABLE_PMNORMALIZE_FALSE
+ENABLE_PMNORMALIZE_TRUE
+ENABLE_PMNULL_FALSE
+ENABLE_PMNULL_TRUE
+ENABLE_PMCISCOIOS_FALSE
+ENABLE_PMCISCOIOS_TRUE
+ENABLE_PMCISCONAMES_FALSE
+ENABLE_PMCISCONAMES_TRUE
+ENABLE_PMLASTMSG_FALSE
+ENABLE_PMLASTMSG_TRUE
+ENABLE_JOURNAL_TESTS_FALSE
+ENABLE_JOURNAL_TESTS_TRUE
+ENABLE_OMJOURNAL_FALSE
+ENABLE_OMJOURNAL_TRUE
+ENABLE_TESTBENCH_FALSE
+ENABLE_TESTBENCH_TRUE
+ENABLE_OMSTDOUT_FALSE
+ENABLE_OMSTDOUT_TRUE
+UDPSPOOF_LIBS
+UDPSPOOF_CFLAGS
+ENABLE_OMUDPSPOOF_FALSE
+ENABLE_OMUDPSPOOF_TRUE
+ENABLE_OMPROG_FALSE
+ENABLE_OMPROG_TRUE
+ENABLE_IMPCAP_FALSE
+ENABLE_IMPCAP_TRUE
+ENABLE_IMPSTATS_FALSE
+ENABLE_IMPSTATS_TRUE
+ENABLE_IMPTCP_FALSE
+ENABLE_IMPTCP_TRUE
+ENABLE_IMSOLARIS_FALSE
+ENABLE_IMSOLARIS_TRUE
+ENABLE_IMHTTP_FALSE
+ENABLE_IMHTTP_TRUE
+CIVETWEB_LIBS
+APU_LIBS
+APU_CFLAGS
+ENABLE_IMPROG_FALSE
+ENABLE_IMPROG_TRUE
+ENABLE_IMTUXEDOULOG_FALSE
+ENABLE_IMTUXEDOULOG_TRUE
+ENABLE_IMDOCKER_TESTS_FALSE
+ENABLE_IMDOCKER_TESTS_TRUE
+ENABLE_IMDOCKER_FALSE
+ENABLE_IMDOCKER_TRUE
+ENABLE_IMFILE_TESTS_FALSE
+ENABLE_IMFILE_TESTS_TRUE
+ENABLE_IMFILE_FALSE
+ENABLE_IMFILE_TRUE
+ENABLE_PMDB2DIAG_FALSE
+ENABLE_PMDB2DIAG_TRUE
+ENABLE_IMBATCHREPORT_FALSE
+ENABLE_IMBATCHREPORT_TRUE
+ENABLE_HELGRIND_FALSE
+ENABLE_HELGRIND_TRUE
+HAVE_VALGRIND_FALSE
+HAVE_VALGRIND_TRUE
+VALGRIND
+ENABLE_IP_FALSE
+ENABLE_IP_TRUE
+IP
+ENABLE_DEFAULT_TESTS_FALSE
+ENABLE_DEFAULT_TESTS_TRUE
+ENABLE_LIBFAKETIME_FALSE
+ENABLE_LIBFAKETIME_TRUE
+ENABLE_RFC3195_FALSE
+ENABLE_RFC3195_TRUE
+LIBLOGGING_LIBS
+LIBLOGGING_CFLAGS
+ENABLE_LIBLOGGING_STDLOG_FALSE
+ENABLE_LIBLOGGING_STDLOG_TRUE
+LIBLOGGING_STDLOG_LIBS
+LIBLOGGING_STDLOG_CFLAGS
+ENABLE_KSI_LS12_FALSE
+ENABLE_KSI_LS12_TRUE
+GT_KSI_LS12_LIBS
+GT_KSI_LS12_CFLAGS
+USE_RELPENGINESETTLSCFGCMD_FALSE
+USE_RELPENGINESETTLSCFGCMD_TRUE
+ENABLE_RELP_FALSE
+ENABLE_RELP_TRUE
+RELP_LIBS
+RELP_CFLAGS
+ENABLE_OMFILE_HARDENED_FALSE
+ENABLE_OMFILE_HARDENED_TRUE
+ENABLE_MMRFC5424ADDHMAC_FALSE
+ENABLE_MMRFC5424ADDHMAC_TRUE
+ENABLE_MMPSTRUCDATA_FALSE
+ENABLE_MMPSTRUCDATA_TRUE
+ENABLE_MMFIELDS_FALSE
+ENABLE_MMFIELDS_TRUE
+ENABLE_MMDARWIN_FALSE
+ENABLE_MMDARWIN_TRUE
+MMDBLOOKUP_USE_DUMMY_FALSE
+MMDBLOOKUP_USE_DUMMY_TRUE
+ENABLE_MMDBLOOKUP_FALSE
+ENABLE_MMDBLOOKUP_TRUE
+ENABLE_MMSEQUENCE_FALSE
+ENABLE_MMSEQUENCE_TRUE
+ENABLE_MMCOUNT_FALSE
+ENABLE_MMCOUNT_TRUE
+ENABLE_MMUTF8FIX_FALSE
+ENABLE_MMUTF8FIX_TRUE
+ENABLE_MMRM1STSPACE_FALSE
+ENABLE_MMRM1STSPACE_TRUE
+ENABLE_MMANON_FALSE
+ENABLE_MMANON_TRUE
+ENABLE_MMAUDIT_FALSE
+ENABLE_MMAUDIT_TRUE
+GLIB_LIBS
+GLIB_CFLAGS
+ENABLE_MMGROK_FALSE
+ENABLE_MMGROK_TRUE
+ENABLE_MMJSONPARSE_FALSE
+ENABLE_MMJSONPARSE_TRUE
+ENABLE_MMNORMALIZE_FALSE
+ENABLE_MMNORMALIZE_TRUE
+LOGNORM_REGEX_SUPPORTED_FALSE
+LOGNORM_REGEX_SUPPORTED_TRUE
+LIBLOGNORM_LIBS
+LIBLOGNORM_CFLAGS
+ENABLE_IMDIAG_FALSE
+ENABLE_IMDIAG_TRUE
+ENABLE_FMHTTP_FALSE
+ENABLE_FMHTTP_TRUE
+ENABLE_MAIL_FALSE
+ENABLE_MAIL_TRUE
+ENABLE_PGSQL_TESTS_FALSE
+ENABLE_PGSQL_TESTS_TRUE
+ENABLE_MYSQL_TESTS_FALSE
+ENABLE_MYSQL_TESTS_TRUE
+ENABLE_EXTENDED_TESTS_FALSE
+ENABLE_EXTENDED_TESTS_TRUE
+ENABLE_RSYSLOGD_FALSE
+ENABLE_RSYSLOGD_TRUE
+RSRT_LIBS
+RSRT_CFLAGS
+RSRT_LIBS1
+RSRT_CFLAGS1
+ENABLE_RSYSLOGRT_FALSE
+ENABLE_RSYSLOGRT_TRUE
+ENABLE_LIBZSTD_FALSE
+ENABLE_LIBZSTD_TRUE
+ZSTD_LIBS
+ZSTD_CFLAGS
+LIBGCRYPT_LIBS
+LIBGCRYPT_CFLAGS
+ENABLE_LIBGCRYPT_FALSE
+ENABLE_LIBGCRYPT_TRUE
+LIBGCRYPT_CONFIG
+ENABLE_GNUTLS_TESTS_FALSE
+ENABLE_GNUTLS_TESTS_TRUE
+ENABLE_GNUTLS_FALSE
+ENABLE_GNUTLS_TRUE
+GNUTLS_LIBS
+GNUTLS_CFLAGS
+ENABLE_OPENSSL_FALSE
+ENABLE_OPENSSL_TRUE
+OPENSSL_LIBS
+OPENSSL_CFLAGS
+ENABLE_CLICKHOUSE_TESTS_FALSE
+ENABLE_CLICKHOUSE_TESTS_TRUE
+ENABLE_ELASTICSEARCH_TESTS_MINIMAL_FALSE
+ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE
+ENABLE_ELASTICSEARCH_TESTS_FALSE
+ENABLE_ELASTICSEARCH_TESTS_TRUE
+ENABLE_OMHTTP_FALSE
+ENABLE_OMHTTP_TRUE
+ENABLE_CLICKHOUSE_FALSE
+ENABLE_CLICKHOUSE_TRUE
+ENABLE_ELASTICSEARCH_FALSE
+ENABLE_ELASTICSEARCH_TRUE
+LIBM
+CURL_LIBS
+CURL_CFLAGS
+ENABLE_UUID_FALSE
+ENABLE_UUID_TRUE
+LIBUUID_LIBS
+LIBUUID_CFLAGS
+ENABLE_SNMP_TESTS_FALSE
+ENABLE_SNMP_TESTS_TRUE
+SNMP_LIBS
+SNMP_CFLAGS
+ENABLE_SNMP_FALSE
+ENABLE_SNMP_TRUE
+LIBDBI_LIBS
+LIBDBI_CFLAGS
+ENABLE_OMLIBDBI_FALSE
+ENABLE_OMLIBDBI_TRUE
+LIBDBI_USE_DUMMY_FALSE
+LIBDBI_USE_DUMMY_TRUE
+ENABLE_PGSQL_FALSE
+ENABLE_PGSQL_TRUE
+PG_CONFIG
+PGSQL_LIBS
+PGSQL_CFLAGS
+ENABLE_MYSQL_FALSE
+ENABLE_MYSQL_TRUE
+MYSQL_CONFIG
+MYSQL_LIBS
+MYSQL_CFLAGS
+ENABLE_USERTOOLS_FALSE
+ENABLE_USERTOOLS_TRUE
+ENABLE_DIAGTOOLS_FALSE
+ENABLE_DIAGTOOLS_TRUE
+ENABLE_JEMALLOC_FALSE
+ENABLE_JEMALLOC_TRUE
+ENABLE_INET_FALSE
+ENABLE_INET_TRUE
+LIBSYSTEMD_LIBS
+LIBSYSTEMD_CFLAGS
+ENABLE_IMJOURNAL_FALSE
+ENABLE_IMJOURNAL_TRUE
+IMJOURNAL_USE_DUMMY_FALSE
+IMJOURNAL_USE_DUMMY_TRUE
+LIBSYSTEMD_JOURNAL_LIBS
+LIBSYSTEMD_JOURNAL_CFLAGS
+ENABLE_IMKMSG_FALSE
+ENABLE_IMKMSG_TRUE
+ENABLE_IMKLOG_SOLARIS_FALSE
+ENABLE_IMKLOG_SOLARIS_TRUE
+ENABLE_IMKLOG_LINUX_FALSE
+ENABLE_IMKLOG_LINUX_TRUE
+ENABLE_IMKLOG_BSD_FALSE
+ENABLE_IMKLOG_BSD_TRUE
+ENABLE_IMKLOG_FALSE
+ENABLE_IMKLOG_TRUE
+IMUDP_LIBS
+PTHREADS_CFLAGS
+PTHREADS_LIBS
+ENABLE_ROOT_TESTS_FALSE
+ENABLE_ROOT_TESTS_TRUE
+ENABLE_GSSAPI_FALSE
+ENABLE_GSSAPI_TRUE
+GSS_LIBS
+ENABLE_FMUNFLATTEN_FALSE
+ENABLE_FMUNFLATTEN_TRUE
+FAUP_LIBS
+ENABLE_FFAUP_FALSE
+ENABLE_FFAUP_TRUE
+HASH_XXHASH_LIBS
+ENABLE_FMHASH_XXHASH_FALSE
+ENABLE_FMHASH_XXHASH_TRUE
+ENABLE_FMHASH_FALSE
+ENABLE_FMHASH_TRUE
+LIBCAPNG_LIBS
+LIBCAPNG_CFLAGS
+LIBCAPNG_PRESENT_LIBS
+LIBCAPNG_PRESENT_CFLAGS
+ZLIB_LIBS
+ZLIB_CFLAGS
+ENABLE_REGEXP_FALSE
+ENABLE_REGEXP_TRUE
+moddirs
+WITH_MODDIRS_FALSE
+WITH_MODDIRS_TRUE
+ENABLE_INOTIFY_FALSE
+ENABLE_INOTIFY_TRUE
+LIBOBJS
+DL_LIBS
+RT_LIBS
+pkgpyexecdir
+pyexecdir
+pkgpythondir
+pythondir
+PYTHON_PLATFORM
+PYTHON_EXEC_PREFIX
+PYTHON_PREFIX
+PYTHON_VERSION
+PYTHON
+OS_AIX_FALSE
+OS_AIX_TRUE
+OS_LINUX_FALSE
+OS_LINUX_TRUE
+OS_APPLE_FALSE
+OS_APPLE_TRUE
+SOL_LIBS
+LIBFASTJSON_LIBS
+LIBFASTJSON_CFLAGS
+LIBESTR_LIBS
+LIBESTR_CFLAGS
+PID_FILE_PATH
+CONF_FILE_PATH
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+WARN_SCANNERFLAGS
+WARN_LDFLAGS
+WARN_CFLAGS
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+ac_ct_AR
+AR
+DLLTOOL
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+EGREP
+GREP
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+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
+runstatedir
+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
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_aix64bits
+enable_dependency_tracking
+enable_static
+enable_shared
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_compile_warnings
+enable_Werror
+enable_atomic_operations
+with_moddirs
+enable_largefile
+enable_regexp
+enable_fmhash
+enable_libcap_ng
+enable_fmhash_xxhash
+enable_ffaup
+enable_fmunflatten
+enable_gssapi_krb5
+enable_root_tests
+enable_klog
+enable_kmsg
+enable_imjournal
+enable_libsystemd
+enable_inet
+enable_jemalloc
+enable_unlimited_select
+enable_debug
+enable_debug_symbols
+enable_debugless
+enable_valgrind
+enable_diagtools
+enable_usertools
+enable_mysql
+enable_pgsql
+enable_libdbi
+enable_snmp
+enable_snmp_tests
+enable_uuid
+enable_elasticsearch
+enable_clickhouse
+enable_omhttp
+enable_elasticsearch_tests
+enable_clickhouse_tests
+enable_openssl
+enable_gnutls
+enable_gnutls_tests
+enable_libgcrypt
+enable_libzstd
+enable_rsyslogrt
+enable_rsyslogd
+enable_extended_tests
+enable_mysql_tests
+enable_pgsql_tests
+enable_mail
+enable_fmhttp
+enable_imdiag
+enable_mmnormalize
+enable_mmjsonparse
+enable_mmgrok
+enable_mmaudit
+enable_mmanon
+enable_mmrm1stspace
+enable_mmutf8fix
+enable_mmcount
+enable_mmsequence
+enable_mmdblookup
+enable_mmdarwin
+enable_mmfields
+enable_mmpstrucdata
+enable_mmrfc5424addhmac
+enable_omfile_hardened
+enable_relp
+enable_omrelp_default_port
+enable_ksi_ls12
+enable_liblogging_stdlog
+enable_rfc3195
+enable_testbench
+enable_libfaketime
+enable_default_tests
+with_valgrind_testbench
+enable_helgrind
+enable_imbatchreport
+enable_pmdb2diag
+enable_imfile
+enable_imfile_tests
+enable_imdocker
+enable_imdocker_tests
+enable_imtuxedoulog
+enable_improg
+enable_imhttp
+enable_imsolaris
+enable_imptcp
+enable_impstats
+enable_impcap
+enable_omprog
+enable_omudpspoof
+enable_omstdout
+enable_omjournal
+enable_journal_tests
+enable_pmlastmsg
+enable_pmcisconames
+enable_pmciscoios
+enable_pmnull
+enable_pmnormalize
+enable_pmaixforwardedfrom
+enable_pmsnare
+enable_pmpanngfw
+enable_omruleset
+enable_omuxsock
+enable_mmsnmptrapd
+enable_omhdfs
+enable_omkafka
+enable_imkafka
+enable_omazureeventhubs_tests
+enable_kafka_tests
+enable_kafka_static
+enable_omazureeventhubs
+enable_qpidproton_static
+enable_ommongodb
+enable_imdtls
+enable_omdtls
+enable_imczmq
+enable_omczmq
+enable_omrabbitmq
+enable_imhiredis
+enable_omhiredis
+enable_redis_tests
+enable_omhttpfs
+enable_omamqp1
+enable_omtcl
+with_tcl
+enable_mmkubernetes
+enable_mmtaghostname
+enable_generate_man_pages
+enable_distcheck_workaround
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+YACC
+YFLAGS
+LT_SYS_LIBRARY_PATH
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+CONF_FILE_PATH
+PID_FILE_PATH
+LIBESTR_CFLAGS
+LIBESTR_LIBS
+LIBFASTJSON_CFLAGS
+LIBFASTJSON_LIBS
+PYTHON
+ZLIB_CFLAGS
+ZLIB_LIBS
+LIBCAPNG_PRESENT_CFLAGS
+LIBCAPNG_PRESENT_LIBS
+LIBCAPNG_CFLAGS
+LIBCAPNG_LIBS
+LIBSYSTEMD_JOURNAL_CFLAGS
+LIBSYSTEMD_JOURNAL_LIBS
+LIBSYSTEMD_CFLAGS
+LIBSYSTEMD_LIBS
+MYSQL_CFLAGS
+MYSQL_LIBS
+PGSQL_CFLAGS
+PGSQL_LIBS
+LIBUUID_CFLAGS
+LIBUUID_LIBS
+CURL_CFLAGS
+CURL_LIBS
+OPENSSL_CFLAGS
+OPENSSL_LIBS
+GNUTLS_CFLAGS
+GNUTLS_LIBS
+ZSTD_CFLAGS
+ZSTD_LIBS
+LIBLOGNORM_CFLAGS
+LIBLOGNORM_LIBS
+RELP_CFLAGS
+RELP_LIBS
+GT_KSI_LS12_CFLAGS
+GT_KSI_LS12_LIBS
+LIBLOGGING_STDLOG_CFLAGS
+LIBLOGGING_STDLOG_LIBS
+LIBLOGGING_CFLAGS
+LIBLOGGING_LIBS
+APU_CFLAGS
+APU_LIBS
+LIBRDKAFKA_CFLAGS
+LIBRDKAFKA_LIBS
+LIBLZ4_CFLAGS
+LIBLZ4_LIBS
+PROTON_CFLAGS
+PROTON_LIBS
+PROTON_PROACTOR_CFLAGS
+PROTON_PROACTOR_LIBS
+LIBMONGOC_CFLAGS
+LIBMONGOC_LIBS
+CZMQ_CFLAGS
+CZMQ_LIBS
+RABBITMQ_CFLAGS
+RABBITMQ_LIBS
+HIREDIS_CFLAGS
+HIREDIS_LIBS
+LIBEVENT_CFLAGS
+LIBEVENT_LIBS'
+
+
+# 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'
+runstatedir='${localstatedir}/run'
+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 ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -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 runstatedir
+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 rsyslog 8.2402.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]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --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/rsyslog]
+ --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 rsyslog 8.2402.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-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-aix64bits Enable compilation of rsyslog using 64 bits
+ [default=no]
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
+ --enable-static[=PKGS] build static libraries [default=no]
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-compile-warnings=[no/yes/error]
+ Enable compiler warnings and errors
+ --disable-Werror Unconditionally make all compiler warnings non-fatal
+ --enable-atomic-operations
+ Enable atomic operation support [default=yes]
+ --disable-largefile omit support for large files
+ --enable-regexp Enable regular expressions support [default=yes]
+ --enable-fmhash Enable fmhash support [default=yes]
+ --enable-libcap-ng Enable dropping capabilities to only the necessary
+ set [default=no]
+ --enable-fmhash-xxhash Enable xxhash in fmhash support [default=no]
+ --enable-ffaup Enable ffaup support [default=no]
+ --enable-fmunflatten Enable fmunflatten support [default=no]
+ --enable-gssapi-krb5 Enable GSSAPI Kerberos 5 support [default=no]
+ --enable-root-tests enable root tests in testbench [default=no]
+ --enable-klog Integrated klog functionality [default=yes]
+ --enable-kmsg Kmsg structured kernel logs functionality
+ [default=no]
+ --enable-imjournal Systemd journal message import [default=no]
+ --enable-libsystemd Enable libsystemd mode [default=auto]
+ --enable-inet Enable automatic load of omfwd and limit build of
+ networking libraries [default=yes]
+ --enable-jemalloc Enable jemalloc support [default=no]
+ --enable-unlimited-select
+ Enable unlimited select() syscall [default=no]
+ --enable-debug Enable debug mode [default=auto]
+ --disable-debug-symbols Disable debugging symbols [default=no]
+ --enable-debugless Enable runtime instrumentation mode [default=no]
+ --enable-valgrind Enable somes special code that rsyslog core
+ developers consider useful for testing. Do NOT use
+ if you don't exactly know what you are doing, except
+ if told so by rsyslog developers. NOT to be used by
+ distro maintainers for building regular packages.
+ [default=no]
+ --enable-diagtools Enable diagnostic tools [default=no]
+ --enable-usertools Enable end user tools [default=no]
+ --enable-mysql Enable MySql database support [default=no]
+ --enable-pgsql Enable PostgreSQL database support [default=no]
+ --enable-libdbi Enable libdbi database support [default=no]
+ --enable-snmp Enable SNMP support [default=no]
+ --enable-snmp-tests Enable omsnmp tests [default=no]
+ --enable-uuid Enable support for uuid generation [default=yes]
+ --enable-elasticsearch Enable elasticsearch output module [default=no]
+ --enable-clickhouse Enable clickhouse output module [default=no]
+ --enable-omhttp Enable http output module [default=no]
+ --enable-elasticsearch-tests
+ enable Elasticsearch specific tests in testbench
+ [default=no]
+ --enable-clickhouse-tests
+ enable Elasticsearch specific tests in testbench
+ [default=no]
+ --enable-openssl Enable openssl support [default=no]
+ --enable-gnutls Enable GNU TLS support [default=no]
+ --enable-gnutls-tests Enable gnutls tests [default=yes]
+ --enable-libgcrypt Enable log file encryption support (libgcrypt)
+ [default=yes]
+ --enable-libzstd Enable log file compression support via libzstd
+ [default=no]
+ --enable-rsyslogrt Build rsyslogrt [default=yes]
+ --enable-rsyslogd Build rsyslogd [default=yes]
+ --enable-extended-tests extended testbench [default=no]
+ --enable-mysql-tests enable MySQL specific tests in testbench
+ [default=no]
+ --enable-pgsql-tests enable PostgreSQL specific tests in testbench
+ [default=no]
+ --enable-mail Enable mail support [default=no]
+ --enable-fmhttp Enable fmhttp [default=yes]
+ --enable-imdiag Enable imdiag [default=no]
+ --enable-mmnormalize Enable building mmnormalize support [default=no]
+ --enable-mmjsonparse Enable building mmjsonparse support [default=no]
+ --enable-mmgrok Enable building mmgrok support [default=no]
+ --enable-mmaudit Enable building mmaudit support [default=no]
+ --enable-mmanon Enable building mmanon support [default=no]
+ --enable-mmrm1stspace Enable building mmrm1stspace support [default=no]
+ --enable-mmutf8fix Enable building mmutf8fix support [default=no]
+ --enable-mmcount Enable message counting [default=no]
+ --enable-mmsequence Enable sequence generator [default=no]
+ --enable-mmdblookup Enable mmdb lookup helper [default=no]
+ --enable-mmdarwin Enable mmdb lookup helper [default=no]
+ --enable-mmfields Enable building mmfields support [default=no]
+ --enable-mmpstrucdata Enable building mmpstrucdata support [default=no]
+ --enable-mmrfc5424addhmac
+ Enable building mmrfc5424addhmac support
+ [default=no]
+ --enable-omfile-hardened
+ Enable omfile-hardened support [default=no]
+ --enable-relp Enable RELP support [default=no]
+ --enable-omrelp-default-port
+ set omrelp default port [default=514]
+ --enable-ksi-ls12 Enable log file signing support via GuardTime KSI
+ LS12 [default=no]
+ --enable-liblogging-stdlog
+ Enable liblogging-stdlog support [default=no]
+ --enable-rfc3195 Enable RFC3195 support [default=no]
+ --enable-testbench testbench enabled [default=no]
+ --enable-libfaketime libfaketime enabled [default=no]
+ --enable-default-tests default-tests enabled [default=yes]
+ --enable-helgrind valgrind helgrind enabled [default=yes]
+ --enable-imbatchreport batch report input module enabled [default=no]
+ --enable-pmdb2diag db2diag parser module enabled [default=no]
+ --enable-imfile file input module enabled [default=no]
+ --enable-imfile-tests Enable imfile tests [default=yes]
+ --enable-imdocker input docker module enabled [default=no]
+ --enable-imdocker-tests Enable imdocker tests [default=no]
+ --enable-imtuxedoulog tuxedo ULOG input module enabled [default=no]
+ --enable-improg external program input module enabled [default=no]
+ --enable-imhttp external http input module enabled [default=no]
+ --enable-imsolaris solaris input module enabled [default=no]
+ --enable-imptcp plain tcp input module enabled [default=no]
+ --enable-impstats periodic statistics module enabled [default=no]
+ --enable-impcap libpcap input module enabled [default=no]
+ --enable-omprog Compiles omprog module [default=no]
+ --enable-omudpspoof Compiles omudpspoof module [default=no]
+ --enable-omstdout Compiles stdout module [default=no]
+ --enable-omjournal Compiles omjournal [default=no]
+ --enable-journal-tests enable systemd journal specific tests in testbench
+ [default=no]
+ --enable-pmlastmsg Compiles lastmsg parser module [default=no]
+ --enable-pmcisconames Compiles cisconames parser module [default=no]
+ --enable-pmciscoios Compiles ciscoios parser module [default=no]
+ --enable-pmnull Compiles null parser module [default=no]
+ --enable-pmnormalize Compiles normalizer parser module [default=no]
+ --enable-pmaixforwardedfrom
+ Compiles aixforwardedfrom parser module [default=no]
+ --enable-pmsnare Compiles snare parser module [default=no]
+ --enable-pmpanngfw Compiles Palo Alto Networks parser module
+ [default=no]
+ --enable-omruleset Compiles ruleset forwarding module [default=no]
+ --enable-omuxsock Compiles omuxsock module [default=no]
+ --enable-mmsnmptrapd Compiles mmsnmptrapd module [default=no]
+ --enable-omhdfs Compiles omhdfs module [default=no]
+ --enable-omkafka Compiles kafka output module [default=no]
+ --enable-imkafka Compiles kafka input and output module [default=no]
+ --enable-omazureeventhubs-tests
+ Enable Omazureeventhubs tests [default=no]
+ --enable-kafka-tests Enable Kafka tests, needs Java [default=no]
+ --enable-kafka-static Enable static library linking for Kafka modules.
+ Removes dependency for rdkafka.so. [default=no]
+ --enable-omazureeventhubs
+ Compiles AzureEventHubs output module [default=no]
+ --enable-qpidproton_static
+ Enable static library linking for qpid-proton
+ (required by omazureeventhubs module). Removes
+ dependency for libqpid-proton*.so. [default=no]
+ --enable-ommongodb Compiles ommongodb module [default=no]
+ --enable-imdtls Compiles DTLS syslog input module [default=no]
+ --enable-omdtls Compiles DTLS syslog output module [default=no]
+ --enable-imczmq Compiles imczmq output module [default=no]
+ --enable-omczmq Compiles omczmq output module [default=no]
+ --enable-omrabbitmq Compiles omrabbitmq output module [default=no]
+ --enable-imhiredis Compiles imhiredis input module [default=no]
+ --enable-omhiredis Compiles omhiredis template module [default=no]
+ --enable-redis-tests Enable redis tests, needs redis-server [default=no]
+ --enable-omhttpfs Compiles omhttpfs template module [default=no]
+ --enable-omamqp1 Compiles omamqp1 output module [default=no]
+ --enable-omtcl Compiles omtcl output module [default=no]
+ --enable-mmkubernetes Enable compilation of the mmkubernetes module
+ [default=no]
+ --enable-mmtaghostname Enable Tag and Hostname messages' modifier
+ [default=no]
+ --enable-generate-man-pages
+ Generate man pages from source [default=no]
+ --enable-distcheck-workaround
+ enable to use make distcheck without runing
+ testbench inside it [default=no]
+
+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-aix-soname=aix|svr4|both
+ shared library versioning (aka "SONAME") variant to
+ provide on AIX, [default=aix].
+ --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-moddirs=DIRS Additional module search paths appended to
+ [$libdir/rsyslog]
+ --without-valgrind-testbench
+ Don't use valgrind in testbench
+
+ --with-tcl directory containing tcl configuration
+ (tclConfig.sh)
+
+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.
+ LT_SYS_LIBRARY_PATH
+ User-defined run-time library search path.
+ 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
+ CONF_FILE_PATH
+ Configuration file path (default : /etc/rsyslog.conf)
+ PID_FILE_PATH
+ Pid file path (default : /var/run/rsyslogd.pid)
+ LIBESTR_CFLAGS
+ C compiler flags for LIBESTR, overriding pkg-config
+ LIBESTR_LIBS
+ linker flags for LIBESTR, overriding pkg-config
+ LIBFASTJSON_CFLAGS
+ C compiler flags for LIBFASTJSON, overriding pkg-config
+ LIBFASTJSON_LIBS
+ linker flags for LIBFASTJSON, overriding pkg-config
+ PYTHON the Python interpreter
+ ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config
+ ZLIB_LIBS linker flags for ZLIB, overriding pkg-config
+ LIBCAPNG_PRESENT_CFLAGS
+ C compiler flags for LIBCAPNG_PRESENT, overriding pkg-config
+ LIBCAPNG_PRESENT_LIBS
+ linker flags for LIBCAPNG_PRESENT, overriding pkg-config
+ LIBCAPNG_CFLAGS
+ C compiler flags for LIBCAPNG, overriding pkg-config
+ LIBCAPNG_LIBS
+ linker flags for LIBCAPNG, overriding pkg-config
+ LIBSYSTEMD_JOURNAL_CFLAGS
+ C compiler flags for LIBSYSTEMD_JOURNAL, overriding pkg-config
+ LIBSYSTEMD_JOURNAL_LIBS
+ linker flags for LIBSYSTEMD_JOURNAL, overriding pkg-config
+ LIBSYSTEMD_CFLAGS
+ C compiler flags for LIBSYSTEMD, overriding pkg-config
+ LIBSYSTEMD_LIBS
+ linker flags for LIBSYSTEMD, overriding pkg-config
+ MYSQL_CFLAGS
+ C compiler flags for MYSQL, overriding pkg-config
+ MYSQL_LIBS linker flags for MYSQL, overriding pkg-config
+ PGSQL_CFLAGS
+ C compiler flags for PGSQL, overriding pkg-config
+ PGSQL_LIBS linker flags for PGSQL, overriding pkg-config
+ LIBUUID_CFLAGS
+ C compiler flags for LIBUUID, overriding pkg-config
+ LIBUUID_LIBS
+ linker flags for LIBUUID, overriding pkg-config
+ CURL_CFLAGS C compiler flags for CURL, overriding pkg-config
+ CURL_LIBS linker flags for CURL, overriding pkg-config
+ OPENSSL_CFLAGS
+ C compiler flags for OPENSSL, overriding pkg-config
+ OPENSSL_LIBS
+ linker flags for OPENSSL, overriding pkg-config
+ GNUTLS_CFLAGS
+ C compiler flags for GNUTLS, overriding pkg-config
+ GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config
+ ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
+ ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
+ LIBLOGNORM_CFLAGS
+ C compiler flags for LIBLOGNORM, overriding pkg-config
+ LIBLOGNORM_LIBS
+ linker flags for LIBLOGNORM, overriding pkg-config
+ RELP_CFLAGS C compiler flags for RELP, overriding pkg-config
+ RELP_LIBS linker flags for RELP, overriding pkg-config
+ GT_KSI_LS12_CFLAGS
+ C compiler flags for GT_KSI_LS12, overriding pkg-config
+ GT_KSI_LS12_LIBS
+ linker flags for GT_KSI_LS12, overriding pkg-config
+ LIBLOGGING_STDLOG_CFLAGS
+ C compiler flags for LIBLOGGING_STDLOG, overriding pkg-config
+ LIBLOGGING_STDLOG_LIBS
+ linker flags for LIBLOGGING_STDLOG, overriding pkg-config
+ LIBLOGGING_CFLAGS
+ C compiler flags for LIBLOGGING, overriding pkg-config
+ LIBLOGGING_LIBS
+ linker flags for LIBLOGGING, overriding pkg-config
+ APU_CFLAGS C compiler flags for APU, overriding pkg-config
+ APU_LIBS linker flags for APU, overriding pkg-config
+ LIBRDKAFKA_CFLAGS
+ C compiler flags for LIBRDKAFKA, overriding pkg-config
+ LIBRDKAFKA_LIBS
+ linker flags for LIBRDKAFKA, overriding pkg-config
+ LIBLZ4_CFLAGS
+ C compiler flags for LIBLZ4, overriding pkg-config
+ LIBLZ4_LIBS linker flags for LIBLZ4, overriding pkg-config
+ PROTON_CFLAGS
+ C compiler flags for PROTON, overriding pkg-config
+ PROTON_LIBS linker flags for PROTON, overriding pkg-config
+ PROTON_PROACTOR_CFLAGS
+ C compiler flags for PROTON_PROACTOR, overriding pkg-config
+ PROTON_PROACTOR_LIBS
+ linker flags for PROTON_PROACTOR, overriding pkg-config
+ LIBMONGOC_CFLAGS
+ C compiler flags for LIBMONGOC, overriding pkg-config
+ LIBMONGOC_LIBS
+ linker flags for LIBMONGOC, overriding pkg-config
+ CZMQ_CFLAGS C compiler flags for CZMQ, overriding pkg-config
+ CZMQ_LIBS linker flags for CZMQ, overriding pkg-config
+ RABBITMQ_CFLAGS
+ C compiler flags for RABBITMQ, overriding pkg-config
+ RABBITMQ_LIBS
+ linker flags for RABBITMQ, overriding pkg-config
+ HIREDIS_CFLAGS
+ C compiler flags for HIREDIS, overriding pkg-config
+ HIREDIS_LIBS
+ linker flags for HIREDIS, overriding pkg-config
+ LIBEVENT_CFLAGS
+ C compiler flags for LIBEVENT, overriding pkg-config
+ LIBEVENT_LIBS
+ linker flags for LIBEVENT, 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 <rsyslog@lists.adiscon.com>.
+_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
+rsyslog configure 8.2402.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_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_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;}
+( $as_echo "## ---------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com ##
+## ---------------------------------------- ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&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_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_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_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_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_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_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
+
+# 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
+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 rsyslog $as_me 8.2402.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
+
+ # UPDATE on release
+
+$as_echo "#define VERSION_YEAR 24" >>confdefs.h
+ # UPDATE on release
+
+$as_echo "#define VERSION_MONTH 2" >>confdefs.h
+ # UPDATE on release
+
+am__api_version='1.16'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; 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 \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$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.
+
+
+# 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+set}" != 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='rsyslog'
+ VERSION='8.2402.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:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver). 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: <https://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='\'
+
+
+unamestr=$(uname)
+if test "$unamestr" = "AIX"; then
+ # Check whether --enable-aix64bits was given.
+if test "${enable_aix64bits+set}" = set; then :
+ enableval=$enable_aix64bits; case "${enableval}" in
+ yes) enable_aix64bits="yes" ;;
+ no) enable_aix64bits="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-aix64bits" "$LINENO" 5 ;;
+ esac
+else
+ enable_aix64bits=no
+
+fi
+
+
+ CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT"
+ LDFLAGS="-brtl"
+ if test "x$enable_aix64bits" == "xyes"; then
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS="$LDFLAGS -b64"
+ AR_CFLAGS="-X64 $AR_CFLAGS"
+ NM="$(which nm) -X64 rcu"
+ fi
+fi
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+ (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ case $?:`cat confinc.out 2>/dev/null` in #(
+ '0:this is the am__doit target') :
+ case $s in #(
+ BSD) :
+ am__include='.include' am__quote='"' ;; #(
+ *) :
+ am__include='include' am__quote='' ;;
+esac ;; #(
+ *) :
+ ;;
+esac
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+$as_echo "${_am_result}" >&6; }
+
+# 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
+
+
+
+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 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 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
+
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+ MINIX=yes
+else
+ MINIX=
+fi
+
+
+ if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_safe_to_define___extensions__=yes
+else
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+# Checks for programs.
+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"
+
+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
+
+
+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 $CC option to accept ISO C99" >&5
+$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
+if ${ac_cv_prog_cc_c99+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+}
+
+int
+main ()
+{
+
+ // Check bool.
+ _Bool success = false;
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
+
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" 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_c99"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c99" != xno; then :
+
+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
+
+
+
+
+
+
+
+
+
+# AIXPORT START: enable dlopen
+if test "$unamestr" = "AIX"; then
+ enable_dlopen=yes
+
+
+
+fi
+# AIXPORT end
+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.6'
+macro_revision='2.4.6'
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $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 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 no = "$withval" || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; 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 yes = "$with_gnu_ld"; 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 no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && 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
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ 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 no != "$lt_cv_path_NM"; 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 -headers /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ 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;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+ # 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 17 != "$i" # 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"}
+
+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 yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; 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
+# that 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.
+ if ( 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* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; 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
+ ;;
+os2*)
+ 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 one 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=cr}
+
+
+
+
+
+
+
+
+
+
+
+{ $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 0 -eq "$ac_status"; 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 0 -ne "$ac_status"; 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 no = "$lt_cv_ar_at_file"; 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
+ bitrig* | 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 ia64 = "$host_cpu"; 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
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# 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"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$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"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/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,
+ # D for any global variable and I for any imported 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};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,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
+ $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+ if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && 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 can'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* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$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 yes = "$pipe_works"; 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 yes = "$GCC"; 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; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+$as_echo_n "checking for a working dd... " >&6; }
+if ${ac_cv_path_lt_DD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+ ac_path_lt_DD_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 dd; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+ $ac_path_lt_DD_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_lt_DD"; then
+ :
+ fi
+else
+ ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+$as_echo "$ac_cv_path_lt_DD" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+$as_echo_n "checking how to truncate binary pipes... " >&6; }
+if ${lt_cv_truncate_bin+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+$as_echo "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+ enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || 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 what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ 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 what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ 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 yes = "$lt_cv_prog_gnu_ld"; 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*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ 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
+ emul=elf
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ 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-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ 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-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ 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 yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ 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*|x86_64-*-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 yes != "$lt_cv_path_mainfest_tool"; 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 0 = "$_lt_result"; 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 cr libconftest.a conftest.o" >&5
+ $AR cr 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 0 = "$_lt_result" && $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 yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; 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 no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+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_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 --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
+
+
+
+
+
+
+
+
+ # 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
+
+
+
+
+
+
+
+
+ shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+$as_echo_n "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test "${with_aix_soname+set}" = set; then :
+ withval=$with_aix_soname; case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname
+else
+ if ${lt_cv_with_aix_soname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_with_aix_soname=aix
+fi
+
+ with_aix_soname=$lt_cv_with_aix_soname
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+$as_echo "$with_aix_soname" >&6; }
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# 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 set != "${COLLECT_NAMES+set}"; 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
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# 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 yes = "$GCC"; 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" ## exclude from sc_useless_quotes_in_assignment
+ # 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 yes = "$lt_cv_prog_compiler_rtti_exceptions"; 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 yes = "$GCC"; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+
+ 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'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ 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 ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ 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'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ 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'
+ ;;
+ # flang / f18. f95 an alias for gfortran or flang on Debian
+ flang* | f18* | f95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ 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'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ 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 that 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" ## exclude from sc_useless_quotes_in_assignment
+ # 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 yes = "$lt_cv_prog_compiler_pic_works"; 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 yes = "$lt_cv_prog_compiler_static_works"; 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 no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; 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 no = "$hard_links"; 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 yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ 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 yes = "$with_gnu_ld"; 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 yes = "$lt_use_gnu_ld_interface"; 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 | $SED -e 's/(^)\+)\s\+//' 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 ia64 != "$host_cpu"; 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, use it as
+ # is; otherwise, prepend EXPORTS...
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; 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
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=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 linux-dietlibc = "$host_os"; 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 no = "$tmp_diet"
+ 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' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-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 yes = "$supports_anon_versioning"; 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
+ tcc*)
+ export_dynamic_flag_spec='-rdynamic'
+ ;;
+ 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 yes = "$supports_anon_versioning"; 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 cannot
+*** 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 no = "$ld_shlibs"; 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 yes = "$GCC" && 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 ia64 = "$host_cpu"; 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 GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ 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) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 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
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ 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,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ 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,yes = "$with_aix_soname,$aix_use_runtimelinking"; 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 set = "${lt_cv_aix_libpath+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 -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; 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 set = "${lt_cv_aix_libpath+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 yes = "$with_gnu_ld"; 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
+ archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+ 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,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $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 yes = "$lt_cv_ld_force_load"; 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*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; 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 yes = "$GCC"; 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 "x$output_objdir/$soname" = "x$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 "x$output_objdir/$soname" = "x$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 yes,no = "$GCC,$with_gnu_ld"; 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 no = "$with_gnu_ld"; 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 yes,no = "$GCC,$with_gnu_ld"; 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 yes = "$lt_cv_prog_compiler__b"; 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 no = "$with_gnu_ld"; 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 yes = "$GCC"; 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 yes = "$lt_cv_irix_exported_symbol"; 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
+ link_all_deplibs=no
+ 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
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ ld_shlibs=yes
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ 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* | bitrig*)
+ 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__`"; 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
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 sequent = "$host_vendor"; 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 yes = "$GCC"; 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 CANNOT 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 yes = "$GCC"; 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 sni = "$host_vendor"; 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 no = "$ld_shlibs" && 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 yes,yes = "$GCC,$enable_shared"; 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 yes = "$GCC"; 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`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ 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"
+ elif test -n "$lt_multi_os_dir"; then
+ 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 ia64 = "$host_cpu"; 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
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # 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'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a(lib.so.V)'
+ # 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'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ 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%'\''`; $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$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ 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=no
+ 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 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ 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 yes = "$lt_cv_prog_gnu_ld"; 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
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # 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
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+
+# 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
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) 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* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ 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
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ 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'
+ ;;
+
+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 yes = "$with_gnu_ld"; 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=sco
+ 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 yes = "$with_gnu_ld"; 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 no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $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 yes = "$hardcode_automatic"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$hardcode_direct" &&
+ # 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 no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+ test no != "$hardcode_minus_L"; 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 relink = "$hardcode_action" ||
+ test yes = "$inherit_rpath"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test yes != "$enable_dlopen"; 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
+
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ 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 no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && 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 yes = "$cross_compiling"; 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 -fvisibility=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 yes = "$lt_cv_dlopen_self"; 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 yes = "$cross_compiling"; 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 -fvisibility=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 what 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ 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 yes = "$enable_shared" || 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:
+
+
+
+
+if test "$GCC" = "yes"
+then
+
+
+
+
+
+ # $is_release = (.git directory does not exist)
+ if test -d ${srcdir}/.git; then :
+ ax_is_release=no
+else
+ ax_is_release=yes
+fi
+
+
+
+
+ # C support is enabled by default.
+
+
+ # Only enable C++ support if AC_PROG_CXX is called. The redefinition of
+ # AC_PROG_CXX is so that a fatal error is emitted if this macro is called
+ # before AC_PROG_CXX, which would otherwise cause no C++ warnings to be
+ # checked.
+
+
+
+
+ # Default value for IS-RELEASE is $ax_is_release
+ ax_compiler_flags_is_release=$ax_is_release
+
+ # Check whether --enable-compile-warnings was given.
+if test "${enable_compile_warnings+set}" = set; then :
+ enableval=$enable_compile_warnings;
+else
+ if test "$ax_compiler_flags_is_release" = "yes"; then :
+ enable_compile_warnings="yes"
+else
+ enable_compile_warnings="error"
+fi
+fi
+
+ # Check whether --enable-Werror was given.
+if test "${enable_Werror+set}" = set; then :
+ enableval=$enable_Werror;
+else
+ enable_Werror=maybe
+fi
+
+
+ # Return the user's chosen warning level
+ if test "$enable_Werror" = "no" -a \
+ "$enable_compile_warnings" = "error"; then :
+
+ enable_compile_warnings="yes"
+
+fi
+
+ ax_enable_compile_warnings=$enable_compile_warnings
+
+
+
+
+
+
+
+
+
+
+ # Variable names
+
+
+ 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. */
+
+ #ifndef __cplusplus
+ #error "no C++"
+ #endif
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_compiler_cxx=yes;
+else
+ ax_compiler_cxx=no;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+ # flags, otherwise they are always appended to the warn_cflags variable, and
+ # Clang warns on them for every compilation unit.
+ # If this is passed to GCC, it will explode, so the flag must be enabled
+ # conditionally.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror=unknown-warning-option" >&5
+$as_echo_n "checking whether C compiler accepts -Werror=unknown-warning-option... " >&6; }
+if ${ax_cv_check_cflags___Werror_unknown_warning_option+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Werror=unknown-warning-option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_cv_check_cflags___Werror_unknown_warning_option=yes
+else
+ ax_cv_check_cflags___Werror_unknown_warning_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror_unknown_warning_option" >&5
+$as_echo "$ax_cv_check_cflags___Werror_unknown_warning_option" >&6; }
+if test "x$ax_cv_check_cflags___Werror_unknown_warning_option" = xyes; then :
+
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+
+else
+
+ ax_compiler_flags_test=""
+
+fi
+
+
+ # Check that -Wno-suggest-attribute=format is supported
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wno-suggest-attribute=format" >&5
+$as_echo_n "checking whether C compiler accepts -Wno-suggest-attribute=format... " >&6; }
+if ${ax_cv_check_cflags___Wno_suggest_attribute_format+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Wno-suggest-attribute=format"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_cv_check_cflags___Wno_suggest_attribute_format=yes
+else
+ ax_cv_check_cflags___Wno_suggest_attribute_format=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wno_suggest_attribute_format" >&5
+$as_echo "$ax_cv_check_cflags___Wno_suggest_attribute_format" >&6; }
+if test "x$ax_cv_check_cflags___Wno_suggest_attribute_format" = xyes; then :
+
+ ax_compiler_no_suggest_attribute_flags="-Wno-suggest-attribute=format"
+
+else
+
+ ax_compiler_no_suggest_attribute_flags=""
+
+fi
+
+
+ # Base flags
+
+
+
+
+for flag in -fno-strict-aliasing ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
+$as_echo_n "checking whether C compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains \$flag"; } >&5
+ (: WARN_CFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+ if test "$ax_enable_compile_warnings" != "no"; then :
+
+ if test "$ax_compiler_cxx" = "no" ; then
+ # C-only flags. Warn in C++
+
+
+
+
+for flag in -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes -Wdeclaration-after-statement -Wimplicit-function-declaration -Wold-style-definition -Wjump-misses-init ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
+$as_echo_n "checking whether C compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains \$flag"; } >&5
+ (: WARN_CFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+ fi
+
+ # "yes" flags
+
+
+
+
+for flag in -Wall -Wextra -Wundef -Wwrite-strings -Wpointer-arith -Wmissing-declarations -Wredundant-decls -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wcast-align -Wformat-nonliteral -Wformat-security -Wsign-compare -Wstrict-aliasing -Wshadow -Winline -Wpacked -Wmissing-format-attribute -Wmissing-noreturn -Winit-self -Wredundant-decls -Wmissing-include-dirs -Wunused-but-set-variable -Warray-bounds -Wreturn-type -Wswitch-enum -Wswitch-default -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -Wnull-dereference -Wdouble-promotion -Wunused-parameter -Wmissing-field-initializers ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
+$as_echo_n "checking whether C compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains \$flag"; } >&5
+ (: WARN_CFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+fi
+ if test "$ax_enable_compile_warnings" = "error"; then :
+
+ # "error" flags; -Werror has to be appended unconditionally because
+ # it's not possible to test for
+ #
+ # suggest-attribute=format is disabled because it gives too many false
+ # positives
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" -Werror "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains -Werror"; } >&5
+ (: WARN_CFLAGS already contains -Werror) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " -Werror"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=-Werror
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+
+
+
+
+
+for flag in $ax_compiler_no_suggest_attribute_flags ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
+$as_echo_n "checking whether C compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains \$flag"; } >&5
+ (: WARN_CFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+fi
+
+ # In the flags below, when disabling specific flags, always add *both*
+ # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example)
+ # we enable -Werror, disable a flag, and a build bot passes CFLAGS=-Wall,
+ # which effectively turns that flag back on again as an error.
+ for flag in $WARN_CFLAGS; do
+ case $flag in #(
+ -Wno-*=*) :
+ ;; #(
+ -Wno-*) :
+
+
+
+
+
+for flag in -Wno-error=$($as_echo $flag | $SED 's/^-Wno-//'); do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
+$as_echo_n "checking whether C compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CFLAGS+:} false; then :
+
+ case " $WARN_CFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS already contains \$flag"; } >&5
+ (: WARN_CFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CFLAGS=\"\$WARN_CFLAGS\""; } >&5
+ (: WARN_CFLAGS="$WARN_CFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+ ;; #(
+ *) :
+ ;;
+esac
+ done
+
+ 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
+
+
+ # Substitute the variables
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Variable names
+
+
+ # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+ # flags, otherwise they are always appended to the warn_ldflags variable,
+ # and Clang warns on them for every compilation unit.
+ # If this is passed to GCC, it will explode, so the flag must be enabled
+ # conditionally.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror=unknown-warning-option" >&5
+$as_echo_n "checking whether C compiler accepts -Werror=unknown-warning-option... " >&6; }
+if ${ax_cv_check_cflags___Werror_unknown_warning_option+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Werror=unknown-warning-option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ax_cv_check_cflags___Werror_unknown_warning_option=yes
+else
+ ax_cv_check_cflags___Werror_unknown_warning_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror_unknown_warning_option" >&5
+$as_echo "$ax_cv_check_cflags___Werror_unknown_warning_option" >&6; }
+if test "x$ax_cv_check_cflags___Werror_unknown_warning_option" = xyes; then :
+
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+
+else
+
+ ax_compiler_flags_test=""
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--as-needed" >&5
+$as_echo_n "checking whether the linker accepts -Wl,--as-needed... " >&6; }
+if ${ax_cv_check_ldflags___Wl___as_needed+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--as-needed"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl___as_needed=yes
+else
+ ax_cv_check_ldflags___Wl___as_needed=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___as_needed" >&5
+$as_echo "$ax_cv_check_ldflags___Wl___as_needed" >&6; }
+if test "x$ax_cv_check_ldflags___Wl___as_needed" = xyes; then :
+
+
+
+
+
+for flag in -Wl,--as-needed; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${AM_LDFLAGS+:} false; then :
+
+ case " $AM_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS already contains \$flag"; } >&5
+ (: AM_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append AM_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ AM_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+else
+ :
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,relro" >&5
+$as_echo_n "checking whether the linker accepts -Wl,-z,relro... " >&6; }
+if ${ax_cv_check_ldflags___Wl__z_relro+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,relro"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl__z_relro=yes
+else
+ ax_cv_check_ldflags___Wl__z_relro=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_relro" >&5
+$as_echo "$ax_cv_check_ldflags___Wl__z_relro" >&6; }
+if test "x$ax_cv_check_ldflags___Wl__z_relro" = xyes; then :
+
+
+
+
+
+for flag in -Wl,-z,relro; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${AM_LDFLAGS+:} false; then :
+
+ case " $AM_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS already contains \$flag"; } >&5
+ (: AM_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append AM_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ AM_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+else
+ :
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,now" >&5
+$as_echo_n "checking whether the linker accepts -Wl,-z,now... " >&6; }
+if ${ax_cv_check_ldflags___Wl__z_now+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,now"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl__z_now=yes
+else
+ ax_cv_check_ldflags___Wl__z_now=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_now" >&5
+$as_echo "$ax_cv_check_ldflags___Wl__z_now" >&6; }
+if test "x$ax_cv_check_ldflags___Wl__z_now" = xyes; then :
+
+
+
+
+
+for flag in -Wl,-z,now; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${AM_LDFLAGS+:} false; then :
+
+ case " $AM_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS already contains \$flag"; } >&5
+ (: AM_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append AM_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ AM_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+else
+ :
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,noexecstack" >&5
+$as_echo_n "checking whether the linker accepts -Wl,-z,noexecstack... " >&6; }
+if ${ax_cv_check_ldflags___Wl__z_noexecstack+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl__z_noexecstack=yes
+else
+ ax_cv_check_ldflags___Wl__z_noexecstack=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_noexecstack" >&5
+$as_echo "$ax_cv_check_ldflags___Wl__z_noexecstack" >&6; }
+if test "x$ax_cv_check_ldflags___Wl__z_noexecstack" = xyes; then :
+
+
+
+
+
+for flag in -Wl,-z,noexecstack; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${AM_LDFLAGS+:} false; then :
+
+ case " $AM_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS already contains \$flag"; } >&5
+ (: AM_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append AM_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ AM_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : AM_LDFLAGS=\"\$AM_LDFLAGS\""; } >&5
+ (: AM_LDFLAGS="$AM_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+else
+ :
+fi
+
+ # textonly, retpolineplt not yet
+
+ # macOS and cygwin linker do not have --as-needed
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--no-as-needed" >&5
+$as_echo_n "checking whether the linker accepts -Wl,--no-as-needed... " >&6; }
+if ${ax_cv_check_ldflags___Wl___no_as_needed+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--no-as-needed"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl___no_as_needed=yes
+else
+ ax_cv_check_ldflags___Wl___no_as_needed=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___no_as_needed" >&5
+$as_echo "$ax_cv_check_ldflags___Wl___no_as_needed" >&6; }
+if test "x$ax_cv_check_ldflags___Wl___no_as_needed" = xyes; then :
+
+ ax_compiler_flags_as_needed_option="-Wl,--no-as-needed"
+
+else
+
+ ax_compiler_flags_as_needed_option=""
+
+fi
+
+
+ # macOS linker speaks with a different accent
+ ax_compiler_flags_fatal_warnings_option=""
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--fatal-warnings" >&5
+$as_echo_n "checking whether the linker accepts -Wl,--fatal-warnings... " >&6; }
+if ${ax_cv_check_ldflags___Wl___fatal_warnings+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--fatal-warnings"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl___fatal_warnings=yes
+else
+ ax_cv_check_ldflags___Wl___fatal_warnings=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___fatal_warnings" >&5
+$as_echo "$ax_cv_check_ldflags___Wl___fatal_warnings" >&6; }
+if test "x$ax_cv_check_ldflags___Wl___fatal_warnings" = xyes; then :
+
+ ax_compiler_flags_fatal_warnings_option="-Wl,--fatal-warnings"
+
+else
+ :
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-fatal_warnings" >&5
+$as_echo_n "checking whether the linker accepts -Wl,-fatal_warnings... " >&6; }
+if ${ax_cv_check_ldflags___Wl__fatal_warnings+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-fatal_warnings"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_cv_check_ldflags___Wl__fatal_warnings=yes
+else
+ ax_cv_check_ldflags___Wl__fatal_warnings=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__fatal_warnings" >&5
+$as_echo "$ax_cv_check_ldflags___Wl__fatal_warnings" >&6; }
+if test "x$ax_cv_check_ldflags___Wl__fatal_warnings" = xyes; then :
+
+ ax_compiler_flags_fatal_warnings_option="-Wl,-fatal_warnings"
+
+else
+ :
+fi
+
+
+ # Base flags
+
+
+
+
+for flag in $ax_compiler_flags_as_needed_option ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_LDFLAGS+:} false; then :
+
+ case " $WARN_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS already contains \$flag"; } >&5
+ (: WARN_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+ if test "$ax_enable_compile_warnings" != "no"; then :
+
+ # "yes" flags
+
+
+
+
+for flag in ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_LDFLAGS+:} false; then :
+
+ case " $WARN_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS already contains \$flag"; } >&5
+ (: WARN_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+fi
+ if test "$ax_enable_compile_warnings" = "error"; then :
+
+ # "error" flags; -Werror has to be appended unconditionally because
+ # it's not possible to test for
+ #
+ # suggest-attribute=format is disabled because it gives too many false
+ # positives
+
+
+
+
+for flag in $ax_compiler_flags_fatal_warnings_option ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_ldflags_$ax_compiler_flags_test_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts $flag" >&5
+$as_echo_n "checking whether the linker accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $ax_compiler_flags_test $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_LDFLAGS+:} false; then :
+
+ case " $WARN_LDFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS already contains \$flag"; } >&5
+ (: WARN_LDFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_LDFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_LDFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_LDFLAGS=\"\$WARN_LDFLAGS\""; } >&5
+ (: WARN_LDFLAGS="$WARN_LDFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+
+fi
+
+ # Substitute the variables
+
+
+
+
+
+
+ # Variable names
+
+
+ # Base flags
+
+if ${WARN_SCANNERFLAGS+:} false; then :
+
+ case " $WARN_SCANNERFLAGS " in #(
+ *" "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS already contains "; } >&5
+ (: WARN_SCANNERFLAGS already contains ) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_SCANNERFLAGS " "
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_SCANNERFLAGS=
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+
+ if test "$ax_enable_compile_warnings" != "no"; then :
+
+ # "yes" flags
+
+if ${WARN_SCANNERFLAGS+:} false; then :
+
+ case " $WARN_SCANNERFLAGS " in #(
+ *" --warn-all "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS already contains --warn-all "; } >&5
+ (: WARN_SCANNERFLAGS already contains --warn-all ) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_SCANNERFLAGS " --warn-all "
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_SCANNERFLAGS= --warn-all
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+
+fi
+ if test "$ax_enable_compile_warnings" = "error"; then :
+
+ # "error" flags
+
+if ${WARN_SCANNERFLAGS+:} false; then :
+
+ case " $WARN_SCANNERFLAGS " in #(
+ *" --warn-error "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS already contains --warn-error "; } >&5
+ (: WARN_SCANNERFLAGS already contains --warn-error ) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_SCANNERFLAGS " --warn-error "
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_SCANNERFLAGS= --warn-error
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_SCANNERFLAGS=\"\$WARN_SCANNERFLAGS\""; } >&5
+ (: WARN_SCANNERFLAGS="$WARN_SCANNERFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+
+fi
+
+ # Substitute the variables
+
+
+
+ # unfortunately, AX_COMPILER_FLAGS does not provide a way to override
+ # the default -Wno-error=warning" flags. So we do this via sed below.
+ # Note: we *really* want to have this error out during CI testing!
+ # rgerhards, 2018-05-09
+ WARN_CFLAGS="$(echo "$WARN_CFLAGS" | sed s/-Wno-error=/-W/g)"
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: compiler is not GCC or close compatible, not using ax_compiler_flags because of this (CC=$CC)" >&5
+$as_echo "$as_me: WARNING: compiler is not GCC or close compatible, not using ax_compiler_flags because of this (CC=$CC)" >&2;}
+fi
+
+
+
+
+
+
+
+
+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
+
+
+if test "$ac_cv_env_CONF_FILE_PATH_set" = "set"; then
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_CONFFILE "${ac_cv_env_CONF_FILE_PATH_value}"
+_ACEOF
+
+fi
+
+
+if test "$ac_cv_env_PID_FILE_PATH_set" = "set"; then
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_PIDFILE "${ac_cv_env_PID_FILE_PATH_value}"
+_ACEOF
+
+fi
+
+
+# modules we require
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBESTR" >&5
+$as_echo_n "checking for LIBESTR... " >&6; }
+
+if test -n "$LIBESTR_CFLAGS"; then
+ pkg_cv_LIBESTR_CFLAGS="$LIBESTR_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libestr >= 0.1.9\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libestr >= 0.1.9") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBESTR_CFLAGS=`$PKG_CONFIG --cflags "libestr >= 0.1.9" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBESTR_LIBS"; then
+ pkg_cv_LIBESTR_LIBS="$LIBESTR_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libestr >= 0.1.9\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libestr >= 0.1.9") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBESTR_LIBS=`$PKG_CONFIG --libs "libestr >= 0.1.9" 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
+ LIBESTR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libestr >= 0.1.9" 2>&1`
+ else
+ LIBESTR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libestr >= 0.1.9" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBESTR_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libestr >= 0.1.9) were not met:
+
+$LIBESTR_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBESTR_CFLAGS
+and LIBESTR_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBESTR_CFLAGS
+and LIBESTR_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBESTR_CFLAGS=$pkg_cv_LIBESTR_CFLAGS
+ LIBESTR_LIBS=$pkg_cv_LIBESTR_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFASTJSON" >&5
+$as_echo_n "checking for LIBFASTJSON... " >&6; }
+
+if test -n "$LIBFASTJSON_CFLAGS"; then
+ pkg_cv_LIBFASTJSON_CFLAGS="$LIBFASTJSON_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libfastjson >= 0.99.8\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libfastjson >= 0.99.8") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBFASTJSON_CFLAGS=`$PKG_CONFIG --cflags "libfastjson >= 0.99.8" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBFASTJSON_LIBS"; then
+ pkg_cv_LIBFASTJSON_LIBS="$LIBFASTJSON_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libfastjson >= 0.99.8\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libfastjson >= 0.99.8") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBFASTJSON_LIBS=`$PKG_CONFIG --libs "libfastjson >= 0.99.8" 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
+ LIBFASTJSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libfastjson >= 0.99.8" 2>&1`
+ else
+ LIBFASTJSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libfastjson >= 0.99.8" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBFASTJSON_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libfastjson >= 0.99.8) were not met:
+
+$LIBFASTJSON_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBFASTJSON_CFLAGS
+and LIBFASTJSON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBFASTJSON_CFLAGS
+and LIBFASTJSON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBFASTJSON_CFLAGS=$pkg_cv_LIBFASTJSON_CFLAGS
+ LIBFASTJSON_LIBS=$pkg_cv_LIBFASTJSON_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define PLATFORM_ID "${host}"
+_ACEOF
+
+# we don't mind if we don't have the lsb_release utility. But if we have, it's
+# nice to have the extra information.
+
+cat >>confdefs.h <<_ACEOF
+#define PLATFORM_ID_LSB "`lsb_release -d`"
+_ACEOF
+
+
+echo HOST: ${host}
+case "${host}" in
+ *-*-linux*)
+
+$as_echo "#define OS_LINUX 1" >>confdefs.h
+
+ os_type="linux"
+ ;;
+ *-*-*darwin*|*-*-dragonfly*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
+
+$as_echo "#define OS_BSD 1" >>confdefs.h
+
+ os_type="bsd"
+ ;;
+ *-apple-*)
+
+$as_echo "#define OS_APPLE 1" >>confdefs.h
+
+ os_type="apple"
+ ;;
+ *-*-kfreebsd*)
+ # kernel is FreeBSD, but userspace is glibc - i.e. like linux
+ # do not DEFINE OS_BSD
+ os_type="bsd"
+ ;;
+ *-*-solaris*)
+ os_type="solaris"
+
+$as_echo "#define OS_SOLARIS 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+$as_echo "#define _XOPEN_SOURCE 600" >>confdefs.h
+
+ CPPFLAGS="-std=c99 $CPPFLAGS"
+ CFLAGS="-std=c99 $CFLAGS"
+ SOL_LIBS="-lsocket -lnsl"
+ # Solaris libuuid does not ship with a pkgconfig file so override the appropriate
+ # variables (but only if they have not been set by the user).
+ LIBUUID_CFLAGS=${LIBUUID_CFLAGS:= }
+ LIBUUID_LIBS=${LIBUUID_LIBS:=-luuid}
+
+ ;;
+ *-*-aix*)
+ os_type="aix"
+
+$as_echo "#define OS_AIX 1" >>confdefs.h
+
+ ;;
+esac
+ if test x$os_type == xapple; then
+ OS_APPLE_TRUE=
+ OS_APPLE_FALSE='#'
+else
+ OS_APPLE_TRUE='#'
+ OS_APPLE_FALSE=
+fi
+
+ if test x$os_type == xlinux; then
+ OS_LINUX_TRUE=
+ OS_LINUX_FALSE='#'
+else
+ OS_LINUX_TRUE='#'
+ OS_LINUX_FALSE=
+fi
+
+ if test x$os_type == xaix; then
+ OS_AIX_TRUE=
+ OS_AIX_FALSE='#'
+else
+ OS_AIX_TRUE='#'
+ OS_AIX_FALSE=
+fi
+
+
+
+
+
+
+
+
+ # Find any Python interpreter.
+ if test -z "$PYTHON"; then
+ for ac_prog in python python2 python3 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0
+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_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # 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_PYTHON="$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
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$PYTHON" && break
+done
+test -n "$PYTHON" || PYTHON=":"
+
+ fi
+ am_display_PYTHON=python
+
+
+ if test "$PYTHON" = :; then
+ :
+ else
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5
+$as_echo_n "checking for $am_display_PYTHON version... " >&6; }
+if ${am_cv_python_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5
+$as_echo "$am_cv_python_version" >&6; }
+ PYTHON_VERSION=$am_cv_python_version
+
+
+
+ PYTHON_PREFIX='${prefix}'
+
+ PYTHON_EXEC_PREFIX='${exec_prefix}'
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5
+$as_echo_n "checking for $am_display_PYTHON platform... " >&6; }
+if ${am_cv_python_platform+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5
+$as_echo "$am_cv_python_platform" >&6; }
+ PYTHON_PLATFORM=$am_cv_python_platform
+
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5
+$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; }
+if ${am_cv_python_pythondir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5
+$as_echo "$am_cv_python_pythondir" >&6; }
+ pythondir=$am_cv_python_pythondir
+
+
+
+ pkgpythondir=\${pythondir}/$PACKAGE
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5
+$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; }
+if ${am_cv_python_pyexecdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5
+$as_echo "$am_cv_python_pyexecdir" >&6; }
+ pyexecdir=$am_cv_python_pyexecdir
+
+
+
+ pkgpyexecdir=\${pyexecdir}/$PACKAGE
+
+
+
+ fi
+
+
+
+# Running from git source?
+in_git_src=no
+if test -d "$srcdir"/.git && ! test -f "$srcdir"/.tarball-version; then :
+ in_git_src=yes
+fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HOSTENV "$host"
+_ACEOF
+
+
+# Some Unix systems, like Gnu Hurd, don't define PATH_MAX
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PATH_MAX" >&5
+$as_echo_n "checking for PATH_MAX... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+int
+main ()
+{
+char checker[PATH_MAX];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; 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, mocking PATH_MAX = 4096" >&5
+$as_echo "no, mocking PATH_MAX = 4096" >&6; }
+
+$as_echo "#define PATH_MAX 4096" >>confdefs.h
+
+
+$as_echo "#define MAXPATHLEN 4096" >>confdefs.h
+ # we assume this does not exit
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Checks for libraries.
+save_LIBS=$LIBS
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} 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 clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; 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_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_clock_gettime+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+RT_LIBS=$LIBS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing mq_getattr" >&5
+$as_echo_n "checking for library containing mq_getattr... " >&6; }
+if ${ac_cv_search_mq_getattr+:} 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 mq_getattr ();
+int
+main ()
+{
+return mq_getattr ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; 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_mq_getattr=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_mq_getattr+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_mq_getattr+:} false; then :
+
+else
+ ac_cv_search_mq_getattr=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_mq_getattr" >&5
+$as_echo "$ac_cv_search_mq_getattr" >&6; }
+ac_res=$ac_cv_search_mq_getattr
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+RT_LIBS="$RT_LIBS $LIBS"
+LIBS=
+{ $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"
+
+fi
+
+DL_LIBS=$LIBS
+LIBS=$save_LIBS
+
+
+
+
+# Checks for header files.
+for ac_header in sys/types.h netinet/in.h arpa/nameser.h netdb.h resolv.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" "#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h> /* inet_ functions / structs */
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h> /* DNS HEADER struct */
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.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
+
+fi
+
+done
+
+
+{ $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_fn_c_check_header_compile "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "
+ #ifdef HAVE_ARPA_INET_H
+ # include <arpa/inet.h>
+ #endif
+
+
+"
+if test "x$ac_cv_header_arpa_inet_h" = xyes; then :
+
+fi
+
+
+for ac_header in libgen.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "
+ #ifdef HAVE_LIBGEN_H
+ # include <libgen.h>
+ #endif
+
+
+"
+if test "x$ac_cv_header_libgen_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGEN_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in malloc.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "
+ #ifdef HAVE_MALLOC_H
+ # include <malloc.h>
+ #endif
+
+
+"
+if test "x$ac_cv_header_malloc_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in fcntl.h locale.h netdb.h netinet/in.h paths.h stddef.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h sys/stat.h unistd.h utmp.h utmpx.h sys/epoll.h sys/prctl.h sys/select.h getopt.h linux/close_range.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
+
+
+# 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
+
+ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default"
+if test "x$ac_cv_type_mode_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define mode_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" "8" "ac_cv_c_uint8_t"
+case $ac_cv_c_uint8_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT8_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t $ac_cv_c_uint8_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
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if ${ac_cv_struct_tm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_struct_tm=time.h
+else
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
+$as_echo "$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5
+$as_echo_n "checking for working volatile... " >&6; }
+if ${ac_cv_c_volatile+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_volatile=yes
+else
+ ac_cv_c_volatile=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_volatile" >&5
+$as_echo "$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+$as_echo "#define volatile /**/" >>confdefs.h
+
+fi
+
+
+sa_includes="\
+$ac_includes_default
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+"
+ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "$sa_includes
+"
+if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+_ACEOF
+
+
+fi
+
+
+# Checks for library functions.
+for ac_header in unistd.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default"
+if test "x$ac_cv_header_unistd_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_UNISTD_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5
+$as_echo_n "checking for working chown... " >&6; }
+if ${ac_cv_func_chown_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_chown_works=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#include <fcntl.h>
+
+int
+main ()
+{
+ char *f = "conftest.chown";
+ struct stat before, after;
+
+ if (creat (f, 0600) < 0)
+ return 1;
+ if (stat (f, &before) < 0)
+ return 1;
+ if (chown (f, (uid_t) -1, (gid_t) -1) == -1)
+ return 1;
+ if (stat (f, &after) < 0)
+ return 1;
+ return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_chown_works=yes
+else
+ ac_cv_func_chown_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+rm -f conftest.chown
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5
+$as_echo "$ac_cv_func_chown_works" >&6; }
+if test $ac_cv_func_chown_works = yes; then
+
+$as_echo "#define HAVE_CHOWN 1" >>confdefs.h
+
+fi
+
+for ac_header in vfork.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+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
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=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: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=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: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+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_header in sys/select.h sys/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
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5
+$as_echo_n "checking types of arguments for select... " >&6; }
+if ${ac_cv_func_select_args+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+ for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+extern int select ($ac_arg1,
+ $ac_arg234, $ac_arg234, $ac_arg234,
+ $ac_arg5);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ done
+done
+# Provide a safe default value.
+: "${ac_cv_func_select_args=int,int *,struct timeval *}"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5
+$as_echo "$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG1 $1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG234 ($2)
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG5 ($3)
+_ACEOF
+
+rm -f conftest*
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
+$as_echo_n "checking return type of signal handlers... " >&6; }
+if ${ac_cv_type_signal+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_type_signal=int
+else
+ ac_cv_type_signal=void
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
+$as_echo "$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5
+$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; }
+if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ /* Linux will dereference the symlink and fail, as required by POSIX.
+ That is better in the sense that it means we will not
+ have to compile and use the lstat wrapper. */
+ return lstat ("conftest.sym/", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+else
+ # If the `ln -s' command failed, then we probably don't even
+ # have an lstat function.
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then
+ case " $LIBOBJS " in
+ *" lstat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5
+$as_echo_n "checking whether stat accepts an empty string... " >&6; }
+if ${ac_cv_func_stat_empty_string_bug+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ return stat ("", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_stat_empty_string_bug=no
+else
+ ac_cv_func_stat_empty_string_bug=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
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5
+$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+ case " $LIBOBJS " in
+ *" stat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+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
+
+for ac_func in vprintf
+do :
+ ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
+if test "x$ac_cv_func_vprintf" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VPRINTF 1
+_ACEOF
+
+ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes; then :
+
+$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
+
+fi
+
+fi
+done
+
+
+for ac_func in flock recvmmsg basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setsid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64 asprintf close_range
+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_func "$LINENO" "setns" "ac_cv_func_setns"
+if test "x$ac_cv_func_setns" = xyes; then :
+
+$as_echo "#define HAVE_SETNS 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "off64_t" "ac_cv_type_off64_t" "$ac_includes_default"
+if test "x$ac_cv_type_off64_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_OFF64_T 1
+_ACEOF
+
+
+fi
+
+
+for ac_header in sys/inotify.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_inotify_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_INOTIFY_H 1
+_ACEOF
+ rsyslog_sysinotify=yes
+fi
+
+done
+
+for ac_func in inotify_init
+do :
+ ac_fn_c_check_func "$LINENO" "inotify_init" "ac_cv_func_inotify_init"
+if test "x$ac_cv_func_inotify_init" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_INOTIFY_INIT 1
+_ACEOF
+ rsyslog_inotify_init=yes
+fi
+done
+
+ if test x$rsyslog_sysinotify = xyes -a x$rsyslog_inotify_init = xyes; then
+ ENABLE_INOTIFY_TRUE=
+ ENABLE_INOTIFY_FALSE='#'
+else
+ ENABLE_INOTIFY_TRUE='#'
+ ENABLE_INOTIFY_FALSE=
+fi
+
+
+# getifaddrs is in libc (mostly) or in libsocket (eg Solaris 11) or not defined (eg Solaris 10)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getifaddrs" >&5
+$as_echo_n "checking for library containing getifaddrs... " >&6; }
+if ${ac_cv_search_getifaddrs+:} 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 getifaddrs ();
+int
+main ()
+{
+return getifaddrs ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; 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_getifaddrs=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_getifaddrs+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_getifaddrs+:} false; then :
+
+else
+ ac_cv_search_getifaddrs=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getifaddrs" >&5
+$as_echo "$ac_cv_search_getifaddrs" >&6; }
+ac_res=$ac_cv_search_getifaddrs
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_GETIFADDRS 1" >>confdefs.h
+
+fi
+
+
+# the check below is probably ugly. If someone knows how to do it in a better way, please
+# let me know! -- rgerhards, 2010-10-06
+ac_fn_c_check_decl "$LINENO" "SCM_CREDENTIALS" "ac_cv_have_decl_SCM_CREDENTIALS" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_have_decl_SCM_CREDENTIALS" = xyes; then :
+
+$as_echo "#define HAVE_SCM_CREDENTIALS 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "SO_TIMESTAMP" "ac_cv_have_decl_SO_TIMESTAMP" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_have_decl_SO_TIMESTAMP" = xyes; then :
+
+$as_echo "#define HAVE_SO_TIMESTAMP 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "SYS_gettid" "ac_cv_have_decl_SYS_gettid" "#include <sys/syscall.h>
+"
+if test "x$ac_cv_have_decl_SYS_gettid" = xyes; then :
+
+$as_echo "#define HAVE_SYS_gettid 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct sysinfo" "uptime" "ac_cv_member_struct_sysinfo_uptime" "#include <sys/sysinfo.h>
+"
+if test "x$ac_cv_member_struct_sysinfo_uptime" = xyes; then :
+
+$as_echo "#define HAVE_SYSINFO_UPTIME 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "GLOB_NOMAGIC" "ac_cv_have_decl_GLOB_NOMAGIC" "#include <glob.h>
+"
+if test "x$ac_cv_have_decl_GLOB_NOMAGIC" = xyes; then :
+
+$as_echo "#define HAVE_GLOB_NOMAGIC 1" >>confdefs.h
+
+fi
+
+
+# Check for MAXHOSTNAMELEN
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAXHOSTNAMELEN" >&5
+$as_echo_n "checking for MAXHOSTNAMELEN... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/param.h>
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ return MAXHOSTNAMELEN;
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+ # note: we use 1024 here, which should be far more than needed by any system. If that's too low, we simply
+ # life with the need to change it. Most of the code doesn't need it anyways, but there are a few places
+ # where it actually is needed and it makes no sense to change them.
+
+$as_echo "#define MAXHOSTNAMELEN 1024" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no; defined as 64" >&5
+$as_echo "no; defined as 64" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# check if GNU's ld is used
+
+# Check for __builtin_expect()
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_expect()" >&5
+$as_echo_n "checking for __builtin_expect()... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return __builtin_expect(main != 0, 1)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_BUILTIN_EXPECT 1" >>confdefs.h
+
+ { $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
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+# check for availability of atomic operations
+# Note: this switch is primarily for the testbench, so that we can try
+# to build w/o automic operations on systems that actually support them.
+# Usually, atomic operations should be used when available as this
+# speeds up processig.
+# note that when automic operations are enabled but not available, they
+# will silently NOT be used!
+# Check whether --enable-atomic-operations was given.
+if test "${enable_atomic_operations+set}" = set; then :
+ enableval=$enable_atomic_operations; case "${enableval}" in
+ yes) enable_atomic_operations="yes" ;;
+ no) enable_atomic_operations="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-atomic-operations" "$LINENO" 5 ;;
+ esac
+else
+ enable_atomic_operations=yes
+
+fi
+
+if test "$enable_atomic_operations" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler provides atomic builtins" >&5
+$as_echo_n "checking whether the compiler provides atomic builtins... " >&6; }
+if ${ap_cv_atomic_builtins+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ap_cv_atomic_builtins=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+int main()
+{
+ unsigned long val = 1010, tmp, *mem = &val;
+ time_t tval = 1010, ttmp, *tmem = &tval;
+
+ if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+ return 1;
+ tmp = val;
+ if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+ return 1;
+ if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+ return 1;
+ tmp = 3030;
+ if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+ return 1;
+ if (__sync_lock_test_and_set(&val, 4040) != 3030)
+ return 1;
+ mem = &tmp;
+ if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+ return 1;
+
+ if (__sync_fetch_and_add(&tval, 1010) != 1010 || tval != 2020)
+ return 1;
+ ttmp = tval;
+ if (__sync_fetch_and_sub(tmem, 1010) != ttmp || tval != 1010)
+ return 1;
+ if (__sync_sub_and_fetch(&tval, 1010) != 0 || tval != 0)
+ return 1;
+ ttmp = 3030;
+ if (__sync_val_compare_and_swap(tmem, 0, ttmp) != 0 || tval != ttmp)
+ return 1;
+ if (__sync_lock_test_and_set(&tval, 4040) != 3030)
+ return 1;
+ tmem = &ttmp;
+ if (__sync_val_compare_and_swap(&tmem, &ttmp, &tval) != &ttmp)
+ return 1;
+
+ __sync_synchronize();
+
+ if (mem != &val)
+ return 1;
+
+ if (tmem != &tval)
+ return 1;
+
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ap_cv_atomic_builtins=yes
+else
+ ap_cv_atomic_builtins=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: $ap_cv_atomic_builtins" >&5
+$as_echo "$ap_cv_atomic_builtins" >&6; }
+
+if test "$ap_cv_atomic_builtins" = "yes"; then
+
+$as_echo "#define HAVE_ATOMIC_BUILTINS 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler provides atomic builtins for 64 bit data types" >&5
+$as_echo_n "checking whether the compiler provides atomic builtins for 64 bit data types... " >&6; }
+if ${ap_cv_atomic_builtins_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ap_cv_atomic_builtins_64=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int main()
+{
+ unsigned long long val = 1010, tmp, *mem = &val;
+
+ if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+ return 1;
+
+ tmp = val;
+
+ if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+ return 1;
+
+ if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+ return 1;
+
+ tmp = 3030;
+
+ if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+ return 1;
+
+ if (__sync_lock_test_and_set(&val, 4040) != 3030)
+ return 1;
+
+ mem = &tmp;
+
+ if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+ return 1;
+
+ __sync_synchronize();
+
+ if (mem != &val)
+ return 1;
+
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ap_cv_atomic_builtins_64=yes
+else
+ ap_cv_atomic_builtins_64=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: $ap_cv_atomic_builtins_64" >&5
+$as_echo "$ap_cv_atomic_builtins_64" >&6; }
+
+if test "$ap_cv_atomic_builtins_64" = "yes"; then
+
+$as_echo "#define HAVE_ATOMIC_BUILTINS64 1" >>confdefs.h
+
+fi
+
+
+fi
+
+# fall back to POSIX sems for atomic operations (cpu expensive)
+for ac_header in semaphore.h sys/syscall.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
+
+
+
+# Additional module directories
+
+# Check whether --with-moddirs was given.
+if test "${with_moddirs+set}" = set; then :
+ withval=$with_moddirs; _save_IFS=$IFS ; IFS=$PATH_SEPARATOR ; moddirs=""
+ for w in ${with_moddirs} ;
+ do
+ case $w in
+ "") continue ;; */) ;; *) w="${w}/" ;;
+ esac
+ for m in ${moddirs} ;
+ do
+ test "x$w" = "x${libdir}/${PACKAGE}/" || \
+ test "x$w" = "x$m" || test "x$w" = "x/" && \
+ continue 2
+ done
+ case $moddirs in
+ "") moddirs="$w" ;; *) moddirs="${moddirs}:${w}" ;;
+ esac
+ done ; IFS=$_save_IFS
+else
+ moddirs=""
+
+fi
+
+ if test x$moddirs != x; then
+ WITH_MODDIRS_TRUE=
+ WITH_MODDIRS_FALSE='#'
+else
+ WITH_MODDIRS_TRUE='#'
+ WITH_MODDIRS_FALSE=
+fi
+
+
+
+
+# Large file support
+# http://www.gnu.org/software/autoconf/manual/html_node/System-Services.html#index-AC_005fSYS_005fLARGEFILE-1028
+# 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
+
+case "${enable_largefile}" in
+ no) ;;
+ *) enable_largefile="yes" ;;
+esac
+
+# Regular expressions
+# Check whether --enable-regexp was given.
+if test "${enable_regexp+set}" = set; then :
+ enableval=$enable_regexp; case "${enableval}" in
+ yes) enable_regexp="yes" ;;
+ no) enable_regexp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-regexp" "$LINENO" 5 ;;
+ esac
+else
+ enable_regexp=yes
+
+fi
+
+ if test x$enable_regexp = xyes; then
+ ENABLE_REGEXP_TRUE=
+ ENABLE_REGEXP_FALSE='#'
+else
+ ENABLE_REGEXP_TRUE='#'
+ ENABLE_REGEXP_FALSE=
+fi
+
+if test "$enable_regexp" = "yes"; then
+
+$as_echo "#define FEATURE_REGEXP 1" >>confdefs.h
+
+fi
+
+# zlib support
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5
+$as_echo_n "checking for ZLIB... " >&6; }
+
+if test -n "$ZLIB_CFLAGS"; then
+ pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "zlib") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$ZLIB_LIBS"; then
+ pkg_cv_ZLIB_LIBS="$ZLIB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "zlib") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib" 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
+ ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib" 2>&1`
+ else
+ ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$ZLIB_PKG_ERRORS" >&5
+
+ found_zlib=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ found_zlib=no
+else
+ ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS
+ ZLIB_LIBS=$pkg_cv_ZLIB_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ found_zlib=yes
+fi
+if test "x$found_zlib" = "xno"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inflate" >&5
+$as_echo_n "checking for library containing inflate... " >&6; }
+if ${ac_cv_search_inflate+:} 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 inflate ();
+int
+main ()
+{
+return inflate ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' z; 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_inflate=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_inflate+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_inflate+:} false; then :
+
+else
+ ac_cv_search_inflate=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inflate" >&5
+$as_echo "$ac_cv_search_inflate" >&6; }
+ac_res=$ac_cv_search_inflate
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = xyes; then :
+ found_zlib=yes
+fi
+
+
+fi
+
+ if test "x$found_zlib" = "xno" ; then
+ as_fn_error $? "zlib library and headers not found" "$LINENO" 5
+ fi
+ ZLIB_LIBS="-lz"
+
+
+fi
+
+
+#hash implementations header checks
+# Check whether --enable-fmhash was given.
+if test "${enable_fmhash+set}" = set; then :
+ enableval=$enable_fmhash; case "${enableval}" in
+ yes) enable_fmhash="yes" ;;
+ no) enable_fmhash="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-fmhash" "$LINENO" 5 ;;
+ esac
+else
+ enable_fmhash=yes
+
+fi
+
+
+# Check whether --enable-libcap-ng was given.
+if test "${enable_libcap_ng+set}" = set; then :
+ enableval=$enable_libcap_ng; case "${enableval}" in
+ yes) enable_libcapng="yes" ;;
+ no) enable_libcapng="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable_libcapng" "$LINENO" 5 ;;
+ esac
+else
+ enable_libcapng=no
+
+fi
+
+
+if test "$enable_libcapng" = "yes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCAPNG_PRESENT" >&5
+$as_echo_n "checking for LIBCAPNG_PRESENT... " >&6; }
+
+if test -n "$LIBCAPNG_PRESENT_CFLAGS"; then
+ pkg_cv_LIBCAPNG_PRESENT_CFLAGS="$LIBCAPNG_PRESENT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcap-ng") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBCAPNG_PRESENT_CFLAGS=`$PKG_CONFIG --cflags "libcap-ng" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBCAPNG_PRESENT_LIBS"; then
+ pkg_cv_LIBCAPNG_PRESENT_LIBS="$LIBCAPNG_PRESENT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcap-ng") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBCAPNG_PRESENT_LIBS=`$PKG_CONFIG --libs "libcap-ng" 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
+ LIBCAPNG_PRESENT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcap-ng" 2>&1`
+ else
+ LIBCAPNG_PRESENT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcap-ng" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBCAPNG_PRESENT_PKG_ERRORS" >&5
+
+ as_fn_error $? "libcap-ng is not present." "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "libcap-ng is not present." "$LINENO" 5
+
+else
+ LIBCAPNG_PRESENT_CFLAGS=$pkg_cv_LIBCAPNG_PRESENT_CFLAGS
+ LIBCAPNG_PRESENT_LIBS=$pkg_cv_LIBCAPNG_PRESENT_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define ENABLE_LIBCAPNG_PRESENT 1" >>confdefs.h
+
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCAPNG" >&5
+$as_echo_n "checking for LIBCAPNG... " >&6; }
+
+if test -n "$LIBCAPNG_CFLAGS"; then
+ pkg_cv_LIBCAPNG_CFLAGS="$LIBCAPNG_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng >= 0.8.2\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcap-ng >= 0.8.2") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBCAPNG_CFLAGS=`$PKG_CONFIG --cflags "libcap-ng >= 0.8.2" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBCAPNG_LIBS"; then
+ pkg_cv_LIBCAPNG_LIBS="$LIBCAPNG_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng >= 0.8.2\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcap-ng >= 0.8.2") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBCAPNG_LIBS=`$PKG_CONFIG --libs "libcap-ng >= 0.8.2" 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
+ LIBCAPNG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcap-ng >= 0.8.2" 2>&1`
+ else
+ LIBCAPNG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcap-ng >= 0.8.2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBCAPNG_PKG_ERRORS" >&5
+
+ as_fn_error $? "libcap-ng is present, but outdated - need 0.8.2 or above." "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "libcap-ng is present, but outdated - need 0.8.2 or above." "$LINENO" 5
+
+else
+ LIBCAPNG_CFLAGS=$pkg_cv_LIBCAPNG_CFLAGS
+ LIBCAPNG_LIBS=$pkg_cv_LIBCAPNG_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define ENABLE_LIBCAPNG 1" >>confdefs.h
+
+fi
+ CFLAGS="$CFLAGS $LIBCAPNG_CFLAGS"
+ LIBS="$LIBS $LIBCAPNG_LIBS"
+fi
+
+
+# Check whether --enable-fmhash-xxhash was given.
+if test "${enable_fmhash_xxhash+set}" = set; then :
+ enableval=$enable_fmhash_xxhash; case "${enableval}" in
+ yes) enable_fmhash_xxhash="yes" ;;
+ no) enable_fmhash_xxhash="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-fmhash-xxhash" "$LINENO" 5 ;;
+ esac
+else
+ enable_fmhash_xxhash=no
+
+fi
+
+
+ if test "x$enable_fmhash" = "xyes" || test "x$enable_fmhash_xxhash" = "xyes"; then
+ ENABLE_FMHASH_TRUE=
+ ENABLE_FMHASH_FALSE='#'
+else
+ ENABLE_FMHASH_TRUE='#'
+ ENABLE_FMHASH_FALSE=
+fi
+
+
+ if test x$enable_fmhash_xxhash = xyes; then
+ ENABLE_FMHASH_XXHASH_TRUE=
+ ENABLE_FMHASH_XXHASH_FALSE='#'
+else
+ ENABLE_FMHASH_XXHASH_TRUE='#'
+ ENABLE_FMHASH_XXHASH_FALSE=
+fi
+
+if test "$enable_fmhash_xxhash" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XXH64 in -lxxhash" >&5
+$as_echo_n "checking for XXH64 in -lxxhash... " >&6; }
+if ${ac_cv_lib_xxhash_XXH64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxxhash $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 XXH64 ();
+int
+main ()
+{
+return XXH64 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_xxhash_XXH64=yes
+else
+ ac_cv_lib_xxhash_XXH64=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_xxhash_XXH64" >&5
+$as_echo "$ac_cv_lib_xxhash_XXH64" >&6; }
+if test "x$ac_cv_lib_xxhash_XXH64" = xyes; then :
+
+ ac_fn_c_check_header_mongrel "$LINENO" "xxhash.h" "ac_cv_header_xxhash_h" "$ac_includes_default"
+if test "x$ac_cv_header_xxhash_h" = xyes; then :
+
+
+$as_echo "#define USE_HASH_XXHASH 1" >>confdefs.h
+
+ HASH_XXHASH_LIBS="-lxxhash"
+
+else
+ as_fn_error $? "Unable to add XXHASH support for hash64." "$LINENO" 5
+fi
+
+
+
+fi
+
+fi
+
+
+#faup header checks
+# Check whether --enable-ffaup was given.
+if test "${enable_ffaup+set}" = set; then :
+ enableval=$enable_ffaup; case "${enableval}" in
+ yes) enable_ffaup="yes" ;;
+ no) enable_ffaup="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-ffaup" "$LINENO" 5 ;;
+ esac
+else
+ enable_ffaup=no
+
+fi
+
+
+ if test x$enable_ffaup = xyes; then
+ ENABLE_FFAUP_TRUE=
+ ENABLE_FFAUP_FALSE='#'
+else
+ ENABLE_FFAUP_TRUE='#'
+ ENABLE_FFAUP_FALSE=
+fi
+
+if test "$enable_ffaup" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for faup_init in -lfaupl" >&5
+$as_echo_n "checking for faup_init in -lfaupl... " >&6; }
+if ${ac_cv_lib_faupl_faup_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfaupl $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 faup_init ();
+int
+main ()
+{
+return faup_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_faupl_faup_init=yes
+else
+ ac_cv_lib_faupl_faup_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_faupl_faup_init" >&5
+$as_echo "$ac_cv_lib_faupl_faup_init" >&6; }
+if test "x$ac_cv_lib_faupl_faup_init" = xyes; then :
+
+ ac_fn_c_check_header_mongrel "$LINENO" "faup/faup.h" "ac_cv_header_faup_faup_h" "$ac_includes_default"
+if test "x$ac_cv_header_faup_faup_h" = xyes; then :
+
+ FAUP_LIBS="-lfaupl"
+
+else
+ as_fn_error $? "Unable to add faup support for URL parsing." "$LINENO" 5
+fi
+
+
+
+fi
+
+fi
+
+
+# rscript function unflatten
+# Check whether --enable-fmunflatten was given.
+if test "${enable_fmunflatten+set}" = set; then :
+ enableval=$enable_fmunflatten; case "${enableval}" in
+ yes) enable_fmunflatten="yes" ;;
+ no) enable_fmunflatten="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-fmunflatten" "$LINENO" 5 ;;
+ esac
+else
+ enable_fmunflatten=no
+
+fi
+
+ if test x$enable_fmunflatten = xyes; then
+ ENABLE_FMUNFLATTEN_TRUE=
+ ENABLE_FMUNFLATTEN_FALSE='#'
+else
+ ENABLE_FMUNFLATTEN_TRUE='#'
+ ENABLE_FMUNFLATTEN_FALSE=
+fi
+
+
+
+#gssapi
+# Check whether --enable-gssapi_krb5 was given.
+if test "${enable_gssapi_krb5+set}" = set; then :
+ enableval=$enable_gssapi_krb5; case "${enableval}" in
+ yes) enable_gssapi_krb5="yes" ;;
+ no) enable_gssapi_krb5="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-gssapi-krb5" "$LINENO" 5 ;;
+ esac
+else
+ enable_gssapi_krb5=no
+
+fi
+
+
+case "${os_type}" in
+solaris) GSSLIB=gss ;;
+*) GSSLIB=gssapi_krb5 ;;
+esac
+
+if test $enable_gssapi_krb5 = yes; then
+ as_ac_Lib=`$as_echo "ac_cv_lib_$GSSLIB''_gss_acquire_cred" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_acquire_cred in -l$GSSLIB" >&5
+$as_echo_n "checking for gss_acquire_cred in -l$GSSLIB... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$GSSLIB $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 gss_acquire_cred ();
+int
+main ()
+{
+return gss_acquire_cred ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_ac_Lib=yes"
+else
+ eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+
+ ac_fn_c_check_header_mongrel "$LINENO" "gssapi/gssapi.h" "ac_cv_header_gssapi_gssapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_gssapi_h" = xyes; then :
+
+
+$as_echo "#define USE_GSSAPI /**/" >>confdefs.h
+
+ GSS_LIBS="-l$GSSLIB"
+
+
+fi
+
+
+
+fi
+
+fi
+ if test x$enable_gssapi_krb5 = xyes; then
+ ENABLE_GSSAPI_TRUE=
+ ENABLE_GSSAPI_FALSE='#'
+else
+ ENABLE_GSSAPI_TRUE='#'
+ ENABLE_GSSAPI_FALSE=
+fi
+
+
+
+# shall the testbench try to run test that require root permissions?
+# This is uncommon. Test skip if run under non-root, but that pollutes the
+# testbench result. So the default is not to do that.
+# Check whether --enable-root_tests was given.
+if test "${enable_root_tests+set}" = set; then :
+ enableval=$enable_root_tests; case "${enableval}" in
+ yes) enable_root_tests="yes" ;;
+ no) enable_root_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-root-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_root_tests=no
+
+fi
+
+ if test x$enable_root_tests = xyes; then
+ ENABLE_ROOT_TESTS_TRUE=
+ ENABLE_ROOT_TESTS_FALSE='#'
+else
+ ENABLE_ROOT_TESTS_TRUE='#'
+ ENABLE_ROOT_TESTS_FALSE=
+fi
+
+
+# multithreading via pthreads
+if test "$os_type" != "solaris"
+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
+
+ { $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 -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 :
+
+ PTHREADS_LIBS="-lpthread"
+ if test "$unamestr" = "AIX"; then
+ case "${CC}" in
+ *xlc*|*xlC*) PTHREADS_CFLAGS="-qthreaded" ;;
+ *) PTHREADS_CFLAGS="-lpthreads" ;;
+ esac
+ else
+ PTHREADS_CFLAGS="-pthread"
+ fi
+
+
+
+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 $? "pthread is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+
+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 $? "pthread is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+done
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_rwlockattr_setkind_np in -lpthread" >&5
+$as_echo_n "checking for pthread_rwlockattr_setkind_np in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_rwlockattr_setkind_np+:} 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_rwlockattr_setkind_np ();
+int
+main ()
+{
+return pthread_rwlockattr_setkind_np ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_rwlockattr_setkind_np=yes
+else
+ ac_cv_lib_pthread_pthread_rwlockattr_setkind_np=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_rwlockattr_setkind_np" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_rwlockattr_setkind_np" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_rwlockattr_setkind_np" = xyes; then :
+
+$as_echo "#define HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np in -lpthread" >&5
+$as_echo_n "checking for pthread_setname_np in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_setname_np+:} 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_setname_np ();
+int
+main ()
+{
+return pthread_setname_np ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_setname_np=yes
+else
+ ac_cv_lib_pthread_pthread_setname_np=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_setname_np" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_setname_np" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_setname_np" = xyes; then :
+
+$as_echo "#define HAVE_PTHREAD_SETNAME_NP 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_setschedparam" >&5
+$as_echo_n "checking for library containing pthread_setschedparam... " >&6; }
+if ${ac_cv_search_pthread_setschedparam+:} 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 pthread_setschedparam ();
+int
+main ()
+{
+return pthread_setschedparam ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; 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_pthread_setschedparam=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_pthread_setschedparam+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_pthread_setschedparam+:} false; then :
+
+else
+ ac_cv_search_pthread_setschedparam=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_setschedparam" >&5
+$as_echo "$ac_cv_search_pthread_setschedparam" >&6; }
+ac_res=$ac_cv_search_pthread_setschedparam
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+ rsyslog_have_pthread_setschedparam=yes
+
+$as_echo "#define HAVE_PTHREAD_SETSCHEDPARAM 1" >>confdefs.h
+
+
+else
+
+ rsyslog_have_pthread_setschedparam=no
+
+
+fi
+
+for ac_header in sched.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default"
+if test "x$ac_cv_header_sched_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SCHED_H 1
+_ACEOF
+
+ rsyslog_have_sched_h=yes
+
+else
+
+ rsyslog_have_sched_h=no
+
+
+fi
+
+done
+
+if test "$rsyslog_have_pthread_setschedparam" = "yes" -a "$rsyslog_have_sched_h" = "yes"; then
+ save_LIBS=$LIBS
+ LIBS=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sched_get_priority_max" >&5
+$as_echo_n "checking for library containing sched_get_priority_max... " >&6; }
+if ${ac_cv_search_sched_get_priority_max+:} 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 sched_get_priority_max ();
+int
+main ()
+{
+return sched_get_priority_max ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; 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_sched_get_priority_max=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_sched_get_priority_max+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_sched_get_priority_max+:} false; then :
+
+else
+ ac_cv_search_sched_get_priority_max=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sched_get_priority_max" >&5
+$as_echo "$ac_cv_search_sched_get_priority_max" >&6; }
+ac_res=$ac_cv_search_sched_get_priority_max
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ if test "x$ac_cv_search" != "xno"; then
+ for ac_func in sched_get_priority_max
+do :
+ ac_fn_c_check_func "$LINENO" "sched_get_priority_max" "ac_cv_func_sched_get_priority_max"
+if test "x$ac_cv_func_sched_get_priority_max" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SCHED_GET_PRIORITY_MAX 1
+_ACEOF
+
+fi
+done
+
+ fi
+ IMUDP_LIBS=$LIBS
+
+ LIBS=$save_LIBS
+fi
+
+if test "$unamestr" = "AIX"; then
+enable_klog="no"
+else
+# klog
+# Check whether --enable-klog was given.
+if test "${enable_klog+set}" = set; then :
+ enableval=$enable_klog; case "${enableval}" in
+ yes) enable_klog="yes" ;;
+ no) enable_klog="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-klog" "$LINENO" 5 ;;
+ esac
+else
+ enable_klog="yes"
+
+fi
+
+fi
+ if test x$enable_klog = xyes; then
+ ENABLE_IMKLOG_TRUE=
+ ENABLE_IMKLOG_FALSE='#'
+else
+ ENABLE_IMKLOG_TRUE='#'
+ ENABLE_IMKLOG_FALSE=
+fi
+
+ if test x$os_type = xbsd; then
+ ENABLE_IMKLOG_BSD_TRUE=
+ ENABLE_IMKLOG_BSD_FALSE='#'
+else
+ ENABLE_IMKLOG_BSD_TRUE='#'
+ ENABLE_IMKLOG_BSD_FALSE=
+fi
+
+ if test x$os_type = xlinux; then
+ ENABLE_IMKLOG_LINUX_TRUE=
+ ENABLE_IMKLOG_LINUX_FALSE='#'
+else
+ ENABLE_IMKLOG_LINUX_TRUE='#'
+ ENABLE_IMKLOG_LINUX_FALSE=
+fi
+
+ if test x$os_type = xsolaris; then
+ ENABLE_IMKLOG_SOLARIS_TRUE=
+ ENABLE_IMKLOG_SOLARIS_FALSE='#'
+else
+ ENABLE_IMKLOG_SOLARIS_TRUE='#'
+ ENABLE_IMKLOG_SOLARIS_FALSE=
+fi
+
+
+# kmsg
+# Check whether --enable-kmsg was given.
+if test "${enable_kmsg+set}" = set; then :
+ enableval=$enable_kmsg; case "${enableval}" in
+ yes) enable_kmsg="yes" ;;
+ no) enable_kmsg="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-kmsg" "$LINENO" 5 ;;
+ esac
+else
+ enable_kmsg="no"
+
+fi
+
+ if test x$enable_kmsg = xyes; then
+ ENABLE_IMKMSG_TRUE=
+ ENABLE_IMKMSG_FALSE='#'
+else
+ ENABLE_IMKMSG_TRUE='#'
+ ENABLE_IMKMSG_FALSE=
+fi
+
+
+# imjournal
+# Check whether --enable-imjournal was given.
+if test "${enable_imjournal+set}" = set; then :
+ enableval=$enable_imjournal; case "${enableval}" in
+ yes) enable_imjournal="yes" ;;
+ no) enable_imjournal="no" ;;
+ optional) enable_imjournal="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imjournal" "$LINENO" 5 ;;
+ esac
+else
+ enable_imjournal="no"
+
+fi
+
+imjournal_use_dummy="no"
+if test "x$enable_imjournal" = "xyes" -o "x$enable_imjournal" = "xoptional"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 234 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 234 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd >= 234 " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 234 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 234 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd >= 234 " 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd >= 234 " 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd >= 234 " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd >= 209 " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd >= 209 " 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd >= 209 " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd >= 209 " 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test x$enable_imjournal = xyes; 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 $? "imjournal support libraries are missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ imjournal_use_dummy="yes"
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define NEW_JOURNAL 1" >>confdefs.h
+
+fi
+fi
+ if test x$imjournal_use_dummy = xyes; then
+ IMJOURNAL_USE_DUMMY_TRUE=
+ IMJOURNAL_USE_DUMMY_FALSE='#'
+else
+ IMJOURNAL_USE_DUMMY_TRUE='#'
+ IMJOURNAL_USE_DUMMY_FALSE=
+fi
+
+ if test x$enable_imjournal = xyes -o x$enable_imjournal = xoptional; then
+ ENABLE_IMJOURNAL_TRUE=
+ ENABLE_IMJOURNAL_FALSE='#'
+else
+ ENABLE_IMJOURNAL_TRUE='#'
+ ENABLE_IMJOURNAL_FALSE=
+fi
+
+
+# use libsystemd
+# Check whether --enable-libsystemd was given.
+if test "${enable_libsystemd+set}" = set; then :
+ enableval=$enable_libsystemd; case "${enableval}" in
+ yes) enable_libsystemd="yes" ;;
+ no) enable_libsystemd="no" ;;
+ auto) enable_libsystemd="auto" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-libsystemd" "$LINENO" 5 ;;
+ esac
+else
+ enable_libsystemd="auto"
+
+fi
+
+if test "$enable_libsystemd" = "yes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD" >&5
+$as_echo_n "checking for LIBSYSTEMD... " >&6; }
+
+if test -n "$LIBSYSTEMD_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_CFLAGS="$LIBSYSTEMD_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "libsystemd" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_LIBS"; then
+ pkg_cv_LIBSYSTEMD_LIBS="$LIBSYSTEMD_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_LIBS=`$PKG_CONFIG --libs "libsystemd" 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
+ LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1`
+ else
+ LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libsystemd) were not met:
+
+$LIBSYSTEMD_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_CFLAGS
+and LIBSYSTEMD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_CFLAGS
+and LIBSYSTEMD_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS
+ LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LIBSYSTEMD 1" >>confdefs.h
+
+
+fi
+fi
+if test "$enable_libsystemd" = "auto"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD" >&5
+$as_echo_n "checking for LIBSYSTEMD... " >&6; }
+
+if test -n "$LIBSYSTEMD_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_CFLAGS="$LIBSYSTEMD_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "libsystemd" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_LIBS"; then
+ pkg_cv_LIBSYSTEMD_LIBS="$LIBSYSTEMD_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_LIBS=`$PKG_CONFIG --libs "libsystemd" 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
+ LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1`
+ else
+ LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsystemd not present - disabling systemd support" >&5
+$as_echo "$as_me: WARNING: libsystemd not present - disabling systemd support" >&2;}
+ enable_libsystemd="no"
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsystemd not present - disabling systemd support" >&5
+$as_echo "$as_me: WARNING: libsystemd not present - disabling systemd support" >&2;}
+ enable_libsystemd="no"
+
+
+else
+ LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS
+ LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LIBSYSTEMD 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --enable-libsystemd in auto mode" >&5
+$as_echo "$as_me: --enable-libsystemd in auto mode" >&6;}
+ enable_libsystemd="yes"
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --enable-libsystemd in auto mode, enable-libsystemd is set to ${enable_libsystemd}" >&5
+$as_echo "$as_me: --enable-libsystemd in auto mode, enable-libsystemd is set to ${enable_libsystemd}" >&6;}
+fi
+
+# inet
+# Check whether --enable-inet was given.
+if test "${enable_inet+set}" = set; then :
+ enableval=$enable_inet; case "${enableval}" in
+ yes) enable_inet="yes" ;;
+ no) enable_inet="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-inet" "$LINENO" 5 ;;
+ esac
+else
+ enable_inet="yes"
+
+fi
+
+ if test x$enable_inet = xyes; then
+ ENABLE_INET_TRUE=
+ ENABLE_INET_FALSE='#'
+else
+ ENABLE_INET_TRUE='#'
+ ENABLE_INET_FALSE=
+fi
+
+if test "$enable_inet" = "yes"; then
+
+$as_echo "#define SYSLOG_INET 1" >>confdefs.h
+
+fi
+
+# jemalloc
+# Check whether --enable-jemalloc was given.
+if test "${enable_jemalloc+set}" = set; then :
+ enableval=$enable_jemalloc; case "${enableval}" in
+ yes) enable_jemalloc="yes" ;;
+ no) enable_jemalloc="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-jemalloc" "$LINENO" 5 ;;
+ esac
+else
+ enable_jemalloc="no"
+
+fi
+
+ if test x$enable_jemalloc = xyes; then
+ ENABLE_JEMALLOC_TRUE=
+ ENABLE_JEMALLOC_FALSE='#'
+else
+ ENABLE_JEMALLOC_TRUE='#'
+ ENABLE_JEMALLOC_FALSE=
+fi
+
+if test "$enable_jemalloc" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for malloc_stats_print in -ljemalloc" >&5
+$as_echo_n "checking for malloc_stats_print in -ljemalloc... " >&6; }
+if ${ac_cv_lib_jemalloc_malloc_stats_print+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljemalloc
+ $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 malloc_stats_print ();
+int
+main ()
+{
+return malloc_stats_print ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_jemalloc_malloc_stats_print=yes
+else
+ ac_cv_lib_jemalloc_malloc_stats_print=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_jemalloc_malloc_stats_print" >&5
+$as_echo "$ac_cv_lib_jemalloc_malloc_stats_print" >&6; }
+if test "x$ac_cv_lib_jemalloc_malloc_stats_print" = xyes; then :
+ RT_LIBS="$RT_LIBS -ljemalloc"
+
+$as_echo "#define HAVE_JEMALLOC 1" >>confdefs.h
+
+
+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 $? "jemalloc library is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+fi
+
+
+# support for unlimited select() syscall
+# Check whether --enable-unlimited_select was given.
+if test "${enable_unlimited_select+set}" = set; then :
+ enableval=$enable_unlimited_select; case "${enableval}" in
+ yes) enable_unlimited_select="yes" ;;
+ no) enable_unlimited_select="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-unlimited-select" "$LINENO" 5 ;;
+ esac
+else
+ enable_unlimited_select="no"
+
+fi
+
+if test "$enable_unlimited_select" = "yes"; then
+
+$as_echo "#define USE_UNLIMITED_SELECT 1" >>confdefs.h
+
+fi
+
+
+# debug
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+ enableval=$enable_debug; case "${enableval}" in
+ yes) enable_debug="yes" ;;
+ no) enable_debug="no" ;;
+ auto) enable_debug="auto" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;;
+ esac
+else
+ enable_debug="auto"
+
+fi
+
+if test "$enable_debug" = "auto"; then
+ if test "x$in_git_src" = "xyes"; then
+ enable_debug="yes"
+ else
+ enable_debug="no"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: enable-debug in auto mode, enable-debug is set to ${enable_debug}" >&5
+$as_echo "$as_me: enable-debug in auto mode, enable-debug is set to ${enable_debug}" >&6;}
+fi
+if test "$enable_debug" = "yes"; then
+
+$as_echo "#define DEBUG 1" >>confdefs.h
+
+fi
+if test "$enable_debug" = "no"; then
+
+$as_echo "#define NDEBUG 1" >>confdefs.h
+
+fi
+
+
+# debug-symbols
+# Check whether --enable-debug_symbols was given.
+if test "${enable_debug_symbols+set}" = set; then :
+ enableval=$enable_debug_symbols; case "${enableval}" in
+ yes) enable_debug_symbols="yes" ;;
+ no) enable_debug_symbols="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --disable-debug-symbols" "$LINENO" 5 ;;
+ esac
+else
+ enable_debug_symbols="yes"
+
+fi
+
+
+
+# total debugless: highest performance, but no way at all to enable debug
+# logging
+# Check whether --enable-debugless was given.
+if test "${enable_debugless+set}" = set; then :
+ enableval=$enable_debugless; case "${enableval}" in
+ yes) enable_debugless="yes" ;;
+ no) enable_debugless="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-debugless" "$LINENO" 5 ;;
+ esac
+else
+ enable_debugless="no"
+
+fi
+
+if test "$enable_debugless" = "yes"; then
+
+$as_echo "#define DEBUGLESS 1" >>confdefs.h
+
+fi
+
+
+# valgrind
+# Check whether --enable-valgrind was given.
+if test "${enable_valgrind+set}" = set; then :
+ enableval=$enable_valgrind; case "${enableval}" in
+ yes) enable_valgrind="yes" ;;
+ no) enable_valgrind="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-valgrind" "$LINENO" 5 ;;
+ esac
+else
+ enable_valgrind="no"
+
+fi
+
+if test "$enable_valgrind" = "yes"; then
+
+$as_echo "#define VALGRIND 1" >>confdefs.h
+
+fi
+
+
+# compile diagnostic tools (small helpers usually not needed)
+# Check whether --enable-diagtools was given.
+if test "${enable_diagtools+set}" = set; then :
+ enableval=$enable_diagtools; case "${enableval}" in
+ yes) enable_diagtools="yes" ;;
+ no) enable_diagtools="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-diagtools" "$LINENO" 5 ;;
+ esac
+else
+ enable_diagtools=no
+
+fi
+
+ if test x$enable_diagtools = xyes; then
+ ENABLE_DIAGTOOLS_TRUE=
+ ENABLE_DIAGTOOLS_FALSE='#'
+else
+ ENABLE_DIAGTOOLS_TRUE='#'
+ ENABLE_DIAGTOOLS_FALSE=
+fi
+
+
+
+# compile end-user tools
+# Check whether --enable-usertools was given.
+if test "${enable_usertools+set}" = set; then :
+ enableval=$enable_usertools; case "${enableval}" in
+ yes) enable_usertools="yes" ;;
+ no) enable_usertools="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-usertools" "$LINENO" 5 ;;
+ esac
+else
+ enable_usertools=no
+
+fi
+
+ if test x$enable_usertools = xyes; then
+ ENABLE_USERTOOLS_TRUE=
+ ENABLE_USERTOOLS_FALSE='#'
+else
+ ENABLE_USERTOOLS_TRUE='#'
+ ENABLE_USERTOOLS_FALSE=
+fi
+
+
+
+# MySQL support
+# Check whether --enable-mysql was given.
+if test "${enable_mysql+set}" = set; then :
+ enableval=$enable_mysql; case "${enableval}" in
+ yes) enable_mysql="yes" ;;
+ no) enable_mysql="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mysql" "$LINENO" 5 ;;
+ esac
+else
+ enable_mysql=no
+
+fi
+
+if test "x$enable_mysql" = "xyes"; then :
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MYSQL" >&5
+$as_echo_n "checking for MYSQL... " >&6; }
+
+if test -n "$MYSQL_CFLAGS"; then
+ pkg_cv_MYSQL_CFLAGS="$MYSQL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mysqlclient\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "mysqlclient") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_MYSQL_CFLAGS=`$PKG_CONFIG --cflags "mysqlclient" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$MYSQL_LIBS"; then
+ pkg_cv_MYSQL_LIBS="$MYSQL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mysqlclient\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "mysqlclient") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_MYSQL_LIBS=`$PKG_CONFIG --libs "mysqlclient" 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
+ MYSQL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "mysqlclient" 2>&1`
+ else
+ MYSQL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "mysqlclient" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$MYSQL_PKG_ERRORS" >&5
+
+
+ # Extract the first word of "mysql_config", so it can be a program name with args.
+set dummy mysql_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_prog_MYSQL_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MYSQL_CONFIG"; then
+ ac_cv_prog_MYSQL_CONFIG="$MYSQL_CONFIG" # 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_MYSQL_CONFIG="mysql_config"
+ $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_MYSQL_CONFIG" && ac_cv_prog_MYSQL_CONFIG="no"
+fi
+fi
+MYSQL_CONFIG=$ac_cv_prog_MYSQL_CONFIG
+if test -n "$MYSQL_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5
+$as_echo "$MYSQL_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${MYSQL_CONFIG}" = "xno"; 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 $? "mysql_config not found - usually a package named mysql-dev, libmysql-dev or similar, is missing - install it to fix this issue
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags`
+ MYSQL_LIBS=`$MYSQL_CONFIG --libs`
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ # Extract the first word of "mysql_config", so it can be a program name with args.
+set dummy mysql_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_prog_MYSQL_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MYSQL_CONFIG"; then
+ ac_cv_prog_MYSQL_CONFIG="$MYSQL_CONFIG" # 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_MYSQL_CONFIG="mysql_config"
+ $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_MYSQL_CONFIG" && ac_cv_prog_MYSQL_CONFIG="no"
+fi
+fi
+MYSQL_CONFIG=$ac_cv_prog_MYSQL_CONFIG
+if test -n "$MYSQL_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5
+$as_echo "$MYSQL_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${MYSQL_CONFIG}" = "xno"; 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 $? "mysql_config not found - usually a package named mysql-dev, libmysql-dev or similar, is missing - install it to fix this issue
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags`
+ MYSQL_LIBS=`$MYSQL_CONFIG --libs`
+
+else
+ MYSQL_CFLAGS=$pkg_cv_MYSQL_CFLAGS
+ MYSQL_LIBS=$pkg_cv_MYSQL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have mysql_library_init" >&5
+$as_echo_n "checking if we have mysql_library_init... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $MYSQL_CFLAGS"
+ save_LIBS="$LIBS"
+ { $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 $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 :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBMYSQLCLIENT 1
+_ACEOF
+
+ LIBS="-lmysqlclient $LIBS"
+
+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 $? "MySQL library is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ LIBS="$LIBS $MYSQL_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <mysql.h>
+ #include <stdio.h>
+int
+main ()
+{
+mysql_library_init(0, NULL, NULL)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ have_mysql_library_init=yes
+else
+ have_mysql_library_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+
+fi
+ if test x$enable_mysql = xyes; then
+ ENABLE_MYSQL_TRUE=
+ ENABLE_MYSQL_FALSE='#'
+else
+ ENABLE_MYSQL_TRUE='#'
+ ENABLE_MYSQL_FALSE=
+fi
+
+if test "$have_mysql_library_init" = "yes"; then
+
+$as_echo "#define HAVE_MYSQL_LIBRARY_INIT 1" >>confdefs.h
+
+fi
+
+
+
+
+# PostgreSQL support
+# Check whether --enable-pgsql was given.
+if test "${enable_pgsql+set}" = set; then :
+ enableval=$enable_pgsql; case "${enableval}" in
+ yes) enable_pgsql="yes" ;;
+ no) enable_pgsql="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pgsql" "$LINENO" 5 ;;
+ esac
+else
+ enable_pgsql=no
+
+fi
+
+if test "x$enable_pgsql" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PGSQL" >&5
+$as_echo_n "checking for PGSQL... " >&6; }
+
+if test -n "$PGSQL_CFLAGS"; then
+ pkg_cv_PGSQL_CFLAGS="$PGSQL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libpq") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PGSQL_CFLAGS=`$PKG_CONFIG --cflags "libpq" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$PGSQL_LIBS"; then
+ pkg_cv_PGSQL_LIBS="$PGSQL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libpq") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PGSQL_LIBS=`$PKG_CONFIG --libs "libpq" 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
+ PGSQL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpq" 2>&1`
+ else
+ PGSQL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpq" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$PGSQL_PKG_ERRORS" >&5
+
+
+ # Extract the first word of "pg_config", so it can be a program name with args.
+set dummy pg_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_prog_PG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PG_CONFIG"; then
+ ac_cv_prog_PG_CONFIG="$PG_CONFIG" # 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_PG_CONFIG="pg_config"
+ $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_PG_CONFIG" && ac_cv_prog_PG_CONFIG="no"
+fi
+fi
+PG_CONFIG=$ac_cv_prog_PG_CONFIG
+if test -n "$PG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5
+$as_echo "$PG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${PG_CONFIG}" = "xno"; 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 $? "pg_config not found
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { $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 -L`$PG_CONFIG --libdir`
+ $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 :
+ PGSQL_CFLAGS="-I`$PG_CONFIG --includedir`"
+ PGSQL_LIBS="-L`$PG_CONFIG --libdir` -lpq"
+
+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 $? "PgSQL library is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ # Extract the first word of "pg_config", so it can be a program name with args.
+set dummy pg_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_prog_PG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PG_CONFIG"; then
+ ac_cv_prog_PG_CONFIG="$PG_CONFIG" # 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_PG_CONFIG="pg_config"
+ $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_PG_CONFIG" && ac_cv_prog_PG_CONFIG="no"
+fi
+fi
+PG_CONFIG=$ac_cv_prog_PG_CONFIG
+if test -n "$PG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5
+$as_echo "$PG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${PG_CONFIG}" = "xno"; 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 $? "pg_config not found
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { $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 -L`$PG_CONFIG --libdir`
+ $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 :
+ PGSQL_CFLAGS="-I`$PG_CONFIG --includedir`"
+ PGSQL_LIBS="-L`$PG_CONFIG --libdir` -lpq"
+
+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 $? "PgSQL library is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+
+else
+ PGSQL_CFLAGS=$pkg_cv_PGSQL_CFLAGS
+ PGSQL_LIBS=$pkg_cv_PGSQL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PGsslInUse in -lpq" >&5
+$as_echo_n "checking for PGsslInUse in -lpq... " >&6; }
+if ${ac_cv_lib_pq_PGsslInUse+:} 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 PGsslInUse ();
+int
+main ()
+{
+return PGsslInUse ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pq_PGsslInUse=yes
+else
+ ac_cv_lib_pq_PGsslInUse=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_PGsslInUse" >&5
+$as_echo "$ac_cv_lib_pq_PGsslInUse" >&6; }
+if test "x$ac_cv_lib_pq_PGsslInUse" = xyes; then :
+
+$as_echo "#define HAVE_PGSSLINUSE 1" >>confdefs.h
+
+
+fi
+
+fi
+ if test x$enable_pgsql = xyes; then
+ ENABLE_PGSQL_TRUE=
+ ENABLE_PGSQL_FALSE='#'
+else
+ ENABLE_PGSQL_TRUE='#'
+ ENABLE_PGSQL_FALSE=
+fi
+
+
+
+
+# libdbi support
+# Check whether --enable-libdbi was given.
+if test "${enable_libdbi+set}" = set; then :
+ enableval=$enable_libdbi; case "${enableval}" in
+ yes) enable_libdbi="yes" ;;
+ no) enable_libdbi="no" ;;
+ optional) enable_libdbi="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-libdbi" "$LINENO" 5 ;;
+ esac
+else
+ enable_libdbi=no
+
+fi
+
+libdbi_use_dummy="no"
+if test "x$enable_libdbi" = "xyes" -o x$enable_libdbi = xoptional; then
+ 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
+
+else
+
+ if test x$enable_libdbi = xyes; 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 $? "libdbi is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ libdbi_use_dummy="yes"
+
+
+fi
+
+done
+
+ { $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 :
+ LIBDBI_CFLAGS=""
+ LIBDBI_LIBS="-ldbi"
+
+else
+
+ if test x$enable_libdbi = xyes; 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 $? "libdbi is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+ libdbi_use_dummy="yes"
+
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbi_initialize_r in -ldbi" >&5
+$as_echo_n "checking for dbi_initialize_r in -ldbi... " >&6; }
+if ${ac_cv_lib_dbi_dbi_initialize_r+:} 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_r ();
+int
+main ()
+{
+return dbi_initialize_r ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dbi_dbi_initialize_r=yes
+else
+ ac_cv_lib_dbi_dbi_initialize_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_dbi_dbi_initialize_r" >&5
+$as_echo "$ac_cv_lib_dbi_dbi_initialize_r" >&6; }
+if test "x$ac_cv_lib_dbi_dbi_initialize_r" = xyes; then :
+
+$as_echo "#define HAVE_DBI_R 1" >>confdefs.h
+
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbi_conn_transaction_begin in -ldbi" >&5
+$as_echo_n "checking for dbi_conn_transaction_begin in -ldbi... " >&6; }
+if ${ac_cv_lib_dbi_dbi_conn_transaction_begin+:} 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_conn_transaction_begin ();
+int
+main ()
+{
+return dbi_conn_transaction_begin ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dbi_dbi_conn_transaction_begin=yes
+else
+ ac_cv_lib_dbi_dbi_conn_transaction_begin=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_conn_transaction_begin" >&5
+$as_echo "$ac_cv_lib_dbi_dbi_conn_transaction_begin" >&6; }
+if test "x$ac_cv_lib_dbi_dbi_conn_transaction_begin" = xyes; then :
+
+$as_echo "#define HAVE_DBI_TXSUPP 1" >>confdefs.h
+
+
+fi
+
+fi
+ if test x$libdbi_use_dummy = xyes; then
+ LIBDBI_USE_DUMMY_TRUE=
+ LIBDBI_USE_DUMMY_FALSE='#'
+else
+ LIBDBI_USE_DUMMY_TRUE='#'
+ LIBDBI_USE_DUMMY_FALSE=
+fi
+
+ if test x$enable_libdbi = xyes -o x$enable_libdbi = xoptional; then
+ ENABLE_OMLIBDBI_TRUE=
+ ENABLE_OMLIBDBI_FALSE='#'
+else
+ ENABLE_OMLIBDBI_TRUE='#'
+ ENABLE_OMLIBDBI_FALSE=
+fi
+
+
+
+
+
+# SNMP support
+# Check whether --enable-snmp was given.
+if test "${enable_snmp+set}" = set; then :
+ enableval=$enable_snmp; case "${enableval}" in
+ yes) enable_snmp="yes" ;;
+ no) enable_snmp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-snmp" "$LINENO" 5 ;;
+ esac
+else
+ enable_snmp=no
+
+fi
+
+if test "x$enable_snmp" = "xyes"; then
+ 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
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Net-SNMP is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snmp_timeout in -lnetsnmp" >&5
+$as_echo_n "checking for snmp_timeout in -lnetsnmp... " >&6; }
+if ${ac_cv_lib_netsnmp_snmp_timeout+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetsnmp $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 snmp_timeout ();
+int
+main ()
+{
+return snmp_timeout ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_netsnmp_snmp_timeout=yes
+else
+ ac_cv_lib_netsnmp_snmp_timeout=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_snmp_timeout" >&5
+$as_echo "$ac_cv_lib_netsnmp_snmp_timeout" >&6; }
+if test "x$ac_cv_lib_netsnmp_snmp_timeout" = xyes; then :
+ SNMP_CFLAGS=""
+ SNMP_LIBS="-lnetsnmp"
+
+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 $? "Net-SNMP library is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+fi
+ if test x$enable_snmp = xyes; then
+ ENABLE_SNMP_TRUE=
+ ENABLE_SNMP_FALSE='#'
+else
+ ENABLE_SNMP_TRUE='#'
+ ENABLE_SNMP_FALSE=
+fi
+
+
+
+
+# SNMP Test Support
+# Check whether --enable-snmp-tests was given.
+if test "${enable_snmp_tests+set}" = set; then :
+ enableval=$enable_snmp_tests; case "${enableval}" in
+ yes) enable_snmp_tests="yes" ;;
+ no) enable_snmp_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-snmp-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_snmp_tests=no
+
+fi
+
+ if test x$enable_snmp_tests = xyes; then
+ ENABLE_SNMP_TESTS_TRUE=
+ ENABLE_SNMP_TESTS_FALSE='#'
+else
+ ENABLE_SNMP_TESTS_TRUE='#'
+ ENABLE_SNMP_TESTS_FALSE=
+fi
+
+
+# uuid support
+# Check whether --enable-uuid was given.
+if test "${enable_uuid+set}" = set; then :
+ enableval=$enable_uuid; case "${enableval}" in
+ yes) enable_uuid="yes" ;;
+ no) enable_uuid="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-uuid" "$LINENO" 5 ;;
+ esac
+else
+ enable_uuid=yes
+
+fi
+
+if test "x$enable_uuid" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUUID" >&5
+$as_echo_n "checking for LIBUUID... " >&6; }
+
+if test -n "$LIBUUID_CFLAGS"; then
+ pkg_cv_LIBUUID_CFLAGS="$LIBUUID_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"uuid\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "uuid") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBUUID_CFLAGS=`$PKG_CONFIG --cflags "uuid" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBUUID_LIBS"; then
+ pkg_cv_LIBUUID_LIBS="$LIBUUID_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"uuid\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "uuid") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBUUID_LIBS=`$PKG_CONFIG --libs "uuid" 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
+ LIBUUID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "uuid" 2>&1`
+ else
+ LIBUUID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "uuid" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBUUID_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (uuid) were not met:
+
+$LIBUUID_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBUUID_CFLAGS
+and LIBUUID_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBUUID_CFLAGS
+and LIBUUID_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBUUID_CFLAGS=$pkg_cv_LIBUUID_CFLAGS
+ LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+$as_echo "#define USE_LIBUUID 1" >>confdefs.h
+
+fi
+ if test x$enable_uuid = xyes; then
+ ENABLE_UUID_TRUE=
+ ENABLE_UUID_FALSE='#'
+else
+ ENABLE_UUID_TRUE='#'
+ ENABLE_UUID_FALSE=
+fi
+
+
+
+# elasticsearch support
+# Check whether --enable-elasticsearch was given.
+if test "${enable_elasticsearch+set}" = set; then :
+ enableval=$enable_elasticsearch; case "${enableval}" in
+ yes) enable_elasticsearch="yes" ;;
+ no) enable_elasticsearch="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-elasticsearch" "$LINENO" 5 ;;
+ esac
+else
+ enable_elasticsearch=no
+
+fi
+
+if test "x$enable_elasticsearch" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5
+$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; }
+if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmw $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 _mwvalidcheckl ();
+int
+main ()
+{
+return _mwvalidcheckl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mw__mwvalidcheckl=yes
+else
+ ac_cv_lib_mw__mwvalidcheckl=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_mw__mwvalidcheckl" >&5
+$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; }
+if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then :
+ LIBM=-lmw
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM="$LIBM -lm"
+fi
+
+ ;;
+*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM=-lm
+fi
+
+ ;;
+esac
+
+
+fi
+ if test x$enable_elasticsearch = xyes; then
+ ENABLE_ELASTICSEARCH_TRUE=
+ ENABLE_ELASTICSEARCH_FALSE='#'
+else
+ ENABLE_ELASTICSEARCH_TRUE='#'
+ ENABLE_ELASTICSEARCH_FALSE=
+fi
+
+
+
+# clickhouse support
+# Check whether --enable-clickhouse was given.
+if test "${enable_clickhouse+set}" = set; then :
+ enableval=$enable_clickhouse; case "${enableval}" in
+ yes) enable_clickhouse="yes" ;;
+ no) enable_clickhouse="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-clickhouse" "$LINENO" 5 ;;
+ esac
+else
+ enable_clickhouse=no
+
+fi
+
+if test "x$enable_clickhouse" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5
+$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; }
+if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmw $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 _mwvalidcheckl ();
+int
+main ()
+{
+return _mwvalidcheckl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mw__mwvalidcheckl=yes
+else
+ ac_cv_lib_mw__mwvalidcheckl=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_mw__mwvalidcheckl" >&5
+$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; }
+if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then :
+ LIBM=-lmw
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM="$LIBM -lm"
+fi
+
+ ;;
+*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM=-lm
+fi
+
+ ;;
+esac
+
+
+fi
+ if test x$enable_clickhouse = xyes; then
+ ENABLE_CLICKHOUSE_TRUE=
+ ENABLE_CLICKHOUSE_FALSE='#'
+else
+ ENABLE_CLICKHOUSE_TRUE='#'
+ ENABLE_CLICKHOUSE_FALSE=
+fi
+
+
+
+# omhttp support
+# Check whether --enable-omhttp was given.
+if test "${enable_omhttp+set}" = set; then :
+ enableval=$enable_omhttp; case "${enableval}" in
+ yes) enable_omhttp="yes" ;;
+ no) enable_omhttp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omhttp" "$LINENO" 5 ;;
+ esac
+else
+ enable_omhttp=no
+
+fi
+
+if test "x$enable_omhttp" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5
+$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; }
+if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmw $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 _mwvalidcheckl ();
+int
+main ()
+{
+return _mwvalidcheckl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mw__mwvalidcheckl=yes
+else
+ ac_cv_lib_mw__mwvalidcheckl=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_mw__mwvalidcheckl" >&5
+$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; }
+if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then :
+ LIBM=-lmw
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM="$LIBM -lm"
+fi
+
+ ;;
+*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM=-lm
+fi
+
+ ;;
+esac
+
+
+fi
+ if test x$enable_omhttp = xyes; then
+ ENABLE_OMHTTP_TRUE=
+ ENABLE_OMHTTP_FALSE='#'
+else
+ ENABLE_OMHTTP_TRUE='#'
+ ENABLE_OMHTTP_FALSE=
+fi
+
+
+
+# capability to enable elasticsearch testbench tests. This requries that an ES test
+# environment is present on the local (127.0.0.1) machine.
+# we support a "minimal" mode to take care of travis where we cannot run all tests
+# due to runtime constraints
+# Check whether --enable-elasticsearch_tests was given.
+if test "${enable_elasticsearch_tests+set}" = set; then :
+ enableval=$enable_elasticsearch_tests; case "${enableval}" in
+ yes) enable_elasticsearch_tests="yes" ;;
+ no) enable_elasticsearch_tests="no" ;;
+ minimal) enable_elasticsearch_tests="minimal" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-elasticsearch-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_elasticsearch_tests=no
+
+fi
+
+ if test x$enable_elasticsearch_tests = xyes; then
+ ENABLE_ELASTICSEARCH_TESTS_TRUE=
+ ENABLE_ELASTICSEARCH_TESTS_FALSE='#'
+else
+ ENABLE_ELASTICSEARCH_TESTS_TRUE='#'
+ ENABLE_ELASTICSEARCH_TESTS_FALSE=
+fi
+
+ if test x$enable_elasticsearch_tests = xminimal -o x$enable_elasticsearch_tests = xyes; then
+ ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE=
+ ENABLE_ELASTICSEARCH_TESTS_MINIMAL_FALSE='#'
+else
+ ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE='#'
+ ENABLE_ELASTICSEARCH_TESTS_MINIMAL_FALSE=
+fi
+
+
+
+# capability to enable clickhouse testbench tests. This requries that a test
+# environment is present on the local (127.0.0.1) machine.
+# Check whether --enable-clickhouse_tests was given.
+if test "${enable_clickhouse_tests+set}" = set; then :
+ enableval=$enable_clickhouse_tests; case "${enableval}" in
+ yes) enable_clickhouse_tests="yes" ;;
+ no) enable_clickhouse_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-clickhouse-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_clickhouse_tests=no
+
+fi
+
+ if test x$enable_clickhouse_tests = xyes; then
+ ENABLE_CLICKHOUSE_TESTS_TRUE=
+ ENABLE_CLICKHOUSE_TESTS_FALSE='#'
+else
+ ENABLE_CLICKHOUSE_TESTS_TRUE='#'
+ ENABLE_CLICKHOUSE_TESTS_FALSE=
+fi
+
+
+
+# openssl support
+# Check whether --enable-openssl was given.
+if test "${enable_openssl+set}" = set; then :
+ enableval=$enable_openssl; case "${enableval}" in
+ yes) enable_openssl="yes" ;;
+ no) enable_openssl="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-openssl" "$LINENO" 5 ;;
+ esac
+else
+ enable_openssl=no
+
+fi
+
+if test "x$enable_openssl" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+$as_echo_n "checking for OPENSSL... " >&6; }
+
+if test -n "$OPENSSL_CFLAGS"; then
+ pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$OPENSSL_LIBS"; then
+ pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl" 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
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1`
+ else
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$OPENSSL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (openssl) were not met:
+
+$OPENSSL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS
+ OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+$as_echo "#define ENABLE_OPENSSL 1" >>confdefs.h
+
+ save_libs=$LIBS
+fi
+ if test x$enable_openssl = xyes; then
+ ENABLE_OPENSSL_TRUE=
+ ENABLE_OPENSSL_FALSE='#'
+else
+ ENABLE_OPENSSL_TRUE='#'
+ ENABLE_OPENSSL_FALSE=
+fi
+
+
+
+# GnuTLS support
+# Check whether --enable-gnutls was given.
+if test "${enable_gnutls+set}" = set; then :
+ enableval=$enable_gnutls; case "${enableval}" in
+ yes) enable_gnutls="yes" ;;
+ no) enable_gnutls="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-gnutls" "$LINENO" 5 ;;
+ esac
+else
+ enable_gnutls=no
+
+fi
+
+if test "x$enable_gnutls" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5
+$as_echo_n "checking for GNUTLS... " >&6; }
+
+if test -n "$GNUTLS_CFLAGS"; then
+ pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 1.4.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gnutls >= 1.4.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 1.4.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GNUTLS_LIBS"; then
+ pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 1.4.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gnutls >= 1.4.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 1.4.0" 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
+ GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 1.4.0" 2>&1`
+ else
+ GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 1.4.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GNUTLS_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (gnutls >= 1.4.0) were not met:
+
+$GNUTLS_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GNUTLS_CFLAGS
+and GNUTLS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables GNUTLS_CFLAGS
+and GNUTLS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS
+ GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+$as_echo "#define ENABLE_GNUTLS 1" >>confdefs.h
+
+ save_libs=$LIBS
+ LIBS="$LIBS $GNUTLS_LIBS"
+ for ac_func in gnutls_certificate_set_retrieve_function
+do :
+ ac_fn_c_check_func "$LINENO" "gnutls_certificate_set_retrieve_function" "ac_cv_func_gnutls_certificate_set_retrieve_function"
+if test "x$ac_cv_func_gnutls_certificate_set_retrieve_function" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION 1
+_ACEOF
+
+fi
+done
+
+ for ac_func in gnutls_certificate_type_set_priority
+do :
+ ac_fn_c_check_func "$LINENO" "gnutls_certificate_type_set_priority" "ac_cv_func_gnutls_certificate_type_set_priority"
+if test "x$ac_cv_func_gnutls_certificate_type_set_priority" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY 1
+_ACEOF
+
+fi
+done
+
+ LIBS=$save_libs
+fi
+
+ if test x$enable_gnutls = xyes; then
+ ENABLE_GNUTLS_TRUE=
+ ENABLE_GNUTLS_FALSE='#'
+else
+ ENABLE_GNUTLS_TRUE='#'
+ ENABLE_GNUTLS_FALSE=
+fi
+
+
+# Check whether --enable-gnutls-tests was given.
+if test "${enable_gnutls_tests+set}" = set; then :
+ enableval=$enable_gnutls_tests; case "${enableval}" in
+ yes) enable_gnutls_tests="yes" ;;
+ no) enable_gnutls_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-gnutls-tests" "$LINENO" 5 ;;
+ esac
+else
+ if [ "$enable_gnutls" == "yes" ]; then
+ enable_gnutls_tests=yes
+ else
+ enable_gnutls_tests=no
+ fi
+
+fi
+
+if [ "$enable_gnutls_tests" == "yes" ] && [ "$enable_gnutls" != "yes" ]; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gnutls-tests can not be enabled without gnutls support. Disabling gnutls tests..." >&5
+$as_echo "$as_me: WARNING: gnutls-tests can not be enabled without gnutls support. Disabling gnutls tests..." >&2;}
+ enable_gnutls_tests="no"
+fi
+
+ if test x$enable_gnutls_tests = xyes; then
+ ENABLE_GNUTLS_TESTS_TRUE=
+ ENABLE_GNUTLS_TESTS_FALSE='#'
+else
+ ENABLE_GNUTLS_TESTS_TRUE='#'
+ ENABLE_GNUTLS_TESTS_FALSE=
+fi
+
+
+
+# libgcrypt support
+# Check whether --enable-libgcrypt was given.
+if test "${enable_libgcrypt+set}" = set; then :
+ enableval=$enable_libgcrypt; case "${enableval}" in
+ yes) enable_libgcrypt="yes" ;;
+ no) enable_libgcrypt="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-libgcrypt" "$LINENO" 5 ;;
+ esac
+else
+ enable_libgcrypt=yes
+
+fi
+
+if test "x$enable_libgcrypt" = "xyes"; then
+ # 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_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
+
+ test -z "$ac_cv_path_LIBGCRYPT_CONFIG" && ac_cv_path_LIBGCRYPT_CONFIG="no"
+ ;;
+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
+
+
+ if test "x${LIBGCRYPT_CONFIG}" = "xno"; 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 $? "libgcrypt-config not found in PATH
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_cipher_open in -lgcrypt" >&5
+$as_echo_n "checking for gcry_cipher_open in -lgcrypt... " >&6; }
+if ${ac_cv_lib_gcrypt_gcry_cipher_open+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgcrypt `${LIBGCRYPT_CONFIG} --libs --cflags`
+ $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_cipher_open ();
+int
+main ()
+{
+return gcry_cipher_open ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_gcrypt_gcry_cipher_open=yes
+else
+ ac_cv_lib_gcrypt_gcry_cipher_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_gcrypt_gcry_cipher_open" >&5
+$as_echo "$ac_cv_lib_gcrypt_gcry_cipher_open" >&6; }
+if test "x$ac_cv_lib_gcrypt_gcry_cipher_open" = xyes; then :
+ LIBGCRYPT_CFLAGS="`${LIBGCRYPT_CONFIG} --cflags`"
+ LIBGCRYPT_LIBS="`${LIBGCRYPT_CONFIG} --libs`"
+
+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 $? "libgcrypt is missing
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+
+$as_echo "#define ENABLE_LIBGCRYPT 1" >>confdefs.h
+
+fi
+ if test x$enable_libgcrypt = xyes; then
+ ENABLE_LIBGCRYPT_TRUE=
+ ENABLE_LIBGCRYPT_FALSE='#'
+else
+ ENABLE_LIBGCRYPT_TRUE='#'
+ ENABLE_LIBGCRYPT_FALSE=
+fi
+
+
+
+
+# libzstd support
+# Check whether --enable-libzstd was given.
+if test "${enable_libzstd+set}" = set; then :
+ enableval=$enable_libzstd; case "${enableval}" in
+ yes) enable_libzstd="yes" ;;
+ no) enable_libzstd="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-libzstd" "$LINENO" 5 ;;
+ esac
+else
+ enable_libzstd=no
+
+fi
+
+if test "x$enable_libzstd" = "xyes"; then
+ save_LIBS="$LIBS"
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZSTD" >&5
+$as_echo_n "checking for ZSTD... " >&6; }
+
+if test -n "$ZSTD_CFLAGS"; then
+ pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zstd >= 1.4.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "zstd >= 1.4.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "zstd >= 1.4.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$ZSTD_LIBS"; then
+ pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zstd >= 1.4.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "zstd >= 1.4.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "zstd >= 1.4.0" 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
+ ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zstd >= 1.4.0" 2>&1`
+ else
+ ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zstd >= 1.4.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$ZSTD_PKG_ERRORS" >&5
+
+
+ LIBS="$LIBS -lzstd"
+ ZSTD_LIBS="-lzstd"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ZSTD_compressStream2" >&5
+$as_echo_n "checking for library containing ZSTD_compressStream2... " >&6; }
+if ${ac_cv_search_ZSTD_compressStream2+:} 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 ZSTD_compressStream2 ();
+int
+main ()
+{
+return ZSTD_compressStream2 ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' zstd; 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_ZSTD_compressStream2=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ZSTD_compressStream2+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ZSTD_compressStream2+:} false; then :
+
+else
+ ac_cv_search_ZSTD_compressStream2=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ZSTD_compressStream2" >&5
+$as_echo "$ac_cv_search_ZSTD_compressStream2" >&6; }
+ac_res=$ac_cv_search_ZSTD_compressStream2
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+ #include <zstd.h>
+int
+main ()
+{
+
+ ZSTD_CCtx* cctx = ZSTD_createCCtx();
+ ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 5);
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "libzstd version must be >= 1.4.0" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ as_fn_error $? "libzstd not found" "$LINENO" 5
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ LIBS="$LIBS -lzstd"
+ ZSTD_LIBS="-lzstd"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ZSTD_compressStream2" >&5
+$as_echo_n "checking for library containing ZSTD_compressStream2... " >&6; }
+if ${ac_cv_search_ZSTD_compressStream2+:} 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 ZSTD_compressStream2 ();
+int
+main ()
+{
+return ZSTD_compressStream2 ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' zstd; 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_ZSTD_compressStream2=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ZSTD_compressStream2+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ZSTD_compressStream2+:} false; then :
+
+else
+ ac_cv_search_ZSTD_compressStream2=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ZSTD_compressStream2" >&5
+$as_echo "$ac_cv_search_ZSTD_compressStream2" >&6; }
+ac_res=$ac_cv_search_ZSTD_compressStream2
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+ #include <zstd.h>
+int
+main ()
+{
+
+ ZSTD_CCtx* cctx = ZSTD_createCCtx();
+ ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 5);
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "libzstd version must be >= 1.4.0" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ as_fn_error $? "libzstd not found" "$LINENO" 5
+
+fi
+
+
+else
+ ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
+ ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ LIBS="$save_LIBS"
+fi
+ if test x$enable_libzstd = xyes; then
+ ENABLE_LIBZSTD_TRUE=
+ ENABLE_LIBZSTD_FALSE='#'
+else
+ ENABLE_LIBZSTD_TRUE='#'
+ ENABLE_LIBZSTD_FALSE=
+fi
+
+
+
+# support for building the rsyslogd runtime
+# Check whether --enable-rsyslogrt was given.
+if test "${enable_rsyslogrt+set}" = set; then :
+ enableval=$enable_rsyslogrt; case "${enableval}" in
+ yes) enable_rsyslogrt="yes" ;;
+ no) enable_rsyslogrt="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-rsyslogrt" "$LINENO" 5 ;;
+ esac
+else
+ enable_rsyslogrt=yes
+
+fi
+
+if test "x$enable_rsyslogrt" = "xyes"; then
+ RSRT_CFLAGS1="-I\$(top_srcdir)/runtime -I\$(top_srcdir) -I\$(top_srcdir)/grammar"
+ RSRT_LIBS1="\$(top_builddir)/runtime/librsyslog.la"
+fi
+ if test x$enable_rsyslogrt = xyes; then
+ ENABLE_RSYSLOGRT_TRUE=
+ ENABLE_RSYSLOGRT_FALSE='#'
+else
+ ENABLE_RSYSLOGRT_TRUE='#'
+ ENABLE_RSYSLOGRT_FALSE=
+fi
+
+RSRT_CFLAGS="\$(RSRT_CFLAGS1) \$(LIBESTR_CFLAGS) \$(LIBFASTJSON_CFLAGS) \$(LIBSYSTEMD_CFLAGS)"
+if test "$GCC" = "yes"; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute"
+ if $CC -Werror=implicit-function-declaration -x c -c /dev/null -o /dev/null 2>/dev/null; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -Werror=implicit-function-declaration"
+ elif $CC -Werror-implicit-function-declaration -x c -c /dev/null -o /dev/null 2>/dev/null; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -Werror-implicit-function-declaration"
+ fi
+
+ if test "x$enable_debug_symbols" = "xyes"; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -g"
+ fi
+fi
+RSRT_CFLAGS="$RSRT_CFLAGS $WARN_CFLAGS"
+RSRT_LIBS="\$(RSRT_LIBS1) \$(LIBESTR_LIBS) \$(LIBFASTJSON_LIBS) \$(LIBSYSTEMD_LIBS)"
+
+
+
+
+
+
+# support for NOT building rsyslogd (useful for source-based packaging systems)
+# Check whether --enable-rsyslogd was given.
+if test "${enable_rsyslogd+set}" = set; then :
+ enableval=$enable_rsyslogd; case "${enableval}" in
+ yes) enable_rsyslogd="yes" ;;
+ no) enable_rsyslogd="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-rsyslogd" "$LINENO" 5 ;;
+ esac
+else
+ enable_rsyslogd=yes
+
+fi
+
+ if test x$enable_rsyslogd = xyes; then
+ ENABLE_RSYSLOGD_TRUE=
+ ENABLE_RSYSLOGD_FALSE='#'
+else
+ ENABLE_RSYSLOGD_TRUE='#'
+ ENABLE_RSYSLOGD_FALSE=
+fi
+
+
+
+# capability to enable an extended testbench. By default, this is off. The reason
+# for this switch is that some test simply take too long to execute them on a regular
+# basis. So we enable to skip them, while the majority of tests can still be used. The
+# idea is that at least "make distcheck" executes the extended testbench, and also
+# developers should explicitely enable it after important changes. -- rgerhards, 2010-04-12
+# Check whether --enable-extended_tests was given.
+if test "${enable_extended_tests+set}" = set; then :
+ enableval=$enable_extended_tests; case "${enableval}" in
+ yes) enable_extended_tests="yes" ;;
+ no) enable_extended_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-extended-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_extended_tests=no
+
+fi
+
+ if test x$enable_extended_tests = xyes; then
+ ENABLE_EXTENDED_TESTS_TRUE=
+ ENABLE_EXTENDED_TESTS_FALSE='#'
+else
+ ENABLE_EXTENDED_TESTS_TRUE='#'
+ ENABLE_EXTENDED_TESTS_FALSE=
+fi
+
+
+
+# capability to enable MySQL testbench tests. This requries that a Syslog database
+# with the default schema has been created on the local (127.0.0.1) MySQL server and
+# a user "rsyslog" with password "testbench" exists, is able to login with default
+# parameters and has sufficient (read: all) privileges on that database.
+# rgerhards, 2011-03-09
+# Check whether --enable-mysql_tests was given.
+if test "${enable_mysql_tests+set}" = set; then :
+ enableval=$enable_mysql_tests; case "${enableval}" in
+ yes) enable_mysql_tests="yes" ;;
+ no) enable_mysql_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mysql-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_mysql_tests=no
+
+fi
+
+ if test x$enable_mysql_tests = xyes; then
+ ENABLE_MYSQL_TESTS_TRUE=
+ ENABLE_MYSQL_TESTS_FALSE='#'
+else
+ ENABLE_MYSQL_TESTS_TRUE='#'
+ ENABLE_MYSQL_TESTS_FALSE=
+fi
+
+
+
+# capability to enable PostgreSQL testbench tests. This requries that a Syslog database
+# with the default schema (see plugins/ompgsql/createDB.sql) has been created on the
+# local (127.0.0.1) PostgreSQL server and a user "rsyslog" with password "testbench"
+# exists, is able to login with default parameters and has sufficient (read: all)
+# privileges on that database
+# Check whether --enable-pgsql_tests was given.
+if test "${enable_pgsql_tests+set}" = set; then :
+ enableval=$enable_pgsql_tests; case "${enableval}" in
+ yes) enable_pgsql_tests="yes" ;;
+ no) enable_pgsql_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pgsql-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_pgsql_tests=no
+
+fi
+
+ if test x$enable_pgsql_tests = xyes; then
+ ENABLE_PGSQL_TESTS_TRUE=
+ ENABLE_PGSQL_TESTS_FALSE='#'
+else
+ ENABLE_PGSQL_TESTS_TRUE='#'
+ ENABLE_PGSQL_TESTS_FALSE=
+fi
+
+
+
+# Mail support (so far we do not need a library, but we need to turn this on and off)
+# Check whether --enable-mail was given.
+if test "${enable_mail+set}" = set; then :
+ enableval=$enable_mail; case "${enableval}" in
+ yes) enable_mail="yes" ;;
+ no) enable_mail="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mail" "$LINENO" 5 ;;
+ esac
+else
+ enable_mail=no
+
+fi
+
+ if test x$enable_mail = xyes; then
+ ENABLE_MAIL_TRUE=
+ ENABLE_MAIL_FALSE='#'
+else
+ ENABLE_MAIL_TRUE='#'
+ ENABLE_MAIL_FALSE=
+fi
+
+
+
+# Check whether --enable-fmhttp was given.
+if test "${enable_fmhttp+set}" = set; then :
+ enableval=$enable_fmhttp; case "${enableval}" in
+ yes) enable_fmhttp="yes" ;;
+ no) enable_fmhttp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-fmhttp" "$LINENO" 5 ;;
+ esac
+else
+ enable_fmhttp=yes
+
+fi
+
+if test "$enable_fmhttp" = "yes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_fmhttp = xyes; then
+ ENABLE_FMHTTP_TRUE=
+ ENABLE_FMHTTP_FALSE='#'
+else
+ ENABLE_FMHTTP_TRUE='#'
+ ENABLE_FMHTTP_FALSE=
+fi
+
+
+
+# imdiag support
+# This is a core testbench tool. You need to enable it if you want to
+# use not only a small subset of the testbench.
+# Check whether --enable-imdiag was given.
+if test "${enable_imdiag+set}" = set; then :
+ enableval=$enable_imdiag; case "${enableval}" in
+ yes) enable_imdiag="yes" ;;
+ no) enable_imdiag="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imdiag" "$LINENO" 5 ;;
+ esac
+else
+ enable_imdiag=no
+
+fi
+
+if test "x$enable_imdiag" = "xyes"; then
+
+$as_echo "#define ENABLE_IMDIAG 1" >>confdefs.h
+
+fi
+ if test x$enable_imdiag = xyes; then
+ ENABLE_IMDIAG_TRUE=
+ ENABLE_IMDIAG_FALSE='#'
+else
+ ENABLE_IMDIAG_TRUE='#'
+ ENABLE_IMDIAG_FALSE=
+fi
+
+
+
+# mmnormalize
+# Check whether --enable-mmnormalize was given.
+if test "${enable_mmnormalize+set}" = set; then :
+ enableval=$enable_mmnormalize; case "${enableval}" in
+ yes) enable_mmnormalize="yes" ;;
+ no) enable_mmnormalize="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmnormalize" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmnormalize=no
+
+fi
+
+if test "x$enable_mmnormalize" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLOGNORM" >&5
+$as_echo_n "checking for LIBLOGNORM... " >&6; }
+
+if test -n "$LIBLOGNORM_CFLAGS"; then
+ pkg_cv_LIBLOGNORM_CFLAGS="$LIBLOGNORM_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lognorm >= 2.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "lognorm >= 2.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGNORM_CFLAGS=`$PKG_CONFIG --cflags "lognorm >= 2.0.3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLOGNORM_LIBS"; then
+ pkg_cv_LIBLOGNORM_LIBS="$LIBLOGNORM_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lognorm >= 2.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "lognorm >= 2.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGNORM_LIBS=`$PKG_CONFIG --libs "lognorm >= 2.0.3" 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
+ LIBLOGNORM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lognorm >= 2.0.3" 2>&1`
+ else
+ LIBLOGNORM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lognorm >= 2.0.3" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLOGNORM_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (lognorm >= 2.0.3) were not met:
+
+$LIBLOGNORM_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBLOGNORM_CFLAGS
+and LIBLOGNORM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBLOGNORM_CFLAGS
+and LIBLOGNORM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBLOGNORM_CFLAGS=$pkg_cv_LIBLOGNORM_CFLAGS
+ LIBLOGNORM_LIBS=$pkg_cv_LIBLOGNORM_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $LIBLOGNORM_CFLAGS"
+ LIBS="$LIBS $LIBLOGNORM_LIBS"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LOGNORM_REGEX_SUPPORTED defined" >&5
+$as_echo_n "checking for LOGNORM_REGEX_SUPPORTED defined... " >&6; }
+if ${ac_cv_defined_LOGNORM_REGEX_SUPPORTED+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <lognorm-features.h>
+int
+main ()
+{
+
+ #ifdef LOGNORM_REGEX_SUPPORTED
+ int ok;
+ #else
+ choke me
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_defined_LOGNORM_REGEX_SUPPORTED=yes
+else
+ ac_cv_defined_LOGNORM_REGEX_SUPPORTED=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_defined_LOGNORM_REGEX_SUPPORTED" >&5
+$as_echo "$ac_cv_defined_LOGNORM_REGEX_SUPPORTED" >&6; }
+if test $ac_cv_defined_LOGNORM_REGEX_SUPPORTED != "no"; then :
+ lognorm_regex_supported="yes"
+fi
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+ if test x$lognorm_regex_supported = xyes; then
+ LOGNORM_REGEX_SUPPORTED_TRUE=
+ LOGNORM_REGEX_SUPPORTED_FALSE='#'
+else
+ LOGNORM_REGEX_SUPPORTED_TRUE='#'
+ LOGNORM_REGEX_SUPPORTED_FALSE=
+fi
+
+ if test x$enable_mmnormalize = xyes; then
+ ENABLE_MMNORMALIZE_TRUE=
+ ENABLE_MMNORMALIZE_FALSE='#'
+else
+ ENABLE_MMNORMALIZE_TRUE='#'
+ ENABLE_MMNORMALIZE_FALSE=
+fi
+
+
+# mmnjsonparse
+# Check whether --enable-mmjsonparse was given.
+if test "${enable_mmjsonparse+set}" = set; then :
+ enableval=$enable_mmjsonparse; case "${enableval}" in
+ yes) enable_mmjsonparse="yes" ;;
+ no) enable_mmjsonparse="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmjsonparse" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmjsonparse=no
+
+fi
+
+ if test x$enable_mmjsonparse = xyes; then
+ ENABLE_MMJSONPARSE_TRUE=
+ ENABLE_MMJSONPARSE_FALSE='#'
+else
+ ENABLE_MMJSONPARSE_TRUE='#'
+ ENABLE_MMJSONPARSE_FALSE=
+fi
+
+
+# mmgrok
+# Check whether --enable-mmgrok was given.
+if test "${enable_mmgrok+set}" = set; then :
+ enableval=$enable_mmgrok; case "${enableval}" in
+ yes) enable_mmgrok="yes" ;;
+ no) enable_mmgrok="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmgrok" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmgrok=no
+
+fi
+
+if test "x$enable_mmgrok" = "xyes"; then
+ for ac_header in grok.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "grok.h" "ac_cv_header_grok_h" "$ac_includes_default"
+if test "x$ac_cv_header_grok_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GROK_H 1
+_ACEOF
+
+fi
+
+done
+
+ GLIB_CFLAGS="$(pkg-config --cflags glib-2.0)"
+ GLIB_LIBS="$(pkg-config --libs glib-2.0)"
+fi
+ if test x$enable_mmgrok = xyes; then
+ ENABLE_MMGROK_TRUE=
+ ENABLE_MMGROK_FALSE='#'
+else
+ ENABLE_MMGROK_TRUE='#'
+ ENABLE_MMGROK_FALSE=
+fi
+
+
+
+
+# mmaudit
+# Check whether --enable-mmaudit was given.
+if test "${enable_mmaudit+set}" = set; then :
+ enableval=$enable_mmaudit; case "${enableval}" in
+ yes) enable_mmaudit="yes" ;;
+ no) enable_mmaudit="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmaudit" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmaudit=no
+
+fi
+
+ if test x$enable_mmaudit = xyes; then
+ ENABLE_MMAUDIT_TRUE=
+ ENABLE_MMAUDIT_FALSE='#'
+else
+ ENABLE_MMAUDIT_TRUE='#'
+ ENABLE_MMAUDIT_FALSE=
+fi
+
+
+
+# mmanon
+# Check whether --enable-mmanon was given.
+if test "${enable_mmanon+set}" = set; then :
+ enableval=$enable_mmanon; case "${enableval}" in
+ yes) enable_mmanon="yes" ;;
+ no) enable_mmanon="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmanon" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmanon=no
+
+fi
+
+ if test x$enable_mmanon = xyes; then
+ ENABLE_MMANON_TRUE=
+ ENABLE_MMANON_FALSE='#'
+else
+ ENABLE_MMANON_TRUE='#'
+ ENABLE_MMANON_FALSE=
+fi
+
+
+
+# mmrm1stspace
+# Check whether --enable-mmrm1stspace was given.
+if test "${enable_mmrm1stspace+set}" = set; then :
+ enableval=$enable_mmrm1stspace; case "${enableval}" in
+ yes) enable_mmrm1stspace="yes" ;;
+ no) enable_mmrm1stspace="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmrm1stspace" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmrm1stspace=no
+
+fi
+
+ if test x$enable_mmrm1stspace = xyes; then
+ ENABLE_MMRM1STSPACE_TRUE=
+ ENABLE_MMRM1STSPACE_FALSE='#'
+else
+ ENABLE_MMRM1STSPACE_TRUE='#'
+ ENABLE_MMRM1STSPACE_FALSE=
+fi
+
+
+
+# mmutf8fix
+# Check whether --enable-mmutf8fix was given.
+if test "${enable_mmutf8fix+set}" = set; then :
+ enableval=$enable_mmutf8fix; case "${enableval}" in
+ yes) enable_mmutf8fix="yes" ;;
+ no) enable_mmutf8fix="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmutf8fix" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmutf8fix=no
+
+fi
+
+ if test x$enable_mmutf8fix = xyes; then
+ ENABLE_MMUTF8FIX_TRUE=
+ ENABLE_MMUTF8FIX_FALSE='#'
+else
+ ENABLE_MMUTF8FIX_TRUE='#'
+ ENABLE_MMUTF8FIX_FALSE=
+fi
+
+
+
+# mmcount
+# Check whether --enable-mmcount was given.
+if test "${enable_mmcount+set}" = set; then :
+ enableval=$enable_mmcount; case "${enableval}" in
+ yes) enable_mmcount="yes" ;;
+ no) enable_mmcount="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmcount" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmcount=no
+
+fi
+
+ if test x$enable_mmcount = xyes; then
+ ENABLE_MMCOUNT_TRUE=
+ ENABLE_MMCOUNT_FALSE='#'
+else
+ ENABLE_MMCOUNT_TRUE='#'
+ ENABLE_MMCOUNT_FALSE=
+fi
+
+
+
+# mmsequence
+# Check whether --enable-mmsequence was given.
+if test "${enable_mmsequence+set}" = set; then :
+ enableval=$enable_mmsequence; case "${enableval}" in
+ yes) enable_mmsequence="yes" ;;
+ no) enable_mmsequence="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmsequence" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmsequence=no
+
+fi
+
+ if test x$enable_mmsequence = xyes; then
+ ENABLE_MMSEQUENCE_TRUE=
+ ENABLE_MMSEQUENCE_FALSE='#'
+else
+ ENABLE_MMSEQUENCE_TRUE='#'
+ ENABLE_MMSEQUENCE_FALSE=
+fi
+
+
+
+
+# mmdblookup
+# Check whether --enable-mmdblookup was given.
+if test "${enable_mmdblookup+set}" = set; then :
+ enableval=$enable_mmdblookup; case "${enableval}" in
+ yes) enable_mmdblookup="yes" ;;
+ no) enable_mmdblookup="no" ;;
+ optional) enable_mmdblookup="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmdblookup" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmdblookup=no
+
+fi
+
+ if test x$enable_mmdblookup = xyes -o x$enable_mmdblookup = xoptional; then
+ ENABLE_MMDBLOOKUP_TRUE=
+ ENABLE_MMDBLOOKUP_FALSE='#'
+else
+ ENABLE_MMDBLOOKUP_TRUE='#'
+ ENABLE_MMDBLOOKUP_FALSE=
+fi
+
+mmdblookup_use_dummy="no"
+if test x$enable_mmdblookup = xoptional -o x$enable_mmdblookup = xyes; then
+ #PKG_CHECK_MODULES(LIBMAXMINDDB, libmaxminddb) -- does not work - later?
+ for ac_header in maxminddb.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default"
+if test "x$ac_cv_header_maxminddb_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MAXMINDDB_H 1
+_ACEOF
+
+
+else
+
+ if test x$enable_mmdblookup = xyes; then :
+ as_fn_error $? "libmaxminddb library for mmdblookup could not be found" "$LINENO" 5
+
+fi
+ mmdblookup_use_dummy="yes"
+
+$as_echo "#define ENABLE_MMBDLOOKUP_DUMMY 1" >>confdefs.h
+
+
+fi
+
+done
+
+fi
+ if test x$mmdblookup_use_dummy = xyes; then
+ MMDBLOOKUP_USE_DUMMY_TRUE=
+ MMDBLOOKUP_USE_DUMMY_FALSE='#'
+else
+ MMDBLOOKUP_USE_DUMMY_TRUE='#'
+ MMDBLOOKUP_USE_DUMMY_FALSE=
+fi
+
+
+
+# mmdarwin
+# Check whether --enable-mmdarwin was given.
+if test "${enable_mmdarwin+set}" = set; then :
+ enableval=$enable_mmdarwin; case "${enableval}" in
+ yes) enable_mmdarwin="yes" ;;
+ no) enable_mmdarwin="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmdarwin" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmdarwin=no
+
+fi
+
+if test "x$enable_mmdarwin"; then
+ for ac_header in protocol.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "protocol.h" "ac_cv_header_protocol_h" "$ac_includes_default"
+if test "x$ac_cv_header_protocol_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_PROTOCOL_H 1
+_ACEOF
+
+fi
+
+done
+
+fi
+ if test x$enable_mmdarwin = xyes; then
+ ENABLE_MMDARWIN_TRUE=
+ ENABLE_MMDARWIN_FALSE='#'
+else
+ ENABLE_MMDARWIN_TRUE='#'
+ ENABLE_MMDARWIN_FALSE=
+fi
+
+
+
+
+
+# mmfields
+# Check whether --enable-mmfields was given.
+if test "${enable_mmfields+set}" = set; then :
+ enableval=$enable_mmfields; case "${enableval}" in
+ yes) enable_mmfields="yes" ;;
+ no) enable_mmfields="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmfields" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmfields=no
+
+fi
+
+ if test x$enable_mmfields = xyes; then
+ ENABLE_MMFIELDS_TRUE=
+ ENABLE_MMFIELDS_FALSE='#'
+else
+ ENABLE_MMFIELDS_TRUE='#'
+ ENABLE_MMFIELDS_FALSE=
+fi
+
+
+# mmpstrucdata
+# Check whether --enable-mmpstrucdata was given.
+if test "${enable_mmpstrucdata+set}" = set; then :
+ enableval=$enable_mmpstrucdata; case "${enableval}" in
+ yes) enable_mmpstrucdata="yes" ;;
+ no) enable_mmpstrucdata="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmpstrucdata" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmpstrucdata=no
+
+fi
+
+ if test x$enable_mmpstrucdata = xyes; then
+ ENABLE_MMPSTRUCDATA_TRUE=
+ ENABLE_MMPSTRUCDATA_FALSE='#'
+else
+ ENABLE_MMPSTRUCDATA_TRUE='#'
+ ENABLE_MMPSTRUCDATA_FALSE=
+fi
+
+
+
+# mmrfc5424addhmac
+# Check whether --enable-mmrfc5424addhmac was given.
+if test "${enable_mmrfc5424addhmac+set}" = set; then :
+ enableval=$enable_mmrfc5424addhmac; case "${enableval}" in
+ yes) enable_mmrfc5424addhmac="yes" ;;
+ no) enable_mmrfc5424addhmac="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmrfc5424addhmac" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmrfc5424addhmac=no
+
+fi
+
+if test "x$enable_mmrfc5424addhmac" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+$as_echo_n "checking for OPENSSL... " >&6; }
+
+if test -n "$OPENSSL_CFLAGS"; then
+ pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.7" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$OPENSSL_LIBS"; then
+ pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.7" 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
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.7" 2>&1`
+ else
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.7" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$OPENSSL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (openssl >= 0.9.7) were not met:
+
+$OPENSSL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS
+ OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+#AC_CHECK_LIB([crypto],[CRYPTO_new_ex_data], [], [AC_MSG_ERROR([OpenSSL libraries required])])
+#AC_CHECK_LIB([ssl],[SSL_library_init], [], [AC_MSG_ERROR([OpenSSL libraries required])])
+#AC_CHECK_HEADERS([openssl/crypto.h openssl/x509.h openssl/pem.h openssl/ssl.h openssl/err.h],[],[AC_MSG_ERROR([OpenSSL headers required])])
+fi
+ if test x$enable_mmrfc5424addhmac = xyes; then
+ ENABLE_MMRFC5424ADDHMAC_TRUE=
+ ENABLE_MMRFC5424ADDHMAC_FALSE='#'
+else
+ ENABLE_MMRFC5424ADDHMAC_TRUE='#'
+ ENABLE_MMRFC5424ADDHMAC_FALSE=
+fi
+
+
+
+# experimental omfile-hardened module
+# Check whether --enable-omfile-hardened was given.
+if test "${enable_omfile_hardened+set}" = set; then :
+ enableval=$enable_omfile_hardened; case "${enableval}" in
+ yes) enable_omfile_hardened="yes" ;;
+ no) enable_omfile_hardened="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omfile-hardened" "$LINENO" 5 ;;
+ esac
+else
+ enable_omfile_hardened=no
+
+fi
+
+ if test x$enable_omfile_hardened = xyes; then
+ ENABLE_OMFILE_HARDENED_TRUE=
+ ENABLE_OMFILE_HARDENED_FALSE='#'
+else
+ ENABLE_OMFILE_HARDENED_TRUE='#'
+ ENABLE_OMFILE_HARDENED_FALSE=
+fi
+
+
+
+# RELP support
+# Check whether --enable-relp was given.
+if test "${enable_relp+set}" = set; then :
+ enableval=$enable_relp; case "${enableval}" in
+ yes) enable_relp="yes" ;;
+ no) enable_relp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-relp" "$LINENO" 5 ;;
+ esac
+else
+ enable_relp=no
+
+fi
+
+if test "x$enable_relp" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RELP" >&5
+$as_echo_n "checking for RELP... " >&6; }
+
+if test -n "$RELP_CFLAGS"; then
+ pkg_cv_RELP_CFLAGS="$RELP_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"relp >= 1.2.14\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "relp >= 1.2.14") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RELP_CFLAGS=`$PKG_CONFIG --cflags "relp >= 1.2.14" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$RELP_LIBS"; then
+ pkg_cv_RELP_LIBS="$RELP_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"relp >= 1.2.14\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "relp >= 1.2.14") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RELP_LIBS=`$PKG_CONFIG --libs "relp >= 1.2.14" 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
+ RELP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "relp >= 1.2.14" 2>&1`
+ else
+ RELP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "relp >= 1.2.14" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$RELP_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (relp >= 1.2.14) were not met:
+
+$RELP_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables RELP_CFLAGS
+and RELP_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables RELP_CFLAGS
+and RELP_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ RELP_CFLAGS=$pkg_cv_RELP_CFLAGS
+ RELP_LIBS=$pkg_cv_RELP_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+$as_echo "#define ENABLE_RELP 1" >>confdefs.h
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $RELP_CFLAGS"
+ LIBS="$LIBS $RELP_LIBS"
+ # Export RELP Version for testbench tools
+ RELP_VERSION="$(pkg-config --modversion relp)"
+
+cat >>confdefs.h <<_ACEOF
+#define RELP_VERSION "${RELP_VERSION}"
+_ACEOF
+
+
+ ac_fn_c_check_func "$LINENO" "relpSrvSetOversizeMode" "ac_cv_func_relpSrvSetOversizeMode"
+if test "x$ac_cv_func_relpSrvSetOversizeMode" = xyes; then :
+
+$as_echo "#define HAVE_RELPSRVSETOVERSIZEMODE 1" >>confdefs.h
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "relpSrvSetLstnAddr" "ac_cv_func_relpSrvSetLstnAddr"
+if test "x$ac_cv_func_relpSrvSetLstnAddr" = xyes; then :
+
+$as_echo "#define HAVE_RELPSRVSETLSTNADDR 1" >>confdefs.h
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "relpEngineSetTLSLibByName" "ac_cv_func_relpEngineSetTLSLibByName"
+if test "x$ac_cv_func_relpEngineSetTLSLibByName" = xyes; then :
+
+$as_echo "#define HAVE_RELPENGINESETTLSLIBBYNAME 1" >>confdefs.h
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "relpSrvSetTlsConfigCmd" "ac_cv_func_relpSrvSetTlsConfigCmd"
+if test "x$ac_cv_func_relpSrvSetTlsConfigCmd" = xyes; then :
+
+$as_echo "#define HAVE_RELPENGINESETTLSCFGCMD 1" >>confdefs.h
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "relpSrvSetTlsConfigCmd" "ac_cv_func_relpSrvSetTlsConfigCmd"
+if test "x$ac_cv_func_relpSrvSetTlsConfigCmd" = xyes; then :
+ HAVE_RELPENGINESETTLSCFGCMD=1
+fi
+
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+ if test x$enable_relp = xyes; then
+ ENABLE_RELP_TRUE=
+ ENABLE_RELP_FALSE='#'
+else
+ ENABLE_RELP_TRUE='#'
+ ENABLE_RELP_FALSE=
+fi
+
+ if test "x$HAVE_RELPENGINESETTLSCFGCMD" = x1; then
+ USE_RELPENGINESETTLSCFGCMD_TRUE=
+ USE_RELPENGINESETTLSCFGCMD_FALSE='#'
+else
+ USE_RELPENGINESETTLSCFGCMD_TRUE='#'
+ USE_RELPENGINESETTLSCFGCMD_FALSE=
+fi
+
+
+# RELP default port
+# Check whether --enable-omrelp-default-port was given.
+if test "${enable_omrelp_default_port+set}" = set; then :
+ enableval=$enable_omrelp_default_port;
+cat >>confdefs.h <<_ACEOF
+#define RELP_DFLT_PT "${enableval}"
+_ACEOF
+
+else
+
+$as_echo "#define RELP_DFLT_PT \"514\"" >>confdefs.h
+
+
+fi
+
+
+
+
+# GuardTime KSI LOGSIG 12 support
+# Check whether --enable-ksi-ls12 was given.
+if test "${enable_ksi_ls12+set}" = set; then :
+ enableval=$enable_ksi_ls12; case "${enableval}" in
+ yes) enable_ksi_ls12="yes" ;;
+ no) enable_ksi_ls12="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-ksi-ls12" "$LINENO" 5 ;;
+ esac
+else
+ enable_ksi_ls12=no
+
+fi
+
+if test "x$enable_ksi_ls12" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GT_KSI_LS12" >&5
+$as_echo_n "checking for GT_KSI_LS12... " >&6; }
+
+if test -n "$GT_KSI_LS12_CFLAGS"; then
+ pkg_cv_GT_KSI_LS12_CFLAGS="$GT_KSI_LS12_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libksi >= 3.19.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libksi >= 3.19.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GT_KSI_LS12_CFLAGS=`$PKG_CONFIG --cflags "libksi >= 3.19.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GT_KSI_LS12_LIBS"; then
+ pkg_cv_GT_KSI_LS12_LIBS="$GT_KSI_LS12_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libksi >= 3.19.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libksi >= 3.19.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GT_KSI_LS12_LIBS=`$PKG_CONFIG --libs "libksi >= 3.19.0" 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
+ GT_KSI_LS12_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libksi >= 3.19.0" 2>&1`
+ else
+ GT_KSI_LS12_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libksi >= 3.19.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GT_KSI_LS12_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libksi >= 3.19.0) were not met:
+
+$GT_KSI_LS12_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GT_KSI_LS12_CFLAGS
+and GT_KSI_LS12_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables GT_KSI_LS12_CFLAGS
+and GT_KSI_LS12_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ GT_KSI_LS12_CFLAGS=$pkg_cv_GT_KSI_LS12_CFLAGS
+ GT_KSI_LS12_LIBS=$pkg_cv_GT_KSI_LS12_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_ksi_ls12 = xyes; then
+ ENABLE_KSI_LS12_TRUE=
+ ENABLE_KSI_LS12_FALSE='#'
+else
+ ENABLE_KSI_LS12_TRUE='#'
+ ENABLE_KSI_LS12_FALSE=
+fi
+
+
+# liblogging-stdlog support
+# we use liblogging-stdlog inside the testbench, which is why we need to check for it in any case
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLOGGING_STDLOG" >&5
+$as_echo_n "checking for LIBLOGGING_STDLOG... " >&6; }
+
+if test -n "$LIBLOGGING_STDLOG_CFLAGS"; then
+ pkg_cv_LIBLOGGING_STDLOG_CFLAGS="$LIBLOGGING_STDLOG_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblogging-stdlog >= 1.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblogging-stdlog >= 1.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGGING_STDLOG_CFLAGS=`$PKG_CONFIG --cflags "liblogging-stdlog >= 1.0.3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLOGGING_STDLOG_LIBS"; then
+ pkg_cv_LIBLOGGING_STDLOG_LIBS="$LIBLOGGING_STDLOG_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblogging-stdlog >= 1.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblogging-stdlog >= 1.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGGING_STDLOG_LIBS=`$PKG_CONFIG --libs "liblogging-stdlog >= 1.0.3" 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
+ LIBLOGGING_STDLOG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblogging-stdlog >= 1.0.3" 2>&1`
+ else
+ LIBLOGGING_STDLOG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblogging-stdlog >= 1.0.3" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLOGGING_STDLOG_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: liblogging-stdlog not found, parts of the testbench will not run" >&5
+$as_echo "$as_me: liblogging-stdlog not found, parts of the testbench will not run" >&6;}
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: liblogging-stdlog not found, parts of the testbench will not run" >&5
+$as_echo "$as_me: liblogging-stdlog not found, parts of the testbench will not run" >&6;}
+
+else
+ LIBLOGGING_STDLOG_CFLAGS=$pkg_cv_LIBLOGGING_STDLOG_CFLAGS
+ LIBLOGGING_STDLOG_LIBS=$pkg_cv_LIBLOGGING_STDLOG_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LIBLOGGING_STDLOG 1" >>confdefs.h
+
+ found_liblogging_stdlog="yes"
+fi
+
+# Check whether --enable-liblogging-stdlog was given.
+if test "${enable_liblogging_stdlog+set}" = set; then :
+ enableval=$enable_liblogging_stdlog; case "${enableval}" in
+ yes) enable_liblogging_stdlog="yes" ;;
+ no) enable_liblogging_stdlog="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-liblogging-stdlog" "$LINENO" 5 ;;
+ esac
+else
+ enable_liblogging_stdlog=no
+
+fi
+
+if test "x$enable_liblogging_stdlog" = "xyes" -a "x$found_liblogging_stdlog" != "xyes"; then
+ as_fn_error $? "--enable-liblogging-stdlog set but liblogging-stdlog was not found" "$LINENO" 5
+fi
+ if test "x$enable_liblogging_stdlog" = "xyes"; then
+ ENABLE_LIBLOGGING_STDLOG_TRUE=
+ ENABLE_LIBLOGGING_STDLOG_FALSE='#'
+else
+ ENABLE_LIBLOGGING_STDLOG_TRUE='#'
+ ENABLE_LIBLOGGING_STDLOG_FALSE=
+fi
+
+
+# RFC 3195 support
+# Check whether --enable-rfc3195 was given.
+if test "${enable_rfc3195+set}" = set; then :
+ enableval=$enable_rfc3195; case "${enableval}" in
+ yes) enable_rfc3195="yes" ;;
+ no) enable_rfc3195="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-rfc3195" "$LINENO" 5 ;;
+ esac
+else
+ enable_rfc3195=no
+
+fi
+
+if test "x$enable_rfc3195" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLOGGING" >&5
+$as_echo_n "checking for LIBLOGGING... " >&6; }
+
+if test -n "$LIBLOGGING_CFLAGS"; then
+ pkg_cv_LIBLOGGING_CFLAGS="$LIBLOGGING_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblogging-rfc3195 >= 1.0.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblogging-rfc3195 >= 1.0.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGGING_CFLAGS=`$PKG_CONFIG --cflags "liblogging-rfc3195 >= 1.0.1" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLOGGING_LIBS"; then
+ pkg_cv_LIBLOGGING_LIBS="$LIBLOGGING_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblogging-rfc3195 >= 1.0.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblogging-rfc3195 >= 1.0.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGGING_LIBS=`$PKG_CONFIG --libs "liblogging-rfc3195 >= 1.0.1" 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
+ LIBLOGGING_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblogging-rfc3195 >= 1.0.1" 2>&1`
+ else
+ LIBLOGGING_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblogging-rfc3195 >= 1.0.1" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLOGGING_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (liblogging-rfc3195 >= 1.0.1) were not met:
+
+$LIBLOGGING_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBLOGGING_CFLAGS
+and LIBLOGGING_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBLOGGING_CFLAGS
+and LIBLOGGING_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBLOGGING_CFLAGS=$pkg_cv_LIBLOGGING_CFLAGS
+ LIBLOGGING_LIBS=$pkg_cv_LIBLOGGING_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_rfc3195 = xyes; then
+ ENABLE_RFC3195_TRUE=
+ ENABLE_RFC3195_FALSE='#'
+else
+ ENABLE_RFC3195_TRUE='#'
+ ENABLE_RFC3195_FALSE=
+fi
+
+
+
+# enable/disable the testbench (e.g. because some important parts
+# are missing)
+# Check whether --enable-testbench was given.
+if test "${enable_testbench+set}" = set; then :
+ enableval=$enable_testbench; case "${enableval}" in
+ yes) enable_testbench="yes" ;;
+ no) enable_testbench="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-testbench" "$LINENO" 5 ;;
+ esac
+else
+ enable_testbench=no
+
+fi
+
+
+# Add a capability to turn off libfaketime tests. Unfortunately, libfaketime
+# becomes more and more problematic in newer versions and causes aborts
+# on some platforms. This provides the ability to turn it off. In the
+# longer term, we should consider writing our own replacement.
+# Check whether --enable-libfaketime was given.
+if test "${enable_libfaketime+set}" = set; then :
+ enableval=$enable_libfaketime; case "${enableval}" in
+ yes) enable_libfaketime="yes" ;;
+ no) enable_libfaketime="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-libfaketime" "$LINENO" 5 ;;
+ esac
+else
+ enable_libfaketime=no
+
+fi
+
+ if test "x${enable_libfaketime}" = "xyes"; then
+ ENABLE_LIBFAKETIME_TRUE=
+ ENABLE_LIBFAKETIME_FALSE='#'
+else
+ ENABLE_LIBFAKETIME_TRUE='#'
+ ENABLE_LIBFAKETIME_FALSE=
+fi
+
+
+# this permits to control the "default tests" in testbench runs. These
+# are those tests that do not need a special configure option. There are
+# some situations where we really want to turn them of so that we can
+# run tests only for a specific component (e.g. ElasticSearch).
+# This also enables us to do some parallel testing even while the
+# testbench is not yet able to support make -j check
+# Check whether --enable-default-tests was given.
+if test "${enable_default_tests+set}" = set; then :
+ enableval=$enable_default_tests; case "${enableval}" in
+ yes) enable_default_tests="yes" ;;
+ no) enable_default_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-default-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_default_tests=yes
+
+fi
+
+ if test "x${enable_default_tests}" = "xyes"; then
+ ENABLE_DEFAULT_TESTS_TRUE=
+ ENABLE_DEFAULT_TESTS_FALSE='#'
+else
+ ENABLE_DEFAULT_TESTS_TRUE='#'
+ ENABLE_DEFAULT_TESTS_FALSE=
+fi
+
+
+# Extract the first word of "ip", so it can be a program name with args.
+set dummy ip; 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_IP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$IP"; then
+ ac_cv_prog_IP="$IP" # 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_IP="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_IP" && ac_cv_prog_IP="no"
+fi
+fi
+IP=$ac_cv_prog_IP
+if test -n "$IP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IP" >&5
+$as_echo "$IP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x${IP}" = "xno"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Will not check network namespace functionality as 'ip' (part of iproute2) is not available." >&5
+$as_echo "$as_me: Will not check network namespace functionality as 'ip' (part of iproute2) is not available." >&6;}
+fi
+ if test "x${IP}" = "xyes"; then
+ ENABLE_IP_TRUE=
+ ENABLE_IP_FALSE='#'
+else
+ ENABLE_IP_TRUE='#'
+ ENABLE_IP_FALSE=
+fi
+
+
+
+# valgrind-testbench
+
+# Check whether --with-valgrind_testbench was given.
+if test "${with_valgrind_testbench+set}" = set; then :
+ withval=$with_valgrind_testbench;
+fi
+
+
+if test "x$with_valgrind_testbench" != "xno"; then
+ # Extract the first word of "valgrind", so it can be a program name with args.
+set dummy valgrind; 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_VALGRIND+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$VALGRIND"; then
+ ac_cv_prog_VALGRIND="$VALGRIND" # 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_VALGRIND="valgrind"
+ $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_VALGRIND" && ac_cv_prog_VALGRIND="no"
+fi
+fi
+VALGRIND=$ac_cv_prog_VALGRIND
+if test -n "$VALGRIND"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND" >&5
+$as_echo "$VALGRIND" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+ if test "x$enable_testbench" = "xyes" && test "x$VALGRIND" = "xno"; then
+ if test "x$with_valgrind_testbench" = "xyes"; then
+ as_fn_error $? "valgrind is missing but forced with --with-valgrind-testbench. Either install valgrind or remove the option!" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: valgrind is missing -- testbench won't use valgrind!" >&5
+$as_echo "$as_me: WARNING: valgrind is missing -- testbench won't use valgrind!" >&2;}
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: testbench will use valgrind" >&5
+$as_echo "$as_me: testbench will use valgrind" >&6;}
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: testbench won't use valgrind due to set --without-valgrind-testbench option" >&5
+$as_echo "$as_me: testbench won't use valgrind due to set --without-valgrind-testbench option" >&6;}
+fi
+ if test "x$with_valgrind_testbench" != "xno" && test "x$VALGRIND" != "xno"; then
+ HAVE_VALGRIND_TRUE=
+ HAVE_VALGRIND_FALSE='#'
+else
+ HAVE_VALGRIND_TRUE='#'
+ HAVE_VALGRIND_FALSE=
+fi
+
+
+# ability to disable helgrind tests - we at least need this for
+# clang coverage reports, where we cannot suppress the races
+# Check whether --enable-helgrind was given.
+if test "${enable_helgrind+set}" = set; then :
+ enableval=$enable_helgrind; case "${enableval}" in
+ yes) enable_helgrind="yes" ;;
+ no) enable_helgrind="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-helgrind" "$LINENO" 5 ;;
+ esac
+else
+ enable_helgrind=yes
+
+fi
+
+ if test x$enable_helgrind = xyes; then
+ ENABLE_HELGRIND_TRUE=
+ ENABLE_HELGRIND_FALSE='#'
+else
+ ENABLE_HELGRIND_TRUE='#'
+ ENABLE_HELGRIND_FALSE=
+fi
+
+
+# settings for the batch report input module
+# Check whether --enable-imbatchreport was given.
+if test "${enable_imbatchreport+set}" = set; then :
+ enableval=$enable_imbatchreport; case "${enableval}" in
+ yes) enable_imbatchreport="yes" ;;
+ no) enable_imbatchreport="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imbatchreport" "$LINENO" 5 ;;
+ esac
+else
+ enable_imbatchreport=no
+
+fi
+
+ if test x$enable_imbatchreport = xyes; then
+ ENABLE_IMBATCHREPORT_TRUE=
+ ENABLE_IMBATCHREPORT_FALSE='#'
+else
+ ENABLE_IMBATCHREPORT_TRUE='#'
+ ENABLE_IMBATCHREPORT_FALSE=
+fi
+
+
+# settings for the db2diag parser module
+# Check whether --enable-pmdb2diag was given.
+if test "${enable_pmdb2diag+set}" = set; then :
+ enableval=$enable_pmdb2diag; case "${enableval}" in
+ yes) enable_pmdb2diag="yes" ;;
+ no) enable_pmdb2diag="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmdb2diag" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmdb2diag=no
+
+fi
+
+ if test x$enable_pmdb2diag = xyes; then
+ ENABLE_PMDB2DIAG_TRUE=
+ ENABLE_PMDB2DIAG_FALSE='#'
+else
+ ENABLE_PMDB2DIAG_TRUE='#'
+ ENABLE_PMDB2DIAG_FALSE=
+fi
+
+
+# settings for the file input module
+# Check whether --enable-imfile was given.
+if test "${enable_imfile+set}" = set; then :
+ enableval=$enable_imfile; case "${enableval}" in
+ yes) enable_imfile="yes" ;;
+ no) enable_imfile="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imfile" "$LINENO" 5 ;;
+ esac
+else
+ enable_imfile=no
+
+fi
+
+if test "x$enable_imfile" = "xyes"; then
+ for ac_func in port_create
+do :
+ ac_fn_c_check_func "$LINENO" "port_create" "ac_cv_func_port_create"
+if test "x$ac_cv_func_port_create" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_PORT_CREATE 1
+_ACEOF
+
+fi
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris File Events Notification API support" >&5
+$as_echo_n "checking for Solaris File Events Notification API support... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <port.h>
+ #include <sys/port.h>
+
+int
+main ()
+{
+
+ return PORT_SOURCE_FILE;
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_PORT_SOURCE_FILE 1" >>confdefs.h
+
+ { $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
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ if test x$enable_imfile = xyes; then
+ ENABLE_IMFILE_TRUE=
+ ENABLE_IMFILE_FALSE='#'
+else
+ ENABLE_IMFILE_TRUE='#'
+ ENABLE_IMFILE_FALSE=
+fi
+
+
+# Check whether --enable-imfile-tests was given.
+if test "${enable_imfile_tests+set}" = set; then :
+ enableval=$enable_imfile_tests; case "${enableval}" in
+ yes) enable_imfile_tests="yes" ;;
+ no) enable_imfile_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imfile-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_imfile_tests=yes
+
+fi
+
+if [ "$enable_imfile_tests" == "yes" ] && [ "$enable_imfile" != "yes" ]; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: imfile-tests can not be enabled without imfile support. Disabling imfile tests..." >&5
+$as_echo "$as_me: WARNING: imfile-tests can not be enabled without imfile support. Disabling imfile tests..." >&2;}
+ enable_imfile_tests="no"
+fi
+ if test x$enable_imfile_tests = xyes; then
+ ENABLE_IMFILE_TESTS_TRUE=
+ ENABLE_IMFILE_TESTS_FALSE='#'
+else
+ ENABLE_IMFILE_TESTS_TRUE='#'
+ ENABLE_IMFILE_TESTS_FALSE=
+fi
+
+
+
+# settings for the docker log input module
+# Check whether --enable-imdocker was given.
+if test "${enable_imdocker+set}" = set; then :
+ enableval=$enable_imdocker; case "${enableval}" in
+ yes) enable_imdocker="yes" ;;
+ no) enable_imdocker="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imdocker" "$LINENO" 5 ;;
+ esac
+else
+ enable_imdocker=no
+
+fi
+
+if test "x$enable_imdocker" = "xyes"; then
+ 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
+
+fi
+
+done
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.40.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl >= 7.40.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl >= 7.40.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.40.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl >= 7.40.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl >= 7.40.0" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl >= 7.40.0" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl >= 7.40.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl >= 7.40.0) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_imdocker = xyes; then
+ ENABLE_IMDOCKER_TRUE=
+ ENABLE_IMDOCKER_FALSE='#'
+else
+ ENABLE_IMDOCKER_TRUE='#'
+ ENABLE_IMDOCKER_FALSE=
+fi
+
+
+# Check whether --enable-imdocker-tests was given.
+if test "${enable_imdocker_tests+set}" = set; then :
+ enableval=$enable_imdocker_tests; case "${enableval}" in
+ yes) enable_imdocker_tests="yes" ;;
+ no) enable_imdocker_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imdocker-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_imdocker_tests=no
+
+fi
+
+
+ if test x$enable_imdocker_tests = xyes; then
+ ENABLE_IMDOCKER_TESTS_TRUE=
+ ENABLE_IMDOCKER_TESTS_FALSE='#'
+else
+ ENABLE_IMDOCKER_TESTS_TRUE='#'
+ ENABLE_IMDOCKER_TESTS_FALSE=
+fi
+
+
+
+# settings for the tuxedo ULOG input module
+# Check whether --enable-imtuxedoulog was given.
+if test "${enable_imtuxedoulog+set}" = set; then :
+ enableval=$enable_imtuxedoulog; case "${enableval}" in
+ yes) enable_imtuxedoulog="yes" ;;
+ no) enable_imtuxedoulog="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imtuxedoulog" "$LINENO" 5 ;;
+ esac
+else
+ enable_imtuxedoulog=no
+
+fi
+
+ if test x$enable_imtuxedoulog = xyes; then
+ ENABLE_IMTUXEDOULOG_TRUE=
+ ENABLE_IMTUXEDOULOG_FALSE='#'
+else
+ ENABLE_IMTUXEDOULOG_TRUE='#'
+ ENABLE_IMTUXEDOULOG_FALSE=
+fi
+
+
+# settings for the external program input module
+# Check whether --enable-improg was given.
+if test "${enable_improg+set}" = set; then :
+ enableval=$enable_improg; case "${enableval}" in
+ yes) enable_improg="yes" ;;
+ no) enable_improg="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-improg" "$LINENO" 5 ;;
+ esac
+else
+ enable_improg=no
+
+fi
+
+ if test x$enable_improg = xyes; then
+ ENABLE_IMPROG_TRUE=
+ ENABLE_IMPROG_FALSE='#'
+else
+ ENABLE_IMPROG_TRUE='#'
+ ENABLE_IMPROG_FALSE=
+fi
+
+
+# settings for the external http input module
+# Check whether --enable-imhttp was given.
+if test "${enable_imhttp+set}" = set; then :
+ enableval=$enable_imhttp; case "${enableval}" in
+ yes) enable_imhttp="yes" ;;
+ no) enable_imhttp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imhttp" "$LINENO" 5 ;;
+ esac
+else
+ enable_imhttp=no
+
+fi
+
+if test "x$enable_imhttp" = "xyes"; then
+ for ac_header in civetweb.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "civetweb.h" "ac_cv_header_civetweb_h" "$ac_includes_default"
+if test "x$ac_cv_header_civetweb_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_CIVETWEB_H 1
+_ACEOF
+
+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 $? "civetweb is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing mg_version" >&5
+$as_echo_n "checking for library containing mg_version... " >&6; }
+if ${ac_cv_search_mg_version+:} 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 mg_version ();
+int
+main ()
+{
+return mg_version ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' civetweb; 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_mg_version=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_mg_version+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_mg_version+:} false; then :
+
+else
+ ac_cv_search_mg_version=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_mg_version" >&5
+$as_echo "$ac_cv_search_mg_version" >&6; }
+ac_res=$ac_cv_search_mg_version
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for APU" >&5
+$as_echo_n "checking for APU... " >&6; }
+
+if test -n "$APU_CFLAGS"; then
+ pkg_cv_APU_CFLAGS="$APU_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"apr-util-1 >= 1.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "apr-util-1 >= 1.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_APU_CFLAGS=`$PKG_CONFIG --cflags "apr-util-1 >= 1.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$APU_LIBS"; then
+ pkg_cv_APU_LIBS="$APU_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"apr-util-1 >= 1.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "apr-util-1 >= 1.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_APU_LIBS=`$PKG_CONFIG --libs "apr-util-1 >= 1.0" 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
+ APU_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "apr-util-1 >= 1.0" 2>&1`
+ else
+ APU_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "apr-util-1 >= 1.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$APU_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (apr-util-1 >= 1.0) were not met:
+
+$APU_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables APU_CFLAGS
+and APU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables APU_CFLAGS
+and APU_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ APU_CFLAGS=$pkg_cv_APU_CFLAGS
+ APU_LIBS=$pkg_cv_APU_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $APU_CFLAGS"
+ LIBS="$LIBS $APU_LIBS"
+
+ for ac_header in apr_md5.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "apr_md5.h" "ac_cv_header_apr_md5_h" "$ac_includes_default"
+if test "x$ac_cv_header_apr_md5_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_APR_MD5_H 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_header in apr_base64.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "apr_base64.h" "ac_cv_header_apr_base64_h" "$ac_includes_default"
+if test "x$ac_cv_header_apr_base64_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_APR_BASE64_H 1
+_ACEOF
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing apr_base64_decode" >&5
+$as_echo_n "checking for library containing apr_base64_decode... " >&6; }
+if ${ac_cv_search_apr_base64_decode+:} 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 apr_base64_decode ();
+int
+main ()
+{
+return apr_base64_decode ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' aprutil-1; 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_apr_base64_decode=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_apr_base64_decode+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_apr_base64_decode+:} false; then :
+
+else
+ ac_cv_search_apr_base64_decode=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_apr_base64_decode" >&5
+$as_echo "$ac_cv_search_apr_base64_decode" >&6; }
+ac_res=$ac_cv_search_apr_base64_decode
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing apr_password_validate" >&5
+$as_echo_n "checking for library containing apr_password_validate... " >&6; }
+if ${ac_cv_search_apr_password_validate+:} 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 apr_password_validate ();
+int
+main ()
+{
+return apr_password_validate ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' aprutil-1; 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_apr_password_validate=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_apr_password_validate+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_apr_password_validate+:} false; then :
+
+else
+ ac_cv_search_apr_password_validate=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_apr_password_validate" >&5
+$as_echo "$ac_cv_search_apr_password_validate" >&6; }
+ac_res=$ac_cv_search_apr_password_validate
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+ CIVETWEB_LIBS=-lcivetweb
+
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+ if test x$enable_imhttp = xyes; then
+ ENABLE_IMHTTP_TRUE=
+ ENABLE_IMHTTP_FALSE='#'
+else
+ ENABLE_IMHTTP_TRUE='#'
+ ENABLE_IMHTTP_FALSE=
+fi
+
+
+# settings for the door input module (under solaris, thus default off)
+# Check whether --enable-imsolaris was given.
+if test "${enable_imsolaris+set}" = set; then :
+ enableval=$enable_imsolaris; case "${enableval}" in
+ yes) enable_imsolaris="yes" ;;
+ no) enable_imsolaris="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imsolaris" "$LINENO" 5 ;;
+ esac
+else
+ enable_imsolaris=no
+
+fi
+
+ if test x$enable_imsolaris = xyes; then
+ ENABLE_IMSOLARIS_TRUE=
+ ENABLE_IMSOLARIS_FALSE='#'
+else
+ ENABLE_IMSOLARIS_TRUE='#'
+ ENABLE_IMSOLARIS_FALSE=
+fi
+
+
+# settings for the ptcp input module
+# Check whether --enable-imptcp was given.
+if test "${enable_imptcp+set}" = set; then :
+ enableval=$enable_imptcp; case "${enableval}" in
+ yes) enable_imptcp="yes" ;;
+ no) enable_imptcp="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imptcp" "$LINENO" 5 ;;
+ esac
+else
+ enable_imptcp=no
+
+fi
+
+ if test x$enable_imptcp = xyes; then
+ ENABLE_IMPTCP_TRUE=
+ ENABLE_IMPTCP_FALSE='#'
+else
+ ENABLE_IMPTCP_TRUE='#'
+ ENABLE_IMPTCP_FALSE=
+fi
+
+
+
+# settings for the pstats input module
+# Check whether --enable-impstats was given.
+if test "${enable_impstats+set}" = set; then :
+ enableval=$enable_impstats; case "${enableval}" in
+ yes) enable_impstats="yes" ;;
+ no) enable_impstats="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-impstats" "$LINENO" 5 ;;
+ esac
+else
+ enable_impstats=no
+
+fi
+
+ if test x$enable_impstats = xyes; then
+ ENABLE_IMPSTATS_TRUE=
+ ENABLE_IMPSTATS_FALSE='#'
+else
+ ENABLE_IMPSTATS_TRUE='#'
+ ENABLE_IMPSTATS_FALSE=
+fi
+
+
+# settings for the pcap input module
+# Check whether --enable-impcap was given.
+if test "${enable_impcap+set}" = set; then :
+ enableval=$enable_impcap; case "${enableval}" in
+ yes) enable_impcap="yes" ;;
+ no) enable_impcap="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-impcap" "$LINENO" 5 ;;
+ esac
+else
+ enable_impcap=no
+
+fi
+
+
+if test "x$enable_impcap" = "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
+ { $as_echo "$as_me:${as_lineno-$LINENO}: pcap found" >&5
+$as_echo "$as_me: pcap found" >&6;}
+else
+ as_fn_error $? "libpcap library and headers not found" "$LINENO" 5
+
+fi
+
+done
+
+fi
+ if test x$enable_impcap = xyes; then
+ ENABLE_IMPCAP_TRUE=
+ ENABLE_IMPCAP_FALSE='#'
+else
+ ENABLE_IMPCAP_TRUE='#'
+ ENABLE_IMPCAP_FALSE=
+fi
+
+
+# settings for the omprog output module
+# Check whether --enable-omprog was given.
+if test "${enable_omprog+set}" = set; then :
+ enableval=$enable_omprog; case "${enableval}" in
+ yes) enable_omprog="yes" ;;
+ no) enable_omprog="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omprog" "$LINENO" 5 ;;
+ esac
+else
+ enable_omprog=no
+
+fi
+
+ if test x$enable_omprog = xyes; then
+ ENABLE_OMPROG_TRUE=
+ ENABLE_OMPROG_FALSE='#'
+else
+ ENABLE_OMPROG_TRUE='#'
+ ENABLE_OMPROG_FALSE=
+fi
+
+
+
+# settings for omudpspoof
+# Check whether --enable-omudpspoof was given.
+if test "${enable_omudpspoof+set}" = set; then :
+ enableval=$enable_omudpspoof; case "${enableval}" in
+ yes) enable_omudpspoof="yes" ;;
+ no) enable_omudpspoof="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omudpspoof" "$LINENO" 5 ;;
+ esac
+else
+ enable_omudpspoof=no
+
+fi
+
+
+if test "x$enable_omudpspoof" = "xyes"; then
+ for ac_header in libnet.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "libnet.h" "ac_cv_header_libnet_h" "$ac_includes_default"
+if test "x$ac_cv_header_libnet_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNET_H 1
+_ACEOF
+
+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 $? "libnet is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnet_init in -lnet" >&5
+$as_echo_n "checking for libnet_init in -lnet... " >&6; }
+if ${ac_cv_lib_net_libnet_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnet $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 libnet_init ();
+int
+main ()
+{
+return libnet_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_net_libnet_init=yes
+else
+ ac_cv_lib_net_libnet_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_net_libnet_init" >&5
+$as_echo "$ac_cv_lib_net_libnet_init" >&6; }
+if test "x$ac_cv_lib_net_libnet_init" = xyes; then :
+ UDPSPOOF_CFLAGS=""
+ UDPSPOOF_LIBS="-lnet"
+
+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 $? "libnet is missing
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+
+fi
+ if test x$enable_omudpspoof = xyes; then
+ ENABLE_OMUDPSPOOF_TRUE=
+ ENABLE_OMUDPSPOOF_FALSE='#'
+else
+ ENABLE_OMUDPSPOOF_TRUE='#'
+ ENABLE_OMUDPSPOOF_FALSE=
+fi
+
+
+
+
+
+# settings for omstdout
+# Check whether --enable-omstdout was given.
+if test "${enable_omstdout+set}" = set; then :
+ enableval=$enable_omstdout; case "${enableval}" in
+ yes) enable_omstdout="yes" ;;
+ no) enable_omstdout="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omstdout" "$LINENO" 5 ;;
+ esac
+else
+ enable_omstdout=no
+
+fi
+
+ if test x$enable_omstdout = xyes; then
+ ENABLE_OMSTDOUT_TRUE=
+ ENABLE_OMSTDOUT_FALSE='#'
+else
+ ENABLE_OMSTDOUT_TRUE='#'
+ ENABLE_OMSTDOUT_FALSE=
+fi
+
+
+ if test x$enable_testbench = xyes; then
+ ENABLE_TESTBENCH_TRUE=
+ ENABLE_TESTBENCH_FALSE='#'
+else
+ ENABLE_TESTBENCH_TRUE='#'
+ ENABLE_TESTBENCH_FALSE=
+fi
+
+if test "x$enable_testbench" = "xyes"; then
+ if test "x$enable_imdiag" != "xyes"; then
+ as_fn_error $? "\"--enable-testbench requires --enable-imdiag\"" "$LINENO" 5
+ fi
+ if test "x$enable_omstdout" != "xyes"; then
+ as_fn_error $? "\"--enable-testbench requires --enable-omstdout\"" "$LINENO" 5
+ fi
+fi
+
+
+# settings for omjournal
+# Check whether --enable-omjournal was given.
+if test "${enable_omjournal+set}" = set; then :
+ enableval=$enable_omjournal; case "${enableval}" in
+ yes) enable_omjournal="yes" ;;
+ no) enable_omjournal="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omjournal" "$LINENO" 5 ;;
+ esac
+else
+ enable_omjournal=no
+
+fi
+
+if test "x$enable_omjournal" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd >= 209 " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209 \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd >= 209 ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd >= 209 " 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd >= 209 " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libsystemd-journal >= 197) were not met:
+
+$LIBSYSTEMD_JOURNAL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_JOURNAL_CFLAGS
+and LIBSYSTEMD_JOURNAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_JOURNAL_CFLAGS
+and LIBSYSTEMD_JOURNAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD_JOURNAL" >&5
+$as_echo_n "checking for LIBSYSTEMD_JOURNAL... " >&6; }
+
+if test -n "$LIBSYSTEMD_JOURNAL_CFLAGS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS="$LIBSYSTEMD_JOURNAL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal >= 197" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBSYSTEMD_JOURNAL_LIBS"; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS="$LIBSYSTEMD_JOURNAL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal >= 197\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libsystemd-journal >= 197") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBSYSTEMD_JOURNAL_LIBS=`$PKG_CONFIG --libs "libsystemd-journal >= 197" 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
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ else
+ LIBSYSTEMD_JOURNAL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal >= 197" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBSYSTEMD_JOURNAL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libsystemd-journal >= 197) were not met:
+
+$LIBSYSTEMD_JOURNAL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_JOURNAL_CFLAGS
+and LIBSYSTEMD_JOURNAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBSYSTEMD_JOURNAL_CFLAGS
+and LIBSYSTEMD_JOURNAL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+else
+ LIBSYSTEMD_JOURNAL_CFLAGS=$pkg_cv_LIBSYSTEMD_JOURNAL_CFLAGS
+ LIBSYSTEMD_JOURNAL_LIBS=$pkg_cv_LIBSYSTEMD_JOURNAL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_omjournal = xyes; then
+ ENABLE_OMJOURNAL_TRUE=
+ ENABLE_OMJOURNAL_FALSE='#'
+else
+ ENABLE_OMJOURNAL_TRUE='#'
+ ENABLE_OMJOURNAL_FALSE=
+fi
+
+
+# capability to enable journal testbench tests. They have very special requirements,
+# so it does not make sense to have them run by default.
+# Also note that as of now, they have a pretty high rate of false positives due
+# to bugs in the journal.
+# see also https://github.com/rsyslog/rsyslog/issues/2931#issuecomment-416914707
+# Check whether --enable-journal_tests was given.
+if test "${enable_journal_tests+set}" = set; then :
+ enableval=$enable_journal_tests; case "${enableval}" in
+ yes) enable_journal_tests="yes" ;;
+ no) enable_journal_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-journal-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_journal_tests=no
+
+fi
+
+ if test x$enable_journal_tests = xyes; then
+ ENABLE_JOURNAL_TESTS_TRUE=
+ ENABLE_JOURNAL_TESTS_FALSE='#'
+else
+ ENABLE_JOURNAL_TESTS_TRUE='#'
+ ENABLE_JOURNAL_TESTS_FALSE=
+fi
+
+
+
+# settings for pmlastmsg
+# Check whether --enable-pmlastmsg was given.
+if test "${enable_pmlastmsg+set}" = set; then :
+ enableval=$enable_pmlastmsg; case "${enableval}" in
+ yes) enable_pmlastmsg="yes" ;;
+ no) enable_pmlastmsg="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmlastmsg" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmlastmsg=no
+
+fi
+
+ if test x$enable_pmlastmsg = xyes; then
+ ENABLE_PMLASTMSG_TRUE=
+ ENABLE_PMLASTMSG_FALSE='#'
+else
+ ENABLE_PMLASTMSG_TRUE='#'
+ ENABLE_PMLASTMSG_FALSE=
+fi
+
+
+
+# settings for pmcisconames
+# Check whether --enable-pmcisconames was given.
+if test "${enable_pmcisconames+set}" = set; then :
+ enableval=$enable_pmcisconames; case "${enableval}" in
+ yes) enable_pmcisconames="yes" ;;
+ no) enable_pmcisconames="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmcisconames" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmcisconames=no
+
+fi
+
+ if test x$enable_pmcisconames = xyes; then
+ ENABLE_PMCISCONAMES_TRUE=
+ ENABLE_PMCISCONAMES_FALSE='#'
+else
+ ENABLE_PMCISCONAMES_TRUE='#'
+ ENABLE_PMCISCONAMES_FALSE=
+fi
+
+
+
+# settings for pmciscoios
+# Check whether --enable-pmciscoios was given.
+if test "${enable_pmciscoios+set}" = set; then :
+ enableval=$enable_pmciscoios; case "${enableval}" in
+ yes) enable_pmciscoios="yes" ;;
+ no) enable_pmciscoios="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmciscoios" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmciscoios=no
+
+fi
+
+ if test x$enable_pmciscoios = xyes; then
+ ENABLE_PMCISCOIOS_TRUE=
+ ENABLE_PMCISCOIOS_FALSE='#'
+else
+ ENABLE_PMCISCOIOS_TRUE='#'
+ ENABLE_PMCISCOIOS_FALSE=
+fi
+
+
+
+# settings for pmnull
+# Check whether --enable-pmnull was given.
+if test "${enable_pmnull+set}" = set; then :
+ enableval=$enable_pmnull; case "${enableval}" in
+ yes) enable_pmnull="yes" ;;
+ no) enable_pmnull="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmnull" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmnull=no
+
+fi
+
+ if test x$enable_pmnull = xyes; then
+ ENABLE_PMNULL_TRUE=
+ ENABLE_PMNULL_FALSE='#'
+else
+ ENABLE_PMNULL_TRUE='#'
+ ENABLE_PMNULL_FALSE=
+fi
+
+
+
+# settings for pmnormalize
+# Check whether --enable-pmnormalize was given.
+if test "${enable_pmnormalize+set}" = set; then :
+ enableval=$enable_pmnormalize; case "${enableval}" in
+ yes) enable_pmnormalize="yes" ;;
+ no) enable_pmnormalize="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmnormalize" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmnormalize=no
+
+fi
+
+ if test x$enable_pmnormalize = xyes; then
+ ENABLE_PMNORMALIZE_TRUE=
+ ENABLE_PMNORMALIZE_FALSE='#'
+else
+ ENABLE_PMNORMALIZE_TRUE='#'
+ ENABLE_PMNORMALIZE_FALSE=
+fi
+
+
+
+# settings for pmaixforwardedfrom
+# Check whether --enable-pmaixforwardedfrom was given.
+if test "${enable_pmaixforwardedfrom+set}" = set; then :
+ enableval=$enable_pmaixforwardedfrom; case "${enableval}" in
+ yes) enable_pmaixforwardedfrom="yes" ;;
+ no) enable_pmaixforwardedfrom="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmaixforwardedfrom" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmaixforwardedfrom=no
+
+fi
+
+ if test x$enable_pmaixforwardedfrom = xyes; then
+ ENABLE_PMAIXFORWARDEDFROM_TRUE=
+ ENABLE_PMAIXFORWARDEDFROM_FALSE='#'
+else
+ ENABLE_PMAIXFORWARDEDFROM_TRUE='#'
+ ENABLE_PMAIXFORWARDEDFROM_FALSE=
+fi
+
+
+
+# settings for pmsnare
+# Check whether --enable-pmsnare was given.
+if test "${enable_pmsnare+set}" = set; then :
+ enableval=$enable_pmsnare; case "${enableval}" in
+ yes) enable_pmsnare="yes" ;;
+ no) enable_pmsnare="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmsnare" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmsnare=no
+
+fi
+
+ if test x$enable_pmsnare = xyes; then
+ ENABLE_PMSNARE_TRUE=
+ ENABLE_PMSNARE_FALSE='#'
+else
+ ENABLE_PMSNARE_TRUE='#'
+ ENABLE_PMSNARE_FALSE=
+fi
+
+
+
+# settings for pmpanngfw
+# Check whether --enable-pmpanngfw was given.
+if test "${enable_pmpanngfw+set}" = set; then :
+ enableval=$enable_pmpanngfw; case "${enableval}" in
+ yes) enable_pmpanngfw="yes" ;;
+ no) enable_pmpanngfw="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-pmpanngfw" "$LINENO" 5 ;;
+ esac
+else
+ enable_pmpanngfw=no
+
+fi
+
+ if test x$enable_pmpanngfw = xyes; then
+ ENABLE_PMPANNGFW_TRUE=
+ ENABLE_PMPANNGFW_FALSE='#'
+else
+ ENABLE_PMPANNGFW_TRUE='#'
+ ENABLE_PMPANNGFW_FALSE=
+fi
+
+
+
+# settings for omruleset
+# Check whether --enable-omruleset was given.
+if test "${enable_omruleset+set}" = set; then :
+ enableval=$enable_omruleset; case "${enableval}" in
+ yes) enable_omruleset="yes" ;;
+ no) enable_omruleset="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omruleset" "$LINENO" 5 ;;
+ esac
+else
+ enable_omruleset=no
+
+fi
+
+ if test x$enable_omruleset = xyes; then
+ ENABLE_OMRULESET_TRUE=
+ ENABLE_OMRULESET_FALSE='#'
+else
+ ENABLE_OMRULESET_TRUE='#'
+ ENABLE_OMRULESET_FALSE=
+fi
+
+
+
+# settings for omuxsock
+# Check whether --enable-omuxsock was given.
+if test "${enable_omuxsock+set}" = set; then :
+ enableval=$enable_omuxsock; case "${enableval}" in
+ yes) enable_omuxsock="yes" ;;
+ no) enable_omuxsock="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omuxsock" "$LINENO" 5 ;;
+ esac
+else
+ enable_omuxsock=no
+
+fi
+
+ if test x$enable_omuxsock = xyes; then
+ ENABLE_OMUXSOCK_TRUE=
+ ENABLE_OMUXSOCK_FALSE='#'
+else
+ ENABLE_OMUXSOCK_TRUE='#'
+ ENABLE_OMUXSOCK_FALSE=
+fi
+
+
+
+# settings for mmsnmptrapd message modification module
+# Check whether --enable-mmsnmptrapd was given.
+if test "${enable_mmsnmptrapd+set}" = set; then :
+ enableval=$enable_mmsnmptrapd; case "${enableval}" in
+ yes) enable_mmsnmptrapd="yes" ;;
+ no) enable_mmsnmptrapd="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmsnmptrapd" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmsnmptrapd=no
+
+fi
+
+ if test x$enable_mmsnmptrapd = xyes; then
+ ENABLE_MMSNMPTRAPD_TRUE=
+ ENABLE_MMSNMPTRAPD_FALSE='#'
+else
+ ENABLE_MMSNMPTRAPD_TRUE='#'
+ ENABLE_MMSNMPTRAPD_FALSE=
+fi
+
+
+
+# settings for the omhdfs;
+# Check whether --enable-omhdfs was given.
+if test "${enable_omhdfs+set}" = set; then :
+ enableval=$enable_omhdfs; case "${enableval}" in
+ yes) enable_omhdfs="yes" ;;
+ no) enable_omhdfs="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omhdfs" "$LINENO" 5 ;;
+ esac
+else
+ enable_omhdfs=no
+
+fi
+
+if test "x$enable_omhdfs"; then
+ for ac_header in hdfs.h hadoop/hdfs.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
+
+fi
+ if test x$enable_omhdfs = xyes; then
+ ENABLE_OMHDFS_TRUE=
+ ENABLE_OMHDFS_FALSE='#'
+else
+ ENABLE_OMHDFS_TRUE='#'
+ ENABLE_OMHDFS_FALSE=
+fi
+
+
+# support for kafka input output
+# Check whether --enable-omkafka was given.
+if test "${enable_omkafka+set}" = set; then :
+ enableval=$enable_omkafka; case "${enableval}" in
+ yes) enable_omkafka="yes" ;;
+ no) enable_omkafka="no" ;;
+ optional) enable_omkafka="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omkafka" "$LINENO" 5 ;;
+ esac
+else
+ enable_omkafka=no
+
+fi
+
+# Check whether --enable-imkafka was given.
+if test "${enable_imkafka+set}" = set; then :
+ enableval=$enable_imkafka; case "${enableval}" in
+ yes) enable_imkafka="yes" ;;
+ no) enable_imkafka="no" ;;
+ optional) enable_imkafka="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imkafka" "$LINENO" 5 ;;
+ esac
+else
+ enable_imkafka=no
+
+fi
+
+
+# Check whether --enable-omazureeventhubs_tests was given.
+if test "${enable_omazureeventhubs_tests+set}" = set; then :
+ enableval=$enable_omazureeventhubs_tests; case "${enableval}" in
+ yes) enable_omazureeventhubs_tests="yes" ;;
+ no) enable_omazureeventhubs_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omazureeventhubs-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_omazureeventhubs_tests=no
+
+fi
+
+ if test x$enable_omazureeventhubs_tests = xyes; then
+ ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE=
+ ENABLE_OMAZUREEVENTHUBS_TESTS_FALSE='#'
+else
+ ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE='#'
+ ENABLE_OMAZUREEVENTHUBS_TESTS_FALSE=
+fi
+
+
+# Check whether --enable-kafka_tests was given.
+if test "${enable_kafka_tests+set}" = set; then :
+ enableval=$enable_kafka_tests; case "${enableval}" in
+ yes) enable_kafka_tests="yes" ;;
+ no) enable_kafka_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-kafka-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_kafka_tests=no
+
+fi
+
+ if test x$enable_kafka_tests = xyes; then
+ ENABLE_KAFKA_TESTS_TRUE=
+ ENABLE_KAFKA_TESTS_FALSE='#'
+else
+ ENABLE_KAFKA_TESTS_TRUE='#'
+ ENABLE_KAFKA_TESTS_FALSE=
+fi
+
+
+# Check whether --enable-kafka_static was given.
+if test "${enable_kafka_static+set}" = set; then :
+ enableval=$enable_kafka_static; case "${enableval}" in
+ yes) enable_kafka_static="yes" ;;
+ no) enable_kafka_static="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-kafka-static" "$LINENO" 5 ;;
+ esac
+else
+ enable_kafka_static=no
+
+fi
+
+ if test x$enable_kafka_static = xyes; then
+ ENABLE_KAFKA_STATIC_TRUE=
+ ENABLE_KAFKA_STATIC_FALSE='#'
+else
+ ENABLE_KAFKA_STATIC_TRUE='#'
+ ENABLE_KAFKA_STATIC_FALSE=
+fi
+
+
+# omkafka works with older library
+omkafka_use_dummy="no"
+if test "$enable_omkafka" = "yes" -o "$enable_omkafka" = "optional"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBRDKAFKA" >&5
+$as_echo_n "checking for LIBRDKAFKA... " >&6; }
+
+if test -n "$LIBRDKAFKA_CFLAGS"; then
+ pkg_cv_LIBRDKAFKA_CFLAGS="$LIBRDKAFKA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_CFLAGS=`$PKG_CONFIG --cflags "rdkafka >= 0.9.1" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBRDKAFKA_LIBS"; then
+ pkg_cv_LIBRDKAFKA_LIBS="$LIBRDKAFKA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_LIBS=`$PKG_CONFIG --libs "rdkafka >= 0.9.1" 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
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "rdkafka >= 0.9.1" 2>&1`
+ else
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "rdkafka >= 0.9.1" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBRDKAFKA_PKG_ERRORS" >&5
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBRDKAFKA" >&5
+$as_echo_n "checking for LIBRDKAFKA... " >&6; }
+
+if test -n "$LIBRDKAFKA_CFLAGS"; then
+ pkg_cv_LIBRDKAFKA_CFLAGS="$LIBRDKAFKA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librdkafka\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librdkafka") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_CFLAGS=`$PKG_CONFIG --cflags "librdkafka" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBRDKAFKA_LIBS"; then
+ pkg_cv_LIBRDKAFKA_LIBS="$LIBRDKAFKA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librdkafka\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librdkafka") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_LIBS=`$PKG_CONFIG --libs "librdkafka" 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
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "librdkafka" 2>&1`
+ else
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "librdkafka" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBRDKAFKA_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_last_error in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_last_error in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_last_error+:} 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_last_error ();
+int
+main ()
+{
+return rd_kafka_last_error ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_last_error=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_last_error=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_last_error" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_last_error" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_last_error" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_omkafka" = "yes"; then :
+ as_fn_error $? "could not find rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: omkafka: no suiteable build environment, use omkafka dummy" >&5
+$as_echo "$as_me: omkafka: no suiteable build environment, use omkafka dummy" >&6;}
+ omkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_OMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_last_error in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_last_error in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_last_error+:} 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_last_error ();
+int
+main ()
+{
+return rd_kafka_last_error ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_last_error=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_last_error=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_last_error" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_last_error" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_last_error" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_omkafka" = "yes"; then :
+ as_fn_error $? "could not find rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: omkafka: no suiteable build environment, use omkafka dummy" >&5
+$as_echo "$as_me: omkafka: no suiteable build environment, use omkafka dummy" >&6;}
+ omkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_OMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+else
+ LIBRDKAFKA_CFLAGS=$pkg_cv_LIBRDKAFKA_CFLAGS
+ LIBRDKAFKA_LIBS=$pkg_cv_LIBRDKAFKA_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBRDKAFKA" >&5
+$as_echo_n "checking for LIBRDKAFKA... " >&6; }
+
+if test -n "$LIBRDKAFKA_CFLAGS"; then
+ pkg_cv_LIBRDKAFKA_CFLAGS="$LIBRDKAFKA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librdkafka\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librdkafka") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_CFLAGS=`$PKG_CONFIG --cflags "librdkafka" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBRDKAFKA_LIBS"; then
+ pkg_cv_LIBRDKAFKA_LIBS="$LIBRDKAFKA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librdkafka\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librdkafka") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_LIBS=`$PKG_CONFIG --libs "librdkafka" 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
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "librdkafka" 2>&1`
+ else
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "librdkafka" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBRDKAFKA_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_last_error in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_last_error in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_last_error+:} 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_last_error ();
+int
+main ()
+{
+return rd_kafka_last_error ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_last_error=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_last_error=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_last_error" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_last_error" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_last_error" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_omkafka" = "yes"; then :
+ as_fn_error $? "could not find rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: omkafka: no suiteable build environment, use omkafka dummy" >&5
+$as_echo "$as_me: omkafka: no suiteable build environment, use omkafka dummy" >&6;}
+ omkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_OMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_last_error in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_last_error in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_last_error+:} 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_last_error ();
+int
+main ()
+{
+return rd_kafka_last_error ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_last_error=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_last_error=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_last_error" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_last_error" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_last_error" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_omkafka" = "yes"; then :
+ as_fn_error $? "could not find rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: omkafka: no suiteable build environment, use omkafka dummy" >&5
+$as_echo "$as_me: omkafka: no suiteable build environment, use omkafka dummy" >&6;}
+ omkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_OMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+else
+ LIBRDKAFKA_CFLAGS=$pkg_cv_LIBRDKAFKA_CFLAGS
+ LIBRDKAFKA_LIBS=$pkg_cv_LIBRDKAFKA_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+else
+ LIBRDKAFKA_CFLAGS=$pkg_cv_LIBRDKAFKA_CFLAGS
+ LIBRDKAFKA_LIBS=$pkg_cv_LIBRDKAFKA_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$omkafka_use_dummy = xyes; then
+ OMKAFKA_USE_DUMMY_TRUE=
+ OMKAFKA_USE_DUMMY_FALSE='#'
+else
+ OMKAFKA_USE_DUMMY_TRUE='#'
+ OMKAFKA_USE_DUMMY_FALSE=
+fi
+
+if test "$enable_omkafka" = "yes" -o "$enable_omkafka" = "optional" && test "$omkafka_use_dummy" = "no"; 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
+
+fi
+
+done
+
+
+ # Add additional dependencies if statically linking rdkafka
+ if test "x$enable_kafka_static" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLZ4" >&5
+$as_echo_n "checking for LIBLZ4... " >&6; }
+
+if test -n "$LIBLZ4_CFLAGS"; then
+ pkg_cv_LIBLZ4_CFLAGS="$LIBLZ4_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLZ4_CFLAGS=`$PKG_CONFIG --cflags "liblz4" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLZ4_LIBS"; then
+ pkg_cv_LIBLZ4_LIBS="$LIBLZ4_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLZ4_LIBS=`$PKG_CONFIG --libs "liblz4" 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
+ LIBLZ4_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblz4" 2>&1`
+ else
+ LIBLZ4_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblz4" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLZ4_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress in -llz4" >&5
+$as_echo_n "checking for LZ4_compress in -llz4... " >&6; }
+if ${ac_cv_lib_lz4_LZ4_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-llz4 $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 LZ4_compress ();
+int
+main ()
+{
+return LZ4_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lz4_LZ4_compress=yes
+else
+ ac_cv_lib_lz4_LZ4_compress=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_lz4_LZ4_compress" >&5
+$as_echo "$ac_cv_lib_lz4_LZ4_compress" >&6; }
+if test "x$ac_cv_lib_lz4_LZ4_compress" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: liblz4 is missing but library present, using -llz4" >&5
+$as_echo "$as_me: WARNING: liblz4 is missing but library present, using -llz4" >&2;}
+ LIBRDKAFKA_LIBS=-llz4
+
+else
+
+ as_fn_error $? "could not find liblz4 library" "$LINENO" 5
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress in -llz4" >&5
+$as_echo_n "checking for LZ4_compress in -llz4... " >&6; }
+if ${ac_cv_lib_lz4_LZ4_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-llz4 $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 LZ4_compress ();
+int
+main ()
+{
+return LZ4_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lz4_LZ4_compress=yes
+else
+ ac_cv_lib_lz4_LZ4_compress=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_lz4_LZ4_compress" >&5
+$as_echo "$ac_cv_lib_lz4_LZ4_compress" >&6; }
+if test "x$ac_cv_lib_lz4_LZ4_compress" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: liblz4 is missing but library present, using -llz4" >&5
+$as_echo "$as_me: WARNING: liblz4 is missing but library present, using -llz4" >&2;}
+ LIBRDKAFKA_LIBS=-llz4
+
+else
+
+ as_fn_error $? "could not find liblz4 library" "$LINENO" 5
+
+fi
+
+
+else
+ LIBLZ4_CFLAGS=$pkg_cv_LIBLZ4_CFLAGS
+ LIBLZ4_LIBS=$pkg_cv_LIBLZ4_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ fi
+fi
+
+imkafka_use_dummy="no"
+# imkafka needs newer library
+if test "x$enable_imkafka" = "xyes" -o "$enable_imkafka" = "optional"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBRDKAFKA" >&5
+$as_echo_n "checking for LIBRDKAFKA... " >&6; }
+
+if test -n "$LIBRDKAFKA_CFLAGS"; then
+ pkg_cv_LIBRDKAFKA_CFLAGS="$LIBRDKAFKA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_CFLAGS=`$PKG_CONFIG --cflags "rdkafka >= 0.9.1" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBRDKAFKA_LIBS"; then
+ pkg_cv_LIBRDKAFKA_LIBS="$LIBRDKAFKA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rdkafka >= 0.9.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rdkafka >= 0.9.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBRDKAFKA_LIBS=`$PKG_CONFIG --libs "rdkafka >= 0.9.1" 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
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "rdkafka >= 0.9.1" 2>&1`
+ else
+ LIBRDKAFKA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "rdkafka >= 0.9.1" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBRDKAFKA_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_consumer_poll in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_consumer_poll in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_consumer_poll+:} 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_consumer_poll ();
+int
+main ()
+{
+return rd_kafka_consumer_poll ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_consumer_poll=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_consumer_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_rdkafka_rd_kafka_consumer_poll" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_consumer_poll" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_consumer_poll" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_imkafka" = "yes"; then :
+ as_fn_error $? "could not find sufficiently current rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: imkafka: no suiteable build environment, use imkafka dummy" >&5
+$as_echo "$as_me: imkafka: no suiteable build environment, use imkafka dummy" >&6;}
+ imkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_IMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_consumer_poll in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_consumer_poll in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_consumer_poll+:} 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_consumer_poll ();
+int
+main ()
+{
+return rd_kafka_consumer_poll ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rdkafka_rd_kafka_consumer_poll=yes
+else
+ ac_cv_lib_rdkafka_rd_kafka_consumer_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_rdkafka_rd_kafka_consumer_poll" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_consumer_poll" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_consumer_poll" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: librdkafka is missing but library present, using -lrdkafka" >&5
+$as_echo "$as_me: WARNING: librdkafka is missing but library present, using -lrdkafka" >&2;}
+ LIBRDKAFKA_LIBS=-lrdkafka
+
+else
+
+ if test "$enable_imkafka" = "yes"; then :
+ as_fn_error $? "could not find sufficiently current rdkafka library" "$LINENO" 5
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: imkafka: no suiteable build environment, use imkafka dummy" >&5
+$as_echo "$as_me: imkafka: no suiteable build environment, use imkafka dummy" >&6;}
+ imkafka_use_dummy=yes
+
+$as_echo "#define ENABLE_IMKAFKA_DUMMY 1" >>confdefs.h
+
+
+fi
+
+
+else
+ LIBRDKAFKA_CFLAGS=$pkg_cv_LIBRDKAFKA_CFLAGS
+ LIBRDKAFKA_LIBS=$pkg_cv_LIBRDKAFKA_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$imkafka_use_dummy = xyes; then
+ IMKAFKA_USE_DUMMY_TRUE=
+ IMKAFKA_USE_DUMMY_FALSE='#'
+else
+ IMKAFKA_USE_DUMMY_TRUE='#'
+ IMKAFKA_USE_DUMMY_FALSE=
+fi
+
+if test "$enable_imkafka" = "yes" -o "$enable_imkafka" = "optional" && test "$imkafka_use_dummy" = "no"; 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
+
+fi
+
+done
+
+
+ # Add additional dependencies if statically linking rdkafka
+ if test "x$enable_kafka_static" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLZ4" >&5
+$as_echo_n "checking for LIBLZ4... " >&6; }
+
+if test -n "$LIBLZ4_CFLAGS"; then
+ pkg_cv_LIBLZ4_CFLAGS="$LIBLZ4_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLZ4_CFLAGS=`$PKG_CONFIG --cflags "liblz4" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLZ4_LIBS"; then
+ pkg_cv_LIBLZ4_LIBS="$LIBLZ4_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLZ4_LIBS=`$PKG_CONFIG --libs "liblz4" 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
+ LIBLZ4_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblz4" 2>&1`
+ else
+ LIBLZ4_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblz4" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLZ4_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress in -llz4" >&5
+$as_echo_n "checking for LZ4_compress in -llz4... " >&6; }
+if ${ac_cv_lib_lz4_LZ4_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-llz4 $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 LZ4_compress ();
+int
+main ()
+{
+return LZ4_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lz4_LZ4_compress=yes
+else
+ ac_cv_lib_lz4_LZ4_compress=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_lz4_LZ4_compress" >&5
+$as_echo "$ac_cv_lib_lz4_LZ4_compress" >&6; }
+if test "x$ac_cv_lib_lz4_LZ4_compress" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: liblz4 is missing but library present, using -llz4" >&5
+$as_echo "$as_me: WARNING: liblz4 is missing but library present, using -llz4" >&2;}
+ LIBRDKAFKA_LIBS=-llz4
+
+else
+
+ as_fn_error $? "could not find liblz4 library" "$LINENO" 5
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress in -llz4" >&5
+$as_echo_n "checking for LZ4_compress in -llz4... " >&6; }
+if ${ac_cv_lib_lz4_LZ4_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-llz4 $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 LZ4_compress ();
+int
+main ()
+{
+return LZ4_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lz4_LZ4_compress=yes
+else
+ ac_cv_lib_lz4_LZ4_compress=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_lz4_LZ4_compress" >&5
+$as_echo "$ac_cv_lib_lz4_LZ4_compress" >&6; }
+if test "x$ac_cv_lib_lz4_LZ4_compress" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: liblz4 is missing but library present, using -llz4" >&5
+$as_echo "$as_me: WARNING: liblz4 is missing but library present, using -llz4" >&2;}
+ LIBRDKAFKA_LIBS=-llz4
+
+else
+
+ as_fn_error $? "could not find liblz4 library" "$LINENO" 5
+
+fi
+
+
+else
+ LIBLZ4_CFLAGS=$pkg_cv_LIBLZ4_CFLAGS
+ LIBLZ4_LIBS=$pkg_cv_LIBLZ4_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ fi
+fi
+
+if test "x$enable_omkafka" = "xyes" && test "x$enable_imkafka" = "xyes"; then
+ if test "x$enable_kafka_tests" = "xyes"; then
+
+if test "x$JAVAPREFIX" = x; then :
+ test "x$JAVAC" = x && for ac_prog in "gcj -C" guavac jikes javac
+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_JAVAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVAC"; then
+ ac_cv_prog_JAVAC="$JAVAC" # 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_JAVAC="$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
+JAVAC=$ac_cv_prog_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
+
+
+ test -n "$JAVAC" && break
+done
+
+else
+ test "x$JAVAC" = x && for ac_prog in "gcj -C" guavac jikes javac
+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_JAVAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVAC"; then
+ ac_cv_prog_JAVAC="$JAVAC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $JAVAPREFIX/bin
+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_JAVAC="$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
+JAVAC=$ac_cv_prog_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
+
+
+ test -n "$JAVAC" && break
+done
+
+fi
+test "x$JAVAC" = x && as_fn_error $? "no acceptable Java compiler found in \$PATH" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVAC works" >&5
+$as_echo_n "checking if $JAVAC works... " >&6; }
+if ${ac_cv_prog_javac_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+cat << \EOF > $JAVA_TEST
+/* #line 27833 "configure" */
+public class Test {
+}
+EOF
+if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } >/dev/null 2>&1; then
+ ac_cv_prog_javac_works=yes
+else
+ as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5
+ echo "configure: failed program was:" >&5
+ cat $JAVA_TEST >&5
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_works" >&5
+$as_echo "$ac_cv_prog_javac_works" >&6; }
+
+ #we don't need javac, but macro documentation says JAVAC *must* be checked before JAVA
+
+if test "x$JAVAPREFIX" = x; then :
+ test x$JAVA = x && for ac_prog in kaffe java
+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_JAVA+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVA"; then
+ ac_cv_prog_JAVA="$JAVA" # 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_JAVA="$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
+JAVA=$ac_cv_prog_JAVA
+if test -n "$JAVA"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5
+$as_echo "$JAVA" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$JAVA" && break
+done
+
+else
+ test x$JAVA = x && for ac_prog in kaffe java
+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_JAVA+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVA"; then
+ ac_cv_prog_JAVA="$JAVA" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $JAVAPREFIX/bin
+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_JAVA="$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
+JAVA=$ac_cv_prog_JAVA
+if test -n "$JAVA"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5
+$as_echo "$JAVA" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$JAVA" && break
+done
+
+fi
+test x$JAVA = x && as_fn_error $? "no acceptable Java virtual machine found in \$PATH" "$LINENO" 5
+
+ if test x$ac_cv_prog_javac_works = xno; then
+ as_fn_error $? "Cannot compile java source. $JAVAC does not work properly" "$LINENO" 5
+ fi
+ if test x$ac_cv_prog_javac_works = x; then
+
+if test "x$JAVAPREFIX" = x; then :
+ test "x$JAVAC" = x && for ac_prog in "gcj -C" guavac jikes javac
+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_JAVAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVAC"; then
+ ac_cv_prog_JAVAC="$JAVAC" # 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_JAVAC="$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
+JAVAC=$ac_cv_prog_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
+
+
+ test -n "$JAVAC" && break
+done
+
+else
+ test "x$JAVAC" = x && for ac_prog in "gcj -C" guavac jikes javac
+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_JAVAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$JAVAC"; then
+ ac_cv_prog_JAVAC="$JAVAC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $JAVAPREFIX/bin
+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_JAVAC="$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
+JAVAC=$ac_cv_prog_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
+
+
+ test -n "$JAVAC" && break
+done
+
+fi
+test "x$JAVAC" = x && as_fn_error $? "no acceptable Java compiler found in \$PATH" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVAC works" >&5
+$as_echo_n "checking if $JAVAC works... " >&6; }
+if ${ac_cv_prog_javac_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+cat << \EOF > $JAVA_TEST
+/* #line 28049 "configure" */
+public class Test {
+}
+EOF
+if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } >/dev/null 2>&1; then
+ ac_cv_prog_javac_works=yes
+else
+ as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5
+ echo "configure: failed program was:" >&5
+ cat $JAVA_TEST >&5
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_works" >&5
+$as_echo "$ac_cv_prog_javac_works" >&6; }
+
+
+ fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVA works" >&5
+$as_echo_n "checking if $JAVA works... " >&6; }
+if ${ac_cv_prog_java_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+JAVA_TEST=Test.java
+CLASS_TEST=Test.class
+TEST=Test
+cat << \EOF > $JAVA_TEST
+/* [#]line 28083 "configure" */
+public class Test {
+public static void main (String args[]) {
+ System.exit (0);
+} }
+EOF
+ if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } && test -s $CLASS_TEST; then
+ :
+ else
+ echo "configure: failed program was:" >&5
+ cat $JAVA_TEST >&5
+ as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5
+ fi
+if { ac_try='$JAVA -classpath . $JAVAFLAGS $TEST'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } >/dev/null 2>&1; then
+ ac_cv_prog_java_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat $JAVA_TEST >&5
+ as_fn_error $? "The Java VM $JAVA failed (see config.log, check the CLASSPATH?)" "$LINENO" 5
+fi
+rm -f $JAVA_TEST $CLASS_TEST
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_java_works" >&5
+$as_echo "$ac_cv_prog_java_works" >&6; }
+
+
+
+ # Extract the first word of "wget", so it can be a program name with args.
+set dummy wget; 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_WGET+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$WGET"; then
+ ac_cv_prog_WGET="$WGET" # 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_WGET="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_WGET" && ac_cv_prog_WGET="no"
+fi
+fi
+WGET=$ac_cv_prog_WGET
+if test -n "$WGET"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5
+$as_echo "$WGET" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${WGET}" = "xno"; 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 $? "wget, which is a kafka-tests dependency, not found
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ # Extract the first word of "readlink", so it can be a program name with args.
+set dummy readlink; 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_READLINK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READLINK"; then
+ ac_cv_prog_READLINK="$READLINK" # 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_READLINK="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_READLINK" && ac_cv_prog_READLINK="no"
+fi
+fi
+READLINK=$ac_cv_prog_READLINK
+if test -n "$READLINK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINK" >&5
+$as_echo "$READLINK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${READLINK}" = "xno"; 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 $? "readlink, which is a kafka-tests dependency, not found
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+else
+ if test "x$enable_kafka_tests" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: kafka-tests can not be enabled without omkafka and imkafka support. Disabling enable_kafka_tests..." >&5
+$as_echo "$as_me: WARNING: kafka-tests can not be enabled without omkafka and imkafka support. Disabling enable_kafka_tests..." >&2;}
+ enable_kafka_tests="no"
+ fi
+fi
+ if test x$enable_omkafka = xyes -o x$enable_omkafka = xoptional; then
+ ENABLE_OMKAFKA_TRUE=
+ ENABLE_OMKAFKA_FALSE='#'
+else
+ ENABLE_OMKAFKA_TRUE='#'
+ ENABLE_OMKAFKA_FALSE=
+fi
+
+ if test x$enable_imkafka = xyes -o x$enable_imkafka = xoptional; then
+ ENABLE_IMKAFKA_TRUE=
+ ENABLE_IMKAFKA_FALSE='#'
+else
+ ENABLE_IMKAFKA_TRUE='#'
+ ENABLE_IMKAFKA_FALSE=
+fi
+
+
+
+# omazureeventhubs support for output module
+# Check whether --enable-omazureeventhubs was given.
+if test "${enable_omazureeventhubs+set}" = set; then :
+ enableval=$enable_omazureeventhubs; case "${enableval}" in
+ yes) enable_omazureeventhubs="yes" ;;
+ no) enable_omazureeventhubs="no" ;;
+ optional) enable_omazureeventhubs="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omazureeventhubs" "$LINENO" 5 ;;
+ esac
+else
+ enable_omazureeventhubs=no
+
+fi
+
+
+# PROTON PROTOCOL SUPPORT for omazureeventhubs
+# uses qpid-proton library
+if test "x$enable_omazureeventhubs" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTON" >&5
+$as_echo_n "checking for PROTON... " >&6; }
+
+if test -n "$PROTON_CFLAGS"; then
+ pkg_cv_PROTON_CFLAGS="$PROTON_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton >= 0.13\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton >= 0.13") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_CFLAGS=`$PKG_CONFIG --cflags "libqpid-proton >= 0.13" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$PROTON_LIBS"; then
+ pkg_cv_PROTON_LIBS="$PROTON_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton >= 0.13\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton >= 0.13") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_LIBS=`$PKG_CONFIG --libs "libqpid-proton >= 0.13" 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
+ PROTON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libqpid-proton >= 0.13" 2>&1`
+ else
+ PROTON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libqpid-proton >= 0.13" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$PROTON_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libqpid-proton >= 0.13) were not met:
+
+$PROTON_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables PROTON_CFLAGS
+and PROTON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables PROTON_CFLAGS
+and PROTON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ PROTON_CFLAGS=$pkg_cv_PROTON_CFLAGS
+ PROTON_LIBS=$pkg_cv_PROTON_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+fi
+if test "x$enable_omazureeventhubs" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTON_PROACTOR" >&5
+$as_echo_n "checking for PROTON_PROACTOR... " >&6; }
+
+if test -n "$PROTON_PROACTOR_CFLAGS"; then
+ pkg_cv_PROTON_PROACTOR_CFLAGS="$PROTON_PROACTOR_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton-proactor >= 0.13\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton-proactor >= 0.13") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_PROACTOR_CFLAGS=`$PKG_CONFIG --cflags "libqpid-proton-proactor >= 0.13" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$PROTON_PROACTOR_LIBS"; then
+ pkg_cv_PROTON_PROACTOR_LIBS="$PROTON_PROACTOR_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton-proactor >= 0.13\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton-proactor >= 0.13") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_PROACTOR_LIBS=`$PKG_CONFIG --libs "libqpid-proton-proactor >= 0.13" 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
+ PROTON_PROACTOR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libqpid-proton-proactor >= 0.13" 2>&1`
+ else
+ PROTON_PROACTOR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libqpid-proton-proactor >= 0.13" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$PROTON_PROACTOR_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libqpid-proton-proactor >= 0.13) were not met:
+
+$PROTON_PROACTOR_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables PROTON_PROACTOR_CFLAGS
+and PROTON_PROACTOR_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables PROTON_PROACTOR_CFLAGS
+and PROTON_PROACTOR_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ PROTON_PROACTOR_CFLAGS=$pkg_cv_PROTON_PROACTOR_CFLAGS
+ PROTON_PROACTOR_LIBS=$pkg_cv_PROTON_PROACTOR_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+fi
+ if test x$enable_omazureeventhubs = xyes; then
+ ENABLE_OMAZUREEVENTHUBS_TRUE=
+ ENABLE_OMAZUREEVENTHUBS_FALSE='#'
+else
+ ENABLE_OMAZUREEVENTHUBS_TRUE='#'
+ ENABLE_OMAZUREEVENTHUBS_FALSE=
+fi
+
+# END PROTON
+
+if test "x$enable_omazureeventhubs" = "xyes"; then
+ if test "x$enable_omazure_tests" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: omazureveenthubs: TEST Suite enabled, requires Azure Environment variables!" >&5
+$as_echo "$as_me: omazureveenthubs: TEST Suite enabled, requires Azure Environment variables!" >&6;}
+ fi
+else
+ if test "x$enable_omazure_tests" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Omazureeventhubs Tests can not be enabled omazureveenthubs support. Disabling enable_omazure_tests..." >&5
+$as_echo "$as_me: WARNING: Omazureeventhubs Tests can not be enabled omazureveenthubs support. Disabling enable_omazure_tests..." >&2;}
+ enable_omazure_tests="no"
+ fi
+fi
+
+# Static QPID-Proton support?
+# Check whether --enable-qpidproton_static was given.
+if test "${enable_qpidproton_static+set}" = set; then :
+ enableval=$enable_qpidproton_static; case "${enableval}" in
+ yes) enable_qpidproton_static="yes" ;;
+ no) enable_qpidproton_static="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-qpidproton_static" "$LINENO" 5 ;;
+ esac
+else
+ enable_qpidproton_static=no
+
+fi
+
+ if test x$enable_qpidproton_static = xyes; then
+ ENABLE_QPIDPROTON_STATIC_TRUE=
+ ENABLE_QPIDPROTON_STATIC_FALSE='#'
+else
+ ENABLE_QPIDPROTON_STATIC_TRUE='#'
+ ENABLE_QPIDPROTON_STATIC_FALSE=
+fi
+
+
+#MONGODB SUPPORT
+# Check whether --enable-ommongodb was given.
+if test "${enable_ommongodb+set}" = set; then :
+ enableval=$enable_ommongodb; case "${enableval}" in
+ yes) enable_ommongodb="yes" ;;
+ no) enable_ommongodb="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-ommongodb" "$LINENO" 5 ;;
+ esac
+else
+ enable_ommongodb=no
+
+fi
+
+if test "x$enable_ommongodb" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBMONGOC" >&5
+$as_echo_n "checking for LIBMONGOC... " >&6; }
+
+if test -n "$LIBMONGOC_CFLAGS"; then
+ pkg_cv_LIBMONGOC_CFLAGS="$LIBMONGOC_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmongoc-1.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libmongoc-1.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBMONGOC_CFLAGS=`$PKG_CONFIG --cflags "libmongoc-1.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBMONGOC_LIBS"; then
+ pkg_cv_LIBMONGOC_LIBS="$LIBMONGOC_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmongoc-1.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libmongoc-1.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBMONGOC_LIBS=`$PKG_CONFIG --libs "libmongoc-1.0" 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
+ LIBMONGOC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libmongoc-1.0" 2>&1`
+ else
+ LIBMONGOC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libmongoc-1.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBMONGOC_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libmongoc-1.0) were not met:
+
+$LIBMONGOC_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBMONGOC_CFLAGS
+and LIBMONGOC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBMONGOC_CFLAGS
+and LIBMONGOC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBMONGOC_CFLAGS=$pkg_cv_LIBMONGOC_CFLAGS
+ LIBMONGOC_LIBS=$pkg_cv_LIBMONGOC_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ for ac_func in mongoc_client_set_ssl_opts
+do :
+ ac_fn_c_check_func "$LINENO" "mongoc_client_set_ssl_opts" "ac_cv_func_mongoc_client_set_ssl_opts"
+if test "x$ac_cv_func_mongoc_client_set_ssl_opts" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MONGOC_CLIENT_SET_SSL_OPTS 1
+_ACEOF
+
+fi
+done
+
+
+fi
+ if test x$enable_ommongodb = xyes; then
+ ENABLE_OMMONGODB_TRUE=
+ ENABLE_OMMONGODB_FALSE='#'
+else
+ ENABLE_OMMONGODB_TRUE='#'
+ ENABLE_OMMONGODB_FALSE=
+fi
+
+# end of mongodb code
+
+
+# BEGIN IMDTLS INPUT SUPPORT
+# Check whether --enable-imdtls was given.
+if test "${enable_imdtls+set}" = set; then :
+ enableval=$enable_imdtls; case "${enableval}" in
+ yes) enable_imdtls="yes" ;;
+ no) enable_imdtls="no" ;;
+ optional) enable_imdtls="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imdtls" "$LINENO" 5 ;;
+ esac
+else
+ enable_imdtls=no
+
+fi
+
+if test "x$enable_imdtls" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+$as_echo_n "checking for OPENSSL... " >&6; }
+
+if test -n "$OPENSSL_CFLAGS"; then
+ pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$OPENSSL_LIBS"; then
+ pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl" 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
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1`
+ else
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$OPENSSL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (openssl) were not met:
+
+$OPENSSL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS
+ OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_imdtls = xyes; then
+ ENABLE_IMDTLS_TRUE=
+ ENABLE_IMDTLS_FALSE='#'
+else
+ ENABLE_IMDTLS_TRUE='#'
+ ENABLE_IMDTLS_FALSE=
+fi
+
+# END IMDTLS INPUT
+
+# BEGIN OMDTLS INPUT SUPPORT
+# Check whether --enable-omdtls was given.
+if test "${enable_omdtls+set}" = set; then :
+ enableval=$enable_omdtls; case "${enableval}" in
+ yes) enable_omdtls="yes" ;;
+ no) enable_omdtls="no" ;;
+ optional) enable_omdtls="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omdtls" "$LINENO" 5 ;;
+ esac
+else
+ enable_omdtls=no
+
+fi
+
+if test "x$enable_omdtls" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+$as_echo_n "checking for OPENSSL... " >&6; }
+
+if test -n "$OPENSSL_CFLAGS"; then
+ pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$OPENSSL_LIBS"; then
+ pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "openssl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl" 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
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1`
+ else
+ OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$OPENSSL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (openssl) were not met:
+
+$OPENSSL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables OPENSSL_CFLAGS
+and OPENSSL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS
+ OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_omdtls = xyes; then
+ ENABLE_OMDTLS_TRUE=
+ ENABLE_OMDTLS_FALSE='#'
+else
+ ENABLE_OMDTLS_TRUE='#'
+ ENABLE_OMDTLS_FALSE=
+fi
+
+# END OMDTLS INPUT
+
+
+# BEGIN CZMQ INPUT SUPPORT
+# Check whether --enable-imczmq was given.
+if test "${enable_imczmq+set}" = set; then :
+ enableval=$enable_imczmq; case "${enableval}" in
+ yes) enable_imczmq="yes" ;;
+ no) enable_imczmq="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imczmq" "$LINENO" 5 ;;
+ esac
+else
+ enable_imczmq=no
+
+fi
+
+if test "x$enable_imczmq" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CZMQ" >&5
+$as_echo_n "checking for CZMQ... " >&6; }
+
+if test -n "$CZMQ_CFLAGS"; then
+ pkg_cv_CZMQ_CFLAGS="$CZMQ_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libczmq >= 4.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libczmq >= 4.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CZMQ_CFLAGS=`$PKG_CONFIG --cflags "libczmq >= 4.0.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CZMQ_LIBS"; then
+ pkg_cv_CZMQ_LIBS="$CZMQ_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libczmq >= 4.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libczmq >= 4.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CZMQ_LIBS=`$PKG_CONFIG --libs "libczmq >= 4.0.0" 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
+ CZMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libczmq >= 4.0.0" 2>&1`
+ else
+ CZMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libczmq >= 4.0.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CZMQ_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libczmq >= 4.0.0) were not met:
+
+$CZMQ_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CZMQ_CFLAGS
+and CZMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CZMQ_CFLAGS
+and CZMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CZMQ_CFLAGS=$pkg_cv_CZMQ_CFLAGS
+ CZMQ_LIBS=$pkg_cv_CZMQ_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_imczmq = xyes; then
+ ENABLE_IMCZMQ_TRUE=
+ ENABLE_IMCZMQ_FALSE='#'
+else
+ ENABLE_IMCZMQ_TRUE='#'
+ ENABLE_IMCZMQ_FALSE=
+fi
+
+# END CZMQ INPUT
+
+
+# BEGIN CZMQ OUTPUT SUPPORT
+# Check whether --enable-omczmq was given.
+if test "${enable_omczmq+set}" = set; then :
+ enableval=$enable_omczmq; case "${enableval}" in
+ yes) enable_omczmq="yes" ;;
+ no) enable_omczmq="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omczmq" "$LINENO" 5 ;;
+ esac
+else
+ enable_omczmq=no
+
+fi
+
+if test "x$enable_omczmq" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CZMQ" >&5
+$as_echo_n "checking for CZMQ... " >&6; }
+
+if test -n "$CZMQ_CFLAGS"; then
+ pkg_cv_CZMQ_CFLAGS="$CZMQ_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libczmq >= 4.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libczmq >= 4.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CZMQ_CFLAGS=`$PKG_CONFIG --cflags "libczmq >= 4.0.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CZMQ_LIBS"; then
+ pkg_cv_CZMQ_LIBS="$CZMQ_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libczmq >= 4.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libczmq >= 4.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CZMQ_LIBS=`$PKG_CONFIG --libs "libczmq >= 4.0.0" 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
+ CZMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libczmq >= 4.0.0" 2>&1`
+ else
+ CZMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libczmq >= 4.0.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CZMQ_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libczmq >= 4.0.0) were not met:
+
+$CZMQ_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CZMQ_CFLAGS
+and CZMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CZMQ_CFLAGS
+and CZMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CZMQ_CFLAGS=$pkg_cv_CZMQ_CFLAGS
+ CZMQ_LIBS=$pkg_cv_CZMQ_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+ if test x$enable_omczmq = xyes; then
+ ENABLE_OMCZMQ_TRUE=
+ ENABLE_OMCZMQ_FALSE='#'
+else
+ ENABLE_OMCZMQ_TRUE='#'
+ ENABLE_OMCZMQ_FALSE=
+fi
+
+
+# END CZMQ SUPPORT
+
+
+# BEGIN RABBITMQ OUTPUT SUPPORT
+
+# Check whether --enable-omrabbitmq was given.
+if test "${enable_omrabbitmq+set}" = set; then :
+ enableval=$enable_omrabbitmq; case "${enableval}" in
+ yes) enable_omrabbitmq="yes" ;;
+ no) enable_omrabbitmq="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omrabbitmq" "$LINENO" 5 ;;
+ esac
+else
+ enable_omrabbitmq=no
+
+fi
+
+if test "x$enable_omrabbitmq" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RABBITMQ" >&5
+$as_echo_n "checking for RABBITMQ... " >&6; }
+
+if test -n "$RABBITMQ_CFLAGS"; then
+ pkg_cv_RABBITMQ_CFLAGS="$RABBITMQ_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librabbitmq >= 0.2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librabbitmq >= 0.2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RABBITMQ_CFLAGS=`$PKG_CONFIG --cflags "librabbitmq >= 0.2.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$RABBITMQ_LIBS"; then
+ pkg_cv_RABBITMQ_LIBS="$RABBITMQ_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librabbitmq >= 0.2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "librabbitmq >= 0.2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RABBITMQ_LIBS=`$PKG_CONFIG --libs "librabbitmq >= 0.2.0" 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
+ RABBITMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "librabbitmq >= 0.2.0" 2>&1`
+ else
+ RABBITMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "librabbitmq >= 0.2.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$RABBITMQ_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (librabbitmq >= 0.2.0) were not met:
+
+$RABBITMQ_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables RABBITMQ_CFLAGS
+and RABBITMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables RABBITMQ_CFLAGS
+and RABBITMQ_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ RABBITMQ_CFLAGS=$pkg_cv_RABBITMQ_CFLAGS
+ RABBITMQ_LIBS=$pkg_cv_RABBITMQ_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+fi
+ if test x$enable_omrabbitmq = xyes; then
+ ENABLE_OMRABBITMQ_TRUE=
+ ENABLE_OMRABBITMQ_FALSE='#'
+else
+ ENABLE_OMRABBITMQ_TRUE='#'
+ ENABLE_OMRABBITMQ_FALSE=
+fi
+
+
+# END RABBITMQ SUPPORT
+
+# HIREDIS SUPPORT
+
+# Check whether --enable-imhiredis was given.
+if test "${enable_imhiredis+set}" = set; then :
+ enableval=$enable_imhiredis; case "${enableval}" in
+ yes) enable_imhiredis="yes" ;;
+ no) enable_imhiredis="no" ;;
+ optional) enable_imhiredis="optional" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-imhiredis" "$LINENO" 5 ;;
+ esac
+else
+ enable_imhiredis=no
+
+fi
+
+# Check whether --enable-omhiredis was given.
+if test "${enable_omhiredis+set}" = set; then :
+ enableval=$enable_omhiredis; case "${enableval}" in
+ yes) enable_omhiredis="yes" ;;
+ no) enable_omhiredis="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omhiredis" "$LINENO" 5 ;;
+ esac
+else
+ enable_omhiredis=no
+
+fi
+
+
+# Check whether --enable-redis_tests was given.
+if test "${enable_redis_tests+set}" = set; then :
+ enableval=$enable_redis_tests; case "${enableval}" in
+ yes) enable_redis_tests="yes" ;;
+ no) enable_redis_tests="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-redis-tests" "$LINENO" 5 ;;
+ esac
+else
+ enable_redis_tests=no
+
+fi
+
+ if test x$enable_redis_tests = xyes; then
+ ENABLE_REDIS_TESTS_TRUE=
+ ENABLE_REDIS_TESTS_FALSE='#'
+else
+ ENABLE_REDIS_TESTS_TRUE='#'
+ ENABLE_REDIS_TESTS_FALSE=
+fi
+
+
+if test "x$enable_omhiredis" = "xyes" -o "x$enable_imhiredis" = "xyes" ; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HIREDIS" >&5
+$as_echo_n "checking for HIREDIS... " >&6; }
+
+if test -n "$HIREDIS_CFLAGS"; then
+ pkg_cv_HIREDIS_CFLAGS="$HIREDIS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hiredis >= 0.10.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "hiredis >= 0.10.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_HIREDIS_CFLAGS=`$PKG_CONFIG --cflags "hiredis >= 0.10.1" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$HIREDIS_LIBS"; then
+ pkg_cv_HIREDIS_LIBS="$HIREDIS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hiredis >= 0.10.1\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "hiredis >= 0.10.1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_HIREDIS_LIBS=`$PKG_CONFIG --libs "hiredis >= 0.10.1" 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
+ HIREDIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "hiredis >= 0.10.1" 2>&1`
+ else
+ HIREDIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "hiredis >= 0.10.1" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$HIREDIS_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing redisConnectWithTimeout" >&5
+$as_echo_n "checking for library containing redisConnectWithTimeout... " >&6; }
+if ${ac_cv_search_redisConnectWithTimeout+:} 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 redisConnectWithTimeout ();
+int
+main ()
+{
+return redisConnectWithTimeout ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' hiredis; 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_redisConnectWithTimeout=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_redisConnectWithTimeout+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_redisConnectWithTimeout+:} false; then :
+
+else
+ ac_cv_search_redisConnectWithTimeout=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_redisConnectWithTimeout" >&5
+$as_echo "$ac_cv_search_redisConnectWithTimeout" >&6; }
+ac_res=$ac_cv_search_redisConnectWithTimeout
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+ #include <hiredis/hiredis.h>
+int
+main ()
+{
+ #define major 0
+ #define minor 10
+ #define patch 1
+ #if (( HIREDIS_MAJOR > major ) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR > minor )) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR == minor ) && ( HIREDIS_PATCH >= patch ))) \
+ /* OK */
+ #else
+ # error Hiredis version must be >= major.minor.path
+ #endif
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "hiredis version must be >= 0.10.1" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ as_fn_error $? "hiredis not found" "$LINENO" 5
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing redisConnectWithTimeout" >&5
+$as_echo_n "checking for library containing redisConnectWithTimeout... " >&6; }
+if ${ac_cv_search_redisConnectWithTimeout+:} 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 redisConnectWithTimeout ();
+int
+main ()
+{
+return redisConnectWithTimeout ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' hiredis; 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_redisConnectWithTimeout=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_redisConnectWithTimeout+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_redisConnectWithTimeout+:} false; then :
+
+else
+ ac_cv_search_redisConnectWithTimeout=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_redisConnectWithTimeout" >&5
+$as_echo "$ac_cv_search_redisConnectWithTimeout" >&6; }
+ac_res=$ac_cv_search_redisConnectWithTimeout
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+ #include <hiredis/hiredis.h>
+int
+main ()
+{
+ #define major 0
+ #define minor 10
+ #define patch 1
+ #if (( HIREDIS_MAJOR > major ) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR > minor )) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR == minor ) && ( HIREDIS_PATCH >= patch ))) \
+ /* OK */
+ #else
+ # error Hiredis version must be >= major.minor.path
+ #endif
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "hiredis version must be >= 0.10.1" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ as_fn_error $? "hiredis not found" "$LINENO" 5
+
+fi
+
+
+else
+ HIREDIS_CFLAGS=$pkg_cv_HIREDIS_CFLAGS
+ HIREDIS_LIBS=$pkg_cv_HIREDIS_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+
+if test "x$enable_imhiredis" = "xyes" ; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEVENT" >&5
+$as_echo_n "checking for LIBEVENT... " >&6; }
+
+if test -n "$LIBEVENT_CFLAGS"; then
+ pkg_cv_LIBEVENT_CFLAGS="$LIBEVENT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent >= 2.0, libevent_pthreads\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libevent >= 2.0, libevent_pthreads") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBEVENT_CFLAGS=`$PKG_CONFIG --cflags "libevent >= 2.0, libevent_pthreads" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBEVENT_LIBS"; then
+ pkg_cv_LIBEVENT_LIBS="$LIBEVENT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent >= 2.0, libevent_pthreads\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libevent >= 2.0, libevent_pthreads") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBEVENT_LIBS=`$PKG_CONFIG --libs "libevent >= 2.0, libevent_pthreads" 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
+ LIBEVENT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libevent >= 2.0, libevent_pthreads" 2>&1`
+ else
+ LIBEVENT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libevent >= 2.0, libevent_pthreads" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBEVENT_PKG_ERRORS" >&5
+
+ # libevent not found
+ as_fn_error $? "no libevent >= 2.0 found with pthreads support, imhiredis cannot use pub/sub" "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ # libevent not found
+ as_fn_error $? "no libevent >= 2.0 found with pthreads support, imhiredis cannot use pub/sub" "$LINENO" 5
+else
+ LIBEVENT_CFLAGS=$pkg_cv_LIBEVENT_CFLAGS
+ LIBEVENT_LIBS=$pkg_cv_LIBEVENT_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ # libevent found
+
+ HIREDIS_LIBS="$HIREDIS_LIBS -levent -levent_pthreads"
+
+fi
+fi
+
+if test "x$enable_imhiredis" = "xyes" || test "x$enable_omhiredis" = "xyes"; then
+ if test "x$enable_redis_tests" = "xyes"; then
+ # Extract the first word of "redis-server", so it can be a program name with args.
+set dummy redis-server; 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_REDIS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$REDIS"; then
+ ac_cv_prog_REDIS="$REDIS" # 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_REDIS="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_REDIS" && ac_cv_prog_REDIS="no"
+fi
+fi
+REDIS=$ac_cv_prog_REDIS
+if test -n "$REDIS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $REDIS" >&5
+$as_echo "$REDIS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x${REDIS}" = "xno"; 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 $? "redis-server, which is a redis-tests dependency, not found
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+else
+ if test "x$enable_redis_tests" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: redis-tests can not be enabled without imhiredis or omhiredis support.
+ Disabling enable_redis_tests..." >&5
+$as_echo "$as_me: WARNING: redis-tests can not be enabled without imhiredis or omhiredis support.
+ Disabling enable_redis_tests..." >&2;}
+ enable_redis_tests="no"
+ fi
+fi
+
+ if test x$enable_omhiredis = xyes; then
+ ENABLE_OMHIREDIS_TRUE=
+ ENABLE_OMHIREDIS_FALSE='#'
+else
+ ENABLE_OMHIREDIS_TRUE='#'
+ ENABLE_OMHIREDIS_FALSE=
+fi
+
+ if test x$enable_imhiredis = xyes; then
+ ENABLE_IMHIREDIS_TRUE=
+ ENABLE_IMHIREDIS_FALSE='#'
+else
+ ENABLE_IMHIREDIS_TRUE='#'
+ ENABLE_IMHIREDIS_FALSE=
+fi
+
+
+# END HIREDIS SUPPORT
+
+
+# HTTPFS SUPPORT
+
+# Check whether --enable-omhttpfs was given.
+if test "${enable_omhttpfs+set}" = set; then :
+ enableval=$enable_omhttpfs; case "${enableval}" in
+ yes) enable_omhttpfs="yes" ;;
+ no) enable_omhttpfs="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omhttpfs" "$LINENO" 5 ;;
+ esac
+else
+ enable_omhttpfs=no
+
+fi
+
+
+if test "x$enable_omhttpfs" = "xyes"; then
+ 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
+
+fi
+
+done
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5
+$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; }
+if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmw $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 _mwvalidcheckl ();
+int
+main ()
+{
+return _mwvalidcheckl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mw__mwvalidcheckl=yes
+else
+ ac_cv_lib_mw__mwvalidcheckl=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_mw__mwvalidcheckl" >&5
+$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; }
+if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then :
+ LIBM=-lmw
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM="$LIBM -lm"
+fi
+
+ ;;
+*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+$as_echo_n "checking for cos in -lm... " >&6; }
+if ${ac_cv_lib_m_cos+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-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 cos ();
+int
+main ()
+{
+return cos ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_cos=yes
+else
+ ac_cv_lib_m_cos=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_m_cos" >&5
+$as_echo "$ac_cv_lib_m_cos" >&6; }
+if test "x$ac_cv_lib_m_cos" = xyes; then :
+ LIBM=-lm
+fi
+
+ ;;
+esac
+
+
+ #PKG_CHECK_MODULES(HTTPFS, curl >= 7.0.0)
+fi
+ if test x$enable_omhttpfs = xyes; then
+ ENABLE_OMHTTPFS_TRUE=
+ ENABLE_OMHTTPFS_FALSE='#'
+else
+ ENABLE_OMHTTPFS_TRUE='#'
+ ENABLE_OMHTTPFS_FALSE=
+fi
+
+
+# END HTTPFS SUPPORT
+
+# AMQP 1.0 PROTOCOL SUPPORT
+# uses the Proton protocol library
+
+# Check whether --enable-omamqp1 was given.
+if test "${enable_omamqp1+set}" = set; then :
+ enableval=$enable_omamqp1; case "${enableval}" in
+ yes) enable_omamqp1="yes" ;;
+ no) enable_omamqp1="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omamqp1" "$LINENO" 5 ;;
+ esac
+else
+ enable_omamqp1=no
+
+fi
+
+if test "x$enable_omamqp1" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTON" >&5
+$as_echo_n "checking for PROTON... " >&6; }
+
+if test -n "$PROTON_CFLAGS"; then
+ pkg_cv_PROTON_CFLAGS="$PROTON_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton >= 0.9\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton >= 0.9") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_CFLAGS=`$PKG_CONFIG --cflags "libqpid-proton >= 0.9" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$PROTON_LIBS"; then
+ pkg_cv_PROTON_LIBS="$PROTON_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libqpid-proton >= 0.9\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libqpid-proton >= 0.9") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_PROTON_LIBS=`$PKG_CONFIG --libs "libqpid-proton >= 0.9" 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
+ PROTON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libqpid-proton >= 0.9" 2>&1`
+ else
+ PROTON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libqpid-proton >= 0.9" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$PROTON_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libqpid-proton >= 0.9) were not met:
+
+$PROTON_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables PROTON_CFLAGS
+and PROTON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables PROTON_CFLAGS
+and PROTON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ PROTON_CFLAGS=$pkg_cv_PROTON_CFLAGS
+ PROTON_LIBS=$pkg_cv_PROTON_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+fi
+ if test x$enable_omamqp1 = xyes; then
+ ENABLE_OMAMQP1_TRUE=
+ ENABLE_OMAMQP1_FALSE='#'
+else
+ ENABLE_OMAMQP1_TRUE='#'
+ ENABLE_OMAMQP1_FALSE=
+fi
+
+
+# END AMQP 1.0 PROTOCOL SUPPORT
+
+# TCL SUPPORT
+
+# Check whether --enable-omtcl was given.
+if test "${enable_omtcl+set}" = set; then :
+ enableval=$enable_omtcl; case "${enableval}" in
+ yes) enable_omtcl="yes" ;;
+ no) enable_omtcl="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-omtcl" "$LINENO" 5 ;;
+ esac
+else
+ enable_omtcl=no
+
+fi
+
+
+if test "x$enable_omtcl" = "xyes"; then
+
+ #
+ # Ok, lets find the tcl configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tcl
+ #
+
+ if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+
+# Check whether --with-tcl was given.
+if test "${with_tcl+set}" = set; then :
+ withval=$with_tcl; with_tclconfig="${withval}"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
+$as_echo_n "checking for Tcl configuration... " >&6; }
+ if ${ac_cv_c_tclconfig+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+
+ # First check to see if --with-tcl was specified.
+ if test x"${with_tclconfig}" != x ; then
+ case "${with_tclconfig}" in
+ */tclConfig.sh )
+ if test -f "${with_tclconfig}"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5
+$as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;}
+ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
+ else
+ as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tcl.framework/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.6 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
+ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+fi
+
+
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCL_BIN_DIR="# no Tcl configs found"
+ as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5
+ else
+ no_tcl=
+ TCL_BIN_DIR="${ac_cv_c_tclconfig}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
+ fi
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; }
+
+ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
+$as_echo "loading" >&6; }
+ . "${TCL_BIN_DIR}/tclConfig.sh"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+
+ # If the TCL_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TCL_LIB_SPEC will be set to the value
+ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+ # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
+ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
+ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tcl.framework installed in an arbitrary location.
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
+ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
+ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
+ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
+ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+fi
+ if test x$enable_omtcl = xyes; then
+ ENABLE_OMTCL_TRUE=
+ ENABLE_OMTCL_FALSE='#'
+else
+ ENABLE_OMTCL_TRUE='#'
+ ENABLE_OMTCL_FALSE=
+fi
+
+
+# END TCL SUPPORT
+
+# mmkubernetes - Kubernetes metadata support
+
+# Check whether --enable-mmkubernetes was given.
+if test "${enable_mmkubernetes+set}" = set; then :
+ enableval=$enable_mmkubernetes; case "${enableval}" in
+ yes) enable_mmkubernetes="yes" ;;
+ no) enable_mmkubernetes="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmkubernetes" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmkubernetes=no
+
+fi
+
+if test "x$enable_mmkubernetes" = "xyes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5
+$as_echo_n "checking for CURL... " >&6; }
+
+if test -n "$CURL_CFLAGS"; then
+ pkg_cv_CURL_CFLAGS="$CURL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$CURL_LIBS"; then
+ pkg_cv_CURL_LIBS="$CURL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl" 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
+ CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1`
+ else
+ CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$CURL_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (libcurl) were not met:
+
+$CURL_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables CURL_CFLAGS
+and CURL_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ CURL_CFLAGS=$pkg_cv_CURL_CFLAGS
+ CURL_LIBS=$pkg_cv_CURL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLOGNORM" >&5
+$as_echo_n "checking for LIBLOGNORM... " >&6; }
+
+if test -n "$LIBLOGNORM_CFLAGS"; then
+ pkg_cv_LIBLOGNORM_CFLAGS="$LIBLOGNORM_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lognorm >= 2.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "lognorm >= 2.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGNORM_CFLAGS=`$PKG_CONFIG --cflags "lognorm >= 2.0.3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBLOGNORM_LIBS"; then
+ pkg_cv_LIBLOGNORM_LIBS="$LIBLOGNORM_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lognorm >= 2.0.3\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "lognorm >= 2.0.3") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBLOGNORM_LIBS=`$PKG_CONFIG --libs "lognorm >= 2.0.3" 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
+ LIBLOGNORM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lognorm >= 2.0.3" 2>&1`
+ else
+ LIBLOGNORM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lognorm >= 2.0.3" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBLOGNORM_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (lognorm >= 2.0.3) were not met:
+
+$LIBLOGNORM_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBLOGNORM_CFLAGS
+and LIBLOGNORM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables LIBLOGNORM_CFLAGS
+and LIBLOGNORM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ LIBLOGNORM_CFLAGS=$pkg_cv_LIBLOGNORM_CFLAGS
+ LIBLOGNORM_LIBS=$pkg_cv_LIBLOGNORM_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $LIBLOGNORM_CFLAGS"
+ LIBS="$LIBS $LIBLOGNORM_LIBS"
+
+ ac_fn_c_check_func "$LINENO" "ln_loadSamplesFromString" "ac_cv_func_ln_loadSamplesFromString"
+if test "x$ac_cv_func_ln_loadSamplesFromString" = xyes; then :
+
+$as_echo "#define HAVE_LOADSAMPLESFROMSTRING 1" >>confdefs.h
+
+else
+
+$as_echo "#define NO_LOADSAMPLESFROMSTRING 1" >>confdefs.h
+
+fi
+
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+ if test x$enable_mmkubernetes = xyes; then
+ ENABLE_MMKUBERNETES_TRUE=
+ ENABLE_MMKUBERNETES_FALSE='#'
+else
+ ENABLE_MMKUBERNETES_TRUE='#'
+ ENABLE_MMKUBERNETES_FALSE=
+fi
+
+
+# END Kubernetes metadata support
+
+
+# mmtaghostname
+# Check whether --enable-mmtaghostname was given.
+if test "${enable_mmtaghostname+set}" = set; then :
+ enableval=$enable_mmtaghostname; case "${enableval}" in
+ yes) enable_mmtaghostname="yes" ;;
+ no) enable_mmtaghostname="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-mmtaghostname" "$LINENO" 5 ;;
+ esac
+else
+ enable_mmtaghostname=no
+
+fi
+
+ if test x$enable_mmtaghostname = xyes; then
+ ENABLE_MMTAGHOSTNAME_TRUE=
+ ENABLE_MMTAGHOSTNAME_FALSE='#'
+else
+ ENABLE_MMTAGHOSTNAME_TRUE='#'
+ ENABLE_MMTAGHOSTNAME_FALSE=
+fi
+
+#END mmtaghostname
+
+# man pages
+have_to_generate_man_pages="no"
+git_src_have_to_generate_man_pages="yes" # default to use when building from git source
+# Check whether --enable-generate-man-pages was given.
+if test "${enable_generate_man_pages+set}" = set; then :
+ enableval=$enable_generate_man_pages; case "${enableval}" in
+ yes) have_to_generate_man_pages="yes" ;;
+ no) have_to_generate_man_pages="no" ;
+ git_src_have_to_generate_man_pages="no"
+ ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-generate-man-pages" "$LINENO" 5 ;;
+ esac
+else
+ have_to_generate_man_pages=no
+
+fi
+
+
+
+# This provides a work-around to use "make distcheck" without
+# running tests (mode used pre 2018-07-02)
+# Check whether --enable-distcheck-workaround was given.
+if test "${enable_distcheck_workaround+set}" = set; then :
+ enableval=$enable_distcheck_workaround; case "${enableval}" in
+ yes) enable_distcheck_workaround="yes" ;;
+ no) enable_distcheck_workaround="no" ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-distcheck_workaround" "$LINENO" 5 ;;
+ esac
+else
+ enable_distcheck_workaround="no"
+
+fi
+
+ if test x$enable_distcheck_workaround = xyes; then
+ ENABLE_DISTCHECK_WORKAROUND_TRUE=
+ ENABLE_DISTCHECK_WORKAROUND_FALSE='#'
+else
+ ENABLE_DISTCHECK_WORKAROUND_TRUE='#'
+ ENABLE_DISTCHECK_WORKAROUND_FALSE=
+fi
+
+
+
+if test "x$in_git_src" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Running from git source" >&5
+$as_echo "$as_me: Running from git source" >&6;}
+
+ have_to_generate_man_pages=$git_src_have_to_generate_man_pages
+
+ if test "x$LEX" != "xflex"; then
+ as_fn_error $? "flex program is needed to build rsyslog, please install flex." "$LINENO" 5
+ fi
+
+ if test "x$YACC" = "xyacc"; then
+ # AC_PROG_YACC only checks for yacc replacements, not for yacc itself
+ # Extract the first word of "yacc", so it can be a program name with args.
+set dummy yacc; 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_FOUND+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$YACC_FOUND"; then
+ ac_cv_prog_YACC_FOUND="$YACC_FOUND" # 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_FOUND="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_YACC_FOUND" && ac_cv_prog_YACC_FOUND="no"
+fi
+fi
+YACC_FOUND=$ac_cv_prog_YACC_FOUND
+if test -n "$YACC_FOUND"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC_FOUND" >&5
+$as_echo "$YACC_FOUND" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$YACC_FOUND" = "xno"; then
+ as_fn_error $? "A yacc program is needed to build rsyslog, please install bison." "$LINENO" 5
+ fi
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Not running from git source" >&5
+$as_echo "$as_me: Not running from git source" >&6;}
+fi
+
+ if test x$have_to_generate_man_pages = xyes; then
+ ENABLE_GENERATE_MAN_PAGES_TRUE=
+ ENABLE_GENERATE_MAN_PAGES_FALSE='#'
+else
+ ENABLE_GENERATE_MAN_PAGES_TRUE='#'
+ ENABLE_GENERATE_MAN_PAGES_FALSE=
+fi
+
+
+# rst2man
+for ac_prog in rst2man rst2man.py
+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_RST2MAN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RST2MAN"; then
+ ac_cv_prog_RST2MAN="$RST2MAN" # 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_RST2MAN="$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
+RST2MAN=$ac_cv_prog_RST2MAN
+if test -n "$RST2MAN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RST2MAN" >&5
+$as_echo "$RST2MAN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$RST2MAN" && break
+done
+test -n "$RST2MAN" || RST2MAN="false"
+
+if test "x$have_to_generate_man_pages" = "xyes" && test "x$RST2MAN" = "xfalse"; then
+ as_fn_error $? "rst2man is required when building from git source or --enable-generate-man-pages option was set, please install python-docutils." "$LINENO" 5
+fi
+
+
+ac_config_files="$ac_config_files Makefile runtime/Makefile compat/Makefile grammar/Makefile tools/Makefile plugins/imudp/Makefile plugins/imtcp/Makefile plugins/im3195/Makefile plugins/imgssapi/Makefile plugins/imuxsock/Makefile plugins/imjournal/Makefile plugins/immark/Makefile plugins/imklog/Makefile plugins/omhdfs/Makefile plugins/omkafka/Makefile plugins/omprog/Makefile plugins/mmexternal/Makefile plugins/omstdout/Makefile plugins/omjournal/Makefile plugins/pmciscoios/Makefile plugins/pmnull/Makefile plugins/pmnormalize/Makefile plugins/omruleset/Makefile plugins/omuxsock/Makefile plugins/imfile/Makefile plugins/imsolaris/Makefile plugins/imptcp/Makefile plugins/impstats/Makefile plugins/imrelp/Makefile plugins/imdiag/Makefile plugins/imkafka/Makefile plugins/omtesting/Makefile plugins/omgssapi/Makefile plugins/ommysql/Makefile plugins/ompgsql/Makefile plugins/omrelp/Makefile plugins/omlibdbi/Makefile plugins/ommail/Makefile plugins/fmhttp/Makefile plugins/omsnmp/Makefile plugins/omudpspoof/Makefile plugins/ommongodb/Makefile plugins/mmnormalize/Makefile plugins/mmjsonparse/Makefile plugins/mmaudit/Makefile plugins/mmanon/Makefile plugins/mmrm1stspace/Makefile plugins/mmutf8fix/Makefile plugins/mmfields/Makefile plugins/mmpstrucdata/Makefile plugins/omelasticsearch/Makefile plugins/omclickhouse/Makefile plugins/mmsnmptrapd/Makefile plugins/pmlastmsg/Makefile plugins/mmdblookup/Makefile plugins/omazureeventhubs/Makefile plugins/imdtls/Makefile plugins/omdtls/Makefile contrib/mmdarwin/Makefile contrib/omhttp/Makefile contrib/fmhash/Makefile contrib/fmunflatten/Makefile contrib/ffaup/Makefile contrib/pmsnare/Makefile contrib/pmpanngfw/Makefile contrib/pmaixforwardedfrom/Makefile contrib/omhiredis/Makefile contrib/omrabbitmq/Makefile contrib/imkmsg/Makefile contrib/mmgrok/Makefile contrib/mmcount/Makefile contrib/omczmq/Makefile contrib/imczmq/Makefile contrib/mmsequence/Makefile contrib/mmrfc5424addhmac/Makefile contrib/pmcisconames/Makefile contrib/omhttpfs/Makefile contrib/omamqp1/Makefile contrib/omtcl/Makefile contrib/imbatchreport/Makefile contrib/omfile-hardened/Makefile contrib/mmkubernetes/Makefile contrib/impcap/Makefile contrib/imtuxedoulog/Makefile contrib/improg/Makefile contrib/imhttp/Makefile contrib/mmtaghostname/Makefile contrib/imdocker/Makefile contrib/pmdb2diag/Makefile contrib/imhiredis/Makefile tests/set-envvars tests/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 "${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 "${OS_APPLE_TRUE}" && test -z "${OS_APPLE_FALSE}"; then
+ as_fn_error $? "conditional \"OS_APPLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OS_LINUX_TRUE}" && test -z "${OS_LINUX_FALSE}"; then
+ as_fn_error $? "conditional \"OS_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OS_AIX_TRUE}" && test -z "${OS_AIX_FALSE}"; then
+ as_fn_error $? "conditional \"OS_AIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_INOTIFY_TRUE}" && test -z "${ENABLE_INOTIFY_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_INOTIFY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_MODDIRS_TRUE}" && test -z "${WITH_MODDIRS_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_MODDIRS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_REGEXP_TRUE}" && test -z "${ENABLE_REGEXP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_REGEXP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FMHASH_TRUE}" && test -z "${ENABLE_FMHASH_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_FMHASH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FMHASH_XXHASH_TRUE}" && test -z "${ENABLE_FMHASH_XXHASH_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_FMHASH_XXHASH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FFAUP_TRUE}" && test -z "${ENABLE_FFAUP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_FFAUP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FMUNFLATTEN_TRUE}" && test -z "${ENABLE_FMUNFLATTEN_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_FMUNFLATTEN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_GSSAPI_TRUE}" && test -z "${ENABLE_GSSAPI_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_GSSAPI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_ROOT_TESTS_TRUE}" && test -z "${ENABLE_ROOT_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_ROOT_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKLOG_TRUE}" && test -z "${ENABLE_IMKLOG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKLOG_BSD_TRUE}" && test -z "${ENABLE_IMKLOG_BSD_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKLOG_BSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKLOG_LINUX_TRUE}" && test -z "${ENABLE_IMKLOG_LINUX_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKLOG_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKLOG_SOLARIS_TRUE}" && test -z "${ENABLE_IMKLOG_SOLARIS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKLOG_SOLARIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKMSG_TRUE}" && test -z "${ENABLE_IMKMSG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKMSG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${IMJOURNAL_USE_DUMMY_TRUE}" && test -z "${IMJOURNAL_USE_DUMMY_FALSE}"; then
+ as_fn_error $? "conditional \"IMJOURNAL_USE_DUMMY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMJOURNAL_TRUE}" && test -z "${ENABLE_IMJOURNAL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMJOURNAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_INET_TRUE}" && test -z "${ENABLE_INET_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_INET\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_JEMALLOC_TRUE}" && test -z "${ENABLE_JEMALLOC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_JEMALLOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_DIAGTOOLS_TRUE}" && test -z "${ENABLE_DIAGTOOLS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_DIAGTOOLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_USERTOOLS_TRUE}" && test -z "${ENABLE_USERTOOLS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_USERTOOLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MYSQL_TRUE}" && test -z "${ENABLE_MYSQL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MYSQL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PGSQL_TRUE}" && test -z "${ENABLE_PGSQL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PGSQL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBDBI_USE_DUMMY_TRUE}" && test -z "${LIBDBI_USE_DUMMY_FALSE}"; then
+ as_fn_error $? "conditional \"LIBDBI_USE_DUMMY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMLIBDBI_TRUE}" && test -z "${ENABLE_OMLIBDBI_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMLIBDBI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_SNMP_TRUE}" && test -z "${ENABLE_SNMP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_SNMP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_SNMP_TESTS_TRUE}" && test -z "${ENABLE_SNMP_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_SNMP_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_UUID_TRUE}" && test -z "${ENABLE_UUID_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_UUID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_ELASTICSEARCH_TRUE}" && test -z "${ENABLE_ELASTICSEARCH_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_ELASTICSEARCH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_CLICKHOUSE_TRUE}" && test -z "${ENABLE_CLICKHOUSE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_CLICKHOUSE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMHTTP_TRUE}" && test -z "${ENABLE_OMHTTP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMHTTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_ELASTICSEARCH_TESTS_TRUE}" && test -z "${ENABLE_ELASTICSEARCH_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_ELASTICSEARCH_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE}" && test -z "${ENABLE_ELASTICSEARCH_TESTS_MINIMAL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_ELASTICSEARCH_TESTS_MINIMAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_CLICKHOUSE_TESTS_TRUE}" && test -z "${ENABLE_CLICKHOUSE_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_CLICKHOUSE_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OPENSSL_TRUE}" && test -z "${ENABLE_OPENSSL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OPENSSL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_GNUTLS_TRUE}" && test -z "${ENABLE_GNUTLS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_GNUTLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_GNUTLS_TESTS_TRUE}" && test -z "${ENABLE_GNUTLS_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_GNUTLS_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_LIBGCRYPT_TRUE}" && test -z "${ENABLE_LIBGCRYPT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_LIBGCRYPT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_LIBZSTD_TRUE}" && test -z "${ENABLE_LIBZSTD_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_LIBZSTD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_RSYSLOGRT_TRUE}" && test -z "${ENABLE_RSYSLOGRT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_RSYSLOGRT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_RSYSLOGD_TRUE}" && test -z "${ENABLE_RSYSLOGD_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_RSYSLOGD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_EXTENDED_TESTS_TRUE}" && test -z "${ENABLE_EXTENDED_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_EXTENDED_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MYSQL_TESTS_TRUE}" && test -z "${ENABLE_MYSQL_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MYSQL_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PGSQL_TESTS_TRUE}" && test -z "${ENABLE_PGSQL_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PGSQL_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MAIL_TRUE}" && test -z "${ENABLE_MAIL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FMHTTP_TRUE}" && test -z "${ENABLE_FMHTTP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_FMHTTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMDIAG_TRUE}" && test -z "${ENABLE_IMDIAG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMDIAG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LOGNORM_REGEX_SUPPORTED_TRUE}" && test -z "${LOGNORM_REGEX_SUPPORTED_FALSE}"; then
+ as_fn_error $? "conditional \"LOGNORM_REGEX_SUPPORTED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMNORMALIZE_TRUE}" && test -z "${ENABLE_MMNORMALIZE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMNORMALIZE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMJSONPARSE_TRUE}" && test -z "${ENABLE_MMJSONPARSE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMJSONPARSE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMGROK_TRUE}" && test -z "${ENABLE_MMGROK_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMGROK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMAUDIT_TRUE}" && test -z "${ENABLE_MMAUDIT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMAUDIT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMANON_TRUE}" && test -z "${ENABLE_MMANON_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMANON\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMRM1STSPACE_TRUE}" && test -z "${ENABLE_MMRM1STSPACE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMRM1STSPACE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMUTF8FIX_TRUE}" && test -z "${ENABLE_MMUTF8FIX_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMUTF8FIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMCOUNT_TRUE}" && test -z "${ENABLE_MMCOUNT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMCOUNT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMSEQUENCE_TRUE}" && test -z "${ENABLE_MMSEQUENCE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMSEQUENCE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMDBLOOKUP_TRUE}" && test -z "${ENABLE_MMDBLOOKUP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMDBLOOKUP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MMDBLOOKUP_USE_DUMMY_TRUE}" && test -z "${MMDBLOOKUP_USE_DUMMY_FALSE}"; then
+ as_fn_error $? "conditional \"MMDBLOOKUP_USE_DUMMY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMDARWIN_TRUE}" && test -z "${ENABLE_MMDARWIN_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMDARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMFIELDS_TRUE}" && test -z "${ENABLE_MMFIELDS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMFIELDS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMPSTRUCDATA_TRUE}" && test -z "${ENABLE_MMPSTRUCDATA_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMPSTRUCDATA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMRFC5424ADDHMAC_TRUE}" && test -z "${ENABLE_MMRFC5424ADDHMAC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMRFC5424ADDHMAC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMFILE_HARDENED_TRUE}" && test -z "${ENABLE_OMFILE_HARDENED_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMFILE_HARDENED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_RELP_TRUE}" && test -z "${ENABLE_RELP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_RELP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_RELPENGINESETTLSCFGCMD_TRUE}" && test -z "${USE_RELPENGINESETTLSCFGCMD_FALSE}"; then
+ as_fn_error $? "conditional \"USE_RELPENGINESETTLSCFGCMD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_KSI_LS12_TRUE}" && test -z "${ENABLE_KSI_LS12_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_KSI_LS12\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_LIBLOGGING_STDLOG_TRUE}" && test -z "${ENABLE_LIBLOGGING_STDLOG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_LIBLOGGING_STDLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_RFC3195_TRUE}" && test -z "${ENABLE_RFC3195_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_RFC3195\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_LIBFAKETIME_TRUE}" && test -z "${ENABLE_LIBFAKETIME_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_LIBFAKETIME\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_DEFAULT_TESTS_TRUE}" && test -z "${ENABLE_DEFAULT_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_DEFAULT_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IP_TRUE}" && test -z "${ENABLE_IP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_VALGRIND_TRUE}" && test -z "${HAVE_VALGRIND_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_VALGRIND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_HELGRIND_TRUE}" && test -z "${ENABLE_HELGRIND_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_HELGRIND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMBATCHREPORT_TRUE}" && test -z "${ENABLE_IMBATCHREPORT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMBATCHREPORT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMDB2DIAG_TRUE}" && test -z "${ENABLE_PMDB2DIAG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMDB2DIAG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMFILE_TRUE}" && test -z "${ENABLE_IMFILE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMFILE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMFILE_TESTS_TRUE}" && test -z "${ENABLE_IMFILE_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMFILE_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMDOCKER_TRUE}" && test -z "${ENABLE_IMDOCKER_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMDOCKER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMDOCKER_TESTS_TRUE}" && test -z "${ENABLE_IMDOCKER_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMDOCKER_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMTUXEDOULOG_TRUE}" && test -z "${ENABLE_IMTUXEDOULOG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMTUXEDOULOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMPROG_TRUE}" && test -z "${ENABLE_IMPROG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMPROG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMHTTP_TRUE}" && test -z "${ENABLE_IMHTTP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMHTTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMSOLARIS_TRUE}" && test -z "${ENABLE_IMSOLARIS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMSOLARIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMPTCP_TRUE}" && test -z "${ENABLE_IMPTCP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMPTCP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMPSTATS_TRUE}" && test -z "${ENABLE_IMPSTATS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMPSTATS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMPCAP_TRUE}" && test -z "${ENABLE_IMPCAP_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMPCAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMPROG_TRUE}" && test -z "${ENABLE_OMPROG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMPROG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMUDPSPOOF_TRUE}" && test -z "${ENABLE_OMUDPSPOOF_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMUDPSPOOF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMSTDOUT_TRUE}" && test -z "${ENABLE_OMSTDOUT_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMSTDOUT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_TESTBENCH_TRUE}" && test -z "${ENABLE_TESTBENCH_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_TESTBENCH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMJOURNAL_TRUE}" && test -z "${ENABLE_OMJOURNAL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMJOURNAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_JOURNAL_TESTS_TRUE}" && test -z "${ENABLE_JOURNAL_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_JOURNAL_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMLASTMSG_TRUE}" && test -z "${ENABLE_PMLASTMSG_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMLASTMSG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMCISCONAMES_TRUE}" && test -z "${ENABLE_PMCISCONAMES_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMCISCONAMES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMCISCOIOS_TRUE}" && test -z "${ENABLE_PMCISCOIOS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMCISCOIOS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMNULL_TRUE}" && test -z "${ENABLE_PMNULL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMNULL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMNORMALIZE_TRUE}" && test -z "${ENABLE_PMNORMALIZE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMNORMALIZE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMAIXFORWARDEDFROM_TRUE}" && test -z "${ENABLE_PMAIXFORWARDEDFROM_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMAIXFORWARDEDFROM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMSNARE_TRUE}" && test -z "${ENABLE_PMSNARE_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMSNARE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PMPANNGFW_TRUE}" && test -z "${ENABLE_PMPANNGFW_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_PMPANNGFW\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMRULESET_TRUE}" && test -z "${ENABLE_OMRULESET_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMRULESET\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMUXSOCK_TRUE}" && test -z "${ENABLE_OMUXSOCK_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMUXSOCK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMSNMPTRAPD_TRUE}" && test -z "${ENABLE_MMSNMPTRAPD_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMSNMPTRAPD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMHDFS_TRUE}" && test -z "${ENABLE_OMHDFS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMHDFS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE}" && test -z "${ENABLE_OMAZUREEVENTHUBS_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMAZUREEVENTHUBS_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_KAFKA_TESTS_TRUE}" && test -z "${ENABLE_KAFKA_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_KAFKA_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_KAFKA_STATIC_TRUE}" && test -z "${ENABLE_KAFKA_STATIC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_KAFKA_STATIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OMKAFKA_USE_DUMMY_TRUE}" && test -z "${OMKAFKA_USE_DUMMY_FALSE}"; then
+ as_fn_error $? "conditional \"OMKAFKA_USE_DUMMY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${IMKAFKA_USE_DUMMY_TRUE}" && test -z "${IMKAFKA_USE_DUMMY_FALSE}"; then
+ as_fn_error $? "conditional \"IMKAFKA_USE_DUMMY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMKAFKA_TRUE}" && test -z "${ENABLE_OMKAFKA_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMKAFKA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMKAFKA_TRUE}" && test -z "${ENABLE_IMKAFKA_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMKAFKA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMAZUREEVENTHUBS_TRUE}" && test -z "${ENABLE_OMAZUREEVENTHUBS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMAZUREEVENTHUBS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_QPIDPROTON_STATIC_TRUE}" && test -z "${ENABLE_QPIDPROTON_STATIC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_QPIDPROTON_STATIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMMONGODB_TRUE}" && test -z "${ENABLE_OMMONGODB_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMMONGODB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMDTLS_TRUE}" && test -z "${ENABLE_IMDTLS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMDTLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMDTLS_TRUE}" && test -z "${ENABLE_OMDTLS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMDTLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMCZMQ_TRUE}" && test -z "${ENABLE_IMCZMQ_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMCZMQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMCZMQ_TRUE}" && test -z "${ENABLE_OMCZMQ_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMCZMQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMRABBITMQ_TRUE}" && test -z "${ENABLE_OMRABBITMQ_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMRABBITMQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_REDIS_TESTS_TRUE}" && test -z "${ENABLE_REDIS_TESTS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_REDIS_TESTS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMHIREDIS_TRUE}" && test -z "${ENABLE_OMHIREDIS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMHIREDIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_IMHIREDIS_TRUE}" && test -z "${ENABLE_IMHIREDIS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_IMHIREDIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMHTTPFS_TRUE}" && test -z "${ENABLE_OMHTTPFS_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMHTTPFS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMAMQP1_TRUE}" && test -z "${ENABLE_OMAMQP1_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMAMQP1\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_OMTCL_TRUE}" && test -z "${ENABLE_OMTCL_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_OMTCL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMKUBERNETES_TRUE}" && test -z "${ENABLE_MMKUBERNETES_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMKUBERNETES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MMTAGHOSTNAME_TRUE}" && test -z "${ENABLE_MMTAGHOSTNAME_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_MMTAGHOSTNAME\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_DISTCHECK_WORKAROUND_TRUE}" && test -z "${ENABLE_DISTCHECK_WORKAROUND_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_DISTCHECK_WORKAROUND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_GENERATE_MAN_PAGES_TRUE}" && test -z "${ENABLE_GENERATE_MAN_PAGES_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_GENERATE_MAN_PAGES\" 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 rsyslog $as_me 8.2402.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 <rsyslog@lists.adiscon.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+rsyslog config.status 8.2402.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
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+
+# 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'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_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"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $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_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $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"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $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"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $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"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $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_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+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\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ 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 \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that 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'
+ 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" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "runtime/Makefile") CONFIG_FILES="$CONFIG_FILES runtime/Makefile" ;;
+ "compat/Makefile") CONFIG_FILES="$CONFIG_FILES compat/Makefile" ;;
+ "grammar/Makefile") CONFIG_FILES="$CONFIG_FILES grammar/Makefile" ;;
+ "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
+ "plugins/imudp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imudp/Makefile" ;;
+ "plugins/imtcp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imtcp/Makefile" ;;
+ "plugins/im3195/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/im3195/Makefile" ;;
+ "plugins/imgssapi/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imgssapi/Makefile" ;;
+ "plugins/imuxsock/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imuxsock/Makefile" ;;
+ "plugins/imjournal/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imjournal/Makefile" ;;
+ "plugins/immark/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/immark/Makefile" ;;
+ "plugins/imklog/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imklog/Makefile" ;;
+ "plugins/omhdfs/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omhdfs/Makefile" ;;
+ "plugins/omkafka/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omkafka/Makefile" ;;
+ "plugins/omprog/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omprog/Makefile" ;;
+ "plugins/mmexternal/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmexternal/Makefile" ;;
+ "plugins/omstdout/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omstdout/Makefile" ;;
+ "plugins/omjournal/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omjournal/Makefile" ;;
+ "plugins/pmciscoios/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pmciscoios/Makefile" ;;
+ "plugins/pmnull/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pmnull/Makefile" ;;
+ "plugins/pmnormalize/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pmnormalize/Makefile" ;;
+ "plugins/omruleset/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omruleset/Makefile" ;;
+ "plugins/omuxsock/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omuxsock/Makefile" ;;
+ "plugins/imfile/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imfile/Makefile" ;;
+ "plugins/imsolaris/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imsolaris/Makefile" ;;
+ "plugins/imptcp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imptcp/Makefile" ;;
+ "plugins/impstats/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/impstats/Makefile" ;;
+ "plugins/imrelp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imrelp/Makefile" ;;
+ "plugins/imdiag/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imdiag/Makefile" ;;
+ "plugins/imkafka/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imkafka/Makefile" ;;
+ "plugins/omtesting/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omtesting/Makefile" ;;
+ "plugins/omgssapi/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omgssapi/Makefile" ;;
+ "plugins/ommysql/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ommysql/Makefile" ;;
+ "plugins/ompgsql/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ompgsql/Makefile" ;;
+ "plugins/omrelp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omrelp/Makefile" ;;
+ "plugins/omlibdbi/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omlibdbi/Makefile" ;;
+ "plugins/ommail/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ommail/Makefile" ;;
+ "plugins/fmhttp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/fmhttp/Makefile" ;;
+ "plugins/omsnmp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omsnmp/Makefile" ;;
+ "plugins/omudpspoof/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omudpspoof/Makefile" ;;
+ "plugins/ommongodb/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ommongodb/Makefile" ;;
+ "plugins/mmnormalize/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmnormalize/Makefile" ;;
+ "plugins/mmjsonparse/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmjsonparse/Makefile" ;;
+ "plugins/mmaudit/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmaudit/Makefile" ;;
+ "plugins/mmanon/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmanon/Makefile" ;;
+ "plugins/mmrm1stspace/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmrm1stspace/Makefile" ;;
+ "plugins/mmutf8fix/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmutf8fix/Makefile" ;;
+ "plugins/mmfields/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmfields/Makefile" ;;
+ "plugins/mmpstrucdata/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmpstrucdata/Makefile" ;;
+ "plugins/omelasticsearch/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omelasticsearch/Makefile" ;;
+ "plugins/omclickhouse/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omclickhouse/Makefile" ;;
+ "plugins/mmsnmptrapd/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmsnmptrapd/Makefile" ;;
+ "plugins/pmlastmsg/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pmlastmsg/Makefile" ;;
+ "plugins/mmdblookup/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/mmdblookup/Makefile" ;;
+ "plugins/omazureeventhubs/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omazureeventhubs/Makefile" ;;
+ "plugins/imdtls/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/imdtls/Makefile" ;;
+ "plugins/omdtls/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omdtls/Makefile" ;;
+ "contrib/mmdarwin/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmdarwin/Makefile" ;;
+ "contrib/omhttp/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omhttp/Makefile" ;;
+ "contrib/fmhash/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/fmhash/Makefile" ;;
+ "contrib/fmunflatten/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/fmunflatten/Makefile" ;;
+ "contrib/ffaup/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/ffaup/Makefile" ;;
+ "contrib/pmsnare/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/pmsnare/Makefile" ;;
+ "contrib/pmpanngfw/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/pmpanngfw/Makefile" ;;
+ "contrib/pmaixforwardedfrom/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/pmaixforwardedfrom/Makefile" ;;
+ "contrib/omhiredis/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omhiredis/Makefile" ;;
+ "contrib/omrabbitmq/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omrabbitmq/Makefile" ;;
+ "contrib/imkmsg/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imkmsg/Makefile" ;;
+ "contrib/mmgrok/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmgrok/Makefile" ;;
+ "contrib/mmcount/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmcount/Makefile" ;;
+ "contrib/omczmq/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omczmq/Makefile" ;;
+ "contrib/imczmq/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imczmq/Makefile" ;;
+ "contrib/mmsequence/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmsequence/Makefile" ;;
+ "contrib/mmrfc5424addhmac/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmrfc5424addhmac/Makefile" ;;
+ "contrib/pmcisconames/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/pmcisconames/Makefile" ;;
+ "contrib/omhttpfs/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omhttpfs/Makefile" ;;
+ "contrib/omamqp1/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omamqp1/Makefile" ;;
+ "contrib/omtcl/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omtcl/Makefile" ;;
+ "contrib/imbatchreport/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imbatchreport/Makefile" ;;
+ "contrib/omfile-hardened/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/omfile-hardened/Makefile" ;;
+ "contrib/mmkubernetes/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmkubernetes/Makefile" ;;
+ "contrib/impcap/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/impcap/Makefile" ;;
+ "contrib/imtuxedoulog/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imtuxedoulog/Makefile" ;;
+ "contrib/improg/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/improg/Makefile" ;;
+ "contrib/imhttp/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imhttp/Makefile" ;;
+ "contrib/mmtaghostname/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/mmtaghostname/Makefile" ;;
+ "contrib/imdocker/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imdocker/Makefile" ;;
+ "contrib/pmdb2diag/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/pmdb2diag/Makefile" ;;
+ "contrib/imhiredis/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/imhiredis/Makefile" ;;
+ "tests/set-envvars") CONFIG_FILES="$CONFIG_FILES tests/set-envvars" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/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 = ""
+
+}
+{
+ 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 = ""
+}
+/^[\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.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ case $CONFIG_FILES in #(
+ *\'*) :
+ eval set x "$CONFIG_FILES" ;; #(
+ *) :
+ set x $CONFIG_FILES ;; #(
+ *) :
+ ;;
+esac
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$am_mf" : 'X\(//\)[^/]' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$am_mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$am_mf" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { echo "$as_me:$LINENO: cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles" >&5
+ (cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } || am_rc=$?
+ done
+ if test $am_rc -ne 0; 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 $? "Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. Try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { am_dirpart=; unset am_dirpart;}
+ { am_filepart=; unset am_filepart;}
+ { am_mf=; unset am_mf;}
+ { am_rc=; unset am_rc;}
+ rm -f conftest-deps.mk
+}
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options that 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
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 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 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# 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
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# 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 into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# 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
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# 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 where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# 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
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# 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
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_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 set != "${COLLECT_NAMES+set}"; 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)
+
+ 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
+
+
+echo "****************************************************"
+echo "rsyslog will be compiled with the following settings:"
+echo
+echo " Large file support enabled: $enable_largefile"
+echo " Networking support enabled: $enable_inet"
+echo " Regular expressions support enabled: $enable_regexp"
+echo " rsyslog runtime will be built: $enable_rsyslogrt"
+echo " rsyslogd will be built: $enable_rsyslogd"
+echo " have to generate man pages: $have_to_generate_man_pages"
+echo " Unlimited select() support enabled: $enable_unlimited_select"
+echo " uuid support enabled: $enable_uuid"
+echo " Log file signing support via KSI LS12: $enable_ksi_ls12"
+echo " Log file encryption support: $enable_libgcrypt"
+echo " Log file compression via zstd support: $enable_libzstd"
+echo " anonymization support enabled: $enable_mmanon"
+echo " message counting support enabled: $enable_mmcount"
+echo " liblogging-stdlog support enabled: $enable_liblogging_stdlog"
+echo " libsystemd enabled: $enable_libsystemd"
+echo " kafka static linking enabled: $enable_kafka_static"
+echo " qpid proton static linking enabled: $enable_qpidproton_static"
+echo " atomic operations enabled: $enable_atomic_operations"
+echo " libcap-ng support enabled: $enable_libcapng"
+
+echo
+echo "---{ input plugins }---"
+if test "$unamestr" != "AIX"; then
+echo " Klog functionality enabled: $enable_klog ($os_type)"
+fi
+echo " /dev/kmsg functionality enabled: $enable_kmsg"
+echo " plain tcp input module enabled: $enable_imptcp"
+echo " DTLS udp input module enabled: $enable_imdtls"
+echo " imdiag enabled: $enable_imdiag"
+echo " file input module enabled: $enable_imfile"
+echo " docker log input module enabled: $enable_imdocker"
+echo " Solaris input module enabled: $enable_imsolaris"
+echo " periodic statistics module enabled: $enable_impstats"
+echo " imczmq input module enabled: $enable_imczmq"
+echo " imjournal input module enabled: $enable_imjournal"
+if test "$enable_imjournal" = "optional"; then
+echo " imjournal use dummy: $imjournal_use_dummy"
+fi
+echo " imbatchreport input module enabled: $enable_imbatchreport"
+echo " imkafka module will be compiled: $enable_imkafka"
+if test "$enable_imkafka" = "optional"; then
+echo " imkafka use dummy: $imkafka_use_dummy"
+fi
+echo " impcap input module enabled: $enable_impcap"
+echo " imtuxedoulog module will be compiled: $enable_imtuxedoulog"
+echo " improg input module enabled: $enable_improg"
+echo " imhttp input module enabled: $enable_imhttp"
+echo " imhiredis input module enabled: $enable_imhiredis"
+echo
+echo "---{ output plugins }---"
+echo " Mail support enabled: $enable_mail"
+echo " omfile-hardened module will be compiled: $enable_omfile_hardened"
+echo " omprog module will be compiled: $enable_omprog"
+echo " omstdout module will be compiled: $enable_omstdout"
+echo " omjournal module will be compiled: $enable_omjournal"
+echo " omhdfs module will be compiled: $enable_omhdfs"
+echo " omelasticsearch module will be compiled: $enable_elasticsearch"
+echo " omclickhouse module will be compiled: $enable_clickhouse"
+echo " omhttp module will be compiled: $enable_omhttp"
+echo " omruleset module will be compiled: $enable_omruleset"
+echo " omudpspoof module will be compiled: $enable_omudpspoof"
+echo " omuxsock module will be compiled: $enable_omuxsock"
+echo " omczmq module will be compiled: $enable_omczmq"
+echo " omrabbitmq module will be compiled: $enable_omrabbitmq"
+echo " omhttpfs module will be compiled: $enable_omhttpfs"
+echo " omamqp1 module will be compiled: $enable_omamqp1"
+echo " omtcl module will be compiled: $enable_omtcl"
+echo " omkafka module will be compiled: $enable_omkafka"
+echo " omhiredis module will be compiled: $enable_omhiredis"
+echo " omazureeventhubs module will be compiled: $enable_omazureeventhubs"
+echo " omdtls module will be compiled: $enable_omdtls"
+echo
+echo "---{ parser modules }---"
+echo " pmlastmsg module will be compiled: $enable_pmlastmsg"
+echo " pmcisconames module will be compiled: $enable_pmcisconames"
+echo " pmciscoios module will be compiled: $enable_pmciscoios"
+echo " pmnull module will be compiled: $enable_pmnull"
+echo " pmnormalize module will be compiled: $enable_pmnormalize"
+echo " pmaixforwardedfrom module w.be compiled: $enable_pmaixforwardedfrom"
+echo " pmsnare module will be compiled: $enable_pmsnare"
+echo " pmdb2diag module will be compiled: $enable_pmdb2diag"
+echo " pmpanngfw module will be compiled: $enable_pmpanngfw"
+echo
+echo "---{ message modification modules }---"
+echo " mmnormalize module will be compiled: $enable_mmnormalize"
+echo " mmjsonparse module will be compiled: $enable_mmjsonparse"
+echo " mmgrok module will be compiled: $enable_mmgrok"
+echo " mmjaduit module will be compiled: $enable_mmaudit"
+echo " mmsnmptrapd module will be compiled: $enable_mmsnmptrapd"
+echo " mmutf8fix enabled: $enable_mmutf8fix"
+echo " mmrfc5424addhmac enabled: $enable_mmrfc5424addhmac"
+echo " mmpstrucdata enabled: $enable_mmpstrucdata"
+echo " mmsequence enabled: $enable_mmsequence"
+echo " mmdblookup enabled: $enable_mmdblookup"
+echo " mmdarwin enabled: $enable_mmdarwin"
+echo " mmfields enabled: $enable_mmfields"
+echo " mmrm1stspace module enabled: $enable_mmrm1stspace"
+echo " mmkubernetes enabled: $enable_mmkubernetes"
+echo " mmtaghostname enabled: $enable_mmtaghostname"
+echo
+echo "---{ database support }---"
+echo " MySql support enabled: $enable_mysql"
+echo " libdbi support enabled: $enable_libdbi"
+if test "$enable_libdbi" = "optional"; then
+echo " libdbi use dummy: $libdbi_use_dummy"
+fi
+echo " PostgreSQL support enabled: $enable_pgsql"
+echo " mongodb support enabled: $enable_ommongodb"
+echo " hiredis support enabled: $enable_omhiredis"
+echo
+echo "---{ protocol support }---"
+echo " openssl network stream driver enabled: $enable_openssl"
+echo " GnuTLS network stream driver enabled: $enable_gnutls"
+echo " GSSAPI Kerberos 5 support enabled: $enable_gssapi_krb5"
+echo " RELP support enabled: $enable_relp"
+echo " SNMP support enabled: $enable_snmp"
+echo
+echo "---{ function modules }---"
+echo " fmhttp enabled: $enable_fmhttp"
+echo " fmhash enabled: $enable_fmhash"
+echo " fmhash with xxhash enabled: $enable_fmhash_xxhash"
+echo " fmunflatten enabled: $enable_fmunflatten"
+echo " ffaup enabled: $enable_ffaup"
+echo
+echo "---{ debugging support }---"
+echo " distcheck workaround enabled: $enable_distcheck_workaround"
+echo " Testbench enabled: $enable_testbench"
+echo " valgrind tests enabled: $with_valgrind_testbench"
+echo " valgrind helgrind tests enabled: $enable_helgrind"
+echo " Default tests enabled: $enable_default_tests"
+echo " Testbench libfaketime tests enabled: $enable_libfaketime"
+echo " Extended Testbench enabled: $enable_extended_tests"
+echo " MySQL Tests enabled: $enable_mysql_tests"
+echo " Elasticsearch Tests: $enable_elasticsearch_tests"
+echo " ClickHouse Tests: $enable_clickhouse_tests"
+echo " PostgreSQL Tests enabled: $enable_pgsql_tests"
+echo " Kafka Tests enabled: $enable_kafka_tests"
+echo " Redis Tests enabled: $enable_redis_tests"
+echo " Omazureeventhubs Tests enabled: $enable_omazureeventhubs_tests"
+echo " Imdocker Tests enabled: $enable_imdocker_tests"
+echo " gnutls tests enabled: $enable_gnutls_tests"
+echo " imfile tests enabled: $enable_imfile_tests"
+echo " systemd journal tests enabled: $enable_journal_tests"
+echo " SNMP Tests enabled: $enable_snmp_tests"
+echo " Debug mode enabled: $enable_debug"
+echo " (total) debugless mode enabled: $enable_debugless"
+echo " Diagnostic tools enabled: $enable_diagtools"
+echo " End-User tools enabled: $enable_usertools"
+echo " Valgrind support settings enabled: $enable_valgrind"
+echo
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..0de2eed
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,3097 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([rsyslog],[8.2402.0],[rsyslog@lists.adiscon.com]) # UPDATE on release
+AC_DEFINE(VERSION_YEAR, 24, [year part of real rsyslog version]) # UPDATE on release
+AC_DEFINE(VERSION_MONTH, 2, [month part of real rsyslog version]) # UPDATE on release
+
+AM_INIT_AUTOMAKE([subdir-objects])
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+unamestr=$(uname)
+if test "$unamestr" = "AIX"; then
+ AC_ARG_ENABLE(aix64bits,
+ [AS_HELP_STRING([--enable-aix64bits],[Enable compilation of rsyslog using 64 bits @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_aix64bits="yes" ;;
+ no) enable_aix64bits="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-aix64bits) ;;
+ esac],
+ [enable_aix64bits=no]
+ )
+
+ CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT"
+ LDFLAGS="-brtl"
+ if test "x$enable_aix64bits" == "xyes"; then
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS="$LDFLAGS -b64"
+ AR_CFLAGS="-X64 $AR_CFLAGS"
+ NM="$(which nm) -X64 rcu"
+ fi
+fi
+
+AC_CONFIG_SRCDIR([ChangeLog])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_HEADERS([config.h])
+
+AC_USE_SYSTEM_EXTENSIONS
+
+# Checks for programs.
+AC_PROG_LEX
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_CC_C99
+AC_DISABLE_STATIC
+# AIXPORT START: enable dlopen
+if test "$unamestr" = "AIX"; then
+ AC_LIBTOOL_DLOPEN
+fi
+# AIXPORT end
+AC_PROG_LIBTOOL
+AC_CANONICAL_HOST
+
+if test "$GCC" = "yes"
+then
+ m4_ifdef([AX_IS_RELEASE], [
+ AX_IS_RELEASE([git-directory])
+ m4_ifdef([AX_COMPILER_FLAGS], [
+ AX_COMPILER_FLAGS(,,,,[-Wunused-parameter -Wmissing-field-initializers])
+ # unfortunately, AX_COMPILER_FLAGS does not provide a way to override
+ # the default -Wno-error=warning" flags. So we do this via sed below.
+ # Note: we *really* want to have this error out during CI testing!
+ # rgerhards, 2018-05-09
+ WARN_CFLAGS="$(echo "$WARN_CFLAGS" | sed s/-Wno-error=/-W/g)"
+ ], [
+ CFLAGS="$CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute -g"
+ AC_MSG_WARN([missing AX_COMPILER_FLAGS macro, not using it])
+ ])
+ ], [
+ CFLAGS="$CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute -g"
+ AC_MSG_WARN([missing AX_IS_RELEASE macro, not using AX_COMPILER_FLAGS macro because of this])
+ ])
+else
+ AC_MSG_WARN([compiler is not GCC or close compatible, not using ax_compiler_flags because of this (CC=$CC)])
+fi
+
+PKG_PROG_PKG_CONFIG
+
+AC_ARG_VAR(CONF_FILE_PATH, Configuration file path (default : /etc/rsyslog.conf))
+if test "$ac_cv_env_CONF_FILE_PATH_set" = "set"; then
+ AC_DEFINE_UNQUOTED(PATH_CONFFILE, "${ac_cv_env_CONF_FILE_PATH_value}", "Configuration file path (default : /etc/rsyslog.conf)")
+fi
+
+AC_ARG_VAR(PID_FILE_PATH, Pid file path (default : /var/run/rsyslogd.pid))
+if test "$ac_cv_env_PID_FILE_PATH_set" = "set"; then
+ AC_DEFINE_UNQUOTED(PATH_PIDFILE, "${ac_cv_env_PID_FILE_PATH_value}", "Pid file path (default : /var/run/rsyslogd.pid)")
+fi
+
+
+# modules we require
+PKG_CHECK_MODULES(LIBESTR, libestr >= 0.1.9)
+
+PKG_CHECK_MODULES([LIBFASTJSON], [libfastjson >= 0.99.8],,)
+
+AC_DEFINE_UNQUOTED([PLATFORM_ID], ["${host}"], [platform id for display purposes])
+# we don't mind if we don't have the lsb_release utility. But if we have, it's
+# nice to have the extra information.
+AC_DEFINE_UNQUOTED([PLATFORM_ID_LSB], ["`lsb_release -d`"], [platform id for display purposes])
+
+echo HOST: ${host}
+case "${host}" in
+ *-*-linux*)
+ AC_DEFINE([OS_LINUX], [1], [Indicator for a Linux OS])
+ os_type="linux"
+ ;;
+ *-*-*darwin*|*-*-dragonfly*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
+ AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS])
+ os_type="bsd"
+ ;;
+ *-apple-*)
+ AC_DEFINE([OS_APPLE], [1], [Indicator for APPLE OS])
+ os_type="apple"
+ ;;
+ *-*-kfreebsd*)
+ # kernel is FreeBSD, but userspace is glibc - i.e. like linux
+ # do not DEFINE OS_BSD
+ os_type="bsd"
+ ;;
+ *-*-solaris*)
+ os_type="solaris"
+ AC_DEFINE([OS_SOLARIS], [1], [Indicator for a Solaris OS])
+ AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], [1], [Use POSIX pthread semantics])
+ AC_DEFINE([_XOPEN_SOURCE], [600], [Use X/Open CAE Specification])
+ CPPFLAGS="-std=c99 $CPPFLAGS"
+ CFLAGS="-std=c99 $CFLAGS"
+ SOL_LIBS="-lsocket -lnsl"
+ # Solaris libuuid does not ship with a pkgconfig file so override the appropriate
+ # variables (but only if they have not been set by the user).
+ LIBUUID_CFLAGS=${LIBUUID_CFLAGS:= }
+ LIBUUID_LIBS=${LIBUUID_LIBS:=-luuid}
+ AC_SUBST(SOL_LIBS)
+ ;;
+ *-*-aix*)
+ os_type="aix"
+ AC_DEFINE([OS_AIX], [1], [Indicator for a AIX OS])
+ ;;
+esac
+AM_CONDITIONAL(OS_APPLE, test x$os_type == xapple)
+AM_CONDITIONAL(OS_LINUX, test x$os_type == xlinux)
+AM_CONDITIONAL(OS_AIX, test x$os_type == xaix)
+
+AM_PATH_PYTHON(,, [:])
+
+# Running from git source?
+in_git_src=no
+AS_IF([test -d "$srcdir"/.git && ! test -f "$srcdir"/.tarball-version], [in_git_src=yes])
+
+
+AC_DEFINE_UNQUOTED([HOSTENV], "$host", [the host environment, can be queried via a system variable])
+
+# Some Unix systems, like Gnu Hurd, don't define PATH_MAX
+AC_MSG_CHECKING([for PATH_MAX])
+AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include <limits.h>]],
+ [[char checker[PATH_MAX];]])],
+ [
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AC_MSG_RESULT([no, mocking PATH_MAX = 4096])
+ AC_DEFINE([PATH_MAX], 4096, [replacement for missing PATH_MAX])
+ AC_DEFINE([MAXPATHLEN], 4096, [replacement for missing PATH_MAX]) # we assume this does not exit
+ ]
+ )
+
+# Checks for libraries.
+save_LIBS=$LIBS
+LIBS=
+AC_SEARCH_LIBS(clock_gettime, rt)
+RT_LIBS=$LIBS
+AC_SEARCH_LIBS(mq_getattr, rt)
+RT_LIBS="$RT_LIBS $LIBS"
+LIBS=
+AC_SEARCH_LIBS(dlopen, dl)
+DL_LIBS=$LIBS
+LIBS=$save_LIBS
+
+AC_SUBST(RT_LIBS)
+AC_SUBST(DL_LIBS)
+
+# Checks for header files.
+AC_HEADER_RESOLV
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADER([arpa/inet.h],[],[],[
+ [#ifdef HAVE_ARPA_INET_H
+ # include <arpa/inet.h>
+ #endif
+ ]
+])
+AC_CHECK_HEADERS([libgen.h],[],[],[
+ [#ifdef HAVE_LIBGEN_H
+ # include <libgen.h>
+ #endif
+ ]
+])
+AC_CHECK_HEADERS([malloc.h],[],[],[
+ [#ifdef HAVE_MALLOC_H
+ # include <malloc.h>
+ #endif
+ ]
+])
+AC_CHECK_HEADERS([fcntl.h locale.h netdb.h netinet/in.h paths.h stddef.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h sys/stat.h unistd.h utmp.h utmpx.h sys/epoll.h sys/prctl.h sys/select.h getopt.h linux/close_range.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_MODE_T
+AC_TYPE_UID_T
+AC_TYPE_UINT8_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_C_VOLATILE
+
+sa_includes="\
+$ac_includes_default
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+"
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[$sa_includes])
+
+# Checks for library functions.
+AC_FUNC_CHOWN
+AC_FUNC_FORK
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_FUNC_STRERROR_R
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([flock recvmmsg basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setsid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64 asprintf close_range])
+AC_CHECK_FUNC([setns], [AC_DEFINE([HAVE_SETNS], [1], [Define if setns exists.])])
+AC_CHECK_TYPES([off64_t])
+
+AC_CHECK_HEADERS([sys/inotify.h], [rsyslog_sysinotify=yes])
+AC_CHECK_FUNCS([inotify_init], [rsyslog_inotify_init=yes])
+AM_CONDITIONAL(ENABLE_INOTIFY, test x$rsyslog_sysinotify = xyes -a x$rsyslog_inotify_init = xyes)
+
+# getifaddrs is in libc (mostly) or in libsocket (eg Solaris 11) or not defined (eg Solaris 10)
+AC_SEARCH_LIBS([getifaddrs], [socket], [AC_DEFINE(HAVE_GETIFADDRS, [1], [set define])])
+
+# the check below is probably ugly. If someone knows how to do it in a better way, please
+# let me know! -- rgerhards, 2010-10-06
+AC_CHECK_DECL([SCM_CREDENTIALS], [AC_DEFINE(HAVE_SCM_CREDENTIALS, [1], [set define])], [], [#include <sys/types.h>
+#include <sys/socket.h>])
+AC_CHECK_DECL([SO_TIMESTAMP], [AC_DEFINE(HAVE_SO_TIMESTAMP, [1], [set define])], [], [#include <sys/types.h>
+#include <sys/socket.h>])
+AC_CHECK_DECL([SYS_gettid], [AC_DEFINE(HAVE_SYS_gettid, [1], [set define])], [], [#include <sys/syscall.h>])
+AC_CHECK_MEMBER([struct sysinfo.uptime], [AC_DEFINE(HAVE_SYSINFO_UPTIME, [1], [set define])], [], [#include <sys/sysinfo.h>])
+AC_CHECK_DECL([GLOB_NOMAGIC], [AC_DEFINE(HAVE_GLOB_NOMAGIC, [1], [set define])], [], [#include <glob.h>])
+
+# Check for MAXHOSTNAMELEN
+AC_MSG_CHECKING(for MAXHOSTNAMELEN)
+AC_TRY_COMPILE([
+ #include <sys/param.h>
+ #include <netdb.h>
+ ], [
+ return MAXHOSTNAMELEN;
+ ]
+ ,
+ AC_MSG_RESULT(yes)
+ ,
+ # note: we use 1024 here, which should be far more than needed by any system. If that's too low, we simply
+ # life with the need to change it. Most of the code doesn't need it anyways, but there are a few places
+ # where it actually is needed and it makes no sense to change them.
+ AC_DEFINE(MAXHOSTNAMELEN, 1024, [Define with a value if your <sys/param.h> does not define MAXHOSTNAMELEN])
+ AC_MSG_RESULT(no; defined as 64)
+)
+
+# check if GNU's ld is used
+
+# Check for __builtin_expect()
+AC_MSG_CHECKING([for __builtin_expect()])
+AC_LINK_IFELSE([AC_LANG_PROGRAM(, return __builtin_expect(main != 0, 1))],
+ [AC_DEFINE(HAVE_BUILTIN_EXPECT, 1,
+ Define to 1 if compiler supports __builtin_expect)
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])])
+
+# check for availability of atomic operations
+# Note: this switch is primarily for the testbench, so that we can try
+# to build w/o automic operations on systems that actually support them.
+# Usually, atomic operations should be used when available as this
+# speeds up processig.
+# note that when automic operations are enabled but not available, they
+# will silently NOT be used!
+AC_ARG_ENABLE(atomic-operations,
+ [AS_HELP_STRING([--enable-atomic-operations],[Enable atomic operation support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_atomic_operations="yes" ;;
+ no) enable_atomic_operations="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-atomic-operations) ;;
+ esac],
+ [enable_atomic_operations=yes]
+)
+if test "$enable_atomic_operations" = "yes"; then
+ RS_ATOMIC_OPERATIONS
+ RS_ATOMIC_OPERATIONS_64BIT
+fi
+
+# fall back to POSIX sems for atomic operations (cpu expensive)
+AC_CHECK_HEADERS([semaphore.h sys/syscall.h])
+
+
+# Additional module directories
+AC_ARG_WITH(moddirs,
+ [AS_HELP_STRING([--with-moddirs=DIRS],[Additional module search paths appended to @<:@$libdir/rsyslog@:>@])],
+ [_save_IFS=$IFS ; IFS=$PATH_SEPARATOR ; moddirs=""
+ for w in ${with_moddirs} ;
+ do
+ case $w in
+ "") continue ;; */) ;; *) w="${w}/" ;;
+ esac
+ for m in ${moddirs} ;
+ do
+ test "x$w" = "x${libdir}/${PACKAGE}/" || \
+ test "x$w" = "x$m" || test "x$w" = "x/" && \
+ continue 2
+ done
+ case $moddirs in
+ "") moddirs="$w" ;; *) moddirs="${moddirs}:${w}" ;;
+ esac
+ done ; IFS=$_save_IFS],[moddirs=""]
+)
+AM_CONDITIONAL(WITH_MODDIRS, test x$moddirs != x)
+AC_SUBST(moddirs)
+
+
+# Large file support
+# http://www.gnu.org/software/autoconf/manual/html_node/System-Services.html#index-AC_005fSYS_005fLARGEFILE-1028
+AC_SYS_LARGEFILE
+case "${enable_largefile}" in
+ no) ;;
+ *) enable_largefile="yes" ;;
+esac
+
+# Regular expressions
+AC_ARG_ENABLE(regexp,
+ [AS_HELP_STRING([--enable-regexp],[Enable regular expressions support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_regexp="yes" ;;
+ no) enable_regexp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-regexp) ;;
+ esac],
+ [enable_regexp=yes]
+)
+AM_CONDITIONAL(ENABLE_REGEXP, test x$enable_regexp = xyes)
+if test "$enable_regexp" = "yes"; then
+ AC_DEFINE(FEATURE_REGEXP, 1, [Regular expressions support enabled.])
+fi
+
+# zlib support
+PKG_CHECK_MODULES([ZLIB], [zlib], [found_zlib=yes], [found_zlib=no])
+AS_IF([test "x$found_zlib" = "xno"], [
+ AC_SEARCH_LIBS([inflate], [z], [AC_CHECK_HEADER([zlib.h], [found_zlib=yes])])
+ if test "x$found_zlib" = "xno" ; then
+ AC_MSG_ERROR([zlib library and headers not found])
+ fi
+ ZLIB_LIBS="-lz"
+ AC_SUBST(ZLIB_LIBS)
+])
+
+
+#hash implementations header checks
+AC_ARG_ENABLE(fmhash,
+ [AS_HELP_STRING([--enable-fmhash],[Enable fmhash support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_fmhash="yes" ;;
+ no) enable_fmhash="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-fmhash) ;;
+ esac],
+ [enable_fmhash=yes]
+)
+
+AC_ARG_ENABLE(libcap-ng,
+ [AS_HELP_STRING([--enable-libcap-ng],[Enable dropping capabilities to only the necessary set @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_libcapng="yes" ;;
+ no) enable_libcapng="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable_libcapng) ;;
+ esac],
+ [enable_libcapng=no]
+)
+
+if test "$enable_libcapng" = "yes"; then
+ PKG_CHECK_MODULES(
+ [LIBCAPNG_PRESENT],
+ [libcap-ng],
+ [AC_DEFINE([ENABLE_LIBCAPNG_PRESENT], [1], [Indicator that libcap-ng is present])],
+ [AC_MSG_ERROR(libcap-ng is not present.)]
+ )
+ PKG_CHECK_MODULES(
+ [LIBCAPNG],
+ [libcap-ng >= 0.8.2],
+ [AC_DEFINE([ENABLE_LIBCAPNG], [1], [Indicator that libcap-ng is present])],
+ [AC_MSG_ERROR([libcap-ng is present, but outdated - need 0.8.2 or above.])]
+ )
+ CFLAGS="$CFLAGS $LIBCAPNG_CFLAGS"
+ LIBS="$LIBS $LIBCAPNG_LIBS"
+fi
+
+
+AC_ARG_ENABLE(fmhash-xxhash,
+ [AS_HELP_STRING([--enable-fmhash-xxhash],[Enable xxhash in fmhash support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_fmhash_xxhash="yes" ;;
+ no) enable_fmhash_xxhash="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-fmhash-xxhash) ;;
+ esac],
+ [enable_fmhash_xxhash=no]
+)
+
+AM_CONDITIONAL(ENABLE_FMHASH, [test "x$enable_fmhash" = "xyes" || test "x$enable_fmhash_xxhash" = "xyes"])
+
+AM_CONDITIONAL(ENABLE_FMHASH_XXHASH, test x$enable_fmhash_xxhash = xyes)
+if test "$enable_fmhash_xxhash" = "yes"; then
+ AC_CHECK_LIB([xxhash], [XXH64], [
+ AC_CHECK_HEADER([xxhash.h], [
+ AC_DEFINE(USE_HASH_XXHASH, 1,
+ [Using XXHASH for hash64.])
+ HASH_XXHASH_LIBS="-lxxhash"
+ AC_SUBST(HASH_XXHASH_LIBS)],
+ [AC_MSG_ERROR([Unable to add XXHASH support for hash64.])])
+ ])
+fi
+
+
+#faup header checks
+AC_ARG_ENABLE(ffaup,
+ [AS_HELP_STRING([--enable-ffaup],[Enable ffaup support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_ffaup="yes" ;;
+ no) enable_ffaup="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-ffaup) ;;
+ esac],
+ [enable_ffaup=no]
+)
+
+AM_CONDITIONAL(ENABLE_FFAUP, test x$enable_ffaup = xyes)
+if test "$enable_ffaup" = "yes"; then
+ AC_CHECK_LIB([faupl], [faup_init], [
+ AC_CHECK_HEADER([faup/faup.h], [
+ FAUP_LIBS="-lfaupl"
+ AC_SUBST(FAUP_LIBS)],
+ [AC_MSG_ERROR([Unable to add faup support for URL parsing.])])
+ ])
+fi
+
+
+# rscript function unflatten
+AC_ARG_ENABLE(fmunflatten,
+ [AS_HELP_STRING([--enable-fmunflatten],[Enable fmunflatten support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_fmunflatten="yes" ;;
+ no) enable_fmunflatten="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-fmunflatten) ;;
+ esac],
+ [enable_fmunflatten=no]
+)
+AM_CONDITIONAL(ENABLE_FMUNFLATTEN, test x$enable_fmunflatten = xyes)
+
+
+#gssapi
+AC_ARG_ENABLE(gssapi_krb5,
+ [AS_HELP_STRING([--enable-gssapi-krb5],[Enable GSSAPI Kerberos 5 support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_gssapi_krb5="yes" ;;
+ no) enable_gssapi_krb5="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gssapi-krb5) ;;
+ esac],
+ [enable_gssapi_krb5=no]
+)
+
+case "${os_type}" in
+solaris) GSSLIB=gss ;;
+*) GSSLIB=gssapi_krb5 ;;
+esac
+
+if test $enable_gssapi_krb5 = yes; then
+ AC_CHECK_LIB($GSSLIB, gss_acquire_cred, [
+ AC_CHECK_HEADER(gssapi/gssapi.h, [
+ AC_DEFINE(USE_GSSAPI,,
+ Define if you want to use GSSAPI)
+ GSS_LIBS="-l$GSSLIB"
+ AC_SUBST(GSS_LIBS)
+ ])
+ ])
+fi
+AM_CONDITIONAL(ENABLE_GSSAPI, test x$enable_gssapi_krb5 = xyes)
+
+
+# shall the testbench try to run test that require root permissions?
+# This is uncommon. Test skip if run under non-root, but that pollutes the
+# testbench result. So the default is not to do that.
+AC_ARG_ENABLE(root_tests,
+ [AS_HELP_STRING([--enable-root-tests],[enable root tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_root_tests="yes" ;;
+ no) enable_root_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-root-tests) ;;
+ esac],
+ [enable_root_tests=no]
+)
+AM_CONDITIONAL(ENABLE_ROOT_TESTS, test x$enable_root_tests = xyes)
+
+# multithreading via pthreads
+if test "$os_type" != "solaris"
+then
+ AC_CHECK_HEADERS(
+ [pthread.h],
+ [
+ AC_CHECK_LIB(
+ [pthread],
+ [pthread_create],
+ [
+ PTHREADS_LIBS="-lpthread"
+ if test "$unamestr" = "AIX"; then
+ case "${CC}" in
+ *xlc*|*xlC*) PTHREADS_CFLAGS="-qthreaded" ;;
+ *) PTHREADS_CFLAGS="-lpthreads" ;;
+ esac
+ else
+ PTHREADS_CFLAGS="-pthread"
+ fi
+ AC_SUBST(PTHREADS_LIBS)
+ AC_SUBST(PTHREADS_CFLAGS)
+ ],
+ [AC_MSG_FAILURE([pthread is missing])],
+ [-lpthread]
+ )
+ ],
+ [AC_MSG_FAILURE([pthread is missing])]
+ )
+fi
+
+AC_CHECK_LIB(
+ [pthread],
+ [pthread_rwlockattr_setkind_np],
+ [AC_DEFINE(
+ [HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP],
+ [1],
+ [Set-kind available for rwlock attr.])])
+
+AC_CHECK_LIB(
+ [pthread],
+ [pthread_setname_np],
+ [AC_DEFINE(
+ [HAVE_PTHREAD_SETNAME_NP],
+ [1],
+ [Can set thread-name.])])
+
+AC_SEARCH_LIBS(
+ [pthread_setschedparam],
+ [pthread],
+ [
+ rsyslog_have_pthread_setschedparam=yes
+ AC_DEFINE([HAVE_PTHREAD_SETSCHEDPARAM],
+ [1],
+ [Can set thread scheduling parameters])
+ ],
+ [
+ rsyslog_have_pthread_setschedparam=no
+ ]
+)
+AC_CHECK_HEADERS(
+ [sched.h],
+ [
+ rsyslog_have_sched_h=yes
+ ],
+ [
+ rsyslog_have_sched_h=no
+ ]
+)
+if test "$rsyslog_have_pthread_setschedparam" = "yes" -a "$rsyslog_have_sched_h" = "yes"; then
+ save_LIBS=$LIBS
+ LIBS=
+ AC_SEARCH_LIBS(sched_get_priority_max, rt)
+ if test "x$ac_cv_search" != "xno"; then
+ AC_CHECK_FUNCS(sched_get_priority_max)
+ fi
+ IMUDP_LIBS=$LIBS
+ AC_SUBST(IMUDP_LIBS)
+ LIBS=$save_LIBS
+fi
+
+if test "$unamestr" = "AIX"; then
+enable_klog="no"
+else
+# klog
+AC_ARG_ENABLE(klog,
+ [AS_HELP_STRING([--enable-klog],[Integrated klog functionality @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_klog="yes" ;;
+ no) enable_klog="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-klog) ;;
+ esac],
+ [enable_klog="yes"]
+)
+fi
+AM_CONDITIONAL(ENABLE_IMKLOG, test x$enable_klog = xyes)
+AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x$os_type = xbsd)
+AM_CONDITIONAL(ENABLE_IMKLOG_LINUX, test x$os_type = xlinux)
+AM_CONDITIONAL(ENABLE_IMKLOG_SOLARIS, test x$os_type = xsolaris)
+
+# kmsg
+AC_ARG_ENABLE(kmsg,
+ [AS_HELP_STRING([--enable-kmsg],[Kmsg structured kernel logs functionality @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_kmsg="yes" ;;
+ no) enable_kmsg="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-kmsg) ;;
+ esac],
+ [enable_kmsg="no"]
+)
+AM_CONDITIONAL(ENABLE_IMKMSG, test x$enable_kmsg = xyes)
+
+# imjournal
+AC_ARG_ENABLE(imjournal,
+ [AS_HELP_STRING([--enable-imjournal],[Systemd journal message import @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imjournal="yes" ;;
+ no) enable_imjournal="no" ;;
+ optional) enable_imjournal="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imjournal) ;;
+ esac],
+ [enable_imjournal="no"]
+)
+imjournal_use_dummy="no"
+if test "x$enable_imjournal" = "xyes" -o "x$enable_imjournal" = "xoptional"; then
+ PKG_CHECK_MODULES([LIBSYSTEMD_JOURNAL], [libsystemd >= 234] , [AC_DEFINE(NEW_JOURNAL, 1, [new systemd present])] , [
+ PKG_CHECK_MODULES([LIBSYSTEMD_JOURNAL], [libsystemd >= 209] , , [
+ PKG_CHECK_MODULES([LIBSYSTEMD_JOURNAL], [libsystemd-journal >= 197], , [
+ AS_IF([test x$enable_imjournal = xyes],
+ AC_MSG_FAILURE([imjournal support libraries are missing])
+ )
+ imjournal_use_dummy="yes"
+ ])
+ ])
+ ])
+fi
+AM_CONDITIONAL(IMJOURNAL_USE_DUMMY, test x$imjournal_use_dummy = xyes)
+AM_CONDITIONAL(ENABLE_IMJOURNAL, test x$enable_imjournal = xyes -o x$enable_imjournal = xoptional)
+
+# use libsystemd
+AC_ARG_ENABLE(libsystemd,
+ [AS_HELP_STRING([--enable-libsystemd],[Enable libsystemd mode @<:@default=auto@:>@])],
+ [case "${enableval}" in
+ yes) enable_libsystemd="yes" ;;
+ no) enable_libsystemd="no" ;;
+ auto) enable_libsystemd="auto" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-libsystemd) ;;
+ esac],
+ [enable_libsystemd="auto"]
+)
+if test "$enable_libsystemd" = "yes"; then
+ PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd],
+ [ AC_DEFINE(HAVE_LIBSYSTEMD, 1, [libsystemd present]) ]
+ )
+fi
+if test "$enable_libsystemd" = "auto"; then
+ PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd],
+ [ AC_DEFINE(HAVE_LIBSYSTEMD, 1, [libsystemd present])
+ AC_MSG_NOTICE([--enable-libsystemd in auto mode])
+ enable_libsystemd="yes"
+ ],
+ [ AC_MSG_WARN([libsystemd not present - disabling systemd support])
+ enable_libsystemd="no"
+ ]
+ )
+ AC_MSG_NOTICE([--enable-libsystemd in auto mode, enable-libsystemd is set to ${enable_libsystemd}])
+fi
+
+# inet
+AC_ARG_ENABLE(inet,
+ [AS_HELP_STRING([--enable-inet],[Enable automatic load of omfwd and limit build of networking libraries @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_inet="yes" ;;
+ no) enable_inet="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-inet) ;;
+ esac],
+ [enable_inet="yes"]
+)
+AM_CONDITIONAL(ENABLE_INET, test x$enable_inet = xyes)
+if test "$enable_inet" = "yes"; then
+ AC_DEFINE(SYSLOG_INET, 1, [network support is integrated.])
+fi
+
+# jemalloc
+AC_ARG_ENABLE(jemalloc,
+ [AS_HELP_STRING([--enable-jemalloc],[Enable jemalloc support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_jemalloc="yes" ;;
+ no) enable_jemalloc="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-jemalloc) ;;
+ esac],
+ [enable_jemalloc="no"]
+)
+AM_CONDITIONAL(ENABLE_JEMALLOC, test x$enable_jemalloc = xyes)
+if test "$enable_jemalloc" = "yes"; then
+ AC_CHECK_LIB(
+ [jemalloc],
+ [malloc_stats_print],
+ [RT_LIBS="$RT_LIBS -ljemalloc"
+ AC_DEFINE(HAVE_JEMALLOC, 1, [jemalloc support is integrated.])
+ ],
+ [AC_MSG_FAILURE([jemalloc library is missing])],
+ []
+ )
+fi
+
+
+# support for unlimited select() syscall
+AC_ARG_ENABLE(unlimited_select,
+ [AS_HELP_STRING([--enable-unlimited-select],[Enable unlimited select() syscall @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_unlimited_select="yes" ;;
+ no) enable_unlimited_select="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-unlimited-select) ;;
+ esac],
+ [enable_unlimited_select="no"]
+)
+if test "$enable_unlimited_select" = "yes"; then
+ AC_DEFINE(USE_UNLIMITED_SELECT, 1, [If defined, the select() syscall won't be limited to a particular number of file descriptors.])
+fi
+
+
+# debug
+AC_ARG_ENABLE(debug,
+ [AS_HELP_STRING([--enable-debug],[Enable debug mode @<:@default=auto@:>@])],
+ [case "${enableval}" in
+ yes) enable_debug="yes" ;;
+ no) enable_debug="no" ;;
+ auto) enable_debug="auto" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+ esac],
+ [enable_debug="auto"]
+)
+if test "$enable_debug" = "auto"; then
+ if test "x$in_git_src" = "xyes"; then
+ enable_debug="yes"
+ else
+ enable_debug="no"
+ fi
+ AC_MSG_NOTICE([enable-debug in auto mode, enable-debug is set to ${enable_debug}])
+fi
+if test "$enable_debug" = "yes"; then
+ AC_DEFINE(DEBUG, 1, [Defined if debug mode is enabled (its easier to check).])
+fi
+if test "$enable_debug" = "no"; then
+ AC_DEFINE(NDEBUG, 1, [Defined if debug mode is disabled.])
+fi
+
+
+# debug-symbols
+AC_ARG_ENABLE(debug_symbols,
+ [AS_HELP_STRING([--disable-debug-symbols],[Disable debugging symbols @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_debug_symbols="yes" ;;
+ no) enable_debug_symbols="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-debug-symbols) ;;
+ esac],
+ [enable_debug_symbols="yes"]
+)
+
+
+# total debugless: highest performance, but no way at all to enable debug
+# logging
+AC_ARG_ENABLE(debugless,
+ [AS_HELP_STRING([--enable-debugless],[Enable runtime instrumentation mode @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_debugless="yes" ;;
+ no) enable_debugless="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-debugless) ;;
+ esac],
+ [enable_debugless="no"]
+)
+if test "$enable_debugless" = "yes"; then
+ AC_DEFINE(DEBUGLESS, 1, [Defined if debugless mode is enabled.])
+fi
+
+
+# valgrind
+AC_ARG_ENABLE(valgrind,
+ [AS_HELP_STRING([--enable-valgrind],[Enable somes special code that rsyslog core developers consider useful for testing. Do NOT use if you don't exactly know what you are doing, except if told so by rsyslog developers. NOT to be used by distro maintainers for building regular packages. @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_valgrind="yes" ;;
+ no) enable_valgrind="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;;
+ esac],
+ [enable_valgrind="no"]
+)
+if test "$enable_valgrind" = "yes"; then
+ AC_DEFINE(VALGRIND, 1, [Defined if valgrind support settings are to be enabled (e.g. prevents dlclose()).])
+fi
+
+
+# compile diagnostic tools (small helpers usually not needed)
+AC_ARG_ENABLE(diagtools,
+ [AS_HELP_STRING([--enable-diagtools],[Enable diagnostic tools @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_diagtools="yes" ;;
+ no) enable_diagtools="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-diagtools) ;;
+ esac],
+ [enable_diagtools=no]
+)
+AM_CONDITIONAL(ENABLE_DIAGTOOLS, test x$enable_diagtools = xyes)
+
+
+# compile end-user tools
+AC_ARG_ENABLE(usertools,
+ [AS_HELP_STRING([--enable-usertools],[Enable end user tools @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_usertools="yes" ;;
+ no) enable_usertools="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-usertools) ;;
+ esac],
+ [enable_usertools=no]
+)
+AM_CONDITIONAL(ENABLE_USERTOOLS, test x$enable_usertools = xyes)
+
+
+# MySQL support
+AC_ARG_ENABLE(mysql,
+ [AS_HELP_STRING([--enable-mysql],[Enable MySql database support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mysql="yes" ;;
+ no) enable_mysql="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mysql) ;;
+ esac],
+ [enable_mysql=no]
+)
+AS_IF([test "x$enable_mysql" = "xyes"],[
+ PKG_CHECK_MODULES([MYSQL],[mysqlclient],,[
+ AC_CHECK_PROG(
+ [MYSQL_CONFIG],
+ [mysql_config],
+ [mysql_config],
+ [no],,
+ )
+ AS_IF([test "x${MYSQL_CONFIG}" = "xno"],[
+ AC_MSG_FAILURE([mysql_config not found - usually a package named mysql-dev, libmysql-dev or similar, is missing - install it to fix this issue])
+ ])
+ MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags`
+ MYSQL_LIBS=`$MYSQL_CONFIG --libs`
+ ])
+ AC_MSG_CHECKING(if we have mysql_library_init)
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $MYSQL_CFLAGS"
+ save_LIBS="$LIBS"
+ AC_CHECK_LIB(
+ [mysqlclient],
+ [mysql_init],
+ ,
+ [AC_MSG_FAILURE([MySQL library is missing])],
+ [$MYSQL_LIBS]
+ )
+ LIBS="$LIBS $MYSQL_LIBS"
+ AC_TRY_LINK(
+ [#include <mysql.h>
+ #include <stdio.h>],
+ [mysql_library_init(0, NULL, NULL)],
+ [have_mysql_library_init=yes],
+ [have_mysql_library_init=no])
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+])
+AM_CONDITIONAL(ENABLE_MYSQL, test x$enable_mysql = xyes)
+if test "$have_mysql_library_init" = "yes"; then
+ AC_DEFINE([HAVE_MYSQL_LIBRARY_INIT], [1], [mysql_library_init available])
+fi
+AC_SUBST(MYSQL_CFLAGS)
+AC_SUBST(MYSQL_LIBS)
+
+
+# PostgreSQL support
+AC_ARG_ENABLE(pgsql,
+ [AS_HELP_STRING([--enable-pgsql],[Enable PostgreSQL database support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pgsql="yes" ;;
+ no) enable_pgsql="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pgsql) ;;
+ esac],
+ [enable_pgsql=no]
+)
+if test "x$enable_pgsql" = "xyes"; then
+ PKG_CHECK_MODULES([PGSQL], [libpq],, [
+ AC_CHECK_PROG(
+ [PG_CONFIG],
+ [pg_config],
+ [pg_config],
+ [no],,,
+ )
+ if test "x${PG_CONFIG}" = "xno"; then
+ AC_MSG_FAILURE([pg_config not found])
+ fi
+ AC_CHECK_LIB(
+ [pq],
+ [PQconnectdb],
+ [PGSQL_CFLAGS="-I`$PG_CONFIG --includedir`"
+ PGSQL_LIBS="-L`$PG_CONFIG --libdir` -lpq"
+ ],
+ [AC_MSG_FAILURE([PgSQL library is missing])],
+ [-L`$PG_CONFIG --libdir`]
+ )
+ ])
+ AC_CHECK_LIB(
+ [pq],
+ [PGsslInUse],
+ [AC_DEFINE([HAVE_PGSSLINUSE], [1], [PGsslInUse function available])]
+ )
+fi
+AM_CONDITIONAL(ENABLE_PGSQL, test x$enable_pgsql = xyes)
+AC_SUBST(PGSQL_CFLAGS)
+AC_SUBST(PGSQL_LIBS)
+
+# libdbi support
+AC_ARG_ENABLE(libdbi,
+ [AS_HELP_STRING([--enable-libdbi],[Enable libdbi database support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_libdbi="yes" ;;
+ no) enable_libdbi="no" ;;
+ optional) enable_libdbi="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-libdbi) ;;
+ esac],
+ [enable_libdbi=no]
+)
+libdbi_use_dummy="no"
+if test "x$enable_libdbi" = "xyes" -o x$enable_libdbi = xoptional; then
+ AC_CHECK_HEADERS(
+ [dbi/dbi.h],,[
+ AS_IF([test x$enable_libdbi = xyes],
+ AC_MSG_FAILURE([libdbi is missing])
+ )
+ libdbi_use_dummy="yes"
+ ]
+ )
+ AC_CHECK_LIB(
+ [dbi],
+ [dbi_initialize],
+ [LIBDBI_CFLAGS=""
+ LIBDBI_LIBS="-ldbi"
+ ], [
+ AS_IF([test x$enable_libdbi = xyes],
+ AC_MSG_FAILURE([libdbi is missing])
+ )
+ libdbi_use_dummy="yes"
+ ]
+ )
+ AC_CHECK_LIB(
+ [dbi],
+ [dbi_initialize_r],
+ [AC_DEFINE([HAVE_DBI_R], [1], [Define to 1 if libdbi supports the new plugin-safe interface])]
+ )
+ AC_CHECK_LIB(
+ [dbi],
+ [dbi_conn_transaction_begin],
+ [AC_DEFINE([HAVE_DBI_TXSUPP], [1], [Define to 1 if libdbi supports transactions])]
+ )
+fi
+AM_CONDITIONAL(LIBDBI_USE_DUMMY, test x$libdbi_use_dummy = xyes)
+AM_CONDITIONAL(ENABLE_OMLIBDBI, test x$enable_libdbi = xyes -o x$enable_libdbi = xoptional)
+AC_SUBST(LIBDBI_CFLAGS)
+AC_SUBST(LIBDBI_LIBS)
+
+
+# SNMP support
+AC_ARG_ENABLE(snmp,
+ [AS_HELP_STRING([--enable-snmp],[Enable SNMP support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_snmp="yes" ;;
+ no) enable_snmp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-snmp) ;;
+ esac],
+ [enable_snmp=no]
+)
+if test "x$enable_snmp" = "xyes"; then
+ AC_CHECK_HEADERS(
+ [net-snmp/net-snmp-config.h],,
+ [AC_MSG_FAILURE([Net-SNMP is missing])]
+ )
+ AC_CHECK_LIB(
+ [netsnmp],
+ [snmp_timeout],
+ [SNMP_CFLAGS=""
+ SNMP_LIBS="-lnetsnmp"
+ ],
+ [AC_MSG_FAILURE([Net-SNMP library is missing])]
+ )
+fi
+AM_CONDITIONAL(ENABLE_SNMP, test x$enable_snmp = xyes)
+AC_SUBST(SNMP_CFLAGS)
+AC_SUBST(SNMP_LIBS)
+
+# SNMP Test Support
+AC_ARG_ENABLE(snmp-tests,
+ [AS_HELP_STRING([--enable-snmp-tests],[Enable omsnmp tests @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_snmp_tests="yes" ;;
+ no) enable_snmp_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-snmp-tests) ;;
+ esac],
+ [enable_snmp_tests=no]
+)
+AM_CONDITIONAL(ENABLE_SNMP_TESTS, test x$enable_snmp_tests = xyes)
+
+# uuid support
+AC_ARG_ENABLE(uuid,
+ [AS_HELP_STRING([--enable-uuid],[Enable support for uuid generation @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_uuid="yes" ;;
+ no) enable_uuid="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-uuid) ;;
+ esac],
+ [enable_uuid=yes]
+)
+if test "x$enable_uuid" = "xyes"; then
+ PKG_CHECK_MODULES([LIBUUID], [uuid])
+ AC_DEFINE(USE_LIBUUID, 1, [Define if you want to enable libuuid support])
+fi
+AM_CONDITIONAL(ENABLE_UUID, test x$enable_uuid = xyes)
+
+
+# elasticsearch support
+AC_ARG_ENABLE(elasticsearch,
+ [AS_HELP_STRING([--enable-elasticsearch],[Enable elasticsearch output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_elasticsearch="yes" ;;
+ no) enable_elasticsearch="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-elasticsearch) ;;
+ esac],
+ [enable_elasticsearch=no]
+)
+if test "x$enable_elasticsearch" = "xyes"; then
+ PKG_CHECK_MODULES([CURL], [libcurl])
+ LT_LIB_M
+fi
+AM_CONDITIONAL(ENABLE_ELASTICSEARCH, test x$enable_elasticsearch = xyes)
+
+
+# clickhouse support
+AC_ARG_ENABLE(clickhouse,
+ [AS_HELP_STRING([--enable-clickhouse],[Enable clickhouse output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_clickhouse="yes" ;;
+ no) enable_clickhouse="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-clickhouse) ;;
+ esac],
+ [enable_clickhouse=no]
+)
+if test "x$enable_clickhouse" = "xyes"; then
+ PKG_CHECK_MODULES([CURL], [libcurl])
+ LT_LIB_M
+fi
+AM_CONDITIONAL(ENABLE_CLICKHOUSE, test x$enable_clickhouse = xyes)
+
+
+# omhttp support
+AC_ARG_ENABLE(omhttp,
+ [AS_HELP_STRING([--enable-omhttp],[Enable http output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omhttp="yes" ;;
+ no) enable_omhttp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omhttp) ;;
+ esac],
+ [enable_omhttp=no]
+)
+if test "x$enable_omhttp" = "xyes"; then
+ PKG_CHECK_MODULES([CURL], [libcurl])
+ LT_LIB_M
+fi
+AM_CONDITIONAL(ENABLE_OMHTTP, test x$enable_omhttp = xyes)
+
+
+# capability to enable elasticsearch testbench tests. This requries that an ES test
+# environment is present on the local (127.0.0.1) machine.
+# we support a "minimal" mode to take care of travis where we cannot run all tests
+# due to runtime constraints
+AC_ARG_ENABLE(elasticsearch_tests,
+ [AS_HELP_STRING([--enable-elasticsearch-tests],[enable Elasticsearch specific tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_elasticsearch_tests="yes" ;;
+ no) enable_elasticsearch_tests="no" ;;
+ minimal) enable_elasticsearch_tests="minimal" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-elasticsearch-tests) ;;
+ esac],
+ [enable_elasticsearch_tests=no]
+)
+AM_CONDITIONAL(ENABLE_ELASTICSEARCH_TESTS, test x$enable_elasticsearch_tests = xyes)
+AM_CONDITIONAL(ENABLE_ELASTICSEARCH_TESTS_MINIMAL, test x$enable_elasticsearch_tests = xminimal -o x$enable_elasticsearch_tests = xyes)
+
+
+# capability to enable clickhouse testbench tests. This requries that a test
+# environment is present on the local (127.0.0.1) machine.
+AC_ARG_ENABLE(clickhouse_tests,
+ [AS_HELP_STRING([--enable-clickhouse-tests],[enable Elasticsearch specific tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_clickhouse_tests="yes" ;;
+ no) enable_clickhouse_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-clickhouse-tests) ;;
+ esac],
+ [enable_clickhouse_tests=no]
+)
+AM_CONDITIONAL(ENABLE_CLICKHOUSE_TESTS, test x$enable_clickhouse_tests = xyes)
+
+
+# openssl support
+AC_ARG_ENABLE(openssl,
+ [AS_HELP_STRING([--enable-openssl],[Enable openssl support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_openssl="yes" ;;
+ no) enable_openssl="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-openssl) ;;
+ esac],
+ [enable_openssl=no]
+)
+if test "x$enable_openssl" = "xyes"; then
+ PKG_CHECK_MODULES(OPENSSL, openssl)
+ AC_DEFINE([ENABLE_OPENSSL], [1], [Indicator that openssl is present])
+ save_libs=$LIBS
+fi
+AM_CONDITIONAL(ENABLE_OPENSSL, test x$enable_openssl = xyes)
+
+
+# GnuTLS support
+AC_ARG_ENABLE(gnutls,
+ [AS_HELP_STRING([--enable-gnutls],[Enable GNU TLS support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_gnutls="yes" ;;
+ no) enable_gnutls="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gnutls) ;;
+ esac],
+ [enable_gnutls=no]
+)
+if test "x$enable_gnutls" = "xyes"; then
+ PKG_CHECK_MODULES(GNUTLS, gnutls >= 1.4.0)
+ AC_DEFINE([ENABLE_GNUTLS], [1], [Indicator that GnuTLS is present])
+ save_libs=$LIBS
+ LIBS="$LIBS $GNUTLS_LIBS"
+ AC_CHECK_FUNCS(gnutls_certificate_set_retrieve_function,,)
+ AC_CHECK_FUNCS(gnutls_certificate_type_set_priority,,)
+ LIBS=$save_libs
+fi
+
+AM_CONDITIONAL(ENABLE_GNUTLS, test x$enable_gnutls = xyes)
+
+AC_ARG_ENABLE(gnutls-tests,
+ [AS_HELP_STRING([--enable-gnutls-tests],[Enable gnutls tests @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_gnutls_tests="yes" ;;
+ no) enable_gnutls_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gnutls-tests) ;;
+ esac],
+ [if [[ "$enable_gnutls" == "yes" ]]; then
+ enable_gnutls_tests=yes
+ else
+ enable_gnutls_tests=no
+ fi]
+)
+if [[ "$enable_gnutls_tests" == "yes" ]] && [[ "$enable_gnutls" != "yes" ]]; then
+ AC_MSG_WARN([gnutls-tests can not be enabled without gnutls support. Disabling gnutls tests...])
+ enable_gnutls_tests="no"
+fi
+
+AM_CONDITIONAL(ENABLE_GNUTLS_TESTS, test x$enable_gnutls_tests = xyes)
+
+
+# libgcrypt support
+AC_ARG_ENABLE(libgcrypt,
+ [AS_HELP_STRING([--enable-libgcrypt],[Enable log file encryption support (libgcrypt) @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_libgcrypt="yes" ;;
+ no) enable_libgcrypt="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-libgcrypt) ;;
+ esac],
+ [enable_libgcrypt=yes]
+)
+if test "x$enable_libgcrypt" = "xyes"; then
+ AC_PATH_PROG([LIBGCRYPT_CONFIG],[libgcrypt-config],[no])
+ if test "x${LIBGCRYPT_CONFIG}" = "xno"; then
+ AC_MSG_FAILURE([libgcrypt-config not found in PATH])
+ fi
+ AC_CHECK_LIB(
+ [gcrypt],
+ [gcry_cipher_open],
+ [LIBGCRYPT_CFLAGS="`${LIBGCRYPT_CONFIG} --cflags`"
+ LIBGCRYPT_LIBS="`${LIBGCRYPT_CONFIG} --libs`"
+ ],
+ [AC_MSG_FAILURE([libgcrypt is missing])],
+ [`${LIBGCRYPT_CONFIG} --libs --cflags`]
+ )
+ AC_DEFINE([ENABLE_LIBGCRYPT], [1], [Indicator that LIBGCRYPT is present])
+fi
+AM_CONDITIONAL(ENABLE_LIBGCRYPT, test x$enable_libgcrypt = xyes)
+AC_SUBST(LIBGCRYPT_CFLAGS)
+AC_SUBST(LIBGCRYPT_LIBS)
+
+# libzstd support
+AC_ARG_ENABLE(libzstd,
+ [AS_HELP_STRING([--enable-libzstd],[Enable log file compression support via libzstd @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_libzstd="yes" ;;
+ no) enable_libzstd="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-libzstd) ;;
+ esac],
+ [enable_libzstd=no]
+)
+if test "x$enable_libzstd" = "xyes"; then
+ save_LIBS="$LIBS"
+ PKG_CHECK_MODULES([ZSTD], zstd >= 1.4.0, [],
+ [
+ LIBS="$LIBS -lzstd"
+ ZSTD_LIBS="-lzstd"
+ AC_SUBST(ZSTD_LIBS)
+ AC_SEARCH_LIBS(ZSTD_compressStream2, zstd,
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[ #include <zstd.h> ]],
+ [[
+ ZSTD_CCtx* cctx = ZSTD_createCCtx();
+ ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 5);
+ ]]
+ )],
+ [],
+ [AC_MSG_ERROR([libzstd version must be >= 1.4.0])]
+ )],
+ [AC_MSG_ERROR([libzstd not found])]
+ )]
+ )
+ LIBS="$save_LIBS"
+fi
+AM_CONDITIONAL(ENABLE_LIBZSTD, test x$enable_libzstd = xyes)
+
+
+# support for building the rsyslogd runtime
+AC_ARG_ENABLE(rsyslogrt,
+ [AS_HELP_STRING([--enable-rsyslogrt],[Build rsyslogrt @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_rsyslogrt="yes" ;;
+ no) enable_rsyslogrt="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-rsyslogrt) ;;
+ esac],
+ [enable_rsyslogrt=yes]
+)
+if test "x$enable_rsyslogrt" = "xyes"; then
+ RSRT_CFLAGS1="-I\$(top_srcdir)/runtime -I\$(top_srcdir) -I\$(top_srcdir)/grammar"
+ RSRT_LIBS1="\$(top_builddir)/runtime/librsyslog.la"
+fi
+AM_CONDITIONAL(ENABLE_RSYSLOGRT, test x$enable_rsyslogrt = xyes)
+RSRT_CFLAGS="\$(RSRT_CFLAGS1) \$(LIBESTR_CFLAGS) \$(LIBFASTJSON_CFLAGS) \$(LIBSYSTEMD_CFLAGS)"
+if test "$GCC" = "yes"; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute"
+ if $CC -Werror=implicit-function-declaration -x c -c /dev/null -o /dev/null 2>/dev/null; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -Werror=implicit-function-declaration"
+ elif $CC -Werror-implicit-function-declaration -x c -c /dev/null -o /dev/null 2>/dev/null; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -Werror-implicit-function-declaration"
+ fi
+
+ if test "x$enable_debug_symbols" = "xyes"; then
+ RSRT_CFLAGS="$RSRT_CFLAGS -g"
+ fi
+fi
+RSRT_CFLAGS="$RSRT_CFLAGS $WARN_CFLAGS"
+RSRT_LIBS="\$(RSRT_LIBS1) \$(LIBESTR_LIBS) \$(LIBFASTJSON_LIBS) \$(LIBSYSTEMD_LIBS)"
+AC_SUBST(RSRT_CFLAGS1)
+AC_SUBST(RSRT_LIBS1)
+AC_SUBST(RSRT_CFLAGS)
+AC_SUBST(RSRT_LIBS)
+
+
+# support for NOT building rsyslogd (useful for source-based packaging systems)
+AC_ARG_ENABLE(rsyslogd,
+ [AS_HELP_STRING([--enable-rsyslogd],[Build rsyslogd @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_rsyslogd="yes" ;;
+ no) enable_rsyslogd="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-rsyslogd) ;;
+ esac],
+ [enable_rsyslogd=yes]
+)
+AM_CONDITIONAL(ENABLE_RSYSLOGD, test x$enable_rsyslogd = xyes)
+
+
+# capability to enable an extended testbench. By default, this is off. The reason
+# for this switch is that some test simply take too long to execute them on a regular
+# basis. So we enable to skip them, while the majority of tests can still be used. The
+# idea is that at least "make distcheck" executes the extended testbench, and also
+# developers should explicitely enable it after important changes. -- rgerhards, 2010-04-12
+AC_ARG_ENABLE(extended_tests,
+ [AS_HELP_STRING([--enable-extended-tests],[extended testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_extended_tests="yes" ;;
+ no) enable_extended_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-extended-tests) ;;
+ esac],
+ [enable_extended_tests=no]
+)
+AM_CONDITIONAL(ENABLE_EXTENDED_TESTS, test x$enable_extended_tests = xyes)
+
+
+# capability to enable MySQL testbench tests. This requries that a Syslog database
+# with the default schema has been created on the local (127.0.0.1) MySQL server and
+# a user "rsyslog" with password "testbench" exists, is able to login with default
+# parameters and has sufficient (read: all) privileges on that database.
+# rgerhards, 2011-03-09
+AC_ARG_ENABLE(mysql_tests,
+ [AS_HELP_STRING([--enable-mysql-tests],[enable MySQL specific tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mysql_tests="yes" ;;
+ no) enable_mysql_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mysql-tests) ;;
+ esac],
+ [enable_mysql_tests=no]
+)
+AM_CONDITIONAL(ENABLE_MYSQL_TESTS, test x$enable_mysql_tests = xyes)
+
+
+# capability to enable PostgreSQL testbench tests. This requries that a Syslog database
+# with the default schema (see plugins/ompgsql/createDB.sql) has been created on the
+# local (127.0.0.1) PostgreSQL server and a user "rsyslog" with password "testbench"
+# exists, is able to login with default parameters and has sufficient (read: all)
+# privileges on that database
+AC_ARG_ENABLE(pgsql_tests,
+ [AS_HELP_STRING([--enable-pgsql-tests],[enable PostgreSQL specific tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pgsql_tests="yes" ;;
+ no) enable_pgsql_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pgsql-tests) ;;
+ esac],
+ [enable_pgsql_tests=no]
+)
+AM_CONDITIONAL(ENABLE_PGSQL_TESTS, test x$enable_pgsql_tests = xyes)
+
+
+# Mail support (so far we do not need a library, but we need to turn this on and off)
+AC_ARG_ENABLE(mail,
+ [AS_HELP_STRING([--enable-mail],[Enable mail support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mail="yes" ;;
+ no) enable_mail="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mail) ;;
+ esac],
+ [enable_mail=no]
+)
+AM_CONDITIONAL(ENABLE_MAIL, test x$enable_mail = xyes)
+
+
+AC_ARG_ENABLE(fmhttp,
+ [AS_HELP_STRING([--enable-fmhttp],[Enable fmhttp @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_fmhttp="yes" ;;
+ no) enable_fmhttp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-fmhttp) ;;
+ esac],
+ [enable_fmhttp=yes]
+)
+if test "$enable_fmhttp" = "yes"; then
+ PKG_CHECK_MODULES([CURL], [libcurl])
+fi
+AM_CONDITIONAL(ENABLE_FMHTTP, test x$enable_fmhttp = xyes)
+
+
+# imdiag support
+# This is a core testbench tool. You need to enable it if you want to
+# use not only a small subset of the testbench.
+AC_ARG_ENABLE(imdiag,
+ [AS_HELP_STRING([--enable-imdiag],[Enable imdiag @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imdiag="yes" ;;
+ no) enable_imdiag="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imdiag) ;;
+ esac],
+ [enable_imdiag=no]
+)
+if test "x$enable_imdiag" = "xyes"; then
+ AC_DEFINE([ENABLE_IMDIAG], [1], [Indicator that IMDIAG is present])
+fi
+AM_CONDITIONAL(ENABLE_IMDIAG, test x$enable_imdiag = xyes)
+
+
+# mmnormalize
+AC_ARG_ENABLE(mmnormalize,
+ [AS_HELP_STRING([--enable-mmnormalize],[Enable building mmnormalize support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmnormalize="yes" ;;
+ no) enable_mmnormalize="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmnormalize) ;;
+ esac],
+ [enable_mmnormalize=no]
+)
+if test "x$enable_mmnormalize" = "xyes"; then
+ PKG_CHECK_MODULES(LIBLOGNORM, lognorm >= 2.0.3)
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $LIBLOGNORM_CFLAGS"
+ LIBS="$LIBS $LIBLOGNORM_LIBS"
+
+ AX_CHECK_DEFINED([[#include <lognorm-features.h>]],LOGNORM_REGEX_SUPPORTED,[lognorm_regex_supported="yes"],)
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+AM_CONDITIONAL(LOGNORM_REGEX_SUPPORTED, test x$lognorm_regex_supported = xyes)
+AM_CONDITIONAL(ENABLE_MMNORMALIZE, test x$enable_mmnormalize = xyes)
+
+# mmnjsonparse
+AC_ARG_ENABLE(mmjsonparse,
+ [AS_HELP_STRING([--enable-mmjsonparse],[Enable building mmjsonparse support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmjsonparse="yes" ;;
+ no) enable_mmjsonparse="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmjsonparse) ;;
+ esac],
+ [enable_mmjsonparse=no]
+)
+AM_CONDITIONAL(ENABLE_MMJSONPARSE, test x$enable_mmjsonparse = xyes)
+
+# mmgrok
+AC_ARG_ENABLE(mmgrok,
+ [AS_HELP_STRING([--enable-mmgrok],[Enable building mmgrok support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmgrok="yes" ;;
+ no) enable_mmgrok="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmgrok) ;;
+ esac],
+ [enable_mmgrok=no]
+)
+if test "x$enable_mmgrok" = "xyes"; then
+ AC_CHECK_HEADERS([grok.h])
+ GLIB_CFLAGS="$(pkg-config --cflags glib-2.0)"
+ GLIB_LIBS="$(pkg-config --libs glib-2.0)"
+fi
+AM_CONDITIONAL(ENABLE_MMGROK, test x$enable_mmgrok = xyes)
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+# mmaudit
+AC_ARG_ENABLE(mmaudit,
+ [AS_HELP_STRING([--enable-mmaudit],[Enable building mmaudit support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmaudit="yes" ;;
+ no) enable_mmaudit="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmaudit) ;;
+ esac],
+ [enable_mmaudit=no]
+)
+AM_CONDITIONAL(ENABLE_MMAUDIT, test x$enable_mmaudit = xyes)
+
+
+# mmanon
+AC_ARG_ENABLE(mmanon,
+ [AS_HELP_STRING([--enable-mmanon],[Enable building mmanon support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmanon="yes" ;;
+ no) enable_mmanon="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmanon) ;;
+ esac],
+ [enable_mmanon=no]
+)
+AM_CONDITIONAL(ENABLE_MMANON, test x$enable_mmanon = xyes)
+
+
+# mmrm1stspace
+AC_ARG_ENABLE(mmrm1stspace,
+ [AS_HELP_STRING([--enable-mmrm1stspace],[Enable building mmrm1stspace support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmrm1stspace="yes" ;;
+ no) enable_mmrm1stspace="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmrm1stspace) ;;
+ esac],
+ [enable_mmrm1stspace=no]
+)
+AM_CONDITIONAL(ENABLE_MMRM1STSPACE, test x$enable_mmrm1stspace = xyes)
+
+
+# mmutf8fix
+AC_ARG_ENABLE(mmutf8fix,
+ [AS_HELP_STRING([--enable-mmutf8fix],[Enable building mmutf8fix support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmutf8fix="yes" ;;
+ no) enable_mmutf8fix="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmutf8fix) ;;
+ esac],
+ [enable_mmutf8fix=no]
+)
+AM_CONDITIONAL(ENABLE_MMUTF8FIX, test x$enable_mmutf8fix = xyes)
+
+
+# mmcount
+AC_ARG_ENABLE(mmcount,
+ [AS_HELP_STRING([--enable-mmcount],[Enable message counting @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmcount="yes" ;;
+ no) enable_mmcount="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmcount) ;;
+ esac],
+ [enable_mmcount=no]
+)
+AM_CONDITIONAL(ENABLE_MMCOUNT, test x$enable_mmcount = xyes)
+
+
+# mmsequence
+AC_ARG_ENABLE(mmsequence,
+ [AS_HELP_STRING([--enable-mmsequence],[Enable sequence generator @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmsequence="yes" ;;
+ no) enable_mmsequence="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmsequence) ;;
+ esac],
+ [enable_mmsequence=no]
+)
+AM_CONDITIONAL(ENABLE_MMSEQUENCE, test x$enable_mmsequence = xyes)
+
+
+
+# mmdblookup
+AC_ARG_ENABLE(mmdblookup,
+ [AS_HELP_STRING([--enable-mmdblookup],[Enable mmdb lookup helper @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmdblookup="yes" ;;
+ no) enable_mmdblookup="no" ;;
+ optional) enable_mmdblookup="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmdblookup) ;;
+ esac],
+ [enable_mmdblookup=no]
+)
+AM_CONDITIONAL(ENABLE_MMDBLOOKUP, test x$enable_mmdblookup = xyes -o x$enable_mmdblookup = xoptional)
+mmdblookup_use_dummy="no"
+if test x$enable_mmdblookup = xoptional -o x$enable_mmdblookup = xyes; then
+ #PKG_CHECK_MODULES(LIBMAXMINDDB, libmaxminddb) -- does not work - later?
+ AC_CHECK_HEADERS([maxminddb.h], [
+ ], [
+ AS_IF([test x$enable_mmdblookup = xyes],
+ AC_MSG_ERROR(libmaxminddb library for mmdblookup could not be found)
+ )
+ mmdblookup_use_dummy="yes"
+ AC_DEFINE([ENABLE_MMBDLOOKUP_DUMMY], [1], [Indicator that we need to build a dummy module])
+ ])
+fi
+AM_CONDITIONAL(MMDBLOOKUP_USE_DUMMY, test x$mmdblookup_use_dummy = xyes)
+
+
+# mmdarwin
+AC_ARG_ENABLE(mmdarwin,
+ [AS_HELP_STRING([--enable-mmdarwin],[Enable mmdb lookup helper @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmdarwin="yes" ;;
+ no) enable_mmdarwin="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmdarwin) ;;
+ esac],
+ [enable_mmdarwin=no]
+)
+if test "x$enable_mmdarwin"; then
+ AC_CHECK_HEADERS([protocol.h])
+fi
+AM_CONDITIONAL(ENABLE_MMDARWIN, test x$enable_mmdarwin = xyes)
+
+
+
+
+# mmfields
+AC_ARG_ENABLE(mmfields,
+ [AS_HELP_STRING([--enable-mmfields],[Enable building mmfields support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmfields="yes" ;;
+ no) enable_mmfields="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmfields) ;;
+ esac],
+ [enable_mmfields=no]
+)
+AM_CONDITIONAL(ENABLE_MMFIELDS, test x$enable_mmfields = xyes)
+
+# mmpstrucdata
+AC_ARG_ENABLE(mmpstrucdata,
+ [AS_HELP_STRING([--enable-mmpstrucdata],[Enable building mmpstrucdata support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmpstrucdata="yes" ;;
+ no) enable_mmpstrucdata="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmpstrucdata) ;;
+ esac],
+ [enable_mmpstrucdata=no]
+)
+AM_CONDITIONAL(ENABLE_MMPSTRUCDATA, test x$enable_mmpstrucdata = xyes)
+
+
+# mmrfc5424addhmac
+AC_ARG_ENABLE(mmrfc5424addhmac,
+ [AS_HELP_STRING([--enable-mmrfc5424addhmac],[Enable building mmrfc5424addhmac support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmrfc5424addhmac="yes" ;;
+ no) enable_mmrfc5424addhmac="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmrfc5424addhmac) ;;
+ esac],
+ [enable_mmrfc5424addhmac=no]
+)
+if test "x$enable_mmrfc5424addhmac" = "xyes"; then
+ PKG_CHECK_MODULES(OPENSSL, openssl >= 0.9.7)
+#AC_CHECK_LIB([crypto],[CRYPTO_new_ex_data], [], [AC_MSG_ERROR([OpenSSL libraries required])])
+#AC_CHECK_LIB([ssl],[SSL_library_init], [], [AC_MSG_ERROR([OpenSSL libraries required])])
+#AC_CHECK_HEADERS([openssl/crypto.h openssl/x509.h openssl/pem.h openssl/ssl.h openssl/err.h],[],[AC_MSG_ERROR([OpenSSL headers required])])
+fi
+AM_CONDITIONAL(ENABLE_MMRFC5424ADDHMAC, test x$enable_mmrfc5424addhmac = xyes)
+
+
+# experimental omfile-hardened module
+AC_ARG_ENABLE(omfile-hardened,
+ [AS_HELP_STRING([--enable-omfile-hardened],[Enable omfile-hardened support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omfile_hardened="yes" ;;
+ no) enable_omfile_hardened="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omfile-hardened) ;;
+ esac],
+ [enable_omfile_hardened=no]
+)
+AM_CONDITIONAL(ENABLE_OMFILE_HARDENED, test x$enable_omfile_hardened = xyes)
+
+
+# RELP support
+AC_ARG_ENABLE(relp,
+ [AS_HELP_STRING([--enable-relp],[Enable RELP support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_relp="yes" ;;
+ no) enable_relp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-relp) ;;
+ esac],
+ [enable_relp=no]
+)
+if test "x$enable_relp" = "xyes"; then
+ PKG_CHECK_MODULES(RELP, relp >= 1.2.14)
+ AC_DEFINE([ENABLE_RELP], [1], [Indicator that RELP is present])
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $RELP_CFLAGS"
+ LIBS="$LIBS $RELP_LIBS"
+ # Export RELP Version for testbench tools
+ RELP_VERSION="$(pkg-config --modversion relp)"
+ AC_DEFINE_UNQUOTED([RELP_VERSION], "${RELP_VERSION}", [Define version of librelp used.])
+
+ AC_CHECK_FUNC([relpSrvSetOversizeMode],
+ [AC_DEFINE([HAVE_RELPSRVSETOVERSIZEMODE], [1], [Define if relpSrvSetOversizeMode exists.])])
+ AC_CHECK_FUNC([relpSrvSetLstnAddr],
+ [AC_DEFINE([HAVE_RELPSRVSETLSTNADDR], [1], [Define if relpSrvSetLstnAddr exists.])])
+ AC_CHECK_FUNC([relpEngineSetTLSLibByName],
+ [AC_DEFINE([HAVE_RELPENGINESETTLSLIBBYNAME], [1], [Define if relpEngineSetTLSLibByName exists.])])
+ AC_CHECK_FUNC([relpSrvSetTlsConfigCmd],
+ [AC_DEFINE([HAVE_RELPENGINESETTLSCFGCMD], [1], [Define if relpSrvSetTlsConfigCmd exists.])])
+ AC_CHECK_FUNC([relpSrvSetTlsConfigCmd],
+ [HAVE_RELPENGINESETTLSCFGCMD=1])
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+AM_CONDITIONAL(ENABLE_RELP, test x$enable_relp = xyes)
+AM_CONDITIONAL([USE_RELPENGINESETTLSCFGCMD], [test "x$HAVE_RELPENGINESETTLSCFGCMD" = x1])
+
+# RELP default port
+AC_ARG_ENABLE(omrelp-default-port,
+ [AS_HELP_STRING([--enable-omrelp-default-port],[set omrelp default port @<:@default=514@:>@])],
+ [ AC_DEFINE_UNQUOTED(RELP_DFLT_PT, "${enableval}", [default port for omrelp]) ],
+ [ AC_DEFINE(RELP_DFLT_PT, "514", [default port for omrelp]) ]
+)
+
+
+
+# GuardTime KSI LOGSIG 12 support
+AC_ARG_ENABLE(ksi-ls12,
+ [AS_HELP_STRING([--enable-ksi-ls12],[Enable log file signing support via GuardTime KSI LS12 @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_ksi_ls12="yes" ;;
+ no) enable_ksi_ls12="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-ksi-ls12) ;;
+ esac],
+ [enable_ksi_ls12=no]
+)
+if test "x$enable_ksi_ls12" = "xyes"; then
+ PKG_CHECK_MODULES(GT_KSI_LS12, libksi >= 3.19.0)
+fi
+AM_CONDITIONAL(ENABLE_KSI_LS12, test x$enable_ksi_ls12 = xyes)
+
+# liblogging-stdlog support
+# we use liblogging-stdlog inside the testbench, which is why we need to check for it in any case
+PKG_CHECK_MODULES(LIBLOGGING_STDLOG, liblogging-stdlog >= 1.0.3,
+ [AC_DEFINE(HAVE_LIBLOGGING_STDLOG, 1, [Define to 1 if liblogging-stdlog is available.])
+ found_liblogging_stdlog="yes"],
+ [AC_MSG_NOTICE([liblogging-stdlog not found, parts of the testbench will not run])]
+)
+
+AC_ARG_ENABLE(liblogging-stdlog,
+ [AS_HELP_STRING([--enable-liblogging-stdlog],[Enable liblogging-stdlog support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_liblogging_stdlog="yes" ;;
+ no) enable_liblogging_stdlog="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-liblogging-stdlog) ;;
+ esac],
+ [enable_liblogging_stdlog=no]
+)
+if test "x$enable_liblogging_stdlog" = "xyes" -a "x$found_liblogging_stdlog" != "xyes"; then
+ AC_MSG_ERROR(--enable-liblogging-stdlog set but liblogging-stdlog was not found)
+fi
+AM_CONDITIONAL(ENABLE_LIBLOGGING_STDLOG, [test "x$enable_liblogging_stdlog" = "xyes"])
+
+# RFC 3195 support
+AC_ARG_ENABLE(rfc3195,
+ [AS_HELP_STRING([--enable-rfc3195],[Enable RFC3195 support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_rfc3195="yes" ;;
+ no) enable_rfc3195="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-rfc3195) ;;
+ esac],
+ [enable_rfc3195=no]
+)
+if test "x$enable_rfc3195" = "xyes"; then
+ PKG_CHECK_MODULES(LIBLOGGING, liblogging-rfc3195 >= 1.0.1)
+fi
+AM_CONDITIONAL(ENABLE_RFC3195, test x$enable_rfc3195 = xyes)
+
+
+# enable/disable the testbench (e.g. because some important parts
+# are missing)
+AC_ARG_ENABLE(testbench,
+ [AS_HELP_STRING([--enable-testbench],[testbench enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_testbench="yes" ;;
+ no) enable_testbench="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-testbench) ;;
+ esac],
+ [enable_testbench=no]
+)
+
+# Add a capability to turn off libfaketime tests. Unfortunately, libfaketime
+# becomes more and more problematic in newer versions and causes aborts
+# on some platforms. This provides the ability to turn it off. In the
+# longer term, we should consider writing our own replacement.
+AC_ARG_ENABLE(libfaketime,
+ [AS_HELP_STRING([--enable-libfaketime],[libfaketime enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_libfaketime="yes" ;;
+ no) enable_libfaketime="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-libfaketime) ;;
+ esac],
+ [enable_libfaketime=no]
+)
+AM_CONDITIONAL(ENABLE_LIBFAKETIME, test "x${enable_libfaketime}" = "xyes")
+
+# this permits to control the "default tests" in testbench runs. These
+# are those tests that do not need a special configure option. There are
+# some situations where we really want to turn them of so that we can
+# run tests only for a specific component (e.g. ElasticSearch).
+# This also enables us to do some parallel testing even while the
+# testbench is not yet able to support make -j check
+AC_ARG_ENABLE(default-tests,
+ [AS_HELP_STRING([--enable-default-tests],[default-tests enabled @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_default_tests="yes" ;;
+ no) enable_default_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-default-tests) ;;
+ esac],
+ [enable_default_tests=yes]
+)
+AM_CONDITIONAL(ENABLE_DEFAULT_TESTS, test "x${enable_default_tests}" = "xyes")
+
+AC_CHECK_PROG(IP, [ip], [yes], [no])
+if test "x${IP}" = "xno"; then
+ AC_MSG_NOTICE([Will not check network namespace functionality as 'ip' (part of iproute2) is not available.])
+fi
+AM_CONDITIONAL(ENABLE_IP, test "x${IP}" = "xyes")
+
+
+# valgrind-testbench
+AC_ARG_WITH([valgrind_testbench],
+ [AS_HELP_STRING([--without-valgrind-testbench], [Don't use valgrind in testbench])]
+)
+
+if test "x$with_valgrind_testbench" != "xno"; then
+ AC_CHECK_PROG(VALGRIND, [valgrind], [valgrind], [no])
+
+ if test "x$enable_testbench" = "xyes" && test "x$VALGRIND" = "xno"; then
+ if test "x$with_valgrind_testbench" = "xyes"; then
+ AC_MSG_ERROR([valgrind is missing but forced with --with-valgrind-testbench. Either install valgrind or remove the option!])
+ else
+ AC_MSG_WARN([valgrind is missing -- testbench won't use valgrind!])
+ fi
+ else
+ AC_MSG_NOTICE([testbench will use valgrind])
+ fi
+else
+ AC_MSG_NOTICE([testbench won't use valgrind due to set --without-valgrind-testbench option])
+fi
+AM_CONDITIONAL([HAVE_VALGRIND], [test "x$with_valgrind_testbench" != "xno" && test "x$VALGRIND" != "xno"])
+
+# ability to disable helgrind tests - we at least need this for
+# clang coverage reports, where we cannot suppress the races
+AC_ARG_ENABLE(helgrind,
+ [AS_HELP_STRING([--enable-helgrind],[valgrind helgrind enabled @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_helgrind="yes" ;;
+ no) enable_helgrind="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-helgrind) ;;
+ esac],
+ [enable_helgrind=yes]
+)
+AM_CONDITIONAL(ENABLE_HELGRIND, test x$enable_helgrind = xyes)
+
+# settings for the batch report input module
+AC_ARG_ENABLE(imbatchreport,
+ [AS_HELP_STRING([--enable-imbatchreport],[batch report input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imbatchreport="yes" ;;
+ no) enable_imbatchreport="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imbatchreport) ;;
+ esac],
+ [enable_imbatchreport=no]
+)
+AM_CONDITIONAL(ENABLE_IMBATCHREPORT, test x$enable_imbatchreport = xyes)
+
+# settings for the db2diag parser module
+AC_ARG_ENABLE(pmdb2diag,
+ [AS_HELP_STRING([--enable-pmdb2diag],[db2diag parser module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmdb2diag="yes" ;;
+ no) enable_pmdb2diag="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmdb2diag) ;;
+ esac],
+ [enable_pmdb2diag=no]
+)
+AM_CONDITIONAL(ENABLE_PMDB2DIAG, test x$enable_pmdb2diag = xyes)
+
+# settings for the file input module
+AC_ARG_ENABLE(imfile,
+ [AS_HELP_STRING([--enable-imfile],[file input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imfile="yes" ;;
+ no) enable_imfile="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imfile) ;;
+ esac],
+ [enable_imfile=no]
+)
+if test "x$enable_imfile" = "xyes"; then
+ AC_CHECK_FUNCS(port_create,,)
+ AC_MSG_CHECKING(for Solaris File Events Notification API support)
+ AC_TRY_COMPILE([
+ #include <port.h>
+ #include <sys/port.h>
+ ], [
+ return PORT_SOURCE_FILE;
+ ]
+ ,
+ AC_DEFINE(HAVE_PORT_SOURCE_FILE, 1, [Enable FEN support for imfile])
+ AC_MSG_RESULT(yes)
+ ,
+ AC_MSG_RESULT(no)
+ )
+fi
+AM_CONDITIONAL(ENABLE_IMFILE, test x$enable_imfile = xyes)
+
+AC_ARG_ENABLE(imfile-tests,
+ [AS_HELP_STRING([--enable-imfile-tests],[Enable imfile tests @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_imfile_tests="yes" ;;
+ no) enable_imfile_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imfile-tests) ;;
+ esac],
+ [enable_imfile_tests=yes]
+)
+if [[ "$enable_imfile_tests" == "yes" ]] && [[ "$enable_imfile" != "yes" ]]; then
+ AC_MSG_WARN([imfile-tests can not be enabled without imfile support. Disabling imfile tests...])
+ enable_imfile_tests="no"
+fi
+AM_CONDITIONAL(ENABLE_IMFILE_TESTS, test x$enable_imfile_tests = xyes)
+
+
+# settings for the docker log input module
+AC_ARG_ENABLE(imdocker,
+ [AS_HELP_STRING([--enable-imdocker],[input docker module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imdocker="yes" ;;
+ no) enable_imdocker="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imdocker) ;;
+ esac],
+ [enable_imdocker=no]
+)
+if test "x$enable_imdocker" = "xyes"; then
+ AC_CHECK_HEADERS([curl/curl.h])
+ PKG_CHECK_MODULES([CURL], [libcurl >= 7.40.0])
+fi
+AM_CONDITIONAL(ENABLE_IMDOCKER, test x$enable_imdocker = xyes)
+
+AC_ARG_ENABLE(imdocker-tests,
+ [AS_HELP_STRING([--enable-imdocker-tests],[Enable imdocker tests @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imdocker_tests="yes" ;;
+ no) enable_imdocker_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imdocker-tests) ;;
+ esac],
+ [enable_imdocker_tests=no]
+)
+
+AM_CONDITIONAL(ENABLE_IMDOCKER_TESTS, test x$enable_imdocker_tests = xyes)
+
+
+# settings for the tuxedo ULOG input module
+AC_ARG_ENABLE(imtuxedoulog,
+ [AS_HELP_STRING([--enable-imtuxedoulog],[tuxedo ULOG input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imtuxedoulog="yes" ;;
+ no) enable_imtuxedoulog="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imtuxedoulog) ;;
+ esac],
+ [enable_imtuxedoulog=no]
+)
+AM_CONDITIONAL(ENABLE_IMTUXEDOULOG, test x$enable_imtuxedoulog = xyes)
+
+# settings for the external program input module
+AC_ARG_ENABLE(improg,
+ [AS_HELP_STRING([--enable-improg],[external program input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_improg="yes" ;;
+ no) enable_improg="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-improg) ;;
+ esac],
+ [enable_improg=no]
+)
+AM_CONDITIONAL(ENABLE_IMPROG, test x$enable_improg = xyes)
+
+# settings for the external http input module
+AC_ARG_ENABLE(imhttp,
+ [AS_HELP_STRING([--enable-imhttp],[external http input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imhttp="yes" ;;
+ no) enable_imhttp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imhttp) ;;
+ esac],
+ [enable_imhttp=no]
+)
+if test "x$enable_imhttp" = "xyes"; then
+ AC_CHECK_HEADERS(
+ [civetweb.h],,
+ [AC_MSG_FAILURE([civetweb is missing])]
+ )
+ AC_SEARCH_LIBS(mg_version, civetweb)
+
+ PKG_CHECK_MODULES(APU, apr-util-1 >= 1.0)
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $APU_CFLAGS"
+ LIBS="$LIBS $APU_LIBS"
+
+ AC_CHECK_HEADERS([apr_md5.h])
+ AC_CHECK_HEADERS([apr_base64.h])
+ AC_SEARCH_LIBS(apr_base64_decode, aprutil-1)
+ AC_SEARCH_LIBS(apr_password_validate, aprutil-1)
+
+ CIVETWEB_LIBS=-lcivetweb
+ AC_SUBST(CIVETWEB_LIBS)
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+AM_CONDITIONAL(ENABLE_IMHTTP, test x$enable_imhttp = xyes)
+
+# settings for the door input module (under solaris, thus default off)
+AC_ARG_ENABLE(imsolaris,
+ [AS_HELP_STRING([--enable-imsolaris],[solaris input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imsolaris="yes" ;;
+ no) enable_imsolaris="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imsolaris) ;;
+ esac],
+ [enable_imsolaris=no]
+)
+AM_CONDITIONAL(ENABLE_IMSOLARIS, test x$enable_imsolaris = xyes)
+
+# settings for the ptcp input module
+AC_ARG_ENABLE(imptcp,
+ [AS_HELP_STRING([--enable-imptcp],[plain tcp input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imptcp="yes" ;;
+ no) enable_imptcp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imptcp) ;;
+ esac],
+ [enable_imptcp=no]
+)
+AM_CONDITIONAL(ENABLE_IMPTCP, test x$enable_imptcp = xyes)
+
+
+# settings for the pstats input module
+AC_ARG_ENABLE(impstats,
+ [AS_HELP_STRING([--enable-impstats],[periodic statistics module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_impstats="yes" ;;
+ no) enable_impstats="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-impstats) ;;
+ esac],
+ [enable_impstats=no]
+)
+AM_CONDITIONAL(ENABLE_IMPSTATS, test x$enable_impstats = xyes)
+
+# settings for the pcap input module
+AC_ARG_ENABLE(impcap,
+ [AS_HELP_STRING([--enable-impcap],[libpcap input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_impcap="yes" ;;
+ no) enable_impcap="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-impcap) ;;
+ esac],
+ [enable_impcap=no]
+)
+
+if test "x$enable_impcap" = "xyes"; then
+ AC_CHECK_HEADERS([pcap.h],
+ [AC_MSG_NOTICE([pcap found])],
+ AC_MSG_ERROR([libpcap library and headers not found])
+ )
+fi
+AM_CONDITIONAL(ENABLE_IMPCAP, test x$enable_impcap = xyes)
+
+# settings for the omprog output module
+AC_ARG_ENABLE(omprog,
+ [AS_HELP_STRING([--enable-omprog],[Compiles omprog module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omprog="yes" ;;
+ no) enable_omprog="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omprog) ;;
+ esac],
+ [enable_omprog=no]
+)
+AM_CONDITIONAL(ENABLE_OMPROG, test x$enable_omprog = xyes)
+
+
+# settings for omudpspoof
+AC_ARG_ENABLE(omudpspoof,
+ [AS_HELP_STRING([--enable-omudpspoof],[Compiles omudpspoof module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omudpspoof="yes" ;;
+ no) enable_omudpspoof="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omudpspoof) ;;
+ esac],
+ [enable_omudpspoof=no]
+)
+
+if test "x$enable_omudpspoof" = "xyes"; then
+ AC_CHECK_HEADERS(
+ [libnet.h],,
+ [AC_MSG_FAILURE([libnet is missing])]
+ )
+ AC_CHECK_LIB(
+ [net],
+ [libnet_init],
+ [UDPSPOOF_CFLAGS=""
+ UDPSPOOF_LIBS="-lnet"
+ ],
+ [AC_MSG_FAILURE([libnet is missing])]
+ )
+fi
+AM_CONDITIONAL(ENABLE_OMUDPSPOOF, test x$enable_omudpspoof = xyes)
+AC_SUBST(UDPSPOOF_CFLAGS)
+AC_SUBST(UDPSPOOF_LIBS)
+
+
+# settings for omstdout
+AC_ARG_ENABLE(omstdout,
+ [AS_HELP_STRING([--enable-omstdout],[Compiles stdout module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omstdout="yes" ;;
+ no) enable_omstdout="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omstdout) ;;
+ esac],
+ [enable_omstdout=no]
+)
+AM_CONDITIONAL(ENABLE_OMSTDOUT, test x$enable_omstdout = xyes)
+
+AM_CONDITIONAL(ENABLE_TESTBENCH, test x$enable_testbench = xyes)
+if test "x$enable_testbench" = "xyes"; then
+ if test "x$enable_imdiag" != "xyes"; then
+ AC_MSG_ERROR("--enable-testbench requires --enable-imdiag")
+ fi
+ if test "x$enable_omstdout" != "xyes"; then
+ AC_MSG_ERROR("--enable-testbench requires --enable-omstdout")
+ fi
+fi
+
+
+# settings for omjournal
+AC_ARG_ENABLE(omjournal,
+ [AS_HELP_STRING([--enable-omjournal],[Compiles omjournal @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omjournal="yes" ;;
+ no) enable_omjournal="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omjournal) ;;
+ esac],
+ [enable_omjournal=no]
+)
+if test "x$enable_omjournal" = "xyes"; then
+ PKG_CHECK_MODULES([LIBSYSTEMD_JOURNAL], [libsystemd >= 209] ,, [
+ PKG_CHECK_MODULES([LIBSYSTEMD_JOURNAL], [libsystemd-journal >= 197])
+ ])
+fi
+AM_CONDITIONAL(ENABLE_OMJOURNAL, test x$enable_omjournal = xyes)
+
+# capability to enable journal testbench tests. They have very special requirements,
+# so it does not make sense to have them run by default.
+# Also note that as of now, they have a pretty high rate of false positives due
+# to bugs in the journal.
+# see also https://github.com/rsyslog/rsyslog/issues/2931#issuecomment-416914707
+AC_ARG_ENABLE(journal_tests,
+ [AS_HELP_STRING([--enable-journal-tests],[enable systemd journal specific tests in testbench @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_journal_tests="yes" ;;
+ no) enable_journal_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-journal-tests) ;;
+ esac],
+ [enable_journal_tests=no]
+)
+AM_CONDITIONAL(ENABLE_JOURNAL_TESTS, test x$enable_journal_tests = xyes)
+
+
+# settings for pmlastmsg
+AC_ARG_ENABLE(pmlastmsg,
+ [AS_HELP_STRING([--enable-pmlastmsg],[Compiles lastmsg parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmlastmsg="yes" ;;
+ no) enable_pmlastmsg="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmlastmsg) ;;
+ esac],
+ [enable_pmlastmsg=no]
+)
+AM_CONDITIONAL(ENABLE_PMLASTMSG, test x$enable_pmlastmsg = xyes)
+
+
+# settings for pmcisconames
+AC_ARG_ENABLE(pmcisconames,
+ [AS_HELP_STRING([--enable-pmcisconames],[Compiles cisconames parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmcisconames="yes" ;;
+ no) enable_pmcisconames="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmcisconames) ;;
+ esac],
+ [enable_pmcisconames=no]
+)
+AM_CONDITIONAL(ENABLE_PMCISCONAMES, test x$enable_pmcisconames = xyes)
+
+
+# settings for pmciscoios
+AC_ARG_ENABLE(pmciscoios,
+ [AS_HELP_STRING([--enable-pmciscoios],[Compiles ciscoios parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmciscoios="yes" ;;
+ no) enable_pmciscoios="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmciscoios) ;;
+ esac],
+ [enable_pmciscoios=no]
+)
+AM_CONDITIONAL(ENABLE_PMCISCOIOS, test x$enable_pmciscoios = xyes)
+
+
+# settings for pmnull
+AC_ARG_ENABLE(pmnull,
+ [AS_HELP_STRING([--enable-pmnull],[Compiles null parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmnull="yes" ;;
+ no) enable_pmnull="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmnull) ;;
+ esac],
+ [enable_pmnull=no]
+)
+AM_CONDITIONAL(ENABLE_PMNULL, test x$enable_pmnull = xyes)
+
+
+# settings for pmnormalize
+AC_ARG_ENABLE(pmnormalize,
+ [AS_HELP_STRING([--enable-pmnormalize],[Compiles normalizer parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmnormalize="yes" ;;
+ no) enable_pmnormalize="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmnormalize) ;;
+ esac],
+ [enable_pmnormalize=no]
+)
+AM_CONDITIONAL(ENABLE_PMNORMALIZE, test x$enable_pmnormalize = xyes)
+
+
+# settings for pmaixforwardedfrom
+AC_ARG_ENABLE(pmaixforwardedfrom,
+ [AS_HELP_STRING([--enable-pmaixforwardedfrom],[Compiles aixforwardedfrom parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmaixforwardedfrom="yes" ;;
+ no) enable_pmaixforwardedfrom="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmaixforwardedfrom) ;;
+ esac],
+ [enable_pmaixforwardedfrom=no]
+)
+AM_CONDITIONAL(ENABLE_PMAIXFORWARDEDFROM, test x$enable_pmaixforwardedfrom = xyes)
+
+
+# settings for pmsnare
+AC_ARG_ENABLE(pmsnare,
+ [AS_HELP_STRING([--enable-pmsnare],[Compiles snare parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmsnare="yes" ;;
+ no) enable_pmsnare="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmsnare) ;;
+ esac],
+ [enable_pmsnare=no]
+)
+AM_CONDITIONAL(ENABLE_PMSNARE, test x$enable_pmsnare = xyes)
+
+
+# settings for pmpanngfw
+AC_ARG_ENABLE(pmpanngfw,
+ [AS_HELP_STRING([--enable-pmpanngfw],[Compiles Palo Alto Networks parser module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_pmpanngfw="yes" ;;
+ no) enable_pmpanngfw="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pmpanngfw) ;;
+ esac],
+ [enable_pmpanngfw=no]
+)
+AM_CONDITIONAL(ENABLE_PMPANNGFW, test x$enable_pmpanngfw = xyes)
+
+
+# settings for omruleset
+AC_ARG_ENABLE(omruleset,
+ [AS_HELP_STRING([--enable-omruleset],[Compiles ruleset forwarding module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omruleset="yes" ;;
+ no) enable_omruleset="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omruleset) ;;
+ esac],
+ [enable_omruleset=no]
+)
+AM_CONDITIONAL(ENABLE_OMRULESET, test x$enable_omruleset = xyes)
+
+
+# settings for omuxsock
+AC_ARG_ENABLE(omuxsock,
+ [AS_HELP_STRING([--enable-omuxsock],[Compiles omuxsock module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omuxsock="yes" ;;
+ no) enable_omuxsock="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omuxsock) ;;
+ esac],
+ [enable_omuxsock=no]
+)
+AM_CONDITIONAL(ENABLE_OMUXSOCK, test x$enable_omuxsock = xyes)
+
+
+# settings for mmsnmptrapd message modification module
+AC_ARG_ENABLE(mmsnmptrapd,
+ [AS_HELP_STRING([--enable-mmsnmptrapd],[Compiles mmsnmptrapd module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmsnmptrapd="yes" ;;
+ no) enable_mmsnmptrapd="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmsnmptrapd) ;;
+ esac],
+ [enable_mmsnmptrapd=no]
+)
+AM_CONDITIONAL(ENABLE_MMSNMPTRAPD, test x$enable_mmsnmptrapd = xyes)
+
+
+# settings for the omhdfs;
+AC_ARG_ENABLE(omhdfs,
+ [AS_HELP_STRING([--enable-omhdfs],[Compiles omhdfs module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omhdfs="yes" ;;
+ no) enable_omhdfs="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omhdfs) ;;
+ esac],
+ [enable_omhdfs=no]
+)
+if test "x$enable_omhdfs"; then
+ AC_CHECK_HEADERS([hdfs.h hadoop/hdfs.h])
+fi
+AM_CONDITIONAL(ENABLE_OMHDFS, test x$enable_omhdfs = xyes)
+
+# support for kafka input output
+AC_ARG_ENABLE(omkafka,
+ [AS_HELP_STRING([--enable-omkafka],[Compiles kafka output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omkafka="yes" ;;
+ no) enable_omkafka="no" ;;
+ optional) enable_omkafka="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omkafka) ;;
+ esac],
+ [enable_omkafka=no]
+)
+AC_ARG_ENABLE(imkafka,
+ [AS_HELP_STRING([--enable-imkafka],[Compiles kafka input and output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imkafka="yes" ;;
+ no) enable_imkafka="no" ;;
+ optional) enable_imkafka="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imkafka) ;;
+ esac],
+ [enable_imkafka=no]
+)
+
+AC_ARG_ENABLE(omazureeventhubs_tests,
+ [AS_HELP_STRING([--enable-omazureeventhubs-tests],[Enable Omazureeventhubs tests @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omazureeventhubs_tests="yes" ;;
+ no) enable_omazureeventhubs_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omazureeventhubs-tests) ;;
+ esac],
+ [enable_omazureeventhubs_tests=no]
+)
+AM_CONDITIONAL(ENABLE_OMAZUREEVENTHUBS_TESTS, test x$enable_omazureeventhubs_tests = xyes)
+
+AC_ARG_ENABLE(kafka_tests,
+ [AS_HELP_STRING([--enable-kafka-tests],[Enable Kafka tests, needs Java @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_kafka_tests="yes" ;;
+ no) enable_kafka_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-kafka-tests) ;;
+ esac],
+ [enable_kafka_tests=no]
+)
+AM_CONDITIONAL(ENABLE_KAFKA_TESTS, test x$enable_kafka_tests = xyes)
+
+AC_ARG_ENABLE(kafka_static,
+ [AS_HELP_STRING([--enable-kafka-static],[Enable static library linking for Kafka modules. Removes dependency for rdkafka.so. @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_kafka_static="yes" ;;
+ no) enable_kafka_static="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-kafka-static) ;;
+ esac],
+ [enable_kafka_static=no]
+)
+AM_CONDITIONAL(ENABLE_KAFKA_STATIC, test x$enable_kafka_static = xyes)
+
+# omkafka works with older library
+omkafka_use_dummy="no"
+if test "$enable_omkafka" = "yes" -o "$enable_omkafka" = "optional"; then
+ PKG_CHECK_MODULES([LIBRDKAFKA], [rdkafka >= 0.9.1],, [
+ PKG_CHECK_MODULES([LIBRDKAFKA], [librdkafka],, [
+ AC_CHECK_LIB([rdkafka], [rd_kafka_last_error], [
+ AC_MSG_WARN([librdkafka is missing but library present, using -lrdkafka])
+ LIBRDKAFKA_LIBS=-lrdkafka
+ ], [
+ AS_IF([test "$enable_omkafka" = "yes"],
+ AC_MSG_ERROR([could not find rdkafka library])
+ )
+ AC_MSG_NOTICE([omkafka: no suiteable build environment, use omkafka dummy])
+ omkafka_use_dummy=yes
+ AC_DEFINE([ENABLE_OMKAFKA_DUMMY], [1], [Indicator that we need to build a dummy omkafka module])
+ ])
+ ])
+ ])
+fi
+AM_CONDITIONAL(OMKAFKA_USE_DUMMY, test x$omkafka_use_dummy = xyes)
+if test "$enable_omkafka" = "yes" -o "$enable_omkafka" = "optional" && test "$omkafka_use_dummy" = "no"; then
+ AC_CHECK_HEADERS([librdkafka/rdkafka.h])
+
+ # Add additional dependencies if statically linking rdkafka
+ if test "x$enable_kafka_static" = "xyes"; then
+ PKG_CHECK_MODULES([LIBLZ4], [liblz4],, [
+ AC_CHECK_LIB([lz4], [LZ4_compress], [
+ AC_MSG_WARN([liblz4 is missing but library present, using -llz4])
+ LIBRDKAFKA_LIBS=-llz4
+ ], [
+ AC_MSG_ERROR([could not find liblz4 library])
+ ])
+ ])
+ fi
+fi
+
+imkafka_use_dummy="no"
+# imkafka needs newer library
+if test "x$enable_imkafka" = "xyes" -o "$enable_imkafka" = "optional"; then
+ PKG_CHECK_MODULES([LIBRDKAFKA], [rdkafka >= 0.9.1],, [
+ AC_CHECK_LIB([rdkafka], [rd_kafka_consumer_poll], [
+ AC_MSG_WARN([librdkafka is missing but library present, using -lrdkafka])
+ LIBRDKAFKA_LIBS=-lrdkafka
+ ], [
+ AS_IF([test "$enable_imkafka" = "yes"],
+ AC_MSG_ERROR([could not find sufficiently current rdkafka library])
+ )
+ AC_MSG_NOTICE([imkafka: no suiteable build environment, use imkafka dummy])
+ imkafka_use_dummy=yes
+ AC_DEFINE([ENABLE_IMKAFKA_DUMMY], [1], [Indicator that we need to build a dummy imkafka module])
+ ])
+ ])
+fi
+AM_CONDITIONAL(IMKAFKA_USE_DUMMY, test x$imkafka_use_dummy = xyes)
+if test "$enable_imkafka" = "yes" -o "$enable_imkafka" = "optional" && test "$imkafka_use_dummy" = "no"; then
+ AC_CHECK_HEADERS([librdkafka/rdkafka.h])
+
+ # Add additional dependencies if statically linking rdkafka
+ if test "x$enable_kafka_static" = "xyes"; then
+ PKG_CHECK_MODULES([LIBLZ4], [liblz4],, [
+ AC_CHECK_LIB([lz4], [LZ4_compress], [
+ AC_MSG_WARN([liblz4 is missing but library present, using -llz4])
+ LIBRDKAFKA_LIBS=-llz4
+ ], [
+ AC_MSG_ERROR([could not find liblz4 library])
+ ])
+ ])
+ fi
+fi
+
+if test "x$enable_omkafka" = "xyes" && test "x$enable_imkafka" = "xyes"; then
+ if test "x$enable_kafka_tests" = "xyes"; then
+ AX_PROG_JAVAC #we don't need javac, but macro documentation says JAVAC *must* be checked before JAVA
+ AX_PROG_JAVA
+ AC_CHECK_PROG(WGET, [wget], [yes], [no])
+ if test "x${WGET}" = "xno"; then
+ AC_MSG_FAILURE([wget, which is a kafka-tests dependency, not found])
+ fi
+ AC_CHECK_PROG(READLINK, [readlink], [yes], [no])
+ if test "x${READLINK}" = "xno"; then
+ AC_MSG_FAILURE([readlink, which is a kafka-tests dependency, not found])
+ fi
+ fi
+else
+ if test "x$enable_kafka_tests" = "xyes"; then
+ AC_MSG_WARN([kafka-tests can not be enabled without omkafka and imkafka support. Disabling enable_kafka_tests...])
+ enable_kafka_tests="no"
+ fi
+fi
+AM_CONDITIONAL(ENABLE_OMKAFKA, test x$enable_omkafka = xyes -o x$enable_omkafka = xoptional)
+AM_CONDITIONAL(ENABLE_IMKAFKA, test x$enable_imkafka = xyes -o x$enable_imkafka = xoptional)
+
+
+# omazureeventhubs support for output module
+AC_ARG_ENABLE(omazureeventhubs,
+ [AS_HELP_STRING([--enable-omazureeventhubs],[Compiles AzureEventHubs output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omazureeventhubs="yes" ;;
+ no) enable_omazureeventhubs="no" ;;
+ optional) enable_omazureeventhubs="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omazureeventhubs) ;;
+ esac],
+ [enable_omazureeventhubs=no]
+)
+
+# PROTON PROTOCOL SUPPORT for omazureeventhubs
+# uses qpid-proton library
+if test "x$enable_omazureeventhubs" = "xyes"; then
+ PKG_CHECK_MODULES(PROTON, libqpid-proton >= 0.13)
+ AC_SUBST(PROTON_CFLAGS)
+ AC_SUBST(PROTON_LIBS)
+fi
+if test "x$enable_omazureeventhubs" = "xyes"; then
+ PKG_CHECK_MODULES(PROTON_PROACTOR, libqpid-proton-proactor >= 0.13)
+ AC_SUBST(PROTON_PROACTOR_CFLAGS)
+ AC_SUBST(PROTON_PROACTOR_LIBS)
+fi
+AM_CONDITIONAL(ENABLE_OMAZUREEVENTHUBS, test x$enable_omazureeventhubs = xyes)
+# END PROTON
+
+if test "x$enable_omazureeventhubs" = "xyes"; then
+ if test "x$enable_omazure_tests" = "xyes"; then
+ AC_MSG_NOTICE([omazureveenthubs: TEST Suite enabled, requires Azure Environment variables!])
+ fi
+else
+ if test "x$enable_omazure_tests" = "xyes"; then
+ AC_MSG_WARN([Omazureeventhubs Tests can not be enabled omazureveenthubs support. Disabling enable_omazure_tests...])
+ enable_omazure_tests="no"
+ fi
+fi
+
+# Static QPID-Proton support?
+AC_ARG_ENABLE(qpidproton_static,
+ [AS_HELP_STRING([--enable-qpidproton_static],[Enable static library linking for qpid-proton (required by omazureeventhubs module). Removes dependency for libqpid-proton*.so. @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_qpidproton_static="yes" ;;
+ no) enable_qpidproton_static="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-qpidproton_static) ;;
+ esac],
+ [enable_qpidproton_static=no]
+)
+AM_CONDITIONAL(ENABLE_QPIDPROTON_STATIC, test x$enable_qpidproton_static = xyes)
+
+#MONGODB SUPPORT
+AC_ARG_ENABLE(ommongodb,
+ [AS_HELP_STRING([--enable-ommongodb],[Compiles ommongodb module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_ommongodb="yes" ;;
+ no) enable_ommongodb="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-ommongodb) ;;
+ esac],
+ [enable_ommongodb=no]
+)
+if test "x$enable_ommongodb" = "xyes"; then
+ PKG_CHECK_MODULES(LIBMONGOC, libmongoc-1.0)
+ AC_CHECK_FUNCS(mongoc_client_set_ssl_opts,,)
+
+fi
+AM_CONDITIONAL(ENABLE_OMMONGODB, test x$enable_ommongodb = xyes)
+# end of mongodb code
+
+
+# BEGIN IMDTLS INPUT SUPPORT
+AC_ARG_ENABLE(imdtls,
+ [AS_HELP_STRING([--enable-imdtls],[Compiles DTLS syslog input module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imdtls="yes" ;;
+ no) enable_imdtls="no" ;;
+ optional) enable_imdtls="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imdtls) ;;
+ esac],
+ [enable_imdtls=no]
+)
+if test "x$enable_imdtls" = "xyes"; then
+ PKG_CHECK_MODULES(OPENSSL, openssl)
+fi
+AM_CONDITIONAL(ENABLE_IMDTLS, test x$enable_imdtls = xyes)
+# END IMDTLS INPUT
+
+# BEGIN OMDTLS INPUT SUPPORT
+AC_ARG_ENABLE(omdtls,
+ [AS_HELP_STRING([--enable-omdtls],[Compiles DTLS syslog output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omdtls="yes" ;;
+ no) enable_omdtls="no" ;;
+ optional) enable_omdtls="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omdtls) ;;
+ esac],
+ [enable_omdtls=no]
+)
+if test "x$enable_omdtls" = "xyes"; then
+ PKG_CHECK_MODULES(OPENSSL, openssl)
+fi
+AM_CONDITIONAL(ENABLE_OMDTLS, test x$enable_omdtls = xyes)
+# END OMDTLS INPUT
+
+
+# BEGIN CZMQ INPUT SUPPORT
+AC_ARG_ENABLE(imczmq,
+ [AS_HELP_STRING([--enable-imczmq],[Compiles imczmq output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imczmq="yes" ;;
+ no) enable_imczmq="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imczmq) ;;
+ esac],
+ [enable_imczmq=no]
+)
+if test "x$enable_imczmq" = "xyes"; then
+ PKG_CHECK_MODULES(CZMQ, libczmq >= 4.0.0)
+fi
+AM_CONDITIONAL(ENABLE_IMCZMQ, test x$enable_imczmq = xyes)
+# END CZMQ INPUT
+
+
+# BEGIN CZMQ OUTPUT SUPPORT
+AC_ARG_ENABLE(omczmq,
+ [AS_HELP_STRING([--enable-omczmq],[Compiles omczmq output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omczmq="yes" ;;
+ no) enable_omczmq="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omczmq) ;;
+ esac],
+ [enable_omczmq=no]
+)
+if test "x$enable_omczmq" = "xyes"; then
+ PKG_CHECK_MODULES(CZMQ, libczmq >= 4.0.0)
+fi
+AM_CONDITIONAL(ENABLE_OMCZMQ, test x$enable_omczmq = xyes)
+
+# END CZMQ SUPPORT
+
+
+# BEGIN RABBITMQ OUTPUT SUPPORT
+
+AC_ARG_ENABLE(omrabbitmq,
+ [AS_HELP_STRING([--enable-omrabbitmq],[Compiles omrabbitmq output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omrabbitmq="yes" ;;
+ no) enable_omrabbitmq="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omrabbitmq) ;;
+ esac],
+ [enable_omrabbitmq=no]
+)
+if test "x$enable_omrabbitmq" = "xyes"; then
+ PKG_CHECK_MODULES(RABBITMQ, librabbitmq >= 0.2.0)
+ AC_SUBST(RABBITMQ_CFLAGS)
+ AC_SUBST(RABBITMQ_LIBS)
+fi
+AM_CONDITIONAL(ENABLE_OMRABBITMQ, test x$enable_omrabbitmq = xyes)
+
+# END RABBITMQ SUPPORT
+
+# HIREDIS SUPPORT
+
+AC_ARG_ENABLE(imhiredis,
+ [AS_HELP_STRING([--enable-imhiredis],[Compiles imhiredis input module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imhiredis="yes" ;;
+ no) enable_imhiredis="no" ;;
+ optional) enable_imhiredis="optional" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imhiredis) ;;
+ esac],
+ [enable_imhiredis=no]
+)
+AC_ARG_ENABLE(omhiredis,
+ [AS_HELP_STRING([--enable-omhiredis],[Compiles omhiredis template module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omhiredis="yes" ;;
+ no) enable_omhiredis="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omhiredis) ;;
+ esac],
+ [enable_omhiredis=no]
+)
+
+AC_ARG_ENABLE(redis_tests,
+ [AS_HELP_STRING([--enable-redis-tests],[Enable redis tests, needs redis-server @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_redis_tests="yes" ;;
+ no) enable_redis_tests="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-redis-tests) ;;
+ esac],
+ [enable_redis_tests=no]
+)
+AM_CONDITIONAL(ENABLE_REDIS_TESTS, test x$enable_redis_tests = xyes)
+
+if test "x$enable_omhiredis" = "xyes" -o "x$enable_imhiredis" = "xyes" ; then
+ PKG_CHECK_MODULES(HIREDIS, hiredis >= 0.10.1, [],
+ [AC_SEARCH_LIBS(redisConnectWithTimeout, hiredis,
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[ #include <hiredis/hiredis.h> ]],
+ [[ #define major 0
+ #define minor 10
+ #define patch 1
+ #if (( HIREDIS_MAJOR > major ) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR > minor )) || \
+ (( HIREDIS_MAJOR == major ) && ( HIREDIS_MINOR == minor ) && ( HIREDIS_PATCH >= patch ))) \
+ /* OK */
+ #else
+ # error Hiredis version must be >= major.minor.path
+ #endif
+ ]]
+ )],
+ [],
+ [AC_MSG_ERROR([hiredis version must be >= 0.10.1])]
+ )],
+ [AC_MSG_ERROR([hiredis not found])]
+ )]
+ )
+fi
+
+if test "x$enable_imhiredis" = "xyes" ; then
+ PKG_CHECK_MODULES(LIBEVENT, [libevent >= 2.0, libevent_pthreads],
+ # libevent found
+ [
+ HIREDIS_LIBS="$HIREDIS_LIBS -levent -levent_pthreads"
+ ],
+ # libevent not found
+ [AC_MSG_ERROR([no libevent >= 2.0 found with pthreads support, imhiredis cannot use pub/sub])])
+fi
+
+if test "x$enable_imhiredis" = "xyes" || test "x$enable_omhiredis" = "xyes"; then
+ if test "x$enable_redis_tests" = "xyes"; then
+ AC_CHECK_PROG(REDIS, [redis-server], [yes], [no])
+ if test "x${REDIS}" = "xno"; then
+ AC_MSG_FAILURE([redis-server, which is a redis-tests dependency, not found])
+ fi
+ fi
+else
+ if test "x$enable_redis_tests" = "xyes"; then
+ AC_MSG_WARN([redis-tests can not be enabled without imhiredis or omhiredis support.
+ Disabling enable_redis_tests...])
+ enable_redis_tests="no"
+ fi
+fi
+
+AM_CONDITIONAL(ENABLE_OMHIREDIS, test x$enable_omhiredis = xyes)
+AM_CONDITIONAL(ENABLE_IMHIREDIS, test x$enable_imhiredis = xyes)
+
+# END HIREDIS SUPPORT
+
+
+# HTTPFS SUPPORT
+
+AC_ARG_ENABLE(omhttpfs,
+ [AS_HELP_STRING([--enable-omhttpfs],[Compiles omhttpfs template module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omhttpfs="yes" ;;
+ no) enable_omhttpfs="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omhttpfs) ;;
+ esac],
+ [enable_omhttpfs=no]
+)
+
+if test "x$enable_omhttpfs" = "xyes"; then
+ AC_CHECK_HEADERS([curl/curl.h])
+ PKG_CHECK_MODULES([CURL], [libcurl])
+ LT_LIB_M
+ #PKG_CHECK_MODULES(HTTPFS, curl >= 7.0.0)
+fi
+AM_CONDITIONAL(ENABLE_OMHTTPFS, test x$enable_omhttpfs = xyes)
+
+# END HTTPFS SUPPORT
+
+# AMQP 1.0 PROTOCOL SUPPORT
+# uses the Proton protocol library
+
+AC_ARG_ENABLE(omamqp1,
+ [AS_HELP_STRING([--enable-omamqp1],[Compiles omamqp1 output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omamqp1="yes" ;;
+ no) enable_omamqp1="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omamqp1) ;;
+ esac],
+ [enable_omamqp1=no]
+)
+if test "x$enable_omamqp1" = "xyes"; then
+ PKG_CHECK_MODULES(PROTON, libqpid-proton >= 0.9)
+ AC_SUBST(PROTON_CFLAGS)
+ AC_SUBST(PROTON_LIBS)
+fi
+AM_CONDITIONAL(ENABLE_OMAMQP1, test x$enable_omamqp1 = xyes)
+
+# END AMQP 1.0 PROTOCOL SUPPORT
+
+# TCL SUPPORT
+
+AC_ARG_ENABLE(omtcl,
+ [AS_HELP_STRING([--enable-omtcl],[Compiles omtcl output module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omtcl="yes" ;;
+ no) enable_omtcl="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omtcl) ;;
+ esac],
+ [enable_omtcl=no]
+)
+
+if test "x$enable_omtcl" = "xyes"; then
+ SC_PATH_TCLCONFIG
+ SC_LOAD_TCLCONFIG
+ AC_SUBST(TCL_INCLUDE_SPEC)
+fi
+AM_CONDITIONAL(ENABLE_OMTCL, test x$enable_omtcl = xyes)
+
+# END TCL SUPPORT
+
+# mmkubernetes - Kubernetes metadata support
+
+AC_ARG_ENABLE(mmkubernetes,
+ [AS_HELP_STRING([--enable-mmkubernetes],
+ [Enable compilation of the mmkubernetes module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmkubernetes="yes" ;;
+ no) enable_mmkubernetes="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmkubernetes) ;;
+ esac],
+ [enable_mmkubernetes=no]
+)
+if test "x$enable_mmkubernetes" = "xyes"; then
+ PKG_CHECK_MODULES([CURL], [libcurl])
+ PKG_CHECK_MODULES(LIBLOGNORM, lognorm >= 2.0.3)
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+
+ CFLAGS="$CFLAGS $LIBLOGNORM_CFLAGS"
+ LIBS="$LIBS $LIBLOGNORM_LIBS"
+
+ AC_CHECK_FUNC([ln_loadSamplesFromString],
+ [AC_DEFINE([HAVE_LOADSAMPLESFROMSTRING], [1], [Define if ln_loadSamplesFromString exists.])],
+ [AC_DEFINE([NO_LOADSAMPLESFROMSTRING], [1], [Define if ln_loadSamplesFromString does not exist.])])
+
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+fi
+AM_CONDITIONAL(ENABLE_MMKUBERNETES, test x$enable_mmkubernetes = xyes)
+
+# END Kubernetes metadata support
+
+
+# mmtaghostname
+AC_ARG_ENABLE(mmtaghostname,
+ [AS_HELP_STRING([--enable-mmtaghostname],[Enable Tag and Hostname messages' modifier @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmtaghostname="yes" ;;
+ no) enable_mmtaghostname="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmtaghostname) ;;
+ esac],
+ [enable_mmtaghostname=no]
+)
+AM_CONDITIONAL(ENABLE_MMTAGHOSTNAME, test x$enable_mmtaghostname = xyes)
+#END mmtaghostname
+
+# man pages
+have_to_generate_man_pages="no"
+git_src_have_to_generate_man_pages="yes" # default to use when building from git source
+AC_ARG_ENABLE(generate-man-pages,
+ [AS_HELP_STRING([--enable-generate-man-pages],[Generate man pages from source @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) have_to_generate_man_pages="yes" ;;
+ no) have_to_generate_man_pages="no" ;
+ git_src_have_to_generate_man_pages="no"
+ ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-generate-man-pages) ;;
+ esac],
+ [have_to_generate_man_pages=no]
+)
+
+
+# This provides a work-around to use "make distcheck" without
+# running tests (mode used pre 2018-07-02)
+AC_ARG_ENABLE(distcheck-workaround,
+ [AS_HELP_STRING([--enable-distcheck-workaround],[enable to use make distcheck without runing testbench inside it @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_distcheck_workaround="yes" ;;
+ no) enable_distcheck_workaround="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-distcheck_workaround) ;;
+ esac],
+ [enable_distcheck_workaround="no"]
+)
+AM_CONDITIONAL(ENABLE_DISTCHECK_WORKAROUND, test x$enable_distcheck_workaround = xyes)
+
+
+if test "x$in_git_src" = "xyes"; then
+ AC_MSG_NOTICE([Running from git source])
+
+ have_to_generate_man_pages=$git_src_have_to_generate_man_pages
+
+ if test "x$LEX" != "xflex"; then
+ AC_MSG_ERROR([flex program is needed to build rsyslog, please install flex.])
+ fi
+
+ if test "x$YACC" = "xyacc"; then
+ # AC_PROG_YACC only checks for yacc replacements, not for yacc itself
+ AC_CHECK_PROG([YACC_FOUND], [yacc], [yes], [no])
+ if test "x$YACC_FOUND" = "xno"; then
+ AC_MSG_ERROR([A yacc program is needed to build rsyslog, please install bison.])
+ fi
+ fi
+else
+ AC_MSG_NOTICE([Not running from git source])
+fi
+
+AM_CONDITIONAL(ENABLE_GENERATE_MAN_PAGES, test x$have_to_generate_man_pages = xyes)
+
+# rst2man
+AC_CHECK_PROGS([RST2MAN], [rst2man rst2man.py], [false])
+if test "x$have_to_generate_man_pages" = "xyes" && test "x$RST2MAN" = "xfalse"; then
+ AC_MSG_ERROR([rst2man is required when building from git source or --enable-generate-man-pages option was set, please install python-docutils.])
+fi
+
+
+AC_CONFIG_FILES([Makefile \
+ runtime/Makefile \
+ compat/Makefile \
+ grammar/Makefile \
+ tools/Makefile \
+ plugins/imudp/Makefile \
+ plugins/imtcp/Makefile \
+ plugins/im3195/Makefile \
+ plugins/imgssapi/Makefile \
+ plugins/imuxsock/Makefile \
+ plugins/imjournal/Makefile \
+ plugins/immark/Makefile \
+ plugins/imklog/Makefile \
+ plugins/omhdfs/Makefile \
+ plugins/omkafka/Makefile \
+ plugins/omprog/Makefile \
+ plugins/mmexternal/Makefile \
+ plugins/omstdout/Makefile \
+ plugins/omjournal/Makefile \
+ plugins/pmciscoios/Makefile \
+ plugins/pmnull/Makefile \
+ plugins/pmnormalize/Makefile \
+ plugins/omruleset/Makefile \
+ plugins/omuxsock/Makefile \
+ plugins/imfile/Makefile \
+ plugins/imsolaris/Makefile \
+ plugins/imptcp/Makefile \
+ plugins/impstats/Makefile \
+ plugins/imrelp/Makefile \
+ plugins/imdiag/Makefile \
+ plugins/imkafka/Makefile \
+ plugins/omtesting/Makefile \
+ plugins/omgssapi/Makefile \
+ plugins/ommysql/Makefile \
+ plugins/ompgsql/Makefile \
+ plugins/omrelp/Makefile \
+ plugins/omlibdbi/Makefile \
+ plugins/ommail/Makefile \
+ plugins/fmhttp/Makefile \
+ plugins/omsnmp/Makefile \
+ plugins/omudpspoof/Makefile \
+ plugins/ommongodb/Makefile \
+ plugins/mmnormalize/Makefile \
+ plugins/mmjsonparse/Makefile \
+ plugins/mmaudit/Makefile \
+ plugins/mmanon/Makefile \
+ plugins/mmrm1stspace/Makefile \
+ plugins/mmutf8fix/Makefile \
+ plugins/mmfields/Makefile \
+ plugins/mmpstrucdata/Makefile \
+ plugins/omelasticsearch/Makefile \
+ plugins/omclickhouse/Makefile \
+ plugins/mmsnmptrapd/Makefile \
+ plugins/pmlastmsg/Makefile \
+ plugins/mmdblookup/Makefile \
+ plugins/omazureeventhubs/Makefile \
+ plugins/imdtls/Makefile \
+ plugins/omdtls/Makefile \
+ contrib/mmdarwin/Makefile \
+ contrib/omhttp/Makefile \
+ contrib/fmhash/Makefile \
+ contrib/fmunflatten/Makefile \
+ contrib/ffaup/Makefile \
+ contrib/pmsnare/Makefile \
+ contrib/pmpanngfw/Makefile \
+ contrib/pmaixforwardedfrom/Makefile \
+ contrib/omhiredis/Makefile \
+ contrib/omrabbitmq/Makefile \
+ contrib/imkmsg/Makefile \
+ contrib/mmgrok/Makefile \
+ contrib/mmcount/Makefile \
+ contrib/omczmq/Makefile \
+ contrib/imczmq/Makefile \
+ contrib/mmsequence/Makefile \
+ contrib/mmrfc5424addhmac/Makefile \
+ contrib/pmcisconames/Makefile \
+ contrib/omhttpfs/Makefile \
+ contrib/omamqp1/Makefile \
+ contrib/omtcl/Makefile \
+ contrib/imbatchreport/Makefile \
+ contrib/omfile-hardened/Makefile \
+ contrib/mmkubernetes/Makefile \
+ contrib/impcap/Makefile \
+ contrib/imtuxedoulog/Makefile \
+ contrib/improg/Makefile \
+ contrib/imhttp/Makefile \
+ contrib/mmtaghostname/Makefile \
+ contrib/imdocker/Makefile \
+ contrib/pmdb2diag/Makefile \
+ contrib/imhiredis/Makefile \
+ tests/set-envvars \
+ tests/Makefile])
+AC_OUTPUT
+
+echo "****************************************************"
+echo "rsyslog will be compiled with the following settings:"
+echo
+echo " Large file support enabled: $enable_largefile"
+echo " Networking support enabled: $enable_inet"
+echo " Regular expressions support enabled: $enable_regexp"
+echo " rsyslog runtime will be built: $enable_rsyslogrt"
+echo " rsyslogd will be built: $enable_rsyslogd"
+echo " have to generate man pages: $have_to_generate_man_pages"
+echo " Unlimited select() support enabled: $enable_unlimited_select"
+echo " uuid support enabled: $enable_uuid"
+echo " Log file signing support via KSI LS12: $enable_ksi_ls12"
+echo " Log file encryption support: $enable_libgcrypt"
+echo " Log file compression via zstd support: $enable_libzstd"
+echo " anonymization support enabled: $enable_mmanon"
+echo " message counting support enabled: $enable_mmcount"
+echo " liblogging-stdlog support enabled: $enable_liblogging_stdlog"
+echo " libsystemd enabled: $enable_libsystemd"
+echo " kafka static linking enabled: $enable_kafka_static"
+echo " qpid proton static linking enabled: $enable_qpidproton_static"
+echo " atomic operations enabled: $enable_atomic_operations"
+echo " libcap-ng support enabled: $enable_libcapng"
+
+echo
+echo "---{ input plugins }---"
+if test "$unamestr" != "AIX"; then
+echo " Klog functionality enabled: $enable_klog ($os_type)"
+fi
+echo " /dev/kmsg functionality enabled: $enable_kmsg"
+echo " plain tcp input module enabled: $enable_imptcp"
+echo " DTLS udp input module enabled: $enable_imdtls"
+echo " imdiag enabled: $enable_imdiag"
+echo " file input module enabled: $enable_imfile"
+echo " docker log input module enabled: $enable_imdocker"
+echo " Solaris input module enabled: $enable_imsolaris"
+echo " periodic statistics module enabled: $enable_impstats"
+echo " imczmq input module enabled: $enable_imczmq"
+echo " imjournal input module enabled: $enable_imjournal"
+if test "$enable_imjournal" = "optional"; then
+echo " imjournal use dummy: $imjournal_use_dummy"
+fi
+echo " imbatchreport input module enabled: $enable_imbatchreport"
+echo " imkafka module will be compiled: $enable_imkafka"
+if test "$enable_imkafka" = "optional"; then
+echo " imkafka use dummy: $imkafka_use_dummy"
+fi
+echo " impcap input module enabled: $enable_impcap"
+echo " imtuxedoulog module will be compiled: $enable_imtuxedoulog"
+echo " improg input module enabled: $enable_improg"
+echo " imhttp input module enabled: $enable_imhttp"
+echo " imhiredis input module enabled: $enable_imhiredis"
+echo
+echo "---{ output plugins }---"
+echo " Mail support enabled: $enable_mail"
+echo " omfile-hardened module will be compiled: $enable_omfile_hardened"
+echo " omprog module will be compiled: $enable_omprog"
+echo " omstdout module will be compiled: $enable_omstdout"
+echo " omjournal module will be compiled: $enable_omjournal"
+echo " omhdfs module will be compiled: $enable_omhdfs"
+echo " omelasticsearch module will be compiled: $enable_elasticsearch"
+echo " omclickhouse module will be compiled: $enable_clickhouse"
+echo " omhttp module will be compiled: $enable_omhttp"
+echo " omruleset module will be compiled: $enable_omruleset"
+echo " omudpspoof module will be compiled: $enable_omudpspoof"
+echo " omuxsock module will be compiled: $enable_omuxsock"
+echo " omczmq module will be compiled: $enable_omczmq"
+echo " omrabbitmq module will be compiled: $enable_omrabbitmq"
+echo " omhttpfs module will be compiled: $enable_omhttpfs"
+echo " omamqp1 module will be compiled: $enable_omamqp1"
+echo " omtcl module will be compiled: $enable_omtcl"
+echo " omkafka module will be compiled: $enable_omkafka"
+echo " omhiredis module will be compiled: $enable_omhiredis"
+echo " omazureeventhubs module will be compiled: $enable_omazureeventhubs"
+echo " omdtls module will be compiled: $enable_omdtls"
+echo
+echo "---{ parser modules }---"
+echo " pmlastmsg module will be compiled: $enable_pmlastmsg"
+echo " pmcisconames module will be compiled: $enable_pmcisconames"
+echo " pmciscoios module will be compiled: $enable_pmciscoios"
+echo " pmnull module will be compiled: $enable_pmnull"
+echo " pmnormalize module will be compiled: $enable_pmnormalize"
+echo " pmaixforwardedfrom module w.be compiled: $enable_pmaixforwardedfrom"
+echo " pmsnare module will be compiled: $enable_pmsnare"
+echo " pmdb2diag module will be compiled: $enable_pmdb2diag"
+echo " pmpanngfw module will be compiled: $enable_pmpanngfw"
+echo
+echo "---{ message modification modules }---"
+echo " mmnormalize module will be compiled: $enable_mmnormalize"
+echo " mmjsonparse module will be compiled: $enable_mmjsonparse"
+echo " mmgrok module will be compiled: $enable_mmgrok"
+echo " mmjaduit module will be compiled: $enable_mmaudit"
+echo " mmsnmptrapd module will be compiled: $enable_mmsnmptrapd"
+echo " mmutf8fix enabled: $enable_mmutf8fix"
+echo " mmrfc5424addhmac enabled: $enable_mmrfc5424addhmac"
+echo " mmpstrucdata enabled: $enable_mmpstrucdata"
+echo " mmsequence enabled: $enable_mmsequence"
+echo " mmdblookup enabled: $enable_mmdblookup"
+echo " mmdarwin enabled: $enable_mmdarwin"
+echo " mmfields enabled: $enable_mmfields"
+echo " mmrm1stspace module enabled: $enable_mmrm1stspace"
+echo " mmkubernetes enabled: $enable_mmkubernetes"
+echo " mmtaghostname enabled: $enable_mmtaghostname"
+echo
+echo "---{ database support }---"
+echo " MySql support enabled: $enable_mysql"
+echo " libdbi support enabled: $enable_libdbi"
+if test "$enable_libdbi" = "optional"; then
+echo " libdbi use dummy: $libdbi_use_dummy"
+fi
+echo " PostgreSQL support enabled: $enable_pgsql"
+echo " mongodb support enabled: $enable_ommongodb"
+echo " hiredis support enabled: $enable_omhiredis"
+echo
+echo "---{ protocol support }---"
+echo " openssl network stream driver enabled: $enable_openssl"
+echo " GnuTLS network stream driver enabled: $enable_gnutls"
+echo " GSSAPI Kerberos 5 support enabled: $enable_gssapi_krb5"
+echo " RELP support enabled: $enable_relp"
+echo " SNMP support enabled: $enable_snmp"
+echo
+echo "---{ function modules }---"
+echo " fmhttp enabled: $enable_fmhttp"
+echo " fmhash enabled: $enable_fmhash"
+echo " fmhash with xxhash enabled: $enable_fmhash_xxhash"
+echo " fmunflatten enabled: $enable_fmunflatten"
+echo " ffaup enabled: $enable_ffaup"
+echo
+echo "---{ debugging support }---"
+echo " distcheck workaround enabled: $enable_distcheck_workaround"
+echo " Testbench enabled: $enable_testbench"
+echo " valgrind tests enabled: $with_valgrind_testbench"
+echo " valgrind helgrind tests enabled: $enable_helgrind"
+echo " Default tests enabled: $enable_default_tests"
+echo " Testbench libfaketime tests enabled: $enable_libfaketime"
+echo " Extended Testbench enabled: $enable_extended_tests"
+echo " MySQL Tests enabled: $enable_mysql_tests"
+echo " Elasticsearch Tests: $enable_elasticsearch_tests"
+echo " ClickHouse Tests: $enable_clickhouse_tests"
+echo " PostgreSQL Tests enabled: $enable_pgsql_tests"
+echo " Kafka Tests enabled: $enable_kafka_tests"
+echo " Redis Tests enabled: $enable_redis_tests"
+echo " Omazureeventhubs Tests enabled: $enable_omazureeventhubs_tests"
+echo " Imdocker Tests enabled: $enable_imdocker_tests"
+echo " gnutls tests enabled: $enable_gnutls_tests"
+echo " imfile tests enabled: $enable_imfile_tests"
+echo " systemd journal tests enabled: $enable_journal_tests"
+echo " SNMP Tests enabled: $enable_snmp_tests"
+echo " Debug mode enabled: $enable_debug"
+echo " (total) debugless mode enabled: $enable_debugless"
+echo " Diagnostic tools enabled: $enable_diagtools"
+echo " End-User tools enabled: $enable_usertools"
+echo " Valgrind support settings enabled: $enable_valgrind"
+echo
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..7de58a8
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,12 @@
+This directory contains a number of possibly useful things that do not
+directly relate to rsyslog. They are not actively supported, but as
+I said often helpful. Use them with some care, as they may be outdated
+in respect to the current release of rsyslog.
+
+At least some of this stuff has been found by our users and been
+included after a brief check and possibly an adaptation. If you have
+something useful you would like to see in contrib, just drop us a
+note (see https://www.rsyslog.com for how to do that at the time your
+are reading this document).
+
+rgerhards, 2007-08-08
diff --git a/contrib/ffaup/Makefile.am b/contrib/ffaup/Makefile.am
new file mode 100644
index 0000000..8493662
--- /dev/null
+++ b/contrib/ffaup/Makefile.am
@@ -0,0 +1,8 @@
+#
+# ffaup support
+#
+pkglib_LTLIBRARIES = ffaup.la
+ffaup_la_SOURCES = ffaup.c
+ffaup_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ffaup_la_LDFLAGS = -module -avoid-version
+ffaup_la_LIBADD = $(FAUP_LIBS)
diff --git a/contrib/ffaup/Makefile.in b/contrib/ffaup/Makefile.in
new file mode 100644
index 0000000..42d5b20
--- /dev/null
+++ b/contrib/ffaup/Makefile.in
@@ -0,0 +1,801 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/ffaup
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+ffaup_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_ffaup_la_OBJECTS = ffaup_la-ffaup.lo
+ffaup_la_OBJECTS = $(am_ffaup_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 =
+ffaup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ffaup_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/ffaup_la-ffaup.Plo
+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 = $(ffaup_la_SOURCES)
+DIST_SOURCES = $(ffaup_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+#
+# ffaup support
+#
+pkglib_LTLIBRARIES = ffaup.la
+ffaup_la_SOURCES = ffaup.c
+ffaup_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ffaup_la_LDFLAGS = -module -avoid-version
+ffaup_la_LIBADD = $(FAUP_LIBS)
+all: 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) --gnu contrib/ffaup/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/ffaup/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+ffaup.la: $(ffaup_la_OBJECTS) $(ffaup_la_DEPENDENCIES) $(EXTRA_ffaup_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(ffaup_la_LINK) -rpath $(pkglibdir) $(ffaup_la_OBJECTS) $(ffaup_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffaup_la-ffaup.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+ffaup_la-ffaup.lo: ffaup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ffaup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ffaup_la-ffaup.lo -MD -MP -MF $(DEPDIR)/ffaup_la-ffaup.Tpo -c -o ffaup_la-ffaup.lo `test -f 'ffaup.c' || echo '$(srcdir)/'`ffaup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ffaup_la-ffaup.Tpo $(DEPDIR)/ffaup_la-ffaup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffaup.c' object='ffaup_la-ffaup.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) $(ffaup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ffaup_la-ffaup.lo `test -f 'ffaup.c' || echo '$(srcdir)/'`ffaup.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/ffaup_la-ffaup.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/ffaup_la-ffaup.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/ffaup/ffaup.c b/contrib/ffaup/ffaup.c
new file mode 100644
index 0000000..c75ff7b
--- /dev/null
+++ b/contrib/ffaup/ffaup.c
@@ -0,0 +1,395 @@
+/* ffaup.c
+ * This is a function module for URL parsing.
+ *
+ * File begun on 2021/10/23 by TBertin
+ *
+ * Copyright 2007-2021 Theo Bertin for Advens
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#ifndef _AIX
+#include <typedefs.h>
+#endif
+#include <sys/types.h>
+#include <string.h>
+#include <faup/faup.h>
+#include <faup/decode.h>
+#include <faup/options.h>
+#include <faup/output.h>
+
+#include "config.h"
+#include "rsyslog.h"
+#include "parserif.h"
+#include "module-template.h"
+#include "rainerscript.h"
+
+
+
+MODULE_TYPE_FUNCTION
+MODULE_TYPE_NOKEEP
+DEF_FMOD_STATIC_DATA
+
+faup_options_t *glbOptions = NULL;
+
+enum _faup_parse_type_t {
+ FAUP_PARSE_ALL,
+ FAUP_PARSE_SCHEME,
+ FAUP_PARSE_CREDENTIAL,
+ FAUP_PARSE_SUBDOMAIN,
+ FAUP_PARSE_DOMAIN,
+ FAUP_PARSE_DOMAIN_WITHOUT_TLD,
+ FAUP_PARSE_HOST,
+ FAUP_PARSE_TLD,
+ FAUP_PARSE_PORT,
+ FAUP_PARSE_RESOURCE_PATH,
+ FAUP_PARSE_QUERY_STRING,
+ FAUP_PARSE_FRAGMENT
+};
+typedef enum _faup_parse_type_t faup_parse_type_t;
+
+
+static inline sbool check_param_count_faup(unsigned short nParams) {
+ return nParams != 1;
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti, const faup_parse_type_t parse_type) {
+ struct svar srcVal;
+ int bMustFree;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ char *url = (char*) var2CString(&srcVal, &bMustFree);
+
+ /*
+ We use the faup_handler_t struct directly instead of calling faup_init to avoid overhead and useless
+ allocations. Using one handler is not possible as the lib is not thread-safe and thread-locale solutions
+ still cause some issues.
+ If the faup_init function changes significantly in the future, it may cause issue.
+ (Validated with faup v1.5 and faup-master fecf768603e713bc903c56c8df0870fae14e3f93)
+ */
+ faup_handler_t fh = {0};
+ fh.options = glbOptions;
+
+ // default, return 0
+ ret->datatype = 'N';
+ ret->d.n = 0;
+
+ if(!faup_decode(&fh, url, strlen(url))) {
+ parser_errmsg("faup: could not parse the value\n");
+ // No returned error code, so the reason doesn't matter
+ FINALIZE;
+ }
+
+ switch(parse_type) {
+ case FAUP_PARSE_ALL:
+ ret->datatype = 'J';
+ ret->d.json = json_object_new_object();
+ json_object_object_add(
+ ret->d.json,
+ "scheme",
+ json_object_new_string_len(
+ url + faup_get_scheme_pos(&fh),
+ faup_get_scheme_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "credential",
+ json_object_new_string_len(
+ url + faup_get_credential_pos(&fh),
+ faup_get_credential_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "subdomain",
+ json_object_new_string_len(
+ url + faup_get_subdomain_pos(&fh),
+ faup_get_subdomain_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "domain",
+ json_object_new_string_len(
+ url + faup_get_domain_pos(&fh),
+ faup_get_domain_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "domain_without_tld",
+ json_object_new_string_len(
+ url + faup_get_domain_without_tld_pos(&fh),
+ faup_get_domain_without_tld_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "host",
+ json_object_new_string_len(
+ url + faup_get_host_pos(&fh),
+ faup_get_host_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "tld",
+ json_object_new_string_len(
+ url + faup_get_tld_pos(&fh),
+ faup_get_tld_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "port",
+ json_object_new_string_len(
+ url + faup_get_port_pos(&fh),
+ faup_get_port_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "resource_path",
+ json_object_new_string_len(
+ url + faup_get_resource_path_pos(&fh),
+ faup_get_resource_path_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "query_string",
+ json_object_new_string_len(
+ url + faup_get_query_string_pos(&fh),
+ faup_get_query_string_size(&fh)));
+ json_object_object_add(
+ ret->d.json,
+ "fragment",
+ json_object_new_string_len(
+ url + faup_get_fragment_pos(&fh),
+ faup_get_fragment_size(&fh)));
+ break;
+ case FAUP_PARSE_SCHEME:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_scheme_pos(&fh), faup_get_scheme_size(&fh));
+ break;
+ case FAUP_PARSE_CREDENTIAL:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_credential_pos(&fh), faup_get_credential_size(&fh));
+ break;
+ case FAUP_PARSE_SUBDOMAIN:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_subdomain_pos(&fh), faup_get_subdomain_size(&fh));
+ break;
+ case FAUP_PARSE_DOMAIN:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_domain_pos(&fh), faup_get_domain_size(&fh));
+ break;
+ case FAUP_PARSE_DOMAIN_WITHOUT_TLD:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_domain_without_tld_pos(&fh), faup_get_domain_without_tld_size(&fh));
+ break;
+ case FAUP_PARSE_HOST:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_host_pos(&fh), faup_get_host_size(&fh));
+ break;
+ case FAUP_PARSE_TLD:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_tld_pos(&fh), faup_get_tld_size(&fh));
+ break;
+ case FAUP_PARSE_PORT:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_port_pos(&fh), faup_get_port_size(&fh));
+ break;
+ case FAUP_PARSE_RESOURCE_PATH:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_resource_path_pos(&fh), faup_get_resource_path_size(&fh));
+ break;
+ case FAUP_PARSE_QUERY_STRING:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_query_string_pos(&fh), faup_get_query_string_size(&fh));
+ break;
+ case FAUP_PARSE_FRAGMENT:
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr(
+ url + faup_get_fragment_pos(&fh), faup_get_fragment_size(&fh));
+ break;
+ }
+
+finalize_it:
+ if(bMustFree) {
+ free(url);
+ }
+ varFreeMembers(&srcVal);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_full(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_ALL);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_scheme(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SCHEME);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_credential(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_CREDENTIAL);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_subdomain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SUBDOMAIN);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_domain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_domain_without_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN_WITHOUT_TLD);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_host(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_HOST);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_TLD);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_port(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_PORT);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_resource_path(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_RESOURCE_PATH);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_query_string(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_QUERY_STRING);
+}
+
+
+static void ATTR_NONNULL()
+do_faup_parse_fragment(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_FRAGMENT);
+}
+
+
+static rsRetVal ATTR_NONNULL(1)
+initFunc_faup_parse(struct cnffunc *const func)
+{
+ DEFiRet;
+
+ // Rsyslog cannot free the funcdata object,
+ // a library-specific freeing function will be used during destruction
+ func->destructable_funcdata = 0;
+ if(check_param_count_faup(func->nParams)) {
+ parser_errmsg("ffaup: ffaup(key) insufficient params.\n");
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static struct scriptFunct functions[] = {
+ {"faup", 1, 1, do_faup_parse_full, initFunc_faup_parse, NULL},
+ {"faup_scheme", 1, 1, do_faup_parse_scheme, initFunc_faup_parse, NULL},
+ {"faup_credential", 1, 1, do_faup_parse_credential, initFunc_faup_parse, NULL},
+ {"faup_subdomain", 1, 1, do_faup_parse_subdomain, initFunc_faup_parse, NULL},
+ {"faup_domain", 1, 1, do_faup_parse_domain, initFunc_faup_parse, NULL},
+ {"faup_domain_without_tld", 1, 1, do_faup_parse_domain_without_tld, initFunc_faup_parse, NULL},
+ {"faup_host", 1, 1, do_faup_parse_host, initFunc_faup_parse, NULL},
+ {"faup_tld", 1, 1, do_faup_parse_tld, initFunc_faup_parse, NULL},
+ {"faup_port", 1, 1, do_faup_parse_port, initFunc_faup_parse, NULL},
+ {"faup_resource_path", 1, 1, do_faup_parse_resource_path, initFunc_faup_parse, NULL},
+ {"faup_query_string", 1, 1, do_faup_parse_query_string, initFunc_faup_parse, NULL},
+ {"faup_fragment", 1, 1, do_faup_parse_fragment, initFunc_faup_parse, NULL},
+ {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array
+};
+
+BEGINgetFunctArray
+CODESTARTgetFunctArray
+ dbgprintf("Faup: ffaup\n");
+ *version = 1;
+ *functArray = functions;
+ENDgetFunctArray
+
+
+BEGINmodExit
+CODESTARTmodExit
+ dbgprintf("ffaup: freeing options\n");
+ if(glbOptions){
+ faup_options_free(glbOptions);
+ glbOptions = NULL;
+ }
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_FMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ dbgprintf("ffaup: initializing options\n");
+ glbOptions = faup_options_new();
+ if(!glbOptions) {
+ parser_errmsg("ffaup: could not initialize options\n");
+ ABORT_FINALIZE(RS_RET_FAUP_INIT_OPTIONS_FAILED);
+ }
+ // Don't generate a string output, and don't load LUA modules
+ // This is useful only for the faup executable
+ glbOptions->output = FAUP_OUTPUT_NONE;
+ glbOptions->exec_modules = FAUP_MODULES_NOEXEC;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("rsyslog ffaup init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/contrib/fmhash/Makefile.am b/contrib/fmhash/Makefile.am
new file mode 100644
index 0000000..d16e121
--- /dev/null
+++ b/contrib/fmhash/Makefile.am
@@ -0,0 +1,8 @@
+#
+# fmhash support
+#
+pkglib_LTLIBRARIES = fmhash.la
+fmhash_la_SOURCES = fmhash.c
+fmhash_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+fmhash_la_LDFLAGS = -module -avoid-version
+fmhash_la_LIBADD = $(HASH_XXHASH_LIBS)
diff --git a/contrib/fmhash/Makefile.in b/contrib/fmhash/Makefile.in
new file mode 100644
index 0000000..892be4b
--- /dev/null
+++ b/contrib/fmhash/Makefile.in
@@ -0,0 +1,801 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/fmhash
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+fmhash_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fmhash_la_OBJECTS = fmhash_la-fmhash.lo
+fmhash_la_OBJECTS = $(am_fmhash_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 =
+fmhash_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(fmhash_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/fmhash_la-fmhash.Plo
+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 = $(fmhash_la_SOURCES)
+DIST_SOURCES = $(fmhash_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+#
+# fmhash support
+#
+pkglib_LTLIBRARIES = fmhash.la
+fmhash_la_SOURCES = fmhash.c
+fmhash_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+fmhash_la_LDFLAGS = -module -avoid-version
+fmhash_la_LIBADD = $(HASH_XXHASH_LIBS)
+all: 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) --gnu contrib/fmhash/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/fmhash/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+fmhash.la: $(fmhash_la_OBJECTS) $(fmhash_la_DEPENDENCIES) $(EXTRA_fmhash_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(fmhash_la_LINK) -rpath $(pkglibdir) $(fmhash_la_OBJECTS) $(fmhash_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmhash_la-fmhash.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+fmhash_la-fmhash.lo: fmhash.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmhash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fmhash_la-fmhash.lo -MD -MP -MF $(DEPDIR)/fmhash_la-fmhash.Tpo -c -o fmhash_la-fmhash.lo `test -f 'fmhash.c' || echo '$(srcdir)/'`fmhash.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fmhash_la-fmhash.Tpo $(DEPDIR)/fmhash_la-fmhash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fmhash.c' object='fmhash_la-fmhash.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) $(fmhash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fmhash_la-fmhash.lo `test -f 'fmhash.c' || echo '$(srcdir)/'`fmhash.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/fmhash_la-fmhash.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/fmhash_la-fmhash.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/fmhash/fmhash.c b/contrib/fmhash/fmhash.c
new file mode 100644
index 0000000..224b824
--- /dev/null
+++ b/contrib/fmhash/fmhash.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2018, Harshvardhan Shrivastava
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+ */
+
+#include "config.h"
+#include <stdint.h>
+#include <stddef.h>
+#ifndef _AIX
+#include <typedefs.h>
+#endif
+#include <sys/types.h>
+#include <string.h>
+#ifdef USE_HASH_XXHASH
+# include <xxhash.h>
+#endif
+
+#include "rsyslog.h"
+#include "parserif.h"
+#include "module-template.h"
+#include "rainerscript.h"
+
+
+
+MODULE_TYPE_FUNCTION
+MODULE_TYPE_NOKEEP
+DEF_FMOD_STATIC_DATA
+
+typedef uint64_t hash_t;
+typedef uint32_t seed_t;
+typedef struct hash_context_s hash_context_t;
+
+typedef hash_t (*hash_impl)(const void*, size_t, seed_t);
+
+typedef rsRetVal (*hash_wrapper_2)(struct svar *__restrict__ const
+ , struct svar *__restrict__ const, hash_context_t*, hash_t*);
+typedef rsRetVal (*hash_wrapper_3)(struct svar *__restrict__ const, struct svar *__restrict__ const
+ , struct svar *__restrict__ const, hash_context_t*, hash_t*);
+
+struct hash_context_s {
+ hash_impl hashXX;
+ hash_wrapper_2 hash_wrapper_1_2;
+ hash_wrapper_3 hash_wrapper_2_3;
+};
+
+/*
+ * Fowler–Noll–Vo hash 32 bit
+ * http://www.isthe.com/chongo/src/fnv/hash_32.c
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static hash_t
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+fnv_32(const void* input, size_t len, seed_t seed) {
+ unsigned char *bp = (unsigned char *)input; /* start of buffer */
+
+ /*
+ * FNV-1 hash each octet in the buffer
+ */
+ size_t i;
+ for (i = 0; i < len; i++) {
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+ seed += (seed<<1) + (seed<<4) + (seed<<7) + (seed<<8) + (seed<<24);
+
+ /* xor the bottom with the current octet */
+ seed ^= (seed_t)*bp++;
+ }
+
+ /* return our new hash value */
+ return seed;
+}
+
+
+/*
+ * Modified Bernstein
+ * http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static hash_t
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+djb_hash(const void* input, size_t len, seed_t seed) {
+ const char *p = input;
+ hash_t hash = 5381;
+ size_t i;
+ for (i = 0; i < len; i++) {
+ hash = 33 * hash ^ p[i];
+ }
+
+ return hash + seed;
+}
+
+/*Get 32 bit hash for input*/
+static hash_t
+hash32(const void* input, size_t len, seed_t seed) {
+ hash_t xhash = 0;
+#ifdef USE_HASH_XXHASH
+ xhash = XXH32(input, len, seed);
+#else
+ xhash = fnv_32(input, len, seed);
+#endif
+ return xhash;
+}
+
+/*Get 64 bit hash for input*/
+static hash_t
+hash64(const void* input, size_t len, seed_t seed) {
+ hash_t xhash = 0;
+#ifdef USE_HASH_XXHASH
+ xhash = XXH64(input, len, seed);
+#else
+ xhash = djb_hash(input, len, seed);
+#endif
+ return xhash;
+}
+
+static rsRetVal
+hash_wrapper2(struct svar *__restrict__ const sourceVal
+ , struct svar *__restrict__ const seedVal, hash_context_t* hcontext, hash_t* xhash) {
+ DEFiRet;
+ int freeHashStr = 0, success = 0;
+ char *hashStr = NULL;
+ seed_t seed = 0;
+ if(seedVal) {
+ seed = var2Number(seedVal, &success);
+ if (!success) {
+ parser_warnmsg("fmhash: hashXX(string, seed) didn't get a valid 'seed' limit"
+ ", defaulting hash value to 0");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ }
+
+ hashStr = (char*)var2CString(sourceVal, &freeHashStr);
+ size_t len = strlen(hashStr);
+ (*xhash) = hcontext->hashXX(hashStr, len, seed);
+ DBGPRINTF("fmhash: hashXX generated hash %" PRIu64 " for string(%.*s)"
+ , (*xhash), (int)len, hashStr);
+finalize_it:
+ if (freeHashStr) {
+ free(hashStr);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+hash_wrapper3(struct svar *__restrict__ const sourceVal, struct svar *__restrict__ const modVal
+ , struct svar *__restrict__ const seedVal, hash_context_t* hcontext, hash_t* xhash) {
+
+ DEFiRet;
+ int success = 0;
+ hash_t mod = var2Number(modVal, &success);
+ if (! success) {
+ parser_warnmsg("fmhash: hashXXmod(string, mod)/hash64mod(string, mod, seed) didn't"
+ " get a valid 'mod' limit, defaulting hash value to 0");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ if(mod == 0) {
+ parser_warnmsg("fmhash: hashXXmod(string, mod)/hash64mod(string, mod, seed) invalid"
+ ", 'mod' is zero, , defaulting hash value to 0");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+
+ CHKiRet((hcontext->hash_wrapper_1_2(sourceVal, seedVal, hcontext, xhash)));
+ if(mod != 0) {
+ (*xhash) = (*xhash) % mod;
+ }
+ DBGPRINTF("fmhash: hashXXmod generated hash-mod %" PRIu64 ".", (*xhash));
+finalize_it:
+ RETiRet;
+}
+
+static void
+init_hash32_context(hash_context_t* hash32_context) {
+ hash32_context->hashXX = hash32;
+ hash32_context->hash_wrapper_1_2 = hash_wrapper2;
+ hash32_context->hash_wrapper_2_3 = hash_wrapper3;
+};
+
+static void
+init_hash64_context(hash_context_t* hash64_context) {
+ hash64_context->hashXX = hash64;
+ hash64_context->hash_wrapper_1_2 = hash_wrapper2;
+ hash64_context->hash_wrapper_2_3 = hash_wrapper3;
+};
+
+static void ATTR_NONNULL()
+fmHashXX(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+ DEFiRet;
+ struct svar hashStrVal;
+ struct svar seedVal;
+ hash_context_t* hcontext = NULL;
+ hash_t xhash = 0;
+ cnfexprEval(func->expr[0], &hashStrVal, usrptr, pWti);
+ if(func->nParams == 2) cnfexprEval(func->expr[1], &seedVal, usrptr, pWti);
+ ret->d.n = 0;
+ ret->datatype = 'N';
+ hcontext = (hash_context_t*) func->funcdata;
+ CHKiRet((hcontext->hash_wrapper_1_2(&hashStrVal
+ , (func->nParams == 2 ? &seedVal : NULL)
+ , hcontext, &xhash)));
+ ret->d.n = xhash;
+finalize_it:
+ varFreeMembers(&hashStrVal);
+ if(func->nParams == 2) varFreeMembers(&seedVal);
+}
+
+static void ATTR_NONNULL()
+fmHashXXmod(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) {
+
+ DEFiRet;
+ struct svar hashStrVal;
+ struct svar modVal;
+ struct svar seedVal;
+ hash_context_t* hcontext = NULL;
+ hash_t xhash = 0;
+ cnfexprEval(func->expr[0], &hashStrVal, usrptr, pWti);
+ cnfexprEval(func->expr[1], &modVal, usrptr, pWti);
+ if(func->nParams == 3) cnfexprEval(func->expr[2], &seedVal, usrptr, pWti);
+ ret->d.n = 0;
+ ret->datatype = 'N';
+ hcontext = (hash_context_t*) func->funcdata;
+ CHKiRet((hcontext->hash_wrapper_2_3(&hashStrVal
+ , &modVal, func->nParams > 2 ? &seedVal : NULL
+ , hcontext, &xhash)));
+ ret->d.n = xhash;
+finalize_it:
+ varFreeMembers(&hashStrVal);
+ varFreeMembers(&modVal);
+ if(func->nParams == 3) varFreeMembers(&seedVal);
+}
+
+static inline sbool check_param_count_hash(unsigned short nParams) {
+ return (nParams != 1 && nParams != 2);
+}
+
+static inline sbool check_param_count_hashmod(unsigned short nParams) {
+ return (nParams != 2 && nParams != 3);
+}
+
+static rsRetVal ATTR_NONNULL(1)
+init_fmHash64(struct cnffunc *const func)
+{
+ DEFiRet;
+ hash_context_t *hash_context = NULL;
+ if(check_param_count_hash(func->nParams)) {
+ parser_errmsg("fmhash: hash64(string) / hash64(string, seed)"
+ " insufficient params.\n");
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+ }
+ func->destructable_funcdata = 1;
+ CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t)));
+ init_hash64_context(hash_context);
+ func->funcdata = (void*)hash_context;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL(1)
+init_fmHash64mod(struct cnffunc *const func)
+{
+ DEFiRet;
+ hash_context_t *hash_context = NULL;
+ if(check_param_count_hashmod(func->nParams)) {
+ parser_errmsg("fmhash: hash64mod(string, mod)/hash64mod(string, mod, seed)"
+ " insufficient params.\n");
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+ }
+ func->destructable_funcdata = 1;
+ CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t)));
+ init_hash64_context(hash_context);
+ func->funcdata = (void*)hash_context;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL(1)
+init_fmHash32(struct cnffunc *const func)
+{
+ DEFiRet;
+ hash_context_t *hash_context = NULL;
+ if(check_param_count_hash(func->nParams)) {
+ parser_errmsg("fmhash: hash32(string) / hash32(string, seed)"
+ " insufficient params.\n");
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+ }
+ func->destructable_funcdata = 1;
+ CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t)));
+ init_hash32_context(hash_context);
+ func->funcdata = (void*)hash_context;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL(1)
+init_fmHash32mod(struct cnffunc *const func)
+{
+ DEFiRet;
+ hash_context_t *hash_context = NULL;
+ if(check_param_count_hashmod(func->nParams)) {
+ parser_errmsg("fmhash: hash32mod(string, mod)/hash32mod(string, mod, seed)"
+ " insufficient params.\n");
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+ }
+ func->destructable_funcdata = 1;
+ CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t)));
+ init_hash32_context(hash_context);
+ func->funcdata = (void*)hash_context;
+finalize_it:
+ RETiRet;
+}
+
+
+static struct scriptFunct functions[] = {
+ {"hash64", 1, 2, fmHashXX, init_fmHash64, NULL},
+ {"hash64mod", 2, 3, fmHashXXmod, init_fmHash64mod, NULL},
+ {"hash32", 1, 2, fmHashXX, init_fmHash32, NULL},
+ {"hash32mod", 2, 3, fmHashXXmod, init_fmHash32mod, NULL},
+ {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array
+};
+
+
+BEGINgetFunctArray
+CODESTARTgetFunctArray
+ dbgprintf("Hash: fmhhash\n");
+ *version = 1;
+ *functArray = functions;
+ENDgetFunctArray
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_FMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("rsyslog fmhash init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/contrib/fmunflatten/Makefile.am b/contrib/fmunflatten/Makefile.am
new file mode 100644
index 0000000..b3d27e4
--- /dev/null
+++ b/contrib/fmunflatten/Makefile.am
@@ -0,0 +1,5 @@
+pkglib_LTLIBRARIES = fmunflatten.la
+fmunflatten_la_SOURCES = fmunflatten.c
+fmunflatten_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JSON_C_CFLAGS)
+fmunflatten_la_LDFLAGS = -module -avoid-version
+fmunflatten_la_LIBADD = $(JSON_C_LIBS)
diff --git a/contrib/fmunflatten/Makefile.in b/contrib/fmunflatten/Makefile.in
new file mode 100644
index 0000000..366f145
--- /dev/null
+++ b/contrib/fmunflatten/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/fmunflatten
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+fmunflatten_la_DEPENDENCIES =
+am_fmunflatten_la_OBJECTS = fmunflatten_la-fmunflatten.lo
+fmunflatten_la_OBJECTS = $(am_fmunflatten_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 =
+fmunflatten_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(fmunflatten_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo
+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 = $(fmunflatten_la_SOURCES)
+DIST_SOURCES = $(fmunflatten_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = fmunflatten.la
+fmunflatten_la_SOURCES = fmunflatten.c
+fmunflatten_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JSON_C_CFLAGS)
+fmunflatten_la_LDFLAGS = -module -avoid-version
+fmunflatten_la_LIBADD = $(JSON_C_LIBS)
+all: 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) --gnu contrib/fmunflatten/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/fmunflatten/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+fmunflatten.la: $(fmunflatten_la_OBJECTS) $(fmunflatten_la_DEPENDENCIES) $(EXTRA_fmunflatten_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(fmunflatten_la_LINK) -rpath $(pkglibdir) $(fmunflatten_la_OBJECTS) $(fmunflatten_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+fmunflatten_la-fmunflatten.lo: fmunflatten.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmunflatten_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fmunflatten_la-fmunflatten.lo -MD -MP -MF $(DEPDIR)/fmunflatten_la-fmunflatten.Tpo -c -o fmunflatten_la-fmunflatten.lo `test -f 'fmunflatten.c' || echo '$(srcdir)/'`fmunflatten.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fmunflatten_la-fmunflatten.Tpo $(DEPDIR)/fmunflatten_la-fmunflatten.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fmunflatten.c' object='fmunflatten_la-fmunflatten.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) $(fmunflatten_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fmunflatten_la-fmunflatten.lo `test -f 'fmunflatten.c' || echo '$(srcdir)/'`fmunflatten.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/fmunflatten/fmunflatten.c b/contrib/fmunflatten/fmunflatten.c
new file mode 100644
index 0000000..f1e4e69
--- /dev/null
+++ b/contrib/fmunflatten/fmunflatten.c
@@ -0,0 +1,243 @@
+/*
+ * This is a function module providing ability to unflatten a JSON tree.
+ *
+ * Copyright 2020 Julien Thomas < jthomas @ zenetys.com >
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdint.h>
+#include <stddef.h>
+#ifndef _AIX
+#include <typedefs.h>
+#endif
+#include <sys/types.h>
+#include <string.h>
+
+#include "rsyslog.h"
+
+#include "errmsg.h"
+#include "msg.h"
+#include "parserif.h"
+#include "module-template.h"
+#include "rainerscript.h"
+#include "wti.h"
+
+#define FMUNFLATTEN_KBUFLEN 256
+#define _jso_type(x) json_type_to_name(json_object_get_type(x))
+
+MODULE_TYPE_FUNCTION
+MODULE_TYPE_NOKEEP
+DEF_FMOD_STATIC_DATA
+
+struct unflatten_ctx {
+ char *kbuf;
+ size_t kbuf_len;
+ char delim;
+};
+
+/* forward declarations */
+void unflatten_add(struct unflatten_ctx *ctx, struct json_object *dst, const char *key, struct json_object *value);
+void unflatten(struct unflatten_ctx *ctx, struct json_object *src, struct json_object *dst);
+
+void unflatten_add(struct unflatten_ctx *ctx,
+ struct json_object *dst,
+ const char *key,
+ struct json_object *value)
+{
+ const char *p = key;
+ const char *q = p;
+ int depth = 0;
+ size_t klen;
+ struct json_object *o;
+ json_bool exists_already;
+ int create;
+
+ while (1) {
+ while (*q != ctx->delim && *q != '\0')
+ q++;
+ klen = q - p;
+ if (klen + 1 > ctx->kbuf_len) {
+ DBGPRINTF("warning: flat key \"%.20s...\" truncated at depth #%d, buffer too "
+ "small (max %zd)\n", key, depth, ctx->kbuf_len);
+ klen = ctx->kbuf_len - 1;
+ }
+ memcpy(ctx->kbuf, p, klen);
+ ctx->kbuf[klen] = '\0';
+ exists_already = json_object_object_get_ex(dst, ctx->kbuf, &o);
+
+ if (*q == ctx->delim) {
+ if (!exists_already)
+ create = 1;
+ else if (json_object_is_type(o, json_type_object))
+ create = 0;
+ else {
+ DBGPRINTF("warning: while processing flat key \"%s\" at depth #%d (intermediate "
+ "node), overriding existing value of type %s by an object\n", key, depth,
+ _jso_type(o));
+ json_object_object_del(dst, ctx->kbuf);
+ create = 1;
+ }
+ if (create) {
+ o = json_object_new_object();
+ json_object_object_add(dst, ctx->kbuf, o);
+ }
+ dst = o;
+ p = q + 1;
+ q = p;
+ depth++;
+ }
+ else if (*q == '\0') {
+ if (json_object_is_type(value, json_type_object)) {
+ if (exists_already) {
+ if (!json_object_is_type(o, json_type_object)) {
+ DBGPRINTF("warning: while processing flat key \"%s\" at depth #%d "
+ "(final node), overriding existing value of type %s by an "
+ "object\n", key, depth, _jso_type(o));
+ json_object_object_del(dst, ctx->kbuf);
+ o = json_object_new_object();
+ json_object_object_add(dst, ctx->kbuf, o);
+ }
+ }
+ else {
+ o = json_object_new_object();
+ json_object_object_add(dst, ctx->kbuf, o);
+ }
+ unflatten(ctx, value, o);
+ }
+ else {
+ if (exists_already) {
+ DBGPRINTF("warning: while processing flat key \"%s\" at depth #%d "
+ "(final node), overriding existing value\n", key, depth);
+ json_object_object_del(dst, ctx->kbuf);
+ }
+ o = jsonDeepCopy(value);
+ json_object_object_add(dst, ctx->kbuf, o);
+ }
+ break;
+ }
+ }
+}
+
+void unflatten(struct unflatten_ctx *ctx,
+ struct json_object *src,
+ struct json_object *dst)
+{
+ struct json_object_iterator it = json_object_iter_begin(src);
+ struct json_object_iterator itEnd = json_object_iter_end(src);
+ const char *key;
+ struct json_object *value;
+
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ key = json_object_iter_peek_name(&it);
+ value = json_object_iter_peek_value(&it);
+ unflatten_add(ctx, dst, key, value);
+ json_object_iter_next(&it);
+ }
+}
+
+static void ATTR_NONNULL()
+doFunc_unflatten(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar src_var;
+ struct svar delim_var;
+
+ char kbuf[FMUNFLATTEN_KBUFLEN];
+ struct unflatten_ctx ctx = {
+ .kbuf = kbuf,
+ .kbuf_len = sizeof(kbuf),
+ .delim = 0
+ };
+
+ /* A dummy value of 0 (number) is returned by default. Callers should also
+ * call script_error() to check if this script function succeeded before
+ * using the value it returns. */
+ ret->datatype = 'N';
+ ret->d.n = 0;
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EINVAL);
+
+ cnfexprEval(func->expr[0], &src_var, usrptr, pWti);
+ cnfexprEval(func->expr[1], &delim_var, usrptr, pWti);
+
+ /* Check argument 2 (delimiter character). */
+ if (delim_var.datatype == 'S' && es_strlen(delim_var.d.estr) == 1)
+ ctx.delim = *es_getBufAddr(delim_var.d.estr);
+ else if (delim_var.datatype == 'N')
+ ctx.delim = delim_var.d.n;
+ if (ctx.delim == 0) {
+ LogError(0, RS_RET_INVALID_PARAMS, "unflatten: invalid argument 2 (delim), single character "
+ "required (as string or decimal charcode)");
+ FINALIZE;
+ }
+
+ /* Check argument 1 (source). Not logging an error avoids emitting logs for
+ * messages when $! was not touched. */
+ if (src_var.datatype != 'J') {
+ DBGPRINTF("unsupported argument 1 (src) datatype %c\n", src_var.datatype);
+ FINALIZE;
+ }
+
+ ret->datatype = 'J';
+ if (json_object_is_type(src_var.d.json, json_type_object)) {
+ ret->d.json = json_object_new_object();
+ unflatten(&ctx, src_var.d.json, ret->d.json);
+ }
+ else
+ ret->d.json = jsonDeepCopy(src_var.d.json);
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EOK);
+
+finalize_it:
+ varFreeMembers(&src_var);
+ varFreeMembers(&delim_var);
+}
+
+static rsRetVal ATTR_NONNULL(1)
+initFunc_unflatten(struct cnffunc *const func)
+{
+ DEFiRet;
+ func->destructable_funcdata = 0;
+ RETiRet;
+}
+
+static struct scriptFunct functions[] = {
+ { "unflatten", 2, 2, doFunc_unflatten, initFunc_unflatten, NULL },
+ { NULL, 0, 0, NULL, NULL, NULL } /* last element to check end of array */
+};
+
+BEGINgetFunctArray
+CODESTARTgetFunctArray
+ *version = 1;
+ *functArray = functions;
+ENDgetFunctArray
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_FMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("rsyslog fmunflatten init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/contrib/gnutls/ca.pem b/contrib/gnutls/ca.pem
new file mode 100644
index 0000000..6324c7d
--- /dev/null
+++ b/contrib/gnutls/ca.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICYjCCAc2gAwIBAgIBATALBgkqhkiG9w0BAQUwWDELMAkGA1UEBhMCREUxHTAb
+BgNVBAoTFHJzeXNsb2cgdGVzdCByb290IENBMQswCQYDVQQLEwJDQTEdMBsGA1UE
+AxMUcnN5c2xvZy10ZXN0LXJvb3QtY2EwHhcNMDgwNTIwMTI1ODEyWhcNMTgwNTE4
+MTI1ODI0WjBYMQswCQYDVQQGEwJERTEdMBsGA1UEChMUcnN5c2xvZyB0ZXN0IHJv
+b3QgQ0ExCzAJBgNVBAsTAkNBMR0wGwYDVQQDExRyc3lzbG9nLXRlc3Qtcm9vdC1j
+YTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGAw2s+V+WCK7jx9MLpDD4pO8SCqq6Q
+nK/BptvKM+YeBrV9ud3lq6YgbpNmv3/wig43rqpolqk7PdDxTW/mdXPmM72oKr/N
+Fc2cAyOEXK8JTWiqwc//V4qMAnKFfLOxr1dr7WRD0k4Tc8+BWJMQjL2zmGXiSGEF
+YWYIFHLmnX4ZgyMCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E
+BQMDBwYAMB0GA1UdDgQWBBQzYQQgUm0YLNdarJnc2c1LxYVClDALBgkqhkiG9w0B
+AQUDgYEAuGWtH7Jkpa0n/izqQ5ddDQP/LT6taivCwlpEYEU9aumpQPWWxtYywKaP
+RfM1JTMLAiYd8MS7TJ8TYRvvR32Y02Y+OhXn11xERkWvBT2M9yzqX6hDfRueN7RT
+fPWsfm/NBTVojzjaECcTFenZid7PC5JiFbcU6PSUMZ49/JPhxAo=
+-----END CERTIFICATE-----
diff --git a/contrib/gnutls/cert.pem b/contrib/gnutls/cert.pem
new file mode 100644
index 0000000..6b5b13c
--- /dev/null
+++ b/contrib/gnutls/cert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIChjCCAfGgAwIBAgIBADALBgkqhkiG9w0BAQUwWDELMAkGA1UEBhMCREUxHTAb
+BgNVBAoTFHJzeXNsb2cgdGVzdCByb290IENBMQswCQYDVQQLEwJDQTEdMBsGA1UE
+AxMUcnN5c2xvZy10ZXN0LXJvb3QtY2EwHhcNMDgwNTIwMTMwNDE5WhcNMTgwNTE4
+MTMwNDI2WjA6MQswCQYDVQQGEwJERTEQMA4GA1UEChMHcnN5c2xvZzEZMBcGA1UE
+CxMQdGVzdCBjZXJ0aWZpY2F0ZTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGAxmHe
+fztJgaGxFYEceiUg0hdMlRVWBqoZelJ8BeXTDnXcu/5F2HtM+l+QDyDaGjKlx+NI
+K4rkj7d6Wd3AKPgOYS0VSDZe3a1xf9rRYzOthWTv7tYi4/LTqPXqN5lKE71dgrB/
+/gOmvV/1YD776FIxVGCSAT0hHwkFC3slmpJSwD8CAwEAAaOBhDCBgTAMBgNVHRMB
+Af8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHREECzAJ
+ggdyc3lzbG9nMB0GA1UdDgQWBBQYu6eC9UALvC+5K5VOnFRi5OC98TAfBgNVHSME
+GDAWgBQzYQQgUm0YLNdarJnc2c1LxYVClDALBgkqhkiG9w0BAQUDgYEAXaymqsG9
+PNBhhWIRFvXCDMaDM71vUtgSFoNUbxIV607ua2HQosPPM4EHIda6N6hdBK1bMQoG
+yqBwhvw0JVaVaO70Kbs2m2Ypk3YcpJtRqyp8q8+2y/w1Mk1QazFZC29aYgX2iNVf
+X4/x38YEL7Gu5vqPrTn++agnV4ZXECKuvLQ=
+-----END CERTIFICATE-----
diff --git a/contrib/gnutls/key.pem b/contrib/gnutls/key.pem
new file mode 100644
index 0000000..3ff507f
--- /dev/null
+++ b/contrib/gnutls/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDGYd5/O0mBobEVgRx6JSDSF0yVFVYGqhl6UnwF5dMOddy7/kXY
+e0z6X5APINoaMqXH40griuSPt3pZ3cAo+A5hLRVINl7drXF/2tFjM62FZO/u1iLj
+8tOo9eo3mUoTvV2CsH/+A6a9X/VgPvvoUjFUYJIBPSEfCQULeyWaklLAPwIDAQAB
+AoGARIwKqmHc+0rYenq7UUVE+vMMBjNyHyllVkvsCMmpzMRS+i5ZCf1I0vZ0O5X5
+ZrX7bH8PL+R1J2eZgjXKMR3NMZBuyKHewItD9t2rIC0eD/ITlwq3VybbaMsw666e
+INxSmax+dS5CEcLevHHP3c+Q7S7QAFiWV43TdFUGXWJktIkCQQDPQ5WAZ+/Tvv0Q
+vtRjXMeTVaw/bSuKNUeDzFkmGyePnFeCReNFtJLE9PFSQWcPuYcbZgU59JTfA5ac
+Un+cHm31AkEA9Qek+q7PcJ+kON9E6SNodCZn6gLyHjnWrq4tf8pZO3NvoX2QiuD4
+rwF7KWjr6q1JzADpLtwXnuYEhyiLFjJA4wJAcElMCEnG2y+ASH8p7z7HfKGQdLg/
+O1wMB3JA5e0WLK5lllUogI4IaZ3N02NNY25+rLBDqpc/w+ZcxQnIypqNtQJATs9p
+ofON5wSB1oUBbhckZo9fxuWxqEUkJsUA/2Q+9R843XE8h166vdc1HOmRT8bywHne
+hmLl+gazmCFTMw1wzwJAHng+3zGUl4D8Ov3MPFD6hwYYK6/pEdtz/NUsCSazF7eK
+XuuP+DXPHNhXOuF1A3tP74pfc/fC1uCUH2G5z3Fy0Q==
+-----END RSA PRIVATE KEY-----
diff --git a/contrib/imbatchreport/Makefile.am b/contrib/imbatchreport/Makefile.am
new file mode 100644
index 0000000..a28f4f6
--- /dev/null
+++ b/contrib/imbatchreport/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imbatchreport.la
+
+imbatchreport_la_SOURCES = imbatchreport.c
+imbatchreport_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imbatchreport_la_LDFLAGS = -module -avoid-version
+imbatchreport_la_LIBADD =
diff --git a/contrib/imbatchreport/Makefile.in b/contrib/imbatchreport/Makefile.in
new file mode 100644
index 0000000..db343f2
--- /dev/null
+++ b/contrib/imbatchreport/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imbatchreport
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imbatchreport_la_DEPENDENCIES =
+am_imbatchreport_la_OBJECTS = imbatchreport_la-imbatchreport.lo
+imbatchreport_la_OBJECTS = $(am_imbatchreport_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 =
+imbatchreport_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(imbatchreport_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo
+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 = $(imbatchreport_la_SOURCES)
+DIST_SOURCES = $(imbatchreport_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imbatchreport.la
+imbatchreport_la_SOURCES = imbatchreport.c
+imbatchreport_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imbatchreport_la_LDFLAGS = -module -avoid-version
+imbatchreport_la_LIBADD =
+all: 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) --gnu contrib/imbatchreport/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imbatchreport/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imbatchreport.la: $(imbatchreport_la_OBJECTS) $(imbatchreport_la_DEPENDENCIES) $(EXTRA_imbatchreport_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imbatchreport_la_LINK) -rpath $(pkglibdir) $(imbatchreport_la_OBJECTS) $(imbatchreport_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imbatchreport_la-imbatchreport.lo: imbatchreport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imbatchreport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imbatchreport_la-imbatchreport.lo -MD -MP -MF $(DEPDIR)/imbatchreport_la-imbatchreport.Tpo -c -o imbatchreport_la-imbatchreport.lo `test -f 'imbatchreport.c' || echo '$(srcdir)/'`imbatchreport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imbatchreport_la-imbatchreport.Tpo $(DEPDIR)/imbatchreport_la-imbatchreport.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imbatchreport.c' object='imbatchreport_la-imbatchreport.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) $(imbatchreport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imbatchreport_la-imbatchreport.lo `test -f 'imbatchreport.c' || echo '$(srcdir)/'`imbatchreport.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imbatchreport/imbatchreport.c b/contrib/imbatchreport/imbatchreport.c
new file mode 100644
index 0000000..be71ee7
--- /dev/null
+++ b/contrib/imbatchreport/imbatchreport.c
@@ -0,0 +1,1033 @@
+/* imbatchreport.c
+ *
+ * This is the input module for reading full text file data. A text file is a
+ * non-binary file who's lines are delimited by the \n character. The file is
+ * treated as a single message. An optional structured data can be written at
+ * the end of the file.
+ *
+ * No state file are used as it should only grow with time. Instead the state
+ * is managed using the name of the file. A "glob" allows the module to identify
+ * "to be treated" files. The module can be configured either to deleted the
+ * the file on success either to rename the file on success. The size limit is
+ * fixed by rsyslog max message size global parameter. All files larger than this
+ * limit produce a message which references it as "too large" and its new location
+ * The "too large" files are also renamed to keep them available.
+ *
+ * This modules allows one to centralize batch reports with other standard logs and
+ * performance monitoring in a single repository (ElasticSearch, HDFS, ...). This
+ * centralization helps to identify cause of global performance issues.
+ *
+ * Work originally begun on 2014-07-01 by Philippe Duveau @ Pari Mutuel Urbain
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h> /* do NOT remove: will soon be done by the module generation macros */
+#include <sys/types.h>
+#include <unistd.h>
+#include <glob.h>
+#include <fnmatch.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include "rsyslog.h" /* error codes etc... */
+#include "dirty.h"
+#include "cfsysline.h" /* access to config file objects */
+#include "module-template.h"
+#include "srUtils.h" /* some utility functions */
+#include "msg.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "stringbuf.h"
+#include "ruleset.h"
+#include "ratelimit.h"
+
+#include <regex.h>
+
+MODULE_TYPE_INPUT /* must be present for input modules, do not remove */
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imbatchreport")
+
+/* defines for freebsd */
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA /* must be present, starts static data */
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
+
+#define SRUCTDATA_BUFFER_LEN 150
+#define READ_BUFFER_LEN 512
+#define FILE_TOO_LARGE "File too large : "
+#define FILE_TOO_LARGE_LEN sizeof(FILE_TOO_LARGE)-1
+
+#define DFLT_PollInterval 10
+
+#define ADD_METADATA_UNSPECIFIED -1
+
+typedef enum action_batchreport_t {
+ action_nothing,
+ action_rename,
+ action_delete
+} action_batchreport_t;
+
+struct instanceConf_s {
+ uchar *pszFollow_glob;
+ uchar *pszDirName;
+ uchar *pszFileBaseName;
+ uchar *pszTag;
+ int lenTag;
+ uchar *pszTSk;
+ int lenTSk;
+ uchar *pszProgk;
+ int lenProgk;
+ int must_stop;
+ uchar *pszBindRuleset;
+ int bDedupSpace;
+ int iFacility;
+ int iSeverity;
+ char *ff_regex;
+ /* Full treatment : this should contain a regex applied on filename. The matching
+ part is then replaced with ff_replace to put the file out of scan criteria */
+ regex_t ff_preg;
+
+ char *ff_rename;
+ int len_rename;
+
+ char *ff_reject;
+ int len_reject;
+
+ int filename_oversize;
+ ruleset_t *pBindRuleset;
+ /* ruleset to bind listener to (use system default if unspecified) */
+
+ ratelimit_t *ratelimiter;
+
+ struct instanceConf_s *next;
+
+ action_batchreport_t action;
+
+ char *pszNewFName;
+ int fd;
+
+ sbool goon;
+};
+
+/* global configuration variables */
+static struct {
+ uchar *hostname;
+ size_t lhostname;
+
+ char *msg_buffer;
+ size_t max_msg_size;
+
+ instanceConf_t *root;
+
+ /* number of seconds to sleep when there was no file activity */
+ int iPollInterval;
+} fixedModConf;
+
+/* config variables */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "pollinginterval", eCmdHdlrPositiveInt, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "reports", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "tag", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "programkey", eCmdHdlrString, 0 },
+ { "timestampkey", eCmdHdlrString, 0 },
+ { "deduplicatespace", eCmdHdlrBinary, 0},
+ { "rename", eCmdHdlrString, 0 },
+ { "delete", eCmdHdlrString, 0 },
+ { "severity", eCmdHdlrSeverity, 0 },
+ { "facility", eCmdHdlrFacility, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+/* enqueue the read file line as a message. The provided string is
+ * not freed - thuis must be done by the caller.
+ */
+static rsRetVal enqMsg(instanceConf_t *pInst, smsg_t *pMsg)
+{
+ DEFiRet;
+
+ MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetHOSTNAME(pMsg, fixedModConf.hostname, (const int) fixedModConf.lhostname);
+ MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag);
+ MsgSetPROCID(pMsg, "-");
+ MsgSetMSGID(pMsg, "-");
+
+ pMsg->iFacility = pInst->iFacility >> 3;
+ pMsg->iSeverity = pInst->iSeverity;
+
+ MsgSetRuleset(pMsg, pInst->pBindRuleset);
+
+ CHKiRet(ratelimitAddMsg(pInst->ratelimiter, NULL, pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+/* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case
+ * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27
+ */
+static void pollFileCancelCleanup(void *pArg)
+{
+ instanceConf_t *ppInst = (instanceConf_t*) pArg;
+ if (ppInst->fd > 0)
+ close(ppInst->fd);
+ if (ppInst->pszNewFName)
+ free(ppInst->pszNewFName);
+}
+
+/* readAndSendFile try to read the file and send the message.
+ * @param pInst point to instance
+ * @param filename the file name
+ * @param fstate the file stat
+ */
+static rsRetVal readAndSendFile(instanceConf_t *pInst, char *filename, char *fpath, struct stat *fstat)
+{
+ smsg_t *pMsg = NULL;
+ size_t file_len, read_len = 0, sd_buf_l, msg_len = 0, idx = 0;
+ int last_is_space = 0;
+ struct timeval tvm;
+ uchar sd_buffer[SRUCTDATA_BUFFER_LEN];
+ uchar read_buffer[READ_BUFFER_LEN];
+
+ DEFiRet;
+
+ CHKiRet(msgConstruct(&pMsg));
+
+ msgAddMetadata(pMsg, (uchar*)"filename", (uchar*)filename);
+
+ /* get the file modification time : end of the batch*/
+ tvm.tv_sec = fstat->st_mtime;
+ tvm.tv_usec = 0;
+
+ file_len = lseek(pInst->fd, 0, SEEK_END);
+
+ MsgSetStructuredData(pMsg, "-");
+
+ /* Let's read the end of the file first and put it in the buffer for structuredData
+ * This will help to find the real end of the message
+ */
+ sd_buf_l = (file_len < SRUCTDATA_BUFFER_LEN) ? file_len : SRUCTDATA_BUFFER_LEN;
+
+ if (lseek(pInst->fd, file_len - sd_buf_l, SEEK_SET) >= 0) {
+ uchar *sdp = sd_buffer+sd_buf_l-1;
+ int nb_rm = 0; /* number of space chars removed */
+ size_t stdata_len = 0, t;
+ char *tmp;
+
+ if ((t=read(pInst->fd, sd_buffer, sd_buf_l)) != sd_buf_l) {
+ LogError(0, RS_RET_READ_ERR, "read end of file for structured data failed (%zu / %zu)",
+ t, sd_buf_l);
+ return RS_RET_READ_ERR;
+ }
+
+ /* let's trim the end */
+ for (; sdp > sd_buffer && (*sdp=='\n' || *sdp=='\t' || *sdp==' '); sdp--, sd_buf_l--)
+ file_len--;
+
+ if (sd_buf_l > 1 && *sdp == ']') {
+ stdata_len = 1;
+ /* it seems that we have structured data let find the begin */
+ for (; sdp > sd_buffer && *sdp!='['; sdp--, stdata_len++) {
+ if (*sdp == '\n') {
+ /* line feed not supported in structured data */
+ stdata_len--;
+ memmove(sdp, sdp+1, stdata_len);
+ nb_rm++;
+ }
+ }
+ if (*sdp == '[') {
+ /* we got a structured data */
+ DBGPRINTF("structured data : %.*s\n", (int)stdata_len, sdp);
+ MsgAddToStructuredData(pMsg, sdp, stdata_len);
+
+ /* extracting timestamp from structured data overwrite the file creation time */
+ if (pInst->pszTSk) {
+ uchar *field = (uchar*)strstr((char*)sdp, (char*)pInst->pszTSk), v;
+ if (field != NULL)
+ {
+ tvm.tv_sec = 0;
+ tvm.tv_usec = 0;
+ for (field += pInst->lenTSk; (v = *field ^ 0x30) <= 9; field++)
+ tvm.tv_sec = tvm.tv_sec*10 + v;
+ }
+ }
+
+ /* extracting program from structured data */
+ if (pInst->pszProgk) {
+ char *field = strstr((char*)sdp, (char*)pInst->pszProgk);
+ if (field != NULL)
+ {
+ tmp = field + pInst->lenProgk;
+ if ((field = strchr(tmp, '\"')) != NULL) {
+ *field = '\0';
+ MsgSetAPPNAME(pMsg, tmp);
+ }
+ }
+ }
+
+ /* let's trim until useful message end */
+ for (sdp--; sdp > sd_buffer && (*sdp=='\n' || *sdp=='\t' || *sdp==' '); sdp--)
+ nb_rm++;
+ }
+ }
+ /* computing the new file_len */
+ file_len -= nb_rm + stdata_len;
+ }
+
+ datetime.timeval2syslogTime(&tvm, &pMsg->tTIMESTAMP, TIME_IN_UTC);
+ pMsg->ttGenTime = tvm.tv_sec;
+
+ /* go back to beginning */
+ if (lseek(pInst->fd, 0, SEEK_SET) < 0) {
+ LogError(0, RS_RET_READ_ERR, "readAndSendFile : error while seeking to beginning.");
+ return RS_RET_READ_ERR;
+ }
+
+ /* Now read the file */
+ msg_len = 0;
+ while (msg_len < fixedModConf.max_msg_size && (read_len = read(pInst->fd, read_buffer,
+ (file_len > READ_BUFFER_LEN) ? READ_BUFFER_LEN : file_len)) > 0) {
+ file_len -= read_len;
+ idx = 0;
+ while (read_len > 0 && msg_len < fixedModConf.max_msg_size) {
+ switch (read_buffer[idx]){
+ case '\t':
+ case ' ':
+ /* this is to reduce consecutive spaces to only one */
+ if (!last_is_space)
+ fixedModConf.msg_buffer[msg_len++] = ' ';
+ /* if pInst->bDedupSpace is off last_is_space will never be true */
+ last_is_space = pInst->bDedupSpace;
+ break;
+ case '\n':
+ /* this is for trailing spaces */
+ if (last_is_space) msg_len--;
+ fixedModConf.msg_buffer[msg_len++] = '\\';
+ /* risk of overflow is managed by making buffer one char longer
+ * than fixedModConf.max_msg_size */
+ fixedModConf.msg_buffer[msg_len++] = 'n';
+ break;
+ default:
+ fixedModConf.msg_buffer[msg_len++] = read_buffer[idx];
+ last_is_space = 0;
+ }
+ idx++;
+ read_len--;
+ }
+ }
+
+ close(pInst->fd);
+ pInst->fd = 0;
+
+ if (file_len > 0 || read_len > 0) {
+ /* file is too large to be stored in one message */
+ memcpy(fixedModConf.msg_buffer, FILE_TOO_LARGE, FILE_TOO_LARGE_LEN);
+ msg_len = strlen(fpath);
+ memcpy(fixedModConf.msg_buffer + FILE_TOO_LARGE_LEN, fpath, msg_len);
+ msg_len += FILE_TOO_LARGE_LEN;
+ }
+
+ /* file is stored in the message */
+ MsgSetRawMsg(pMsg, fixedModConf.msg_buffer, msg_len);
+
+ MsgSetMSGoffs(pMsg, 0);
+ if ((iRet = enqMsg(pInst, pMsg)) == RS_RET_OK && (file_len > 0 || read_len > 0))
+ iRet = RS_RET_FILE_TOO_LARGE;
+
+finalize_it:
+ RETiRet;
+}
+
+/* poll a glob */
+static void pollFile(instanceConf_t *pInst)
+{
+ pInst->fd = 0;
+ glob_t glob_res;
+
+ pthread_cleanup_push(pollFileCancelCleanup, pInst);
+
+ DBGPRINTF("polling files : %s\n", pInst->pszFollow_glob);
+
+ /* We "glob" to find candidate regular file (or other) */
+ if (glob((char*)pInst->pszFollow_glob, GLOB_NOSORT, 0, &glob_res) != 0)
+ FINALIZE;
+
+ for (size_t i = 0; i < glob_res.gl_pathc && glbl.GetGlobalInputTermState() == 0; i++)
+ {
+ struct stat fstat;
+ rsRetVal ret;
+ char *filename = strrchr(glob_res.gl_pathv[i], '/');
+ if (filename)
+ filename++;
+ else
+ filename = glob_res.gl_pathv[i];
+ char *fpath = glob_res.gl_pathv[i];
+
+ /* let's verify that the file is a regular one */
+ if (!stat(fpath, &fstat) && S_ISREG(fstat.st_mode) )
+ {
+ regmatch_t matches[1];
+ int toolargeOrFailure = 0;
+
+ DBGPRINTF("Regular file found '%s')\n", fpath);
+
+ /* With this test we verify that we have conditions to remove the
+ * file from glob scope. If the regular expression not apply we
+ * can not rename it */
+ if (regexec(&pInst->ff_preg, fpath, 1, matches, 0)) {
+ pInst->must_stop = 1;
+ FINALIZE;
+ }
+
+ pInst->fd = open(fpath,
+ O_NOCTTY | O_RDONLY | O_NONBLOCK | O_LARGEFILE, 0);
+
+ if (pInst->fd <= 0)
+ {
+ /* file could be open unfortunately we will try each polling */
+ char errStr[512];
+ int eno = errno;
+ rs_strerror_r(eno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_READ_ERR,"open the file %s failed with error %s", fpath, errStr);
+ continue;
+ }
+
+ /* let's read the file and send it to output */
+ ret = readAndSendFile(pInst, filename, fpath, &fstat);
+ /* is the file to large to be sent */
+ toolargeOrFailure = ret == RS_RET_FILE_TOO_LARGE;
+
+ if (ret != RS_RET_OK && ret != RS_RET_FILE_TOO_LARGE) {
+ LogError(0, ret, "The module could not manage the file %s", fpath);
+ toolargeOrFailure = 1;
+ }
+
+ if (pInst->action == action_rename || toolargeOrFailure)
+ {
+ pInst->pszNewFName = (char*)malloc(strlen(fpath)+
+ pInst->filename_oversize);
+ memcpy(pInst->pszNewFName, fpath, matches[0].rm_so);
+ strcpy((char*)pInst->pszNewFName + matches[0].rm_so,
+ (toolargeOrFailure) ? pInst->ff_reject : pInst->ff_rename);
+
+ if (rename(fpath, pInst->pszNewFName))
+ {
+ /* if the module can not rename the file, it must stop to avoid flooding
+ * but it keep chance to manage max files as possible
+ */
+ LogError(0, RS_RET_STREAM_DISABLED, "module stopped : was unable"
+ " to rename form %s to %s.", fpath , pInst->pszNewFName);
+ pInst->must_stop = 1;
+ }
+ else
+ DBGPRINTF("file %s sent and renamed to %s.\n", fpath, pInst->pszNewFName);
+ free(pInst->pszNewFName);
+ pInst->pszNewFName = NULL;
+ }
+ else
+ {
+ if (unlink(fpath))
+ {
+ /* if the module can not remove the file, it must stop to avoid flooding
+ * but it keep chance to manage max files as possible
+ */
+ LogError(0, RS_RET_STREAM_DISABLED, "module stopped : unable to delete %s.",
+ fpath);
+ pInst->must_stop = 1;
+ }
+ else
+ DBGPRINTF("file %s sent and deleted\n", fpath);
+ }
+ } /* if stat */
+ } /* for */
+
+finalize_it:
+ globfree(&glob_res);
+
+ pthread_cleanup_pop(0);
+}
+
+static void addInstance(instanceConf_t *inst) {
+
+ if(fixedModConf.root == NULL) {
+ fixedModConf.root = inst;
+ } else {
+ fixedModConf.root->next = inst;
+ fixedModConf.root = inst;
+ }
+}
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ *pinst = NULL;
+
+ CHKmalloc(inst = (instanceConf_t*)malloc(sizeof(instanceConf_t)));
+
+ inst->next = NULL;
+ inst->pBindRuleset = NULL;
+
+ inst->pszBindRuleset = NULL;
+ inst->pszFollow_glob = NULL;
+ inst->pszDirName = NULL;
+ inst->pszFileBaseName = NULL;
+ inst->pszTag = NULL;
+ inst->pszTSk = NULL;
+ inst->pszProgk = NULL;
+ inst->ff_regex = NULL;
+ inst->ff_rename = NULL;
+ inst->ff_reject = NULL;
+
+ inst->iSeverity = LOG_NOTICE;
+ inst->iFacility = LOG_LOCAL0;
+ inst->len_rename = 0;
+ inst->len_reject = 0;
+ inst->bDedupSpace = 1;
+ inst->goon = 0;
+ inst->ratelimiter = NULL;
+
+ inst->action = action_nothing;
+
+ inst->must_stop = 0;
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* the basen(ame) buffer must be of size MAXFNAME
+ * returns the index of the slash in front of basename
+ */
+static int getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path)
+{
+ int i;
+ const int lenName = ustrlen(path);
+ for(i = lenName ; i >= 0 ; --i) {
+ if(path[i] == '/') {
+
+ if(i == lenName)
+ basen[0] = '\0';
+ else {
+ memcpy(basen, path+i+1, lenName-i);
+ }
+ break;
+ }
+ }
+ if (i == -1) {
+ memcpy(basen, path, lenName);
+ i = 0;
+ }
+ return i;
+}
+
+/* this function checks instance parameters and does some required pre-processing
+ * (e.g. split filename in path and actual name)
+ * Note: we do NOT use dirname()/basename() as they have portability problems.
+ */
+static rsRetVal checkInstance(instanceConf_t *inst)
+{
+ char dirn[MAXFNAME];
+ uchar basen[MAXFNAME];
+ int i;
+ struct stat sb;
+ int r;
+ int eno;
+ char errStr[512], *s, *d;
+ regmatch_t matches[1];
+ DEFiRet;
+
+ i = getBasename(basen, inst->pszFollow_glob);
+ memcpy(dirn, inst->pszFollow_glob, i);
+ dirn[i] = '\0';
+ CHKmalloc(inst->pszFileBaseName = (uchar*) strdup((char*)basen));
+ CHKmalloc(inst->pszDirName = (uchar*) strdup(dirn));
+
+ if(dirn[0] == '\0') {
+ dirn[0] = '.';
+ dirn[1] = '\0';
+ }
+ r = stat(dirn, &sb);
+ if(r != 0) {
+ eno = errno;
+ rs_strerror_r(eno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_CONFIG_ERROR, "Configured directory can not be stated '%s': %s",
+ dirn, errStr);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(!S_ISDIR(sb.st_mode)) {
+ LogError(0, RS_RET_CONFIG_ERROR, "Configured directory is NOT a directory : '%s'", dirn);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if (stat((char*)inst->pszFollow_glob, &sb) == 0 && !S_ISREG(sb.st_mode)) {
+ LogError(0, RS_RET_CONFIG_ERROR, "Configured report is not a glob or a regular file.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ for (s=(char*)inst->pszFollow_glob, d = dirn; *s; s++, d++)
+ *d = (*s != '*' && *s != '?') ? *s : '~';
+ *d = '\0';
+
+ if (regexec(&inst->ff_preg, dirn, 1, matches, 0)) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "Regex does not match globed filenames: Instance ignored to avoid loops.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if (inst->action == action_rename) {
+ strcpy(dirn + matches[0].rm_so, inst->ff_rename);
+ if (fnmatch((char*)inst->pszFollow_glob, dirn, FNM_PATHNAME) == 0)
+ {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "Normal renaming leaves files in glob scope: Instance ignored to avoid loops.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ }
+ strcpy(dirn + matches[0].rm_so, inst->ff_reject);
+ if (fnmatch((char*)inst->pszFollow_glob, dirn, FNM_PATHNAME) == 0)
+ {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "Reject renaming leaves files in glob scope: Instance ignored to avoid loops.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ dbgprintf("instance checked");
+
+finalize_it:
+ RETiRet;
+}
+
+static void freeInstance(instanceConf_t *inst) {
+ if (inst == NULL)
+ return;
+
+ if (inst->pszBindRuleset) free(inst->pszBindRuleset);
+ if (inst->pszFollow_glob) free(inst->pszFollow_glob);
+ if (inst->pszDirName) free(inst->pszDirName);
+ if (inst->pszFileBaseName) free(inst->pszFileBaseName);
+ if (inst->pszTag) free(inst->pszTag);
+ if (inst->pszTSk) free(inst->pszTSk);
+ if (inst->pszProgk) free(inst->pszProgk);
+
+ if (inst->len_reject) regfree(&inst->ff_preg);
+
+ if (inst->ff_regex) free(inst->ff_regex);
+ if (inst->ff_rename) free(inst->ff_rename);
+ if (inst->ff_reject) free(inst->ff_reject);
+
+ if (inst->ratelimiter) ratelimitDestruct(inst->ratelimiter);
+ free(inst);
+}
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst = NULL;
+ int i;
+ char *temp;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imbatchreport)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ DBGPRINTF("input param blk in imbatchreport:\n");
+ if(Debug) cnfparamsPrint(&inppblk, pvals);
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "reports")) {
+ inst->pszFollow_glob = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tag")) {
+ inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ inst->lenTag = ustrlen(inst->pszTag);
+ } else if(!strcmp(inppblk.descr[i].name, "programkey")) {
+ inst->pszProgk = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ inst->lenProgk = ustrlen(inst->pszProgk) + 2;
+ } else if(!strcmp(inppblk.descr[i].name, "timestampkey")) {
+ inst->pszTSk = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ inst->lenTSk = ustrlen(inst->pszTSk) + 1;
+ } else if(!strcmp(inppblk.descr[i].name, "deduplicatespace")) {
+ inst->bDedupSpace = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "severity")) {
+ inst->iSeverity = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "facility")) {
+ inst->iFacility = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "rename")) {
+ if (inst->action == action_delete)
+ {
+ LogError(0, RS_RET_PARAM_ERROR, "'rename' and 'delete' are exclusive !");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+
+ inst->ff_regex = es_str2cstr(pvals[i].val.d.estr, NULL);
+
+ while ((temp = strchr(inst->ff_regex, '\t')) != NULL)
+ *temp = ' ';
+
+ inst->len_reject = 0;
+
+ if ((inst->ff_rename = strchr(inst->ff_regex, ' ')) != NULL ) {
+ *inst->ff_rename++ = '\0';
+
+ while (*inst->ff_rename == ' ') inst->ff_rename++;
+ if ((inst->ff_reject = strchr(inst->ff_rename, ' ')) != NULL ) {
+
+ *inst->ff_reject++ = '\0';
+ while (*inst->ff_reject == ' ') inst->ff_reject++;
+
+ temp = strchr(inst->ff_reject, ' ');
+ if (temp) *temp = '\0';
+
+ if (strcmp(inst->ff_rename, "-")){
+ inst->ff_rename = strdup(inst->ff_rename);
+ inst->len_rename = strlen(inst->ff_rename);
+ }else{
+ inst->ff_rename = strdup("");
+ inst->len_rename = 0;
+ }
+
+ inst->ff_reject = strdup(inst->ff_reject);
+ inst->len_reject = strlen(inst->ff_reject);
+
+ if (inst->len_reject && regcomp(&inst->ff_preg,
+ (char*)inst->ff_regex,
+ REG_EXTENDED))
+ {
+ inst->len_reject = 0;
+ LogError(0, RS_RET_SYNTAX_ERROR, "The first part of 'rename' "
+ "parameter does not contain a valid regex");
+ ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
+ }
+ }
+ }
+ if (inst->len_reject == 0)
+ {
+ LogError(0, RS_RET_PARAM_ERROR, "'rename' must specify THREE "
+ "parameters separated by spaces or tabs ! The second "
+ "parameter can be a null string to get this use a '-'.");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+
+ inst->action = action_rename;
+
+ } else if(!strcmp(inppblk.descr[i].name, "delete")) {
+ if (inst->action == action_rename)
+ {
+ LogError(0, RS_RET_PARAM_ERROR, "'rename' and 'delete' are exclusive !");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+
+ inst->ff_regex = es_str2cstr(pvals[i].val.d.estr, NULL);
+
+ while ((temp = strchr(inst->ff_regex, '\t')) != NULL)
+ *temp = ' ';
+
+ inst->len_reject = 0;
+
+ if ((inst->ff_reject = strchr(inst->ff_regex, ' ')) != NULL ) {
+ *inst->ff_reject++ = '\0';
+
+ while (*inst->ff_reject == ' ') inst->ff_reject++;
+
+ temp = strchr(inst->ff_reject, ' ');
+ if (temp) *temp = '\0';
+
+ inst->ff_reject = strdup(inst->ff_reject);
+ inst->len_reject = strlen(inst->ff_reject);
+
+ if (regcomp(&inst->ff_preg, (char*)inst->ff_regex, REG_EXTENDED))
+ {
+ inst->len_reject = 0;
+ LogError(0, RS_RET_SYNTAX_ERROR,
+ "The first part of 'delete' parameter does not contain a valid regex");
+ ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
+ }
+
+ }
+
+ if (inst->len_reject == 0)
+ {
+ LogError(0, RS_RET_PARAM_ERROR,
+ "'delete' must specify TWO parameters separated by spaces or tabs !");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ inst->action = action_delete;
+
+ } else {
+ dbgprintf("Configuration param '%s' non-handled\n", inppblk.descr[i].name);
+ }
+ }
+
+ if(inst->action == action_nothing) {
+ LogError(0, RS_RET_PARAM_NOT_PERMITTED, "either 'rename' or 'delete' must be set");
+ ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED);
+ }
+
+ inst->filename_oversize = (inst->len_rename > inst->len_reject) ? inst->len_rename : inst->len_reject;
+
+ CHKiRet(ratelimitNew(&inst->ratelimiter, "imbatchreport", (char*)inst->pszFollow_glob));
+
+ inst->goon = 1;
+
+ CHKiRet(checkInstance(inst));
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+
+ if (iRet == RS_RET_OK)
+ addInstance(inst);
+ else
+ freeInstance(inst);
+
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ pModConf->pConf = pConf;
+ fixedModConf.iPollInterval = DFLT_PollInterval;
+
+ fixedModConf.msg_buffer = NULL;
+ fixedModConf.root = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imbatchreport:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "pollinginterval")) {
+ fixedModConf.iPollInterval = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ dbgprintf("polling interval is %d\n",
+ fixedModConf.iPollInterval);
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = fixedModConf.root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ if(fixedModConf.root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS,
+ "no files configured to be monitored - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = fixedModConf.root ; inst != NULL ; ) {
+ del = inst;
+ inst = inst->next;
+ freeInstance(del);
+ }
+ENDfreeCnf
+
+BEGINwillRun
+CODESTARTwillRun
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imbatchreport"),
+ sizeof("imbatchreport") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ fixedModConf.max_msg_size = glbl.GetMaxLine(runConf);
+ DBGPRINTF("Max message len %zu\n", fixedModConf.max_msg_size);
+ CHKmalloc(fixedModConf.msg_buffer = (char*)malloc(fixedModConf.max_msg_size + 1));
+finalize_it:
+ENDwillRun
+
+BEGINrunInput
+CODESTARTrunInput
+ fixedModConf.hostname = glbl.GetLocalHostName();
+ fixedModConf.lhostname = ustrlen(fixedModConf.hostname);
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ instanceConf_t *pInst;
+ for(pInst = fixedModConf.root ; pInst != NULL ; pInst = pInst->next) {
+ if (pInst->goon) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ break;
+ pollFile(pInst);
+ /* We got a major problem so */
+ pInst->goon = !pInst->must_stop;
+ }
+ }
+
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(fixedModConf.iPollInterval, 10);
+ }
+ DBGPRINTF("terminating upon request of rsyslog core\n");
+ RETiRet;
+ENDrunInput
+
+/* This function is called by the framework after runInput() has been terminated. It
+ * shall free any resources and prepare the module for unload.
+ */
+BEGINafterRun
+CODESTARTafterRun
+ if (fixedModConf.msg_buffer)
+ free(fixedModConf.msg_buffer);
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* The following entry points are defined in module-template.h.
+ * In general, they need to be present, but you do NOT need to provide
+ * any code here.
+ */
+BEGINmodExit
+CODESTARTmodExit
+
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* modInit() is called once the module is loaded. It must perform all module-wide
+ * initialization tasks. There are also a number of housekeeping tasks that the
+ * framework requires. These are handled by the macros. Please note that the
+ * complexity of processing is depending on the actual module. However, only
+ * thing absolutely necessary should be done here. Actual app-level processing
+ * is to be performed in runInput(). A good sample of what to do here may be to
+ * set some variable defaults.
+ */
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ENDmodInit
+
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf,
+ instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "ruleset '%s' for %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszFollow_glob);
+}
diff --git a/contrib/imczmq/Makefile.am b/contrib/imczmq/Makefile.am
new file mode 100644
index 0000000..9bf7adb
--- /dev/null
+++ b/contrib/imczmq/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = imczmq.la
+
+imczmq_la_SOURCES = imczmq.c
+imczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS)
+imczmq_la_LDFLAGS = -module -avoid-version
+imczmq_la_LIBADD = $(CZMQ_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/imczmq/Makefile.in b/contrib/imczmq/Makefile.in
new file mode 100644
index 0000000..9782e4b
--- /dev/null
+++ b/contrib/imczmq/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imczmq
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imczmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imczmq_la_OBJECTS = imczmq_la-imczmq.lo
+imczmq_la_OBJECTS = $(am_imczmq_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 =
+imczmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imczmq_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imczmq_la-imczmq.Plo
+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 = $(imczmq_la_SOURCES)
+DIST_SOURCES = $(imczmq_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imczmq.la
+imczmq_la_SOURCES = imczmq.c
+imczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS)
+imczmq_la_LDFLAGS = -module -avoid-version
+imczmq_la_LIBADD = $(CZMQ_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/imczmq/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imczmq/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imczmq.la: $(imczmq_la_OBJECTS) $(imczmq_la_DEPENDENCIES) $(EXTRA_imczmq_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imczmq_la_LINK) -rpath $(pkglibdir) $(imczmq_la_OBJECTS) $(imczmq_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imczmq_la-imczmq.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imczmq_la-imczmq.lo: imczmq.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imczmq_la-imczmq.lo -MD -MP -MF $(DEPDIR)/imczmq_la-imczmq.Tpo -c -o imczmq_la-imczmq.lo `test -f 'imczmq.c' || echo '$(srcdir)/'`imczmq.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imczmq_la-imczmq.Tpo $(DEPDIR)/imczmq_la-imczmq.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imczmq.c' object='imczmq_la-imczmq.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) $(imczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imczmq_la-imczmq.lo `test -f 'imczmq.c' || echo '$(srcdir)/'`imczmq.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imczmq_la-imczmq.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imczmq_la-imczmq.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imczmq/README b/contrib/imczmq/README
new file mode 100644
index 0000000..369a82a
--- /dev/null
+++ b/contrib/imczmq/README
@@ -0,0 +1,39 @@
+CZMQ Input Plugin
+
+REQUIREMENTS:
+
+* libsodium ( https://github.com/jedisct1/libsodium )
+* zeromq v4.x build with libsodium support ( http://zeromq.org/ )
+* czmq 3.x ( http://czmq.zeromq.org/ )
+
+-------------------------------------------------------------------------------
+module(
+ load="imczmq"
+ servercertpath="/etc/curve.d/server"
+ clientcertpath="/etc/curve.d/"
+ authtype="CURVESERVER"
+ authenticator="on"
+)
+
+input(
+ type="imczmq"
+ endpoints="@tcp://*:24555"
+ socktype="PULL"
+)
+-------------------------------------------------------------------------------
+
+Explanation of Options:
+
+Module
+------
+servercertpath: path to server cert if using CURVE
+clientcertpath: path to client cert(s) if using CURVE
+authtype: CURVESERVER, CURVECLIENT (omit for no auth)
+authenticator: whether to start an authenticator thread
+
+Action
+------
+type: type of action (imczmq for this plugin)
+endpoints: comma delimited list of zeromq endpoints (see zeromq documentation)
+socktype: zeromq socket type (currently supports PULL, SUB, ROUTER, DISH, SERVER)
+authtype: CURVECLIENT or CURVESERVER
diff --git a/contrib/imczmq/imczmq.c b/contrib/imczmq/imczmq.c
new file mode 100644
index 0000000..77674d4
--- /dev/null
+++ b/contrib/imczmq/imczmq.c
@@ -0,0 +1,632 @@
+/* imczmq.c
+ * Copyright (C) 2016 Brian Knox
+ * Copyright (C) 2014 Rainer Gerhards
+ *
+ * Author: Brian Knox <bknox@digitalocean.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "rsyslog.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "cfsysline.h"
+#include "dirty.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "module-template.h"
+#include "msg.h"
+#include "net.h"
+#include "parser.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "srUtils.h"
+#include "unicode-helper.h"
+#include <czmq.h>
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imczmq");
+
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+static struct cnfparamdescr modpdescr[] = {
+ { "authenticator", eCmdHdlrBinary, 0 },
+ { "authtype", eCmdHdlrString, 0 },
+ { "servercertpath", eCmdHdlrString, 0 },
+ { "clientcertpath", eCmdHdlrString, 0 },
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+struct modConfData_s {
+ rsconf_t *pConf;
+ instanceConf_t *root;
+ instanceConf_t *tail;
+ int authenticator;
+ char *authType;
+ char *serverCertPath;
+ char *clientCertPath;
+};
+
+struct instanceConf_s {
+ bool serverish;
+ int sockType;
+ char *sockEndpoints;
+ char *topics;
+ uchar *pszBindRuleset;
+ ruleset_t *pBindRuleset;
+ struct instanceConf_s *next;
+};
+
+struct listener_t {
+ zsock_t *sock;
+ ruleset_t *ruleset;
+};
+
+static zlist_t *listenerList;
+static modConfData_t *runModConf = NULL;
+static prop_t *s_namep = NULL;
+
+static struct cnfparamdescr inppdescr[] = {
+ { "endpoints", eCmdHdlrGetWord, 1 },
+ { "socktype", eCmdHdlrGetWord, 1 },
+ { "ruleset", eCmdHdlrGetWord, 0 },
+ { "topics", eCmdHdlrGetWord, 0 },
+};
+
+#include "im-helper.h"
+
+static struct cnfparamblk inppblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(inppdescr) / sizeof(struct cnfparamdescr),
+ inppdescr
+};
+
+static void setDefaults(instanceConf_t* iconf) {
+ iconf->serverish = true;
+ iconf->sockType = -1;
+ iconf->sockEndpoints = NULL;
+ iconf->topics = NULL;
+ iconf->pszBindRuleset = NULL;
+ iconf->pBindRuleset = NULL;
+ iconf->next = NULL;
+};
+
+static rsRetVal createInstance(instanceConf_t** pinst) {
+ DEFiRet;
+ instanceConf_t* inst;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+
+ setDefaults(inst);
+
+ if(runModConf->root == NULL || runModConf->tail == NULL) {
+ runModConf->tail = runModConf->root = inst;
+ }
+ else {
+ runModConf->tail->next = inst;
+ runModConf->tail = inst;
+ }
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal addListener(instanceConf_t* iconf){
+ DEFiRet;
+
+ DBGPRINTF("imczmq: addListener called..\n");
+ struct listener_t* pData = NULL;
+ CHKmalloc(pData=(struct listener_t*)malloc(sizeof(struct listener_t)));
+ pData->ruleset = iconf->pBindRuleset;
+
+ pData->sock = zsock_new(iconf->sockType);
+ if(!pData->sock) {
+ LogError(0, RS_RET_NO_ERRCODE,
+ "imczmq: new socket failed for endpoints: %s",
+ iconf->sockEndpoints);
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+
+ DBGPRINTF("imczmq: created socket of type %d..\n", iconf->sockType);
+
+ if(runModConf->authType) {
+ if(!strcmp(runModConf->authType, "CURVESERVER")) {
+ DBGPRINTF("imczmq: we are a CURVESERVER\n");
+ zcert_t *serverCert = zcert_load(runModConf->serverCertPath);
+ if(!serverCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->serverCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ zsock_set_zap_domain(pData->sock, "global");
+ zsock_set_curve_server(pData->sock, 1);
+ zcert_apply(serverCert, pData->sock);
+ zcert_destroy(&serverCert);
+ }
+ else if(!strcmp(runModConf->authType, "CURVECLIENT")) {
+ DBGPRINTF("imczmq: we are a CURVECLIENT\n");
+ zcert_t *serverCert = zcert_load(runModConf->serverCertPath);
+ if(!serverCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->serverCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ const char *server_key = zcert_public_txt(serverCert);
+ zcert_destroy(&serverCert);
+ zsock_set_curve_serverkey(pData->sock, server_key);
+
+ zcert_t *clientCert = zcert_load(runModConf->clientCertPath);
+ if(!clientCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->clientCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ zcert_apply(clientCert, pData->sock);
+ zcert_destroy(&clientCert);
+ }
+
+ }
+
+ switch(iconf->sockType) {
+ case ZMQ_SUB:
+#if defined(ZMQ_DISH)
+ case ZMQ_DISH:
+#endif
+ iconf->serverish = false;
+ break;
+ case ZMQ_PULL:
+#if defined(ZMQ_GATHER)
+ case ZMQ_GATHER:
+#endif
+ case ZMQ_ROUTER:
+#if defined(ZMQ_SERVER)
+ case ZMQ_SERVER:
+#endif
+ iconf->serverish = true;
+ break;
+ }
+
+ if(iconf->topics) {
+ // A zero-length topic means subscribe to everything
+ if(!*iconf->topics && iconf->sockType == ZMQ_SUB) {
+ DBGPRINTF("imczmq: subscribing to all topics\n");
+ zsock_set_subscribe(pData->sock, "");
+ }
+
+ char topic[256];
+ while(*iconf->topics) {
+ char *delimiter = strchr(iconf->topics, ',');
+ if(!delimiter) {
+ delimiter = iconf->topics + strlen(iconf->topics);
+ }
+ memcpy (topic, iconf->topics, delimiter - iconf->topics);
+ topic[delimiter-iconf->topics] = 0;
+ DBGPRINTF("imczmq: subscribing to %s\n", topic);
+ if(iconf->sockType == ZMQ_SUB) {
+ zsock_set_subscribe (pData->sock, topic);
+ }
+#if defined(ZMQ_DISH)
+ else if(iconf->sockType == ZMQ_DISH) {
+ int rc = zsock_join (pData->sock, topic);
+ if(rc != 0) {
+ LogError(0, NO_ERRCODE, "could not join group %s", topic);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+#endif
+ if(*delimiter == 0) {
+ break;
+ }
+ iconf->topics = delimiter + 1;
+ }
+ }
+
+ int rc = zsock_attach(pData->sock, (const char*)iconf->sockEndpoints,
+ iconf->serverish);
+ if (rc == -1) {
+ LogError(0, NO_ERRCODE, "zsock_attach to %s failed",
+ iconf->sockEndpoints);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ DBGPRINTF("imczmq: attached socket to %s\n", iconf->sockEndpoints);
+
+ rc = zlist_append(listenerList, (void *)pData);
+ if(rc != 0) {
+ LogError(0, NO_ERRCODE, "could not append listener");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(pData);
+ }
+ RETiRet;
+}
+
+static rsRetVal rcvData(void){
+ DEFiRet;
+
+ if(!listenerList) {
+ listenerList = zlist_new();
+ if(!listenerList) {
+ LogError(0, NO_ERRCODE, "could not allocate list");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ zactor_t *authActor = NULL;
+
+ if(runModConf->authenticator == 1) {
+ authActor = zactor_new(zauth, NULL);
+ zstr_sendx(authActor, "CURVE", runModConf->clientCertPath, NULL);
+ zsock_wait(authActor);
+ }
+
+ instanceConf_t *inst;
+ for(inst = runModConf->root; inst != NULL; inst=inst->next) {
+ CHKiRet(addListener(inst));
+ }
+
+ zpoller_t *poller = zpoller_new(NULL);
+ if(!poller) {
+ LogError(0, NO_ERRCODE, "could not create poller");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ DBGPRINTF("imczmq: created poller\n");
+
+ struct listener_t *pData;
+
+ pData = zlist_first(listenerList);
+ if(!pData) {
+ LogError(0, NO_ERRCODE, "imczmq: no listeners were "
+ "started, input not activated.\n");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ while(pData) {
+ int rc = zpoller_add(poller, pData->sock);
+ if(rc != 0) {
+ LogError(0, NO_ERRCODE, "imczmq: could not add "
+ "socket to poller, input not activated.\n");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+ pData = zlist_next(listenerList);
+ }
+
+ zsock_t *which = (zsock_t *)zpoller_wait(poller, -1);
+ while(which) {
+ if (zpoller_terminated(poller)) {
+ break;
+ }
+ pData = zlist_first(listenerList);
+ while(pData->sock != which) {
+ pData = zlist_next(listenerList);
+ }
+
+ if(which == pData->sock) {
+ DBGPRINTF("imczmq: found matching socket\n");
+ }
+
+ zframe_t *frame = zframe_recv(which);
+ char *buf = NULL;
+
+ if (frame != NULL)
+ buf = zframe_strdup(frame);
+
+ zframe_destroy(&frame);
+
+ if(buf == NULL) {
+ DBGPRINTF("imczmq: null buffer\n");
+ continue;
+ }
+ smsg_t *pMsg;
+ if(msgConstruct(&pMsg) == RS_RET_OK) {
+ MsgSetRawMsg(pMsg, buf, strlen(buf));
+ MsgSetInputName(pMsg, s_namep);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
+ MsgSetMSGoffs(pMsg, 0);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ MsgSetRuleset(pMsg, pData->ruleset);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ submitMsg2(pMsg);
+ }
+
+ free(buf);
+ which = (zsock_t *)zpoller_wait(poller, -1);
+ }
+finalize_it:
+ zpoller_destroy(&poller);
+ pData = zlist_first(listenerList);
+ while(pData) {
+ zsock_destroy(&pData->sock);
+ free(pData->ruleset);
+ pData = zlist_next(listenerList);
+ }
+ zlist_destroy(&listenerList);
+ zactor_destroy(&authActor);
+ RETiRet;
+}
+
+BEGINrunInput
+CODESTARTrunInput
+ iRet = rcvData();
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ CHKiRet(prop.Construct(&s_namep));
+ CHKiRet(prop.SetString(s_namep,
+ UCHAR_CONSTANT("imczmq"),
+ sizeof("imczmq") - 1));
+
+ CHKiRet(prop.ConstructFinalize(s_namep));
+
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ if(s_namep != NULL) {
+ prop.Destruct(&s_namep);
+ }
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination) {
+ iRet = RS_RET_OK;
+ }
+ENDisCompatibleWithFeature
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ runModConf = pModConf;
+ runModConf->pConf = pConf;
+ runModConf->authenticator = 0;
+ runModConf->authType = NULL;
+ runModConf->serverCertPath = NULL;
+ runModConf->clientCertPath = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals* pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(NULL == pvals) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imczmq: error processing module "
+ "config parameters ['module(...)']");
+
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ for(i=0; i < modpblk.nParams; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+ if(!strcmp(modpblk.descr[i].name, "authenticator")) {
+ runModConf->authenticator = (int)pvals[i].val.d.n;
+ }
+ else if(!strcmp(modpblk.descr[i].name, "authtype")) {
+ runModConf->authType = es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if(!strcmp(modpblk.descr[i].name, "servercertpath")) {
+ runModConf->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if(!strcmp(modpblk.descr[i].name, "clientcertpath")) {
+ runModConf->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "imczmq: config error, unknown "
+ "param %s in setModCnf\n",
+ modpblk.descr[i].name);
+ }
+ }
+
+ DBGPRINTF("imczmq: authenticator set to %d\n", runModConf->authenticator);
+ DBGPRINTF("imczmq: authType set to %s\n", runModConf->authType);
+ DBGPRINTF("imczmq: serverCertPath set to %s\n", runModConf->serverCertPath);
+ DBGPRINTF("imczmq: clientCertPath set to %s\n", runModConf->clientCertPath);
+
+finalize_it:
+ if(pvals != NULL) {
+ cnfparamvalsDestruct(pvals, &modpblk);
+ }
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE,
+ "imczmq: ruleset '%s' for socket %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->sockEndpoints);
+}
+
+
+BEGINcheckCnf
+instanceConf_t* inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root; inst!=NULL; inst=inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ putenv((char*)"ZSYS_SIGHANDLER=false");
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *inst_r;
+CODESTARTfreeCnf
+ free(pModConf->authType);
+ free(pModConf->serverCertPath);
+ free(pModConf->clientCertPath);
+ for (inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindRuleset);
+ free(inst->sockEndpoints);
+ inst_r = inst;
+ inst = inst->next;
+ free(inst_r);
+ }
+
+ENDfreeCnf
+
+
+BEGINnewInpInst
+ struct cnfparamvals* pvals;
+ instanceConf_t* inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imczmq)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(NULL==pvals) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imczmq: required parameters are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("imczmq: input param blk:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+
+ if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if(!strcmp(inppblk.descr[i].name, "endpoints")) {
+ inst->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if(!strcmp(inppblk.descr[i].name, "topics")) {
+ inst->topics = es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if(!strcmp(inppblk.descr[i].name, "socktype")){
+ char *stringType = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if( NULL == stringType ){
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "imczmq: out of memory error copying sockType param");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ if(!strcmp("PULL", stringType)) {
+ inst->sockType = ZMQ_PULL;
+ }
+#if defined(ZMQ_GATHER)
+ else if(!strcmp("GATHER", stringType)) {
+ inst->sockType = ZMQ_GATHER;
+ }
+#endif
+ else if(!strcmp("SUB", stringType)) {
+ inst->sockType = ZMQ_SUB;
+ }
+#if defined(ZMQ_DISH)
+ else if(!strcmp("DISH", stringType)) {
+ inst->sockType = ZMQ_DISH;
+ }
+#endif
+ else if(!strcmp("ROUTER", stringType)) {
+ inst->sockType = ZMQ_ROUTER;
+ }
+#if defined(ZMQ_SERVER)
+ else if(!strcmp("SERVER", stringType)) {
+ inst->sockType = ZMQ_SERVER;
+ }
+#endif
+ free(stringType);
+
+ }
+ else {
+ LogError(0, NO_ERRCODE,
+ "imczmq: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ENDmodInit
+
diff --git a/contrib/imdocker/Makefile.am b/contrib/imdocker/Makefile.am
new file mode 100644
index 0000000..68c516e
--- /dev/null
+++ b/contrib/imdocker/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imdocker.la
+
+imdocker_la_SOURCES = imdocker.c
+imdocker_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+imdocker_la_LDFLAGS = -module -avoid-version
+imdocker_la_LIBADD = $(CURL_LIBS)
diff --git a/contrib/imdocker/Makefile.in b/contrib/imdocker/Makefile.in
new file mode 100644
index 0000000..2421da3
--- /dev/null
+++ b/contrib/imdocker/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imdocker
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imdocker_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imdocker_la_OBJECTS = imdocker_la-imdocker.lo
+imdocker_la_OBJECTS = $(am_imdocker_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 =
+imdocker_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imdocker_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imdocker_la-imdocker.Plo
+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 = $(imdocker_la_SOURCES)
+DIST_SOURCES = $(imdocker_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imdocker.la
+imdocker_la_SOURCES = imdocker.c
+imdocker_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+imdocker_la_LDFLAGS = -module -avoid-version
+imdocker_la_LIBADD = $(CURL_LIBS)
+all: 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) --gnu contrib/imdocker/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imdocker/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imdocker.la: $(imdocker_la_OBJECTS) $(imdocker_la_DEPENDENCIES) $(EXTRA_imdocker_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imdocker_la_LINK) -rpath $(pkglibdir) $(imdocker_la_OBJECTS) $(imdocker_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imdocker_la-imdocker.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imdocker_la-imdocker.lo: imdocker.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imdocker_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imdocker_la-imdocker.lo -MD -MP -MF $(DEPDIR)/imdocker_la-imdocker.Tpo -c -o imdocker_la-imdocker.lo `test -f 'imdocker.c' || echo '$(srcdir)/'`imdocker.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imdocker_la-imdocker.Tpo $(DEPDIR)/imdocker_la-imdocker.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imdocker.c' object='imdocker_la-imdocker.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) $(imdocker_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imdocker_la-imdocker.lo `test -f 'imdocker.c' || echo '$(srcdir)/'`imdocker.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imdocker_la-imdocker.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imdocker_la-imdocker.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imdocker/imdocker.c b/contrib/imdocker/imdocker.c
new file mode 100644
index 0000000..d7445ea
--- /dev/null
+++ b/contrib/imdocker/imdocker.c
@@ -0,0 +1,1794 @@
+/* imdocker.c
+ * This is an implementation of the docker container log input module. It uses the
+ * Docker API in order to stream all container logs available on a host. Will also
+ * update relevant container metadata.
+ *
+ * Copyright (C) 2018, 2019 the rsyslog project.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __sun
+#define _XPG4_2
+#endif
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <curl/curl.h>
+#include <json.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdbool.h>
+#include "cfsysline.h" /* access to config file objects */
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "srUtils.h" /* some utility functions */
+#include "errmsg.h"
+#include "net.h"
+#include "glbl.h"
+#include "msg.h"
+#include "parser.h"
+#include "prop.h"
+#include "debug.h"
+#include "statsobj.h"
+#include "datetime.h"
+#include "ratelimit.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#if !defined(_AIX)
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#endif
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imdocker")
+
+extern int Debug;
+
+#define USE_MULTI_LINE
+#undef ENABLE_DEBUG_BYTE_BUFFER
+
+/* defines */
+#define DOCKER_TAG_NAME "docker:"
+
+#define DOCKER_CONTAINER_ID_PARSE_NAME "Id"
+#define DOCKER_CONTAINER_NAMES_PARSE_NAME "Names"
+#define DOCKER_CONTAINER_IMAGEID_PARSE_NAME "ImageID"
+#define DOCKER_CONTAINER_CREATED_PARSE_NAME "Created"
+#define DOCKER_CONTAINER_LABELS_PARSE_NAME "Labels"
+
+/* label defines */
+#define DOCKER_CONTAINER_LABEL_KEY_STARTREGEX "imdocker.startregex"
+
+/* DEFAULT VALUES */
+#define DFLT_pollingInterval 60 /* polling interval in seconds */
+#define DFLT_retrieveNewLogsFromStart 1/* Process newly found containers logs from start */
+#define DFLT_containersLimit 25 /* maximum number of containers */
+#define DFLT_trimLineOverBytes 4194304 /* limit log lines to the value - 4MB default */
+#define DFLT_bEscapeLF 1 /* whether line feeds should be escaped */
+
+#define DFLT_SEVERITY pri2sev(LOG_INFO)
+#define DFLT_FACILITY pri2fac(LOG_USER)
+
+enum {
+ dst_invalid = -1,
+ dst_stdin,
+ dst_stdout,
+ dst_stderr,
+ dst_stream_type_count
+} docker_stream_type_t;
+
+/* imdocker specific structs */
+typedef struct imdocker_buf_s {
+ uchar *data;
+ size_t len;
+ size_t data_size;
+} imdocker_buf_t;
+
+typedef struct docker_cont_logs_buf_s {
+ imdocker_buf_t *buf;
+ int8_t stream_type;
+ size_t bytes_remaining;
+} docker_cont_logs_buf_t;
+
+struct docker_cont_logs_inst_s;
+typedef rsRetVal (*submitmsg_funcptr) (struct docker_cont_logs_inst_s *pInst, docker_cont_logs_buf_t *pBufdata,
+ const uchar* pszTag);
+typedef submitmsg_funcptr SubmitMsgFuncPtr;
+
+/* curl request instance */
+typedef struct docker_cont_logs_req_s {
+ CURL *curl;
+ docker_cont_logs_buf_t* data_bufs[dst_stream_type_count];
+ SubmitMsgFuncPtr submitMsg;
+} docker_cont_logs_req_t;
+
+typedef struct imdocker_req_s {
+ CURL *curl;
+ imdocker_buf_t *buf;
+} imdocker_req_t;
+
+typedef struct docker_container_info_s {
+ uchar *name;
+ uchar *image_id;
+ uint64_t created;
+ /* json string container labels */
+ uchar *json_str_labels;
+} docker_container_info_t;
+
+typedef struct docker_cont_logs_inst_s {
+ char *id;
+ char short_id[12];
+ docker_container_info_t *container_info;
+ docker_cont_logs_req_t *logsReq;
+ uchar *start_regex;
+ regex_t start_preg; /* compiled version of start_regex */
+ uint32_t prevSegEnd;
+} docker_cont_logs_inst_t;
+
+typedef struct docker_cont_log_instances_s {
+ struct hashtable* ht_container_log_insts;
+ pthread_mutex_t mut;
+ CURLM *curlm;
+ /* track the latest created container */
+ uint64_t last_container_created;
+ uchar *last_container_id;
+ time_t time_started;
+} docker_cont_log_instances_t;
+
+/* FORWARD DEFINITIONS */
+
+/* imdocker_buf_t */
+static rsRetVal imdockerBufNew(imdocker_buf_t **ppThis);
+static void imdockerBufDestruct(imdocker_buf_t *pThis);
+
+/* docker_cont_logs_buf_t */
+static rsRetVal dockerContLogsBufNew(docker_cont_logs_buf_t **ppThis);
+static void dockerContLogsBufDestruct(docker_cont_logs_buf_t *pThis);
+static rsRetVal dockerContLogsBufWrite(docker_cont_logs_buf_t *pThis, const uchar *pdata,
+ size_t write_size);
+
+/* imdocker_req_t */
+static rsRetVal imdockerReqNew(imdocker_req_t **ppThis);
+static void imdockerReqDestruct(imdocker_req_t *pThis);
+
+/* docker_cont_logs_req_t */
+static rsRetVal dockerContLogsReqNew(docker_cont_logs_req_t **ppThis, SubmitMsgFuncPtr submitMsg);
+static void dockerContLogsReqDestruct(docker_cont_logs_req_t *pThis);
+
+/* docker_cont_logs_inst_t */
+static rsRetVal
+dockerContLogsInstNew(docker_cont_logs_inst_t **ppThis, const char* id,
+ docker_container_info_t *container_info, SubmitMsgFuncPtr submitMsg);
+
+static void dockerContLogsInstDestruct(docker_cont_logs_inst_t *pThis);
+static rsRetVal dockerContLogsInstSetUrlById (sbool isInit, docker_cont_logs_inst_t *pThis,
+ CURLM *curlm, const char* containerId);
+
+/* docker_cont_log_instances_t */
+static rsRetVal dockerContLogReqsNew(docker_cont_log_instances_t **ppThis);
+static rsRetVal dockerContLogReqsDestruct(docker_cont_log_instances_t *pThis);
+static rsRetVal dockerContLogReqsGet(docker_cont_log_instances_t *pThis,
+ docker_cont_logs_inst_t** ppContLogsInst, const char *id);
+static rsRetVal dockerContLogReqsPrint(docker_cont_log_instances_t *pThis);
+static rsRetVal dockerContLogReqsAdd(docker_cont_log_instances_t *pThis,
+ docker_cont_logs_inst_t *pContLogsReqInst);
+static rsRetVal dockerContLogReqsRemove(docker_cont_log_instances_t *pThis, const char *id);
+
+/* docker_container_info_t */
+static rsRetVal dockerContainerInfoNew(docker_container_info_t **pThis);
+static void dockerContainerInfoDestruct(docker_container_info_t *pThis);
+
+/* utility functions */
+static CURLcode docker_get(imdocker_req_t *req, const char* url);
+static char* dupDockerContainerName(const char* pname);
+static rsRetVal SubmitMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData,
+ const uchar* pszTag);
+/* support multi-line */
+static rsRetVal
+SubmitMsg2(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag);
+static size_t imdocker_container_list_curlCB(void *data, size_t size, size_t nmemb, void *buffer);
+static size_t imdocker_container_logs_curlCB(void *data, size_t size, size_t nmemb, void *buffer);
+static sbool get_stream_info(const uchar* data, size_t size, int8_t *stream_type, size_t *payload_size);
+static int8_t is_valid_stream_type(int8_t stream_type);
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(statsobj)
+
+statsobj_t *modStats;
+STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+STATSCOUNTER_DEF(ctrLostRatelimit, mutCtrLostRatelimit)
+STATSCOUNTER_DEF(ctrCurlError, mutCtrCurlError)
+
+const char* DFLT_dockerAPIUnixSockAddr = "/var/run/docker.sock";
+const char* DFLT_dockerAPIAdd = "http://localhost:2375";
+const char* DFLT_apiVersionStr = "v1.27";
+const char* DFLT_listContainersOptions = "";
+const char* DFLT_getContainerLogOptions = "timestamps=0&follow=1&stdout=1&stderr=1&tail=1";
+const char* DFLT_getContainerLogOptionsWithoutTail = "timestamps=0&follow=1&stdout=1&stderr=1";
+
+/* Overall module configuration structure here. */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *apiVersionStr;
+ uchar *listContainersOptions;
+ uchar *getContainerLogOptions;
+ uchar *getContainerLogOptionsWithoutTail;
+ int iPollInterval; /* in seconds */
+ uchar *dockerApiUnixSockAddr;
+ uchar *dockerApiAddr;
+ sbool retrieveNewLogsFromStart;
+ int containersLimit;
+ int trimLineOverBytes;
+ int iDfltSeverity;
+ int iDfltFacility;
+ sbool bEscapeLf;
+};
+
+static modConfData_t *loadModConf = NULL;
+static modConfData_t *runModConf = NULL;
+
+static prop_t *pInputName = NULL; /* our inputName currently is always "imdocker", and this will hold it */
+static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */
+
+static ratelimit_t *ratelimiter = NULL;
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "apiversionstr", eCmdHdlrString, 0 },
+ { "dockerapiunixsockaddr", eCmdHdlrString, 0 },
+ { "dockerapiaddr", eCmdHdlrString, 0 },
+ { "listcontainersoptions", eCmdHdlrString, 0 },
+ { "getcontainerlogoptions", eCmdHdlrString, 0 },
+ { "pollinginterval", eCmdHdlrPositiveInt, 0 },
+ { "retrievenewlogsfromstart", eCmdHdlrBinary, 0 },
+ { "trimlineoverbytes", eCmdHdlrPositiveInt, 0 },
+ { "defaultseverity", eCmdHdlrSeverity, 0 },
+ { "defaultfacility", eCmdHdlrFacility, 0 },
+ { "escapelf", eCmdHdlrBinary, 0 },
+};
+
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+static int bLegacyCnfModGlobalsPermitted; /* are legacy module-global config parameters permitted? */
+
+/* imdocker specific functions */
+static rsRetVal
+imdockerBufNew(imdocker_buf_t **ppThis) {
+ DEFiRet;
+
+ imdocker_buf_t *pThis = (imdocker_buf_t*) calloc(1, sizeof(imdocker_buf_t));
+ if (!pThis) { return RS_RET_OUT_OF_MEMORY; }
+ *ppThis = pThis;
+
+ RETiRet;
+}
+
+static void
+imdockerBufDestruct(imdocker_buf_t *pThis) {
+ if (pThis) {
+ if (pThis->data) {
+ free(pThis->data);
+ pThis->data = NULL;
+ }
+ free(pThis);
+ }
+}
+
+static rsRetVal
+dockerContLogsBufNew(docker_cont_logs_buf_t **ppThis) {
+ DEFiRet;
+
+ docker_cont_logs_buf_t *pThis = (docker_cont_logs_buf_t*) calloc(1, sizeof(docker_cont_logs_buf_t));
+ if (pThis && (iRet = imdockerBufNew(&pThis->buf)) == RS_RET_OK) {
+ pThis->stream_type = dst_invalid;
+ pThis->bytes_remaining = 0;
+ *ppThis = pThis;
+ } else {
+ dockerContLogsBufDestruct(pThis);
+ }
+
+ RETiRet;
+}
+
+static void
+dockerContLogsBufDestruct(docker_cont_logs_buf_t *pThis) {
+ if (pThis) {
+ if (pThis->buf) {
+ imdockerBufDestruct(pThis->buf);
+ }
+ free(pThis);
+ }
+}
+
+static rsRetVal
+dockerContLogsBufWrite(docker_cont_logs_buf_t *const pThis, const uchar *const pdata, const size_t write_size) {
+ DEFiRet;
+
+ imdocker_buf_t *const mem = pThis->buf;
+ if (mem->len + write_size + 1 > mem->data_size) {
+ uchar *const pbuf = realloc(mem->data, mem->len + write_size + 1);
+ if(pbuf == NULL) {
+ LogError(errno, RS_RET_ERR, "%s() - realloc failed!\n", __FUNCTION__);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ mem->data = pbuf;
+ mem->data_size = mem->len+ write_size + 1;
+ }
+ /* copy the bytes, and advance pdata */
+ memcpy(&(mem->data[mem->len]), pdata, write_size);
+ mem->len += write_size;
+ mem->data[mem->len] = '\0';
+
+ if (write_size > pThis->bytes_remaining) {
+ pThis->bytes_remaining = 0;
+ } else {
+ pThis->bytes_remaining -= write_size;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal imdockerReqNew(imdocker_req_t **ppThis) {
+ DEFiRet;
+
+ imdocker_req_t *pThis = (imdocker_req_t*) calloc(1, sizeof(imdocker_req_t));
+ CHKmalloc(pThis);
+ pThis->curl = curl_easy_init();
+ if (!pThis->curl) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ CHKiRet(imdockerBufNew(&(pThis->buf)));
+ *ppThis = pThis;
+
+finalize_it:
+ if (iRet != RS_RET_OK && pThis) {
+ imdockerReqDestruct(pThis);
+ }
+ RETiRet;
+}
+
+void imdockerReqDestruct(imdocker_req_t *pThis) {
+ if (pThis) {
+ if (pThis->buf) {
+ imdockerBufDestruct(pThis->buf);
+ }
+
+ if (pThis->curl) {
+ curl_easy_cleanup(pThis->curl);
+ pThis->curl = NULL;
+ }
+ free(pThis);
+ }
+}
+
+static rsRetVal
+dockerContLogsReqNew(docker_cont_logs_req_t **ppThis, SubmitMsgFuncPtr submitMsg) {
+ DEFiRet;
+
+ docker_cont_logs_req_t *pThis = (docker_cont_logs_req_t*) calloc(1, sizeof(docker_cont_logs_req_t));
+ CHKmalloc(pThis);
+ pThis->submitMsg = submitMsg;
+ pThis->curl = curl_easy_init();
+ if (!pThis->curl) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (int i = 0; i < dst_stream_type_count; i ++) {
+ CHKiRet(dockerContLogsBufNew(&pThis->data_bufs[i]));
+ }
+
+ *ppThis = pThis;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (pThis) {
+ dockerContLogsReqDestruct(pThis);
+ }
+ }
+ RETiRet;
+}
+
+static void
+dockerContLogsReqDestruct(docker_cont_logs_req_t *pThis) {
+ if (pThis) {
+ for (int i = 0; i < dst_stream_type_count; i++) {
+ dockerContLogsBufDestruct(pThis->data_bufs[i]);
+ }
+
+ if (pThis->curl) {
+ curl_easy_cleanup(pThis->curl);
+ pThis->curl=NULL;
+ }
+
+ free(pThis);
+ }
+}
+
+/**
+ * debugging aide
+ */
+static rsRetVal
+dockerContLogsInstPrint(docker_cont_logs_inst_t * pThis) {
+ DEFiRet;
+ DBGPRINTF("\t container id: %s\n", pThis->id);
+ char* pUrl = NULL;
+ curl_easy_getinfo(pThis->logsReq->curl, CURLINFO_EFFECTIVE_URL, &pUrl);
+ DBGPRINTF("\t container url: %s\n", pUrl);
+
+ RETiRet;
+}
+
+static void
+dockerContLogsInstDestruct(docker_cont_logs_inst_t *pThis) {
+ if (pThis) {
+ if (pThis->id) {
+ free((void*)pThis->id);
+ }
+ if (pThis->container_info) {
+ dockerContainerInfoDestruct(pThis->container_info);
+ }
+ if (pThis->logsReq) {
+ dockerContLogsReqDestruct(pThis->logsReq);
+ }
+ if (pThis->start_regex) {
+ free(pThis->start_regex);
+ regfree(&pThis->start_preg);
+ }
+ free(pThis);
+ }
+}
+
+static rsRetVal
+parseLabels(docker_cont_logs_inst_t *inst, const uchar* json) {
+ DEFiRet;
+
+ /* parse out if we need to do special handling for mult-line */
+ DBGPRINTF("%s() - parsing json=%s\n", __FUNCTION__, json);
+
+ struct fjson_object *json_obj = fjson_tokener_parse((const char*)json);
+ struct fjson_object_iterator it = fjson_object_iter_begin(json_obj);
+ struct fjson_object_iterator itEnd = fjson_object_iter_end(json_obj);
+ while (!fjson_object_iter_equal(&it, &itEnd)) {
+ if (Debug) {
+ DBGPRINTF("%s - \t%s: '%s'\n",
+ __FUNCTION__,
+ fjson_object_iter_peek_name(&it),
+ fjson_object_get_string(fjson_object_iter_peek_value(&it)));
+ }
+
+ if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_LABEL_KEY_STARTREGEX) == 0) {
+ inst->start_regex = (uchar*)strdup(fjson_object_get_string(fjson_object_iter_peek_value(&it)));
+ // compile the regex for future use.
+ int err = regcomp(&inst->start_preg, fjson_object_get_string(fjson_object_iter_peek_value(&it)),
+ REG_EXTENDED);
+ if (err != 0) {
+ char errbuf[512];
+ regerror(err, &inst->start_preg, errbuf, sizeof(errbuf));
+ LogError(0, err, "%s() - error in startregex compile: %s", __FUNCTION__, errbuf);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ fjson_object_iter_next(&it);
+ }
+
+finalize_it:
+ if (json_obj) {
+ json_object_put(json_obj);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dockerContLogsInstNew(docker_cont_logs_inst_t **ppThis, const char* id,
+ docker_container_info_t *container_info, SubmitMsgFuncPtr submitMsg) {
+ DEFiRet;
+
+ docker_cont_logs_inst_t *pThis = NULL;
+ CHKmalloc(pThis = calloc(1, sizeof(docker_cont_logs_inst_t)));
+
+ pThis->id = strdup((char*)id);
+ strncpy((char*) pThis->short_id, id, sizeof(pThis->short_id)-1);
+ CHKiRet(dockerContLogsReqNew(&pThis->logsReq, submitMsg));
+ /* make a copy */
+ if (container_info) {
+ CHKiRet(dockerContainerInfoNew(&pThis->container_info));
+ if (container_info->image_id) {
+ pThis->container_info->image_id = (uchar*)strdup((char*)container_info->image_id);
+ }
+ if (container_info->name) {
+ const char *pname = (const char*)container_info->name;
+ /* removes un-needed characters */
+ pThis->container_info->name = (uchar*)dupDockerContainerName(pname);
+ }
+ if (container_info->json_str_labels) {
+ pThis->container_info->json_str_labels =
+ (uchar*)strdup((char*)container_info->json_str_labels);
+ }
+ pThis->container_info->created = container_info->created;
+ }
+ pThis->start_regex = NULL;
+ pThis->prevSegEnd = 0;
+ /* initialize based on labels found */
+ if (pThis->container_info && pThis->container_info->json_str_labels) {
+ parseLabels(pThis, pThis->container_info->json_str_labels);
+ }
+
+ *ppThis = pThis;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (pThis) {
+ dockerContLogsInstDestruct(pThis);
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dockerContLogsInstSetUrl(docker_cont_logs_inst_t *pThis, CURLM *curlm, const char* pUrl) {
+ DEFiRet;
+ CURLcode ccode = CURLE_OK;
+ CURLMcode mcode = CURLM_OK;
+
+ if (curlm) {
+ docker_cont_logs_req_t *req = pThis->logsReq;
+ if (!runModConf->dockerApiAddr) {
+ ccode = curl_easy_setopt(req->curl, CURLOPT_UNIX_SOCKET_PATH,
+ runModConf->dockerApiUnixSockAddr);
+ if (ccode != CURLE_OK) {
+ LogError(0, RS_RET_ERR,
+ "imdocker: curl_easy_setopt(CURLOPT_UNIX_SOCKET_PATH) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEFUNCTION, imdocker_container_logs_curlCB);
+ if (ccode != CURLE_OK) {
+ LogError(0, RS_RET_ERR,
+ "imdocker: curl_easy_setopt(CURLOPT_WRITEFUNCTION) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEDATA, pThis);
+ if (ccode != CURLE_OK) {
+ LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEDATA) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ ccode = curl_easy_setopt(pThis->logsReq->curl, CURLOPT_URL, pUrl);
+ if (ccode != CURLE_OK) {
+ LogError(0, RS_RET_ERR, "imdocker: could not set url - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ ccode = curl_easy_setopt(pThis->logsReq->curl, CURLOPT_PRIVATE, pThis->id);
+ if (ccode != CURLE_OK) {
+ LogError(0, RS_RET_ERR, "imdocker: could not set private data - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ mcode = curl_multi_add_handle(curlm, pThis->logsReq->curl);
+ if (mcode != CURLM_OK) {
+ LogError(0, RS_RET_ERR, "imdocker: error curl_multi_add_handle ret- %d:%s\n",
+ mcode, curl_multi_strerror(mcode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+finalize_it:
+ if (ccode != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dockerContLogsInstSetUrlById (sbool isInit, docker_cont_logs_inst_t *pThis, CURLM *curlm,
+ const char* containerId) {
+ char url[256];
+ const uchar* container_log_options = runModConf->getContainerLogOptionsWithoutTail;
+
+ if (isInit || !runModConf->retrieveNewLogsFromStart) {
+ container_log_options = runModConf->getContainerLogOptions;
+ }
+
+ const uchar* pApiAddr = (uchar*)"http:";
+ if (runModConf->dockerApiAddr) {
+ pApiAddr = runModConf->dockerApiAddr;
+ }
+
+ snprintf(url, sizeof(url), "%s/%s/containers/%s/logs?%s",
+ pApiAddr, runModConf->apiVersionStr, containerId, container_log_options);
+ DBGPRINTF("%s() - url: %s\n", __FUNCTION__, url);
+
+ return dockerContLogsInstSetUrl(pThis, curlm, url);
+}
+
+/* special destructor for hashtable object. */
+static void
+dockerContLogReqsDestructForHashtable(void *pData) {
+ docker_cont_logs_inst_t *pThis = (docker_cont_logs_inst_t *) pData;
+ dockerContLogsInstDestruct(pThis);
+}
+
+static rsRetVal
+dockerContLogReqsNew(docker_cont_log_instances_t **ppThis) {
+ DEFiRet;
+
+ docker_cont_log_instances_t *pThis = calloc(1, sizeof(docker_cont_log_instances_t));
+ CHKmalloc(pThis);
+ CHKmalloc(pThis->ht_container_log_insts =
+ create_hashtable(7, hash_from_string, key_equals_string,
+ dockerContLogReqsDestructForHashtable));
+
+ CHKiConcCtrl(pthread_mutex_init(&pThis->mut, NULL));
+
+ pThis->curlm = curl_multi_init();
+ if (!pThis->curlm) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ *ppThis = pThis;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (pThis) {
+ dockerContLogReqsDestruct(pThis);
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dockerContLogReqsDestruct(docker_cont_log_instances_t *pThis) {
+ DEFiRet;
+
+ if (pThis) {
+ if (pThis->ht_container_log_insts) {
+ pthread_mutex_lock(&pThis->mut);
+ hashtable_destroy(pThis->ht_container_log_insts, 1);
+ pthread_mutex_unlock(&pThis->mut);
+ }
+ if (pThis->last_container_id) {
+ free(pThis->last_container_id);
+ }
+ curl_multi_cleanup(pThis->curlm);
+ pthread_mutex_destroy(&pThis->mut);
+ free(pThis);
+ }
+
+ RETiRet;
+}
+
+/* NOTE: not thread safe - used internally to update container log requests */
+static rsRetVal
+dockerContLogReqsGet(docker_cont_log_instances_t *pThis,
+ docker_cont_logs_inst_t** ppContLogsInst, const char *id) {
+ DEFiRet;
+
+ if (ppContLogsInst && id) {
+ docker_cont_logs_inst_t *pSearchObj = hashtable_search(pThis->ht_container_log_insts, (void*)id);
+ if (!pSearchObj) {
+ return RS_RET_NOT_FOUND;
+ }
+ *ppContLogsInst = pSearchObj;
+ }
+
+ RETiRet;
+}
+
+/* debug print
+ *
+ * NOTE: not thread safe
+ *
+ */
+static rsRetVal
+dockerContLogReqsPrint(docker_cont_log_instances_t *pThis) {
+ DEFiRet;
+ int count = 0;
+
+ count = hashtable_count(pThis->ht_container_log_insts);
+ if (count) {
+ int ret = 0;
+ struct hashtable_itr *itr = hashtable_iterator(pThis->ht_container_log_insts);
+
+ DBGPRINTF("%s() - All container instances, count=%d...\n", __FUNCTION__, count);
+ do {
+ docker_cont_logs_inst_t *pObj = hashtable_iterator_value(itr);
+ dockerContLogsInstPrint(pObj);
+ ret = hashtable_iterator_advance(itr);
+ } while (ret);
+ free (itr);
+ DBGPRINTF("End of container instances.\n");
+ }
+
+ RETiRet;
+}
+
+/* NOTE: not thread safe */
+static rsRetVal
+dockerContLogReqsAdd(docker_cont_log_instances_t *pThis,
+ docker_cont_logs_inst_t *pContLogsReqInst)
+{
+ DEFiRet;
+ if (!pContLogsReqInst) {
+ return RS_RET_ERR;
+ }
+
+ uchar *keyName = (uchar*)strdup((char*)pContLogsReqInst->id);
+
+ if (keyName) {
+ docker_cont_logs_inst_t *pFind;
+ if (RS_RET_NOT_FOUND == dockerContLogReqsGet(pThis, &pFind, (void*)keyName)) {
+ if (!hashtable_insert(pThis->ht_container_log_insts, keyName, pContLogsReqInst)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ keyName = NULL;
+ }
+ }
+finalize_it:
+ free(keyName);
+ RETiRet;
+}
+
+static rsRetVal
+dockerContLogReqsRemove(docker_cont_log_instances_t *pThis, const char *id) {
+ DEFiRet;
+
+ if (pThis && id) {
+ CHKiConcCtrl(pthread_mutex_lock(&pThis->mut));
+ docker_cont_logs_inst_t *pRemoved =
+ hashtable_remove(pThis->ht_container_log_insts, (void*)id);
+ pthread_mutex_unlock(&pThis->mut);
+ if (pRemoved) {
+ dockerContLogsInstDestruct(pRemoved);
+ } else {
+ iRet = RS_RET_NOT_FOUND;
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+dockerContainerInfoNew(docker_container_info_t **ppThis) {
+ DEFiRet;
+ docker_container_info_t* pThis = calloc(1, sizeof(docker_container_info_t));
+ CHKmalloc(pThis);
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+dockerContainerInfoDestruct(docker_container_info_t *pThis) {
+ if (pThis) {
+ if (pThis->image_id) { free(pThis->image_id); }
+ if (pThis->name) { free(pThis->name); }
+ if (pThis->json_str_labels) { free(pThis->json_str_labels); }
+ free(pThis);
+ }
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+
+ dbgprintf("imdocker: beginCnfLoad\n");
+
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+
+ /* init our settings */
+ loadModConf->iPollInterval = DFLT_pollingInterval; /* in seconds */
+ loadModConf->retrieveNewLogsFromStart = DFLT_retrieveNewLogsFromStart;
+ loadModConf->containersLimit = DFLT_containersLimit;
+ loadModConf->trimLineOverBytes = DFLT_trimLineOverBytes;
+ loadModConf->bEscapeLf = DFLT_bEscapeLF;
+
+ /* Use the default url */
+ loadModConf->apiVersionStr = NULL;
+ loadModConf->dockerApiUnixSockAddr = NULL;
+ loadModConf->dockerApiAddr = NULL;
+ loadModConf->listContainersOptions = NULL;
+ loadModConf->getContainerLogOptions = NULL;
+ loadModConf->getContainerLogOptionsWithoutTail = NULL;
+ loadModConf->iDfltFacility = DFLT_FACILITY;
+ loadModConf->iDfltSeverity = DFLT_SEVERITY;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if (Debug) {
+ dbgprintf("module (global) param blk for imdocker:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ dbgprintf("%s() - iteration %d\n", __FUNCTION__,i);
+ dbgprintf("%s() - modpblk descr: %s\n", __FUNCTION__, modpblk.descr[i].name);
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "pollinginterval")) {
+ loadModConf->iPollInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "containterlimit")) {
+ loadModConf->containersLimit = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "trimlineoverbytes")) {
+ loadModConf->trimLineOverBytes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "listcontainersoptions")) {
+ loadModConf->listContainersOptions = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "getcontainerlogoptions")) {
+ loadModConf->getContainerLogOptions = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ /* also intialize the non-tail version */
+ size_t offset = 0;
+ char buf[256];
+ size_t buf_size = sizeof(buf);
+ strncpy(buf, (char*)loadModConf->getContainerLogOptions, buf_size-1);
+ size_t option_str_len = strlen((char*)loadModConf->getContainerLogOptions);
+ uchar *option_str = calloc(1, option_str_len);
+ CHKmalloc(option_str);
+
+ const char *search_str = "tail=";
+ size_t search_str_len = strlen(search_str);
+ char *token = strtok(buf, "&");
+
+ while (token != NULL) {
+ if (strncmp(token, search_str, search_str_len) == 0) {
+ token = strtok(NULL, "&");
+ continue;
+ }
+ int len = strlen(token);
+ if (offset + len + 1 >= option_str_len) {
+ break;
+ }
+ int bytes = snprintf((char*)option_str + offset,
+ (option_str_len - offset), "%s&", token);
+ if (bytes <= 0) {
+ break;
+ }
+ offset += bytes;
+ token = strtok(NULL, "&");
+ }
+ loadModConf->getContainerLogOptionsWithoutTail = option_str;
+ } else if(!strcmp(modpblk.descr[i].name, "dockerapiunixsockaddr")) {
+ loadModConf->dockerApiUnixSockAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "dockerapiaddr")) {
+ loadModConf->dockerApiAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "apiversionstr")) {
+ loadModConf->apiVersionStr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "retrievenewlogsfromstart")) {
+ loadModConf->retrieveNewLogsFromStart = (sbool) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaultseverity")) {
+ loadModConf->iDfltSeverity = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaultfacility")) {
+ loadModConf->iDfltFacility = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "escapelf")) {
+ loadModConf->bEscapeLf = (sbool) pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "imdocker: program error, non-handled "
+ "param '%s' in setModCnf\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* disable legacy module-global config directives */
+ bLegacyCnfModGlobalsPermitted = 0;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ if (!loadModConf->dockerApiUnixSockAddr) {
+ loadModConf->dockerApiUnixSockAddr = (uchar*) strdup(DFLT_dockerAPIUnixSockAddr);
+ }
+ if (!loadModConf->apiVersionStr) {
+ loadModConf->apiVersionStr = (uchar*) strdup(DFLT_apiVersionStr);
+ }
+ if (!loadModConf->listContainersOptions) {
+ loadModConf->listContainersOptions = (uchar*) strdup(DFLT_listContainersOptions);
+ }
+ if (!loadModConf->getContainerLogOptions) {
+ loadModConf->getContainerLogOptions = (uchar*) strdup(DFLT_getContainerLogOptions);
+ }
+if (!loadModConf->getContainerLogOptionsWithoutTail) {
+ loadModConf->getContainerLogOptionsWithoutTail =
+ (uchar*) strdup(DFLT_getContainerLogOptionsWithoutTail);
+ }
+ runModConf = loadModConf;
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&modStats));
+ CHKiRet(statsobj.SetName(modStats, UCHAR_CONSTANT("imdocker")));
+ CHKiRet(statsobj.SetOrigin(modStats, UCHAR_CONSTANT("imdocker")));
+
+ STATSCOUNTER_INIT(ctrSubmit, mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrSubmit));
+
+ STATSCOUNTER_INIT(ctrLostRatelimit, mutCtrLostRatelimit);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("ratelimit.discarded"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrLostRatelimit));
+
+ STATSCOUNTER_INIT(ctrCurlError, mutCtrCurlError);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("curl.errors"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCurlError));
+
+ CHKiRet(statsobj.ConstructFinalize(modStats));
+ /* end stats */
+finalize_it:
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ if (loadModConf->dockerApiUnixSockAddr) {
+ free(loadModConf->dockerApiUnixSockAddr);
+ }
+ if (loadModConf->dockerApiAddr) {
+ free(loadModConf->dockerApiAddr);
+ }
+ if (loadModConf->apiVersionStr) {
+ free(loadModConf->apiVersionStr);
+ }
+ if (loadModConf->getContainerLogOptions) {
+ free(loadModConf->getContainerLogOptions);
+ }
+ if (loadModConf->getContainerLogOptionsWithoutTail) {
+ free(loadModConf->getContainerLogOptionsWithoutTail);
+ }
+ if (loadModConf->listContainersOptions) {
+ free(loadModConf->listContainersOptions);
+ }
+ statsobj.Destruct(&modStats);
+ENDfreeCnf
+
+static rsRetVal
+addDockerMetaData(const uchar* container_id, docker_container_info_t* pinfo, smsg_t *pMsg) {
+ const uchar *names[4] = {
+ (const uchar*) DOCKER_CONTAINER_ID_PARSE_NAME,
+ (const uchar*) DOCKER_CONTAINER_NAMES_PARSE_NAME,
+ (const uchar*) DOCKER_CONTAINER_IMAGEID_PARSE_NAME,
+ (const uchar*) DOCKER_CONTAINER_LABELS_PARSE_NAME
+ };
+
+ const uchar * empty_str= (const uchar*) "";
+ const uchar *id = container_id ? container_id : empty_str;
+ const uchar *name = pinfo->name ? pinfo->name : empty_str;
+ const uchar *image_id = pinfo->image_id ? pinfo->image_id : empty_str;
+ const uchar *json_str_labels = pinfo->json_str_labels ? pinfo->json_str_labels : empty_str;
+
+ const uchar *values[4] = {
+ id,
+ name,
+ image_id,
+ json_str_labels
+ };
+
+ return msgAddMultiMetadata(pMsg, names, values, 4);
+}
+
+static rsRetVal
+enqMsg(docker_cont_logs_inst_t *pInst, uchar *msg, size_t len, const uchar *pszTag,
+ int facility, int severity, struct timeval *tp)
+{
+ struct syslogTime st;
+ smsg_t *pMsg;
+ DEFiRet;
+
+ if (!msg) {
+ return RS_RET_ERR;
+ }
+
+ if (tp == NULL) {
+ CHKiRet(msgConstruct(&pMsg));
+ } else {
+ datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
+ CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
+ }
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)msg, len);
+
+ if (loadModConf->bEscapeLf) {
+ parser.SanitizeMsg(pMsg);
+ } else {
+ /* Perform some of the SanitizeMsg operations here - specifically:
+ * - remove NULL character at end of message.
+ * - drop trailing LFs.
+ * See SanitizeMsg() for more info.
+ */
+ size_t lenMsg = pMsg->iLenRawMsg;
+ uchar *pszMsg = pMsg->pszRawMsg;
+
+ if(pszMsg[lenMsg-1] == '\0') {
+ DBGPRINTF("dropped NULL at very end of message\n");
+ lenMsg--;
+ }
+
+ if(glbl.GetParserDropTrailingLFOnReception(loadModConf->pConf)
+ && lenMsg > 0 && pszMsg[lenMsg-1] == '\n') {
+ DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n");
+ lenMsg--;
+ pszMsg[lenMsg] = '\0';
+ }
+ pMsg->iLenRawMsg = lenMsg;
+ }
+
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ if (pLocalHostIP) { MsgSetRcvFromIP(pMsg, pLocalHostIP); }
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
+ pMsg->iFacility = facility;
+ pMsg->iSeverity = severity;
+
+ /* docker container metadata */
+ addDockerMetaData((const uchar*)pInst->short_id, pInst->container_info, pMsg);
+
+ const char *name = (const char*)pInst->container_info->name;
+ DBGPRINTF("imdocker: %s - %s:%s\n", __FUNCTION__, name, msg);
+ CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg));
+ STATSCOUNTER_INC(ctrSubmit, mutCtrSubmit);
+
+finalize_it:
+ if (iRet == RS_RET_DISCARDMSG)
+ STATSCOUNTER_INC(ctrLostRatelimit, mutCtrLostRatelimit)
+
+ RETiRet;
+}
+
+static int8_t
+is_valid_stream_type(int8_t stream_type) {
+ return (dst_invalid < stream_type && stream_type < dst_stream_type_count);
+}
+
+/* For use to get docker specific stream information */
+static sbool
+get_stream_info(const uchar* data, size_t size, int8_t *stream_type, size_t *payload_size) {
+ if (size < 8 || !data || !stream_type || !payload_size) {
+ return 0;
+ }
+ const uchar* pdata = data;
+ *stream_type = pdata[0];
+ pdata += 4;
+ uint32_t len = 0;
+ memcpy(&len, pdata, sizeof(len));
+ *payload_size = ntohl(len);
+ return 1;
+}
+#ifdef ENABLE_DEBUG_BYTE_BUFFER
+static void debug_byte_buffer(const uchar* data, size_t size) {
+ if (Debug) {
+ DBGPRINTF("%s() - ENTER, size=%lu\n", __FUNCTION__, size);
+ for (size_t i = 0; i < size; i++) {
+ DBGPRINTF("0x%02x,", data[i]);
+ }
+ DBGPRINTF("\n");
+ }
+}
+#endif
+
+/**
+ * imdocker_container_list_curlCB
+ *
+ * Callback function for CURLOPT_WRITEFUNCTION to get
+ * the results of a docker api call to list all containers.
+ *
+ */
+static size_t
+imdocker_container_list_curlCB(void *data, size_t size, size_t nmemb, void *buffer) {
+ DEFiRet;
+
+ size_t realsize = size*nmemb;
+ uchar *pbuf=NULL;
+ imdocker_buf_t *mem = (imdocker_buf_t*)buffer;
+
+ if ((pbuf = realloc(mem->data, mem->len + realsize + 1)) == NULL) {
+ LogError(errno, RS_RET_ERR, "%s() - realloc failed!\n", __FUNCTION__);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ mem->data = pbuf;
+ mem->data_size = mem->len + realsize + 1;
+
+ memcpy(&(mem->data[mem->len]), data, realsize);
+ mem->len += realsize;
+ mem->data[mem->len] = 0;
+
+#ifdef ENABLE_DEBUG_BYTE_BUFFER
+ debug_byte_buffer((const uchar*) data, realsize);
+#endif
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ return 0;
+ }
+ return realsize;
+}
+
+static rsRetVal
+SubmitMultiLineMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData,
+ const uchar* pszTag, size_t len) {
+ DEFiRet;
+
+ imdocker_buf_t *mem = (imdocker_buf_t*)pBufData->buf;
+ DBGPRINTF("%s() {type=%d, len=%u} %s\n",
+ __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data);
+
+ uchar* message = (uchar*)mem->data;
+ int facility = loadModConf->iDfltFacility;
+ int severity = pBufData->stream_type == dst_stderr ? LOG_ERR : loadModConf->iDfltSeverity;
+ enqMsg(pInst, message, len, (const uchar*)pszTag, facility, severity, NULL);
+
+ size_t size = mem->len - pInst->prevSegEnd;
+ memmove(mem->data, mem->data+pInst->prevSegEnd, size);
+ mem->data[len] = '\0';
+ mem->len = size;
+ pBufData->bytes_remaining = 0;
+
+ RETiRet;
+}
+
+static rsRetVal
+SubmitMsgWithStartRegex(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) {
+ imdocker_buf_t *mem = (imdocker_buf_t*)pBufData->buf;
+ /* must be null terminated string */
+ assert(mem->data[mem->len] == 0 || mem->data[mem->len] == '\0');
+ const char* thisLine = (const char*) mem->data;
+
+ if (pInst->prevSegEnd) {
+ thisLine = (const char*) mem->data+pInst->prevSegEnd;
+ }
+ DBGPRINTF("prevSeg: %d, thisLine: '%s'\n", pInst->prevSegEnd, thisLine);
+ DBGPRINTF("line(s) so far: '%s'\n", mem->data);
+
+ /* check if this line is a start of multi-line message */
+ regex_t *start_preg = (pInst->start_regex == NULL) ? NULL : &pInst->start_preg;
+ const int isStartMatch = start_preg ?
+ !regexec(start_preg, (char*)thisLine, 0, NULL, 0) : 0;
+
+ if (isStartMatch && pInst->prevSegEnd != 0) {
+ SubmitMultiLineMsg(pInst, pBufData, pszTag, pInst->prevSegEnd);
+ pInst->prevSegEnd = 0;
+ FINALIZE;
+ } else {
+ /* just continue parsing using same buffer */
+ pInst->prevSegEnd = mem->len;
+ }
+
+finalize_it:
+ return RS_RET_OK;
+}
+
+static rsRetVal
+SubmitMsg2(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) {
+ imdocker_buf_t *mem = (imdocker_buf_t*)pBufData->buf;
+ DBGPRINTF("%s() - {type=%d, len=%u} %s\n",
+ __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data);
+
+ if (pInst->start_regex) {
+ SubmitMsgWithStartRegex(pInst, pBufData, pszTag);
+ } else {
+ SubmitMsg(pInst, pBufData, pszTag);
+ }
+ return RS_RET_OK;
+}
+
+static rsRetVal
+SubmitMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) {
+ imdocker_buf_t *mem = (imdocker_buf_t*)pBufData->buf;
+ DBGPRINTF("%s() - {type=%d, len=%u} %s\n",
+ __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data);
+
+ uchar* message = mem->data;
+ int facility = loadModConf->iDfltFacility;
+ int severity = pBufData->stream_type == dst_stderr ? LOG_ERR : loadModConf->iDfltSeverity;
+ enqMsg(pInst, message, mem->len, (const uchar*)pszTag, facility, severity, NULL);
+
+ /* clear existing buffer. */
+ mem->len = 0;
+ memset(mem->data, 0, mem->data_size);
+ pBufData->bytes_remaining = 0;
+
+ return RS_RET_OK;
+}
+
+/** imdocker_container_logs_curlCB
+ *
+ * Callback function for CURLOPT_WRITEFUNCTION, gets container logs
+ *
+ * The main container log stream handler. This function is registerred with curl to
+ * as callback to handle container log streaming. It follows the docker stream protocol
+ * as described in the docker container logs api. As per docker's api documentation,
+ * Docker Stream format:
+ * When the TTY setting is disabled in POST /containers/create, the stream over the
+ * hijacked connected is multiplexed to separate out stdout and stderr. The stream
+ * consists of a series of frames, each containing a header and a payload.
+ *
+ * The header contains the information which the stream writes (stdout or stderr). It also
+ * contains the size of the associated frame encoded in the last four bytes (uint32).
+ *
+ * It is encoded on the first eight bytes like this:
+ *
+ * header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
+ * STREAM_TYPE can be:
+ * 0: stdin (is written on stdout)
+ * 1: stdout
+ * 2: stderr
+ *
+ * Docker sends out data in 16KB sized frames, however with the addition of a header
+ * of 8 bytes, a frame may be split into 2 chunks by curl. The 2nd chunk will only
+ * contain enough data to complete the frame (8 leftever bytes). Including the header,
+ * this amounts to 16 bytes; 8 bytes for the header, and 8 bytes for the remaining frame
+ * data.
+ *
+ */
+static size_t
+imdocker_container_logs_curlCB(void *data, size_t size, size_t nmemb, void *buffer) {
+ DEFiRet;
+
+ const uint8_t frame_size = 8;
+ const char imdocker_eol_char = '\n';
+ int8_t stream_type = dst_invalid;
+
+ docker_cont_logs_inst_t* pInst = (docker_cont_logs_inst_t*) buffer;
+ docker_cont_logs_req_t* req = pInst->logsReq;
+
+ size_t realsize = size*nmemb;
+ const uchar* pdata = data;
+ size_t write_size = 0;
+
+#ifdef ENABLE_DEBUG_BYTE_BUFFER
+ debug_byte_buffer((const uchar*) data, realsize);
+#endif
+
+ if (req->data_bufs[dst_stdout]->bytes_remaining || req->data_bufs[dst_stderr]->bytes_remaining) {
+ /* on continuation, stream types should matches with previous */
+ if (req->data_bufs[dst_stdout]->bytes_remaining) {
+ if (req->data_bufs[dst_stderr]->bytes_remaining != 0) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if (req->data_bufs[dst_stderr]->bytes_remaining) {
+ if (req->data_bufs[dst_stdout]->bytes_remaining != 0) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ stream_type = req->data_bufs[dst_stdout]->bytes_remaining ? dst_stdout : dst_stderr;
+ docker_cont_logs_buf_t *pDataBuf = req->data_bufs[stream_type];
+
+ /* read off the remaining bytes */
+ DBGPRINTF("Chunk continuation, remaining bytes: type: %d, "
+ "bytes remaining: %u, realsize: %u, data pos: %u\n",
+ stream_type, (unsigned int)pDataBuf->bytes_remaining,
+ (unsigned int)realsize, (unsigned int)pDataBuf->buf->len);
+
+ write_size = MIN(pDataBuf->bytes_remaining, realsize);
+ CHKiRet(dockerContLogsBufWrite(pDataBuf, pdata, write_size));
+
+ /* submit it */
+ if (pDataBuf->bytes_remaining == 0) {
+ imdocker_buf_t *mem = pDataBuf->buf;
+ if (mem->data[mem->len-1] == imdocker_eol_char) {
+ const char* szContainerId = NULL;
+ CURLcode ccode;
+ if(CURLE_OK != (ccode = curl_easy_getinfo(req->curl,
+ CURLINFO_PRIVATE,
+ &szContainerId))) {
+ LogError(0, RS_RET_ERR,
+ "imdocker: could not get private data req[%p] - %d:%s\n",
+ req->curl, ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ req->submitMsg(pInst, pDataBuf, (const uchar*)DOCKER_TAG_NAME);
+ }
+ }
+
+ pdata += write_size;
+ }
+
+ /* not enough room left */
+ if ((size_t)(pdata - (const uchar*)data) >= realsize) {
+ return (pdata - (const uchar*)data);
+ }
+
+ size_t payload_size = 0;
+ const uchar* pread = pdata + frame_size;
+ docker_cont_logs_buf_t* pDataBuf = NULL;
+
+ if (get_stream_info(pdata, realsize, &stream_type, &payload_size)
+ && is_valid_stream_type(stream_type)) {
+ pDataBuf = req->data_bufs[stream_type];
+ pDataBuf->stream_type = stream_type;
+ pDataBuf->bytes_remaining = payload_size;
+ write_size = MIN(payload_size, realsize - frame_size);
+ } else {
+ /* copy all the data and submit to prevent data loss */
+ stream_type = req->data_bufs[dst_stderr]->bytes_remaining ? dst_stderr : dst_stdout;
+
+ pDataBuf = req->data_bufs[stream_type];
+ pDataBuf->stream_type = stream_type;
+
+ /* just write everything out */
+ pDataBuf->bytes_remaining = 0;
+ write_size = realsize;
+ pread = pdata;
+ }
+
+ /* allocate the expected payload size */
+ CHKiRet(dockerContLogsBufWrite(pDataBuf, pread, write_size));
+ if (pDataBuf->bytes_remaining == 0) {
+ DBGPRINTF("%s() - write size is same as payload_size\n", __FUNCTION__);
+ req->submitMsg(pInst, pDataBuf, (const uchar*)DOCKER_TAG_NAME);
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ return 0;
+ }
+ return realsize;
+}
+
+CURLcode docker_get(imdocker_req_t *req, const char* url) {
+ CURLcode ccode;
+
+ if (!runModConf->dockerApiAddr) {
+ if ((ccode = curl_easy_setopt(req->curl, CURLOPT_UNIX_SOCKET_PATH, runModConf->dockerApiUnixSockAddr))
+ != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_UNIX_SOCKET_PATH) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ return ccode;
+ }
+ }
+ if ((ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEFUNCTION, imdocker_container_list_curlCB)) != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEFUNCTION) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ return ccode;
+ }
+ if ((ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEDATA, req->buf)) != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEDATA) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ return ccode;
+ }
+
+ if ((ccode = curl_easy_setopt(req->curl, CURLOPT_URL, url)) != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_URL) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ return ccode;
+ }
+ CURLcode response = curl_easy_perform(req->curl);
+
+ return response;
+}
+
+static char*
+dupDockerContainerName(const char* pname) {
+ int len = strlen(pname);
+ if (len >= 2 && *pname == '/') {
+ /* skip '/' character */
+ return strdup(pname+1);
+ } else {
+ return strdup(pname);
+ }
+}
+
+static rsRetVal
+process_json(sbool isInit, const char* json, docker_cont_log_instances_t *pInstances) {
+ DEFiRet;
+ struct fjson_object *json_obj = NULL;
+ int mut_locked = 0;
+ DBGPRINTF("%s() - parsing json=%s\n", __FUNCTION__, json);
+
+ if (!pInstances) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ json_obj = fjson_tokener_parse(json);
+ if (!json_obj || !fjson_object_is_type(json_obj, fjson_type_array)) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ int length = fjson_object_array_length(json_obj);
+ /* LOCK the update process. */
+ CHKiConcCtrl(pthread_mutex_lock(&pInstances->mut));
+ mut_locked = 1;
+
+ for (int i = 0; i < length; i++) {
+ fjson_object* p_json_elm = json_object_array_get_idx(json_obj, i);
+
+ DBGPRINTF("element: %d...\n", i);
+ if (p_json_elm) {
+ const char *containerId=NULL;
+ docker_container_info_t containerInfo = {
+ .name=NULL,
+ .image_id=NULL,
+ .created=0,
+ .json_str_labels=NULL
+ };
+
+ struct fjson_object_iterator it = fjson_object_iter_begin(p_json_elm);
+ struct fjson_object_iterator itEnd = fjson_object_iter_end(p_json_elm);
+ while (!fjson_object_iter_equal(&it, &itEnd)) {
+ if (Debug) {
+ DBGPRINTF("\t%s: '%s'\n",
+ fjson_object_iter_peek_name(&it),
+ fjson_object_get_string(fjson_object_iter_peek_value(&it)));
+ }
+
+ if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_ID_PARSE_NAME) == 0) {
+ containerId =
+ fjson_object_get_string(fjson_object_iter_peek_value(&it));
+ } else if (strcmp(fjson_object_iter_peek_name(&it),
+ DOCKER_CONTAINER_NAMES_PARSE_NAME) == 0) {
+ int names_array_length =
+ fjson_object_array_length(fjson_object_iter_peek_value(&it));
+ if (names_array_length) {
+ fjson_object* names_elm =
+ json_object_array_get_idx(fjson_object_iter_peek_value(&it), 0);
+ containerInfo.name = (uchar*)fjson_object_get_string(names_elm);
+ }
+ } else if (strcmp(fjson_object_iter_peek_name(&it),
+ DOCKER_CONTAINER_IMAGEID_PARSE_NAME) == 0) {
+ containerInfo.image_id =
+ (uchar*)fjson_object_get_string(
+ fjson_object_iter_peek_value(&it)
+ );
+ } else if (strcmp(fjson_object_iter_peek_name(&it),
+ DOCKER_CONTAINER_CREATED_PARSE_NAME) == 0) {
+ containerInfo.created =
+ fjson_object_get_int64(
+ fjson_object_iter_peek_value(&it)
+ );
+ } else if (strcmp(fjson_object_iter_peek_name(&it),
+ DOCKER_CONTAINER_LABELS_PARSE_NAME) == 0) {
+ containerInfo.json_str_labels =
+ (uchar*) fjson_object_get_string(
+ fjson_object_iter_peek_value(&it)
+ );
+ DBGPRINTF("labels: %s\n", containerInfo.json_str_labels);
+ }
+ fjson_object_iter_next(&it);
+ }
+
+ if (containerId) {
+ docker_cont_logs_inst_t *pInst = NULL;
+ iRet = dockerContLogReqsGet(pInstances, &pInst, containerId);
+ if (iRet == RS_RET_NOT_FOUND) {
+#ifdef USE_MULTI_LINE
+ if (dockerContLogsInstNew(&pInst, containerId, &containerInfo, SubmitMsg2)
+#else
+ if (dockerContLogsInstNew(&pInst, containerId, &containerInfo, SubmitMsg)
+#endif
+ == RS_RET_OK) {
+ if (pInstances->last_container_created < containerInfo.created) {
+ pInstances->last_container_created = containerInfo.created;
+ if (pInstances->last_container_id) {
+ free(pInstances->last_container_id);
+ }
+ pInstances->last_container_id = (uchar*)strdup(containerId);
+ DBGPRINTF("last_container_id updated: ('%s', %u)\n",
+ pInstances->last_container_id,
+ (unsigned)pInstances->last_container_created);
+ }
+ CHKiRet(dockerContLogsInstSetUrlById(isInit, pInst,
+ pInstances->curlm, containerId));
+ CHKiRet(dockerContLogReqsAdd(pInstances, pInst));
+ }
+ }
+ }
+ }
+ }
+
+finalize_it:
+ if (mut_locked) {
+ pthread_mutex_unlock(&pInstances->mut);
+ }
+ if (json_obj) {
+ json_object_put(json_obj);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+getContainerIds(sbool isInit, docker_cont_log_instances_t *pInstances, const char* url) {
+ DEFiRet;
+ imdocker_req_t *req=NULL;
+
+ CHKiRet(imdockerReqNew(&req));
+
+ CURLcode response = docker_get(req, url);
+ if (response != CURLE_OK) {
+ DBGPRINTF("%s() - curl response: %d\n", __FUNCTION__, response);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ CHKiRet(process_json(isInit, (const char*)req->buf->data, pInstances));
+
+finalize_it:
+ if (req) {
+ imdockerReqDestruct(req);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+getContainerIdsAndAppend(sbool isInit, docker_cont_log_instances_t *pInstances) {
+ DEFiRet;
+
+ char url[256];
+ const uchar* pApiAddr = (uchar*)"http:";
+
+ if (runModConf->dockerApiAddr) {
+ pApiAddr = runModConf->dockerApiAddr;
+ }
+
+ /*
+ * TODO: consider if we really need 'isInit' parameter. I suspect we don't need it
+ * and i'm almost certain Travis CI will complain its not used.
+ */
+ if (pInstances->last_container_id) {
+ snprintf(url, sizeof(url), "%s/%s/containers/json?%s&filters={\"since\":[\"%s\"]}",
+ pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions,
+ pInstances->last_container_id);
+ } else {
+ snprintf(url, sizeof(url), "%s/%s/containers/json?%s",
+ pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions);
+ }
+ DBGPRINTF("listcontainers url: %s\n", url);
+
+ CHKiRet(getContainerIds(isInit, pInstances, (const char*)url));
+ if (Debug) { dockerContLogReqsPrint(pInstances); }
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+cleanupCompletedContainerRequests(docker_cont_log_instances_t *pInstances) {
+ // clean up
+ int rc=0, msgs_left=0;
+ CURLMsg *msg=NULL;
+ CURL *pCurl;
+
+ while ((msg = curl_multi_info_read(pInstances->curlm, &msgs_left))) {
+ if (msg->msg == CURLMSG_DONE) {
+ pCurl = msg->easy_handle;
+ rc = msg->data.result;
+ if (rc != CURLE_OK) {
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ LogError(0, RS_RET_ERR, "imdocker: %s() - curl error code: %d:%s\n",
+ __FUNCTION__, rc, curl_multi_strerror(rc));
+ continue;
+ }
+
+ CURLcode ccode;
+ if (Debug) {
+ long http_status=0;
+ curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &http_status);
+ DBGPRINTF("http status: %lu\n", http_status);
+ }
+ curl_multi_remove_handle(pInstances->curlm, pCurl);
+
+ const char* szContainerId = NULL;
+ if ((ccode = curl_easy_getinfo(pCurl, CURLINFO_PRIVATE, &szContainerId)) == CURLE_OK) {
+ DBGPRINTF("container disconnected: %s\n", szContainerId);
+ dockerContLogReqsRemove(pInstances, szContainerId);
+ DBGPRINTF("container removed...\n");
+ } else {
+ LogError(0, RS_RET_ERR, "imdocker: private data not found "
+ "curl_easy_setopt(CURLINFO_PRIVATE) error - %d:%s\n",
+ ccode, curl_easy_strerror(ccode));
+ STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError);
+ }
+ }
+ }
+}
+
+static rsRetVal
+processAndPollContainerLogs(docker_cont_log_instances_t *pInstances) {
+ DEFiRet;
+ int count=0;
+
+ count = hashtable_count(pInstances->ht_container_log_insts);
+ DBGPRINTF("%s() - container instances: %d\n", __FUNCTION__, count);
+
+ int still_running=0;
+
+ curl_multi_perform(pInstances->curlm, &still_running);
+ do {
+ int numfds = 0;
+
+ int res = curl_multi_wait(pInstances->curlm, NULL, 0, 1000, &numfds);
+ if (res != CURLM_OK) {
+ LogError(0, RS_RET_ERR, "error: curl_multi_wait() numfds=%d, res=%d:%s\n",
+ numfds, res, curl_multi_strerror(res));
+ return res;
+ }
+
+ int prev_still_running = still_running;
+ curl_multi_perform(pInstances->curlm, &still_running);
+
+ if (prev_still_running > still_running) {
+ cleanupCompletedContainerRequests(pInstances);
+ }
+
+ } while (still_running && glbl.GetGlobalInputTermState() == 0);
+
+ cleanupCompletedContainerRequests(pInstances);
+
+ RETiRet;
+}
+
+static void*
+getContainersTask(void *pdata) {
+ docker_cont_log_instances_t *pInstances = (docker_cont_log_instances_t*) pdata;
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ srSleep(runModConf->iPollInterval, 10);
+ getContainerIdsAndAppend(false, pInstances);
+ }
+ return pdata;
+}
+
+/* This function is called to gather input. */
+BEGINrunInput
+ rsRetVal localRet = RS_RET_OK;
+ docker_cont_log_instances_t *pInstances=NULL;
+ pthread_t thrd_id; /* the worker's thread ID */
+ pthread_attr_t thrd_attr;
+ int get_containers_thread_initialized = 0;
+ time_t now;
+CODESTARTrunInput
+ datetime.GetTime(&now);
+
+ CHKiRet(ratelimitNew(&ratelimiter, "imdocker", NULL));
+ curl_global_init(CURL_GLOBAL_ALL);
+ localRet = dockerContLogReqsNew(&pInstances);
+ if (localRet != RS_RET_OK) {
+ return localRet;
+ }
+ pInstances->time_started = now;
+
+ /* get all current containers now */
+ CHKiRet(getContainerIdsAndAppend(true, pInstances));
+
+ /* using default stacksize */
+ CHKiConcCtrl(pthread_attr_init(&thrd_attr));
+ CHKiConcCtrl(pthread_create(&thrd_id, &thrd_attr, getContainersTask, pInstances));
+ get_containers_thread_initialized = 1;
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ CHKiRet(processAndPollContainerLogs(pInstances));
+ if (glbl.GetGlobalInputTermState() == 0) {
+ /* exited from processAndPollContainerLogs, sleep before retrying */
+ srSleep(1, 10);
+ }
+ }
+
+finalize_it:
+ if (get_containers_thread_initialized) {
+ pthread_kill(thrd_id, SIGTTIN);
+ pthread_join(thrd_id, NULL);
+ pthread_attr_destroy(&thrd_attr);
+ }
+ if (pInstances) {
+ dockerContLogReqsDestruct(pInstances);
+ }
+ if (ratelimiter) {
+ ratelimitDestruct(ratelimiter);
+ }
+ENDrunInput
+
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+BEGINafterRun
+CODESTARTafterRun
+ENDafterRun
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
+ if(pLocalHostIP != NULL)
+ prop.Destruct(&pLocalHostIP);
+
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+
+ DBGPRINTF("imdocker version %s initializing\n", VERSION);
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdocker"), sizeof("imdocker") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ENDmodInit
diff --git a/contrib/imhiredis/COPYING b/contrib/imhiredis/COPYING
new file mode 100644
index 0000000..f44bd49
--- /dev/null
+++ b/contrib/imhiredis/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/contrib/imhiredis/Makefile.am b/contrib/imhiredis/Makefile.am
new file mode 100644
index 0000000..6528a19
--- /dev/null
+++ b/contrib/imhiredis/Makefile.am
@@ -0,0 +1,7 @@
+pkglib_LTLIBRARIES = imhiredis.la
+imhiredis_la_SOURCES = imhiredis.c
+imhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS)
+imhiredis_la_LDFLAGS = -module -avoid-version
+imhiredis_la_LIBADD = $(HIREDIS_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/imhiredis/Makefile.in b/contrib/imhiredis/Makefile.in
new file mode 100644
index 0000000..fb3a3e2
--- /dev/null
+++ b/contrib/imhiredis/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imhiredis
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imhiredis_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imhiredis_la_OBJECTS = imhiredis_la-imhiredis.lo
+imhiredis_la_OBJECTS = $(am_imhiredis_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 =
+imhiredis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imhiredis_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imhiredis_la-imhiredis.Plo
+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 = $(imhiredis_la_SOURCES)
+DIST_SOURCES = $(imhiredis_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING \
+ README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imhiredis.la
+imhiredis_la_SOURCES = imhiredis.c
+imhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS)
+imhiredis_la_LDFLAGS = -module -avoid-version
+imhiredis_la_LIBADD = $(HIREDIS_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/imhiredis/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imhiredis/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imhiredis.la: $(imhiredis_la_OBJECTS) $(imhiredis_la_DEPENDENCIES) $(EXTRA_imhiredis_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imhiredis_la_LINK) -rpath $(pkglibdir) $(imhiredis_la_OBJECTS) $(imhiredis_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imhiredis_la-imhiredis.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imhiredis_la-imhiredis.lo: imhiredis.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imhiredis_la-imhiredis.lo -MD -MP -MF $(DEPDIR)/imhiredis_la-imhiredis.Tpo -c -o imhiredis_la-imhiredis.lo `test -f 'imhiredis.c' || echo '$(srcdir)/'`imhiredis.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imhiredis_la-imhiredis.Tpo $(DEPDIR)/imhiredis_la-imhiredis.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imhiredis.c' object='imhiredis_la-imhiredis.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) $(imhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imhiredis_la-imhiredis.lo `test -f 'imhiredis.c' || echo '$(srcdir)/'`imhiredis.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imhiredis_la-imhiredis.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imhiredis_la-imhiredis.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imhiredis/README b/contrib/imhiredis/README
new file mode 100644
index 0000000..70a9b31
--- /dev/null
+++ b/contrib/imhiredis/README
@@ -0,0 +1,81 @@
+Redis Input Plugin using hiredis library
+
+REQUIREMENTS:
+
+* hiredis ( https://github.com/redis/hiredis.git )
+
+USAGE:
+
+This plugin has two current "modes" that it supports:
+
+1. "queue"
+The queue mode will LPOP or RPOP your message from a redis list.
+Following parameters are required:
+ - mode: Set mode to "queue" to enable the queue mode
+ - key: The key to xPOP on
+ - server: The name or IP address of the redis server
+ - port: The redis listening port
+
+Following parameters are optional:
+ - password: If set, the plugin will issue an "AUTH" command before calling xPOP
+ - uselpop: If set to "1", LPOP will be used instead of default RPOP
+
+Redis pipelining is used inside the worker thread. The dequeue batch size is configured with the "batchsize" parameter (default is 10).
+
+Imhiredis will query Redis every second to see if entries are in the list, if that's the case they will be dequeued
+continuously by batches of "batchsize elements" until none remains.
+
+Due to its balance between polling interval and pipelining and its use of lists, this mode is quite performant and reliable.
+However, due to the 1 second polling frequency, one may consider using the `subscribe` mode instead if very low latency is required.
+
+```
+module(load="imhiredis")
+
+input(
+ type="imhiredis"
+ mode="queue"
+ key="vulture"
+ server="127.0.0.1"
+ port="6379"
+ uselpop="1"
+ password="foobar"
+ batchsize="10"
+)
+```
+
+
+
+2. "subscribe"
+The subscribe mode will SUBSCRIBE to a redis channel. The "key"
+parameter is required and will be used for the subscribe channel.
+
+Following parameters are required:
+ - mode: Set mode to "subscribe" to enable the subscribe mode
+ - key: The key to subscribe to (aka the "channel")
+ - server: The name or IP address of the redis server
+ - port: The redis listening port
+
+Following parameters are optional:
+ - password: If set, the plugin will issue an "AUTH" command before listening to a channel
+ - uselpop: If set to "1", LPOP will be used instead of default RPOP
+
+
+```
+module(load="imhiredis")
+
+input(
+ type="imhiredis"
+ mode="subscribe"
+ key="vulture"
+ server="127.0.0.1"
+ port="6379"
+ password="foobar"
+ batchsize="10"
+)
+```
+
+
+TODO
+* TLS support
+
+
diff --git a/contrib/imhiredis/imhiredis.c b/contrib/imhiredis/imhiredis.c
new file mode 100644
index 0000000..e1a8e1c
--- /dev/null
+++ b/contrib/imhiredis/imhiredis.c
@@ -0,0 +1,2298 @@
+/* imhiredis.c
+* Copyright 2021 aDvens
+*
+* This file is contrib for rsyslog.
+* This input plugin is a log consumer from REDIS
+* See README for doc
+*
+*
+* 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, 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
+* 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, see
+* <http://www.gnu.org/licenses/>.
+*
+* Author: Jérémie Jourdin
+* <jeremie.jourdin@advens.fr>
+*/
+
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/uio.h>
+#include <hiredis/hiredis.h>
+#include <hiredis/async.h>
+#include <hiredis/adapters/libevent.h>
+#include <event2/thread.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "glbl.h"
+#include "cfsysline.h"
+#include "msg.h"
+#include "dirty.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imhiredis")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+#define BATCH_SIZE 10
+#define WAIT_TIME_MS 500
+#define STREAM_INDEX_STR_MAXLEN 44 // "18446744073709551615-18446744073709551615"
+#define IMHIREDIS_MODE_QUEUE 1
+#define IMHIREDIS_MODE_SUBSCRIBE 2
+#define IMHIREDIS_MODE_STREAM 3
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(statsobj)
+
+
+typedef struct redisNode_s {
+ sbool isMaster;
+ sbool usesSocket;
+ uchar *socketPath;
+ uchar *server;
+ int port;
+ struct redisNode_s *next;
+} redisNode;
+
+
+struct instanceConf_s {
+ uchar *password;
+ uchar *key;
+ uchar *modeDescription;
+ uchar *streamConsumerGroup;
+ uchar *streamConsumerName;
+ uchar *streamReadFrom;
+ int streamAutoclaimIdleTime;
+ sbool streamConsumerACK;
+ int mode;
+ uint batchsize;
+ sbool useLPop;
+
+ struct {
+ int nmemb;
+ char **name;
+ char **varname;
+ } fieldList;
+
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *pszBindRuleset; /* default name of Ruleset to bind to */
+
+ redisContext *conn;
+ redisAsyncContext *aconn;
+ struct event_base *evtBase;
+
+ redisNode *currentNode; /* currently used redis node, can be any of the nodes in the redisNodesList list */
+ /* the list of seen nodes
+ * the preferred node (the one from configuration) will always be the first element
+ * second one is a master (if preferred one is unavailable/replica) or a replica, others are replicas
+ * the preferred node may appear twice, but it is accepted
+ */
+ redisNode *redisNodesList;
+
+ struct instanceConf_s *next;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+};
+
+/* The following structure controls the worker threads. Global data is
+ * needed for their access.
+ */
+static struct imhiredisWrkrInfo_s {
+ pthread_t tid; /* the worker's thread ID */
+ instanceConf_t *inst; /* Pointer to imhiredis instance */
+ rsRetVal (*fnConnectMaster)(instanceConf_t *inst);
+ sbool (*fnIsConnected)(instanceConf_t *inst);
+ rsRetVal (*fnRun)(instanceConf_t *inst);
+} *imhiredisWrkrInfo;
+
+
+/* GLOBAL DATA */
+pthread_attr_t wrkrThrdAttr; /* Attribute for worker threads ; read only after startup */
+
+static int activeHiredisworkers = 0;
+static char *REDIS_REPLIES[] = {
+ "unknown", // 0
+ "string", // 1
+ "array", // 2
+ "integer", // 3
+ "nil", // 4
+ "status", // 5
+ "error", // 6
+ "double", // 7
+ "bool", // 8
+ "map", // 9
+ "set", // 10
+ "attr", // 11
+ "push", // 12
+ "bignum", // 13
+ "verb", // 14
+ };
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "socketPath", eCmdHdlrGetWord, 0 },
+ { "server", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrInt, 0 },
+ { "password", eCmdHdlrGetWord, 0 },
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "batchsize", eCmdHdlrInt, 0 },
+ { "key", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "uselpop", eCmdHdlrBinary, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "stream.consumerGroup", eCmdHdlrGetWord, 0 },
+ { "stream.consumerName", eCmdHdlrGetWord, 0 },
+ { "stream.readFrom", eCmdHdlrGetWord, 0 },
+ { "stream.consumerACK", eCmdHdlrBinary, 0 },
+ { "stream.autoclaimIdleTime", eCmdHdlrNonNegInt, 0 },
+ { "fields", eCmdHdlrArray, 0 },
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+struct timeval glblRedisConnectTimeout = { 3, 0 }; /* 3 seconds */
+
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+
+/* forward references */
+static void redisAsyncRecvCallback (redisAsyncContext __attribute__((unused)) *c, void *reply, void *inst_obj);
+static void redisAsyncConnectCallback (const redisAsyncContext *c, int status);
+static void redisAsyncDisconnectCallback (const redisAsyncContext *c, int status);
+static struct json_object* _redisParseIntegerReply(const redisReply *reply);
+static struct json_object* _redisParseStringReply(const redisReply *reply);
+static struct json_object* _redisParseArrayReply(const redisReply *reply);
+#ifdef REDIS_REPLY_DOUBLE
+static struct json_object* _redisParseDoubleReply(const redisReply *reply);
+#endif
+static rsRetVal enqMsg(instanceConf_t *const inst, const char *message, size_t msgLen);
+static rsRetVal enqMsgJson(instanceConf_t *const inst, struct json_object *json, struct json_object *metadata);
+rsRetVal redisAuthentSynchronous(redisContext *conn, uchar *password);
+rsRetVal redisAuthentAsynchronous(redisAsyncContext *aconn, uchar *password);
+rsRetVal redisActualizeCurrentNode(instanceConf_t *inst);
+rsRetVal redisGetServersList(redisNode *node, uchar *password, redisNode **result);
+rsRetVal redisAuthenticate(instanceConf_t *inst);
+rsRetVal redisConnectSync(redisContext **conn, redisNode *node);
+rsRetVal connectMasterSync(instanceConf_t *inst);
+static sbool isConnectedSync(instanceConf_t *inst);
+rsRetVal redisConnectAsync(redisAsyncContext **aconn, redisNode *node);
+rsRetVal connectMasterAsync(instanceConf_t *inst);
+static sbool isConnectedAsync(instanceConf_t *inst);
+rsRetVal redisDequeue(instanceConf_t *inst);
+rsRetVal ensureConsumerGroupCreated(instanceConf_t *inst);
+rsRetVal ackStreamIndex(instanceConf_t *inst, uchar *stream, uchar *group, uchar *index);
+static rsRetVal enqueueRedisStreamReply(instanceConf_t *const inst, redisReply *reply);
+static rsRetVal handleRedisXREADReply(instanceConf_t *const inst, const redisReply *reply);
+static rsRetVal handleRedisXAUTOCLAIMReply(
+ instanceConf_t *const inst, const redisReply *reply, char **autoclaimIndex);
+rsRetVal redisStreamRead(instanceConf_t *inst);
+rsRetVal redisSubscribe(instanceConf_t *inst);
+void workerLoop(struct imhiredisWrkrInfo_s *me);
+static void *imhirediswrkr(void *myself);
+static rsRetVal createRedisNode(redisNode **root);
+rsRetVal copyNode(redisNode *src, redisNode **dst);
+redisNode *freeNode(redisNode *node);
+void insertNodeAfter(redisNode *root, redisNode *elem);
+void dbgPrintNode(redisNode *node);
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ DEFiRet;
+ instanceConf_t *inst;
+ CHKmalloc(inst = calloc(1, sizeof(instanceConf_t)));
+
+ inst->next = NULL;
+ inst->password = NULL;
+ inst->key = NULL;
+ inst->mode = 0;
+ inst->batchsize = 0;
+ inst->useLPop = 0;
+ inst->streamConsumerGroup = NULL;
+ inst->streamConsumerName = NULL;
+ CHKmalloc(inst->streamReadFrom = calloc(1, STREAM_INDEX_STR_MAXLEN));
+ inst->streamAutoclaimIdleTime = 0;
+ inst->streamConsumerACK = 1;
+ inst->pszBindRuleset = NULL;
+ inst->pBindRuleset = NULL;
+ inst->fieldList.nmemb = 0;
+
+ /* Redis objects */
+ inst->conn = NULL;
+ inst->aconn = NULL;
+
+ /* redis nodes list */
+ CHKiRet(createRedisNode(&(inst->redisNodesList)));
+ inst->currentNode = inst->redisNodesList;
+
+ /* libevent base for async connection */
+ inst->evtBase = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* this function checks instance parameters and does some required pre-processing
+ */
+static rsRetVal ATTR_NONNULL()
+checkInstance(instanceConf_t *const inst)
+{
+ DEFiRet;
+ /* first node should be created from configuration */
+ assert(inst->redisNodesList != NULL);
+
+ /* check and print redis connection settings */
+ if (inst->redisNodesList->server != NULL && inst->redisNodesList->socketPath != NULL) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: both 'server' and 'socketPath' are given, "
+ "ignoring 'socketPath'.");
+ free(inst->redisNodesList->socketPath);
+ inst->redisNodesList->socketPath = NULL;
+ }
+
+ if(inst->redisNodesList->server != NULL && inst->redisNodesList->server[0] != '\0') {
+ if (inst->redisNodesList->port == 0) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: port not set, setting default 6379");
+ inst->redisNodesList->port = 6379;
+ }
+ DBGPRINTF("imhiredis: preferred server is %s (%d)\n",
+ inst->redisNodesList->server,
+ inst->redisNodesList->port);
+ inst->redisNodesList->usesSocket = 0;
+ }
+ else if(inst->redisNodesList->socketPath != NULL && inst->redisNodesList->socketPath[0] != '\0') {
+ DBGPRINTF("imhiredis: preferred server is %s\n",
+ inst->redisNodesList->socketPath);
+ inst->redisNodesList->usesSocket = 1;
+ } else {
+ LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: neither 'server' nor 'socketPath' are defined!");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+
+ if (inst->mode < IMHIREDIS_MODE_QUEUE || inst->mode > IMHIREDIS_MODE_STREAM) {
+ LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: invalid mode, please choose 'subscribe', "
+ "'queue' or 'stream' mode.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if (inst->mode != IMHIREDIS_MODE_QUEUE && inst->useLPop) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'uselpop' set with mode != queue : ignored.");
+ }
+
+ if (inst->mode == IMHIREDIS_MODE_STREAM) {
+ if(inst->streamConsumerGroup != NULL && inst->streamConsumerName == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: invalid configuration, "
+ "please set a consumer name when mode is 'stream' and a consumer group is set");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(inst->streamAutoclaimIdleTime != 0 && inst->streamConsumerGroup == NULL) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'stream.autoclaimIdleTime' "
+ "set with no consumer group set : ignored.");
+ }
+ if(inst->streamReadFrom[0] == '\0') {
+ inst->streamReadFrom[0] = '$';
+ }
+ } else {
+ if (inst->streamConsumerGroup != NULL) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'stream.consumerGroup' "
+ "set with mode != stream : ignored.");
+ }
+ if (inst->streamConsumerName != NULL) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'stream.consumerName' "
+ "set with mode != stream : ignored.");
+ }
+ if (inst->streamAutoclaimIdleTime != 0) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'stream.autoclaimIdleTime' "
+ "set with mode != stream : ignored.");
+ }
+ if (inst->streamConsumerACK == 0) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'stream.consumerACK' "
+ "disabled with mode != stream : ignored.");
+ }
+ if (inst->fieldList.nmemb > 0) {
+ LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING,"imhiredis: 'fields' "
+ "unused for mode != stream : ignored.");
+ }
+ }
+
+ if (inst->batchsize !=0 ) {
+ DBGPRINTF("imhiredis: batchsize is '%d'\n", inst->batchsize);
+ }
+ else {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING,
+ "imhiredis: batchsize not set, setting to default (%d)",BATCH_SIZE);
+ inst->batchsize=BATCH_SIZE;
+ }
+
+ if (inst->password != NULL) {
+ DBGPRINTF("imhiredis: password is '%s'\n", inst->password);
+ }
+
+ // set default current node as first node in list (preferred node)
+ inst->currentNode = inst->redisNodesList;
+ // search master node (should be either preferred node or its master)
+ if (RS_RET_OK != redisActualizeCurrentNode(inst) || inst->currentNode == NULL) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: could not connect to a valid master!");
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* function to generate an error message if the ruleset cannot be found */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imhiredis: ruleset '%s' not found - "
+ "using default ruleset instead",
+ inst->pszBindRuleset);
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imhiredis)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imhiredis:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+
+ if(!strcmp(inppblk.descr[i].name, "server")) {
+ inst->redisNodesList->server = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "socketPath")) {
+ inst->redisNodesList->socketPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "port")) {
+ inst->redisNodesList->port = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "password")) {
+ inst->password = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "stream.consumerGroup")) {
+ inst->streamConsumerGroup = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "stream.consumerName")) {
+ inst->streamConsumerName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "stream.consumerACK")) {
+ inst->streamConsumerACK = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "stream.readFrom")) {
+ // inst->streamReadFrom is already allocated, only copy contents
+ memcpy(inst->streamReadFrom,
+ es_getBufAddr(pvals[i].val.d.estr),
+ es_strlen(pvals[i].val.d.estr));
+ inst->streamReadFrom[es_strlen(pvals[i].val.d.estr)] = '\0';
+ } else if(!strcmp(inppblk.descr[i].name, "stream.autoclaimIdleTime")) {
+ inst->streamAutoclaimIdleTime = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "uselpop")) {
+ inst->useLPop = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "mode")) {
+ inst->modeDescription = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (!strcmp((const char*)inst->modeDescription, "queue")) {
+ inst->mode = IMHIREDIS_MODE_QUEUE;
+ } else if (!strcmp((const char*)inst->modeDescription, "subscribe")) {
+ inst->mode = IMHIREDIS_MODE_SUBSCRIBE;
+ } else if (!strcmp((const char*)inst->modeDescription, "stream")) {
+ inst->mode = IMHIREDIS_MODE_STREAM;
+ } else {
+ LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR, "imhiredis: unsupported mode "
+ "'%s'", inst->modeDescription);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if (!strcmp(inppblk.descr[i].name, "fields")) {
+ inst->fieldList.nmemb = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(inst->fieldList.name = calloc(inst->fieldList.nmemb, sizeof(char *)));
+ CHKmalloc(inst->fieldList.varname = calloc(inst->fieldList.nmemb, sizeof(char *)));
+ for (int j = 0; j < pvals[i].val.d.ar->nmemb; ++j) {
+ char *const param = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ char *varname = NULL;
+ char *name;
+ if(*param == ':') {
+ char *b = strchr(param+1, ':');
+ if(b == NULL) {
+ LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR,
+ "imhiredis: missing closing colon: '%s'", param);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ *b = '\0'; /* split name & varname */
+ varname = param+1;
+ name = b+1;
+ } else {
+ name = param;
+ }
+ CHKmalloc(inst->fieldList.name[j] = strdup(name));
+ char vnamebuf[1024];
+ snprintf(vnamebuf, sizeof(vnamebuf),
+ "!%s", (varname == NULL) ? name : varname);
+ CHKmalloc(inst->fieldList.varname[j] = strdup(vnamebuf));
+ DBGPRINTF("will map '%s' to '%s'\n",
+ inst->fieldList.name[j],
+ inst->fieldList.varname[j]);
+ free(param);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "batchsize")) {
+ inst->batchsize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "key")) {
+ inst->key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imhiredis: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ DBGPRINTF("imhiredis: checking config sanity\n");
+ if (inst->modeDescription == NULL) {
+ CHKmalloc(inst->modeDescription = (uchar*)strdup("subscribe"));
+ inst->mode = IMHIREDIS_MODE_SUBSCRIBE;
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: \"mode\" parameter not specified "
+ "using default redis 'subscribe' mode -- this may not be what you want!");
+ }
+ if (inst->key == NULL) {
+ LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR, "imhiredis: \"key\" required parameter not specified!");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ if(inst->redisNodesList->server == NULL && inst->redisNodesList->socketPath == NULL) {
+ CHKmalloc(inst->redisNodesList->server = (uchar *)strdup("127.0.0.1"));
+ inst->redisNodesList->port = 6379;
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: no server parameter specified "
+ "using default 127.0.0.1:6379 -- this may not be what you want!");
+ }
+ if (inst->password == NULL) {
+ LogMsg(0, RS_RET_OK, LOG_INFO, "imhiredis: no password specified");
+ }
+
+ DBGPRINTF("imhiredis: newInpInst key=%s, mode=%s, uselpop=%d\n",
+ inst->key, inst->modeDescription, inst->useLPop);
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imhiredis: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imhiredis:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ } else {
+ dbgprintf("imhiredis: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ for(instanceConf_t *inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ iRet = checkInstance(inst);
+ if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE)
+ inst->evtBase = event_base_new();
+ }
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+ redisNode *node;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ if (inst->evtBase)
+ event_base_free(inst->evtBase);
+ if (inst->password != NULL)
+ free(inst->password);
+ free(inst->modeDescription);
+ free(inst->key);
+ if(inst->streamConsumerGroup != NULL)
+ free(inst->streamConsumerGroup);
+ if(inst->streamConsumerName != NULL)
+ free(inst->streamConsumerName);
+ free(inst->streamReadFrom);
+ free(inst->pszBindRuleset);
+ if(inst->fieldList.name != NULL) {
+ for(int i = 0 ; i < inst->fieldList.nmemb ; ++i) {
+ free(inst->fieldList.name[i]);
+ free(inst->fieldList.varname[i]);
+ }
+ free(inst->fieldList.name);
+ free(inst->fieldList.varname);
+ }
+ if(inst->conn != NULL) {
+ redisFree(inst->conn);
+ inst->conn = NULL;
+ }
+ if(inst->aconn != NULL) {
+ redisAsyncFree(inst->aconn);
+ inst->aconn = NULL;
+ }
+
+ for (node = inst->redisNodesList; node != NULL; node = freeNode(node)) {;}
+
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+
+/* Cleanup imhiredis worker threads */
+static void
+shutdownImhiredisWorkers(void)
+{
+ int i;
+ instanceConf_t *inst;
+
+ assert(imhiredisWrkrInfo != NULL);
+
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE && inst->aconn) {
+ DBGPRINTF("imhiredis: disconnecting async worker\n");
+ redisAsyncDisconnect(inst->aconn);
+ }
+ }
+
+ // event_base_loopbreak(runModConf->evtBase);
+
+ DBGPRINTF("imhiredis: waiting on imhiredis workerthread termination\n");
+ for(i = 0 ; i < activeHiredisworkers ; ++i) {
+ pthread_join(imhiredisWrkrInfo[i].tid, NULL);
+ DBGPRINTF("imhiredis: Stopped worker %d\n", i);
+ }
+ free(imhiredisWrkrInfo);
+ imhiredisWrkrInfo = NULL;
+
+ return;
+}
+
+
+/* This function is called to gather input. */
+BEGINrunInput
+ int i;
+ instanceConf_t *inst;
+CODESTARTrunInput
+ DBGPRINTF("imhiredis: runInput loop started ...\n");
+ activeHiredisworkers = 0;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ ++activeHiredisworkers;
+ }
+
+ if(activeHiredisworkers == 0) {
+ LogError(0, RS_RET_ERR, "imhiredis: no active inputs, input does "
+ "not run - there should have been additional error "
+ "messages given previously");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+
+ DBGPRINTF("imhiredis: Starting %d imhiredis workerthreads\n", activeHiredisworkers);
+ imhiredisWrkrInfo = calloc(activeHiredisworkers, sizeof(struct imhiredisWrkrInfo_s));
+ if (imhiredisWrkrInfo == NULL) {
+ LogError(errno, RS_RET_OUT_OF_MEMORY, "imhiredis: worker-info array allocation failed.");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* Start worker threads for each imhiredis input source
+ */
+ i = 0;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ /* init worker info structure! */
+ imhiredisWrkrInfo[i].inst = inst; /* Set reference pointer */
+ pthread_create(&imhiredisWrkrInfo[i].tid, &wrkrThrdAttr, imhirediswrkr, &(imhiredisWrkrInfo[i]));
+ i++;
+ }
+
+ // This thread simply runs the various threads, then waits for Rsyslog to stop
+ while(glbl.GetGlobalInputTermState() == 0) {
+ if(glbl.GetGlobalInputTermState() == 0)
+ /* Check termination state every 0.5s
+ * should be sufficient to grant fast response to shutdown while not hogging CPU
+ */
+ srSleep(0, 500000);
+ }
+ DBGPRINTF("imhiredis: terminating upon request of rsyslog core\n");
+
+ shutdownImhiredisWorkers();
+finalize_it:
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imhiredis"), sizeof("imhiredis") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ pthread_attr_destroy(&wrkrThrdAttr);
+
+ /* force cleaning of all libevent-related structures
+ * (clean shutdowns are not always guaranteed without it)
+ */
+ libevent_global_shutdown();
+
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ /* initialize "read-only" thread attributes */
+ pthread_attr_init(&wrkrThrdAttr);
+ pthread_attr_setstacksize(&wrkrThrdAttr, 4096*1024);
+
+ /* activate libevent for (p)threads support */
+ evthread_use_pthreads();
+
+ENDmodInit
+
+
+/* ------------------------------ callbacks ------------------------------ */
+
+
+/**
+ * Asynchronous subscribe callback handler
+ */
+static void redisAsyncRecvCallback (redisAsyncContext *aconn, void *reply, void __attribute__((unused)) *unused) {
+ /*
+ redisReply is supposed to be an array of three elements: [''message', <channel>, <message>]
+
+
+ JJO: For future reference (https://github.com/redis/hiredis/blob/master/README.md)
+
+ Important: the current version of hiredis (1.0.0) frees replies when the asynchronous API is used.
+ This means you should not call freeReplyObject when you use this API.
+ The reply is cleaned up by hiredis after the callback returns.
+ TODO We may have to change this function in the future to free replies.
+ */
+ instanceConf_t *const inst = (instanceConf_t *) aconn->data;
+ redisReply * r = (redisReply *) reply;
+ if (r == NULL) return;
+
+ if (r->elements < 3 || r->element[2]->str == NULL) {
+ return;
+ }
+ enqMsg(inst, r->element[2]->str, r->element[2]->len);
+
+ return;
+}
+
+
+/**
+ * Asynchronous connection callback handler
+ */
+static void redisAsyncConnectCallback (const redisAsyncContext *c, int status) {
+ if (status != REDIS_OK) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis (async): could not connect to redis: "
+ "%s", c->errstr);
+ // remove async context from instance config object, still contained in context's 'data' field
+ instanceConf_t *inst = (instanceConf_t *) c->data;
+ assert(inst != NULL);
+ inst->aconn = NULL;
+ return;
+ }
+ DBGPRINTF("imhiredis (async): successfully connected!\n");
+
+ return;
+}
+
+
+/**
+ * Asynchronous disconnection callback handler
+ */
+static void redisAsyncDisconnectCallback (const redisAsyncContext *c, int status) {
+
+ // remove context from instance config object (which is stored in the context 'data' field by us)
+ // context will be freed by the library, so it's only set to NULL here
+ instanceConf_t *inst = (instanceConf_t *) c->data;
+ assert(inst != NULL);
+ inst->aconn = NULL;
+ inst->currentNode = NULL;
+
+ if (status != REDIS_OK) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis (async): got disconnected from redis: "
+ "%s", c->errstr);
+ return;
+ }
+ DBGPRINTF("imhiredis (async): successfully disconnected!\n");
+
+ return;
+}
+
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+/*
+ * sends a ROLE command to the redis pointed by context
+ * context should be a valid redis context
+ * returns a valid redisReply pointer if an array reply was received, NULL otherwise
+ */
+redisReply *getRole(redisContext *c) {
+ redisReply *reply;
+
+ assert(c != NULL);
+
+ reply = redisCommand(c, "ROLE");
+ if (reply == NULL) {
+ DBGPRINTF("imhiredis: could not get reply from ROLE command\n");
+ }
+ else if (reply->type == REDIS_REPLY_ERROR) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis got an error while querying role -> "
+ "%s\n", reply->str);
+ freeReplyObject(reply);
+ reply = NULL;
+ }
+ else if (reply->type != REDIS_REPLY_ARRAY) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis: did not get an array from ROLE command");
+ freeReplyObject(reply);
+ reply = NULL;
+ }
+
+ return reply;
+}
+
+
+static struct json_object* _redisParseIntegerReply(const redisReply *reply) {
+ return json_object_new_int64(reply->integer);
+}
+
+#ifdef REDIS_REPLY_DOUBLE
+static struct json_object* _redisParseDoubleReply(const redisReply *reply) {
+ return json_object_new_double_s(reply->dval, reply->str);
+}
+#endif
+
+static struct json_object* _redisParseStringReply(const redisReply *reply) {
+ return json_object_new_string_len(reply->str, reply->len);
+}
+
+static struct json_object* _redisParseArrayReply(const redisReply *reply) {
+ struct json_object *result = NULL;
+ struct json_object *res = NULL;
+ char *key = NULL;
+
+ result = json_object_new_object(); // the redis type name is ARRAY, but represents a dict
+
+ if (result != NULL) {
+ for(size_t i = 0; i < reply->elements; i++) {
+ if (reply->element[i]->type == REDIS_REPLY_STRING && i % 2 == 0) {
+ key = reply->element[i]->str;
+ } else {
+ switch(reply->element[i]->type) {
+ case REDIS_REPLY_INTEGER:
+ res = _redisParseIntegerReply(reply->element[i]);
+ json_object_object_add(result, key, res);
+ break;
+#ifdef REDIS_REPLY_DOUBLE
+ case REDIS_REPLY_DOUBLE:
+ res = _redisParseDoubleReply(reply->element[i]);
+ json_object_object_add(result, key, res);
+ break;
+#endif
+ case REDIS_REPLY_STRING:
+ res = _redisParseStringReply(reply->element[i]);
+ json_object_object_add(result, key, res);
+ break;
+ case REDIS_REPLY_ARRAY:
+ res = _redisParseArrayReply(reply->element[i]);
+ json_object_object_add(result, key, res);
+ break;
+ default:
+ DBGPRINTF("Unhandled case!\n");
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING,
+ "Redis reply object contains an unhandled type!");
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * enqueue the hiredis message. The provided string is
+ * not freed - this must be done by the caller.
+ */
+static rsRetVal enqMsg(instanceConf_t *const inst, const char *message, size_t msgLen) {
+ DEFiRet;
+ smsg_t *pMsg;
+
+ if (message == NULL || message[0] == '\0') {
+ /* we do not process empty lines */
+ FINALIZE;
+ }
+
+ DBGPRINTF("imhiredis: enqMsg: Msg -> '%s'\n", message);
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, message, msgLen);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ CHKiRet(submitMsg2(pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal enqMsgJson(instanceConf_t *const inst, struct json_object *json, struct json_object *metadata) {
+ DEFiRet;
+ smsg_t *pMsg;
+ struct json_object *tempJson = NULL;
+
+ assert(json != NULL);
+
+ CHKiRet(msgConstruct(&pMsg)); // In case of allocation error -> needs to break
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ if(RS_RET_OK != MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY))
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING,
+ "Could not set Flow Control on message.");
+ if(inst->fieldList.nmemb != 0) {
+ for (int i = 0; i < inst->fieldList.nmemb; i++)
+ {
+ DBGPRINTF("processing field '%s'\n", inst->fieldList.name[i]);
+
+ /* case 1: static field. We simply forward it */
+ if (inst->fieldList.name[i][0] != '!' && inst->fieldList.name[i][0] != '.')
+ {
+ DBGPRINTF("field is static, taking it as it is...\n");
+ tempJson = json_object_new_string(inst->fieldList.name[i]);
+ }
+ /* case 2: dynamic field. We retrieve its value from the JSON logline and add it */
+ else
+ {
+ DBGPRINTF("field is dynamic, searching in root object...\n");
+ if (!json_object_object_get_ex(json, inst->fieldList.name[i]+1, &tempJson)) {
+
+ DBGPRINTF("Did not find value %s in message\n", inst->fieldList.name[i]);
+ continue;
+ }
+ // Getting object as it will not keep the same lifetime as its origin object
+ tempJson = json_object_get(tempJson);
+ // original object is put: no need for it anymore
+ json_object_put(json);
+ }
+
+ DBGPRINTF("got value of field '%s'\n", inst->fieldList.name[i]);
+ DBGPRINTF("will insert to '%s'\n", inst->fieldList.varname[i]);
+
+ if(RS_RET_OK != msgAddJSON(pMsg, (uchar *)inst->fieldList.varname[i], tempJson, 0, 0)) {
+ LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR,
+ "Failed to add value to '%s'", inst->fieldList.varname[i]);
+ }
+
+ tempJson = NULL;
+ }
+ } else {
+ if(RS_RET_OK != msgAddJSON(pMsg, (uchar*)"!", json, 0, 0)) {
+ LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR,
+ "Failed to add json info to message!");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+ }
+ if (metadata != NULL && RS_RET_OK != msgAddJSON(pMsg, (uchar*)".", metadata, 0, 0)) {
+ LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR,
+ "Failed to add metadata to message!");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+ if(RS_RET_OK != submitMsg2(pMsg)) {
+ LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR,
+ "Failed to submit message to main queue!");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+ DBGPRINTF("enqMsgJson: message enqueued!\n");
+
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * execute a synchronous authentication using the context conn
+ * conn and password should be non-NULL
+ * conn should be a valid context
+ */
+rsRetVal redisAuthentSynchronous(redisContext *conn, uchar *password) {
+ DEFiRet;
+ redisReply *reply = NULL;
+
+ assert(conn != NULL);
+ assert(password != NULL);
+ assert(password[0] != '\0');
+
+ reply = (redisReply *) redisCommand(conn, "AUTH %s", password);
+ if (reply == NULL) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: Could not authenticate!\n");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ } else if (strncmp(reply->str, "OK", 2)) {
+ LogError(0, RS_RET_REDIS_AUTH_FAILED, "imhiredis: Authentication failure -> %s\n", reply->str);
+ ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED);
+ }
+
+finalize_it:
+ if(reply)
+ freeReplyObject(reply);
+ RETiRet;
+}
+
+
+/*
+ * execute an asynchronous authentication using the context aconn
+ * aconn and password should be non-NULL
+ * aconn should be a valid (async) context
+ */
+rsRetVal redisAuthentAsynchronous(redisAsyncContext *aconn, uchar *password) {
+ DEFiRet;
+
+ assert(aconn != NULL);
+ assert(password != NULL);
+ assert(password[0] != '\0');
+
+ if (REDIS_OK != redisAsyncCommand(aconn, NULL, NULL, "AUTH %s", password)) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: error while authenticating asynchronously -> %s\n",
+ aconn->errstr);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * connect to node, authenticate (if necessary), get role, then get all node information provided by ROLE
+ * node should be a non-NULL valid redisNode pointer
+ * password can be NULL, meaning no authentication will be done
+ * result will hold the result of the ROLE command executed on the node:
+ * - NULL if the node was a single master instance
+ * - a single (master) node if the provided node was a replica
+ * - a list of (replica) nodes if the provided node was a master
+ */
+rsRetVal redisGetServersList(redisNode *node, uchar *password, redisNode **result) {
+ DEFiRet;
+ redisContext *context;
+ redisReply *reply = NULL, *replica;
+ unsigned int i;
+
+ assert(node != NULL);
+
+ CHKiRet(redisConnectSync(&context, node));
+
+ if(password != NULL && password[0] != '\0') {
+ CHKiRet(redisAuthentSynchronous(context, password));
+ }
+
+ reply = getRole(context);
+
+ if(reply == NULL) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: did not get the role of the server");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+ /*
+ * string comparisons for ROLE could be skipped
+ * as each role returns a different number of elements,
+ * but lets keep it as a security...
+ */
+ if ( reply->elements == 5 &&
+ strncmp(reply->element[0]->str, "slave", 5) == 0) {
+
+ CHKiRet(createRedisNode(result));
+ (*result)->server = (uchar *) strdup((const char *)reply->element[1]->str);
+ (*result)->port = reply->element[2]->integer;
+ (*result)->isMaster = 1;
+ }
+ else if ( reply->elements == 3 &&
+ reply->element[2]->type == REDIS_REPLY_ARRAY &&
+ strncmp(reply->element[0]->str, "master", 6) == 0) {
+
+ // iterate on all replicas given in the reply (if any)
+ for (i = 0; i < reply->element[2]->elements; i++) {
+ replica = reply->element[2]->element[i];
+
+ if (replica->type == REDIS_REPLY_ARRAY && replica->elements == 3) {
+ /* node will be a new node every time
+ * with old ones shifted in the list
+ */
+ CHKiRet(createRedisNode(result));
+ (*result)->server = (uchar *) strdup((const char *)replica->element[0]->str);
+ // yes, the value in that case is a string and NOT an integer!
+ (*result)->port = atoi(replica->element[1]->str);
+ }
+ }
+ } else {
+ // we have a sentinel, or a problem
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+finalize_it:
+ if (reply != NULL)
+ freeReplyObject(reply);
+ if (context != NULL)
+ redisFree(context);
+ RETiRet;
+}
+
+
+
+/*
+ * actualize the current master node to use during connection for instance inst
+ * inst should be a valid, non-NULL instanceConf object
+ * inst should also possess at least a single node in inst->redisNodeList
+ * if the function returns RS_RET_OK, inst->currentNode and inst->redisNodeList have been both updated
+ * to reflect new master and potential replicas
+ * the first configured node (called preferred node) is always kept as the first entry in redisNodeList
+ */
+rsRetVal redisActualizeCurrentNode(instanceConf_t *inst) {
+ DEFiRet;
+ redisReply *reply = NULL;
+ redisNode *node, *tmp, *newList = NULL;
+
+ assert(inst != NULL);
+ assert(inst->redisNodesList != NULL);
+
+ inst->currentNode = NULL;
+ // keep first node in list = preferred node (comes from configuration)
+ copyNode(inst->redisNodesList, &newList);
+ newList->next = NULL;
+
+ for (node = inst->redisNodesList; node != NULL; node = node->next) {
+ tmp = NULL;
+
+ DBGPRINTF("imhiredis: trying to connect to node to get info...\n");
+ dbgPrintNode(node);
+
+ if (RS_RET_OK == redisGetServersList(node, inst->password, &tmp)) {
+ // server replied
+
+ if (tmp && tmp->isMaster) {
+ DBGPRINTF("imhiredis: node replied with a master node, is a replica\n");
+ // master node, keep it as potential new active node
+ inst->currentNode = tmp;
+ tmp = NULL;
+
+ // try to connect to the master and get replicas
+ if(RS_RET_OK != redisGetServersList(inst->currentNode, inst->password, &tmp)) {
+
+ /* had a master, but cannot connect
+ * save suspected master in new list but keep searching with other nodes
+ */
+ DBGPRINTF("imhiredis: had a master but cannot connect, keeping in list\n");
+ dbgPrintNode(inst->currentNode);
+ insertNodeAfter(newList, inst->currentNode);
+ inst->currentNode = NULL;
+ continue;
+ }
+ } else {
+ DBGPRINTF("imhiredis: node replied with a list of replicas, is a master\n");
+ // copy the node to the new currentNode, list owning node will be freed
+ node->isMaster = 1;
+ copyNode(node, &(inst->currentNode));
+ inst->currentNode->next = NULL;
+ }
+
+ /*
+ * here, tmp is a list of replicas or NULL (single node)
+ * inst->currentNode is the new active master
+ */
+
+ // add the replicas to the list
+ if (tmp) {
+ insertNodeAfter(newList, tmp);
+ DBGPRINTF("imhiredis: inserting replicas to list\n");
+ for (tmp = newList->next; tmp != NULL; tmp = tmp->next) {
+ dbgPrintNode(tmp);
+ }
+ }
+ // insert the master after the preferred node (configuration)
+ DBGPRINTF("imhiredis: inserting new master node in list\n");
+ dbgPrintNode(inst->currentNode);
+ insertNodeAfter(newList, inst->currentNode);
+
+ // swap newList and redisNodesList to free old list at the end of the function
+ tmp = newList;
+ newList = inst->redisNodesList;
+ inst->redisNodesList = tmp;
+ FINALIZE;
+ }
+ }
+
+ DBGPRINTF("imhiredis: did not find a valid master");
+ iRet = RS_RET_NOT_FOUND;
+ inst->currentNode = NULL;
+
+finalize_it:
+ if (reply != NULL)
+ freeReplyObject(reply);
+ // newList is always completely freed
+ for (node = newList; node != NULL; ) {
+ node = freeNode(node);
+ }
+
+ RETiRet;
+}
+
+
+/*
+ * authentication function, for both synchronous and asynchronous modes (queue or subscribe)
+ * inst, inst->curentMode and inst->password should not be NULL
+ */
+rsRetVal redisAuthenticate(instanceConf_t *inst) {
+ DEFiRet;
+ redisContext *usedContext = NULL;
+ redisReply *reply = NULL;
+
+ assert(inst != NULL);
+ assert(inst->currentNode != NULL);
+ assert(inst->password != NULL);
+ assert(inst->password[0] != '\0');
+
+ DBGPRINTF("imhiredis: authenticating...\n");
+
+ // Create a temporary context for synchronous connection, used to validate AUTH command in asynchronous contexts
+ if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE) {
+ if (RS_RET_OK != redisConnectSync(&usedContext, inst->currentNode)) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: could not connect to current "
+ "active node synchronously to validate authentication");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+ } else {
+ usedContext = inst->conn;
+ }
+
+ /*
+ * Try synchronous connection, whatever the method for the instance
+ * This is also done for the asynchronous mode, to validate the successful authentication
+ */
+ CHKiRet(redisAuthentSynchronous(usedContext, inst->password));
+
+ if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE) {
+ CHKiRet(redisAuthentAsynchronous(inst->aconn, inst->password));
+ }
+
+ DBGPRINTF("imhiredis: authentication successful\n");
+
+finalize_it:
+ if(inst->mode == IMHIREDIS_MODE_SUBSCRIBE && usedContext)
+ redisFree(usedContext);
+ if(reply)
+ freeReplyObject(reply);
+ RETiRet;
+}
+
+
+/*
+ * connection function for synchronous (queue) mode
+ * node should not be NULL
+ */
+rsRetVal redisConnectSync(redisContext **conn, redisNode *node) {
+ DEFiRet;
+
+ assert(node != NULL);
+
+ if (node->usesSocket)
+ *conn = redisConnectUnixWithTimeout((const char *)node->socketPath, glblRedisConnectTimeout);
+ else
+ *conn = redisConnectWithTimeout((const char *)node->server, node->port, glblRedisConnectTimeout);
+
+ if (*conn == NULL) {
+ if (node->usesSocket) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s' "
+ "-> could not allocate context!\n", node->socketPath);
+ } else {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s', "
+ "port %d -> could not allocate context!\n", node->server, node->port);
+ }
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+ else if ((*conn)->err) {
+ if (node->usesSocket) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s' "
+ "-> %s\n", node->socketPath, (*conn)->errstr);
+ } else {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s', "
+ "port %d -> %s\n", node->server, node->port, (*conn)->errstr);
+ }
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (*conn)
+ redisFree(*conn);
+ *conn = NULL;
+ }
+ RETiRet;
+}
+
+
+/*
+ * connection function for asynchronous (subscribe) mode
+ * node should not be NULL
+ */
+rsRetVal redisConnectAsync(redisAsyncContext **aconn, redisNode *node) {
+ DEFiRet;
+
+ assert(node != NULL);
+
+ if (node->usesSocket)
+ *aconn = redisAsyncConnectUnix((const char*)node->socketPath);
+ else
+ *aconn = redisAsyncConnect((const char *)node->server, node->port);
+
+ if(*aconn == NULL) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): could not allocate context!\n");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ } else if ((*aconn)->err) {
+ if (node->usesSocket) {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): cannot connect to server '%s' "
+ "-> %s\n", node->socketPath, (*aconn)->errstr);
+ } else {
+ LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): cannot connect to server '%s', port '%d' "
+ "-> %s\n", node->server, node->port, (*aconn)->errstr);
+ }
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if(*aconn)
+ redisAsyncFree(*aconn);
+ *aconn = NULL;
+ }
+ RETiRet;
+}
+
+/*
+ * Helper method to connect to the current master asynchronously
+ * 'inst' parameter should be non-NULL and have a valid currentNode object
+ */
+rsRetVal connectMasterAsync(instanceConf_t *inst) {
+ DEFiRet;
+
+ if(RS_RET_OK != redisConnectAsync(&(inst->aconn), inst->currentNode)) {
+ inst->currentNode = NULL;
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+ if( inst->password != NULL &&
+ inst->password[0] != '\0' &&
+ RS_RET_OK != redisAuthenticate(inst)) {
+
+ redisAsyncFree(inst->aconn);
+ inst->aconn = NULL;
+ inst->currentNode = NULL;
+ ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED);
+ }
+
+ // finalize context creation
+ inst->aconn->data = (void *)inst;
+ redisAsyncSetConnectCallback(inst->aconn, redisAsyncConnectCallback);
+ redisAsyncSetDisconnectCallback(inst->aconn, redisAsyncDisconnectCallback);
+ redisLibeventAttach(inst->aconn, inst->evtBase);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * Helper method to check if (async) instance is connected
+ */
+static sbool isConnectedAsync(instanceConf_t *inst) {
+ return inst->aconn != NULL;
+}
+
+
+/*
+ * Helper method to connect to the current master synchronously
+ * 'inst' parameter should be non-NULL and have a valid currentNode object
+ */
+rsRetVal connectMasterSync(instanceConf_t *inst) {
+ DEFiRet;
+
+ if(RS_RET_OK != redisConnectSync(&(inst->conn), inst->currentNode)) {
+ inst->currentNode = NULL;
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+ if( inst->password != NULL &&
+ inst->password[0] != '\0' &&
+ RS_RET_OK != redisAuthenticate(inst)) {
+
+ redisFree(inst->conn);
+ inst->conn = NULL;
+ inst->currentNode = NULL;
+ ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * Helper method to check if instance is connected
+ */
+static sbool isConnectedSync(instanceConf_t *inst) {
+ return inst->conn != NULL;
+}
+
+/*
+ * dequeue all entries in the redis list, using batches of 10 commands
+ */
+rsRetVal redisDequeue(instanceConf_t *inst) {
+ DEFiRet;
+ redisReply *reply = NULL;
+ uint replyType = 0, i;
+
+ assert(inst != NULL);
+
+ DBGPRINTF("redisDequeue: beginning to dequeue key '%s'\n", inst->key);
+
+ do {
+ // append a batch of inst->batchsize POP commands (either LPOP or RPOP depending on conf)
+ if (inst->useLPop == 1) {
+ DBGPRINTF("redisDequeue: Queuing #%d LPOP commands on key '%s' \n",
+ inst->batchsize,
+ inst->key);
+ for (i=0; i<inst->batchsize; ++i ) {
+ if (REDIS_OK != redisAppendCommand(inst->conn, "LPOP %s", inst->key))
+ break;
+ }
+ } else {
+ DBGPRINTF("redisDequeue: Queuing #%d RPOP commands on key '%s' \n",
+ inst->batchsize,
+ inst->key);
+ for (i=0; i<inst->batchsize; i++) {
+ if (REDIS_OK != redisAppendCommand(inst->conn, "RPOP %s", inst->key))
+ break;
+ }
+ }
+
+ DBGPRINTF("redisDequeue: Dequeuing...\n")
+ // parse responses from appended commands
+ do {
+ if (REDIS_OK != redisGetReply(inst->conn, (void **) &reply)) {
+ // error getting reply, must stop
+ LogError(0, RS_RET_REDIS_ERROR, "redisDequeue: Error reading reply after POP #%d "
+ "on key '%s'", (inst->batchsize - i), inst->key);
+ // close connection
+ redisFree(inst->conn);
+ inst->currentNode = NULL;
+ inst->conn = NULL;
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ } else {
+ if (reply != NULL) {
+ replyType = reply->type;
+ switch(replyType) {
+ case REDIS_REPLY_STRING:
+ enqMsg(inst, reply->str, reply->len);
+ break;
+ case REDIS_REPLY_NIL:
+ // replies are dequeued but are empty = end of list
+ break;
+ case REDIS_REPLY_ERROR:
+ // There is a problem with the key or the Redis instance
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisDequeue: error "
+ "while POP'ing key '%s' -> %s", inst->key, reply->str);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ default:
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "redisDequeue: "
+ "unexpected reply type: %s", REDIS_REPLIES[replyType%15]);
+ }
+ freeReplyObject(reply);
+ reply = NULL;
+ } else { /* reply == NULL */
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisDequeue: unexpected empty reply "
+ "for successful return");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+ }
+
+ // while there are replies to unpack, continue
+ } while (--i > 0);
+
+ if(replyType == REDIS_REPLY_NIL) {
+ /* sleep 1s between 2 POP tries, when no new entries are available (list is empty)
+ * this does NOT limit dequeing rate, but prevents the input from polling Redis too often
+ */
+ for(i = 0; i < 10; i++) {
+ // Time to stop the thread
+ if (glbl.GetGlobalInputTermState() != 0)
+ FINALIZE;
+ // 100ms sleeps
+ srSleep(0, 100000);
+ }
+ }
+
+ // while input can run, continue with a new batch
+ } while (glbl.GetGlobalInputTermState() == 0);
+
+ DBGPRINTF("redisDequeue: finished to dequeue key '%s'\n", inst->key);
+
+finalize_it:
+ if (reply)
+ freeReplyObject(reply);
+ RETiRet;
+}
+
+
+rsRetVal ensureConsumerGroupCreated(instanceConf_t *inst) {
+ DEFiRet;
+ redisReply *reply = NULL;
+
+ DBGPRINTF("ensureConsumerGroupCreated: Creating group %s on stream %s\n", inst->streamConsumerGroup, inst->key);
+
+ reply = (redisReply *)redisCommand(inst->conn, "XGROUP CREATE %s %s %s MKSTREAM",
+ inst->key,
+ inst->streamConsumerGroup,
+ inst->streamReadFrom);
+ if(reply != NULL) {
+ switch(reply->type) {
+ case REDIS_REPLY_STATUS:
+ case REDIS_REPLY_STRING:
+ if(0 == strncmp("OK", reply->str, reply->len))
+ DBGPRINTF("ensureConsumerGroupCreated: Consumer group %s created successfully "
+ "for stream %s\n",
+ inst->streamConsumerGroup,
+ inst->key);
+ break;
+ case REDIS_REPLY_ERROR:
+ if(strcasestr(reply->str, "BUSYGROUP") != NULL) {
+ DBGPRINTF("ensureConsumerGroupCreated: Consumer group %s already exists for "
+ "stream %s, ignoring\n",
+ inst->streamConsumerGroup,
+ inst->key);
+ } else {
+ LogError(0, RS_RET_ERR, "ensureConsumerGroupCreated: An unknown error "
+ "occurred while creating a Consumer group %s on stream %s -> %s",
+ inst->streamConsumerGroup,
+ inst->key,
+ reply->str);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ break;
+ default:
+ LogError(0, RS_RET_ERR, "ensureConsumerGroupCreated: An unknown reply was received "
+ "-> %s", REDIS_REPLIES[(reply->type)%15]);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ LogError(0, RS_RET_REDIS_ERROR, "ensureConsumerGroupCreated: Could not create group %s on stream %s!",
+ inst->streamConsumerGroup,
+ inst->key);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+finalize_it:
+ if(reply != NULL)
+ freeReplyObject(reply);
+ RETiRet;
+}
+
+
+rsRetVal ackStreamIndex(instanceConf_t *inst, uchar *stream, uchar *group, uchar *index) {
+ DEFiRet;
+ redisReply *reply = NULL;
+
+ DBGPRINTF("ackStream: Acknowledging index '%s' in stream %s\n", index, stream);
+
+ reply = (redisReply *)redisCommand(inst->conn, "XACK %s %s %s",
+ stream,
+ group,
+ index);
+ if(reply != NULL) {
+ switch(reply->type) {
+ case REDIS_REPLY_INTEGER:
+ if(reply->integer == 1) {
+ DBGPRINTF("ackStreamIndex: index successfully acknowledged "
+ "for stream %s\n",
+ inst->key);
+ } else {
+ DBGPRINTF("ackStreamIndex: message was not acknowledged "
+ "-> already done?");
+ }
+ break;
+ case REDIS_REPLY_ERROR:
+ LogError(0, RS_RET_ERR, "ackStreamIndex: An error occurred "
+ "while trying to ACK message %s on %s[%s] -> %s",
+ index,
+ stream,
+ group,
+ reply->str);
+ ABORT_FINALIZE(RS_RET_ERR);
+ default:
+ LogError(0, RS_RET_ERR, "ackStreamIndex: unexpected reply type: %s",
+ REDIS_REPLIES[(reply->type)%15]);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ } else {
+ LogError(0, RS_RET_REDIS_ERROR, "ackStreamIndex: Could not ACK message with index %s for %s[%s]!",
+ index,
+ stream,
+ group);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+finalize_it:
+ if(reply != NULL) {
+ freeReplyObject(reply);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal enqueueRedisStreamReply(instanceConf_t *const inst, redisReply *reply) {
+ DEFiRet;
+ struct json_object *json = NULL, *metadata = NULL, *redis = NULL;
+
+ json = _redisParseArrayReply(reply->element[1]);
+
+ CHKmalloc(metadata = json_object_new_object());
+ CHKmalloc(redis = json_object_new_object());
+ json_object_object_add(redis, "stream", json_object_new_string((char *)inst->key));
+ json_object_object_add(redis, "index", _redisParseStringReply(reply->element[0]));
+ if(inst->streamConsumerGroup != NULL) {
+ json_object_object_add(redis, "group", json_object_new_string((char *)inst->streamConsumerGroup));
+ }
+ if(inst->streamConsumerName != NULL) {
+ json_object_object_add(redis, "consumer", json_object_new_string((char *)inst->streamConsumerName));
+ }
+
+ // ownership of redis object allocated by json_object_new_object() is taken by json
+ // no need to free/destroy/put redis object
+ json_object_object_add(metadata, "redis", redis);
+
+ CHKiRet(enqMsgJson(inst, json, metadata));
+ // enqueued message successfully, json and metadata objects are now owned by enqueued message
+ // no need to free/destroy/put json objects
+ json = NULL;
+ metadata = NULL;
+
+ if(inst->streamConsumerGroup != NULL && inst->streamConsumerACK) {
+ CHKiRet(ackStreamIndex(
+ inst,
+ (uchar *)inst->key,
+ inst->streamConsumerGroup,
+ (uchar *)reply->element[0]->str
+ ));
+ }
+
+finalize_it:
+ // If that happens, there was an error during one of the steps and the json object is not enqueued
+ if(json != NULL) json_object_put(json);
+ if(metadata != NULL) json_object_put(metadata);
+ RETiRet;
+}
+
+
+/*
+ * handle the hiredis Stream XREAD/XREADGROUP return objects. The provided reply is
+ * not freed - this must be done by the caller.
+ * example of stream to parse:
+ * 1) 1) "mystream" <- name of the stream indexes are from (list of streams requested)
+ * 2) 1) 1) "1681749395006-0" <- list of indexes returned for stream
+ * 2) 1) "key1"
+ * 2) "value1"
+ * 2) 1) "1681749409349-0"
+ * 2) 1) "key2"
+ * 2) "value2"
+ * 3) "key2.2"
+ * 4) "value2.2"
+ * json equivalent:
+ * [
+ * "mystream": [
+ * {
+ * "1681749395006-0": {
+ * "key1": "value1"
+ * }
+ * },
+ * {
+ * "1681749409349-0": {
+ * "key2": "value2",
+ * "key2.2": "value2.2"
+ * }
+ * }
+ * ]
+ * ]
+ */
+static rsRetVal handleRedisXREADReply(instanceConf_t *const inst, const redisReply *reply) {
+ DEFiRet;
+ redisReply *streamObj = NULL, *msgList = NULL, *msgObj = NULL;
+
+ if(reply == NULL || reply->type != REDIS_REPLY_ARRAY) {
+ /* we do not process empty or non-ARRAY lines */
+ DBGPRINTF("handleRedisXREADReply: object is not an array, ignoring\n");
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: object is not an array, ignoring");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ } else {
+ // iterating on streams
+ for(size_t i = 0; i < reply->elements; i++) {
+ streamObj = reply->element[i];
+ // object should contain the name of the stream, and an array containing the messages
+ if(streamObj->type != REDIS_REPLY_ARRAY || streamObj->elements != 2) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong object format, "
+ "object should contain the name of the stream and an array of messages");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+ if(streamObj->element[0]->type != REDIS_REPLY_STRING) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field format, "
+ "first entry is not a string (supposed to be stream name)");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ msgList = streamObj->element[1];
+
+ if(msgList->type != REDIS_REPLY_ARRAY) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field format, "
+ "second entry is not an array (supposed to be list of messages for stream)");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ DBGPRINTF("handleRedisXREADReply: enqueuing messages for stream '%s'\n",
+ streamObj->element[0]->str);
+
+ for(size_t j = 0; j < msgList->elements; j++) {
+ msgObj = msgList->element[j];
+ // Object should contain the name of the index, and its content(s)
+ if(msgObj->type != REDIS_REPLY_ARRAY || msgObj->elements != 2) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong object "
+ "format, object should contain the index and its content(s)");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+ if(msgObj->element[0]->type != REDIS_REPLY_STRING) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field "
+ "format, first entry should be a string (index name)");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ if(msgObj->type != REDIS_REPLY_ARRAY) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field "
+ "format, second entry should be an array (index content(s))");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ CHKiRet(enqueueRedisStreamReply(inst, msgObj));
+
+ // Update current stream index
+ memcpy(inst->streamReadFrom, msgObj->element[0]->str, msgObj->element[0]->len);
+ inst->streamReadFrom[msgObj->element[0]->len] = '\0';
+ DBGPRINTF("handleRedisXREADReply: current stream index is %s\n", inst->streamReadFrom);
+ }
+ }
+ }
+
+ DBGPRINTF("handleRedisXREADReply: finished enqueuing!\n");
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * handle the hiredis Stream XAUTOCLAIM return object. The provided reply is
+ * not freed - this must be done by the caller.
+ * example of stream to parse:
+ * 1) "1681904437564-0" <- next index to use for XAUTOCLAIM
+ * 2) 1) 1) "1681904437525-0" <- list of indexes reclaimed
+ * 2) 1) "toto"
+ * 2) "tata"
+ * 2) 1) "1681904437532-0"
+ * 2) 1) "titi"
+ * 2) "tutu"
+ * 3) (empty) <- indexes that no longer exist, were deleted from the PEL
+ * json equivalent:
+ * "1681904437564-0": [
+ * {
+ * "1681904437525-0": {
+ * "toto": "tata"
+ * }
+ * },
+ * {
+ * "1681904437532-0": {
+ * "titi": "tutu"
+ * }
+ * }
+ * ]
+ */
+static rsRetVal handleRedisXAUTOCLAIMReply(
+ instanceConf_t *const inst,
+ const redisReply *reply,
+ char **autoclaimIndex) {
+ DEFiRet;
+ redisReply *msgList = NULL, *msgObj = NULL;
+
+ if(reply == NULL || reply->type != REDIS_REPLY_ARRAY) {
+ /* we do not process empty or non-ARRAY lines */
+ DBGPRINTF("handleRedisXAUTOCLAIMReply: object is not an array, ignoring\n");
+ FINALIZE;
+ } else {
+ // Object should contain between 2 and 3 elements (depends on Redis server version)
+ if(reply->elements < 2 || reply->elements > 3) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: wrong number of fields, "
+ "cannot process entry");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+ if(reply->element[0]->type != REDIS_REPLY_STRING) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: the first element "
+ "is not a string, cannot process entry");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ msgList = reply->element[1];
+
+ if(msgList->type != REDIS_REPLY_ARRAY) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: the second element "
+ "is not an array, cannot process entry");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ DBGPRINTF("handleRedisXAUTOCLAIMReply: re-claiming messages for stream '%s'\n", inst->key);
+
+ for(size_t j = 0; j < msgList->elements; j++) {
+ msgObj = msgList->element[j];
+ // Object should contain the name of the index, and its content(s)
+ if(msgObj->type != REDIS_REPLY_ARRAY || msgObj->elements != 2) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: wrong message "
+ "format, cannot process");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+ if(msgObj->element[0]->type != REDIS_REPLY_STRING) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: first message "
+ "element not a string, cannot process");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ if(msgObj->type != REDIS_REPLY_ARRAY) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: second message "
+ "element not an array, cannot process");
+ ABORT_FINALIZE(RS_RET_OK_WARN);
+ }
+
+ CHKiRet(enqueueRedisStreamReply(inst, msgObj));
+ }
+
+ // Update current stream index with next index from XAUTOCLAIM
+ // No message has to be claimed after that if value is "0-0"
+ memcpy(*autoclaimIndex, reply->element[0]->str, reply->element[0]->len);
+ (*autoclaimIndex)[reply->element[0]->len] = '\0';
+ DBGPRINTF("handleRedisXAUTOCLAIMReply: next stream index is %s\n", (*autoclaimIndex));
+ }
+
+ DBGPRINTF("handleRedisXAUTOCLAIMReply: finished re-claiming!\n");
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * Read Redis stream
+ */
+rsRetVal redisStreamRead(instanceConf_t *inst) {
+ DEFiRet;
+ redisReply *reply = NULL;
+ uint replyType = 0;
+ sbool mustClaimIdle = 0;
+ char *autoclaimIndex = NULL;
+
+ assert(inst != NULL);
+
+ // Ensure stream group is created before reading from it
+ if(inst->streamConsumerGroup != NULL) {
+ CHKiRet(ensureConsumerGroupCreated(inst));
+ }
+
+
+ if(inst->streamAutoclaimIdleTime != 0) {
+ DBGPRINTF("redisStreamRead: getting pending entries for stream '%s' from '%s', with idle time %d\n",
+ inst->key, inst->streamReadFrom, inst->streamAutoclaimIdleTime);
+ CHKmalloc(autoclaimIndex = calloc(1, STREAM_INDEX_STR_MAXLEN));
+ // Cannot claim from '$', will have to claim from the beginning of the stream
+ if(inst->streamReadFrom[0] == '$') {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "Cannot claim pending entries from '$', "
+ "will have to claim from the beginning of the stream");
+ memcpy(autoclaimIndex, "0-0", 4);
+ } else {
+ memcpy(autoclaimIndex, inst->streamReadFrom, STREAM_INDEX_STR_MAXLEN);
+ }
+ mustClaimIdle = 1;
+ } else {
+ DBGPRINTF("redisStreamRead: beginning to read stream '%s' from '%s'\n",
+ inst->key, inst->streamReadFrom);
+ }
+
+ do {
+ if(inst->streamConsumerGroup == NULL) {
+ reply = (redisReply *)redisCommand(inst->conn, "XREAD COUNT %d BLOCK %d STREAMS %s %s",
+ BATCH_SIZE,
+ WAIT_TIME_MS,
+ inst->key,
+ inst->streamReadFrom);
+ } else {
+ if(mustClaimIdle) {
+ reply = (redisReply *)redisCommand(inst->conn,
+ "XAUTOCLAIM %s %s %s %d %s COUNT %d",
+ inst->key,
+ inst->streamConsumerGroup,
+ inst->streamConsumerName,
+ inst->streamAutoclaimIdleTime,
+ autoclaimIndex,
+ BATCH_SIZE);
+ } else {
+
+ reply = (redisReply *)redisCommand(inst->conn,
+ "XREADGROUP GROUP %s %s COUNT %d BLOCK %d STREAMS %s >",
+ inst->streamConsumerGroup,
+ inst->streamConsumerName,
+ BATCH_SIZE,
+ WAIT_TIME_MS,
+ inst->key);
+ }
+ }
+ if(reply == NULL) {
+ LogError(0, RS_RET_REDIS_ERROR, "redisStreamRead: Error while trying to read stream '%s'",
+ inst->key);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+ replyType = reply->type;
+ switch(replyType) {
+ case REDIS_REPLY_ARRAY:
+ DBGPRINTF("reply is an array, proceeding...\n");
+ if(mustClaimIdle) {
+ CHKiRet(handleRedisXAUTOCLAIMReply(inst, reply, &autoclaimIndex));
+ if(!strncmp(autoclaimIndex, "0-0", 4)) {
+ DBGPRINTF("redisStreamRead: Caught up with pending messages, "
+ "getting back to regular reads\n");
+ mustClaimIdle = 0;
+ }
+ } else {
+ CHKiRet(handleRedisXREADReply(inst, reply));
+ }
+ break;
+ case REDIS_REPLY_NIL:
+ // replies are dequeued but are empty = end of list
+ if(mustClaimIdle) mustClaimIdle = 0;
+ break;
+ case REDIS_REPLY_ERROR:
+ // There is a problem with the key or the Redis instance
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisStreamRead: error "
+ "while reading stream(s) -> %s", reply->str);
+ srSleep(1, 0);
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ default:
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "redisStreamRead: unexpected "
+ "reply type: %s", REDIS_REPLIES[replyType%15]);
+ }
+ freeReplyObject(reply);
+ reply = NULL;
+
+ // while input can run, continue with a new batch
+ } while (glbl.GetGlobalInputTermState() == 0);
+
+ DBGPRINTF("redisStreamRead: finished to dequeue key '%s'\n", inst->key);
+
+finalize_it:
+ if(reply != NULL)
+ freeReplyObject(reply);
+ if(inst->conn != NULL) {
+ redisFree(inst->conn);
+ inst->conn = NULL;
+ inst->currentNode = NULL;
+ }
+ if(autoclaimIndex != NULL)
+ free(autoclaimIndex);
+ RETiRet;
+}
+
+
+/*
+ * Subscribe to Redis channel
+ */
+rsRetVal redisSubscribe(instanceConf_t *inst) {
+ DEFiRet;
+
+ DBGPRINTF("redisSubscribe: subscribing to channel '%s'\n", inst->key);
+ int ret = redisAsyncCommand(
+ inst->aconn,
+ redisAsyncRecvCallback,
+ NULL,
+ "SUBSCRIBE %s",
+ inst->key);
+
+ if (ret != REDIS_OK) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisSubscribe: Could not subscribe");
+ ABORT_FINALIZE(RS_RET_REDIS_ERROR);
+ }
+
+ // Will block on this function as long as connection is open and event loop is not stopped
+ event_base_dispatch(inst->evtBase);
+ DBGPRINTF("redisSubscribe: finished.\n");
+
+finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * generic worker function
+ */
+void workerLoop(struct imhiredisWrkrInfo_s *me) {
+ uint i;
+ DBGPRINTF("workerLoop: beginning of worker loop...\n");
+
+ // Connect first time without delay
+ if (me->inst->currentNode != NULL) {
+ rsRetVal ret = me->fnConnectMaster(me->inst);
+ if(ret != RS_RET_OK) {
+ LogMsg(0, ret, LOG_WARNING, "workerLoop: Could not connect successfully to master");
+ }
+ }
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ if (!me->fnIsConnected(me->inst)) {
+ /*
+ * Sleep 10 seconds before attempting to resume a broken connexion
+ * (sleep small amounts to avoid missing termination status)
+ */
+ LogMsg(0, RS_RET_OK, LOG_INFO, "workerLoop: "
+ "no valid connection, sleeping 10 seconds before retrying...");
+ for(i = 0; i < 100; i++) {
+ // Rsyslog asked for shutdown, thread should be stopped
+ if (glbl.GetGlobalInputTermState() != 0)
+ goto end_loop;
+ // 100ms sleeps
+ srSleep(0, 100000);
+ }
+
+ // search the current master node
+ if (me->inst->currentNode == NULL) {
+ if(RS_RET_OK != redisActualizeCurrentNode(me->inst))
+ continue;
+ }
+
+ // connect to current master
+ if (me->inst->currentNode != NULL) {
+ rsRetVal ret = me->fnConnectMaster(me->inst);
+ if(ret != RS_RET_OK) {
+ LogMsg(0, ret, LOG_WARNING, "workerLoop: "
+ "Could not connect successfully to master");
+ }
+ }
+ }
+ if (me->fnIsConnected(me->inst)) {
+ me->fnRun(me->inst);
+ }
+ }
+
+end_loop:
+ return;
+}
+
+
+/*
+ * Workerthread function for a single hiredis consumer
+ */
+static void *
+imhirediswrkr(void *myself)
+{
+ struct imhiredisWrkrInfo_s *me = (struct imhiredisWrkrInfo_s*) myself;
+ DBGPRINTF("imhiredis: started hiredis consumer workerthread\n");
+ dbgPrintNode(me->inst->currentNode);
+
+ if(me->inst->mode == IMHIREDIS_MODE_QUEUE) {
+ me->fnConnectMaster = connectMasterSync;
+ me->fnIsConnected = isConnectedSync;
+ me->fnRun = redisDequeue;
+ }
+ else if (me->inst->mode == IMHIREDIS_MODE_STREAM) {
+ me->fnConnectMaster = connectMasterSync;
+ me->fnIsConnected = isConnectedSync;
+ me->fnRun = redisStreamRead;
+ }
+ else if (me->inst->mode == IMHIREDIS_MODE_SUBSCRIBE) {
+ me->fnConnectMaster = connectMasterAsync;
+ me->fnIsConnected = isConnectedAsync;
+ me->fnRun = redisSubscribe;
+ }
+
+ workerLoop(me);
+
+ DBGPRINTF("imhiredis: stopped hiredis consumer workerthread\n");
+ return NULL;
+}
+
+
+
+// -------------------------- redisNode functions -----------------------------------
+
+/*
+ * create a redisNode and set default values
+ * if a valid node is given as parameter, the new node is inserted as the new head of the linked list
+ */
+static rsRetVal
+createRedisNode(redisNode **root) {
+ redisNode *node;
+ DEFiRet;
+ CHKmalloc(node = malloc(sizeof(redisNode)));
+ node->port = 0;
+ node->server = NULL;
+ node->socketPath = NULL;
+ node->usesSocket = 0;
+ node->isMaster = 0;
+ node->next = NULL;
+
+ if ((*root) == NULL) {
+ *root = node;
+ } else {
+ node->next = (*root);
+ *root = node;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * make a complete copy of the src node into the newly-created node in dst
+ * if dst already contains a node, the new node will be added as the new head of the provided list
+ * src should not be NULL
+ */
+rsRetVal copyNode(redisNode *src, redisNode **dst) {
+ DEFiRet;
+
+ assert(src != NULL);
+
+ CHKiRet(createRedisNode(dst));
+
+ (*dst)->isMaster = src->isMaster;
+ (*dst)->next = src->next;
+ (*dst)->port = src->port;
+ (*dst)->usesSocket = src->usesSocket;
+
+ if (src->server)
+ (*dst)->server = (uchar *) strdup((const char *)src->server);
+ if (src->socketPath)
+ (*dst)->socketPath = (uchar *) strdup((const char *)src->socketPath);
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * free all ressources of the node
+ * will return next node if one is present, NULL otherwise
+ */
+redisNode *freeNode(redisNode *node) {
+ redisNode *ret = NULL;
+ if (node != NULL) {
+ if (node->next != NULL)
+ ret = node->next;
+
+ if(node->server != NULL)
+ free(node->server);
+ if(node->socketPath != NULL)
+ free(node->socketPath);
+ free(node);
+ }
+
+ return ret;
+}
+
+/*
+ * insert node 'elem' after node 'root' in the linked list
+ * both root and elem should not be NULL
+ */
+void insertNodeAfter(redisNode *root, redisNode *elem) {
+ assert(root != NULL);
+ assert(elem != NULL);
+
+ if(root->next != NULL) {
+ elem->next = root->next;
+ }
+ root->next = elem;
+
+ return;
+}
+
+void dbgPrintNode(redisNode *node) {
+ if (node != NULL) {
+ if (node->usesSocket) {
+ if (node->isMaster) {
+ DBGPRINTF("imhiredis: node is %s (master)\n", node->socketPath);
+ } else {
+ DBGPRINTF("imhiredis: node is %s (replica)\n", node->socketPath);
+ }
+ } else {
+ if (node->isMaster) {
+ DBGPRINTF("imhiredis: node is %s:%d (master)\n", node->server, node->port);
+ } else {
+ DBGPRINTF("imhiredis: node is %s:%d (replica)\n", node->server, node->port);
+ }
+ }
+ }
+ return;
+}
diff --git a/contrib/imhttp/Makefile.am b/contrib/imhttp/Makefile.am
new file mode 100644
index 0000000..ce64dc4
--- /dev/null
+++ b/contrib/imhttp/Makefile.am
@@ -0,0 +1,5 @@
+pkglib_LTLIBRARIES = imhttp.la
+
+imhttp_la_SOURCES = imhttp.c
+imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS)
+imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS)
diff --git a/contrib/imhttp/Makefile.in b/contrib/imhttp/Makefile.in
new file mode 100644
index 0000000..8eff726
--- /dev/null
+++ b/contrib/imhttp/Makefile.in
@@ -0,0 +1,795 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imhttp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imhttp_la_LIBADD =
+am_imhttp_la_OBJECTS = imhttp_la-imhttp.lo
+imhttp_la_OBJECTS = $(am_imhttp_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 =
+imhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imhttp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imhttp_la-imhttp.Plo
+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 = $(imhttp_la_SOURCES)
+DIST_SOURCES = $(imhttp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imhttp.la
+imhttp_la_SOURCES = imhttp.c
+imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS)
+imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS)
+all: 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) --gnu contrib/imhttp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imhttp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imhttp.la: $(imhttp_la_OBJECTS) $(imhttp_la_DEPENDENCIES) $(EXTRA_imhttp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imhttp_la_LINK) -rpath $(pkglibdir) $(imhttp_la_OBJECTS) $(imhttp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imhttp_la-imhttp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imhttp_la-imhttp.lo: imhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imhttp_la-imhttp.lo -MD -MP -MF $(DEPDIR)/imhttp_la-imhttp.Tpo -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imhttp_la-imhttp.Tpo $(DEPDIR)/imhttp_la-imhttp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imhttp.c' object='imhttp_la-imhttp.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) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imhttp_la-imhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imhttp/imhttp.c b/contrib/imhttp/imhttp.c
new file mode 100644
index 0000000..95704af
--- /dev/null
+++ b/contrib/imhttp/imhttp.c
@@ -0,0 +1,1326 @@
+/* imhttp.c
+ * This is an input module for receiving http input.
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "rsyslog.h"
+#include "cfsysline.h" /* access to config file objects */
+#include "module-template.h"
+#include "ruleset.h"
+#include "unicode-helper.h"
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "statsobj.h"
+#include "ratelimit.h"
+#include "dirty.h"
+
+#include "civetweb.h"
+#include <apr_base64.h>
+#include <apr_md5.h>
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imhttp")
+
+/* static data */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+#define CIVETWEB_OPTION_NAME_PORTS "listening_ports"
+#define CIVETWEB_OPTION_NAME_DOCUMENT_ROOT "document_root"
+#define MAX_READ_BUFFER_SIZE 16384
+#define INIT_SCRATCH_BUF_SIZE 4096
+/* General purpose buffer size. */
+#define IMHTTP_MAX_BUF_LEN (8192)
+
+struct option {
+ const char *name;
+ const char *val;
+};
+
+struct auth_s {
+ char workbuf[IMHTTP_MAX_BUF_LEN];
+ char* pworkbuf;
+ size_t workbuf_len;
+ char* pszUser;
+ char* pszPasswd;
+};
+
+struct data_parse_s {
+ sbool content_compressed;
+ sbool bzInitDone; /* did we do an init of zstrm already? */
+ z_stream zstrm; /* zip stream to use for tcp compression */
+ // Currently only used for octet specific parsing
+ enum {
+ eAtStrtFram,
+ eInOctetCnt,
+ eInMsg,
+ } inputState;
+ size_t iOctetsRemain; /* Number of Octets remaining in message */
+ enum {
+ TCP_FRAMING_OCTET_STUFFING,
+ TCP_FRAMING_OCTET_COUNTING
+ } framingMode;
+};
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ struct option ports;
+ struct option docroot;
+ struct option *options;
+ int nOptions;
+};
+
+struct instanceConf_s {
+ struct instanceConf_s *next;
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *pszEndpoint; /* endpoint to configure */
+ uchar *pszBasicAuthFile; /* file containing basic auth users/pass */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ ratelimit_t *ratelimiter;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ prop_t *pInputName;
+ sbool flowControl;
+ sbool bDisableLFDelim;
+ sbool bSuppOctetFram;
+ sbool bAddMetadata;
+};
+
+struct conn_wrkr_s {
+ struct data_parse_s parseState;
+ uchar* pMsg; /* msg scratch buffer */
+ size_t iMsg; /* index of next char to store in msg */
+ uchar zipBuf[64*1024];
+ multi_submit_t multiSub;
+ smsg_t *pMsgs[CONF_NUM_MULTISUB];
+ char *pReadBuf;
+ size_t readBufSize;
+ prop_t *propRemoteAddr;
+ const struct mg_request_info *pri; /* do not free me - used to hold a reference only */
+ char *pScratchBuf;
+ size_t scratchBufSize;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+static prop_t *pInputName = NULL;
+
+//static size_t s_iMaxLine = 16; /* get maximum size we currently support */
+static size_t s_iMaxLine = 16384; /* get maximum size we currently support */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ports", eCmdHdlrString, 0 },
+ { "documentroot", eCmdHdlrString, 0 },
+ { "liboptions", eCmdHdlrArray, 0 },
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+static struct cnfparamdescr inppdescr[] = {
+ { "endpoint", eCmdHdlrString, 0},
+ { "basicauthfile", eCmdHdlrString, 0},
+ { "ruleset", eCmdHdlrString, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "supportoctetcountedframing", eCmdHdlrBinary, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "addmetadata", eCmdHdlrBinary, 0 }
+};
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+static struct cnfparamblk inppblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+};
+
+static struct {
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted)
+ STATSCOUNTER_DEF(ctrFailed, mutCtrFailed);
+ STATSCOUNTER_DEF(ctrDiscarded, mutCtrDiscarded);
+} statsCounter;
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+#define min(a, b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+#define EXIT_URI "/exit"
+volatile int exitNow = 0;
+
+struct mg_callbacks callbacks;
+
+typedef struct httpserv_s {
+ struct mg_context *ctx;
+ struct mg_callbacks callbacks;
+ const char **civetweb_options;
+ size_t civetweb_options_count;
+} httpserv_t;
+
+static httpserv_t *s_httpserv;
+
+/* FORWARD DECLARATIONS */
+static rsRetVal processData(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len);
+
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = calloc(1, sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pBindRuleset = NULL;
+ inst->pszEndpoint = NULL;
+ inst->pszBasicAuthFile = NULL;
+ inst->ratelimiter = NULL;
+ inst->pszInputName = NULL;
+ inst->pInputName = NULL;
+ inst->ratelimitBurst = 10000; /* arbitrary high limit */
+ inst->ratelimitInterval = 0; /* off */
+ inst->flowControl = 1;
+ inst->bDisableLFDelim = 0;
+ inst->bSuppOctetFram = 0;
+ inst->bAddMetadata = 0;
+ // construct statsobj
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+processCivetwebOptions(char *const param,
+ const char **const name,
+ const char **const paramval)
+{
+ DEFiRet;
+ char *val = strstr(param, "=");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ *val = '\0'; /* terminates name */
+ ++val; /* now points to begin of value */
+ CHKmalloc(*name = strdup(param));
+ CHKmalloc(*paramval = strdup(val));
+
+finalize_it:
+ RETiRet;
+}
+
+static sbool valid_civetweb_option(const struct mg_option *valid_opts, const char* option)
+{
+ const struct mg_option *pvalid_opts = valid_opts;
+ for (; pvalid_opts != NULL && pvalid_opts->name != NULL; pvalid_opts++) {
+ if (strcmp(pvalid_opts->name, option) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#if 0
+static int
+log_message(__attribute__((unused)) const struct mg_connection *conn, const char *message)
+{
+ puts(message);
+ return 1;
+}
+#endif
+/*
+ * thread_type:
+ * 0 indicates the master thread
+ * 1 indicates a worker thread handling client connections
+ * 2 indicates an internal helper thread (timer thread)
+*/
+static void*
+init_thread(__attribute__((unused)) const struct mg_context *ctx, int thread_type)
+{
+ DEFiRet;
+ struct conn_wrkr_s *data = NULL;
+ if (thread_type == 1) {
+ CHKmalloc(data = calloc(1, sizeof(struct conn_wrkr_s)));
+ data->pMsg = NULL;
+ data->iMsg = 0;
+ data->parseState.bzInitDone = 0;
+ data->parseState.content_compressed = 0;
+ data->parseState.inputState = eAtStrtFram;
+ data->parseState.iOctetsRemain = 0;
+ data->multiSub.maxElem = CONF_NUM_MULTISUB;
+ data->multiSub.ppMsgs = data->pMsgs;
+ data->multiSub.nElem = 0;
+ data->pReadBuf = malloc(MAX_READ_BUFFER_SIZE);
+ data->readBufSize = MAX_READ_BUFFER_SIZE;
+
+ data->parseState.bzInitDone = 0;
+ data->parseState.content_compressed = 0;
+ data->parseState.inputState = eAtStrtFram;
+ data->parseState.iOctetsRemain = 0;
+
+ CHKmalloc(data->pMsg = calloc(1, 1 + s_iMaxLine));
+ data->iMsg = 0;
+ data->propRemoteAddr = NULL;
+ data->pScratchBuf = NULL;
+ data->scratchBufSize = 0;
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ free(data);
+ return NULL;
+ }
+ return data;
+}
+
+static void
+exit_thread(__attribute__((unused)) const struct mg_context *ctx,
+ __attribute__((unused)) int thread_type, void *thread_pointer)
+{
+ if (thread_type == 1) {
+ struct conn_wrkr_s *data = (struct conn_wrkr_s *) thread_pointer;
+ if (data->propRemoteAddr) {
+ prop.Destruct(&data->propRemoteAddr);
+ }
+ if (data->scratchBufSize) {
+ free(data->pScratchBuf);
+ }
+ free(data->pReadBuf);
+ free(data->pMsg);
+ free(data);
+ }
+}
+
+static rsRetVal
+msgAddMetadataFromHttpHeader(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr)
+{
+ struct json_object *json = NULL;
+ DEFiRet;
+ const struct mg_request_info *ri = connWrkr->pri;
+ #define MAX_HTTP_HEADERS 64 /* hard limit */
+ int count = min(ri->num_headers, MAX_HTTP_HEADERS);
+
+ CHKmalloc(json = json_object_new_object());
+ for (int i = 0 ; i < count ; i++ ) {
+ struct json_object *const jval = json_object_new_string(ri->http_headers[i].value);
+ CHKmalloc(jval);
+ /* truncate header names bigger than INIT_SCRATCH_BUF_SIZE */
+ strncpy(connWrkr->pScratchBuf, ri->http_headers[i].name, connWrkr->scratchBufSize - 1);
+ /* make header lowercase */
+ char* pname = connWrkr->pScratchBuf;
+ while (pname && *pname != '\0') {
+ *pname = tolower(*pname);
+ pname++;
+ }
+ json_object_object_add(json, (const char *const)connWrkr->pScratchBuf, jval);
+ }
+ CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!httpheaders", json, 0, 0));
+
+finalize_it:
+ if (iRet != RS_RET_OK && json) {
+ json_object_put(json);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+msgAddMetadataFromHttpQueryParams(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr)
+{
+ struct json_object *json = NULL;
+ DEFiRet;
+ const struct mg_request_info *ri = connWrkr->pri;
+
+ if (ri && ri->query_string) {
+ strncpy(connWrkr->pScratchBuf, ri->query_string, connWrkr->scratchBufSize - 1);
+ char *pquery_str = connWrkr->pScratchBuf;
+ if (pquery_str) {
+ CHKmalloc(json = json_object_new_object());
+
+ char* saveptr = NULL;
+ char *kv_pair = strtok_r(pquery_str, "&;", &saveptr);
+
+ for ( ; kv_pair != NULL; kv_pair = strtok_r(NULL, "&;", &saveptr)) {
+ char *saveptr2 = NULL;
+ char *key = strtok_r(kv_pair, "=", &saveptr2);
+ if (key) {
+ char *value = strtok_r(NULL, "=", &saveptr2);
+ struct json_object *const jval = json_object_new_string(value);
+ CHKmalloc(jval);
+ json_object_object_add(json, (const char *)key, jval);
+ }
+ }
+ CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!queryparams", json, 0, 0));
+ }
+ }
+finalize_it:
+ if (iRet != RS_RET_OK && json) {
+ json_object_put(json);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+doSubmitMsg(const instanceConf_t *const __restrict__ inst,
+ struct conn_wrkr_s *connWrkr, const uchar* msg, size_t len)
+{
+ smsg_t *pMsg;
+ DEFiRet;
+
+ assert(len <= s_iMaxLine);
+ if (len == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetFlowControlType(pMsg, inst->flowControl
+ ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY);
+ if (inst->pInputName) {
+ MsgSetInputName(pMsg, inst->pInputName);
+ } else {
+ MsgSetInputName(pMsg, pInputName);
+ }
+ MsgSetRawMsg(pMsg, (const char*)msg, len);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ if (connWrkr->propRemoteAddr) {
+ MsgSetRcvFromIP(pMsg, connWrkr->propRemoteAddr);
+ }
+ if (inst) {
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ }
+ // TODO: make these flags configurable.
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+
+ if (inst->bAddMetadata) {
+ CHKiRet(msgAddMetadataFromHttpHeader(pMsg, connWrkr));
+ CHKiRet(msgAddMetadataFromHttpQueryParams(pMsg, connWrkr));
+ }
+
+ ratelimitAddMsg(inst->ratelimiter, &connWrkr->multiSub, pMsg);
+ STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+finalize_it:
+ connWrkr->iMsg = 0;
+ if (iRet != RS_RET_OK) {
+ STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+processOctetMsgLen(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, char ch)
+{
+ DEFiRet;
+ if (connWrkr->parseState.inputState == eAtStrtFram) {
+ if (inst->bSuppOctetFram && isdigit(ch)) {
+ connWrkr->parseState.inputState = eInOctetCnt;
+ connWrkr->parseState.iOctetsRemain = 0;
+ connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_COUNTING;
+ } else {
+ connWrkr->parseState.inputState = eInMsg;
+ connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_STUFFING;
+ }
+ }
+
+ // parsing character.
+ if (connWrkr->parseState.inputState == eInOctetCnt) {
+ if (isdigit(ch)) {
+ if (connWrkr->parseState.iOctetsRemain <= 200000000) {
+ connWrkr->parseState.iOctetsRemain = connWrkr->parseState.iOctetsRemain * 10 + ch - '0';
+ }
+ // temporarily save this character into the message buffer
+ if(connWrkr->iMsg + 1 < s_iMaxLine) {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ const char *remoteAddr = "";
+ if (connWrkr->propRemoteAddr) {
+ remoteAddr = (const char *)propGetSzStr(connWrkr->propRemoteAddr);
+ }
+
+ /* handle space delimeter */
+ if (ch != ' ') {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message "
+ "from peer: (ip) %s: to input: %s, delimiter is not "
+ "SP but has ASCII value %d.",
+ remoteAddr, inst->pszInputName, ch);
+ }
+
+ if (connWrkr->parseState.iOctetsRemain < 1) {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message"
+ " from peer: (ip) %s: delimiter is not "
+ "SP but has ASCII value %d.",
+ remoteAddr, ch);
+ } else if (connWrkr->parseState.iOctetsRemain > s_iMaxLine) {
+ DBGPRINTF("truncating message with %lu octets - max msg size is %lu\n",
+ connWrkr->parseState.iOctetsRemain, s_iMaxLine);
+ LogError(0, NO_ERRCODE, "received oversize message from peer: "
+ "(hostname) (ip) %s: size is %lu bytes, max msg "
+ "size is %lu, truncating...",
+ remoteAddr, connWrkr->parseState.iOctetsRemain, s_iMaxLine);
+ }
+ connWrkr->parseState.inputState = eInMsg;
+ }
+ /* reset msg len for actual message processing */
+ connWrkr->iMsg = 0;
+ /* retrieve next character */
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processOctetCounting(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+ const uchar* pbuf = (const uchar*)buf;
+ const uchar* pbufLast = pbuf + len;
+
+ while (pbuf < pbufLast) {
+ char ch = *pbuf;
+
+ if (connWrkr->parseState.inputState == eAtStrtFram || connWrkr->parseState.inputState == eInOctetCnt) {
+ processOctetMsgLen(inst, connWrkr, ch);
+ if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING) {
+ pbuf++;
+ }
+ } else if (connWrkr->parseState.inputState == eInMsg) {
+ if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_STUFFING) {
+ if (connWrkr->iMsg < s_iMaxLine) {
+ if (ch == '\n') {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ } else {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ }
+ pbuf++;
+ } else {
+ assert (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING);
+ /* parsing payload */
+ size_t remainingBytes = pbufLast - pbuf;
+ // figure out how much is in block
+ size_t count = min (connWrkr->parseState.iOctetsRemain, remainingBytes);
+ if (connWrkr->iMsg + count >= s_iMaxLine) {
+ count = s_iMaxLine - connWrkr->iMsg;
+ }
+
+ // just copy the bytes
+ if (count) {
+ memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count);
+ pbuf += count;
+ connWrkr->iMsg += count;
+ connWrkr->parseState.iOctetsRemain -= count;
+ }
+
+ if (connWrkr->parseState.iOctetsRemain == 0) {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ }
+ }
+ } else {
+ // unexpected
+ assert(0);
+ break;
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDisableLF(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+ const uchar *pbuf = (const uchar*)buf;
+ size_t remainingBytes = len;
+ const uchar* pbufLast = pbuf + len;
+
+ while (pbuf < pbufLast) {
+ size_t count = 0;
+ if (connWrkr->iMsg + remainingBytes >= s_iMaxLine) {
+ count = s_iMaxLine - connWrkr->iMsg;
+ } else {
+ count = remainingBytes;
+ }
+
+ if (count) {
+ memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count);
+ pbuf += count;
+ connWrkr->iMsg += count;
+ remainingBytes -= count;
+ }
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDataUncompressed(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ const uchar *pbuf = (const uchar*)buf;
+ DEFiRet;
+
+ if (inst->bDisableLFDelim) {
+ /* do block processing */
+ iRet = processDisableLF(inst, connWrkr, buf, len);
+ } else if (inst->bSuppOctetFram) {
+ iRet = processOctetCounting(inst, connWrkr, buf, len);
+ } else {
+ const uchar* pbufLast = pbuf + len;
+ while (pbuf < pbufLast) {
+ char ch = *pbuf;
+ if (connWrkr->iMsg < s_iMaxLine) {
+ if (ch == '\n') {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ } else {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ }
+ pbuf++;
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDataCompressed(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+
+ if (!connWrkr->parseState.bzInitDone) {
+ /* allocate deflate state */
+ connWrkr->parseState.zstrm.zalloc = Z_NULL;
+ connWrkr->parseState.zstrm.zfree = Z_NULL;
+ connWrkr->parseState.zstrm.opaque = Z_NULL;
+ int rc = inflateInit2(&connWrkr->parseState.zstrm, (MAX_WBITS | 16));
+ if (rc != Z_OK) {
+ dbgprintf("imhttp: error %d returned from zlib/inflateInit()\n", rc);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ connWrkr->parseState.bzInitDone = 1;
+ }
+
+ connWrkr->parseState.zstrm.next_in = (Bytef*) buf;
+ connWrkr->parseState.zstrm.avail_in = len;
+ /* run inflate() on buffer until everything has been uncompressed */
+ int outtotal = 0;
+ do {
+ int zRet = 0;
+ int outavail = 0;
+ dbgprintf("imhttp: in inflate() loop, avail_in %d, total_in %ld\n",
+ connWrkr->parseState.zstrm.avail_in, connWrkr->parseState.zstrm.total_in);
+
+ connWrkr->parseState.zstrm.avail_out = sizeof(connWrkr->zipBuf);
+ connWrkr->parseState.zstrm.next_out = connWrkr->zipBuf;
+ zRet = inflate(&connWrkr->parseState.zstrm, Z_SYNC_FLUSH);
+ dbgprintf("imhttp: inflate(), ret: %d, avail_out: %d\n", zRet, connWrkr->parseState.zstrm.avail_out);
+ outavail = sizeof(connWrkr->zipBuf) - connWrkr->parseState.zstrm.avail_out;
+ if (outavail != 0) {
+ outtotal += outavail;
+ CHKiRet(processDataUncompressed(inst, connWrkr, (const char*)connWrkr->zipBuf, outavail));
+ }
+ } while (connWrkr->parseState.zstrm.avail_out == 0);
+
+ dbgprintf("imhttp: processDataCompressed complete, sizes: in %lld, out %llu\n", (long long) len,
+ (long long unsigned) outtotal);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+processData(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+
+ //inst->bDisableLFDelim = 0;
+ if (connWrkr->parseState.content_compressed) {
+ iRet = processDataCompressed(inst, connWrkr, buf, len);
+ } else {
+ iRet = processDataUncompressed(inst, connWrkr, buf, len);
+ }
+
+ RETiRet;
+}
+
+/* Return 1 on success. Always initializes the auth structure. */
+static int
+parse_auth_header(struct mg_connection *conn, struct auth_s *auth)
+{
+ if (!auth || !conn) {
+ return 0;
+ }
+
+ const char *auth_header = NULL;
+ if (((auth_header = mg_get_header(conn, "Authorization")) == NULL) ||
+ strncasecmp(auth_header, "Basic ", 6) != 0) {
+ return 0;
+ }
+
+ /* Parse authorization header */
+ const char* src = auth_header + 6;
+ size_t len = apr_base64_decode_len((const char*)src);
+ auth->pworkbuf = auth->workbuf;
+ if (len > sizeof(auth->workbuf)) {
+ auth->pworkbuf = calloc(0, len);
+ auth->workbuf_len = len;
+ }
+ len = apr_base64_decode(auth->pworkbuf, src);
+ if (len == 0) {
+ return 0;
+ }
+
+ char *passwd = NULL, *saveptr = NULL;
+ char *user = strtok_r(auth->pworkbuf, ":", &saveptr);
+ if (user) {
+ passwd = strtok_r(NULL, ":", &saveptr);
+ }
+
+ auth->pszUser = user;
+ auth->pszPasswd = passwd;
+
+ return 1;
+}
+
+static int
+read_auth_file(FILE* filep, struct auth_s *auth)
+{
+ if (!filep) {
+ return 0;
+ }
+ char workbuf[IMHTTP_MAX_BUF_LEN];
+ size_t l = 0;
+ char* user;
+ char* passwd;
+
+ while (fgets(workbuf, sizeof(workbuf), filep)) {
+ l = strnlen(workbuf, sizeof(workbuf));
+ while (l > 0) {
+ if (isspace(workbuf[l-1]) || iscntrl(workbuf[l-1])) {
+ l--;
+ workbuf[l] = 0;
+ } else {
+ break;
+ }
+ }
+
+ if (l < 1) {
+ continue;
+ }
+
+ if (workbuf[0] == '#') {
+ continue;
+ }
+
+ user = workbuf;
+ passwd = strchr(workbuf, ':');
+ if (!passwd) {
+ continue;
+ }
+ *passwd = '\0';
+ passwd++;
+
+ if (!strcasecmp(auth->pszUser, user)) {
+ return (apr_password_validate(auth->pszPasswd, passwd) == APR_SUCCESS);
+ }
+ }
+ return 0;
+}
+
+/* Authorize against the opened passwords file. Return 1 if authorized. */
+static int
+authorize(struct mg_connection* conn, FILE* filep)
+{
+ if (!conn || !filep) {
+ return 0;
+ }
+
+ struct auth_s auth = { .workbuf_len=0, .pworkbuf=NULL, .pszUser=NULL, .pszPasswd=NULL};
+ if (!parse_auth_header(conn, &auth)) {
+ return 0;
+ }
+
+ /* validate against htpasswd file */
+ return read_auth_file(filep, &auth);
+}
+
+/* Provides Basic Authorization handling that validates against a 'htpasswd' file.
+ see also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
+*/
+static int
+basicAuthHandler(struct mg_connection *conn, void *cbdata)
+{
+ const instanceConf_t* inst = (const instanceConf_t*) cbdata;
+ char errStr[512];
+ FILE *fp = NULL;
+ int ret = 1;
+
+ if (!inst->pszBasicAuthFile) {
+ mg_cry(conn, "warning: 'BasicAuthFile' not configured.\n");
+ ret = 0;
+ goto finalize;
+ }
+
+ fp = fopen((const char *)inst->pszBasicAuthFile, "r");
+ if (fp == NULL) {
+ if (strerror_r(errno, errStr, sizeof(errStr)) == 0) {
+ mg_cry(conn,
+ "error: 'BasicAuthFile' file '%s' could not be accessed: %s\n",
+ inst->pszBasicAuthFile, errStr);
+ } else {
+ mg_cry(conn,
+ "error: 'BasicAuthFile' file '%s' could not be accessed: %d\n",
+ inst->pszBasicAuthFile, errno);
+ }
+ ret = 0;
+ goto finalize;
+ }
+
+ ret = authorize(conn, fp);
+
+finalize:
+ if (!ret) {
+ mg_send_http_error(conn, 401, "WWW-Authenticate: Basic realm=\"User Visible Realm\"\n");
+ }
+ if (fp ) {
+ fclose(fp);
+ }
+ return ret;
+}
+
+/* cbdata should actually contain instance data and we can actually use this instance data
+ * to hold reusable scratch buffer.
+ */
+static int
+postHandler(struct mg_connection *conn, void *cbdata)
+{
+ int rc = 1;
+ instanceConf_t* inst = (instanceConf_t*) cbdata;
+ const struct mg_request_info *ri = mg_get_request_info(conn);
+ struct conn_wrkr_s *connWrkr = mg_get_thread_pointer(conn);
+ connWrkr->multiSub.nElem = 0;
+ memset(&connWrkr->parseState, 0, sizeof(connWrkr->parseState));
+ connWrkr->pri = ri;
+
+ if (inst->bAddMetadata && connWrkr->scratchBufSize == 0) {
+ connWrkr->pScratchBuf = calloc(1, INIT_SCRATCH_BUF_SIZE);
+ if (!connWrkr->pScratchBuf) {
+ mg_cry(conn, "%s() - could not alloc scratch buffer!\n", __FUNCTION__);
+ rc = 500;
+ FINALIZE;
+ }
+ connWrkr->scratchBufSize = INIT_SCRATCH_BUF_SIZE;
+ }
+
+ if (0 != strcmp(ri->request_method, "POST")) {
+ /* Not a POST request */
+ int ret = mg_get_request_link(conn, connWrkr->pReadBuf, connWrkr->readBufSize);
+ mg_printf(conn,
+ "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
+ mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+ mg_printf(conn,
+ "%s method not allowed in the POST handler\n",
+ ri->request_method);
+ if (ret >= 0) {
+ mg_printf(conn,
+ "use a web tool to send a POST request to %s\n",
+ connWrkr->pReadBuf);
+ }
+ STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ rc = 405;
+ FINALIZE;
+ }
+
+ if (ri->remote_addr[0] != '\0') {
+ size_t len = strnlen(ri->remote_addr, sizeof(ri->remote_addr));
+ prop.CreateOrReuseStringProp(&connWrkr->propRemoteAddr, (const uchar*)ri->remote_addr, len);
+ }
+
+ if (ri->content_length >= 0) {
+ /* We know the content length in advance */
+ if (ri->content_length > (long long) connWrkr->readBufSize) {
+ connWrkr->pReadBuf = realloc(connWrkr->pReadBuf, ri->content_length+1);
+ if (!connWrkr->pReadBuf) {
+ mg_cry(conn, "%s() - realloc failed!\n", __FUNCTION__);
+ FINALIZE;
+ }
+ connWrkr->readBufSize = ri->content_length+1;
+ }
+ } else {
+ /* We must read until we find the end (chunked encoding
+ * or connection close), indicated my mg_read returning 0 */
+ }
+
+ if (ri->num_headers > 0) {
+ int i;
+ for (i = 0; i < ri->num_headers; i++) {
+ if (!strcasecmp(ri->http_headers[i].name, "content-encoding") &&
+ !strcasecmp(ri->http_headers[i].value, "gzip")) {
+ connWrkr->parseState.content_compressed = 1;
+ }
+ }
+ }
+
+ while (1) {
+ int count = mg_read(conn, connWrkr->pReadBuf, connWrkr->readBufSize);
+ if (count > 0) {
+ processData(inst, connWrkr, (const char*)connWrkr->pReadBuf, count);
+ } else {
+ break;
+ }
+ }
+
+ /* submit remainder */
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ multiSubmitFlush(&connWrkr->multiSub);
+
+ mg_send_http_ok(conn, "text/plain", 0);
+ rc = 200;
+
+finalize_it:
+ if (connWrkr->parseState.bzInitDone) {
+ inflateEnd(&connWrkr->parseState.zstrm);
+ }
+ /* reset */
+ connWrkr->iMsg = 0;
+
+ return rc;
+}
+
+static int runloop(void)
+{
+ dbgprintf("imhttp started.\n");
+
+ /* Add handler for form data */
+ for(instanceConf_t *inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ assert(inst->pszEndpoint);
+ if (inst->pszEndpoint) {
+ dbgprintf("setting request handler: '%s'\n", inst->pszEndpoint);
+ mg_set_request_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, postHandler, inst);
+ if (inst->pszBasicAuthFile) {
+ mg_set_auth_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, basicAuthHandler, inst);
+ }
+ }
+ }
+
+ /* Wait until the server should be closed */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ sleep(1);
+ }
+ return EXIT_SUCCESS;
+}
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imhttp)\n");
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imhttp: required parameter are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imtcp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "endpoint")) {
+ inst->pszEndpoint = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "basicauthfile")) {
+ inst->pszBasicAuthFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->flowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "disablelfdelimiter")) {
+ inst->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if (!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) {
+ inst->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if (!strcmp(inppblk.descr[i].name, "addmetadata")) {
+ inst->bAddMetadata = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imhttp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ if (inst->pszInputName) {
+ CHKiRet(prop.Construct(&inst->pInputName));
+ CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(inst->pInputName));
+ }
+ CHKiRet(ratelimitNew(&inst->ratelimiter, "imphttp", NULL));
+ ratelimitSetLinuxLike(inst->ratelimiter, inst->ratelimitInterval, inst->ratelimitBurst);
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ loadModConf->ports.name = NULL;
+ loadModConf->docroot.name = NULL;
+ loadModConf->nOptions = 0;
+ loadModConf->options = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imhttp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imhttp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(int i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "ports")) {
+ assert(loadModConf->ports.name == NULL);
+ assert(loadModConf->ports.val == NULL);
+ loadModConf->ports.name = strdup(CIVETWEB_OPTION_NAME_PORTS);
+ loadModConf->ports.val = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(modpblk.descr[i].name, "documentroot")) {
+ assert(loadModConf->docroot.name == NULL);
+ assert(loadModConf->docroot.val == NULL);
+ loadModConf->docroot.name = strdup(CIVETWEB_OPTION_NAME_DOCUMENT_ROOT);
+ loadModConf->docroot.val = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "liboptions")) {
+ loadModConf->nOptions = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(loadModConf->options = malloc(sizeof(struct option) *
+ pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processCivetwebOptions(cstr, &loadModConf->options[j].name,
+ &loadModConf->options[j].val));
+ free(cstr);
+ }
+ } else {
+ dbgprintf("imhttp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imhttp: ruleset '%s' for %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszEndpoint);
+}
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ /* verify civetweb options are valid */
+ const struct mg_option *valid_opts = mg_get_valid_options();
+ for (int i = 0; i < pModConf->nOptions; ++i) {
+ if (!valid_civetweb_option(valid_opts, pModConf->options[i].name)) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "imhttp: module loaded, but "
+ "invalid civetweb option found - imhttp may not receive connections.");
+ iRet = RS_RET_CONF_PARSE_WARNING;
+ }
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+
+ if (!s_httpserv) {
+ CHKmalloc(s_httpserv = calloc(1, sizeof(httpserv_t)));
+ }
+ /* options represents (key, value) so allocate 2x, and null terminated */
+ size_t count = 1;
+ if (runModConf->ports.val) {
+ count += 2;
+ }
+ if (runModConf->docroot.val) {
+ count += 2;
+ }
+ count += (2 * runModConf->nOptions);
+ CHKmalloc(s_httpserv->civetweb_options = calloc(count, sizeof(*s_httpserv->civetweb_options)));
+
+ const char **pcivetweb_options = s_httpserv->civetweb_options;
+ if (runModConf->nOptions) {
+ s_httpserv->civetweb_options_count = count;
+ for (int i = 0; i < runModConf->nOptions; ++i) {
+ *pcivetweb_options = runModConf->options[i].name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->options[i].val;
+ pcivetweb_options++;
+ }
+ }
+ /* append port, docroot */
+ if (runModConf->ports.val) {
+ *pcivetweb_options = runModConf->ports.name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->ports.val;
+ pcivetweb_options++;
+ }
+ if (runModConf->docroot.val) {
+ *pcivetweb_options = runModConf->docroot.name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->docroot.val;
+ pcivetweb_options++;
+ }
+
+ const char **option = s_httpserv->civetweb_options;
+ for (; option && *option != NULL; option++) {
+ dbgprintf("imhttp: civetweb option: %s\n", *option);
+ }
+
+ CHKiRet(statsobj.Construct(&statsCounter.stats));
+ CHKiRet(statsobj.SetName(statsCounter.stats, UCHAR_CONSTANT("imhttp")));
+ CHKiRet(statsobj.SetOrigin(statsCounter.stats, UCHAR_CONSTANT("imhttp")));
+ STATSCOUNTER_INIT(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrSubmitted)));
+
+ STATSCOUNTER_INIT(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("failed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrFailed)));
+
+ STATSCOUNTER_INIT(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("discarded"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrDiscarded)));
+
+ CHKiRet(statsobj.ConstructFinalize(statsCounter.stats));
+
+ /* init civetweb libs and start server w/no input */
+ mg_init_library(MG_FEATURES_TLS);
+ memset(&callbacks, 0, sizeof(callbacks));
+ //callbacks.log_message = log_message;
+ //callbacks.init_ssl = init_ssl;
+ callbacks.init_thread = init_thread;
+ callbacks.exit_thread = exit_thread;
+ s_httpserv->ctx = mg_start(&callbacks, NULL, s_httpserv->civetweb_options);
+ /* Check return value: */
+ if (s_httpserv->ctx == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "Cannot start CivetWeb - mg_start failed.\n");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+
+ finalize_it:
+ if (iRet != RS_RET_OK) {
+ free(s_httpserv);
+ s_httpserv = NULL;
+ LogError(0, NO_ERRCODE, "imhttp: error %d trying to activate configuration", iRet);
+ }
+ RETiRet;
+ENDactivateCnf
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ if (inst->ratelimiter) {
+ ratelimitDestruct(inst->ratelimiter);
+ }
+ if (inst->pInputName) {
+ prop.Destruct(&inst->pInputName);
+ }
+ free(inst->pszEndpoint);
+ free(inst->pszBasicAuthFile);
+ free(inst->pszBindRuleset);
+ free(inst->pszInputName);
+
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+
+ for (int i = 0; i < pModConf->nOptions; ++i) {
+ free((void*) pModConf->options[i].name);
+ free((void*) pModConf->options[i].val);
+ }
+ free(pModConf->options);
+
+ free((void*)pModConf->ports.name);
+ free((void*)pModConf->ports.val);
+ free((void*)pModConf->docroot.name);
+ free((void*)pModConf->docroot.val);
+
+ if (statsCounter.stats) {
+ statsobj.Destruct(&statsCounter.stats);
+ }
+ENDfreeCnf
+
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ runloop();
+ENDrunInput
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+BEGINafterRun
+CODESTARTafterRun
+ if (s_httpserv) {
+ mg_stop(s_httpserv->ctx);
+ mg_exit_library();
+ free(s_httpserv->civetweb_options);
+ free(s_httpserv);
+ }
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ // if(eFeat == sFEATURENonCancelInputTermination)
+ // iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL) {
+ prop.Destruct(&pInputName);
+ }
+
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imhttp"), sizeof("imhttp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+ENDmodInit
diff --git a/contrib/imkmsg/Makefile.am b/contrib/imkmsg/Makefile.am
new file mode 100644
index 0000000..87c177d
--- /dev/null
+++ b/contrib/imkmsg/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = imkmsg.la
+imkmsg_la_SOURCES = imkmsg.c imkmsg.h
+
+imkmsg_la_SOURCES += kmsg.c
+
+imkmsg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imkmsg_la_LDFLAGS = -module -avoid-version
+imkmsg_la_LIBADD =
diff --git a/contrib/imkmsg/Makefile.in b/contrib/imkmsg/Makefile.in
new file mode 100644
index 0000000..e58e4ff
--- /dev/null
+++ b/contrib/imkmsg/Makefile.in
@@ -0,0 +1,807 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/imkmsg
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imkmsg_la_DEPENDENCIES =
+am_imkmsg_la_OBJECTS = imkmsg_la-imkmsg.lo imkmsg_la-kmsg.lo
+imkmsg_la_OBJECTS = $(am_imkmsg_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 =
+imkmsg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imkmsg_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imkmsg_la-imkmsg.Plo \
+ ./$(DEPDIR)/imkmsg_la-kmsg.Plo
+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 = $(imkmsg_la_SOURCES)
+DIST_SOURCES = $(imkmsg_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imkmsg.la
+imkmsg_la_SOURCES = imkmsg.c imkmsg.h kmsg.c
+imkmsg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imkmsg_la_LDFLAGS = -module -avoid-version
+imkmsg_la_LIBADD =
+all: 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) --gnu contrib/imkmsg/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imkmsg/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imkmsg.la: $(imkmsg_la_OBJECTS) $(imkmsg_la_DEPENDENCIES) $(EXTRA_imkmsg_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imkmsg_la_LINK) -rpath $(pkglibdir) $(imkmsg_la_OBJECTS) $(imkmsg_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkmsg_la-imkmsg.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkmsg_la-kmsg.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imkmsg_la-imkmsg.lo: imkmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkmsg_la-imkmsg.lo -MD -MP -MF $(DEPDIR)/imkmsg_la-imkmsg.Tpo -c -o imkmsg_la-imkmsg.lo `test -f 'imkmsg.c' || echo '$(srcdir)/'`imkmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkmsg_la-imkmsg.Tpo $(DEPDIR)/imkmsg_la-imkmsg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imkmsg.c' object='imkmsg_la-imkmsg.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) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkmsg_la-imkmsg.lo `test -f 'imkmsg.c' || echo '$(srcdir)/'`imkmsg.c
+
+imkmsg_la-kmsg.lo: kmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkmsg_la-kmsg.lo -MD -MP -MF $(DEPDIR)/imkmsg_la-kmsg.Tpo -c -o imkmsg_la-kmsg.lo `test -f 'kmsg.c' || echo '$(srcdir)/'`kmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkmsg_la-kmsg.Tpo $(DEPDIR)/imkmsg_la-kmsg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmsg.c' object='imkmsg_la-kmsg.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) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkmsg_la-kmsg.lo `test -f 'kmsg.c' || echo '$(srcdir)/'`kmsg.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imkmsg_la-imkmsg.Plo
+ -rm -f ./$(DEPDIR)/imkmsg_la-kmsg.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imkmsg_la-imkmsg.Plo
+ -rm -f ./$(DEPDIR)/imkmsg_la-kmsg.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imkmsg/imkmsg.c b/contrib/imkmsg/imkmsg.c
new file mode 100644
index 0000000..9018b0b
--- /dev/null
+++ b/contrib/imkmsg/imkmsg.c
@@ -0,0 +1,372 @@
+/* The kernel log module.
+ *
+ * This is rsyslog Linux only module for reading structured kernel logs.
+ * Module is based on imklog module so it retains its structure
+ * and other part is currently in kmsg.c file instead of this (imkmsg.c)
+ * For more information see that file.
+ *
+ * To test under Linux:
+ * echo test1 > /dev/kmsg
+ *
+ * Copyright (C) 2008-2023 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#include "dirty.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "msg.h"
+#include "module-template.h"
+#include "datetime.h"
+#include "imkmsg.h"
+#include "net.h"
+#include "glbl.h"
+#include "prop.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imkmsg")
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+
+/* config settings */
+typedef struct configSettings_s {
+ int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */
+} configSettings_t;
+static configSettings_t cs;
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "parsekerneltimestamp", eCmdHdlrGetWord, 0 },
+ { "readmode", eCmdHdlrGetWord, 0 },
+ { "expectedbootcompleteseconds", eCmdHdlrPositiveInt, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this module */
+static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */
+
+static inline void
+initConfigSettings(void)
+{
+ cs.iFacilIntMsg = klogFacilIntMsg();
+}
+
+
+/* enqueue the the kernel message into the message queue.
+ * The provided msg string is not freed - thus must be done
+ * by the caller.
+ * rgerhards, 2008-04-12
+ */
+static rsRetVal
+enqMsg(uchar *msg, uchar* pszTag, syslog_pri_t pri, struct timeval *tp, struct json_object *json)
+{
+ struct syslogTime st;
+ smsg_t *pMsg;
+ DEFiRet;
+
+ assert(msg != NULL);
+ assert(pszTag != NULL);
+
+ if(tp == NULL) {
+ CHKiRet(msgConstruct(&pMsg));
+ } else {
+ datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
+ CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
+ }
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsgWOSize(pMsg, (char*)msg);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, pLocalHostIP);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
+ msgSetPRI(pMsg, pri);
+ pMsg->json = json;
+ CHKiRet(submitMsg2(pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* log an imkmsg-internal message
+ * rgerhards, 2008-04-14
+ */
+rsRetVal imkmsgLogIntMsg(syslog_pri_t priority, const char *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+ uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
+
+ va_start(ap, fmt);
+ vsnprintf((char*)msgBuf, sizeof(msgBuf), fmt, ap);
+ va_end(ap);
+
+ logmsgInternal(NO_ERRCODE, priority, msgBuf, 0);
+
+ RETiRet;
+}
+
+
+/* log a message from /dev/kmsg
+ */
+rsRetVal Syslog(syslog_pri_t priority, uchar *pMsg, struct timeval *tp, struct json_object *json)
+{
+ DEFiRet;
+ iRet = enqMsg((uchar*)pMsg, (uchar*) "kernel:", priority, tp, json);
+ RETiRet;
+}
+
+
+/* helper for some klog drivers which need to know the MaxLine global setting. They can
+ * not obtain it themselfs, because they are no modules and can not query the object hander.
+ * It would probably be a good idea to extend the interface to support it, but so far
+ * we create a (sufficiently valid) work-around. -- rgerhards, 2008-11-24
+ */
+int klog_getMaxLine(void)
+{
+ return glbl.GetMaxLine(runModConf->pConf);
+}
+
+
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(!pThrd->bShallStop) {
+ /* klogLogKMsg() waits for the next kernel message, obtains it
+ * and then submits it to the rsyslog main queue.
+ * rgerhards, 2008-04-09
+ */
+ CHKiRet(klogLogKMsg(runModConf));
+ }
+finalize_it:
+ENDrunInput
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ pModConf->iFacilIntMsg = klogFacilIntMsg();
+ pModConf->parseKernelStamp = KMSG_PARSE_TS_STARTUP_ONLY;
+ pModConf->readMode = KMSG_READMODE_FULL_BOOT;
+ pModConf->expected_boot_complete_secs = 90;
+ loadModConf->configSetViaV2Method = 0;
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ initConfigSettings();
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imkmsg:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "parsekerneltimestamp")) {
+ if( !es_strconstcmp(pvals[i].val.d.estr, "on")
+ || !es_strconstcmp(pvals[i].val.d.estr, "always")) {
+ loadModConf->parseKernelStamp = KMSG_PARSE_TS_ALWAYS;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "startup")) {
+ loadModConf->parseKernelStamp = KMSG_PARSE_TS_STARTUP_ONLY;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "off")) {
+ loadModConf->parseKernelStamp = KMSG_PARSE_TS_OFF;
+ } else {
+ const char *const cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_PARAM_ERROR, "imkmsg: unknown "
+ "parse mode '%s'", cstr);
+ free((void*)cstr);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "expectedbootcompleteseconds")) {
+ loadModConf->expected_boot_complete_secs = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "readmode")) {
+ if(!es_strconstcmp(pvals[i].val.d.estr, "full-boot")) {
+ loadModConf->readMode = KMSG_READMODE_FULL_BOOT;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "full-always")) {
+ loadModConf->readMode = KMSG_READMODE_FULL_ALWAYS;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "new-only")) {
+ loadModConf->readMode = KMSG_READMODE_NEW_ONLY;
+ } else {
+ const char *const cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_PARAM_ERROR, "imkmsg: unknown "
+ "read mode '%s', keeping default setting", cstr);
+ free((void*)cstr);
+ }
+ } else {
+ LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_WARNING,
+ "imkmsg: RSYSLOG BUG, non-handled param '%s' in "
+ "beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* disable legacy module-global config directives */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->iFacilIntMsg = cs.iFacilIntMsg;
+ }
+
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ iRet = klogWillRunPrePrivDrop(runModConf);
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINwillRun
+CODESTARTwillRun
+ iRet = klogWillRunPostPrivDrop(runModConf);
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ iRet = klogAfterRun(runModConf);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ if(pLocalHostIP != NULL)
+ prop.Destruct(&pLocalHostIP);
+
+ /* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.iFacilIntMsg = klogFacilIntMsg();
+ return RS_RET_OK;
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imkmsg"), sizeof("imkmsg") - 1));
+ CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+
+ /* init legacy config settings */
+ initConfigSettings();
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/contrib/imkmsg/imkmsg.h b/contrib/imkmsg/imkmsg.h
new file mode 100644
index 0000000..0021f25
--- /dev/null
+++ b/contrib/imkmsg/imkmsg.h
@@ -0,0 +1,78 @@
+/* imkmsg.h
+ * These are the definitions for the kmsg message generation module.
+ *
+ * Copyright 2007-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IMKLOG_H_INCLUDED
+#define IMKLOG_H_INCLUDED 1
+
+#include "rsyslog.h"
+#include "dirty.h"
+
+typedef enum _kernel_ts_parse_mods {
+ KMSG_PARSE_TS_OFF = 0,
+ KMSG_PARSE_TS_ALWAYS = 1,
+ KMSG_PARSE_TS_STARTUP_ONLY = 2
+ } t_kernel_ts_parse_mode;
+
+typedef enum _kernel_readmode {
+ KMSG_READMODE_FULL_BOOT = 0,
+ KMSG_READMODE_FULL_ALWAYS = 1,
+ KMSG_READMODE_NEW_ONLY = 2
+ } t_kernel_readmode;
+
+/* we need to have the modConf type present in all submodules */
+struct modConfData_s {
+ rsconf_t *pConf;
+ int iFacilIntMsg;
+ uchar *pszPath;
+ int console_log_level;
+ int expected_boot_complete_secs;
+ t_kernel_ts_parse_mode parseKernelStamp;
+ t_kernel_readmode readMode;
+ sbool configSetViaV2Method;
+};
+
+/* interface to "drivers"
+ * the platform specific drivers must implement these entry points. Only one
+ * driver may be active at any given time, thus we simply rely on the linker
+ * to resolve the addresses.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(modConfData_t *pModConf);
+rsRetVal klogWillRunPrePrivDrop(modConfData_t *pModConf);
+rsRetVal klogWillRunPostPrivDrop(modConfData_t *pModConf);
+rsRetVal klogAfterRun(modConfData_t *pModConf);
+int klogFacilIntMsg();
+
+/* the functions below may be called by the drivers */
+rsRetVal imkmsgLogIntMsg(syslog_pri_t priority, const char *fmt, ...) __attribute__((format(printf,2, 3)));
+rsRetVal Syslog(syslog_pri_t priority, uchar *msg, struct timeval *tp, struct json_object *json);
+int klogFacilIntMsg(void);
+
+/* prototypes */
+extern int klog_getMaxLine(void); /* work-around for klog drivers to get configured max line size */
+extern int InitKsyms(modConfData_t*);
+extern void DeinitKsyms(void);
+extern int InitMsyms(void);
+extern void DeinitMsyms(void);
+extern char * ExpandKadds(char *, char *);
+extern void SetParanoiaLevel(int);
+
+#endif /* #ifndef IMKLOG_H_INCLUDED */
diff --git a/contrib/imkmsg/kmsg.c b/contrib/imkmsg/kmsg.c
new file mode 100644
index 0000000..2548634
--- /dev/null
+++ b/contrib/imkmsg/kmsg.c
@@ -0,0 +1,327 @@
+/* imkmsg driver for Linux /dev/kmsg structured logging
+ *
+ * This contains Linux-specific functionality to read /dev/kmsg
+ * For a general overview, see head comment in imkmsg.c.
+ * This is heavily based on imklog bsd.c file.
+ *
+ * Copyright 2008-2023 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/klog.h>
+#include <sys/sysinfo.h>
+#include <sys/time.h>
+#include <json.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "debug.h"
+#include "imkmsg.h"
+
+/* globals */
+static int fklog = -1; /* kernel log fd */
+static int bInInitialReading = 1; /* are we in the intial kmsg reading phase? */
+/* Note: There is a problem with kernel log time.
+ * See https://github.com/troglobit/sysklogd/commit/9f6fbb3301e571d8af95f8d771469291384e9e95
+ * We use the same work-around if bFixKernelStamp is on, and use the kernel log time
+ * only for past records, which we assume to be from recent boot. Later on, we do not
+ * use them but system time.
+ * UNFORTUNATELY, with /dev/kmsg, we always get old messages on startup. That means we
+ * may also pull old messages. We do not address this right now, as for 10 years "old
+ * messages" was pretty acceptable. So we wait until someone complains. Hint: we could
+ * do a seek to the end of kmsg if desired to not pull old messages.
+ * 2023-10-31 rgerhards
+ */
+
+#ifndef _PATH_KLOG
+# define _PATH_KLOG "/dev/kmsg"
+#endif
+
+/* submit a message to imkmsg Syslog() API. In this function, we parse
+ * necessary information from kernel log line, and make json string
+ * from the rest.
+ */
+static void
+submitSyslog(modConfData_t *const pModConf, const uchar *buf)
+{
+ long offs = 0;
+ struct timeval tv;
+ struct timeval *tp = NULL;
+ struct sysinfo info;
+ unsigned long int timestamp = 0;
+ char name[1024];
+ char value[1024];
+ char msg[1024];
+ syslog_pri_t priority = 0;
+ long int sequnum = 0;
+ struct json_object *json = NULL, *jval;
+
+ /* create new json object */
+ json = json_object_new_object();
+
+ /* get priority */
+ for (; isdigit(*buf); buf++) {
+ priority = (priority * 10) + (*buf - '0');
+ }
+ buf++;
+
+ /* get messages sequence number and add it to json */
+ for (; isdigit(*buf); buf++) {
+ sequnum = (sequnum * 10) + (*buf - '0');
+ }
+ buf++; /* skip , */
+ jval = json_object_new_int(sequnum);
+ json_object_object_add(json, "sequnum", jval);
+
+ /* get timestamp */
+ for (; isdigit(*buf); buf++) {
+ timestamp = (timestamp * 10) + (*buf - '0');
+ }
+
+ while (*buf != ';') {
+ buf++; /* skip everything till the first ; */
+ }
+ buf++; /* skip ; */
+
+ /* get message */
+ offs = 0;
+ for (; *buf != '\n' && *buf != '\0'; buf++, offs++) {
+ msg[offs] = *buf;
+ }
+ msg[offs] = '\0';
+ jval = json_object_new_string((char*)msg);
+ json_object_object_add(json, "msg", jval);
+
+ if (*buf != '\0') /* message has appended properties, skip \n */
+ buf++;
+
+ while (*buf) {
+ /* get name of the property */
+ buf++; /* skip ' ' */
+ offs = 0;
+ for (; *buf != '=' && *buf != ' '; buf++, offs++) {
+ name[offs] = *buf;
+ }
+ name[offs] = '\0';
+ buf++; /* skip = or ' ' */;
+
+ offs = 0;
+ for (; *buf != '\n' && *buf != '\0'; buf++, offs++) {
+ value[offs] = *buf;
+ }
+ value[offs] = '\0';
+ if (*buf != '\0') {
+ buf++; /* another property, skip \n */
+ }
+
+ jval = json_object_new_string((char*)value);
+ json_object_object_add(json, name, jval);
+ }
+
+ if( (pModConf->parseKernelStamp == KMSG_PARSE_TS_ALWAYS)
+ || ((pModConf->parseKernelStamp == KMSG_PARSE_TS_STARTUP_ONLY) && bInInitialReading) ) {
+ /* calculate timestamp */
+ sysinfo(&info);
+ gettimeofday(&tv, NULL);
+
+ /* get boot time */
+ tv.tv_sec -= info.uptime;
+
+ tv.tv_sec += timestamp / 1000000;
+ tv.tv_usec += timestamp % 1000000;
+
+ while (tv.tv_usec < 0) {
+ tv.tv_sec--;
+ tv.tv_usec += 1000000;
+ }
+
+ while (tv.tv_usec >= 1000000) {
+ tv.tv_sec++;
+ tv.tv_usec -= 1000000;
+ }
+
+ tp = &tv;
+ }
+
+ Syslog(priority, (uchar *)msg, tp, json);
+}
+
+
+/* open the kernel log - will be called inside the willRun() imkmsg entry point
+ */
+rsRetVal
+klogWillRunPrePrivDrop(modConfData_t __attribute__((unused)) *pModConf)
+{
+ char errmsg[2048];
+ DEFiRet;
+
+ fklog = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK, 0);
+ if (fklog < 0) {
+ imkmsgLogIntMsg(LOG_ERR, "imkmsg: cannot open kernel log (%s): %s.",
+ _PATH_KLOG, rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* make sure the kernel log is readable after dropping privileges
+ */
+rsRetVal
+klogWillRunPostPrivDrop(modConfData_t __attribute__((unused)) *pModConf)
+{
+ char errmsg[2048];
+ int r;
+ DEFiRet;
+
+ /* this normally returns EINVAL */
+ /* on an OpenVZ VM, we get EPERM */
+ r = read(fklog, NULL, 0);
+ if (r < 0 && errno != EINVAL && errno != EAGAIN && errno != EWOULDBLOCK) {
+ imkmsgLogIntMsg(LOG_ERR, "imkmsg: cannot open kernel log (%s): %s.",
+ _PATH_KLOG, rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ fklog = -1;
+ ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static void
+change_reads_to_blocking(const int fd)
+{
+ const int flags = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+}
+
+/* Read kernel log while data are available, each read() reads one
+ * record of printk buffer.
+ */
+static void
+readkmsg(modConfData_t *const pModConf)
+{
+ int i;
+ uchar pRcv[16*1024+1];
+ char errmsg[2048];
+ off_t seek_result = 0;
+
+ if(pModConf->readMode == KMSG_READMODE_FULL_BOOT) {
+ struct sysinfo info;
+ sysinfo(&info);
+ DBGPRINTF("imkmsg: system uptime is %lld, expected %d\n",
+ (long long) info.uptime, pModConf->expected_boot_complete_secs);
+ if(info.uptime > pModConf->expected_boot_complete_secs) {
+ seek_result = lseek(fklog, 0, SEEK_END);
+ }
+ } else if(pModConf->readMode == KMSG_READMODE_NEW_ONLY) {
+ seek_result = lseek(fklog, 0, SEEK_END);
+ } else if(pModConf->readMode != KMSG_READMODE_FULL_ALWAYS) {
+ imkmsgLogIntMsg(LOG_ERR, "imkmsg: internal program error, "
+ "unknown read mode %d, assuming 'full-always'",
+ pModConf->readMode);
+ }
+
+ if(seek_result == (off_t) -1) {
+ imkmsgLogIntMsg(LOG_WARNING,
+ "imkmsg: could not seek to requested klog entries - will"
+ "now potentially output all messages");
+ }
+
+ for (;;) {
+ dbgprintf("imkmsg waiting for kernel log line\n");
+
+ /* every read() from the opened device node receives one record of the printk buffer */
+ i = read(fklog, pRcv, 8192);
+ if (i > 0) {
+ /* successful read of message of nonzero length */
+ pRcv[i] = '\0';
+ } else if (i < 0 && errno == EPIPE) {
+ imkmsgLogIntMsg(LOG_WARNING,
+ "imkmsg: some messages in circular buffer got overwritten");
+ continue;
+ } else {
+ /* something went wrong - error or zero length message */
+ if(i < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+ DBGPRINTF("imkmsg: initial read done, changing to blocking mode\n");
+ change_reads_to_blocking(fklog);
+ bInInitialReading = 0;
+ continue;
+ }
+ if(i < 0 && errno != EINTR && errno != EAGAIN) {
+ /* error occurred */
+ imkmsgLogIntMsg(LOG_ERR,
+ "imkmsg: error reading kernel log - shutting down: %s",
+ rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ fklog = -1;
+ }
+ break;
+ }
+
+ submitSyslog(pModConf, pRcv);
+ }
+}
+
+
+/* to be called in the module's AfterRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogAfterRun(modConfData_t *pModConf)
+{
+ DEFiRet;
+ if(fklog != -1)
+ close(fklog);
+ /* Turn on logging of messages to console, but only if a log level was speficied */
+ if(pModConf->console_log_level != -1)
+ klogctl(7, NULL, 0);
+ RETiRet;
+}
+
+
+/* to be called in the module's WillRun entry point, this is the main
+ * "message pull" mechanism.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(modConfData_t *const pModConf)
+{
+ DEFiRet;
+ readkmsg(pModConf);
+ RETiRet;
+}
+
+
+/* provide the (system-specific) default facility for internal messages
+ * rgerhards, 2008-04-14
+ */
+int
+klogFacilIntMsg(void)
+{
+ return LOG_SYSLOG;
+}
+
diff --git a/contrib/impcap/Makefile.am b/contrib/impcap/Makefile.am
new file mode 100644
index 0000000..e1c80e5
--- /dev/null
+++ b/contrib/impcap/Makefile.am
@@ -0,0 +1,22 @@
+pkglib_LTLIBRARIES = impcap.la
+
+impcap_la_SOURCES = impcap.c
+impcap_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+impcap_la_LDFLAGS = -module -avoid-version
+impcap_la_LIBADD = -lpcap
+
+impcap_la_SOURCES += arp_parser.c
+impcap_la_SOURCES += eth_parser.c
+impcap_la_SOURCES += icmp_parser.c
+impcap_la_SOURCES += ipv4_parser.c
+impcap_la_SOURCES += ipv6_parser.c
+impcap_la_SOURCES += ipx_parser.c
+impcap_la_SOURCES += llc_parser.c
+impcap_la_SOURCES += udp_parser.c
+impcap_la_SOURCES += dns_parser.c
+impcap_la_SOURCES += tcp_parser.c
+impcap_la_SOURCES += smb_parser.c
+impcap_la_SOURCES += ftp_parser.c
+impcap_la_SOURCES += http_parser.c
+
+EXTRA_DIST=parsers.h
diff --git a/contrib/impcap/Makefile.in b/contrib/impcap/Makefile.in
new file mode 100644
index 0000000..506aaef
--- /dev/null
+++ b/contrib/impcap/Makefile.in
@@ -0,0 +1,949 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/impcap
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+impcap_la_DEPENDENCIES =
+am_impcap_la_OBJECTS = impcap_la-impcap.lo impcap_la-arp_parser.lo \
+ impcap_la-eth_parser.lo impcap_la-icmp_parser.lo \
+ impcap_la-ipv4_parser.lo impcap_la-ipv6_parser.lo \
+ impcap_la-ipx_parser.lo impcap_la-llc_parser.lo \
+ impcap_la-udp_parser.lo impcap_la-dns_parser.lo \
+ impcap_la-tcp_parser.lo impcap_la-smb_parser.lo \
+ impcap_la-ftp_parser.lo impcap_la-http_parser.lo
+impcap_la_OBJECTS = $(am_impcap_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 =
+impcap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(impcap_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/impcap_la-arp_parser.Plo \
+ ./$(DEPDIR)/impcap_la-dns_parser.Plo \
+ ./$(DEPDIR)/impcap_la-eth_parser.Plo \
+ ./$(DEPDIR)/impcap_la-ftp_parser.Plo \
+ ./$(DEPDIR)/impcap_la-http_parser.Plo \
+ ./$(DEPDIR)/impcap_la-icmp_parser.Plo \
+ ./$(DEPDIR)/impcap_la-impcap.Plo \
+ ./$(DEPDIR)/impcap_la-ipv4_parser.Plo \
+ ./$(DEPDIR)/impcap_la-ipv6_parser.Plo \
+ ./$(DEPDIR)/impcap_la-ipx_parser.Plo \
+ ./$(DEPDIR)/impcap_la-llc_parser.Plo \
+ ./$(DEPDIR)/impcap_la-smb_parser.Plo \
+ ./$(DEPDIR)/impcap_la-tcp_parser.Plo \
+ ./$(DEPDIR)/impcap_la-udp_parser.Plo
+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 = $(impcap_la_SOURCES)
+DIST_SOURCES = $(impcap_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = impcap.la
+impcap_la_SOURCES = impcap.c arp_parser.c eth_parser.c icmp_parser.c \
+ ipv4_parser.c ipv6_parser.c ipx_parser.c llc_parser.c \
+ udp_parser.c dns_parser.c tcp_parser.c smb_parser.c \
+ ftp_parser.c http_parser.c
+impcap_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+impcap_la_LDFLAGS = -module -avoid-version
+impcap_la_LIBADD = -lpcap
+EXTRA_DIST = parsers.h
+all: 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) --gnu contrib/impcap/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/impcap/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+impcap.la: $(impcap_la_OBJECTS) $(impcap_la_DEPENDENCIES) $(EXTRA_impcap_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(impcap_la_LINK) -rpath $(pkglibdir) $(impcap_la_OBJECTS) $(impcap_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-arp_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-dns_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-eth_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ftp_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-http_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-icmp_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-impcap.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipv4_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipv6_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipx_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-llc_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-smb_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-tcp_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-udp_parser.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+impcap_la-impcap.lo: impcap.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-impcap.lo -MD -MP -MF $(DEPDIR)/impcap_la-impcap.Tpo -c -o impcap_la-impcap.lo `test -f 'impcap.c' || echo '$(srcdir)/'`impcap.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-impcap.Tpo $(DEPDIR)/impcap_la-impcap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='impcap.c' object='impcap_la-impcap.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-impcap.lo `test -f 'impcap.c' || echo '$(srcdir)/'`impcap.c
+
+impcap_la-arp_parser.lo: arp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-arp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-arp_parser.Tpo -c -o impcap_la-arp_parser.lo `test -f 'arp_parser.c' || echo '$(srcdir)/'`arp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-arp_parser.Tpo $(DEPDIR)/impcap_la-arp_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='arp_parser.c' object='impcap_la-arp_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-arp_parser.lo `test -f 'arp_parser.c' || echo '$(srcdir)/'`arp_parser.c
+
+impcap_la-eth_parser.lo: eth_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-eth_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-eth_parser.Tpo -c -o impcap_la-eth_parser.lo `test -f 'eth_parser.c' || echo '$(srcdir)/'`eth_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-eth_parser.Tpo $(DEPDIR)/impcap_la-eth_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='eth_parser.c' object='impcap_la-eth_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-eth_parser.lo `test -f 'eth_parser.c' || echo '$(srcdir)/'`eth_parser.c
+
+impcap_la-icmp_parser.lo: icmp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-icmp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-icmp_parser.Tpo -c -o impcap_la-icmp_parser.lo `test -f 'icmp_parser.c' || echo '$(srcdir)/'`icmp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-icmp_parser.Tpo $(DEPDIR)/impcap_la-icmp_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='icmp_parser.c' object='impcap_la-icmp_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-icmp_parser.lo `test -f 'icmp_parser.c' || echo '$(srcdir)/'`icmp_parser.c
+
+impcap_la-ipv4_parser.lo: ipv4_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipv4_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipv4_parser.Tpo -c -o impcap_la-ipv4_parser.lo `test -f 'ipv4_parser.c' || echo '$(srcdir)/'`ipv4_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipv4_parser.Tpo $(DEPDIR)/impcap_la-ipv4_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipv4_parser.c' object='impcap_la-ipv4_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipv4_parser.lo `test -f 'ipv4_parser.c' || echo '$(srcdir)/'`ipv4_parser.c
+
+impcap_la-ipv6_parser.lo: ipv6_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipv6_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipv6_parser.Tpo -c -o impcap_la-ipv6_parser.lo `test -f 'ipv6_parser.c' || echo '$(srcdir)/'`ipv6_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipv6_parser.Tpo $(DEPDIR)/impcap_la-ipv6_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipv6_parser.c' object='impcap_la-ipv6_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipv6_parser.lo `test -f 'ipv6_parser.c' || echo '$(srcdir)/'`ipv6_parser.c
+
+impcap_la-ipx_parser.lo: ipx_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipx_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipx_parser.Tpo -c -o impcap_la-ipx_parser.lo `test -f 'ipx_parser.c' || echo '$(srcdir)/'`ipx_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipx_parser.Tpo $(DEPDIR)/impcap_la-ipx_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipx_parser.c' object='impcap_la-ipx_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipx_parser.lo `test -f 'ipx_parser.c' || echo '$(srcdir)/'`ipx_parser.c
+
+impcap_la-llc_parser.lo: llc_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-llc_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-llc_parser.Tpo -c -o impcap_la-llc_parser.lo `test -f 'llc_parser.c' || echo '$(srcdir)/'`llc_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-llc_parser.Tpo $(DEPDIR)/impcap_la-llc_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llc_parser.c' object='impcap_la-llc_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-llc_parser.lo `test -f 'llc_parser.c' || echo '$(srcdir)/'`llc_parser.c
+
+impcap_la-udp_parser.lo: udp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-udp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-udp_parser.Tpo -c -o impcap_la-udp_parser.lo `test -f 'udp_parser.c' || echo '$(srcdir)/'`udp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-udp_parser.Tpo $(DEPDIR)/impcap_la-udp_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udp_parser.c' object='impcap_la-udp_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-udp_parser.lo `test -f 'udp_parser.c' || echo '$(srcdir)/'`udp_parser.c
+
+impcap_la-dns_parser.lo: dns_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-dns_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-dns_parser.Tpo -c -o impcap_la-dns_parser.lo `test -f 'dns_parser.c' || echo '$(srcdir)/'`dns_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-dns_parser.Tpo $(DEPDIR)/impcap_la-dns_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns_parser.c' object='impcap_la-dns_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-dns_parser.lo `test -f 'dns_parser.c' || echo '$(srcdir)/'`dns_parser.c
+
+impcap_la-tcp_parser.lo: tcp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-tcp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-tcp_parser.Tpo -c -o impcap_la-tcp_parser.lo `test -f 'tcp_parser.c' || echo '$(srcdir)/'`tcp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-tcp_parser.Tpo $(DEPDIR)/impcap_la-tcp_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcp_parser.c' object='impcap_la-tcp_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-tcp_parser.lo `test -f 'tcp_parser.c' || echo '$(srcdir)/'`tcp_parser.c
+
+impcap_la-smb_parser.lo: smb_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-smb_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-smb_parser.Tpo -c -o impcap_la-smb_parser.lo `test -f 'smb_parser.c' || echo '$(srcdir)/'`smb_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-smb_parser.Tpo $(DEPDIR)/impcap_la-smb_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smb_parser.c' object='impcap_la-smb_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-smb_parser.lo `test -f 'smb_parser.c' || echo '$(srcdir)/'`smb_parser.c
+
+impcap_la-ftp_parser.lo: ftp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ftp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ftp_parser.Tpo -c -o impcap_la-ftp_parser.lo `test -f 'ftp_parser.c' || echo '$(srcdir)/'`ftp_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ftp_parser.Tpo $(DEPDIR)/impcap_la-ftp_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftp_parser.c' object='impcap_la-ftp_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ftp_parser.lo `test -f 'ftp_parser.c' || echo '$(srcdir)/'`ftp_parser.c
+
+impcap_la-http_parser.lo: http_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-http_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-http_parser.Tpo -c -o impcap_la-http_parser.lo `test -f 'http_parser.c' || echo '$(srcdir)/'`http_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-http_parser.Tpo $(DEPDIR)/impcap_la-http_parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_parser.c' object='impcap_la-http_parser.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) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-http_parser.lo `test -f 'http_parser.c' || echo '$(srcdir)/'`http_parser.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/impcap_la-arp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-dns_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-eth_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ftp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-http_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-icmp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-impcap.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipv4_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipv6_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipx_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-llc_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-smb_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-tcp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-udp_parser.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/impcap_la-arp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-dns_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-eth_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ftp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-http_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-icmp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-impcap.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipv4_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipv6_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-ipx_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-llc_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-smb_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-tcp_parser.Plo
+ -rm -f ./$(DEPDIR)/impcap_la-udp_parser.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/impcap/arp_parser.c b/contrib/impcap/arp_parser.c
new file mode 100644
index 0000000..5d8ce6e
--- /dev/null
+++ b/contrib/impcap/arp_parser.c
@@ -0,0 +1,163 @@
+/* arp_parser.c
+ *
+ * This file contains functions to parse ARP and RARP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+struct arp_header_s {
+ uint16_t hwType;
+ uint16_t pType;
+ uint8_t hwAddrLen;
+ uint8_t pAddrLen;
+ uint16_t opCode;
+ uint8_t pAddr[];
+};
+
+typedef struct arp_header_s arp_header_t;
+
+/*
+ * This function parses the bytes in the received packet to extract ARP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the ARP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where ARP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *arp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("arp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 28) { /* too small for ARP header*/
+ DBGPRINTF("ARP packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0);
+ }
+
+ /* Union to prevent cast from uchar to arp_header_t */
+ union {
+ const uchar *pck;
+ arp_header_t *hdr;
+ } arp_header_to_char;
+
+ arp_header_to_char.pck = packet;
+ arp_header_t *arp_header = arp_header_to_char.hdr;
+
+ char pAddrSrc[20], pAddrDst[20];
+
+ json_object_object_add(jparent, "ARP_hwType", json_object_new_int(ntohs(arp_header->hwType)));
+ json_object_object_add(jparent, "ARP_pType", json_object_new_int(ntohs(arp_header->pType)));
+ json_object_object_add(jparent, "ARP_op", json_object_new_int(ntohs(arp_header->opCode)));
+
+ if (ntohs(arp_header->hwType) == 1) { /* ethernet addresses */
+ char hwAddrSrc[20], hwAddrDst[20];
+
+ ether_ntoa_r((struct ether_addr *)arp_header->pAddr, hwAddrSrc);
+ ether_ntoa_r((struct ether_addr *)(arp_header->pAddr + arp_header->hwAddrLen + arp_header->pAddrLen),
+ hwAddrDst);
+
+ json_object_object_add(jparent, "ARP_hwSrc", json_object_new_string((char *)hwAddrSrc));
+ json_object_object_add(jparent, "ARP_hwDst", json_object_new_string((char *)hwAddrDst));
+ }
+
+ if (ntohs(arp_header->pType) == ETHERTYPE_IP) {
+ inet_ntop(AF_INET, (void *)(arp_header->pAddr + arp_header->hwAddrLen), pAddrSrc, 20);
+ inet_ntop(AF_INET, (void *)(arp_header->pAddr + 2 * arp_header->hwAddrLen + arp_header->pAddrLen),
+ pAddrDst, 20);
+
+ json_object_object_add(jparent, "ARP_pSrc", json_object_new_string((char *)pAddrSrc));
+ json_object_object_add(jparent, "ARP_pDst", json_object_new_string((char *)pAddrDst));
+ }
+
+ RETURN_DATA_AFTER(28);
+}
+
+/*
+ * This function parses the bytes in the received packet to extract RARP metadata.
+ * This is a copy of ARP handler, as structure is the same but protocol code and name are different
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the RARP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where RARP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *rarp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("rarp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 28) { /* too small for RARP header*/
+ DBGPRINTF("RARP packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0);
+ }
+
+ /* Union to prevent cast from uchar to arp_header_t */
+ union {
+ const uchar *pck;
+ arp_header_t *hdr;
+ } arp_header_to_char;
+
+ arp_header_to_char.pck = packet;
+ arp_header_t *rarp_header = arp_header_to_char.hdr;
+
+ char pAddrSrc[20], pAddrDst[20];
+
+ json_object_object_add(jparent, "RARP_hwType", json_object_new_int(ntohs(rarp_header->hwType)));
+ json_object_object_add(jparent, "RARP_pType", json_object_new_int(ntohs(rarp_header->pType)));
+ json_object_object_add(jparent, "RARP_op", json_object_new_int(ntohs(rarp_header->opCode)));
+
+ if (ntohs(rarp_header->hwType) == 1) { /* ethernet addresses */
+ char *hwAddrSrc = ether_ntoa((struct ether_addr *)rarp_header->pAddr);
+ char *hwAddrDst = ether_ntoa((struct ether_addr *)(rarp_header->pAddr +
+ rarp_header->hwAddrLen +
+ rarp_header->pAddrLen));
+
+ json_object_object_add(jparent, "RARP_hwSrc", json_object_new_string((char *)hwAddrSrc));
+ json_object_object_add(jparent, "RARP_hwDst", json_object_new_string((char *)hwAddrDst));
+ }
+
+ if (ntohs(rarp_header->pType) == ETHERTYPE_IP) {
+ inet_ntop(AF_INET, (void *)(rarp_header->pAddr + rarp_header->hwAddrLen), pAddrSrc, 20);
+ inet_ntop(AF_INET, (void *)(rarp_header->pAddr + 2 * rarp_header->hwAddrLen + rarp_header->pAddrLen),
+ pAddrDst, 20);
+
+ json_object_object_add(jparent, "RARP_pSrc", json_object_new_string((char *)pAddrSrc));
+ json_object_object_add(jparent, "RARP_pDst", json_object_new_string((char *)pAddrDst));
+ }
+
+ RETURN_DATA_AFTER(28);
+}
diff --git a/contrib/impcap/dns_parser.c b/contrib/impcap/dns_parser.c
new file mode 100644
index 0000000..f9f4e68
--- /dev/null
+++ b/contrib/impcap/dns_parser.c
@@ -0,0 +1,372 @@
+/* dns_parser.c
+ *
+ * This file contains functions to parse DNS headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Kevin Guillemot (kevin.guillemot@advens.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+
+/* List of RCodes defined in RFC6895 : https://tools.ietf.org/html/rfc6895 */
+static const char *dns_rcodes[] = {
+ "NoError", // 0
+ "FormErr", // 1
+ "ServFail", // 2
+ "NXDomain", // 3
+ "NotImp", // 4
+ "Refused", // 5
+ "YXDomain", // 6
+ "YXRRSet", // 7
+ "NXRRSet", // 8
+ "NotAuth", // 9
+ "NotZone", // 10
+ "", // 11 - Reserved
+ "", // 12 - Reserved
+ "", // 13 - Reserved
+ "", // 14 - Reserved
+ "", // 15 - Reserved
+ "BADVERS|BADSIG", // 16
+ "BADKEY", // 17
+ "BADTIME", // 18
+ "BADMODE", // 19
+ "BADNAME", // 20
+ "BADALG", // 21
+ "BADTRUNC", // 22
+ /* Reserved for private use */
+ NULL
+};
+
+/* List of record types (maybe not complete) */
+static const char *dns_types[] = {
+ 0,
+ "A", // 1
+ "NS", // 2
+ "MD", // 3
+ "MF", // 4
+ "CNAME", // 5
+ "SOA", // 6
+ "MB", // 7
+ "MG", // 8
+ "MR", // 9
+ "NULL", // 10
+ "WKS", // 11
+ "PTR", // 12
+ "HINFO", // 13
+ "MINFO", // 14
+ "MX", // 15
+ "TXT", // 16
+ "RP", // 17
+ "AFSDB", // 18
+ "X25", // 19
+ "ISDN", // 20
+ "RT", // 21
+ "NSAP", // 22
+ "NSAP-PTR", // 23
+ "SIG", // 24
+ "KEY", // 25
+ "PX", // 26
+ "GPOS", // 27
+ "AAAA", // 28
+ "LOC", // 29
+ "NXT", // 30
+ "EID", // 31
+ "NIMLOC", // 32
+ "SRV", // 33
+ "ATMA", // 34
+ "NAPTR", // 35
+ "KX", // 36
+ "CERT", // 37
+ "A6", // 38
+ "DNAME", // 39
+ "SINK", // 40
+ "OPT", // 41
+ "APL", // 42
+ "DS", // 43
+ "SSHFP", // 44
+ "IPSECKEY", // 45
+ "RRSIG", // 46
+ "NSEC", // 47
+ "DNSKEY", // 48
+ "DHCID", // 49
+ "NSEC3", // 50
+ "NSEC3PARAM", // 51
+ "TLSA", // 51
+ "SMIMEA", // 52
+ "Unassigned", // 53
+ "HIP", // 53
+ "NINFO", // 54
+ "RKEY", // 55
+ "TALINK", // 56
+ "CDS", // 57
+ "CDNSKEY", // 58
+ "OPENPGPKEY", // 59
+ "CSYNC", // 60
+ "ZONEMD", // 61
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ "SPF", // 99
+ "UINFO", // 100
+ "UID", // 101
+ "GID", // 102
+ "UNSPEC", // 103
+ "NID", // 104
+ "L32", // 105
+ "L64", // 106
+ "LP", // 107
+ "EUI48", // 108
+ "EUI64", // 109
+ /* Reserved for private use */
+ NULL
+};
+/* Part 2, since 249. To prevent useless large buffer in memory */
+static const char *dns_types2[] = {
+ "TKEY",
+ "TSIG",
+ "IXFR",
+ "AXFR",
+ "MAILB",
+ "MAILA",
+ "*",
+ "URI",
+ "CAA",
+ "AVC",
+ "DOA",
+ "AMTRELAY",
+ NULL
+};
+/* Part 3, since 32768. To prevent useless large buffer in memory */
+static const char *dns_types3[] = {
+ "TA",
+ "DLV",
+ NULL
+};
+
+
+/* This function takes an integer as parameter
+ * and returns the corresponding string type of DNS query
+ */
+static const char *get_type(uint16_t x) {
+ const char **types = NULL;
+ uint16_t len_types3 = (sizeof(dns_types3) / sizeof(char *)) - 1;
+ uint16_t len_types2 = (sizeof(dns_types2) / sizeof(char *)) - 1;
+ uint16_t len_types = (sizeof(dns_types) / sizeof(char *)) - 1;
+ if (x >= 32768 && x < 32768 + len_types3) {
+ types = dns_types3;
+ x -= 32768;
+ }
+ else if (x >= 249 && x < 249 + len_types2) {
+ types = dns_types2;
+ x -= 249;
+ }
+ else if (x > 0 && x < len_types)
+ types = dns_types;
+ else
+ return "UNKNOWN";
+ if (types[x] != NULL)
+ return types[x];
+ return "UNKNOWN";
+}
+
+
+/* This function takes an integer as parameter
+ * and returns the corresponding string class of DNS query
+ */
+static const char *get_class(uint16_t x) {
+ switch (x) {
+ case 1:
+ return "IN";
+ case 3:
+ return "CH";
+ case 4:
+ return "HS";
+ case 254:
+ return "QCLASS NONE";
+ case 255:
+ return "QCLASS *";
+ }
+ return "UNKNOWN";
+}
+
+
+/*
+ * This function parses the bytes in the received packet to extract DNS metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where DNS metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *dns_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ const uchar *packet_ptr = packet;
+ const uchar *end_packet = packet + pktSize;
+ DBGPRINTF("dns_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ /* Union to prevent cast from uchar to smb_header_t */
+ union {
+ unsigned short int *two_bytes;
+ const uchar *pckt;
+ } union_short_int;
+
+ /* Get transaction id */
+ union_short_int.pckt = packet_ptr;
+ unsigned short int transaction_id = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("transaction_id = %02x \n", transaction_id);
+ union_short_int.pckt += 2;
+
+ /* Get flags */
+ unsigned short int flags = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("flags = %02x \n", flags);
+
+ /* Get response flag */
+ unsigned short int response_flag = (flags >> 15) & 0b1; // Get the left bit
+ //DBGPRINTF("response_flag = %02x \n", response_flag);
+
+ /* Get Opcode */
+ unsigned short int opcode = (flags >> 11) & 0b1111;
+ //DBGPRINTF("opcode = %02x \n", opcode);
+
+ /* Verify Z: reserved bit */
+ unsigned short int reserved = (flags >> 6) & 0b1;
+ //DBGPRINTF("reserved = %02x \n", reserved);
+ /* Reserved bit MUST be 0 */
+ if (reserved != 0) {
+ DBGPRINTF("DNS packet reserved bit (Z) is not 0, aborting message. \n");
+ RETURN_DATA_AFTER(0)
+ }
+
+ /* Get reply code : 4 last bits */
+ unsigned short int reply_code = flags & 0b1111;
+ //DBGPRINTF("reply_code = %02x \n", reply_code);
+
+ union_short_int.pckt += 2;
+
+ /* Get QDCOUNT */
+ unsigned short int query_count = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("query_count = %02x \n", query_count);
+ union_short_int.pckt += 2;
+
+ /* Get ANCOUNT */
+ unsigned short int answer_count = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("answer_count = %02x \n", answer_count);
+ union_short_int.pckt += 2;
+
+ /* Get NSCOUNT */
+ unsigned short int authority_count = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("authority_count = %02x \n", authority_count);
+ union_short_int.pckt += 2;
+
+ /* Get ARCOUNT */
+ unsigned short int additionnal_count = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("additionnal_count = %02x \n", additionnal_count);
+ union_short_int.pckt += 2;
+ packet_ptr = union_short_int.pckt;
+
+ fjson_object *queries = NULL;
+ if ((queries = json_object_new_array()) == NULL) {
+ DBGPRINTF("impcap::dns_parser: Cannot create new json array. Stopping.\n");
+ RETURN_DATA_AFTER(0)
+ }
+
+ // For each query of query_count
+ int query_cpt = 0;
+ while (query_cpt < query_count && packet_ptr < end_packet) {
+ size_t query_size = strnlen((const char *)packet_ptr, (size_t)(end_packet - packet_ptr));
+ // Check if query is valid (max 255 bytes, plus a '\0')
+ if (query_size >= 256) {
+ DBGPRINTF("impcap::dns_parser: Length of domain queried is > 255. Stopping.\n");
+ break;
+ }
+ // Check if remaining data is enough to hold query + '\0' + 4 bytes (QTYPE and QCLASS fields)
+ if (query_size + 5 > (size_t)(end_packet - packet_ptr)) {
+ DBGPRINTF("impcap::dns_parser: packet size too small to parse query. Stopping.\n");
+ break;
+ }
+ fjson_object *query = NULL;
+ if ((query = json_object_new_object()) == NULL) {
+ DBGPRINTF("impcap::dns_parser: Cannot create new json object. Stopping.\n");
+ break;
+ }
+ char domain_query[256] = {0};
+ uchar nb_char = *packet_ptr;
+ packet_ptr++;
+ size_t cpt = 0;
+ while (cpt + 1 < query_size) {
+ if (nb_char == 0) {
+ nb_char = *packet_ptr;
+ domain_query[cpt] = '.';
+ } else {
+ domain_query[cpt] = (char)*packet_ptr;
+ nb_char--;
+ }
+ cpt++;
+ packet_ptr++;
+ }
+ domain_query[cpt] = '\0';
+ if (cpt)
+ packet_ptr++; // pass the last \0, only if query was not empty
+ // DBGPRINTF("Requested domain : '%s' \n", domain_query);
+
+ /* Register the name in dict */
+ json_object_object_add(query, "qname", json_object_new_string(domain_query));
+ /* Get QTYPE */
+ union_short_int.pckt = packet_ptr;
+ unsigned short int qtype = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("qtype = %02x \n", qtype);
+ json_object_object_add(query, "qtype", json_object_new_int((int)qtype));
+ json_object_object_add(query, "type", json_object_new_string(get_type(qtype)));
+ union_short_int.pckt += 2;
+ /* Retrieve QCLASS */
+ unsigned short int qclass = ntohs(*(union_short_int.two_bytes));
+ //DBGPRINTF("qclass = %02x \n", qclass);
+ json_object_object_add(query, "qclass", json_object_new_int((int)qclass));
+ json_object_object_add(query, "class", json_object_new_string(get_class(qclass)));
+ packet_ptr = union_short_int.pckt + 2;
+ /* Register the query in json array */
+ json_object_array_add(queries, query);
+ query_cpt++;
+ }
+
+ json_object_object_add(jparent, "DNS_transaction_id", json_object_new_int((int)transaction_id));
+
+ json_bool is_reponse = FALSE;
+ if (response_flag)
+ is_reponse = TRUE;
+ json_object_object_add(jparent, "DNS_response_flag", json_object_new_boolean(is_reponse));
+
+ json_object_object_add(jparent, "DNS_opcode", json_object_new_int(opcode));
+ json_object_object_add(jparent, "DNS_rcode", json_object_new_int((int)reply_code));
+ json_object_object_add(jparent, "DNS_error", json_object_new_string(dns_rcodes[reply_code]));
+ json_object_object_add(jparent, "DNS_QDCOUNT", json_object_new_int((int)query_count));
+ json_object_object_add(jparent, "DNS_ANCOUNT", json_object_new_int((int)answer_count));
+ json_object_object_add(jparent, "DNS_NSCOUNT", json_object_new_int((int)authority_count));
+ json_object_object_add(jparent, "DNS_ARCOUNT", json_object_new_int((int)additionnal_count));
+ json_object_object_add(jparent, "DNS_Names", queries);
+
+ /* Packet has been successfully parsed, there still can be some responses left, but do not process them */
+ RETURN_DATA_AFTER(0);
+}
diff --git a/contrib/impcap/eth_parser.c b/contrib/impcap/eth_parser.c
new file mode 100644
index 0000000..4bda2d5
--- /dev/null
+++ b/contrib/impcap/eth_parser.c
@@ -0,0 +1,179 @@
+/* eth_parser.c
+ *
+ * This file contains functions to parse Ethernet II headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpacked"
+#pragma GCC diagnostic ignored "-Wattributes"
+struct __attribute__ ((__packed__)) eth_header_s {
+ uint8_t addrDst[6];
+ uint8_t addrSrc[6];
+ uint16_t type;
+};
+
+struct __attribute__ ((__packed__)) vlan_header_s {
+ uint8_t addrDst[6];
+ uint8_t addrSrc[6];
+ uint16_t vlanCode;
+ uint16_t vlanTag;
+ uint16_t type;
+};
+#pragma GCC diagnostic pop
+
+typedef struct eth_header_s eth_header_t;
+typedef struct vlan_header_s vlan_header_t;
+
+
+/*
+ * Get an ethernet header type as uint16_t
+ * and return the correspondence as string
+ * NOTE : Only most common types are present, to complete if needed
+ */
+static const char *eth_type_to_string(uint16_t eth_type) {
+ switch (eth_type) {
+ case 0x00bb: // Extreme Networks Discovery Protocol
+ return "EDP";
+ case 0x0200: // PUP protocol
+ return "PUP";
+ case 0x0800: // IP protocol
+ return "IP";
+ case 0x0806: // address resolution protocol
+ return "ARP";
+ case 0x88a2: // AoE protocol
+ return "AOE";
+ case 0x2000: // Cisco Discovery Protocol
+ return "CDP";
+ case 0x2004: // Cisco Dynamic Trunking Protocol
+ return "DTP";
+ case 0x8035: // reverse addr resolution protocol
+ return "REVARP";
+ case 0x8100: // IEEE 802.1Q VLAN tagging
+ return "802.1Q";
+ case 0x88a8: // IEEE 802.1ad
+ return "802.1AD";
+ case 0x9100: // Legacy QinQ
+ return "QINQ1";
+ case 0x9200: // Legacy QinQ
+ return "QINQ2";
+ case 0x8137: // Internetwork Packet Exchange
+ return "IPX";
+ case 0x86DD: // IPv6 protocol
+ return "IPv6";
+ case 0x880B: // PPP
+ return "PPP";
+ case 0x8847: // MPLS
+ return "MPLS";
+ case 0x8848: // MPLS Multicast
+ return "MPLS_MCAST";
+ case 0x8863: // PPP Over Ethernet Discovery Stage
+ return "PPPoE_DISC";
+ case 0x8864: // PPP Over Ethernet Session Stage
+ return "PPPoE";
+ case 0x88CC: // Link Layer Discovery Protocol
+ return "LLDP";
+ case 0x6558: // Transparent Ethernet Bridging
+ return "TEB";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+/*
+ * This function parses the bytes in the received packet to extract Ethernet II metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the ETH header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where ETH metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *eth_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("entered eth_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+ if (pktSize < 14) { /* too short for eth header */
+ DBGPRINTF("ETH packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ eth_header_t *eth_header = (eth_header_t *)packet;
+ char ethMacSrc[20], ethMacDst[20];
+ uint8_t hdrLen = 14;
+
+ ether_ntoa_r((struct ether_addr *)eth_header->addrSrc, ethMacSrc);
+ ether_ntoa_r((struct ether_addr *)eth_header->addrDst, ethMacDst);
+
+ json_object_object_add(jparent, "ETH_src", json_object_new_string((char *)ethMacSrc));
+ json_object_object_add(jparent, "ETH_dst", json_object_new_string((char *)ethMacDst));
+
+ uint16_t ethType = (uint16_t)ntohs(eth_header->type);
+
+ if (ethType == ETHERTYPE_VLAN) {
+ vlan_header_t *vlan_header = (vlan_header_t *)packet;
+ json_object_object_add(jparent, "ETH_tag", json_object_new_int(ntohs(vlan_header->vlanTag)));
+ ethType = (uint16_t)ntohs(vlan_header->type);
+ hdrLen += 4;
+ }
+
+ data_ret_t *ret;
+
+ if (ethType < 1500) {
+ /* this is a LLC header */
+ json_object_object_add(jparent, "ETH_len", json_object_new_int(ethType));
+ ret = llc_parse(packet + hdrLen, pktSize - hdrLen, jparent);
+
+ /* packet has the minimum allowed size, so the remaining data is
+ * most likely padding, this should not appear as data, so remove it
+ * */
+ //TODO this is a quick win, a more elaborate solution would be to check if all data
+ // is indeed zero, but that would take more processing time
+ if (pktSize <= 60 && ret->pData != NULL) {
+ if (!ret->pData[0]) ret->size = 0;
+ }
+ return ret;
+ }
+
+ json_object_object_add(jparent, "ETH_type", json_object_new_int(ethType));
+ json_object_object_add(jparent, "ETH_typestr", json_object_new_string((char *)eth_type_to_string(ethType)));
+ ret = eth_proto_parse(ethType, (packet + hdrLen), (pktSize - hdrLen), jparent);
+
+ /* packet has the minimum allowed size, so the remaining data is
+ * most likely padding, this should not appear as data, so remove it */
+ if (pktSize <= 60 && ret->pData != NULL) {
+ if (!ret->pData[0]) ret->size = 0;
+ }
+ return ret;
+}
diff --git a/contrib/impcap/ftp_parser.c b/contrib/impcap/ftp_parser.c
new file mode 100644
index 0000000..6e724c9
--- /dev/null
+++ b/contrib/impcap/ftp_parser.c
@@ -0,0 +1,152 @@
+/* ftp_parser.c
+ *
+ * This file contains functions to parse FTP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+static const int ftp_cds[] = {
+ 100, 110, 120, 125, 150,
+ 200, 202, 211, 212, 213, 214, 215, 220, 221, 225, 226, 227, 228, 229, 230, 231, 232, 250, 257,
+ 300, 331, 332, 350,
+ 400, 421, 425, 426, 430, 434, 450, 451, 452,
+ 500, 501, 502, 503, 504, 530, 532, 550, 551, 552, 553,
+ 600, 631, 632, 633,
+ 10000, 100054, 10060, 10061, 10066, 10068,
+ 0
+};
+
+static const char *ftp_cmds[] = {
+ "STOR",
+ "TYPE",
+ "ABOR",
+ "ACCT",
+ "ALLO",
+ "APPE",
+ "CDUP",
+ "CWD",
+ "DELE",
+ "HELP",
+ "LIST",
+ "MKD",
+ "MODE",
+ "NLST",
+ "NOOP",
+ "PASS",
+ "PASV",
+ "PORT",
+ "PWD",
+ "QUIT",
+ "REIN",
+ "REST",
+ "RETR",
+ "RMD",
+ "RNFR",
+ "RNTO",
+ "SITE",
+ "SMNT",
+ "STAT",
+ "STOU",
+ "STRU",
+ "SYST",
+ "USER",
+ NULL
+};
+
+/*
+ * This function searches for a valid command in the header (from the list defined in ftp_cmds[])
+ * and returns either the command or a NULL pointer
+*/
+static const char *check_Command_ftp(uchar *first_part_packet) {
+ DBGPRINTF("in check_Command_ftp\n");
+ DBGPRINTF("first_part_packet : '%s' \n", first_part_packet);
+ int i = 0;
+ for (i = 0; ftp_cmds[i] != NULL; i++) {
+ if (strncmp((const char *)first_part_packet, ftp_cmds[i], strlen((const char *)ftp_cmds[i]) + 1) == 0) {
+ return ftp_cmds[i];
+ }
+ }
+ return "UNKNOWN";
+}
+
+/*
+ * This function searches for a valid code in the header (from the list defined in ftp_cds[])
+ * and returns either the command or a NULL pointer
+*/
+static int check_Code_ftp(uchar *first_part_packet) {
+ DBGPRINTF("in check_Code_ftp\n");
+ DBGPRINTF("first_part_packet : %s \n", first_part_packet);
+ int i = 0;
+ for (i = 0; ftp_cds[i] != 0; i++) {
+ if (strtol((const char *)first_part_packet, NULL, 10) == ftp_cds[i]) {
+ return ftp_cds[i];
+ }
+ }
+ return 0;
+}
+
+/*
+ * This function parses the bytes in the received packet to extract FTP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the FTP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where FTP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *ftp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("ftp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 5) { /* too short for ftp packet*/
+ RETURN_DATA_AFTER(0)
+ }
+ uchar *packet2 = (uchar *)malloc(pktSize * sizeof(uchar));
+
+ memcpy(packet2, packet, pktSize); // strtok changes original packet
+ uchar *frst_part_ftp;
+ frst_part_ftp = (uchar *)strtok((char *)packet2, " "); // Get first part of packet ftp
+ strtok(NULL, "\r\n");
+
+ if (frst_part_ftp) {
+ int code = check_Code_ftp(frst_part_ftp);
+ const char *command = check_Command_ftp(frst_part_ftp);
+ if (code != 0) {
+ json_object_object_add(jparent, "FTP_response", json_object_new_int(code));
+ } else if (command != NULL) {
+ json_object_object_add(jparent, "FTP_request", json_object_new_string(command));
+ }
+ }
+ free(packet2);
+ RETURN_DATA_AFTER(0)
+}
diff --git a/contrib/impcap/http_parser.c b/contrib/impcap/http_parser.c
new file mode 100644
index 0000000..56d8a25
--- /dev/null
+++ b/contrib/impcap/http_parser.c
@@ -0,0 +1,159 @@
+/* http_parser.c
+ *
+ * This file contains functions to parse HTTP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+static const char *keywords[] = {
+ "OPTIONS",
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "TRACE",
+ "CONNECT",
+ "HTTP",
+ NULL
+};
+
+static inline char *string_split(char **initString, const char *delimiterString) {
+ char *ret = *initString;
+
+ if (*initString) {
+ char *pos = strstr(*initString, delimiterString);
+ if (pos) {
+ *initString = pos;
+ **initString = '\0';
+ *initString += strlen(delimiterString);
+ } else {
+ *initString = NULL;
+ }
+ }
+
+ return ret;
+}
+
+static inline int has_status_keyword(char *http) {
+ const char *found;
+ int i;
+
+ for (i = 0; keywords[i] != NULL; i++) {
+ found = strstr(http, keywords[i]);
+ if (found && (found - http) < 20) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This function catches HTTP header fields and status line
+ * and adds them to the provided json object
+*/
+static inline void catch_status_and_fields(char *header, struct json_object *jparent) {
+ DBGPRINTF("catch_status_and_fields\n");
+
+ struct json_object *fields = json_object_new_object();
+
+ char *statusLine = string_split(&header, "\r\n");
+ char *firstPart, *secondPart, *thirdPart;
+ firstPart = string_split(&statusLine, " ");
+ secondPart = string_split(&statusLine, " ");
+ thirdPart = statusLine;
+ if (firstPart && secondPart && thirdPart) {
+ if (strstr(firstPart, "HTTP")) {
+ json_object_object_add(jparent, "HTTP_version", json_object_new_string(firstPart));
+ json_object_object_add(jparent, "HTTP_status_code", json_object_new_string(secondPart));
+ json_object_object_add(jparent, "HTTP_reason", json_object_new_string(thirdPart));
+ } else {
+ json_object_object_add(jparent, "HTTP_method", json_object_new_string(firstPart));
+ json_object_object_add(jparent, "HTTP_request_URI", json_object_new_string(secondPart));
+ json_object_object_add(jparent, "HTTP_version", json_object_new_string(thirdPart));
+ }
+ }
+
+ char *fieldValue = string_split(&header, "\r\n");
+ char *field, *value;
+ while (fieldValue) {
+ field = string_split(&fieldValue, ":");
+ value = fieldValue;
+ if (value) {
+ while (*value == ' ') { value++; }
+ DBGPRINTF("got header field -> '%s': '%s'\n", field, value);
+ json_object_object_add(fields, field, json_object_new_string(value));
+ }
+
+ fieldValue = string_split(&header, "\r\n");
+ }
+
+ json_object_object_add(jparent, "HTTP_header_fields", fields);
+
+ return;
+}
+
+/*
+ * This function parses the bytes in the received packet to extract HTTP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the beginning of the header will be checked by the function
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where HTTP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *http_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("http_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+ if (pktSize < 6) {
+ RETURN_DATA_AFTER(0)
+ }
+
+ char *pHttp = malloc(pktSize + 1);
+ char *http = pHttp;
+ memcpy(http, packet, pktSize);
+ *(http + pktSize) = '\0';
+
+ if (!has_status_keyword(http)) {
+ free(pHttp);
+ RETURN_DATA_AFTER(0)
+ }
+
+ char *header = string_split(&http, "\r\n\r\n");
+
+ catch_status_and_fields(header, jparent);
+
+ free(pHttp);
+ RETURN_DATA_AFTER(0)
+}
diff --git a/contrib/impcap/icmp_parser.c b/contrib/impcap/icmp_parser.c
new file mode 100644
index 0000000..8a627ee
--- /dev/null
+++ b/contrib/impcap/icmp_parser.c
@@ -0,0 +1,79 @@
+/* icmp_parser.c
+ *
+ * This file contains functions to parse ICMP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+struct icmp_header_s {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint8_t data[];
+};
+
+typedef struct icmp_header_s icmp_header_t;
+
+/*
+ * This function parses the bytes in the received packet to extract ICMP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the ICMP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where ICMP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *icmp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("icmp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 8) {
+ DBGPRINTF("ICMP packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0);
+ }
+
+ /* Union to prevent cast from uchar to icmp_header_t */
+ union {
+ const uchar *pck;
+ icmp_header_t *hdr;
+ } icmp_header_to_char;
+
+ icmp_header_to_char.pck = packet;
+ icmp_header_t *icmp_header = icmp_header_to_char.hdr;
+
+ json_object_object_add(jparent, "net_icmp_type", json_object_new_int(icmp_header->type));
+ json_object_object_add(jparent, "net_icmp_code", json_object_new_int(icmp_header->code));
+ json_object_object_add(jparent, "icmp_checksum", json_object_new_int(ntohs(icmp_header->checksum)));
+
+ RETURN_DATA_AFTER(8)
+}
diff --git a/contrib/impcap/impcap.c b/contrib/impcap/impcap.c
new file mode 100644
index 0000000..cdb1e54
--- /dev/null
+++ b/contrib/impcap/impcap.c
@@ -0,0 +1,748 @@
+/* impcap.c
+ *
+ * This is an input module using libpcap, a
+ * portable C/C++ library for network traffic capture.
+ * This module reads packets received from a network interface
+ * using libpcap, to extract information such as IP addresses, ports,
+ * protocols, etc... and make it available to rsyslog and other modules.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <signal.h>
+#include <json.h>
+
+#include <pcap.h>
+
+#include "rsyslog.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "datetime.h"
+
+#include "errmsg.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "rainerscript.h"
+#include "rsconf.h"
+#include "glbl.h"
+#include "srUtils.h"
+
+#include "parsers.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("impcap")
+
+#define DEFAULT_META_CONTAINER "!impcap"
+#define DEFAULT_DATA_CONTAINER "!data"
+
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(datetime)
+
+static prop_t *pInputName = NULL;
+
+char *stringToHex(char *string, size_t length);
+
+static ATTR_NORETURN void *startCaptureThread(void *instanceConf);
+
+/* conf structures */
+
+struct instanceConf_s {
+ char *interface;
+ uchar *filePath;
+ pcap_t *device;
+ uchar *filter;
+ uchar *tag;
+ uint8_t promiscuous;
+ uint8_t immediateMode;
+ uint32_t bufSize;
+ uint8_t bufTimeout;
+ uint8_t pktBatchCnt;
+ pthread_t tid;
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ struct instanceConf_s *next;
+};
+
+struct modConfData_s {
+ rsconf_t *pConf;
+ instanceConf_t *root, *tail;
+ uint16_t snap_length;
+ uint8_t metadataOnly;
+ char *metadataContainer;
+ char *dataContainer;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ {"interface", eCmdHdlrGetWord, 0},
+ {"file", eCmdHdlrString, 0},
+ {"promiscuous", eCmdHdlrBinary, 0},
+ {"filter", eCmdHdlrString, 0},
+ {"tag", eCmdHdlrString, 0},
+ {"ruleset", eCmdHdlrString, 0},
+ {"no_buffer", eCmdHdlrBinary, 0},
+ {"buffer_size", eCmdHdlrPositiveInt, 0},
+ {"buffer_timeout", eCmdHdlrPositiveInt, 0},
+ {"packet_count", eCmdHdlrPositiveInt, 0}
+};
+static struct cnfparamblk inppblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(inppdescr) / sizeof(struct cnfparamdescr),
+ inppdescr
+};
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ {"snap_length", eCmdHdlrPositiveInt, 0},
+ {"metadata_only", eCmdHdlrBinary, 0},
+ {"metadata_container", eCmdHdlrGetWord, 0},
+ {"data_container", eCmdHdlrGetWord, 0}
+};
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr) / sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+#include "im-helper.h"
+
+/*
+ * create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst) {
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->interface = NULL;
+ inst->filePath = NULL;
+ inst->device = NULL;
+ inst->promiscuous = 0;
+ inst->filter = NULL;
+ inst->tag = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->immediateMode = 0;
+ inst->bufTimeout = 10;
+ inst->bufSize = 1024 * 1024 * 15; /* should be enough for up to 10Gb interface*/
+ inst->pktBatchCnt = 5;
+
+ /* node created, let's add to global config */
+ if (loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* input instances */
+
+BEGINnewInpInst
+struct cnfparamvals *pvals;
+instanceConf_t *inst;
+int i;
+CODESTARTnewInpInst
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "impcap: required parameters are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for (i = 0 ; i<inppblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(inppblk.descr[i].name, "interface")) {
+ inst->interface = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(inppblk.descr[i].name, "file")) {
+ inst->filePath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(inppblk.descr[i].name, "promiscuous")) {
+ inst->promiscuous = (uint8_t)pvals[i].val.d.n;
+ }
+ else if (!strcmp(inppblk.descr[i].name, "filter")) {
+ inst->
+ filter = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(inppblk.descr[i].name, "tag")) {
+ inst->tag = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(inppblk.descr[i].name, "no_buffer")) {
+ inst->immediateMode = (uint8_t)pvals[i].val.d.n;
+ }
+ else if (!strcmp(inppblk.descr[i].name, "buffer_size")) {
+ inst->bufSize = (uint32_t)pvals[i].val.d.n;
+ }
+ else if (!strcmp(inppblk.descr[i].name, "buffer_timeout")) {
+ inst->bufTimeout = (uint8_t)pvals[i].val.d.n;
+ }
+ else if (!strcmp(inppblk.descr[i].name, "packet_count")) {
+ inst->pktBatchCnt = (uint8_t)pvals[i].val.d.n;
+ }
+ else {
+ dbgprintf("impcap: non-handled param %s in beginCnfLoad\n", inppblk.descr[i].name);
+ }
+ }
+
+finalize_it:
+
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+/* global mod conf (v2 system) */
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if (pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "impcap: error processing module "
+ "config parameters missing [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ for (i = 0 ; i<modpblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(modpblk.descr[i].name, "snap_length")) {
+ loadModConf->snap_length = (int)pvals[i].val.d.n;
+ }
+ else if (!strcmp(modpblk.descr[i].name, "metadata_only")) {
+ loadModConf->metadataOnly = (uint8_t)pvals[i].val.d.n;
+ }
+ else if (!strcmp(modpblk.descr[i].name, "metadata_container")) {
+ loadModConf->metadataContainer = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else if (!strcmp(modpblk.descr[i].name, "data_container")) {
+ loadModConf->dataContainer = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ }
+ else {
+ dbgprintf("impcap: non-handled param %s in beginSetModCnf\n", modpblk.descr[i].name);
+ }
+ }
+
+ if (!loadModConf->metadataContainer)
+ CHKmalloc(loadModConf->metadataContainer = strdup(DEFAULT_META_CONTAINER));
+
+ if (!loadModConf->dataContainer)
+ CHKmalloc(loadModConf->dataContainer = strdup(DEFAULT_DATA_CONTAINER));
+finalize_it:
+ if (pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+/* config v2 system */
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ loadModConf->pConf = pConf;
+ loadModConf->metadataOnly = 0;
+ loadModConf->snap_length = 65535;
+ loadModConf->metadataContainer = NULL;
+ loadModConf->dataContainer = NULL;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) {
+ LogError(0, NO_ERRCODE, "impcap: ruleset '%s' for interface %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->interface);
+}
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ if (pModConf->root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS , "impcap: module loaded, but "
+ "no interface defined - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+
+ if (pModConf->metadataOnly) { /* if metadata_only is "on", snap_length is overwritten */
+ pModConf->snap_length = 100; /* arbitrary value, but should be enough for most protocols */
+ }
+
+ if (!pModConf->metadataContainer || !pModConf->dataContainer) {
+ LogError(0, RS_RET_LOAD_ERROR, "impcap: no name defined for metadata_container and "
+ "data_container, this shouldn't happen");
+ }
+ else {
+ DBGPRINTF("impcap: metadata will be stored in '%s', and data in '%s'\n",
+ pModConf->metadataContainer, pModConf->dataContainer);
+ }
+
+ for (inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ if (inst->interface ==NULL &&inst->filePath == NULL) {
+ iRet = RS_RET_INVALID_PARAMS;
+ LogError(0, RS_RET_LOAD_ERROR, "impcap: 'interface' or 'file' must be specified");
+ break;
+ }
+ if (inst->interface !=NULL &&inst->filePath != NULL) {
+ iRet = RS_RET_INVALID_PARAMS;
+ LogError(0, RS_RET_LOAD_ERROR, "impcap: either 'interface' or 'file' must be specified");
+ break;
+ }
+ }
+
+ENDcheckCnf
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+ instanceConf_t *inst;
+ pcap_t *dev = NULL;
+ struct bpf_program filter_program;
+ bpf_u_int32 SubNet, NetMask;
+ char errBuf[PCAP_ERRBUF_SIZE];
+ uint8_t retCode = 0;
+CODESTARTactivateCnf
+ for (inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ if (inst->filePath != NULL) {
+ dev = pcap_open_offline((const char *)inst->filePath, errBuf);
+ if (dev == NULL) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while opening capture file: '%s'", errBuf);
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ }
+ else if (inst->interface != NULL) {
+ dev = pcap_create((const char *)inst->interface, errBuf);
+ if (dev == NULL) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while creating packet capture: '%s'",
+ errBuf);
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+
+ DBGPRINTF("setting snap_length %d\n", pModConf->snap_length);
+ if (pcap_set_snaplen(dev, pModConf->snap_length)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting snap length: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+
+ DBGPRINTF("setting promiscuous %d\n", inst->promiscuous);
+ if (pcap_set_promisc(dev, inst->promiscuous)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting promiscuous mode: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+
+ if (inst->immediateMode) {
+ DBGPRINTF("setting immediate mode %d\n", inst->immediateMode);
+ retCode = pcap_set_immediate_mode(dev, inst->immediateMode);
+ if (retCode) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting immediate mode: '%s',"
+ " using buffer instead\n",pcap_geterr(dev));
+ }
+ }
+
+ if (!inst->immediateMode || retCode){
+ DBGPRINTF("setting buffer size %u \n", inst->bufSize);
+ if (pcap_set_buffer_size(dev, inst->bufSize)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting buffer size: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ DBGPRINTF("setting buffer timeout %dms\n", inst->bufTimeout);
+ if (pcap_set_timeout(dev, inst->bufTimeout)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting buffer timeout: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ }
+
+ switch (pcap_activate(dev)) {
+ case PCAP_WARNING_PROMISC_NOTSUP:
+ LogError(0, NO_ERRCODE, "interface doesn't support promiscuous mode");
+ break;
+ case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
+ LogError(0, NO_ERRCODE, "timestamp type is not supported");
+ break;
+ case PCAP_WARNING:
+ LogError(0, NO_ERRCODE, "pcap: %s", pcap_geterr(dev));
+ break;
+ case PCAP_ERROR_ACTIVATED:
+ LogError(0, RS_RET_LOAD_ERROR, "already activated, shouldn't happen");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR_NO_SUCH_DEVICE:
+ LogError(0, RS_RET_LOAD_ERROR, "device doesn't exist");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR_PERM_DENIED:
+ LogError(0, RS_RET_LOAD_ERROR, "elevated privilege needed to open capture "
+ "interface");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR_PROMISC_PERM_DENIED:
+ LogError(0, RS_RET_LOAD_ERROR, "elevated privilege needed to put interface "
+ "in promiscuous mode");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR_RFMON_NOTSUP:
+ LogError(0, RS_RET_LOAD_ERROR, "interface doesn't support monitor mode");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR_IFACE_NOT_UP:
+ LogError(0, RS_RET_LOAD_ERROR, "interface is not up");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ case PCAP_ERROR:
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: %s", pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+
+ if (inst->filter != NULL) {
+ DBGPRINTF("getting netmask on %s\n", inst->interface);
+ //obtain the subnet
+ if (pcap_lookupnet(inst->interface, &SubNet, &NetMask, errBuf)){
+ DBGPRINTF("could not get netmask\n");
+ NetMask = PCAP_NETMASK_UNKNOWN;
+ }
+ DBGPRINTF("setting filter to '%s'\n", inst->filter);
+ /* Compile the filter */
+ if (pcap_compile(dev, &filter_program, (const char *)inst->filter, 1, NetMask)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while compiling filter: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ else if (pcap_setfilter(dev, &filter_program)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting filter: '%s'",
+ pcap_geterr(dev));
+ pcap_freecode(& filter_program);
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ pcap_freecode(&filter_program);
+ }
+
+ if (pcap_set_datalink(dev, DLT_EN10MB)) {
+ LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting datalink type: '%s'",
+ pcap_geterr(dev));
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+ } /* inst->interface != NULL */
+ else {
+ LogError(0, RS_RET_LOAD_ERROR, "impcap: no capture method specified, "
+ "please specify either 'interface' or 'file' in config");
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR);
+ }
+
+ inst->device = dev;
+ }
+
+finalize_it:
+ if(iRet != 0) {
+ if(dev) pcap_close(dev);
+ }
+ENDactivateCnf
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ DBGPRINTF("impcap: freeing confs...\n");
+ for (inst = pModConf->root ; inst != NULL ; ) {
+ del = inst;
+ inst = inst->next;
+ free(del->filePath);
+ free(del->filter);
+ free(del->pszBindRuleset);
+ free(del->interface);
+ free(del->tag);
+ free(del);
+ }
+ free(pModConf->metadataContainer);
+ free(pModConf->dataContainer);
+ DBGPRINTF("impcap: finished freeing confs\n");
+ENDfreeCnf
+
+/* runtime functions */
+
+/*
+ * Converts a list of bytes to their hexadecimal representation in ASCII
+ *
+ * Gets the list of bytes and the length as parameters
+ *
+ * Returns a pointer on the new list, being a string of ASCII characters
+ * representing hexadecimal values, in the form "A5B34C65..."
+ * its size is twice length parameter + 1
+*/
+char *stringToHex(char *string, size_t length) {
+ const char *hexChar = "0123456789ABCDEF";
+ char *retBuf;
+ uint16_t i;
+
+ retBuf = malloc((2 * length + 1) * sizeof(char));
+ for (i = 0; i < length; ++i) {
+ retBuf[2 * i] = hexChar[(string[i] & 0xF0) >> 4];
+ retBuf[2 * i + 1] = hexChar[string[i] & 0x0F];
+ }
+ retBuf[2 * length] = '\0';
+
+ return retBuf;
+}
+
+/*
+ * This method parses every packet received by libpcap, and is called by it
+ * It creates the message for Rsyslog, calls the parsers and add all necessary information
+ * in the message
+*/
+void packet_parse(uchar *arg, const struct pcap_pkthdr *pkthdr, const uchar *packet) {
+ DBGPRINTF("impcap : entered packet_parse\n");
+ smsg_t *pMsg;
+
+ /* Prevent cast error from char to int with arg */
+ union {
+ uchar *buf;
+ int *id;
+ } aux;
+
+ aux.buf = arg;
+ int *id = aux.id;
+ msgConstruct(&pMsg);
+
+ MsgSetInputName(pMsg, pInputName);
+ //search inst in loadmodconf,and check if there is tag. if so set tag in msg.
+ pthread_t ctid = pthread_self();
+ instanceConf_t * inst;
+ for (inst = runModConf->root; inst != NULL; inst = inst->next) {
+ if (pthread_equal(ctid, inst->tid)) {
+ if (inst->pBindRuleset != NULL) {
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ }
+ if (inst->tag != NULL) {
+ MsgSetTAG(pMsg, inst->tag, strlen((const char *)inst->tag));
+ }
+ }
+ }
+
+
+ struct json_object *jown = json_object_new_object();
+ json_object_object_add(jown, "ID", json_object_new_int(++(*id)));
+
+ struct syslogTime sysTimePkt;
+ char timeStr[30];
+ struct timeval tv = pkthdr->ts;
+ datetime.timeval2syslogTime(&tv, &sysTimePkt, 1/*inUTC*/);
+ if (datetime.formatTimestamp3339(&sysTimePkt, timeStr)) {
+ json_object_object_add(jown, "timestamp", json_object_new_string(timeStr));
+ }
+
+ json_object_object_add(jown, "net_bytes_total", json_object_new_int(pkthdr->len));
+
+ data_ret_t * dataLeft = eth_parse(packet, pkthdr->caplen, jown);
+
+ json_object_object_add(jown, "net_bytes_data", json_object_new_int(dataLeft->size));
+ char *dataHex = stringToHex(dataLeft->pData, dataLeft->size);
+ if (dataHex != NULL) {
+ struct json_object *jadd = json_object_new_object();
+ json_object_object_add(jadd, "length", json_object_new_int(strlen(dataHex)));
+ json_object_object_add(jadd, "content", json_object_new_string(dataHex));
+ msgAddJSON(pMsg, (uchar *)runModConf->dataContainer, jadd, 0, 0);
+ free(dataHex);
+ }
+ free(dataLeft);
+
+ msgAddJSON(pMsg, (uchar *)runModConf->metadataContainer, jown, 0, 0);
+ submitMsg2(pMsg);
+}
+
+/* This is used to terminate the plugin.
+ */
+static void
+doSIGTTIN(int __attribute__((unused)) sig)
+{
+ pthread_t tid = pthread_self();
+ const int bTerminate = ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
+ DBGPRINTF("impcap: awoken via SIGTTIN; bTerminateInputs: %d\n", bTerminate);
+ if(bTerminate) {
+ for(instanceConf_t *inst = runModConf->root; inst != NULL; inst = inst->next) {
+ if(pthread_equal(tid, inst->tid)) {
+ pcap_breakloop(inst->device);
+ DBGPRINTF("impcap: thread %lx, termination requested via SIGTTIN - telling libpcap\n",
+ (long unsigned int)tid);
+ }
+ }
+ }
+}
+
+/*
+ * This is the main function for each thread
+ * taking care of a specified network interface
+*/
+static ATTR_NORETURN void *startCaptureThread(void *instanceConf) {
+ int id = 0;
+ pthread_t tid = pthread_self();
+
+ /* we want to support non-cancel input termination. To do so, we must signal libpcap
+ * when to stop. As we run on the same thread, we need to register as SIGTTIN handler,
+ * which will be used to put the terminating condition into libpcap.
+ */
+ DBGPRINTF("impcap: setting catch for SIGTTIN, thread %lx\n",
+ (long unsigned int)tid);
+ sigset_t sigSet;
+ struct sigaction sigAct;
+ sigfillset(&sigSet);
+ pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
+ sigemptyset(&sigSet);
+ sigaddset(&sigSet, SIGTTIN);
+ pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
+ memset(&sigAct, 0, sizeof (sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = doSIGTTIN;
+ sigaction(SIGTTIN, &sigAct, NULL);
+
+ instanceConf_t * inst = (instanceConf_t * )instanceConf;
+ DBGPRINTF("impcap: thread %lx, begin capture!\n",
+ (long unsigned int)tid);
+ while (glbl.GetGlobalInputTermState() == 0) {
+ pcap_dispatch(inst->device, inst->pktBatchCnt, packet_parse, (uchar * ) & id);
+ }
+ DBGPRINTF("impcap: thread %lx, capture finished\n",
+ (long unsigned int)tid);
+ pthread_exit(0);
+}
+
+BEGINrunInput
+ instanceConf_t *inst;
+ int ret = 0;
+CODESTARTrunInput
+ for (inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ /* creates a thread and starts capturing on the interface */
+ ret = pthread_create(&inst->tid, NULL, startCaptureThread, inst);
+ if (ret) {
+ LogError(0, RS_RET_NO_RUN, "impcap: error while creating threads\n");
+ }
+ }
+
+ DBGPRINTF("impcap: starting to wait for close condition\n");
+ // TODO: Use thread for capture instead of just waiting
+ while(glbl.GetGlobalInputTermState() == 0) {
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(0, 400000);
+ }
+
+ DBGPRINTF("impcap: received close signal, signaling instance threads...\n");
+ for (inst = runModConf->root; inst != NULL; inst = inst->next) {
+ pthread_kill(inst->tid, SIGTTIN);
+ }
+
+ DBGPRINTF("impcap: threads signaled, waiting for join...");
+ for (inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ pthread_join(inst->tid, NULL);
+ pcap_close(inst->device);
+ }
+
+ DBGPRINTF("impcap: finished threads, stopping\n");
+ENDrunInput
+
+BEGINwillRun
+CODESTARTwillRun
+/* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("impcap"), sizeof("impcap") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+BEGINafterRun
+CODESTARTafterRun
+ if (pInputName != NULL) {
+ prop.Destruct(&pInputName);
+ }
+ENDafterRun
+
+BEGINmodExit
+CODESTARTmodExit
+ DBGPRINTF("impcap:: modExit\n");
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+/* declaration of functions */
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+ CODEqueryEtryPt_STD_IMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_QUERIES
+ CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+ CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES /* might need it */
+ CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/impcap/ipv4_parser.c b/contrib/impcap/ipv4_parser.c
new file mode 100644
index 0000000..2693c60
--- /dev/null
+++ b/contrib/impcap/ipv4_parser.c
@@ -0,0 +1,101 @@
+/* ipv4_parser.c
+ *
+ * This file contains functions to parse IP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+struct ipv4_header_s {
+/*#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char version:4;
+ unsigned char ihl:4;
+#else*/
+ unsigned char ihl:4;
+ unsigned char version:4;
+//#endif
+ uint8_t service;
+ uint16_t totLen;
+ uint16_t id;
+ uint16_t frag;
+ uint8_t ttl;
+ uint8_t proto;
+ uint16_t hdrChksum;
+ uint8_t addrSrc[4];
+ uint8_t addrDst[4];
+ uint8_t pOptions[];
+};
+
+typedef struct ipv4_header_s ipv4_header_t;
+
+/*
+ * This function parses the bytes in the received packet to extract IP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the IP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where IP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *ipv4_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("ipv4_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 20) { /* too small for IPv4 header + data (header might be longer)*/
+ DBGPRINTF("IPv4 packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ /* Union to prevent cast from uchar to ipv4_header_t */
+ union {
+ const uchar *pck;
+ ipv4_header_t *hdr;
+ } ipv4_header_to_char;
+
+ ipv4_header_to_char.pck = packet;
+ ipv4_header_t *ipv4_header = ipv4_header_to_char.hdr;
+
+ char addrSrc[20], addrDst[20];
+ uint8_t hdrLen = 4 * ipv4_header->ihl; /* 4 x length in words */
+
+ inet_ntop(AF_INET, (void *)&ipv4_header->addrSrc, addrSrc, 20);
+ inet_ntop(AF_INET, (void *)&ipv4_header->addrDst, addrDst, 20);
+
+ json_object_object_add(jparent, "net_dst_ip", json_object_new_string((char *)addrDst));
+ json_object_object_add(jparent, "net_src_ip", json_object_new_string((char *)addrSrc));
+ json_object_object_add(jparent, "IP_ihl", json_object_new_int(ipv4_header->ihl));
+ json_object_object_add(jparent, "net_ttl", json_object_new_int(ipv4_header->ttl));
+ json_object_object_add(jparent, "IP_proto", json_object_new_int(ipv4_header->proto));
+
+
+ return ip_proto_parse(ipv4_header->proto, (packet + hdrLen), (pktSize - hdrLen), jparent);
+}
diff --git a/contrib/impcap/ipv6_parser.c b/contrib/impcap/ipv6_parser.c
new file mode 100644
index 0000000..25c6b4c
--- /dev/null
+++ b/contrib/impcap/ipv6_parser.c
@@ -0,0 +1,305 @@
+/* ipv6_parser.c
+ *
+ * This file contains functions to parse IPv6 headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpacked"
+#pragma GCC diagnostic ignored "-Wattributes"
+typedef struct __attribute__ ((__packed__)) ipv6_header_s {
+#ifndef IPV6_VERSION_MASK
+#define IPV6_VERSION_MASK 0xF0000000
+#endif
+#ifndef IPV6_TC_MASK
+#define IPV6_TC_MASK 0x0FF00000
+#endif
+#ifndef IPV6_FLOW_MASK
+#define IPV6_FLOW_MASK 0x000FFFFF
+#endif
+ uint32_t vtf;
+ uint16_t dataLength;
+ uint8_t nextHeader;
+#define IPV6_NHDR_HBH 0
+#define IPV6_NHDR_TCP 6
+#define IPV6_NHDR_UDP 17
+#define IPV6_NHDR_ENCIP6 41
+#define IPV6_NHDR_ROUT 43
+#define IPV6_NHDR_FRAG 44
+#define IPV6_NHDR_RRSV 46
+#define IPV6_NHDR_SEC 50
+#define IPV6_NHDR_AUTH 51
+#define IPV6_NHDR_ICMP6 58
+#define IPV6_NHDR_NONHDR 59
+#define IPV6_NHDR_DOPTS 60
+
+ uint8_t hopLimit;
+ uint8_t addrSrc[16];
+ uint8_t addrDst[16];
+} ipv6_header_t;
+#pragma GCC diagnostic pop
+
+#ifndef IPV6_VERSION
+#define IPV6_VERSION(h) (ntohl(h->vtf) & IPV6_VERSION_MASK)>>28
+#endif
+#ifndef IPV6_TC
+#define IPV6_TC(h) (ntohl(h->vtf) & IPV6_TC_MASK)>>20
+#endif
+#ifndef IPV6_FLOW
+#define IPV6_FLOW(h) (ntohl(h->vtf) & IPV6_FLOW_MASK)
+#endif
+
+/* extension headers */
+typedef struct hbh_header_s {
+ uint8_t nextHeader;
+ uint8_t hLength;
+ uint8_t *pOptions;
+} hbh_header_t;
+
+typedef struct dest_header_s {
+ uint8_t nextHeader;
+ uint8_t hLength;
+ uint8_t *pOptions;
+} dest_header_t;
+
+typedef struct route_header_s {
+ uint8_t nextHeader;
+ uint8_t hLength;
+ uint8_t rType;
+ uint8_t segsLeft;
+ uint32_t reserved;
+ uint8_t addrs[16];
+} route_header_t;
+
+typedef struct frag_header_s {
+ uint8_t nextHeader;
+ uint8_t reserved;
+ uint16_t offsetFlags;
+ uint32_t id;
+} frag_header_t;
+
+static inline uint8_t hbh_header_parse(const uchar **packet, int *pktSize) {
+ DBGPRINTF("hbh_header_parse\n");
+
+ /* Union to prevent cast from uchar to hbh_header_t */
+ union {
+ const uchar *pck;
+ hbh_header_t *hdr;
+ } hbh_header_to_char;
+
+ hbh_header_to_char.pck = *packet;
+ hbh_header_t *hbh_header = hbh_header_to_char.hdr;
+
+ /* hbh_header->hLength is the number of octets of header in 8-octet units minus 1
+ * the header length SHOULD be a multiple of 8 */
+ uint8_t hByteLength = hbh_header->hLength * 8 + 8;
+ DBGPRINTF("hByteLength: %d\n", hByteLength);
+ *pktSize -= hByteLength;
+ *packet += hByteLength;
+
+ return hbh_header->nextHeader;
+}
+
+static inline uint8_t dest_header_parse(const uchar **packet, int *pktSize) {
+ DBGPRINTF("dest_header_parse\n");
+
+ /* Union to prevent cast from uchar to dest_header_t */
+ union {
+ const uchar *pck;
+ dest_header_t *hdr;
+ } dest_header_to_char;
+
+ dest_header_to_char.pck = *packet;
+ dest_header_t *dest_header = dest_header_to_char.hdr;
+
+ /* dest_header->hLength is the number of octets of header in 8-octet units minus 1
+ * the header length SHOULD be a multiple of 8 */
+ uint8_t hByteLength = dest_header->hLength * 8 + 8;
+ DBGPRINTF("hByteLength: %d\n", hByteLength);
+ *pktSize -= hByteLength;
+ *packet += hByteLength;
+
+ return dest_header->nextHeader;
+}
+
+static inline uint8_t route_header_parse(const uchar **packet, int *pktSize, struct json_object *jparent) {
+ DBGPRINTF("route_header_parse\n");
+
+ /* Union to prevent cast from uchar to route_header_t */
+ union {
+ const uchar *pck;
+ route_header_t *hdr;
+ } route_header_to_char;
+
+ route_header_to_char.pck = *packet;
+ route_header_t *route_header = route_header_to_char.hdr;
+
+ /* route_header->hLength is the number of octets of header in 8-octet units minus 1
+ * the header length (in bytes) SHOULD be a multiple of 8 */
+ uint8_t hByteLength = route_header->hLength * 8 + 8;
+ *pktSize -= hByteLength;
+ *packet += hByteLength;
+
+ if (route_header->rType == 0) {
+ json_object_object_add(jparent, "IP6_route_seg_left", json_object_new_int(route_header->segsLeft));
+
+ hByteLength -= 8; //leave only length of routing addresses
+
+ char addrStr[40], routeFieldName[20];
+ int addrNum = 1;
+ uint8_t *addr = &(route_header->addrs[0]);
+
+ //while there is enough space for an IPv6 address
+ while (hByteLength >= 16) {
+ inet_ntop(AF_INET6, (void *)addr, addrStr, 40);
+ snprintf(routeFieldName, 20, "IP6_route_%d", addrNum++);
+ json_object_object_add(jparent, routeFieldName, json_object_new_string((char *)addrStr));
+
+ addr += 16;
+ hByteLength -= 16;
+ }
+ }
+
+ return route_header->nextHeader;
+}
+
+#define FRAG_OFFSET_MASK 0xFFF8
+#define MFLAG_MASK 0x0001
+static inline uint8_t frag_header_parse(const uchar **packet, int *pktSize, struct json_object *jparent) {
+ DBGPRINTF("frag_header_parse\n");
+
+ /* Union to prevent cast from uchar to frag_header_t */
+ union {
+ const uchar *pck;
+ frag_header_t *hdr;
+ } frag_header_to_char;
+
+ frag_header_to_char.pck = *packet;
+ frag_header_t *frag_header = frag_header_to_char.hdr;
+
+ uint16_t flags = ntohs(frag_header->offsetFlags);
+
+ json_object_object_add(jparent, "IP6_frag_offset", json_object_new_int((flags & FRAG_OFFSET_MASK) >> 3));
+ json_object_object_add(jparent, "IP6_frag_more", json_object_new_boolean(flags & MFLAG_MASK));
+ json_object_object_add(jparent, "IP6_frag_id", json_object_new_int64(frag_header->id));
+
+ *pktSize -= 8;
+ *packet += 8;
+
+ return frag_header->nextHeader;
+}
+
+/*
+ * This function parses the bytes in the received packet to extract IPv6 metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the IPv6 header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where IPv6 metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *ipv6_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("ipv6_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 40) { /* too small for IPv6 header + data (header might be longer)*/
+ DBGPRINTF("IPv6 packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ ipv6_header_t *ipv6_header = (ipv6_header_t *)packet;
+
+ char addrSrc[40], addrDst[40];
+
+ inet_ntop(AF_INET6, (void *)&ipv6_header->addrSrc, addrSrc, 40);
+ inet_ntop(AF_INET6, (void *)&ipv6_header->addrDst, addrDst, 40);
+
+ json_object_object_add(jparent, "net_dst_ip", json_object_new_string((char *)addrDst));
+ json_object_object_add(jparent, "net_src_ip", json_object_new_string((char *)addrSrc));
+ json_object_object_add(jparent, "net_ttl", json_object_new_int(ipv6_header->hopLimit));
+
+ uint8_t nextHeader = ipv6_header->nextHeader;
+
+ packet += sizeof(ipv6_header_t);
+ pktSize -= sizeof(ipv6_header_t);
+
+ DBGPRINTF("beginning ext headers scan\n");
+ uint8_t hasNext = 1;
+ do {
+ switch (nextHeader) {
+ case IPV6_NHDR_HBH:
+ nextHeader = hbh_header_parse(&packet, &pktSize);
+ break;
+ case IPV6_NHDR_TCP:
+ json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader));
+ return tcp_parse(packet, pktSize, jparent);
+ case IPV6_NHDR_UDP:
+ json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader));
+ return udp_parse(packet, pktSize, jparent);
+ case IPV6_NHDR_ENCIP6:
+ hasNext = 0;
+ break;
+ case IPV6_NHDR_ROUT:
+ nextHeader = route_header_parse(&packet, &pktSize, jparent);
+ break;
+ case IPV6_NHDR_FRAG:
+ nextHeader = frag_header_parse(&packet, &pktSize, jparent);
+ break;
+ case IPV6_NHDR_RRSV:
+ hasNext = 0;
+ break;
+ case IPV6_NHDR_SEC:
+ hasNext = 0;
+ break;
+ case IPV6_NHDR_AUTH:
+ hasNext = 0;
+ break;
+ case IPV6_NHDR_ICMP6:
+ json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader));
+ return icmp_parse(packet, pktSize, jparent);
+ case IPV6_NHDR_NONHDR:
+ hasNext = 0;
+ break;
+ case IPV6_NHDR_DOPTS:
+ nextHeader = dest_header_parse(&packet, &pktSize);
+ break;
+ default:
+ hasNext = 0;
+ break;
+ }
+ } while (hasNext);
+
+ json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader));
+ RETURN_DATA_AFTER(0)
+}
diff --git a/contrib/impcap/ipx_parser.c b/contrib/impcap/ipx_parser.c
new file mode 100644
index 0000000..acd43bc
--- /dev/null
+++ b/contrib/impcap/ipx_parser.c
@@ -0,0 +1,97 @@
+/* ipx_parser.c
+ *
+ * This file contains functions to parse IPX (Novell) headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpacked"
+#pragma GCC diagnostic ignored "-Wattributes"
+struct __attribute__ ((__packed__)) ipx_header_s {
+ uint16_t chksum;
+ uint16_t pktLen;
+ uint8_t transCtrl;
+ uint8_t type;
+ uint32_t dstNet;
+ uint8_t dstNode[6];
+ uint16_t dstSocket;
+ uint32_t srcNet;
+ uint8_t srcNode[6];
+ uint16_t srcSocket;
+};
+#pragma GCC diagnostic pop
+
+typedef struct ipx_header_s ipx_header_t;
+
+/*
+ * This function parses the bytes in the received packet to extract IPX metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the IPX header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where IPX metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *ipx_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+
+ DBGPRINTF("entered ipx_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 30) { /* too short for IPX header */
+ DBGPRINTF("IPX packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ char ipxSrcNode[20], ipxDstNode[20];
+ ipx_header_t *ipx_header = (ipx_header_t *)packet;
+
+ snprintf(ipxDstNode, sizeof(ipxDstNode), "%02x:%02x:%02x:%02x:%02x:%02x", ipx_header->dstNode[0],
+ ipx_header->dstNode[1], ipx_header->dstNode[2], ipx_header->dstNode[3], ipx_header->dstNode[4],
+ ipx_header->dstNode[5]);
+
+ snprintf(ipxSrcNode, sizeof(ipxSrcNode), "%02x:%02x:%02x:%02x:%02x:%02x", ipx_header->srcNode[0],
+ ipx_header->srcNode[1], ipx_header->srcNode[2], ipx_header->srcNode[3], ipx_header->srcNode[4],
+ ipx_header->srcNode[5]);
+
+ json_object_object_add(jparent, "IPX_transCtrl", json_object_new_int(ipx_header->transCtrl));
+ json_object_object_add(jparent, "IPX_type", json_object_new_int(ipx_header->type));
+ json_object_object_add(jparent, "IPX_dest_net", json_object_new_int(ntohl(ipx_header->dstNet)));
+ json_object_object_add(jparent, "IPX_src_net", json_object_new_int(ntohl(ipx_header->srcNet)));
+ json_object_object_add(jparent, "IPX_dest_node", json_object_new_string(ipxDstNode));
+ json_object_object_add(jparent, "IPX_src_node", json_object_new_string(ipxSrcNode));
+ json_object_object_add(jparent, "IPX_dest_socket", json_object_new_int(ntohs(ipx_header->dstSocket)));
+ json_object_object_add(jparent, "IPX_src_socket", json_object_new_int(ntohs(ipx_header->srcSocket)));
+
+ RETURN_DATA_AFTER(30)
+}
diff --git a/contrib/impcap/llc_parser.c b/contrib/impcap/llc_parser.c
new file mode 100644
index 0000000..fca4568
--- /dev/null
+++ b/contrib/impcap/llc_parser.c
@@ -0,0 +1,109 @@
+/* llc_parser.c
+ *
+ * This file contains functions to parse llc headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+/*
+ * This function parses the bytes in the received packet to extract LLC metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the LLC header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where LLC metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *llc_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("entered llc_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 3) { /* too short for llc header */
+ DBGPRINTF("LLC packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ uint8_t dsapField, dsap, ssapField, ssap;
+ uint16_t ctrl;
+ uint8_t headerLen;
+
+ dsapField = (uint8_t)packet[0];
+ ssapField = (uint8_t)packet[1];
+ DBGPRINTF("dsapField : %02X\n", dsapField);
+ DBGPRINTF("ssapField : %02X\n", ssapField);
+
+ if (dsapField == 0xff && ssapField == 0xff) {
+ /* this is an IPX packet, without LLC */
+ return ipx_parse(packet, pktSize, jparent);
+ }
+
+ if ((packet[2] & 0x03) == 3) {
+ /* U frame: LLC control is 8 bits */
+ ctrl = (uint8_t)packet[2];
+ headerLen = 3;
+ } else {
+ /* I and S data frames: LLC control is 16 bits */
+ ctrl = ntohs((uint16_t)packet[2]);
+ headerLen = 4;
+ }
+
+ /* don't take last bit into account */
+ dsap = dsapField & 0xfe;
+ ssap = ssapField & 0xfe;
+
+ json_object_object_add(jparent, "LLC_dsap", json_object_new_int(dsap));
+ json_object_object_add(jparent, "LLC_ssap", json_object_new_int(ssap));
+ json_object_object_add(jparent, "LLC_ctrl", json_object_new_int(ctrl));
+
+ if (dsap == 0xaa && ssap == 0xaa && ctrl == 0x03) {
+ /* SNAP header */
+ uint32_t orgCode = packet[headerLen] << 16 |
+ packet[headerLen + 1] << 8 |
+ packet[headerLen + 2];
+ uint16_t ethType = packet[headerLen + 3] << 8 |
+ packet[headerLen + 4];
+ json_object_object_add(jparent, "SNAP_oui", json_object_new_int(orgCode));
+ json_object_object_add(jparent, "SNAP_ethType", json_object_new_int(ethType));
+ return eth_proto_parse(ethType, packet + headerLen, pktSize - headerLen, jparent);
+ }
+ if (dsap == 0x06 && ssap == 0x06 && ctrl == 0x03) {
+ /* IPv4 header */
+ return ipv4_parse(packet + headerLen, pktSize - headerLen, jparent);
+ }
+ if (dsap == 0xe0 && ssap == 0xe0 && ctrl == 0x03) {
+ /* IPX packet with LLC */
+ return ipx_parse(packet + headerLen, pktSize - headerLen, jparent);
+ }
+
+ RETURN_DATA_AFTER(headerLen)
+}
diff --git a/contrib/impcap/parsers.h b/contrib/impcap/parsers.h
new file mode 100644
index 0000000..d2e71d4
--- /dev/null
+++ b/contrib/impcap/parsers.h
@@ -0,0 +1,189 @@
+/* parser.h
+ *
+ * This file contains the prototypes of all the parsers available within impcap.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pcap.h>
+
+#include "rsyslog.h"
+#include "msg.h"
+#include "dirty.h"
+
+#ifdef __FreeBSD__
+#include <sys/socket.h>
+#else
+
+#include <netinet/ether.h>
+
+#endif
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <net/ethernet.h>
+#include <arpa/inet.h>
+
+#ifndef INCLUDED_PARSER_H
+#define INCLUDED_PARSER_H 1
+
+/* data return structure */
+struct data_ret_s {
+ size_t size;
+ char *pData;
+};
+typedef struct data_ret_s data_ret_t;
+
+#define RETURN_DATA_AFTER(x) data_ret_t *retData = malloc(sizeof(data_ret_t)); \
+ if(pktSize > x) { \
+ retData->size = pktSize - x; \
+ retData->pData = (char *)packet + x; \
+ } \
+ else { \
+ retData->size = 0; \
+ retData->pData = NULL; \
+ } \
+ return retData; \
+
+/* --- handlers prototypes --- */
+void packet_parse(uchar *arg, const struct pcap_pkthdr *pkthdr, const uchar *packet);
+
+data_ret_t *eth_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *llc_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *ipx_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *ipv4_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *icmp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *tcp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *udp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *ipv6_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *arp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *rarp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *ah_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *esp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *ftp_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *http_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+data_ret_t *dns_parse(const uchar *packet, int pktSize, struct json_object *jparent);
+
+
+// inline function definitions
+static inline data_ret_t *dont_parse(
+ const uchar *packet,
+ int pktSize,
+ __attribute__((unused)) struct json_object *jparent);
+
+static inline data_ret_t *eth_proto_parse(
+ uint16_t ethProto,
+ const uchar *packet,
+ int pktSize,
+ struct json_object *jparent);
+
+static inline data_ret_t *ip_proto_parse(
+ uint16_t ipProto,
+ const uchar *packet,
+ int pktSize,
+ struct json_object *jparent);
+
+/*
+ * Mock function to do no parsing when protocol is not a valid number
+*/
+static inline data_ret_t *dont_parse(
+ const uchar *packet,
+ int pktSize,
+ __attribute__((unused)) struct json_object *jparent)
+{
+ DBGPRINTF("protocol not handled\n");
+ RETURN_DATA_AFTER(0)
+}
+
+// proto code handlers
+static inline data_ret_t *eth_proto_parse(
+ uint16_t ethProto,
+ const uchar *packet,
+ int pktSize,
+ struct json_object *jparent)
+{
+ switch(ethProto) {
+ case ETHERTYPE_IP:
+ return ipv4_parse(packet, pktSize, jparent);
+ case ETHERTYPE_IPV6:
+ return ipv6_parse(packet, pktSize, jparent);
+ case ETHERTYPE_ARP:
+ return arp_parse(packet, pktSize, jparent);
+ case ETHERTYPE_REVARP:
+ return rarp_parse(packet, pktSize, jparent);
+ case ETHERTYPE_IPX:
+ return ipx_parse(packet, pktSize, jparent);
+ default:
+ return dont_parse(packet, pktSize, jparent);
+ }
+}
+
+static inline data_ret_t *ip_proto_parse(
+ uint16_t ipProto,
+ const uchar *packet,
+ int pktSize,
+ struct json_object *jparent)
+{
+ switch(ipProto) {
+ case IPPROTO_TCP:
+ return tcp_parse(packet, pktSize, jparent);
+ case IPPROTO_UDP:
+ return udp_parse(packet, pktSize, jparent);
+ case IPPROTO_ICMP:
+ return icmp_parse(packet, pktSize, jparent);
+ default:
+ return dont_parse(packet, pktSize, jparent);
+ }
+}
+
+#endif /* INCLUDED_PARSER_H */
diff --git a/contrib/impcap/smb_parser.c b/contrib/impcap/smb_parser.c
new file mode 100644
index 0000000..e673cd3
--- /dev/null
+++ b/contrib/impcap/smb_parser.c
@@ -0,0 +1,145 @@
+/* smb_parser.c
+ *
+ * This file contains functions to parse SMB (version 2 and 3) headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+/* SMB2 opCodes */
+#define SMB2_NEGOTIATE 0x00
+#define SMB2_SESSIONSET 0x01
+#define SMB2_SESSIONLOGOFF 0x02
+#define SMB2_TREECONNECT 0x03
+#define SMB2_TREEDISCONNECT 0x04
+#define SMB2_CREATE 0x05
+#define SMB2_CLOSE 0x06
+#define SMB2_FLUSH 0x07
+#define SMB2_READ 0x08
+#define SMB2_WRITE 0x09
+#define SMB2_LOCK 0x0a
+#define SMB2_IOCTL 0x0b
+#define SMB2_CANCEL 0x0c
+#define SMB2_KEEPALIVE 0x0d
+#define SMB2_FIND 0x0e
+#define SMB2_NOTIFY 0x0f
+#define SMB2_GETINFO 0x10
+#define SMB2_SETINFO 0x11
+#define SMB2_BREAK 0x12
+
+struct smb_header_s {
+ uint32_t version;
+ uint16_t headerLength;
+ uint16_t padding1;
+ uint32_t ntStatus;
+ uint16_t opCode;
+ uint16_t padding2;
+ uint32_t flags;
+ uint32_t chainOffset;
+ uint32_t comSeqNumber[2];
+ uint32_t processID;
+ uint32_t treeID;
+ uint32_t userID[2];
+ uint32_t signature[4];
+};
+
+typedef struct smb_header_s smb_header_t;
+
+static char flagCodes[5] = "RPCS";
+
+/*
+ * This function parses the bytes in the received packet to extract SMB2 metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the beginning of the header will be checked by the function
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where SMB2 metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("smb_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ int pktSizeCpy = pktSize;
+ const uchar *packetCpy = packet;
+
+ while (pktSizeCpy > 0) {
+ /* don't check packetCpy[0] to include SMB version byte at the beginning */
+ if (packetCpy[1] == 'S') {
+ if (packetCpy[2] == 'M') {
+ if (packetCpy[3] == 'B') {
+ break;
+ }
+ }
+ }
+ packetCpy++, pktSizeCpy--;
+ }
+
+ if ((int)pktSizeCpy < 64) {
+ DBGPRINTF("SMB packet too small : %d\n", pktSizeCpy);
+ RETURN_DATA_AFTER(0)
+ }
+
+ /* Union to prevent cast from uchar to smb_header_t */
+ union {
+ const uchar *pck;
+ smb_header_t *hdr;
+ } smb_header_to_char;
+
+ smb_header_to_char.pck = packetCpy;
+ smb_header_t *smb_header = smb_header_to_char.hdr;
+
+ char flags[5] = {0};
+ uint64_t seqNum, userID;
+ uint8_t version;
+
+ version = (smb_header->version == 0xFF) ? 1 : 2;
+ seqNum = smb_header->comSeqNumber[0] | smb_header->comSeqNumber[1] << 16;
+ userID = smb_header->userID[0] | smb_header->userID[1] << 16;
+
+ uint8_t i, pos = 0;
+ for (i = 0; i < 4; ++i) {
+ if (smb_header->flags & (0x01 << i))
+ flags[pos++] = flagCodes[i];
+ }
+
+ json_object_object_add(jparent, "SMB_version", json_object_new_int(version));
+ json_object_object_add(jparent, "SMB_NTstatus", json_object_new_int64(smb_header->ntStatus));
+ json_object_object_add(jparent, "SMB_operation", json_object_new_int(smb_header->opCode));
+ json_object_object_add(jparent, "SMB_flags", json_object_new_string(flags));
+ json_object_object_add(jparent, "SMB_seqNumber", json_object_new_int64(seqNum));
+ json_object_object_add(jparent, "SMB_processID", json_object_new_int64(smb_header->processID));
+ json_object_object_add(jparent, "SMB_treeID", json_object_new_int64(smb_header->treeID));
+ json_object_object_add(jparent, "SMB_userID", json_object_new_int64(userID));
+
+ RETURN_DATA_AFTER(0)
+}
diff --git a/contrib/impcap/tcp_parser.c b/contrib/impcap/tcp_parser.c
new file mode 100644
index 0000000..b96c1f3
--- /dev/null
+++ b/contrib/impcap/tcp_parser.c
@@ -0,0 +1,121 @@
+/* tcp_parser.c
+ *
+ * This file contains functions to parse TCP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+#define SMB_PORT 445
+#define HTTP_PORT 80
+#define HTTP_PORT_ALT 8080
+#define FTP_PORT 21
+#define FTP_PORT_DATA 20
+
+struct tcp_header_s {
+ uint16_t srcPort;
+ uint16_t dstPort;
+ uint32_t seq;
+ uint32_t ack;
+ uint8_t dor;
+ uint8_t flags;
+ uint16_t windowSize;
+ uint16_t checksum;
+ uint16_t urgPointer;
+ uint8_t options[];
+};
+
+typedef struct tcp_header_s tcp_header_t;
+
+static char flagCodes[10] = "FSRPAUECN";
+
+/*
+ * This function parses the bytes in the received packet to extract TCP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the TCP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where TCP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *tcp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("tcp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 20) {
+ DBGPRINTF("TCP packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ /* Union to prevent cast from uchar to tcp_header_t */
+ union {
+ const uchar *pck;
+ tcp_header_t *hdr;
+ } tcp_header_to_char;
+
+ tcp_header_to_char.pck = packet;
+ tcp_header_t *tcp_header = tcp_header_to_char.hdr;
+
+ uint8_t i, pos = 0;
+ char flags[10] = {0};
+
+ for (i = 0; i < 8; ++i) {
+ if (tcp_header->flags & (0x01 << i))
+ flags[pos++] = flagCodes[i];
+ }
+ if (tcp_header->dor & 0x01)
+ flags[pos++] = flagCodes[9];
+
+ uint16_t srcPort = ntohs(tcp_header->srcPort);
+ uint16_t dstPort = ntohs(tcp_header->dstPort);
+
+ uint8_t headerLength = (tcp_header->dor & 0xF0) >> 2; //>>4 to offset but <<2 to get offset as bytes
+
+ json_object_object_add(jparent, "net_src_port", json_object_new_int(srcPort));
+ json_object_object_add(jparent, "net_dst_port", json_object_new_int(dstPort));
+ json_object_object_add(jparent, "TCP_seq_number", json_object_new_int64(ntohl(tcp_header->seq)));
+ json_object_object_add(jparent, "TCP_ack_number", json_object_new_int64(ntohl(tcp_header->ack)));
+ json_object_object_add(jparent, "net_flags", json_object_new_string(flags));
+
+ if (srcPort == SMB_PORT || dstPort == SMB_PORT) {
+ return smb_parse(packet + headerLength, pktSize - headerLength, jparent);
+ }
+ if (srcPort == FTP_PORT || dstPort == FTP_PORT || srcPort == FTP_PORT_DATA || dstPort == FTP_PORT_DATA) {
+ return ftp_parse(packet + headerLength, pktSize - headerLength, jparent);
+ }
+ if (srcPort == HTTP_PORT || dstPort == HTTP_PORT ||
+ srcPort == HTTP_PORT_ALT || dstPort == HTTP_PORT_ALT) {
+ return http_parse(packet + headerLength, pktSize - headerLength, jparent);
+ }
+ DBGPRINTF("tcp return after header length (%u)\n", headerLength);
+ RETURN_DATA_AFTER(headerLength)
+}
diff --git a/contrib/impcap/udp_parser.c b/contrib/impcap/udp_parser.c
new file mode 100644
index 0000000..a9b7dca
--- /dev/null
+++ b/contrib/impcap/udp_parser.c
@@ -0,0 +1,90 @@
+/* udp_parser.c
+ *
+ * This file contains functions to parse UDP headers.
+ *
+ * File begun on 2018-11-13
+ *
+ * Created by:
+ * - Théo Bertin (theo.bertin@advens.fr)
+ *
+ * With:
+ * - François Bernard (francois.bernard@isen.yncrea.fr)
+ * - Tianyu Geng (tianyu.geng@isen.yncrea.fr)
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "parsers.h"
+
+#define DNS_PORT 53
+
+struct udp_header_s {
+ uint16_t srcPort;
+ uint16_t dstPort;
+ uint16_t totalLength;
+ uint16_t checksum;
+};
+
+typedef struct udp_header_s udp_header_t;
+
+/*
+ * This function parses the bytes in the received packet to extract UDP metadata.
+ *
+ * its parameters are:
+ * - a pointer on the list of bytes representing the packet
+ * the first byte must be the beginning of the UDP header
+ * - the size of the list passed as first parameter
+ * - a pointer on a json_object, containing all the metadata recovered so far
+ * this is also where UDP metadata will be added
+ *
+ * This function returns a structure containing the data unprocessed by this parser
+ * or the ones after (as a list of bytes), and the length of this data.
+*/
+data_ret_t *udp_parse(const uchar *packet, int pktSize, struct json_object *jparent) {
+ DBGPRINTF("udp_parse\n");
+ DBGPRINTF("packet size %d\n", pktSize);
+
+ if (pktSize < 8) {
+ DBGPRINTF("UDP packet too small : %d\n", pktSize);
+ RETURN_DATA_AFTER(0)
+ }
+
+ /* Union to prevent cast from uchar to udp_header_t */
+ union {
+ const uchar *pck;
+ udp_header_t *hdr;
+ } udp_header_to_char;
+
+ udp_header_to_char.pck = packet;
+ udp_header_t *udp_header = udp_header_to_char.hdr;
+
+ // Prevent endianness issue
+ unsigned short int src_port = ntohs(udp_header->srcPort);
+ unsigned short int dst_port = ntohs(udp_header->dstPort);
+
+ json_object_object_add(jparent, "net_src_port", json_object_new_int(src_port));
+ json_object_object_add(jparent, "net_dst_port", json_object_new_int(dst_port));
+ json_object_object_add(jparent, "UDP_Length", json_object_new_int(ntohs(udp_header->totalLength)));
+ json_object_object_add(jparent, "UDP_Checksum", json_object_new_int(ntohs(udp_header->checksum)));
+
+ if (src_port == DNS_PORT || dst_port == DNS_PORT) {
+ return dns_parse(packet + sizeof(udp_header_t), pktSize - sizeof(udp_header_t), jparent);
+ }
+
+ RETURN_DATA_AFTER(8)
+}
diff --git a/contrib/improg/Makefile.am b/contrib/improg/Makefile.am
new file mode 100644
index 0000000..3309098
--- /dev/null
+++ b/contrib/improg/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = improg.la
+
+improg_la_SOURCES = improg.c
+improg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+improg_la_LDFLAGS = -module -avoid-version
+improg_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+improg_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+improg_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/contrib/improg/Makefile.in b/contrib/improg/Makefile.in
new file mode 100644
index 0000000..bf69352
--- /dev/null
+++ b/contrib/improg/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = contrib/improg
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+improg_la_DEPENDENCIES =
+am_improg_la_OBJECTS = improg_la-improg.lo
+improg_la_OBJECTS = $(am_improg_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 =
+improg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(improg_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/improg_la-improg.Plo
+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 = $(improg_la_SOURCES)
+DIST_SOURCES = $(improg_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = improg.la
+improg_la_SOURCES = improg.c
+improg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_1)
+improg_la_LDFLAGS = -module -avoid-version $(am__append_2)
+improg_la_LIBADD =
+all: 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) --gnu contrib/improg/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/improg/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+improg.la: $(improg_la_OBJECTS) $(improg_la_DEPENDENCIES) $(EXTRA_improg_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(improg_la_LINK) -rpath $(pkglibdir) $(improg_la_OBJECTS) $(improg_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/improg_la-improg.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+improg_la-improg.lo: improg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(improg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT improg_la-improg.lo -MD -MP -MF $(DEPDIR)/improg_la-improg.Tpo -c -o improg_la-improg.lo `test -f 'improg.c' || echo '$(srcdir)/'`improg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/improg_la-improg.Tpo $(DEPDIR)/improg_la-improg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='improg.c' object='improg_la-improg.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) $(improg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o improg_la-improg.lo `test -f 'improg.c' || echo '$(srcdir)/'`improg.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/improg_la-improg.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/improg_la-improg.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/improg/improg.c b/contrib/improg/improg.c
new file mode 100644
index 0000000..d525ddd
--- /dev/null
+++ b/contrib/improg/improg.c
@@ -0,0 +1,722 @@
+/* improg.c
+ * This input plugin enables rsyslog to execute a program and
+ * receive from it the message stream as standard input.
+ * One message per line with a maximum size
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * File begun on 2009-04-01 by RGerhards
+ * File copied and adjust from improg.c on 2019-02-07 by Ph. Duveau
+ *
+ * Copyright 2009-2018 Adiscon GmbH.
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <poll.h>
+
+/* Very strange error on solaris 11 LOG_CRON already defined here.
+ * It is redefined in rsyslog.h
+ * The error also appeared with module omprog but the warning is
+ * accepted without generated an error
+ */
+#ifdef LOG_CRON
+#undef LOG_CRON
+#endif
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "glbl.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "ratelimit.h"
+#include "stringbuf.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("improg")
+
+struct instanceConf_s {
+ uchar *pszBinary; /* name of external program to call */
+ char **aParams; /* optional parameters to pass to external program */
+ int iParams; /* holds the count of parameters if set */
+ uchar *pszTag;
+ size_t lenTag;
+ int iFacility;
+ int iSeverity;
+ int bConfirmMessages; /* does the program provide feedback via stdout? */
+ int bSignalOnClose; /* should send SIGTERM to program before closing pipe? */
+ long lCloseTimeout; /* how long to wait for program to terminate after closing pipe (ms) */
+ int bKillUnresponsive; /* should send SIGKILL if closeTimeout is reached? */
+ cstr_t *ppCStr;
+ int bIsRunning; /* is program currently running? 0-no, 1-yes */
+ pid_t pid; /* pid of currently running child process */
+ int fdPipeToChild; /* fd for sending data to the program */
+ int fdPipeFromChild; /* fd for receiving messages from the program, or -1 */
+ uchar *pszBindRuleset;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ ratelimit_t *ratelimiter;
+ struct instanceConf_s *next;
+ struct instanceConf_s *prev;
+};
+
+/* config variables */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+
+};
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+static prop_t *pInputName = NULL;
+
+#define NO_HUP_FORWARD -1 /* indicates that HUP should NOT be forwarded */
+#define DEFAULT_CONFIRM_TIMEOUT_MS 10000
+#define DEFAULT_CLOSE_TIMEOUT_MS 5000
+#define RESPONSE_LINE_BUFFER_SIZE 4096
+#define OUTPUT_CAPTURE_BUFFER_SIZE 4096
+#define MAX_FD_TO_CLOSE 65535
+
+static instanceConf_t *confRoot = NULL;
+static fd_set rfds;
+static int nfds = 0;
+
+extern char **environ; /* POSIX environment ptr, by std not in a header... (see man 7 environ) */
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *pInst)
+{
+ LogError(0, NO_ERRCODE, "improg: ruleset '%s' for binary %s not found - "
+ "using default ruleset instead", pInst->pszBindRuleset,
+ pInst->pszBinary);
+}
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "binary", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "tag", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "severity", eCmdHdlrSeverity, 0 },
+ { "facility", eCmdHdlrFacility, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "confirmmessages", eCmdHdlrBinary, 0 },
+ { "signalonclose", eCmdHdlrBinary, 0 },
+ { "closetimeout", eCmdHdlrInt, 0 },
+ { "killunresponsive", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+/* execute the external program (must be called in child context after fork).
+ */
+static __attribute__((noreturn)) void execBinary(const instanceConf_t *pInst, int pipeToParent, int pipeFromParent)
+{
+ int maxFd, fd, sigNum;
+ struct sigaction sigAct;
+ sigset_t sigSet;
+ char errStr[1024];
+
+ if(dup2(pipeToParent, STDOUT_FILENO) == -1) {
+ goto failed;
+ }
+
+ if(pipeFromParent != -1) {
+ if(dup2(pipeFromParent, STDIN_FILENO) == -1) {
+ goto failed;
+ }
+ }
+
+ /* close the file handles the child process doesn't need (all above STDERR).
+ * The following way is simple and portable, though not perfect.
+ * See https://stackoverflow.com/a/918469 for alternatives.
+ */
+ maxFd = sysconf(_SC_OPEN_MAX);
+ if(maxFd < 0 || maxFd > MAX_FD_TO_CLOSE) {
+ maxFd = MAX_FD_TO_CLOSE;
+ }
+ # ifdef VALGRIND
+ else {
+ maxFd -= 10;
+ }
+ # endif
+ for(fd = STDERR_FILENO + 1 ; fd <= maxFd ; ++fd) {
+ close(fd);
+ }
+
+ /* reset signal handlers to default */
+ memset(&sigAct, 0, sizeof(sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = SIG_DFL;
+ for(sigNum = 1 ; sigNum < NSIG ; ++sigNum) {
+ sigaction(sigNum, &sigAct, NULL);
+ }
+
+ /* we need to block SIGINT, otherwise our program is cancelled when we are
+ * stopped in debug mode.
+ */
+ sigAct.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &sigAct, NULL);
+ sigemptyset(&sigSet);
+ sigprocmask(SIG_SETMASK, &sigSet, NULL);
+
+ alarm(0);
+
+ /* finally exec program */
+ execve((char*)pInst->pszBinary, pInst->aParams, environ);
+
+failed:
+ /* an error occurred: log it and exit the child process. We use the
+ * 'syslog' system call to log the error (we cannot use LogMsg/LogError,
+ * since these functions add directly to the rsyslog input queue).
+ */
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("improg: failed to execute program '%s': %s\n",
+ pInst->pszBinary, errStr);
+ openlog("rsyslogd", 0, LOG_SYSLOG);
+ syslog(LOG_ERR, "improg: failed to execute program '%s': %s\n",
+ pInst->pszBinary, errStr);
+ /* let's print the error to stderr for test bench purposes */
+ fprintf(stderr, "improg: failed to execute program '%s': %s\n",
+ pInst->pszBinary, errStr);
+ exit(1);
+}
+
+/* creates a pipe and starts program, uses pipe as stdin for program.
+ * rgerhards, 2009-04-01
+ */
+static rsRetVal openPipe(instanceConf_t *pInst)
+{
+ int pipeFromChild[2] = { -1, -1 };
+ int pipeToChild[2] = { -1, -1 };
+ pid_t cpid;
+ DEFiRet;
+
+ /* if the 'confirmMessages' setting is enabled, open a pipe to send
+ message confirmations to the program */
+ if(pInst->bConfirmMessages && pipe(pipeToChild) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ /* open a pipe to receive messages to the program */
+ if(pipe(pipeFromChild) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ DBGPRINTF("improg: executing program '%s' with '%d' parameters\n",
+ pInst->pszBinary, pInst->iParams);
+
+ cpid = fork();
+ if(cpid == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_FORK);
+ }
+
+ if(cpid == 0) { /* we are now the child process: execute the program */
+ /* close the pipe ends that the child doesn't need */
+ close(pipeFromChild[0]);
+ if(pipeToChild[1] != -1) {
+ close(pipeToChild[1]);
+ }
+
+ execBinary(pInst, pipeFromChild[1], pipeToChild[0]);
+ /* NO CODE HERE - WILL NEVER BE REACHED! */
+ }
+
+ DBGPRINTF("improg: child has pid %ld\n", (long int) cpid);
+
+ /* close the pipe ends that the parent doesn't need */
+ close(pipeFromChild[1]);
+ if(pipeToChild[0] != -1) {
+ close(pipeToChild[0]);
+ }
+
+ pInst->fdPipeToChild = pipeToChild[1]; /* we'll send messages confirmations to the program via this fd */
+ pInst->fdPipeFromChild = pipeFromChild[0]; /* we'll receive message via this fd */
+
+ FD_SET(pInst->fdPipeFromChild, &rfds); /* manage select read fd set */
+ nfds = (nfds > pInst->fdPipeFromChild) ? nfds : pInst->fdPipeFromChild+1;
+
+ pInst->pid = cpid;
+ pInst->bIsRunning = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pipeFromChild[0] != -1) {
+ close(pipeFromChild[0]);
+ close(pipeFromChild[1]);
+ }
+ if(pipeToChild[0] != -1) {
+ close(pipeToChild[0]);
+ close(pipeToChild[1]);
+ }
+ }
+ RETiRet;
+}
+
+static void waitForChild(instanceConf_t *pInst)
+{
+ int status;
+ int ret;
+ long counter;
+
+ counter = pInst->lCloseTimeout / 10;
+ while ((ret = waitpid(pInst->pid, &status, WNOHANG)) == 0 && counter > 0) {
+ srSleep(0, 10000); /* 0 seconds, 10 milliseconds */
+ --counter;
+ }
+
+ if (ret == 0) { /* timeout reached */
+ if (!pInst->bKillUnresponsive) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: program '%s' (pid %ld) did not terminate "
+ "within timeout (%ld ms); ignoring it", pInst->pszBinary, (long int)pInst->pid,
+ pInst->lCloseTimeout);
+ return;
+ }
+
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: program '%s' (pid %ld) did not terminate "
+ "within timeout (%ld ms); killing it", pInst->pszBinary, (long int)pInst->pid,
+ pInst->lCloseTimeout);
+ if (kill(pInst->pid, SIGKILL) == -1) {
+ LogError(errno, RS_RET_SYS_ERR, "improg: could not send SIGKILL to child process");
+ return;
+ }
+
+ ret = waitpid(pInst->pid, &status, 0);
+ }
+
+ /* waitpid will fail with errno == ECHILD if the child process has already
+ been reaped by the rsyslogd main loop (see rsyslogd.c) */
+ if(ret == pInst->pid) {
+ glblReportChildProcessExit(runConf, pInst->pszBinary, pInst->pid, status);
+ }
+}
+
+/* Send SIGTERM to child process if configured to do so, close pipe
+ * and wait for child to terminate.
+ */
+static void terminateChild(instanceConf_t *pInst)
+{
+ if(pInst->bIsRunning) {
+
+ if(pInst->fdPipeFromChild != -1) {
+ close(pInst->fdPipeFromChild);
+ FD_CLR(pInst->fdPipeFromChild, &rfds);
+ pInst->fdPipeFromChild = -1;
+
+ }
+
+ if(pInst->fdPipeToChild != -1) {
+ close(pInst->fdPipeToChild);
+ pInst->fdPipeToChild = -1;
+ }
+
+ /* wait for the child AFTER closing the pipe, so it receives EOF */
+ waitForChild(pInst);
+
+ pInst->bIsRunning = 0;
+ }
+}
+
+static rsRetVal startChild(instanceConf_t *pInst)
+{
+ DEFiRet;
+
+ if (!pInst->bIsRunning)
+
+ CHKiRet(openPipe(pInst));
+
+finalize_it:
+ if(iRet != RS_RET_OK && pInst->bIsRunning) {
+ /* if initialization has failed, terminate program */
+ terminateChild(pInst);
+ }
+ RETiRet;
+}
+
+static rsRetVal enqLine(instanceConf_t *const __restrict__ pInst)
+{
+ DEFiRet;
+ smsg_t *pMsg;
+
+ if(cstrLen(pInst->ppCStr) == 0) {
+ /* we do not process empty lines */
+ FINALIZE;
+ }
+
+ CHKiRet(msgConstruct(&pMsg));
+
+ MsgSetMSGoffs(pMsg, 0);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetAPPNAME(pMsg, (const char*)pInst->pszTag);
+ MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag);
+ msgSetPRI(pMsg, pInst->iFacility | pInst->iSeverity);
+ MsgSetRawMsg(pMsg, (const char*)rsCStrGetBufBeg(pInst->ppCStr), cstrLen(pInst->ppCStr));
+ MsgSetRuleset(pMsg, pInst->pBindRuleset);
+
+ ratelimitAddMsg(pInst->ratelimiter, NULL, pMsg);
+finalize_it:
+ RETiRet;
+}
+
+/* read line(s) from the external program and sent them when they are complete */
+static rsRetVal readChild(instanceConf_t *const pInst){
+ char c;
+ int retval;
+
+ while ((retval = read(pInst->fdPipeFromChild, &c, 1)) == 1) {
+ if (c=='\n'){
+ enqLine(pInst);
+ /* if confirm required then send an ACK to the program */
+ if (pInst->bConfirmMessages) {
+ if (write(pInst->fdPipeToChild,"ACK\n",sizeof("ACK\n")-1) <= 0)
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: pipe to child seems to be closed.");
+ }
+ rsCStrTruncate(pInst->ppCStr, rsCStrLen(pInst->ppCStr));
+ } else {
+ cstrAppendChar(pInst->ppCStr, c);
+ }
+ }
+ return (retval == 0) ? RS_RET_OK : RS_RET_IO_ERROR;
+}
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal ATTR_NONNULL(1) createInstance(instanceConf_t **const ppInst)
+{
+ instanceConf_t *pInst;
+ DEFiRet;
+ CHKmalloc(pInst = malloc(sizeof(instanceConf_t)));
+ pInst->next = NULL;
+ pInst->pszBindRuleset = NULL;
+ pInst->pBindRuleset = NULL;
+ pInst->ratelimiter = NULL;
+ pInst->iSeverity = 5;
+ pInst->iFacility = 128;
+
+ pInst->pszTag = NULL;
+ pInst->lenTag = 0;
+
+ pInst->bIsRunning = 0;
+ pInst->pid = -1;
+ pInst->fdPipeToChild = -1;
+ pInst->fdPipeFromChild = -1;
+
+ pInst->pszBinary = NULL;
+ pInst->aParams = NULL;
+ pInst->iParams = 0;
+
+ pInst->bConfirmMessages = 1;
+ pInst->bSignalOnClose = 0;
+ pInst->lCloseTimeout = 200;
+ pInst->bKillUnresponsive = 1;
+
+ *ppInst = pInst;
+finalize_it:
+ RETiRet;
+}
+
+/* This adds a new listener object to the bottom of the list, but
+ * it does NOT initialize any data members except for the list
+ * pointers themselves.
+ */
+static rsRetVal ATTR_NONNULL() lstnAdd(instanceConf_t *pInst)
+{
+ DEFiRet;
+ CHKiRet(ratelimitNew(&pInst->ratelimiter, "improg", (char*)pInst->pszBinary));
+
+ /* insert it at the begin of the list */
+ pInst->prev = NULL;
+ pInst->next = confRoot;
+
+ if (confRoot != NULL)
+ confRoot->prev = pInst;
+
+ confRoot = pInst;
+
+finalize_it:
+ RETiRet;
+}
+
+/* delete a listener object */
+static void ATTR_NONNULL(1) lstnFree(instanceConf_t *pInst)
+{
+ DBGPRINTF("lstnFree called for %s\n", pInst->pszBinary);
+ if (pInst->ratelimiter != NULL)
+ ratelimitDestruct(pInst->ratelimiter);
+ if(pInst->pszBinary != NULL)
+ free(pInst->pszBinary);
+ if (pInst->pszTag)
+ free(pInst->pszTag);
+ if (pInst->pszBindRuleset != NULL)
+ free(pInst->pszBindRuleset);
+ if (pInst->aParams) {
+ int i;
+ for (i = 0;pInst->aParams[i]; i++)
+ free(pInst->aParams[i]);
+ free(pInst->aParams);
+ }
+ if (pInst->ppCStr)
+ rsCStrDestruct(&pInst->ppCStr);
+ free(pInst);
+}
+
+/* read */
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *pInst = NULL;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (improg)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("input param blk in improg:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pInst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "binary")) {
+ CHKiRet(split_binary_parameters(&pInst->pszBinary, &pInst->aParams, &pInst->iParams,
+ pvals[i].val.d.estr));
+ } else if(!strcmp(inppblk.descr[i].name, "tag")) {
+ pInst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ pInst->lenTag = es_strlen(pvals[i].val.d.estr);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ pInst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "severity")) {
+ pInst->iSeverity = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "facility")) {
+ pInst->iFacility = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "confirmmessages")) {
+ pInst->bConfirmMessages = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "signalonclose")) {
+ pInst->bSignalOnClose = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "closetimeout")) {
+ pInst->lCloseTimeout = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "killunresponsive")) {
+ pInst->bKillUnresponsive = pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+ if(pInst->pszBinary == NULL) {
+ LogError(0, RS_RET_FILE_NOT_SPECIFIED,
+ "ulogbase is not configured - no input will be gathered");
+ ABORT_FINALIZE(RS_RET_FILE_NOT_SPECIFIED);
+ }
+
+ CHKiRet(cstrConstruct(&pInst->ppCStr));
+
+ if ((iRet = lstnAdd(pInst)) != RS_RET_OK) {
+ ABORT_FINALIZE(iRet);
+ }
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ if (pInst && iRet != RS_RET_OK)
+ lstnFree(pInst);
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("improg"), sizeof("improg") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+BEGINrunInput
+ struct timeval tv;
+ int retval;
+ instanceConf_t *pInst;
+CODESTARTrunInput
+ FD_ZERO(&rfds);
+
+ for(pInst = confRoot ; pInst != NULL ; pInst = pInst->next) {
+ startChild(pInst);
+ }
+
+ for(pInst = confRoot ; pInst != NULL ; pInst = pInst->next) {
+ if (pInst->bIsRunning && pInst->fdPipeToChild > 0){
+ if (write(pInst->fdPipeToChild, "START\n", sizeof("START\n")-1) <= 0)
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: pipe to child seems to be closed.");
+ DBGPRINTF("Sending START to %s\n", pInst->pszBinary);
+ }
+ }
+
+ /* main module loop */
+ tv.tv_usec = 1000;
+ while (glbl.GetGlobalInputTermState() == 0)
+ {
+ fd_set temp;
+ memcpy(&temp, &rfds, sizeof(fd_set));
+ tv.tv_sec = 0;
+
+ /* wait for external data or 0.1 second */
+ retval = select(nfds, &temp, NULL, NULL, &tv);
+
+ /* retval is the number of fd with data to read */
+ while (retval>0) {
+ for (pInst = confRoot; pInst != NULL; pInst = pInst->next) {
+ if (FD_ISSET(pInst->fdPipeFromChild, &temp)) {
+ DBGPRINTF("read child %s\n",pInst->pszBinary);
+ readChild(pInst);
+ retval--;
+ }
+ }
+ }
+ tv.tv_usec = 100000;
+ }
+ DBGPRINTF("terminating upon request of rsyslog core\n");
+ENDrunInput
+
+/* This function is called by the framework after runInput() has been terminated. It
+ * shall free any resources and prepare the module for unload.
+ * CODEqueryEtryPt_STD_IMOD_QUERIES
+ */
+BEGINafterRun
+CODESTARTafterRun
+ instanceConf_t *pInst = confRoot, *nextInst;
+ confRoot = NULL;
+
+ DBGPRINTF("afterRun\n");
+
+ while(pInst != NULL) {
+ nextInst = pInst->next;
+
+ if (pInst->bIsRunning) {
+ if (pInst->bSignalOnClose) {
+ kill(pInst->pid, SIGTERM);
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "%s SIGTERM signaled.", pInst->aParams[0]);
+ }
+ if (pInst->fdPipeToChild > 0){
+ if (write(pInst->fdPipeToChild, "STOP\n", strlen("STOP\n")) <= 0 &&
+ !pInst->bSignalOnClose)
+ LogMsg(0, NO_ERRCODE, LOG_WARNING,
+ "improg: pipe to child seems to be closed.");
+ }
+ terminateChild(pInst);
+ }
+
+ lstnFree(pInst);
+
+ pInst = nextInst;
+ }
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction) {
+ iRet = RS_RET_OK;
+ }
+ENDisCompatibleWithFeature
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+instanceConf_t *pInst;
+CODESTARTcheckCnf
+ for(pInst = confRoot ; pInst != NULL ; pInst = pInst->next) {
+ std_checkRuleset(pModConf , pInst);
+ }
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/imtuxedoulog/Makefile.am b/contrib/imtuxedoulog/Makefile.am
new file mode 100644
index 0000000..1423b85
--- /dev/null
+++ b/contrib/imtuxedoulog/Makefile.am
@@ -0,0 +1,13 @@
+pkglib_LTLIBRARIES = imtuxedoulog.la
+
+imtuxedoulog_la_SOURCES = imtuxedoulog.c
+
+imtuxedoulog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imtuxedoulog_la_LDFLAGS = -module -avoid-version
+imtuxedoulog_la_LIBADD =
+
+if OS_AIX
+imtuxedoulog_la_CPPFLAGS += -ma
+endif
+
+
diff --git a/contrib/imtuxedoulog/Makefile.in b/contrib/imtuxedoulog/Makefile.in
new file mode 100644
index 0000000..442dcb5
--- /dev/null
+++ b/contrib/imtuxedoulog/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@OS_AIX_TRUE@am__append_1 = -ma
+subdir = contrib/imtuxedoulog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imtuxedoulog_la_DEPENDENCIES =
+am_imtuxedoulog_la_OBJECTS = imtuxedoulog_la-imtuxedoulog.lo
+imtuxedoulog_la_OBJECTS = $(am_imtuxedoulog_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 =
+imtuxedoulog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(imtuxedoulog_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo
+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 = $(imtuxedoulog_la_SOURCES)
+DIST_SOURCES = $(imtuxedoulog_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imtuxedoulog.la
+imtuxedoulog_la_SOURCES = imtuxedoulog.c
+imtuxedoulog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) \
+ $(RSRT_CFLAGS) $(am__append_1)
+imtuxedoulog_la_LDFLAGS = -module -avoid-version
+imtuxedoulog_la_LIBADD =
+all: 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) --gnu contrib/imtuxedoulog/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imtuxedoulog/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imtuxedoulog.la: $(imtuxedoulog_la_OBJECTS) $(imtuxedoulog_la_DEPENDENCIES) $(EXTRA_imtuxedoulog_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imtuxedoulog_la_LINK) -rpath $(pkglibdir) $(imtuxedoulog_la_OBJECTS) $(imtuxedoulog_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imtuxedoulog_la-imtuxedoulog.lo: imtuxedoulog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imtuxedoulog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imtuxedoulog_la-imtuxedoulog.lo -MD -MP -MF $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Tpo -c -o imtuxedoulog_la-imtuxedoulog.lo `test -f 'imtuxedoulog.c' || echo '$(srcdir)/'`imtuxedoulog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Tpo $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imtuxedoulog.c' object='imtuxedoulog_la-imtuxedoulog.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) $(imtuxedoulog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imtuxedoulog_la-imtuxedoulog.lo `test -f 'imtuxedoulog.c' || echo '$(srcdir)/'`imtuxedoulog.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/imtuxedoulog/imtuxedoulog.c b/contrib/imtuxedoulog/imtuxedoulog.c
new file mode 100644
index 0000000..ffb863c
--- /dev/null
+++ b/contrib/imtuxedoulog/imtuxedoulog.c
@@ -0,0 +1,860 @@
+/* imtuxedoulog.c
+ *
+ * This is the input module for reading Tuxedo ULOG files. The particularity of this file
+ * is that the timestamp is split between the filename (date) and the log line (time).
+ * So this module switches on the date base betwwen files to open only the current file.
+ * The log line is parsed according to the Tuxedo format. The ECID is extracted as a
+ * structured data attribute.
+ *
+ * Work originally begun on 2019-01-11 by Philippe Duveau
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h> /* do NOT remove: will soon be done by the module generation macros */
+#include <sys/types.h>
+#include <unistd.h>
+#include <glob.h>
+#include <poll.h>
+#include <fnmatch.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef _AIX
+# include <alloca.h>
+#endif
+#include "rsyslog.h" /* error codes etc... */
+#include "dirty.h"
+#include "cfsysline.h" /* access to config file objects */
+#include "module-template.h" /* generic module interface code - very important, read it! */
+#include "srUtils.h" /* some utility functions */
+#include "msg.h"
+#include "stream.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "stringbuf.h"
+#include "ruleset.h"
+#include "ratelimit.h"
+
+struct instanceConf_s {
+ uchar *pszUlogBaseName;
+ uchar *pszCurrFName;
+ struct tm currTm;
+ uchar *pszTag;
+ size_t lenTag;
+ uchar *pszStateFile;
+ uchar *pszBindRuleset;
+ int nMultiSub;
+ int iPersistStateInterval;
+ int iFacility;
+ int iSeverity;
+ strm_t *pStrm; /* its stream (NULL if not assigned) */
+ int maxLinesAtOnce;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ ratelimit_t *ratelimiter;
+ multi_submit_t multiSub;
+ int nRecords;
+ struct instanceConf_s *next;
+ struct instanceConf_s *prev;
+};
+
+/* config variables */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+
+static instanceConf_t *confRoot = NULL;
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL; /* modConf ptr to use for run process */
+
+
+MODULE_TYPE_INPUT /* must be present for input modules, do not remove */
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imtuxedoulog")
+
+/* defines */
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA /* must be present, starts static data */
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+#define NUM_MULTISUB 1024 /* default max number of submits */
+#define DFLT_PollInterval 10
+
+int iPollInterval = DFLT_PollInterval;
+int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */
+
+struct syslogTime syslogTz;
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+
+/* module-global parameters */
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "ulogbase", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "tag", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "severity", eCmdHdlrSeverity, 0 },
+ { "facility", eCmdHdlrFacility, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "maxlinesatonce", eCmdHdlrInt, 0 },
+ { "persiststateinterval", eCmdHdlrInt, 0 },
+ { "maxsubmitatonce", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+static uchar * mkFileNameWithTime(instanceConf_t *in)
+{
+ uchar out[MAXFNAME];
+ struct timeval tp;
+#if defined(__hpux)
+ struct timezone tz;
+ gettimeofday(&tp, &tz);
+#else
+ gettimeofday(&tp, NULL);
+#endif
+ localtime_r(&tp.tv_sec, &(in->currTm));
+ snprintf((char*)out, MAXFNAME, "%s.%02d%02d%02d", (char*)in->pszUlogBaseName,
+ in->currTm.tm_mon+1, in->currTm.tm_mday, in->currTm.tm_year % 100);
+ return ustrdup(out);
+}
+
+/*
+* Helper function to combine statefile and workdir
+*/
+static int getFullStateFileName(uchar* pszstatefile, uchar* pszout, int ilenout)
+{
+ int lenout;
+ const uchar* pszworkdir;
+
+ /* Get Raw Workdir, if it is NULL we need to propper handle it */
+ pszworkdir = glblGetWorkDirRaw(runModConf->pConf);
+
+ /* Construct file name */
+ lenout = snprintf((char*)pszout, ilenout, "%s/%s",
+ (char*) (pszworkdir == NULL ? "." : (char*) pszworkdir), (char*)pszstatefile);
+
+ /* return out length */
+ return lenout;
+}
+
+/* this generates a state file name suitable for the current file. To avoid
+ * malloc calls, it must be passed a buffer which should be MAXFNAME large.
+ * Note: the buffer is not necessarily populated ... always ONLY use the
+ * RETURN VALUE!
+ */
+static uchar * ATTR_NONNULL(2) getStateFileName(instanceConf_t *const __restrict__ pInst,
+ uchar *const __restrict__ buf,
+ size_t lenbuf,
+ const uchar *pszFileName)
+{
+ uchar *ret;
+
+ /* Use pszFileName parameter if set */
+ pszFileName = pszFileName == NULL ? pInst->pszUlogBaseName : pszFileName;
+
+ DBGPRINTF("getStateFileName for '%s'\n", pszFileName);
+ if(pInst == NULL || pInst->pszStateFile == NULL) {
+ lenbuf = snprintf((char*)buf, lenbuf - 1, "imtuxedoulog-state:%s", pszFileName);
+ buf[lenbuf] = '\0'; /* be on the safe side... */
+ uchar *p = buf;
+ for( ; *p ; ++p) {
+ if(*p == '/')
+ *p = '-';
+ }
+ ret = buf;
+ } else {
+ ret = pInst->pszStateFile;
+ }
+ return ret;
+}
+
+/* this func parses the line according to samples described in README.md
+ */
+static rsRetVal parseMsg(smsg_t *pMsg, char *rawMsg, size_t msgLen,
+ instanceConf_t *const __restrict__ pInst) {
+ char *prog, *host, *text = NULL, *strtData = NULL, *tmp;
+ int hour, min, sec;
+ rsRetVal ret;
+
+ hour = (rawMsg[0] ^ 0x30) * 10 + (rawMsg[1] ^ 0x30);
+ min = (rawMsg[2] ^ 0x30) * 10 + (rawMsg[3] ^ 0x30);
+ sec = (rawMsg[4] ^ 0x30) * 10 + (rawMsg[5] ^ 0x30);
+
+ if (hour < 0 || hour > 23 || min < 0 || min > 59
+ || sec < 0 || sec > 59)
+ return RS_RET_COULD_NOT_PARSE;
+
+ host = rawMsg + ((rawMsg[10] == '.') ? 11 : 10);
+
+ prog = memchr(host, '!', msgLen-(host - rawMsg));
+
+ if (prog == NULL)
+ return RS_RET_COULD_NOT_PARSE;
+
+ prog++;
+
+ strtData = memchr(prog, ':', msgLen-(prog - rawMsg));
+
+ if (strtData == NULL)
+ return RS_RET_COULD_NOT_PARSE;
+
+ pMsg->tTIMESTAMP.year = pInst->currTm.tm_year + 1900;
+ pMsg->tTIMESTAMP.month = pInst->currTm.tm_mon + 1;
+ pMsg->tTIMESTAMP.day = pInst->currTm.tm_mday;
+ pMsg->tTIMESTAMP.hour = hour;
+ pMsg->tTIMESTAMP.minute = min;
+ pMsg->tTIMESTAMP.second = sec;
+ pMsg->tTIMESTAMP.OffsetMode = syslogTz.OffsetMode;
+ pMsg->tTIMESTAMP.OffsetHour = syslogTz.OffsetHour;
+ pMsg->tTIMESTAMP.OffsetMinute = syslogTz.OffsetMinute;
+
+ pMsg->tTIMESTAMP.secfrac = atoi(rawMsg+7);
+ /* secfracprecision depends on the char on position 9 (case 1 or case 2) */
+ pMsg->tTIMESTAMP.secfracPrecision = (rawMsg[9]=='.') ? 2 : 3;
+
+ for (tmp = strtData ; prog < tmp && *tmp!='.'; tmp--)
+ ;
+ if (tmp > prog)
+ *tmp = '\0';
+ else
+ *strtData = '\0';
+
+ strtData = strtData + 2;
+
+ /* Case 4 */
+ if (memcmp(strtData, "gtrid", 5) == 0)
+ {
+ strtData = memchr(strtData, ':', msgLen-(strtData - rawMsg));
+ if (strtData != NULL) strtData += 2;
+ }
+
+ text = strtData;
+
+ /* ecid point to message text or the word ECID */
+ if (strtData != NULL && memcmp(strtData, "ECID", 4) == 0)
+ {
+ text = memchr(strtData+6, '>', msgLen-(strtData-rawMsg));
+ /* case 3 : we have the word ECID */
+ if (text != NULL)
+ {
+ *(--strtData) = '[';
+ strtData[5] = '=';
+ strtData[6] = '\"';
+ *text++ = '\"';
+ *text++ = ']';
+ text++;
+ ret = MsgAddToStructuredData(pMsg, (uchar*)strtData, text - strtData);
+ if (ret!=RS_RET_OK)
+ LogMsg(0, ret, LOG_WARNING, "Add StructuredData to message failed.");
+ }
+ }
+
+ /* now compute the new length */
+ msgLen -= text - rawMsg;
+
+ if (text != NULL)
+ MsgSetRawMsg(pMsg, text, msgLen);
+
+ MsgSetMSGoffs(pMsg, 0);
+
+ /* set hostname */
+ MsgSetHOSTNAME(pMsg, (const uchar*)host, prog - host - 1);
+
+ if (*prog == '\0')
+ return 0;
+
+ /* set procid */
+ ret = MsgSetPROCID(pMsg, prog);
+ if (ret != RS_RET_OK)
+ LogMsg(0, ret, LOG_WARNING, "Set PROCID to message failed.");
+
+ return RS_RET_OK;
+}
+
+/* enqueue the read file line as a message. The provided string is
+ * not freed - this must be done by the caller.
+ */
+#define MAX_OFFSET_REPRESENTATION_NUM_BYTES 20
+static rsRetVal enqLine(instanceConf_t *const __restrict__ pInst,
+ cstr_t *const __restrict__ cstrLine)
+{
+ DEFiRet;
+ smsg_t *pMsg;
+ const size_t msgLen = cstrLen(cstrLine);
+ rsRetVal ret;
+
+ if(msgLen == 0) {
+ /* we do not process empty lines */
+ FINALIZE;
+ }
+
+ CHKiRet(msgConstruct(&pMsg));
+
+ if (parseMsg(pMsg, (char*)rsCStrGetSzStrNoNULL(cstrLine), msgLen, pInst) != RS_RET_OK) {
+ if ((ret = msgDestruct(&pMsg)) != RS_RET_OK)
+ LogMsg(0, ret, LOG_ERR, "msgDestruct failed.");
+ FINALIZE;
+ }
+
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag);
+ msgSetPRI(pMsg, pInst->iFacility | pInst->iSeverity);
+ MsgSetRuleset(pMsg, pInst->pBindRuleset);
+ if ((ret = MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY)) != RS_RET_OK)
+ LogMsg(0, ret, LOG_WARNING, "Set Flow Control to message failed.");
+ if ((ret = MsgSetAPPNAME(pMsg, (const char*)pInst->pszTag)) != RS_RET_OK)
+ LogMsg(0, ret, LOG_WARNING, "Set APPNAME to message failed.");
+
+ if ((iRet = ratelimitAddMsg(pInst->ratelimiter, &pInst->multiSub, pMsg)) != RS_RET_OK) {
+ if ((ret = msgDestruct(&pMsg)) != RS_RET_OK)
+ LogMsg(0, ret, LOG_ERR, "msgDestruct failed.");
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* try to open a file which has a state file. If the state file does not
+ * exist or cannot be read, an error is returned.
+ */
+static rsRetVal ATTR_NONNULL(1) openFileWithStateFile(instanceConf_t *const __restrict__ pInst)
+{
+ DEFiRet;
+ strm_t *psSF = NULL;
+ uchar pszSFNam[MAXFNAME];
+ size_t lenSFNam;
+ struct stat stat_buf;
+ uchar statefile[MAXFNAME];
+
+ uchar *const statefn = getStateFileName(pInst, statefile, sizeof(statefile), NULL);
+ DBGPRINTF("trying to open state for '%s', state file '%s'\n",
+ pInst->pszUlogBaseName, statefn);
+
+ /* Get full path and file name */
+ lenSFNam = getFullStateFileName(statefn, pszSFNam, sizeof(pszSFNam));
+
+ /* check if the file exists */
+ if(stat((char*) pszSFNam, &stat_buf) == -1) {
+ if(errno == ENOENT) {
+ DBGPRINTF("NO state file (%s) exists for '%s'\n", pszSFNam, pInst->pszUlogBaseName);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ } else {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("error trying to access state file for '%s':%s\n",
+ pInst->pszUlogBaseName, errStr);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ }
+
+ /* If we reach this point, we have a state file */
+
+ CHKiRet(strm.Construct(&psSF));
+ CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(psSF, pszSFNam, lenSFNam));
+ CHKiRet(strm.SetFileNotFoundError(psSF, 1));
+ CHKiRet(strm.ConstructFinalize(psSF));
+
+ /* read back in the object */
+ CHKiRet(obj.Deserialize(&pInst->pStrm, (uchar*) "strm", psSF, NULL, pInst));
+ DBGPRINTF("deserialized state file, state file base name '%s', "
+ "configured base name '%s'\n", pInst->pStrm->pszFName,
+ pInst->pszUlogBaseName);
+ if(ustrcmp(pInst->pStrm->pszFName, pInst->pszCurrFName)) {
+ LogError(0, RS_RET_STATEFILE_WRONG_FNAME, "imtuxedoulog: state file '%s' "
+ "contains file name '%s', but is used for file '%s'. State "
+ "file deleted, starting from begin of file.",
+ pszSFNam, pInst->pStrm->pszFName, pInst->pszCurrFName);
+
+ unlink((char*)pszSFNam);
+ ABORT_FINALIZE(RS_RET_STATEFILE_WRONG_FNAME);
+ }
+
+ strm.CheckFileChange(pInst->pStrm);
+ CHKiRet(strm.SeekCurrOffs(pInst->pStrm));
+
+ /* note: we do not delete the state file, so that the last position remains
+ * known even in the case that rsyslogd aborts for some reason (like powerfail)
+ */
+
+finalize_it:
+ if(psSF != NULL)
+ strm.Destruct(&psSF);
+
+ RETiRet;
+}
+
+/* try to open a file for which no state file exists. This function does NOT
+ * check if a state file actually exists or not -- this must have been
+ * checked before calling it.
+ */
+static rsRetVal openFileWithoutStateFile(instanceConf_t *const __restrict__ pInst)
+{
+ DEFiRet;
+
+ DBGPRINTF("clean startup withOUT state file for '%s'\n", pInst->pszUlogBaseName);
+ if(pInst->pStrm != NULL)
+ strm.Destruct(&pInst->pStrm);
+ CHKiRet(strm.Construct(&pInst->pStrm));
+ CHKiRet(strm.SettOperationsMode(pInst->pStrm, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(pInst->pStrm, STREAMTYPE_FILE_MONITOR));
+ CHKiRet(strm.SetFName(pInst->pStrm, pInst->pszCurrFName, strlen((char*) pInst->pszCurrFName)));
+ CHKiRet(strm.SetFileNotFoundError(pInst->pStrm, 1));
+ CHKiRet(strm.ConstructFinalize(pInst->pStrm));
+
+finalize_it:
+ RETiRet;
+}
+
+/* try to open a file. This involves checking if there is a status file and,
+ * if so, reading it in. Processing continues from the last known location.
+ */
+static rsRetVal openFile(instanceConf_t *const __restrict__ pInst)
+{
+ DEFiRet;
+
+ CHKiRet_Hdlr(openFileWithStateFile(pInst)) {
+ CHKiRet(openFileWithoutStateFile(pInst));
+ }
+
+ CHKiRet(strm.SetbReopenOnTruncate(pInst->pStrm, 1));
+
+finalize_it:
+ RETiRet;
+}
+
+/* This function persists information for a specific file being monitored.
+ * To do so, it simply persists the stream object. We do NOT abort on error
+ * iRet as that makes matters worse (at least we can try persisting the others...).
+ * rgerhards, 2008-02-13
+ */
+static void persistStrmState(instanceConf_t *pInst)
+{
+ DEFiRet;
+ strm_t *psSF = NULL; /* state file (stream) */
+ size_t lenDir;
+ uchar statefile[MAXFNAME];
+
+ uchar *const statefn = getStateFileName(pInst, statefile, sizeof(statefile), NULL);
+ DBGPRINTF("persisting state for '%s' to file '%s'\n",
+ pInst->pszUlogBaseName, statefn);
+ CHKiRet(strm.Construct(&psSF));
+ lenDir = ustrlen(glbl.GetWorkDir(runModConf->pConf));
+ if(lenDir > 0)
+ CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(runModConf->pConf), lenDir));
+ CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC));
+ CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(psSF, statefn, strlen((char*) statefn)));
+ CHKiRet(strm.SetFileNotFoundError(psSF, 1));
+ CHKiRet(strm.ConstructFinalize(psSF));
+
+ CHKiRet(strm.Serialize(pInst->pStrm, psSF));
+ CHKiRet(strm.Flush(psSF));
+
+ CHKiRet(strm.Destruct(&psSF));
+
+finalize_it:
+ if(psSF != NULL)
+ strm.Destruct(&psSF);
+
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "imtuxedoulog: could not persist state "
+ "file %s - data may be repeated on next "
+ "startup. Is WorkDirectory set?",
+ statefn);
+ }
+}
+
+/* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case
+ * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27
+ */
+static void pollFileCancelCleanup(void *pArg)
+{
+ cstr_t **ppCStr = (cstr_t**) pArg;
+ if(*ppCStr != NULL) {
+ rsCStrDestruct(ppCStr);
+ }
+}
+
+static void pollFileReal(instanceConf_t *pInst, int *pbHadFileData, cstr_t **ppCStr)
+{
+ DEFiRet;
+
+ int nProcessed = 0;
+ if(pInst->pStrm == NULL) {
+ CHKiRet(openFile(pInst)); /* open file */
+ }
+
+ /* loop below will be exited when strmReadLine() returns EOF */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ if(pInst->maxLinesAtOnce != 0 && nProcessed >= pInst->maxLinesAtOnce)
+ break;
+ CHKiRet(strm.ReadLine(pInst->pStrm, ppCStr, 0, 0, NULL, -1, NULL));
+ ++nProcessed;
+ if(pbHadFileData != NULL)
+ *pbHadFileData = 1; /* this is just a flag, so set it and forget it */
+ CHKiRet(enqLine(pInst, *ppCStr)); /* process line */
+ rsCStrDestruct(ppCStr); /* discard string (must be done by us!) */
+
+ if(pInst->iPersistStateInterval > 0 && ++pInst->nRecords >= pInst->iPersistStateInterval) {
+ persistStrmState(pInst);
+ pInst->nRecords = 0;
+ }
+ }
+
+finalize_it:
+ multiSubmitFlush(&pInst->multiSub);
+
+ if(*ppCStr != NULL) {
+ rsCStrDestruct(ppCStr);
+ }
+}
+
+/* poll a file, need to check file rollover etc. open file if not open */
+static void pollFile(instanceConf_t *pInst, int *pbHadFileData)
+{
+ cstr_t *pCStr = NULL;
+ /* Note: we must do pthread_cleanup_push() immediately, because the POSIX macros
+ * otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14
+ */
+ pthread_cleanup_push(pollFileCancelCleanup, &pCStr);
+ pollFileReal(pInst, pbHadFileData, &pCStr);
+ pthread_cleanup_pop(0);
+}
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal ATTR_NONNULL(1) createInstance(instanceConf_t **const pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pBindRuleset = NULL;
+ inst->ratelimiter = NULL;
+ inst->pStrm = NULL;
+ inst->multiSub.ppMsgs = NULL;
+
+ inst->pszBindRuleset = NULL;
+ inst->pszUlogBaseName = NULL;
+ inst->pszCurrFName = NULL;
+ inst->pszTag = NULL;
+ inst->pszStateFile = NULL;
+ inst->nMultiSub = NUM_MULTISUB;
+ inst->iSeverity = 5;
+ inst->iFacility = 128;
+ inst->maxLinesAtOnce = 0;
+ inst->iPersistStateInterval = 0;
+ inst->nRecords = 0;
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* This adds a new listener object to the bottom of the list, but
+ * it does NOT initialize any data members except for the list
+ * pointers themselves.
+ */
+static rsRetVal ATTR_NONNULL() lstnAdd(instanceConf_t *pInst)
+{
+ DEFiRet;
+ CHKiRet(ratelimitNew(&pInst->ratelimiter, "imtuxedoulog", (char*)pInst->pszUlogBaseName));
+ CHKmalloc(pInst->multiSub.ppMsgs = malloc(pInst->nMultiSub * sizeof(smsg_t *)));
+ pInst->multiSub.maxElem = pInst->nMultiSub;
+ pInst->multiSub.nElem = 0;
+
+ /* insert it at the begin of the list */
+ pInst->prev = NULL;
+ pInst->next = confRoot;
+
+ if (confRoot != NULL)
+ confRoot->prev = pInst;
+
+ confRoot = pInst;
+
+finalize_it:
+ RETiRet;
+}
+
+/* delete a listener object */
+static void ATTR_NONNULL(1) lstnDel(instanceConf_t *pInst)
+{
+ DBGPRINTF("lstnDel called for %s\n", pInst->pszUlogBaseName);
+ if(pInst->pStrm != NULL) { /* stream open? */
+ persistStrmState(pInst);
+ strm.Destruct(&(pInst->pStrm));
+ }
+ if (pInst->ratelimiter != NULL)
+ ratelimitDestruct(pInst->ratelimiter);
+ if (pInst->multiSub.ppMsgs != NULL)
+ free(pInst->multiSub.ppMsgs);
+
+ free(pInst->pszUlogBaseName);
+ if (pInst->pszCurrFName != NULL)
+ free(pInst->pszCurrFName);
+ if (pInst->pszTag)
+ free(pInst->pszTag);
+ if (pInst->pszStateFile)
+ free(pInst->pszStateFile);
+ if (pInst->pszBindRuleset != NULL)
+ free(pInst->pszBindRuleset);
+ free(pInst);
+}
+
+/* Monitor files in traditional polling mode.
+ */
+static void do_polling(void)
+{
+ int bHadFileData; /* were there at least one file with data during this run? */
+ struct stat sb;
+ while(glbl.GetGlobalInputTermState() == 0) {
+ do {
+ instanceConf_t *pInst;
+ bHadFileData = 0;
+ for(pInst = confRoot ; pInst != NULL ; pInst = pInst->next) {
+ uchar *temp = mkFileNameWithTime(pInst);
+
+ DBGPRINTF("imtuxedoulog: do_polling start '%s' / '%s'\n", pInst->pszUlogBaseName, temp);
+ /*
+ * Is the file name is different : a rotation time is reached
+ * If so, then it the new file exists ? and is a file ?
+ */
+ if (temp && stat((const char*)temp, &sb) == 0 && S_ISREG(sb.st_mode) &&
+ (pInst->pszCurrFName == NULL ||
+ strcmp((char*)temp,(char*)pInst->pszCurrFName) != 0))
+ {
+ DBGPRINTF("imtuxedoulog: timed file : rotation reach "
+ "switching form '%s' to '%s' !",
+ (char*)pInst->pszUlogBaseName, temp );
+
+ /* first of all change the listener datas */
+ if (pInst->pszCurrFName != NULL) {
+ free(pInst->pszCurrFName);
+ strm.Destruct(&pInst->pStrm);
+ }
+ pInst->pszCurrFName = temp;
+ temp = NULL;
+
+ /* And finish by destroy the stream object, so the next polling will recreate
+ * it based on new data.
+ */
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+ }
+ if (temp) free(temp);
+
+ /* let's poll the file */
+ if (pInst->pszCurrFName != NULL)
+ pollFile(pInst, &bHadFileData);
+
+ DBGPRINTF("imtuxedoulog: do_polling end for '%s'\n", pInst->pszUlogBaseName);
+ if (pInst->iPersistStateInterval == -1)
+ persistStrmState(pInst);
+ }
+ } while(bHadFileData == 1 && glbl.GetGlobalInputTermState() == 0);
+
+ /* Note: the additional 10ns wait is vitally important. It guards rsyslog
+ * against totally hogging the CPU if the users selects a polling interval
+ * of 0 seconds. It doesn't hurt any other valid scenario. So do not remove.
+ * rgerhards, 2008-02-14
+ */
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(iPollInterval, 10);
+ }
+}
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imtuxedoulog)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("input param blk in imtuxedoulog:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "ulogbase")) {
+ inst->pszUlogBaseName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tag")) {
+ inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ inst->lenTag = es_strlen(pvals[i].val.d.estr);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "severity")) {
+ inst->iSeverity = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "facility")) {
+ inst->iFacility = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) {
+ inst->maxLinesAtOnce = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "persiststateinterval")) {
+ inst->iPersistStateInterval = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) {
+ inst->nMultiSub = pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+ if(inst->pszUlogBaseName == NULL) {
+ lstnDel(inst);
+ LogError(0, RS_RET_FILE_NOT_SPECIFIED,
+ "ulogbase is not configured - no input will be gathered");
+ ABORT_FINALIZE(RS_RET_FILE_NOT_SPECIFIED);
+ }
+
+ if ((iRet = lstnAdd(inst)) != RS_RET_OK) {
+ LogError(0, iRet,
+ "add input %s to list failed", inst->pszUlogBaseName);
+ lstnDel(inst);
+ ABORT_FINALIZE(iRet);
+ }
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = confRoot ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf , inst);
+ }
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+BEGINrunInput
+CODESTARTrunInput
+ do_polling();
+ DBGPRINTF("terminating upon request of rsyslog core\n");
+ENDrunInput
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imtuxedoulog"), sizeof("imtuxedoulog") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+BEGINafterRun
+CODESTARTafterRun
+ while(confRoot != NULL) {
+ instanceConf_t *inst = confRoot;
+ confRoot = confRoot->next;
+ lstnDel(inst);
+ }
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release objects we used */
+ objRelease(strm, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imtuxedoulog: ruleset '%s' for ULOG base %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszUlogBaseName);
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/mmcount/Makefile.am b/contrib/mmcount/Makefile.am
new file mode 100644
index 0000000..9c8c99d
--- /dev/null
+++ b/contrib/mmcount/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmcount.la
+
+mmcount_la_SOURCES = mmcount.c
+mmcount_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmcount_la_LDFLAGS = -module -avoid-version
+mmcount_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/mmcount/Makefile.in b/contrib/mmcount/Makefile.in
new file mode 100644
index 0000000..b14f90b
--- /dev/null
+++ b/contrib/mmcount/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmcount
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmcount_la_DEPENDENCIES =
+am_mmcount_la_OBJECTS = mmcount_la-mmcount.lo
+mmcount_la_OBJECTS = $(am_mmcount_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 =
+mmcount_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmcount_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmcount_la-mmcount.Plo
+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 = $(mmcount_la_SOURCES)
+DIST_SOURCES = $(mmcount_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmcount.la
+mmcount_la_SOURCES = mmcount.c
+mmcount_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmcount_la_LDFLAGS = -module -avoid-version
+mmcount_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/mmcount/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmcount/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmcount.la: $(mmcount_la_OBJECTS) $(mmcount_la_DEPENDENCIES) $(EXTRA_mmcount_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmcount_la_LINK) -rpath $(pkglibdir) $(mmcount_la_OBJECTS) $(mmcount_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmcount_la-mmcount.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmcount_la-mmcount.lo: mmcount.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmcount_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmcount_la-mmcount.lo -MD -MP -MF $(DEPDIR)/mmcount_la-mmcount.Tpo -c -o mmcount_la-mmcount.lo `test -f 'mmcount.c' || echo '$(srcdir)/'`mmcount.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmcount_la-mmcount.Tpo $(DEPDIR)/mmcount_la-mmcount.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmcount.c' object='mmcount_la-mmcount.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) $(mmcount_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmcount_la-mmcount.lo `test -f 'mmcount.c' || echo '$(srcdir)/'`mmcount.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmcount_la-mmcount.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmcount_la-mmcount.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmcount/mmcount.c b/contrib/mmcount/mmcount.c
new file mode 100644
index 0000000..9c5ad55
--- /dev/null
+++ b/contrib/mmcount/mmcount.c
@@ -0,0 +1,351 @@
+/* mmcount.c
+ * count messages by priority or json property of given app-name.
+ *
+ * Copyright 2013 Red Hat Inc.
+ * Copyright 2014 Rainer Gerhards
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <json.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "hashtable.h"
+
+
+#define JSON_COUNT_NAME "!mmcount"
+#define SEVERITY_COUNT 8
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmcount")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ char *pszAppName;
+ int severity[SEVERITY_COUNT];
+ char *pszKey;
+ char *pszValue;
+ int valueCounter;
+ struct hashtable *ht;
+ pthread_mutex_t mut;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "appname", eCmdHdlrGetWord, 0 },
+ { "key", eCmdHdlrGetWord, 0 },
+ { "value", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pthread_mutex_init(&pData->mut, NULL);
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ int i;
+
+ pData->pszAppName = NULL;
+ for (i = 0; i < SEVERITY_COUNT; i++)
+ pData->severity[i] = 0;
+ pData->pszKey = NULL;
+ pData->pszValue = NULL;
+ pData->valueCounter = 0;
+ pData->ht = NULL;
+}
+
+static unsigned int
+hash_from_key_fn(void *k)
+{
+ return *(unsigned int *)k;
+}
+
+static int
+key_equals_fn(void *k1, void *k2)
+{
+ return (*(unsigned int *)k1 == *(unsigned int *)k2);
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmcount)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "appname")) {
+ pData->pszAppName = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "value")) {
+ pData->pszValue = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ dbgprintf("mmcount: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+
+ if(pData->pszAppName == NULL) {
+ dbgprintf("mmcount: action requires a appname");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(pData->pszKey != NULL && pData->pszValue == NULL) {
+ if(NULL == (pData->ht = create_hashtable(100, hash_from_key_fn, key_equals_fn, NULL))) {
+ DBGPRINTF("mmcount: error creating hash table!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+static int *
+getCounter(struct hashtable *ht, const char *str) {
+ unsigned int key;
+ int *pCounter;
+ unsigned int *pKey;
+
+ /* we dont store str as key, instead we store hash of the str
+ as key to reduce memory usage */
+ key = hash_from_string((char*)str);
+ pCounter = hashtable_search(ht, &key);
+ if(pCounter) {
+ return pCounter;
+ }
+
+ /* counter is not found for the str, so add new entry and
+ return the counter */
+ if(NULL == (pKey = (unsigned int*)malloc(sizeof(unsigned int)))) {
+ DBGPRINTF("mmcount: memory allocation for key failed\n");
+ return NULL;
+ }
+ *pKey = key;
+
+ if(NULL == (pCounter = (int*)malloc(sizeof(int)))) {
+ DBGPRINTF("mmcount: memory allocation for value failed\n");
+ free(pKey);
+ return NULL;
+ }
+ *pCounter = 0;
+
+ if(!hashtable_insert(ht, pKey, pCounter)) {
+ DBGPRINTF("mmcount: inserting element into hashtable failed\n");
+ free(pKey);
+ free(pCounter);
+ return NULL;
+ }
+ return pCounter;
+}
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ char *appname;
+ struct json_object *json = NULL;
+ struct json_object *keyjson = NULL;
+ const char *pszValue;
+ int *pCounter;
+ instanceData *const pData = pWrkrData->pData;
+CODESTARTdoAction
+ appname = getAPPNAME(pMsg, LOCK_MUTEX);
+
+ pthread_mutex_lock(&pData->mut);
+ if(0 != strcmp(appname, pData->pszAppName)) {
+ /* we are not working for this appname. nothing to do */
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ if(!pData->pszKey) {
+ /* no key given for count, so we count severity */
+ if(pMsg->iSeverity < SEVERITY_COUNT) {
+ pData->severity[pMsg->iSeverity]++;
+ json = json_object_new_int(pData->severity[pMsg->iSeverity]);
+ }
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* key is given, so get the property json */
+ msgPropDescr_t pProp;
+ msgPropDescrFill(&pProp, (uchar*)pData->pszKey, strlen(pData->pszKey));
+ rsRetVal localRet = msgGetJSONPropJSON(pMsg, &pProp, &keyjson);
+ msgPropDescrDestruct(&pProp);
+ if(localRet != RS_RET_OK) {
+ /* key not found in the message. nothing to do */
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* key found, so get the value */
+ pszValue = (char*)json_object_get_string(keyjson);
+ if(pszValue == NULL) { /* json null object returns NULL! */
+ pszValue = "";
+ }
+
+ if(pData->pszValue) {
+ /* value also given for count */
+ if(!strcmp(pszValue, pData->pszValue)) {
+ /* count for (value and key and appname) matched */
+ pData->valueCounter++;
+ json = json_object_new_int(pData->valueCounter);
+ }
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* value is not given, so we count for each value of given key */
+ pCounter = getCounter(pData->ht, pszValue);
+ if(pCounter) {
+ (*pCounter)++;
+ json = json_object_new_int(*pCounter);
+ }
+finalize_it:
+ pthread_mutex_unlock(&pData->mut);
+
+ if(json) {
+ msgAddJSON(pMsg, (uchar *)JSON_COUNT_NAME, json, 0, 0);
+ }
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmcount: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/contrib/mmdarwin/Makefile.am b/contrib/mmdarwin/Makefile.am
new file mode 100644
index 0000000..4b88691
--- /dev/null
+++ b/contrib/mmdarwin/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmdarwin.la
+
+mmdarwin_la_SOURCES = mmdarwin.c protocol.h
+mmdarwin_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmdarwin_la_LDFLAGS = -module -avoid-version
+mmdarwin_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/mmdarwin/Makefile.in b/contrib/mmdarwin/Makefile.in
new file mode 100644
index 0000000..60812d4
--- /dev/null
+++ b/contrib/mmdarwin/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmdarwin
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmdarwin_la_DEPENDENCIES =
+am_mmdarwin_la_OBJECTS = mmdarwin_la-mmdarwin.lo
+mmdarwin_la_OBJECTS = $(am_mmdarwin_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 =
+mmdarwin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmdarwin_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo
+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 = $(mmdarwin_la_SOURCES)
+DIST_SOURCES = $(mmdarwin_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmdarwin.la
+mmdarwin_la_SOURCES = mmdarwin.c protocol.h
+mmdarwin_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmdarwin_la_LDFLAGS = -module -avoid-version
+mmdarwin_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/mmdarwin/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmdarwin/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmdarwin.la: $(mmdarwin_la_OBJECTS) $(mmdarwin_la_DEPENDENCIES) $(EXTRA_mmdarwin_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmdarwin_la_LINK) -rpath $(pkglibdir) $(mmdarwin_la_OBJECTS) $(mmdarwin_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmdarwin_la-mmdarwin.lo: mmdarwin.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmdarwin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmdarwin_la-mmdarwin.lo -MD -MP -MF $(DEPDIR)/mmdarwin_la-mmdarwin.Tpo -c -o mmdarwin_la-mmdarwin.lo `test -f 'mmdarwin.c' || echo '$(srcdir)/'`mmdarwin.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmdarwin_la-mmdarwin.Tpo $(DEPDIR)/mmdarwin_la-mmdarwin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmdarwin.c' object='mmdarwin_la-mmdarwin.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) $(mmdarwin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmdarwin_la-mmdarwin.lo `test -f 'mmdarwin.c' || echo '$(srcdir)/'`mmdarwin.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmdarwin/mmdarwin.c b/contrib/mmdarwin/mmdarwin.c
new file mode 100644
index 0000000..e36dbde
--- /dev/null
+++ b/contrib/mmdarwin/mmdarwin.c
@@ -0,0 +1,953 @@
+/* Copyright 2019 Advens
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <uuid/uuid.h>
+#include <json.h>
+
+#include "protocol.h" /* custom file written for Darwin */
+
+#define JSON_DEFAULT_CONTAINER "!mmdarwin"
+#define JSON_DARWIN_ID "darwin_id"
+#define INVLD_SOCK -1
+#define INITIAL_BUFFER_SIZE 32
+#define BUFFER_DEFAULT_MAX_SIZE 65536
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmdarwin")
+
+DEFobjCurrIf(glbl)
+DEF_OMOD_STATIC_DATA
+
+typedef struct dyn_buffer_t
+{
+ char *buffer;
+ size_t bufferAllocSize;
+ size_t bufferMsgSize;
+ size_t bufferMaxSize;
+} dyn_buffer;
+
+/* config variables */
+typedef struct _instanceData
+{
+ char *pUUIDKey; /* the key to the UUID generated by an mmdarwin instance */
+ char *pCertitudeKey; /* the key name to save in the enriched log
+ line the certitude obtained from Darwin */
+ uchar *pSockName; /* the socket path of the filter which will be used by
+ Darwin */
+ unsigned long long int filterCode; /* the filter code associated to the filter which will be used
+ by Darwin */
+ enum darwin_filter_response_type response; /* the type of response for Darwin: no / back / darwin / both */
+ struct
+ {
+ int nmemb;
+ char **name;
+ char **varname;
+ } fieldList; /* our keys (fields) to be extracted from the JSON-parsed log line */
+ unsigned int socketMaxUse;
+ sbool sendPartial;
+} instanceData;
+
+typedef struct wrkrInstanceData
+{
+ instanceData *pData;
+ int sock; /* the socket of the filter which will be used by Darwin */
+ struct sockaddr_un addr; /* the sockaddr_un used to connect to the Darwin filter */
+ uint8_t pktSentSocket;
+ dyn_buffer darwinBody; /* the body object used (and reused) to hold data to send to Darwin */
+ dyn_buffer fieldBuffer;
+} wrkrInstanceData_t;
+
+struct modConfData_s
+{
+ /* our overall config object */
+ rsconf_t *pConf;
+ const char *container;
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ {"container", eCmdHdlrGetWord, 0},
+};
+static struct cnfparamblk modpblk =
+ {CNFPARAMBLK_VERSION,
+ sizeof(modpdescr) / sizeof(struct cnfparamdescr),
+ modpdescr};
+
+/* tables for interfacing with the v6 config system
+ * action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ {"key", eCmdHdlrGetWord, CNFPARAM_REQUIRED},
+ {"socketpath", eCmdHdlrGetWord, CNFPARAM_REQUIRED},
+ {"fields", eCmdHdlrArray, CNFPARAM_REQUIRED},
+ {"filtercode", eCmdHdlrGetWord, 0}, /* optional parameter */
+ {"response", eCmdHdlrGetWord, 0}, /* optional parameter */
+ {"send_partial", eCmdHdlrBinary, 0}, /* optional parameter */
+ {"socket_max_use", eCmdHdlrNonNegInt, 0}, /* optional parameter - will disappear in future updates */
+};
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr) / sizeof(struct cnfparamdescr),
+ actpdescr};
+
+/* custom functions */
+#define min(a, b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+static rsRetVal openSocket(wrkrInstanceData_t *pWrkrData);
+static rsRetVal closeSocket(wrkrInstanceData_t *pWrkrData);
+static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData);
+
+static rsRetVal sendMsg(wrkrInstanceData_t *pWrkrData, void *msg, size_t len);
+static rsRetVal receiveMsg(wrkrInstanceData_t *pWrkrData, void *response, size_t len);
+
+const char* get_uuid_object(smsg_t *const pMsg);
+int get_field(smsg_t *const pMsg, const char *pFieldName, char **ppRetString);
+int expand_buffer(dyn_buffer *pBody, size_t new_size);
+int add_field_to_body(dyn_buffer *pBody, const char *field, size_t size);
+int start_new_line(dyn_buffer *pBody);
+int end_body(dyn_buffer *pBody);
+
+/* open socket to remote system
+ */
+static rsRetVal openSocket(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ assert(pWrkrData->sock == INVLD_SOCK);
+
+ if ((pWrkrData->sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ char errStr[1024];
+ int eno = errno;
+ DBGPRINTF("mmdarwin::openSocket:: error %d creating AF_UNIX/SOCK_STREAM: %s.\n",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ pWrkrData->sock = INVLD_SOCK;
+ ABORT_FINALIZE(RS_RET_NO_SOCKET);
+ }
+
+ memset(&pWrkrData->addr, 0, sizeof(struct sockaddr_un));
+ pWrkrData->addr.sun_family = AF_UNIX;
+ strncpy(pWrkrData->addr.sun_path, (char *)pWrkrData->pData->pSockName, sizeof(pWrkrData->addr.sun_path) - 1);
+
+ DBGPRINTF("mmdarwin::openSocket:: connecting to Darwin...\n");
+
+ if (connect(pWrkrData->sock, (struct sockaddr *)&pWrkrData->addr, sizeof(struct sockaddr_un)) == -1)
+ {
+ LogError(errno, RS_RET_NO_SOCKET, "mmdarwin::openSocket:: error connecting to Darwin "
+ "via socket '%s'",
+ pWrkrData->pData->pSockName);
+
+ pWrkrData->sock = INVLD_SOCK;
+ ABORT_FINALIZE(RS_RET_NO_SOCKET);
+ }
+
+ DBGPRINTF("mmdarwin::openSocket:: connected !\n");
+finalize_it:
+ if (iRet != RS_RET_OK)
+ {
+ closeSocket(pWrkrData);
+ }
+ RETiRet;
+}
+
+/* close socket to remote system
+ */
+static rsRetVal closeSocket(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ if (pWrkrData->sock != INVLD_SOCK)
+ {
+ if (close(pWrkrData->sock) != 0)
+ {
+ char errStr[1024];
+ int eno = errno;
+ DBGPRINTF("mmdarwin::closeSocket:: error %d closing the socket: %s.\n",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ }
+ pWrkrData->sock = INVLD_SOCK;
+ }
+ RETiRet;
+}
+
+/* try to resume connection if it is not ready
+ */
+static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+
+ DBGPRINTF("mmdarwin::doTryResume:: trying to resume\n");
+ closeSocket(pWrkrData);
+ iRet = openSocket(pWrkrData);
+
+ if (iRet != RS_RET_OK)
+ {
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+/* send a message via TCP
+ * inspired by rgehards, 2007-12-20
+ */
+static rsRetVal sendMsg(wrkrInstanceData_t *pWrkrData, void *msg, size_t len)
+{
+ DEFiRet;
+
+ DBGPRINTF("mmdarwin::sendMsg:: sending message to Darwin...\n");
+
+ if (pWrkrData->sock == INVLD_SOCK)
+ {
+ CHKiRet(doTryResume(pWrkrData));
+ }
+
+ if (pWrkrData->sock != INVLD_SOCK)
+ {
+ if (send(pWrkrData->sock, msg, len, 0) == -1)
+ {
+ char errStr[1024];
+ DBGPRINTF("mmdarwin::sendData:: error while sending data: error[%d] -> %s\n",
+ errno, rs_strerror_r(errno, errStr, sizeof(errStr)));
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* receive a message via TCP
+ * inspired by rgehards, 2007-12-20
+ */
+static rsRetVal receiveMsg(wrkrInstanceData_t *pWrkrData, void *response, size_t len)
+{
+ DEFiRet;
+
+ DBGPRINTF("mmdarwin::receiveMsg:: receiving message from Darwin...\n");
+
+ if (pWrkrData->sock == INVLD_SOCK)
+ {
+ CHKiRet(doTryResume(pWrkrData));
+ }
+
+ if (pWrkrData->sock != INVLD_SOCK)
+ {
+ if (recv(pWrkrData->sock, response, len, MSG_WAITALL) <= 0)
+ {
+ char errStr[1024];
+ DBGPRINTF("mmdarwin::receiveMsg:: error while receiving data: error[%d] -> %s\n",
+ errno, rs_strerror_r(errno, errStr, sizeof(errStr)));
+ iRet = RS_RET_NONE;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/**
+ * Get the string corresponding to a field supposedly present in the provided message
+ *
+ * params:
+ * - pMsg: a pointer to the rsyslog message where the field should be
+ * - pFieldName: a nul-terminated pointer to string representing the name of the field to search for
+ * - ppRetString: the pointer to contain the potential return string
+ *
+ * return: 1 if a string was put in ppRetString, 0 otherwise
+ *
+ * note: the string placed in ppRetString should be freed by the caller
+ */
+int get_field(smsg_t *const pMsg, const char *pFieldName, char **ppRetString)
+{
+ DBGPRINTF("mmdarwin::get_field:: getting key '%s' in msg\n", pFieldName);
+ struct json_object *pJson = NULL;
+ char *pFieldString = NULL;
+ int retVal = 0;
+
+ msgPropDescr_t propDesc;
+ msgPropDescrFill(&propDesc, (uchar *)pFieldName, strlen(pFieldName));
+ msgGetJSONPropJSONorString(pMsg, &propDesc, &pJson, (uchar **)&pFieldString);
+
+ if (pFieldString)
+ {
+ *ppRetString = pFieldString;
+ DBGPRINTF("mmdarwin::get_field:: got string\n");
+ retVal = 1;
+ }
+ else if (pJson)
+ {
+ pFieldString = (char *)json_object_get_string(pJson);
+ if (pFieldString)
+ {
+ *ppRetString = strdup(pFieldString);
+ retVal = 1;
+ DBGPRINTF("mmdarwin::get_field:: got string from json\n");
+ json_object_put(pJson);
+ }
+ }
+
+ msgPropDescrDestruct(&propDesc);
+ return retVal;
+}
+
+/**
+ * expands the buffer object in the dyn_buffer object
+ *
+ * params:
+ * - pBody: a pointer to the concerned structure to expand
+ * - new_size: the new size to give to the underlying buffer
+ *
+ * return: 0 if the expansion was successful, -1 otherwise
+ */
+int expand_buffer(dyn_buffer *pBody, size_t new_size)
+{
+ /* return error if new_size tries to exceed max defined size */
+ if (new_size > pBody->bufferMaxSize)
+ return -1;
+ while (pBody->bufferAllocSize < new_size)
+ pBody->bufferAllocSize += INITIAL_BUFFER_SIZE;
+
+ DBGPRINTF("mmdarwin::expand_buffer:: expanding buffer to %zu\n", pBody->bufferAllocSize);
+
+ char *tmp = realloc(pBody->buffer, pBody->bufferAllocSize * sizeof(char));
+
+ if (!tmp)
+ {
+ DBGPRINTF("mmdarwin::expand_buffer:: could not resize buffer\n");
+ return -1;
+ }
+
+ pBody->buffer = tmp;
+ return 0;
+}
+
+/**
+ * adds a field to the dyn_buffer buffer
+ *
+ * params:
+ * - pBody: the pointer on the dyn_buffer structure
+ * - field: the potentially not null-terminated string to add as a field to the dyn_buffer
+ * - size: the size of the string (without the '\0' character)
+ *
+ * return: 0 if the field was indeed added to the dyn_buffer, -1 otherwise
+ */
+int add_field_to_body(dyn_buffer *pBody, const char *field, size_t size)
+{
+ /* get required additional size for field, quotes, colon, and \0
+ and potentially also for the beginning of the message structure */
+ int beginning = (pBody->bufferMsgSize == 0) ? 2 : 0;
+ size_t requiredBodySize = pBody->bufferMsgSize + size + 4 + beginning;
+
+ /* resize body buffer if necessary */
+ if (requiredBodySize > pBody->bufferAllocSize)
+ {
+ if (expand_buffer(pBody, requiredBodySize) != 0)
+ {
+ return -1;
+ }
+ }
+
+ /* add message structure beginning if current message is empty */
+ if (!pBody->bufferMsgSize)
+ {
+ pBody->buffer[0] = '[';
+ pBody->buffer[1] = '[';
+ pBody->bufferMsgSize += 2;
+ }
+
+ /* add field with quotes and colon */
+ pBody->buffer[pBody->bufferMsgSize++] = '\"';
+ memcpy((void *)&pBody->buffer[pBody->bufferMsgSize], (const void *)field, size);
+ pBody->bufferMsgSize += size;
+ pBody->buffer[pBody->bufferMsgSize++] = '\"';
+ pBody->buffer[pBody->bufferMsgSize++] = ',';
+
+ return 0;
+}
+
+/**
+ * small helper function to start a new input line (used for bulk-calls) in the dyn_buffer.
+ * will close current line with a ']' and start the next with a '['.
+ * will also remove leading ',' in fields list.
+ *
+ * params:
+ * - pBody: the pointer on the dyn_buffer on which to start a new input line
+ *
+ * return: 0 if successful, -1 otherwise
+ */
+int start_new_line(dyn_buffer *pBody)
+{
+ /* don't if the message is empty */
+ if (!pBody->bufferMsgSize)
+ {
+ return -1;
+ }
+
+ DBGPRINTF("mmdarwin::start_new_line:: starting new line entry in body\n");
+
+ if (pBody->bufferAllocSize < pBody->bufferMsgSize + 2)
+ {
+ if (expand_buffer(pBody, pBody->bufferAllocSize + 2) != 0)
+ {
+ return -1;
+ }
+ }
+
+ pBody->buffer[pBody->bufferMsgSize - 1] = ']';
+ pBody->buffer[pBody->bufferMsgSize++] = ',';
+ pBody->buffer[pBody->bufferMsgSize++] = '[';
+ return 0;
+}
+
+/**
+ * small helper function to close the dyn_buffer structure.
+ * will close the line list with two ']' and will remove the leading ',' in the fields list
+ *
+ * params:
+ * - pBody: the pointer on the dyn_buffer on which to start a new input line
+ *
+ * return: 0 if successful, -1 otherwise
+ */
+int end_body(dyn_buffer *pBody)
+{
+ /* don't if the message is empty */
+ if (!pBody->bufferMsgSize)
+ {
+ return -1;
+ }
+
+ DBGPRINTF("mmdarwin::end_body:: finishing body structure\n");
+
+ if (pBody->bufferAllocSize < pBody->bufferMsgSize + 2)
+ {
+ if (expand_buffer(pBody, pBody->bufferAllocSize + 2) != 0)
+ {
+ return -1;
+ }
+ }
+
+ pBody->buffer[pBody->bufferMsgSize - 1] = ']';
+ pBody->buffer[pBody->bufferMsgSize++] = ']';
+ pBody->buffer[pBody->bufferMsgSize++] = '\0';
+ return 0;
+}
+
+/**
+ * Get the potential existing uuid put by previous mmdarwin call in a json
+ *
+ * params:
+ * - pJson: the pointer on the json
+ *
+ * return: a valid json_object pointer if found, NULL otherwise
+ */
+const char* get_uuid_object(smsg_t *const pMsg) {
+ struct json_object *mmdarwin_object = NULL;
+ const char *result = NULL, *key = NULL;
+
+ msgPropDescr_t propDesc;
+ msgPropDescrFill(&propDesc, (uchar *)runModConf->container, strlen(runModConf->container));
+ msgGetJSONPropJSON(pMsg, &propDesc, &mmdarwin_object);
+
+ if(mmdarwin_object) {
+ struct json_object_iterator it = json_object_iter_begin(mmdarwin_object);
+ struct json_object_iterator itEnd = json_object_iter_end(mmdarwin_object);
+
+ while(!json_object_iter_equal(&it, &itEnd)) {
+ key = json_object_iter_peek_name(&it);
+
+ if(!strcmp(key, JSON_DARWIN_ID)) {
+ // should always be a (non-empty) null-terminated string, safe to use with strdup()
+ result = strdup(json_object_get_string(json_object_iter_peek_value(&it)));
+ break;
+ }
+
+ json_object_iter_next(&it);
+ }
+ json_object_put(mmdarwin_object);
+ }
+
+ msgPropDescrDestruct(&propDesc);
+ return result;
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free((void *)pModConf->container);
+ENDfreeCnf
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("%s\n", pData->pSockName);
+ENDdbgPrintInstInfo
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->pktSentSocket = 0;
+ pWrkrData->darwinBody.bufferAllocSize = 0;
+ pWrkrData->darwinBody.bufferMaxSize = BUFFER_DEFAULT_MAX_SIZE;
+ pWrkrData->darwinBody.bufferMsgSize = 0;
+ pWrkrData->sock = INVLD_SOCK;
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if (pData->fieldList.name != NULL)
+ {
+ for (int i = 0; i < pData->fieldList.nmemb; ++i)
+ {
+ free(pData->fieldList.name[i]);
+ free(pData->fieldList.varname[i]);
+ }
+ free(pData->fieldList.name);
+ free(pData->fieldList.varname);
+ }
+ free(pData->pUUIDKey);
+ free(pData->pCertitudeKey);
+ free(pData->pSockName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ closeSocket(pWrkrData);
+ free(pWrkrData->darwinBody.buffer);
+ENDfreeWrkrInstance
+
+BEGINsetModCnf
+struct cnfparamvals *pvals = NULL;
+int i;
+CODESTARTsetModCnf
+ loadModConf->container = NULL;
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if (pvals == NULL)
+ {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "mmdarwin: error processing module config parameters missing [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if (Debug)
+ {
+ DBGPRINTF("mmdarwin::setModCnf:: module (global) param blk for mmdarwin:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for (i = 0; i < modpblk.nParams; ++i)
+ {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(modpblk.descr[i].name, "container"))
+ {
+ loadModConf->container = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(loadModConf->container[0] != '!' && loadModConf->container[0] != '.') {
+ LogError(0, RS_RET_INVALID_PARAMS, "mmdarwin: container should either"
+ " begin with '!' or '.'\n");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ }
+ else
+ {
+ DBGPRINTF("mmdarwin::setModCnf:: program error, non-handled "
+ "param '%s'\n",
+ modpblk.descr[i].name);
+ }
+ }
+
+ if (loadModConf->container == NULL)
+ {
+ CHKmalloc(loadModConf->container = strdup(JSON_DEFAULT_CONTAINER));
+ }
+
+finalize_it :
+ if (pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+static inline void setInstParamDefaults(instanceData *pData)
+{
+ DBGPRINTF("mmdarwin::setInstParamDefaults::\n");
+ pData->pUUIDKey = NULL;
+ pData->pCertitudeKey = NULL;
+ pData->pSockName = NULL;
+ pData->fieldList.nmemb = 0;
+ pData->filterCode = DARWIN_FILTER_CODE_NO;
+ pData->response = DARWIN_RESPONSE_SEND_NO;
+ pData->socketMaxUse = 0;
+ pData->sendPartial = 0;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("mmdarwin::newActInst::\n");
+ if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL)
+ {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for (i = 0; i < actpblk.nParams; ++i)
+ {
+ if (!pvals[i].bUsed)
+ continue;
+
+ if (!strcmp(actpblk.descr[i].name, "key"))
+ {
+ char *key = es_str2cstr(pvals[i].val.d.estr, NULL);
+ char vnamebuf[1024];
+ snprintf(vnamebuf, sizeof(vnamebuf), "%s!%s", loadModConf->container, key);
+ CHKmalloc(pData->pCertitudeKey = strdup(vnamebuf));
+ free(key);
+ DBGPRINTF("mmdarwin::newActInst:: certitudeKey is %s\n", pData->pCertitudeKey);
+ }
+ else if (!strcmp(actpblk.descr[i].name, "socketpath"))
+ {
+ pData->pSockName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("mmdarwin::newActInst:: sockName is %s\n", pData->pSockName);
+ }
+ else if (!strcmp(actpblk.descr[i].name, "socket_max_use"))
+ {
+ pData->socketMaxUse = (uint32_t)pvals[i].val.d.n;
+ DBGPRINTF("mmdarwin::newActInst:: socketMaxUse is %d\n", pData->socketMaxUse);
+ }
+ else if (!strcmp(actpblk.descr[i].name, "send_partial"))
+ {
+ pData->sendPartial = (sbool)pvals[i].val.d.n;
+ if (pData->sendPartial)
+ {
+ DBGPRINTF("mmdarwin::newActInst:: sending bodies even if fields are missing\n");
+ }
+ else
+ {
+ DBGPRINTF("mmdarwin::newActInst:: only sending complete bodies\n");
+ }
+ }
+ else if (!strcmp(actpblk.descr[i].name, "response"))
+ {
+ char *response = es_str2cstr(pvals[i].val.d.estr, NULL);
+
+ if (!strcmp(response, "no"))
+ {
+ pData->response = DARWIN_RESPONSE_SEND_NO;
+ DBGPRINTF("mmdarwin::newActInst:: response type is 'no'\n");
+ }
+ else if (!strcmp(response, "back"))
+ {
+ pData->response = DARWIN_RESPONSE_SEND_BACK;
+ DBGPRINTF("mmdarwin::newActInst:: response type is 'back'\n");
+ }
+ else if (!strcmp(response, "darwin"))
+ {
+ pData->response = DARWIN_RESPONSE_SEND_DARWIN;
+ DBGPRINTF("mmdarwin::newActInst:: response type is 'darwin'\n");
+ }
+ else if (!strcmp(response, "both"))
+ {
+ pData->response = DARWIN_RESPONSE_SEND_BOTH;
+ DBGPRINTF("mmdarwin::newActInst:: response type is 'both'\n");
+ }
+ else
+ {
+ DBGPRINTF(
+ "mmdarwin::newActInst:: invalid 'response' value: %s. 'No response' set.\n",
+ response);
+
+ pData->response = DARWIN_RESPONSE_SEND_NO;
+ DBGPRINTF("mmdarwin::newActInst:: response type is 'no'\n");
+ }
+
+ free(response);
+ }
+ else if (!strcmp(actpblk.descr[i].name, "filtercode"))
+ {
+ char *filterCode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->filterCode = strtoull(filterCode, NULL, 16);
+ free(filterCode);
+ }
+ else if (!strcmp(actpblk.descr[i].name, "fields"))
+ {
+ pData->fieldList.nmemb = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->fieldList.name = calloc(pData->fieldList.nmemb, sizeof(char *)));
+ CHKmalloc(pData->fieldList.varname = calloc(pData->fieldList.nmemb, sizeof(char *)));
+
+ for (int j = 0; j < pData->fieldList.nmemb; ++j)
+ {
+ char *const param = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ char *varname = NULL;
+ char *name;
+ if (*param == ':')
+ {
+ char *b = strchr(param + 1, ':');
+ if (b == NULL)
+ {
+ parser_errmsg(
+ "mmdarwin::newActInst:: missing closing colon: '%s'", param);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ *b = '\0'; /* split name & varname */
+ varname = param + 1;
+ name = b + 1;
+ }
+ else
+ {
+ name = param;
+ }
+ CHKmalloc(pData->fieldList.name[j] = strdup(name));
+ char vnamebuf[1024];
+ snprintf(vnamebuf, sizeof(vnamebuf),
+ "%s!%s", loadModConf->container,
+ (varname == NULL) ? name : varname);
+ CHKmalloc(pData->fieldList.varname[j] = strdup(vnamebuf));
+ free(param);
+ DBGPRINTF("mmdarwin::newActInst:: will look for field %s\n", pData->fieldList.name[j]);
+ }
+ }
+ else
+ {
+ DBGPRINTF(
+ "mmdarwin::newActInst:: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ // reserve space for 'container!key\0'
+ size_t sizeKey = strlen(loadModConf->container) + strlen(JSON_DARWIN_ID) + 2;
+ pData->pUUIDKey = malloc(sizeKey);
+ snprintf(pData->pUUIDKey, sizeKey, "%s!%s", loadModConf->container, JSON_DARWIN_ID);
+ DBGPRINTF("mmdarwin:: uuid key is %s\n", pData->pUUIDKey);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pWrkrData);
+ENDtryResume
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **)pMsgData; /* the raw data */
+ smsg_t *pMsg = ppMsg[0]; /* the raw log line */
+ instanceData *pData = pWrkrData->pData; /* the parameters given for the plugin */
+ char *pFieldValue = NULL; /* ponter to the found field value */
+ int fieldsNum = 0; /* number of fields retrieved */
+
+CODESTARTdoAction
+ DBGPRINTF("mmdarwin::doAction:: beggining action\n");
+ pWrkrData->darwinBody.bufferMsgSize = 0;
+ fieldsNum = 0;
+
+ for (int i = 0; i < pData->fieldList.nmemb; i++)
+ {
+ DBGPRINTF("mmdarwin::doAction:: processing field '%s'\n", pData->fieldList.name[i]);
+ pFieldValue = NULL;
+
+ /* case 1: static field. We simply forward it to Darwin */
+ if (pData->fieldList.name[i][0] != '!' && pData->fieldList.name[i][0] != '.')
+ {
+ pFieldValue = strdup(pData->fieldList.name[i]);
+ }
+ /* case 2: dynamic field. We retrieve its value from the JSON logline and forward it to
+ * Darwin */
+ else
+ {
+ if (!get_field(pMsg, pData->fieldList.name[i], &pFieldValue))
+ {
+ DBGPRINTF("mmdarwin::doAction:: \
+could not extract field '%s' from message\n", pData->fieldList.name[i]);
+ continue;
+ }
+ }
+
+ DBGPRINTF(
+ "mmdarwin::doAction:: got value of field '%s': '%s'\n", pData->fieldList.name[i], pFieldValue);
+
+ if (add_field_to_body(&(pWrkrData->darwinBody), pFieldValue, strlen(pFieldValue)) != 0)
+ {
+ DBGPRINTF("mmdarwin::doAction:: could not add field to body, aborting\n");
+ free(pFieldValue);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fieldsNum++;
+ free(pFieldValue);
+ }
+
+ if (fieldsNum)
+ {
+ if (!pData->sendPartial && fieldsNum != pData->fieldList.nmemb)
+ {
+ DBGPRINTF("mmdarwin::doAction:: not all fields could be retrieved, not sending partial message."
+ " (if you wish to send partial messages anyway, set 'send_partial' to 'on' in instance parameters)\n");
+ FINALIZE;
+ }
+ if (end_body(&(pWrkrData->darwinBody)) != 0)
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ else
+ {
+ DBGPRINTF("mmdarwin::doAction:: no fields retrieved, finalizing\n");
+ FINALIZE;
+ }
+
+ DBGPRINTF("mmdarwin::doAction:: body to send: '%s'\n", pWrkrData->darwinBody.buffer);
+
+ if (pData->socketMaxUse)
+ {
+ /* need to rotate socket connections */
+ if (!pWrkrData->pktSentSocket)
+ {
+ DBGPRINTF("mmdarwin::doAction:: opening a new connection\n");
+ CHKiRet(doTryResume(pWrkrData));
+ }
+ pWrkrData->pktSentSocket = (pWrkrData->pktSentSocket + 1) % pData->socketMaxUse;
+ }
+
+ /* the Darwin header to be sent to the filter */
+ darwin_filter_packet_t header = {
+ .type = DARWIN_PACKET_OTHER,
+ .response = pData->response,
+ .filter_code = pData->filterCode,
+ .body_size = pWrkrData->darwinBody.bufferMsgSize};
+
+ const char *uuid = get_uuid_object(pMsg);
+ if(uuid) {
+ DBGPRINTF("mmdarwin: using existing UUID = %s\n", uuid);
+ if(uuid_parse(uuid, header.evt_id))
+ LogError(0, RS_RET_ERR, "mmdarwin:: failed to parse existing UUID: %s\n", uuid);
+ free((void*)uuid);
+ }
+ else {
+ uuid_generate(header.evt_id);
+ char uuidStr[40];
+ uuid_unparse(header.evt_id, uuidStr);
+ DBGPRINTF("mmdarwin: generated new UUID = %s\n", uuidStr);
+ msgAddJSON(pMsg, (uchar *)pData->pUUIDKey, json_object_new_string(uuidStr), 0, 0);
+ }
+
+ DBGPRINTF("mmdarwin::doAction:: sending header to Darwin\n");
+ CHKiRet(sendMsg(pWrkrData, &header, sizeof(darwin_filter_packet_t)));
+
+ DBGPRINTF("mmdarwin::doAction:: sending body to Darwin\n");
+ CHKiRet(sendMsg(pWrkrData, (void *)(pWrkrData->darwinBody.buffer), pWrkrData->darwinBody.bufferMsgSize));
+
+ /* there is no need to wait for a response that will never come */
+ if (pData->response == DARWIN_RESPONSE_SEND_NO || pData->response == DARWIN_RESPONSE_SEND_DARWIN)
+ {
+ DBGPRINTF("mmdarwin::doAction:: no response will be sent back "
+ "(darwin response type is set to 'no' or 'darwin')\n");
+ goto finalize_it;
+ }
+
+ darwin_filter_packet_t response;
+ memset(&response, 0, sizeof(response));
+ DBGPRINTF("mmdarwin::doAction:: receiving from Darwin\n");
+ CHKiRet(receiveMsg(pWrkrData, &response, sizeof(response)));
+
+ unsigned int certitude = response.certitude_list[0];
+ DBGPRINTF("mmdarwin::doAction:: end of the transaction, certitude is %d\n", certitude);
+
+ msgAddJSON(pMsg, (uchar *)pData->pCertitudeKey, json_object_new_int(certitude), 0, 0);
+
+finalize_it :
+ DBGPRINTF("mmdarwin::doAction:: finished processing log line\n");
+
+ENDdoAction
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmdarwin::modInit:: module compiled with rsyslog version %s.\n", VERSION);
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/mmdarwin/protocol.h b/contrib/mmdarwin/protocol.h
new file mode 100644
index 0000000..fce211f
--- /dev/null
+++ b/contrib/mmdarwin/protocol.h
@@ -0,0 +1,70 @@
+/* Copyright 2019 Advens
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DARWIN_PROTOCOL_H
+#define DARWIN_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h>
+#include <netinet/in.h>
+
+#define DARWIN_FILTER_CODE_NO 0x00000000
+// the default certitude list size, which is 1, to allow FMAs (see flexible array members on C99) for both C and C++
+// code
+#define DEFAULT_CERTITUDE_LIST_SIZE 1
+
+ /// Represent the receiver of the results.
+ ///
+ /// \enum darwin_response_type
+ enum darwin_filter_response_type
+ {
+ DARWIN_RESPONSE_SEND_NO = 0, //!< Don't send results to anybody.
+ DARWIN_RESPONSE_SEND_BACK, //!< Send results back to caller.
+ DARWIN_RESPONSE_SEND_DARWIN, //!< Send results to the next filter.
+ DARWIN_RESPONSE_SEND_BOTH, //!< Send results to both caller and the next filter.
+ };
+
+ /// Represent the type of information sent.
+ ///
+ /// \enum darwin_packet_type
+ enum darwin_packet_type
+ {
+ DARWIN_PACKET_OTHER = 0, //!< Information sent by something else.
+ DARWIN_PACKET_FILTER, //!< Information sent by another filter.
+ };
+
+ /// First packet to be sent to a filter.
+ ///
+ /// \struct darwin_filter_packet_t
+ typedef struct
+ {
+ enum darwin_packet_type type; //!< The type of information sent.
+ enum darwin_filter_response_type response; //!< Whom the response will be sent to.
+ long filter_code; //!< The unique identifier code of a filter.
+ size_t body_size; //!< The complete size of the the parameters to be sent
+ unsigned char evt_id[16]; //!< An array containing the event ID
+ size_t certitude_size; //!< The size of the list containing the certitudes.
+ unsigned int certitude_list[DEFAULT_CERTITUDE_LIST_SIZE];
+ //!< The scores or the certitudes of the module. May be used to pass other info in specific cases.
+ } darwin_filter_packet_t;
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !DARWIN_PROTOCOL_H */
diff --git a/contrib/mmgrok/Makefile.am b/contrib/mmgrok/Makefile.am
new file mode 100644
index 0000000..00c1011
--- /dev/null
+++ b/contrib/mmgrok/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmgrok.la
+
+mmgrok_la_SOURCES = mmgrok.c
+mmgrok_la_CPPFLAGS = $(GLIB_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmgrok_la_LDFLAGS = -module -avoid-version
+mmgrok_la_LIBADD = $(GLIB_LIBS) -lgrok $(LIBFASTJSON_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/mmgrok/Makefile.in b/contrib/mmgrok/Makefile.in
new file mode 100644
index 0000000..596dbfe
--- /dev/null
+++ b/contrib/mmgrok/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmgrok
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+mmgrok_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_mmgrok_la_OBJECTS = mmgrok_la-mmgrok.lo
+mmgrok_la_OBJECTS = $(am_mmgrok_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 =
+mmgrok_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmgrok_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmgrok_la-mmgrok.Plo
+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 = $(mmgrok_la_SOURCES)
+DIST_SOURCES = $(mmgrok_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmgrok.la
+mmgrok_la_SOURCES = mmgrok.c
+mmgrok_la_CPPFLAGS = $(GLIB_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmgrok_la_LDFLAGS = -module -avoid-version
+mmgrok_la_LIBADD = $(GLIB_LIBS) -lgrok $(LIBFASTJSON_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/mmgrok/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmgrok/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmgrok.la: $(mmgrok_la_OBJECTS) $(mmgrok_la_DEPENDENCIES) $(EXTRA_mmgrok_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmgrok_la_LINK) -rpath $(pkglibdir) $(mmgrok_la_OBJECTS) $(mmgrok_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmgrok_la-mmgrok.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmgrok_la-mmgrok.lo: mmgrok.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmgrok_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmgrok_la-mmgrok.lo -MD -MP -MF $(DEPDIR)/mmgrok_la-mmgrok.Tpo -c -o mmgrok_la-mmgrok.lo `test -f 'mmgrok.c' || echo '$(srcdir)/'`mmgrok.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmgrok_la-mmgrok.Tpo $(DEPDIR)/mmgrok_la-mmgrok.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmgrok.c' object='mmgrok_la-mmgrok.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) $(mmgrok_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmgrok_la-mmgrok.lo `test -f 'mmgrok.c' || echo '$(srcdir)/'`mmgrok.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmgrok_la-mmgrok.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmgrok_la-mmgrok.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmgrok/README b/contrib/mmgrok/README
new file mode 100644
index 0000000..1194212
--- /dev/null
+++ b/contrib/mmgrok/README
@@ -0,0 +1,32 @@
+Grok Message Modify Plugin
+
+Using hundreds of grok patterns from logstash-patterns-core.
+
+Build
+
+This plugin requires libfastjson (always present in rsyslog core), glib2, and grok packages.
+
+If you use RH/CentOS/Fedora, you'll have to build grok rpms by yourself as follow:
+
+ sudo yum install -y yum-utils rpmdevtools
+ git clone git@github.com:jordansissel/grok.git
+ mkdir -p ~/rpmbuild/SPECS/; cp grok/grok.spec.template ~/rpmbuild/SPECS/grok.spec
+ (mkdir -p ~/rpmbuild/SOURCES/; cd ~/rpmbuild/SOURCES/; spectool -g ../SPECS/grok.spec)
+ sudo yum-builddep ~/rpmbuild/SPECS/grok.spec
+ rpmbuild -bb ~/rpmbuild/SPECS/grok.spec
+ # use yum command instead of rpm, because grok depends on libevent, pcre, tokyocabinet
+ sudo yum install -y libjson-c-devel glib2-devel ~/rpmbuild/RPMS/x86_64/grok*.rpm
+
+Example
+
+module(load="mmgrok")
+template(name="tmlp" type="string" string="%$!msg!test%\n")
+action(type="mmgrok" patterndir="path/to/yourpatternsDir" match="%{WORD:test}" source="msg" target="!msg")
+action(type="omfile" file="path/to/file" template="tmlp")
+
+Description
+
+patterndir: path to grok patterns dir, default: /usr/share/grok/patterns/base
+match:the pattern used to match message
+source: the source message/variable to be matched
+target: the root path to write the captured json tree
diff --git a/contrib/mmgrok/mmgrok.c b/contrib/mmgrok/mmgrok.c
new file mode 100644
index 0000000..340c7ba
--- /dev/null
+++ b/contrib/mmgrok/mmgrok.c
@@ -0,0 +1,418 @@
+/* mmgrok.c
+ * Grok the message is parsed into a structured json data inside JSON.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <json.h>
+#include <grok.h>
+#include <glib.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmgrok");
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+DEF_OMOD_STATIC_DATA
+
+typedef struct result_s{
+ char *key;
+ int key_len;
+ const char *value;
+ int value_len;
+ char *type;
+}result_t;
+
+/* config variables */
+typedef struct _instanceData
+{
+ char *pszPatternDir;
+ char *pszMatch;
+ char *pszSource;
+ char *pszTarget;/* as a json root for store parse json data */
+ smsg_t *pmsg; /* store origin messages*/
+}instanceData;
+
+typedef struct wrkrInstanceData{
+ instanceData *pData;
+}wrkrInstanceData_t;
+
+struct modConfData_s{
+ rsconf_t *pConf;/* our overall config object */
+};
+
+static modConfData_t *loadModConf = NULL;
+static modConfData_t *runModConf = NULL;
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[]={
+ {"patterndir",eCmdHdlrString,0},
+ {"match",eCmdHdlrString,0},
+ {"source",eCmdHdlrString,0},
+ {"target",eCmdHdlrString,0},
+};
+
+static struct cnfparamblk actpblk =
+{
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->pszPatternDir);
+ free(pData->pszMatch);
+ free(pData->pszSource);
+ free(pData->pszTarget);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void setInstParamDefaults(instanceData *pData)
+{
+ pData->pszPatternDir= NULL;
+ pData->pszMatch = NULL;
+ pData->pszSource = NULL;
+ pData->pszTarget = NULL;
+ pData->pmsg = NULL;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmgrok)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "patterndir")) {
+ pData->pszPatternDir= es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ else if(!strcmp(actpblk.descr[i].name, "match")) {
+ pData->pszMatch = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ else if(!strcmp(actpblk.descr[i].name, "source")) {
+ pData->pszSource= es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ else if(!strcmp(actpblk.descr[i].name,"target"))
+ {
+ pData->pszTarget=es_str2cstr(pvals[i].val.d.estr,NULL);
+ continue;
+ }
+ else{
+ DBGPRINTF("mmgrok: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ if(pData->pszTarget == NULL) {
+ CHKmalloc(pData->pszTarget = strdup("!"));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("mmgrok\n");
+ENDdbgPrintInstInfo
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+static inline grok_t *CreateGrok(void)
+{
+ grok_t *grok = grok_new();
+ if(grok == NULL){
+ DBGPRINTF("mmgrok: create a grok faile!");
+ exit(1);
+ }
+ grok_init(grok);
+ return grok;
+}
+
+/* the parseing is complate message into json */
+static rsRetVal
+smsg_to_json(GList *list,instanceData *pData)
+{
+ GList *it= list;
+
+ struct json_object *json;
+ struct json_object *jval;
+
+ DEFiRet;
+
+ json = json_object_new_object();
+ if(json == NULL)
+ {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ for(;it;it= it->next)
+ {
+ int key_len = ((result_t *)it->data)->key_len;
+ char *key = (char *)malloc(key_len+1);
+ snprintf(key,key_len+1,"%.*s",key_len,((result_t *)it->data)->key);
+ int value_len = ((result_t *)it->data)->value_len;
+ char *value = (char *)malloc(value_len+1);
+ snprintf(value,value_len+1,"%.*s",value_len,((result_t*)it->data)->value);
+ jval = json_object_new_string(value);
+ json_object_object_add(json,key,jval);
+ free(key);
+ free(value);
+ }
+ msgAddJSON(pData->pmsg,(uchar*)pData->pszTarget,json,0,0);
+finalize_it:
+ RETiRet;
+}
+
+/* store parse result ,use list in glib*/
+static rsRetVal
+parse_result_store(const grok_match_t gm,instanceData *pData)
+{
+ GList *re_list = NULL;
+ char *pname;
+ const char *pdata;
+ int pname_len,pdata_len;
+
+ char *key;
+ char *type;
+ DEFiRet;
+
+ grok_match_walk_init(&gm); //grok API
+
+ while(grok_match_walk_next(&gm,&pname,&pname_len,&pdata,&pdata_len) == 0) {
+ /* parse key and value type from patterns */
+ key = strchr(pname,':');
+
+ if(key!=NULL) {
+ int key_len;
+ result_t *result = g_new0(result_t,1);
+ key_len = pname_len - ((key+1) - pname);
+ key = key+1;
+ pname_len = key_len;
+ type = strchr(key,':');
+ int type_len;
+ if(type != NULL) {
+ key_len = (type - key);
+ type = type+1;
+ type_len = pname_len - key_len -1;
+ type[type_len] = '\0';
+ } else {
+ type = (char*)"null";
+ }
+ /* store parse result into list */
+ result->key = key;
+ result->key_len = key_len;
+ result->value = pdata;
+ result->value_len = pdata_len;
+ result->type = type;
+ /* the value of merger the same key*/
+ re_list = g_list_append(re_list,result);
+ }
+ }
+ smsg_to_json(re_list,pData);
+ g_list_free(re_list);
+ grok_match_walk_end(&gm);
+ RETiRet;
+}
+
+/* motify message for per line */
+static rsRetVal
+MotifyLine(char *line,grok_t *grok,instanceData *pData)
+{
+ grok_match_t gm;
+ DEFiRet;
+ grok_patterns_import_from_file(grok,pData->pszPatternDir);
+ int compile = grok_compile(grok,pData->pszMatch);
+ if(compile!=GROK_OK)
+ {
+ DBGPRINTF("mmgrok: grok_compile faile!exit code: %d\n",compile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ int exe = grok_exec(grok,line,&gm);
+ if(exe!=GROK_OK)
+ {
+ DBGPRINTF("mmgrok: grok_exec faile!exit code: %d\n",exe);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ parse_result_store(gm,pData);
+finalize_it:
+ RETiRet;
+}
+
+/* motify rsyslog messages */
+static rsRetVal
+MotifyMessage(instanceData *pData)
+{
+ char *saveptr = NULL;
+ DEFiRet;
+ grok_t *grok = CreateGrok();
+ char *msg = strdup(pData->pszSource);
+ char *line = NULL;
+ line = strtok_r(msg, "\n", &saveptr);
+ while(line!=NULL) {
+ MotifyLine(line,grok,pData);
+ line = strtok_r(NULL, "\n", &saveptr);
+ }
+ free(msg);msg=NULL;
+ RETiRet;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *buf;
+ instanceData *pData;
+
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ buf = getMSG(pMsg);
+ pData->pmsg = pMsg;
+ while(*buf && isspace(*buf)) {
+ ++buf;
+ }
+
+ if(*buf == '\0' ) {
+ DBGPRINTF("mmgrok: not msg for mmgrok!");
+ ABORT_FINALIZE(RS_RET_NO_CEE_MSG);
+ }
+ pData->pszSource = (char *)buf;
+ CHKiRet(MotifyMessage(pData));
+
+finalize_it:
+ENDdoAction
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(strncmp((char*) p, ":mmgrok:", sizeof(":mmgrok:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ p += sizeof(":mmgrok:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ if(*(p-1) == ';')
+ --p;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat"));
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ RETiRet;
+}
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported;
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmgrok: module compiled with rsyslog version %s.\n", VERSION);
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("mmgrok: msg-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/contrib/mmkubernetes/Makefile.am b/contrib/mmkubernetes/Makefile.am
new file mode 100644
index 0000000..88dca48
--- /dev/null
+++ b/contrib/mmkubernetes/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmkubernetes.la
+
+mmkubernetes_la_SOURCES = mmkubernetes.c
+mmkubernetes_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBLOGNORM_CFLAGS)
+mmkubernetes_la_LDFLAGS = -module -avoid-version
+mmkubernetes_la_LIBADD = $(CURL_LIBS) $(LIBLOGNORM_LIBS)
+
+EXTRA_DIST = k8s_filename.rulebase k8s_container_name.rulebase
diff --git a/contrib/mmkubernetes/Makefile.in b/contrib/mmkubernetes/Makefile.in
new file mode 100644
index 0000000..983a32f
--- /dev/null
+++ b/contrib/mmkubernetes/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmkubernetes
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+mmkubernetes_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_mmkubernetes_la_OBJECTS = mmkubernetes_la-mmkubernetes.lo
+mmkubernetes_la_OBJECTS = $(am_mmkubernetes_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 =
+mmkubernetes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmkubernetes_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo
+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 = $(mmkubernetes_la_SOURCES)
+DIST_SOURCES = $(mmkubernetes_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmkubernetes.la
+mmkubernetes_la_SOURCES = mmkubernetes.c
+mmkubernetes_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBLOGNORM_CFLAGS)
+mmkubernetes_la_LDFLAGS = -module -avoid-version
+mmkubernetes_la_LIBADD = $(CURL_LIBS) $(LIBLOGNORM_LIBS)
+EXTRA_DIST = k8s_filename.rulebase k8s_container_name.rulebase
+all: 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) --gnu contrib/mmkubernetes/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmkubernetes/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmkubernetes.la: $(mmkubernetes_la_OBJECTS) $(mmkubernetes_la_DEPENDENCIES) $(EXTRA_mmkubernetes_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmkubernetes_la_LINK) -rpath $(pkglibdir) $(mmkubernetes_la_OBJECTS) $(mmkubernetes_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmkubernetes_la-mmkubernetes.lo: mmkubernetes.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmkubernetes_la-mmkubernetes.lo -MD -MP -MF $(DEPDIR)/mmkubernetes_la-mmkubernetes.Tpo -c -o mmkubernetes_la-mmkubernetes.lo `test -f 'mmkubernetes.c' || echo '$(srcdir)/'`mmkubernetes.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmkubernetes_la-mmkubernetes.Tpo $(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmkubernetes.c' object='mmkubernetes_la-mmkubernetes.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) $(mmkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmkubernetes_la-mmkubernetes.lo `test -f 'mmkubernetes.c' || echo '$(srcdir)/'`mmkubernetes.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmkubernetes/k8s_container_name.rulebase b/contrib/mmkubernetes/k8s_container_name.rulebase
new file mode 100644
index 0000000..1fe7373
--- /dev/null
+++ b/contrib/mmkubernetes/k8s_container_name.rulebase
@@ -0,0 +1,3 @@
+version=2
+rule=:%k8s_prefix:char-to:_%_%container_name:char-to:.%.%container_hash:char-to:_%_%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%
+rule=:%k8s_prefix:char-to:_%_%container_name:char-to:_%_%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%
diff --git a/contrib/mmkubernetes/k8s_filename.rulebase b/contrib/mmkubernetes/k8s_filename.rulebase
new file mode 100644
index 0000000..a7b2cac
--- /dev/null
+++ b/contrib/mmkubernetes/k8s_filename.rulebase
@@ -0,0 +1,2 @@
+version=2
+rule=:/var/log/containers/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log
diff --git a/contrib/mmkubernetes/mmkubernetes.c b/contrib/mmkubernetes/mmkubernetes.c
new file mode 100644
index 0000000..525962e
--- /dev/null
+++ b/contrib/mmkubernetes/mmkubernetes.c
@@ -0,0 +1,2085 @@
+/* mmkubernetes.c
+ * This is a message modification module. It uses metadata obtained
+ * from the message to query Kubernetes and obtain additional metadata
+ * relating to the container instance.
+ *
+ * Inspired by:
+ * https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * Copyright 2016 Red Hat Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* needed for asprintf */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <libestr.h>
+#include <liblognorm.h>
+#include <json.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "statsobj.h"
+#include "regexp.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "srUtils.h"
+#include "unicode-helper.h"
+#include "datetime.h"
+
+/* static data */
+MODULE_TYPE_OUTPUT /* this is technically an output plugin */
+MODULE_TYPE_KEEP /* releasing the module would cause a leak through libcurl */
+MODULE_CNFNAME("mmkubernetes")
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(regexp)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(datetime)
+
+#define HAVE_LOADSAMPLESFROMSTRING 1
+#if defined(NO_LOADSAMPLESFROMSTRING)
+#undef HAVE_LOADSAMPLESFROMSTRING
+#endif
+/* original from fluentd plugin:
+ * 'var\.log\.containers\.(?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?\
+ * (\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_\
+ * (?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
+ * this is for _tag_ match, not actual filename match - in_tail turns filename
+ * into a fluentd tag
+ */
+#define DFLT_FILENAME_LNRULES "rule=:/var/log/containers/%pod_name:char-to:_%_"\
+ "%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"
+#define DFLT_FILENAME_RULEBASE "/etc/rsyslog.d/k8s_filename.rulebase"
+/* original from fluentd plugin:
+ * '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)\
+ * (\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_\
+ * (?<namespace>[^_]+)_[^_]+_[^_]+$'
+ */
+#define DFLT_CONTAINER_LNRULES "rule=:%k8s_prefix:char-to:_%_%container_name:char-to:.%."\
+ "%container_hash:char-to:_%_"\
+ "%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%\n"\
+ "rule=:%k8s_prefix:char-to:_%_%container_name:char-to:_%_"\
+ "%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%"
+#define DFLT_CONTAINER_RULEBASE "/etc/rsyslog.d/k8s_container_name.rulebase"
+#define DFLT_SRCMD_PATH "$!metadata!filename"
+#define DFLT_DSTMD_PATH "$!"
+#define DFLT_DE_DOT 1 /* true */
+#define DFLT_DE_DOT_SEPARATOR "_"
+#define DFLT_CONTAINER_NAME "$!CONTAINER_NAME" /* name of variable holding CONTAINER_NAME value */
+#define DFLT_CONTAINER_ID_FULL "$!CONTAINER_ID_FULL" /* name of variable holding CONTAINER_ID_FULL value */
+#define DFLT_KUBERNETES_URL "https://kubernetes.default.svc.cluster.local:443"
+#define DFLT_BUSY_RETRY_INTERVAL 5 /* retry every 5 seconds */
+#define DFLT_SSL_PARTIAL_CHAIN 0 /* disallow X509_V_FLAG_PARTIAL_CHAIN by default */
+#define DFLT_CACHE_ENTRY_TTL 3600 /* delete entries from the cache older than 3600 seconds */
+#define DFLT_CACHE_EXPIRE_INTERVAL -1 /* delete all expired entries from the cache every N seconds
+ -1 disables cache expiration/ttl checking
+ 0 means - run cache expiration for every record */
+
+/* only support setting the partial chain flag on openssl platforms that have the define */
+#if defined(ENABLE_OPENSSL) && defined(X509_V_FLAG_PARTIAL_CHAIN)
+#define SUPPORT_SSL_PARTIAL_CHAIN 1
+#endif
+
+struct cache_entry_s {
+ time_t ttl; /* when this entry should expire */
+ void *data; /* the user data */
+};
+
+static struct cache_s {
+ const uchar *kbUrl;
+ struct hashtable *mdHt;
+ struct hashtable *nsHt;
+ pthread_mutex_t *cacheMtx;
+ int lastBusyTime; /* when we got the last busy response from kubernetes */
+ time_t expirationTime; /* if cache expiration checking is enable, time to check for expiration */
+} **caches;
+
+typedef struct {
+ int nmemb;
+ uchar **patterns;
+ regex_t *regexps;
+} annotation_match_t;
+
+/* module configuration data */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *kubernetesUrl; /* scheme, host, port, and optional path prefix for Kubernetes API lookups */
+ uchar *srcMetadataPath; /* where to get data for kubernetes queries */
+ uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
+ uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
+ sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
+ sbool skipVerifyHost; /* For testing/debugging - skip cert hostname verify (CURLOPT_SSL_VERIFYHOST FALSE) */
+ uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
+ uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
+ sbool de_dot; /* If true (default), convert '.' characters in labels & annotations to de_dot_separator */
+ uchar *de_dot_separator; /* separator character (default '_') to use for de_dotting */
+ size_t de_dot_separator_len; /* length of separator character */
+ annotation_match_t annotation_match; /* annotation keys must match these to be included in record */
+ char *fnRules; /* lognorm rules for container log filename match */
+ uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */
+ char *contRules; /* lognorm rules for CONTAINER_NAME value match */
+ uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
+ sbool sslPartialChain; /* if true, allow using intermediate certs without root certs */
+ int cacheEntryTTL; /* delete entries from the cache if they are older than this many seconds */
+ int cacheExpireInterval; /* delete all expired entries from the cache every this many seconds */
+};
+
+/* action (instance) configuration data */
+typedef struct _instanceData {
+ uchar *kubernetesUrl; /* scheme, host, port, and optional path prefix for Kubernetes API lookups */
+ msgPropDescr_t *srcMetadataDescr; /* where to get data for kubernetes queries */
+ uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */
+ uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */
+ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */
+ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */
+ sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */
+ sbool skipVerifyHost; /* For testing/debugging - skip cert hostname verify (CURLOPT_SSL_VERIFYHOST FALSE) */
+ uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */
+ uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */
+ sbool de_dot; /* If true (default), convert '.' characters in labels & annotations to de_dot_separator */
+ uchar *de_dot_separator; /* separator character (default '_') to use for de_dotting */
+ size_t de_dot_separator_len; /* length of separator character */
+ annotation_match_t annotation_match; /* annotation keys must match these to be included in record */
+ char *fnRules; /* lognorm rules for container log filename match */
+ uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */
+ ln_ctx fnCtxln; /**< context to be used for liblognorm */
+ char *contRules; /* lognorm rules for CONTAINER_NAME value match */
+ uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */
+ ln_ctx contCtxln; /**< context to be used for liblognorm */
+ msgPropDescr_t *contNameDescr; /* CONTAINER_NAME field */
+ msgPropDescr_t *contIdFullDescr; /* CONTAINER_ID_FULL field */
+ struct cache_s *cache;
+ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */
+ sbool sslPartialChain; /* if true, allow using intermediate certs without root certs */
+ int cacheEntryTTL; /* delete entries from the cache if they are older than this many seconds */
+ int cacheExpireInterval; /* delete all expired entries from the cache every this many seconds */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ CURL *curlCtx;
+ struct curl_slist *curlHdr;
+ char *curlRply;
+ size_t curlRplyLen;
+ statsobj_t *stats; /* stats for this instance */
+ STATSCOUNTER_DEF(k8sRecordSeen, mutK8sRecordSeen);
+ STATSCOUNTER_DEF(namespaceMetadataSuccess, mutNamespaceMetadataSuccess);
+ STATSCOUNTER_DEF(namespaceMetadataNotFound, mutNamespaceMetadataNotFound);
+ STATSCOUNTER_DEF(namespaceMetadataBusy, mutNamespaceMetadataBusy);
+ STATSCOUNTER_DEF(namespaceMetadataError, mutNamespaceMetadataError);
+ STATSCOUNTER_DEF(podMetadataSuccess, mutPodMetadataSuccess);
+ STATSCOUNTER_DEF(podMetadataNotFound, mutPodMetadataNotFound);
+ STATSCOUNTER_DEF(podMetadataBusy, mutPodMetadataBusy);
+ STATSCOUNTER_DEF(podMetadataError, mutPodMetadataError);
+ STATSCOUNTER_DEF(podCacheNumEntries, mutPodCacheNumEntries);
+ STATSCOUNTER_DEF(namespaceCacheNumEntries, mutNamespaceCacheNumEntries);
+ STATSCOUNTER_DEF(podCacheHits, mutPodCacheHits);
+ STATSCOUNTER_DEF(namespaceCacheHits, mutNamespaceCacheHits);
+ /* cache misses should correspond to metadata success, busy, etc. k8s api calls */
+ STATSCOUNTER_DEF(podCacheMisses, mutPodCacheMisses);
+ STATSCOUNTER_DEF(namespaceCacheMisses, mutNamespaceCacheMisses);
+} wrkrInstanceData_t;
+
+/* module parameters (v6 config format) */
+static struct cnfparamdescr modpdescr[] = {
+ { "kubernetesurl", eCmdHdlrString, 0 },
+ { "srcmetadatapath", eCmdHdlrString, 0 },
+ { "dstmetadatapath", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "allowunsignedcerts", eCmdHdlrBinary, 0 },
+ { "skipverifyhost", eCmdHdlrBinary, 0 },
+ { "token", eCmdHdlrString, 0 },
+ { "tokenfile", eCmdHdlrString, 0 },
+ { "annotation_match", eCmdHdlrArray, 0 },
+ { "de_dot", eCmdHdlrBinary, 0 },
+ { "de_dot_separator", eCmdHdlrString, 0 },
+ { "filenamerulebase", eCmdHdlrString, 0 },
+ { "containerrulebase", eCmdHdlrString, 0 },
+ { "busyretryinterval", eCmdHdlrInt, 0 },
+ { "sslpartialchain", eCmdHdlrBinary, 0 },
+ { "cacheentryttl", eCmdHdlrInt, 0 },
+ { "cacheexpireinterval", eCmdHdlrInt, 0 }
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ ,
+ { "filenamerules", eCmdHdlrArray, 0 },
+ { "containerrules", eCmdHdlrArray, 0 }
+#endif
+};
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+/* action (instance) parameters (v6 config format) */
+static struct cnfparamdescr actpdescr[] = {
+ { "kubernetesurl", eCmdHdlrString, 0 },
+ { "srcmetadatapath", eCmdHdlrString, 0 },
+ { "dstmetadatapath", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "allowunsignedcerts", eCmdHdlrBinary, 0 },
+ { "skipverifyhost", eCmdHdlrBinary, 0 },
+ { "token", eCmdHdlrString, 0 },
+ { "tokenfile", eCmdHdlrString, 0 },
+ { "annotation_match", eCmdHdlrArray, 0 },
+ { "de_dot", eCmdHdlrBinary, 0 },
+ { "de_dot_separator", eCmdHdlrString, 0 },
+ { "filenamerulebase", eCmdHdlrString, 0 },
+ { "containerrulebase", eCmdHdlrString, 0 },
+ { "busyretryinterval", eCmdHdlrInt, 0 },
+ { "sslpartialchain", eCmdHdlrBinary, 0 },
+ { "cacheentryttl", eCmdHdlrInt, 0 },
+ { "cacheexpireinterval", eCmdHdlrInt, 0 }
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ ,
+ { "filenamerules", eCmdHdlrArray, 0 },
+ { "containerrules", eCmdHdlrArray, 0 }
+#endif
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */
+
+static void free_annotationmatch(annotation_match_t *match) {
+ if (match) {
+ for(int ii = 0 ; ii < match->nmemb; ++ii) {
+ if (match->patterns)
+ free(match->patterns[ii]);
+ if (match->regexps)
+ regexp.regfree(&match->regexps[ii]);
+ }
+ free(match->patterns);
+ match->patterns = NULL;
+ free(match->regexps);
+ match->regexps = NULL;
+ match->nmemb = 0;
+ }
+}
+
+static int init_annotationmatch(annotation_match_t *match, struct cnfarray *ar) {
+ DEFiRet;
+
+ match->nmemb = ar->nmemb;
+ CHKmalloc(match->patterns = calloc(sizeof(uchar*), match->nmemb));
+ CHKmalloc(match->regexps = calloc(sizeof(regex_t), match->nmemb));
+ for(int jj = 0; jj < ar->nmemb; ++jj) {
+ int rexret = 0;
+ match->patterns[jj] = (uchar*)es_str2cstr(ar->arr[jj], NULL);
+ rexret = regexp.regcomp(&match->regexps[jj],
+ (char *)match->patterns[jj], REG_EXTENDED|REG_NOSUB);
+ if (0 != rexret) {
+ char errMsg[512];
+ regexp.regerror(rexret, &match->regexps[jj], errMsg, sizeof(errMsg));
+ iRet = RS_RET_CONFIG_ERROR;
+ LogError(0, iRet,
+ "error: could not compile annotation_match string [%s]"
+ " into an extended regexp - %d: %s\n",
+ match->patterns[jj], rexret, errMsg);
+ break;
+ }
+ }
+finalize_it:
+ if (iRet)
+ free_annotationmatch(match);
+ RETiRet;
+}
+
+static int copy_annotationmatch(annotation_match_t *src, annotation_match_t *dest) {
+ DEFiRet;
+
+ dest->nmemb = src->nmemb;
+ CHKmalloc(dest->patterns = malloc(sizeof(uchar*) * dest->nmemb));
+ CHKmalloc(dest->regexps = calloc(sizeof(regex_t), dest->nmemb));
+ for(int jj = 0 ; jj < src->nmemb ; ++jj) {
+ CHKmalloc(dest->patterns[jj] = (uchar*)strdup((char *)src->patterns[jj]));
+ /* assumes was already successfully compiled */
+ regexp.regcomp(&dest->regexps[jj], (char *)dest->patterns[jj], REG_EXTENDED|REG_NOSUB);
+ }
+finalize_it:
+ if (iRet)
+ free_annotationmatch(dest);
+ RETiRet;
+}
+
+/* takes a hash of annotations and returns another json object hash containing only the
+ * keys that match - this logic is taken directly from fluent-plugin-kubernetes_metadata_filter
+ * except that we do not add the key multiple times to the object to be returned
+ */
+static struct json_object *match_annotations(annotation_match_t *match,
+ struct json_object *annotations) {
+ struct json_object *ret = NULL;
+
+ for (int jj = 0; jj < match->nmemb; ++jj) {
+ struct json_object_iterator it = json_object_iter_begin(annotations);
+ struct json_object_iterator itEnd = json_object_iter_end(annotations);
+ for (;!json_object_iter_equal(&it, &itEnd); json_object_iter_next(&it)) {
+ const char *const key = json_object_iter_peek_name(&it);
+ if (!ret || !fjson_object_object_get_ex(ret, key, NULL)) {
+ if (!regexp.regexec(&match->regexps[jj], key, 0, NULL, 0)) {
+ if (!ret) {
+ ret = json_object_new_object();
+ }
+ json_object_object_add(ret, key,
+ json_object_get(json_object_iter_peek_value(&it)));
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+/* This will take a hash of labels or annotations and will de_dot the keys.
+ * It will return a brand new hash. AFAICT, there is no safe way to
+ * iterate over the hash while modifying it in place.
+ */
+static struct json_object *de_dot_json_object(struct json_object *jobj,
+ const char *delim, size_t delim_len) {
+ struct json_object *ret = NULL;
+ struct json_object_iterator it = json_object_iter_begin(jobj);
+ struct json_object_iterator itEnd = json_object_iter_end(jobj);
+ es_str_t *new_es_key = NULL;
+ DEFiRet;
+
+ ret = json_object_new_object();
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ const char *const key = json_object_iter_peek_name(&it);
+ const char *cc = strstr(key, ".");
+ if (NULL == cc) {
+ json_object_object_add(ret, key,
+ json_object_get(json_object_iter_peek_value(&it)));
+ } else {
+ char *new_key = NULL;
+ const char *prevcc = key;
+ new_es_key = es_newStrFromCStr(key, (es_size_t)(cc-prevcc));
+ while (cc) {
+ if (es_addBuf(&new_es_key, (char *)delim, (es_size_t)delim_len))
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ cc += 1; /* one past . */
+ prevcc = cc; /* beginning of next substring */
+ if ((cc = strstr(prevcc, ".")) || (cc = strchr(prevcc, '\0'))) {
+ if (es_addBuf(&new_es_key, (char *)prevcc, (es_size_t)(cc-prevcc)))
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ if (!*cc)
+ cc = NULL; /* EOS - done */
+ }
+ }
+ new_key = es_str2cstr(new_es_key, NULL);
+ es_deleteStr(new_es_key);
+ new_es_key = NULL;
+ json_object_object_add(ret, new_key,
+ json_object_get(json_object_iter_peek_value(&it)));
+ free(new_key);
+ }
+ json_object_iter_next(&it);
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ json_object_put(ret);
+ ret = NULL;
+ }
+ if (new_es_key)
+ es_deleteStr(new_es_key);
+ return ret;
+}
+
+/* given a "metadata" object field, do
+ * - make sure "annotations" field has only the matching keys
+ * - de_dot the "labels" and "annotations" fields keys
+ * This modifies the jMetadata object in place
+ */
+static void parse_labels_annotations(struct json_object *jMetadata,
+ annotation_match_t *match, sbool de_dot,
+ const char *delim, size_t delim_len) {
+ struct json_object *jo = NULL;
+
+ if (fjson_object_object_get_ex(jMetadata, "annotations", &jo)) {
+ if ((jo = match_annotations(match, jo)))
+ json_object_object_add(jMetadata, "annotations", jo);
+ else
+ json_object_object_del(jMetadata, "annotations");
+ }
+ /* dedot labels and annotations */
+ if (de_dot) {
+ struct json_object *jo2 = NULL;
+ if (fjson_object_object_get_ex(jMetadata, "annotations", &jo)) {
+ if ((jo2 = de_dot_json_object(jo, delim, delim_len))) {
+ json_object_object_add(jMetadata, "annotations", jo2);
+ }
+ }
+ if (fjson_object_object_get_ex(jMetadata, "labels", &jo)) {
+ if ((jo2 = de_dot_json_object(jo, delim, delim_len))) {
+ json_object_object_add(jMetadata, "labels", jo2);
+ }
+ }
+ }
+}
+
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+static int array_to_rules(struct cnfarray *ar, char **rules) {
+ DEFiRet;
+ es_str_t *tmpstr = NULL;
+ es_size_t size = 0;
+
+ if (rules == NULL)
+ FINALIZE;
+ *rules = NULL;
+ if (!ar->nmemb)
+ FINALIZE;
+ for (int jj = 0; jj < ar->nmemb; jj++)
+ size += es_strlen(ar->arr[jj]);
+ if (!size)
+ FINALIZE;
+ CHKmalloc(tmpstr = es_newStr(size));
+ CHKiRet((es_addStr(&tmpstr, ar->arr[0])));
+ CHKiRet((es_addBufConstcstr(&tmpstr, "\n")));
+ for(int jj=1; jj < ar->nmemb; ++jj) {
+ CHKiRet((es_addStr(&tmpstr, ar->arr[jj])));
+ CHKiRet((es_addBufConstcstr(&tmpstr, "\n")));
+ }
+ CHKiRet((es_addBufConstcstr(&tmpstr, "\0")));
+ CHKmalloc(*rules = es_str2cstr(tmpstr, NULL));
+finalize_it:
+ if (tmpstr) {
+ es_deleteStr(tmpstr);
+ }
+ if (iRet != RS_RET_OK) {
+ free(*rules);
+ *rules = NULL;
+ }
+ RETiRet;
+}
+#endif
+
+/* callback for liblognorm error messages */
+static void
+errCallBack(void __attribute__((unused)) *cookie, const char *msg,
+ size_t __attribute__((unused)) lenMsg)
+{
+ LogError(0, RS_RET_ERR_LIBLOGNORM, "liblognorm error: %s", msg);
+}
+
+static rsRetVal
+set_lnctx(ln_ctx *ctxln, char *instRules, uchar *instRulebase, char *modRules, uchar *modRulebase)
+{
+ DEFiRet;
+ if (ctxln == NULL)
+ FINALIZE;
+ CHKmalloc(*ctxln = ln_initCtx());
+ ln_setErrMsgCB(*ctxln, errCallBack, NULL);
+ if(instRules) {
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ if(ln_loadSamplesFromString(*ctxln, instRules) !=0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' "
+ "could not be loaded", instRules);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+#else
+ (void)instRules;
+#endif
+ } else if(instRulebase) {
+ if(ln_loadSamples(*ctxln, (char*) instRulebase) != 0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' "
+ "could not be loaded", instRulebase);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ } else if(modRules) {
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ if(ln_loadSamplesFromString(*ctxln, modRules) !=0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' "
+ "could not be loaded", modRules);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+#else
+ (void)modRules;
+#endif
+ } else if(modRulebase) {
+ if(ln_loadSamples(*ctxln, (char*) modRulebase) != 0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' "
+ "could not be loaded", modRulebase);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ }
+finalize_it:
+ if (iRet != RS_RET_OK){
+ ln_exitCtx(*ctxln);
+ *ctxln = NULL;
+ }
+ RETiRet;
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+ FILE *fp = NULL;
+ int ret;
+ char errStr[1024];
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "mmkubernetes: "
+ "error processing module config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for mmkubernetes:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ loadModConf->de_dot = DFLT_DE_DOT;
+ loadModConf->busyRetryInterval = DFLT_BUSY_RETRY_INTERVAL;
+ loadModConf->sslPartialChain = DFLT_SSL_PARTIAL_CHAIN;
+ loadModConf->cacheEntryTTL = DFLT_CACHE_ENTRY_TTL;
+ loadModConf->cacheExpireInterval = DFLT_CACHE_EXPIRE_INTERVAL;
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ } else if(!strcmp(modpblk.descr[i].name, "kubernetesurl")) {
+ free(loadModConf->kubernetesUrl);
+ loadModConf->kubernetesUrl = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "srcmetadatapath")) {
+ free(loadModConf->srcMetadataPath);
+ loadModConf->srcMetadataPath = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ /* todo: sanitize the path */
+ } else if(!strcmp(modpblk.descr[i].name, "dstmetadatapath")) {
+ free(loadModConf->dstMetadataPath);
+ loadModConf->dstMetadataPath = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ /* todo: sanitize the path */
+ } else if(!strcmp(modpblk.descr[i].name, "tls.cacert")) {
+ free(loadModConf->caCertFile);
+ loadModConf->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->caCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.cacert' file %s couldn't be accessed: %s\n",
+ loadModConf->caCertFile, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "tls.mycert")) {
+ free(loadModConf->myCertFile);
+ loadModConf->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ loadModConf->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "tls.myprivkey")) {
+ loadModConf->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ loadModConf->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "allowunsignedcerts")) {
+ loadModConf->allowUnsignedCerts = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "skipverifyhost")) {
+ loadModConf->skipVerifyHost = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "token")) {
+ free(loadModConf->token);
+ loadModConf->token = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "tokenfile")) {
+ free(loadModConf->tokenFile);
+ loadModConf->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->tokenFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: token file %s couldn't be accessed: %s\n",
+ loadModConf->tokenFile, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "annotation_match")) {
+ free_annotationmatch(&loadModConf->annotation_match);
+ if ((ret = init_annotationmatch(&loadModConf->annotation_match, pvals[i].val.d.ar)))
+ ABORT_FINALIZE(ret);
+ } else if(!strcmp(modpblk.descr[i].name, "de_dot")) {
+ loadModConf->de_dot = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "de_dot_separator")) {
+ free(loadModConf->de_dot_separator);
+ loadModConf->de_dot_separator = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ } else if(!strcmp(modpblk.descr[i].name, "filenamerules")) {
+ free(loadModConf->fnRules);
+ CHKiRet((array_to_rules(pvals[i].val.d.ar, &loadModConf->fnRules)));
+#endif
+ } else if(!strcmp(modpblk.descr[i].name, "filenamerulebase")) {
+ free(loadModConf->fnRulebase);
+ loadModConf->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->fnRulebase, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: filenamerulebase file %s couldn't be accessed: %s\n",
+ loadModConf->fnRulebase, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ } else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
+ free(loadModConf->contRules);
+ CHKiRet((array_to_rules(pvals[i].val.d.ar, &loadModConf->contRules)));
+#endif
+ } else if(!strcmp(modpblk.descr[i].name, "containerrulebase")) {
+ free(loadModConf->contRulebase);
+ loadModConf->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)loadModConf->contRulebase, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: containerrulebase file %s couldn't be accessed: %s\n",
+ loadModConf->contRulebase, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "busyretryinterval")) {
+ loadModConf->busyRetryInterval = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "sslpartialchain")) {
+#if defined(SUPPORT_SSL_PARTIAL_CHAIN)
+ loadModConf->sslPartialChain = pvals[i].val.d.n;
+#else
+ LogMsg(0, RS_RET_VALUE_NOT_IN_THIS_MODE, LOG_INFO,
+ "sslpartialchain is only supported for OpenSSL\n");
+#endif
+ } else if(!strcmp(modpblk.descr[i].name, "cacheentryttl")) {
+ loadModConf->cacheEntryTTL = pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "cacheexpireinterval")) {
+ loadModConf->cacheExpireInterval = pvals[i].val.d.n;
+ } else {
+ dbgprintf("mmkubernetes: program error, non-handled "
+ "param '%s' in module() block\n", modpblk.descr[i].name);
+ /* todo: error message? */
+ }
+ }
+
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ if (loadModConf->fnRules && loadModConf->fnRulebase) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: only 1 of filenamerules or filenamerulebase may be used");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if (loadModConf->contRules && loadModConf->contRulebase) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: only 1 of containerrules or containerrulebase may be used");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+#endif
+
+ if ((loadModConf->cacheExpireInterval > -1)) {
+ if ((loadModConf->cacheEntryTTL < 0)) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: cacheentryttl value [%d] is invalid - "
+ "value must be 0 or greater",
+ loadModConf->cacheEntryTTL);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ }
+
+ /* set defaults */
+ if(loadModConf->srcMetadataPath == NULL)
+ loadModConf->srcMetadataPath = (uchar *) strdup(DFLT_SRCMD_PATH);
+ if(loadModConf->dstMetadataPath == NULL)
+ loadModConf->dstMetadataPath = (uchar *) strdup(DFLT_DSTMD_PATH);
+ if(loadModConf->de_dot_separator == NULL)
+ loadModConf->de_dot_separator = (uchar *) strdup(DFLT_DE_DOT_SEPARATOR);
+ if(loadModConf->de_dot_separator)
+ loadModConf->de_dot_separator_len = strlen((const char *)loadModConf->de_dot_separator);
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ if (loadModConf->fnRules == NULL && loadModConf->fnRulebase == NULL)
+ loadModConf->fnRules = strdup(DFLT_FILENAME_LNRULES);
+ if (loadModConf->contRules == NULL && loadModConf->contRulebase == NULL)
+ loadModConf->contRules = strdup(DFLT_CONTAINER_LNRULES);
+#else
+ if (loadModConf->fnRulebase == NULL)
+ loadModConf->fnRulebase = (uchar *)strdup(DFLT_FILENAME_RULEBASE);
+ if (loadModConf->contRulebase == NULL)
+ loadModConf->contRulebase = (uchar *)strdup(DFLT_CONTAINER_RULEBASE);
+#endif
+ caches = calloc(1, sizeof(struct cache_s *));
+
+finalize_it:
+ if (fp)
+ fclose(fp);
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->kubernetesUrl);
+ msgPropDescrDestruct(pData->srcMetadataDescr);
+ free(pData->srcMetadataDescr);
+ free(pData->dstMetadataPath);
+ free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
+ free(pData->token);
+ free(pData->tokenFile);
+ free(pData->fnRules);
+ free(pData->fnRulebase);
+ ln_exitCtx(pData->fnCtxln);
+ free(pData->contRules);
+ free(pData->contRulebase);
+ ln_exitCtx(pData->contCtxln);
+ free_annotationmatch(&pData->annotation_match);
+ free(pData->de_dot_separator);
+ msgPropDescrDestruct(pData->contNameDescr);
+ free(pData->contNameDescr);
+ msgPropDescrDestruct(pData->contIdFullDescr);
+ free(pData->contIdFullDescr);
+ENDfreeInstance
+
+static size_t curlCB(char *data, size_t size, size_t nmemb, void *usrptr)
+{
+ DEFiRet;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *) usrptr;
+ char * buf;
+ size_t newlen;
+
+ newlen = pWrkrData->curlRplyLen + size * nmemb;
+ CHKmalloc(buf = realloc(pWrkrData->curlRply, newlen));
+ memcpy(buf + pWrkrData->curlRplyLen, data, size * nmemb);
+ pWrkrData->curlRply = buf;
+ pWrkrData->curlRplyLen = newlen;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ return 0;
+ }
+ return size * nmemb;
+}
+
+#if defined(SUPPORT_SSL_PARTIAL_CHAIN)
+static CURLcode set_ssl_partial_chain(CURL *curl, void *ssl_ctx, void *userptr)
+{
+ (void)userptr; /* currently unused */
+ CURLcode rv = CURLE_ABORTED_BY_CALLBACK;
+ X509_STORE *store = NULL;
+
+ store = SSL_CTX_get_cert_store((SSL_CTX *)ssl_ctx);
+ if(!store)
+ goto finalize_it;
+ if(!X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN))
+ goto finalize_it;
+ rv = CURLE_OK;
+finalize_it:
+ return rv;
+}
+#endif
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ CURL *ctx;
+ struct curl_slist *hdr = NULL;
+ char *tokenHdr = NULL;
+ FILE *fp = NULL;
+ char *token = NULL;
+ char *statsName = NULL;
+
+ CHKiRet(statsobj.Construct(&(pWrkrData->stats)));
+ if ((-1 == asprintf(&statsName, "mmkubernetes(%s)", pWrkrData->pData->kubernetesUrl)) ||
+ (!statsName)) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ CHKiRet(statsobj.SetName(pWrkrData->stats, (uchar *)statsName));
+ free(statsName);
+ statsName = NULL;
+ CHKiRet(statsobj.SetOrigin(pWrkrData->stats, UCHAR_CONSTANT("mmkubernetes")));
+ STATSCOUNTER_INIT(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("recordseen"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->k8sRecordSeen)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatasuccess"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataSuccess)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataNotFound, pWrkrData->mutNamespaceMetadataNotFound);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatanotfound"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataNotFound)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataBusy, pWrkrData->mutNamespaceMetadataBusy);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatabusy"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataBusy)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceMetadataError, pWrkrData->mutNamespaceMetadataError);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadataerror"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataError)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatasuccess"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataSuccess)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatanotfound"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataNotFound)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatabusy"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataBusy)));
+ STATSCOUNTER_INIT(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadataerror"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataError)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachenumentries"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheNumEntries)));
+ STATSCOUNTER_INIT(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachenumentries"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheNumEntries)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceCacheHits, pWrkrData->mutNamespaceCacheHits);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachehits"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheHits)));
+ STATSCOUNTER_INIT(pWrkrData->podCacheHits, pWrkrData->mutPodCacheHits);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachehits"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheHits)));
+ STATSCOUNTER_INIT(pWrkrData->namespaceCacheMisses, pWrkrData->mutNamespaceCacheMisses);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachemisses"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheMisses)));
+ STATSCOUNTER_INIT(pWrkrData->podCacheMisses, pWrkrData->mutPodCacheMisses);
+ CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachemisses"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheMisses)));
+ CHKiRet(statsobj.ConstructFinalize(pWrkrData->stats));
+
+ hdr = curl_slist_append(hdr, "Content-Type: text/json; charset=utf-8");
+ if (pWrkrData->pData->token) {
+ if ((-1 == asprintf(&tokenHdr, "Authorization: Bearer %s", pWrkrData->pData->token)) ||
+ (!tokenHdr)) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ } else if (pWrkrData->pData->tokenFile) {
+ struct stat statbuf;
+ fp = fopen((const char*)pWrkrData->pData->tokenFile, "r");
+ if (fp && !fstat(fileno(fp), &statbuf)) {
+ size_t bytesread;
+ CHKmalloc(token = malloc((statbuf.st_size+1)*sizeof(char)));
+ if (0 < (bytesread = fread(token, sizeof(char), statbuf.st_size, fp))) {
+ token[bytesread] = '\0';
+ if ((-1 == asprintf(&tokenHdr, "Authorization: Bearer %s", token)) ||
+ (!tokenHdr)) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ }
+ free(token);
+ token = NULL;
+ }
+ if (fp) {
+ fclose(fp);
+ fp = NULL;
+ }
+ }
+ if (tokenHdr) {
+ hdr = curl_slist_append(hdr, tokenHdr);
+ free(tokenHdr);
+ }
+ pWrkrData->curlHdr = hdr;
+ ctx = curl_easy_init();
+ curl_easy_setopt(ctx, CURLOPT_HTTPHEADER, hdr);
+ curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, curlCB);
+ curl_easy_setopt(ctx, CURLOPT_WRITEDATA, pWrkrData);
+ if(pWrkrData->pData->caCertFile)
+ curl_easy_setopt(ctx, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
+ if(pWrkrData->pData->myCertFile)
+ curl_easy_setopt(ctx, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
+ if(pWrkrData->pData->myPrivKeyFile)
+ curl_easy_setopt(ctx, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
+ if(pWrkrData->pData->allowUnsignedCerts)
+ curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 0);
+ if(pWrkrData->pData->skipVerifyHost)
+ curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYHOST, 0);
+#if defined(SUPPORT_SSL_PARTIAL_CHAIN)
+ if(pWrkrData->pData->sslPartialChain) {
+ curl_easy_setopt(ctx, CURLOPT_SSL_CTX_FUNCTION, set_ssl_partial_chain);
+ curl_easy_setopt(ctx, CURLOPT_SSL_CTX_DATA, NULL);
+ }
+#endif
+ pWrkrData->curlCtx = ctx;
+finalize_it:
+ free(token);
+ free(statsName);
+ if ((iRet != RS_RET_OK) && pWrkrData->stats) {
+ statsobj.Destruct(&(pWrkrData->stats));
+ }
+ if (fp) {
+ fclose(fp);
+ }
+ENDcreateWrkrInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ curl_easy_cleanup(pWrkrData->curlCtx);
+ curl_slist_free_all(pWrkrData->curlHdr);
+ statsobj.Destruct(&(pWrkrData->stats));
+ENDfreeWrkrInstance
+
+
+/* next function is work-around to avoid type-unsafe casts. It looks
+ * like not really needed in practice, but gcc 8 complains and doing
+ * it 100% correct for sure does not hurt ;-) -- rgerhards, 2018-07-19
+ */
+static void
+hashtable_json_object_put(void *jso)
+{
+ json_object_put((struct fjson_object *)jso);
+}
+
+static void
+cache_entry_free(struct cache_entry_s *cache_entry)
+{
+ if (NULL != cache_entry) {
+ if (cache_entry->data) {
+ hashtable_json_object_put(cache_entry->data);
+ cache_entry->data = NULL;
+ }
+ free(cache_entry);
+ }
+}
+
+static void
+cache_entry_free_raw(void *cache_entry_void)
+{
+ cache_entry_free((struct cache_entry_s *)cache_entry_void);
+}
+
+static struct cache_s *
+cacheNew(instanceData *pData)
+{
+ DEFiRet;
+ struct cache_s *cache = NULL;
+ time_t now;
+ int need_mutex_destroy = 0;
+
+ CHKmalloc(cache = (struct cache_s *)calloc(1, sizeof(struct cache_s)));
+ CHKmalloc(cache->cacheMtx = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)));
+ CHKmalloc(cache->mdHt = create_hashtable(100, hash_from_string,
+ key_equals_string, cache_entry_free_raw));
+ CHKmalloc(cache->nsHt = create_hashtable(100, hash_from_string,
+ key_equals_string, cache_entry_free_raw));
+ CHKiConcCtrl(pthread_mutex_init(cache->cacheMtx, NULL));
+ need_mutex_destroy = 1;
+ datetime.GetTime(&now);
+ cache->kbUrl = pData->kubernetesUrl;
+ cache->expirationTime = 0;
+ if (pData->cacheExpireInterval > -1)
+ cache->expirationTime = pData->cacheExpireInterval + pData->cacheEntryTTL + now;
+ cache->lastBusyTime = 0;
+ dbgprintf("mmkubernetes: created cache mdht [%p] nsht [%p]\n",
+ cache->mdHt, cache->nsHt);
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(errno, iRet, "mmkubernetes: cacheNew: unable to create metadata cache for %s",
+ pData->kubernetesUrl);
+ if (cache) {
+ if (cache->mdHt)
+ hashtable_destroy(cache->mdHt, 1);
+ if (cache->nsHt)
+ hashtable_destroy(cache->nsHt, 1);
+ if (cache->cacheMtx) {
+ if (need_mutex_destroy)
+ pthread_mutex_destroy(cache->cacheMtx);
+ free(cache->cacheMtx);
+ }
+ free(cache);
+ cache = NULL;
+ }
+ }
+ return cache;
+}
+
+
+static void cacheFree(struct cache_s *cache)
+{
+ hashtable_destroy(cache->mdHt, 1);
+ hashtable_destroy(cache->nsHt, 1);
+ pthread_mutex_destroy(cache->cacheMtx);
+ free(cache->cacheMtx);
+ free(cache);
+}
+
+/* must be called with cache->cacheMtx held */
+/* assumes caller has reference to jso (json_object_get or is a new object) */
+static struct cache_entry_s *cache_entry_new(time_t ttl, struct fjson_object *jso)
+{
+ DEFiRet;
+ struct cache_entry_s *cache_entry = NULL;
+
+ CHKmalloc(cache_entry = malloc(sizeof(struct cache_entry_s)));
+ cache_entry->ttl = ttl;
+ cache_entry->data = (void *)jso;
+finalize_it:
+ if (iRet) {
+ free(cache_entry);
+ cache_entry = NULL;
+ }
+ return cache_entry;
+}
+
+static int cache_delete_expired_entries(wrkrInstanceData_t *pWrkrData, int isnsmd, time_t now)
+{
+ struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt;
+ struct hashtable_itr *itr = NULL;
+ int more;
+
+ if ((pWrkrData->pData->cacheExpireInterval < 0) || (now < pWrkrData->pData->cache->expirationTime)) {
+ return 0; /* not enabled or not time yet */
+ }
+
+ /* set next expiration time */
+ pWrkrData->pData->cache->expirationTime = now + pWrkrData->pData->cacheExpireInterval;
+
+ if (hashtable_count(ht) < 1)
+ return 1; /* expire interval hit but nothing to do */
+
+ itr = hashtable_iterator(ht);
+ if (NULL == itr)
+ return 1; /* expire interval hit but nothing to do - err? */
+
+ do {
+ struct cache_entry_s *cache_entry = (struct cache_entry_s *)hashtable_iterator_value(itr);
+
+ if (now >= cache_entry->ttl) {
+ cache_entry_free(cache_entry);
+ if (isnsmd) {
+ STATSCOUNTER_DEC(pWrkrData->namespaceCacheNumEntries,
+ pWrkrData->mutNamespaceCacheNumEntries);
+ } else {
+ STATSCOUNTER_DEC(pWrkrData->podCacheNumEntries,
+ pWrkrData->mutPodCacheNumEntries);
+ }
+ more = hashtable_iterator_remove(itr);
+ } else {
+ more = hashtable_iterator_advance(itr);
+ }
+ } while (more);
+ free(itr);
+ dbgprintf("mmkubernetes: cache_delete_expired_entries: cleaned [%s] cache - size is now [%llu]\n",
+ isnsmd ? "namespace" : "pod",
+ isnsmd ? pWrkrData->namespaceCacheNumEntries : pWrkrData->podCacheNumEntries);
+ return 1;
+}
+
+/* must be called with cache->cacheMtx held */
+static struct fjson_object *
+cache_entry_get(wrkrInstanceData_t *pWrkrData,
+ int isnsmd, const char *key, time_t now)
+{
+ struct fjson_object *jso = NULL;
+ struct cache_entry_s *cache_entry = NULL;
+ int checkttl = 1;
+ struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt;
+
+ /* see if it is time for a general cache expiration */
+ if (cache_delete_expired_entries(pWrkrData, isnsmd, now))
+ checkttl = 0; /* no need to check ttl now */
+ cache_entry = (struct cache_entry_s *)hashtable_search(ht, (void *)key);
+ if (cache_entry && checkttl && (now >= cache_entry->ttl)) {
+ cache_entry = (struct cache_entry_s *)hashtable_remove(ht, (void *)key);
+ if (isnsmd) {
+ STATSCOUNTER_DEC(pWrkrData->namespaceCacheNumEntries,
+ pWrkrData->mutNamespaceCacheNumEntries);
+ } else {
+ STATSCOUNTER_DEC(pWrkrData->podCacheNumEntries,
+ pWrkrData->mutPodCacheNumEntries);
+ }
+ cache_entry_free(cache_entry);
+ cache_entry = NULL;
+ }
+ if (cache_entry) {
+ jso = (struct fjson_object *)cache_entry->data;
+ if (isnsmd) {
+ STATSCOUNTER_INC(pWrkrData->namespaceCacheHits,
+ pWrkrData->mutNamespaceCacheHits);
+ } else {
+ STATSCOUNTER_INC(pWrkrData->podCacheHits,
+ pWrkrData->mutPodCacheHits);
+ }
+ dbgprintf("mmkubernetes: cache_entry_get: cache hit for [%s] cache key [%s] - hits is now [%llu]\n",
+ isnsmd ? "namespace" : "pod", key,
+ isnsmd ? pWrkrData->namespaceCacheHits : pWrkrData->podCacheHits);
+ } else {
+ if (isnsmd) {
+ STATSCOUNTER_INC(pWrkrData->namespaceCacheMisses,
+ pWrkrData->mutNamespaceCacheMisses);
+ } else {
+ STATSCOUNTER_INC(pWrkrData->podCacheMisses,
+ pWrkrData->mutPodCacheMisses);
+ }
+ dbgprintf("mmkubernetes: cache_entry_get: cache miss for [%s] cache key [%s] - misses is now [%llu]\n",
+ isnsmd ? "namespace" : "pod", key,
+ isnsmd ? pWrkrData->namespaceCacheMisses : pWrkrData->podCacheMisses);
+ }
+
+ return jso;
+}
+
+/* must be called with cache->cacheMtx held */
+/* key is passed in - caller must copy or otherwise ensure it is ok to pass off
+ * ownership
+ */
+static rsRetVal
+cache_entry_add(wrkrInstanceData_t *pWrkrData,
+ int isnsmd, const char *key, struct fjson_object *jso, time_t now, const int bDupKey)
+{
+ DEFiRet;
+ struct cache_entry_s *cache_entry = NULL;
+ struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt;
+
+ /* see if it is time for a general cache expiration */
+ (void)cache_delete_expired_entries(pWrkrData, isnsmd, now);
+ CHKmalloc(cache_entry = cache_entry_new(now + pWrkrData->pData->cacheEntryTTL, jso));
+ if (cache_entry) {
+ if (!hashtable_insert(ht, (void *)(bDupKey ? strdup(key) : key), cache_entry))
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ if (isnsmd) {
+ STATSCOUNTER_INC(pWrkrData->namespaceCacheNumEntries,
+ pWrkrData->mutNamespaceCacheNumEntries);
+ } else {
+ STATSCOUNTER_INC(pWrkrData->podCacheNumEntries,
+ pWrkrData->mutPodCacheNumEntries);
+ }
+ cache_entry = NULL;
+ }
+finalize_it:
+ if (cache_entry)
+ cache_entry_free(cache_entry);
+ return iRet;
+}
+
+/* must be called with cache->cacheMtx held */
+static struct fjson_object *cache_entry_get_md(wrkrInstanceData_t *pWrkrData, const char *key, time_t now)
+{
+ return cache_entry_get(pWrkrData, 0, key, now);
+}
+
+/* must be called with cache->cacheMtx held */
+static struct fjson_object *cache_entry_get_nsmd(wrkrInstanceData_t *pWrkrData, const char *key, time_t now)
+{
+ return cache_entry_get(pWrkrData, 1, key, now);
+}
+
+/* must be called with cache->cacheMtx held */
+static rsRetVal cache_entry_add_md(wrkrInstanceData_t *pWrkrData, const char *key,
+ struct fjson_object *jso, time_t now)
+{
+ return cache_entry_add(pWrkrData, 0, key, jso, now, 0);
+}
+
+/* must be called with cache->cacheMtx held */
+static rsRetVal cache_entry_add_nsmd(wrkrInstanceData_t *pWrkrData, const char *key,
+ struct fjson_object *jso, time_t now)
+{
+ return cache_entry_add(pWrkrData, 1, key, jso, now, 1);
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+ FILE *fp = NULL;
+ char *rxstr = NULL;
+ char *srcMetadataPath = NULL;
+ char errStr[1024];
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmkubernetes)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "mmkubernetes: "
+ "error processing config parameters [action(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in mmkubernetes:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+
+ pData->de_dot = loadModConf->de_dot;
+ pData->allowUnsignedCerts = loadModConf->allowUnsignedCerts;
+ pData->skipVerifyHost = loadModConf->skipVerifyHost;
+ pData->busyRetryInterval = loadModConf->busyRetryInterval;
+ pData->sslPartialChain = loadModConf->sslPartialChain;
+ pData->cacheEntryTTL = loadModConf->cacheEntryTTL;
+ pData->cacheExpireInterval = loadModConf->cacheExpireInterval;
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ } else if(!strcmp(actpblk.descr[i].name, "kubernetesurl")) {
+ free(pData->kubernetesUrl);
+ pData->kubernetesUrl = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "srcmetadatapath")) {
+ msgPropDescrDestruct(pData->srcMetadataDescr);
+ free(pData->srcMetadataDescr);
+ CHKmalloc(pData->srcMetadataDescr = malloc(sizeof(msgPropDescr_t)));
+ srcMetadataPath = es_str2cstr(pvals[i].val.d.estr, NULL);
+ CHKiRet(msgPropDescrFill(pData->srcMetadataDescr, (uchar *)srcMetadataPath,
+ strlen(srcMetadataPath)));
+ /* todo: sanitize the path */
+ } else if(!strcmp(actpblk.descr[i].name, "dstmetadatapath")) {
+ free(pData->dstMetadataPath);
+ pData->dstMetadataPath = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ /* todo: sanitize the path */
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ free(pData->caCertFile);
+ pData->caCertFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->caCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->caCertFile, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
+ pData->allowUnsignedCerts = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "skipverifyhost")) {
+ pData->skipVerifyHost = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "token")) {
+ free(pData->token);
+ pData->token = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tokenfile")) {
+ free(pData->tokenFile);
+ pData->tokenFile = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->tokenFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: token file %s couldn't be accessed: %s\n",
+ pData->tokenFile, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "annotation_match")) {
+ free_annotationmatch(&pData->annotation_match);
+ if (RS_RET_OK != (iRet = init_annotationmatch(&pData->annotation_match, pvals[i].val.d.ar)))
+ ABORT_FINALIZE(iRet);
+ } else if(!strcmp(actpblk.descr[i].name, "de_dot")) {
+ pData->de_dot = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "de_dot_separator")) {
+ free(pData->de_dot_separator);
+ pData->de_dot_separator = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ } else if(!strcmp(modpblk.descr[i].name, "filenamerules")) {
+ free(pData->fnRules);
+ CHKiRet((array_to_rules(pvals[i].val.d.ar, &pData->fnRules)));
+#endif
+ } else if(!strcmp(modpblk.descr[i].name, "filenamerulebase")) {
+ free(pData->fnRulebase);
+ pData->fnRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->fnRulebase, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: filenamerulebase file %s couldn't be accessed: %s\n",
+ pData->fnRulebase, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ } else if(!strcmp(modpblk.descr[i].name, "containerrules")) {
+ free(pData->contRules);
+ CHKiRet((array_to_rules(pvals[i].val.d.ar, &pData->contRules)));
+#endif
+ } else if(!strcmp(modpblk.descr[i].name, "containerrulebase")) {
+ free(pData->contRulebase);
+ pData->contRulebase = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->contRulebase, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_NO_FILE_ACCESS;
+ LogError(0, iRet,
+ "error: containerrulebase file %s couldn't be accessed: %s\n",
+ pData->contRulebase, errStr);
+ ABORT_FINALIZE(iRet);
+ } else {
+ fclose(fp);
+ fp = NULL;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "busyretryinterval")) {
+ pData->busyRetryInterval = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "sslpartialchain")) {
+#if defined(SUPPORT_SSL_PARTIAL_CHAIN)
+ pData->sslPartialChain = pvals[i].val.d.n;
+#else
+ LogMsg(0, RS_RET_VALUE_NOT_IN_THIS_MODE, LOG_INFO,
+ "sslpartialchain is only supported for OpenSSL\n");
+#endif
+ } else if(!strcmp(actpblk.descr[i].name, "cacheentryttl")) {
+ pData->cacheEntryTTL = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "cacheexpireinterval")) {
+ pData->cacheExpireInterval = pvals[i].val.d.n;
+ } else {
+ dbgprintf("mmkubernetes: program error, non-handled "
+ "param '%s' in action() block\n", actpblk.descr[i].name);
+ /* todo: error message? */
+ }
+ }
+
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ if (pData->fnRules && pData->fnRulebase) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: only 1 of filenamerules or filenamerulebase may be used");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if (pData->contRules && pData->contRulebase) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: only 1 of containerrules or containerrulebase may be used");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+#endif
+ CHKiRet(set_lnctx(&pData->fnCtxln, pData->fnRules, pData->fnRulebase,
+ loadModConf->fnRules, loadModConf->fnRulebase));
+ CHKiRet(set_lnctx(&pData->contCtxln, pData->contRules, pData->contRulebase,
+ loadModConf->contRules, loadModConf->contRulebase));
+
+ if ((pData->cacheExpireInterval > -1)) {
+ if ((pData->cacheEntryTTL < 0)) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmkubernetes: cacheentryttl value [%d] is invalid - "
+ "value must be 0 or greater",
+ pData->cacheEntryTTL);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ }
+
+ if(pData->kubernetesUrl == NULL) {
+ if(loadModConf->kubernetesUrl == NULL) {
+ CHKmalloc(pData->kubernetesUrl = (uchar *) strdup(DFLT_KUBERNETES_URL));
+ } else {
+ CHKmalloc(pData->kubernetesUrl = (uchar *) strdup((char *) loadModConf->kubernetesUrl));
+ }
+ }
+ if(pData->srcMetadataDescr == NULL) {
+ CHKmalloc(pData->srcMetadataDescr = malloc(sizeof(msgPropDescr_t)));
+ CHKiRet(msgPropDescrFill(pData->srcMetadataDescr, loadModConf->srcMetadataPath,
+ strlen((char *)loadModConf->srcMetadataPath)));
+ }
+ if(pData->dstMetadataPath == NULL)
+ pData->dstMetadataPath = (uchar *) strdup((char *) loadModConf->dstMetadataPath);
+ if(pData->caCertFile == NULL && loadModConf->caCertFile)
+ pData->caCertFile = (uchar *) strdup((char *) loadModConf->caCertFile);
+ if(pData->myCertFile == NULL && loadModConf->myCertFile)
+ pData->myCertFile = (uchar *) strdup((char *) loadModConf->myCertFile);
+ if(pData->myPrivKeyFile == NULL && loadModConf->myPrivKeyFile)
+ pData->myPrivKeyFile = (uchar *) strdup((char *) loadModConf->myPrivKeyFile);
+ if(pData->token == NULL && loadModConf->token)
+ pData->token = (uchar *) strdup((char *) loadModConf->token);
+ if(pData->tokenFile == NULL && loadModConf->tokenFile)
+ pData->tokenFile = (uchar *) strdup((char *) loadModConf->tokenFile);
+ if(pData->de_dot_separator == NULL && loadModConf->de_dot_separator)
+ pData->de_dot_separator = (uchar *) strdup((char *) loadModConf->de_dot_separator);
+ if((pData->annotation_match.nmemb == 0) && (loadModConf->annotation_match.nmemb > 0))
+ copy_annotationmatch(&loadModConf->annotation_match, &pData->annotation_match);
+
+ if(pData->de_dot_separator)
+ pData->de_dot_separator_len = strlen((const char *)pData->de_dot_separator);
+
+ CHKmalloc(pData->contNameDescr = malloc(sizeof(msgPropDescr_t)));
+ CHKiRet(msgPropDescrFill(pData->contNameDescr, (uchar*) DFLT_CONTAINER_NAME,
+ strlen(DFLT_CONTAINER_NAME)));
+ CHKmalloc(pData->contIdFullDescr = malloc(sizeof(msgPropDescr_t)));
+ CHKiRet(msgPropDescrFill(pData->contIdFullDescr, (uchar*) DFLT_CONTAINER_ID_FULL,
+ strlen(DFLT_CONTAINER_NAME)));
+
+ /* get the cache for this url */
+ for(i = 0; caches[i] != NULL; i++) {
+ if(!strcmp((char *) pData->kubernetesUrl, (char *) caches[i]->kbUrl))
+ break;
+ }
+ if(caches[i] != NULL) {
+ pData->cache = caches[i];
+ } else {
+ CHKmalloc(pData->cache = cacheNew(pData));
+ struct cache_s **new_caches = realloc(caches, (i + 2) * sizeof(struct cache_s *));
+ CHKmalloc(new_caches);
+ caches = new_caches;
+ caches[i] = pData->cache;
+ caches[i + 1] = NULL;
+ }
+CODE_STD_FINALIZERnewActInst
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &actpblk);
+ if(fp)
+ fclose(fp);
+ free(rxstr);
+ free(srcMetadataPath);
+ENDnewActInst
+
+
+/* legacy config format is not supported */
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(strncmp((char *) p, ":mmkubernetes:", sizeof(":mmkubernetes:") - 1)) {
+ LogError(0, RS_RET_LEGA_ACT_NOT_SUPPORTED,
+ "mmkubernetes supports only v6+ config format, use: "
+ "action(type=\"mmkubernetes\" ...)");
+ }
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ int i;
+
+ free(pModConf->kubernetesUrl);
+ free(pModConf->srcMetadataPath);
+ free(pModConf->dstMetadataPath);
+ free(pModConf->caCertFile);
+ free(pModConf->myCertFile);
+ free(pModConf->myPrivKeyFile);
+ free(pModConf->token);
+ free(pModConf->tokenFile);
+ free(pModConf->de_dot_separator);
+ free(pModConf->fnRules);
+ free(pModConf->fnRulebase);
+ free(pModConf->contRules);
+ free(pModConf->contRulebase);
+ free_annotationmatch(&pModConf->annotation_match);
+ for(i = 0; caches[i] != NULL; i++) {
+ dbgprintf("mmkubernetes: freeing cache [%d] mdht [%p] nsht [%p]\n",
+ i, caches[i]->mdHt, caches[i]->nsHt);
+ cacheFree(caches[i]);
+ }
+ free(caches);
+ENDfreeCnf
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("mmkubernetes\n");
+ dbgprintf("\tkubernetesUrl='%s'\n", pData->kubernetesUrl);
+ dbgprintf("\tsrcMetadataPath='%s'\n", pData->srcMetadataDescr->name);
+ dbgprintf("\tdstMetadataPath='%s'\n", pData->dstMetadataPath);
+ dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
+ dbgprintf("\tallowUnsignedCerts='%d'\n", pData->allowUnsignedCerts);
+ dbgprintf("\tskipVerifyHost='%d'\n", pData->skipVerifyHost);
+ dbgprintf("\ttoken='%s'\n", pData->token);
+ dbgprintf("\ttokenFile='%s'\n", pData->tokenFile);
+ dbgprintf("\tde_dot='%d'\n", pData->de_dot);
+ dbgprintf("\tde_dot_separator='%s'\n", pData->de_dot_separator);
+ dbgprintf("\tfilenamerulebase='%s'\n", pData->fnRulebase);
+ dbgprintf("\tcontainerrulebase='%s'\n", pData->contRulebase);
+#if HAVE_LOADSAMPLESFROMSTRING == 1
+ dbgprintf("\tfilenamerules='%s'\n", pData->fnRules);
+ dbgprintf("\tcontainerrules='%s'\n", pData->contRules);
+#endif
+ dbgprintf("\tbusyretryinterval='%d'\n", pData->busyRetryInterval);
+ dbgprintf("\tcacheentryttl='%d'\n", pData->cacheEntryTTL);
+ dbgprintf("\tcacheexpireinterval='%d'\n", pData->cacheExpireInterval);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+static rsRetVal
+extractMsgMetadata(smsg_t *pMsg, instanceData *pData, struct json_object **json)
+{
+ DEFiRet;
+ uchar *filename = NULL, *container_name = NULL, *container_id_full = NULL;
+ rs_size_t fnLen, container_name_len, container_id_full_len;
+ unsigned short freeFn = 0, free_container_name = 0, free_container_id_full = 0;
+ int lnret;
+ struct json_object *cnid = NULL;
+
+ if (!json)
+ FINALIZE;
+ *json = NULL;
+ /* extract metadata from the CONTAINER_NAME field and see if CONTAINER_ID_FULL is present */
+ container_name = MsgGetProp(pMsg, NULL, pData->contNameDescr,
+ &container_name_len, &free_container_name, NULL);
+ container_id_full = MsgGetProp(
+ pMsg, NULL, pData->contIdFullDescr, &container_id_full_len, &free_container_id_full, NULL);
+
+ if (container_name && container_id_full && container_name_len && container_id_full_len) {
+ dbgprintf("mmkubernetes: CONTAINER_NAME: '%s' CONTAINER_ID_FULL: '%s'.\n",
+ container_name, container_id_full);
+ if ((lnret = ln_normalize(pData->contCtxln, (char*)container_name,
+ container_name_len, json))) {
+ if (LN_WRONGPARSER != lnret) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: error parsing container_name [%s]: [%d]",
+ container_name, lnret);
+
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* else assume parser didn't find a match and fall through */
+ } else if (fjson_object_object_get_ex(*json, "pod_name", NULL) &&
+ fjson_object_object_get_ex(*json, "namespace_name", NULL) &&
+ fjson_object_object_get_ex(*json, "container_name", NULL)) {
+ /* if we have fields for pod name, namespace name, container name,
+ * and container id, we are good to go */
+ /* add field for container id */
+ json_object_object_add(*json, "container_id",
+ json_object_new_string_len((const char *)container_id_full,
+ container_id_full_len));
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ }
+
+ /* extract metadata from the file name */
+ filename = MsgGetProp(pMsg, NULL, pData->srcMetadataDescr, &fnLen, &freeFn, NULL);
+ if((filename == NULL) || (fnLen == 0))
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+
+ dbgprintf("mmkubernetes: filename: '%s' len %d.\n", filename, fnLen);
+ if ((lnret = ln_normalize(pData->fnCtxln, (char*)filename, fnLen, json))) {
+ if (LN_WRONGPARSER != lnret) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: error parsing container_name [%s]: [%d]",
+ filename, lnret);
+
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ /* no match */
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ }
+ /* if we have fields for pod name, namespace name, container name,
+ * and container id, we are good to go */
+ if (fjson_object_object_get_ex(*json, "pod_name", NULL) &&
+ fjson_object_object_get_ex(*json, "namespace_name", NULL) &&
+ fjson_object_object_get_ex(*json, "container_name_and_id", &cnid)) {
+ /* parse container_name_and_id into container_name and container_id */
+ const char *container_name_and_id = json_object_get_string(cnid);
+ const char *last_dash = NULL;
+ if (container_name_and_id && (last_dash = strrchr(container_name_and_id, '-')) &&
+ *(last_dash + 1) && (last_dash != container_name_and_id)) {
+ json_object_object_add(*json, "container_name",
+ json_object_new_string_len(container_name_and_id,
+ (int)(last_dash-container_name_and_id)));
+ json_object_object_add(*json, "container_id",
+ json_object_new_string(last_dash + 1));
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ }
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+finalize_it:
+ if(freeFn)
+ free(filename);
+ if (free_container_name)
+ free(container_name);
+ if (free_container_id_full)
+ free(container_id_full);
+ if (iRet != RS_RET_OK) {
+ json_object_put(*json);
+ *json = NULL;
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+queryKB(wrkrInstanceData_t *pWrkrData, char *url, time_t now, struct json_object **rply)
+{
+ DEFiRet;
+ CURLcode ccode;
+ struct json_tokener *jt = NULL;
+ struct json_object *jo;
+ long resp_code = 400;
+
+ if (pWrkrData->pData->cache->lastBusyTime) {
+ now -= pWrkrData->pData->cache->lastBusyTime;
+ if (now < pWrkrData->pData->busyRetryInterval) {
+ LogMsg(0, RS_RET_RETRY, LOG_DEBUG,
+ "mmkubernetes: Waited [%ld] of [%d] seconds for the requested url [%s]\n",
+ now, pWrkrData->pData->busyRetryInterval, url);
+ ABORT_FINALIZE(RS_RET_RETRY);
+ } else {
+ LogMsg(0, RS_RET_OK, LOG_DEBUG,
+ "mmkubernetes: Cleared busy status after [%d] seconds - "
+ "will retry the requested url [%s]\n",
+ pWrkrData->pData->busyRetryInterval, url);
+ pWrkrData->pData->cache->lastBusyTime = 0;
+ }
+ }
+
+ /* query kubernetes for pod info */
+ ccode = curl_easy_setopt(pWrkrData->curlCtx, CURLOPT_URL, url);
+ if(ccode != CURLE_OK)
+ ABORT_FINALIZE(RS_RET_ERR);
+ if(CURLE_OK != (ccode = curl_easy_perform(pWrkrData->curlCtx))) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: failed to connect to [%s] - %d:%s\n",
+ url, ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ if(CURLE_OK != (ccode = curl_easy_getinfo(pWrkrData->curlCtx,
+ CURLINFO_RESPONSE_CODE, &resp_code))) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: could not get response code from query to [%s] - %d:%s\n",
+ url, ccode, curl_easy_strerror(ccode));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(resp_code == 401) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: Unauthorized: not allowed to view url - "
+ "check token/auth credentials [%s]\n",
+ url);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(resp_code == 403) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: Forbidden: no access - "
+ "check permissions to view url [%s]\n",
+ url);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(resp_code == 404) {
+ LogMsg(0, RS_RET_NOT_FOUND, LOG_INFO,
+ "mmkubernetes: Not Found: the resource does not exist at url [%s]\n",
+ url);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ if(resp_code == 429) {
+ if (pWrkrData->pData->busyRetryInterval) {
+ pWrkrData->pData->cache->lastBusyTime = now;
+ }
+
+ LogMsg(0, RS_RET_RETRY, LOG_INFO,
+ "mmkubernetes: Too Many Requests: the server is too heavily loaded "
+ "to provide the data for the requested url [%s]\n",
+ url);
+ ABORT_FINALIZE(RS_RET_RETRY);
+ }
+ if(resp_code != 200) {
+ LogMsg(0, RS_RET_ERR, LOG_ERR,
+ "mmkubernetes: server returned unexpected code [%ld] for url [%s]\n",
+ resp_code, url);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* parse retrieved data */
+ jt = json_tokener_new();
+ json_tokener_reset(jt);
+ jo = json_tokener_parse_ex(jt, pWrkrData->curlRply, pWrkrData->curlRplyLen);
+ json_tokener_free(jt);
+ if(!json_object_is_type(jo, json_type_object)) {
+ json_object_put(jo);
+ jo = NULL;
+ LogMsg(0, RS_RET_JSON_PARSE_ERR, LOG_INFO,
+ "mmkubernetes: unable to parse string as JSON:[%.*s]\n",
+ (int)pWrkrData->curlRplyLen, pWrkrData->curlRply);
+ ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
+ }
+
+ dbgprintf("mmkubernetes: queryKB reply:\n%s\n",
+ json_object_to_json_string_ext(jo, JSON_C_TO_STRING_PRETTY));
+
+ *rply = jo;
+
+finalize_it:
+ if(pWrkrData->curlRply != NULL) {
+ free(pWrkrData->curlRply);
+ pWrkrData->curlRply = NULL;
+ pWrkrData->curlRplyLen = 0;
+ }
+ RETiRet;
+}
+
+
+/* versions < 8.16.0 don't support BEGINdoAction_NoStrings */
+#if defined(BEGINdoAction_NoStrings)
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+#else
+BEGINdoAction
+ smsg_t *pMsg = (smsg_t*) ppString[0];
+#endif
+ const char *podName = NULL, *ns = NULL, *containerName = NULL,
+ *containerID = NULL;
+ char *mdKey = NULL;
+ struct json_object *jMetadata = NULL, *jMetadataCopy = NULL, *jMsgMeta = NULL,
+ *jo = NULL;
+ int add_pod_metadata = 1;
+ time_t now;
+
+CODESTARTdoAction
+ CHKiRet_Hdlr(extractMsgMetadata(pMsg, pWrkrData->pData, &jMsgMeta)) {
+ ABORT_FINALIZE((iRet == RS_RET_NOT_FOUND) ? RS_RET_OK : iRet);
+ }
+
+ datetime.GetTime(&now);
+ STATSCOUNTER_INC(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen);
+
+ if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo))
+ podName = json_object_get_string(jo);
+ if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo))
+ ns = json_object_get_string(jo);
+ if (fjson_object_object_get_ex(jMsgMeta, "container_name", &jo))
+ containerName = json_object_get_string(jo);
+ if (fjson_object_object_get_ex(jMsgMeta, "container_id", &jo))
+ containerID = json_object_get_string(jo);
+ assert(podName != NULL);
+ assert(ns != NULL);
+ assert(containerName != NULL);
+ assert(containerID != NULL);
+
+ dbgprintf("mmkubernetes:\n podName: '%s'\n namespace: '%s'\n containerName: '%s'\n"
+ " containerID: '%s'\n", podName, ns, containerName, containerID);
+
+ /* check cache for metadata */
+ if ((-1 == asprintf(&mdKey, "%s_%s_%s", ns, podName, containerName)) ||
+ (!mdKey)) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pthread_mutex_lock(pWrkrData->pData->cache->cacheMtx);
+ jMetadata = cache_entry_get_md(pWrkrData, mdKey, now);
+
+ if(jMetadata == NULL) {
+ char *url = NULL;
+ struct json_object *jReply = NULL, *jo2 = NULL, *jNsMeta = NULL, *jPodData = NULL;
+
+ /* check cache for namespace metadata */
+ jNsMeta = cache_entry_get_nsmd(pWrkrData, (const char *)ns, now);
+
+ if(jNsMeta == NULL) {
+ /* query kubernetes for namespace info */
+ /* todo: move url definitions elsewhere */
+ if ((-1 == asprintf(&url, "%s/api/v1/namespaces/%s",
+ (char *) pWrkrData->pData->kubernetesUrl, ns)) ||
+ (!url)) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ iRet = queryKB(pWrkrData, url, now, &jReply);
+ free(url);
+ if (iRet == RS_RET_NOT_FOUND) {
+ /* negative cache namespace - make a dummy empty namespace metadata object */
+ jNsMeta = json_object_new_object();
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataNotFound,
+ pWrkrData->mutNamespaceMetadataNotFound);
+ } else if (iRet == RS_RET_RETRY) {
+ /* server is busy - retry or error */
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataBusy,
+ pWrkrData->mutNamespaceMetadataBusy);
+ if (0 == pWrkrData->pData->busyRetryInterval) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ add_pod_metadata = 0; /* don't cache pod metadata either - retry both */
+ } else if (iRet != RS_RET_OK) {
+ /* one of many possible transient errors: apiserver error, network, config, auth.
+ * Instead of causing hard error and disabling this module, we can return
+ * basic namespace metadata that is extracted from container log file path.
+ * When transient error resolves, other metadata will become
+ * available. For a new a new pod whose metadata is not yet cached, this
+ * will allow 401, 403, 500, etc. return status from apiserver treated
+ * similar to 404 returns.
+ * */
+ jNsMeta = json_object_new_object();
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataError,
+ pWrkrData->mutNamespaceMetadataError);
+ } else if (fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) {
+ jNsMeta = json_object_get(jNsMeta);
+ parse_labels_annotations(jNsMeta, &pWrkrData->pData->annotation_match,
+ pWrkrData->pData->de_dot,
+ (const char *)pWrkrData->pData->de_dot_separator,
+ pWrkrData->pData->de_dot_separator_len);
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
+ pWrkrData->mutNamespaceMetadataSuccess);
+ } else {
+ /* namespace with no metadata??? */
+ LogMsg(0, RS_RET_ERR, LOG_INFO,
+ "mmkubernetes: namespace [%s] has no metadata!\n", ns);
+ /* negative cache namespace - make a dummy empty namespace metadata object */
+ jNsMeta = json_object_new_object();
+ STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess,
+ pWrkrData->mutNamespaceMetadataSuccess);
+ }
+
+ if(jNsMeta) {
+ if ((iRet = cache_entry_add_nsmd(pWrkrData, ns, jNsMeta, now))) {
+ ABORT_FINALIZE(iRet);
+ }
+ }
+ json_object_put(jReply);
+ jReply = NULL;
+ }
+
+ if ((-1 == asprintf(&url, "%s/api/v1/namespaces/%s/pods/%s",
+ (char *) pWrkrData->pData->kubernetesUrl, ns, podName)) ||
+ (!url)) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ iRet = queryKB(pWrkrData, url, now, &jReply);
+ free(url);
+ if (iRet == RS_RET_NOT_FOUND) {
+ /* negative cache pod - make a dummy empty pod metadata object */
+ iRet = RS_RET_OK;
+ STATSCOUNTER_INC(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound);
+ } else if (iRet == RS_RET_RETRY) {
+ /* server is busy - retry or error */
+ STATSCOUNTER_INC(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy);
+ if (0 == pWrkrData->pData->busyRetryInterval) {
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ add_pod_metadata = 0; /* do not cache so that we can retry */
+ iRet = RS_RET_OK;
+ } else if(iRet != RS_RET_OK) {
+ /* This is likely caused by transient apiserver errors: 401, 403, 500, etc.
+ * Treat it similar to 404 while returning file path based pod metadata.
+ * When transient error condition resolves, additional metadata will be
+ * available for events originating from a new pod whose metatadata is not
+ * yet cached.
+ * */
+ iRet = RS_RET_OK;
+ STATSCOUNTER_INC(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError);
+ } else {
+ STATSCOUNTER_INC(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess);
+ }
+
+ jo = json_object_new_object();
+ if(jNsMeta && fjson_object_object_get_ex(jNsMeta, "uid", &jo2))
+ json_object_object_add(jo, "namespace_id", json_object_get(jo2));
+ if(jNsMeta && fjson_object_object_get_ex(jNsMeta, "labels", &jo2))
+ json_object_object_add(jo, "namespace_labels", json_object_get(jo2));
+ if(jNsMeta && fjson_object_object_get_ex(jNsMeta, "annotations", &jo2))
+ json_object_object_add(jo, "namespace_annotations", json_object_get(jo2));
+ if(jNsMeta && fjson_object_object_get_ex(jNsMeta, "creationTimestamp", &jo2))
+ json_object_object_add(jo, "creation_timestamp", json_object_get(jo2));
+ if(fjson_object_object_get_ex(jReply, "metadata", &jPodData)) {
+ if(fjson_object_object_get_ex(jPodData, "uid", &jo2))
+ json_object_object_add(jo, "pod_id", json_object_get(jo2));
+ parse_labels_annotations(jPodData, &pWrkrData->pData->annotation_match,
+ pWrkrData->pData->de_dot,
+ (const char *)pWrkrData->pData->de_dot_separator,
+ pWrkrData->pData->de_dot_separator_len);
+ if(fjson_object_object_get_ex(jPodData, "annotations", &jo2))
+ json_object_object_add(jo, "annotations", json_object_get(jo2));
+ if(fjson_object_object_get_ex(jPodData, "labels", &jo2))
+ json_object_object_add(jo, "labels", json_object_get(jo2));
+ }
+ if(fjson_object_object_get_ex(jReply, "spec", &jPodData)) {
+ if(fjson_object_object_get_ex(jPodData, "nodeName", &jo2)) {
+ json_object_object_add(jo, "host", json_object_get(jo2));
+ }
+ }
+ json_object_put(jReply);
+ jReply = NULL;
+
+ if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo2))
+ json_object_object_add(jo, "pod_name", json_object_get(jo2));
+ if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo2))
+ json_object_object_add(jo, "namespace_name", json_object_get(jo2));
+ if (fjson_object_object_get_ex(jMsgMeta, "container_name", &jo2))
+ json_object_object_add(jo, "container_name", json_object_get(jo2));
+ json_object_object_add(jo, "master_url",
+ json_object_new_string((const char *)pWrkrData->pData->kubernetesUrl));
+ jMetadata = json_object_new_object();
+ json_object_object_add(jMetadata, "kubernetes", jo);
+ jo = json_object_new_object();
+ if (fjson_object_object_get_ex(jMsgMeta, "container_id", &jo2))
+ json_object_object_add(jo, "container_id", json_object_get(jo2));
+ json_object_object_add(jMetadata, "docker", jo);
+
+ if (add_pod_metadata) {
+ if ((iRet = cache_entry_add_md(pWrkrData, mdKey, jMetadata, now)))
+ ABORT_FINALIZE(iRet);
+ mdKey = NULL;
+ }
+ }
+
+ /* make a copy of the metadata for the msg to own */
+ /* todo: use json_object_deep_copy when implementation available in libfastjson */
+ /* yes, this is expensive - but there is no other way to make this thread safe - we
+ * can't allow the msg to have a shared pointer to an element inside the cache,
+ * outside of the cache lock
+ */
+ jMetadataCopy = json_tokener_parse(json_object_get_string(jMetadata));
+ if (!add_pod_metadata) {
+ /* jMetadata object was created from scratch and not cached */
+ json_object_put(jMetadata);
+ jMetadata = NULL;
+ }
+ pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx);
+ /* the +1 is there to skip the leading '$' */
+ msgAddJSON(pMsg, (uchar *) pWrkrData->pData->dstMetadataPath + 1, jMetadataCopy, 0, 0);
+
+finalize_it:
+ json_object_put(jMsgMeta);
+ free(mdKey);
+ENDdoAction
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+/* all the macros bellow have to be in a specific order */
+BEGINmodExit
+CODESTARTmodExit
+ curl_global_cleanup();
+
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(regexp, LM_REGEXP_FILENAME);
+ objRelease(statsobj, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmkubernetes: module compiled with rsyslog version %s.\n", VERSION);
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(regexp, LM_REGEXP_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ /* CURL_GLOBAL_ALL initializes more than is needed but the
+ * libcurl documentation discourages use of other values
+ */
+ curl_global_init(CURL_GLOBAL_ALL);
+ENDmodInit
diff --git a/contrib/mmrfc5424addhmac/Makefile.am b/contrib/mmrfc5424addhmac/Makefile.am
new file mode 100644
index 0000000..6567def
--- /dev/null
+++ b/contrib/mmrfc5424addhmac/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmrfc5424addhmac.la
+
+mmrfc5424addhmac_la_SOURCES = mmrfc5424addhmac.c
+mmrfc5424addhmac_la_CPPFLAGS = $(OPENSSL_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmrfc5424addhmac_la_LDFLAGS = -module -avoid-version
+mmrfc5424addhmac_la_LIBADD = $(OPENSSL_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/mmrfc5424addhmac/Makefile.in b/contrib/mmrfc5424addhmac/Makefile.in
new file mode 100644
index 0000000..b49dff5
--- /dev/null
+++ b/contrib/mmrfc5424addhmac/Makefile.in
@@ -0,0 +1,801 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmrfc5424addhmac
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+mmrfc5424addhmac_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_mmrfc5424addhmac_la_OBJECTS = \
+ mmrfc5424addhmac_la-mmrfc5424addhmac.lo
+mmrfc5424addhmac_la_OBJECTS = $(am_mmrfc5424addhmac_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 =
+mmrfc5424addhmac_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmrfc5424addhmac_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo
+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 = $(mmrfc5424addhmac_la_SOURCES)
+DIST_SOURCES = $(mmrfc5424addhmac_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmrfc5424addhmac.la
+mmrfc5424addhmac_la_SOURCES = mmrfc5424addhmac.c
+mmrfc5424addhmac_la_CPPFLAGS = $(OPENSSL_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmrfc5424addhmac_la_LDFLAGS = -module -avoid-version
+mmrfc5424addhmac_la_LIBADD = $(OPENSSL_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/mmrfc5424addhmac/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmrfc5424addhmac/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmrfc5424addhmac.la: $(mmrfc5424addhmac_la_OBJECTS) $(mmrfc5424addhmac_la_DEPENDENCIES) $(EXTRA_mmrfc5424addhmac_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmrfc5424addhmac_la_LINK) -rpath $(pkglibdir) $(mmrfc5424addhmac_la_OBJECTS) $(mmrfc5424addhmac_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmrfc5424addhmac_la-mmrfc5424addhmac.lo: mmrfc5424addhmac.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmrfc5424addhmac_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmrfc5424addhmac_la-mmrfc5424addhmac.lo -MD -MP -MF $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Tpo -c -o mmrfc5424addhmac_la-mmrfc5424addhmac.lo `test -f 'mmrfc5424addhmac.c' || echo '$(srcdir)/'`mmrfc5424addhmac.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Tpo $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmrfc5424addhmac.c' object='mmrfc5424addhmac_la-mmrfc5424addhmac.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) $(mmrfc5424addhmac_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmrfc5424addhmac_la-mmrfc5424addhmac.lo `test -f 'mmrfc5424addhmac.c' || echo '$(srcdir)/'`mmrfc5424addhmac.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmrfc5424addhmac/mmrfc5424addhmac.c b/contrib/mmrfc5424addhmac/mmrfc5424addhmac.c
new file mode 100644
index 0000000..b696ca1
--- /dev/null
+++ b/contrib/mmrfc5424addhmac/mmrfc5424addhmac.c
@@ -0,0 +1,382 @@
+/* mmrfc5424addhmac.c
+ * custom module: add hmac to RFC5424 messages
+ *
+ * Note on important design decision: This module is fully self-contained.
+ * Most importantly, it does not rely on mmpstrucdata to populate the
+ * structured data portion of the messages JSON. There are two reasons
+ * for this:
+ * 1. robustness
+ * - this guard against misconfiguration
+ * - it permits us to be more liberal in regard to malformed
+ * structured data
+ * - it permits us to handle border-cases (like duplicate
+ * SD-IDs) with much less complexity
+ * 2. performance
+ * With being "on the spot" of what we need we can reduce memory
+ * reads and writes. This is a considerable save if the JSON representation
+ * is not otherwise needed.
+ *
+ * Note that the recommended calling sequence if both of these modules
+ * are used is
+ *
+ * 1. mmrfc5424addhmac
+ * 2. mmpstrucdata
+ *
+ * This sequence permits mmpstrucdata to pick up the modifications we
+ * made in this module here.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <openssl/hmac.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmrfc5424addhmac")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ uchar *key;
+ int16_t keylen; /* cached length of key, to avoid recomputation */
+ uchar *sdid; /* SD-ID to be used to persist the hmac */
+ int16_t sdidLen;
+ const EVP_MD *algo;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "key", eCmdHdlrString, 1 },
+ { "hashfunction", eCmdHdlrString, 1 },
+ { "sd_id", eCmdHdlrGetWord, 1 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->key = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ char *ciphername;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmrfc5424addhmac)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->keylen = es_strlen(pvals[i].val.d.estr);
+ } else if(!strcmp(actpblk.descr[i].name, "hashfunction")) {
+ ciphername = es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->algo = EVP_get_digestbyname(ciphername);
+ if(pData->algo == NULL) {
+ LogError(0, RS_RET_CRY_INVLD_ALGO,
+ "hashFunction '%s' unknown to openssl - "
+ "cannot continue", ciphername);
+ free(ciphername);
+ ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO);
+ }
+ free(ciphername);
+ } else if(!strcmp(actpblk.descr[i].name, "sd_id")) {
+ pData->sdid = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->sdidLen = es_strlen(pvals[i].val.d.estr);
+ } else {
+ dbgprintf("mmrfc5424addhmac: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+/* turn the binary data in bin of length len into a
+ * printable hex string. "print" must be 2*len+1 (for \0)
+ */
+static void
+hexify(uchar *bin, int len, uchar *print)
+{
+ static const char hexchars[16] =
+ {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+ int iSrc, iDst;
+
+ for(iSrc = iDst = 0 ; iSrc < len ; ++iSrc) {
+ print[iDst++] = hexchars[bin[iSrc]>>4];
+ print[iDst++] = hexchars[bin[iSrc]&0x0f];
+ }
+ print[iDst] = '\0';
+}
+
+
+/* skip to end of current SD-ID. This function can be improved
+ * in regard to fully parsing based on RFC5424, HOWEVER, this would
+ * also reduce performance. So we consider the current implementation
+ * to be superior.
+ */
+static void
+skipSDID(uchar *sdbuf, int sdlen, int *rootIdx)
+{
+ int i;
+ i = *rootIdx;
+ while(i < sdlen) {
+ if(sdbuf[i] == ']') {
+ if(i > *rootIdx && sdbuf[i-1] == '\\') {
+ ; /* escaped, nothing to do! */
+ } else {
+ ++i; /* eat ']' */
+ break;
+ }
+ }
+ ++i;
+ }
+ *rootIdx = i;
+}
+
+static void
+getSDID(uchar *sdbuf, int sdlen, int *rootIdx, uchar *sdid)
+{
+ int i, j;
+ i = *rootIdx;
+ j = 0;
+
+ if(sdbuf[i] != '[') {
+ ++i;
+ goto done;
+ }
+
+ ++i;
+ while(i < sdlen && sdbuf[i] != '=' && sdbuf[i] != ' '
+ && sdbuf[i] != ']' && sdbuf[i] != '"') {
+ sdid[j++] = sdbuf[i++];
+ }
+done:
+ sdid[j] = '\0';
+ *rootIdx = i;
+}
+
+/* check if "our" hmac is already present */
+static sbool
+isHmacPresent(instanceData *pData, smsg_t *pMsg)
+{
+ uchar *sdbuf;
+ rs_size_t sdlen;
+ sbool found;
+ int i;
+ uchar sdid[33]; /* RFC-based size limit */
+
+ MsgGetStructuredData(pMsg, &sdbuf, &sdlen);
+ found = 0;
+
+ if(sdbuf[0] == '-') /* RFC: struc data is empty! */
+ goto done;
+
+ i = 0;
+ while(i < sdlen && !found) {
+ getSDID(sdbuf, sdlen, &i, sdid);
+ if(!strcmp((char*)pData->sdid, (char*)sdid)) {
+ found = 1;
+ break;
+ }
+ skipSDID(sdbuf, sdlen, &i);
+ }
+
+done:
+ return found;
+}
+
+static rsRetVal
+hashMsg(instanceData *pData, smsg_t *pMsg)
+{
+ uchar *pRawMsg;
+ int lenRawMsg;
+ uchar *sdbuf;
+ rs_size_t sdlen;
+ unsigned int hashlen;
+ uchar hash[EVP_MAX_MD_SIZE];
+ uchar hashPrintable[2*EVP_MAX_MD_SIZE+1];
+ uchar newsd[64*1024]; /* we assume this is sufficient... */
+ int lenNewsd;
+ DEFiRet;
+
+ MsgGetStructuredData(pMsg, &sdbuf, &sdlen);
+ getRawMsg(pMsg, &pRawMsg, &lenRawMsg);
+ HMAC(pData->algo, pData->key, pData->keylen,
+ pRawMsg, lenRawMsg, hash, &hashlen);
+ hexify(hash, hashlen, hashPrintable);
+ lenNewsd = snprintf((char*)newsd, sizeof(newsd), "[%s hash=\"%s\"]",
+ (char*)pData->sdid, (char*)hashPrintable);
+ MsgAddToStructuredData(pMsg, newsd, lenNewsd);
+ RETiRet;
+}
+
+
+BEGINdoAction
+ instanceData *pData = pWrkrData->pData;
+ smsg_t *pMsg;
+CODESTARTdoAction
+ pMsg = (smsg_t*) ppString[0];
+ if( msgGetProtocolVersion(pMsg) == MSG_RFC5424_PROTOCOL
+ && !isHmacPresent(pData, pMsg)) {
+ hashMsg(pData, pMsg);
+ } else {
+ if(Debug) {
+ uchar *pRawMsg;
+ int lenRawMsg;
+ getRawMsg(pMsg, &pRawMsg, &lenRawMsg);
+ dbgprintf("mmrfc5424addhmac: non-rfc5424 or HMAC already "
+ "present: %.256s\n", pRawMsg);
+ }
+ }
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ EVP_cleanup();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmrfc5424addhmac: module compiled with rsyslog version %s.\n", VERSION);
+ OpenSSL_add_all_digests();
+ENDmodInit
diff --git a/contrib/mmsequence/Makefile.am b/contrib/mmsequence/Makefile.am
new file mode 100644
index 0000000..543d6d8
--- /dev/null
+++ b/contrib/mmsequence/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmsequence.la
+
+mmsequence_la_SOURCES = mmsequence.c
+mmsequence_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmsequence_la_LDFLAGS = -module -avoid-version
+mmsequence_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/mmsequence/Makefile.in b/contrib/mmsequence/Makefile.in
new file mode 100644
index 0000000..00aadbd
--- /dev/null
+++ b/contrib/mmsequence/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmsequence
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmsequence_la_DEPENDENCIES =
+am_mmsequence_la_OBJECTS = mmsequence_la-mmsequence.lo
+mmsequence_la_OBJECTS = $(am_mmsequence_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 =
+mmsequence_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmsequence_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmsequence_la-mmsequence.Plo
+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 = $(mmsequence_la_SOURCES)
+DIST_SOURCES = $(mmsequence_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmsequence.la
+mmsequence_la_SOURCES = mmsequence.c
+mmsequence_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmsequence_la_LDFLAGS = -module -avoid-version
+mmsequence_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/mmsequence/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmsequence/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmsequence.la: $(mmsequence_la_OBJECTS) $(mmsequence_la_DEPENDENCIES) $(EXTRA_mmsequence_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmsequence_la_LINK) -rpath $(pkglibdir) $(mmsequence_la_OBJECTS) $(mmsequence_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmsequence_la-mmsequence.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmsequence_la-mmsequence.lo: mmsequence.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmsequence_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmsequence_la-mmsequence.lo -MD -MP -MF $(DEPDIR)/mmsequence_la-mmsequence.Tpo -c -o mmsequence_la-mmsequence.lo `test -f 'mmsequence.c' || echo '$(srcdir)/'`mmsequence.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmsequence_la-mmsequence.Tpo $(DEPDIR)/mmsequence_la-mmsequence.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmsequence.c' object='mmsequence_la-mmsequence.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) $(mmsequence_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmsequence_la-mmsequence.lo `test -f 'mmsequence.c' || echo '$(srcdir)/'`mmsequence.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmsequence_la-mmsequence.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmsequence_la-mmsequence.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmsequence/mmsequence.c b/contrib/mmsequence/mmsequence.c
new file mode 100644
index 0000000..78350a1
--- /dev/null
+++ b/contrib/mmsequence/mmsequence.c
@@ -0,0 +1,406 @@
+/* mmsequence.c
+ * Generate a number based on some sequence.
+ *
+ * Copyright 2013 pavel@levshin.spb.ru.
+ *
+ * Based on: mmcount.c
+ * Copyright 2013 Red Hat Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <time.h>
+#include <limits.h>
+#include <json.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "hashtable.h"
+
+#define JSON_VAR_NAME "$!mmsequence"
+
+enum mmSequenceModes {
+ mmSequenceRandom,
+ mmSequencePerInstance,
+ mmSequencePerKey
+};
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmsequence")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ enum mmSequenceModes mode;
+ int valueFrom;
+ int valueTo;
+ int step;
+ unsigned int seed;
+ int value;
+ char *pszKey;
+ char *pszVar;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "from", eCmdHdlrNonNegInt, 0 },
+ { "to", eCmdHdlrPositiveInt, 0 },
+ { "step", eCmdHdlrNonNegInt, 0 },
+ { "key", eCmdHdlrGetWord, 0 },
+ { "var", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* table for key-counter pairs */
+static struct hashtable *ght;
+static pthread_mutex_t ght_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_mutex_t inst_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->mode = mmSequencePerInstance;
+ pData->valueFrom = 0;
+ pData->valueTo = INT_MAX;
+ pData->step = 1;
+ pData->pszKey = (char*)"";
+ pData->pszVar = (char*)JSON_VAR_NAME;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ char *cstr;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmsequence)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "mode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random",
+ sizeof("random")-1)) {
+ pData->mode = mmSequenceRandom;
+ } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"instance",
+ sizeof("instance")-1)) {
+ pData->mode = mmSequencePerInstance;
+ } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"key",
+ sizeof("key")-1)) {
+ pData->mode = mmSequencePerKey;
+ } else {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_INVLD_MODE,
+ "mmsequence: invalid mode '%s' - ignored",
+ cstr);
+ free(cstr);
+ }
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "from")) {
+ pData->valueFrom = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "to")) {
+ pData->valueTo = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "step")) {
+ pData->step = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "var")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (strlen(cstr) < 3) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmsequence: valid variable name should be at least "
+ "3 symbols long, got %s", cstr);
+ free(cstr);
+ } else if (cstr[0] != '$') {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmsequence: valid variable name should start with $,"
+ "got %s", cstr);
+ free(cstr);
+ } else {
+ pData->pszVar = cstr;
+ }
+ continue;
+ }
+ dbgprintf("mmsequence: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ switch(pData->mode) {
+ case mmSequenceRandom:
+ pData->seed = (unsigned int)(intptr_t)pData ^ (unsigned int)time(NULL);
+ break;
+ case mmSequencePerInstance:
+ pData->value = pData->valueTo;
+ break;
+ case mmSequencePerKey:
+ if (pthread_mutex_lock(&ght_mutex)) {
+ DBGPRINTF("mmsequence: mutex lock has failed!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if (ght == NULL) {
+ if(NULL == (ght = create_hashtable(100, hash_from_string, key_equals_string, NULL))) {
+ pthread_mutex_unlock(&ght_mutex);
+ DBGPRINTF("mmsequence: error creating hash table!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ pthread_mutex_unlock(&ght_mutex);
+ break;
+ default:
+ LogError(0, RS_RET_INVLD_MODE,
+ "mmsequence: this mode is not currently implemented");
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+static int *
+getCounter(struct hashtable *ht, char *str, int initial) {
+ int *pCounter;
+ char *pStr;
+
+ pCounter = hashtable_search(ht, str);
+ if(pCounter) {
+ return pCounter;
+ }
+
+ /* counter is not found for the str, so add new entry and
+ return the counter */
+ if(NULL == (pStr = strdup(str))) {
+ DBGPRINTF("mmsequence: memory allocation for key failed\n");
+ return NULL;
+ }
+
+ if(NULL == (pCounter = (int*)malloc(sizeof(*pCounter)))) {
+ DBGPRINTF("mmsequence: memory allocation for value failed\n");
+ free(pStr);
+ return NULL;
+ }
+ *pCounter = initial;
+
+ if(!hashtable_insert(ht, pStr, pCounter)) {
+ DBGPRINTF("mmsequence: inserting element into hashtable failed\n");
+ free(pStr);
+ free(pCounter);
+ return NULL;
+ }
+ return pCounter;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ struct json_object *json;
+ int val = 0;
+ int *pCounter;
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+
+ switch(pData->mode) {
+ case mmSequenceRandom:
+ val = pData->valueFrom + (rand_r(&pData->seed) %
+ (pData->valueTo - pData->valueFrom));
+ break;
+ case mmSequencePerInstance:
+ if (!pthread_mutex_lock(&inst_mutex)) {
+ if (pData->value >= pData->valueTo - pData->step) {
+ pData->value = pData->valueFrom;
+ } else {
+ pData->value += pData->step;
+ }
+ val = pData->value;
+ pthread_mutex_unlock(&inst_mutex);
+ } else {
+ LogError(0, RS_RET_ERR,
+ "mmsequence: mutex lock has failed!");
+ }
+ break;
+ case mmSequencePerKey:
+ if (!pthread_mutex_lock(&ght_mutex)) {
+ pCounter = getCounter(ght, pData->pszKey, pData->valueTo);
+ if(pCounter) {
+ if (*pCounter >= pData->valueTo - pData->step
+ || *pCounter < pData->valueFrom ) {
+ *pCounter = pData->valueFrom;
+ } else {
+ *pCounter += pData->step;
+ }
+ val = *pCounter;
+ } else {
+ LogError(0, RS_RET_NOT_FOUND,
+ "mmsequence: unable to fetch the counter from hash");
+ }
+ pthread_mutex_unlock(&ght_mutex);
+ } else {
+ LogError(0, RS_RET_ERR,
+ "mmsequence: mutex lock has failed!");
+ }
+
+ break;
+ default:
+ LogError(0, RS_RET_NOT_IMPLEMENTED,
+ "mmsequence: this mode is not currently implemented");
+ }
+
+ /* finalize_it: */
+ json = json_object_new_int(val);
+ if (json == NULL) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED,
+ "mmsequence: unable to create JSON");
+ } else if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)pData->pszVar + 1, json, 0, 0)) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED,
+ "mmsequence: unable to pass out the value");
+ json_object_put(json);
+ }
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmsequence: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/contrib/mmtaghostname/Makefile.am b/contrib/mmtaghostname/Makefile.am
new file mode 100644
index 0000000..5ba01ae
--- /dev/null
+++ b/contrib/mmtaghostname/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmtaghostname.la
+
+mmtaghostname_la_SOURCES = mmtaghostname.c
+mmtaghostname_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmtaghostname_la_LDFLAGS = -module -avoid-version
+mmtaghostname_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/mmtaghostname/Makefile.in b/contrib/mmtaghostname/Makefile.in
new file mode 100644
index 0000000..bb9ad5d
--- /dev/null
+++ b/contrib/mmtaghostname/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/mmtaghostname
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmtaghostname_la_DEPENDENCIES =
+am_mmtaghostname_la_OBJECTS = mmtaghostname_la-mmtaghostname.lo
+mmtaghostname_la_OBJECTS = $(am_mmtaghostname_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 =
+mmtaghostname_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmtaghostname_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo
+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 = $(mmtaghostname_la_SOURCES)
+DIST_SOURCES = $(mmtaghostname_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmtaghostname.la
+mmtaghostname_la_SOURCES = mmtaghostname.c
+mmtaghostname_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmtaghostname_la_LDFLAGS = -module -avoid-version
+mmtaghostname_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/mmtaghostname/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/mmtaghostname/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmtaghostname.la: $(mmtaghostname_la_OBJECTS) $(mmtaghostname_la_DEPENDENCIES) $(EXTRA_mmtaghostname_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmtaghostname_la_LINK) -rpath $(pkglibdir) $(mmtaghostname_la_OBJECTS) $(mmtaghostname_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmtaghostname_la-mmtaghostname.lo: mmtaghostname.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmtaghostname_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmtaghostname_la-mmtaghostname.lo -MD -MP -MF $(DEPDIR)/mmtaghostname_la-mmtaghostname.Tpo -c -o mmtaghostname_la-mmtaghostname.lo `test -f 'mmtaghostname.c' || echo '$(srcdir)/'`mmtaghostname.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmtaghostname_la-mmtaghostname.Tpo $(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmtaghostname.c' object='mmtaghostname_la-mmtaghostname.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) $(mmtaghostname_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmtaghostname_la-mmtaghostname.lo `test -f 'mmtaghostname.c' || echo '$(srcdir)/'`mmtaghostname.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/mmtaghostname/mmtaghostname.c b/contrib/mmtaghostname/mmtaghostname.c
new file mode 100644
index 0000000..ae72252
--- /dev/null
+++ b/contrib/mmtaghostname/mmtaghostname.c
@@ -0,0 +1,205 @@
+/* mmtaghostname.c
+ * This is a message modification module.
+ *
+ * The name of the module is inspired by the parser module pmnull
+ * Its objectives are closed to this parser but as a message modification
+ * it can be used in a different step of the message processing without
+ * interfering in the parser chain process and can be applied before or
+ * after parsing process.
+ *
+ * Its purposes are :
+ * - to add a tag on message produce by input module which does not provide
+ * a tag like imudp or imtcp. Useful when the tag is used for routing the
+ * message.
+ * - to force message hostname to the rsyslog valeur. The use case is
+ * application in auto-scaling systems (AWS) providing logs through udp/tcp
+ * were the name of the host is based on an ephemeral IPs with a short term
+ * meaning. In this situation rsyslog local host name is generally the
+ * auto-scaling name then logs produced by the application is affected to
+ * the application instead of the ephemeral VM.
+ *
+ *
+ * This file is a contribution of rsyslog.
+ *
+ * Author : Ph. Duveau <philippe.duveau@free.fr>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "dirty.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmtaghostname")
+
+/* internal structures */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+
+/* parser instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "tag", eCmdHdlrString, 0 },
+ { "forcelocalhostname", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+typedef struct _instanceData {
+ char *pszTag;
+ size_t lenTag;
+ int bForceLocalHostname;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+static const uchar *pszHostname = NULL;
+static size_t lenHostname = 0;
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("mmtaghostname:\n");
+ dbgprintf("\ttag='%s'\n", pData->pszTag);
+ dbgprintf("\tforce local hostname='%d'\n", pData->bForceLocalHostname);
+ENDdbgPrintInstInfo
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->pszTag = NULL;
+ pData->lenTag = 0;
+ pData->bForceLocalHostname = 0;
+ENDcreateInstance
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->pszTag);
+ENDfreeInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+BEGINnewActInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newParserInst (mmtaghostname)\n");
+
+ CHKiRet(createInstance(&pData));
+
+ if(lst == NULL)
+ FINALIZE; /* just set defaults, no param block! */
+
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("parser param blk in mmtaghostname:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "tag")) {
+ pData->pszTag = (char *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->lenTag = strlen(pData->pszTag);
+ } else if(!strcmp(parserpblk.descr[i].name, "forcelocalhostname")) {
+ pData->bForceLocalHostname = pvals[i].val.d.n;
+ } else {
+ dbgprintf("program error, non-handled param '%s'\n",
+ parserpblk.descr[i].name);
+ }
+ }
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+CODE_STD_FINALIZERnewActInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ENDnewActInst
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ instanceData *pData = pWrkrData->pData;
+CODESTARTdoAction
+ DBGPRINTF("Message will now be managed by mmtaghostname\n");
+ if(pData->pszTag != NULL) {
+ MsgSetTAG(pMsg, (uchar *)pData->pszTag, pData->lenTag);
+ }
+ if (pData->bForceLocalHostname) {
+ if (pszHostname == NULL) {
+ pszHostname = glbl.GetLocalHostName();
+ lenHostname = ustrlen(glbl.GetLocalHostName());
+ }
+ MsgSetHOSTNAME(pMsg, pszHostname, lenHostname);
+ DBGPRINTF("Message hostname forced to local\n");
+ }
+ENDdoAction
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/omamqp1/Makefile.am b/contrib/omamqp1/Makefile.am
new file mode 100644
index 0000000..8cc3b0b
--- /dev/null
+++ b/contrib/omamqp1/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omamqp1.la
+
+omamqp1_la_SOURCES = omamqp1.c
+omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(PROTON_CFLAGS)
+omamqp1_la_LDFLAGS = -module -avoid-version
+omamqp1_la_LIBADD = $(PROTON_LIBS) $(PTHREADS_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/omamqp1/Makefile.in b/contrib/omamqp1/Makefile.in
new file mode 100644
index 0000000..5b86d3a
--- /dev/null
+++ b/contrib/omamqp1/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omamqp1
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omamqp1_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_omamqp1_la_OBJECTS = omamqp1_la-omamqp1.lo
+omamqp1_la_OBJECTS = $(am_omamqp1_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 =
+omamqp1_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omamqp1_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omamqp1_la-omamqp1.Plo
+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 = $(omamqp1_la_SOURCES)
+DIST_SOURCES = $(omamqp1_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omamqp1.la
+omamqp1_la_SOURCES = omamqp1.c
+omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(PROTON_CFLAGS)
+omamqp1_la_LDFLAGS = -module -avoid-version
+omamqp1_la_LIBADD = $(PROTON_LIBS) $(PTHREADS_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/omamqp1/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omamqp1/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omamqp1.la: $(omamqp1_la_OBJECTS) $(omamqp1_la_DEPENDENCIES) $(EXTRA_omamqp1_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omamqp1_la_LINK) -rpath $(pkglibdir) $(omamqp1_la_OBJECTS) $(omamqp1_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omamqp1_la-omamqp1.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omamqp1_la-omamqp1.lo: omamqp1.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omamqp1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omamqp1_la-omamqp1.lo -MD -MP -MF $(DEPDIR)/omamqp1_la-omamqp1.Tpo -c -o omamqp1_la-omamqp1.lo `test -f 'omamqp1.c' || echo '$(srcdir)/'`omamqp1.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omamqp1_la-omamqp1.Tpo $(DEPDIR)/omamqp1_la-omamqp1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omamqp1.c' object='omamqp1_la-omamqp1.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) $(omamqp1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omamqp1_la-omamqp1.lo `test -f 'omamqp1.c' || echo '$(srcdir)/'`omamqp1.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omamqp1_la-omamqp1.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omamqp1_la-omamqp1.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omamqp1/omamqp1.c b/contrib/omamqp1/omamqp1.c
new file mode 100644
index 0000000..38d0022
--- /dev/null
+++ b/contrib/omamqp1/omamqp1.c
@@ -0,0 +1,921 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ * omamqp1.c
+ *
+ * This output plugin enables rsyslog to send messages to an AMQP 1.0 protocol
+ * compliant message bus.
+ *
+ * AMQP glue code Copyright (C) 2015-2016 Kenneth A. Giusti
+ * <kgiusti@gmail.com>
+ */
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+
+#include <pthread.h>
+#include <time.h>
+#include <proton/reactor.h>
+#include <proton/handlers.h>
+#include <proton/event.h>
+#include <proton/connection.h>
+#include <proton/session.h>
+#include <proton/link.h>
+#include <proton/delivery.h>
+#include <proton/message.h>
+#include <proton/transport.h>
+#include <proton/sasl.h>
+#include <proton/url.h>
+#include <proton/version.h>
+
+
+/* work-around issues in this contributed module */
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omamqp1")
+
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+
+/* Settings for the action */
+typedef struct _configSettings {
+ pn_url_t *url; /* address of message bus */
+ uchar *username; /* authentication credentials */
+ uchar *password;
+ uchar *target; /* endpoint for sent log messages */
+ uchar *templateName;
+ int bDisableSASL; /* do not enable SASL? 0-enable 1-disable */
+ int idleTimeout; /* disconnect idle connection (seconds) */
+ int reconnectDelay; /* pause before re-connecting (seconds) */
+ int maxRetries; /* drop unrouteable messages after maxRetries attempts */
+} configSettings_t;
+
+
+/* Control for communicating with the protocol engine thread */
+
+typedef enum { // commands sent to protocol thread
+ COMMAND_DONE, // marks command complete
+ COMMAND_SEND, // send a message to the message bus
+ COMMAND_IS_READY, // is the connection to the message bus active?
+ COMMAND_SHUTDOWN // cleanup and terminate protocol thread.
+} commands_t;
+
+
+typedef struct _threadIPC {
+ pthread_mutex_t lock;
+ pthread_cond_t condition;
+ commands_t command;
+ rsRetVal result; // of command
+ pn_message_t *message;
+ uint64_t tag; // per message id
+} threadIPC_t;
+
+
+/* per-instance data */
+
+typedef struct _instanceData {
+ configSettings_t config;
+ threadIPC_t ipc;
+ int bThreadRunning;
+ pthread_t thread_id;
+ pn_reactor_t *reactor;
+ pn_handler_t *handler;
+ pn_message_t *message;
+ int log_count;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+
+/* glue code */
+
+typedef void dispatch_t(pn_handler_t *, pn_event_t *, pn_event_type_t);
+
+static void _init_thread_ipc(threadIPC_t *pIPC);
+static void _clean_thread_ipc(threadIPC_t *ipc);
+static void _init_config_settings(configSettings_t *pConfig);
+static void _clean_config_settings(configSettings_t *pConfig);
+static rsRetVal _shutdown_thread(instanceData *pData);
+static rsRetVal _new_handler(pn_handler_t **handler,
+ pn_reactor_t *reactor,
+ dispatch_t *dispatcher,
+ configSettings_t *config,
+ threadIPC_t *ipc);
+static void _del_handler(pn_handler_t *handler);
+static rsRetVal _launch_protocol_thread(instanceData *pData);
+static rsRetVal _shutdown_thread(instanceData *pData);
+static rsRetVal _issue_command(threadIPC_t *ipc,
+ pn_reactor_t *reactor,
+ commands_t command,
+ pn_message_t *message);
+static void dispatcher(pn_handler_t *handler,
+ pn_event_t *event,
+ pn_event_type_t type);
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "host", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "target", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "username", eCmdHdlrGetWord, 0 },
+ { "password", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "idleTimeout", eCmdHdlrNonNegInt, 0 },
+ { "reconnectDelay", eCmdHdlrPositiveInt, 0 },
+ { "maxRetries", eCmdHdlrNonNegInt, 0 },
+ { "disableSASL", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+{
+ if (eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+}
+ENDisCompatibleWithFeature
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+{
+ memset(pData, 0, sizeof(instanceData));
+ _init_config_settings(&pData->config);
+ _init_thread_ipc(&pData->ipc);
+}
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+{
+ _shutdown_thread(pData);
+ _clean_config_settings(&pData->config);
+ _clean_thread_ipc(&pData->ipc);
+ if (pData->reactor) pn_reactor_free(pData->reactor);
+ if (pData->handler) pn_handler_free(pData->handler);
+ if (pData->message) pn_message_free(pData->message);
+}
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+{
+ configSettings_t *cfg = &pData->config;
+ dbgprintf("omamqp1:\n");
+ dbgprintf(" host=%s\n", pn_url_str(cfg->url));
+ dbgprintf(" username=%s\n", cfg->username);
+ //dbgprintf(" password=%s\n", pData->password);
+ dbgprintf(" target=%s\n", cfg->target);
+ dbgprintf(" template=%s\n", cfg->templateName);
+ dbgprintf(" disableSASL=%d\n", cfg->bDisableSASL);
+ dbgprintf(" idleTimeout=%d\n", cfg->idleTimeout);
+ dbgprintf(" reconnectDelay=%d\n", cfg->reconnectDelay);
+ dbgprintf(" maxRetries=%d\n", cfg->maxRetries);
+ dbgprintf(" running=%d\n", pData->bThreadRunning);
+}
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+{
+ // is the link active?
+ instanceData *pData = pWrkrData->pData;
+ iRet = _issue_command(&pData->ipc, pData->reactor, COMMAND_IS_READY, NULL);
+}
+ENDtryResume
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+{
+ DBGPRINTF("omamqp1: beginTransaction\n");
+ instanceData *pData = pWrkrData->pData;
+ pData->log_count = 0;
+ if (pData->message) pn_message_free(pData->message);
+ pData->message = pn_message();
+ CHKmalloc(pData->message);
+ pn_data_t *body = pn_message_body(pData->message);
+ pn_data_put_list(body);
+ pn_data_enter(body);
+}
+finalize_it:
+ENDbeginTransaction
+
+
+BEGINdoAction
+CODESTARTdoAction
+{
+ DBGPRINTF("omamqp1: doAction\n");
+ instanceData *pData = pWrkrData->pData;
+ if (!pData->message) ABORT_FINALIZE(RS_RET_OK);
+ pn_bytes_t msg = pn_bytes(strlen((const char *)ppString[0]),
+ (const char *)ppString[0]);
+ pn_data_t *body = pn_message_body(pData->message);
+ pn_data_put_string(body, msg);
+ pData->log_count++;
+ iRet = RS_RET_DEFER_COMMIT;
+}
+finalize_it:
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+{
+ DBGPRINTF("omamqp1: endTransaction\n");
+ instanceData *pData = pWrkrData->pData;
+ if (!pData->message) ABORT_FINALIZE(RS_RET_OK);
+ pn_data_t *body = pn_message_body(pData->message);
+ pn_data_exit(body);
+ pn_message_t *message = pData->message;
+ pData->message = NULL;
+ if (pData->log_count > 0) {
+ DBGPRINTF("omamqp1: sending [%d] records\n", pData->log_count);
+ CHKiRet(_issue_command(&pData->ipc, pData->reactor, COMMAND_SEND, message));
+ } else {
+ DBGPRINTF("omamqp1: no log messages to send\n");
+ pn_message_free(message);
+ }
+}
+finalize_it:
+ENDendTransaction
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ configSettings_t *cs;
+CODESTARTnewActInst
+{
+ if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ cs = &pData->config;
+
+ CODE_STD_STRING_REQUESTnewActInst(1);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(actpblk.descr[i].name, "host")) {
+ char *u = es_str2cstr(pvals[i].val.d.estr, NULL);
+ cs->url = pn_url_parse(u);
+ if (!cs->url) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR, "omamqp1: Invalid host URL configured: '%s'", u);
+ free(u);
+ ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR);
+ }
+ free(u);
+ } else if (!strcmp(actpblk.descr[i].name, "template")) {
+ cs->templateName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "target")) {
+ cs->target = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "username")) {
+ cs->username = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "password")) {
+ cs->password = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "reconnectDelay")) {
+ cs->reconnectDelay = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "idleTimeout")) {
+ cs->idleTimeout = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "maxRetries")) {
+ cs->maxRetries = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "disableSASL")) {
+ cs->bDisableSASL = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("omamqp1: program error, unrecognized param '%s', ignored.\n",
+ actpblk.descr[i].name);
+ }
+ }
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((cs->templateName == NULL)
+ ? "RSYSLOG_FileFormat" : (char*)cs->templateName), OMSR_NO_RQD_TPL_OPTS));
+
+ // once configuration is known, start the protocol engine thread
+ pData->reactor = pn_reactor();
+ CHKmalloc(pData->reactor);
+ CHKiRet(_new_handler(&pData->handler, pData->reactor, dispatcher, &pData->config, &pData->ipc));
+ CHKiRet(_launch_protocol_thread(pData));
+}
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+ CODESTARTqueryEtryPt
+ CODEqueryEtryPt_STD_OMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ CODEqueryEtryPt_TXIF_OMOD_QUERIES /* use transaction interface */
+ CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+{
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current
+ interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("omamqp1: module compiled with rsyslog version %s.\n", VERSION);
+ DBGPRINTF("omamqp1: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
+}
+ENDmodInit
+
+
+///////////////////////////////////////
+// All the Proton-specific glue code //
+///////////////////////////////////////
+
+
+/* state maintained by the protocol thread */
+
+typedef struct {
+ const configSettings_t *config;
+ threadIPC_t *ipc;
+ pn_reactor_t *reactor; // AMQP 1.0 protocol engine
+ pn_connection_t *conn;
+ pn_link_t *sender;
+ pn_delivery_t *delivery;
+ char *encode_buffer;
+ size_t buffer_size;
+ uint64_t tag;
+ int msgs_sent;
+ int msgs_settled;
+ int retries;
+ sbool stopped;
+} protocolState_t;
+
+// protocolState_t is embedded in the engine handler
+#define PROTOCOL_STATE(eh) ((protocolState_t *) pn_handler_mem(eh))
+
+
+static void _init_config_settings(configSettings_t *pConfig)
+{
+ memset(pConfig, 0, sizeof(configSettings_t));
+ pConfig->reconnectDelay = 5;
+ pConfig->maxRetries = 10;
+}
+
+
+static void _clean_config_settings(configSettings_t *pConfig)
+{
+ if (pConfig->url) pn_url_free(pConfig->url);
+ if (pConfig->username) free(pConfig->username);
+ if (pConfig->password) free(pConfig->password);
+ if (pConfig->target) free(pConfig->target);
+ if (pConfig->templateName) free(pConfig->templateName);
+ memset(pConfig, 0, sizeof(configSettings_t));
+}
+
+
+static void _init_thread_ipc(threadIPC_t *pIPC)
+{
+ memset(pIPC, 0, sizeof(threadIPC_t));
+ pthread_mutex_init(&pIPC->lock, NULL);
+ pthread_cond_init(&pIPC->condition, NULL);
+ pIPC->command = COMMAND_DONE;
+ pIPC->result = RS_RET_OK;
+}
+
+static void _clean_thread_ipc(threadIPC_t *ipc)
+{
+ pthread_cond_destroy(&ipc->condition);
+ pthread_mutex_destroy(&ipc->lock);
+}
+
+
+// create a new handler for the engine and set up the protocolState
+static rsRetVal _new_handler(pn_handler_t **handler,
+ pn_reactor_t *reactor,
+ dispatch_t *dispatch,
+ configSettings_t *config,
+ threadIPC_t *ipc)
+{
+ DEFiRet;
+ *handler = pn_handler_new(dispatch, sizeof(protocolState_t), _del_handler);
+ CHKmalloc(*handler);
+ pn_handler_add(*handler, pn_handshaker());
+ protocolState_t *pState = PROTOCOL_STATE(*handler);
+ memset(pState, 0, sizeof(protocolState_t));
+ pState->buffer_size = 64; // will grow if not enough
+ pState->encode_buffer = (char *)malloc(pState->buffer_size);
+ CHKmalloc(pState->encode_buffer);
+ pState->reactor = reactor;
+ pState->stopped = false;
+ // these are _references_, don't free them:
+ pState->config = config;
+ pState->ipc = ipc;
+
+finalize_it:
+ RETiRet;
+}
+
+
+// in case existing buffer too small
+static rsRetVal _grow_buffer(protocolState_t *pState)
+{
+ DEFiRet;
+ pState->buffer_size *= 2;
+ free(pState->encode_buffer);
+ pState->encode_buffer = (char *)malloc(pState->buffer_size);
+ CHKmalloc(pState->encode_buffer);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* release the pn_handler_t instance. Do not call this directly,
+ * it will be called by the reactor when all references to the
+ * handler have been released.
+ */
+static void _del_handler(pn_handler_t *handler)
+{
+ protocolState_t *pState = PROTOCOL_STATE(handler);
+ if (pState->encode_buffer) free(pState->encode_buffer);
+}
+
+
+// Close the sender and its parent session and connection
+static void _close_connection(protocolState_t *ps)
+{
+ if (ps->sender) {
+ pn_link_close(ps->sender);
+ pn_session_close(pn_link_session(ps->sender));
+ }
+ if (ps->conn) pn_connection_close(ps->conn);
+}
+
+static void _abort_command(protocolState_t *ps)
+{
+ threadIPC_t *ipc = ps->ipc;
+
+ pthread_mutex_lock(&ipc->lock);
+ switch (ipc->command) {
+ case COMMAND_SEND:
+ dbgprintf("omamqp1: aborted the message send in progress\n");
+ CASE_FALLTHROUGH
+ case COMMAND_IS_READY:
+ ipc->result = RS_RET_SUSPENDED;
+ ipc->command = COMMAND_DONE;
+ pthread_cond_signal(&ipc->condition);
+ break;
+ case COMMAND_SHUTDOWN: // cannot be aborted
+ case COMMAND_DONE:
+ break;
+ }
+ pthread_mutex_unlock(&ipc->lock);
+}
+
+
+// log a protocol error received from the message bus
+static void _log_error(const char *message, pn_condition_t *cond)
+{
+ const char *name = pn_condition_get_name(cond);
+ const char *desc = pn_condition_get_description(cond);
+ dbgprintf("omamqp1: %s %s:%s\n",
+ message,
+ (name) ? name : "<no name>",
+ (desc) ? desc : "<no description>");
+}
+
+
+/* is the link ready to send messages? */
+static sbool _is_ready(pn_link_t *link)
+{
+ return (link
+ && pn_link_state(link) == (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE)
+ && pn_link_credit(link) > 0);
+}
+
+
+/* Process each event emitted by the protocol engine */
+static void dispatcher(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type)
+{
+ protocolState_t *ps = PROTOCOL_STATE(handler);
+ const configSettings_t *cfg = ps->config;
+
+ //DBGPRINTF("omamqp1: Event received: %s\n", pn_event_type_name(type));
+
+ switch (type) {
+
+ case PN_LINK_REMOTE_OPEN:
+ DBGPRINTF("omamqp1: Message bus opened link.\n");
+ break;
+
+ case PN_DELIVERY:
+ // has the message been delivered to the message bus?
+ if (ps->delivery) {
+ assert(ps->delivery == pn_event_delivery(event));
+ if (pn_delivery_updated(ps->delivery)) {
+ rsRetVal result = RS_RET_IDLE;
+ uint64_t rs = pn_delivery_remote_state(ps->delivery);
+ switch (rs) {
+ case PN_ACCEPTED:
+ DBGPRINTF("omamqp1: Message ACCEPTED by message bus\n");
+ result = RS_RET_OK;
+ break;
+ case PN_REJECTED:
+ dbgprintf("omamqp1: message bus rejected log message: invalid message - dropping\n");
+ // message bus considers this a 'bad message'. Cannot be redelivered.
+ // Likely a configuration error. Drop the message by returning OK
+ result = RS_RET_OK;
+ break;
+ case PN_RELEASED:
+ case PN_MODIFIED:
+ // the message bus cannot accept the message. This may be temporary - retry
+ // up to maxRetries before dropping
+ if (++ps->retries >= cfg->maxRetries) {
+ dbgprintf("omamqp1: message bus failed to accept message - dropping\n");
+ result = RS_RET_OK;
+ } else {
+ dbgprintf("omamqp1: message bus cannot accept message, retrying\n");
+ result = RS_RET_SUSPENDED;
+ }
+ break;
+ case PN_RECEIVED:
+ // not finished yet, wait for next delivery update
+ break;
+ default:
+ // no other terminal states defined, so ignore anything else
+ dbgprintf("omamqp1: unknown delivery state=0x%lX, assuming message accepted\n",
+ (unsigned long) pn_delivery_remote_state(ps->delivery));
+ result = RS_RET_OK;
+ break;
+ }
+
+ if (result != RS_RET_IDLE) {
+ // the command is complete
+ threadIPC_t *ipc = ps->ipc;
+ pthread_mutex_lock(&ipc->lock);
+ assert(ipc->command == COMMAND_SEND);
+ ipc->result = result;
+ ipc->command = COMMAND_DONE;
+ pthread_cond_signal(&ipc->condition);
+ pthread_mutex_unlock(&ipc->lock);
+ pn_delivery_settle(ps->delivery);
+ ps->delivery = NULL;
+ if (result == RS_RET_OK) {
+ ps->retries = 0;
+ }
+ }
+ }
+ }
+ break;
+
+
+ case PN_CONNECTION_BOUND:
+ if (!cfg->bDisableSASL) {
+ // force use of SASL, even allowing PLAIN authentication
+ pn_sasl_t *sasl = pn_sasl(pn_event_transport(event));
+#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10
+ pn_sasl_set_allow_insecure_mechs(sasl, true);
+#else
+ // proton version <= 0.9 only supports PLAIN authentication
+ const char *user = cfg->username
+ ? (char *)cfg->username
+ : pn_url_get_username(cfg->url);
+ if (user) {
+ pn_sasl_plain(sasl, user, (cfg->password
+ ? (char *) cfg->password
+ : pn_url_get_password(cfg->url)));
+ }
+#endif
+ }
+ if (cfg->idleTimeout) {
+ // configured as seconds, set as milliseconds
+ pn_transport_set_idle_timeout(pn_event_transport(event),
+ cfg->idleTimeout * 1000);
+ }
+ break;
+
+ case PN_CONNECTION_UNBOUND:
+ DBGPRINTF("omamqp1: cleaning up connection resources\n");
+ pn_connection_release(pn_event_connection(event));
+ ps->conn = NULL;
+ ps->sender = NULL;
+ ps->delivery = NULL;
+ break;
+
+
+ case PN_TRANSPORT_ERROR:
+ {
+ // TODO: if auth failure, does it make sense to retry???
+ pn_transport_t *tport = pn_event_transport(event);
+ pn_condition_t *cond = pn_transport_condition(tport);
+ if (pn_condition_is_set(cond)) {
+ _log_error("transport failure", cond);
+ }
+ dbgprintf("omamqp1: network transport failed, reconnecting...\n");
+ // the protocol thread will attempt to reconnect if it is not
+ // being shut down
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+// Send a command to the protocol thread and
+// wait for the command to complete
+static rsRetVal _issue_command(threadIPC_t *ipc,
+ pn_reactor_t *reactor,
+ commands_t command,
+ pn_message_t *message)
+{
+ DEFiRet;
+
+ DBGPRINTF("omamqp1: Sending command %d to protocol thread\n", command);
+
+ pthread_mutex_lock(&ipc->lock);
+
+ if (message) {
+ assert(ipc->message == NULL);
+ ipc->message = message;
+ }
+ assert(ipc->command == COMMAND_DONE);
+ ipc->command = command;
+ pn_reactor_wakeup(reactor);
+ while (ipc->command != COMMAND_DONE) {
+ pthread_cond_wait(&ipc->condition, &ipc->lock);
+ }
+ iRet = ipc->result;
+ if (ipc->message) {
+ pn_message_free(ipc->message);
+ ipc->message = NULL;
+ }
+
+ pthread_mutex_unlock(&ipc->lock);
+
+ DBGPRINTF("omamqp1: Command %d completed, status=%d\n", command, iRet);
+ RETiRet;
+}
+
+
+// check if a command needs processing
+static void _poll_command(protocolState_t *ps)
+{
+ if (ps->stopped) return;
+
+ threadIPC_t *ipc = ps->ipc;
+
+ pthread_mutex_lock(&ipc->lock);
+
+ switch (ipc->command) {
+
+ case COMMAND_SHUTDOWN:
+ DBGPRINTF("omamqp1: Protocol thread processing shutdown command\n");
+ ps->stopped = true;
+ _close_connection(ps);
+ // wait for the shutdown to complete before ack'ing this command
+ break;
+
+ case COMMAND_IS_READY:
+ DBGPRINTF("omamqp1: Protocol thread processing ready query command\n");
+ ipc->result = _is_ready(ps->sender)
+ ? RS_RET_OK
+ : RS_RET_SUSPENDED;
+ ipc->command = COMMAND_DONE;
+ pthread_cond_signal(&ipc->condition);
+ break;
+
+ case COMMAND_SEND:
+ if (ps->delivery) break; // currently processing this command
+ DBGPRINTF("omamqp1: Protocol thread processing send message command\n");
+ if (!_is_ready(ps->sender)) {
+ ipc->result = RS_RET_SUSPENDED;
+ ipc->command = COMMAND_DONE;
+ pthread_cond_signal(&ipc->condition);
+ break;
+ }
+
+ // send the message
+ ++ps->tag;
+ ps->delivery = pn_delivery(ps->sender,
+ pn_dtag((const char *)&ps->tag, sizeof(ps->tag)));
+ pn_message_t *message = ipc->message;
+ assert(message);
+
+ int rc = 0;
+ size_t len = ps->buffer_size;
+ do {
+ rc = pn_message_encode(message, ps->encode_buffer, &len);
+ if (rc == PN_OVERFLOW) {
+ _grow_buffer(ps);
+ len = ps->buffer_size;
+ }
+ } while (rc == PN_OVERFLOW);
+
+ pn_link_send(ps->sender, ps->encode_buffer, len);
+ pn_link_advance(ps->sender);
+ ++ps->msgs_sent;
+ // command completes when remote updates the delivery (see PN_DELIVERY)
+ break;
+
+ case COMMAND_DONE:
+ break;
+ }
+
+ pthread_mutex_unlock(&ipc->lock);
+}
+
+/* runs the protocol engine, allowing it to handle TCP socket I/O and timer
+ * events in the background.
+*/
+static void *amqp1_thread(void *arg)
+{
+
+ pn_handler_t *handler = (pn_handler_t *)arg;
+ protocolState_t *ps = PROTOCOL_STATE(handler);
+ const configSettings_t *cfg = ps->config;
+
+ // have pn_reactor_process() exit after 5 sec to poll for commands
+ pn_reactor_set_timeout(ps->reactor, 5000);
+ pn_reactor_start(ps->reactor);
+
+ while (!ps->stopped) {
+ // setup a connection:
+ const char *host = pn_url_get_host(cfg->url);
+ const char *port = pn_url_get_port(cfg->url);
+ if (!port) port = "5672";
+
+#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 13
+ ps->conn = pn_reactor_connection_to_host(ps->reactor,
+ host,
+ port,
+ handler);
+ pn_connection_set_hostname(ps->conn, host);
+#else
+ {
+ char host_addr[300];
+ ps->conn = pn_reactor_connection(ps->reactor, handler);
+ snprintf(host_addr, sizeof(host_addr), "%s:%s", host, port);
+ pn_connection_set_hostname(ps->conn, host_addr);
+ }
+#endif
+ pn_connection_set_container(ps->conn, "rsyslogd-omamqp1");
+
+#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10
+ // proton version <= 0.9 did not support Cyrus SASL
+ const char *user = cfg->username
+ ? (char *)cfg->username
+ : pn_url_get_username(cfg->url);
+ if (user)
+ pn_connection_set_user(ps->conn, user);
+
+ const char *pword = cfg->password
+ ? (char *) cfg->password
+ : pn_url_get_password(cfg->url);
+ if (pword)
+ pn_connection_set_password(ps->conn, pword);
+#endif
+ pn_connection_open(ps->conn);
+ pn_session_t *ssn = pn_session(ps->conn);
+ pn_session_open(ssn);
+ ps->sender = pn_sender(ssn, (char *)cfg->target);
+ pn_link_set_snd_settle_mode(ps->sender, PN_SND_UNSETTLED);
+ char *addr = (char *)ps->config->target;
+ pn_terminus_set_address(pn_link_target(ps->sender), addr);
+ pn_terminus_set_address(pn_link_source(ps->sender), addr);
+ pn_link_open(ps->sender);
+
+ // run the protocol engine until the connection closes or thread is shut down
+ sbool engine_running = true;
+ while (engine_running) {
+ engine_running = pn_reactor_process(ps->reactor);
+ _poll_command(ps);
+ }
+
+ _abort_command(ps); // unblock main thread if necessary
+
+ // delay reconnectDelay seconds before re-connecting:
+ int delay = ps->config->reconnectDelay;
+ while (delay-- > 0 && !ps->stopped) {
+ srSleep(1, 0);
+ _poll_command(ps);
+ }
+ }
+ pn_reactor_stop(ps->reactor);
+ // stop command is now done:
+ threadIPC_t *ipc = ps->ipc;
+ pthread_mutex_lock(&ipc->lock);
+ ipc->result = RS_RET_OK;
+ ipc->command = COMMAND_DONE;
+ pthread_cond_signal(&ipc->condition);
+ pthread_mutex_unlock(&ipc->lock);
+
+ DBGPRINTF("omamqp1: Protocol thread stopped\n");
+
+ return 0;
+}
+
+
+static rsRetVal _launch_protocol_thread(instanceData *pData)
+{
+ int rc;
+ DBGPRINTF("omamqp1: Starting protocol thread\n");
+ do {
+ rc = pthread_create(&pData->thread_id, NULL, amqp1_thread, pData->handler);
+ if (!rc) {
+ pData->bThreadRunning = true;
+ return RS_RET_OK;
+ }
+ } while (rc == EAGAIN);
+ LogError(0, RS_RET_SYS_ERR, "omamqp1: thread create failed: %d", rc);
+ return RS_RET_SYS_ERR;
+}
+
+static rsRetVal _shutdown_thread(instanceData *pData)
+{
+ DEFiRet;
+
+ if (pData->bThreadRunning) {
+ DBGPRINTF("omamqp1: shutting down thread...\n");
+ CHKiRet(_issue_command(&pData->ipc, pData->reactor, COMMAND_SHUTDOWN, NULL));
+ pthread_join(pData->thread_id, NULL);
+ pData->bThreadRunning = false;
+ DBGPRINTF("omamqp1: thread shutdown complete\n");
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* vi:set ai:
+ */
+
diff --git a/contrib/omczmq/Makefile.am b/contrib/omczmq/Makefile.am
new file mode 100644
index 0000000..d2b09bd
--- /dev/null
+++ b/contrib/omczmq/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omczmq.la
+
+omczmq_la_SOURCES = omczmq.c
+omczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS)
+omczmq_la_LDFLAGS = -module -avoid-version
+omczmq_la_LIBADD = $(CZMQ_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/omczmq/Makefile.in b/contrib/omczmq/Makefile.in
new file mode 100644
index 0000000..cd0990e
--- /dev/null
+++ b/contrib/omczmq/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omczmq
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omczmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omczmq_la_OBJECTS = omczmq_la-omczmq.lo
+omczmq_la_OBJECTS = $(am_omczmq_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 =
+omczmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omczmq_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omczmq_la-omczmq.Plo
+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 = $(omczmq_la_SOURCES)
+DIST_SOURCES = $(omczmq_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omczmq.la
+omczmq_la_SOURCES = omczmq.c
+omczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS)
+omczmq_la_LDFLAGS = -module -avoid-version
+omczmq_la_LIBADD = $(CZMQ_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/omczmq/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omczmq/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omczmq.la: $(omczmq_la_OBJECTS) $(omczmq_la_DEPENDENCIES) $(EXTRA_omczmq_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omczmq_la_LINK) -rpath $(pkglibdir) $(omczmq_la_OBJECTS) $(omczmq_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omczmq_la-omczmq.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omczmq_la-omczmq.lo: omczmq.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omczmq_la-omczmq.lo -MD -MP -MF $(DEPDIR)/omczmq_la-omczmq.Tpo -c -o omczmq_la-omczmq.lo `test -f 'omczmq.c' || echo '$(srcdir)/'`omczmq.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omczmq_la-omczmq.Tpo $(DEPDIR)/omczmq_la-omczmq.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omczmq.c' object='omczmq_la-omczmq.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) $(omczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omczmq_la-omczmq.lo `test -f 'omczmq.c' || echo '$(srcdir)/'`omczmq.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omczmq_la-omczmq.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omczmq_la-omczmq.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omczmq/README b/contrib/omczmq/README
new file mode 100644
index 0000000..5399840
--- /dev/null
+++ b/contrib/omczmq/README
@@ -0,0 +1,79 @@
+CZMQ Output Plugin
+
+REQUIREMENTS:
+
+* libsodium ( https://github.com/jedisct1/libsodium )
+* zeromq built with libsodium support ( http://zeromq.org/ )
+* czmq ( http://czmq.zeromq.org/ )
+
+EXPLANATION OF OPTIONS
+
+Module
+------
+servercertpath: path to server cert if using CURVE
+clientcertpath: path to client cert(s) if using CURVE
+authtype: CURVESERVER, CURVECLIENT (omit for no auth)
+authenticator: whether to start an authenticator thread
+
+Action
+------
+type: type of action (omczmq for this plugin)
+endpoints: comma delimited list of zeromq endpoints (see zeromq documentation)
+socktype: zeromq socket type (currently supports PUSH, PUB, DEALER, RADIO, CLIENT, SCATTER)
+sendtimeout: timeout in ms before send errors
+sendhwm: number of messages to store in internal buffer before discarding (defaults to 1000)
+connecttimeout: connection timeout in ms(requires libzmq 4.2 or higher)
+heartbeativl: time in ms between sending heartbeat PING messages (requires libzmq 4.2 or higher)
+heartbeattimeout: time in milliseconds to wait for a PING response before disconnect(libzmq 4.2 or higher)
+heartbeatttl: time remote peer should wait between PINGs before disconnect (libzmq 4.2 or higher)
+topicframe: "on" to send topic as separate frame if PUB socket
+topics: comma delimited list of topics or templates to make topics from if PUB or RADIO socket
+dynatopic: if "on" topics list is treated as list of template names
+template: template to use for message (defaults to RSYSLOG_ForwardFormat)
+
+EXAMPLE CONFIGURATION
+
+This configuration sets up an omczmq endpoint as a ZMQ_PUB socket with CURVE authentication.
+Clients whose certificates are in the '/etc/curve.d/allowed_clients/' directory will be
+allowed to connect. Each message is published on two topics ( "hostname.programname" and
+"programname.hostname" ) which are constructed from properties of the log message.
+
+For instance, a log from sshd from host.example.com will be published on two topics:
+ * host.example.com.sshd
+ * sshd.host.example.com
+
+In this configuration, the output is configured to send each message as a two frame
+message, with the topic in the first flame and the rsyslog message in the second.
+
+-------------------------------------------------------------------------------
+module(
+ load="omczmq"
+ servercertpath="/etc/curve.d/example_server"
+ clientcertpath="/etc/curve.d/allowed_clients"
+ authtype="CURVESERVER"
+ authenticator="on"
+)
+
+template(name="host_program_topic" type="list") {
+ property(name="hostname")
+ constant(value=".")
+ property(name="programname")
+}
+
+template(name="program_host_topic" type="list") {
+ property(name="programname")
+ constant(value=".")
+ property(name="hostname")
+}
+
+
+action(
+ name="to_zeromq"
+ type="omczmq"
+ socktype="PUB"
+ endpoints="@tcp://*:31338"
+ topics="host_program_topic,program_host_topic"
+ dynatopic="on"
+ topicframe="on"
+)
+-------------------------------------------------------------------------------
diff --git a/contrib/omczmq/omczmq.c b/contrib/omczmq/omczmq.c
new file mode 100644
index 0000000..a16e7e8
--- /dev/null
+++ b/contrib/omczmq/omczmq.c
@@ -0,0 +1,652 @@
+/* omczmq.c
+ * Copyright (C) 2016 Brian Knox
+ * Copyright (C) 2014 Rainer Gerhards
+ *
+ * Author: Brian Knox <bknox@digitalocean.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include <czmq.h>
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omczmq")
+
+DEF_OMOD_STATIC_DATA
+
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cnfparamdescr modpdescr[] = {
+ { "authenticator", eCmdHdlrBinary, 0 },
+ { "authtype", eCmdHdlrGetWord, 0 },
+ { "clientcertpath", eCmdHdlrGetWord, 0 },
+ { "servercertpath", eCmdHdlrGetWord, 0 }
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+struct modConfData_s {
+ rsconf_t *pConf;
+ uchar *tplName;
+ int authenticator;
+ char *authType;
+ char *serverCertPath;
+ char *clientCertPath;
+};
+
+static modConfData_t *runModConf = NULL;
+static zactor_t *authActor;
+
+typedef struct _instanceData {
+ zsock_t *sock;
+ bool serverish;
+ int sendTimeout;
+ zlist_t *topics;
+ bool sendError;
+ char *sockEndpoints;
+ int sockType;
+ int sendHWM;
+#if(CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >=4 && ZMQ_VERSION_MINOR >=2)
+ int heartbeatIvl;
+ int heartbeatTimeout;
+ int heartbeatTTL;
+ int connectTimeout;
+#endif
+ uchar *tplName;
+ sbool topicFrame;
+ sbool dynaTopic;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+static struct cnfparamdescr actpdescr[] = {
+ { "endpoints", eCmdHdlrGetWord, 1 },
+ { "socktype", eCmdHdlrGetWord, 1 },
+ { "sendhwm", eCmdHdlrGetWord, 0 },
+#if(CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >=4 && ZMQ_VERSION_MINOR >=2)
+ { "heartbeatttl", eCmdHdlrGetWord, 0},
+ { "heartbeativl", eCmdHdlrGetWord, 0},
+ { "heartbeattimeout", eCmdHdlrGetWord, 0},
+ { "connecttimeout", eCmdHdlrGetWord, 0},
+#endif
+ { "sendtimeout", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "topics", eCmdHdlrGetWord, 0 },
+ { "topicframe", eCmdHdlrGetWord, 0},
+ { "dynatopic", eCmdHdlrBinary, 0 }
+};
+
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr) / sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+static rsRetVal initCZMQ(instanceData* pData) {
+ DEFiRet;
+ int rc;
+ putenv((char*)"ZSYS_SIGHANDLER=false");
+ pData->sock = zsock_new(pData->sockType);
+ if(!pData->sock) {
+ LogError(0, RS_RET_NO_ERRCODE,
+ "omczmq: new socket failed for endpoints: %s",
+ pData->sockEndpoints);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ zsock_set_sndtimeo(pData->sock, pData->sendTimeout);
+
+#if(CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >=4 && ZMQ_VERSION_MINOR >=2)
+ if(pData->heartbeatIvl > 0 && pData->heartbeatTimeout > 0 && pData->heartbeatTTL > 0) {
+ zsock_set_heartbeat_ivl(pData->sock, pData->heartbeatIvl);
+ zsock_set_heartbeat_timeout(pData->sock, pData->heartbeatTimeout);
+ zsock_set_heartbeat_ttl(pData->sock, pData->heartbeatTTL);
+ }
+#endif
+
+ if(runModConf->authType) {
+ if (!strcmp(runModConf->authType, "CURVESERVER")) {
+ zcert_t *serverCert = zcert_load(runModConf->serverCertPath);
+ if(!serverCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->serverCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ zsock_set_zap_domain(pData->sock, "global");
+ zsock_set_curve_server(pData->sock, 1);
+ zcert_apply(serverCert, pData->sock);
+ zcert_destroy(&serverCert);
+ }
+ else if(!strcmp(runModConf->authType, "CURVECLIENT")) {
+ zcert_t *serverCert = zcert_load(runModConf->serverCertPath);
+ if(!serverCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->serverCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ const char *server_key = zcert_public_txt(serverCert);
+ zcert_destroy(&serverCert);
+ zsock_set_curve_serverkey(pData->sock, server_key);
+
+ zcert_t *clientCert = zcert_load(runModConf->clientCertPath);
+ if(!clientCert) {
+ LogError(0, NO_ERRCODE, "could not load cert %s",
+ runModConf->clientCertPath);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ zcert_apply(clientCert, pData->sock);
+ zcert_destroy(&clientCert);
+ }
+ }
+
+ switch(pData->sockType) {
+ case ZMQ_PUB:
+#if defined(ZMQ_RADIO)
+ case ZMQ_RADIO:
+#endif
+ pData->serverish = true;
+ break;
+ case ZMQ_PUSH:
+#if defined(ZMQ_SCATTER)
+ case ZMQ_SCATTER:
+#endif
+ case ZMQ_DEALER:
+#if defined(ZMQ_CLIENT)
+ case ZMQ_CLIENT:
+#endif
+ pData->serverish = false;
+ break;
+ }
+
+ rc = zsock_attach(pData->sock, pData->sockEndpoints, pData->serverish);
+ if(rc == -1) {
+ LogError(0, NO_ERRCODE, "zsock_attach to %s failed",
+ pData->sockEndpoints);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal outputCZMQ(uchar** ppString, instanceData* pData) {
+ DEFiRet;
+
+ if(NULL == pData->sock) {
+ CHKiRet(initCZMQ(pData));
+ }
+
+ /* if we are using a PUB (or RADIO) socket and we have a topic list then we
+ * need some special care and attention */
+#if defined(ZMQ_RADIO)
+ DBGPRINTF("omczmq: ZMQ_RADIO is defined...\n");
+ if((pData->sockType == ZMQ_PUB || pData->sockType == ZMQ_RADIO) && pData->topics) {
+#else
+ DBGPRINTF("omczmq: ZMQ_RADIO is NOT defined...\n");
+ if(pData->sockType == ZMQ_PUB && pData->topics) {
+#endif
+ int templateIndex = 1;
+ const char *topic = (const char *)zlist_first(pData->topics);
+ while(topic) {
+ int rc;
+ /* if dynaTopic is true, the topic is constructed by rsyslog
+ * by applying the supplied template to the message properties */
+ if(pData->dynaTopic)
+ topic = (const char*)ppString[templateIndex];
+
+ if (pData->sockType == ZMQ_PUB) {
+ /* if topicFrame is true, send the topic as a separate zmq frame */
+ if(pData->topicFrame) {
+ rc = zstr_sendx(pData->sock, topic, (char*)ppString[0], NULL);
+ }
+
+ /* if topicFrame is false, concatenate the topic with the
+ * message in the same frame */
+ else {
+ rc = zstr_sendf(pData->sock, "%s%s", topic, (char*)ppString[0]);
+ }
+
+ /* if we have a send error notify rsyslog */
+ if(rc != 0) {
+ pData->sendError = true;
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+#if defined(ZMQ_RADIO)
+ else if(pData->sockType == ZMQ_RADIO) {
+ DBGPRINTF("omczmq: sending on RADIO socket...\n");
+ zframe_t *frame = zframe_from((char*)ppString[0]);
+ if (!frame) {
+ DBGPRINTF("omczmq: failed to create frame...\n");
+ pData->sendError = true;
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ rc = zframe_set_group(frame, topic);
+ if (rc != 0) {
+ DBGPRINTF("omczmq: failed to set group '%d'...\n", rc);
+ pData->sendError = true;
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ DBGPRINTF("omczmq: set RADIO group to '%s'\n", topic);
+ rc = zframe_send(&frame, pData->sock, 0);
+ if(rc != 0) {
+ pData->sendError = true;
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+#endif
+
+ /* get the next topic from the list, and increment
+ * our topic index */
+ topic = zlist_next(pData->topics);
+ templateIndex++;
+ }
+ }
+
+ /* we aren't a PUB socket and we don't have a topic list - this means
+ * we can just send the message using the rsyslog template */
+ else {
+ int rc = zstr_send(pData->sock, (char*)ppString[0]);
+ if(rc != 0) {
+ pData->sendError = true;
+ DBGPRINTF("omczmq: send error: %d", rc);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+static inline void
+setInstParamDefaults(instanceData* pData) {
+ pData->sockEndpoints = NULL;
+ pData->sock = NULL;
+ pData->sendError = false;
+ pData->serverish = false;
+ pData->tplName = NULL;
+ pData->sockType = -1;
+ pData->sendTimeout = -1;
+ pData->topics = NULL;
+ pData->topicFrame = false;
+#if(CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >=4 && ZMQ_VERSION_MINOR >=2)
+ pData->heartbeatIvl = 0;
+ pData->heartbeatTimeout = 0;
+ pData->heartbeatTTL = 0;
+#endif
+}
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction) {
+ iRet = RS_RET_OK;
+ }
+ENDisCompatibleWithFeature
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ zlist_destroy(&pData->topics);
+ zsock_destroy(&pData->sock);
+ free(pData->sockEndpoints);
+ free(pData->tplName);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+BEGINtryResume
+ instanceData *pData;
+CODESTARTtryResume
+ pthread_mutex_lock(&mutDoAct);
+ pData = pWrkrData->pData;
+ DBGPRINTF("omczmq: trying to resume...\n");
+ zsock_destroy(&pData->sock);
+ iRet = initCZMQ(pData);
+ pthread_mutex_unlock(&mutDoAct);
+ENDtryResume
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ runModConf = pModConf;
+ runModConf->pConf = pConf;
+ runModConf->authenticator = 0;
+ runModConf->authType = NULL;
+ runModConf->serverCertPath = NULL;
+ runModConf->clientCertPath = NULL;
+ENDbeginCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ if(runModConf->authenticator == 1) {
+ if(!authActor) {
+ DBGPRINTF("omczmq: starting authActor\n");
+ authActor = zactor_new(zauth, NULL);
+ if(!strcmp(runModConf->clientCertPath, "*")) {
+ zstr_sendx(authActor, "CURVE", CURVE_ALLOW_ANY, NULL);
+ }
+ else {
+ zstr_sendx(authActor, "CURVE", runModConf->clientCertPath, NULL);
+ }
+ zsock_wait(authActor);
+ }
+ }
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ free(pModConf->authType);
+ free(pModConf->serverCertPath);
+ free(pModConf->clientCertPath);
+ DBGPRINTF("omczmq: stopping authActor\n");
+ zactor_destroy(&authActor);
+ENDfreeCnf
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if (pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ for (i=0; i<modpblk.nParams; ++i) {
+ if(!pvals[i].bUsed) {
+ DBGPRINTF("omczmq: pvals[i].bUSed continuing\n");
+ continue;
+ }
+ if(!strcmp(modpblk.descr[i].name, "authenticator")) {
+ runModConf->authenticator = (int)pvals[i].val.d.n;
+ }
+ else if(!strcmp(modpblk.descr[i].name, "authtype")) {
+ runModConf->authType = es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: authtype set to %s\n", runModConf->authType);
+ }
+ else if(!strcmp(modpblk.descr[i].name, "servercertpath")) {
+ runModConf->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: serverCertPath set to %s\n", runModConf->serverCertPath);
+ }
+ else if(!strcmp(modpblk.descr[i].name, "clientcertpath")) {
+ runModConf->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: clientCertPath set to %s\n", runModConf->clientCertPath);
+ }
+ else {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "omczmq: config error, unknown "
+ "param %s in setModCnf\n",
+ modpblk.descr[i].name);
+ }
+ }
+
+ DBGPRINTF("omczmq: authenticator set to %d\n", runModConf->authenticator);
+ DBGPRINTF("omczmq: authType set to %s\n", runModConf->authType);
+ DBGPRINTF("omczmq: serverCertPath set to %s\n", runModConf->serverCertPath);
+ DBGPRINTF("omczmq: clientCertPath set to %s\n", runModConf->clientCertPath);
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ runModConf = NULL;
+ENDendCnfLoad
+
+
+BEGINdoAction
+ instanceData *pData;
+CODESTARTdoAction
+ pthread_mutex_lock(&mutDoAct);
+ pData = pWrkrData->pData;
+ iRet = outputCZMQ(ppString, pData);
+ pthread_mutex_unlock(&mutDoAct);
+ENDdoAction
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int iNumTpls;
+CODESTARTnewActInst
+ if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0; i < actpblk.nParams; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+
+ if(!strcmp(actpblk.descr[i].name, "endpoints")) {
+ pData->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: sockEndPoints set to '%s'\n", pData->sockEndpoints);
+ }
+ else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: template set to '%s'\n", pData->tplName);
+ }
+ else if(!strcmp(actpblk.descr[i].name, "dynatopic")) {
+ pData->dynaTopic = pvals[i].val.d.n;
+ DBGPRINTF("omczmq: dynaTopic set to %s\n", pData->dynaTopic ? "true" : "false");
+ }
+ else if(!strcmp(actpblk.descr[i].name, "sendtimeout")) {
+ pData->sendTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
+ DBGPRINTF("omczmq: sendTimeout set to %d\n", pData->sendTimeout);
+ }
+ else if(!strcmp(actpblk.descr[i].name, "sendhwm")) {
+ pData->sendTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
+ DBGPRINTF("omczmq: sendHWM set to %d\n", pData->sendHWM);
+ }
+#if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >=4 && ZMQ_VERSION_MINOR >=2)
+ else if(!strcmp(actpblk.descr[i].name, "heartbeativl")) {
+ pData->heartbeatIvl = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
+ DBGPRINTF("omczmq: heartbeatbeatIvl set to %d\n", pData->heartbeatIvl);
+ }
+ else if(!strcmp(actpblk.descr[i].name, "heartbeattimeout")) {
+ pData->heartbeatTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
+ DBGPRINTF("omczmq: heartbeatTimeout set to %d\n", pData->heartbeatTimeout);
+ }
+ else if(!strcmp(actpblk.descr[i].name, "heartbeatttl")) {
+ pData->heartbeatTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL));
+ DBGPRINTF("omczmq: heartbeatTTL set to %d\n", pData->heartbeatTTL);
+ }
+#endif
+ else if(!strcmp(actpblk.descr[i].name, "socktype")){
+ char *stringType = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(stringType != NULL){
+ if(!strcmp("PUB", stringType)) {
+ pData->sockType = ZMQ_PUB;
+ DBGPRINTF("omczmq: sockType set to ZMQ_PUB\n");
+ }
+#if defined(ZMQ_RADIO)
+ else if(!strcmp("RADIO", stringType)) {
+ pData->sockType = ZMQ_RADIO;
+ DBGPRINTF("omczmq: sockType set to ZMQ_RADIO\n");
+ }
+#endif
+ else if(!strcmp("PUSH", stringType)) {
+ pData->sockType = ZMQ_PUSH;
+ DBGPRINTF("omczmq: sockType set to ZMQ_PUSH\n");
+ }
+#if defined(ZMQ_SCATTER)
+ else if(!strcmp("SCATTER", stringType)) {
+ pData->sockType = ZMQ_SCATTER;
+ DBGPRINTF("omczmq: sockType set to ZMQ_SCATTER\n");
+ }
+#endif
+ else if(!strcmp("DEALER", stringType)) {
+ pData->sockType = ZMQ_DEALER;
+ DBGPRINTF("omczmq: sockType set to ZMQ_DEALER\n");
+ }
+#if defined(ZMQ_CLIENT)
+ else if(!strcmp("CLIENT", stringType)) {
+ pData->sockType = ZMQ_CLIENT;
+ DBGPRINTF("omczmq: sockType set to ZMQ_CLIENT\n");
+ }
+#endif
+ free(stringType);
+ }
+ else{
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omczmq: out of memory");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ }
+ else if(!strcmp(actpblk.descr[i].name, "topicframe")) {
+ pData->topicFrame = pvals[i].val.d.n;
+ DBGPRINTF("omczmq: topicFrame set to %s\n", pData->topicFrame ? "true" : "false");
+ }
+ else if(!strcmp(actpblk.descr[i].name, "topics")) {
+ pData->topics = zlist_new();
+ char *topics = es_str2cstr(pvals[i].val.d.estr, NULL);
+ DBGPRINTF("omczmq: topics set to %s\n", topics);
+ char *topics_org = topics;
+ char topic[256];
+ if(topics == NULL){
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "out of memory");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ while(*topics) {
+ char *delimiter = strchr(topics, ',');
+ if (!delimiter) {
+ delimiter = topics + strlen(topics);
+ }
+ memcpy (topic, topics, delimiter - topics);
+ topic[delimiter-topics] = 0;
+ char *current_topic = strdup(topic);
+ zlist_append (pData->topics, current_topic);
+ if(*delimiter == 0) {
+ break;
+ }
+ topics = delimiter + 1;
+ }
+ free(topics_org);
+
+ }
+ else {
+ LogError(0, NO_ERRCODE,
+ "omczmq: config error - '%s' is not a valid option",
+ actpblk.descr[i].name);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ }
+
+ iNumTpls = 1;
+ if (pData->dynaTopic) {
+ iNumTpls = zlist_size (pData->topics) + iNumTpls;
+ }
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls)
+
+ if (pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup("RSYSLOG_ForwardFormat"),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+ else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)pData->tplName, OMSR_NO_RQD_TPL_OPTS));
+ }
+
+ i = 1;
+ if (pData->dynaTopic) {
+ char *topic = zlist_first(pData->topics);
+ while (topic) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, i, (uchar*)strdup(topic), OMSR_NO_RQD_TPL_OPTS));
+ i++;
+ topic = zlist_next(pData->topics);
+ }
+ }
+
+ CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINinitConfVars
+CODESTARTinitConfVars
+ENDinitConfVars
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+ CODEqueryEtryPt_STD_OMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_QUERIES
+ CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+ CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("omczmq: module compiled with rsyslog version %s.\n", VERSION);
+
+ INITLegCnfVars
+ENDmodInit
diff --git a/contrib/omfile-hardened/Makefile.am b/contrib/omfile-hardened/Makefile.am
new file mode 100644
index 0000000..c1c754e
--- /dev/null
+++ b/contrib/omfile-hardened/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omfile-hardened.la
+
+omfile_hardened_la_SOURCES = omfile-hardened.c
+omfile_hardened_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+omfile_hardened_la_LDFLAGS = -module -avoid-version
+omfile_hardened_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/omfile-hardened/Makefile.in b/contrib/omfile-hardened/Makefile.in
new file mode 100644
index 0000000..e1ba943
--- /dev/null
+++ b/contrib/omfile-hardened/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omfile-hardened
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omfile_hardened_la_DEPENDENCIES =
+am_omfile_hardened_la_OBJECTS = omfile_hardened_la-omfile-hardened.lo
+omfile_hardened_la_OBJECTS = $(am_omfile_hardened_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 =
+omfile_hardened_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(omfile_hardened_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo
+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 = $(omfile_hardened_la_SOURCES)
+DIST_SOURCES = $(omfile_hardened_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omfile-hardened.la
+omfile_hardened_la_SOURCES = omfile-hardened.c
+omfile_hardened_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+omfile_hardened_la_LDFLAGS = -module -avoid-version
+omfile_hardened_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/omfile-hardened/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omfile-hardened/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omfile-hardened.la: $(omfile_hardened_la_OBJECTS) $(omfile_hardened_la_DEPENDENCIES) $(EXTRA_omfile_hardened_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omfile_hardened_la_LINK) -rpath $(pkglibdir) $(omfile_hardened_la_OBJECTS) $(omfile_hardened_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omfile_hardened_la-omfile-hardened.lo: omfile-hardened.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omfile_hardened_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omfile_hardened_la-omfile-hardened.lo -MD -MP -MF $(DEPDIR)/omfile_hardened_la-omfile-hardened.Tpo -c -o omfile_hardened_la-omfile-hardened.lo `test -f 'omfile-hardened.c' || echo '$(srcdir)/'`omfile-hardened.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omfile_hardened_la-omfile-hardened.Tpo $(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile-hardened.c' object='omfile_hardened_la-omfile-hardened.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) $(omfile_hardened_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omfile_hardened_la-omfile-hardened.lo `test -f 'omfile-hardened.c' || echo '$(srcdir)/'`omfile-hardened.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omfile-hardened/omfile-hardened.c b/contrib/omfile-hardened/omfile-hardened.c
new file mode 100644
index 0000000..2b14a2c
--- /dev/null
+++ b/contrib/omfile-hardened/omfile-hardened.c
@@ -0,0 +1,1654 @@
+/* omfile.c
+ * This is the implementation of the build-in file output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c, which
+ * at the time of the fork from sysklogd was under BSD license)
+ *
+ * A large re-write of this file was done in June, 2009. The focus was
+ * to introduce many more features (like zipped writing), clean up the code
+ * and make it more reliable. In short, that rewrite tries to provide a new
+ * solid basis for the next three to five years to come. During it, bugs
+ * may have been introduced ;) -- rgerhards, 2009-06-04
+ *
+ * Note that as of 2010-02-28 this module does no longer handle
+ * pipes. These have been moved to ompipe, to reduced the entanglement
+ * between the two different functionalities. -- rgerhards
+ *
+ * Copyright 2007-2017 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include "glbl.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <sys/statvfs.h>
+#ifdef HAVE_ATOMIC_BUILTINS
+# include <pthread.h>
+#endif
+
+
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "outchannel.h"
+#include "omfile.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "stream.h"
+#include "unicode-helper.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "sigprov.h"
+#include "cryprov.h"
+#include "parserif.h"
+#include "janitor.h"
+#include "rsconf.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omfile")
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(statsobj)
+
+/* for our current LRU mechanism, we need a monotonically increasing counters. We use
+ * it much like a "Lamport logical clock": we do not need the actual time, we just need
+ * to know the sequence in which files were accessed. So we use a simple counter to
+ * create that sequence. We use an unsigned 64 bit value which is extremely unlike to
+ * wrap within the lifetime of a process. If we process 1,000,000 file writes per
+ * second, the process could still exist over 500,000 years before a wrap to 0 happens.
+ * That should be sufficient (and even than, there would no really bad effect ;)).
+ * The variable below is the global counter/clock.
+ */
+#if HAVE_ATOMIC_BUILTINS64
+static uint64 clockFileAccess = 0;
+#else
+static unsigned clockFileAccess = 0;
+#endif
+/* and the "tick" function */
+#ifndef HAVE_ATOMIC_BUILTINS
+static pthread_mutex_t mutClock;
+#endif
+static uint64
+getClockFileAccess(void)
+{
+#if HAVE_ATOMIC_BUILTINS64
+ return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock);
+#else
+ return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock);
+#endif
+}
+
+
+/* The following structure is a dynafile name cache entry.
+ */
+struct s_dynaFileCacheEntry {
+ uchar *pName; /* name currently open, if dynamic name */
+ strm_t *pStrm; /* our output stream */
+ void *sigprovFileData; /* opaque data ptr for provider use */
+ uint64 clkTickAccessed;/* for LRU - based on clockFileAccess */
+ short nInactive; /* number of minutes not writen - for close timeout */
+};
+typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
+
+
+#define IOBUF_DFLT_SIZE 4096 /* default size for io buffers */
+#define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */
+#define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */
+#define FLUSHONTX_DFLT 1 /* default for flush on TX end */
+
+typedef struct _instanceData {
+ pthread_mutex_t mutWrite; /* guard against multiple instances writing to single file */
+ uchar *fname; /* file or template name (display only) */
+ uchar *tplName; /* name of assigned template */
+ strm_t *pStrm; /* our output stream */
+ short nInactive; /* number of minutes not writen (STATIC files only) */
+ char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */
+ int fCreateMode; /* file creation mode for open() */
+ int fDirCreateMode; /* creation mode for mkdir() */
+ int bCreateDirs; /* auto-create directories? */
+ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */
+ uint8_t iNumTpls; /* number of tpls we use */
+ uid_t fileUID; /* IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int bFailOnChown; /* fail creation if chown fails? */
+ uchar *sigprovName; /* signature provider */
+ uchar *sigprovNameFull;/* full internal signature provider name */
+ sigprov_if_t sigprov; /* ptr to signature provider interface */
+ void *sigprovData; /* opaque data ptr for provider use */
+ void *sigprovFileData;/* opaque data ptr for file instance */
+ sbool useSigprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ uchar *cryprovName; /* crypto provider */
+ uchar *cryprovNameFull;/* full internal crypto provider name */
+ void *cryprovData; /* opaque data ptr for provider use */
+ cryprov_if_t cryprov; /* ptr to crypto provider interface */
+ sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ int iCurrElt; /* currently active cache element (-1 = none) */
+ uint iCurrCacheSize; /* currently cache size (1-based) */
+ uint iDynaFileCacheSize; /* size of file handle cache */
+ /* The cache is implemented as an array. An empty element is indicated
+ * by a NULL pointer. Memory is allocated as needed. The following
+ * pointer points to the overall structure.
+ */
+ dynaFileCacheEntry **dynCache;
+ off_t iSizeLimit; /* file size limit, 0 = no limit */
+ uchar *pszSizeLimitCmd; /* command to carry out when size limit is reached */
+ int iZipLevel; /* zip mode to use for this selector */
+ uint iIOBufSize; /* size of associated io buffer */
+ int iFlushInterval; /* how fast flush buffer on inactivity? */
+ short iCloseTimeout; /* after how many *minutes* shall the file be closed if inactive? */
+ sbool bFlushOnTXEnd; /* flush write buffers when transaction has ended? */
+ sbool bUseAsyncWriter; /* use async stream writer? */
+ sbool bVeryRobustZip;
+ statsobj_t *stats; /* dynafile, primarily cache stats */
+ STATSCOUNTER_DEF(ctrRequests, mutCtrRequests);
+ STATSCOUNTER_DEF(ctrLevel0, mutCtrLevel0);
+ STATSCOUNTER_DEF(ctrEvict, mutCtrEvict);
+ STATSCOUNTER_DEF(ctrMiss, mutCtrMiss);
+ STATSCOUNTER_DEF(ctrMax, mutCtrMax);
+ STATSCOUNTER_DEF(ctrCloseTimeouts, mutCtrCloseTimeouts);
+ char janitorID[128]; /* holds ID for janitor calls */
+} instanceData;
+
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+
+typedef struct configSettings_s {
+ uint iDynaFileCacheSize; /* max cache for dynamic files */
+ int fCreateMode; /* mode to use when creating files */
+ int fDirCreateMode; /* mode to use when creating files */
+ int bFailOnChown; /* fail if chown fails? */
+ uid_t fileUID; /* UID to be used for newly created files */
+ uid_t fileGID; /* GID to be used for newly created files */
+ uid_t dirUID; /* UID to be used for newly created directories */
+ uid_t dirGID; /* GID to be used for newly created directories */
+ int bCreateDirs;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
+ int bEnableSync;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
+ int iZipLevel; /* zip compression mode (0..9 as usual) */
+ sbool bFlushOnTXEnd;/* flush write buffers when transaction has ended? */
+ int64 iIOBufSize; /* size of an io buffer */
+ int iFlushInterval; /* how often flush the output buffer on inactivity? */
+ int bUseAsyncWriter; /* should we enable asynchronous writing? */
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t cs;
+uchar *pszFileDfltTplName; /* name of the default template to use */
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+ int fCreateMode; /* default mode to use when creating files */
+ int fDirCreateMode; /* default mode to use when creating files */
+ uid_t fileUID; /* default IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int bDynafileDoNotSuspend;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "dirowner", eCmdHdlrUID, 0 },
+ { "dirownernum", eCmdHdlrInt, 0 },
+ { "dirgroup", eCmdHdlrGID, 0 },
+ { "dirgroupnum", eCmdHdlrInt, 0 },
+ { "fileowner", eCmdHdlrUID, 0 },
+ { "fileownernum", eCmdHdlrInt, 0 },
+ { "filegroup", eCmdHdlrGID, 0 },
+ { "dynafile.donotsuspend", eCmdHdlrBinary, 0 },
+ { "filegroupnum", eCmdHdlrInt, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "dynafilecachesize", eCmdHdlrInt, 0 }, /* legacy: dynafilecachesize */
+ { "ziplevel", eCmdHdlrInt, 0 }, /* legacy: omfileziplevel */
+ { "flushinterval", eCmdHdlrInt, 0 }, /* legacy: omfileflushinterval */
+ { "asyncwriting", eCmdHdlrBinary, 0 }, /* legacy: omfileasyncwriting */
+ { "veryrobustzip", eCmdHdlrBinary, 0 },
+ { "flushontxend", eCmdHdlrBinary, 0 }, /* legacy: omfileflushontxend */
+ { "iobuffersize", eCmdHdlrSize, 0 }, /* legacy: omfileiobuffersize */
+ { "dirowner", eCmdHdlrUID, 0 }, /* legacy: dirowner */
+ { "dirownernum", eCmdHdlrInt, 0 }, /* legacy: dirownernum */
+ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */
+ { "dirgroupnum", eCmdHdlrInt, 0 }, /* legacy: dirgroupnum */
+ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */
+ { "fileownernum", eCmdHdlrInt, 0 }, /* legacy: fileownernum */
+ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */
+ { "filegroupnum", eCmdHdlrInt, 0 }, /* legacy: filegroupnum */
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: filecreatemode */
+ { "failonchownfailure", eCmdHdlrBinary, 0 }, /* legacy: failonchownfailure */
+ { "createdirs", eCmdHdlrBinary, 0 }, /* legacy: createdirs */
+ { "sync", eCmdHdlrBinary, 0 }, /* legacy: actionfileenablesync */
+ { "file", eCmdHdlrString, 0 }, /* either "file" or ... */
+ { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */
+ { "sig.provider", eCmdHdlrGetWord, 0 },
+ { "cry.provider", eCmdHdlrGetWord, 0 },
+ { "closetimeout", eCmdHdlrPositiveInt, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(pszFileDfltTplName == NULL)
+ return (uchar*)"RSYSLOG_FileFormat";
+ else
+ return pszFileDfltTplName;
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ pszFileDfltTplName = NULL; /* make sure this can be free'ed! */
+ iRet = resetConfigVariables(NULL, NULL); /* params are dummies */
+ENDinitConfVars
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ if(pData->bDynamicName) {
+ dbgprintf("[dynamic]\n");
+ } else { /* regular file */
+ dbgprintf("%s%s\n", pData->fname,
+ (pData->pStrm == NULL) ? " (closed)" : "");
+ }
+
+ dbgprintf("\ttemplate='%s'\n", pData->fname);
+ dbgprintf("\tuse async writer=%d\n", pData->bUseAsyncWriter);
+ dbgprintf("\tflush on TX end=%d\n", pData->bFlushOnTXEnd);
+ dbgprintf("\tflush interval=%d\n", pData->iFlushInterval);
+ dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize);
+ dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "on" : "off");
+ dbgprintf("\tvery robust zip: %s\n", pData->bCreateDirs ? "on" : "off");
+ dbgprintf("\tfile owner %d, group %d\n", (int) pData->fileUID, (int) pData->fileGID);
+ dbgprintf("\tdirectory owner %d, group %d\n", (int) pData->dirUID, (int) pData->dirGID);
+ dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n",
+ pData->fDirCreateMode, pData->fCreateMode);
+ dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no");
+ENDdbgPrintInstInfo
+
+
+
+/* set the default template to be used
+ * This is a module-global parameter, and as such needs special handling. It needs to
+ * be coordinated with values set via the v2 config system (rsyslog v6+). What we do
+ * is we do not permit this directive after the v2 config system has been used to set
+ * the parameter.
+ */
+static rsRetVal
+setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal)
+{
+ DEFiRet;
+
+ if(loadModConf != NULL && loadModConf->tplName != NULL) {
+ free(newVal);
+ parser_errmsg("omfile: default template already set via module "
+ "global parameter - can no longer be changed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = newVal;
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the dynaFile cache size. Does some limit checking.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+
+ if(iNewVal < 1) {
+ errno = 0;
+ parser_errmsg(
+ "DynaFileCacheSize must be greater 0 (%d given), changed to 1.", iNewVal);
+ iRet = RS_RET_VAL_OUT_OF_RANGE;
+ iNewVal = 1;
+ } else if(iNewVal > 1000) {
+ errno = 0;
+ parser_errmsg(
+ "DynaFileCacheSize maximum is 1,000 (%d given), changed to 1,000.", iNewVal);
+ iRet = RS_RET_VAL_OUT_OF_RANGE;
+ iNewVal = 1000;
+ }
+
+ cs.iDynaFileCacheSize = iNewVal;
+ DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal);
+
+ RETiRet;
+}
+
+
+/* Helper to cfline(). Parses a output channel name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template. Maps the output channel to the
+ * proper filed structure settings. Everything is stored in the
+ * filed struct. Over time, the dependency on filed might be
+ * removed.
+ * rgerhards 2005-06-21
+ */
+static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringRequest_t *pOMSR,
+ int iEntry, int iTplOpts)
+{
+ DEFiRet;
+ size_t i;
+ struct outchannel *pOch;
+ char szBuf[128]; /* should be more than sufficient */
+
+ ++p; /* skip '$' */
+ i = 0;
+ /* get outchannel name */
+ while(*p && *p != ';' && *p != ' ' &&
+ i < (sizeof(szBuf) - 1) ) {
+ szBuf[i++] = *p++;
+ }
+ szBuf[i] = '\0';
+
+ /* got the name, now look up the channel... */
+ pOch = ochFind(szBuf, i);
+
+ if(pOch == NULL) {
+ parser_errmsg(
+ "outchannel '%s' not found - ignoring action line",
+ szBuf);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ /* check if there is a file name in the outchannel... */
+ if(pOch->pszFileTemplate == NULL) {
+ parser_errmsg(
+ "outchannel '%s' has no file name template - ignoring action line",
+ szBuf);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* OK, we finally got a correct template. So let's use it... */
+ pData->fname = ustrdup(pOch->pszFileTemplate);
+ pData->iSizeLimit = pOch->uSizeLimit;
+ /* WARNING: It is dangerous "just" to pass the pointer. As we
+ * never rebuild the output channel description, this is acceptable here.
+ */
+ pData->pszSizeLimitCmd = pOch->cmdOnSizeLimit;
+
+ iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl());
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function deletes an entry from the dynamic file name
+ * cache. A pointer to the cache must be passed in as well
+ * as the index of the to-be-deleted entry. This index may
+ * point to an unallocated entry, in whcih case the
+ * function immediately returns. Parameter bFreeEntry is 1
+ * if the entry should be free()ed and 0 if not.
+ */
+static rsRetVal
+dynaFileDelCacheEntry(instanceData *__restrict__ const pData, const int iEntry, const int bFreeEntry)
+{
+ dynaFileCacheEntry **pCache = pData->dynCache;
+ DEFiRet;
+ assert(pCache != NULL);
+
+ if(pCache[iEntry] == NULL)
+ FINALIZE;
+
+ DBGPRINTF("Removing entry %d for file '%s' from dynaCache.\n", iEntry,
+ pCache[iEntry]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[iEntry]->pName);
+
+ if(pCache[iEntry]->pName != NULL) {
+ free(pCache[iEntry]->pName);
+ pCache[iEntry]->pName = NULL;
+ }
+
+ if(pCache[iEntry]->pStrm != NULL) {
+ strm.Destruct(&pCache[iEntry]->pStrm);
+ if(pData->useSigprov) {
+ pData->sigprov.OnFileClose(pCache[iEntry]->sigprovFileData);
+ pCache[iEntry]->sigprovFileData = NULL;
+ }
+ }
+
+ if(bFreeEntry) {
+ free(pCache[iEntry]);
+ pCache[iEntry] = NULL;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function frees all dynamic file name cache entries and closes the
+ * relevant files. Part of Shutdown and HUP processing.
+ * rgerhards, 2008-10-23
+ */
+static void
+dynaFileFreeCacheEntries(instanceData *__restrict__ const pData)
+{
+ register uint i;
+ assert(pData != NULL);
+
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ dynaFileDelCacheEntry(pData, i, 1);
+ }
+ pData->iCurrElt = -1; /* invalidate current element */
+}
+
+
+/* This function frees the dynamic file name cache.
+ */
+static void dynaFileFreeCache(instanceData *__restrict__ const pData)
+{
+ assert(pData != NULL);
+
+ dynaFileFreeCacheEntries(pData);
+ if(pData->dynCache != NULL)
+ free(pData->dynCache);
+}
+
+
+/* close current file */
+static rsRetVal
+closeFile(instanceData *__restrict__ const pData)
+{
+ DEFiRet;
+ if(pData->useSigprov) {
+ pData->sigprov.OnFileClose(pData->sigprovFileData);
+ pData->sigprovFileData = NULL;
+ }
+ strm.Destruct(&pData->pStrm);
+ RETiRet;
+}
+
+
+/* This prepares the signature provider to process a file */
+static rsRetVal
+sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn)
+{
+ DEFiRet;
+ pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData);
+ RETiRet;
+}
+
+/* This is now shared code for all types of files. It simply prepares
+ * file access, which, among others, means the the file wil be opened
+ * and any directories in between will be created (based on config, of
+ * course). -- rgerhards, 2008-10-22
+ * changed to iRet interface - 2009-03-19
+ */
+static rsRetVal
+prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName)
+{
+ int fd;
+ char errStr[1024]; /* buffer for strerr() */
+ DEFiRet;
+
+ pData->pStrm = NULL;
+ if(access((char*)newFileName, F_OK) != 0) {
+ /* file does not exist, create it (and eventually parent directories */
+ if(pData->bCreateDirs) {
+ /* We first need to create parent dirs if they are missing.
+ * We do not report any errors here ourselfs but let the code
+ * fall through to error handler below.
+ */
+ if(makeFileParentDirs(newFileName, ustrlen(newFileName),
+ pData->fDirCreateMode, pData->dirUID,
+ pData->dirGID, pData->bFailOnChown) != 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg( "omfile: creating parent "
+ "directories for file '%s' failed: %s",
+ newFileName, errStr);
+ ABORT_FINALIZE(RS_RET_ERR); /* we give up */
+ }
+ }
+ /* no matter if we needed to create directories or not, we now try to create
+ * the file. -- rgerhards, 2008-12-18 (based on patch from William Tisater)
+ */
+ fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
+ pData->fCreateMode);
+ if(fd != -1) {
+ /* check and set uid/gid */
+ if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ /* we need to set owner/group */
+ if(fchown(fd, pData->fileUID, pData->fileGID) != 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg(
+ "omfile: chown for file '%s' failed: %s",
+ newFileName, errStr);
+ if(pData->bFailOnChown) {
+ close(fd);
+ ABORT_FINALIZE(RS_RET_ERR); /* we give up */
+ }
+ /* we will silently ignore the chown() failure
+ * if configured to do so.
+ */
+ }
+ }
+ close(fd); /* close again, as we need a stream further on */
+ }
+ else {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ /* the copies below are clumpsy, but there is no way around given the
+ * anomalies in dirname() and basename() [they MODIFY the provided buffer...]
+ */
+ uchar szNameBuf[MAXFNAME+1];
+ uchar szDirName[MAXFNAME+1];
+ uchar szBaseName[MAXFNAME+1];
+ ustrncpy(szNameBuf, newFileName, MAXFNAME);
+ szNameBuf[MAXFNAME] = '\0';
+ ustrncpy(szDirName, (uchar*)dirname((char*)szNameBuf), MAXFNAME);
+ szDirName[MAXFNAME] = '\0';
+ ustrncpy(szNameBuf, newFileName, MAXFNAME);
+ szNameBuf[MAXFNAME] = '\0';
+ ustrncpy(szBaseName, (uchar*)basename((char*)szNameBuf), MAXFNAME);
+ szBaseName[MAXFNAME] = '\0';
+
+ CHKiRet(strm.Construct(&pData->pStrm));
+ CHKiRet(strm.SetFName(pData->pStrm, szBaseName, ustrlen(szBaseName)));
+ CHKiRet(strm.SetDir(pData->pStrm, szDirName, ustrlen(szDirName)));
+ CHKiRet(strm.SetiZipLevel(pData->pStrm, pData->iZipLevel));
+ CHKiRet(strm.SetbVeryReliableZip(pData->pStrm, pData->bVeryRobustZip));
+ CHKiRet(strm.SetsIOBufSize(pData->pStrm, (size_t) pData->iIOBufSize));
+ CHKiRet(strm.SettOperationsMode(pData->pStrm, STREAMMODE_WRITE_APPEND));
+ CHKiRet(strm.SettOpenMode(pData->pStrm, cs.fCreateMode));
+ CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile));
+ CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit));
+ if(pData->useCryprov) {
+ CHKiRet(strm.Setcryprov(pData->pStrm, &pData->cryprov));
+ CHKiRet(strm.SetcryprovData(pData->pStrm, pData->cryprovData));
+ }
+ /* set the flush interval only if we actually use it - otherwise it will activate
+ * async processing, which is a real performance waste if we do not do buffered
+ * writes! -- rgerhards, 2009-07-06
+ */
+ if(pData->bUseAsyncWriter)
+ CHKiRet(strm.SetiFlushInterval(pData->pStrm, pData->iFlushInterval));
+ if(pData->pszSizeLimitCmd != NULL)
+ CHKiRet(strm.SetpszSizeLimitCmd(pData->pStrm, ustrdup(pData->pszSizeLimitCmd)));
+ CHKiRet(strm.ConstructFinalize(pData->pStrm));
+
+ if(pData->useSigprov)
+ sigprovPrepare(pData, szNameBuf);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pData->pStrm != NULL) {
+ closeFile(pData);
+ }
+ }
+ RETiRet;
+}
+
+// <kortemik date="2018-02-20">
+/* verify enough we have space left for writes */
+static rsRetVal
+fsCheck(instanceData *__restrict__ const pData, const uchar *__restrict__ const fileName)
+{
+ DEFiRet;
+ struct statvfs stat;
+ char *pathcopy;
+ const char *path;
+
+ pathcopy = strdup((char*)fileName);
+ path = dirname(pathcopy);
+
+ if (statvfs(path, &stat) != 0) {
+ iRet = RS_RET_FILE_NO_STAT;
+ LogError(0, iRet, "could not stat %s", path);
+ FINALIZE;
+ }
+
+ /* check if we have space available for all buffers to be flushed and for
+ * a maximum length message, perhaps current msg size would be enough */
+ if (stat.f_bsize * stat.f_bavail <
+ pData->iIOBufSize * pData->iDynaFileCacheSize + (uint)(glbl.GetMaxLine(runModConf->pConf)))
+ {
+ iRet = RS_RET_FS_ERR;
+ LogError(0, iRet, "too few available blocks in %s", path);
+ FINALIZE;
+ }
+ /* there must be enough inodes left, one is left for administrative purposes
+ * check is not done if file system reports 0 total inodes, such as btrfs */
+ if (stat.f_favail < 2 && stat.f_files > 0)
+ {
+ iRet = RS_RET_FS_ERR;
+ LogError(0, iRet, "too few available inodes in %s", path);
+ FINALIZE;
+ }
+
+ /* file system must not be read only */
+ if (stat.f_flag == ST_RDONLY)
+ {
+ iRet = RS_RET_FS_ERR;
+ LogError(0, iRet, "file-system is read-only in %s", path);
+ FINALIZE;
+ }
+
+ iRet = RS_RET_OK;
+
+finalize_it:
+ if (pathcopy != NULL)
+ free(pathcopy);
+ RETiRet;
+}
+// </kortemik>
+
+/* This function handles dynamic file names. It checks if the
+ * requested file name is already open and, if not, does everything
+ * needed to switch to the it.
+ * Function returns 0 if all went well and non-zero otherwise.
+ * On successful return pData->fd must point to the correct file to
+ * be written.
+ * This is a helper to writeFile(). rgerhards, 2007-07-03
+ */
+static rsRetVal
+prepareDynFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName)
+{
+ uint64 ctOldest; /* "timestamp" of oldest element */
+ int iOldest;
+ uint i;
+ int iFirstFree;
+ rsRetVal localRet;
+ dynaFileCacheEntry **pCache;
+ DEFiRet;
+
+ assert(pData != NULL);
+ assert(newFileName != NULL);
+
+ pCache = pData->dynCache;
+
+ /* first check, if we still have the current file */
+ if( (pData->iCurrElt != -1)
+ && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) {
+ CHKiRet(fsCheck(pData, newFileName));
+
+ /* great, we are all set */
+ pCache[pData->iCurrElt]->clkTickAccessed = getClockFileAccess();
+ STATSCOUNTER_INC(pData->ctrLevel0, pData->mutCtrLevel0);
+ /* LRU needs only a strictly monotonically increasing counter, so such a one could do */
+ FINALIZE;
+ }
+
+ /* ok, no luck. Now let's search the table if we find a matching spot.
+ * While doing so, we also prepare for creation of a new one.
+ */
+ pData->iCurrElt = -1; /* invalid current element pointer */
+ iFirstFree = -1; /* not yet found */
+ iOldest = 0; /* we assume the first element to be the oldest - that will change as we loop */
+ ctOldest = getClockFileAccess(); /* there must always be an older one */
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL || pCache[i]->pName == NULL) {
+ if(iFirstFree == -1)
+ iFirstFree = i;
+ } else { /* got an element, let's see if it matches */
+ if(!ustrcmp(newFileName, pCache[i]->pName)) {
+ CHKiRet(fsCheck(pData, newFileName));
+
+ /* we found our element! */
+ pData->pStrm = pCache[i]->pStrm;
+ if(pData->useSigprov)
+ pData->sigprovFileData = pCache[i]->sigprovFileData;
+ pData->iCurrElt = i;
+ pCache[i]->clkTickAccessed = getClockFileAccess(); /* update "timestamp" for LRU */
+ FINALIZE;
+ }
+ /* did not find it - so lets keep track of the counters for LRU */
+ if(pCache[i]->clkTickAccessed < ctOldest) {
+ ctOldest = pCache[i]->clkTickAccessed;
+ iOldest = i;
+ }
+ }
+ }
+
+ /* we have not found an entry */
+ STATSCOUNTER_INC(pData->ctrMiss, pData->mutCtrMiss);
+
+ /* similarly, we need to set the current pStrm to NULL, because otherwise, if prepareFile() fails,
+ * we may end up using an old stream. This bug depends on how exactly prepareFile fails,
+ * but it could be triggered in the common case of a failed open() system call.
+ * rgerhards, 2010-03-22
+ */
+ pData->pStrm = NULL, pData->sigprovFileData = NULL;
+
+ if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) {
+ /* there is space left, so set it to that index */
+ iFirstFree = pData->iCurrCacheSize++;
+ STATSCOUNTER_SETMAX_NOMUT(pData->ctrMax, (unsigned) pData->iCurrCacheSize);
+ }
+
+ /* Note that the following code sequence does not work with the cache entry itself,
+ * but rather with pData->pStrm, the (sole) stream pointer in the non-dynafile case.
+ * The cache array is only updated after the open was successful. -- rgerhards, 2010-03-21
+ */
+ if(iFirstFree == -1) {
+ dynaFileDelCacheEntry(pData, iOldest, 0);
+ STATSCOUNTER_INC(pData->ctrEvict, pData->mutCtrEvict);
+ iFirstFree = iOldest; /* this one *is* now free ;) */
+ } else {
+ /* we need to allocate memory for the cache structure */
+ CHKmalloc(pCache[iFirstFree] = (dynaFileCacheEntry*) calloc(1, sizeof(dynaFileCacheEntry)));
+ }
+
+ /* Ok, we finally can open the file */
+ localRet = prepareFile(pData, newFileName); /* ignore exact error, we check fd below */
+
+ /* check if we had an error */
+ if(localRet != RS_RET_OK) {
+ /* We do no longer care about internal messages. The errmsg rate limiter
+ * will take care of too-frequent error messages.
+ */
+ parser_errmsg("Could not open dynamic file '%s' [state %d]", newFileName, localRet);
+ ABORT_FINALIZE(localRet);
+ }
+
+ localRet = fsCheck(pData, newFileName);
+ if(localRet != RS_RET_OK) {
+ parser_errmsg("Invalid file-system condition for dynamic file '%s' [state %d]", newFileName, localRet);
+ ABORT_FINALIZE(localRet);
+ }
+
+ if((pCache[iFirstFree]->pName = ustrdup(newFileName)) == NULL) {
+ closeFile(pData); /* need to free failed entry! */
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pCache[iFirstFree]->pStrm = pData->pStrm;
+ if(pData->useSigprov)
+ pCache[iFirstFree]->sigprovFileData = pData->sigprovFileData;
+ pCache[iFirstFree]->clkTickAccessed = getClockFileAccess();
+ pData->iCurrElt = iFirstFree;
+ DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName);
+
+finalize_it:
+ if(iRet == RS_RET_OK)
+ pCache[pData->iCurrElt]->nInactive = 0;
+ RETiRet;
+}
+
+
+/* do the actual write process. This function is to be called once we are ready for writing.
+ * It will do buffered writes and persist data only when the buffer is full. Note that we must
+ * be careful to detect when the file handle changed.
+ * rgerhards, 2009-06-03
+ */
+static rsRetVal
+doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf)
+{
+ DEFiRet;
+ assert(pData != NULL);
+ assert(pszBuf != NULL);
+
+ DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, strt data %.128s\n",
+ pData->pStrm, lenBuf, pszBuf);
+ if(pData->pStrm != NULL){
+ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf));
+ if(pData->useSigprov) {
+ CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, pszBuf, lenBuf));
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* rgerhards 2004-11-11: write to a file output. */
+static rsRetVal
+writeFile(instanceData *__restrict__ const pData,
+ const actWrkrIParams_t *__restrict__ const pParam,
+ const int iMsg)
+{
+ DEFiRet;
+
+ STATSCOUNTER_INC(pData->ctrRequests, pData->mutCtrRequests);
+ /* first check if we have a dynamic file name and, if so,
+ * check if it still is ok or a new file needs to be created
+ */
+ if(pData->bDynamicName) {
+ DBGPRINTF("omfile: file to log to: %s\n",
+ actParam(pParam, pData->iNumTpls, iMsg, 1).param);
+ CHKiRet(prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param));
+ } else { /* "regular", non-dynafile */
+ if(pData->pStrm == NULL) {
+ CHKiRet(prepareFile(pData, pData->fname));
+ if(pData->pStrm == NULL) {
+ parser_errmsg(
+ "Could not open output file '%s'", pData->fname);
+ }
+ CHKiRet(fsCheck(pData, pData->fname));
+ }
+ pData->nInactive = 0;
+ }
+
+ iRet = doWrite(pData, actParam(pParam, pData->iNumTpls, iMsg, 0).param,
+ actParam(pParam, pData->iNumTpls, iMsg, 0).lenStr);
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ pModConf->fCreateMode = 0644;
+ pModConf->fDirCreateMode = 0700;
+ pModConf->fileUID = -1;
+ pModConf->dirUID = -1;
+ pModConf->fileGID = -1;
+ pModConf->dirGID = -1;
+ pModConf->bDynafileDoNotSuspend = 1;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omfile:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pszFileDfltTplName != NULL) {
+ parser_errmsg("omfile: warning: default template was already "
+ "set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "dircreatemode")) {
+ loadModConf->fDirCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filecreatemode")) {
+ loadModConf->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirowner")) {
+ loadModConf->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirownernum")) {
+ loadModConf->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirgroup")) {
+ loadModConf->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirgroupnum")) {
+ loadModConf->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "fileowner")) {
+ loadModConf->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "fileownernum")) {
+ loadModConf->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filegroup")) {
+ loadModConf->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filegroupnum")) {
+ loadModConf->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dynafile.donotsuspend")) {
+ loadModConf->bDynafileDoNotSuspend = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("omfile: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+/* This function checks dynafile cache for janitor action */
+static void
+janitorChkDynaFiles(instanceData *__restrict__ const pData)
+{
+ uint i;
+ dynaFileCacheEntry **pCache = pData->dynCache;
+
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL)
+ continue;
+ DBGPRINTF("omfile janitor: checking dynafile %d:%s, inactive since %d\n", i,
+ pCache[i]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[i]->pName,
+ (int) pCache[i]->nInactive);
+ if(pCache[i]->nInactive >= pData->iCloseTimeout) {
+ STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ dynaFileDelCacheEntry(pData, i, 1);
+ if(pData->iCurrElt >= 0) {
+ if((uint)(pData->iCurrElt) == i)
+ pData->iCurrElt = -1; /* no longer available! */
+ }
+ } else {
+ pCache[i]->nInactive += runModConf->pConf->globals.janitorInterval;
+ }
+ }
+}
+
+/* callback for the janitor. This cleans out files (if so configured) */
+static void
+janitorCB(void *pUsr)
+{
+ instanceData *__restrict__ const pData = (instanceData *) pUsr;
+ pthread_mutex_lock(&pData->mutWrite);
+ if(pData->bDynamicName) {
+ janitorChkDynaFiles(pData);
+ } else {
+ if(pData->pStrm != NULL) {
+ DBGPRINTF("omfile janitor: checking file %s, inactive since %d\n",
+ pData->fname, pData->nInactive);
+ if(pData->nInactive >= pData->iCloseTimeout) {
+ STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ closeFile(pData);
+ } else {
+ pData->nInactive += runModConf->pConf->globals.janitorInterval;
+ }
+ }
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+}
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->pStrm = NULL;
+ pthread_mutex_init(&pData->mutWrite, NULL);
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ free(pData->fname);
+ if(pData->iCloseTimeout > 0)
+ janitorDelEtry(pData->janitorID);
+ if(pData->bDynamicName) {
+ dynaFileFreeCache(pData);
+ } else if(pData->pStrm != NULL)
+ closeFile(pData);
+ if(pData->stats != NULL)
+ statsobj.Destruct(&(pData->stats));
+ if(pData->useSigprov) {
+ pData->sigprov.Destruct(&pData->sigprovData);
+ obj.ReleaseObj(__FILE__, pData->sigprovNameFull+2, pData->sigprovNameFull,
+ (void*) &pData->sigprov);
+ free(pData->sigprovName);
+ free(pData->sigprovNameFull);
+ }
+ if(pData->useCryprov) {
+ pData->cryprov.Destruct(&pData->cryprovData);
+ obj.ReleaseObj(__FILE__, pData->cryprovNameFull+2, pData->cryprovNameFull,
+ (void*) &pData->cryprov);
+ free(pData->cryprovName);
+ free(pData->cryprovNameFull);
+ }
+ pthread_mutex_destroy(&pData->mutWrite);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ /* we have nothing to do to begin a transaction */
+ENDbeginTransaction
+
+
+BEGINcommitTransaction
+ instanceData *__restrict__ const pData = pWrkrData->pData;
+ unsigned i;
+CODESTARTcommitTransaction
+ pthread_mutex_lock(&pData->mutWrite);
+
+ for(i = 0 ; i < nParams ; ++i) {
+ CHKiRet(writeFile(pData, pParams, i));
+ }
+ /* Note: pStrm may be NULL if there was an error opening the stream */
+ /* if bFlushOnTXEnd is set, we need to flush on transaction end - in
+ * any case. It is not relevant if this is using background writes
+ * (which then become pretty slow) or not. And, similarly, no flush
+ * happens when it is not set. Please see
+ * https://github.com/rsyslog/rsyslog/issues/1297
+ * for a discussion of why we actually need this.
+ * rgerhards, 2017-01-13
+ */
+ if(pData->bFlushOnTXEnd && pData->pStrm != NULL) {
+ CHKiRet(strm.Flush(pData->pStrm));
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (runModConf->bDynafileDoNotSuspend == 0 || !(pData->bDynamicName)) {
+ LogError(0, iRet, "suspending action");
+ iRet = RS_RET_SUSPENDED;
+ }
+ else {
+ LogError(0, iRet, "discarding message");
+ }
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+ENDcommitTransaction
+
+
+static void
+setInstParamDefaults(instanceData *__restrict__ const pData)
+{
+ pData->fname = NULL;
+ pData->tplName = NULL;
+ pData->fileUID = loadModConf->fileUID;
+ pData->fileGID = loadModConf->fileGID;
+ pData->dirUID = loadModConf->dirUID;
+ pData->dirGID = loadModConf->dirGID;
+ pData->bFailOnChown = 1;
+ pData->iDynaFileCacheSize = 10;
+ pData->fCreateMode = loadModConf->fCreateMode;
+ pData->fDirCreateMode = loadModConf->fDirCreateMode;
+ pData->bCreateDirs = 1;
+ pData->bSyncFile = 0;
+ pData->iZipLevel = 0;
+ pData->bVeryRobustZip = 0;
+ pData->bFlushOnTXEnd = FLUSHONTX_DFLT;
+ pData->iIOBufSize = IOBUF_DFLT_SIZE;
+ pData->iFlushInterval = FLUSH_INTRVL_DFLT;
+ pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+ pData->sigprovName = NULL;
+ pData->cryprovName = NULL;
+ pData->useSigprov = 0;
+ pData->useCryprov = 0;
+ pData->iCloseTimeout = -1;
+}
+
+
+static rsRetVal
+setupInstStatsCtrs(instanceData *__restrict__ const pData)
+{
+ uchar ctrName[512];
+ DEFiRet;
+
+ if(!pData->bDynamicName) {
+ FINALIZE;
+ }
+
+ /* support statistics gathering */
+ snprintf((char*)ctrName, sizeof(ctrName), "dynafile cache %s", pData->fname);
+ ctrName[sizeof(ctrName)-1] = '\0'; /* be on the save side */
+ CHKiRet(statsobj.Construct(&(pData->stats)));
+ CHKiRet(statsobj.SetName(pData->stats, ctrName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar*)"omfile"));
+ STATSCOUNTER_INIT(pData->ctrRequests, pData->mutCtrRequests);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("requests"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrRequests)));
+ STATSCOUNTER_INIT(pData->ctrLevel0, pData->mutCtrLevel0);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("level0"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrLevel0)));
+ STATSCOUNTER_INIT(pData->ctrMiss, pData->mutCtrMiss);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("missed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMiss)));
+ STATSCOUNTER_INIT(pData->ctrEvict, pData->mutCtrEvict);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("evicted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrEvict)));
+ STATSCOUNTER_INIT(pData->ctrMax, pData->mutCtrMax);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("maxused"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMax)));
+ STATSCOUNTER_INIT(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("closetimeouts"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrCloseTimeouts)));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+initSigprov(instanceData *__restrict__ const pData, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmsig_%s", pData->sigprovName)
+ == sizeof(szDrvrName)) {
+ parser_errmsg("omfile: signature provider "
+ "name is too long: '%s' - signatures disabled",
+ pData->sigprovName);
+ goto done;
+ }
+ pData->sigprovNameFull = ustrdup(szDrvrName);
+
+ pData->sigprov.ifVersion = sigprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pData->sigprov)
+ != RS_RET_OK) {
+ parser_errmsg("omfile: could not load "
+ "signature provider '%s' - signatures disabled",
+ szDrvrName);
+ goto done;
+ }
+
+ if(pData->sigprov.Construct(&pData->sigprovData) != RS_RET_OK) {
+ parser_errmsg("omfile: error constructing "
+ "signature provider %s dataset - signatures disabled",
+ szDrvrName);
+ goto done;
+ }
+ pData->sigprov.SetCnfParam(pData->sigprovData, lst);
+
+ dbgprintf("loaded signature provider %s, data instance at %p\n",
+ szDrvrName, pData->sigprovData);
+ pData->useSigprov = 1;
+done: return;
+}
+
+static rsRetVal
+initCryprov(instanceData *__restrict__ const pData, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+ DEFiRet;
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pData->cryprovName)
+ == sizeof(szDrvrName)) {
+ parser_errmsg("omfile: crypto provider "
+ "name is too long: '%s' - encryption disabled",
+ pData->cryprovName);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pData->cryprovNameFull = ustrdup(szDrvrName);
+
+ pData->cryprov.ifVersion = cryprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pData->cryprov)
+ != RS_RET_OK) {
+ parser_errmsg("omfile: could not load "
+ "crypto provider '%s' - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+
+ if(pData->cryprov.Construct(&pData->cryprovData) != RS_RET_OK) {
+ parser_errmsg("omfile: error constructing "
+ "crypto provider %s dataset - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+ CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst, CRYPROV_PARAMTYPE_REGULAR));
+
+ dbgprintf("loaded crypto provider %s, data instance at %p\n",
+ szDrvrName, pData->cryprovData);
+ pData->useCryprov = 1;
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplToUse;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omfile)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("omfile: either the \"file\" or "
+ "\"dynafile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omfile:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "dynafilecachesize")) {
+ pData->iDynaFileCacheSize = (uint) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) {
+ pData->iZipLevel = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushinterval")) {
+ pData->iFlushInterval = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "veryrobustzip")) {
+ pData->bVeryRobustZip = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "asyncwriting")) {
+ pData->bUseAsyncWriter = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushontxend")) {
+ pData->bFlushOnTXEnd = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "iobuffersize")) {
+ pData->iIOBufSize = (uint) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirowner")) {
+ pData->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirownernum")) {
+ pData->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirgroup")) {
+ pData->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirgroupnum")) {
+ pData->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "fileowner")) {
+ pData->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "fileownernum")) {
+ pData->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filegroup")) {
+ pData->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filegroupnum")) {
+ pData->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dircreatemode")) {
+ pData->fDirCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filecreatemode")) {
+ pData->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "failonchownfailure")) {
+ pData->bFailOnChown = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "sync")) {
+ pData->bSyncFile = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "createdirs")) {
+ pData->bCreateDirs = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "file")) {
+ pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ pData->bDynamicName = 0;
+ } else if(!strcmp(actpblk.descr[i].name, "dynafile")) {
+ if(pData->fname != NULL) {
+ parser_errmsg("omfile: both \"file\" and \"dynafile\" set, will use dynafile");
+ }
+ pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(2)
+ pData->bDynamicName = 1;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "sig.provider")) {
+ pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) {
+ pData->cryprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "closetimeout")) {
+ pData->iCloseTimeout = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("omfile: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->fname == NULL) {
+ parser_errmsg("omfile: either the \"file\" or "
+ "\"dynafile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(pData->sigprovName != NULL) {
+ initSigprov(pData, lst);
+ }
+
+ if(pData->cryprovName != NULL) {
+ CHKiRet(initCryprov(pData, lst));
+ }
+
+ tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
+ pData->iNumTpls = 1;
+
+ if(pData->bDynamicName) {
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS));
+ pData->iNumTpls = 2;
+ // TODO: create unified code for this (legacy+v6 system)
+ /* we now allocate the cache table */
+ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+ calloc(pData->iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ pData->iCurrElt = -1; /* no current element */
+ }
+// TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
+ setupInstStatsCtrs(pData);
+
+ if(pData->iCloseTimeout == -1) { /* unset? */
+ pData->iCloseTimeout = (pData->bDynamicName) ? 10 : 0;
+ }
+
+ snprintf(pData->janitorID, sizeof(pData->janitorID), "omfile:%sfile:%s:%p",
+ (pData->bDynamicName) ? "dyna" : "", pData->fname, pData);
+ pData->janitorID[sizeof(pData->janitorID)-1] = '\0'; /* just in case... */
+
+ if(pData->iCloseTimeout > 0)
+ janitorAddEtry(janitorCB, pData->janitorID, pData);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ uchar fname[MAXFNAME];
+CODESTARTparseSelectorAct
+ /* Note: the indicator sequence permits us to use '$' to signify
+ * outchannel, what otherwise is not possible due to truely
+ * unresolvable grammar conflicts (*this time no way around*).
+ * rgerhards, 2011-07-09
+ */
+ if(!strncmp((char*) p, ":omfile:", sizeof(":omfile:") - 1)) {
+ p += sizeof(":omfile:") - 1;
+ }
+ if(!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-'))
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+
+ CHKiRet(createInstance(&pData));
+
+ if(*p == '-') {
+ pData->bSyncFile = 0;
+ p++;
+ } else {
+ pData->bSyncFile = cs.bEnableSync;
+ }
+ pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
+
+ switch(*p) {
+ case '$':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ pData->iNumTpls = 1;
+ /* rgerhards 2005-06-21: this is a special setting for output-channel
+ * definitions. In the long term, this setting will probably replace
+ * anything else, but for the time being we must co-exist with the
+ * traditional mode lines.
+ * rgerhards, 2007-07-24: output-channels will go away. We keep them
+ * for compatibility reasons, but seems to have been a bad idea.
+ */
+ CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+ pData->bDynamicName = 0;
+ break;
+
+ case '?': /* This is much like a regular file handle, but we need to obtain
+ * a template name. rgerhards, 2007-07-03
+ */
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ pData->iNumTpls = 2;
+ ++p; /* eat '?' */
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl()));
+ pData->fname = ustrdup(fname);
+ pData->bDynamicName = 1;
+ pData->iCurrElt = -1; /* no current element */
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS));
+ /* we now allocate the cache table */
+ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+ calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ break;
+
+ case '/':
+ case '.':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ pData->iNumTpls = 1;
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl()));
+ pData->fname = ustrdup(fname);
+ pData->bDynamicName = 0;
+ break;
+ default:
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* freeze current paremeters for this action */
+ pData->iDynaFileCacheSize = cs.iDynaFileCacheSize;
+ pData->fCreateMode = cs.fCreateMode;
+ pData->fDirCreateMode = cs.fDirCreateMode;
+ pData->bCreateDirs = cs.bCreateDirs;
+ pData->bFailOnChown = cs.bFailOnChown;
+ pData->fileUID = cs.fileUID;
+ pData->fileGID = cs.fileGID;
+ pData->dirUID = cs.dirUID;
+ pData->dirGID = cs.dirGID;
+ pData->iZipLevel = cs.iZipLevel;
+ pData->bFlushOnTXEnd = cs.bFlushOnTXEnd;
+ pData->iIOBufSize = (uint) cs.iIOBufSize;
+ pData->iFlushInterval = cs.iFlushInterval;
+ pData->bUseAsyncWriter = cs.bUseAsyncWriter;
+ pData->bVeryRobustZip = 0; /* cannot be specified via legacy conf */
+ pData->iCloseTimeout = 0; /* cannot be specified via legacy conf */
+ setupInstStatsCtrs(pData);
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.fileUID = -1;
+ cs.fileGID = -1;
+ cs.dirUID = -1;
+ cs.dirGID = -1;
+ cs.bFailOnChown = 1;
+ cs.iDynaFileCacheSize = 10;
+ cs.fCreateMode = 0644;
+ cs.fDirCreateMode = 0700;
+ cs.bCreateDirs = 1;
+ cs.bEnableSync = 0;
+ cs.iZipLevel = 0;
+ cs.bFlushOnTXEnd = FLUSHONTX_DFLT;
+ cs.iIOBufSize = IOBUF_DFLT_SIZE;
+ cs.iFlushInterval = FLUSH_INTRVL_DFLT;
+ cs.bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutWrite);
+ if(pData->bDynamicName) {
+ dynaFileFreeCacheEntries(pData);
+ } else {
+ if(pData->pStrm != NULL) {
+ closeFile(pData);
+ }
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+ENDdoHUP
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(strm, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ DESTROY_ATOMIC_HELPER_MUT(mutClock);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+ENDqueryEtryPt
+
+
+BEGINmodInit(File)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+INITLegCnfVars
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ INIT_ATOMIC_HELPER_MUT(mutClock);
+
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, setDynaFileCacheSize,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &cs.iZipLevel,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &cs.iFlushInterval,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileasyncwriting", 0, eCmdHdlrBinary, NULL, &cs.bUseAsyncWriter,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &cs.bFlushOnTXEnd,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &cs.iIOBufSize,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &cs.dirUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirownernum", 0, eCmdHdlrInt, NULL, &cs.dirUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &cs.dirGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroupnum", 0, eCmdHdlrInt, NULL, &cs.dirGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &cs.fileUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileownernum", 0, eCmdHdlrInt, NULL, &cs.fileUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &cs.fileGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroupnum", 0, eCmdHdlrInt, NULL, &cs.fileGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL,
+ &cs.fDirCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL,
+ &cs.fCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &cs.bCreateDirs,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &cs.bFailOnChown,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrGoneAway, NULL, NULL,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &cs.bEnableSync,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/omhiredis/COPYING b/contrib/omhiredis/COPYING
new file mode 100644
index 0000000..f44bd49
--- /dev/null
+++ b/contrib/omhiredis/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/contrib/omhiredis/Makefile.am b/contrib/omhiredis/Makefile.am
new file mode 100644
index 0000000..2332be4
--- /dev/null
+++ b/contrib/omhiredis/Makefile.am
@@ -0,0 +1,7 @@
+pkglib_LTLIBRARIES = omhiredis.la
+omhiredis_la_SOURCES = omhiredis.c
+omhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS)
+omhiredis_la_LDFLAGS = -module -avoid-version
+omhiredis_la_LIBADD = $(HIREDIS_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/omhiredis/Makefile.in b/contrib/omhiredis/Makefile.in
new file mode 100644
index 0000000..8ac13e7
--- /dev/null
+++ b/contrib/omhiredis/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omhiredis
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omhiredis_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omhiredis_la_OBJECTS = omhiredis_la-omhiredis.lo
+omhiredis_la_OBJECTS = $(am_omhiredis_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 =
+omhiredis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omhiredis_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omhiredis_la-omhiredis.Plo
+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 = $(omhiredis_la_SOURCES)
+DIST_SOURCES = $(omhiredis_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING \
+ README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omhiredis.la
+omhiredis_la_SOURCES = omhiredis.c
+omhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS)
+omhiredis_la_LDFLAGS = -module -avoid-version
+omhiredis_la_LIBADD = $(HIREDIS_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/omhiredis/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omhiredis/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omhiredis.la: $(omhiredis_la_OBJECTS) $(omhiredis_la_DEPENDENCIES) $(EXTRA_omhiredis_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omhiredis_la_LINK) -rpath $(pkglibdir) $(omhiredis_la_OBJECTS) $(omhiredis_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhiredis_la-omhiredis.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omhiredis_la-omhiredis.lo: omhiredis.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhiredis_la-omhiredis.lo -MD -MP -MF $(DEPDIR)/omhiredis_la-omhiredis.Tpo -c -o omhiredis_la-omhiredis.lo `test -f 'omhiredis.c' || echo '$(srcdir)/'`omhiredis.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhiredis_la-omhiredis.Tpo $(DEPDIR)/omhiredis_la-omhiredis.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhiredis.c' object='omhiredis_la-omhiredis.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) $(omhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhiredis_la-omhiredis.lo `test -f 'omhiredis.c' || echo '$(srcdir)/'`omhiredis.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omhiredis_la-omhiredis.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omhiredis_la-omhiredis.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omhiredis/README b/contrib/omhiredis/README
new file mode 100644
index 0000000..56b7030
--- /dev/null
+++ b/contrib/omhiredis/README
@@ -0,0 +1,70 @@
+Redis Outplug Plugin using hiredis library
+
+REQUIREMENTS:
+
+* hiredis ( https://github.com/redis/hiredis.git )
+
+USAGE:
+
+This plugin has three current "modes" that it supports:
+
+1. "template"
+
+This is the original mode that the plugin supported. You use an rsyslog template
+to construct a command that is sent directly to redis. This mode currently has
+an issue dealing with strings that contain spaces. It's useful for doing things
+like incrementing counters for statistics.
+
+```
+module(load="omhiredis")
+
+template(
+ name="simple_count"
+ type="string"
+ string="HINCRBY testcount %programname% 1")
+
+*.* action(
+ name="count_redis"
+ type="omhiredis"
+ mode="template"
+ template="simple_count"
+ )
+```
+
+2. "queue"
+The queue mode will LPUSH your message to a redis list. Unlike the template
+mode, it handles full rsyslog messages properly. If a template is not
+supplied, it will default to the RSYSLOG_ForwardFormat template. The "key"
+parameter is required.
+
+```
+module(load="omhiredis")
+
+*.* action(
+ name="push_redis"
+ type="omhiredis"
+ mode="queue"
+ key="testqueue"
+ )
+```
+
+3. "publish"
+The publish mode will PUBLISH to a redis channel. Unlike the template mode,
+it handles full rsyslog messages properly. If a template is not supplied,
+it will default to the RSYSLOG_ForwardFormat template. The "key"
+parameter is required and will be used for the publish channel.
+
+```
+module(load="omhiredis")
+
+*.* action(
+ name="publish_redis"
+ type="omhiredis"
+ mode="publish"
+ key="testpublish"
+ )
+```
+
+
+NOTES
+* dequeuebatchsize now sets the pipeline size for hiredis, allowing pipelining commands.
diff --git a/contrib/omhiredis/omhiredis.c b/contrib/omhiredis/omhiredis.c
new file mode 100644
index 0000000..eb22ed8
--- /dev/null
+++ b/contrib/omhiredis/omhiredis.c
@@ -0,0 +1,753 @@
+/* omhiredis.c
+* Copyright 2012 Talksum, Inc
+* Copyright 2015 DigitalOcean, Inc
+*
+* 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, 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
+* 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, see
+* <http://www.gnu.org/licenses/>.
+*
+* Author: Brian Knox
+* <bknox@digitalocean.com>
+*/
+
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <signal.h>
+#include <time.h>
+#include <math.h>
+#include <hiredis/hiredis.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omhiredis")
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+#define OMHIREDIS_MODE_TEMPLATE 0
+#define OMHIREDIS_MODE_QUEUE 1
+#define OMHIREDIS_MODE_PUBLISH 2
+#define OMHIREDIS_MODE_SET 3
+#define OMHIREDIS_MODE_STREAM 4
+
+/* our instance data.
+ * this will be accessable
+ * via pData */
+typedef struct _instanceData {
+ uchar *server; /* redis server address */
+ int port; /* redis port */
+ uchar *serverpassword; /* redis password */
+ uchar *tplName; /* template name */
+ char *modeDescription; /* mode description */
+ int mode; /* mode constant */
+ uchar *key; /* key for QUEUE, PUBLISH and STREAM modes */
+ uchar *streamKeyAck; /* key name for STREAM ACKs (when enabled) */
+ uchar *streamGroupAck; /* group name for STREAM ACKs (when enabled) */
+ uchar *streamIndexAck; /* index name for STREAM ACKs (when enabled) */
+ int expiration; /* expiration value for SET/SETEX mode */
+ sbool dynaKey; /* Should we treat the key as a template? */
+ sbool streamDynaKeyAck; /* Should we treat the groupAck as a template? */
+ sbool streamDynaGroupAck; /* Should we treat the groupAck as a template? */
+ sbool streamDynaIndexAck; /* Should we treat the IndexAck as a template? */
+ sbool useRPush; /* Should we use RPUSH instead of LPUSH? */
+ uchar *streamOutField; /* Field to place message into (for stream insertions only) */
+ uint streamCapacityLimit; /* zero means stream is not capped (default)
+ setting a non-zero value ultimately activates the approximate MAXLEN option '~'
+ (see Redis XADD docs)*/
+ sbool streamAck; /* Should the module send an XACK for each inserted message?
+ This feature requires that 3 infos are present in the '$.' object of the log:
+ - $.redis!stream
+ - $.redis!group
+ - $.redis!index
+ Those 3 infos can either be provided through usage of imhiredis
+ or set manually with Rainerscript */
+ sbool streamDel; /* Should the module send an XDEL for each inserted message?
+ This feature requires that 2 infos are present in the '$.' object of the log:
+ - $.redis!stream
+ - $.redis!index
+ Those 2 infos can either be provided through usage of imhiredis
+ or set manually with Rainerscript */
+
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData; /* instanc data */
+ redisContext *conn; /* redis connection */
+ int count; /* count of command sent for current batch */
+} wrkrInstanceData_t;
+
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 0 },
+ { "serverport", eCmdHdlrInt, 0 },
+ { "serverpassword", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "key", eCmdHdlrGetWord, 0 },
+ { "expiration", eCmdHdlrInt, 0 },
+ { "dynakey", eCmdHdlrBinary, 0 },
+ { "userpush", eCmdHdlrBinary, 0 },
+ { "stream.outField", eCmdHdlrGetWord, 0 },
+ { "stream.capacityLimit", eCmdHdlrNonNegInt, 0 },
+ { "stream.ack", eCmdHdlrBinary, 0 },
+ { "stream.del", eCmdHdlrBinary, 0 },
+ { "stream.keyAck", eCmdHdlrGetWord, 0 },
+ { "stream.groupAck", eCmdHdlrGetWord, 0 },
+ { "stream.indexAck", eCmdHdlrGetWord, 0 },
+ { "stream.dynaKeyAck", eCmdHdlrBinary, 0 },
+ { "stream.dynaGroupAck", eCmdHdlrBinary, 0 },
+ { "stream.dynaIndexAck", eCmdHdlrBinary, 0 },
+};
+
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->conn = NULL; /* Connect later */
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+/* called when closing */
+static void closeHiredis(wrkrInstanceData_t *pWrkrData)
+{
+ if(pWrkrData->conn != NULL) {
+ redisFree(pWrkrData->conn);
+ pWrkrData->conn = NULL;
+ }
+}
+
+/* Free our instance data. */
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if (pData->server != NULL) {
+ free(pData->server);
+ }
+ free(pData->key);
+ free(pData->modeDescription);
+ free(pData->serverpassword);
+ free(pData->tplName);
+ free(pData->streamKeyAck);
+ free(pData->streamGroupAck);
+ free(pData->streamIndexAck);
+ free(pData->streamOutField);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ closeHiredis(pWrkrData);
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ENDdbgPrintInstInfo
+
+/* establish our connection to redis */
+static rsRetVal initHiredis(wrkrInstanceData_t *pWrkrData, int bSilent)
+{
+ char *server;
+ redisReply *reply = NULL;
+ DEFiRet;
+
+ server = (pWrkrData->pData->server == NULL) ? (char *)"127.0.0.1" :
+ (char*) pWrkrData->pData->server;
+ DBGPRINTF("omhiredis: trying connect to '%s' at port %d\n", server,
+ pWrkrData->pData->port);
+
+ struct timeval timeout = { 1, 500000 }; /* 1.5 seconds */
+ pWrkrData->conn = redisConnectWithTimeout(server, pWrkrData->pData->port,
+ timeout);
+ if (pWrkrData->conn->err) {
+ if(!bSilent)
+ LogError(0, RS_RET_SUSPENDED,
+ "can not initialize redis handle");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if (pWrkrData->pData->serverpassword != NULL) {
+ reply = redisCommand(pWrkrData->conn, "AUTH %s", (char*) pWrkrData->pData->serverpassword);
+ if (reply == NULL) {
+ DBGPRINTF("omhiredis: could not get reply from AUTH command\n");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ else if (reply->type == REDIS_REPLY_ERROR) {
+ LogError(0, NO_ERRCODE, "omhiredis: error while authenticating: %s", reply->str);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK && pWrkrData-> conn != NULL) {
+ redisFree(pWrkrData->conn);
+ pWrkrData->conn = NULL;
+ }
+ if (reply != NULL) freeReplyObject(reply);
+ RETiRet;
+}
+
+static rsRetVal isMaster(wrkrInstanceData_t *pWrkrData) {
+ DEFiRet;
+ redisReply *reply = NULL;
+
+ assert(pWrkrData->conn != NULL);
+
+ reply = redisCommand(pWrkrData->conn, "ROLE");
+ if (reply == NULL) {
+ DBGPRINTF("omhiredis: could not get reply from ROLE command\n");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ else if (reply->type == REDIS_REPLY_ERROR) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "omhiredis: got an error while querying role -> "
+ "%s\n", reply->str);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ else if (reply->type != REDIS_REPLY_ARRAY || reply->element[0]->type != REDIS_REPLY_STRING) {
+ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "omhiredis: did not get a proper reply from ROLE command");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ else {
+ if (strncmp(reply->element[0]->str, "master", 6)) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "omhiredis: current connected node is not a master");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+finalize_it:
+ free(reply);
+ RETiRet;
+}
+
+static rsRetVal writeHiredis(uchar* key, uchar *message, wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ int rc, expire;
+ size_t msgLen;
+ char *formattedMsg = NULL;
+
+ /* if we do not have a redis connection, call
+ * initHiredis and try to establish one */
+ if(pWrkrData->conn == NULL)
+ CHKiRet(initHiredis(pWrkrData, 0));
+
+ /* try to append the command to the pipeline.
+ * REDIS_ERR reply indicates something bad
+ * happened, in which case abort. otherwise
+ * increase our current pipeline count
+ * by 1 and continue. */
+ switch(pWrkrData->pData->mode) {
+ case OMHIREDIS_MODE_TEMPLATE:
+ rc = redisAppendCommand(pWrkrData->conn, (char*)message);
+ break;
+ case OMHIREDIS_MODE_QUEUE:
+ rc = redisAppendCommand(pWrkrData->conn,
+ pWrkrData->pData->useRPush ? "RPUSH %s %s" : "LPUSH %s %s",
+ key, (char*)message);
+ break;
+ case OMHIREDIS_MODE_PUBLISH:
+ rc = redisAppendCommand(pWrkrData->conn, "PUBLISH %s %s", key, (char*)message);
+ break;
+ case OMHIREDIS_MODE_SET:
+ expire = pWrkrData->pData->expiration;
+
+ if (expire > 0)
+ msgLen = redisFormatCommand(&formattedMsg, "SETEX %s %d %s", key, expire, message);
+ else
+ msgLen = redisFormatCommand(&formattedMsg, "SET %s %s", key, message);
+ if (msgLen)
+ rc = redisAppendFormattedCommand(pWrkrData->conn, formattedMsg, msgLen);
+ else {
+ dbgprintf("omhiredis: could not append SET command\n");
+ rc = REDIS_ERR;
+ }
+ break;
+ case OMHIREDIS_MODE_STREAM:
+ if (pWrkrData->pData->streamCapacityLimit != 0) {
+ rc = redisAppendCommand(pWrkrData->conn, "XADD %s MAXLEN ~ %d * %s %s",
+ key,
+ pWrkrData->pData->streamCapacityLimit,
+ pWrkrData->pData->streamOutField,
+ message);
+ } else {
+ rc = redisAppendCommand(pWrkrData->conn, "XADD %s * %s %s",
+ key,
+ pWrkrData->pData->streamOutField,
+ message);
+ }
+ break;
+ default:
+ dbgprintf("omhiredis: mode %d is invalid something is really wrong\n",
+ pWrkrData->pData->mode);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if (rc == REDIS_ERR) {
+ LogError(0, NO_ERRCODE, "omhiredis: %s", pWrkrData->conn->errstr);
+ dbgprintf("omhiredis: %s\n", pWrkrData->conn->errstr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ pWrkrData->count++;
+ }
+
+finalize_it:
+ free(formattedMsg);
+ RETiRet;
+}
+
+static rsRetVal ackHiredisStreamIndex(wrkrInstanceData_t *pWrkrData, uchar *key, uchar *group, uchar *index) {
+ DEFiRet;
+
+ if (REDIS_ERR == redisAppendCommand(pWrkrData->conn, "XACK %s %s %s", key, group, index)) {
+ LogError(0, NO_ERRCODE, "omhiredis: %s", pWrkrData->conn->errstr);
+ DBGPRINTF("omhiredis: %s\n", pWrkrData->conn->errstr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ pWrkrData->count++;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal delHiredisStreamIndex(wrkrInstanceData_t *pWrkrData, uchar *key, uchar *index) {
+ DEFiRet;
+
+ if (REDIS_ERR == redisAppendCommand(pWrkrData->conn, "XDEL %s %s", key, index)) {
+ LogError(0, NO_ERRCODE, "omhiredis: %s", pWrkrData->conn->errstr);
+ DBGPRINTF("omhiredis: %s\n", pWrkrData->conn->errstr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ pWrkrData->count++;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* called when resuming from suspended state.
+ * try to restablish our connection to redis */
+BEGINtryResume
+CODESTARTtryResume
+ closeHiredis(pWrkrData);
+ CHKiRet(initHiredis(pWrkrData, 0));
+ // Must get a master node for all modes, except 'publish'
+ if(pWrkrData->pData->mode != OMHIREDIS_MODE_PUBLISH) {
+ CHKiRet(isMaster(pWrkrData));
+ }
+finalize_it:
+ENDtryResume
+
+/* begin a transaction.
+ * if I decide to use MULTI ... EXEC in the
+ * future, this block should send the
+ * MULTI command to redis. */
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ dbgprintf("omhiredis: beginTransaction called\n");
+ pWrkrData->count = 0;
+ENDbeginTransaction
+
+/* call writeHiredis for this log line,
+ * which appends it as a command to the
+ * current pipeline */
+BEGINdoAction
+ uchar *message, *key, *keyNameAck, *groupNameAck, *IndexNameAck;
+ int inputIndex = 0;
+CODESTARTdoAction
+ // Don't change the order of conditions/assignations here without changing the end of the newActInst function!
+ message = ppString[inputIndex++];
+ key = pWrkrData->pData->dynaKey ? ppString[inputIndex++] : pWrkrData->pData->key;
+ keyNameAck = pWrkrData->pData->streamDynaKeyAck ? ppString[inputIndex++] : pWrkrData->pData->streamKeyAck;
+ groupNameAck = pWrkrData->pData->streamDynaGroupAck ? ppString[inputIndex++] : pWrkrData->pData->streamGroupAck;
+ IndexNameAck = pWrkrData->pData->streamDynaIndexAck ? ppString[inputIndex++] : pWrkrData->pData->streamIndexAck;
+
+ CHKiRet(writeHiredis(key, message, pWrkrData));
+
+ if(pWrkrData->pData->streamAck) {
+ CHKiRet(ackHiredisStreamIndex(pWrkrData, keyNameAck, groupNameAck, IndexNameAck));
+ }
+ if(pWrkrData->pData->streamDel) {
+ CHKiRet(delHiredisStreamIndex(pWrkrData, keyNameAck, IndexNameAck));
+ }
+
+ iRet = RS_RET_DEFER_COMMIT;
+finalize_it:
+ENDdoAction
+
+/* called when we have reached the end of a
+ * batch (queue.dequeuebatchsize). this
+ * iterates over the replies, putting them
+ * into the pData->replies buffer. we currently
+ * don't really bother to check for errors
+ * which should be fixed */
+BEGINendTransaction
+CODESTARTendTransaction
+ dbgprintf("omhiredis: endTransaction called\n");
+ redisReply *reply;
+ int i;
+ for ( i = 0; i < pWrkrData->count; i++ ) {
+ if( REDIS_OK != redisGetReply( pWrkrData->conn, (void*)&reply) || pWrkrData->conn->err ) {
+ dbgprintf("omhiredis: %s\n", pWrkrData->conn->errstr);
+ LogError(0, RS_RET_REDIS_ERROR, "Error while processing replies: %s", pWrkrData->conn->errstr);
+ closeHiredis(pWrkrData);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ else {
+ if (reply->type == REDIS_REPLY_ERROR) {
+ LogError(0, RS_RET_REDIS_ERROR, "Received error from redis -> %s", reply->str);
+ closeHiredis(pWrkrData);
+ freeReplyObject(reply);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ freeReplyObject(reply);
+ }
+ }
+
+finalize_it:
+ENDendTransaction
+
+/* set defaults. note server is set to NULL
+ * and is set to a default in initHiredis if
+ * it is still null when it's called - I should
+ * probable just set the default here instead */
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->server = NULL;
+ pData->port = 6379;
+ pData->serverpassword = NULL;
+ pData->tplName = NULL;
+ pData->mode = OMHIREDIS_MODE_TEMPLATE;
+ pData->expiration = 0;
+ pData->modeDescription = NULL;
+ pData->key = NULL;
+ pData->dynaKey = 0;
+ pData->useRPush = 0;
+ pData->streamOutField = NULL;
+ pData->streamKeyAck = NULL;
+ pData->streamDynaKeyAck = 0;
+ pData->streamGroupAck = NULL;
+ pData->streamDynaGroupAck = 0;
+ pData->streamIndexAck = NULL;
+ pData->streamDynaIndexAck = 0;
+ pData->streamCapacityLimit = 0;
+ pData->streamAck = 0;
+ pData->streamDel = 0;
+}
+
+/* here is where the work to set up a new instance
+ * is done. this reads the config options from
+ * the rsyslog conf and takes appropriate setup
+ * actions. */
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int iNumTpls;
+ uchar *strDup = NULL;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL)
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ pData->server = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->port = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "serverpassword")) {
+ pData->serverpassword = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynakey")) {
+ pData->dynaKey = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "userpush")) {
+ pData->useRPush = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.outField")) {
+ pData->streamOutField = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "stream.keyAck")) {
+ pData->streamKeyAck = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "stream.dynaKeyAck")) {
+ pData->streamDynaKeyAck = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.groupAck")) {
+ pData->streamGroupAck = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "stream.dynaGroupAck")) {
+ pData->streamDynaGroupAck = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.indexAck")) {
+ pData->streamIndexAck = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "stream.dynaIndexAck")) {
+ pData->streamDynaIndexAck = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.capacityLimit")) {
+ pData->streamCapacityLimit = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.ack")) {
+ pData->streamAck = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "stream.del")) {
+ pData->streamDel = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "mode")) {
+ pData->modeDescription = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (!strcmp(pData->modeDescription, "template")) {
+ pData->mode = OMHIREDIS_MODE_TEMPLATE;
+ } else if (!strcmp(pData->modeDescription, "queue")) {
+ pData->mode = OMHIREDIS_MODE_QUEUE;
+ } else if (!strcmp(pData->modeDescription, "publish")) {
+ pData->mode = OMHIREDIS_MODE_PUBLISH;
+ } else if (!strcmp(pData->modeDescription, "set")) {
+ pData->mode = OMHIREDIS_MODE_SET;
+ } else if (!strcmp(pData->modeDescription, "stream")) {
+ pData->mode = OMHIREDIS_MODE_STREAM;
+ } else {
+ dbgprintf("omhiredis: unsupported mode %s\n", actpblk.descr[i].name);
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "expiration")) {
+ pData->expiration = pvals[i].val.d.n;
+ dbgprintf("omhiredis: expiration set to %d\n", pData->expiration);
+ } else {
+ dbgprintf("omhiredis: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ dbgprintf("omhiredis: checking config sanity\n");
+
+ if (!pData->modeDescription) {
+ dbgprintf("omhiredis: no mode specified, setting it to 'template'\n");
+ pData->mode = OMHIREDIS_MODE_TEMPLATE;
+ }
+
+ if (pData->mode == OMHIREDIS_MODE_STREAM && !pData->streamOutField) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: no stream.outField set, "\
+ "using 'msg' as default");
+ pData->streamOutField = ustrdup("msg");
+ }
+
+ if (pData->tplName == NULL) {
+ if(pData->mode == OMHIREDIS_MODE_TEMPLATE) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR, "omhiredis: selected mode requires a template");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ } else {
+ CHKmalloc(pData->tplName = ustrdup("RSYSLOG_ForwardFormat"));
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: no template set, "\
+ "using RSYSLOG_ForwardFormat as default");
+ }
+ }
+
+ if (pData->mode != OMHIREDIS_MODE_TEMPLATE && pData->key == NULL) {
+
+ LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "omhiredis: mode %s requires a key", pData->modeDescription);
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if (pData->expiration && pData->mode != OMHIREDIS_MODE_SET) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: expiration set but mode is not "\
+ "'set', expiration will be ignored");
+ }
+
+ if (pData->mode != OMHIREDIS_MODE_STREAM) {
+ if (pData->streamOutField) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.outField set "\
+ "but mode is not 'stream', field will be ignored");
+ }
+ if (pData->streamAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.ack set "\
+ "but mode is not 'stream', XACK will be ignored");
+ }
+ if (pData->streamDel) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.del set "\
+ "but mode is not 'stream', XDEL will be ignored");
+ }
+ if (pData->streamCapacityLimit) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.capacityLimit set "\
+ "but mode is not 'stream', stream trimming will be ignored");
+ }
+ if (pData->streamKeyAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.keyAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ if (pData->streamDynaKeyAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaKeyAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ if (pData->streamGroupAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.groupAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ if (pData->streamDynaGroupAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaGroupAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ if (pData->streamIndexAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.indexAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ if (pData->streamDynaIndexAck) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaIndexAck set "\
+ "but mode is not 'stream', parameter will be ignored");
+ }
+ } else {
+ if(pData->streamAck) {
+ if(!pData->streamKeyAck || !pData->streamGroupAck || !pData->streamIndexAck) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "omhiredis: 'stream.ack' is set but one of "\
+ "'stream.keyAck', 'stream.groupAck' or 'stream.indexAck' is missing");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ }
+ if(pData->streamDel) {
+ if(!pData->streamKeyAck || !pData->streamIndexAck) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "omhiredis: 'stream.del' is set but one of "\
+ "'stream.keyAck' or 'stream.indexAck' is missing");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ }
+ }
+
+ if (pData->streamDynaKeyAck && pData->streamKeyAck == NULL) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaKeyAck' set "\
+ "but 'stream.keyAck' is empty, disabling");
+ pData->streamDynaKeyAck = 0;
+ }
+ if (pData->streamDynaGroupAck && pData->streamGroupAck == NULL) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaGroupAck' set "\
+ "but 'stream.groupAck' is empty, disabling");
+ pData->streamDynaGroupAck = 0;
+ }
+ if (pData->streamDynaIndexAck && pData->streamIndexAck == NULL) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaGroupAck' set "\
+ "but 'stream.indexAck' is empty, disabling");
+ pData->streamDynaIndexAck = 0;
+ }
+
+ iNumTpls = 1;
+
+ if (pData->dynaKey) {
+ assert(pData->key != NULL);
+ iNumTpls += 1;
+ }
+ if (pData->streamDynaKeyAck) {
+ assert(pData->streamKeyAck != NULL);
+ iNumTpls += 1;
+ }
+ if (pData->streamDynaGroupAck) {
+ assert(pData->streamGroupAck != NULL);
+ iNumTpls += 1;
+ }
+ if (pData->streamDynaIndexAck) {
+ assert(pData->streamIndexAck != NULL);
+ iNumTpls += 1;
+ }
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls);
+
+ /* Insert templates in opposite order (keep in sync with doAction), order will be
+ * - tplName
+ * - key
+ * - streamKeyAck
+ * - streamGroupAck
+ * - streamIndexAck
+ */
+ if (pData->streamDynaIndexAck) {
+ CHKmalloc(strDup = ustrdup(pData->streamIndexAck));
+ CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS));
+ strDup = NULL; /* handed over */
+ }
+
+ if (pData->streamDynaGroupAck) {
+ CHKmalloc(strDup = ustrdup(pData->streamGroupAck));
+ CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS));
+ strDup = NULL; /* handed over */
+ }
+
+ if (pData->streamDynaKeyAck) {
+ CHKmalloc(strDup = ustrdup(pData->streamKeyAck));
+ CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS));
+ strDup = NULL; /* handed over */
+ }
+
+ if (pData->dynaKey) {
+ CHKmalloc(strDup = ustrdup(pData->key));
+ CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS));
+ strDup = NULL; /* handed over */
+ }
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, ustrdup(pData->tplName), OMSR_NO_RQD_TPL_OPTS));
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ free(strDup);
+ENDnewActInst
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+/* register our plugin entry points
+ * with the rsyslog core engine */
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* supports transaction interface */
+ENDqueryEtryPt
+
+/* note we do not support rsyslog v5 syntax */
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* only supports rsyslog 6 configs */
+CODEmodInit_QueryRegCFSLineHdlr
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ if (!bCoreSupportsBatching) {
+ LogError(0, NO_ERRCODE, "omhiredis: rsyslog core does not support batching - abort");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ DBGPRINTF("omhiredis: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/contrib/omhttp/Makefile.am b/contrib/omhttp/Makefile.am
new file mode 100644
index 0000000..cb29149
--- /dev/null
+++ b/contrib/omhttp/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omhttp.la
+
+omhttp_la_SOURCES = omhttp.c
+omhttp_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omhttp_la_LDFLAGS = -module -avoid-version
+omhttp_la_LIBADD = $(CURL_LIBS) $(LIBM)
+
+EXTRA_DIST =
diff --git a/contrib/omhttp/Makefile.in b/contrib/omhttp/Makefile.in
new file mode 100644
index 0000000..1dc03f3
--- /dev/null
+++ b/contrib/omhttp/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omhttp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omhttp_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_omhttp_la_OBJECTS = omhttp_la-omhttp.lo
+omhttp_la_OBJECTS = $(am_omhttp_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 =
+omhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omhttp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omhttp_la-omhttp.Plo
+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 = $(omhttp_la_SOURCES)
+DIST_SOURCES = $(omhttp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omhttp.la
+omhttp_la_SOURCES = omhttp.c
+omhttp_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omhttp_la_LDFLAGS = -module -avoid-version
+omhttp_la_LIBADD = $(CURL_LIBS) $(LIBM)
+EXTRA_DIST =
+all: 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) --gnu contrib/omhttp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omhttp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omhttp.la: $(omhttp_la_OBJECTS) $(omhttp_la_DEPENDENCIES) $(EXTRA_omhttp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omhttp_la_LINK) -rpath $(pkglibdir) $(omhttp_la_OBJECTS) $(omhttp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhttp_la-omhttp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omhttp_la-omhttp.lo: omhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhttp_la-omhttp.lo -MD -MP -MF $(DEPDIR)/omhttp_la-omhttp.Tpo -c -o omhttp_la-omhttp.lo `test -f 'omhttp.c' || echo '$(srcdir)/'`omhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhttp_la-omhttp.Tpo $(DEPDIR)/omhttp_la-omhttp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhttp.c' object='omhttp_la-omhttp.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) $(omhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhttp_la-omhttp.lo `test -f 'omhttp.c' || echo '$(srcdir)/'`omhttp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omhttp_la-omhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omhttp_la-omhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omhttp/omhttp.c b/contrib/omhttp/omhttp.c
new file mode 100644
index 0000000..a2a8111
--- /dev/null
+++ b/contrib/omhttp/omhttp.c
@@ -0,0 +1,2212 @@
+/* omhttp.c
+ * This is an http output module based on omelasticsearch
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * Copyright 2011 Nathan Scott.
+ * Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2018 Christian Tramnitz
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(__FreeBSD__)
+#include <unistd.h>
+#endif
+#include <json.h>
+#include <zlib.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "obj-types.h"
+#include "ratelimit.h"
+#include "ruleset.h"
+#include "statsobj.h"
+
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omhttp")
+
+/* internal structures */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+statsobj_t *httpStats;
+STATSCOUNTER_DEF(ctrMessagesSubmitted, mutCtrMessagesSubmitted); // Number of message submitted to module
+STATSCOUNTER_DEF(ctrMessagesSuccess, mutCtrMessagesSuccess); // Number of messages successfully sent
+STATSCOUNTER_DEF(ctrMessagesFail, mutCtrMessagesFail); // Number of messages that failed to send
+STATSCOUNTER_DEF(ctrMessagesRetry, mutCtrMessagesRetry); // Number of messages requeued for retry
+STATSCOUNTER_DEF(ctrHttpRequestCount, mutCtrHttpRequestCount); // Number of attempted HTTP requests
+STATSCOUNTER_DEF(ctrHttpRequestSuccess, mutCtrHttpRequestSuccess); // Number of successful HTTP requests
+STATSCOUNTER_DEF(ctrHttpRequestFail, mutCtrHttpRequestFail); // Number of failed HTTP req, 4XX+ are NOT failures
+STATSCOUNTER_DEF(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess); // Number of requests returning 1XX/2XX status
+STATSCOUNTER_DEF(ctrHttpStatusFail, mutCtrHttpStatusFail); // Number of requests returning 300+ status
+
+static prop_t *pInputName = NULL;
+
+#define WRKR_DATA_TYPE_ES 0xBADF0001
+
+#define HTTP_HEADER_CONTENT_JSON "Content-Type: application/json; charset=utf-8"
+#define HTTP_HEADER_CONTENT_TEXT "Content-Type: text/plain"
+#define HTTP_HEADER_CONTENT_KAFKA "Content-Type: application/vnd.kafka.v1+json"
+#define HTTP_HEADER_ENCODING_GZIP "Content-Encoding: gzip"
+#define HTTP_HEADER_EXPECT_EMPTY "Expect:"
+
+#define VALID_BATCH_FORMATS "newline jsonarray kafkarest lokirest"
+typedef enum batchFormat_e {
+ FMT_NEWLINE,
+ FMT_JSONARRAY,
+ FMT_KAFKAREST,
+ FMT_LOKIREST
+} batchFormat_t;
+
+/* REST API uses this URL:
+ * https://<hostName>:<restPort>/restPath
+*/
+typedef struct curl_slist HEADER;
+typedef struct instanceConf_s {
+ int defaultPort;
+ int fdErrFile; /* error file fd or -1 if not open */
+ pthread_mutex_t mutErrFile;
+ uchar **serverBaseUrls;
+ int numServers;
+ long healthCheckTimeout;
+ uchar *uid;
+ uchar *pwd;
+ uchar *authBuf;
+ uchar *httpcontenttype;
+ uchar *headerContentTypeBuf;
+ uchar *httpheaderkey;
+ uchar *httpheadervalue;
+ uchar *headerBuf;
+ uchar **httpHeaders;
+ int nHttpHeaders;
+ uchar *restPath;
+ uchar *checkPath;
+ uchar *tplName;
+ uchar *errorFile;
+ sbool batchMode;
+ uchar *batchFormatName;
+ batchFormat_t batchFormat;
+ sbool bFreeBatchFormatName;
+ sbool dynRestPath;
+ size_t maxBatchBytes;
+ size_t maxBatchSize;
+ sbool compress;
+ int compressionLevel; /* Compression level for zlib, default=-1, fastest=1, best=9, none=0*/
+ sbool useHttps;
+ sbool allowUnsignedCerts;
+ sbool skipVerifyHost;
+ uchar *caCertFile;
+ uchar *myCertFile;
+ uchar *myPrivKeyFile;
+ sbool reloadOnHup;
+ sbool retryFailures;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ /* for retries */
+ ratelimit_t *ratelimiter;
+ uchar *retryRulesetName;
+ ruleset_t *retryRuleset;
+ struct instanceConf_s *next;
+} instanceData;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+};
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+
+typedef struct wrkrInstanceData {
+ PTR_ASSERT_DEF
+ instanceData *pData;
+ int serverIndex;
+ int replyLen;
+ char *reply;
+ long httpStatusCode; /* http status code of response */
+ CURL *curlCheckConnHandle; /* libcurl session handle for checking the server connection */
+ CURL *curlPostHandle; /* libcurl session handle for posting data to the server */
+ HEADER *curlHeader; /* json POST request info */
+ uchar *restURL; /* last used URL for error reporting */
+ sbool bzInitDone;
+ z_stream zstrm; /* zip stream to use for gzip http compression */
+ struct {
+ uchar **data; /* array of strings, this will be batched up lazily */
+ uchar *restPath; /* Helper for restpath in batch mode */
+ size_t sizeBytes; /* total length of this batch in bytes */
+ size_t nmemb; /* number of messages in batch (for statistics counting) */
+
+ } batch;
+ struct {
+ uchar *buf;
+ size_t curLen;
+ size_t len;
+ } compressCtx;
+} wrkrInstanceData_t;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrArray, 0 },
+ { "serverport", eCmdHdlrInt, 0 },
+ { "healthchecktimeout", eCmdHdlrInt, 0 },
+ { "httpcontenttype", eCmdHdlrGetWord, 0 },
+ { "httpheaderkey", eCmdHdlrGetWord, 0 },
+ { "httpheadervalue", eCmdHdlrString, 0 },
+ { "httpheaders", eCmdHdlrArray, 0 },
+ { "uid", eCmdHdlrGetWord, 0 },
+ { "pwd", eCmdHdlrGetWord, 0 },
+ { "restpath", eCmdHdlrGetWord, 0 },
+ { "checkpath", eCmdHdlrGetWord, 0 },
+ { "dynrestpath", eCmdHdlrBinary, 0 },
+ { "batch", eCmdHdlrBinary, 0 },
+ { "batch.format", eCmdHdlrGetWord, 0 },
+ { "batch.maxbytes", eCmdHdlrSize, 0 },
+ { "batch.maxsize", eCmdHdlrSize, 0 },
+ { "compress", eCmdHdlrBinary, 0 },
+ { "compress.level", eCmdHdlrInt, 0 },
+ { "usehttps", eCmdHdlrBinary, 0 },
+ { "errorfile", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "allowunsignedcerts", eCmdHdlrBinary, 0 },
+ { "skipverifyhost", eCmdHdlrBinary, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "reloadonhup", eCmdHdlrBinary, 0 },
+ { "retry", eCmdHdlrBinary, 0 },
+ { "retry.ruleset", eCmdHdlrString, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static rsRetVal curlSetup(wrkrInstanceData_t *pWrkrData);
+static void curlCleanup(wrkrInstanceData_t *pWrkrData);
+static void curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData);
+
+/* compressCtx functions */
+static void ATTR_NONNULL()
+initCompressCtx(wrkrInstanceData_t *pWrkrData);
+
+static void ATTR_NONNULL()
+freeCompressCtx(wrkrInstanceData_t *pWrkrData);
+
+static rsRetVal ATTR_NONNULL()
+resetCompressCtx(wrkrInstanceData_t *pWrkrData, size_t len);
+
+static rsRetVal ATTR_NONNULL()
+growCompressCtx(wrkrInstanceData_t *pWrkrData, size_t newLen);
+
+static rsRetVal ATTR_NONNULL()
+appendCompressCtx(wrkrInstanceData_t *pWrkrData, uchar *srcBuf, size_t srcLen);
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->fdErrFile = -1;
+ pthread_mutex_init(&pData->mutErrFile, NULL);
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+ pData->ratelimiter = NULL;
+ pData->retryRulesetName = NULL;
+ pData->retryRuleset = NULL;
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+uchar **batchData;
+CODESTARTcreateWrkrInstance
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ pWrkrData->curlHeader = NULL;
+ pWrkrData->curlPostHandle = NULL;
+ pWrkrData->curlCheckConnHandle = NULL;
+ pWrkrData->serverIndex = 0;
+ pWrkrData->httpStatusCode = 0;
+ pWrkrData->restURL = NULL;
+ pWrkrData->bzInitDone = 0;
+ if(pData->batchMode) {
+ pWrkrData->batch.nmemb = 0;
+ pWrkrData->batch.sizeBytes = 0;
+ batchData = (uchar **) malloc(pData->maxBatchSize * sizeof(uchar *));
+ if (batchData == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: cannot allocate memory for batch queue turning off batch mode\n");
+ pData->batchMode = 0; /* at least it works */
+ } else {
+ pWrkrData->batch.data = batchData;
+ pWrkrData->batch.restPath = NULL;
+ }
+ }
+ initCompressCtx(pWrkrData);
+ iRet = curlSetup(pWrkrData);
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+ int i;
+CODESTARTfreeInstance
+ if(pData->fdErrFile != -1)
+ close(pData->fdErrFile);
+ pthread_mutex_destroy(&pData->mutErrFile);
+ for(i = 0 ; i < pData->numServers ; ++i)
+ free(pData->serverBaseUrls[i]);
+ free(pData->serverBaseUrls);
+ free(pData->uid);
+ free(pData->httpcontenttype);
+ free(pData->headerContentTypeBuf);
+ free(pData->httpheaderkey);
+ free(pData->httpheadervalue);
+ for(i = 0 ; i < pData->nHttpHeaders ; ++i) {
+ free((void*) pData->httpHeaders[i]);
+ }
+ free(pData->httpHeaders);
+ pData->nHttpHeaders = 0;
+ free(pData->pwd);
+ free(pData->authBuf);
+ free(pData->headerBuf);
+ free(pData->restPath);
+ free(pData->checkPath);
+ free(pData->tplName);
+ free(pData->errorFile);
+ free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
+ free(pData->retryRulesetName);
+ if (pData->ratelimiter != NULL)
+ ratelimitDestruct(pData->ratelimiter);
+ if (pData->bFreeBatchFormatName)
+ free(pData->batchFormatName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ curlCleanup(pWrkrData);
+
+ free(pWrkrData->restURL);
+ pWrkrData->restURL = NULL;
+
+ free(pWrkrData->batch.data);
+ pWrkrData->batch.data = NULL;
+
+ if (pWrkrData->batch.restPath != NULL) {
+ free(pWrkrData->batch.restPath);
+ pWrkrData->batch.restPath = NULL;
+ }
+
+ if (pWrkrData->bzInitDone)
+ deflateEnd(&pWrkrData->zstrm);
+ freeCompressCtx(pWrkrData);
+
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+ int i;
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omhttp\n");
+ dbgprintf("\ttemplate='%s'\n", pData->tplName);
+ dbgprintf("\tnumServers=%d\n", pData->numServers);
+ dbgprintf("\thealthCheckTimeout=%lu\n", pData->healthCheckTimeout);
+ dbgprintf("\tserverBaseUrls=");
+ for(i = 0 ; i < pData->numServers ; ++i)
+ dbgprintf("%c'%s'", i == 0 ? '[' : ' ', pData->serverBaseUrls[i]);
+ dbgprintf("]\n");
+ dbgprintf("\tdefaultPort=%d\n", pData->defaultPort);
+ dbgprintf("\tuid='%s'\n", pData->uid == NULL ? (uchar*)"(not configured)" : pData->uid);
+ dbgprintf("\thttpcontenttype='%s'\n", pData->httpcontenttype == NULL ?
+ (uchar*)"(not configured)" : pData->httpcontenttype);
+ dbgprintf("\thttpheaderkey='%s'\n", pData->httpheaderkey == NULL ?
+ (uchar*)"(not configured)" : pData->httpheaderkey);
+ dbgprintf("\thttpheadervalue='%s'\n", pData->httpheadervalue == NULL ?
+ (uchar*)"(not configured)" : pData->httpheadervalue);
+ dbgprintf("\thttpHeaders=[");
+ for(i = 0 ; i < pData->nHttpHeaders ; ++i)
+ dbgprintf("\t%s\n",pData->httpHeaders[i]);
+ dbgprintf("\t]\n");
+ dbgprintf("\tpwd=(%sconfigured)\n", pData->pwd == NULL ? "not " : "");
+ dbgprintf("\trest path='%s'\n", pData->restPath);
+ dbgprintf("\tcheck path='%s'\n", pData->checkPath);
+ dbgprintf("\tdynamic rest path=%d\n", pData->dynRestPath);
+ dbgprintf("\tuse https=%d\n", pData->useHttps);
+ dbgprintf("\tbatch=%d\n", pData->batchMode);
+ dbgprintf("\tbatch.format='%s'\n", pData->batchFormatName);
+ dbgprintf("\tbatch.maxbytes=%zu\n", pData->maxBatchBytes);
+ dbgprintf("\tbatch.maxsize=%zu\n", pData->maxBatchSize);
+ dbgprintf("\tcompress=%d\n", pData->compress);
+ dbgprintf("\tcompress.level=%d\n", pData->compressionLevel);
+ dbgprintf("\tallowUnsignedCerts=%d\n", pData->allowUnsignedCerts);
+ dbgprintf("\tskipVerifyHost=%d\n", pData->skipVerifyHost);
+ dbgprintf("\terrorfile='%s'\n", pData->errorFile == NULL ?
+ (uchar*)"(not configured)" : pData->errorFile);
+ dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
+ dbgprintf("\treloadonhup='%d'\n", pData->reloadOnHup);
+ dbgprintf("\tretry='%d'\n", pData->retryFailures);
+ dbgprintf("\tretry.ruleset='%s'\n", pData->retryRulesetName);
+ dbgprintf("\tratelimit.interval='%u'\n", pData->ratelimitInterval);
+ dbgprintf("\tratelimit.burst='%u'\n", pData->ratelimitBurst);
+ENDdbgPrintInstInfo
+
+
+/* http POST result string ... useful for debugging */
+static size_t
+curlResult(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ char *p = (char *)ptr;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t*) userdata;
+ char *buf;
+ size_t newlen;
+ PTR_ASSERT_CHK(pWrkrData, WRKR_DATA_TYPE_ES);
+ newlen = pWrkrData->replyLen + size*nmemb;
+ if((buf = realloc(pWrkrData->reply, newlen + 1)) == NULL) {
+ LogError(errno, RS_RET_ERR, "omhttp: realloc failed in curlResult");
+ return 0; /* abort due to failure */
+ }
+ memcpy(buf+pWrkrData->replyLen, p, size*nmemb);
+ pWrkrData->replyLen = newlen;
+ pWrkrData->reply = buf;
+ return size*nmemb;
+}
+
+/* Build basic URL part, which includes hostname and port as follows:
+ * http://hostname:port/ based on a server param
+ * Newly creates a cstr for this purpose.
+ * Note: serverParam MUST NOT end in '/' (caller must strip if it exists)
+ */
+static rsRetVal
+computeBaseUrl(const char*const serverParam,
+ const int defaultPort,
+ const sbool useHttps,
+ uchar **baseUrl)
+{
+# define SCHEME_HTTPS "https://"
+# define SCHEME_HTTP "http://"
+
+ char portBuf[64];
+ int r = 0;
+ const char *host = serverParam;
+ DEFiRet;
+
+ assert(serverParam[strlen(serverParam)-1] != '/');
+
+ es_str_t *urlBuf = es_newStr(256);
+ if (urlBuf == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: failed to allocate es_str urlBuf in computeBaseUrl");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* Find where the hostname/ip of the server starts. If the scheme is not specified
+ * in the uri, start the buffer with a scheme corresponding to the useHttps parameter.
+ */
+ if (strcasestr(serverParam, SCHEME_HTTP))
+ host = serverParam + strlen(SCHEME_HTTP);
+ else if (strcasestr(serverParam, SCHEME_HTTPS))
+ host = serverParam + strlen(SCHEME_HTTPS);
+ else
+ r = useHttps ? es_addBuf(&urlBuf, SCHEME_HTTPS, sizeof(SCHEME_HTTPS)-1) :
+ es_addBuf(&urlBuf, SCHEME_HTTP, sizeof(SCHEME_HTTP)-1);
+
+ if (r == 0) r = es_addBuf(&urlBuf, (char *)serverParam, strlen(serverParam));
+ if (r == 0 && !strchr(host, ':')) {
+ snprintf(portBuf, sizeof(portBuf), ":%d", defaultPort);
+ r = es_addBuf(&urlBuf, portBuf, strlen(portBuf));
+ }
+ if (r == 0) r = es_addChar(&urlBuf, '/');
+ if (r == 0) *baseUrl = (uchar*) es_str2cstr(urlBuf, NULL);
+
+ if (r != 0 || baseUrl == NULL) {
+ LogError(0, RS_RET_ERR,
+ "omhttp: error occurred computing baseUrl from server %s", serverParam);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ if (urlBuf) {
+ es_deleteStr(urlBuf);
+ }
+ RETiRet;
+}
+
+static inline void
+incrementServerIndex(wrkrInstanceData_t *pWrkrData)
+{
+ pWrkrData->serverIndex = (pWrkrData->serverIndex + 1) % pWrkrData->pData->numServers;
+}
+
+
+/* checks if connection to ES can be established; also iterates over
+ * potential servers to support high availability (HA) feature. If it
+ * needs to switch server, will record new one in curl handle.
+ */
+static rsRetVal ATTR_NONNULL()
+checkConn(wrkrInstanceData_t *const pWrkrData)
+{
+ CURL *curl;
+ CURLcode res;
+ es_str_t *urlBuf = NULL;
+ char* healthUrl;
+ char* serverUrl;
+ char* checkPath;
+ int i;
+ int r;
+ DEFiRet;
+
+ if (pWrkrData->pData->checkPath == NULL) {
+ DBGPRINTF("omhttp: checkConn no health check uri configured skipping it\n");
+ FINALIZE;
+ }
+
+ pWrkrData->reply = NULL;
+ pWrkrData->replyLen = 0;
+ curl = pWrkrData->curlCheckConnHandle;
+ urlBuf = es_newStr(256);
+ if (urlBuf == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: unable to allocate buffer for health check uri.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ for(i = 0; i < pWrkrData->pData->numServers; ++i) {
+ serverUrl = (char*) pWrkrData->pData->serverBaseUrls[pWrkrData->serverIndex];
+ checkPath = (char*) pWrkrData->pData->checkPath;
+
+ es_emptyStr(urlBuf);
+ r = es_addBuf(&urlBuf, serverUrl, strlen(serverUrl));
+ if(r == 0 && checkPath != NULL)
+ r = es_addBuf(&urlBuf, checkPath, strlen(checkPath));
+ if(r == 0)
+ healthUrl = es_str2cstr(urlBuf, NULL);
+ if(r != 0 || healthUrl == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: unable to allocate buffer for health check uri.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ curlCheckConnSetup(pWrkrData);
+ curl_easy_setopt(curl, CURLOPT_URL, healthUrl);
+ res = curl_easy_perform(curl);
+ free(healthUrl);
+
+ if (res == CURLE_OK) {
+ DBGPRINTF("omhttp: checkConn %s completed with success "
+ "on attempt %d\n", serverUrl, i);
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ DBGPRINTF("omhttp: checkConn %s failed on attempt %d: %s\n",
+ serverUrl, i, curl_easy_strerror(res));
+ incrementServerIndex(pWrkrData);
+ }
+
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "omhttp: checkConn failed after %d attempts.", i);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+
+finalize_it:
+ if(urlBuf != NULL)
+ es_deleteStr(urlBuf);
+
+ free(pWrkrData->reply);
+ pWrkrData->reply = NULL; /* don't leave dangling pointer */
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ DBGPRINTF("omhttp: tryResume called\n");
+ iRet = checkConn(pWrkrData);
+ENDtryResume
+
+
+/* get the current index and type for this message */
+static void ATTR_NONNULL(1)
+getRestPath(const instanceData *const pData, uchar **const tpls,
+ uchar **const restPath)
+{
+ *restPath = pData->restPath;
+ if(tpls == NULL) {
+ goto done;
+ }
+
+ int iNumTpls = 1;
+ if(pData->dynRestPath) {
+ *restPath = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+
+done:
+ assert(restPath != NULL);
+ return;
+}
+
+
+static rsRetVal ATTR_NONNULL(1)
+setPostURL(wrkrInstanceData_t *const pWrkrData, uchar **const tpls)
+{
+ uchar *restPath;
+ char* baseUrl;
+ es_str_t *url;
+ int r;
+ DEFiRet;
+ instanceData *const pData = pWrkrData->pData;
+
+ baseUrl = (char*)pData->serverBaseUrls[pWrkrData->serverIndex];
+ url = es_newStrFromCStr(baseUrl, strlen(baseUrl));
+ if (url == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: error allocating new estr for POST url.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if (pWrkrData->batch.restPath != NULL) {
+ /* get from batch if set! */
+ restPath = pWrkrData->batch.restPath;
+ } else {
+ getRestPath(pData, tpls, &restPath);
+ }
+
+ r = 0;
+ if (restPath != NULL)
+ r = es_addBuf(&url, (char*)restPath, ustrlen(restPath));
+
+ if(r != 0) {
+ LogError(0, RS_RET_ERR, "omhttp: failure in creating restURL, "
+ "error code: %d", r);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(pWrkrData->restURL != NULL)
+ free(pWrkrData->restURL);
+
+ pWrkrData->restURL = (uchar*)es_str2cstr(url, NULL);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_URL, pWrkrData->restURL);
+ DBGPRINTF("omhttp: using REST URL: '%s'\n", pWrkrData->restURL);
+
+finalize_it:
+ if (url != NULL)
+ es_deleteStr(url);
+ RETiRet;
+}
+
+/*
+ * Dumps entire bulk request and response in error log
+ * {
+ * "request": {
+ * "url": "https://url.com:443/path",
+ * "postdata": "mypayload" }
+ * "response" : {
+ * "status": 400,
+ * "response": "error string" }
+ * }
+ */
+static rsRetVal
+renderJsonErrorMessage(wrkrInstanceData_t *pWrkrData, uchar *reqmsg, char **rendered)
+{
+ DEFiRet;
+ fjson_object *req = NULL;
+ fjson_object *res = NULL;
+ fjson_object *errRoot = NULL;
+
+ if ((req = fjson_object_new_object()) == NULL)
+ ABORT_FINALIZE(RS_RET_ERR);
+ fjson_object_object_add(req, "url", fjson_object_new_string((char *)pWrkrData->restURL));
+ fjson_object_object_add(req, "postdata", fjson_object_new_string((char *)reqmsg));
+
+ if ((res = fjson_object_new_object()) == NULL) {
+ fjson_object_put(req); // cleanup request object
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ #define ERR_MSG_NULL "NULL: curl request failed or no response"
+ fjson_object_object_add(res, "status", fjson_object_new_int(pWrkrData->httpStatusCode));
+ if (pWrkrData->reply == NULL) {
+ fjson_object_object_add(res, "message",
+ fjson_object_new_string_len(ERR_MSG_NULL, strlen(ERR_MSG_NULL)));
+ } else {
+ fjson_object_object_add(res, "message",
+ fjson_object_new_string_len(pWrkrData->reply, pWrkrData->replyLen));
+ }
+
+ if ((errRoot = fjson_object_new_object()) == NULL) {
+ fjson_object_put(req); // cleanup request object
+ fjson_object_put(res); // cleanup response object
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object_object_add(errRoot, "request", req);
+ fjson_object_object_add(errRoot, "response", res);
+
+ *rendered = strdup((char *) fjson_object_to_json_string(errRoot));
+
+finalize_it:
+ if (errRoot != NULL)
+ fjson_object_put(errRoot);
+
+ RETiRet;
+}
+
+/* write data error request/replies to separate error file
+ * Note: we open the file but never close it before exit. If it
+ * needs to be closed, HUP must be sent.
+ */
+static rsRetVal ATTR_NONNULL()
+writeDataError(wrkrInstanceData_t *const pWrkrData,
+ instanceData *const pData, uchar *const reqmsg)
+{
+ char *rendered = NULL;
+ size_t toWrite;
+ ssize_t wrRet;
+ sbool bMutLocked = 0;
+
+ DEFiRet;
+
+ if(pData->errorFile == NULL) {
+ DBGPRINTF("omhttp: no local error logger defined - "
+ "ignoring REST error information\n");
+ FINALIZE;
+ }
+
+ pthread_mutex_lock(&pData->mutErrFile);
+ bMutLocked = 1;
+
+ CHKiRet(renderJsonErrorMessage(pWrkrData, reqmsg, &rendered));
+
+ if(pData->fdErrFile == -1) {
+ pData->fdErrFile = open((char*)pData->errorFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pData->fdErrFile == -1) {
+ LogError(errno, RS_RET_ERR, "omhttp: error opening error file %s",
+ pData->errorFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ /* we do not do real error-handling on the err file, as this finally complicates
+ * things way to much.
+ */
+ DBGPRINTF("omhttp: error record: '%s'\n", rendered);
+ toWrite = strlen(rendered) + 1;
+ /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid
+ * caling malloc() -- write() does NOT need '\0'!
+ */
+ rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+ wrRet = write(pData->fdErrFile, rendered, toWrite);
+ if(wrRet != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "omhttp: error writing error file %s, write returned %lld",
+ pData->errorFile, (long long) wrRet);
+ }
+
+finalize_it:
+ if(bMutLocked)
+ pthread_mutex_unlock(&pData->mutErrFile);
+ free(rendered);
+ RETiRet;
+}
+
+static rsRetVal
+queueBatchOnRetryRuleset(wrkrInstanceData_t *const pWrkrData, instanceData *const pData)
+{
+ uchar *msgData;
+ smsg_t *pMsg;
+ DEFiRet;
+
+ if (pData->retryRuleset == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: queueBatchOnRetryRuleset invalid call with a NULL retryRuleset");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (size_t i = 0; i < pWrkrData->batch.nmemb; i++) {
+ msgData = pWrkrData->batch.data[i];
+ DBGPRINTF("omhttp: queueBatchOnRetryRuleset putting message '%s' into retry ruleset '%s'\n",
+ msgData, pData->retryRulesetName);
+
+ // Construct the message object
+ CHKiRet(msgConstruct(&pMsg));
+ CHKiRet(MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (const char *)msgData, ustrlen(msgData));
+ MsgSetMSGoffs(pMsg, 0); // No header
+ MsgSetTAG(pMsg, (const uchar *)"omhttp-retry", 12);
+
+ // And place it on the retry ruleset
+ MsgSetRuleset(pMsg, pData->retryRuleset);
+ ratelimitAddMsg(pData->ratelimiter, NULL, pMsg);
+
+ // Count here in case not entire batch succeeds
+ STATSCOUNTER_INC(ctrMessagesRetry, mutCtrMessagesRetry);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+checkResult(wrkrInstanceData_t *pWrkrData, uchar *reqmsg)
+{
+ instanceData *pData;
+ long statusCode;
+ size_t numMessages;
+ DEFiRet;
+
+ pData = pWrkrData->pData;
+ statusCode = pWrkrData->httpStatusCode;
+
+ if (pData->batchMode) {
+ numMessages = pWrkrData->batch.nmemb;
+ } else {
+ numMessages = 1;
+ }
+
+ // 500+ errors return RS_RET_SUSPENDED if NOT batchMode and should be retried
+ // status 0 is the default and the request failed for some reason, retry this too
+ // 400-499 are malformed input and should not be retried just logged instead
+ if (statusCode == 0) {
+ // request failed, suspend or retry
+ STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages);
+ iRet = RS_RET_SUSPENDED;
+ } else if (statusCode >= 500) {
+ // server error, suspend or retry
+ STATSCOUNTER_INC(ctrHttpStatusFail, mutCtrHttpStatusFail);
+ STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages);
+ iRet = RS_RET_SUSPENDED;
+ } else if (statusCode >= 300) {
+ // redirection or client error, NO suspend nor retry
+ STATSCOUNTER_INC(ctrHttpStatusFail, mutCtrHttpStatusFail);
+ STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages);
+ iRet = RS_RET_DATAFAIL;
+ } else {
+ // success, normal state
+ // includes 2XX (success like 200-OK)
+ // includes 1XX (informational like 100-Continue)
+ STATSCOUNTER_INC(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess);
+ STATSCOUNTER_ADD(ctrMessagesSuccess, mutCtrMessagesSuccess, numMessages);
+ iRet = RS_RET_OK;
+ }
+
+ if (iRet != RS_RET_OK) {
+ LogMsg(0, iRet, LOG_ERR, "omhttp: checkResult error http status code: %ld reply: %s",
+ statusCode, pWrkrData->reply != NULL ? pWrkrData->reply : "NULL");
+
+ writeDataError(pWrkrData, pWrkrData->pData, reqmsg);
+
+ if (iRet == RS_RET_DATAFAIL)
+ ABORT_FINALIZE(iRet);
+
+ if (pData->batchMode && pData->maxBatchSize > 1) {
+ // Write each message back to retry ruleset if configured
+ if (pData->retryFailures && pData->retryRuleset != NULL) {
+ // Retry stats counted inside this function call
+ iRet = queueBatchOnRetryRuleset(pWrkrData, pData);
+ if (iRet != RS_RET_OK) {
+ LogMsg(0, iRet, LOG_ERR,
+ "omhttp: checkResult error while queueing to retry ruleset"
+ "some messages may be lost");
+ }
+ }
+ iRet = RS_RET_OK; // We've done all we can tell rsyslog to carry on
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* Compress a buffer before sending using zlib. Based on code from tools/omfwd.c
+ * Initialize the zstrm object for gzip compression, using this init function.
+ * deflateInit2(z_stream strm, int level, int method,
+ * int windowBits, int memLevel, int strategy);
+ * strm: the zlib stream held in pWrkrData
+ * level: the compression level held in pData
+ * method: the operation constant Z_DEFLATED
+ * windowBits: the size of the compression window 15 = log_2(32768)
+ * to configure as gzip add 16 to windowBits (w | 16) for final value 31
+ * memLevel: the memory optimization level 8 is default)
+ * strategy: using Z_DEFAULT_STRATEGY is default
+ */
+static rsRetVal
+compressHttpPayload(wrkrInstanceData_t *pWrkrData, uchar *message, unsigned len)
+{
+ int zRet;
+ unsigned outavail;
+ uchar zipBuf[32*1024];
+
+ DEFiRet;
+
+ if (!pWrkrData->bzInitDone) {
+ pWrkrData->zstrm.zalloc = Z_NULL;
+ pWrkrData->zstrm.zfree = Z_NULL;
+ pWrkrData->zstrm.opaque = Z_NULL;
+ zRet = deflateInit2(&pWrkrData->zstrm, pWrkrData->pData->compressionLevel,
+ Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
+ if (zRet != Z_OK) {
+ DBGPRINTF("omhttp: compressHttpPayload error %d returned from zlib/deflateInit2()\n", zRet);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ pWrkrData->bzInitDone = 1;
+ }
+
+ CHKiRet(resetCompressCtx(pWrkrData, len));
+
+ /* now doing the compression */
+ pWrkrData->zstrm.next_in = (Bytef*) message;
+ pWrkrData->zstrm.avail_in = len;
+ /* run deflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("omhttp: compressHttpPayload in deflate() loop, avail_in %d, total_in %ld\n",
+ pWrkrData->zstrm.avail_in, pWrkrData->zstrm.total_in);
+ pWrkrData->zstrm.avail_out = sizeof(zipBuf);
+ pWrkrData->zstrm.next_out = zipBuf;
+
+ zRet = deflate(&pWrkrData->zstrm, Z_NO_FLUSH);
+ DBGPRINTF("omhttp: compressHttpPayload after deflate, ret %d, avail_out %d\n",
+ zRet, pWrkrData->zstrm.avail_out);
+ if (zRet != Z_OK)
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out;
+ if (outavail != 0)
+ CHKiRet(appendCompressCtx(pWrkrData, zipBuf, outavail));
+
+ } while (pWrkrData->zstrm.avail_out == 0);
+
+ /* run deflate again with Z_FINISH with no new input */
+ pWrkrData->zstrm.avail_in = 0;
+ do {
+ pWrkrData->zstrm.avail_out = sizeof(zipBuf);
+ pWrkrData->zstrm.next_out = zipBuf;
+ deflate(&pWrkrData->zstrm, Z_FINISH); /* returns Z_STREAM_END == 1 */
+ outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out;
+ if (outavail != 0)
+ CHKiRet(appendCompressCtx(pWrkrData, zipBuf, outavail));
+
+ } while (pWrkrData->zstrm.avail_out == 0);
+
+finalize_it:
+ if (pWrkrData->bzInitDone)
+ deflateEnd(&pWrkrData->zstrm);
+ pWrkrData->bzInitDone = 0;
+ RETiRet;
+
+}
+
+static void ATTR_NONNULL()
+initCompressCtx(wrkrInstanceData_t *pWrkrData)
+{
+ pWrkrData->compressCtx.buf = NULL;
+ pWrkrData->compressCtx.curLen = 0;
+ pWrkrData->compressCtx.len = 0;
+}
+
+static void ATTR_NONNULL()
+freeCompressCtx(wrkrInstanceData_t *pWrkrData)
+{
+ if (pWrkrData->compressCtx.buf != NULL) {
+ free(pWrkrData->compressCtx.buf);
+ pWrkrData->compressCtx.buf = NULL;
+ }
+}
+
+
+static rsRetVal ATTR_NONNULL()
+resetCompressCtx(wrkrInstanceData_t *pWrkrData, size_t len)
+{
+ DEFiRet;
+ pWrkrData->compressCtx.curLen = 0;
+ pWrkrData->compressCtx.len = len;
+ CHKiRet(growCompressCtx(pWrkrData, len));
+
+finalize_it:
+ if (iRet != RS_RET_OK)
+ freeCompressCtx(pWrkrData);
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+growCompressCtx(wrkrInstanceData_t *pWrkrData, size_t newLen)
+{
+ DEFiRet;
+ if (pWrkrData->compressCtx.buf == NULL) {
+ CHKmalloc(pWrkrData->compressCtx.buf = (uchar *)malloc(sizeof(uchar)*newLen));
+ } else {
+ uchar *const newbuf = (uchar *)realloc(pWrkrData->compressCtx.buf, sizeof(uchar)*newLen);
+ CHKmalloc(newbuf);
+ pWrkrData->compressCtx.buf = newbuf;
+ }
+ pWrkrData->compressCtx.len = newLen;
+finalize_it:
+ RETiRet;
+
+}
+
+static rsRetVal ATTR_NONNULL()
+appendCompressCtx(wrkrInstanceData_t *pWrkrData, uchar *srcBuf, size_t srcLen)
+{
+ size_t newLen;
+ DEFiRet;
+ newLen = pWrkrData->compressCtx.curLen + srcLen;
+ if (newLen > pWrkrData->compressCtx.len)
+ CHKiRet(growCompressCtx(pWrkrData, newLen));
+
+ memcpy(pWrkrData->compressCtx.buf + pWrkrData->compressCtx.curLen,
+ srcBuf, srcLen);
+ pWrkrData->compressCtx.curLen = newLen;
+finalize_it:
+ if (iRet != RS_RET_OK)
+ freeCompressCtx(pWrkrData);
+ RETiRet;
+}
+
+/* Some duplicate code to curlSetup, but we need to add the gzip content-encoding
+ * header at runtime, and if the compression fails, we do not want to send it.
+ * Additionally, the curlCheckConnHandle should not be configured with a gzip header.
+ */
+static rsRetVal ATTR_NONNULL()
+buildCurlHeaders(wrkrInstanceData_t *pWrkrData, sbool contentEncodeGzip)
+{
+ struct curl_slist *slist = NULL;
+
+ DEFiRet;
+
+ if (pWrkrData->pData->httpcontenttype != NULL) {
+ // If content type specified use it, otherwise use a sane default
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerContentTypeBuf);
+ } else {
+ if (pWrkrData->pData->batchMode) {
+ // If in batch mode, use the approprate content type header for the format,
+ // defaulting to text/plain with newline
+ switch (pWrkrData->pData->batchFormat) {
+ case FMT_JSONARRAY:
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON);
+ break;
+ case FMT_KAFKAREST:
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_KAFKA);
+ break;
+ case FMT_NEWLINE:
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_TEXT);
+ break;
+ case FMT_LOKIREST:
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON);
+ break;
+ default:
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_TEXT);
+ }
+ } else {
+ // Otherwise non batch, presume most users are sending JSON
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON);
+ }
+ }
+
+ CHKmalloc(slist);
+
+ // Configured headers..
+ if (pWrkrData->pData->headerBuf != NULL) {
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerBuf);
+ CHKmalloc(slist);
+ }
+
+ for (int k = 0 ; k < pWrkrData->pData->nHttpHeaders; k++) {
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->httpHeaders[k]);
+ CHKmalloc(slist);
+ }
+
+ // When sending more than 1Kb, libcurl automatically sends an Except: 100-Continue header
+ // and will wait 1s for a response, could make this configurable but for now disable
+ slist = curl_slist_append(slist, HTTP_HEADER_EXPECT_EMPTY);
+ CHKmalloc(slist);
+
+ if (contentEncodeGzip) {
+ slist = curl_slist_append(slist, HTTP_HEADER_ENCODING_GZIP);
+ CHKmalloc(slist);
+ }
+
+ if (pWrkrData->curlHeader != NULL)
+ curl_slist_free_all(pWrkrData->curlHeader);
+
+ pWrkrData->curlHeader = slist;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ curl_slist_free_all(slist);
+ LogError(0, iRet, "omhttp: error allocating curl header slist, using previous one");
+ }
+ RETiRet;
+}
+
+
+
+static rsRetVal ATTR_NONNULL(1, 2)
+curlPost(wrkrInstanceData_t *pWrkrData, uchar *message, int msglen, uchar **tpls,
+ const int nmsgs __attribute__((unused)))
+{
+ CURLcode curlCode;
+ CURL *const curl = pWrkrData->curlPostHandle;
+ char errbuf[CURL_ERROR_SIZE] = "";
+
+ char *postData;
+ int postLen;
+ sbool compressed;
+ DEFiRet;
+
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+
+ if(pWrkrData->pData->numServers > 1) {
+ /* needs to be called to support ES HA feature */
+ CHKiRet(checkConn(pWrkrData));
+ }
+ CHKiRet(setPostURL(pWrkrData, tpls));
+
+ pWrkrData->reply = NULL;
+ pWrkrData->replyLen = 0;
+ pWrkrData->httpStatusCode = 0;
+
+ postData = (char *)message;
+ postLen = msglen;
+ compressed = 0;
+
+ if (pWrkrData->pData->compress) {
+ iRet = compressHttpPayload(pWrkrData, message, msglen);
+ if (iRet != RS_RET_OK) {
+ LogError(0, iRet, "omhttp: curlPost error while compressing, will default to uncompressed");
+ } else {
+ postData = (char *)pWrkrData->compressCtx.buf;
+ postLen = pWrkrData->compressCtx.curLen;
+ compressed = 1;
+ DBGPRINTF("omhttp: curlPost compressed %d to %d bytes\n", msglen, postLen);
+ }
+ }
+
+ buildCurlHeaders(pWrkrData, compressed);
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postLen);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+
+ curlCode = curl_easy_perform(curl);
+ DBGPRINTF("omhttp: curlPost curl returned %lld\n", (long long) curlCode);
+ STATSCOUNTER_INC(ctrHttpRequestCount, mutCtrHttpRequestCount);
+
+ if (curlCode != CURLE_OK) {
+ STATSCOUNTER_INC(ctrHttpRequestFail, mutCtrHttpRequestFail);
+ LogError(0, RS_RET_SUSPENDED,
+ "omhttp: suspending ourselves due to server failure %lld: %s",
+ (long long) curlCode, errbuf);
+ // Check the result here too and retry if needed, then we should suspend
+ // Usually in batch mode we clobber any iRet values, but probably not a great
+ // idea to keep hitting a dead server. The http status code will be 0 at this point.
+ checkResult(pWrkrData, message);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ STATSCOUNTER_INC(ctrHttpRequestSuccess, mutCtrHttpRequestSuccess);
+ }
+
+ // Grab the HTTP Response code
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &pWrkrData->httpStatusCode);
+ if(pWrkrData->reply == NULL) {
+ DBGPRINTF("omhttp: curlPost pWrkrData reply==NULL, replyLen = '%d'\n",
+ pWrkrData->replyLen);
+ } else {
+ DBGPRINTF("omhttp: curlPost pWrkrData replyLen = '%d'\n", pWrkrData->replyLen);
+ if(pWrkrData->replyLen > 0) {
+ pWrkrData->reply[pWrkrData->replyLen] = '\0';
+ /* Append 0 Byte if replyLen is above 0 - byte has been reserved in malloc */
+ }
+ //TODO: replyLen++? because 0 Byte is appended
+ DBGPRINTF("omhttp: curlPost pWrkrData reply: '%s'\n", pWrkrData->reply);
+ }
+ CHKiRet(checkResult(pWrkrData, message));
+
+finalize_it:
+ incrementServerIndex(pWrkrData);
+ if (pWrkrData->reply != NULL) {
+ free(pWrkrData->reply);
+ pWrkrData->reply = NULL; /* don't leave dangling pointer */
+ }
+ RETiRet;
+}
+
+/* Build a JSON batch that conforms to the Kafka Rest Proxy format.
+ * See https://docs.confluent.io/current/kafka-rest/docs/quickstart.html for more info.
+ * Want {"records": [{"value": "message1"}, {"value": "message2"}]}
+ */
+static rsRetVal
+serializeBatchKafkaRest(wrkrInstanceData_t *pWrkrData, char **batchBuf)
+{
+ fjson_object *batchArray = NULL;
+ fjson_object *recordObj = NULL;
+ fjson_object *valueObj = NULL;
+ fjson_object *msgObj = NULL;
+
+ size_t numMessages = pWrkrData->batch.nmemb;
+ size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas
+ DBGPRINTF("omhttp: serializeBatchKafkaRest numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal);
+
+ DEFiRet;
+
+ batchArray = fjson_object_new_array();
+ if (batchArray == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create array");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (size_t i = 0; i < numMessages; i++) {
+ valueObj = fjson_object_new_object();
+ if (valueObj == NULL) {
+ fjson_object_put(batchArray); // cleanup
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create value object");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ msgObj = fjson_tokener_parse((char *) pWrkrData->batch.data[i]);
+ if (msgObj == NULL) {
+ LogError(0, NO_ERRCODE,
+ "omhttp: serializeBatchKafkaRest failed to parse %s as json ignoring it",
+ pWrkrData->batch.data[i]);
+ continue;
+ }
+ fjson_object_object_add(valueObj, "value", msgObj);
+ fjson_object_array_add(batchArray, valueObj);
+ }
+
+ recordObj = fjson_object_new_object();
+ if (recordObj == NULL) {
+ fjson_object_put(batchArray); // cleanup
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create record object");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object_object_add(recordObj, "records", batchArray);
+
+ const char *batchString = fjson_object_to_json_string_ext(recordObj, FJSON_TO_STRING_PLAIN);
+ *batchBuf = strndup(batchString, strlen(batchString));
+
+finalize_it:
+ if (recordObj != NULL) {
+ fjson_object_put(recordObj);
+ recordObj = NULL;
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+serializeBatchLokiRest(wrkrInstanceData_t *pWrkrData, char **batchBuf)
+{
+ fjson_object *batchArray = NULL;
+ fjson_object *recordObj = NULL;
+ fjson_object *msgObj = NULL;
+
+ size_t numMessages = pWrkrData->batch.nmemb;
+ size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas
+ DBGPRINTF("omhttp: serializeBatchLokiRest numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal);
+
+ DEFiRet;
+
+ batchArray = fjson_object_new_array();
+ if (batchArray == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchLokiRest failed to create array");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (size_t i = 0; i < numMessages; i++) {
+ DBGPRINTF("omhttp: serializeBatchLokiRest parsing message [%s]\n",(char *) pWrkrData->batch.data[i]);
+ msgObj = fjson_tokener_parse((char *) pWrkrData->batch.data[i]);
+ if (msgObj == NULL) {
+ LogError(0, NO_ERRCODE,
+ "omhttp: serializeBatchLokiRest failed to parse %s as json ignoring it",
+ pWrkrData->batch.data[i]);
+ continue;
+ }
+ fjson_object_array_add(batchArray, msgObj);
+ }
+
+ recordObj = fjson_object_new_object();
+ if (recordObj == NULL) {
+ fjson_object_put(batchArray); // cleanup
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchLokiRest failed to create record object");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object_object_add(recordObj, "streams", batchArray);
+
+ const char *batchString = fjson_object_to_json_string_ext(recordObj, FJSON_TO_STRING_PLAIN);
+ *batchBuf = strndup(batchString, strlen(batchString));
+
+finalize_it:
+ if (recordObj != NULL) {
+ fjson_object_put(recordObj);
+ recordObj = NULL;
+ }
+
+ RETiRet;
+}
+/* Build a JSON batch by placing each element in an array.
+ */
+static rsRetVal
+serializeBatchJsonArray(wrkrInstanceData_t *pWrkrData, char **batchBuf)
+{
+ fjson_object *batchArray = NULL;
+ fjson_object *msgObj = NULL;
+ size_t numMessages = pWrkrData->batch.nmemb;
+ size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas
+ DBGPRINTF("omhttp: serializeBatchJsonArray numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal);
+
+ DEFiRet;
+
+ batchArray = fjson_object_new_array();
+ if (batchArray == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchJsonArray failed to create array");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (size_t i = 0; i < numMessages; i++) {
+ msgObj = fjson_tokener_parse((char *) pWrkrData->batch.data[i]);
+ if (msgObj == NULL) {
+ LogError(0, NO_ERRCODE,
+ "omhttp: serializeBatchJsonArray failed to parse %s as json, ignoring it",
+ pWrkrData->batch.data[i]);
+ continue;
+ }
+ fjson_object_array_add(batchArray, msgObj);
+ }
+
+ const char *batchString = fjson_object_to_json_string_ext(batchArray, FJSON_TO_STRING_PLAIN);
+ *batchBuf = strndup(batchString, strlen(batchString));
+
+finalize_it:
+ if (batchArray != NULL) {
+ fjson_object_put(batchArray);
+ batchArray = NULL;
+ }
+ RETiRet;
+}
+
+/* Build a batch by joining each element with a newline character.
+ */
+static rsRetVal
+serializeBatchNewline(wrkrInstanceData_t *pWrkrData, char **batchBuf)
+{
+ DEFiRet;
+ size_t numMessages = pWrkrData->batch.nmemb;
+ size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages; // message + newline + null term
+ int r = 0;
+
+ DBGPRINTF("omhttp: serializeBatchNewline numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal);
+
+ es_str_t *batchString = es_newStr(1024);
+
+ if (batchString == NULL)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ for (size_t i = 0; i < numMessages; i++) {
+ size_t nToCopy = ustrlen(pWrkrData->batch.data[i]);
+ if (r == 0) r = es_addBuf(&batchString, (char *)pWrkrData->batch.data[i], nToCopy);
+ if (i == numMessages - 1) break;
+ if (r == 0) r = es_addChar(&batchString, '\n');
+ }
+
+ if (r == 0) *batchBuf = (char *) es_str2cstr(batchString, NULL);
+
+ if (r != 0 || *batchBuf== NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: serializeBatchNewline failed to build batch string");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if (batchString != NULL)
+ es_deleteStr(batchString);
+
+ RETiRet;
+}
+
+/* Return the final batch size in bytes for each serialization method.
+ * Used to decide if a batch should be flushed early.
+ */
+static size_t
+computeBatchSize(wrkrInstanceData_t *pWrkrData)
+{
+ size_t extraBytes = 0;
+ size_t sizeBytes = pWrkrData->batch.sizeBytes;
+ size_t numMessages = pWrkrData->batch.nmemb;
+
+ switch (pWrkrData->pData->batchFormat) {
+ case FMT_JSONARRAY:
+ // square brackets, commas between each message
+ // 2 + numMessages - 1 = numMessages + 1
+ extraBytes = numMessages > 0 ? numMessages + 1 : 2;
+ break;
+ case FMT_KAFKAREST:
+ // '{}', '[]', '"records":'= 2 + 2 + 10 = 14
+ // '{"value":}' for each message = n * 10
+ // numMessages == 0 handled implicitly in multiplication
+ extraBytes = (numMessages * 10) + 14;
+ break;
+ case FMT_NEWLINE:
+ // newlines between each message
+ extraBytes = numMessages > 0 ? numMessages - 1 : 0;
+ break;
+ case FMT_LOKIREST:
+ // {"streams":[ '{}', '[]', '"streams":' = 14
+ // {"stream": {key:value}..., "values":[[timestamp: msg1]]},
+ // {"stream": {key:value}..., "values":[[timestamp: msg2]]}
+ // ]}
+ // message (11) * numMessages + header ( 16 )
+ extraBytes = (numMessages * 2) + 14;
+ break;
+ default:
+ // newlines between each message
+ extraBytes = numMessages > 0 ? numMessages - 1 : 0;
+ }
+
+ return sizeBytes + extraBytes + 1; // plus a null
+}
+
+static void ATTR_NONNULL()
+initializeBatch(wrkrInstanceData_t *pWrkrData)
+{
+ pWrkrData->batch.sizeBytes = 0;
+ pWrkrData->batch.nmemb = 0;
+ if (pWrkrData->batch.restPath != NULL) {
+ free(pWrkrData->batch.restPath);
+ pWrkrData->batch.restPath = NULL;
+ }
+}
+
+/* Adds a message to this worker's batch
+ */
+static rsRetVal
+buildBatch(wrkrInstanceData_t *pWrkrData, uchar *message)
+{
+ DEFiRet;
+
+ if (pWrkrData->batch.nmemb >= pWrkrData->pData->maxBatchSize) {
+ LogError(0, RS_RET_ERR, "omhttp: buildBatch something has gone wrong,"
+ "number of messages in batch is bigger than the max batch size, bailing");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pWrkrData->batch.data[pWrkrData->batch.nmemb] = message;
+ pWrkrData->batch.sizeBytes += strlen((char *)message);
+ pWrkrData->batch.nmemb++;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+submitBatch(wrkrInstanceData_t *pWrkrData, uchar **tpls)
+{
+ DEFiRet;
+ char *batchBuf = NULL;
+
+ switch (pWrkrData->pData->batchFormat) {
+ case FMT_JSONARRAY:
+ iRet = serializeBatchJsonArray(pWrkrData, &batchBuf);
+ break;
+ case FMT_KAFKAREST:
+ iRet = serializeBatchKafkaRest(pWrkrData, &batchBuf);
+ break;
+ case FMT_LOKIREST:
+ iRet = serializeBatchLokiRest(pWrkrData, &batchBuf);
+ break;
+ case FMT_NEWLINE:
+ iRet = serializeBatchNewline(pWrkrData, &batchBuf);
+ break;
+ default:
+ iRet = serializeBatchNewline(pWrkrData, &batchBuf);
+ }
+
+ if (iRet != RS_RET_OK || batchBuf == NULL)
+ ABORT_FINALIZE(iRet);
+
+ DBGPRINTF("omhttp: submitBatch, batch: '%s' tpls: '%p'\n", batchBuf, tpls);
+
+ CHKiRet(curlPost(pWrkrData, (uchar*) batchBuf, strlen(batchBuf),
+ tpls, pWrkrData->batch.nmemb));
+
+finalize_it:
+ if (batchBuf != NULL)
+ free(batchBuf);
+ RETiRet;
+}
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ if(!pWrkrData->pData->batchMode) {
+ FINALIZE;
+ }
+
+ initializeBatch(pWrkrData);
+finalize_it:
+ENDbeginTransaction
+
+BEGINdoAction
+size_t nBytes;
+sbool submit;
+CODESTARTdoAction
+ instanceData *const pData = pWrkrData->pData;
+ uchar *restPath = NULL;
+ STATSCOUNTER_INC(ctrMessagesSubmitted, mutCtrMessagesSubmitted);
+
+ if (pWrkrData->pData->batchMode) {
+ if(pData->dynRestPath) {
+ /* Get copy of restpath in batch mode if dynRestPath enabled */
+ getRestPath(pData, ppString, &restPath);
+ if (pWrkrData->batch.restPath == NULL) {
+ pWrkrData->batch.restPath = (uchar*)strdup((char*)restPath);
+ } else if (strcmp((char*)pWrkrData->batch.restPath, (char*)restPath) != 0) {
+ /* Check if the restPath changed - if yes submit the current batch first*/
+ CHKiRet(submitBatch(pWrkrData, NULL));
+ initializeBatch(pWrkrData);
+ }
+ }
+
+ /* If the maxbatchsize is 1, then build and immediately post a batch with 1 element.
+ * This mode will play nicely with rsyslog's action.resumeRetryCount logic.
+ */
+ if (pWrkrData->pData->maxBatchSize == 1) {
+ initializeBatch(pWrkrData);
+ CHKiRet(buildBatch(pWrkrData, ppString[0]));
+ CHKiRet(submitBatch(pWrkrData, ppString));
+ FINALIZE;
+ }
+
+ /* We should submit if any of these conditions are true
+ * 1. Total batch size > pWrkrData->pData->maxBatchSize
+ * 2. Total bytes > pWrkrData->pData->maxBatchBytes
+ */
+ nBytes = ustrlen((char *)ppString[0]) - 1 ;
+ submit = 0;
+
+ if (pWrkrData->batch.nmemb >= pWrkrData->pData->maxBatchSize) {
+ submit = 1;
+ DBGPRINTF("omhttp: maxbatchsize limit reached submitting batch of %zd elements.\n",
+ pWrkrData->batch.nmemb);
+ } else if (computeBatchSize(pWrkrData) + nBytes > pWrkrData->pData->maxBatchBytes) {
+ submit = 1;
+ DBGPRINTF("omhttp: maxbytes limit reached submitting partial batch of %zd elements.\n",
+ pWrkrData->batch.nmemb);
+ }
+
+ if (submit) {
+ CHKiRet(submitBatch(pWrkrData, ppString));
+ initializeBatch(pWrkrData);
+ }
+
+ CHKiRet(buildBatch(pWrkrData, ppString[0]));
+
+ /* If there is only one item in the batch, all previous items have been
+ * submitted or this is the first item for this transaction. Return previous
+ * committed so that all items leading up to the current (exclusive)
+ * are not replayed should a failure occur anywhere else in the transaction. */
+ iRet = pWrkrData->batch.nmemb == 1 ? RS_RET_PREVIOUS_COMMITTED : RS_RET_DEFER_COMMIT;
+ } else {
+ CHKiRet(curlPost(pWrkrData, ppString[0], strlen((char*)ppString[0]), ppString, 1));
+ }
+finalize_it:
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+ /* End Transaction only if batch data is not empty */
+ if (pWrkrData->batch.nmemb > 0) {
+ CHKiRet(submitBatch(pWrkrData, NULL));
+ } else {
+ dbgprintf("omhttp: endTransaction, pWrkrData->batch.nmemb = 0, "
+ "nothing to send. \n");
+ }
+finalize_it:
+ENDendTransaction
+
+/* Creates authentication header uid:pwd
+ */
+static rsRetVal
+computeAuthHeader(char* uid, char* pwd, uchar** authBuf)
+{
+ int r;
+ DEFiRet;
+
+ es_str_t* auth = es_newStr(1024);
+ if (auth == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: failed to allocate es_str auth for auth header construction");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ r = es_addBuf(&auth, uid, strlen(uid));
+ if(r == 0) r = es_addChar(&auth, ':');
+ if(r == 0 && pwd != NULL) r = es_addBuf(&auth, pwd, strlen(pwd));
+ if(r == 0) *authBuf = (uchar*) es_str2cstr(auth, NULL);
+
+ if (r != 0 || *authBuf == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: failed to build auth header\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if (auth != NULL)
+ es_deleteStr(auth);
+ RETiRet;
+}
+
+static rsRetVal
+computeApiHeader(char* key, char* value, uchar** headerBuf)
+{
+ int r;
+ DEFiRet;
+
+ es_str_t* header = es_newStr(10240);
+ if (header == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omhttp: failed to allocate es_str auth for api header construction");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ r = es_addBuf(&header, key, strlen(key));
+ if(r == 0) r = es_addChar(&header, ':');
+ if(r == 0) r = es_addChar(&header, ' ');
+ if(r == 0 && value != NULL) r = es_addBuf(&header, value, strlen(value));
+ if(r == 0) *headerBuf = (uchar*) es_str2cstr(header, NULL);
+
+ if (r != 0 || *headerBuf == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: failed to build http header\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if (header != NULL)
+ es_deleteStr(header);
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader);
+ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData);
+ if(pWrkrData->pData->allowUnsignedCerts)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE);
+ if(pWrkrData->pData->skipVerifyHost)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, FALSE);
+ if(pWrkrData->pData->authBuf != NULL) {
+ curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf);
+ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+ }
+ if(pWrkrData->pData->caCertFile)
+ curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
+ if(pWrkrData->pData->myCertFile)
+ curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
+ if(pWrkrData->pData->myPrivKeyFile)
+ curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
+ /* uncomment for in-dept debuggung:
+ curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */
+}
+
+static void ATTR_NONNULL()
+curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curlSetupCommon(pWrkrData, pWrkrData->curlCheckConnHandle);
+ curl_easy_setopt(pWrkrData->curlCheckConnHandle,
+ CURLOPT_TIMEOUT_MS, pWrkrData->pData->healthCheckTimeout);
+}
+
+static void ATTR_NONNULL(1)
+curlPostSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curlSetupCommon(pWrkrData, pWrkrData->curlPostHandle);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_POST, 1);
+ CURLcode cRet;
+ /* Enable TCP keep-alive for this transfer */
+ cRet = curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_TCP_KEEPALIVE, 1L);
+ if (cRet != CURLE_OK)
+ DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPALIVE\n");
+ /* keep-alive idle time to 120 seconds */
+ cRet = curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_TCP_KEEPIDLE, 120L);
+ if (cRet != CURLE_OK)
+ DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPIDLE\n");
+ /* interval time between keep-alive probes: 60 seconds */
+ cRet = curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_TCP_KEEPINTVL, 60L);
+ if (cRet != CURLE_OK)
+ DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPINTVL\n");
+}
+
+static rsRetVal ATTR_NONNULL()
+curlSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ struct curl_slist *slist = NULL;
+
+ DEFiRet;
+ if (pWrkrData->pData->httpcontenttype != NULL) {
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerContentTypeBuf);
+ } else {
+ slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON);
+ }
+
+ if (pWrkrData->pData->headerBuf != NULL) {
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerBuf);
+ CHKmalloc(slist);
+ }
+
+ for (int k = 0 ; k < pWrkrData->pData->nHttpHeaders; k++) {
+ slist = curl_slist_append(slist, (char *)pWrkrData->pData->httpHeaders[k]);
+ CHKmalloc(slist);
+ }
+
+ // When sending more than 1Kb, libcurl automatically sends an Except: 100-Continue header
+ // and will wait 1s for a response, could make this configurable but for now disable
+ slist = curl_slist_append(slist, HTTP_HEADER_EXPECT_EMPTY);
+ pWrkrData->curlHeader = slist;
+ CHKmalloc(pWrkrData->curlPostHandle = curl_easy_init());
+ curlPostSetup(pWrkrData);
+
+ CHKmalloc(pWrkrData->curlCheckConnHandle = curl_easy_init());
+ curlCheckConnSetup(pWrkrData);
+
+finalize_it:
+ if(iRet != RS_RET_OK && pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+curlCleanup(wrkrInstanceData_t *const pWrkrData)
+{
+ if (pWrkrData->curlHeader != NULL) {
+ curl_slist_free_all(pWrkrData->curlHeader);
+ pWrkrData->curlHeader = NULL;
+ }
+ if (pWrkrData->curlCheckConnHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlCheckConnHandle);
+ pWrkrData->curlCheckConnHandle = NULL;
+ }
+ if (pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+}
+
+static void ATTR_NONNULL()
+setInstParamDefaults(instanceData *const pData)
+{
+ pData->serverBaseUrls = NULL;
+ pData->defaultPort = 443;
+ pData->healthCheckTimeout = 3500;
+ pData->uid = NULL;
+ pData->httpcontenttype = NULL;
+ pData->headerContentTypeBuf = NULL;
+ pData->httpheaderkey = NULL;
+ pData->httpheadervalue = NULL;
+ pData->httpHeaders = NULL;
+ pData->nHttpHeaders = 0;
+ pData->pwd = NULL;
+ pData->authBuf = NULL;
+ pData->restPath = NULL;
+ pData->checkPath = NULL;
+ pData->dynRestPath = 0;
+ pData->batchMode = 0;
+ pData->batchFormatName = (uchar *)"newline";
+ pData->batchFormat = FMT_NEWLINE;
+ pData->bFreeBatchFormatName = 0;
+ pData->useHttps = 1;
+ pData->maxBatchBytes = 10485760; //i.e. 10 MB Is the default max message size for AWS API Gateway
+ pData->maxBatchSize = 100; // 100 messages
+ pData->compress = 0; // off
+ pData->compressionLevel = -1; // default compression
+ pData->allowUnsignedCerts = 0;
+ pData->skipVerifyHost = 0;
+ pData->tplName = NULL;
+ pData->errorFile = NULL;
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+ pData->reloadOnHup= 0;
+ pData->retryFailures = 0;
+ pData->ratelimitBurst = 20000;
+ pData->ratelimitInterval = 600;
+ pData->ratelimiter = NULL;
+ pData->retryRulesetName = NULL;
+ pData->retryRuleset = NULL;
+}
+
+static rsRetVal
+checkHeaderParam(char *const param)
+{
+ DEFiRet;
+ char *val = strstr(param, ":");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing ':' delimiter in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ char* serverParam = NULL;
+ struct cnfarray* servers = NULL;
+ int i;
+ int iNumTpls;
+ FILE *fp;
+ char errStr[1024];
+ char *batchFormatName;
+ int compressionLevel = -1;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ servers = pvals[i].val.d.ar;
+ } else if(!strcmp(actpblk.descr[i].name, "errorfile")) {
+ pData->errorFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->defaultPort = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "healthchecktimeout")) {
+ pData->healthCheckTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "uid")) {
+ pData->uid = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "httpcontenttype")) {
+ pData->httpcontenttype = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "httpheaderkey")) {
+ pData->httpheaderkey = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "httpheadervalue")) {
+ pData->httpheadervalue = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "httpheaders")) {
+ pData->nHttpHeaders = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->httpHeaders = malloc(sizeof(uchar *) * pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(checkHeaderParam(cstr));
+ pData->httpHeaders[j] = (uchar *)cstr;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ pData->pwd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "restpath")) {
+ pData->restPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "checkpath")) {
+ pData->checkPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynrestpath")) {
+ pData->dynRestPath = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "batch")) {
+ pData->batchMode = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "batch.format")) {
+ batchFormatName = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (strstr(VALID_BATCH_FORMATS, batchFormatName) != NULL) {
+ pData->batchFormatName = (uchar *)batchFormatName;
+ pData->bFreeBatchFormatName = 1;
+ if (!strcmp(batchFormatName, "newline")) {
+ pData->batchFormat = FMT_NEWLINE;
+ } else if (!strcmp(batchFormatName, "jsonarray")) {
+ pData->batchFormat = FMT_JSONARRAY;
+ } else if (!strcmp(batchFormatName, "kafkarest")) {
+ pData->batchFormat = FMT_KAFKAREST;
+ } else if (!strcmp(batchFormatName, "lokirest")) {
+ pData->batchFormat = FMT_LOKIREST;
+ }
+ } else {
+ LogError(0, NO_ERRCODE, "error: 'batch.format' %s unknown defaulting to 'newline'",
+ batchFormatName);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "batch.maxbytes")) {
+ pData->maxBatchBytes = (size_t) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "batch.maxsize")) {
+ pData->maxBatchSize = (size_t) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "compress")) {
+ pData->compress = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "compress.level")) {
+ compressionLevel = pvals[i].val.d.n;
+ if (compressionLevel == -1 || (compressionLevel >= 0 && compressionLevel < 10)) {
+ pData->compressionLevel = compressionLevel;
+ } else {
+ LogError(0, NO_ERRCODE, "omhttp: invalid compress.level %d using default instead,"
+ "valid levels are -1 and 0-9",
+ compressionLevel);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
+ pData->allowUnsignedCerts = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "skipverifyhost")) {
+ pData->skipVerifyHost = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "usehttps")) {
+ pData->useHttps = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ pData->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->caCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.cacert' file %s couldn't be accessed: %s\n",
+ pData->caCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "reloadonhup")) {
+ pData->reloadOnHup= pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "retry")) {
+ pData->retryFailures = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "retry.ruleset")) {
+ pData->retryRulesetName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.burst")) {
+ pData->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.interval")) {
+ pData->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR, "omhttp: program error, "
+ "non-handled param '%s'", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->pwd != NULL && pData->uid == NULL) {
+ LogError(0, RS_RET_UID_MISSING,
+ "omhttp: password is provided, but no uid "
+ "- action definition invalid");
+ ABORT_FINALIZE(RS_RET_UID_MISSING);
+ }
+ if(pData->httpheaderkey != NULL && pData->httpheadervalue == NULL) {
+ LogError(0, RS_RET_UID_MISSING,
+ "omhttp: http header key is provided, but no http header value "
+ "- action definition invalid");
+ ABORT_FINALIZE(RS_RET_UID_MISSING);
+ }
+ if(pData->dynRestPath && pData->restPath == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omhttp: requested dynamic rest path, but no name for rest "
+ "path template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if (pData->uid != NULL)
+ CHKiRet(computeAuthHeader((char*) pData->uid, (char*) pData->pwd, &pData->authBuf));
+ if (pData->httpcontenttype != NULL)
+ CHKiRet(computeApiHeader((char*) "Content-Type",
+ (char*) pData->httpcontenttype, &pData->headerContentTypeBuf));
+
+ if (pData->httpheaderkey != NULL)
+ CHKiRet(computeApiHeader((char*) pData->httpheaderkey,
+ (char*) pData->httpheadervalue, &pData->headerBuf));
+
+ iNumTpls = 1;
+ if(pData->dynRestPath) ++iNumTpls;
+ DBGPRINTF("omhttp: requesting %d templates\n", iNumTpls);
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ " StdJSONFmt" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+
+ /* we need to request additional templates. If we have a dynamic search index,
+ * it will always be string 1. Type may be 1 or 2, depending on whether search
+ * index is dynamic as well. Rule needs to be followed throughout the module.
+ */
+ iNumTpls = 1;
+ if(pData->dynRestPath) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->restPath),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+
+ if (servers != NULL) {
+ pData->numServers = servers->nmemb;
+ pData->serverBaseUrls = malloc(servers->nmemb * sizeof(uchar*));
+ if (pData->serverBaseUrls == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer "
+ "for http server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for(i = 0 ; i < servers->nmemb ; ++i) {
+ serverParam = es_str2cstr(servers->arr[i], NULL);
+ if (serverParam == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer "
+ "for http server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* Remove a trailing slash if it exists */
+ const size_t serverParamLastChar = strlen(serverParam)-1;
+ if (serverParam[serverParamLastChar] == '/') {
+ serverParam[serverParamLastChar] = '\0';
+ }
+ CHKiRet(computeBaseUrl(serverParam, pData->defaultPort, pData->useHttps,
+ pData->serverBaseUrls + i));
+ free(serverParam);
+ serverParam = NULL;
+ }
+ } else {
+ LogMsg(0, RS_RET_OK, LOG_WARNING,
+ "omhttp: No servers specified, using localhost");
+ pData->numServers = 1;
+ pData->serverBaseUrls = malloc(sizeof(uchar*));
+ if (pData->serverBaseUrls == NULL) {
+ LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer "
+ "for http server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKiRet(computeBaseUrl("localhost", pData->defaultPort, pData->useHttps, pData->serverBaseUrls));
+ }
+
+ if (pData->retryFailures) {
+ CHKiRet(ratelimitNew(&pData->ratelimiter, "omhttp", NULL));
+ ratelimitSetLinuxLike(pData->ratelimiter, pData->ratelimitInterval, pData->ratelimitBurst);
+ ratelimitSetNoTimeCache(pData->ratelimiter);
+ }
+
+ /* node created, let's add to list of instance configs for the module */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = pData;
+ } else {
+ loadModConf->tail->next = pData;
+ loadModConf->tail = pData;
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ if (serverParam)
+ free(serverParam);
+ENDnewActInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->root = pModConf->tail = NULL;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+
+ if (inst->retryRulesetName) {
+ localRet = ruleset.GetRuleset(pModConf->pConf, &pRuleset, inst->retryRulesetName);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, localRet, "omhttp: retry.ruleset '%s' not found - "
+ "no retry ruleset will be used", inst->retryRulesetName);
+ } else {
+ inst->retryRuleset = pRuleset;
+ }
+ }
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+// HUP handling for the instance...
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutErrFile);
+ if (pData->fdErrFile != -1) {
+ close(pData->fdErrFile);
+ pData->fdErrFile = -1;
+ }
+ pthread_mutex_unlock(&pData->mutErrFile);
+ENDdoHUP
+
+
+// HUP handling for the worker...
+BEGINdoHUPWrkr
+CODESTARTdoHUPWrkr
+ if (pWrkrData->pData->reloadOnHup) {
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "omhttp: received HUP reloading curl handles");
+ curlCleanup(pWrkrData);
+ CHKiRet(curlSetup(pWrkrData));
+ }
+finalize_it:
+ENDdoHUPWrkr
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ curl_global_cleanup();
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ statsobj.Destruct(&httpStats);
+ENDmodExit
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_doHUPWrkr /* Load the worker HUP handling code */
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ CHKiRet(statsobj.Construct(&httpStats));
+ CHKiRet(statsobj.SetName(httpStats, (uchar *)"omhttp"));
+ CHKiRet(statsobj.SetOrigin(httpStats, (uchar*)"omhttp"));
+
+ STATSCOUNTER_INIT(ctrMessagesSubmitted, mutCtrMessagesSubmitted);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesSubmitted));
+
+ STATSCOUNTER_INIT(ctrMessagesSuccess, mutCtrMessagesSuccess);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.success",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesSuccess));
+
+ STATSCOUNTER_INIT(ctrMessagesFail, mutCtrMessagesFail);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.fail",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesFail));
+
+ STATSCOUNTER_INIT(ctrMessagesRetry, mutCtrMessagesRetry);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.retry",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesRetry));
+
+ STATSCOUNTER_INIT(ctrHttpRequestCount, mutCtrHttpRequestCount);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.count",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestCount));
+
+ STATSCOUNTER_INIT(ctrHttpRequestSuccess, mutCtrHttpRequestSuccess);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.success",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestSuccess));
+
+ STATSCOUNTER_INIT(ctrHttpRequestFail, mutCtrHttpRequestFail);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.fail",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestFail));
+
+ STATSCOUNTER_INIT(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.status.success",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpStatusSuccess));
+
+ STATSCOUNTER_INIT(ctrHttpStatusFail, mutCtrHttpStatusFail);
+ CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.status.fail",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpStatusFail));
+
+ CHKiRet(statsobj.ConstructFinalize(httpStats));
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -http disabled");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("omhttp"), sizeof("omhttp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/contrib/omhttpfs/Makefile.am b/contrib/omhttpfs/Makefile.am
new file mode 100644
index 0000000..d3af018
--- /dev/null
+++ b/contrib/omhttpfs/Makefile.am
@@ -0,0 +1,9 @@
+pkglib_LTLIBRARIES = omhttpfs.la
+
+omhttpfs_la_SOURCES = omhttpfs.c
+omhttpfs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBFASTJSON_CFLAGS)
+omhttpfs_la_LDFLAGS = -module -avoid-version
+omhttpfs_la_LIBADD = $(CURL_LIBS) $(LIBFASTJSON_LIBS)
+
+
+EXTRA_DIST =
diff --git a/contrib/omhttpfs/Makefile.in b/contrib/omhttpfs/Makefile.in
new file mode 100644
index 0000000..a55d0bc
--- /dev/null
+++ b/contrib/omhttpfs/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omhttpfs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omhttpfs_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_omhttpfs_la_OBJECTS = omhttpfs_la-omhttpfs.lo
+omhttpfs_la_OBJECTS = $(am_omhttpfs_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 =
+omhttpfs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omhttpfs_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo
+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 = $(omhttpfs_la_SOURCES)
+DIST_SOURCES = $(omhttpfs_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omhttpfs.la
+omhttpfs_la_SOURCES = omhttpfs.c
+omhttpfs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBFASTJSON_CFLAGS)
+omhttpfs_la_LDFLAGS = -module -avoid-version
+omhttpfs_la_LIBADD = $(CURL_LIBS) $(LIBFASTJSON_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/omhttpfs/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omhttpfs/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omhttpfs.la: $(omhttpfs_la_OBJECTS) $(omhttpfs_la_DEPENDENCIES) $(EXTRA_omhttpfs_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omhttpfs_la_LINK) -rpath $(pkglibdir) $(omhttpfs_la_OBJECTS) $(omhttpfs_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omhttpfs_la-omhttpfs.lo: omhttpfs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttpfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhttpfs_la-omhttpfs.lo -MD -MP -MF $(DEPDIR)/omhttpfs_la-omhttpfs.Tpo -c -o omhttpfs_la-omhttpfs.lo `test -f 'omhttpfs.c' || echo '$(srcdir)/'`omhttpfs.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhttpfs_la-omhttpfs.Tpo $(DEPDIR)/omhttpfs_la-omhttpfs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhttpfs.c' object='omhttpfs_la-omhttpfs.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) $(omhttpfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhttpfs_la-omhttpfs.lo `test -f 'omhttpfs.c' || echo '$(srcdir)/'`omhttpfs.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omhttpfs/omhttpfs.c b/contrib/omhttpfs/omhttpfs.c
new file mode 100644
index 0000000..1bdacf6
--- /dev/null
+++ b/contrib/omhttpfs/omhttpfs.c
@@ -0,0 +1,855 @@
+/* omhttpfs.c
+ * Send all output to HDFS via httpfs
+ *
+ * Author: sskaje (sskaje@gmail.com, http://sskaje.me/)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <curl/curl.h>
+#include <json.h>
+#include <json_object.h>
+
+
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "datetime.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omhttpfs")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+
+/* local definitions */
+#define OMHTTPFS_VERSION "1.0"
+#define OMHTTPFS_DEFAULT_PORT 14000
+#define OMHTTPFS_DEFAULT_USER "hdfs"
+#define OMHTTPFS_DEFAULT_HOST "127.0.0.1"
+
+#define HTTPFS_URL_PREFIX_V1 "/webhdfs/v1"
+#define HTTPFS_URL_PREFIX_V1_SSL "/swebhdfs/v1"
+#define HTTPFS_CONTENT_TYPE "Content-Type: application/octet-stream"
+#define HTTPFS_USER_AGENT "omhttpfs by sskaje/" OMHTTPFS_VERSION
+
+#define HTTPFS_CONTENT_TYPE_JSON "application/json"
+#define HTTPFS_JSON_BOOLEAN_TRUE "{\"boolean\":true}"
+
+#define HTTPFS_FILEALREADYEXISTSEXCEPTION "FileAlreadyExistsException"
+
+#define HTTPFS_URL_BUFFER_LENGTH 2048
+
+
+/*
+Examples:
+
+module(load="omhttpfs")
+template(name="hdfs_tmp_file" type="string" string="/tmp/%$YEAR%/test.log")
+template(name="hdfs_tmp_filecontent" type="string" string="%$YEAR%-%$MONTH%-%$DAY% %MSG% ==\n")
+local4.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on")
+local5.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on"
+template="hdfs_tmp_filecontent")
+
+*/
+
+#define DPP(x) DBGPRINTF("OMHTTPFS: %s:%d %s(): %s\n", __FILE__, __LINE__, __FUNCTION__, x)
+
+/**
+ * Exception object
+ *
+ */
+typedef struct _HTTPFS_JSON_REMOTE_EXCEPTION {
+ char message[1024];
+ char exception[256];
+ char class[256];
+} httpfs_json_remote_exception;
+
+
+typedef struct _instanceData {
+ sbool https;
+ uchar* host;
+ uchar* ip;
+ int port;
+ uchar* user;
+
+ int timeout;
+ uchar* file;
+ sbool isDynFile;
+
+ uchar* tplName;
+} instanceData;
+
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+
+ CURL* curl;
+
+ uchar* file;
+
+ int replyLen;
+ char* reply;
+} wrkrInstanceData_t;
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "host", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrInt, 0 },
+ { "user", eCmdHdlrGetWord, 0 },
+ { "https", eCmdHdlrBinary, 0 },
+ { "file", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "isdynfile", eCmdHdlrBinary, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+/**
+ * curl init
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param instanceData *pData
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_init_curl(wrkrInstanceData_t *pWrkrData, instanceData *pData)
+{
+ CURL *curl = NULL;
+
+ curl = curl_easy_init();
+
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
+
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ if (pData->https) {
+ DBGPRINTF("%s(): Enable HTTPS\n", __FUNCTION__);
+ /* for ssl */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+ } else {
+ /* LOG */
+ LogError(0, RS_RET_OBJ_CREATION_FAILED, "omhttpfs: failed to init cURL\n");
+
+ return RS_RET_OBJ_CREATION_FAILED;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, HTTPFS_USER_AGENT);
+
+ pWrkrData->curl = curl;
+ return RS_RET_OK;
+}
+
+/**
+ * Build HTTPFS URL
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param char* op
+ * @param es_str_t** url_buf
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_build_url(wrkrInstanceData_t *pWrkrData, const char* op, es_str_t** url_buf)
+{
+ *url_buf = es_newStr(HTTPFS_URL_BUFFER_LENGTH);
+
+ if (pWrkrData->pData->https) {
+ es_addBuf(url_buf, "https://", sizeof("https://")-1);
+ } else {
+ es_addBuf(url_buf, "http://", sizeof("http://")-1);
+ }
+
+ /* host */
+ es_addBuf(url_buf, (char* )pWrkrData->pData->host, strlen((char*)pWrkrData->pData->host));
+
+ /* port */
+ es_addChar(url_buf, ':');
+ char portBuf[6];
+ snprintf(portBuf, sizeof(portBuf), "%d", pWrkrData->pData->port);
+ es_addBuf(url_buf, portBuf, strlen(portBuf));
+
+ /* prefix */
+ es_addBuf(url_buf, HTTPFS_URL_PREFIX_V1, sizeof(HTTPFS_URL_PREFIX_V1)-1);
+
+ /* path */
+ if (pWrkrData->file[0] != '/') {
+ es_addChar(url_buf, '/');
+ }
+ es_addBuf(url_buf, (char* )pWrkrData->file, strlen((char* )pWrkrData->file));
+
+ /* queries */
+ /* user */
+ es_addBuf(url_buf, "?user.name=", sizeof("?user.name=")-1);
+ es_addBuf(url_buf, (char* )pWrkrData->pData->user, strlen((char* )pWrkrData->pData->user));
+
+ /* extra parameters */
+ es_addBuf(url_buf, op, strlen(op));
+
+ return RS_RET_OK;
+}
+
+/**
+ * curl set URL
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param char* op
+ * @return void
+ */
+static void httpfs_set_url(wrkrInstanceData_t *pWrkrData, const char* op)
+{
+ es_str_t* url;
+ char* url_cstr;
+ httpfs_build_url(pWrkrData, op, &url);
+ url_cstr = es_str2cstr(url, NULL);
+
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_URL, url_cstr);
+ free(url_cstr);
+}
+/**
+ * Set http method to PUT
+ *
+ * @param CURL* curl
+ * @return void
+ */
+static void httpfs_curl_set_put(CURL* curl)
+{
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L);
+ curl_easy_setopt(curl, CURLOPT_NOBODY, 0L);
+ curl_easy_setopt(curl, CURLOPT_POST, 0L);
+ curl_easy_setopt(curl, CURLOPT_PUT, 0L);
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L);
+
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
+}
+/**
+ * Set http method to POST
+ *
+ * @param CURL* curl
+ * @return void
+ */
+static void httpfs_curl_set_post(CURL* curl)
+{
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L);
+ curl_easy_setopt(curl, CURLOPT_NOBODY, 0L);
+ curl_easy_setopt(curl, CURLOPT_PUT, 0L);
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L);
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
+}
+
+/**
+ * Build curl slist
+ *
+ * @param struct curl_slist* headers
+ * @param int hdr_count
+ * @param ...
+ * @return struct curl_slist*
+ */
+static struct curl_slist*
+httpfs_curl_add_header(struct curl_slist* headers, int hdr_count, ...)
+{
+ const char* hdr;
+
+ va_list ar;
+ va_start(ar, hdr_count);
+ for (; hdr_count > 0; hdr_count--) {
+ hdr = va_arg(ar, const char*);
+
+ if (hdr != NULL
+ && hdr[0] != 0) {
+ /* non-empty string */
+ headers = curl_slist_append(headers, hdr);
+ } else {
+ break;
+ }
+ }
+ va_end(ar);
+
+ headers = curl_slist_append(headers, "Expect:");
+ headers = curl_slist_append(headers, "Transfer-Encoding:");
+
+ return headers;
+}
+
+/**
+ * Callback function for CURLOPT_WRITEFUNCTION
+ *
+ * @param void* contents
+ * @param size_t size
+ * @param size_t nmemb
+ * @param void *userp
+ * @return size_t
+ */
+static size_t
+httpfs_curl_result_callback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+ char *newreply = NULL;
+ wrkrInstanceData_t *mem = (wrkrInstanceData_t *)userp;
+
+ newreply = realloc(mem->reply, mem->replyLen + realsize + 1);
+ if (newreply == NULL) {
+ /* out of memory! */
+ dbgprintf("not enough memory (realloc returned NULL)\n");
+
+ if (mem->reply != NULL)
+ free(mem->reply);
+
+ mem->reply = NULL;
+ mem->replyLen = 0;
+
+ return 0;
+ }
+
+ mem->reply = newreply;
+ memcpy(&(mem->reply[mem->replyLen]), contents, realsize);
+ mem->replyLen += realsize;
+ mem->reply[mem->replyLen] = 0;
+
+ return realsize;
+}
+
+/**
+ * Variables declaration
+ * used in httpfs related operation
+ */
+#define HTTPFS_CURL_VARS_INIT \
+ struct curl_slist* headers = NULL; \
+ long response_code; \
+ CURLcode res; \
+ char* content_type;
+
+/**
+ * Resource release
+ * used in httpfs related operation
+ */
+#define HTTPFS_CURL_VARS_RELEASE \
+ curl_slist_free_all(headers);
+
+/**
+ * Curl execution
+ * used in httpfs related operation
+ */
+#define HTTPFS_CURL_EXEC \
+ pWrkrData->reply = NULL; \
+ pWrkrData->replyLen = 0; \
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_WRITEDATA, pWrkrData); \
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_WRITEFUNCTION, httpfs_curl_result_callback); \
+ res = curl_easy_perform(pWrkrData->curl); \
+ if (res == CURLE_OK) { \
+ curl_easy_getinfo(pWrkrData->curl, CURLINFO_CONTENT_TYPE, &content_type); \
+ if (strncmp(content_type, HTTPFS_CONTENT_TYPE_JSON, strlen(HTTPFS_CONTENT_TYPE_JSON))) { \
+ } \
+ curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code); \
+ if (pWrkrData->reply != NULL) { \
+ pWrkrData->reply[pWrkrData->replyLen] = '\0'; \
+ } \
+ } else { \
+ LogError(0, RS_RET_ERR, "CURL request fail, code=%d, error string=%s\n", res, curl_easy_strerror(res)); \
+ return -1; \
+ }
+
+/**
+ * Parse remote exception json string
+ *
+ * @param char* buf
+ * @param int length
+ * @param httpfs_json_remote_exception* jre
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_parse_exception(char* buf, int length, httpfs_json_remote_exception* jre)
+{
+ DEFiRet;
+
+ if (!length) {
+ return RS_RET_JSON_PARSE_ERR;
+ }
+
+ struct json_tokener* jt = json_tokener_new();
+ json_tokener_reset(jt);
+
+ struct json_object *json;
+ json = json_tokener_parse_ex(jt, buf, length);
+ if (!json_object_is_type(json, json_type_object)) {
+ ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
+ }
+
+ if (!json_object_object_get_ex(json, "RemoteException", &json)) {
+ ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
+ }
+
+ struct json_object *jobj;
+
+ memset(jre, 0, sizeof(*jre));
+
+ const char *str;
+
+ json_object_object_get_ex(json, "javaClassName", &jobj);
+ str = json_object_get_string(jobj);
+ strncpy(jre->class, str, sizeof(jre->class));
+ jre->class[sizeof(jre->class)-1] = '\0';
+
+ json_object_object_get_ex(json, "exception", &jobj);
+ str = json_object_get_string(jobj);
+ strncpy(jre->exception, str, sizeof(jre->exception));
+ jre->exception[sizeof(jre->exception)-1] = '\0';
+
+ json_object_object_get_ex(json, "message", &jobj);
+ str = json_object_get_string(jobj);
+ strncpy(jre->message, str, sizeof(jre->message));
+ jre->message[sizeof(jre->message)-1] = '\0';
+
+finalize_it:
+ if(jt != NULL)
+ json_tokener_free(jt);
+ if(json != NULL)
+ json_object_put(json);
+ RETiRet;
+}
+
+
+
+/**
+ * Create a file
+ * op=CREATE
+ * overwrite is turned off
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param char* buf
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_create_file(wrkrInstanceData_t *pWrkrData, uchar* buf)
+{
+ /* httpfs.create automatically create folders, no mkdirs needed. */
+
+ /*
+ curl -b /tmp/c.tmp -c /tmp/c.tmp -d 'aaaaabbbbb' -i -H 'Content-Type: application/octet-stream' -X PUT \
+ 'http://172.16.3.20:14000/webhdfs/v1/tmp/a/b?user.name=hdfs&op=create&data=true'
+ */
+HTTPFS_CURL_VARS_INIT
+ DBGPRINTF("%s(): file=%s\n", __FUNCTION__, pWrkrData->file);
+ httpfs_curl_set_put(pWrkrData->curl);
+
+ /*
+overwrite - if a file with this name already exists, then if true, the file will be overwritten, and if
+false an error will be thrown.
+bufferSize - the size of the buffer to be used.
+replication - required block replication for the file.
+ */
+ httpfs_set_url(pWrkrData, "&op=create&overwrite=false&data=true");
+
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDS, (char*)buf);
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDSIZE, strlen((char*) buf));
+
+ DBGPRINTF("%s(): msg=%s\n", __FUNCTION__, buf);
+
+ headers = httpfs_curl_add_header(headers, 1, HTTPFS_CONTENT_TYPE);
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_HTTPHEADER, headers);
+
+HTTPFS_CURL_EXEC
+
+ int success = 0;
+
+ if (response_code == 201) {
+ success = 1;
+ }
+
+HTTPFS_CURL_VARS_RELEASE
+ if (success) {
+ return RS_RET_OK;
+ } else {
+ return RS_RET_FALSE;
+ }
+}
+
+/**
+ * Append to file
+ * op=APPEND
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param char* buf
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_append_file(wrkrInstanceData_t *pWrkrData, uchar* buf)
+{
+ /*
+ curl -b /tmp/c.tmp -c /tmp/c.tmp -d 'aaaaabbbbb' -i -H 'Content-Type: application/octet-stream' \
+ 'http://172.16.3.20:14000/webhdfs/v1/tmp/a/b?user.name=hdfs&op=append&data=true'
+ */
+HTTPFS_CURL_VARS_INIT
+ DBGPRINTF("%s(): file=%s\n", __FUNCTION__, pWrkrData->file);
+ httpfs_curl_set_post(pWrkrData->curl);
+ httpfs_set_url(pWrkrData, "&op=append&data=true");
+
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDS, (char*)buf);
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDSIZE, strlen((char*) buf));
+
+ headers = httpfs_curl_add_header(headers, 1, HTTPFS_CONTENT_TYPE);
+ curl_easy_setopt(pWrkrData->curl, CURLOPT_HTTPHEADER, headers);
+ DBGPRINTF("%s(): msg=%s\n", __FUNCTION__, buf);
+
+HTTPFS_CURL_EXEC
+
+ int success = 0;
+
+ if (response_code == 200) {
+ success = 1;
+ } else if (response_code == 404) {
+ /* TODO: 404 ? */
+
+ }
+HTTPFS_CURL_VARS_RELEASE
+ if (success) {
+ return RS_RET_OK;
+ } else {
+ return RS_RET_FALSE;
+ }
+}
+
+
+/**
+ * httpfs log
+ *
+ * @param wrkrInstanceData_t *pWrkrData
+ * @param uchar* buf
+ * @return rsRetVal
+ */
+static rsRetVal
+httpfs_log(wrkrInstanceData_t *pWrkrData, uchar* buf)
+{
+ /**
+ append ? 200/end : (404 || ?)
+ create & ~overwrite ? 201/200/end :
+ append ? 200/end : error ?
+
+
+ */
+ DEFiRet;
+
+ long response_code;
+ httpfs_json_remote_exception jre;
+
+ iRet = httpfs_append_file(pWrkrData, buf);
+ if (iRet == RS_RET_OK) {
+ DBGPRINTF("omhttpfs: Append success: %s\n", pWrkrData->file);
+ return RS_RET_OK;
+ }
+
+ curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code);
+ if (response_code != 404) {
+ /* TODO: log error */
+ DBGPRINTF("omhttpfs: Append fail HTTP %ld: %s\n", response_code, pWrkrData->file);
+ return RS_RET_FALSE;
+ }
+
+ iRet = httpfs_create_file(pWrkrData, buf);
+ if (iRet == RS_RET_OK) {
+ DBGPRINTF("omhttpfs: Create file success: %s\n", pWrkrData->file);
+ return RS_RET_OK;
+ }
+
+ curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code);
+ if (response_code == 201) {
+ DBGPRINTF("omhttpfs: Create file success HTTP 201: %s\n", pWrkrData->file);
+ return RS_RET_OK;
+ }
+
+ if (response_code == 500) {
+ DBGPRINTF("omhttpfs: Create file failed HTTP %ld: %s\n", response_code, pWrkrData->file);
+ httpfs_parse_exception(pWrkrData->reply, pWrkrData->replyLen, &jre);
+ if (!strncmp(jre.exception, HTTPFS_FILEALREADYEXISTSEXCEPTION, strlen(HTTPFS_FILEALREADYEXISTSEXCEPTION))) {
+ /* file exists, go to append */
+ DBGPRINTF("omhttpfs: File already exists, append again: %s\n", pWrkrData->file);
+
+ iRet = httpfs_append_file(pWrkrData, buf);
+ if (iRet == RS_RET_OK) {
+ DBGPRINTF("omhttpfs: Re-Append success: %s\n", pWrkrData->file);
+ return RS_RET_OK;
+ } else {
+ DBGPRINTF("omhttpfs: Re-Append failed: %s\n", pWrkrData->file);
+ /* error
+ exit */
+ }
+
+ } else {
+ DBGPRINTF("omhttpfs: Create file failed: %s %s\n", pWrkrData->file, pWrkrData->reply);
+ }
+ } else {
+ DBGPRINTF("omhttpfs: Create file failed: %s %s\n", pWrkrData->file, pWrkrData->reply);
+ }
+
+ return RS_RET_FALSE;
+}
+
+
+BEGINinitConfVars
+ CODESTARTinitConfVars
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ DBGPRINTF("omhttpfs: createInstance\n");
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ DBGPRINTF("omhttpfs: createWrkrInstance\n");
+ pWrkrData->curl = NULL;
+ iRet = httpfs_init_curl(pWrkrData, pWrkrData->pData);
+ DBGPRINTF("omhttpfs: createWrkrInstance,pData %p/%p, pWrkrData %p\n",
+ pData, pWrkrData->pData, pWrkrData);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->file);
+ free(pData->tplName);
+ free(pData->host);
+ free(pData->user);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ free(pWrkrData->file);
+
+ if(pWrkrData->curl) {
+ curl_easy_cleanup(pWrkrData->curl);
+ pWrkrData->curl = NULL;
+ }
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("OmHTTPFS\n");
+ DBGPRINTF("Version: %s\n", OMHTTPFS_VERSION);
+ DBGPRINTF("\tHost: %s\n", pData->host);
+ DBGPRINTF("\tPort: %d\n", pData->port);
+ DBGPRINTF("\tUser: %s\n", pData->user);
+ DBGPRINTF("\tFile: %s\n", pData->file);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ DBGPRINTF("omhttpfs: tryResume called\n");
+ /* TODO: test networking */
+ iRet = RS_RET_OK;
+ENDtryResume
+
+/**
+* Do Action
+*/
+BEGINdoAction
+CODESTARTdoAction
+ DBGPRINTF("omhttpfs: doAction\n");
+ /* dynamic file name */
+ if (pWrkrData->pData->isDynFile) {
+ pWrkrData->file = ustrdup(ppString[1]);
+ } else {
+ pWrkrData->file = ustrdup(pWrkrData->pData->file);
+ }
+
+ /* ppString[0] -> log content */
+ iRet = httpfs_log(pWrkrData, ppString[0]);
+
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omhttpfs: error writing httpfs, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ENDdoAction
+
+
+
+/**
+ * Set default parameters
+ *
+ * @param instanceData *pData
+ * @return void
+ */
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->host = (uchar*) strdup(OMHTTPFS_DEFAULT_HOST);
+ pData->port = OMHTTPFS_DEFAULT_PORT;
+ pData->user = (uchar*) strdup(OMHTTPFS_DEFAULT_USER);
+ pData->https = 0;
+
+ pData->file = NULL;
+ pData->isDynFile = 0;
+ pData->tplName = NULL;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ uchar *tplToUse;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "host")) {
+ pData->host = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "user")) {
+ pData->user = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+
+ } else if(!strcmp(actpblk.descr[i].name, "https")) {
+ pData->https = pvals[i].val.d.n ? 1 : 0;
+
+ } else if(!strcmp(actpblk.descr[i].name, "file")) {
+ pData->file = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL);
+
+ } else if(!strcmp(actpblk.descr[i].name, "isdynfile")) {
+ pData->isDynFile = pvals[i].val.d.n ? 1 : 0;
+
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("omhttpfs: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ if(pData->file == NULL) {
+ /* Note: this is primarily to make clang static analyzer happy, as we
+ * request via pblk that file is a mandatory parameter. However, this is
+ * also a guard against something going really wrong...
+ */
+ LogError(0, RS_RET_INTERNAL_ERROR, "omhttpfs: file is not set "
+ "[this should not be possible]\n");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ if(pData->user == NULL || pData->user[0] == '\0') {
+ pData->user = ustrdup((uchar*) OMHTTPFS_DEFAULT_USER);
+ }
+ if(pData->host == NULL || pData->host[0] == '\0') {
+ pData->host = ustrdup((uchar*) OMHTTPFS_DEFAULT_HOST);
+ }
+
+ if (pData->isDynFile) {
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->file), OMSR_NO_RQD_TPL_OPTS));
+ } else {
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ }
+
+ tplToUse = ustrdup((pData->tplName == NULL) ? (uchar* ) "RSYSLOG_FileFormat" : pData->tplName);
+ iRet = OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+/**
+* Module Exit
+*/
+BEGINmodExit
+CODESTARTmodExit
+ /* */
+ curl_global_cleanup();
+
+ /* release what we no longer need */
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+
+ENDmodExit
+
+/**
+* Query Entry Point
+*/
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+ CODEqueryEtryPt_STD_OMOD_QUERIES
+ CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ CODEqueryEtryPt_STD_OMOD8_QUERIES
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+/**
+* Module Init
+*/
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* tell which objects we need */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -httpfs module init failed");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+
+ DBGPRINTF("omhttpfs version %s is initializing\n", OMHTTPFS_VERSION);
+
+ENDmodInit
diff --git a/contrib/omrabbitmq/Makefile.am b/contrib/omrabbitmq/Makefile.am
new file mode 100644
index 0000000..4c882f0
--- /dev/null
+++ b/contrib/omrabbitmq/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omrabbitmq.la
+
+omrabbitmq_la_SOURCES = omrabbitmq.c
+omrabbitmq_la_CPPFLAGS = $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omrabbitmq_la_LDFLAGS = -module -avoid-version
+omrabbitmq_la_LIBADD = $(RABBITMQ_LIBS)
+
+EXTRA_DIST =
diff --git a/contrib/omrabbitmq/Makefile.in b/contrib/omrabbitmq/Makefile.in
new file mode 100644
index 0000000..7765692
--- /dev/null
+++ b/contrib/omrabbitmq/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omrabbitmq
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omrabbitmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omrabbitmq_la_OBJECTS = omrabbitmq_la-omrabbitmq.lo
+omrabbitmq_la_OBJECTS = $(am_omrabbitmq_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 =
+omrabbitmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omrabbitmq_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo
+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 = $(omrabbitmq_la_SOURCES)
+DIST_SOURCES = $(omrabbitmq_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omrabbitmq.la
+omrabbitmq_la_SOURCES = omrabbitmq.c
+omrabbitmq_la_CPPFLAGS = $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omrabbitmq_la_LDFLAGS = -module -avoid-version
+omrabbitmq_la_LIBADD = $(RABBITMQ_LIBS)
+EXTRA_DIST =
+all: 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) --gnu contrib/omrabbitmq/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omrabbitmq/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omrabbitmq.la: $(omrabbitmq_la_OBJECTS) $(omrabbitmq_la_DEPENDENCIES) $(EXTRA_omrabbitmq_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omrabbitmq_la_LINK) -rpath $(pkglibdir) $(omrabbitmq_la_OBJECTS) $(omrabbitmq_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omrabbitmq_la-omrabbitmq.lo: omrabbitmq.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omrabbitmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omrabbitmq_la-omrabbitmq.lo -MD -MP -MF $(DEPDIR)/omrabbitmq_la-omrabbitmq.Tpo -c -o omrabbitmq_la-omrabbitmq.lo `test -f 'omrabbitmq.c' || echo '$(srcdir)/'`omrabbitmq.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omrabbitmq_la-omrabbitmq.Tpo $(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omrabbitmq.c' object='omrabbitmq_la-omrabbitmq.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) $(omrabbitmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omrabbitmq_la-omrabbitmq.lo `test -f 'omrabbitmq.c' || echo '$(srcdir)/'`omrabbitmq.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omrabbitmq/omrabbitmq.c b/contrib/omrabbitmq/omrabbitmq.c
new file mode 100644
index 0000000..16c69ca
--- /dev/null
+++ b/contrib/omrabbitmq/omrabbitmq.c
@@ -0,0 +1,1381 @@
+/* omrabbitmq.c
+ *
+ * This output plugin enables rsyslog to send messages to the RabbitMQ.
+ *
+ * Copyright 2012-2013 Vaclav Tomec
+ * Copyright 2014 Rainer Gerhards
+ * Copyright 2022 Hamid Maadani
+ *
+ * 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, 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
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Vaclav Tomec
+ * <vaclav.tomec@gmail.com>
+ *
+ * TLS & AMQP heartbeat support added by:
+ * Hamid Maadani
+ * <hamid@dexo.tech>
+ *
+ */
+#include "config.h"
+#include <pthread.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "debug.h"
+#include "datetime.h"
+#include "rsconf.h"
+
+#include <sys/socket.h>
+
+#include "amqp.h"
+#include "amqp_framing.h"
+#include "amqp_tcp_socket.h"
+#include "amqp_ssl_socket.h"
+#if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 4)
+#error "rabbitmq-c version must be >= 0.4.0"
+#endif
+
+#define RABBITMQ_CHANNEL 1
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omrabbitmq")
+
+/*
+ * internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+
+static int instance_counter = 0;
+static int mode_test = 0;
+
+typedef struct {
+ char *host; /* rabbitmq server fqdn or IP */
+ int port; /* rabbitmq server port */
+} server_t;
+
+typedef struct {
+ server_t s; /* rabbitmq server */
+ int failures; /* rabbitmq server failures */
+} server_wrk_t;
+
+
+typedef struct {
+ time_t return_check_interval; /* time interval between usual server health checks */
+ time_t half_return_check_interval; /* for computing */
+ time_t quick_oscillation_interval; /* time interval below which the service is not stable */
+ int quick_oscillation_max; /* number of quick oscillation after which the connection is kept on backup */
+ time_t graceful_interval; /* time interval the connection is kept on backup after which the usual server
+ * check restarts */
+ int quick_oscillation_count; /* current number of simultaneous quick oscillation detected */
+} recover_t;
+
+typedef struct _instanceData {
+ /* here you need to define all action-specific data. A record of type
+ * instanceData will be handed over to each instance of the action. Keep
+ * in mind that there may be several invocations of the same type of action
+ * inside rsyslog.conf, and this is what keeps them apart. Do NOT use
+ * static data for this!
+ */
+ amqp_bytes_t exchange; /* exchange to send message to */
+
+ amqp_bytes_t routing_key; /* fixed routing_key to use */
+ uchar *routing_key_template; /* routing_key template */
+ int idx_routing_key_template; /* routing_key template index in doAction tab */
+
+ sbool populate_properties; /* populates message properties */
+ int delivery_mode; /* delivery mode transient or persistent message */
+ amqp_bytes_t expiration; /* message expiration */
+
+ uchar *body_template; /* body template */
+ int idx_body_template; /* body template index in doAction tab */
+
+ amqp_basic_properties_t amqp_props_tpl_type; /* */
+ char *content_type; /* */
+ amqp_basic_properties_t amqp_props_plaintext; /* */
+
+ char *exchange_type; /* */
+ int durable; /* */
+ int auto_delete; /* */
+
+ int iidx;
+ int nbWrkr;
+
+ server_t server1; /* first rabbitmq server */
+ server_t server2; /* second rabbitmq server */
+
+ char *vhost; /* rabbitmq server vhost */
+ char *user; /* rabbitmq username */
+ char *password; /* rabbitmq username's password */
+
+ int ssl; /* should amqp connection be made over TLS? */
+ int initOpenSSL; /* should rabbitmq-c initialize OpenSSL? */
+ int verifyPeer; /* should peer be verified for TLS? */
+ int verifyHostname; /* should hostname be verified for TLS? */
+ int heartbeat; /* AMQP heartbeat interval in seconds (0 means disabled, which is default) */
+ char *caCert; /* CA certificate to be used for TLS connection */
+
+ recover_t recover_policy;
+
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ amqp_connection_state_t a_conn; /* amqp connection */
+
+ int connected;
+ int channel_opened;
+
+ pthread_t thread; /* */
+ short thread_running; /* */
+ pthread_mutex_t send_mutex; /* */
+ pthread_cond_t cond; /* */
+
+ rsRetVal state; /* state of the connection */
+
+ server_wrk_t serverPrefered; /* usual rabbitmq server */
+ server_wrk_t serverBackup; /* backup rabbitmq server */
+ server_wrk_t *serverActive; /* active rabbitmq server */
+
+ instanceData *pData;
+
+ recover_t recover_policy;
+ time_t last_failback;
+
+ int iidx;
+ int widx;
+ int go_on;
+} wrkrInstanceData_t;
+
+typedef struct _msg2amqp_props_ {
+ propid_t id;
+ const char *name;
+ amqp_bytes_t *standardprop;
+ int flag;
+} msg2amqp_props_t;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "host", eCmdHdlrString, 0 },
+ { "port", eCmdHdlrInt, 0 },
+ { "virtual_host", eCmdHdlrGetWord, 0 },
+ { "heartbeat_interval", eCmdHdlrNonNegInt, 0 },
+ { "user", eCmdHdlrGetWord, 0 },
+ { "password", eCmdHdlrGetWord, 0 },
+ { "ssl", eCmdHdlrBinary, 0 },
+ { "init_openssl", eCmdHdlrBinary, 0 },
+ { "verify_peer", eCmdHdlrBinary, 0 },
+ { "verify_hostname", eCmdHdlrBinary, 0 },
+ { "ca_cert", eCmdHdlrGetWord, 0 },
+ { "exchange", eCmdHdlrGetWord, 0 },
+ { "routing_key", eCmdHdlrGetWord, 0 },
+ { "routing_key_template", eCmdHdlrGetWord, 0 },
+ { "delivery_mode", eCmdHdlrGetWord, 0 },
+ { "expiration", eCmdHdlrNonNegInt, 0 },
+ { "populate_properties", eCmdHdlrBinary, 0 },
+ { "body_template", eCmdHdlrGetWord, 0 },
+ { "content_type", eCmdHdlrGetWord, 0 },
+ { "recover_policy", eCmdHdlrString, 0 },
+ { "exchange_type", eCmdHdlrGetWord, 0},
+ { "durable", eCmdHdlrBinary, 0},
+ { "auto_delete", eCmdHdlrBinary, 0},
+};
+static struct cnfparamblk actpblk =
+ {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static amqp_bytes_t cstring_bytes(const char *str)
+{
+ return str ? amqp_cstring_bytes(str) : amqp_empty_bytes;
+}
+
+/* Initialize recover structure from the configuration string
+ */
+static void init_recover(recover_t *fb, char *str)
+{
+ time_t value[4] = { 0, 0, 0, 0 };
+
+ if (str && *str){
+ int i = -1;
+ do {
+ value[++i] = strtoul(str, &str, 10);
+ if (*str) str++;
+ } while (i < 3 && value[i] && *str);
+ }
+
+ fb->return_check_interval = (value[0]) ? value[0] : 60;
+ fb->half_return_check_interval = fb->return_check_interval / 2;
+ fb->quick_oscillation_interval = (value[1]) ? value[1] : (fb->return_check_interval / 10);
+ fb->quick_oscillation_max = (value[2]) ? (int)(value[2]) : 3;
+ fb->graceful_interval = (value[3]) ? value[3] : (fb->return_check_interval * 10) -
+ fb->half_return_check_interval;
+ fb->quick_oscillation_count = 0;
+}
+
+/* this method compute the delay before next reconnection attempt according
+ */
+static unsigned long next_check(recover_t *fb, time_t last_failback)
+{
+ time_t now = time(NULL);
+ srandom(now);
+
+ if (now - last_failback < fb->quick_oscillation_interval) {
+ /* quick oscillation detected */
+ fb->quick_oscillation_count++;
+
+ if (fb->quick_oscillation_count > fb->quick_oscillation_max) {
+ /* too much oscillation inserting a graceful sleep */
+ fb->quick_oscillation_count = 0;
+ return fb->graceful_interval + fb->return_check_interval * random() / RAND_MAX;
+ }
+ } else
+ fb->quick_oscillation_count = 0;
+
+ /* returning a standard delay between 0,5 and 1,5 * return_check_interval */
+ return fb->half_return_check_interval + fb->return_check_interval * random() / RAND_MAX;
+}
+
+/* authenticate to rabbitmq server and set connection parameter according to rsyslog configuration
+ */
+static int amqp_authenticate(wrkrInstanceData_t *self, amqp_connection_state_t a_conn)
+{
+ amqp_rpc_reply_t ret;
+
+ /* define the frame size */
+ int frame_size = (glbl.GetMaxLine(runConf)<130000) ? 131072 : (glbl.GetMaxLine(runConf)+1072);
+
+ /* authenticate */
+ ret = amqp_login(a_conn, (char const *)self->pData->vhost, 1, frame_size, self->pData->heartbeat,
+ AMQP_SASL_METHOD_PLAIN, self->pData->user, self->pData->password);
+
+ if (ret.reply_type != AMQP_RESPONSE_NORMAL)
+ {
+ LogError(0, RS_RET_RABBITMQ_LOGIN_ERR, "omrabbitmq module %d/%d: login to AMQP "
+ "server %s failed. (%d / %s)",
+ self->iidx, self->widx, self->serverActive->s.host, ret.reply_type,
+ amqp_error_string2(ret.library_error));
+ return 0;
+ }
+
+ /* open the communication channel */
+ amqp_channel_open(a_conn, 1);
+
+ if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL)
+ {
+ LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: open channel failed.",
+ self->iidx, self->widx);
+ return 0;
+ }
+
+ if (self->pData->exchange_type) {
+ /* we declare the exchange according to specifications */
+ amqp_table_t props = { 0, NULL };
+ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 6)
+ amqp_exchange_declare(a_conn, 1, self->pData->exchange, cstring_bytes(self->pData->exchange_type),
+ 0, self->pData->durable, props);
+ #else
+ amqp_exchange_declare(a_conn, 1, self->pData->exchange, cstring_bytes(self->pData->exchange_type),
+ 0, self->pData->durable, self->pData->auto_delete, 0, props);
+ #endif
+
+ if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL)
+ {
+ /* if a problem occurs on declaring the exchange we receive a channel_close with the
+ * error then we can log the error, respond a channel_close_ok and reopen it
+ * so we can work with the existing exchange.
+ */
+ amqp_channel_close_ok_t chan_cls_ok;
+ amqp_channel_close_t *chan_cls =
+ (amqp_channel_close_t*)amqp_get_rpc_reply(a_conn).reply.decoded;
+
+ if (amqp_get_rpc_reply(a_conn).reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION) {
+ LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR,
+ "omrabbitmq module %d/%d: disconnected while exchange declare (%d)",
+ self->iidx, self->widx, amqp_get_rpc_reply(a_conn).library_error);
+ return 0;
+ }
+
+ LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR,
+ "omrabbitmq module %d/%d: exchange declare failed %.*s.", self->iidx, self->widx,
+ (int)chan_cls->reply_text.len, (char*)chan_cls->reply_text.bytes);
+
+ chan_cls_ok.dummy = '\0';
+ amqp_send_method(a_conn, 1, AMQP_CHANNEL_CLOSE_OK_METHOD, &chan_cls_ok);
+
+ /* reopen the communication channel in case of error it should be close by server*/
+ amqp_channel_open(a_conn, 1);
+
+ if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL)
+ {
+ LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: "
+ "open channel failed.", self->iidx, self->widx);
+ return 0;
+ }
+
+ }
+ }
+ /* release the buffers if possible */
+ amqp_maybe_release_buffers(a_conn);
+
+ return 1;
+}
+
+/* This method establish a new connection
+ * @self pointer on the worker datas
+ * @server pointer on the server datas (preferred or backup)
+ * @return the connection state or NULL on error
+ */
+static amqp_connection_state_t tryConnection(wrkrInstanceData_t *self, server_t *server)
+{
+ int retconn = 0;
+ struct timeval delay;
+ delay.tv_sec = 1;
+ delay.tv_usec = 0;
+ amqp_socket_t *sockfd = NULL;
+
+ amqp_connection_state_t a_conn = amqp_new_connection();
+ if (a_conn) {
+ if (self->pData->ssl) {
+ if (!self->pData->initOpenSSL) {
+ // prevent OpenSSL double initialization
+ amqp_set_initialize_ssl_library(0);
+ }
+ sockfd = amqp_ssl_socket_new(a_conn);
+ } else {
+ sockfd = amqp_tcp_socket_new(a_conn);
+ }
+ }
+
+ if (sockfd)
+ {
+ if (self->pData->ssl) {
+#if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8)
+ amqp_ssl_socket_set_verify(sockfd, self->pData->verifyPeer);
+#else
+ amqp_ssl_socket_set_verify_peer(sockfd, self->pData->verifyPeer);
+ amqp_ssl_socket_set_verify_hostname(sockfd, self->pData->verifyHostname);
+#endif
+ if (self->pData->caCert) {
+ amqp_ssl_socket_set_cacert(sockfd, self->pData->caCert);
+ }
+ }
+
+ LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR,
+ "omrabbitmq module %d/%d: server %s port %d.", self->iidx, self->widx,
+ server->host, server->port);
+
+ #if defined(_AIX)
+ retconn = amqp_socket_open(sockfd, server->host, server->port);
+ #else
+ retconn = amqp_socket_open_noblock(sockfd, (const char*)server->host, server->port, &delay);
+ #endif
+ }
+
+ if (retconn == AMQP_STATUS_OK && amqp_authenticate(self, a_conn))
+ return a_conn;
+
+ /* the connection failed so free it and return NULL */
+ amqp_connection_close(a_conn, 200);
+ amqp_destroy_connection(a_conn);
+#if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0)
+ if (self->pData->ssl && self->pData->initOpenSSL) {
+ amqp_uninitialize_ssl_library();
+ }
+#endif
+
+ return NULL;
+}
+
+static int manage_connection(wrkrInstanceData_t *self, amqp_frame_t *pFrame)
+{
+ int result;
+
+ pthread_mutex_unlock(&self->send_mutex);
+
+ do {
+ if (self->serverActive == &self->serverBackup)
+ {
+ amqp_connection_state_t new_conn;
+ struct timeval delay;
+
+ /* The worker is connected to the backup server.
+ * next_check function compute the delay before trying to recover
+ * the connection to the preferred server according to recover_policy
+ */
+ delay.tv_sec = next_check(&self->recover_policy, self->last_failback);
+ delay.tv_usec = 0;
+
+ result = amqp_simple_wait_frame_noblock(self->a_conn, pFrame, &delay);
+
+ /* if connected to backup server then check if usual server is alive.
+ * if so then disconnect from backup */
+ if (result == AMQP_STATUS_TIMEOUT &&
+ (new_conn = tryConnection(self,
+ &(self->serverPrefered.s)))
+ != NULL) {
+ /* connection is re-established to preferred server so
+ * swap connections */
+ amqp_connection_state_t old_conn = self->a_conn;
+
+ /* now lock to avoid message publishing. */
+ pthread_mutex_lock(&self->send_mutex);
+ self->a_conn = new_conn;
+ self->serverActive = &self->serverPrefered;
+ self->serverActive->failures = 0;
+ pthread_mutex_unlock(&self->send_mutex);
+ /* back to unlock mode */
+
+ DBGPRINTF("omrabbitmq module %d: reconnects to usual server.\n",
+ self->iidx);
+ amqp_connection_close(old_conn, 200);
+ amqp_destroy_connection(old_conn);
+#if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0)
+ if (self->pData->ssl && self->pData->initOpenSSL) {
+ amqp_uninitialize_ssl_library();
+ }
+#endif
+ }
+
+ } else {
+
+ result = amqp_simple_wait_frame(self->a_conn, pFrame);
+
+ }
+ } while(result == AMQP_STATUS_TIMEOUT);
+
+ /* now lock the mutex to avoid message publishing. */
+ pthread_mutex_lock(&self->send_mutex);
+
+ return result;
+}
+
+static void send_connection_close(amqp_connection_state_t state) {
+ amqp_connection_close_t *req = malloc(sizeof(amqp_connection_close_t));
+ memset(req, 0, sizeof(amqp_connection_close_t));
+ req->reply_code = 200;
+ req->reply_text.bytes = (void*)"200";
+ req->reply_text.len = 3;
+ req->class_id = (uint16_t)(AMQP_CONNECTION_CLOSE_METHOD >> 16);
+ req->method_id = (uint16_t)(AMQP_CONNECTION_CLOSE_METHOD & 0xFFFF);
+ amqp_send_method(state, 0, AMQP_CONNECTION_CLOSE_METHOD, req);
+ free(req);
+}
+
+static void send_channel_close(amqp_connection_state_t state, amqp_channel_t ch) {
+ amqp_channel_close_t *req = malloc(sizeof(amqp_channel_close_t));
+ memset(req, 0, sizeof(amqp_channel_close_t));
+ req->reply_code = 200;
+ req->reply_text.bytes = (void*)"200";
+ req->reply_text.len = 3;
+ req->class_id = (uint16_t)(AMQP_CHANNEL_CLOSE_METHOD >> 16);
+ req->method_id = (uint16_t)(AMQP_CHANNEL_CLOSE_METHOD & 0xFFFF);
+ amqp_send_method(state, ch, AMQP_CHANNEL_CLOSE_METHOD, req);
+ free(req);
+}
+
+static void send_connection_close_ok(amqp_connection_state_t state) {
+ amqp_connection_close_ok_t *req = malloc(sizeof(amqp_connection_close_ok_t));
+ memset(req, 0, sizeof(amqp_connection_close_ok_t));
+ req->dummy = '\0';
+ amqp_send_method(state, 0, AMQP_CONNECTION_CLOSE_OK_METHOD, req);
+ free(req);
+}
+
+static void send_channel_close_ok(amqp_connection_state_t state, amqp_channel_t ch) {
+ amqp_channel_close_ok_t *req = malloc(sizeof(amqp_channel_close_ok_t));
+ memset(req, 0, sizeof(amqp_channel_close_ok_t));
+ req->dummy = '\0';
+ amqp_send_method(state, ch, AMQP_CHANNEL_CLOSE_OK_METHOD, req);
+ free(req);
+}
+
+/* run_connection_routine is the thread monitoring of the rabbitmq connection.
+ * This method manage reconnection to preferred and backup servers apply the recover_policy
+ */
+static void* run_connection_routine(void* arg)
+{
+ wrkrInstanceData_t *self = (wrkrInstanceData_t *) arg;
+ amqp_frame_t frm;
+ int result;
+ self->connected = 0;
+ self->channel_opened = 0;
+ rsRetVal state_out = RS_RET_SUSPENDED;
+
+ dbgSetThrdName((uchar*)"amqp connection");
+
+ /* now lock to avoid message publishing during part of the thread loop */
+ pthread_mutex_lock(&self->send_mutex);
+
+ self->thread_running = 1;
+
+ self->state = RS_RET_OK;
+
+ srSleep(0,100);
+
+ DBGPRINTF("omrabbitmq module %d/%d: connection thread started\n", self->iidx, self->widx);
+
+ int go_on = self->go_on;
+
+ while (go_on) // this loop is used to reconnect on connection failure
+ {
+ if (self->a_conn != NULL)
+ {
+ amqp_connection_close(self->a_conn, 200);
+ amqp_destroy_connection(self->a_conn);
+#if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0)
+ if (self->pData->ssl && self->pData->initOpenSSL) {
+ amqp_uninitialize_ssl_library();
+ }
+#endif
+ }
+
+ self->a_conn = NULL;
+
+ if (!self->go_on)
+ {
+ go_on = 0;
+ state_out = RS_RET_DISABLE_ACTION;
+ continue; /* lets go back to wile (go_on) and leave cleanly */
+ }
+
+ if (self->serverActive == &self->serverBackup) {
+ self->serverBackup.failures = 0;
+ self->serverPrefered.failures = 0;
+ self->serverActive = &self->serverPrefered;
+ }
+
+ do { /* this loop tries 3 times per server before switching servers */
+ if ((self->a_conn = tryConnection(self, &(self->serverActive->s))) != NULL) {
+ self->serverActive->failures = 0;
+ } else {
+ /* set 1 second before retry */
+ struct timeval delay;
+
+ delay.tv_sec = 1;
+ delay.tv_usec = 0;
+
+ self->serverActive->failures++;
+
+ /* if 3 tries */
+ if (self->serverActive->failures == 3) {
+
+ if (!self->serverBackup.s.host || self->serverBackup.failures == 3)
+ {
+ LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module connection "
+ "failed 3 times on each server.");
+ }
+
+ if (self->serverActive == &self->serverBackup) {
+ self->serverBackup.failures = 0;
+ self->serverPrefered.failures = 0;
+ self->serverActive = &self->serverPrefered;
+ } else {
+ /* on usual server switch to backup server */
+ if (self->serverBackup.s.host)
+ self->serverActive = &self->serverBackup;
+ else
+ self->serverPrefered.failures = 0;
+ }
+ /* set 5 second before new round trip */
+ delay.tv_sec = 5;
+ }
+ select(0,NULL,NULL,NULL,&delay);
+ }
+ }
+ while (self->a_conn == NULL && self->go_on);
+
+ if (!self->go_on)
+ {
+ go_on = 0;
+ state_out = RS_RET_DISABLE_ACTION;
+ continue; /* lets go back to wile (go_on) and leave cleanly */
+ }
+
+ /* signal that the thread is started */
+ pthread_cond_signal(&self->cond);
+
+ self->connected = 1;
+ self->channel_opened = 1;
+
+ DBGPRINTF("omrabbitmq module %d: connected.\n", self->iidx);
+
+ self->state = RS_RET_OK;
+
+ if (self->serverActive == &self->serverBackup)
+ self->last_failback = time(NULL);
+
+ while (self->connected) // this loop is used to manage an established connection
+ {
+
+ result = manage_connection(self, &frm);
+
+ switch (result)
+ {
+ case AMQP_STATUS_NO_MEMORY:
+ LogError(0, RS_RET_OUT_OF_MEMORY, "omrabbitmq module %d/%d: no memory "
+ ": aborting module.", self->iidx, self->widx);
+ go_on = 0; /* non recoverable error let's go out */
+ self->connected = 0;
+ state_out = RS_RET_DISABLE_ACTION;
+ break;
+ case AMQP_STATUS_BAD_AMQP_DATA:
+ LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module %d/%d: bad "
+ "data received : reconnect.", self->iidx, self->widx);
+ self->connected = 0;
+ break;
+ case AMQP_STATUS_SOCKET_ERROR:
+ LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module %d/%d: Socket"
+ " error : reconnect.", self->iidx, self->widx);
+ self->connected = 0;
+ break;
+ case AMQP_STATUS_CONNECTION_CLOSED:
+ LogError(0, RS_RET_OUT_OF_MEMORY, "omrabbitmq module %d/%d: Connection"
+ " closed : reconnect.", self->iidx, self->widx);
+ self->connected = 0;
+ break;
+ case AMQP_STATUS_OK:
+ /* perhaps not a frame type so ignore it */
+ if (frm.frame_type == AMQP_FRAME_METHOD)
+ {
+ amqp_method_number_t id = frm.payload.method.id;
+ /* now handle frames from the server */
+ switch (id)
+ {
+ case AMQP_CONNECTION_CLOSE_OK_METHOD:
+
+ /* We asked to close the connection and server has responded to us */
+ self->connected = 0;
+ go_on = 0;
+ break;
+
+ case AMQP_CHANNEL_CLOSE_OK_METHOD:
+
+ /* We asked to close the channel and server has responded to us */
+ send_connection_close(self->a_conn);
+ self->channel_opened = 0;
+ break;
+
+ case AMQP_CHANNEL_CLOSE_METHOD:
+
+ /* the server wants to close the channel then the connection */
+ LogMsg(0, RS_RET_OK, LOG_WARNING,"omrabbitmq module %d/%d: "
+ "Close Channel Received (%X).", self->iidx, self->widx, id);
+ /* answer the server request & send the method */
+ send_channel_close_ok(self->a_conn, frm.channel);
+ self->channel_opened = 0;
+ break;
+
+ case AMQP_CONNECTION_CLOSE_METHOD:
+
+ /* the server want to close the connection */
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "omrabbitmq module %d/%d: "
+ "Close Connection Received (%X).", self->iidx, self->widx, id);
+ /* answer the server request */
+ send_connection_close_ok(self->a_conn);
+ self->connected = 0;
+ break;
+
+ default :
+
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "omrabbitmq module %d/%d: "
+ "Unmanaged amqp method received (%X) : ignored.",
+ self->iidx, self->widx, id);
+ } /* switch (frm.payload.method.id) */
+ } /* if (frm.frame_type == AMQP_FRAME_METHOD) */
+ break;
+ } /* switch (result) */
+ }
+ }
+ self->state = state_out;
+
+ /* The core ask to die so let's disconnect */
+ if (self->a_conn != NULL)
+ {
+ if (self->channel_opened)
+ amqp_channel_close(self->a_conn, 1, 200);
+ if (self->connected)
+ amqp_connection_close(self->a_conn, 200);
+ amqp_destroy_connection(self->a_conn);
+ self->a_conn = NULL;
+#if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0)
+ if (self->pData->ssl && self->pData->initOpenSSL) {
+ amqp_uninitialize_ssl_library();
+ }
+#endif
+ }
+
+ self->thread_running = 0;
+
+ /* Finishing by unlocking before the end of the thread */
+ pthread_mutex_unlock(&self->send_mutex);
+
+ /* Now notify the worker that this thread is stopping */
+ pthread_cond_signal(&self->cond);
+
+ return NULL;
+}
+
+/* ============================================================================================
+ * Main thread
+ * ============================================================================================
+ */
+
+static rsRetVal startAMQPConnection(wrkrInstanceData_t *self)
+{
+ DEFiRet;
+ pthread_mutex_lock(&self->send_mutex);
+ self->go_on = 1;
+ if (self->thread_running == 0)
+ {
+ if (!pthread_create(&self->thread, NULL, run_connection_routine, self))
+ {
+ pthread_cond_wait(&self->cond,&self->send_mutex);
+ iRet = self->state;
+ }else{
+ iRet = RS_RET_DISABLE_ACTION;
+ }
+ }
+ pthread_mutex_unlock(&self->send_mutex);
+ RETiRet;
+}
+
+static void closeAMQPConnection(wrkrInstanceData_t *self)
+{
+ if (!self || !self->a_conn) return;
+
+ void *ret;
+
+ /* Now locks to allow exclusive access to sock */
+ pthread_mutex_lock(&self->send_mutex);
+
+ self->go_on = 0;
+
+ /* send the method */
+ if (self->a_conn)
+ {
+ if (self->channel_opened){
+ send_channel_close(self->a_conn, 0);
+ } else {
+ send_connection_close(self->a_conn);
+ }
+ }
+ /* Release the lock */
+ pthread_mutex_unlock(&self->send_mutex);
+
+ /* Now wvait for the thread to stop */
+ pthread_join(self->thread, &ret);
+}
+
+/*
+ * Report general error
+ */
+static int manage_error(int x, char const *context)
+{
+ int retVal = 0; // false
+
+ if (x < 0) {
+ #if (AMQP_VERSION_MINOR >= 4)
+ const char *errstr = amqp_error_string2(-x);
+ LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, errstr);
+ #else
+ char *errstr = amqp_error_string(-x);
+ LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, errstr);
+ free(errstr);
+ #endif
+ retVal = 1; // true
+ }
+
+ return retVal;
+}
+
+static rsRetVal publishRabbitMQ(wrkrInstanceData_t *self, amqp_bytes_t exchange,
+ amqp_bytes_t routing_key, amqp_basic_properties_t *p_amqp_props,
+ amqp_bytes_t body_bytes)
+{
+ DEFiRet;
+ /* locks to allow exclusive access to connection */
+ if (mode_test > 0) {
+ struct timeval tv;
+ tv.tv_sec = mode_test/1000;
+ tv.tv_usec = mode_test%1000 * 1000;
+ select(0, NULL, NULL, NULL, &tv);
+ }
+
+ pthread_mutex_lock(&self->send_mutex);
+
+ if (self->state != RS_RET_OK)
+ ABORT_FINALIZE(self->state);
+
+ if (!self->a_conn){
+ ABORT_FINALIZE(RS_RET_RABBITMQ_CONN_ERR);
+ }
+
+ if (manage_error(amqp_basic_publish(self->a_conn, 1, exchange, routing_key,
+ 0, 0, p_amqp_props, body_bytes), "amqp_basic_publish")) {
+ /* error already notified */
+ FINALIZE;
+ }
+
+finalize_it:
+ /* release exclusive access to connection */
+ pthread_mutex_unlock(&self->send_mutex);
+ RETiRet;
+}
+
+BEGINdoAction
+ int iLen;
+CODESTARTdoAction
+ /* The first element is a smsg_t pointer */
+ smsg_t **pMsg = (smsg_t **)pMsgData;
+ smsg_t *msg = pMsg[0];
+
+ amqp_bytes_t body_bytes;
+ amqp_basic_properties_t *amqp_props_msg;
+
+ if (!pWrkrData->pData->idx_body_template)
+ {
+ /* No body template so send it as rawmsg */
+ getRawMsg(msg, (uchar**)(&body_bytes.bytes), &iLen);
+ body_bytes.len = (size_t)iLen;
+ amqp_props_msg = &pWrkrData->pData->amqp_props_plaintext;
+ }
+ else
+ {
+ /* we have a body template */
+ body_bytes = cstring_bytes((char*)ppString[pWrkrData->pData->idx_body_template]);
+ amqp_props_msg = &pWrkrData->pData->amqp_props_tpl_type;
+ }
+
+ if (pWrkrData->pData->populate_properties) {
+ /* populate amqp message properties */
+ msgPropDescr_t pProp;
+ int i, custom = 0;
+ amqp_basic_properties_t amqp_props;
+
+ memcpy(&amqp_props, amqp_props_msg, sizeof(amqp_basic_properties_t));
+
+ /* list and mapping of smsg to amqp properties */
+ msg2amqp_props_t prop_list[] = {
+ { PROP_SYSLOGFACILITY_TEXT, "facility", NULL, 0 },
+ { PROP_SYSLOGSEVERITY_TEXT, "severity", NULL, 0 },
+ { PROP_HOSTNAME, "hostname", NULL, 0 },
+ { PROP_FROMHOST, "fromhost", NULL, 0 },
+ { PROP_SYSLOGTAG, NULL, &(amqp_props.app_id), AMQP_BASIC_APP_ID_FLAG }
+ };
+ int len = sizeof(prop_list)/sizeof(msg2amqp_props_t);
+ uchar *val[sizeof(prop_list)/sizeof(msg2amqp_props_t)];
+ rs_size_t valLen[sizeof(prop_list)/sizeof(msg2amqp_props_t)];
+ unsigned short mustBeFreed[sizeof(prop_list)/sizeof(msg2amqp_props_t)];
+ struct amqp_table_entry_t_ tab_entries[sizeof(prop_list)/sizeof(msg2amqp_props_t)];
+
+ amqp_props.headers.entries = tab_entries;
+
+ amqp_props.timestamp = (uint64_t)datetime.syslogTime2time_t(&msg->tTIMESTAMP);
+ amqp_props._flags |= AMQP_BASIC_TIMESTAMP_FLAG;
+
+ for (i=0; i<len; i++)
+ {
+ /* for each msg property in list get the value and initialize flags */
+ pProp.id = prop_list[i].id;
+ valLen[i] = 0;
+ mustBeFreed[i] = 0;
+ val[i] = (uchar*)MsgGetProp(msg, NULL, &pProp, &(valLen[i]), &(mustBeFreed[i]), NULL);
+ if (val[i] && *val[i])
+ {
+ if (prop_list[i].name)
+ {
+ /* custom amqp properties */
+ tab_entries[custom].key = amqp_cstring_bytes(prop_list[i].name);
+ tab_entries[custom].value.kind = AMQP_FIELD_KIND_UTF8;
+ tab_entries[custom].value.value.bytes = amqp_cstring_bytes((char*)val[i]);
+ amqp_props._flags |= AMQP_BASIC_HEADERS_FLAG;
+ custom++;
+ } else {
+ /* standard amqp properties*/
+ prop_list[i].standardprop->bytes = val[i];
+ prop_list[i].standardprop->len = (size_t)valLen[i];
+ amqp_props._flags |= prop_list[i].flag;
+ }
+ }
+ }
+ amqp_props.headers.num_entries = custom;
+
+ /* CHKiRet could not be used because we need to release allocations */
+ iRet = publishRabbitMQ(pWrkrData, pWrkrData->pData->exchange,
+ (pWrkrData->pData->routing_key_template)?
+ cstring_bytes((char*)ppString[pWrkrData->pData->idx_routing_key_template])
+ : pWrkrData->pData->routing_key,
+ &amqp_props, body_bytes);
+
+ for (i=0; i<len; i++)
+ if (mustBeFreed[i]) free(val[i]);
+ }
+ else
+ {
+ /* As CHKiRet could not be used earlier, iRet is directly used again */
+ iRet = publishRabbitMQ(pWrkrData, pWrkrData->pData->exchange,
+ (pWrkrData->pData->routing_key_template)?
+ cstring_bytes((char*)ppString[pWrkrData->pData->idx_routing_key_template])
+ : pWrkrData->pData->routing_key,
+ amqp_props_msg, body_bytes);
+ }
+
+ENDdoAction
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = startAMQPConnection(pWrkrData);
+ENDtryResume
+
+BEGINcreateInstance
+ void *env_var;
+CODESTARTcreateInstance
+ if ((env_var = getenv("OMRABBITMQ_TEST")) != NULL)
+ mode_test = atoi(env_var);
+
+ memset(pData, 0, sizeof(instanceData));
+ pData->iidx = ++instance_counter;
+ pData->delivery_mode = 2;
+ pData->exchange_type = NULL;
+ pData->durable = 0;
+ pData->auto_delete = 1;
+ pData->ssl = 0;
+ pData->initOpenSSL = 0;
+ pData->verifyPeer = 0;
+ pData->verifyHostname = 0;
+ pData->caCert = NULL;
+ pData->heartbeat = 0;
+ENDcreateInstance
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* this is a cleanup callback. All dynamically-allocated resources
+ * in instance data must be cleaned up here. Prime examples are
+ * malloc()ed memory, file & database handles and the like.
+ */
+ if (pData->exchange.bytes) free(pData->exchange.bytes);
+ if (pData->routing_key.bytes) free(pData->routing_key.bytes);
+ if (pData->routing_key_template) free(pData->routing_key_template);
+ if (pData->body_template) free(pData->body_template);
+ if (pData->expiration.bytes) free(pData->expiration.bytes);
+ if (pData->content_type) free(pData->content_type);
+ if (pData->vhost) free(pData->vhost);
+ if (pData->user) free(pData->user);
+ if (pData->password) free(pData->password);
+ if (pData->exchange_type) free(pData->exchange_type);
+ if (pData->server1.host) free(pData->server1.host);
+ if (pData->caCert) free(pData->caCert);
+ENDfreeInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* use this to specify if select features are supported by this
+ * plugin. If not, the framework will handle that. Currently, only
+ * RepeatedMsgReduction ("last message repeated n times") is optional.
+ */
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* permits to spit out some debug info */
+ dbgprintf("omrabbitmq instance : %d\n", pData->iidx);
+ if (pData->server2.host) {
+ dbgprintf("\thost1='%s' \n", pData->server1.host);
+ dbgprintf("\tport1=%d\n", pData->server1.port);
+ dbgprintf("\thost2='%s' \n", pData->server2.host);
+ dbgprintf("\tport2=%d\n", pData->server2.port);
+ dbgprintf("\tfailback policy :");
+ dbgprintf("\t\tusual server check interval=%ld s",
+ pData->recover_policy.return_check_interval);
+ dbgprintf("\t\tquick oscillation limit=%ld s",
+ pData->recover_policy.quick_oscillation_interval);
+ dbgprintf("\t\tmax number of oscillation=%d s",
+ pData->recover_policy.quick_oscillation_max);
+ dbgprintf("\t\tgraceful interval after quick oscillation detection=%ld s",
+ pData->recover_policy.graceful_interval);
+ }else{
+ dbgprintf("\thost='%s' \n", pData->server1.host);
+ dbgprintf("\tport=%d\n", pData->server1.port);
+ }
+ dbgprintf("\tvirtual_host='%s'\n", pData->vhost);
+ dbgprintf("\tuser='%s'\n", pData->user == NULL ? "(not configured)" : pData->user);
+ dbgprintf("\tpassword=(%sconfigured)\n", pData->password == NULL ? "not " : "");
+ dbgprintf("\tssl=%d\n", pData->ssl);
+ dbgprintf("\tinit_openssl=%d\n", pData->initOpenSSL);
+ dbgprintf("\tverify_peer=%d\n", pData->verifyPeer);
+ dbgprintf("\tverify_hostname=%d\n", pData->verifyHostname);
+ dbgprintf("\tca_cert='%s'\n", pData->caCert);
+ dbgprintf("\theartbeat_interval=%d\n", pData->heartbeat);
+
+ dbgprintf("\texchange='%*s'\n", (int)pData->exchange.len,
+ (char*)pData->exchange.bytes);
+ dbgprintf("\trouting_key='%*s'\n", (int)pData->routing_key.len,
+ (char*) pData->routing_key.bytes);
+ dbgprintf("\trouting_key_template='%s'\n", pData->routing_key_template);
+ dbgprintf("\tbody_template='%s'\n", pData->body_template);
+ dbgprintf("\texchange_type='%s'\n", pData->exchange_type);
+ dbgprintf("\tauto_delete=%d\n", pData->auto_delete);
+ dbgprintf("\tdurable=%d\n", pData->durable);
+ dbgprintf("\tpopulate_properties=%s\n", (pData->populate_properties)?"ON":"OFF");
+ dbgprintf((pData->delivery_mode == 1) ? "\tdelivery_mode=TRANSIENT\n":
+ "\tdelivery_mode=PERSISTENT\n");
+ if (pData->expiration.len == 0) {
+ dbgprintf("\texpiration=UNLIMITED\n");
+ }else{
+ dbgprintf("\texpiration=%*s\n",
+ (int)pData->expiration.len, (char*) pData->expiration.bytes);
+ }
+ENDdbgPrintInstInfo
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ char *host = NULL, *vhost= NULL, *user = NULL, *password = NULL, *recover = NULL;
+ int port = 0;
+ long long expiration = 0;
+CODESTARTnewActInst
+
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+
+ /* let read parameters */
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(actpblk.descr[i].name, "host")) {
+ host = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "recover_policy")) {
+ recover = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "port")) {
+ port = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "virtual_host")) {
+ vhost = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "user")) {
+ user = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "password")) {
+ password = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "ssl")) {
+ pData->ssl = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "ca_cert")) {
+ pData->caCert = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "heartbeat_interval")) {
+ pData->heartbeat = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "init_openssl")) {
+ pData->initOpenSSL = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "verify_peer")) {
+ pData->verifyPeer = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "verify_hostname")) {
+ pData->verifyHostname = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "exchange")) {
+ pData->exchange = cstring_bytes(es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if (!strcmp(actpblk.descr[i].name, "routing_key")) {
+ pData->routing_key = cstring_bytes(es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if (!strcmp(actpblk.descr[i].name, "routing_key_template")) {
+ pData->routing_key_template = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "populate_properties")) {
+ pData->populate_properties = (sbool) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "delivery_mode")) {
+ char *temp = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (temp){
+ if (!strcasecmp(temp, "TRANSIENT") || !strcmp(temp, "1")) {
+ pData->delivery_mode = 1;
+ } else { if (!strcasecmp(temp, "PERSISTENT") || !strcmp(temp, "2")) {
+ pData->delivery_mode = 2;
+ } else {
+ pData->delivery_mode = 0;
+ } }
+ free(temp);
+ }
+ } else if (!strcmp(actpblk.descr[i].name, "expiration")) {
+ expiration = pvals[i].val.d.n;
+ if (expiration > 0) {
+ char buf[40];
+ snprintf(buf, 40, "%lld", expiration);
+ #ifndef __clang_analyzer__
+ pData->expiration = cstring_bytes(strdup(buf));
+ #endif
+ }
+ } else if (!strcmp(actpblk.descr[i].name, "body_template")) {
+ pData->body_template = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "content_type")) {
+ pData->content_type = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "exchange_type")) {
+ pData->exchange_type = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "auto_delete")) {
+ pData->auto_delete = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "durable")) {
+ pData->durable = (int) pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INVALID_PARAMS,
+ "omrabbitmq module %d: program error, non-handled param '%s'\n",
+ pData->iidx, actpblk.descr[i].name);
+ }
+ }
+
+ /* let's check config validity */
+
+ if (host == NULL) {
+ LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: parameter "
+ "host must be specified",
+ pData->iidx);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* first if a template for routing_key is set let verify its existence */
+ if (pData->routing_key_template && tplFind(ourConf, (char*)pData->routing_key_template,
+ strlen((char*)pData->routing_key_template)) == NULL)
+ {
+ LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d : template '%s'"
+ " used for routing key does not exist !",
+ pData->iidx, pData->routing_key_template);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* an exchange must be defined */
+ if (pData->exchange.bytes == NULL) {
+ LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: parameter "
+ "exchange must be specified",
+ pData->iidx);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* a static or a template's routing_key must be defined */
+ if (pData->routing_key.bytes == NULL && pData->routing_key_template == NULL) {
+ LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: "
+ "one of parameters routing_key or "
+ "routing_key_template must be specified", pData->iidx);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* a valid delivery mode must be defined : a 0 means that an invalid value
+ * has been done */
+ if (!pData->delivery_mode)
+ {
+ LogError(0, RS_RET_CONF_PARAM_INVLD, "omrabbitmq module %d disabled: "
+ "parameter delivery_mode must be "
+ "TRANSIENT or PERSISTENT (default)", pData->iidx);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* first if a template for message body is set let verify its existence */
+ if (pData->body_template && *pData->body_template &&
+ tplFind(ourConf, (char*)pData->body_template,
+ strlen((char*)pData->body_template)) == NULL)
+ {
+ LogError(0, RS_RET_CONF_PARAM_INVLD, "omrabbitmq module %d : template '%s'"
+ " used for body does not exist !",
+ pData->iidx, pData->body_template);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ /* Let's define the size of the doAction tab */
+ CODE_STD_STRING_REQUESTnewActInst(1 + ((pData->routing_key_template) ? 1 : 0) +
+ ((pData->body_template && *pData->body_template == '\0') ? 0 : 1));
+
+ /* Set the plain text message props */
+ memset(&pData->amqp_props_plaintext, 0, sizeof(amqp_basic_properties_t));
+ pData->amqp_props_plaintext._flags =
+ AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_CONTENT_TYPE_FLAG;
+ pData->amqp_props_plaintext.delivery_mode = pData->delivery_mode;
+ /* persistent delivery mode */
+ pData->amqp_props_plaintext.content_type = amqp_cstring_bytes("plain/text");
+ if (pData->expiration.len)
+ {
+ pData->amqp_props_plaintext._flags |= AMQP_BASIC_EXPIRATION_FLAG;
+ pData->amqp_props_plaintext.expiration = pData->expiration;
+ }
+
+ memcpy(&pData->amqp_props_tpl_type, &pData->amqp_props_plaintext,
+ sizeof(amqp_basic_properties_t));
+
+ /* The first position of doAction tab will contain the internal message */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+
+ // RabbitMQ properties initialization
+ if (pData->routing_key_template)
+ {
+ pData->idx_routing_key_template = 1;
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1,
+ (uchar*)strdup((const char *)pData->routing_key_template),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+
+ /* if pData->body_template is NULL (not defined) then let's use former
+ * json format if pData->body_template is not an empty string then let's
+ * use it. In this case the content type is defined either
+ * by the template name or the user defined content_type if set
+ * otherwise raw data (unformatted) are sent this is done setting
+ * pData->idx_body_template to 0 */
+ if (pData->body_template == NULL)
+ { /* no template */
+ DBGPRINTF("Body_template is using default StdJSONFmt definition.\n");
+ pData->idx_body_template = pData->idx_routing_key_template + 1;
+ CHKiRet(OMSRsetEntry(*ppOMSR, pData->idx_body_template,
+ (uchar*)strdup(" StdJSONFmt"), OMSR_NO_RQD_TPL_OPTS));
+ pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes("application/json");
+ }
+ else if (*pData->body_template)
+ {
+ pData->idx_body_template = pData->idx_routing_key_template + 1;
+ CHKiRet(OMSRsetEntry(*ppOMSR, pData->idx_body_template,
+ (uchar*)strdup((const char *)pData->body_template),
+ OMSR_NO_RQD_TPL_OPTS));
+ pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes(
+ (pData->content_type)
+ ? pData->content_type
+ : (char*)pData->body_template);
+ }else{
+ pData->idx_body_template = 0;
+ pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes(
+ (pData->content_type)
+ ? pData->content_type
+ :"raw");
+ }
+
+ /* treatment of the server parameter
+ * first the default port */
+ pData->server2.port = pData->server1.port = port ? port : 5672;
+
+ char *temp;
+ int p;
+ pData->server1.host = host;
+
+ /* Is there more than one server in parameter */
+ if ((pData->server2.host = strchr(pData->server1.host,' ')) != NULL)
+ {
+ *pData->server2.host++ ='\0';
+ /* is there a port with the second server */
+ if ((temp = strchr(pData->server2.host,':')) != NULL)
+ {
+ *temp++ ='\0';
+ p = atoi(temp);
+ if (p) pData->server2.port = p;
+ }
+ }
+
+ /* is there a port with the first/unique server */
+ if ((temp = strchr(pData->server1.host,':')) != NULL)
+ {
+ *temp++ ='\0';
+ p = atoi(temp);
+ if (p) pData->server1.port = p;
+ }
+
+ pData->vhost = vhost ? vhost : strdup("/");
+ pData->user = user ? user : strdup("");
+ pData->password = password ? password : strdup("");
+
+ init_recover(&pData->recover_policy, recover);
+
+ if (recover)
+ free(recover);
+
+ dbgPrintInstInfo(pData);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ memset(pWrkrData, 0, sizeof(wrkrInstanceData_t));
+
+ pWrkrData->pData = pData;
+
+ pthread_mutex_init(&pWrkrData->send_mutex, NULL);
+ pthread_cond_init(&pWrkrData->cond, NULL);
+
+ pWrkrData->state = RS_RET_SUSPENDED;
+ pWrkrData->iidx = pData->iidx;
+ pWrkrData->widx = ++pData->nbWrkr;
+
+ memcpy(&(pWrkrData->recover_policy), &(pData->recover_policy),
+ sizeof(recover_t));
+
+ if (pData->server2.host && *pData->server2.host) {
+ time_t odd = time(NULL) % 2;
+ memcpy(&(pWrkrData->serverPrefered.s), (odd) ?
+ &pData->server1 : &pData->server2, sizeof(server_t));
+ memcpy(&(pWrkrData->serverBackup.s), (odd) ?
+ &pData->server2 : &pData->server1, sizeof(server_t));
+ }else{
+ memcpy(&(pWrkrData->serverPrefered.s), &pData->server1, sizeof(server_t));
+ }
+ pWrkrData->serverActive = &pWrkrData->serverPrefered;
+
+ startAMQPConnection(pWrkrData);
+
+ENDcreateWrkrInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+
+ if (pWrkrData != NULL) {
+ closeAMQPConnection(pWrkrData);
+
+ pthread_mutex_destroy(&(pWrkrData->send_mutex));
+ pthread_cond_destroy(&(pWrkrData->cond));
+ }
+ENDfreeWrkrInstance
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+ CODEqueryEtryPt_STD_OMOD_QUERIES
+ CODEqueryEtryPt_STD_OMOD8_QUERIES
+ CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ENDmodInit
diff --git a/contrib/omtcl/Makefile.am b/contrib/omtcl/Makefile.am
new file mode 100644
index 0000000..342f11b
--- /dev/null
+++ b/contrib/omtcl/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omtcl.la
+
+omtcl_la_SOURCES = omtcl.c
+omtcl_la_CPPFLAGS = $(RSRT_CFLAGS) $(TCL_INCLUDE_SPEC)
+omtcl_la_LDFLAGS = -module
+omtcl_la_LIBADD = $(TCL_LIB_SPEC)
+
+EXTRA_DIST =
diff --git a/contrib/omtcl/Makefile.in b/contrib/omtcl/Makefile.in
new file mode 100644
index 0000000..7937c37
--- /dev/null
+++ b/contrib/omtcl/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/omtcl
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omtcl_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omtcl_la_OBJECTS = omtcl_la-omtcl.lo
+omtcl_la_OBJECTS = $(am_omtcl_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 =
+omtcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omtcl_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omtcl_la-omtcl.Plo
+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 = $(omtcl_la_SOURCES)
+DIST_SOURCES = $(omtcl_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omtcl.la
+omtcl_la_SOURCES = omtcl.c
+omtcl_la_CPPFLAGS = $(RSRT_CFLAGS) $(TCL_INCLUDE_SPEC)
+omtcl_la_LDFLAGS = -module
+omtcl_la_LIBADD = $(TCL_LIB_SPEC)
+EXTRA_DIST =
+all: 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) --gnu contrib/omtcl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/omtcl/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omtcl.la: $(omtcl_la_OBJECTS) $(omtcl_la_DEPENDENCIES) $(EXTRA_omtcl_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omtcl_la_LINK) -rpath $(pkglibdir) $(omtcl_la_OBJECTS) $(omtcl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omtcl_la-omtcl.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omtcl_la-omtcl.lo: omtcl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omtcl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omtcl_la-omtcl.lo -MD -MP -MF $(DEPDIR)/omtcl_la-omtcl.Tpo -c -o omtcl_la-omtcl.lo `test -f 'omtcl.c' || echo '$(srcdir)/'`omtcl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omtcl_la-omtcl.Tpo $(DEPDIR)/omtcl_la-omtcl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omtcl.c' object='omtcl_la-omtcl.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) $(omtcl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omtcl_la-omtcl.lo `test -f 'omtcl.c' || echo '$(srcdir)/'`omtcl.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omtcl_la-omtcl.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omtcl_la-omtcl.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/omtcl/omtcl.c b/contrib/omtcl/omtcl.c
new file mode 100644
index 0000000..c0f7f66
--- /dev/null
+++ b/contrib/omtcl/omtcl.c
@@ -0,0 +1,164 @@
+/* omtcl.c
+ * invoke a tcl procedure for every message
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * File begun on 2016-05-16 by fcr
+ *
+ * Copyright 2016 Francisco Castro <fcr@adinet.com.uy>
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+/* work around gcc-7 build problems - acceptable for contributed module */
+#pragma GCC diagnostic ignored "-Wundef"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "tcl.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ Tcl_Interp * interp;
+ Tcl_Obj * cmdName;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData * pData;
+} wrkrInstanceData_t;
+
+BEGINinitConfVars
+CODESTARTinitConfVars
+ENDinitConfVars
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->interp = Tcl_CreateInterp();
+ pData->cmdName = NULL;
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+/* not compatible with message reduction */
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->cmdName != NULL)
+ Tcl_DecrRefCount(pData->cmdName);
+ Tcl_DeleteInterp(pData->interp);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+ Tcl_Obj * objv[2];
+CODESTARTdoAction
+ objv[0] = pWrkrData->pData->cmdName;
+ objv[1] = Tcl_NewStringObj((char*) ppString[0], -1);
+ if (Tcl_EvalObjv(pWrkrData->pData->interp, 2, objv, 0) != TCL_OK) {
+ iRet = RS_RET_ERR;
+ DBGPRINTF("omtcl: %s", Tcl_GetStringResult(pWrkrData->pData->interp));
+ }
+ENDdoAction
+
+BEGINparseSelectorAct
+ char fileName[PATH_MAX+1];
+ char buffer[4096];
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(strncmp((char*) p, ":omtcl:", sizeof(":omtcl:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+ p += sizeof(":omtcl:") - 1;
+
+ if(getSubString(&p, fileName, PATH_MAX+1, ',') || getSubString(&p, buffer, 4096, ';') || !strlen(buffer)) {
+ LogError(0, RS_RET_INVALID_PARAMS, "Invalid OmTcl parameters");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+
+ if (*(p-1) == ';')
+ --p;
+
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*) "RSYSLOG_FileFormat"));
+
+ CHKiRet(createInstance(&pData));
+ pData->cmdName = Tcl_NewStringObj(buffer, -1);
+ Tcl_IncrRefCount(pData->cmdName);
+
+ // TODO parse arguments: file,procname
+ if (Tcl_EvalFile(pData->interp, fileName) == TCL_ERROR) {
+ LogError(0, RS_RET_CONFIG_ERROR, "Loading Tcl script: %s", Tcl_GetStringResult(pData->interp));
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("omtcl: module compiled with rsyslog version %s.\n", VERSION);
+
+ENDmodInit
+
diff --git a/contrib/pmaixforwardedfrom/Makefile.am b/contrib/pmaixforwardedfrom/Makefile.am
new file mode 100644
index 0000000..af359d3
--- /dev/null
+++ b/contrib/pmaixforwardedfrom/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmaixforwardedfrom.la
+
+pmaixforwardedfrom_la_SOURCES = pmaixforwardedfrom.c
+pmaixforwardedfrom_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmaixforwardedfrom_la_LDFLAGS = -module -avoid-version
+pmaixforwardedfrom_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/pmaixforwardedfrom/Makefile.in b/contrib/pmaixforwardedfrom/Makefile.in
new file mode 100644
index 0000000..dab4de0
--- /dev/null
+++ b/contrib/pmaixforwardedfrom/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/pmaixforwardedfrom
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmaixforwardedfrom_la_DEPENDENCIES =
+am_pmaixforwardedfrom_la_OBJECTS = \
+ pmaixforwardedfrom_la-pmaixforwardedfrom.lo
+pmaixforwardedfrom_la_OBJECTS = $(am_pmaixforwardedfrom_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 =
+pmaixforwardedfrom_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(pmaixforwardedfrom_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo
+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 = $(pmaixforwardedfrom_la_SOURCES)
+DIST_SOURCES = $(pmaixforwardedfrom_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmaixforwardedfrom.la
+pmaixforwardedfrom_la_SOURCES = pmaixforwardedfrom.c
+pmaixforwardedfrom_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmaixforwardedfrom_la_LDFLAGS = -module -avoid-version
+pmaixforwardedfrom_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/pmaixforwardedfrom/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/pmaixforwardedfrom/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmaixforwardedfrom.la: $(pmaixforwardedfrom_la_OBJECTS) $(pmaixforwardedfrom_la_DEPENDENCIES) $(EXTRA_pmaixforwardedfrom_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmaixforwardedfrom_la_LINK) -rpath $(pkglibdir) $(pmaixforwardedfrom_la_OBJECTS) $(pmaixforwardedfrom_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmaixforwardedfrom_la-pmaixforwardedfrom.lo: pmaixforwardedfrom.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmaixforwardedfrom_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmaixforwardedfrom_la-pmaixforwardedfrom.lo -MD -MP -MF $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Tpo -c -o pmaixforwardedfrom_la-pmaixforwardedfrom.lo `test -f 'pmaixforwardedfrom.c' || echo '$(srcdir)/'`pmaixforwardedfrom.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Tpo $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmaixforwardedfrom.c' object='pmaixforwardedfrom_la-pmaixforwardedfrom.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) $(pmaixforwardedfrom_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmaixforwardedfrom_la-pmaixforwardedfrom.lo `test -f 'pmaixforwardedfrom.c' || echo '$(srcdir)/'`pmaixforwardedfrom.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/pmaixforwardedfrom/pmaixforwardedfrom.c b/contrib/pmaixforwardedfrom/pmaixforwardedfrom.c
new file mode 100644
index 0000000..f27a236
--- /dev/null
+++ b/contrib/pmaixforwardedfrom/pmaixforwardedfrom.c
@@ -0,0 +1,185 @@
+/* pmaixforwardedfrom.c
+ *
+ * this cleans up messages forwarded from AIX
+ *
+ * instead of actually parsing the message, this modifies the message and then falls through to allow a
+ * later parser to handle the now modified message
+ *
+ * created 2010-12-13 by David Lang based on pmlastmsg
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.aixforwardedfrom")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINparse
+ uchar *p2parse;
+ int lenMsg;
+ int skipLen = 0;
+#define OpeningText "Message forwarded from "
+#define OpeningText2 "From "
+CODESTARTparse
+ dbgprintf("Message will now be parsed by fix AIX Forwarded From parser.\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+
+ /* check if this message is of the type we handle in this (very limited) parser */
+ /* first, we permit SP */
+ while(lenMsg && *p2parse == ' ') {
+ --lenMsg;
+ ++p2parse;
+ }
+ if((unsigned) lenMsg < 24) {
+ /* too short, can not be "our" message */
+ /* minimum message, 16 character timestamp, 'From ", 1 character name, ': '*/
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* skip over timestamp */
+ lenMsg -=16;
+ p2parse +=16;
+ /* if there is the string "Message forwarded from " were the hostname should be */
+ if(!strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1))
+ skipLen = 23;
+ /* or "From " */
+ if(!strncasecmp((char*) p2parse, OpeningText2, sizeof(OpeningText2)-1))
+ skipLen = 5;
+ DBGPRINTF("pmaixforwardedfrom: skipLen %d\n", skipLen);
+ if(!skipLen) {
+ /* wrong opening text */
+ DBGPRINTF("not a AIX message forwarded from mangled log!\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* bump the message portion up by skipLen(23 or 5) characters to overwrite the "Message forwarded from
+" or "From " with the hostname */
+ lenMsg -=skipLen;
+ if(lenMsg < 2) {
+ dbgprintf("not a AIX message forwarded from message has nothing after header\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ memmove(p2parse, p2parse + skipLen, lenMsg);
+ *(p2parse + lenMsg) = '\n';
+ *(p2parse + lenMsg + 1) = '\0';
+ pMsg->iLenRawMsg -=skipLen;
+ pMsg->iLenMSG -=skipLen;
+ /* now look for the : after the hostname to walk past the hostname, also watch for a space in case this isn't
+really an AIX log, but has a similar preamble */
+ while(lenMsg && *p2parse != ' ' && *p2parse != ':') {
+ --lenMsg;
+ ++p2parse;
+ }
+ if (lenMsg < 1) {
+ dbgprintf("not a AIX message forwarded from message has nothing after colon "
+ "or no colon at all\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ if (lenMsg && *p2parse != ':') {
+ DBGPRINTF("not a AIX message forwarded from mangled log but similar enough that the preamble has "
+ "been removed\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* bump the message portion up by one character to overwrite the extra : */
+ lenMsg -=1;
+ memmove(p2parse, p2parse + 1, lenMsg);
+ *(p2parse + lenMsg) = '\n';
+ *(p2parse + lenMsg + 1) = '\0';
+ pMsg->iLenRawMsg -=1;
+ pMsg->iLenMSG -=1;
+ /* now, claim to abort so that something else can parse the now modified message */
+ DBGPRINTF("pmaixforwardedfrom: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+finalize_it:
+ENDparse
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("aixforwardedfrom parser init called, compiled with version %s\n", VERSION);
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+
+
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/contrib/pmcisconames/Makefile.am b/contrib/pmcisconames/Makefile.am
new file mode 100644
index 0000000..16ed347
--- /dev/null
+++ b/contrib/pmcisconames/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmcisconames.la
+
+pmcisconames_la_SOURCES = pmcisconames.c
+pmcisconames_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmcisconames_la_LDFLAGS = -module -avoid-version
+pmcisconames_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/pmcisconames/Makefile.in b/contrib/pmcisconames/Makefile.in
new file mode 100644
index 0000000..b45fa4b
--- /dev/null
+++ b/contrib/pmcisconames/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/pmcisconames
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmcisconames_la_DEPENDENCIES =
+am_pmcisconames_la_OBJECTS = pmcisconames_la-pmcisconames.lo
+pmcisconames_la_OBJECTS = $(am_pmcisconames_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 =
+pmcisconames_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(pmcisconames_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo
+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 = $(pmcisconames_la_SOURCES)
+DIST_SOURCES = $(pmcisconames_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmcisconames.la
+pmcisconames_la_SOURCES = pmcisconames.c
+pmcisconames_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmcisconames_la_LDFLAGS = -module -avoid-version
+pmcisconames_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/pmcisconames/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/pmcisconames/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmcisconames.la: $(pmcisconames_la_OBJECTS) $(pmcisconames_la_DEPENDENCIES) $(EXTRA_pmcisconames_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmcisconames_la_LINK) -rpath $(pkglibdir) $(pmcisconames_la_OBJECTS) $(pmcisconames_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmcisconames_la-pmcisconames.lo: pmcisconames.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmcisconames_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmcisconames_la-pmcisconames.lo -MD -MP -MF $(DEPDIR)/pmcisconames_la-pmcisconames.Tpo -c -o pmcisconames_la-pmcisconames.lo `test -f 'pmcisconames.c' || echo '$(srcdir)/'`pmcisconames.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmcisconames_la-pmcisconames.Tpo $(DEPDIR)/pmcisconames_la-pmcisconames.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmcisconames.c' object='pmcisconames_la-pmcisconames.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) $(pmcisconames_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmcisconames_la-pmcisconames.lo `test -f 'pmcisconames.c' || echo '$(srcdir)/'`pmcisconames.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/pmcisconames/pmcisconames.c b/contrib/pmcisconames/pmcisconames.c
new file mode 100644
index 0000000..0d7cb51
--- /dev/null
+++ b/contrib/pmcisconames/pmcisconames.c
@@ -0,0 +1,185 @@
+/* pmcisconames.c
+ *
+ * this detects logs sent by Cisco devices that mangle their syslog output when you tell them to log by name
+ * by adding ' :' between the name and the %XXX-X-XXXXXXX: tag
+ *
+ * instead of actually parsing the message, this modifies the message and then falls through to allow a later
+ * parser to handle the now modified message
+ *
+ * created 2010-12-13 by David Lang based on pmlastmsg
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.cisconames")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINparse
+ uchar *p2parse;
+ int lenMsg;
+#define OpeningText ": %"
+CODESTARTparse
+ dbgprintf("Message will now be parsed by fix Cisco Names parser.\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+
+ /* check if this message is of the type we handle in this (very limited) parser */
+ /* first, we permit SP */
+ while(lenMsg && *p2parse == ' ') {
+ --lenMsg;
+ ++p2parse;
+ }
+ if((unsigned) lenMsg < 34) {
+ /* too short, can not be "our" message */
+ /* minimum message, 16 character timestamp, 1 character name, ' : %ASA-1-000000: '*/
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* check if the timestamp is a 16 character or 21 character timestamp
+ 'Mmm DD HH:MM:SS ' spaces at 3,6,15 : at 9,12
+ 'Mmm DD YYYY HH:MM:SS ' spaces at 3,6,11,20 : at 14,17
+ check for the : first as that will differentiate the two conditions the fastest
+ this allows the compiler to short circuit the rst of the tests if it is the wrong timestamp
+ but still check the rest to see if it looks correct
+ */
+ if ( *(p2parse + 9) == ':' && *(p2parse + 12) == ':' && *(p2parse + 3) == ' ' && *(p2parse + 6) == ' '
+ && *(p2parse + 15) == ' ') {
+ /* skip over timestamp */
+ dbgprintf("short timestamp found\n");
+ lenMsg -=16;
+ p2parse +=16;
+ } else {
+ if ( *(p2parse + 14) == ':' && *(p2parse + 17) == ':' && *(p2parse + 3) == ' '
+ && *(p2parse + 6) == ' ' && *(p2parse + 11) == ' ' && *(p2parse + 20) == ' ') {
+ /* skip over timestamp */
+ dbgprintf("long timestamp found\n");
+ lenMsg -=21;
+ p2parse +=21;
+ } else {
+ dbgprintf("timestamp is not one of the valid formats\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ }
+ /* now look for the next space to walk past the hostname */
+ while(lenMsg && *p2parse != ' ') {
+ --lenMsg;
+ ++p2parse;
+ }
+ /* Note: we deliberately count the 0-byte below because we need to go chars+1! */
+ if(lenMsg < (int) sizeof(OpeningText)) {
+ dbgprintf("pmcisconames: too short for being cisco messages\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* skip the space after the hostname */
+ lenMsg -=1;
+ p2parse +=1;
+ /* if the syslog tag is : and the next thing starts with a % assume that this is a mangled cisco
+ log and fix it */
+ if(strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1) != 0) {
+ /* wrong opening text */
+ DBGPRINTF("not a cisco name mangled log!\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* bump the message portion up by two characters to overwrite the extra : */
+ lenMsg -=2;
+ memmove(p2parse, p2parse + 2, lenMsg);
+ *(p2parse + lenMsg) = '\n';
+ *(p2parse + lenMsg + 1) = '\0';
+ pMsg->iLenRawMsg -=2;
+ pMsg->iLenMSG -=2;
+ /* now, claim to abort so that something else can parse the now modified message */
+ DBGPRINTF("pmcisconames: new message: [%d]'%s'\n", lenMsg, p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+finalize_it:
+ENDparse
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("cisconames parser init called, compiled with version %s\n", VERSION);
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+
+
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/contrib/pmdb2diag/Makefile.am b/contrib/pmdb2diag/Makefile.am
new file mode 100644
index 0000000..5bde231
--- /dev/null
+++ b/contrib/pmdb2diag/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmdb2diag.la
+
+pmdb2diag_la_SOURCES = pmdb2diag.c
+pmdb2diag_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmdb2diag_la_LDFLAGS = -module -avoid-version
+pmdb2diag_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/pmdb2diag/Makefile.in b/contrib/pmdb2diag/Makefile.in
new file mode 100644
index 0000000..4587599
--- /dev/null
+++ b/contrib/pmdb2diag/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/pmdb2diag
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmdb2diag_la_DEPENDENCIES =
+am_pmdb2diag_la_OBJECTS = pmdb2diag_la-pmdb2diag.lo
+pmdb2diag_la_OBJECTS = $(am_pmdb2diag_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 =
+pmdb2diag_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmdb2diag_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo
+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 = $(pmdb2diag_la_SOURCES)
+DIST_SOURCES = $(pmdb2diag_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmdb2diag.la
+pmdb2diag_la_SOURCES = pmdb2diag.c
+pmdb2diag_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmdb2diag_la_LDFLAGS = -module -avoid-version
+pmdb2diag_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/pmdb2diag/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/pmdb2diag/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmdb2diag.la: $(pmdb2diag_la_OBJECTS) $(pmdb2diag_la_DEPENDENCIES) $(EXTRA_pmdb2diag_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmdb2diag_la_LINK) -rpath $(pkglibdir) $(pmdb2diag_la_OBJECTS) $(pmdb2diag_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmdb2diag_la-pmdb2diag.lo: pmdb2diag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmdb2diag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmdb2diag_la-pmdb2diag.lo -MD -MP -MF $(DEPDIR)/pmdb2diag_la-pmdb2diag.Tpo -c -o pmdb2diag_la-pmdb2diag.lo `test -f 'pmdb2diag.c' || echo '$(srcdir)/'`pmdb2diag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmdb2diag_la-pmdb2diag.Tpo $(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmdb2diag.c' object='pmdb2diag_la-pmdb2diag.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) $(pmdb2diag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmdb2diag_la-pmdb2diag.lo `test -f 'pmdb2diag.c' || echo '$(srcdir)/'`pmdb2diag.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/pmdb2diag/pmdb2diag.c b/contrib/pmdb2diag/pmdb2diag.c
new file mode 100644
index 0000000..5810eb4
--- /dev/null
+++ b/contrib/pmdb2diag/pmdb2diag.c
@@ -0,0 +1,305 @@
+/* pmdb2diag.c
+ *
+ * This is a parser module specifically for DB2diag log file.
+ * It extracted program, pid and severity from the log.
+ *
+ * Copyright 2015 Philippe Duveau @ Pari Mutuel Urbain.
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("db2.diag")
+MODULE_CNFNAME("pmdb2diag")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+
+/* input instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "levelpos", eCmdHdlrInt, 0 },
+ { "timepos", eCmdHdlrInt, 0 },
+ { "timeformat", eCmdHdlrString, 0 },
+ { "pidstarttoprogstartshift", eCmdHdlrInt, 0 },
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+struct instanceConf_s {
+ int levelpos; /* expected severity position in read message */
+ int timepos; /* expected time position in read message */
+ int pidstarttoprogstartshift; /* position of prog related to pid */
+ char *timeformat; /* format of timestamp in read message */
+ char sepSec; /* decimal separator between second and milliseconds */
+};
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINparse2
+ struct tm tm;
+ char *ms, *timepos, *pid, *prog, *eprog, *backslash, *end, *lvl;
+ int lprog, lpid, lvl_len;
+ char buffer[128];
+CODESTARTparse2
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+
+ DBGPRINTF("Message will now be parsed by \"db2diag\" parser.\n");
+ if(pMsg->iLenRawMsg - (int)pMsg->offAfterPRI < pInst->levelpos+4)
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+ /* Instead of comparing strings which a waste of cpu cycles we take interpret the 4 first chars of
+ * level read it as int32 and compare it to same interpretation of our constant "levels"
+ * So this test is not sensitive to ENDIANESS. This is not a clean way but very efficient.
+ */
+ lvl = (char*)(pMsg->pszRawMsg + pMsg->offAfterPRI + pInst->levelpos);
+
+ switch (*lvl) {
+ case 'C': /* Critical */
+ pMsg->iSeverity = LOG_EMERG;
+ lvl_len = 8;
+ break;
+ case 'A': /* Alert */
+ pMsg->iSeverity = LOG_ALERT;
+ lvl_len = 5;
+ break;
+ case 'S': /* Severe */
+ pMsg->iSeverity = LOG_CRIT;
+ lvl_len = 6;
+ break;
+ case 'E': /* Error / Event */
+ pMsg->iSeverity = (lvl[1] == 'r') ? LOG_ERR : LOG_NOTICE;
+ lvl_len = 5;
+ break;
+ case 'W': /* Warning */
+ pMsg->iSeverity = LOG_WARNING;
+ lvl_len = 7;
+ break;
+ case 'I': /* Info */
+ pMsg->iSeverity = LOG_INFO;
+ lvl_len = 4;
+ break;
+ case 'D': /* Debug */
+ pMsg->iSeverity = LOG_DEBUG;
+ lvl_len = 5;
+ break;
+ default:
+ /* perhaps the message does not contain a proper level if so don't parse the log */
+ ABORT_FINALIZE(0);
+ }
+
+ /* let recheck with the real level len */
+ if(pMsg->iLenRawMsg - (int)pMsg->offAfterPRI < pInst->levelpos+lvl_len)
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+ DBGPRINTF("db2parse Level %d\n", pMsg->iSeverity);
+
+ end = (char*)pMsg->pszRawMsg + pMsg->iLenRawMsg ;
+
+ timepos = (char*)pMsg->pszRawMsg + pMsg->offAfterPRI + pInst->timepos;
+
+ DBGPRINTF("db2parse Time %.30s\n", timepos);
+ ms = strptime(timepos, pInst->timeformat, &tm);
+
+ if (ms > timepos && *(ms-1) == pInst->sepSec)
+ {
+ /* the timestamp could be properly interpreted by strptime & our format then set proper timestamp */
+ int secfrac = 0, tzoff = 0;
+
+ char *tzpos = strchr(ms, '+');
+ if (!tzpos) tzpos = strchr(ms, '-');
+ if (!tzpos) tzpos = (char*)"+";
+
+ sscanf(ms, (*tzpos == '+') ? "%d+%d " : "%d-%d ", &secfrac, &tzoff);
+
+ pMsg->tTIMESTAMP.year = tm.tm_year+1900;
+ pMsg->tTIMESTAMP.month = tm.tm_mon + 1;
+ pMsg->tTIMESTAMP.day = tm.tm_mday;
+ pMsg->tTIMESTAMP.hour = tm.tm_hour;
+ pMsg->tTIMESTAMP.minute = tm.tm_min;
+ pMsg->tTIMESTAMP.second = tm.tm_sec;
+ pMsg->tTIMESTAMP.secfrac = secfrac;
+ pMsg->tTIMESTAMP.secfracPrecision = tzpos-ms;
+ pMsg->tTIMESTAMP.OffsetMode = *tzpos;
+ pMsg->tTIMESTAMP.OffsetHour = tzoff / 60;
+ pMsg->tTIMESTAMP.OffsetMinute = tzoff % 60;
+ }
+
+ pid = strchr((char*)pMsg->pszRawMsg + pInst->levelpos + lvl_len, ':');
+ if (!pid || pid>=end) ABORT_FINALIZE(0);
+ pid += 2;
+ lpid = strchr(pid, ' ') - pid;
+
+ DBGPRINTF("db2parse pid %.*s\n", lpid, pid);
+
+ /* set the pid */
+ snprintf(buffer, 128, "%.*s", lpid, pid);
+ MsgSetPROCID(pMsg, buffer);
+
+ prog = pid + pInst->pidstarttoprogstartshift; /* this offset between start of pid to start of prog */
+ if (prog>=end) ABORT_FINALIZE(0);
+
+ eprog = strchr(prog, ' '); /* let find the end of the program */
+ if (eprog && eprog>=end) ABORT_FINALIZE(0);
+
+ backslash = strchr(prog, '\\'); /* perhaps program contain an backslash */
+ if (!backslash || backslash>=end) backslash = end;
+
+ /* Determine the final length of prog */
+ lprog = (eprog && eprog<backslash) ? eprog-prog : backslash-prog;
+
+ DBGPRINTF("db2parse prog %.*s lprog %d\n", lprog, prog, lprog);
+
+/* set the appname */
+ snprintf(buffer, 128, "%.*s", lprog, prog);
+ MsgSetAPPNAME(pMsg, buffer);
+
+ /* the original raw msg if not altered by the parser */
+finalize_it:
+ENDparse2
+
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ free(pInst->timeformat);
+ENDfreeParserInst
+
+static rsRetVal
+createInstance(instanceConf_t **ppInst)
+{
+ instanceConf_t *pInst;
+ DEFiRet;
+ CHKmalloc(pInst = (instanceConf_t *)malloc(sizeof(instanceConf_t)));
+ pInst->timeformat = NULL;
+ pInst->levelpos = 59;
+ pInst->timepos = 0;
+ pInst->pidstarttoprogstartshift = 49;
+
+ *ppInst = pInst;
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewParserInst
+ inst = NULL;
+
+ DBGPRINTF("newParserInst (pmdb2diag)\n");
+ CHKiRet(createInstance(&inst));
+
+ if (lst)
+ {
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("parser param blk in pmdb2diag:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "timeformat")) {
+ inst->timeformat = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(parserpblk.descr[i].name, "timepos")) {
+ inst->timepos = (int)pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "levelpos")) {
+ inst->levelpos = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "pidstarttoprogstartshift")) {
+ inst->pidstarttoprogstartshift = (int) pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("pmdb2diag: program error, non-handled "
+ "param '%s'\n", parserpblk.descr[i].name);
+ }
+ }
+ }
+
+ if (inst->timeformat == NULL)
+ {
+ inst->timeformat = strdup("%Y-%m-%d-%H.%M.%S.");
+ inst->sepSec = '.';
+ }else
+ inst->sepSec = inst->timeformat[strlen(inst->timeformat)-1];
+
+ DBGPRINTF("pmdb2diag: parsing date/time with '%s' at position %d and level at position %d.\n",
+ inst->timeformat, inst->timepos, inst->levelpos);
+
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ENDnewParserInst
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ DBGPRINTF("pmdb2diag parser init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/contrib/pmpanngfw/Makefile.am b/contrib/pmpanngfw/Makefile.am
new file mode 100644
index 0000000..50d7556
--- /dev/null
+++ b/contrib/pmpanngfw/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmpanngfw.la
+
+pmpanngfw_la_SOURCES = pmpanngfw.c
+pmpanngfw_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmpanngfw_la_LDFLAGS = -module -avoid-version
+pmpanngfw_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/pmpanngfw/Makefile.in b/contrib/pmpanngfw/Makefile.in
new file mode 100644
index 0000000..d33221a
--- /dev/null
+++ b/contrib/pmpanngfw/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/pmpanngfw
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmpanngfw_la_DEPENDENCIES =
+am_pmpanngfw_la_OBJECTS = pmpanngfw_la-pmpanngfw.lo
+pmpanngfw_la_OBJECTS = $(am_pmpanngfw_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 =
+pmpanngfw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmpanngfw_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo
+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 = $(pmpanngfw_la_SOURCES)
+DIST_SOURCES = $(pmpanngfw_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmpanngfw.la
+pmpanngfw_la_SOURCES = pmpanngfw.c
+pmpanngfw_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmpanngfw_la_LDFLAGS = -module -avoid-version
+pmpanngfw_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/pmpanngfw/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/pmpanngfw/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmpanngfw.la: $(pmpanngfw_la_OBJECTS) $(pmpanngfw_la_DEPENDENCIES) $(EXTRA_pmpanngfw_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmpanngfw_la_LINK) -rpath $(pkglibdir) $(pmpanngfw_la_OBJECTS) $(pmpanngfw_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmpanngfw_la-pmpanngfw.lo: pmpanngfw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmpanngfw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmpanngfw_la-pmpanngfw.lo -MD -MP -MF $(DEPDIR)/pmpanngfw_la-pmpanngfw.Tpo -c -o pmpanngfw_la-pmpanngfw.lo `test -f 'pmpanngfw.c' || echo '$(srcdir)/'`pmpanngfw.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmpanngfw_la-pmpanngfw.Tpo $(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmpanngfw.c' object='pmpanngfw_la-pmpanngfw.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) $(pmpanngfw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmpanngfw_la-pmpanngfw.lo `test -f 'pmpanngfw.c' || echo '$(srcdir)/'`pmpanngfw.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/pmpanngfw/pmpanngfw.c b/contrib/pmpanngfw/pmpanngfw.c
new file mode 100644
index 0000000..c65cee7
--- /dev/null
+++ b/contrib/pmpanngfw/pmpanngfw.c
@@ -0,0 +1,296 @@
+/* pmpanngfw.c
+ *
+ * this detects logs sent by Palo Alto Networks NGFW and transforms CSV into tab-separated fields
+ * for handling inside the mmnormalize
+ *
+ * Example: foo,"bar,""baz""",qux becomes foo<TAB>bar,"baz"<TAB>qux
+ *
+ * created 2010-12-13 by Luigi Mori (lmori@paloaltonetworks.com) based on pmsnare
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "typedefs.h"
+#include "rsconf.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.panngfw")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+typedef struct {
+ uint64 value;
+ uint64 mask;
+} log_type_t;
+
+const log_type_t log_types[] = {
+ { 0x002c544145524854ULL, 0x00FFFFFFFFFFFFFFULL }, /* THREAT, */
+ { 0x2c43494646415254ULL, 0xFFFFFFFFFFFFFFFFULL }, /* TRAFFIC, */
+ { 0x002c4d4554535953ULL, 0x00FFFFFFFFFFFFFFULL }, /* CONFIG */
+ { 0x002c4749464e4f43ULL, 0x00FFFFFFFFFFFFFFULL } /* SYSTEM */
+};
+
+#define NUM_LOG_TYPES (sizeof(log_types)/sizeof(log_type_t))
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+
+BEGINparse
+ uchar *p2parse;
+ uchar *p2target;
+ uchar *msgend;
+ int lenMsg, lenDelta;
+ int state;
+ int num_fields = 4;
+ uchar *f3_commas[3];
+ int cur_comma = 0;
+ uint64 log_type;
+ unsigned int j;
+CODESTARTparse
+ #define CSV_DELIMITER '\t'
+ #define STATE_FIELD_START 0
+ #define STATE_IN_FIELD 1
+ #define STATE_IN_QUOTE 2
+ #define STATE_IN_QUOTE_QUOTE 3
+
+ state = STATE_FIELD_START;
+
+ dbgprintf("Message will now be parsed by fix Palo Alto Networks NGFW parser.\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+ msgend = p2parse+lenMsg;
+
+ dbgprintf("pmpanngfw: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
+
+ /* pass the first 3 fields */
+ while(p2parse < msgend) {
+ if (*p2parse == ',') {
+ f3_commas[cur_comma] = p2parse;
+ if (cur_comma == 2) {
+ break;
+ }
+ cur_comma++;
+ }
+ p2parse++;
+ }
+
+ /* check number of fields detected so far */
+ if (cur_comma != 2) {
+ dbgprintf("not a PAN-OS syslog message: first 3 fields not found\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* check msg length */
+ p2parse++;
+ if ((p2parse > msgend) || ((msgend - p2parse) < (int)sizeof(uint64))) {
+ dbgprintf("not a PAN-OS syslog message: too short\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* check log type */
+ log_type = *((uint64 *)p2parse);
+ for(j = 0; j < (int)NUM_LOG_TYPES; j++) {
+ if ((log_type & log_types[j].mask) == log_types[j].value)
+ break;
+ }
+ if (j == NUM_LOG_TYPES) {
+ dbgprintf("not a PAN-OS syslog message, log type: %llx\n", log_type);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* set the delimiter */
+ *f3_commas[0] = CSV_DELIMITER;
+ *f3_commas[1] = CSV_DELIMITER;
+ *f3_commas[2] = CSV_DELIMITER;
+
+ p2target = p2parse;
+
+ while(p2parse < msgend) {
+ switch(state) {
+ case STATE_FIELD_START:
+ switch(*p2parse) {
+ case '"':
+ state = STATE_IN_QUOTE;
+ p2parse++;
+ break;
+
+ case ',':
+ state = STATE_FIELD_START;
+ *p2target = CSV_DELIMITER;
+ num_fields++;
+ p2parse++;
+ p2target++;
+ break;
+
+ default:
+ state = STATE_IN_FIELD;
+ *p2target = *p2parse;
+ p2parse++;
+ p2target++;
+ }
+ break;
+
+ case STATE_IN_FIELD:
+ switch(*p2parse) {
+ case ',':
+ state = STATE_FIELD_START;
+ *p2target = CSV_DELIMITER;
+ num_fields++;
+ p2parse++;
+ p2target++;
+ break;
+
+ default:
+ *p2target = *p2parse;
+ p2parse++;
+ p2target++;
+ }
+ break;
+
+ case STATE_IN_QUOTE:
+ switch(*p2parse) {
+ case '"':
+ state = STATE_IN_QUOTE_QUOTE;
+ p2parse++;
+ break;
+
+ default:
+ *p2target = *p2parse;
+ p2parse++;
+ p2target++;
+ }
+ break;
+
+ case STATE_IN_QUOTE_QUOTE:
+ switch(*p2parse) {
+ case '"':
+ state = STATE_IN_QUOTE;
+ *p2target = *p2parse;
+ p2parse++;
+ p2target++;
+ break;
+
+ case ',':
+ state = STATE_FIELD_START;
+ *p2target = CSV_DELIMITER;
+ num_fields++;
+ p2parse++;
+ p2target++;
+ break;
+
+ default:
+ dbgprintf("pmpanngfw: martian char (%d) after quote in quote\n", *p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ break;
+
+ default:
+ dbgprintf("how could I have reached this state ?!?\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ }
+
+ if(p2parse != p2target) {
+ lenDelta = p2parse - p2target;
+
+ assert(lenDelta >= 2);
+
+ *p2target = 0;
+
+ pMsg->iLenRawMsg -= lenDelta;
+ pMsg->iLenMSG -= lenDelta;
+ }
+
+ lenMsg = p2target - (pMsg->pszRawMsg + pMsg->offAfterPRI);
+
+ DBGPRINTF("pmpanngfw: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI);
+ DBGPRINTF("pmpanngfw: # fields: %d\n", num_fields);
+
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+finalize_it:
+ENDparse
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("panngfw parser init called, compiled with version %s\n", VERSION);
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+
+
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/contrib/pmsnare/Makefile.am b/contrib/pmsnare/Makefile.am
new file mode 100644
index 0000000..5b2696a
--- /dev/null
+++ b/contrib/pmsnare/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmsnare.la
+
+pmsnare_la_SOURCES = pmsnare.c
+pmsnare_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmsnare_la_LDFLAGS = -module -avoid-version
+pmsnare_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/contrib/pmsnare/Makefile.in b/contrib/pmsnare/Makefile.in
new file mode 100644
index 0000000..9e94793
--- /dev/null
+++ b/contrib/pmsnare/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = contrib/pmsnare
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmsnare_la_DEPENDENCIES =
+am_pmsnare_la_OBJECTS = pmsnare_la-pmsnare.lo
+pmsnare_la_OBJECTS = $(am_pmsnare_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 =
+pmsnare_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmsnare_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmsnare_la-pmsnare.Plo
+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 = $(pmsnare_la_SOURCES)
+DIST_SOURCES = $(pmsnare_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmsnare.la
+pmsnare_la_SOURCES = pmsnare.c
+pmsnare_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmsnare_la_LDFLAGS = -module -avoid-version
+pmsnare_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu contrib/pmsnare/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/pmsnare/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmsnare.la: $(pmsnare_la_OBJECTS) $(pmsnare_la_DEPENDENCIES) $(EXTRA_pmsnare_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmsnare_la_LINK) -rpath $(pkglibdir) $(pmsnare_la_OBJECTS) $(pmsnare_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmsnare_la-pmsnare.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmsnare_la-pmsnare.lo: pmsnare.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmsnare_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmsnare_la-pmsnare.lo -MD -MP -MF $(DEPDIR)/pmsnare_la-pmsnare.Tpo -c -o pmsnare_la-pmsnare.lo `test -f 'pmsnare.c' || echo '$(srcdir)/'`pmsnare.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmsnare_la-pmsnare.Tpo $(DEPDIR)/pmsnare_la-pmsnare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmsnare.c' object='pmsnare_la-pmsnare.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) $(pmsnare_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmsnare_la-pmsnare.lo `test -f 'pmsnare.c' || echo '$(srcdir)/'`pmsnare.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmsnare_la-pmsnare.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmsnare_la-pmsnare.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/contrib/pmsnare/pmsnare.c b/contrib/pmsnare/pmsnare.c
new file mode 100644
index 0000000..22f17f2
--- /dev/null
+++ b/contrib/pmsnare/pmsnare.c
@@ -0,0 +1,444 @@
+/* pmsnare.c
+ *
+ * this detects logs sent by Snare and cleans them up so that they can be processed by the normal parser
+ *
+ * there are two variations of this, if the client is set to 'syslog' mode it sends
+ *
+ * <pri>timestamp<sp>hostname<sp>tag<tab>otherstuff
+ *
+ * if the client is not set to syslog it sends
+ *
+ * hostname<tab>tag<tab>otherstuff
+ *
+ * The tabs can be represented in different ways. This module will auto-detect the tab representation based on
+ * the global config settings, but they can be overridden for each instance in the config file if needed.
+ *
+ * ToDo, take advantage of items in the message itself to set more friendly information
+ * where the normal parser will find it by re-writing more of the message
+ *
+ * Interesting information includes:
+ *
+ * in the case of windows snare messages:
+ * the system hostname is field 12
+ * the severity is field 3 (criticality ranging form 0 to 4)
+ * the source of the log is field 4 and may be able to be mapped to facility
+ *
+ *
+ * created 2010-12-13 by David Lang based on pmlastmsg
+ * Modified 2017-05-29 by Shane Lawrence.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.snare")
+MODULE_CNFNAME("pmsnare")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+/* Keep a list of parser instances so we can apply global settings after config is loaded. */
+typedef struct modInstances_s {
+ instanceConf_t *root;
+ instanceConf_t *tail;
+} modInstances_t;
+static modInstances_t *modInstances = NULL;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *modConf = NULL;
+
+/* Per-instance config settings. */
+static struct cnfparamdescr parserpdescr[] = {
+ { "parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0 },
+ { "parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0 },
+ { "parser.escapecontrolcharactertab", eCmdHdlrBinary, 0},
+ { "parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk parserpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+};
+struct instanceConf_s {
+ int bEscapeCCOnRcv;
+ int bEscapeTab;
+ int bParserEscapeCCCStyle;
+ uchar cCCEscapeChar;
+ int tabLength;
+ char tabRepresentation[5];
+ struct instanceConf_s *next;
+};
+
+/* Creates the instance and adds it to the list of instances. */
+static rsRetVal createInstance(instanceConf_t **pinst) {
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ *pinst = inst;
+
+ /* Add to list of instances. */
+ if(modInstances == NULL) {
+ CHKmalloc(modInstances = malloc(sizeof(modInstances_t)));
+ modInstances->tail = modInstances->root = NULL;
+ }
+ if (modInstances->tail == NULL) {
+ modInstances->tail = modInstances->root = inst;
+ } else {
+ modInstances->tail->next = inst;
+ modInstances->tail = inst;
+ }
+
+ finalize_it:
+ RETiRet;
+}
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewParserInst
+ DBGPRINTF("newParserInst (pmsnare)\n");
+ inst = NULL;
+ CHKiRet(createInstance(&inst));
+
+ /* Mark these as unset so we know if they should be overridden later. */
+ inst->bEscapeCCOnRcv = -1;
+ inst->bEscapeTab = -1;
+ inst->bParserEscapeCCCStyle = -1;
+ inst->cCCEscapeChar = '\0';
+
+ /* If using the old config, just use global settings for each instance. */
+ if (lst == NULL)
+ FINALIZE;
+
+ /* If using the new config, process module settings for this instance. */
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("pmsnare: parser param blk:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) {
+ inst->bEscapeCCOnRcv = pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharactertab")) {
+ inst->bEscapeTab = pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) {
+ inst->bParserEscapeCCCStyle = pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "parser.controlcharacterescapeprefix")) {
+ inst->cCCEscapeChar = (uchar) *es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("pmsnare: program error, non-handled param '%s'\n", parserpblk.descr[i].name);
+ }
+ }
+
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ if(iRet != RS_RET_OK)
+ free(inst);
+ENDnewParserInst
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ dbgprintf("pmsnare: free parser instance %p\n", pInst);
+ENDfreeParserInst
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+/* Interface with the global config. */
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ modConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ /* Could use module-globals here, but not global globals. */
+ (void) lst;
+ENDsetModCnf
+
+BEGINendCnfLoad
+ instanceConf_t *inst;
+CODESTARTendCnfLoad
+ dbgprintf("pmsnare: Begin endCnfLoad\n");
+ /* Loop through each parser instance and apply global settings to any option that hasn't been overridden.
+ * This can't be done any earlier because the config wasn't fully loaded until now. */
+ for(inst = modInstances->root; inst != NULL; inst = inst->next) {
+ if(inst->bEscapeCCOnRcv == -1)
+ inst->bEscapeCCOnRcv = glbl.GetParserEscapeControlCharactersOnReceive(modConf->pConf);
+ if(inst->bEscapeTab == -1)
+ inst->bEscapeTab = glbl.GetParserEscapeControlCharacterTab(modConf->pConf);
+ if(inst->bParserEscapeCCCStyle == -1)
+ inst->bParserEscapeCCCStyle = glbl.GetParserEscapeControlCharactersCStyle(modConf->pConf);
+ if(inst->cCCEscapeChar == '\0')
+ inst->cCCEscapeChar = glbl.GetParserControlCharacterEscapePrefix(modConf->pConf);
+
+ /* Determine tab representation. Possible options:
+ * "#011" escape on, escapetabs on, no change to prefix (default)
+ * "?011" prefix changed in config
+ * "\\t" C style
+ * '\t' escape turned off
+ */
+ if (inst->bEscapeCCOnRcv && inst->bEscapeTab) {
+ if (inst->bParserEscapeCCCStyle) {
+ strncpy(inst->tabRepresentation, "\\t", 5);
+ } else {
+ strncpy(inst->tabRepresentation, "#011", 5);
+ inst->tabRepresentation[0] = inst->cCCEscapeChar;
+ }
+ } else {
+ strncpy(inst->tabRepresentation, "\t", 5);
+ }
+ inst->tabLength=strlen(inst->tabRepresentation);
+ /* TODO: This debug message would be more useful if it told which Snare instance! */
+ dbgprintf("pmsnare: Snare parser will treat '%s' as tab.\n", inst->tabRepresentation);
+ }
+
+ assert(pModConf == modConf);
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = modInstances->root ; inst != NULL ; ) {
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ free(modInstances);
+ENDfreeCnf
+
+BEGINparse2
+ uchar *p2parse;
+ int lenMsg;
+ int snaremessage; /* 0 means not a snare message, otherwise it's the index of the tab after the tag */
+
+CODESTARTparse2
+ dbgprintf("Message will now be parsed by fix Snare parser.\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+
+ /* check if this message is of the type we handle in this (very limited) parser
+ *
+ * - Find out if the first separator is a tab.
+ * - If it is, see if the second word is one of our expected tags.
+ * - If so, flag as Snare and replace the first tab with space so that
+ * hostname and syslog tag are going to be parsed properly
+ * - Else not a snare message, abort.
+ * - Else assume valid 3164 timestamp, move over to the syslog tag.
+ * - See if syslog header is followed by tab and one of our expected tags.
+ * - If so, flag as Snare.
+ * - See if either type flagged as Snare.
+ * - If so, replace the tab with a space so that it will be parsed properly.
+ */
+
+ snaremessage=0;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* point to start of text, after PRI */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI;
+ dbgprintf("pmsnare: msg to look at: [%d]'%s'\n", lenMsg, p2parse);
+ if((unsigned) lenMsg < 30) {
+ /* too short, can not be "our" message */
+ dbgprintf("pmsnare: Message is too short to be Snare!\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* Find the first separator and check if it's a tab. */
+ while(lenMsg && *p2parse != ' ' && *p2parse != '\t' && *p2parse != pInst->tabRepresentation[0]) {
+ --lenMsg;
+ ++p2parse;
+ }
+ if ((lenMsg > pInst->tabLength) && (strncasecmp((char *)p2parse, pInst->tabRepresentation,
+ pInst->tabLength) == 0)) {
+ dbgprintf("pmsnare: tab separated message\n");
+ dbgprintf("pmsnare: tab [%d]'%s' msg at the first separator: [%d]'%s'\n",
+ pInst->tabLength, pInst->tabRepresentation, lenMsg, p2parse);
+
+ /* Look for the Snare tag. */
+ if(strncasecmp((char*)(p2parse + pInst->tabLength), "MSWinEventLog", 13) == 0) {
+ dbgprintf("Found a non-syslog Windows Snare message.\n");
+ snaremessage = p2parse - pMsg->pszRawMsg + pInst->tabLength + 13;
+ }
+ else if(strncasecmp((char*) (p2parse + pInst->tabLength), "LinuxKAudit", 11) == 0) {
+ dbgprintf("Found a non-syslog Linux Snare message.\n");
+ snaremessage = p2parse - pMsg->pszRawMsg + pInst->tabLength + 11;
+ } else {
+ /* Tab-separated but no Snare tag-> can't be Snare! */
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* This is a non-syslog Snare message. Example:
+ * other.lab.home MSWinEventLog 1 Security 606129 Wed May 17 02:25:10 2017
+ */
+
+ /* Remove the tab between the hostname and Snare tag. */
+ *p2parse = ' ';
+ p2parse++;
+ lenMsg--;
+ lenMsg -= (pInst->tabLength-1); /* size of tab goes from tabLength to 1, so shorten
+ the message by the difference */
+ memmove(p2parse, p2parse+(pInst->tabLength-1), lenMsg);
+ /* move the message portion up to overwrite the tab */
+ *(p2parse + lenMsg) = '\0';
+ pMsg->iLenRawMsg -= (pInst->tabLength-1);
+ pMsg->iLenMSG -= (pInst->tabLength-1);
+ snaremessage -= (pInst->tabLength-1);
+ } else {
+ /* The first separator is not a tab. Look for a syslog Snare message. Example:
+ * <14>May 17 02:25:10 syslog.lab.home MSWinEventLog 1 Security 606129
+ Wed May 17 02:25:10 2017
+ */
+
+ /* go back to the beginning of the message */
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI;
+
+ /* skip over timestamp and space (15 chars + space). */
+ lenMsg -=16;
+ p2parse +=16;
+ /* skip over what should be the hostname and space */
+ while(lenMsg && *p2parse != ' ') {
+ --lenMsg;
+ ++p2parse;
+ }
+ if (lenMsg){
+ --lenMsg;
+ ++p2parse;
+ }
+ dbgprintf("pmsnare: tab [%d]'%s' msg after the timestamp and hostname: [%d]'%s'\n",
+ pInst->tabLength,pInst->tabRepresentation,lenMsg, p2parse);
+
+ /* Look for the Snare tag. */
+ if(lenMsg > 13 && strncasecmp((char*) p2parse, "MSWinEventLog", 13) == 0) {
+ dbgprintf("Found a syslog Windows Snare message.\n");
+ snaremessage = p2parse - pMsg->pszRawMsg + 13;
+ }
+ else if(lenMsg > 11 && strncasecmp((char*) p2parse, "LinuxKAudit", 11) == 0) {
+ dbgprintf("pmsnare: Found a syslog Linux Snare message.\n");
+ snaremessage = p2parse - pMsg->pszRawMsg + 11;
+ }
+ }
+
+ if(snaremessage) {
+ /* Skip to the end of the tag. */
+ p2parse = pMsg->pszRawMsg + snaremessage;
+ lenMsg = pMsg->iLenRawMsg - snaremessage;
+
+ /* Remove the tab after the tag. */
+ *p2parse = ' ';
+ p2parse++;
+ lenMsg--;
+ lenMsg -= (pInst->tabLength-1); /* size of tab goes from tabLength to 1, so shorten
+ the message by the difference */
+ memmove(p2parse, p2parse+(pInst->tabLength-1), lenMsg);
+ /* move the message portion up to overwrite the tab */
+ *(p2parse + lenMsg) = '\0';
+ pMsg->iLenRawMsg -= (pInst->tabLength-1);
+ pMsg->iLenMSG -= (pInst->tabLength-1);
+
+ DBGPRINTF("pmsnare: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI);
+ }
+
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+
+finalize_it:
+ENDparse2
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_MOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("snare parser init called, compiled with version %s\n", VERSION);
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..65cbf70
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2018 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 <https://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 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/devtools/prep-mysql-db.sh b/devtools/prep-mysql-db.sh
new file mode 100755
index 0000000..5f94a3d
--- /dev/null
+++ b/devtools/prep-mysql-db.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# this script prepares a mysql instance for use by the rsyslog testbench
+
+mysql -u root -e "CREATE USER 'rsyslog'@'localhost' IDENTIFIED BY 'testbench';"
+mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'rsyslog'@'localhost'; FLUSH PRIVILEGES;"
diff --git a/devtools/prepare_clickhouse.sh b/devtools/prepare_clickhouse.sh
new file mode 100755
index 0000000..13add08
--- /dev/null
+++ b/devtools/prepare_clickhouse.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# this script prepares a clickhouse instance for use by the rsyslog testbench
+
+
+clickhouse-client --query="CREATE DATABASE rsyslog"
+echo clickouse create database RETURN STATE: $?
+
+# At the moment only the database is created for preperation.
+# Every test creates a table for itself and drops it afterwards.
+# This could look something like this:
+
+#clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.test ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+#clickhouse-client --query="DROP TABLE rsyslog.test"
diff --git a/dirty.h b/dirty.h
new file mode 100644
index 0000000..25d7571
--- /dev/null
+++ b/dirty.h
@@ -0,0 +1,49 @@
+/* This file is an aid to support non-modular object accesses
+ * while we do not have fully modularized everything. Once this is
+ * done, this file can (and should) be deleted. Presence of it
+ * also somewhat indicates that the runtime library is not really
+ * yet a runtime library, because it depends on some functionality
+ * residing somewhere else.
+ *
+ * Copyright 2007-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DIRTY_H_INCLUDED
+#define DIRTY_H_INCLUDED 1
+
+rsRetVal __attribute__((deprecated)) multiSubmitMsg(multi_submit_t *pMultiSub);
+rsRetVal ATTR_NONNULL() multiSubmitMsg2(multi_submit_t *const pMultiSub); /* friends only! */
+rsRetVal submitMsg2(smsg_t *pMsg);
+rsRetVal __attribute__((deprecated)) submitMsg(smsg_t *pMsg);
+rsRetVal multiSubmitFlush(multi_submit_t *pMultiSub);
+rsRetVal logmsgInternal(const int iErr, const syslog_pri_t pri, const uchar *const msg, int flags);
+rsRetVal __attribute__((deprecated)) parseAndSubmitMessage(const uchar *hname,
+ const uchar *hnameIP, const uchar *msg, const int len,
+ const int flags, const flowControl_t flowCtlType,
+ prop_t *pInputName, const struct syslogTime *stTime,
+ const time_t ttGenTime, ruleset_t *pRuleset);
+rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName, struct nvlst *lst);
+rsRetVal startMainQueue(rsconf_t *cnf, qqueue_t *pQueue);
+int get_bHadHUP(void);
+
+extern int MarkInterval;
+#define CONF_VERIFY_PARTIAL_CONF 0x02 /* bit: partial configuration to be checked */
+extern int iConfigVerify; /* is this just a config verify run? */
+extern int bHaveMainQueue;
+
+#endif /* #ifndef DIRTY_H_INCLUDED */
diff --git a/grammar/Makefile.am b/grammar/Makefile.am
new file mode 100644
index 0000000..17bc634
--- /dev/null
+++ b/grammar/Makefile.am
@@ -0,0 +1,20 @@
+BUILT_SOURCES = grammar.h
+CLEANFILES = grammar.h grammar.c lexer.c
+AM_YFLAGS = -d
+noinst_LTLIBRARIES = libgrammar.la
+#bin_PROGRAMS = testdriver # TODO: make this conditional
+
+libgrammar_la_SOURCES = \
+ grammar.y \
+ lexer.l \
+ rainerscript.c \
+ rainerscript.h \
+ parserif.h \
+ grammar.h
+libgrammar_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+libgrammar_la_LIBADD =
+
+#testdriver_SOURCES = testdriver.c libgrammar.la
+#testdriver_CPPFLAGS = $(RSRT_CFLAGS)
+#testdriver_LDADD = libgrammar.la
+#testdriver_LDFLAGS = -lestr
diff --git a/grammar/Makefile.in b/grammar/Makefile.in
new file mode 100644
index 0000000..7e452f3
--- /dev/null
+++ b/grammar/Makefile.in
@@ -0,0 +1,810 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = grammar
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libgrammar_la_DEPENDENCIES =
+am_libgrammar_la_OBJECTS = libgrammar_la-grammar.lo \
+ libgrammar_la-lexer.lo libgrammar_la-rainerscript.lo
+libgrammar_la_OBJECTS = $(am_libgrammar_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 =
+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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/libgrammar_la-grammar.Plo \
+ ./$(DEPDIR)/libgrammar_la-lexer.Plo \
+ ./$(DEPDIR)/libgrammar_la-rainerscript.Plo
+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 =
+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)/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 = $(libgrammar_la_SOURCES)
+DIST_SOURCES = $(libgrammar_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
+ $(top_srcdir)/ylwrap grammar.c grammar.h lexer.c
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+BUILT_SOURCES = grammar.h
+CLEANFILES = grammar.h grammar.c lexer.c
+AM_YFLAGS = -d
+noinst_LTLIBRARIES = libgrammar.la
+#bin_PROGRAMS = testdriver # TODO: make this conditional
+libgrammar_la_SOURCES = \
+ grammar.y \
+ lexer.l \
+ rainerscript.c \
+ rainerscript.h \
+ parserif.h \
+ grammar.h
+
+libgrammar_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+libgrammar_la_LIBADD =
+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) --gnu grammar/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu grammar/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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}; \
+ }
+grammar.h: grammar.c
+ @if test ! -f $@; then rm -f grammar.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) grammar.c; else :; fi
+
+libgrammar.la: $(libgrammar_la_OBJECTS) $(libgrammar_la_DEPENDENCIES) $(EXTRA_libgrammar_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libgrammar_la_OBJECTS) $(libgrammar_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgrammar_la-grammar.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgrammar_la-lexer.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgrammar_la-rainerscript.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+libgrammar_la-grammar.lo: grammar.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgrammar_la-grammar.lo -MD -MP -MF $(DEPDIR)/libgrammar_la-grammar.Tpo -c -o libgrammar_la-grammar.lo `test -f 'grammar.c' || echo '$(srcdir)/'`grammar.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgrammar_la-grammar.Tpo $(DEPDIR)/libgrammar_la-grammar.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='grammar.c' object='libgrammar_la-grammar.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) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgrammar_la-grammar.lo `test -f 'grammar.c' || echo '$(srcdir)/'`grammar.c
+
+libgrammar_la-lexer.lo: lexer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgrammar_la-lexer.lo -MD -MP -MF $(DEPDIR)/libgrammar_la-lexer.Tpo -c -o libgrammar_la-lexer.lo `test -f 'lexer.c' || echo '$(srcdir)/'`lexer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgrammar_la-lexer.Tpo $(DEPDIR)/libgrammar_la-lexer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lexer.c' object='libgrammar_la-lexer.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) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgrammar_la-lexer.lo `test -f 'lexer.c' || echo '$(srcdir)/'`lexer.c
+
+libgrammar_la-rainerscript.lo: rainerscript.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgrammar_la-rainerscript.lo -MD -MP -MF $(DEPDIR)/libgrammar_la-rainerscript.Tpo -c -o libgrammar_la-rainerscript.lo `test -f 'rainerscript.c' || echo '$(srcdir)/'`rainerscript.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgrammar_la-rainerscript.Tpo $(DEPDIR)/libgrammar_la-rainerscript.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rainerscript.c' object='libgrammar_la-rainerscript.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) $(libgrammar_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgrammar_la-rainerscript.lo `test -f 'rainerscript.c' || echo '$(srcdir)/'`rainerscript.c
+
+.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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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:
+ -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."
+ -rm -f grammar.c
+ -rm -f grammar.h
+ -rm -f lexer.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 ./$(DEPDIR)/libgrammar_la-grammar.Plo
+ -rm -f ./$(DEPDIR)/libgrammar_la-lexer.Plo
+ -rm -f ./$(DEPDIR)/libgrammar_la-rainerscript.Plo
+ -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 ./$(DEPDIR)/libgrammar_la-grammar.Plo
+ -rm -f ./$(DEPDIR)/libgrammar_la-lexer.Plo
+ -rm -f ./$(DEPDIR)/libgrammar_la-rainerscript.Plo
+ -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 am--depfiles 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
+
+.PRECIOUS: Makefile
+
+
+#testdriver_SOURCES = testdriver.c libgrammar.la
+#testdriver_CPPFLAGS = $(RSRT_CFLAGS)
+#testdriver_LDADD = libgrammar.la
+#testdriver_LDFLAGS = -lestr
+
+# 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/grammar/grammar.c b/grammar/grammar.c
new file mode 100644
index 0000000..0c4f4a6
--- /dev/null
+++ b/grammar/grammar.c
@@ -0,0 +1,2342 @@
+/* A Bison parser, made by GNU Bison 3.5.1. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 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. */
+
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.5.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* First part of user prologue. */
+#line 29 "grammar.y"
+
+#define IN_GRAMMAR_Y /* tell parserif.h not to redefine things! */
+
+#include "config.h"
+#include <stdio.h>
+#include <libestr.h>
+#include "rainerscript.h"
+#include "parserif.h"
+#define YYDEBUG 1
+extern int yylineno;
+extern char *yytext;
+
+/* keep compile rule clean of errors */
+extern int yylex(void);
+extern int yyerror(const char*);
+
+#line 87 "grammar.c"
+
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
+# ifndef YY_NULLPTR
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# else
+# define YY_NULLPTR ((void*)0)
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Use api.header.include to #include this header
+ instead of duplicating it here. */
+#ifndef YY_YY_GRAMMAR_H_INCLUDED
+# define YY_YY_GRAMMAR_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ NAME = 258,
+ FUNC = 259,
+ BEGINOBJ = 260,
+ ENDOBJ = 261,
+ BEGIN_INCLUDE = 262,
+ BEGIN_ACTION = 263,
+ BEGIN_PROPERTY = 264,
+ BEGIN_CONSTANT = 265,
+ BEGIN_TPL = 266,
+ BEGIN_RULESET = 267,
+ STOP = 268,
+ SET = 269,
+ RESET = 270,
+ UNSET = 271,
+ CONTINUE = 272,
+ EXISTS = 273,
+ CALL = 274,
+ CALL_INDIRECT = 275,
+ LEGACY_ACTION = 276,
+ LEGACY_RULESET = 277,
+ PRIFILT = 278,
+ PROPFILT = 279,
+ BSD_TAG_SELECTOR = 280,
+ BSD_HOST_SELECTOR = 281,
+ RELOAD_LOOKUP_TABLE_PROCEDURE = 282,
+ IF = 283,
+ THEN = 284,
+ ELSE = 285,
+ FOREACH = 286,
+ ITERATOR_ASSIGNMENT = 287,
+ DO = 288,
+ OR = 289,
+ AND = 290,
+ NOT = 291,
+ VAR = 292,
+ STRING = 293,
+ NUMBER = 294,
+ CMP_EQ = 295,
+ CMP_NE = 296,
+ CMP_LE = 297,
+ CMP_GE = 298,
+ CMP_LT = 299,
+ CMP_GT = 300,
+ CMP_CONTAINS = 301,
+ CMP_CONTAINSI = 302,
+ CMP_STARTSWITH = 303,
+ CMP_STARTSWITHI = 304,
+ UMINUS = 305
+ };
+#endif
+/* Tokens. */
+#define NAME 258
+#define FUNC 259
+#define BEGINOBJ 260
+#define ENDOBJ 261
+#define BEGIN_INCLUDE 262
+#define BEGIN_ACTION 263
+#define BEGIN_PROPERTY 264
+#define BEGIN_CONSTANT 265
+#define BEGIN_TPL 266
+#define BEGIN_RULESET 267
+#define STOP 268
+#define SET 269
+#define RESET 270
+#define UNSET 271
+#define CONTINUE 272
+#define EXISTS 273
+#define CALL 274
+#define CALL_INDIRECT 275
+#define LEGACY_ACTION 276
+#define LEGACY_RULESET 277
+#define PRIFILT 278
+#define PROPFILT 279
+#define BSD_TAG_SELECTOR 280
+#define BSD_HOST_SELECTOR 281
+#define RELOAD_LOOKUP_TABLE_PROCEDURE 282
+#define IF 283
+#define THEN 284
+#define ELSE 285
+#define FOREACH 286
+#define ITERATOR_ASSIGNMENT 287
+#define DO 288
+#define OR 289
+#define AND 290
+#define NOT 291
+#define VAR 292
+#define STRING 293
+#define NUMBER 294
+#define CMP_EQ 295
+#define CMP_NE 296
+#define CMP_LE 297
+#define CMP_GE 298
+#define CMP_LT 299
+#define CMP_GT 300
+#define CMP_CONTAINS 301
+#define CMP_CONTAINSI 302
+#define CMP_STARTSWITH 303
+#define CMP_STARTSWITHI 304
+#define UMINUS 305
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+union YYSTYPE
+{
+#line 46 "grammar.y"
+
+ char *s;
+ long long n;
+ es_str_t *estr;
+ enum cnfobjType objType;
+ struct cnfobj *obj;
+ struct cnfstmt *stmt;
+ struct nvlst *nvlst;
+ struct objlst *objlst;
+ struct cnfexpr *expr;
+ struct cnfarray *arr;
+ struct cnffunc *func;
+ struct cnffuncexists *exists;
+ struct cnffparamlst *fparams;
+ struct cnfitr *itr;
+
+#line 256 "grammar.c"
+
+};
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE yylval;
+
+int yyparse (void);
+
+#endif /* !YY_YY_GRAMMAR_H_INCLUDED */
+
+
+
+#ifdef short
+# undef short
+#endif
+
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
+#endif
+
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
+#else
+typedef short yytype_int16;
+#endif
+
+#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST8_TYPE__ yytype_uint8;
+#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
+#else
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_uint8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
+
+#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_PURE
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# 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__ && ! defined __ICC && 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 __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
+
+#define YY_ASSERT(E) ((void) (0 && (E)))
+
+#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
+{
+ yy_state_t yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (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 \
+ { \
+ YYPTRDIFF_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*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, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYPTRDIFF_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 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 507
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 66
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 20
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 81
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 165
+
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 305
+
+
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex. */
+static const yytype_int8 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, 55, 52, 2,
+ 61, 62, 53, 50, 63, 51, 2, 54, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 60,
+ 2, 59, 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, 64, 2, 65, 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, 57, 2, 58, 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, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 56
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
+{
+ 0, 135, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 148, 152, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 173, 177,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 193, 194, 195, 196, 197, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+ 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+ 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+ 233, 234
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* 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", "NAME", "FUNC", "BEGINOBJ", "ENDOBJ",
+ "BEGIN_INCLUDE", "BEGIN_ACTION", "BEGIN_PROPERTY", "BEGIN_CONSTANT",
+ "BEGIN_TPL", "BEGIN_RULESET", "STOP", "SET", "RESET", "UNSET",
+ "CONTINUE", "EXISTS", "CALL", "CALL_INDIRECT", "LEGACY_ACTION",
+ "LEGACY_RULESET", "PRIFILT", "PROPFILT", "BSD_TAG_SELECTOR",
+ "BSD_HOST_SELECTOR", "RELOAD_LOOKUP_TABLE_PROCEDURE", "IF", "THEN",
+ "ELSE", "FOREACH", "ITERATOR_ASSIGNMENT", "DO", "OR", "AND", "NOT",
+ "VAR", "STRING", "NUMBER", "CMP_EQ", "CMP_NE", "CMP_LE", "CMP_GE",
+ "CMP_LT", "CMP_GT", "CMP_CONTAINS", "CMP_CONTAINSI", "CMP_STARTSWITH",
+ "CMP_STARTSWITHI", "'+'", "'-'", "'&'", "'*'", "'/'", "'%'", "UMINUS",
+ "'{'", "'}'", "'='", "';'", "'('", "')'", "','", "'['", "']'", "$accept",
+ "conf", "include", "obj", "propconst", "property", "constant", "nvlst",
+ "nv", "value", "script", "stmt", "block", "actlst", "s_act", "expr",
+ "fparams", "array", "iterator_decl", "arrayelt", 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_int16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 43, 45, 38, 42, 47, 37, 305, 123, 125, 61,
+ 59, 40, 41, 44, 91, 93
+};
+# endif
+
+#define YYPACT_NINF (-48)
+
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
+
+#define YYTABLE_NINF (-20)
+
+#define yytable_value_is_error(Yyn) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ -48, 273, -48, 7, -48, -48, -48, -48, -48, -26,
+ -17, 9, -48, 30, 103, -48, -48, 234, 234, -48,
+ -48, -27, 103, -12, -48, -48, -48, 2, -48, 12,
+ 13, 35, 36, 37, 1, 6, -5, -48, 0, 5,
+ 103, -48, -48, -48, 103, 103, 19, 338, -48, -48,
+ 460, -48, -48, -48, 103, 365, 26, 34, 4, 31,
+ -48, -48, -48, -48, 32, 38, 103, 103, -48, 95,
+ 54, -48, -48, 292, -48, -1, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, -48, 155, -48, 268, 39, 234,
+ 60, 234, -48, -29, -48, 180, 387, 409, -48, 40,
+ 43, -48, 55, -48, 452, 452, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -3, -3, -3, -48,
+ -48, -48, -48, -48, 103, -48, 64, 103, -48, -48,
+ -48, -48, -2, -48, 209, -48, -48, -48, -48, -48,
+ -48, 234, 315, -48, -48, -48, -48, -48, -48, -48,
+ -48, 41, 42, -48, -48
+};
+
+ /* 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_int8 yydefact[] =
+{
+ 2, 0, 1, 37, 19, 19, 19, 19, 44, 0,
+ 0, 0, 47, 0, 0, 43, 5, 0, 0, 6,
+ 7, 0, 0, 0, 36, 3, 4, 26, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 45, 0, 0,
+ 0, 74, 73, 72, 0, 0, 0, 0, 75, 37,
+ 0, 38, 33, 34, 0, 0, 0, 0, 0, 0,
+ 9, 20, 8, 42, 10, 0, 0, 0, 32, 0,
+ 0, 50, 68, 0, 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 46, 0, 24, 76, 0, 0,
+ 0, 0, 41, 0, 14, 0, 0, 0, 70, 0,
+ 0, 67, 0, 78, 49, 48, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 62, 63, 61, 64,
+ 65, 66, 39, 25, 0, 35, 27, 0, 29, 22,
+ 21, 23, 0, 13, 0, 31, 30, 71, 69, 81,
+ 77, 0, 0, 19, 19, 11, 15, 16, 12, 28,
+ 79, 0, 0, 17, 18
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -48, -48, -48, -48, -48, -48, -48, -4, -48, -48,
+ -9, 3, -13, -48, 45, -8, -47, -6, -48, -48
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 24, 25, 142, 156, 157, 29, 61, 140,
+ 95, 51, 52, 27, 28, 97, 98, 48, 57, 75
+};
+
+ /* 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_int16 yytable[] =
+{
+ 30, 31, 32, 33, 26, 53, 47, 153, 154, 139,
+ -19, 34, 5, -19, 55, 59, 59, 8, 60, 62,
+ 35, 12, 109, 13, 14, 15, 88, 89, 90, 91,
+ 92, 93, 71, 37, 54, 46, 72, 73, 59, 59,
+ 59, 63, 64, 65, 59, 59, 36, 163, 164, 56,
+ 91, 92, 93, 96, 58, 68, 155, 74, 106, 107,
+ 66, 69, 112, 100, 113, 67, 70, 101, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 136, 150, 138, 104,
+ 103, 110, 137, 149, 151, 105, 144, 141, 133, 38,
+ 0, 135, 147, 102, 0, 148, 0, 38, 96, 0,
+ 0, 0, 0, 39, 0, 0, 0, 0, 0, 0,
+ 0, 39, 0, 0, 0, 0, 0, 0, 0, 152,
+ 0, 40, 41, 42, 43, 0, 0, 0, 159, 40,
+ 41, 42, 43, 0, 0, 0, 44, 133, 0, 161,
+ 162, 0, 0, 0, 44, 0, 45, 108, 0, 46,
+ 49, 0, 4, 5, 45, 0, 0, 46, 8, 9,
+ 10, 11, 12, 0, 13, 14, 15, 0, 17, 18,
+ 0, 0, 21, 22, 0, 49, 23, 4, 5, 0,
+ 0, 0, 0, 8, 9, 10, 11, 12, 0, 13,
+ 14, 15, 0, 17, 18, 0, 0, 21, 22, 0,
+ 0, 23, 0, 132, 49, 0, 4, 5, 0, 0,
+ 0, 0, 8, 9, 10, 11, 12, 0, 13, 14,
+ 15, 0, 17, 18, 0, 0, 21, 22, 143, 49,
+ 23, 4, 5, 0, 0, 0, 0, 8, 9, 10,
+ 11, 12, 0, 13, 14, 15, 0, 17, 18, 0,
+ 0, 21, 22, 0, 0, 23, 0, 158, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 3, 0,
+ 4, 5, 0, 0, 6, 7, 8, 9, 10, 11,
+ 12, 50, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 76, 77, 23, 0, 0, 0, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 0, 0, 76, 77, 0, 0,
+ 0, 134, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 0, 76,
+ 77, 0, 0, 0, 111, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 0, 76, 77, 0, 0, 0, 160, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 99, 0, 0, 0, 94, 76,
+ 77, 0, 0, 0, 0, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 76, 77, 0, 0, 0, 0, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 76, 77, 0, 0, 145, 0, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 49, 0, 4, 5, 146,
+ 0, 0, 0, 8, 9, 10, 11, 12, 0, 13,
+ 14, 15, 0, 17, 18, 0, 0, 21, 22, 0,
+ 0, 23, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 4, 5, 6, 7, 1, 18, 14, 9, 10, 38,
+ 3, 37, 8, 6, 22, 3, 3, 13, 6, 6,
+ 37, 17, 69, 19, 20, 21, 50, 51, 52, 53,
+ 54, 55, 40, 3, 61, 64, 44, 45, 3, 3,
+ 3, 6, 6, 6, 3, 3, 37, 6, 6, 61,
+ 53, 54, 55, 50, 52, 60, 58, 38, 66, 67,
+ 59, 61, 63, 37, 65, 59, 61, 33, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 99, 134, 101, 57,
+ 59, 37, 32, 38, 30, 57, 105, 103, 95, 4,
+ -1, 62, 62, 58, -1, 62, -1, 4, 105, -1,
+ -1, -1, -1, 18, -1, -1, -1, -1, -1, -1,
+ -1, 18, -1, -1, -1, -1, -1, -1, -1, 137,
+ -1, 36, 37, 38, 39, -1, -1, -1, 151, 36,
+ 37, 38, 39, -1, -1, -1, 51, 144, -1, 153,
+ 154, -1, -1, -1, 51, -1, 61, 62, -1, 64,
+ 5, -1, 7, 8, 61, -1, -1, 64, 13, 14,
+ 15, 16, 17, -1, 19, 20, 21, -1, 23, 24,
+ -1, -1, 27, 28, -1, 5, 31, 7, 8, -1,
+ -1, -1, -1, 13, 14, 15, 16, 17, -1, 19,
+ 20, 21, -1, 23, 24, -1, -1, 27, 28, -1,
+ -1, 31, -1, 58, 5, -1, 7, 8, -1, -1,
+ -1, -1, 13, 14, 15, 16, 17, -1, 19, 20,
+ 21, -1, 23, 24, -1, -1, 27, 28, 58, 5,
+ 31, 7, 8, -1, -1, -1, -1, 13, 14, 15,
+ 16, 17, -1, 19, 20, 21, -1, 23, 24, -1,
+ -1, 27, 28, -1, -1, 31, -1, 58, -1, -1,
+ -1, -1, -1, 0, -1, -1, -1, -1, 5, -1,
+ 7, 8, -1, -1, 11, 12, 13, 14, 15, 16,
+ 17, 57, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 34, 35, 31, -1, -1, -1, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, -1, -1, 34, 35, -1, -1,
+ -1, 63, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, -1, 34,
+ 35, -1, -1, -1, 62, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, -1, 34, 35, -1, -1, -1, 62, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 29, -1, -1, -1, 60, 34,
+ 35, -1, -1, -1, -1, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 34, 35, -1, -1, -1, -1, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 34, 35, -1, -1, 60, -1, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 5, -1, 7, 8, 60,
+ -1, -1, -1, 13, 14, 15, 16, 17, -1, 19,
+ 20, 21, -1, 23, 24, -1, -1, 27, 28, -1,
+ -1, 31, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_int8 yystos[] =
+{
+ 0, 67, 0, 5, 7, 8, 11, 12, 13, 14,
+ 15, 16, 17, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 31, 68, 69, 77, 79, 80, 73,
+ 73, 73, 73, 73, 37, 37, 37, 3, 4, 18,
+ 36, 37, 38, 39, 51, 61, 64, 81, 83, 5,
+ 57, 77, 78, 78, 61, 81, 61, 84, 52, 3,
+ 6, 74, 6, 6, 6, 6, 59, 59, 60, 61,
+ 61, 81, 81, 81, 38, 85, 34, 35, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 60, 76, 77, 81, 82, 29,
+ 37, 33, 80, 59, 57, 57, 81, 81, 62, 82,
+ 37, 62, 63, 65, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 58, 77, 63, 62, 78, 32, 78, 38,
+ 75, 83, 70, 58, 76, 60, 60, 62, 62, 38,
+ 82, 30, 81, 9, 10, 58, 71, 72, 58, 78,
+ 62, 73, 73, 6, 6
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_int8 yyr1[] =
+{
+ 0, 66, 67, 67, 67, 67, 67, 67, 68, 69,
+ 69, 69, 69, 69, 70, 70, 70, 71, 72, 73,
+ 73, 74, 75, 75, 76, 76, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 78, 78,
+ 79, 79, 80, 80, 80, 80, 80, 80, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 82, 82, 83, 84,
+ 85, 85
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_int8 yyr2[] =
+{
+ 0, 2, 0, 2, 2, 2, 2, 2, 3, 3,
+ 3, 6, 6, 5, 0, 2, 2, 3, 3, 0,
+ 2, 3, 1, 1, 1, 2, 1, 4, 6, 4,
+ 5, 5, 3, 2, 2, 4, 1, 1, 1, 3,
+ 1, 3, 3, 1, 1, 2, 3, 1, 3, 3,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 4,
+ 3, 4, 1, 1, 1, 1, 1, 3, 3, 5,
+ 1, 3
+};
+
+
+#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 YYO. |
+`-----------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep)
+{
+ FILE *yyoutput = yyo;
+ YYUSE (yyoutput);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
+# endif
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
+
+static void
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep)
+{
+ YYFPRINTF (yyo, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyo, yytype, yyvaluep);
+ YYFPRINTF (yyo, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yy_state_t *yybottom, yy_state_t *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 (yy_state_t *yyssp, YYSTYPE *yyvsp, int yyrule)
+{
+ int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\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(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
+# else
+/* Return the length of YYSTR. */
+static YYPTRDIFF_T
+yystrlen (const char *yystr)
+{
+ YYPTRDIFF_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 YYPTRDIFF_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYPTRDIFF_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;
+ else
+ goto append;
+
+ append:
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (yyres)
+ return yystpcpy (yyres, yystr) - yyres;
+ else
+ return yystrlen (yystr);
+}
+# 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 (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+ yy_state_t *yyssp, int yytoken)
+{
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat: reported tokens (one for the "unexpected",
+ one per "expected"). */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ /* Cumulated lengths of YYARG. */
+ YYPTRDIFF_T yysize = 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];
+ YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ yysize = yysize0;
+ 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];
+ {
+ YYPTRDIFF_T yysize1
+ = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return 2;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ default: /* Avoid compiler warnings. */
+ 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_
+ }
+
+ {
+ /* Don't count the "%s"s in the final size, but reserve room for
+ the terminator. */
+ YYPTRDIFF_T yysize1 = yysize + (yystrlen (yyformat) - 2 * yycount) + 1;
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return 2;
+ }
+
+ 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)
+{
+ yy_state_fast_t 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. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss;
+ yy_state_t *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYPTRDIFF_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;
+ YYPTRDIFF_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 -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+
+ if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+#else
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
+
+# if defined 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. */
+ yy_state_t *yyss1 = yyss;
+ YYSTYPE *yyvs1 = yyvs;
+
+ /* 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 * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
+ &yystacksize);
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+# else /* defined YYSTACK_RELOCATE */
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yy_state_t *yyss1 = yyss;
+ union yyalloc *yyptr =
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, 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
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
+ 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);
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+ 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 3:
+#line 136 "grammar.y"
+ { cnfDoObj((yyvsp[0].obj)); }
+#line 1615 "grammar.c"
+ break;
+
+ case 4:
+#line 137 "grammar.y"
+ { cnfDoScript((yyvsp[0].stmt)); }
+#line 1621 "grammar.c"
+ break;
+
+ case 5:
+#line 138 "grammar.y"
+ { cnfDoCfsysline((yyvsp[0].s)); }
+#line 1627 "grammar.c"
+ break;
+
+ case 6:
+#line 139 "grammar.y"
+ { cnfDoBSDTag((yyvsp[0].s)); }
+#line 1633 "grammar.c"
+ break;
+
+ case 7:
+#line 140 "grammar.y"
+ { cnfDoBSDHost((yyvsp[0].s)); }
+#line 1639 "grammar.c"
+ break;
+
+ case 8:
+#line 141 "grammar.y"
+ { includeProcessCnf((yyvsp[-1].nvlst)); }
+#line 1645 "grammar.c"
+ break;
+
+ case 9:
+#line 142 "grammar.y"
+ { (yyval.obj) = cnfobjNew((yyvsp[-2].objType), (yyvsp[-1].nvlst)); }
+#line 1651 "grammar.c"
+ break;
+
+ case 10:
+#line 143 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_TPL, (yyvsp[-1].nvlst)); }
+#line 1657 "grammar.c"
+ break;
+
+ case 11:
+#line 145 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_TPL, (yyvsp[-4].nvlst));
+ (yyval.obj)->subobjs = (yyvsp[-1].objlst);
+ }
+#line 1665 "grammar.c"
+ break;
+
+ case 12:
+#line 149 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_RULESET, (yyvsp[-4].nvlst));
+ (yyval.obj)->script = (yyvsp[-1].stmt);
+ }
+#line 1673 "grammar.c"
+ break;
+
+ case 13:
+#line 153 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_RULESET, (yyvsp[-3].nvlst));
+ (yyval.obj)->script = NULL;
+ }
+#line 1681 "grammar.c"
+ break;
+
+ case 14:
+#line 156 "grammar.y"
+ { (yyval.objlst) = NULL; }
+#line 1687 "grammar.c"
+ break;
+
+ case 15:
+#line 157 "grammar.y"
+ { (yyval.objlst) = objlstAdd((yyvsp[-1].objlst), (yyvsp[0].obj)); }
+#line 1693 "grammar.c"
+ break;
+
+ case 16:
+#line 158 "grammar.y"
+ { (yyval.objlst) = objlstAdd((yyvsp[-1].objlst), (yyvsp[0].obj)); }
+#line 1699 "grammar.c"
+ break;
+
+ case 17:
+#line 159 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_PROPERTY, (yyvsp[-1].nvlst)); }
+#line 1705 "grammar.c"
+ break;
+
+ case 18:
+#line 160 "grammar.y"
+ { (yyval.obj) = cnfobjNew(CNFOBJ_CONSTANT, (yyvsp[-1].nvlst)); }
+#line 1711 "grammar.c"
+ break;
+
+ case 19:
+#line 161 "grammar.y"
+ { (yyval.nvlst) = NULL; }
+#line 1717 "grammar.c"
+ break;
+
+ case 20:
+#line 162 "grammar.y"
+ { (yyvsp[0].nvlst)->next = (yyvsp[-1].nvlst); (yyval.nvlst) = (yyvsp[0].nvlst); }
+#line 1723 "grammar.c"
+ break;
+
+ case 21:
+#line 163 "grammar.y"
+ { (yyval.nvlst) = nvlstSetName((yyvsp[0].nvlst), (yyvsp[-2].estr)); }
+#line 1729 "grammar.c"
+ break;
+
+ case 22:
+#line 164 "grammar.y"
+ { (yyval.nvlst) = nvlstNewStr((yyvsp[0].estr)); }
+#line 1735 "grammar.c"
+ break;
+
+ case 23:
+#line 165 "grammar.y"
+ { (yyval.nvlst) = nvlstNewArray((yyvsp[0].arr)); }
+#line 1741 "grammar.c"
+ break;
+
+ case 24:
+#line 166 "grammar.y"
+ { (yyval.stmt) = (yyvsp[0].stmt); }
+#line 1747 "grammar.c"
+ break;
+
+ case 25:
+#line 167 "grammar.y"
+ { (yyval.stmt) = scriptAddStmt((yyvsp[-1].stmt), (yyvsp[0].stmt)); }
+#line 1753 "grammar.c"
+ break;
+
+ case 26:
+#line 168 "grammar.y"
+ { (yyval.stmt) = (yyvsp[0].stmt); }
+#line 1759 "grammar.c"
+ break;
+
+ case 27:
+#line 169 "grammar.y"
+ { (yyval.stmt) = cnfstmtNew(S_IF);
+ (yyval.stmt)->d.s_if.expr = (yyvsp[-2].expr);
+ (yyval.stmt)->d.s_if.t_then = (yyvsp[0].stmt);
+ (yyval.stmt)->d.s_if.t_else = NULL; }
+#line 1768 "grammar.c"
+ break;
+
+ case 28:
+#line 173 "grammar.y"
+ { (yyval.stmt) = cnfstmtNew(S_IF);
+ (yyval.stmt)->d.s_if.expr = (yyvsp[-4].expr);
+ (yyval.stmt)->d.s_if.t_then = (yyvsp[-2].stmt);
+ (yyval.stmt)->d.s_if.t_else = (yyvsp[0].stmt); }
+#line 1777 "grammar.c"
+ break;
+
+ case 29:
+#line 177 "grammar.y"
+ { (yyval.stmt) = cnfstmtNew(S_FOREACH);
+ (yyval.stmt)->d.s_foreach.iter = (yyvsp[-2].itr);
+ (yyval.stmt)->d.s_foreach.body = (yyvsp[0].stmt);}
+#line 1785 "grammar.c"
+ break;
+
+ case 30:
+#line 180 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewSet((yyvsp[-3].s), (yyvsp[-1].expr), 1); }
+#line 1791 "grammar.c"
+ break;
+
+ case 31:
+#line 181 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewSet((yyvsp[-3].s), (yyvsp[-1].expr), 0); }
+#line 1797 "grammar.c"
+ break;
+
+ case 32:
+#line 182 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewUnset((yyvsp[-1].s)); }
+#line 1803 "grammar.c"
+ break;
+
+ case 33:
+#line 183 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewPRIFILT((yyvsp[-1].s), (yyvsp[0].stmt)); }
+#line 1809 "grammar.c"
+ break;
+
+ case 34:
+#line 184 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewPROPFILT((yyvsp[-1].s), (yyvsp[0].stmt)); }
+#line 1815 "grammar.c"
+ break;
+
+ case 35:
+#line 185 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewReloadLookupTable((yyvsp[-1].fparams));}
+#line 1821 "grammar.c"
+ break;
+
+ case 36:
+#line 186 "grammar.y"
+ { (yyval.stmt) = NULL; }
+#line 1827 "grammar.c"
+ break;
+
+ case 37:
+#line 187 "grammar.y"
+ { (yyval.stmt) = NULL; parser_errmsg("declarative object '%s' not permitted in action block [stmt]", yytext);}
+#line 1833 "grammar.c"
+ break;
+
+ case 38:
+#line 188 "grammar.y"
+ { (yyval.stmt) = (yyvsp[0].stmt); }
+#line 1839 "grammar.c"
+ break;
+
+ case 39:
+#line 189 "grammar.y"
+ { (yyval.stmt) = (yyvsp[-1].stmt); }
+#line 1845 "grammar.c"
+ break;
+
+ case 40:
+#line 190 "grammar.y"
+ { (yyval.stmt) = (yyvsp[0].stmt); }
+#line 1851 "grammar.c"
+ break;
+
+ case 41:
+#line 191 "grammar.y"
+ { (yyval.stmt) = scriptAddStmt((yyvsp[-2].stmt), (yyvsp[0].stmt)); }
+#line 1857 "grammar.c"
+ break;
+
+ case 42:
+#line 193 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewAct((yyvsp[-1].nvlst)); }
+#line 1863 "grammar.c"
+ break;
+
+ case 43:
+#line 194 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewLegaAct((yyvsp[0].s)); }
+#line 1869 "grammar.c"
+ break;
+
+ case 44:
+#line 195 "grammar.y"
+ { (yyval.stmt) = cnfstmtNew(S_STOP); }
+#line 1875 "grammar.c"
+ break;
+
+ case 45:
+#line 196 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewCall((yyvsp[0].estr)); }
+#line 1881 "grammar.c"
+ break;
+
+ case 46:
+#line 197 "grammar.y"
+ { (yyval.stmt) = cnfstmtNew(S_CALL_INDIRECT);
+ (yyval.stmt)->d.s_call_ind.expr = (yyvsp[-1].expr);
+ }
+#line 1889 "grammar.c"
+ break;
+
+ case 47:
+#line 200 "grammar.y"
+ { (yyval.stmt) = cnfstmtNewContinue(); }
+#line 1895 "grammar.c"
+ break;
+
+ case 48:
+#line 201 "grammar.y"
+ { (yyval.expr) = cnfexprNew(AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1901 "grammar.c"
+ break;
+
+ case 49:
+#line 202 "grammar.y"
+ { (yyval.expr) = cnfexprNew(OR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1907 "grammar.c"
+ break;
+
+ case 50:
+#line 203 "grammar.y"
+ { (yyval.expr) = cnfexprNew(NOT, NULL, (yyvsp[0].expr)); }
+#line 1913 "grammar.c"
+ break;
+
+ case 51:
+#line 204 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_EQ, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1919 "grammar.c"
+ break;
+
+ case 52:
+#line 205 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_NE, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1925 "grammar.c"
+ break;
+
+ case 53:
+#line 206 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_LE, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1931 "grammar.c"
+ break;
+
+ case 54:
+#line 207 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_GE, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1937 "grammar.c"
+ break;
+
+ case 55:
+#line 208 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_LT, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1943 "grammar.c"
+ break;
+
+ case 56:
+#line 209 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_GT, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1949 "grammar.c"
+ break;
+
+ case 57:
+#line 210 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_CONTAINS, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1955 "grammar.c"
+ break;
+
+ case 58:
+#line 211 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_CONTAINSI, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1961 "grammar.c"
+ break;
+
+ case 59:
+#line 212 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_STARTSWITH, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1967 "grammar.c"
+ break;
+
+ case 60:
+#line 213 "grammar.y"
+ { (yyval.expr) = cnfexprNew(CMP_STARTSWITHI, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1973 "grammar.c"
+ break;
+
+ case 61:
+#line 214 "grammar.y"
+ { (yyval.expr) = cnfexprNew('&', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1979 "grammar.c"
+ break;
+
+ case 62:
+#line 215 "grammar.y"
+ { (yyval.expr) = cnfexprNew('+', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1985 "grammar.c"
+ break;
+
+ case 63:
+#line 216 "grammar.y"
+ { (yyval.expr) = cnfexprNew('-', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1991 "grammar.c"
+ break;
+
+ case 64:
+#line 217 "grammar.y"
+ { (yyval.expr) = cnfexprNew('*', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 1997 "grammar.c"
+ break;
+
+ case 65:
+#line 218 "grammar.y"
+ { (yyval.expr) = cnfexprNew('/', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2003 "grammar.c"
+ break;
+
+ case 66:
+#line 219 "grammar.y"
+ { (yyval.expr) = cnfexprNew('%', (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2009 "grammar.c"
+ break;
+
+ case 67:
+#line 220 "grammar.y"
+ { (yyval.expr) = (yyvsp[-1].expr); }
+#line 2015 "grammar.c"
+ break;
+
+ case 68:
+#line 221 "grammar.y"
+ { (yyval.expr) = cnfexprNew('M', NULL, (yyvsp[0].expr)); }
+#line 2021 "grammar.c"
+ break;
+
+ case 69:
+#line 222 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnffuncexistsNew((yyvsp[-1].s)); }
+#line 2027 "grammar.c"
+ break;
+
+ case 70:
+#line 223 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnffuncNew((yyvsp[-2].estr), NULL); }
+#line 2033 "grammar.c"
+ break;
+
+ case 71:
+#line 224 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnffuncNew((yyvsp[-3].estr), (yyvsp[-1].fparams)); }
+#line 2039 "grammar.c"
+ break;
+
+ case 72:
+#line 225 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnfnumvalNew((yyvsp[0].n)); }
+#line 2045 "grammar.c"
+ break;
+
+ case 73:
+#line 226 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnfstringvalNew((yyvsp[0].estr)); }
+#line 2051 "grammar.c"
+ break;
+
+ case 74:
+#line 227 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) cnfvarNew((yyvsp[0].s)); }
+#line 2057 "grammar.c"
+ break;
+
+ case 75:
+#line 228 "grammar.y"
+ { (yyval.expr) = (struct cnfexpr*) (yyvsp[0].arr); }
+#line 2063 "grammar.c"
+ break;
+
+ case 76:
+#line 229 "grammar.y"
+ { (yyval.fparams) = cnffparamlstNew((yyvsp[0].expr), NULL); }
+#line 2069 "grammar.c"
+ break;
+
+ case 77:
+#line 230 "grammar.y"
+ { (yyval.fparams) = cnffparamlstNew((yyvsp[-2].expr), (yyvsp[0].fparams)); }
+#line 2075 "grammar.c"
+ break;
+
+ case 78:
+#line 231 "grammar.y"
+ { (yyval.arr) = (yyvsp[-1].arr); }
+#line 2081 "grammar.c"
+ break;
+
+ case 79:
+#line 232 "grammar.y"
+ { (yyval.itr) = cnfNewIterator((yyvsp[-3].s), (yyvsp[-1].expr)); }
+#line 2087 "grammar.c"
+ break;
+
+ case 80:
+#line 233 "grammar.y"
+ { (yyval.arr) = cnfarrayNew((yyvsp[0].estr)); }
+#line 2093 "grammar.c"
+ break;
+
+ case 81:
+#line 234 "grammar.y"
+ { (yyval.arr) = cnfarrayAdd((yyvsp[-2].arr), (yyvsp[0].estr)); }
+#line 2099 "grammar.c"
+ break;
+
+
+#line 2103 "grammar.c"
+
+ 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. */
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
+
+ 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 = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, 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 when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
+
+ /* 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 -- parsing is finished, return the result. |
+`-----------------------------------------------------*/
+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 236 "grammar.y"
+
+/*
+int yyerror(char *s)
+{
+ printf("parse failure on or before line %d: %s\n", yylineno, s);
+ return 0;
+}
+*/
diff --git a/grammar/grammar.h b/grammar/grammar.h
new file mode 100644
index 0000000..18eaeff
--- /dev/null
+++ b/grammar/grammar.h
@@ -0,0 +1,186 @@
+/* A Bison parser, made by GNU Bison 3.5.1. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 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. */
+
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
+#ifndef YY_YY_GRAMMAR_H_INCLUDED
+# define YY_YY_GRAMMAR_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ NAME = 258,
+ FUNC = 259,
+ BEGINOBJ = 260,
+ ENDOBJ = 261,
+ BEGIN_INCLUDE = 262,
+ BEGIN_ACTION = 263,
+ BEGIN_PROPERTY = 264,
+ BEGIN_CONSTANT = 265,
+ BEGIN_TPL = 266,
+ BEGIN_RULESET = 267,
+ STOP = 268,
+ SET = 269,
+ RESET = 270,
+ UNSET = 271,
+ CONTINUE = 272,
+ EXISTS = 273,
+ CALL = 274,
+ CALL_INDIRECT = 275,
+ LEGACY_ACTION = 276,
+ LEGACY_RULESET = 277,
+ PRIFILT = 278,
+ PROPFILT = 279,
+ BSD_TAG_SELECTOR = 280,
+ BSD_HOST_SELECTOR = 281,
+ RELOAD_LOOKUP_TABLE_PROCEDURE = 282,
+ IF = 283,
+ THEN = 284,
+ ELSE = 285,
+ FOREACH = 286,
+ ITERATOR_ASSIGNMENT = 287,
+ DO = 288,
+ OR = 289,
+ AND = 290,
+ NOT = 291,
+ VAR = 292,
+ STRING = 293,
+ NUMBER = 294,
+ CMP_EQ = 295,
+ CMP_NE = 296,
+ CMP_LE = 297,
+ CMP_GE = 298,
+ CMP_LT = 299,
+ CMP_GT = 300,
+ CMP_CONTAINS = 301,
+ CMP_CONTAINSI = 302,
+ CMP_STARTSWITH = 303,
+ CMP_STARTSWITHI = 304,
+ UMINUS = 305
+ };
+#endif
+/* Tokens. */
+#define NAME 258
+#define FUNC 259
+#define BEGINOBJ 260
+#define ENDOBJ 261
+#define BEGIN_INCLUDE 262
+#define BEGIN_ACTION 263
+#define BEGIN_PROPERTY 264
+#define BEGIN_CONSTANT 265
+#define BEGIN_TPL 266
+#define BEGIN_RULESET 267
+#define STOP 268
+#define SET 269
+#define RESET 270
+#define UNSET 271
+#define CONTINUE 272
+#define EXISTS 273
+#define CALL 274
+#define CALL_INDIRECT 275
+#define LEGACY_ACTION 276
+#define LEGACY_RULESET 277
+#define PRIFILT 278
+#define PROPFILT 279
+#define BSD_TAG_SELECTOR 280
+#define BSD_HOST_SELECTOR 281
+#define RELOAD_LOOKUP_TABLE_PROCEDURE 282
+#define IF 283
+#define THEN 284
+#define ELSE 285
+#define FOREACH 286
+#define ITERATOR_ASSIGNMENT 287
+#define DO 288
+#define OR 289
+#define AND 290
+#define NOT 291
+#define VAR 292
+#define STRING 293
+#define NUMBER 294
+#define CMP_EQ 295
+#define CMP_NE 296
+#define CMP_LE 297
+#define CMP_GE 298
+#define CMP_LT 299
+#define CMP_GT 300
+#define CMP_CONTAINS 301
+#define CMP_CONTAINSI 302
+#define CMP_STARTSWITH 303
+#define CMP_STARTSWITHI 304
+#define UMINUS 305
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+union YYSTYPE
+{
+#line 46 "grammar.y"
+
+ char *s;
+ long long n;
+ es_str_t *estr;
+ enum cnfobjType objType;
+ struct cnfobj *obj;
+ struct cnfstmt *stmt;
+ struct nvlst *nvlst;
+ struct objlst *objlst;
+ struct cnfexpr *expr;
+ struct cnfarray *arr;
+ struct cnffunc *func;
+ struct cnffuncexists *exists;
+ struct cnffparamlst *fparams;
+ struct cnfitr *itr;
+
+#line 174 "grammar.h"
+
+};
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE yylval;
+
+int yyparse (void);
+
+#endif /* !YY_YY_GRAMMAR_H_INCLUDED */
diff --git a/grammar/grammar.y b/grammar/grammar.y
new file mode 100644
index 0000000..d6e3eed
--- /dev/null
+++ b/grammar/grammar.y
@@ -0,0 +1,243 @@
+/* Bison file for rsyslog config format v2 (RainerScript).
+ * Please note: this file introduces the new config format, but maintains
+ * backward compatibility. In order to do so, the grammar is not 100% clean,
+ * but IMHO still sufficiently easy both to understand for programmers
+ * maitaining the code as well as users writing the config file. Users are,
+ * of course, encouraged to use new constructs only. But it needs to be noted
+ * that some of the legacy constructs (specifically the in-front-of-action
+ * PRI filter) are very hard to beat in ease of use, at least for simpler
+ * cases.
+ *
+ * Copyright 2011-2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+%{
+#define IN_GRAMMAR_Y /* tell parserif.h not to redefine things! */
+
+#include "config.h"
+#include <stdio.h>
+#include <libestr.h>
+#include "rainerscript.h"
+#include "parserif.h"
+#define YYDEBUG 1
+extern int yylineno;
+extern char *yytext;
+
+/* keep compile rule clean of errors */
+extern int yylex(void);
+extern int yyerror(const char*);
+%}
+
+%union {
+ char *s;
+ long long n;
+ es_str_t *estr;
+ enum cnfobjType objType;
+ struct cnfobj *obj;
+ struct cnfstmt *stmt;
+ struct nvlst *nvlst;
+ struct objlst *objlst;
+ struct cnfexpr *expr;
+ struct cnfarray *arr;
+ struct cnffunc *func;
+ struct cnffuncexists *exists;
+ struct cnffparamlst *fparams;
+ struct cnfitr *itr;
+}
+
+%token <estr> NAME
+%token <estr> FUNC
+%token <objType> BEGINOBJ
+%token ENDOBJ
+%token BEGIN_INCLUDE
+%token BEGIN_ACTION
+%token BEGIN_PROPERTY
+%token BEGIN_CONSTANT
+%token BEGIN_TPL
+%token BEGIN_RULESET
+%token STOP
+%token SET
+%token RESET
+%token UNSET
+%token CONTINUE
+%token EXISTS
+%token <cnfstmt> CALL
+%token <cnfstmt> CALL_INDIRECT
+%token <s> LEGACY_ACTION
+%token <s> LEGACY_RULESET
+%token <s> PRIFILT
+%token <s> PROPFILT
+%token <s> BSD_TAG_SELECTOR
+%token <s> BSD_HOST_SELECTOR
+%token <s> RELOAD_LOOKUP_TABLE_PROCEDURE
+%token IF
+%token THEN
+%token ELSE
+%token FOREACH
+%token ITERATOR_ASSIGNMENT
+%token DO
+%token OR
+%token AND
+%token NOT
+%token <s> VAR
+%token <estr> STRING
+%token <n> NUMBER
+%token CMP_EQ
+%token CMP_NE
+%token CMP_LE
+%token CMP_GE
+%token CMP_LT
+%token CMP_GT
+%token CMP_CONTAINS
+%token CMP_CONTAINSI
+%token CMP_STARTSWITH
+%token CMP_STARTSWITHI
+
+%type <nvlst> nv nvlst value
+%type <obj> obj property constant
+%type <objlst> propconst
+%type <expr> expr
+%type <stmt> stmt s_act actlst block script
+%type <itr> iterator_decl
+%type <fparams> fparams
+%type <arr> array arrayelt
+
+%left AND OR
+%left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT CMP_CONTAINS CMP_CONTAINSI CMP_STARTSWITH CMP_STARTSWITHI
+%left '+' '-' '&'
+%left '*' '/' '%'
+%nonassoc UMINUS NOT
+
+%expect 1 /* dangling else */
+/* If more erors show up, Use "bison -v grammar.y" if more conflicts arise and
+ * check grammar.output for were exactly these conflicts exits.
+ */
+%%
+/* note: we use left recursion below, because that saves stack space AND
+ * offers the right sequence so that we can submit the top-layer objects
+ * one by one.
+ */
+conf: /* empty (to end recursion) */
+ | conf obj { cnfDoObj($2); }
+ | conf stmt { cnfDoScript($2); }
+ | conf LEGACY_RULESET { cnfDoCfsysline($2); }
+ | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); }
+ | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); }
+include: BEGIN_INCLUDE nvlst ENDOBJ { includeProcessCnf($2); }
+obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); }
+ | BEGIN_TPL nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_TPL, $2); }
+ | BEGIN_TPL nvlst ENDOBJ '{' propconst '}'
+ { $$ = cnfobjNew(CNFOBJ_TPL, $2);
+ $$->subobjs = $5;
+ }
+ | BEGIN_RULESET nvlst ENDOBJ '{' script '}'
+ { $$ = cnfobjNew(CNFOBJ_RULESET, $2);
+ $$->script = $5;
+ }
+ | BEGIN_RULESET nvlst ENDOBJ '{' '}'
+ { $$ = cnfobjNew(CNFOBJ_RULESET, $2);
+ $$->script = NULL;
+ }
+propconst: { $$ = NULL; }
+ | propconst property { $$ = objlstAdd($1, $2); }
+ | propconst constant { $$ = objlstAdd($1, $2); }
+property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); }
+constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); }
+nvlst: { $$ = NULL; }
+ | nvlst nv { $2->next = $1; $$ = $2; }
+nv: NAME '=' value { $$ = nvlstSetName($3, $1); }
+value: STRING { $$ = nvlstNewStr($1); }
+ | array { $$ = nvlstNewArray($1); }
+script: stmt { $$ = $1; }
+ | script stmt { $$ = scriptAddStmt($1, $2); }
+stmt: actlst { $$ = $1; }
+ | IF expr THEN block { $$ = cnfstmtNew(S_IF);
+ $$->d.s_if.expr = $2;
+ $$->d.s_if.t_then = $4;
+ $$->d.s_if.t_else = NULL; }
+ | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF);
+ $$->d.s_if.expr = $2;
+ $$->d.s_if.t_then = $4;
+ $$->d.s_if.t_else = $6; }
+ | FOREACH iterator_decl DO block { $$ = cnfstmtNew(S_FOREACH);
+ $$->d.s_foreach.iter = $2;
+ $$->d.s_foreach.body = $4;}
+ | RESET VAR '=' expr ';' { $$ = cnfstmtNewSet($2, $4, 1); }
+ | SET VAR '=' expr ';' { $$ = cnfstmtNewSet($2, $4, 0); }
+ | UNSET VAR ';' { $$ = cnfstmtNewUnset($2); }
+ | PRIFILT block { $$ = cnfstmtNewPRIFILT($1, $2); }
+ | PROPFILT block { $$ = cnfstmtNewPROPFILT($1, $2); }
+ | RELOAD_LOOKUP_TABLE_PROCEDURE '(' fparams ')' { $$ = cnfstmtNewReloadLookupTable($3);}
+ | include { $$ = NULL; }
+ | BEGINOBJ { $$ = NULL; parser_errmsg("declarative object '%s' not permitted in action block [stmt]", yytext);}
+block: stmt { $$ = $1; }
+ | '{' script '}' { $$ = $2; }
+actlst: s_act { $$ = $1; }
+ | actlst '&' s_act { $$ = scriptAddStmt($1, $3); }
+/* s_act are actions and action-like statements */
+s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); }
+ | LEGACY_ACTION { $$ = cnfstmtNewLegaAct($1); }
+ | STOP { $$ = cnfstmtNew(S_STOP); }
+ | CALL NAME { $$ = cnfstmtNewCall($2); }
+ | CALL_INDIRECT expr ';' { $$ = cnfstmtNew(S_CALL_INDIRECT);
+ $$->d.s_call_ind.expr = $2;
+ }
+ | CONTINUE { $$ = cnfstmtNewContinue(); }
+expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); }
+ | expr OR expr { $$ = cnfexprNew(OR, $1, $3); }
+ | NOT expr { $$ = cnfexprNew(NOT, NULL, $2); }
+ | expr CMP_EQ expr { $$ = cnfexprNew(CMP_EQ, $1, $3); }
+ | expr CMP_NE expr { $$ = cnfexprNew(CMP_NE, $1, $3); }
+ | expr CMP_LE expr { $$ = cnfexprNew(CMP_LE, $1, $3); }
+ | expr CMP_GE expr { $$ = cnfexprNew(CMP_GE, $1, $3); }
+ | expr CMP_LT expr { $$ = cnfexprNew(CMP_LT, $1, $3); }
+ | expr CMP_GT expr { $$ = cnfexprNew(CMP_GT, $1, $3); }
+ | expr CMP_CONTAINS expr { $$ = cnfexprNew(CMP_CONTAINS, $1, $3); }
+ | expr CMP_CONTAINSI expr { $$ = cnfexprNew(CMP_CONTAINSI, $1, $3); }
+ | expr CMP_STARTSWITH expr { $$ = cnfexprNew(CMP_STARTSWITH, $1, $3); }
+ | expr CMP_STARTSWITHI expr { $$ = cnfexprNew(CMP_STARTSWITHI, $1, $3); }
+ | expr '&' expr { $$ = cnfexprNew('&', $1, $3); }
+ | expr '+' expr { $$ = cnfexprNew('+', $1, $3); }
+ | expr '-' expr { $$ = cnfexprNew('-', $1, $3); }
+ | expr '*' expr { $$ = cnfexprNew('*', $1, $3); }
+ | expr '/' expr { $$ = cnfexprNew('/', $1, $3); }
+ | expr '%' expr { $$ = cnfexprNew('%', $1, $3); }
+ | '(' expr ')' { $$ = $2; }
+ | '-' expr %prec UMINUS { $$ = cnfexprNew('M', NULL, $2); }
+ | EXISTS '(' VAR ')' { $$ = (struct cnfexpr*) cnffuncexistsNew($3); }
+ | FUNC '(' ')' { $$ = (struct cnfexpr*) cnffuncNew($1, NULL); }
+ | FUNC '(' fparams ')' { $$ = (struct cnfexpr*) cnffuncNew($1, $3); }
+ | NUMBER { $$ = (struct cnfexpr*) cnfnumvalNew($1); }
+ | STRING { $$ = (struct cnfexpr*) cnfstringvalNew($1); }
+ | VAR { $$ = (struct cnfexpr*) cnfvarNew($1); }
+ | array { $$ = (struct cnfexpr*) $1; }
+fparams: expr { $$ = cnffparamlstNew($1, NULL); }
+ | expr ',' fparams { $$ = cnffparamlstNew($1, $3); }
+array: '[' arrayelt ']' { $$ = $2; }
+iterator_decl: '(' VAR ITERATOR_ASSIGNMENT expr ')' { $$ = cnfNewIterator($2, $4); }
+arrayelt: STRING { $$ = cnfarrayNew($1); }
+ | arrayelt ',' STRING { $$ = cnfarrayAdd($1, $3); }
+
+%%
+/*
+int yyerror(char *s)
+{
+ printf("parse failure on or before line %d: %s\n", yylineno, s);
+ return 0;
+}
+*/
diff --git a/grammar/lexer.c b/grammar/lexer.c
new file mode 100644
index 0000000..6667bfc
--- /dev/null
+++ b/grammar/lexer.c
@@ -0,0 +1,4150 @@
+#ifndef __clang_analyzer__ /* this is not really our code */
+#include "config.h"
+
+#line 5 "lexer.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 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#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
+
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_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 int 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.
+ */
+ int yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int 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 = NULL; /**< 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 int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = NULL;
+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 ( const char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int 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() (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+FILE *yyin = NULL, *yyout = NULL;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+int yylineno = 1;
+
+extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
+#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 yynoreturn yy_fatal_error ( const 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 = (int) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+#define YY_NUM_RULES 121
+#define YY_END_OF_BUFFER 122
+/* 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 const flex_int16_t yy_accept[667] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 9, 0, 0, 122, 120, 119, 119,
+ 120, 120, 120, 56, 91, 120, 120, 120, 120, 96,
+ 120, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 57, 58, 90, 119, 91,
+ 120, 120, 120, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 112, 111,
+ 111, 112, 112, 97, 99, 112, 102, 98, 100, 101,
+ 112, 109, 109, 109, 71, 71, 70, 69, 68, 54,
+ 53, 53, 54, 10, 9, 9, 10, 10, 4, 8,
+
+ 7, 52, 49, 49, 52, 52, 44, 22, 24, 52,
+ 11, 28, 20, 23, 19, 25, 21, 43, 43, 14,
+ 34, 18, 35, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 26, 27, 52, 0, 0, 118, 0,
+ 0, 95, 95, 95, 93, 105, 96, 0, 96, 96,
+ 96, 96, 96, 96, 96, 1, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 95, 0,
+ 0, 0, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 1, 96, 96, 96, 96, 96, 96, 96,
+
+ 96, 96, 96, 96, 96, 96, 96, 0, 103, 0,
+ 0, 110, 106, 98, 0, 0, 104, 109, 109, 108,
+ 72, 68, 55, 9, 0, 6, 0, 0, 5, 0,
+ 32, 0, 47, 0, 0, 44, 44, 44, 44, 0,
+ 45, 0, 107, 41, 0, 43, 30, 33, 29, 31,
+ 51, 51, 51, 13, 51, 37, 51, 15, 51, 51,
+ 0, 0, 46, 0, 114, 0, 113, 0, 0, 116,
+ 0, 95, 95, 92, 92, 93, 94, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 63, 96, 96, 96,
+
+ 96, 89, 0, 117, 95, 0, 0, 89, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 63, 96, 96,
+ 96, 96, 0, 0, 0, 0, 0, 0, 48, 0,
+ 0, 0, 0, 0, 42, 16, 51, 51, 17, 51,
+ 51, 0, 0, 0, 115, 95, 92, 92, 94, 96,
+ 61, 96, 96, 96, 60, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 59,
+ 96, 96, 96, 0, 0, 0, 96, 61, 96, 96,
+ 60, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+
+ 96, 96, 96, 96, 96, 59, 96, 96, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 51, 51, 51, 12, 0, 0, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 64, 96, 96, 96, 65, 0,
+ 0, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 64, 96, 96, 96, 65,
+ 0, 0, 0, 0, 51, 51, 51, 96, 96, 96,
+ 96, 96, 96, 96, 96, 0, 81, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 0, 0,
+
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 51, 50, 51, 0,
+ 87, 96, 96, 96, 96, 2, 0, 76, 96, 96,
+ 96, 0, 82, 0, 75, 96, 96, 96, 96, 96,
+ 96, 96, 0, 88, 0, 96, 96, 2, 96, 96,
+ 96, 96, 96, 96, 96, 51, 51, 96, 96, 66,
+ 96, 0, 86, 96, 96, 96, 96, 96, 96, 0,
+ 78, 96, 96, 88, 96, 66, 96, 96, 96, 96,
+ 96, 36, 51, 96, 0, 80, 96, 96, 96, 96,
+ 96, 0, 79, 96, 0, 77, 0, 74, 96, 96,
+
+ 51, 51, 96, 0, 84, 96, 96, 96, 96, 96,
+ 96, 96, 38, 39, 96, 96, 0, 73, 96, 96,
+ 96, 96, 51, 96, 96, 96, 96, 96, 96, 40,
+ 62, 0, 83, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 0,
+ 85, 96, 96, 96, 96, 96, 96, 96, 3, 96,
+ 96, 96, 96, 96, 67, 0
+ } ;
+
+static const YY_CHAR yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 21,
+ 21, 21, 21, 21, 21, 22, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+
+ 66, 67, 68, 69, 70, 39, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 51, 82, 83,
+ 84, 85, 86, 59, 87, 88, 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 const YY_CHAR yy_meta[89] =
+ { 0,
+ 1, 2, 3, 4, 5, 6, 1, 7, 1, 1,
+ 8, 1, 1, 9, 10, 11, 12, 13, 14, 15,
+ 15, 16, 17, 18, 1, 19, 1, 20, 21, 22,
+ 23, 24, 24, 24, 22, 25, 25, 25, 25, 25,
+ 25, 25, 26, 25, 25, 25, 26, 25, 26, 25,
+ 27, 25, 28, 25, 25, 21, 8, 21, 1, 29,
+ 30, 22, 23, 24, 24, 24, 22, 25, 25, 25,
+ 25, 25, 25, 26, 25, 25, 25, 26, 25, 26,
+ 25, 25, 28, 25, 25, 1, 1, 1
+ } ;
+
+static const flex_int16_t yy_base[773] =
+ { 0,
+ 0, 88, 176, 0, 262, 263, 265, 268, 260, 265,
+ 287, 0, 374, 389, 405, 0, 1379, 4863, 4863, 4863,
+ 0, 1366, 0, 4863, 4863, 1351, 260, 0, 1346, 0,
+ 0, 462, 465, 444, 458, 456, 460, 462, 458, 473,
+ 476, 484, 473, 477, 470, 4863, 4863, 0, 547, 363,
+ 1339, 570, 538, 586, 599, 646, 611, 607, 609, 647,
+ 650, 645, 648, 667, 696, 669, 713, 711, 4863, 4863,
+ 4863, 506, 1342, 4863, 4863, 1325, 4863, 0, 4863, 4863,
+ 337, 1170, 1161, 1125, 0, 4863, 4863, 4863, 499, 4863,
+ 4863, 4863, 0, 4863, 564, 588, 531, 530, 4863, 4863,
+
+ 4863, 4863, 4863, 4863, 1091, 626, 748, 4863, 4863, 624,
+ 4863, 4863, 4863, 4863, 4863, 4863, 1069, 591, 716, 4863,
+ 257, 1048, 1031, 471, 0, 481, 549, 569, 562, 565,
+ 649, 679, 635, 4863, 4863, 342, 778, 1019, 4863, 806,
+ 787, 0, 793, 635, 0, 4863, 0, 994, 683, 720,
+ 729, 731, 847, 849, 853, 0, 866, 856, 664, 683,
+ 854, 855, 869, 864, 865, 858, 864, 867, 868, 866,
+ 944, 899, 0, 1002, 931, 0, 937, 919, 967, 981,
+ 500, 981, 1015, 944, 991, 1028, 990, 991, 1015, 939,
+ 989, 1012, 876, 1027, 1019, 1035, 1033, 1031, 1032, 1052,
+
+ 1073, 1044, 941, 1053, 1077, 1081, 1086, 641, 4863, 368,
+ 799, 4863, 4863, 0, 500, 376, 4863, 796, 790, 4863,
+ 0, 1116, 0, 1137, 648, 4863, 1122, 741, 4863, 1126,
+ 4863, 1098, 4863, 744, 1128, 1165, 1171, 0, 1179, 893,
+ 4863, 1142, 4863, 622, 0, 1138, 4863, 4863, 4863, 4863,
+ 0, 901, 973, 0, 1133, 0, 1051, 0, 1142, 1140,
+ 512, 1157, 4863, 1165, 4863, 784, 4863, 1240, 1210, 1229,
+ 781, 1327, 775, 0, 0, 0, 0, 1152, 1079, 1159,
+ 700, 1160, 1164, 1171, 1084, 1282, 1293, 1292, 1286, 1289,
+ 1306, 1295, 1296, 1298, 1309, 1310, 0, 1301, 1302, 1314,
+
+ 1315, 0, 1216, 4863, 1348, 629, 995, 1369, 1382, 1393,
+ 1313, 1364, 1360, 1378, 1392, 1316, 1375, 1318, 1387, 1377,
+ 1390, 1407, 1396, 1422, 1402, 1439, 1441, 1394, 1440, 1442,
+ 1454, 1455, 1472, 1479, 1195, 0, 1335, 0, 4863, 1401,
+ 1470, 0, 1481, 0, 0, 0, 1396, 1438, 0, 1450,
+ 1460, 1488, 0, 736, 4863, 712, 0, 0, 0, 1460,
+ 640, 1457, 1472, 1467, 0, 1489, 1492, 1474, 1476, 1480,
+ 627, 1490, 1498, 1499, 1491, 1505, 1511, 1494, 1496, 0,
+ 1504, 844, 1498, 1544, 1548, 1554, 1516, 1522, 1531, 1543,
+ 1525, 1538, 1555, 1542, 1546, 1548, 1549, 1536, 1565, 1578,
+
+ 1560, 1594, 1592, 1575, 1593, 1564, 1584, 1598, 1599, 1637,
+ 1625, 1631, 0, 1641, 0, 1647, 0, 1653, 0, 1655,
+ 0, 1619, 1610, 1620, 0, 1657, 0, 1637, 1625, 1654,
+ 1644, 1639, 1653, 1648, 1658, 1694, 1648, 1653, 1667, 1656,
+ 1661, 1661, 1660, 1675, 0, 1675, 1680, 1668, 0, 760,
+ 912, 1672, 1691, 1684, 1690, 1673, 1696, 1745, 1719, 1718,
+ 1724, 1726, 1729, 1725, 1741, 1709, 1742, 1747, 1748, 1738,
+ 957, 1167, 1773, 0, 1717, 1732, 1737, 1822, 1756, 1762,
+ 1757, 1782, 1778, 1825, 1784, 1829, 4863, 565, 1771, 1851,
+ 1854, 1790, 1803, 1791, 492, 1793, 1794, 1802, 1598, 978,
+
+ 1857, 1805, 1831, 1827, 1880, 1844, 1834, 1885, 1905, 1852,
+ 1859, 1864, 1870, 1873, 1878, 1861, 1806, 0, 872, 1935,
+ 4863, 1853, 1871, 1894, 1876, 0, 1959, 4863, 1962, 1892,
+ 1909, 1966, 4863, 1977, 4863, 1916, 1920, 1006, 1918, 1980,
+ 1933, 1939, 1123, 4863, 1928, 1947, 1957, 1935, 1991, 1963,
+ 1967, 1956, 2009, 1975, 1983, 1952, 1968, 1976, 2040, 0,
+ 1972, 2054, 4863, 1992, 1980, 1995, 1999, 2068, 2001, 2071,
+ 4863, 2075, 2082, 2042, 2086, 2019, 2021, 2054, 2098, 2101,
+ 2104, 464, 2016, 2050, 2117, 4863, 2128, 2051, 2075, 2077,
+ 2074, 2132, 4863, 2073, 2147, 4863, 2150, 4863, 2122, 2092,
+
+ 2085, 2088, 2103, 2163, 4863, 2106, 2177, 436, 2126, 2128,
+ 2130, 2143, 0, 344, 2129, 2138, 2183, 4863, 2126, 2141,
+ 2133, 2150, 2158, 2149, 2204, 2151, 2163, 2158, 2179, 0,
+ 0, 2223, 4863, 2180, 2169, 322, 2178, 2174, 2190, 2181,
+ 2198, 2188, 2194, 2210, 2203, 2276, 2188, 2210, 2212, 2279,
+ 4863, 2203, 2214, 2217, 2229, 2229, 2256, 2232, 0, 2260,
+ 2218, 2258, 263, 2259, 4863, 4863, 2336, 2366, 2396, 2426,
+ 2456, 2486, 2495, 2523, 2553, 2574, 2589, 2616, 2636, 2656,
+ 2684, 2708, 2728, 2757, 2787, 2805, 2834, 2864, 2894, 2913,
+ 2942, 2972, 3002, 3028, 3057, 3073, 3102, 3132, 3162, 3192,
+
+ 3222, 3252, 3273, 3288, 3315, 3335, 3352, 3374, 3398, 3426,
+ 3453, 3477, 3498, 3527, 3552, 3579, 3597, 3626, 3649, 3679,
+ 3709, 3728, 3757, 3782, 3810, 3835, 3863, 3893, 3918, 3942,
+ 3967, 3996, 4021, 4035, 4045, 4074, 4099, 4129, 4159, 4189,
+ 4219, 4249, 4279, 4309, 4339, 4360, 4385, 4410, 4434, 4455,
+ 4484, 4514, 4530, 4540, 4559, 4573, 4583, 4593, 4603, 4618,
+ 4642, 4672, 4702, 4732, 4748, 4758, 4768, 4778, 4788, 4798,
+ 4808, 4832
+ } ;
+
+static const flex_int16_t yy_def[773] =
+ { 0,
+ 666, 666, 666, 3, 667, 667, 668, 668, 669, 669,
+ 666, 11, 670, 670, 666, 15, 666, 666, 666, 666,
+ 671, 672, 673, 666, 666, 666, 674, 674, 675, 676,
+ 677, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 666, 666, 674, 678, 679,
+ 680, 681, 682, 683, 683, 683, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 666, 666,
+ 666, 684, 685, 666, 666, 666, 666, 686, 666, 666,
+ 687, 688, 688, 666, 689, 666, 666, 666, 666, 666,
+ 666, 666, 690, 666, 666, 666, 691, 692, 666, 666,
+
+ 666, 666, 666, 666, 666, 693, 694, 666, 666, 695,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 696, 696, 696, 696, 696, 696, 696,
+ 696, 696, 696, 666, 666, 697, 698, 699, 666, 666,
+ 666, 700, 700, 701, 702, 666, 703, 704, 703, 703,
+ 703, 703, 703, 703, 703, 703, 703, 703, 703, 703,
+ 703, 703, 703, 703, 703, 703, 703, 703, 703, 703,
+ 705, 706, 707, 708, 706, 709, 666, 707, 710, 708,
+ 708, 711, 712, 703, 713, 713, 186, 186, 186, 186,
+ 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+
+ 186, 186, 186, 186, 186, 186, 186, 714, 666, 715,
+ 716, 666, 666, 717, 718, 719, 666, 720, 720, 666,
+ 721, 666, 722, 666, 723, 666, 724, 725, 666, 726,
+ 666, 727, 666, 728, 729, 730, 730, 731, 730, 732,
+ 666, 733, 666, 666, 734, 666, 666, 666, 666, 666,
+ 735, 735, 735, 735, 735, 735, 735, 735, 735, 735,
+ 736, 737, 666, 666, 666, 738, 666, 666, 666, 666,
+ 739, 740, 741, 742, 743, 744, 745, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 746,
+
+ 746, 747, 666, 666, 740, 666, 748, 749, 750, 750,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 751, 752, 666, 753, 666, 754, 666, 755,
+ 666, 756, 666, 757, 758, 759, 759, 759, 759, 759,
+ 759, 666, 760, 761, 666, 762, 763, 764, 745, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 746,
+ 746, 746, 746, 748, 748, 748, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 751,
+ 752, 666, 765, 666, 766, 666, 767, 666, 768, 666,
+ 769, 759, 759, 759, 759, 666, 770, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 746, 666,
+ 666, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 751, 752, 666, 771, 759, 759, 759, 746, 746, 746,
+ 746, 746, 746, 746, 746, 666, 666, 746, 746, 746,
+ 746, 746, 746, 746, 746, 746, 746, 746, 666, 772,
+
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 759, 759, 759, 666,
+ 666, 746, 746, 746, 746, 746, 666, 666, 746, 746,
+ 746, 666, 666, 666, 666, 746, 746, 746, 746, 746,
+ 746, 746, 772, 666, 772, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 759, 759, 746, 746, 746,
+ 746, 666, 666, 746, 746, 746, 746, 746, 746, 666,
+ 666, 746, 746, 772, 310, 310, 310, 310, 310, 310,
+ 310, 759, 759, 746, 666, 666, 746, 746, 746, 746,
+ 746, 666, 666, 746, 666, 666, 666, 666, 310, 310,
+
+ 759, 759, 746, 666, 666, 746, 746, 746, 746, 746,
+ 310, 310, 759, 759, 746, 746, 666, 666, 746, 746,
+ 746, 310, 759, 746, 746, 746, 746, 746, 310, 759,
+ 746, 666, 666, 746, 746, 746, 310, 746, 746, 746,
+ 310, 746, 746, 746, 310, 746, 746, 746, 310, 666,
+ 666, 746, 746, 310, 746, 746, 310, 746, 746, 310,
+ 746, 310, 746, 310, 666, 0, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666
+ } ;
+
+static const flex_int16_t yy_nxt[4952] =
+ { 0,
+ 18, 19, 20, 19, 21, 18, 22, 23, 18, 24,
+ 18, 18, 18, 25, 26, 18, 27, 28, 29, 30,
+ 30, 30, 31, 18, 18, 18, 28, 28, 28, 32,
+ 30, 33, 34, 35, 36, 37, 30, 38, 30, 30,
+ 39, 40, 30, 30, 41, 30, 42, 43, 44, 45,
+ 30, 30, 30, 30, 30, 18, 18, 18, 28, 30,
+ 18, 32, 30, 33, 34, 35, 36, 37, 30, 38,
+ 30, 39, 40, 30, 30, 41, 30, 42, 43, 44,
+ 45, 30, 30, 30, 30, 46, 47, 48, 18, 49,
+ 20, 49, 21, 18, 22, 23, 18, 24, 18, 18,
+
+ 18, 50, 51, 18, 52, 28, 29, 30, 30, 30,
+ 53, 18, 18, 18, 28, 28, 28, 54, 55, 56,
+ 57, 58, 59, 60, 55, 61, 55, 55, 62, 63,
+ 55, 55, 64, 55, 65, 66, 67, 68, 55, 55,
+ 55, 55, 55, 18, 18, 18, 28, 30, 18, 54,
+ 55, 56, 57, 58, 59, 60, 55, 61, 55, 62,
+ 63, 55, 55, 64, 55, 65, 66, 67, 68, 55,
+ 55, 55, 55, 46, 47, 48, 69, 70, 71, 70,
+ 69, 72, 73, 69, 69, 69, 69, 69, 74, 69,
+ 69, 75, 69, 69, 76, 69, 69, 69, 69, 69,
+
+ 69, 77, 69, 69, 69, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 79, 69, 80, 69, 69, 81, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 69, 69, 69, 83, 83, 86, 86, 86, 86,
+ 86, 86, 88, 143, 665, 84, 84, 88, 144, 89,
+ 89, 89, 247, 248, 89, 89, 89, 90, 91, 92,
+ 91, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 90, 90, 90, 90, 90, 90, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 90, 90, 90, 95, 96, 95, 176, 97,
+ 176, 640, 177, 177, 98, 99, 100, 333, 333, 101,
+ 95, 96, 95, 216, 97, 334, 334, 217, 262, 98,
+
+ 99, 100, 263, 623, 101, 102, 103, 104, 103, 105,
+ 106, 102, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 102, 117, 118, 119, 119, 102, 120, 121,
+ 122, 123, 102, 102, 124, 125, 126, 127, 128, 125,
+ 125, 125, 129, 125, 125, 125, 125, 130, 131, 125,
+ 125, 125, 132, 133, 125, 125, 125, 125, 125, 125,
+ 134, 102, 135, 102, 102, 136, 124, 125, 126, 127,
+ 128, 125, 125, 125, 129, 125, 125, 125, 130, 131,
+ 125, 125, 125, 132, 133, 125, 125, 125, 125, 125,
+ 102, 102, 102, 149, 150, 619, 156, 152, 153, 154,
+
+ 155, 158, 159, 306, 157, 161, 166, 666, 151, 162,
+ 168, 209, 170, 252, 169, 307, 160, 164, 222, 222,
+ 222, 167, 163, 601, 253, 149, 150, 152, 156, 153,
+ 154, 155, 158, 165, 159, 157, 226, 161, 166, 151,
+ 229, 162, 168, 170, 252, 180, 169, 160, 171, 164,
+ 171, 539, 167, 163, 181, 253, 216, 148, 148, 148,
+ 217, 173, 210, 173, 165, 224, 224, 224, 262, 174,
+ 142, 142, 263, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 143, 142, 142, 230, 227, 144, 224,
+ 224, 224, 254, 142, 142, 142, 142, 142, 142, 175,
+
+ 147, 183, 147, 176, 256, 184, 184, 147, 257, 147,
+ 244, 244, 175, 147, 183, 147, 176, 186, 184, 184,
+ 147, 255, 147, 254, 530, 142, 142, 142, 142, 142,
+ 142, 233, 306, 234, 241, 256, 185, 275, 185, 257,
+ 185, 244, 244, 245, 307, 147, 209, 190, 142, 186,
+ 185, 255, 191, 226, 185, 142, 142, 142, 147, 175,
+ 147, 183, 147, 176, 189, 184, 184, 147, 185, 147,
+ 185, 260, 185, 245, 185, 187, 185, 196, 190, 185,
+ 242, 185, 235, 191, 193, 185, 438, 192, 195, 188,
+ 185, 197, 194, 185, 189, 258, 198, 210, 185, 429,
+
+ 199, 288, 203, 260, 227, 147, 185, 187, 185, 196,
+ 185, 185, 185, 200, 355, 289, 193, 204, 192, 195,
+ 188, 185, 197, 194, 185, 185, 258, 259, 198, 201,
+ 185, 278, 199, 288, 203, 246, 246, 246, 355, 185,
+ 185, 185, 185, 185, 200, 202, 205, 289, 204, 339,
+ 206, 229, 236, 207, 185, 237, 185, 185, 259, 364,
+ 279, 201, 278, 450, 238, 236, 237, 238, 238, 238,
+ 185, 280, 185, 281, 185, 451, 202, 355, 205, 264,
+ 265, 264, 206, 355, 207, 185, 267, 185, 269, 270,
+ 269, 279, 219, 271, 272, 270, 272, 230, 219, 273,
+
+ 340, 212, 280, 238, 281, 238, 266, 266, 267, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 266, 266, 266, 266, 266, 266, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 266, 266, 266, 282, 283, 284, 285, 448, 287,
+
+ 290, 291, 292, 241, 294, 296, 297, 298, 299, 300,
+ 286, 295, 293, 301, 176, 499, 176, 500, 177, 177,
+ 303, 304, 303, 557, 185, 282, 283, 284, 448, 285,
+ 287, 290, 291, 346, 292, 294, 296, 297, 298, 299,
+ 300, 286, 295, 293, 301, 171, 176, 171, 176, 242,
+ 177, 177, 176, 557, 176, 185, 177, 177, 173, 183,
+ 173, 176, 209, 184, 184, 346, 174, 142, 305, 304,
+ 305, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 544, 306, 142, 313, 185, 666, 328,
+ 142, 142, 142, 142, 142, 142, 307, 181, 384, 385,
+
+ 148, 148, 148, 277, 175, 147, 183, 147, 176, 180,
+ 184, 184, 147, 210, 147, 347, 277, 313, 185, 302,
+ 328, 139, 142, 142, 142, 142, 142, 142, 302, 147,
+ 310, 147, 302, 311, 545, 314, 147, 185, 185, 185,
+ 302, 175, 147, 183, 147, 176, 347, 184, 184, 147,
+ 147, 147, 142, 142, 142, 315, 250, 312, 316, 568,
+ 185, 310, 318, 185, 311, 320, 314, 185, 185, 185,
+ 185, 317, 319, 249, 147, 185, 309, 321, 322, 185,
+ 185, 185, 243, 185, 327, 323, 315, 147, 312, 568,
+ 316, 185, 185, 318, 185, 324, 329, 320, 185, 349,
+
+ 185, 185, 317, 233, 319, 234, 185, 309, 321, 322,
+ 185, 185, 185, 325, 185, 327, 231, 323, 330, 361,
+ 326, 185, 331, 185, 368, 185, 324, 329, 544, 185,
+ 349, 185, 185, 332, 185, 222, 222, 222, 224, 224,
+ 224, 335, 335, 220, 325, 337, 337, 341, 341, 330,
+ 361, 326, 185, 331, 235, 368, 185, 246, 246, 246,
+ 185, 343, 343, 219, 332, 185, 264, 265, 264, 238,
+ 348, 350, 219, 351, 336, 238, 352, 352, 338, 545,
+ 342, 238, 238, 238, 238, 238, 238, 238, 238, 360,
+ 238, 238, 238, 365, 344, 238, 238, 366, 238, 238,
+
+ 238, 367, 348, 350, 336, 351, 362, 363, 338, 353,
+ 342, 269, 270, 269, 412, 412, 271, 303, 304, 303,
+ 238, 360, 238, 216, 344, 365, 238, 217, 238, 366,
+ 269, 270, 269, 367, 238, 271, 238, 362, 363, 353,
+ 266, 266, 267, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 266, 266, 266, 266, 266,
+
+ 266, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 266, 266, 266, 272, 270,
+ 272, 369, 370, 273, 371, 372, 373, 374, 213, 375,
+ 376, 377, 378, 379, 212, 380, 381, 382, 383, 305,
+ 304, 305, 141, 185, 414, 414, 394, 396, 185, 146,
+ 389, 390, 369, 370, 141, 371, 372, 373, 139, 374,
+ 375, 376, 377, 302, 378, 379, 380, 381, 666, 382,
+ 383, 666, 302, 147, 185, 147, 302, 394, 396, 185,
+ 147, 389, 390, 391, 302, 175, 147, 183, 147, 176,
+
+ 185, 184, 184, 147, 185, 147, 175, 147, 183, 147,
+ 176, 392, 184, 184, 147, 185, 147, 185, 185, 387,
+ 416, 416, 393, 364, 395, 391, 398, 185, 147, 397,
+ 185, 185, 185, 388, 185, 185, 185, 399, 400, 666,
+ 401, 147, 185, 392, 422, 403, 185, 185, 185, 185,
+ 666, 387, 147, 417, 393, 395, 666, 398, 185, 666,
+ 397, 185, 185, 185, 388, 185, 402, 185, 399, 666,
+ 400, 401, 404, 185, 405, 422, 403, 209, 185, 185,
+ 185, 185, 185, 417, 406, 423, 407, 408, 409, 418,
+ 418, 410, 410, 185, 185, 185, 424, 402, 411, 411,
+
+ 420, 420, 425, 428, 404, 430, 405, 426, 426, 431,
+ 185, 185, 185, 185, 432, 406, 423, 407, 433, 408,
+ 409, 434, 666, 435, 436, 185, 185, 424, 210, 437,
+ 439, 440, 441, 425, 428, 216, 430, 442, 443, 217,
+ 444, 431, 445, 446, 447, 432, 449, 384, 385, 666,
+ 433, 666, 666, 434, 435, 436, 185, 450, 666, 452,
+ 437, 439, 185, 440, 441, 185, 666, 455, 442, 451,
+ 443, 185, 444, 445, 446, 447, 460, 449, 185, 453,
+ 454, 429, 185, 185, 456, 666, 185, 185, 185, 185,
+ 452, 457, 666, 185, 458, 185, 185, 459, 461, 455,
+
+ 185, 499, 185, 500, 185, 185, 463, 460, 438, 185,
+ 453, 462, 454, 185, 185, 185, 456, 185, 185, 185,
+ 185, 465, 457, 466, 468, 458, 185, 464, 459, 666,
+ 461, 185, 185, 185, 185, 185, 185, 463, 185, 185,
+ 467, 666, 209, 462, 472, 472, 185, 470, 475, 185,
+ 225, 225, 469, 465, 466, 468, 471, 471, 476, 464,
+ 228, 228, 479, 185, 185, 185, 473, 473, 477, 185,
+ 185, 467, 232, 232, 240, 240, 261, 261, 470, 478,
+ 475, 216, 469, 480, 483, 217, 481, 482, 484, 476,
+ 485, 666, 488, 210, 479, 486, 486, 486, 489, 477,
+
+ 490, 666, 491, 492, 493, 487, 494, 495, 496, 497,
+ 478, 498, 185, 505, 501, 480, 483, 481, 482, 484,
+ 502, 504, 485, 488, 185, 666, 503, 666, 506, 489,
+ 185, 185, 490, 491, 492, 493, 185, 494, 666, 495,
+ 496, 497, 498, 185, 505, 501, 486, 486, 486, 185,
+ 666, 508, 502, 504, 517, 185, 487, 503, 185, 185,
+ 506, 185, 185, 507, 185, 185, 185, 185, 510, 185,
+ 509, 512, 511, 513, 666, 514, 515, 666, 185, 518,
+ 185, 185, 185, 508, 519, 185, 517, 185, 185, 185,
+ 185, 516, 234, 234, 507, 185, 185, 185, 522, 510,
+
+ 185, 509, 512, 511, 523, 513, 524, 514, 515, 185,
+ 518, 525, 185, 185, 526, 519, 185, 529, 185, 185,
+ 531, 666, 516, 520, 520, 520, 527, 527, 527, 522,
+ 486, 486, 486, 521, 537, 523, 528, 524, 536, 538,
+ 487, 540, 541, 525, 542, 185, 526, 546, 556, 529,
+ 666, 531, 532, 532, 532, 534, 534, 534, 520, 520,
+ 520, 666, 533, 548, 666, 535, 537, 185, 521, 536,
+ 538, 185, 540, 541, 185, 542, 185, 549, 546, 556,
+ 547, 527, 527, 527, 185, 558, 532, 532, 532, 666,
+ 551, 528, 185, 530, 666, 548, 533, 185, 185, 185,
+
+ 550, 185, 185, 555, 185, 185, 534, 534, 534, 549,
+ 185, 547, 552, 185, 666, 185, 535, 558, 185, 559,
+ 185, 553, 551, 185, 561, 185, 554, 560, 185, 539,
+ 185, 550, 185, 574, 555, 185, 520, 520, 520, 666,
+ 564, 185, 565, 552, 185, 185, 521, 666, 666, 185,
+ 559, 185, 553, 566, 567, 561, 185, 554, 569, 560,
+ 527, 527, 527, 562, 562, 562, 572, 532, 532, 532,
+ 528, 564, 573, 563, 565, 185, 185, 533, 534, 534,
+ 534, 570, 570, 570, 545, 566, 567, 185, 535, 569,
+ 576, 571, 562, 562, 562, 575, 185, 185, 572, 582,
+
+ 577, 578, 563, 185, 573, 583, 185, 185, 580, 579,
+ 570, 570, 570, 584, 666, 185, 581, 666, 185, 587,
+ 571, 588, 576, 185, 666, 666, 575, 185, 185, 589,
+ 582, 185, 577, 578, 185, 590, 591, 583, 185, 579,
+ 580, 585, 585, 585, 594, 584, 185, 544, 581, 185,
+ 587, 586, 666, 588, 185, 562, 562, 562, 666, 185,
+ 589, 599, 185, 666, 602, 563, 590, 666, 591, 592,
+ 592, 592, 570, 570, 570, 594, 595, 595, 595, 593,
+ 185, 606, 571, 597, 597, 597, 596, 585, 585, 585,
+ 185, 600, 599, 598, 185, 602, 603, 586, 545, 592,
+
+ 592, 592, 595, 595, 595, 597, 597, 597, 607, 593,
+ 608, 666, 596, 606, 609, 598, 610, 666, 585, 585,
+ 585, 666, 613, 600, 614, 185, 185, 603, 586, 604,
+ 604, 604, 612, 592, 592, 592, 615, 666, 185, 605,
+ 607, 185, 608, 593, 185, 609, 616, 610, 595, 595,
+ 595, 597, 597, 597, 613, 611, 614, 185, 596, 620,
+ 624, 598, 185, 612, 604, 604, 604, 621, 615, 185,
+ 185, 625, 185, 626, 605, 185, 622, 616, 617, 617,
+ 617, 627, 628, 185, 617, 617, 617, 611, 618, 619,
+ 629, 620, 624, 185, 618, 630, 666, 631, 621, 634,
+
+ 635, 185, 636, 625, 626, 632, 632, 632, 622, 638,
+ 666, 639, 627, 628, 185, 633, 637, 666, 185, 185,
+ 641, 629, 642, 643, 632, 632, 632, 630, 631, 644,
+ 634, 645, 635, 636, 633, 646, 647, 652, 185, 648,
+ 653, 638, 639, 185, 655, 649, 666, 666, 637, 185,
+ 185, 641, 185, 642, 656, 643, 666, 185, 657, 658,
+ 644, 654, 659, 645, 663, 661, 646, 647, 652, 185,
+ 665, 648, 653, 666, 185, 655, 649, 650, 650, 650,
+ 650, 650, 650, 185, 666, 656, 660, 651, 185, 657,
+ 651, 658, 654, 662, 659, 663, 185, 661, 185, 185,
+
+ 185, 666, 666, 666, 664, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 660, 666,
+ 666, 666, 666, 666, 666, 662, 666, 185, 666, 185,
+ 185, 185, 666, 666, 666, 664, 82, 82, 82, 82,
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 82, 82, 82, 82, 82, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 87, 87, 87, 87,
+
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 137, 666, 666, 666,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 140, 140, 140, 140,
+ 140, 140, 140, 142, 142, 666, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 147, 147, 147, 666, 666, 147, 147,
+ 666, 147, 666, 666, 666, 147, 147, 147, 147, 147,
+
+ 147, 147, 147, 148, 148, 666, 666, 666, 666, 666,
+ 148, 148, 148, 148, 148, 148, 148, 172, 666, 172,
+ 666, 666, 666, 666, 172, 172, 666, 172, 666, 666,
+ 666, 666, 172, 666, 666, 666, 666, 172, 172, 172,
+ 172, 172, 172, 172, 175, 666, 175, 666, 175, 666,
+ 175, 666, 666, 666, 666, 666, 666, 175, 175, 175,
+ 175, 175, 175, 175, 178, 666, 666, 178, 178, 666,
+ 178, 178, 178, 666, 666, 666, 666, 178, 178, 178,
+ 178, 178, 178, 178, 179, 179, 666, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 182, 666, 666, 666, 666, 182,
+ 666, 666, 182, 182, 666, 666, 666, 666, 666, 182,
+ 182, 182, 182, 182, 182, 182, 185, 185, 185, 185,
+ 185, 666, 185, 185, 666, 185, 666, 666, 666, 185,
+ 185, 185, 185, 185, 185, 185, 185, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 214, 666, 214,
+ 214, 666, 666, 666, 666, 666, 214, 214, 214, 214,
+ 214, 214, 214, 214, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 218, 218, 218, 218, 218, 218,
+ 218, 218, 666, 218, 218, 218, 218, 218, 218, 218,
+ 218, 218, 218, 218, 218, 218, 218, 218, 218, 218,
+ 218, 218, 218, 218, 221, 666, 666, 666, 221, 221,
+
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 223, 223, 666, 223, 223, 666,
+ 666, 666, 666, 666, 223, 223, 223, 223, 223, 223,
+ 223, 223, 225, 225, 225, 225, 225, 225, 666, 225,
+ 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
+ 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
+ 225, 225, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+
+ 228, 228, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 239, 666, 239, 666, 666, 666, 666, 239,
+ 239, 239, 239, 239, 666, 666, 666, 666, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 251, 251, 666,
+ 666, 666, 666, 666, 251, 251, 251, 251, 251, 251,
+
+ 251, 251, 261, 261, 261, 261, 261, 261, 261, 261,
+ 261, 261, 261, 261, 261, 261, 261, 261, 261, 261,
+ 261, 261, 261, 261, 261, 261, 261, 261, 261, 261,
+ 261, 261, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 142, 142, 666, 142, 142, 142, 142, 142,
+
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 276, 276, 666, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 147, 147, 147, 666, 666, 147, 147, 666,
+ 147, 666, 666, 666, 147, 147, 147, 147, 147, 147,
+
+ 147, 147, 148, 148, 148, 666, 666, 666, 666, 148,
+ 148, 148, 148, 148, 148, 148, 172, 666, 172, 666,
+ 666, 666, 666, 172, 172, 666, 172, 666, 666, 666,
+ 666, 172, 666, 666, 666, 666, 172, 172, 172, 172,
+ 172, 172, 172, 175, 666, 175, 666, 175, 666, 175,
+ 666, 666, 666, 666, 666, 666, 175, 175, 175, 175,
+ 175, 175, 175, 178, 178, 666, 178, 178, 178, 666,
+ 666, 666, 666, 178, 178, 178, 178, 178, 178, 178,
+ 181, 666, 666, 666, 666, 181, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 181, 181, 181, 181, 181,
+
+ 181, 181, 302, 666, 666, 666, 302, 666, 302, 666,
+ 302, 666, 302, 666, 666, 302, 302, 666, 666, 302,
+ 302, 302, 302, 302, 302, 302, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 182, 666, 666, 666,
+ 666, 666, 666, 182, 182, 666, 666, 182, 182, 182,
+ 666, 666, 666, 666, 182, 182, 182, 182, 182, 182,
+ 182, 308, 666, 666, 666, 308, 308, 308, 308, 308,
+ 666, 308, 308, 666, 308, 308, 666, 666, 308, 308,
+
+ 308, 308, 308, 308, 308, 308, 185, 185, 185, 185,
+ 185, 666, 185, 185, 666, 185, 666, 666, 666, 185,
+ 185, 185, 185, 185, 185, 185, 185, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 666, 208,
+ 666, 666, 666, 666, 666, 666, 208, 666, 666, 666,
+ 666, 208, 666, 208, 208, 666, 666, 208, 208, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 214,
+ 666, 214, 214, 666, 666, 666, 666, 666, 214, 214,
+ 214, 214, 214, 214, 214, 214, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 666, 666, 666,
+ 666, 666, 666, 215, 666, 666, 666, 666, 215, 666,
+ 215, 215, 666, 666, 215, 215, 666, 666, 215, 218,
+ 218, 218, 218, 218, 218, 218, 218, 666, 218, 218,
+ 218, 218, 218, 218, 218, 218, 218, 218, 218, 218,
+
+ 218, 218, 218, 218, 218, 218, 218, 218, 218, 221,
+ 666, 666, 666, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 223,
+ 223, 666, 223, 223, 666, 666, 666, 666, 666, 223,
+ 223, 223, 223, 223, 223, 223, 223, 225, 225, 225,
+ 225, 225, 225, 666, 225, 225, 225, 225, 225, 225,
+ 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
+ 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
+ 666, 666, 666, 666, 666, 666, 225, 666, 666, 666,
+
+ 666, 666, 666, 666, 225, 666, 666, 225, 666, 225,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 666, 666, 666, 666, 666, 666, 228,
+ 666, 666, 666, 666, 666, 666, 666, 228, 666, 666,
+ 228, 666, 228, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 234, 234, 234, 234, 234, 234, 234,
+
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 232, 232, 232, 666, 666, 666, 666,
+ 666, 666, 232, 666, 666, 666, 666, 666, 666, 666,
+ 232, 666, 666, 232, 666, 232, 239, 666, 666, 666,
+ 666, 666, 666, 239, 239, 666, 239, 239, 666, 666,
+ 666, 666, 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 238, 666, 666, 666, 666, 666, 666, 238, 238,
+ 666, 238, 238, 666, 666, 666, 666, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 240, 240, 240, 240,
+
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 666,
+ 666, 666, 666, 666, 666, 240, 666, 666, 666, 666,
+ 666, 666, 666, 240, 666, 666, 240, 666, 240, 345,
+ 345, 666, 666, 666, 666, 666, 345, 345, 345, 251,
+ 251, 666, 666, 666, 666, 666, 251, 251, 251, 251,
+ 251, 251, 251, 251, 261, 261, 261, 261, 261, 261,
+ 261, 261, 261, 261, 261, 261, 261, 261, 261, 261,
+ 261, 261, 261, 261, 261, 261, 261, 261, 261, 261,
+
+ 261, 261, 261, 261, 261, 666, 261, 666, 666, 666,
+ 666, 666, 666, 261, 666, 666, 666, 666, 666, 666,
+ 666, 261, 666, 666, 261, 666, 261, 666, 261, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 356,
+ 356, 356, 356, 356, 356, 356, 356, 356, 356, 356,
+ 356, 356, 356, 356, 356, 356, 356, 356, 356, 356,
+ 356, 356, 356, 356, 356, 356, 356, 356, 356, 357,
+ 357, 666, 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357, 357, 358,
+ 358, 666, 358, 358, 358, 358, 358, 358, 358, 358,
+ 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
+
+ 358, 358, 358, 358, 358, 358, 358, 358, 358, 276,
+ 276, 666, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 359,
+ 359, 666, 359, 359, 359, 359, 359, 359, 359, 359,
+ 359, 359, 359, 359, 359, 359, 359, 359, 359, 359,
+ 359, 359, 359, 359, 359, 359, 359, 359, 359, 147,
+ 147, 147, 666, 666, 147, 147, 666, 147, 666, 666,
+ 666, 147, 147, 147, 147, 147, 147, 147, 147, 302,
+ 666, 666, 666, 302, 666, 302, 666, 302, 666, 302,
+
+ 666, 666, 302, 302, 666, 666, 302, 302, 302, 302,
+ 302, 302, 302, 386, 386, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 386, 386, 386, 386, 386, 386, 386, 308, 666,
+ 666, 666, 308, 308, 308, 308, 308, 666, 308, 308,
+ 666, 308, 308, 666, 666, 308, 308, 308, 308, 308,
+ 308, 308, 308, 185, 185, 185, 185, 185, 666, 185,
+ 185, 666, 185, 666, 666, 666, 185, 185, 185, 185,
+ 185, 185, 185, 185, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 413, 413, 666, 666, 666, 666,
+ 666, 413, 413, 413, 415, 415, 666, 666, 666, 666,
+ 666, 415, 415, 415, 234, 234, 234, 666, 666, 666,
+ 666, 666, 666, 234, 666, 666, 666, 666, 666, 666,
+ 666, 234, 666, 666, 234, 666, 234, 419, 419, 666,
+ 666, 666, 666, 666, 419, 419, 419, 421, 421, 666,
+
+ 666, 666, 666, 666, 421, 421, 421, 345, 345, 666,
+ 666, 666, 666, 666, 345, 345, 345, 251, 251, 666,
+ 666, 666, 666, 666, 251, 251, 251, 251, 251, 251,
+ 251, 251, 427, 427, 666, 666, 666, 666, 666, 427,
+ 427, 427, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 354, 354, 354, 354, 354, 354, 354, 354,
+ 354, 354, 356, 356, 356, 356, 356, 356, 356, 356,
+ 356, 356, 356, 356, 356, 356, 356, 356, 356, 356,
+ 356, 356, 356, 356, 356, 356, 356, 356, 356, 356,
+
+ 356, 356, 357, 357, 666, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 357, 357, 357, 357, 357, 357, 357, 357,
+ 357, 357, 358, 358, 666, 358, 358, 358, 358, 358,
+ 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
+ 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
+ 358, 358, 225, 225, 666, 666, 666, 666, 666, 225,
+ 225, 225, 228, 228, 666, 666, 666, 666, 666, 228,
+ 228, 228, 474, 474, 666, 666, 666, 666, 666, 474,
+ 474, 474, 232, 232, 666, 666, 666, 666, 666, 232,
+
+ 232, 232, 240, 240, 666, 666, 666, 666, 666, 240,
+ 240, 240, 261, 261, 666, 666, 666, 666, 666, 261,
+ 261, 261, 234, 234, 666, 666, 666, 666, 666, 234,
+ 234, 234, 543, 543, 543, 543, 543, 543, 543, 543,
+ 543, 543, 543, 543, 543, 543, 543, 543, 543, 543,
+ 543, 543, 543, 543, 543, 543, 543, 543, 543, 543,
+ 543, 543, 17, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666
+ } ;
+
+static const flex_int16_t yy_chk[4952] =
+ { 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, 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, 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, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 6, 7, 7, 7, 8,
+ 8, 8, 9, 27, 663, 5, 6, 10, 27, 9,
+ 9, 9, 121, 121, 10, 10, 10, 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, 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, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 13, 13, 13, 50, 13,
+ 50, 636, 50, 50, 13, 13, 13, 210, 210, 13,
+ 14, 14, 14, 81, 14, 216, 216, 81, 136, 14,
+
+ 14, 14, 136, 614, 14, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 32, 33, 608, 38, 34, 35, 36,
+
+ 37, 39, 40, 181, 38, 41, 43, 181, 33, 41,
+ 44, 72, 45, 124, 44, 181, 40, 42, 89, 89,
+ 89, 43, 41, 582, 126, 32, 33, 34, 38, 35,
+ 36, 37, 39, 42, 40, 38, 97, 41, 43, 33,
+ 98, 41, 44, 45, 124, 53, 44, 40, 49, 42,
+ 49, 495, 43, 41, 53, 126, 215, 53, 53, 53,
+ 215, 49, 72, 49, 42, 95, 95, 95, 261, 49,
+ 52, 52, 261, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 98, 97, 52, 96,
+ 96, 96, 127, 52, 52, 52, 52, 52, 52, 54,
+
+ 54, 54, 54, 54, 129, 54, 54, 54, 130, 54,
+ 118, 118, 55, 55, 55, 55, 55, 54, 55, 55,
+ 55, 128, 55, 127, 488, 52, 52, 52, 52, 52,
+ 52, 106, 306, 106, 110, 129, 58, 144, 59, 130,
+ 57, 244, 244, 118, 306, 54, 208, 58, 144, 54,
+ 58, 128, 59, 225, 57, 52, 52, 52, 55, 56,
+ 56, 56, 56, 56, 57, 56, 56, 56, 58, 56,
+ 59, 133, 57, 118, 62, 56, 60, 63, 58, 61,
+ 110, 58, 106, 59, 61, 57, 371, 60, 62, 56,
+ 60, 63, 61, 61, 57, 131, 64, 208, 66, 361,
+
+ 64, 159, 66, 133, 225, 56, 62, 56, 60, 63,
+ 64, 61, 66, 64, 356, 160, 61, 66, 60, 62,
+ 56, 60, 63, 61, 61, 65, 131, 132, 64, 65,
+ 66, 149, 64, 159, 66, 119, 119, 119, 354, 65,
+ 68, 64, 67, 66, 64, 65, 67, 160, 66, 234,
+ 67, 228, 107, 68, 68, 107, 67, 65, 132, 281,
+ 150, 65, 149, 450, 107, 107, 107, 107, 107, 107,
+ 65, 151, 68, 152, 67, 450, 65, 273, 67, 137,
+ 137, 137, 67, 271, 68, 68, 266, 67, 141, 141,
+ 141, 150, 219, 141, 143, 143, 143, 228, 218, 143,
+
+ 234, 211, 151, 107, 152, 107, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 153, 154, 155, 157, 382, 158,
+
+ 161, 162, 163, 240, 164, 165, 166, 167, 168, 169,
+ 157, 164, 163, 170, 172, 451, 172, 451, 172, 172,
+ 178, 178, 178, 519, 193, 153, 154, 155, 382, 157,
+ 158, 161, 162, 252, 163, 164, 165, 166, 167, 168,
+ 169, 157, 164, 163, 170, 171, 175, 171, 175, 240,
+ 175, 175, 177, 519, 177, 193, 177, 177, 171, 184,
+ 171, 184, 471, 184, 184, 252, 171, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 179, 500, 182, 179, 190, 190, 180, 203,
+ 179, 179, 179, 179, 179, 179, 182, 182, 307, 307,
+
+ 182, 182, 182, 182, 185, 185, 185, 185, 185, 174,
+ 185, 185, 185, 471, 185, 253, 148, 190, 190, 183,
+ 203, 138, 179, 179, 179, 179, 179, 179, 183, 183,
+ 187, 183, 183, 188, 500, 191, 183, 191, 187, 188,
+ 183, 186, 186, 186, 186, 186, 253, 186, 186, 186,
+ 185, 186, 179, 179, 179, 192, 123, 189, 194, 538,
+ 192, 187, 195, 189, 188, 197, 191, 195, 191, 187,
+ 188, 194, 196, 122, 183, 194, 186, 198, 199, 198,
+ 199, 197, 117, 196, 202, 200, 192, 186, 189, 538,
+ 194, 192, 202, 195, 189, 200, 204, 197, 195, 257,
+
+ 200, 204, 194, 232, 196, 232, 194, 186, 198, 199,
+ 198, 199, 197, 201, 196, 202, 105, 200, 205, 279,
+ 201, 201, 206, 202, 285, 205, 200, 204, 543, 206,
+ 257, 200, 204, 207, 207, 222, 222, 222, 224, 224,
+ 224, 227, 227, 84, 201, 230, 230, 235, 235, 205,
+ 279, 201, 201, 206, 232, 285, 205, 246, 246, 246,
+ 206, 242, 242, 83, 207, 207, 264, 264, 264, 236,
+ 255, 259, 82, 260, 227, 237, 262, 262, 230, 543,
+ 235, 236, 236, 239, 236, 236, 236, 237, 237, 278,
+ 237, 237, 237, 282, 242, 239, 239, 283, 239, 239,
+
+ 239, 284, 255, 259, 227, 260, 280, 280, 230, 262,
+ 235, 269, 269, 269, 335, 335, 269, 303, 303, 303,
+ 236, 278, 236, 472, 242, 282, 237, 472, 237, 283,
+ 270, 270, 270, 284, 239, 270, 239, 280, 280, 262,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 268, 268,
+ 268, 268, 268, 268, 268, 268, 268, 268, 272, 272,
+ 272, 286, 287, 272, 288, 289, 290, 291, 76, 292,
+ 293, 294, 295, 296, 73, 298, 299, 300, 301, 305,
+ 305, 305, 51, 311, 337, 337, 316, 318, 318, 29,
+ 311, 311, 286, 287, 26, 288, 289, 290, 22, 291,
+ 292, 293, 294, 308, 295, 296, 298, 299, 17, 300,
+ 301, 0, 308, 308, 311, 308, 308, 316, 318, 318,
+ 308, 311, 311, 313, 308, 309, 309, 309, 309, 309,
+
+ 313, 309, 309, 309, 312, 309, 310, 310, 310, 310,
+ 310, 314, 310, 310, 310, 317, 310, 320, 314, 309,
+ 340, 340, 315, 312, 317, 313, 320, 319, 308, 319,
+ 321, 313, 315, 310, 328, 312, 323, 321, 322, 0,
+ 323, 309, 325, 314, 347, 325, 317, 322, 320, 314,
+ 0, 309, 310, 340, 315, 317, 0, 320, 319, 0,
+ 319, 321, 324, 315, 310, 328, 324, 323, 321, 0,
+ 322, 323, 326, 325, 327, 347, 325, 333, 322, 326,
+ 329, 327, 330, 340, 329, 348, 330, 331, 332, 341,
+ 341, 333, 333, 324, 331, 332, 350, 324, 334, 334,
+
+ 343, 343, 351, 360, 326, 362, 327, 352, 352, 363,
+ 326, 329, 327, 330, 364, 329, 348, 330, 366, 331,
+ 332, 367, 0, 368, 369, 331, 332, 350, 333, 370,
+ 372, 373, 374, 351, 360, 334, 362, 375, 376, 334,
+ 377, 363, 378, 379, 381, 364, 383, 384, 384, 0,
+ 366, 385, 385, 367, 368, 369, 387, 386, 386, 387,
+ 370, 372, 388, 373, 374, 391, 0, 392, 375, 386,
+ 376, 389, 377, 378, 379, 381, 398, 383, 392, 389,
+ 390, 388, 394, 390, 393, 0, 395, 387, 396, 397,
+ 387, 394, 0, 388, 395, 393, 391, 396, 399, 392,
+
+ 401, 499, 389, 499, 406, 399, 401, 398, 397, 392,
+ 389, 400, 390, 394, 390, 404, 393, 395, 400, 396,
+ 397, 403, 394, 404, 407, 395, 393, 402, 396, 0,
+ 399, 401, 403, 405, 402, 406, 399, 401, 408, 409,
+ 405, 0, 410, 400, 411, 411, 404, 409, 422, 400,
+ 412, 412, 408, 403, 404, 407, 410, 410, 423, 402,
+ 414, 414, 429, 403, 405, 402, 416, 416, 424, 408,
+ 409, 405, 418, 418, 420, 420, 426, 426, 409, 428,
+ 422, 411, 408, 430, 433, 411, 431, 432, 434, 423,
+ 435, 0, 437, 410, 429, 436, 436, 436, 438, 424,
+
+ 439, 0, 440, 441, 442, 436, 443, 444, 446, 447,
+ 428, 448, 452, 456, 452, 430, 433, 431, 432, 434,
+ 453, 455, 435, 437, 454, 0, 454, 0, 457, 438,
+ 455, 453, 439, 440, 441, 442, 457, 443, 0, 444,
+ 446, 447, 448, 452, 456, 452, 458, 458, 458, 466,
+ 0, 460, 453, 455, 475, 454, 458, 454, 460, 459,
+ 457, 455, 453, 459, 461, 464, 462, 457, 462, 463,
+ 461, 464, 463, 465, 0, 467, 468, 0, 470, 476,
+ 466, 465, 467, 460, 477, 458, 475, 468, 469, 460,
+ 459, 469, 473, 473, 459, 461, 464, 462, 479, 462,
+
+ 463, 461, 464, 463, 480, 465, 481, 467, 468, 470,
+ 476, 482, 465, 467, 483, 477, 458, 485, 468, 469,
+ 489, 0, 469, 478, 478, 478, 484, 484, 484, 479,
+ 486, 486, 486, 478, 493, 480, 484, 481, 492, 494,
+ 486, 496, 497, 482, 498, 502, 483, 502, 517, 485,
+ 0, 489, 490, 490, 490, 491, 491, 491, 501, 501,
+ 501, 0, 490, 504, 0, 491, 493, 504, 501, 492,
+ 494, 503, 496, 497, 507, 498, 502, 506, 502, 517,
+ 503, 505, 505, 505, 506, 522, 508, 508, 508, 0,
+ 511, 505, 510, 507, 0, 504, 508, 501, 504, 511,
+
+ 510, 516, 503, 516, 512, 507, 509, 509, 509, 506,
+ 513, 503, 512, 514, 0, 506, 509, 522, 515, 523,
+ 505, 514, 511, 510, 525, 508, 515, 524, 501, 513,
+ 511, 510, 516, 545, 516, 512, 520, 520, 520, 0,
+ 530, 513, 531, 512, 514, 509, 520, 0, 0, 515,
+ 523, 505, 514, 536, 537, 525, 508, 515, 539, 524,
+ 527, 527, 527, 529, 529, 529, 541, 532, 532, 532,
+ 527, 530, 542, 529, 531, 548, 509, 532, 534, 534,
+ 534, 540, 540, 540, 545, 536, 537, 546, 534, 539,
+ 547, 540, 549, 549, 549, 546, 552, 547, 541, 556,
+
+ 550, 551, 549, 550, 542, 557, 548, 551, 554, 552,
+ 553, 553, 553, 558, 0, 554, 555, 0, 546, 561,
+ 553, 564, 547, 555, 0, 0, 546, 552, 547, 565,
+ 556, 549, 550, 551, 550, 566, 567, 557, 551, 552,
+ 554, 559, 559, 559, 569, 558, 554, 574, 555, 553,
+ 561, 559, 0, 564, 555, 562, 562, 562, 0, 576,
+ 565, 577, 549, 0, 583, 562, 566, 0, 567, 568,
+ 568, 568, 570, 570, 570, 569, 572, 572, 572, 568,
+ 553, 588, 570, 573, 573, 573, 572, 575, 575, 575,
+ 576, 578, 577, 573, 578, 583, 584, 575, 574, 579,
+
+ 579, 579, 580, 580, 580, 581, 581, 581, 589, 579,
+ 590, 0, 580, 588, 591, 581, 594, 0, 585, 585,
+ 585, 0, 601, 578, 602, 578, 575, 584, 585, 587,
+ 587, 587, 600, 592, 592, 592, 603, 0, 579, 587,
+ 589, 580, 590, 592, 581, 591, 606, 594, 595, 595,
+ 595, 597, 597, 597, 601, 599, 602, 575, 595, 609,
+ 615, 597, 599, 600, 604, 604, 604, 610, 603, 579,
+ 611, 616, 580, 619, 604, 581, 612, 606, 607, 607,
+ 607, 620, 621, 612, 617, 617, 617, 599, 607, 611,
+ 622, 609, 615, 599, 617, 623, 0, 624, 610, 626,
+
+ 627, 611, 628, 616, 619, 625, 625, 625, 612, 634,
+ 0, 635, 620, 621, 612, 625, 629, 0, 637, 629,
+ 637, 622, 638, 639, 632, 632, 632, 623, 624, 640,
+ 626, 641, 627, 628, 632, 642, 643, 647, 641, 644,
+ 648, 634, 635, 645, 652, 645, 0, 0, 629, 637,
+ 629, 637, 649, 638, 653, 639, 0, 654, 654, 655,
+ 640, 649, 656, 641, 661, 658, 642, 643, 647, 641,
+ 664, 644, 648, 0, 645, 652, 645, 646, 646, 646,
+ 650, 650, 650, 649, 0, 653, 657, 646, 654, 654,
+ 650, 655, 649, 660, 656, 661, 657, 658, 662, 664,
+
+ 660, 0, 0, 0, 662, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 657, 0,
+ 0, 0, 0, 0, 0, 660, 0, 657, 0, 662,
+ 664, 660, 0, 0, 0, 662, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 667, 667,
+ 667, 667, 667, 667, 667, 667, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 668, 668, 668, 668,
+ 668, 668, 668, 668, 668, 668, 669, 669, 669, 669,
+
+ 669, 669, 669, 669, 669, 669, 669, 669, 669, 669,
+ 669, 669, 669, 669, 669, 669, 669, 669, 669, 669,
+ 669, 669, 669, 669, 669, 669, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 670, 670, 670, 670,
+ 670, 670, 670, 670, 670, 670, 671, 0, 0, 0,
+ 671, 671, 671, 671, 671, 671, 671, 671, 671, 671,
+ 671, 671, 671, 671, 671, 671, 671, 671, 671, 671,
+ 671, 671, 671, 671, 671, 671, 672, 672, 672, 672,
+ 672, 672, 672, 672, 672, 672, 672, 672, 672, 672,
+
+ 672, 672, 672, 672, 672, 672, 672, 672, 672, 672,
+ 672, 672, 672, 672, 672, 672, 673, 673, 673, 673,
+ 673, 673, 673, 674, 674, 0, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 675, 675, 675, 675, 675, 675, 675,
+ 675, 675, 675, 675, 675, 675, 675, 675, 675, 675,
+ 675, 675, 675, 675, 675, 675, 675, 675, 675, 675,
+ 675, 675, 675, 676, 676, 676, 0, 0, 676, 676,
+ 0, 676, 0, 0, 0, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 677, 677, 0, 0, 0, 0, 0,
+ 677, 677, 677, 677, 677, 677, 677, 678, 0, 678,
+ 0, 0, 0, 0, 678, 678, 0, 678, 0, 0,
+ 0, 0, 678, 0, 0, 0, 0, 678, 678, 678,
+ 678, 678, 678, 678, 679, 0, 679, 0, 679, 0,
+ 679, 0, 0, 0, 0, 0, 0, 679, 679, 679,
+ 679, 679, 679, 679, 680, 0, 0, 680, 680, 0,
+ 680, 680, 680, 0, 0, 0, 0, 680, 680, 680,
+ 680, 680, 680, 680, 681, 681, 0, 681, 681, 681,
+ 681, 681, 681, 681, 681, 681, 681, 681, 681, 681,
+
+ 681, 681, 681, 681, 681, 681, 681, 681, 681, 681,
+ 681, 681, 681, 681, 682, 0, 0, 0, 0, 682,
+ 0, 0, 682, 682, 0, 0, 0, 0, 0, 682,
+ 682, 682, 682, 682, 682, 682, 683, 683, 683, 683,
+ 683, 0, 683, 683, 0, 683, 0, 0, 0, 683,
+ 683, 683, 683, 683, 683, 683, 683, 684, 684, 684,
+ 684, 684, 684, 684, 684, 684, 684, 684, 684, 684,
+ 684, 684, 684, 684, 684, 684, 684, 684, 684, 684,
+ 684, 684, 684, 684, 684, 684, 684, 685, 685, 685,
+ 685, 685, 685, 685, 685, 685, 685, 685, 685, 685,
+
+ 685, 685, 685, 685, 685, 685, 685, 685, 685, 685,
+ 685, 685, 685, 685, 685, 685, 685, 686, 0, 686,
+ 686, 0, 0, 0, 0, 0, 686, 686, 686, 686,
+ 686, 686, 686, 686, 687, 687, 687, 687, 687, 687,
+ 687, 687, 687, 687, 687, 687, 687, 687, 687, 687,
+ 687, 687, 687, 687, 687, 687, 687, 687, 687, 687,
+ 687, 687, 687, 687, 688, 688, 688, 688, 688, 688,
+ 688, 688, 0, 688, 688, 688, 688, 688, 688, 688,
+ 688, 688, 688, 688, 688, 688, 688, 688, 688, 688,
+ 688, 688, 688, 688, 689, 0, 0, 0, 689, 689,
+
+ 689, 689, 689, 689, 689, 689, 689, 689, 689, 689,
+ 689, 689, 689, 689, 689, 689, 689, 689, 689, 689,
+ 689, 689, 689, 689, 690, 690, 0, 690, 690, 0,
+ 0, 0, 0, 0, 690, 690, 690, 690, 690, 690,
+ 690, 690, 691, 691, 691, 691, 691, 691, 0, 691,
+ 691, 691, 691, 691, 691, 691, 691, 691, 691, 691,
+ 691, 691, 691, 691, 691, 691, 691, 691, 691, 691,
+ 691, 691, 692, 692, 692, 692, 692, 692, 692, 692,
+ 692, 692, 692, 692, 692, 692, 692, 692, 692, 692,
+ 692, 692, 692, 692, 692, 692, 692, 692, 692, 692,
+
+ 692, 692, 693, 693, 693, 693, 693, 693, 693, 693,
+ 693, 693, 693, 693, 693, 693, 693, 693, 693, 693,
+ 693, 693, 693, 693, 693, 693, 693, 693, 693, 693,
+ 693, 693, 694, 0, 694, 0, 0, 0, 0, 694,
+ 694, 694, 694, 694, 0, 0, 0, 0, 694, 694,
+ 694, 694, 694, 694, 694, 694, 694, 695, 695, 695,
+ 695, 695, 695, 695, 695, 695, 695, 695, 695, 695,
+ 695, 695, 695, 695, 695, 695, 695, 695, 695, 695,
+ 695, 695, 695, 695, 695, 695, 695, 696, 696, 0,
+ 0, 0, 0, 0, 696, 696, 696, 696, 696, 696,
+
+ 696, 696, 697, 697, 697, 697, 697, 697, 697, 697,
+ 697, 697, 697, 697, 697, 697, 697, 697, 697, 697,
+ 697, 697, 697, 697, 697, 697, 697, 697, 697, 697,
+ 697, 697, 698, 698, 698, 698, 698, 698, 698, 698,
+ 698, 698, 698, 698, 698, 698, 698, 698, 698, 698,
+ 698, 698, 698, 698, 698, 698, 698, 698, 698, 698,
+ 698, 698, 699, 699, 699, 699, 699, 699, 699, 699,
+ 699, 699, 699, 699, 699, 699, 699, 699, 699, 699,
+ 699, 699, 699, 699, 699, 699, 699, 699, 699, 699,
+ 699, 699, 700, 700, 0, 700, 700, 700, 700, 700,
+
+ 700, 700, 700, 700, 700, 700, 700, 700, 700, 700,
+ 700, 700, 700, 700, 700, 700, 700, 700, 700, 700,
+ 700, 700, 701, 701, 701, 701, 701, 701, 701, 701,
+ 701, 701, 701, 701, 701, 701, 701, 701, 701, 701,
+ 701, 701, 701, 701, 701, 701, 701, 701, 701, 701,
+ 701, 701, 702, 702, 0, 702, 702, 702, 702, 702,
+ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702,
+ 702, 702, 703, 703, 703, 0, 0, 703, 703, 0,
+ 703, 0, 0, 0, 703, 703, 703, 703, 703, 703,
+
+ 703, 703, 704, 704, 704, 0, 0, 0, 0, 704,
+ 704, 704, 704, 704, 704, 704, 705, 0, 705, 0,
+ 0, 0, 0, 705, 705, 0, 705, 0, 0, 0,
+ 0, 705, 0, 0, 0, 0, 705, 705, 705, 705,
+ 705, 705, 705, 706, 0, 706, 0, 706, 0, 706,
+ 0, 0, 0, 0, 0, 0, 706, 706, 706, 706,
+ 706, 706, 706, 707, 707, 0, 707, 707, 707, 0,
+ 0, 0, 0, 707, 707, 707, 707, 707, 707, 707,
+ 708, 0, 0, 0, 0, 708, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 708, 708, 708, 708, 708,
+
+ 708, 708, 709, 0, 0, 0, 709, 0, 709, 0,
+ 709, 0, 709, 0, 0, 709, 709, 0, 0, 709,
+ 709, 709, 709, 709, 709, 709, 710, 710, 710, 710,
+ 710, 710, 710, 710, 710, 710, 710, 710, 710, 710,
+ 710, 710, 710, 710, 710, 710, 710, 710, 710, 710,
+ 710, 710, 710, 710, 710, 710, 711, 0, 0, 0,
+ 0, 0, 0, 711, 711, 0, 0, 711, 711, 711,
+ 0, 0, 0, 0, 711, 711, 711, 711, 711, 711,
+ 711, 712, 0, 0, 0, 712, 712, 712, 712, 712,
+ 0, 712, 712, 0, 712, 712, 0, 0, 712, 712,
+
+ 712, 712, 712, 712, 712, 712, 713, 713, 713, 713,
+ 713, 0, 713, 713, 0, 713, 0, 0, 0, 713,
+ 713, 713, 713, 713, 713, 713, 713, 714, 714, 714,
+ 714, 714, 714, 714, 714, 714, 714, 714, 714, 714,
+ 714, 714, 714, 714, 714, 714, 714, 714, 714, 714,
+ 714, 714, 714, 714, 714, 714, 714, 715, 0, 715,
+ 0, 0, 0, 0, 0, 0, 715, 0, 0, 0,
+ 0, 715, 0, 715, 715, 0, 0, 715, 715, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716, 716, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716, 716, 716,
+
+ 716, 716, 716, 716, 716, 716, 716, 716, 716, 717,
+ 0, 717, 717, 0, 0, 0, 0, 0, 717, 717,
+ 717, 717, 717, 717, 717, 717, 718, 718, 718, 718,
+ 718, 718, 718, 718, 718, 718, 718, 718, 718, 718,
+ 718, 718, 718, 718, 718, 718, 718, 718, 718, 718,
+ 718, 718, 718, 718, 718, 718, 719, 0, 0, 0,
+ 0, 0, 0, 719, 0, 0, 0, 0, 719, 0,
+ 719, 719, 0, 0, 719, 719, 0, 0, 719, 720,
+ 720, 720, 720, 720, 720, 720, 720, 0, 720, 720,
+ 720, 720, 720, 720, 720, 720, 720, 720, 720, 720,
+
+ 720, 720, 720, 720, 720, 720, 720, 720, 720, 721,
+ 0, 0, 0, 721, 721, 721, 721, 721, 721, 721,
+ 721, 721, 721, 721, 721, 721, 721, 721, 721, 721,
+ 721, 721, 721, 721, 721, 721, 721, 721, 721, 722,
+ 722, 0, 722, 722, 0, 0, 0, 0, 0, 722,
+ 722, 722, 722, 722, 722, 722, 722, 723, 723, 723,
+ 723, 723, 723, 0, 723, 723, 723, 723, 723, 723,
+ 723, 723, 723, 723, 723, 723, 723, 723, 723, 723,
+ 723, 723, 723, 723, 723, 723, 723, 724, 724, 724,
+ 0, 0, 0, 0, 0, 0, 724, 0, 0, 0,
+
+ 0, 0, 0, 0, 724, 0, 0, 724, 0, 724,
+ 725, 725, 725, 725, 725, 725, 725, 725, 725, 725,
+ 725, 725, 725, 725, 725, 725, 725, 725, 725, 725,
+ 725, 725, 725, 725, 725, 725, 725, 725, 725, 725,
+ 726, 726, 726, 0, 0, 0, 0, 0, 0, 726,
+ 0, 0, 0, 0, 0, 0, 0, 726, 0, 0,
+ 726, 0, 726, 727, 727, 727, 727, 727, 727, 727,
+ 727, 727, 727, 727, 727, 727, 727, 727, 727, 727,
+ 727, 727, 727, 727, 727, 727, 727, 727, 727, 727,
+ 727, 727, 727, 728, 728, 728, 728, 728, 728, 728,
+
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
+ 728, 728, 728, 729, 729, 729, 0, 0, 0, 0,
+ 0, 0, 729, 0, 0, 0, 0, 0, 0, 0,
+ 729, 0, 0, 729, 0, 729, 730, 0, 0, 0,
+ 0, 0, 0, 730, 730, 0, 730, 730, 0, 0,
+ 0, 0, 730, 730, 730, 730, 730, 730, 730, 730,
+ 730, 731, 0, 0, 0, 0, 0, 0, 731, 731,
+ 0, 731, 731, 0, 0, 0, 0, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 732, 732, 732, 732,
+
+ 732, 732, 732, 732, 732, 732, 732, 732, 732, 732,
+ 732, 732, 732, 732, 732, 732, 732, 732, 732, 732,
+ 732, 732, 732, 732, 732, 732, 733, 733, 733, 0,
+ 0, 0, 0, 0, 0, 733, 0, 0, 0, 0,
+ 0, 0, 0, 733, 0, 0, 733, 0, 733, 734,
+ 734, 0, 0, 0, 0, 0, 734, 734, 734, 735,
+ 735, 0, 0, 0, 0, 0, 735, 735, 735, 735,
+ 735, 735, 735, 735, 736, 736, 736, 736, 736, 736,
+ 736, 736, 736, 736, 736, 736, 736, 736, 736, 736,
+ 736, 736, 736, 736, 736, 736, 736, 736, 736, 736,
+
+ 736, 736, 736, 736, 737, 0, 737, 0, 0, 0,
+ 0, 0, 0, 737, 0, 0, 0, 0, 0, 0,
+ 0, 737, 0, 0, 737, 0, 737, 0, 737, 738,
+ 738, 738, 738, 738, 738, 738, 738, 738, 738, 738,
+ 738, 738, 738, 738, 738, 738, 738, 738, 738, 738,
+ 738, 738, 738, 738, 738, 738, 738, 738, 738, 739,
+ 739, 739, 739, 739, 739, 739, 739, 739, 739, 739,
+ 739, 739, 739, 739, 739, 739, 739, 739, 739, 739,
+ 739, 739, 739, 739, 739, 739, 739, 739, 739, 740,
+ 740, 740, 740, 740, 740, 740, 740, 740, 740, 740,
+
+ 740, 740, 740, 740, 740, 740, 740, 740, 740, 740,
+ 740, 740, 740, 740, 740, 740, 740, 740, 740, 741,
+ 741, 741, 741, 741, 741, 741, 741, 741, 741, 741,
+ 741, 741, 741, 741, 741, 741, 741, 741, 741, 741,
+ 741, 741, 741, 741, 741, 741, 741, 741, 741, 742,
+ 742, 0, 742, 742, 742, 742, 742, 742, 742, 742,
+ 742, 742, 742, 742, 742, 742, 742, 742, 742, 742,
+ 742, 742, 742, 742, 742, 742, 742, 742, 742, 743,
+ 743, 0, 743, 743, 743, 743, 743, 743, 743, 743,
+ 743, 743, 743, 743, 743, 743, 743, 743, 743, 743,
+
+ 743, 743, 743, 743, 743, 743, 743, 743, 743, 744,
+ 744, 0, 744, 744, 744, 744, 744, 744, 744, 744,
+ 744, 744, 744, 744, 744, 744, 744, 744, 744, 744,
+ 744, 744, 744, 744, 744, 744, 744, 744, 744, 745,
+ 745, 0, 745, 745, 745, 745, 745, 745, 745, 745,
+ 745, 745, 745, 745, 745, 745, 745, 745, 745, 745,
+ 745, 745, 745, 745, 745, 745, 745, 745, 745, 746,
+ 746, 746, 0, 0, 746, 746, 0, 746, 0, 0,
+ 0, 746, 746, 746, 746, 746, 746, 746, 746, 747,
+ 0, 0, 0, 747, 0, 747, 0, 747, 0, 747,
+
+ 0, 0, 747, 747, 0, 0, 747, 747, 747, 747,
+ 747, 747, 747, 748, 748, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 748, 748, 748, 748, 748, 748, 748, 749, 0,
+ 0, 0, 749, 749, 749, 749, 749, 0, 749, 749,
+ 0, 749, 749, 0, 0, 749, 749, 749, 749, 749,
+ 749, 749, 749, 750, 750, 750, 750, 750, 0, 750,
+ 750, 0, 750, 0, 0, 0, 750, 750, 750, 750,
+ 750, 750, 750, 750, 751, 751, 751, 751, 751, 751,
+ 751, 751, 751, 751, 751, 751, 751, 751, 751, 751,
+
+ 751, 751, 751, 751, 751, 751, 751, 751, 751, 751,
+ 751, 751, 751, 751, 752, 752, 752, 752, 752, 752,
+ 752, 752, 752, 752, 752, 752, 752, 752, 752, 752,
+ 752, 752, 752, 752, 752, 752, 752, 752, 752, 752,
+ 752, 752, 752, 752, 753, 753, 0, 0, 0, 0,
+ 0, 753, 753, 753, 754, 754, 0, 0, 0, 0,
+ 0, 754, 754, 754, 755, 755, 755, 0, 0, 0,
+ 0, 0, 0, 755, 0, 0, 0, 0, 0, 0,
+ 0, 755, 0, 0, 755, 0, 755, 756, 756, 0,
+ 0, 0, 0, 0, 756, 756, 756, 757, 757, 0,
+
+ 0, 0, 0, 0, 757, 757, 757, 758, 758, 0,
+ 0, 0, 0, 0, 758, 758, 758, 759, 759, 0,
+ 0, 0, 0, 0, 759, 759, 759, 759, 759, 759,
+ 759, 759, 760, 760, 0, 0, 0, 0, 0, 760,
+ 760, 760, 761, 761, 761, 761, 761, 761, 761, 761,
+ 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
+ 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
+ 761, 761, 762, 762, 762, 762, 762, 762, 762, 762,
+ 762, 762, 762, 762, 762, 762, 762, 762, 762, 762,
+ 762, 762, 762, 762, 762, 762, 762, 762, 762, 762,
+
+ 762, 762, 763, 763, 0, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 763, 763, 763, 763, 763, 763, 763, 763,
+ 763, 763, 764, 764, 0, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 764, 764, 764, 764, 764, 764, 764, 764,
+ 764, 764, 765, 765, 0, 0, 0, 0, 0, 765,
+ 765, 765, 766, 766, 0, 0, 0, 0, 0, 766,
+ 766, 766, 767, 767, 0, 0, 0, 0, 0, 767,
+ 767, 767, 768, 768, 0, 0, 0, 0, 0, 768,
+
+ 768, 768, 769, 769, 0, 0, 0, 0, 0, 769,
+ 769, 769, 770, 770, 0, 0, 0, 0, 0, 770,
+ 770, 770, 771, 771, 0, 0, 0, 0, 0, 771,
+ 771, 771, 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 772, 772, 772, 772, 772,
+ 772, 772, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static const flex_int32_t yy_rule_can_match_eol[122] =
+ { 0,
+0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1,
+ 0, 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 "lexer.l"
+#line 2 "lexer.l"
+ /* Lex file for rsyslog config format v2 (RainerScript).
+ * Please note: this file introduces the new config format, but maintains
+ * backward compatibility. In order to do so, the grammar is not 100% clean,
+ * but IMHO still sufficiently easy both to understand for programmers
+ * maitaining the code as well as users writing the config file. Users are,
+ * of course, encouraged to use new constructs only. But it needs to be noted
+ * that some of the legacy constructs (specifically the in-front-of-action
+ * PRI filter) are very hard to beat in ease of use, at least for simpler
+ * cases. So while we hope that cfsysline support can be dropped some time in
+ * the future, we will probably keep these useful constructs.
+ *
+ * Copyright 2011-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libestr.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "parserif.h"
+
+PRAGMA_IGNORE_Wsign_compare
+PRAGMA_IGNORE_Wmissing_noreturn
+
+FILE *fp_rs_full_conf_output = NULL;
+
+/* TODO: move this to a better modules, refactor -- rgerhards, 2018-01-22 */
+static char *
+read_file(const char *const filename)
+{
+ char *content = NULL;
+ int fd = -1;
+ struct stat sb;
+ ssize_t nread;
+ assert(filename != NULL);
+
+ if((fd = open((const char*) filename, O_RDONLY)) == -1) {
+ goto done;
+ }
+
+ if(fstat(fd, &sb) == -1) {
+ goto done;
+ }
+
+ content = malloc(sb.st_size+1);
+ if(content == NULL) {
+ goto done;
+ }
+
+ nread = read(fd, content, sb.st_size);
+ content[nread] = '\0';
+ if(nread != (ssize_t) sb.st_size) {
+ free(content);
+ content = NULL;
+ goto done;
+ }
+
+done:
+ if(fd != -1) {
+ close(fd);
+ }
+ return content;
+}
+
+static es_str_t* ATTR_NONNULL(1)
+expand_backticks_echo(const char *param)
+{
+ assert(param != NULL);
+ assert(strncmp(param, "echo ", sizeof("echo ")-1) == 0);
+ char envvar[512];
+ int i_envvar = 0;
+ int in_env = 0;
+ es_str_t *estr;
+
+ param += sizeof("echo ")-1;
+ if((estr = es_newStr(strlen(param))) == NULL) {
+ goto done;
+ }
+
+ while(*param) {
+ if(in_env) {
+ if(isspace(*param) || *param == '/') {
+ envvar[i_envvar] = '\0';
+ const char *envval = getenv(envvar);
+ if(envval != NULL)
+ es_addBuf(&estr, envval, strlen(envval));
+ es_addChar(&estr, *param); /* curr char part of output! */
+ i_envvar = 0;
+ in_env = 0;
+ } else if(i_envvar > sizeof(envvar) - 1) {
+ parser_errmsg("environment variable too long, begins with %s", envvar);
+ goto done;
+ } else {
+ envvar[i_envvar++] = *param;
+ }
+ } else if (*param == '$') {
+ in_env = 1;
+ } else {
+ es_addChar(&estr, *param);
+ }
+ ++param;
+ }
+
+ /* final check, we may be in env var name (very probable!) */
+ if(in_env) {
+ envvar[i_envvar] = '\0';
+ const char *envval = getenv(envvar);
+ if(envval != NULL)
+ es_addBuf(&estr, envval, strlen(envval));
+ }
+
+done: return estr;
+}
+
+
+static es_str_t* ATTR_NONNULL(1)
+expand_backticks(char *const param)
+{
+ es_str_t *estr;
+ assert(param != NULL);
+
+ if(strncmp(param, "echo ", sizeof("echo ")-1) == 0) {
+ estr = expand_backticks_echo(param);
+ } else if(strncmp(param, "cat ", sizeof("cat ")-1) == 0) {
+ const char *val = read_file(param+4);
+ if(val == NULL) {
+ parser_errmsg("file could not be accessed for `%s`", param);
+ const char *errmsg = "/* file cound not be accessed - see"
+ "error messages */";
+ estr = es_newStrFromCStr(errmsg, strlen(errmsg));
+ } else {
+ estr = es_newStrFromCStr(val, strlen(val));
+ }
+ free((void*) val);
+ } else {
+ parser_errmsg("invalid backtick parameter `%s` - replaced by "
+ "empty string (\"\")", param);
+ estr = es_newStr(1);
+ }
+
+ return estr;
+}
+#line 1974 "lexer.c"
+#line 172 "lexer.l"
+ /*%option noyywrap nodefault case-insensitive */
+/* avoid compiler warning: `yyunput' defined but not used */
+#define YY_NO_INPUT 1
+
+ /* INOBJ is selected if we are inside an object (name/value pairs!) */
+
+ /* COMMENT is "the usual trick" to handle C-style comments */
+
+ /* INCL is in $IncludeConfig processing (skip to include file) */
+
+ /* LINENO: support for setting the linenumber */
+
+ /* INCALL: support for the call statement */
+
+ /* IN_PROCEDURE_CALL: support for the call statement */
+
+ /* EXPR is a bit ugly, but we need it to support pre v6-syntax. The problem
+ * is that cfsysline statement start with $..., the same like variables in
+ * an expression. However, cfsysline statements can never appear inside an
+ * expression. So we create a specific expr mode, which is turned on after
+ * we lexed a keyword that needs to be followed by an expression (using
+ * knowledge from the upper layer...). In expr mode, we strictly do
+ * expression-based parsing. Expr mode is stopped when we reach a token
+ * that can not be part of an expression (currently only "then"). As I
+ * wrote this ugly, but the price needed to pay in order to remain
+ * compatible to the previous format.
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <libestr.h>
+#include "rainerscript.h"
+#include "parserif.h"
+#include "grammar.h"
+static int preCommentState; /* save for lex state before a comment */
+
+struct bufstack {
+ struct bufstack *prev;
+ YY_BUFFER_STATE bs;
+ int lineno;
+ char *fn;
+ es_str_t *estr;
+} *currbs = NULL;
+
+char *cnfcurrfn; /* name of currently processed file */
+
+int popfile(void);
+int cnfSetLexFile(const char *fname);
+
+static void cnfPrintToken(const char *token);
+extern int yydebug;
+
+/* somehow, I need these prototype even though the headers are
+ * included. I guess that's some autotools magic I don't understand...
+ */
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) \
+ && !defined(__DragonflyBSD__) && !defined(_AIX)
+int fileno(FILE *stream);
+#endif
+
+
+#line 2039 "lexer.c"
+#line 2040 "lexer.c"
+
+#define INITIAL 0
+#define INOBJ 1
+#define COMMENT 2
+#define INCL 3
+#define LINENO 4
+#define INCALL 5
+#define IN_PROCEDURE_CALL 6
+#define EXPR 7
+
+#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 );
+
+ int 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
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const 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, (size_t) 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 = '*'; \
+ int 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 = (int) fread(buf, 1, (yy_size_t) 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 /*LINTED*/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
+{
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ 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 240 "lexer.l"
+
+
+#line 243 "lexer.l"
+ /* keywords */
+#line 2270 "lexer.c"
+
+ while ( /*CONSTCOND*/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
+ {
+ 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 >= 667 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 4863 );
+
+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] )
+ {
+ int 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:
+YY_RULE_SETUP
+#line 244 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return IF; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 245 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return FOREACH; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 246 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN IN_PROCEDURE_CALL; return RELOAD_LOOKUP_TABLE_PROCEDURE; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 247 "lexer.l"
+{ cnfPrintToken(yytext); return yytext[0]; }
+ YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+#line 248 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 253 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 258 "lexer.l"
+{ cnfPrintToken(yytext); return yytext[0]; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 259 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; return yytext[0]; }
+ YY_BREAK
+case 9:
+/* rule 9 can match eol */
+YY_RULE_SETUP
+#line 260 "lexer.l"
+{cnfPrintToken(yytext); }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 261 "lexer.l"
+{ cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in expression "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 264 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return yytext[0]; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 265 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; return THEN; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 266 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; return DO; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 267 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; return ';'; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 268 "lexer.l"
+{ cnfPrintToken(yytext); return OR; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 269 "lexer.l"
+{ cnfPrintToken(yytext); return AND; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 270 "lexer.l"
+{ cnfPrintToken(yytext); return NOT; }
+ YY_BREAK
+case 18:
+#line 272 "lexer.l"
+case 19:
+#line 273 "lexer.l"
+case 20:
+#line 274 "lexer.l"
+case 21:
+#line 275 "lexer.l"
+case 22:
+#line 276 "lexer.l"
+case 23:
+#line 277 "lexer.l"
+case 24:
+#line 278 "lexer.l"
+case 25:
+#line 279 "lexer.l"
+case 26:
+#line 280 "lexer.l"
+case 27:
+#line 281 "lexer.l"
+case 28:
+YY_RULE_SETUP
+#line 281 "lexer.l"
+{ cnfPrintToken(yytext); return yytext[0]; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 282 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_EQ; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 283 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_LE; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 284 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_GE; }
+ YY_BREAK
+case 32:
+#line 286 "lexer.l"
+case 33:
+YY_RULE_SETUP
+#line 286 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_NE; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 287 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_LT; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 288 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_GT; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 289 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_CONTAINS; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 290 "lexer.l"
+{ cnfPrintToken(yytext); return ITERATOR_ASSIGNMENT; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 291 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_CONTAINSI; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 292 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_STARTSWITH; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 293 "lexer.l"
+{ cnfPrintToken(yytext); return CMP_STARTSWITHI; }
+ YY_BREAK
+case 41:
+#line 295 "lexer.l"
+case 42:
+#line 296 "lexer.l"
+case 43:
+YY_RULE_SETUP
+#line 296 "lexer.l"
+{ cnfPrintToken(yytext); yylval.n = strtoll(yytext, NULL, 0); return NUMBER; }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 297 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(yytext+1); return VAR; }
+ YY_BREAK
+case 45:
+/* rule 45 can match eol */
+YY_RULE_SETUP
+#line 298 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ YY_BREAK
+case 46:
+/* rule 46 can match eol */
+YY_RULE_SETUP
+#line 303 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = expand_backticks(yytext+1);
+ return STRING; }
+ YY_BREAK
+case 47:
+/* rule 47 can match eol */
+YY_RULE_SETUP
+#line 308 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ YY_BREAK
+case 48:
+/* rule 48 can match eol */
+YY_RULE_SETUP
+#line 313 "lexer.l"
+{
+ cnfPrintToken(yytext); parser_errmsg("$-sign in double quotes must be "
+ "escaped, problem string is: %s",
+ yytext); }
+ YY_BREAK
+case 49:
+/* rule 49 can match eol */
+YY_RULE_SETUP
+#line 317 "lexer.l"
+{ cnfPrintToken(yytext); }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 318 "lexer.l"
+{ cnfPrintToken(yytext); return EXISTS; } /* special case function (see rainerscript.c) */
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 319 "lexer.l"
+{ cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ return FUNC; }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 321 "lexer.l"
+{ cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in expression "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+ YY_BREAK
+case 53:
+/* rule 53 can match eol */
+YY_RULE_SETUP
+#line 324 "lexer.l"
+{ cnfPrintToken(yytext); }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 325 "lexer.l"
+{ cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in 'call' statement"
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 328 "lexer.l"
+{ cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ BEGIN INITIAL;
+ return NAME; }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 331 "lexer.l"
+{ cnfPrintToken(yytext); return '&'; }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 332 "lexer.l"
+{ cnfPrintToken(yytext); return '{'; }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 333 "lexer.l"
+{ cnfPrintToken(yytext); return '}'; }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 334 "lexer.l"
+{ cnfPrintToken(yytext); return STOP; }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 335 "lexer.l"
+{ cnfPrintToken(yytext); return ELSE; }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 336 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INCALL; return CALL; }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 337 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return CALL_INDIRECT; }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 338 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return SET; }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 339 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return RESET; }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 340 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN EXPR; return UNSET; }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 341 "lexer.l"
+{ cnfPrintToken(yytext); return CONTINUE; }
+ YY_BREAK
+/* line number support because the "preprocessor" combines lines and so needs
+ * to tell us the real source line.
+ */
+case 67:
+YY_RULE_SETUP
+#line 345 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN LINENO; }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 346 "lexer.l"
+{ cnfPrintToken(yytext); yylineno = atoi(yytext) - 1; }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 347 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; }
+ YY_BREAK
+case 70:
+/* rule 70 can match eol */
+YY_RULE_SETUP
+#line 348 "lexer.l"
+
+ YY_BREAK
+/* $IncludeConfig must be detected as part of CFSYSLINE, because this is
+ * always the longest match :-(
+ */
+case 71:
+/* rule 71 can match eol */
+YY_RULE_SETUP
+#line 352 "lexer.l"
+
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 353 "lexer.l"
+{ cnfPrintToken(yytext); if(cnfDoInclude(yytext, 0) != 0)
+ yyterminate();
+ BEGIN INITIAL; }
+ YY_BREAK
+case 73:
+/* rule 73 can match eol */
+YY_RULE_SETUP
+#line 356 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_MAINQ;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 74:
+/* rule 74 can match eol */
+YY_RULE_SETUP
+#line 358 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_TIMEZONE;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 75:
+/* rule 75 can match eol */
+YY_RULE_SETUP
+#line 360 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_PARSER;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 76:
+/* rule 76 can match eol */
+YY_RULE_SETUP
+#line 362 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_GLOBAL;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 77:
+/* rule 77 can match eol */
+YY_RULE_SETUP
+#line 364 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_TPL;
+ BEGIN INOBJ; return BEGIN_TPL; }
+ YY_BREAK
+case 78:
+/* rule 78 can match eol */
+YY_RULE_SETUP
+#line 366 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_RULESET;
+ BEGIN INOBJ; return BEGIN_RULESET; }
+ YY_BREAK
+case 79:
+/* rule 79 can match eol */
+YY_RULE_SETUP
+#line 368 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_PROPERTY;
+ BEGIN INOBJ; return BEGIN_PROPERTY; }
+ YY_BREAK
+case 80:
+/* rule 80 can match eol */
+YY_RULE_SETUP
+#line 370 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_CONSTANT;
+ BEGIN INOBJ; return BEGIN_CONSTANT; }
+ YY_BREAK
+case 81:
+/* rule 81 can match eol */
+YY_RULE_SETUP
+#line 372 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_INPUT;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 82:
+/* rule 82 can match eol */
+YY_RULE_SETUP
+#line 374 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_MODULE;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 83:
+/* rule 83 can match eol */
+YY_RULE_SETUP
+#line 376 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_LOOKUP_TABLE;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 84:
+/* rule 84 can match eol */
+YY_RULE_SETUP
+#line 378 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_DYN_STATS;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 85:
+/* rule 85 can match eol */
+YY_RULE_SETUP
+#line 380 "lexer.l"
+{ cnfPrintToken(yytext); yylval.objType = CNFOBJ_PERCTILE_STATS;
+ BEGIN INOBJ; return BEGINOBJ; }
+ YY_BREAK
+case 86:
+/* rule 86 can match eol */
+YY_RULE_SETUP
+#line 382 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INOBJ; return BEGIN_INCLUDE; }
+ YY_BREAK
+case 87:
+/* rule 87 can match eol */
+YY_RULE_SETUP
+#line 383 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INOBJ; return BEGIN_ACTION; }
+ YY_BREAK
+case 88:
+/* rule 88 can match eol */
+YY_RULE_SETUP
+#line 384 "lexer.l"
+{
+ cnfPrintToken(yytext); yylval.s = strdup(rmLeadingSpace(yytext));
+ dbgprintf("lexer: propfilt is '%s'\n", yylval.s);
+ return PROPFILT;
+ }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 389 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; }
+ YY_BREAK
+case 90:
+#line 391 "lexer.l"
+case 91:
+#line 392 "lexer.l"
+case 92:
+/* rule 92 can match eol */
+#line 393 "lexer.l"
+case 93:
+/* rule 93 can match eol */
+#line 394 "lexer.l"
+case 94:
+/* rule 94 can match eol */
+#line 395 "lexer.l"
+case 95:
+/* rule 95 can match eol */
+#line 396 "lexer.l"
+case 96:
+/* rule 96 can match eol */
+YY_RULE_SETUP
+#line 396 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = yytext; return LEGACY_ACTION; }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 397 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN INITIAL; return ENDOBJ; }
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 398 "lexer.l"
+{ cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ return NAME; }
+ YY_BREAK
+case 99:
+#line 401 "lexer.l"
+case 100:
+#line 402 "lexer.l"
+case 101:
+#line 403 "lexer.l"
+case 102:
+YY_RULE_SETUP
+#line 403 "lexer.l"
+{ cnfPrintToken(yytext); return(yytext[0]); }
+ YY_BREAK
+case 103:
+/* rule 103 can match eol */
+YY_RULE_SETUP
+#line 404 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ YY_BREAK
+case 104:
+/* rule 104 can match eol */
+YY_RULE_SETUP
+#line 409 "lexer.l"
+{
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = expand_backticks(yytext+1);
+ return STRING; }
+ YY_BREAK
+/*yylval.estr = es_newStrFromBuf(yytext+1, yyleng-2);
+ return VALUE; }*/
+case 105:
+YY_RULE_SETUP
+#line 416 "lexer.l"
+{ cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 417 "lexer.l"
+{ cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 418 "lexer.l"
+{ cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 419 "lexer.l"
+{ cnfPrintToken(yytext); BEGIN preCommentState; }
+ YY_BREAK
+case 109:
+/* rule 109 can match eol */
+YY_RULE_SETUP
+#line 420 "lexer.l"
+
+ YY_BREAK
+case 110:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 421 "lexer.l"
+/* skip comments in input */
+ YY_BREAK
+case 111:
+/* rule 111 can match eol */
+YY_RULE_SETUP
+#line 422 "lexer.l"
+{ cnfPrintToken(yytext); }
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 423 "lexer.l"
+{ cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in object definition "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+ YY_BREAK
+case 113:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 426 "lexer.l"
+{ cnfPrintToken(yytext); /* see comment on $IncludeConfig above */
+ if(!strncasecmp(yytext, "$includeconfig ", 14)) {
+ yyless((yy_size_t)14);
+ BEGIN INCL;
+ } else if(!strncasecmp(yytext, "$ruleset ", 9)) {
+ yylval.s = strdup(yytext);
+ return LEGACY_RULESET;
+ } else {
+ cnfDoCfsysline(strdup(yytext));
+ }
+ }
+ YY_BREAK
+case 114:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 437 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_TAG_SELECTOR; }
+ YY_BREAK
+case 115:
+/* rule 115 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 438 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+ YY_BREAK
+case 116:
+/* rule 116 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 439 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+ YY_BREAK
+case 117:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 440 "lexer.l"
+{ cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+ YY_BREAK
+case 118:
+/* rule 118 can match eol */
+YY_RULE_SETUP
+#line 441 "lexer.l"
+{cnfPrintToken(yytext); }/* skip comments in input */
+ YY_BREAK
+case 119:
+/* rule 119 can match eol */
+YY_RULE_SETUP
+#line 442 "lexer.l"
+{cnfPrintToken(yytext); }/* drop whitespace */
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 443 "lexer.l"
+{ cnfPrintToken(yytext); parser_errmsg("invalid character '%s' "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(INOBJ):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(INCL):
+case YY_STATE_EOF(LINENO):
+case YY_STATE_EOF(INCALL):
+case YY_STATE_EOF(IN_PROCEDURE_CALL):
+case YY_STATE_EOF(EXPR):
+#line 446 "lexer.l"
+{ if(popfile() != 0) yyterminate(); }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 448 "lexer.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+#line 3030 "lexer.c"
+
+ 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)
+{
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ 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
+ {
+ int 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 )
+ {
+ int 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,
+ (yy_size_t) (b->yy_buf_size + 2) );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = NULL;
+
+ 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_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ int 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, (yy_size_t) new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+ }
+
+ (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)
+{
+ yy_state_type yy_current_state;
+ 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 )
+ {
+ 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 >= 667 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + 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 )
+{
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
+
+ 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 >= 667 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 666);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#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 */
+ int offset = (int) ((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 0;
+
+ 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( (yy_size_t) (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; /* After all that talk, this was set to 1 anyways... */
+ (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. */
+ yy_size_t 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 NULL;
+
+ 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 = (int) (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 = NULL;
+ 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 (const char * yystr )
+{
+
+ return yy_scan_bytes( yystr, (int) 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 (const char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = (yy_size_t) (_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 yynoreturn yy_fatal_error (const char* msg )
+{
+ 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.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number 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) = NULL;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = NULL;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = NULL;
+ yyout = NULL;
+#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, const char * s2, int n )
+{
+
+ int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s )
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return 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 realloc(ptr, size);
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 448 "lexer.l"
+
+static void cnfPrintToken(const char *token)
+{
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "%s", token);
+ }
+}
+
+/* add config file or text the the stack of config objects to be
+ * processed.
+ * cnfobjname is either the file name or "text" if generated from
+ * text ("text" can also be replaced by something more intelligent
+ * by the caller.
+ * The provided string is freed.
+ */
+int ATTR_NONNULL()
+cnfAddConfigBuffer(es_str_t *const str, const char *const cnfobj_name)
+{
+ struct bufstack *bs;
+ int r = 0;
+ assert(str != NULL);
+ assert(cnfobj_name != NULL);
+
+ if((bs = malloc(sizeof(struct bufstack))) == NULL) {
+ r = 1;
+ goto done;
+ }
+
+ if(currbs != NULL)
+ currbs->lineno = yylineno;
+ bs->prev = currbs;
+ bs->fn = strdup(cnfobj_name);
+ yy_size_t lll = es_strlen(str);
+ /* NOTE: yy_scan_buffer() does an automatic yy_switch_to_buffer to the new buffer */
+ bs->bs = yy_scan_buffer((char*)es_getBufAddr(str), lll);
+ bs->estr = str; /* needed so we can free it later */
+ currbs = bs;
+ cnfcurrfn = bs->fn;
+ yylineno = 1;
+ dbgprintf("config parser: pushed config fragment on top of stack: %s\n", cnfobj_name);
+
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "\n##### BEGIN CONFIG: %s (put on stack)\n", cnfcurrfn);
+ }
+
+done:
+ if(r != 0) {
+ es_deleteStr(str);
+ }
+ return r;
+}
+
+
+/* set a new buffers. Returns 0 on success, 1 on error, 2 on file not exists.
+ * note: in case of error, errno must be kept valid!
+ */
+int
+cnfSetLexFile(const char *const fname)
+{
+ es_str_t *str = NULL;
+ struct bufstack *bs;
+ FILE *fp;
+ int r = 0;
+
+ /* check for invalid recursive include */
+ for(bs = currbs ; bs != NULL ; bs = bs->prev) {
+ if(!strcmp(fname, bs->fn)) {
+ parser_errmsg("trying to include file '%s', "
+ "which is already included - ignored", fname);
+ r = 1;
+ goto done;
+ }
+ }
+
+ if(fname == NULL) {
+ fp = stdin;
+ } else {
+ if((fp = fopen(fname, "r")) == NULL) {
+ r = 2;
+ goto done;
+ }
+ }
+ readConfFile(fp, &str);
+ if(fp != stdin)
+ fclose(fp);
+
+ r = cnfAddConfigBuffer(str, ((fname == NULL) ? "stdin" : fname));
+
+done:
+ return r;
+}
+
+
+/* returns 0 on success, something else otherwise */
+int
+popfile(void)
+{
+ struct bufstack *bs = currbs;
+
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "\n##### END CONFIG: %s\n", cnfcurrfn);
+ }
+
+ if(bs == NULL)
+ return 1;
+
+ /* delete current entry. But we must not free the file name if
+ * this is the top-level file, because then it may still be used
+ * in error messages for other processing steps.
+ * TODO: change this to another method which stores the file
+ * name inside the config objects. In the longer term, this is
+ * necessary, as otherwise we may provide wrong file name information
+ * at the end of include files as well. -- rgerhards, 2011-07-22
+ */
+ dbgprintf("config parser: reached end of file %s\n", bs->fn);
+ yy_delete_buffer(bs->bs);
+ if(bs->prev != NULL)
+ free(bs->fn);
+ free(bs->estr);
+
+ /* switch back to previous */
+ currbs = bs->prev;
+ free(bs);
+
+ if(currbs == NULL) {
+ dbgprintf("config parser: parsing completed\n");
+ return 1; /* all processed */
+ }
+
+ yy_switch_to_buffer(currbs->bs);
+ yylineno = currbs->lineno;
+ cnfcurrfn = currbs->fn;
+ dbgprintf("config parser: resume parsing of file %s at line %d\n",
+ cnfcurrfn, yylineno);
+ return 0;
+}
+
+void
+tellLexEndParsing(void)
+{
+ free(cnfcurrfn);
+ cnfcurrfn= NULL;
+}
+#endif // #ifndef __clang_analyzer__
+
diff --git a/grammar/lexer.l b/grammar/lexer.l
new file mode 100644
index 0000000..f2e7bba
--- /dev/null
+++ b/grammar/lexer.l
@@ -0,0 +1,590 @@
+ /* Lex file for rsyslog config format v2 (RainerScript).
+ * Please note: this file introduces the new config format, but maintains
+ * backward compatibility. In order to do so, the grammar is not 100% clean,
+ * but IMHO still sufficiently easy both to understand for programmers
+ * maitaining the code as well as users writing the config file. Users are,
+ * of course, encouraged to use new constructs only. But it needs to be noted
+ * that some of the legacy constructs (specifically the in-front-of-action
+ * PRI filter) are very hard to beat in ease of use, at least for simpler
+ * cases. So while we hope that cfsysline support can be dropped some time in
+ * the future, we will probably keep these useful constructs.
+ *
+ * Copyright 2011-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+%top{
+#ifndef __clang_analyzer__ /* this is not really our code */
+#include "config.h"
+}
+
+%{
+#include <libestr.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "parserif.h"
+
+PRAGMA_IGNORE_Wsign_compare
+PRAGMA_IGNORE_Wmissing_noreturn
+
+FILE *fp_rs_full_conf_output = NULL;
+
+/* TODO: move this to a better modules, refactor -- rgerhards, 2018-01-22 */
+static char *
+read_file(const char *const filename)
+{
+ char *content = NULL;
+ int fd = -1;
+ struct stat sb;
+ ssize_t nread;
+ assert(filename != NULL);
+
+ if((fd = open((const char*) filename, O_RDONLY)) == -1) {
+ goto done;
+ }
+
+ if(fstat(fd, &sb) == -1) {
+ goto done;
+ }
+
+ content = malloc(sb.st_size+1);
+ if(content == NULL) {
+ goto done;
+ }
+
+ nread = read(fd, content, sb.st_size);
+ content[nread] = '\0';
+ if(nread != (ssize_t) sb.st_size) {
+ free(content);
+ content = NULL;
+ goto done;
+ }
+
+done:
+ if(fd != -1) {
+ close(fd);
+ }
+ return content;
+}
+
+static es_str_t* ATTR_NONNULL(1)
+expand_backticks_echo(const char *param)
+{
+ assert(param != NULL);
+ assert(strncmp(param, "echo ", sizeof("echo ")-1) == 0);
+ char envvar[512];
+ int i_envvar = 0;
+ int in_env = 0;
+ es_str_t *estr;
+
+ param += sizeof("echo ")-1;
+ if((estr = es_newStr(strlen(param))) == NULL) {
+ goto done;
+ }
+
+ while(*param) {
+ if(in_env) {
+ if(isspace(*param) || *param == '/') {
+ envvar[i_envvar] = '\0';
+ const char *envval = getenv(envvar);
+ if(envval != NULL)
+ es_addBuf(&estr, envval, strlen(envval));
+ es_addChar(&estr, *param); /* curr char part of output! */
+ i_envvar = 0;
+ in_env = 0;
+ } else if(i_envvar > sizeof(envvar) - 1) {
+ parser_errmsg("environment variable too long, begins with %s", envvar);
+ goto done;
+ } else {
+ envvar[i_envvar++] = *param;
+ }
+ } else if (*param == '$') {
+ in_env = 1;
+ } else {
+ es_addChar(&estr, *param);
+ }
+ ++param;
+ }
+
+ /* final check, we may be in env var name (very probable!) */
+ if(in_env) {
+ envvar[i_envvar] = '\0';
+ const char *envval = getenv(envvar);
+ if(envval != NULL)
+ es_addBuf(&estr, envval, strlen(envval));
+ }
+
+done: return estr;
+}
+
+
+static es_str_t* ATTR_NONNULL(1)
+expand_backticks(char *const param)
+{
+ es_str_t *estr;
+ assert(param != NULL);
+
+ if(strncmp(param, "echo ", sizeof("echo ")-1) == 0) {
+ estr = expand_backticks_echo(param);
+ } else if(strncmp(param, "cat ", sizeof("cat ")-1) == 0) {
+ const char *val = read_file(param+4);
+ if(val == NULL) {
+ parser_errmsg("file could not be accessed for `%s`", param);
+ const char *errmsg = "/* file cound not be accessed - see"
+ "error messages */";
+ estr = es_newStrFromCStr(errmsg, strlen(errmsg));
+ } else {
+ estr = es_newStrFromCStr(val, strlen(val));
+ }
+ free((void*) val);
+ } else {
+ parser_errmsg("invalid backtick parameter `%s` - replaced by "
+ "empty string (\"\")", param);
+ estr = es_newStr(1);
+ }
+
+ return estr;
+}
+%}
+
+%option noyywrap nodefault case-insensitive yylineno
+ /*%option noyywrap nodefault case-insensitive */
+
+/* avoid compiler warning: `yyunput' defined but not used */
+%option nounput noinput
+
+
+%x INOBJ
+ /* INOBJ is selected if we are inside an object (name/value pairs!) */
+%x COMMENT
+ /* COMMENT is "the usual trick" to handle C-style comments */
+%x INCL
+ /* INCL is in $IncludeConfig processing (skip to include file) */
+%x LINENO
+ /* LINENO: support for setting the linenumber */
+%x INCALL
+ /* INCALL: support for the call statement */
+%x IN_PROCEDURE_CALL
+ /* IN_PROCEDURE_CALL: support for the call statement */
+%x EXPR
+ /* EXPR is a bit ugly, but we need it to support pre v6-syntax. The problem
+ * is that cfsysline statement start with $..., the same like variables in
+ * an expression. However, cfsysline statements can never appear inside an
+ * expression. So we create a specific expr mode, which is turned on after
+ * we lexed a keyword that needs to be followed by an expression (using
+ * knowledge from the upper layer...). In expr mode, we strictly do
+ * expression-based parsing. Expr mode is stopped when we reach a token
+ * that can not be part of an expression (currently only "then"). As I
+ * wrote this ugly, but the price needed to pay in order to remain
+ * compatible to the previous format.
+ */
+%{
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <libestr.h>
+#include "rainerscript.h"
+#include "parserif.h"
+#include "grammar.h"
+static int preCommentState; /* save for lex state before a comment */
+
+struct bufstack {
+ struct bufstack *prev;
+ YY_BUFFER_STATE bs;
+ int lineno;
+ char *fn;
+ es_str_t *estr;
+} *currbs = NULL;
+
+char *cnfcurrfn; /* name of currently processed file */
+
+int popfile(void);
+int cnfSetLexFile(const char *fname);
+
+static void cnfPrintToken(const char *token);
+extern int yydebug;
+
+/* somehow, I need these prototype even though the headers are
+ * included. I guess that's some autotools magic I don't understand...
+ */
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) \
+ && !defined(__DragonflyBSD__) && !defined(_AIX)
+int fileno(FILE *stream);
+#endif
+
+
+%}
+
+%%
+
+ /* keywords */
+"if" { cnfPrintToken(yytext); BEGIN EXPR; return IF; }
+"foreach" { cnfPrintToken(yytext); BEGIN EXPR; return FOREACH; }
+"reload_lookup_table" { cnfPrintToken(yytext); BEGIN IN_PROCEDURE_CALL; return RELOAD_LOOKUP_TABLE_PROCEDURE; }
+<IN_PROCEDURE_CALL>"(" { cnfPrintToken(yytext); return yytext[0]; }
+<IN_PROCEDURE_CALL>\'([^'\\]|\\['"\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\' {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+<IN_PROCEDURE_CALL>\"([^"\\$]|\\["'\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\" {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+<IN_PROCEDURE_CALL>"," { cnfPrintToken(yytext); return yytext[0]; }
+<IN_PROCEDURE_CALL>")" { cnfPrintToken(yytext); BEGIN INITIAL; return yytext[0]; }
+<IN_PROCEDURE_CALL>[ \t\n]* {cnfPrintToken(yytext); }
+<IN_PROCEDURE_CALL>. { cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in expression "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+<EXPR>"(" { cnfPrintToken(yytext); BEGIN EXPR; return yytext[0]; }
+<EXPR>"then" { cnfPrintToken(yytext); BEGIN INITIAL; return THEN; }
+<EXPR>"do" { cnfPrintToken(yytext); BEGIN INITIAL; return DO; }
+<EXPR>";" { cnfPrintToken(yytext); BEGIN INITIAL; return ';'; }
+<EXPR>"or" { cnfPrintToken(yytext); return OR; }
+<EXPR>"and" { cnfPrintToken(yytext); return AND; }
+<EXPR>"not" { cnfPrintToken(yytext); return NOT; }
+<EXPR>"=" |
+<EXPR>"," |
+<EXPR>"*" |
+<EXPR>"/" |
+<EXPR>"%" |
+<EXPR>"+" |
+<EXPR>"&" |
+<EXPR>"-" |
+<EXPR>"[" |
+<EXPR>"]" |
+<EXPR>")" { cnfPrintToken(yytext); return yytext[0]; }
+<EXPR>"==" { cnfPrintToken(yytext); return CMP_EQ; }
+<EXPR>"<=" { cnfPrintToken(yytext); return CMP_LE; }
+<EXPR>">=" { cnfPrintToken(yytext); return CMP_GE; }
+<EXPR>"!=" |
+<EXPR>"<>" { cnfPrintToken(yytext); return CMP_NE; }
+<EXPR>"<" { cnfPrintToken(yytext); return CMP_LT; }
+<EXPR>">" { cnfPrintToken(yytext); return CMP_GT; }
+<EXPR>"contains" { cnfPrintToken(yytext); return CMP_CONTAINS; }
+<EXPR>"in" { cnfPrintToken(yytext); return ITERATOR_ASSIGNMENT; }
+<EXPR>"contains_i" { cnfPrintToken(yytext); return CMP_CONTAINSI; }
+<EXPR>"startswith" { cnfPrintToken(yytext); return CMP_STARTSWITH; }
+<EXPR>"startswith_i" { cnfPrintToken(yytext); return CMP_STARTSWITHI; }
+<EXPR>0[0-7]+ | /* octal number */
+<EXPR>0x[0-9a-f]+ | /* hex number, following rule is dec; strtoll handles all! */
+<EXPR>([1-9][0-9]*|0) { cnfPrintToken(yytext); yylval.n = strtoll(yytext, NULL, 0); return NUMBER; }
+<EXPR>\$[$!./]{0,1}[@a-z_]*[!@a-z0-9\-_\.\[\]]* { cnfPrintToken(yytext); yylval.s = strdup(yytext+1); return VAR; }
+<EXPR>\'([^'\\]|\\['"\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\' {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+<EXPR>`([^`\\]|\\['`"\\bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*` {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = expand_backticks(yytext+1);
+ return STRING; }
+<EXPR>\"([^"\\$]|\\["'\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\" {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+<EXPR>\"([^"\\]|\\["'\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\" {
+ cnfPrintToken(yytext); parser_errmsg("$-sign in double quotes must be "
+ "escaped, problem string is: %s",
+ yytext); }
+<EXPR>[ \t\n] { cnfPrintToken(yytext); }
+<EXPR>"exists" { cnfPrintToken(yytext); return EXISTS; } /* special case function (see rainerscript.c) */
+<EXPR>[a-z][a-z0-9_]* { cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ return FUNC; }
+<EXPR>. { cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in expression "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+<INCALL>[ \t\n] { cnfPrintToken(yytext); }
+<INCALL>. { cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in 'call' statement"
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+<INCALL>[a-zA-Z][a-zA-Z0-9\-_\.]* { cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ BEGIN INITIAL;
+ return NAME; }
+"&" { cnfPrintToken(yytext); return '&'; }
+"{" { cnfPrintToken(yytext); return '{'; }
+"}" { cnfPrintToken(yytext); return '}'; }
+"stop" { cnfPrintToken(yytext); return STOP; }
+"else" { cnfPrintToken(yytext); return ELSE; }
+"call" { cnfPrintToken(yytext); BEGIN INCALL; return CALL; }
+"call_indirect" { cnfPrintToken(yytext); BEGIN EXPR; return CALL_INDIRECT; }
+"set" { cnfPrintToken(yytext); BEGIN EXPR; return SET; }
+"reset" { cnfPrintToken(yytext); BEGIN EXPR; return RESET; }
+"unset" { cnfPrintToken(yytext); BEGIN EXPR; return UNSET; }
+"continue" { cnfPrintToken(yytext); return CONTINUE; }
+ /* line number support because the "preprocessor" combines lines and so needs
+ * to tell us the real source line.
+ */
+"preprocfilelinenumber(" { cnfPrintToken(yytext); BEGIN LINENO; }
+<LINENO>[0-9]+ { cnfPrintToken(yytext); yylineno = atoi(yytext) - 1; }
+<LINENO>")" { cnfPrintToken(yytext); BEGIN INITIAL; }
+<LINENO>.|\n
+ /* $IncludeConfig must be detected as part of CFSYSLINE, because this is
+ * always the longest match :-(
+ */
+<INCL>.|\n
+<INCL>[^ \t\n]+ { cnfPrintToken(yytext); if(cnfDoInclude(yytext, 0) != 0)
+ yyterminate();
+ BEGIN INITIAL; }
+"main_queue"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_MAINQ;
+ BEGIN INOBJ; return BEGINOBJ; }
+"timezone"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_TIMEZONE;
+ BEGIN INOBJ; return BEGINOBJ; }
+"parser"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_PARSER;
+ BEGIN INOBJ; return BEGINOBJ; }
+"global"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_GLOBAL;
+ BEGIN INOBJ; return BEGINOBJ; }
+"template"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_TPL;
+ BEGIN INOBJ; return BEGIN_TPL; }
+"ruleset"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_RULESET;
+ BEGIN INOBJ; return BEGIN_RULESET; }
+"property"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_PROPERTY;
+ BEGIN INOBJ; return BEGIN_PROPERTY; }
+"constant"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_CONSTANT;
+ BEGIN INOBJ; return BEGIN_CONSTANT; }
+"input"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_INPUT;
+ BEGIN INOBJ; return BEGINOBJ; }
+"module"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_MODULE;
+ BEGIN INOBJ; return BEGINOBJ; }
+"lookup_table"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_LOOKUP_TABLE;
+ BEGIN INOBJ; return BEGINOBJ; }
+"dyn_stats"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_DYN_STATS;
+ BEGIN INOBJ; return BEGINOBJ; }
+"percentile_stats"[ \n\t]*"(" { cnfPrintToken(yytext); yylval.objType = CNFOBJ_PERCTILE_STATS;
+ BEGIN INOBJ; return BEGINOBJ; }
+"include"[ \n\t]*"(" { cnfPrintToken(yytext); BEGIN INOBJ; return BEGIN_INCLUDE; }
+"action"[ \n\t]*"(" { cnfPrintToken(yytext); BEGIN INOBJ; return BEGIN_ACTION; }
+^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\"(\\\"|[^\"])*\" {
+ cnfPrintToken(yytext); yylval.s = strdup(rmLeadingSpace(yytext));
+ dbgprintf("lexer: propfilt is '%s'\n", yylval.s);
+ return PROPFILT;
+ }
+^[ \t]*[\*a-z][\*a-z]*[0-7]*[\.,][,!=;\.\*a-z0-7]+ { cnfPrintToken(yytext); yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; }
+"~" |
+"*" |
+\-\/[^*][^\n]* |
+\/[^*][^\n]* |
+:[a-z0-9]+:[^\n]* |
+[\|\.\-\@\^?~>][^\n]+ |
+[a-z0-9_][a-z0-9_\-\+,;]* { cnfPrintToken(yytext); yylval.s = yytext; return LEGACY_ACTION; }
+<INOBJ>")" { cnfPrintToken(yytext); BEGIN INITIAL; return ENDOBJ; }
+<INOBJ>[a-z][a-z0-9_\.]* { cnfPrintToken(yytext); yylval.estr = es_newStrFromCStr(yytext, yyleng);
+ return NAME; }
+<INOBJ>"," |
+<INOBJ>"[" |
+<INOBJ>"]" |
+<INOBJ>"=" { cnfPrintToken(yytext); return(yytext[0]); }
+<INOBJ>\"([^"\\]|\\['"?\\abfnrtv]|\\[0-7]{1,3})*\" {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+<INOBJ>`([^`\\]|\\['`?\\abfnrtv]|\\[0-7]{1,3})*` {
+ cnfPrintToken(yytext); yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = expand_backticks(yytext+1);
+ return STRING; }
+ /*yylval.estr = es_newStrFromBuf(yytext+1, yyleng-2);
+ return VALUE; }*/
+"/*" { cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+<INOBJ>"/*" { cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+<EXPR>"/*" { cnfPrintToken(yytext); preCommentState = YY_START; BEGIN COMMENT; }
+<COMMENT>"*/" { cnfPrintToken(yytext); BEGIN preCommentState; }
+<COMMENT>([^*]|\n)+|.
+<INOBJ>#.*$ /* skip comments in input */
+<INOBJ>[ \n\t] { cnfPrintToken(yytext); }
+<INOBJ>. { cnfPrintToken(yytext); parser_errmsg("invalid character '%s' in object definition "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+\$[a-z]+.*$ { cnfPrintToken(yytext); /* see comment on $IncludeConfig above */
+ if(!strncasecmp(yytext, "$includeconfig ", 14)) {
+ yyless((yy_size_t)14);
+ BEGIN INCL;
+ } else if(!strncasecmp(yytext, "$ruleset ", 9)) {
+ yylval.s = strdup(yytext);
+ return LEGACY_RULESET;
+ } else {
+ cnfDoCfsysline(strdup(yytext));
+ }
+ }
+![^ \t\n]+[ \t]*$ { cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_TAG_SELECTOR; }
+[+-]\*[ \t\n]*#.*$ { cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+[+-]\*[ \t\n]*$ { cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+^[ \t]*[+-][a-z0-9.:-]+[ \t]*$ { cnfPrintToken(yytext); yylval.s = strdup(yytext); return BSD_HOST_SELECTOR; }
+\#.*\n {cnfPrintToken(yytext); }/* skip comments in input */
+[\n\t ] {cnfPrintToken(yytext); }/* drop whitespace */
+. { cnfPrintToken(yytext); parser_errmsg("invalid character '%s' "
+ "- is there an invalid escape sequence somewhere?",
+ yytext); }
+<<EOF>> { if(popfile() != 0) yyterminate(); }
+
+%%
+static void cnfPrintToken(const char *token)
+{
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "%s", token);
+ }
+}
+
+/* add config file or text the the stack of config objects to be
+ * processed.
+ * cnfobjname is either the file name or "text" if generated from
+ * text ("text" can also be replaced by something more intelligent
+ * by the caller.
+ * The provided string is freed.
+ */
+int ATTR_NONNULL()
+cnfAddConfigBuffer(es_str_t *const str, const char *const cnfobj_name)
+{
+ struct bufstack *bs;
+ int r = 0;
+ assert(str != NULL);
+ assert(cnfobj_name != NULL);
+
+ if((bs = malloc(sizeof(struct bufstack))) == NULL) {
+ r = 1;
+ goto done;
+ }
+
+ if(currbs != NULL)
+ currbs->lineno = yylineno;
+ bs->prev = currbs;
+ bs->fn = strdup(cnfobj_name);
+ yy_size_t lll = es_strlen(str);
+ /* NOTE: yy_scan_buffer() does an automatic yy_switch_to_buffer to the new buffer */
+ bs->bs = yy_scan_buffer((char*)es_getBufAddr(str), lll);
+ bs->estr = str; /* needed so we can free it later */
+ currbs = bs;
+ cnfcurrfn = bs->fn;
+ yylineno = 1;
+ dbgprintf("config parser: pushed config fragment on top of stack: %s\n", cnfobj_name);
+
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "\n##### BEGIN CONFIG: %s (put on stack)\n", cnfcurrfn);
+ }
+
+done:
+ if(r != 0) {
+ es_deleteStr(str);
+ }
+ return r;
+}
+
+
+/* set a new buffers. Returns 0 on success, 1 on error, 2 on file not exists.
+ * note: in case of error, errno must be kept valid!
+ */
+int
+cnfSetLexFile(const char *const fname)
+{
+ es_str_t *str = NULL;
+ struct bufstack *bs;
+ FILE *fp;
+ int r = 0;
+
+ /* check for invalid recursive include */
+ for(bs = currbs ; bs != NULL ; bs = bs->prev) {
+ if(!strcmp(fname, bs->fn)) {
+ parser_errmsg("trying to include file '%s', "
+ "which is already included - ignored", fname);
+ r = 1;
+ goto done;
+ }
+ }
+
+ if(fname == NULL) {
+ fp = stdin;
+ } else {
+ if((fp = fopen(fname, "r")) == NULL) {
+ r = 2;
+ goto done;
+ }
+ }
+ readConfFile(fp, &str);
+ if(fp != stdin)
+ fclose(fp);
+
+ r = cnfAddConfigBuffer(str, ((fname == NULL) ? "stdin" : fname));
+
+done:
+ return r;
+}
+
+
+/* returns 0 on success, something else otherwise */
+int
+popfile(void)
+{
+ struct bufstack *bs = currbs;
+
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(fp_rs_full_conf_output, "\n##### END CONFIG: %s\n", cnfcurrfn);
+ }
+
+ if(bs == NULL)
+ return 1;
+
+ /* delete current entry. But we must not free the file name if
+ * this is the top-level file, because then it may still be used
+ * in error messages for other processing steps.
+ * TODO: change this to another method which stores the file
+ * name inside the config objects. In the longer term, this is
+ * necessary, as otherwise we may provide wrong file name information
+ * at the end of include files as well. -- rgerhards, 2011-07-22
+ */
+ dbgprintf("config parser: reached end of file %s\n", bs->fn);
+ yy_delete_buffer(bs->bs);
+ if(bs->prev != NULL)
+ free(bs->fn);
+ free(bs->estr);
+
+ /* switch back to previous */
+ currbs = bs->prev;
+ free(bs);
+
+ if(currbs == NULL) {
+ dbgprintf("config parser: parsing completed\n");
+ return 1; /* all processed */
+ }
+
+ yy_switch_to_buffer(currbs->bs);
+ yylineno = currbs->lineno;
+ cnfcurrfn = currbs->fn;
+ dbgprintf("config parser: resume parsing of file %s at line %d\n",
+ cnfcurrfn, yylineno);
+ return 0;
+}
+
+void
+tellLexEndParsing(void)
+{
+ free(cnfcurrfn);
+ cnfcurrfn= NULL;
+}
+#endif // #ifndef __clang_analyzer__
diff --git a/grammar/parserif.h b/grammar/parserif.h
new file mode 100644
index 0000000..a22f8dd
--- /dev/null
+++ b/grammar/parserif.h
@@ -0,0 +1,44 @@
+/* rsyslog parser interface.
+ *
+ * Copyright 2011-2016 Rainer Gerhards
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef PARSERIF_H_DEFINED
+#define PARSERIF_H_DEFINED
+#include "rainerscript.h"
+int cnfSetLexFile(const char*);
+void parser_errmsg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void parser_warnmsg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void tellLexEndParsing(void);
+#ifndef IN_GRAMMAR_Y
+int yyparse(void);
+extern int yydebug;
+extern int yylineno;
+extern char *cnfcurrfn;
+extern FILE *fp_rs_full_conf_output;
+#endif
+
+/* entry points to be called after the parser has processed the
+ * element in question. Actual processing must than be done inside
+ * these functions.
+ */
+void cnfDoObj(struct cnfobj *o);
+void cnfDoScript(struct cnfstmt *script);
+void cnfDoCfsysline(char *ln);
+void cnfDoBSDTag(char *ln);
+void cnfDoBSDHost(char *ln);
+int cnfAddConfigBuffer(es_str_t *const str, const char *const cnfobj_name);
+#endif
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
new file mode 100644
index 0000000..69d0b38
--- /dev/null
+++ b/grammar/rainerscript.c
@@ -0,0 +1,5806 @@
+/* rainerscript.c - routines to support RainerScript config language
+ *
+ * Module begun 2011-07-01 by Rainer Gerhards
+ *
+ * Copyright 2011-2022 Rainer Gerhards and Others.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glob.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libestr.h>
+#include <time.h>
+
+#include "rsyslog.h"
+#include "rainerscript.h"
+#include "conf.h"
+#include "parserif.h"
+#include "parse.h"
+#include "rsconf.h"
+#include "grammar.h"
+#include "queue.h"
+#include "srUtils.h"
+#include "regexp.h"
+#include "datetime.h"
+#include "obj.h"
+#include "modules.h"
+#include "ruleset.h"
+#include "msg.h"
+#include "wti.h"
+#include "unicode-helper.h"
+#include "errmsg.h"
+
+PRAGMA_INGORE_Wswitch_enum
+
+DEFobjCurrIf(obj)
+DEFobjCurrIf(regexp)
+DEFobjCurrIf(datetime)
+
+struct cnfexpr* cnfexprOptimize(struct cnfexpr *expr);
+static void cnfstmtOptimizePRIFilt(struct cnfstmt *stmt);
+static void cnfarrayPrint(struct cnfarray *ar, int indent);
+struct cnffunc * cnffuncNew_prifilt(int fac);
+
+static struct cnfparamdescr incpdescr[] = {
+ { "file", eCmdHdlrString, 0 },
+ { "text", eCmdHdlrString, 0 },
+ { "mode", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk incpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(incpdescr)/sizeof(struct cnfparamdescr),
+ incpdescr
+ };
+
+/* debug support: convert token to a human-readable string. Note that
+ * this function only supports a single thread due to a static buffer.
+ * This is deemed a solid solution, as it is intended to be used during
+ * startup, only.
+ * NOTE: This function MUST be updated if new tokens are defined in the
+ * grammar.
+ */
+static const char *
+tokenToString(const int token)
+{
+ const char *tokstr;
+ static char tokbuf[512];
+
+ switch(token) {
+ case NAME: tokstr = "NAME"; break;
+ case FUNC: tokstr = "FUNC"; break;
+ case BEGINOBJ: tokstr ="BEGINOBJ"; break;
+ case ENDOBJ: tokstr ="ENDOBJ"; break;
+ case BEGIN_ACTION: tokstr ="BEGIN_ACTION"; break;
+ case BEGIN_PROPERTY: tokstr ="BEGIN_PROPERTY"; break;
+ case BEGIN_CONSTANT: tokstr ="BEGIN_CONSTANT"; break;
+ case BEGIN_TPL: tokstr ="BEGIN_TPL"; break;
+ case BEGIN_RULESET: tokstr ="BEGIN_RULESET"; break;
+ case STOP: tokstr ="STOP"; break;
+ case SET: tokstr ="SET"; break;
+ case UNSET: tokstr ="UNSET"; break;
+ case CONTINUE: tokstr ="CONTINUE"; break;
+ case CALL: tokstr ="CALL"; break;
+ case LEGACY_ACTION: tokstr ="LEGACY_ACTION"; break;
+ case LEGACY_RULESET: tokstr ="LEGACY_RULESET"; break;
+ case PRIFILT: tokstr ="PRIFILT"; break;
+ case PROPFILT: tokstr ="PROPFILT"; break;
+ case IF: tokstr ="IF"; break;
+ case THEN: tokstr ="THEN"; break;
+ case ELSE: tokstr ="ELSE"; break;
+ case OR: tokstr ="OR"; break;
+ case AND: tokstr ="AND"; break;
+ case NOT: tokstr ="NOT"; break;
+ case VAR: tokstr ="VAR"; break;
+ case STRING: tokstr ="STRING"; break;
+ case NUMBER: tokstr ="NUMBER"; break;
+ case CMP_EQ: tokstr ="CMP_EQ"; break;
+ case CMP_NE: tokstr ="CMP_NE"; break;
+ case CMP_LE: tokstr ="CMP_LE"; break;
+ case CMP_GE: tokstr ="CMP_GE"; break;
+ case CMP_LT: tokstr ="CMP_LT"; break;
+ case CMP_GT: tokstr ="CMP_GT"; break;
+ case CMP_CONTAINS: tokstr ="CMP_CONTAINS"; break;
+ case CMP_CONTAINSI: tokstr ="CMP_CONTAINSI"; break;
+ case CMP_STARTSWITH: tokstr ="CMP_STARTSWITH"; break;
+ case CMP_STARTSWITHI: tokstr ="CMP_STARTSWITHI"; break;
+ case UMINUS: tokstr ="UMINUS"; break;
+ case '&': tokstr ="&"; break;
+ case '+': tokstr ="+"; break;
+ case '-': tokstr ="-"; break;
+ case '*': tokstr ="*"; break;
+ case '/': tokstr ="/"; break;
+ case '%': tokstr ="%"; break;
+ case 'M': tokstr ="M"; break;
+ case 'N': tokstr ="N"; break;
+ case 'S': tokstr ="S"; break;
+ case 'V': tokstr ="V"; break;
+ case 'F': tokstr ="F"; break;
+ case 'A': tokstr ="A"; break;
+ case S_FUNC_EXISTS: tokstr ="exists()"; break;
+ default: snprintf(tokbuf, sizeof(tokbuf), "%c[%d]", token, token);
+ tokstr = tokbuf; break;
+ }
+ return tokstr;
+}
+
+
+const char*
+getFIOPName(const unsigned iFIOP)
+{
+ const char *pRet;
+ switch(iFIOP) {
+ case FIOP_CONTAINS:
+ pRet = "contains";
+ break;
+ case FIOP_ISEQUAL:
+ pRet = "isequal";
+ break;
+ case FIOP_STARTSWITH:
+ pRet = "startswith";
+ break;
+ case FIOP_REGEX:
+ pRet = "regex";
+ break;
+ case FIOP_EREREGEX:
+ pRet = "ereregex";
+ break;
+ case FIOP_ISEMPTY:
+ pRet = "isempty";
+ break;
+ default:
+ pRet = "NOP";
+ break;
+ }
+ return pRet;
+}
+
+const char*
+cnfFiltType2str(const enum cnfFiltType filttype)
+{
+ switch(filttype) {
+ case CNFFILT_NONE:
+ return("filter:none");
+ case CNFFILT_PRI:
+ return("filter:pri");
+ case CNFFILT_PROP:
+ return("filter:prop");
+ case CNFFILT_SCRIPT:
+ return("filter:script");
+ default:
+ return("error:invalid_filter_type"); /* should never be reached */
+ }
+}
+
+const char*
+cnfobjType2str(const enum cnfobjType ot)
+{
+ switch(ot) {
+ case CNFOBJ_ACTION:
+ return "action";
+ break;
+ case CNFOBJ_RULESET:
+ return "ruleset";
+ break;
+ case CNFOBJ_GLOBAL:
+ return "global";
+ break;
+ case CNFOBJ_INPUT:
+ return "input";
+ break;
+ case CNFOBJ_MODULE:
+ return "module";
+ break;
+ case CNFOBJ_TPL:
+ return "template";
+ break;
+ case CNFOBJ_PROPERTY:
+ return "property";
+ break;
+ case CNFOBJ_CONSTANT:
+ return "constant";
+ break;
+ case CNFOBJ_MAINQ:
+ return "main_queue";
+ case CNFOBJ_LOOKUP_TABLE:
+ return "lookup_table";
+ case CNFOBJ_PARSER:
+ return "parser";
+ break;
+ case CNFOBJ_TIMEZONE:
+ return "timezone";
+ break;
+ case CNFOBJ_DYN_STATS:
+ return "dyn_stats";
+ break;
+ case CNFOBJ_PERCTILE_STATS:
+ return "perctile_stats";
+ break;
+ default:return "error: invalid cnfobjType";
+ }
+}
+
+/* This function takes the filter part of a property
+ * based filter and decodes it. It processes the line up to the beginning
+ * of the action part.
+ */
+static rsRetVal
+DecodePropFilter(uchar *pline, struct cnfstmt *stmt)
+{
+ rsParsObj *pPars = NULL;
+ cstr_t *pCSCompOp = NULL;
+ cstr_t *pCSPropName = NULL;
+ int iOffset; /* for compare operations */
+ DEFiRet;
+
+ assert(pline != NULL);
+
+ DBGPRINTF("Decoding property-based filter '%s'\n", pline);
+
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, pline+1)) != RS_RET_OK) {
+ parser_errmsg("error %d constructing parser object", iRet);
+ FINALIZE;
+ }
+
+ /* read property */
+ iRet = parsDelimCStr(pPars, &pCSPropName, ',', 1, 1, 1);
+ if(iRet != RS_RET_OK) {
+ parser_errmsg("error %d parsing filter property", iRet);
+ FINALIZE;
+ }
+ CHKiRet(msgPropDescrFill(&stmt->d.s_propfilt.prop, cstrGetSzStrNoNULL(pCSPropName),
+ cstrLen(pCSPropName)));
+
+ /* read operation */
+ iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1);
+ if(iRet != RS_RET_OK) {
+ parser_errmsg("error %d compare operation property - ignoring selector", iRet);
+ FINALIZE;
+ }
+
+ /* we now first check if the condition is to be negated. To do so, we first
+ * must make sure we have at least one char in the param and then check the
+ * first one.
+ * rgerhards, 2005-09-26
+ */
+ if(rsCStrLen(pCSCompOp) > 0) {
+ if(*rsCStrGetBufBeg(pCSCompOp) == '!') {
+ stmt->d.s_propfilt.isNegated = 1;
+ iOffset = 1; /* ignore '!' */
+ } else {
+ stmt->d.s_propfilt.isNegated = 0;
+ iOffset = 0;
+ }
+ } else {
+ stmt->d.s_propfilt.isNegated = 0;
+ iOffset = 0;
+ }
+
+ if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
+ stmt->d.s_propfilt.operation = FIOP_CONTAINS;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
+ stmt->d.s_propfilt.operation = FIOP_ISEQUAL;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isempty", 7)) {
+ stmt->d.s_propfilt.operation = FIOP_ISEMPTY;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "startswith", 10)) {
+ stmt->d.s_propfilt.operation = FIOP_STARTSWITH;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "regex", 5)) {
+ stmt->d.s_propfilt.operation = FIOP_REGEX;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "ereregex", 8)) {
+ stmt->d.s_propfilt.operation = FIOP_EREREGEX;
+ } else {
+ parser_errmsg("error: invalid compare operation '%s'",
+ (char*) rsCStrGetSzStrNoNULL(pCSCompOp));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(stmt->d.s_propfilt.operation != FIOP_ISEMPTY) {
+ /* read compare value */
+ iRet = parsQuotedCStr(pPars, &stmt->d.s_propfilt.pCSCompValue);
+ if(iRet != RS_RET_OK) {
+ parser_errmsg("error %d compare value property", iRet);
+ FINALIZE;
+ }
+ }
+
+finalize_it:
+ if(pPars != NULL)
+ rsParsDestruct(pPars);
+ if(pCSCompOp != NULL)
+ rsCStrDestruct(&pCSCompOp);
+ if(pCSPropName != NULL)
+ cstrDestruct(&pCSPropName);
+ RETiRet;
+}
+
+static void
+prifiltInvert(struct funcData_prifilt *__restrict__ const prifilt)
+{
+ int i;
+ for(i = 0 ; i < LOG_NFACILITIES+1 ; ++i) {
+ prifilt->pmask[i] = ~prifilt->pmask[i];
+ }
+}
+
+/* set prifilt so that it matches for some severities, sev is its numerical
+ * value. Mode is one of the compop tokens CMP_EQ, CMP_LT, CMP_LE, CMP_GT,
+ * CMP_GE, CMP_NE.
+ */
+static void
+prifiltSetSeverity(struct funcData_prifilt *prifilt, int sev, int mode)
+{
+ static int lessthanmasks[] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+ int i;
+ for(i = 0 ; i < LOG_NFACILITIES+1 ; ++i) {
+ if(mode == CMP_EQ || mode == CMP_NE)
+ prifilt->pmask[i] = 1 << sev;
+ else if(mode == CMP_LT)
+ prifilt->pmask[i] = lessthanmasks[sev];
+ else if(mode == CMP_LE)
+ prifilt->pmask[i] = lessthanmasks[sev+1];
+ else if(mode == CMP_GT)
+ prifilt->pmask[i] = ~lessthanmasks[sev+1];
+ else if(mode == CMP_GE)
+ prifilt->pmask[i] = ~lessthanmasks[sev];
+ else
+ DBGPRINTF("prifiltSetSeverity: program error, invalid mode %s\n",
+ tokenToString(mode));
+ }
+ if(mode == CMP_NE)
+ prifiltInvert(prifilt);
+}
+
+/* set prifilt so that it matches for some facilities, fac is its numerical
+ * value. Mode is one of the compop tokens CMP_EQ, CMP_LT, CMP_LE, CMP_GT,
+ * CMP_GE, CMP_NE. For the given facilities, all severities are enabled.
+ * NOTE: fac MUST be in the range 0..24 (not multiplied by 8)!
+ */
+static void
+prifiltSetFacility(struct funcData_prifilt *__restrict__ const prifilt, const int fac, const int mode)
+{
+ int i;
+
+ memset(prifilt->pmask, 0, sizeof(prifilt->pmask));
+ switch(mode) {
+ case CMP_EQ:
+ prifilt->pmask[fac] = TABLE_ALLPRI;
+ break;
+ case CMP_NE:
+ prifilt->pmask[fac] = TABLE_ALLPRI;
+ prifiltInvert(prifilt);
+ break;
+ case CMP_LT:
+ for(i = 0 ; i < fac ; ++i)
+ prifilt->pmask[i] = TABLE_ALLPRI;
+ break;
+ case CMP_LE:
+ for(i = 0 ; i < fac+1 ; ++i)
+ prifilt->pmask[i] = TABLE_ALLPRI;
+ break;
+ case CMP_GE:
+ for(i = fac ; i < LOG_NFACILITIES+1 ; ++i)
+ prifilt->pmask[i] = TABLE_ALLPRI;
+ break;
+ case CMP_GT:
+ for(i = fac+1 ; i < LOG_NFACILITIES+1 ; ++i)
+ prifilt->pmask[i] = TABLE_ALLPRI;
+ break;
+ default:break;
+ }
+}
+
+/* combine a prifilt with AND/OR (the respective token values are
+ * used to keep things simple).
+ */
+static void
+prifiltCombine(struct funcData_prifilt *__restrict__ const prifilt,
+ struct funcData_prifilt *__restrict__ const prifilt2,
+ const int mode)
+{
+ int i;
+ for(i = 0 ; i < LOG_NFACILITIES+1 ; ++i) {
+ if(mode == AND)
+ prifilt->pmask[i] = prifilt->pmask[i] & prifilt2->pmask[i];
+ else
+ prifilt->pmask[i] = prifilt->pmask[i] | prifilt2->pmask[i];
+ }
+}
+
+
+void
+readConfFile(FILE * const fp, es_str_t **str)
+{
+ char ln[10240];
+ char buf[512];
+ int lenBuf;
+ int bWriteLineno = 0;
+ int len, i;
+ int start; /* start index of to be submitted text */
+ int bContLine = 0;
+ int lineno = 0;
+
+ *str = es_newStr(4096);
+
+ while(fgets(ln, sizeof(ln), fp) != NULL) {
+ ++lineno;
+ if(bWriteLineno) {
+ bWriteLineno = 0;
+ lenBuf = sprintf(buf, "PreprocFileLineNumber(%d)\n", lineno);
+ es_addBuf(str, buf, lenBuf);
+ }
+ len = strlen(ln);
+ /* if we are continuation line, we need to drop leading WS */
+ if(bContLine) {
+ for(start = 0 ; start < len && isspace(ln[start]) ; ++start)
+ /* JUST SCAN */;
+ } else {
+ start = 0;
+ }
+ for(i = len - 1 ; i >= start && isspace(ln[i]) ; --i)
+ /* JUST SCAN */;
+ if(i >= 0) {
+ if(ln[i] == '\\') {
+ --i;
+ bContLine = 1;
+ } else {
+ if(bContLine) /* write line number if we had cont line */
+ bWriteLineno = 1;
+ bContLine = 0;
+ }
+ /* add relevant data to buffer */
+ es_addBuf(str, ln+start, i+1 - start);
+ }
+ if(!bContLine)
+ es_addChar(str, '\n');
+ }
+ /* indicate end of buffer to flex */
+ es_addChar(str, '\0');
+ es_addChar(str, '\0');
+}
+
+/* comparison function for qsort() and bsearch() string array compare */
+static int
+qs_arrcmp(const void *s1, const void *s2)
+{
+ return es_strcmp(*((es_str_t**)s1), *((es_str_t**)s2));
+}
+
+
+struct objlst*
+objlstNew(struct cnfobj *o)
+{
+ struct objlst *lst;
+
+ if((lst = malloc(sizeof(struct objlst))) != NULL) {
+ lst->next = NULL;
+ lst->obj = o;
+ }
+cnfobjPrint(o);
+
+ return lst;
+}
+
+/* add object to end of object list, always returns pointer to root object */
+struct objlst*
+objlstAdd(struct objlst *root, struct cnfobj *o)
+{
+ struct objlst *l;
+ struct objlst *newl;
+
+ newl = objlstNew(o);
+ if(root == 0) {
+ root = newl;
+ } else { /* find last, linear search ok, as only during config phase */
+ for(l = root ; l->next != NULL ; l = l->next)
+ ;
+ l->next = newl;
+ }
+ return root;
+}
+
+/* add stmt to current script, always return root stmt pointer */
+struct cnfstmt*
+scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s)
+{
+ struct cnfstmt *l;
+
+ if(root == NULL) {
+ root = s;
+ } else { /* find last, linear search ok, as only during config phase */
+ for(l = root ; l->next != NULL ; l = l->next)
+ ;
+ l->next = s;
+ }
+ return root;
+}
+
+void
+objlstDestruct(struct objlst *lst)
+{
+ struct objlst *toDel;
+
+ while(lst != NULL) {
+ toDel = lst;
+ lst = lst->next;
+ cnfobjDestruct(toDel->obj);
+ free(toDel);
+ }
+}
+
+void
+objlstPrint(struct objlst *lst)
+{
+ dbgprintf("objlst %p:\n", lst);
+ while(lst != NULL) {
+ cnfobjPrint(lst->obj);
+ lst = lst->next;
+ }
+}
+
+struct nvlst* ATTR_NONNULL(1)
+nvlstNewStr(es_str_t *const value)
+{
+ struct nvlst *lst;
+
+ if((lst = malloc(sizeof(struct nvlst))) != NULL) {
+ lst->next = NULL;
+ lst->val.datatype = 'S';
+ lst->val.d.estr = value;
+ lst->bUsed = 0;
+ }
+
+ return lst;
+}
+
+struct nvlst* ATTR_NONNULL(1)
+nvlstNewStrBackticks(es_str_t *const value)
+{
+ es_str_t *val = NULL;
+ const char *realval;
+
+ char *const param = es_str2cstr(value, NULL);
+ if(param == NULL)
+ goto done;
+
+ if(strncmp(param, "echo $", sizeof("echo $")-1) != 0) {
+ parser_errmsg("invalid backtick parameter `%s` currently "
+ "only `echo $<var>` is supported - replaced by "
+ "empty strong (\"\")", param);
+ realval = NULL;
+ } else {
+ size_t i;
+ const size_t len = strlen(param);
+ for(i = len - 1 ; isspace(param[i]) ; --i) {
+ ; /* just go down */
+ }
+ if(i > 6 && i < len - 1) {
+ param[i+1] = '\0';
+ }
+ realval = getenv(param+6);
+ }
+
+ free((void*)param);
+ if(realval == NULL) {
+ realval = "";
+ }
+ val = es_newStrFromCStr(realval, strlen(realval));
+ es_deleteStr(value);
+
+done:
+ return (val == NULL) ? NULL : nvlstNewStr(val);
+}
+
+struct nvlst*
+nvlstNewArray(struct cnfarray *ar)
+{
+ struct nvlst *lst;
+
+ if((lst = malloc(sizeof(struct nvlst))) != NULL) {
+ lst->next = NULL;
+ lst->val.datatype = 'A';
+ lst->val.d.ar = ar;
+ lst->bUsed = 0;
+ }
+
+ return lst;
+}
+
+struct nvlst*
+nvlstSetName(struct nvlst *lst, es_str_t *name)
+{
+ lst->name = name;
+ return lst;
+}
+
+void
+nvlstDestruct(struct nvlst *lst)
+{
+ struct nvlst *toDel;
+
+ while(lst != NULL) {
+ toDel = lst;
+ lst = lst->next;
+ es_deleteStr(toDel->name);
+ varDelete(&toDel->val);
+ free(toDel);
+ }
+}
+
+void
+nvlstPrint(struct nvlst *lst)
+{
+ char *name, *value;
+ dbgprintf("nvlst %p:\n", lst);
+ while(lst != NULL) {
+ name = es_str2cstr(lst->name, NULL);
+ switch(lst->val.datatype) {
+ case 'A':
+ dbgprintf("\tname: '%s':\n", name);
+ cnfarrayPrint(lst->val.d.ar, 5);
+ break;
+ case 'S':
+ value = es_str2cstr(lst->val.d.estr, NULL);
+ dbgprintf("\tname: '%s', value '%s'\n", name, value);
+ free(value);
+ break;
+ default:dbgprintf("nvlstPrint: unknown type '%s'\n",
+ tokenToString(lst->val.datatype));
+ break;
+ }
+ free(name);
+ lst = lst->next;
+ }
+}
+
+/* find a name starting at node lst. Returns node with this
+ * name or NULL, if none found.
+ */
+struct nvlst*
+nvlstFindName(struct nvlst *lst, es_str_t *name)
+{
+ while(lst != NULL && es_strcmp(lst->name, name))
+ lst = lst->next;
+ return lst;
+}
+
+
+/* find a name starting at node lst. Same as nvlstFindName, but
+ * for classical C strings. This is useful because the config system
+ * uses C string constants.
+ */
+static struct nvlst*
+nvlstFindNameCStr(struct nvlst *lst, const char *const __restrict__ name)
+{
+ es_size_t lenName = strlen(name);
+ while(lst != NULL && es_strcasebufcmp(lst->name, (uchar*)name, lenName))
+ lst = lst->next;
+ return lst;
+}
+
+/* check if the nvlst is disabled, and mark config.enabled directive
+ * as used if it is not. Returns 1 if block is disabled, 0 otherwise.
+ */
+int nvlstChkDisabled(struct nvlst *lst)
+{
+ struct nvlst *valnode;
+
+ if((valnode = nvlstFindNameCStr(lst, "config.enabled")) != NULL) {
+ valnode->bUsed = 1;
+ if(es_strbufcmp(valnode->val.d.estr, (unsigned char*) "on", 2)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* check if there are duplicate names inside a nvlst and emit
+ * an error message, if so.
+ */
+static void
+nvlstChkDupes(struct nvlst *lst)
+{
+ char *cstr;
+
+ while(lst != NULL) {
+ if(nvlstFindName(lst->next, lst->name) != NULL) {
+ cstr = es_str2cstr(lst->name, NULL);
+ parser_errmsg("duplicate parameter '%s' -- "
+ "interpretation is ambiguous, one value "
+ "will be randomly selected. Fix this problem.",
+ cstr);
+ free(cstr);
+ }
+ lst = lst->next;
+ }
+}
+
+
+/* check for unused params and emit error message is found. This must
+ * be called after all config params have been pulled from the object
+ * (otherwise the flags are not correctly set).
+ */
+void
+nvlstChkUnused(struct nvlst *lst)
+{
+ char *cstr;
+
+ while(lst != NULL) {
+ if(!lst->bUsed) {
+ cstr = es_str2cstr(lst->name, NULL);
+ parser_errmsg("parameter '%s' not known -- "
+ "typo in config file?",
+ cstr);
+ free(cstr);
+ }
+ lst = lst->next;
+ }
+}
+
+
+static int
+doGetSize(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ unsigned char *c;
+ es_size_t i;
+ long long n;
+ int r;
+ c = es_getBufAddr(valnode->val.d.estr);
+ n = 0;
+ i = 0;
+ while(i < es_strlen(valnode->val.d.estr) && isdigit(*c)) {
+ n = 10 * n + *c - '0';
+ ++i;
+ ++c;
+ }
+ if(i < es_strlen(valnode->val.d.estr)) {
+ ++i;
+ switch(*c) {
+ /* traditional binary-based definitions */
+ case 'k': n *= 1024; break;
+ case 'm': n *= 1024 * 1024; break;
+ case 'g': n *= 1024 * 1024 * 1024; break;
+ case 't': n *= (int64) 1024 * 1024 * 1024 * 1024; break; /* tera */
+ case 'p': n *= (int64) 1024 * 1024 * 1024 * 1024 * 1024; break; /* peta */
+ case 'e': n *= (int64) 1024 * 1024 * 1024 * 1024 * 1024 * 1024; break; /* exa */
+ /* and now the "new" 1000-based definitions */
+ case 'K': n *= 1000; break;
+ case 'M': n *= 1000000; break;
+ case 'G': n *= 1000000000; break;
+ /* we need to use the multiplication below because otherwise
+ * the compiler gets an error during constant parsing */
+ case 'T': n *= (int64) 1000 * 1000000000; break; /* tera */
+ case 'P': n *= (int64) 1000000 * 1000000000; break; /* peta */
+ case 'E': n *= (int64) 1000000000 * 1000000000; break; /* exa */
+ default: --i; break; /* indicates error */
+ }
+ }
+ if(i == es_strlen(valnode->val.d.estr)) {
+ val->val.datatype = 'N';
+ val->val.d.n = n;
+ r = 1;
+ } else {
+ parser_errmsg("parameter '%s' does not contain a valid size",
+ param->name);
+ r = 0;
+ }
+ return r;
+}
+
+
+static int
+doGetBinary(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int r = 1;
+ val->val.datatype = 'N';
+ if(!es_strbufcmp(valnode->val.d.estr, (unsigned char*) "on", 2)) {
+ val->val.d.n = 1;
+ } else if(!es_strbufcmp(valnode->val.d.estr, (unsigned char*) "off", 3)) {
+ val->val.d.n = 0;
+ } else {
+ parser_errmsg("parameter '%s' must be \"on\" or \"off\" but "
+ "is neither. Results unpredictable.", param->name);
+ val->val.d.n = 0;
+ r = 0;
+ }
+ return r;
+}
+
+static int
+doGetQueueType(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ char *cstr;
+ int r = 1;
+ if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"fixedarray", 10)) {
+ val->val.d.n = QUEUETYPE_FIXED_ARRAY;
+ } else if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"linkedlist", 10)) {
+ val->val.d.n = QUEUETYPE_LINKEDLIST;
+ } else if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"disk", 4)) {
+ val->val.d.n = QUEUETYPE_DISK;
+ } else if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"direct", 6)) {
+ val->val.d.n = QUEUETYPE_DIRECT;
+ } else {
+ cstr = es_str2cstr(valnode->val.d.estr, NULL);
+ parser_errmsg("param '%s': unknown queue type: '%s'",
+ param->name, cstr);
+ free(cstr);
+ r = 0;
+ }
+ val->val.datatype = 'N';
+ return r;
+}
+
+
+/* A file create-mode must be a four-digit octal number
+ * starting with '0'.
+ */
+static int
+doGetFileCreateMode(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int fmtOK = 0;
+ char *cstr;
+ uchar *c;
+ const int len_val = es_strlen(valnode->val.d.estr);
+
+ if(len_val >= 4) {
+ c = es_getBufAddr(valnode->val.d.estr);
+ if( (c[0] == '0')
+ && (c[1] >= '0' && c[1] <= '7')
+ && (c[2] >= '0' && c[2] <= '7')
+ && (c[3] >= '0' && c[3] <= '7') ) {
+ if(len_val == 5) {
+ if(c[4] >= '0' && c[4] <= '7') {
+ fmtOK = 1;
+ }
+ } else {
+ fmtOK = 1;
+ }
+ }
+ }
+
+ if(fmtOK) {
+ val->val.datatype = 'N';
+ val->val.d.n = (c[1]-'0') * 64 + (c[2]-'0') * 8 + (c[3]-'0');
+ if(len_val == 5) {
+ val->val.d.n = val->val.d.n * 8 + (c[4]-'0');
+ }
+ } else {
+ cstr = es_str2cstr(valnode->val.d.estr, NULL);
+ parser_errmsg("file modes need to be specified as "
+ "4- or 5-digit octal numbers starting with '0' -"
+ "parameter '%s=\"%s\"' is not a file mode",
+ param->name, cstr);
+ free(cstr);
+ }
+ return fmtOK;
+}
+
+static int
+doGetGID(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ char *cstr;
+ int r;
+ struct group *resultBuf = NULL;
+ struct group wrkBuf;
+ char *stringBuf = NULL;
+ size_t bufSize = 1024;
+ int e;
+
+ cstr = es_str2cstr(valnode->val.d.estr, NULL);
+ do {
+ char *p;
+
+ /* Increase bufsize and try again.*/
+ bufSize *= 2;
+ p = realloc(stringBuf, bufSize);
+ if(!p) {
+ e = ENOMEM;
+ break;
+ }
+ stringBuf = p;
+ e = getgrnam_r(cstr, &wrkBuf, stringBuf, bufSize, &resultBuf);
+ } while(!resultBuf && (e == ERANGE));
+
+ if(resultBuf == NULL) {
+ if(e != 0) {
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "parameter '%s': error to "
+ "obtaining group id for '%s'", param->name, cstr);
+ exit(1); /* good exit */
+ } else {
+ LogError(e, RS_RET_ERR, "parameter '%s': error to "
+ "obtaining group id for '%s'", param->name, cstr);
+ }
+ }
+ parser_errmsg("parameter '%s': ID for group %s could not "
+ "be found", param->name, cstr);
+ r = 0;
+ } else {
+ val->val.datatype = 'N';
+ val->val.d.n = resultBuf->gr_gid;
+ DBGPRINTF("param '%s': uid %d obtained for group '%s'\n",
+ param->name, (int) resultBuf->gr_gid, cstr);
+ r = 1;
+ }
+ free(stringBuf);
+ free(cstr);
+ return r;
+}
+
+static int
+doGetUID(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ char *cstr;
+ int r;
+ struct passwd *resultBuf;
+ struct passwd wrkBuf;
+ char stringBuf[2048]; /* 2048 has been proven to be large enough */
+ char errStr[1024];
+
+ cstr = es_str2cstr(valnode->val.d.estr, NULL);
+ const int err_no = getpwnam_r(cstr, &wrkBuf, stringBuf, sizeof(stringBuf), &resultBuf);
+ if(resultBuf == NULL) {
+ rs_strerror_r((err_no == 0) ? ENOENT : errno, errStr, sizeof(errStr));
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "parameter '%s': ID for user '%s' could not "
+ "be found: %s", param->name, cstr, errStr);
+ exit(1); /* good exit */
+ } else {
+ LogError(err_no, RS_RET_ERR, "parameter '%s': ID for user '%s' could not "
+ "be found: %s", param->name, cstr, errStr);
+ parser_errmsg("parameter '%s': ID for user '%s' could not "
+ "be found: %s", param->name, cstr, errStr);
+ }
+
+ r = 0;
+ } else {
+ val->val.datatype = 'N';
+ val->val.d.n = resultBuf->pw_uid;
+ DBGPRINTF("param '%s': uid %d obtained for user '%s'\n",
+ param->name, (int) resultBuf->pw_uid, cstr);
+ r = 1;
+ }
+ free(cstr);
+ return r;
+}
+
+/* note: we support all integer formats that es_str2num support,
+ * so hex and octal representations are also valid.
+ */
+static int
+doGetInt(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ long long n;
+ int bSuccess;
+
+ n = es_str2num(valnode->val.d.estr, &bSuccess);
+ if(!bSuccess) {
+ parser_errmsg("parameter '%s' is not a proper number",
+ param->name);
+ }
+ val->val.datatype = 'N';
+ val->val.d.n = n;
+ return bSuccess;
+}
+
+static int
+doGetNonNegInt(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int bSuccess;
+
+ if((bSuccess = doGetInt(valnode, param, val))) {
+ if(val->val.d.n < 0) {
+ parser_errmsg("parameter '%s' cannot be less than zero (was %lld)",
+ param->name, val->val.d.n);
+ bSuccess = 0;
+ }
+ }
+ return bSuccess;
+}
+
+static int
+doGetPositiveInt(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int bSuccess;
+
+ if((bSuccess = doGetInt(valnode, param, val))) {
+ if(val->val.d.n < 1) {
+ parser_errmsg("parameter '%s' cannot be less than one (was %lld)",
+ param->name, val->val.d.n);
+ bSuccess = 0;
+ }
+ }
+ return bSuccess;
+}
+
+static int
+doGetWord(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ es_size_t i;
+ int r = 1;
+ unsigned char *c;
+
+ val->val.datatype = 'S';
+ val->val.d.estr = es_newStr(32);
+ c = es_getBufAddr(valnode->val.d.estr);
+ for(i = 0 ; i < es_strlen(valnode->val.d.estr) && !isspace(c[i]) ; ++i) {
+ es_addChar(&val->val.d.estr, c[i]);
+ }
+ if(i != es_strlen(valnode->val.d.estr)) {
+ parser_errmsg("parameter '%s' contains whitespace, which is not "
+ "permitted",
+ param->name);
+ r = 0;
+ }
+ return r;
+}
+
+static int
+doGetArray(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int r = 1;
+
+ switch(valnode->val.datatype) {
+ case 'S':
+ /* a constant string is assumed to be a single-element array */
+ val->val.datatype = 'A';
+ val->val.d.ar = cnfarrayNew(es_strdup(valnode->val.d.estr));
+ break;
+ case 'A':
+ val->val.datatype = 'A';
+ val->val.d.ar = cnfarrayDup(valnode->val.d.ar);
+ break;
+ default:parser_errmsg("parameter '%s' must be an array, but is a "
+ "different datatype", param->name);
+ r = 0;
+ break;
+ }
+ return r;
+}
+
+static int
+doGetChar(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ int r = 1;
+ if(es_strlen(valnode->val.d.estr) != 1) {
+ parser_errmsg("parameter '%s' must contain exactly one character "
+ "but contains %d - cannot be processed",
+ param->name, es_strlen(valnode->val.d.estr));
+ r = 0;
+ }
+ val->val.datatype = 'S';
+ val->val.d.estr = es_strdup(valnode->val.d.estr);
+ return r;
+}
+
+/* get a single parameter according to its definition. Helper to
+ * nvlstGetParams. returns 1 if success, 0 otherwise
+ */
+static int
+nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *val)
+{
+ uchar *cstr;
+ int r;
+
+ DBGPRINTF("nvlstGetParam: name '%s', type %d, valnode->bUsed %d\n",
+ param->name, (int) param->type, valnode->bUsed);
+ if(valnode->val.datatype != 'S' && param->type != eCmdHdlrArray) {
+ parser_errmsg("parameter '%s' is not a string, which is not "
+ "permitted",
+ param->name);
+ r = 0;
+ goto done;
+ }
+ valnode->bUsed = 1;
+ val->bUsed = 1;
+ switch(param->type) {
+ case eCmdHdlrQueueType:
+ r = doGetQueueType(valnode, param, val);
+ break;
+ case eCmdHdlrUID:
+ r = doGetUID(valnode, param, val);
+ break;
+ case eCmdHdlrGID:
+ r = doGetGID(valnode, param, val);
+ break;
+ case eCmdHdlrBinary:
+ r = doGetBinary(valnode, param, val);
+ break;
+ case eCmdHdlrFileCreateMode:
+ r = doGetFileCreateMode(valnode, param, val);
+ break;
+ case eCmdHdlrInt:
+ r = doGetInt(valnode, param, val);
+ break;
+ case eCmdHdlrNonNegInt:
+ r = doGetNonNegInt(valnode, param, val);
+ break;
+ case eCmdHdlrPositiveInt:
+ r = doGetPositiveInt(valnode, param, val);
+ break;
+ case eCmdHdlrSize:
+ r = doGetSize(valnode, param, val);
+ break;
+ case eCmdHdlrGetChar:
+ r = doGetChar(valnode, param, val);
+ break;
+ case eCmdHdlrFacility:
+ cstr = (uchar*) es_str2cstr(valnode->val.d.estr, NULL);
+ val->val.datatype = 'N';
+ val->val.d.n = decodeSyslogName(cstr, syslogFacNames);
+ free(cstr);
+ r = 1;
+ break;
+ case eCmdHdlrSeverity:
+ cstr = (uchar*) es_str2cstr(valnode->val.d.estr, NULL);
+ val->val.datatype = 'N';
+ val->val.d.n = decodeSyslogName(cstr, syslogPriNames);
+ free(cstr);
+ r = 1;
+ break;
+ case eCmdHdlrGetWord:
+ r = doGetWord(valnode, param, val);
+ break;
+ case eCmdHdlrString:
+ val->val.datatype = 'S';
+ val->val.d.estr = es_strdup(valnode->val.d.estr);
+ r = 1;
+ break;
+ case eCmdHdlrArray:
+ r = doGetArray(valnode, param, val);
+ break;
+ case eCmdHdlrGoneAway:
+ parser_errmsg("parameter '%s' is no longer supported",
+ param->name);
+ r = 1; /* this *is* valid! */
+ break;
+ default:
+ DBGPRINTF("error: invalid param type\n");
+ r = 0;
+ break;
+ }
+done: return r;
+}
+
+
+/* obtain conf params from an nvlst and emit error messages if
+ * necessary. If an already-existing param value is passed, that is
+ * used. If NULL is passed instead, a new one is allocated. In that case,
+ * it is the caller's duty to free it when no longer needed.
+ * NULL is returned on error, otherwise a pointer to the vals array.
+ */
+struct cnfparamvals* ATTR_NONNULL(2)
+nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
+ struct cnfparamvals *vals)
+{
+#ifndef __clang_analyzer__ /* I give up on this one - let Coverity do the work */
+ int i;
+ int bValsWasNULL;
+ int bInError = 0;
+ struct nvlst *valnode;
+ struct cnfparamdescr *param;
+
+ if(params->version != CNFPARAMBLK_VERSION) {
+ DBGPRINTF("nvlstGetParams: invalid param block version "
+ "%d, expected %d\n",
+ params->version, CNFPARAMBLK_VERSION);
+ return NULL;
+ }
+
+ if(vals == NULL) {
+ bValsWasNULL = 1;
+ if((vals = calloc(params->nParams,
+ sizeof(struct cnfparamvals))) == NULL)
+ return NULL;
+ } else {
+ bValsWasNULL = 0;
+ }
+
+ for(i = 0 ; i < params->nParams ; ++i) {
+ param = params->descr + i;
+ if((valnode = nvlstFindNameCStr(lst, param->name)) == NULL) {
+ if(param->flags & CNFPARAM_REQUIRED) {
+ parser_errmsg("parameter '%s' required but not specified - "
+ "fix config", param->name);
+ bInError = 1;
+ }
+ continue;
+ }
+ if(param->flags & CNFPARAM_DEPRECATED) {
+ parser_errmsg("parameter '%s' deprecated but accepted, consider "
+ "removing or replacing it", param->name);
+ }
+ if(vals[i].bUsed) {
+ parser_errmsg("parameter '%s' specified more than once - "
+ "one instance is ignored. Fix config", param->name);
+ continue;
+ }
+ if(!nvlstGetParam(valnode, param, vals + i)) {
+ bInError = 1;
+ }
+ }
+
+ /* done parameter processing */
+ if(bInError) {
+ if(bValsWasNULL)
+ cnfparamvalsDestruct(vals, params);
+ vals = NULL;
+ }
+
+ return vals;
+#else
+ return NULL;
+#endif
+}
+
+
+/* check if at least one cnfparamval is actually set
+ * returns 1 if so, 0 otherwise
+ */
+int
+cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals)
+{
+ int i;
+
+ if(vals == NULL)
+ return 0;
+ if(params->version != CNFPARAMBLK_VERSION) {
+ DBGPRINTF("nvlstGetParams: invalid param block version "
+ "%d, expected %d\n",
+ params->version, CNFPARAMBLK_VERSION);
+ return 0;
+ }
+ for(i = 0 ; i < params->nParams ; ++i) {
+ if(vals[i].bUsed)
+ return 1;
+ }
+ return 0;
+}
+
+
+void
+cnfparamsPrint(const struct cnfparamblk *params, const struct cnfparamvals *vals)
+{
+ int i;
+ char *cstr;
+
+ if(!Debug)
+ return;
+
+ for(i = 0 ; i < params->nParams ; ++i) {
+ dbgprintf("%s: ", params->descr[i].name);
+ if(vals[i].bUsed) {
+ // TODO: other types!
+ switch(vals[i].val.datatype) {
+ case 'S':
+ cstr = es_str2cstr(vals[i].val.d.estr, NULL);
+ dbgprintf(" '%s'", cstr);
+ free(cstr);
+ break;
+ case 'A':
+ cnfarrayPrint(vals[i].val.d.ar, 0);
+ break;
+ case 'N':
+ dbgprintf("%lld", vals[i].val.d.n);
+ break;
+ default:
+ dbgprintf("(unsupported datatype %c)",
+ vals[i].val.datatype);
+ }
+ } else {
+ dbgprintf("(unset)");
+ }
+ dbgprintf("\n");
+ }
+}
+
+struct cnfobj*
+cnfobjNew(enum cnfobjType objType, struct nvlst *lst)
+{
+ struct cnfobj *o;
+
+ if((o = malloc(sizeof(struct cnfobj))) != NULL) {
+ nvlstChkDupes(lst);
+ o->objType = objType;
+ o->nvlst = lst;
+ o->subobjs = NULL;
+ o->script = NULL;
+ }
+
+ return o;
+}
+
+void
+cnfobjDestruct(struct cnfobj *o)
+{
+ if(o != NULL) {
+ nvlstDestruct(o->nvlst);
+ objlstDestruct(o->subobjs);
+ free(o);
+ }
+}
+
+void
+cnfobjPrint(struct cnfobj *o)
+{
+ dbgprintf("obj: '%s'\n", cnfobjType2str(o->objType));
+ nvlstPrint(o->nvlst);
+}
+
+
+struct cnfexpr*
+cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r)
+{
+ struct cnfexpr *expr;
+
+ /* optimize some constructs during parsing */
+ if(nodetype == 'M' && r->nodetype == 'N') {
+ ((struct cnfnumval*)r)->val *= -1;
+ expr = r;
+ goto done;
+ }
+
+ if((expr = malloc(sizeof(struct cnfexpr))) != NULL) {
+ expr->nodetype = nodetype;
+ expr->l = l;
+ expr->r = r;
+ }
+done:
+ return expr;
+}
+
+
+static int64_t
+str2num(es_str_t *s, int *bSuccess)
+{
+ size_t i;
+ int neg;
+ int64_t num = 0;
+ const uchar *const c = es_getBufAddr(s);
+
+ if(s->lenStr == 0) {
+ DBGPRINTF("rainerscript: str2num: strlen == 0; invalid input (no string)\n");
+ if(bSuccess != NULL) {
+ *bSuccess = 1;
+ }
+ goto done;
+ }
+ if(c[0] == '-') {
+ neg = -1;
+ i = 1;
+ } else {
+ neg = 1;
+ i = 0;
+ }
+ while(i < s->lenStr && isdigit(c[i])) {
+ num = num * 10 + c[i] - '0';
+ ++i;
+ }
+ num *= neg;
+ if(bSuccess != NULL)
+ *bSuccess = (i == s->lenStr) ? 1 : 0;
+done:
+ return num;
+}
+
+/* We support decimal integers. Unfortunately, previous versions
+ * said they support oct and hex, but that wasn't really the case.
+ * Everything based on JSON was just dec-converted. As this was/is
+ * the norm, we fix that inconsistency. Luckly, oct and hex support
+ * was never documented.
+ * rgerhards, 2015-11-12
+ */
+long long
+var2Number(struct svar *r, int *bSuccess)
+{
+ long long n = 0;
+ if(r->datatype == 'S') {
+ n = str2num(r->d.estr, bSuccess);
+ } else {
+ if(r->datatype == 'J') {
+ n = (r->d.json == NULL) ? 0 : json_object_get_int64(r->d.json);
+ } else {
+ n = r->d.n;
+ }
+ if(bSuccess != NULL)
+ *bSuccess = 1;
+ }
+ return n;
+}
+
+/* ensure that retval is a string
+ */
+static es_str_t *
+var2String(struct svar *__restrict__ const r, int *__restrict__ const bMustFree)
+{
+ es_str_t *estr;
+ const char *cstr;
+ rs_size_t lenstr;
+ if(r->datatype == 'N') {
+ *bMustFree = 1;
+ estr = es_newStrFromNumber(r->d.n);
+ } else if(r->datatype == 'J') {
+ *bMustFree = 1;
+ if(r->d.json == NULL) {
+ cstr = "",
+ lenstr = 0;
+ } else {
+ cstr = (char*)json_object_get_string(r->d.json);
+ lenstr = strlen(cstr);
+ }
+ estr = es_newStrFromCStr(cstr, lenstr);
+ } else {
+ *bMustFree = 0;
+ estr = r->d.estr;
+ }
+ return estr;
+}
+
+uchar*
+var2CString(struct svar *__restrict__ const r, int *__restrict__ const bMustFree)
+{
+ uchar *cstr;
+ es_str_t *estr;
+ estr = var2String(r, bMustFree);
+ cstr = (uchar*) es_str2cstr(estr, NULL);
+ if(*bMustFree)
+ es_deleteStr(estr);
+ *bMustFree = 1;
+ return cstr;
+}
+
+/* frees struct svar members, but not the struct itself. This is because
+ * it usually is allocated on the stack. Callers why dynamically allocate
+ * struct svar need to free the struct themselfes!
+ */
+
+int SKIP_NOTHING = 0x0;
+int SKIP_STRING = 0x1;
+
+static void
+varFreeMembersSelectively(const struct svar *r, const int skipMask)
+{
+ if(r->datatype == 'J') {
+ json_object_put(r->d.json);
+ } else if( !(skipMask & SKIP_STRING) && (r->datatype == 'S')) {
+ es_deleteStr(r->d.estr);
+ }
+}
+
+void
+varFreeMembers(const struct svar *r)
+{
+ varFreeMembersSelectively(r, SKIP_NOTHING);
+}
+
+
+static rsRetVal
+doExtractFieldByChar(uchar *str, uchar delim, const int matchnbr, uchar **resstr)
+{
+ int iCurrFld;
+ int allocLen;
+ int iLen;
+ uchar *pBuf;
+ uchar *pFld;
+ uchar *pFldEnd;
+ DEFiRet;
+
+ /* first, skip to the field in question */
+ iCurrFld = 1;
+ pFld = str;
+ while(*pFld && iCurrFld < matchnbr) {
+ /* skip fields until the requested field or end of string is found */
+ while(*pFld && (uchar) *pFld != delim)
+ ++pFld; /* skip to field terminator */
+ if(*pFld == delim) {
+ ++pFld; /* eat it */
+ ++iCurrFld;
+ }
+ }
+ DBGPRINTF("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
+
+ if(iCurrFld == matchnbr) {
+ /* field found, now extract it */
+ /* first of all, we need to find the end */
+ pFldEnd = pFld;
+ while(*pFldEnd && *pFldEnd != delim)
+ ++pFldEnd;
+ --pFldEnd; /* we are already at the delimiter - so we need to
+ * step back a little not to copy it as part of the field. */
+ /* we got our end pointer, now do the copy */
+ iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
+ allocLen = iLen + 1;
+# ifdef VALGRIND
+ allocLen += (3 - (iLen % 4));
+ /*older versions of valgrind have a problem with strlen inspecting 4-bytes at a time*/
+# endif
+ CHKmalloc(pBuf = malloc(allocLen));
+ /* now copy */
+ memcpy(pBuf, pFld, iLen);
+ pBuf[iLen] = '\0'; /* terminate it */
+ *resstr = pBuf;
+ } else {
+ ABORT_FINALIZE(RS_RET_FIELD_NOT_FOUND);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+doExtractFieldByStr(uchar *str, char *delim, const rs_size_t lenDelim, const int matchnbr, uchar **resstr)
+{
+ int iCurrFld;
+ int iLen;
+ uchar *pBuf;
+ uchar *pFld;
+ uchar *pFldEnd;
+ DEFiRet;
+
+ if (str == NULL || delim == NULL)
+ ABORT_FINALIZE(RS_RET_FIELD_NOT_FOUND);
+
+ /* first, skip to the field in question */
+ iCurrFld = 1;
+ pFld = str;
+ while(pFld != NULL && iCurrFld < matchnbr) {
+ if((pFld = (uchar*) strstr((char*)pFld, delim)) != NULL) {
+ pFld += lenDelim;
+ ++iCurrFld;
+ }
+ }
+ DBGPRINTF("field() field requested %d, field found %d\n", matchnbr, iCurrFld);
+
+ if(iCurrFld == matchnbr) {
+ /* field found, now extract it */
+ /* first of all, we need to find the end */
+ pFldEnd = (uchar*) strstr((char*)pFld, delim);
+ if(pFldEnd == NULL) {
+ iLen = strlen((char*) pFld);
+ } else { /* found delmiter! Note that pFldEnd *is* already on
+ * the first delmi char, we don't need that. */
+ iLen = pFldEnd - pFld;
+ }
+ /* we got our end pointer, now do the copy */
+ CHKmalloc(pBuf = malloc(iLen + 1));
+ /* now copy */
+ memcpy(pBuf, pFld, iLen);
+ pBuf[iLen] = '\0'; /* terminate it */
+ *resstr = pBuf;
+ } else {
+ ABORT_FINALIZE(RS_RET_FIELD_NOT_FOUND);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static void
+doFunc_re_extract(struct cnffunc *func, struct svar *ret, void* usrptr, wti_t *const pWti)
+{
+ size_t submatchnbr;
+ short matchnbr;
+ regmatch_t pmatch[50];
+ int bMustFree;
+ es_str_t *estr = NULL; /* init just to keep compiler happy */
+ char *str;
+ struct svar r[CNFFUNC_MAX_ARGS];
+ int iLenBuf;
+ unsigned iOffs;
+ short iTry = 0;
+ uchar bFound = 0;
+ iOffs = 0;
+ sbool bHadNoMatch = 0;
+
+ cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
+ /* search string is already part of the compiled regex, so we don't
+ * need it here!
+ */
+ cnfexprEval(func->expr[2], &r[2], usrptr, pWti);
+ cnfexprEval(func->expr[3], &r[3], usrptr, pWti);
+ str = (char*) var2CString(&r[0], &bMustFree);
+ matchnbr = (short) var2Number(&r[2], NULL);
+ submatchnbr = (size_t) var2Number(&r[3], NULL);
+ if(submatchnbr >= sizeof(pmatch)/sizeof(regmatch_t)) {
+ DBGPRINTF("re_extract() submatch %zd is too large\n", submatchnbr);
+ bHadNoMatch = 1;
+ goto finalize_it;
+ }
+
+ /* first see if we find a match, iterating through the series of
+ * potential matches over the string.
+ */
+ while(!bFound) {
+ int iREstat;
+ iREstat = regexp.regexec(func->funcdata, (char*)(str + iOffs),
+ submatchnbr+1, pmatch, 0);
+ DBGPRINTF("re_extract: regexec return is %d\n", iREstat);
+ if(iREstat == 0) {
+ if(pmatch[0].rm_so == -1) {
+ DBGPRINTF("oops ... start offset of successful regexec is -1\n");
+ break;
+ }
+ if(iTry == matchnbr) {
+ bFound = 1;
+ } else {
+ DBGPRINTF("re_extract: regex found at offset %d, new offset %d, tries %d\n",
+ iOffs, (int) (iOffs + pmatch[0].rm_eo), iTry);
+ iOffs += pmatch[0].rm_eo;
+ ++iTry;
+ }
+ } else {
+ break;
+ }
+ }
+ DBGPRINTF("re_extract: regex: end search, found %d\n", bFound);
+ if(!bFound) {
+ bHadNoMatch = 1;
+ goto finalize_it;
+ } else {
+ /* Match- but did it match the one we wanted? */
+ /* we got no match! */
+ if(pmatch[submatchnbr].rm_so == -1) {
+ bHadNoMatch = 1;
+ goto finalize_it;
+ }
+ /* OK, we have a usable match - we now need to malloc pB */
+ iLenBuf = pmatch[submatchnbr].rm_eo - pmatch[submatchnbr].rm_so;
+ estr = es_newStrFromBuf(str + iOffs + pmatch[submatchnbr].rm_so,
+ iLenBuf);
+ }
+
+finalize_it:
+ if(bMustFree) free(str);
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[2]);
+ varFreeMembers(&r[3]);
+
+ if(bHadNoMatch) {
+ cnfexprEval(func->expr[4], &r[4], usrptr, pWti);
+ estr = var2String(&r[4], &bMustFree);
+ varFreeMembersSelectively(&r[4], SKIP_STRING);
+ /* Note that we do NOT free the string that was returned/created
+ * for r[4]. We pass it to the caller, which in turn frees it.
+ * This saves us doing one unnecessary memory alloc & write.
+ */
+ }
+ ret->datatype = 'S';
+ ret->d.estr = estr;
+ return;
+}
+
+
+/* note that we do not need to evaluate any parameters, as the template pointer
+ * is set during initialization().
+ * TODO: think if we can keep our buffer; but that may not be trival thinking about
+ * multiple threads.
+ */
+static void
+doFunc_exec_template(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *const usrptr,
+ wti_t *const pWti __attribute__((unused)))
+{
+ smsg_t *const pMsg = (smsg_t*) usrptr;
+ rsRetVal localRet;
+ actWrkrIParams_t iparam;
+
+ wtiInitIParam(&iparam);
+ localRet = tplToString(func->funcdata, pMsg, &iparam, NULL);
+ if(localRet == RS_RET_OK) {
+ ret->d.estr = es_newStrFromCStr((char*)iparam.param, iparam.lenStr);
+ } else {
+ ret->d.estr = es_newStrFromCStr("", 0);
+ }
+ ret->datatype = 'S';
+ free(iparam.param);
+
+ return;
+}
+
+static es_str_t*
+doFuncReplace(struct svar *__restrict__ const operandVal, struct svar *__restrict__ const findVal,
+ struct svar *__restrict__ const replaceWithVal) {
+ int freeOperand, freeFind, freeReplacement;
+ es_str_t *str = var2String(operandVal, &freeOperand);
+ es_str_t *findStr = var2String(findVal, &freeFind);
+ es_str_t *replaceWithStr = var2String(replaceWithVal, &freeReplacement);
+ uchar *find = es_getBufAddr(findStr);
+ uchar *replaceWith = es_getBufAddr(replaceWithStr);
+ uint lfind = es_strlen(findStr);
+ uint lReplaceWith = es_strlen(replaceWithStr);
+ uint lSrc = es_strlen(str);
+ uint lDst = 0;
+ uchar* src_buff = es_getBufAddr(str);
+ uint i, j;
+ for(i = j = 0; i <= lSrc; i++, lDst++) {
+ if (j == lfind) {
+ lDst = lDst - lfind + lReplaceWith;
+ j = 0;
+ }
+ if (i == lSrc) break;
+ if (src_buff[i] == find[j]) {
+ j++;
+ } else if (j > 0) {
+ i -= (j - 1);
+ lDst -= (j - 1);
+ j = 0;
+ }
+ }
+ es_str_t *res = es_newStr(lDst);
+ unsigned char* dest = es_getBufAddr(res);
+ uint k, s;
+ for(i = j = s = 0; i <= lSrc; i++, s++) {
+ if (j == lfind) {
+ s -= j;
+ for (k = 0; k < lReplaceWith; k++, s++) dest[s] = replaceWith[k];
+ j = 0;
+ }
+ if (i == lSrc) break;
+ if (src_buff[i] == find[j]) {
+ j++;
+ } else {
+ if (j > 0) {
+ i -= j;
+ s -= j;
+ j = 0;
+ }
+ dest[s] = src_buff[i];
+ }
+ }
+ if (j > 0) {
+ for (k = 1; k <= j; k++) dest[s - k] = src_buff[i - k];
+ }
+ res->lenStr = lDst;
+ if(freeOperand) es_deleteStr(str);
+ if(freeFind) es_deleteStr(findStr);
+ if(freeReplacement) es_deleteStr(replaceWithStr);
+ return res;
+}
+
+
+static void ATTR_NONNULL()
+doFunc_parse_json(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *const usrptr,
+ wti_t *const pWti)
+{
+ struct svar srcVal[2];
+ int bMustFree;
+ int bMustFree2;
+ smsg_t *const pMsg = (smsg_t*)usrptr;
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ char *jsontext = (char*) var2CString(&srcVal[0], &bMustFree);
+ char *container = (char*) var2CString(&srcVal[1], &bMustFree2);
+ struct json_object *json;
+
+ int retVal;
+ assert(jsontext != NULL);
+ assert(container != NULL);
+ assert(pMsg != NULL);
+
+ struct json_tokener *const tokener = json_tokener_new();
+ if(tokener == NULL) {
+ retVal = 1;
+ goto finalize_it;
+ }
+ json = json_tokener_parse_ex(tokener, jsontext, strlen(jsontext));
+ if(json == NULL) {
+ retVal = RS_SCRIPT_EINVAL;
+ } else {
+ size_t off = (*container == '$') ? 1 : 0;
+ msgAddJSON(pMsg, (uchar*)container+off, json, 0, 0);
+ retVal = RS_SCRIPT_EOK;
+ }
+ wtiSetScriptErrno(pWti, retVal);
+ json_tokener_free(tokener);
+
+
+finalize_it:
+ ret->datatype = 'N';
+ ret->d.n = retVal;
+
+ if(bMustFree) {
+ free(jsontext);
+ }
+ if(bMustFree2) {
+ free(container);
+ }
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+}
+
+
+static void ATTR_NONNULL()
+doFunc_get_property(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *const usrptr,
+ wti_t *const pWti)
+{
+ int retVal = RS_SCRIPT_EOK;
+ int bMustFree = 0;
+ char *expr = NULL;
+ struct svar srcVal[2] = {{.d={0}, .datatype=0}};
+ struct json_object *json = NULL;
+
+ /* ignore string literals */
+ if (func->expr[0]->nodetype == 'S') {
+ retVal = RS_SCRIPT_EINVAL;
+ FINALIZE;
+ }
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ DBGPRINTF("srcval[0] datatype: %c\n", srcVal[0].datatype);
+ DBGPRINTF("srcval[1] datatype: %c\n", srcVal[1].datatype);
+
+ switch (srcVal[0].datatype) {
+ case 'J': {
+ json = srcVal[0].d.json;
+ break;
+ }
+ case 'S': {
+ ret->d.estr = es_strdup(srcVal[0].d.estr);
+ ret->datatype = 'S';
+ FINALIZE;
+ break;
+ }
+ default: {
+ ret->d.estr = es_newStrFromCStr("", 1);
+ ret->datatype = 'S';
+ FINALIZE;
+ break;
+ }
+ }
+
+ switch (json_object_get_type(json)) {
+ case json_type_object: {
+ expr = (char*) var2CString(&srcVal[1], &bMustFree);
+ if (expr && expr[0] == '\0') {
+ ret->d.json = json_object_get(json);
+ ret->datatype = 'J';
+ break;
+ }
+ if (expr && !json_object_object_get_ex(json, (char*)expr, &ret->d.json)) {
+ retVal = RS_SCRIPT_EINVAL;
+ FINALIZE;
+ }
+ if (ret->d.json) {
+ ret->d.json = json_object_get(ret->d.json);
+ ret->datatype = 'J';
+ } else {
+ ret->d.estr = es_newStrFromCStr("", 1);
+ ret->datatype = 'S';
+ }
+ break;
+ }
+ case json_type_array: {
+ int success = 0;
+ long long index = var2Number(&srcVal[1], &success);
+ if (!success || index < 0 || (size_t)index >= sizeof(size_t)) {
+ retVal = RS_SCRIPT_EINVAL;
+ FINALIZE;
+ }
+ ret->d.json = json_object_array_get_idx(json, index);
+ if (ret->d.json) {
+ ret->d.json = json_object_get(ret->d.json);
+ ret->datatype = 'J';
+ } else {
+ ret->d.estr = es_newStrFromCStr("", 1);
+ ret->datatype = 'S';
+ }
+ break;
+ }
+ case json_type_boolean:
+ case json_type_int: {
+ ret->d.n = json_object_get_int64(json);
+ ret->datatype = 'N';
+ break;
+ }
+ case json_type_double: {
+ ret->d.n = json_object_get_double(json);
+ ret->datatype = 'N';
+ break;
+ }
+ case json_type_string: {
+ ret->d.estr = es_newStrFromCStr(json_object_get_string(json), json_object_get_string_len(json));
+ ret->datatype = 'S';
+ break;
+ }
+ case json_type_null: {
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr("", 1);
+ break;
+ }
+ default:
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "Warning - unhandled json type(%d) !!!!\n", json_object_get_type(json));
+ retVal = RS_SCRIPT_EINVAL;
+ break;
+ }
+
+finalize_it:
+ wtiSetScriptErrno(pWti, retVal);
+
+ if (retVal != RS_SCRIPT_EOK) {
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromCStr("", 1);
+ }
+ if (bMustFree) {
+ free(expr);
+ }
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+}
+
+static void ATTR_NONNULL()
+doFunct_RandomGen(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ int success = 0;
+ struct svar srcVal;
+ long long retVal;
+ long int x;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ long long max = var2Number(&srcVal, &success);
+ if (! success) {
+ DBGPRINTF("rainerscript: random(max) didn't get a valid 'max' limit, defaulting random-number "
+ "value to 0");
+ retVal = 0;
+ goto done;
+ }
+ if(max == 0) {
+ DBGPRINTF("rainerscript: random(max) invalid, 'max' is zero, , defaulting random-number value to 0");
+ retVal = 0;
+ goto done;
+ }
+ x = labs(randomNumber());
+ if (max > MAX_RANDOM_NUMBER) {
+ DBGPRINTF("rainerscript: desired random-number range [0 - %lld] "
+ "is wider than supported limit of [0 - %d)\n",
+ max, MAX_RANDOM_NUMBER);
+ }
+
+ retVal = (x % max);
+done:
+ ret->d.n = retVal;
+ ret->datatype = 'N';
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_LTrim(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ char *str = (char*)var2CString(&srcVal, &bMustFree);
+
+ const int len = strlen(str);
+ int i;
+ es_str_t *estr = NULL;
+
+ for(i = 0; i < len; i++) {
+ if(str[i] != ' ') {
+ break;
+ }
+ }
+
+ estr = es_newStrFromCStr(str + i, len - i);
+
+ ret->d.estr = estr;
+ ret->datatype = 'S';
+ varFreeMembers(&srcVal);
+ if(bMustFree)
+ free(str);
+}
+
+static void ATTR_NONNULL()
+doFunct_RTrim(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ char *str = (char*)var2CString(&srcVal, &bMustFree);
+
+ int len = strlen(str);
+ int i;
+ es_str_t *estr = NULL;
+
+ for(i = (len - 1); i > 0; i--) {
+ if(str[i] != ' ') {
+ break;
+ }
+ }
+
+ if(i > 0 || str[0] != ' ') {
+ estr = es_newStrFromCStr(str, (i + 1));
+ } else {
+ estr = es_newStr(1);
+ }
+
+ ret->d.estr = estr;
+ ret->datatype = 'S';
+ varFreeMembers(&srcVal);
+ if(bMustFree)
+ free(str);
+}
+
+static void ATTR_NONNULL()
+doFunct_Getenv(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ /* note: the optimizer shall have replaced calls to getenv()
+ * with a constant argument to a single string (once obtained via
+ * getenv()). So we do NOT need to check if there is just a
+ * string following.
+ */
+ struct svar srcVal;
+ char *envvar;
+ es_str_t *estr;
+ char *str;
+ int bMustFree;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ estr = var2String(&srcVal, &bMustFree);
+ str = (char*) es_str2cstr(estr, NULL);
+ envvar = getenv(str);
+ if(envvar == NULL) {
+ ret->d.estr = es_newStr(0);
+ } else {
+ ret->d.estr = es_newStrFromCStr(envvar, strlen(envvar));
+ }
+ ret->datatype = 'S';
+ if(bMustFree) {
+ es_deleteStr(estr);
+ }
+ varFreeMembers(&srcVal);
+ free(str);
+
+}
+
+static void ATTR_NONNULL()
+doFunct_ToLower(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ es_str_t *estr;
+ int bMustFree;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ estr = var2String(&srcVal, &bMustFree);
+ if(!bMustFree) {/* let caller handle that M) */
+ estr = es_strdup(estr);
+ }
+ es_tolower(estr);
+ ret->datatype = 'S';
+ ret->d.estr = estr;
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_CStr(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ es_str_t *estr;
+ int bMustFree;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ estr = var2String(&srcVal, &bMustFree);
+ if(!bMustFree) /* let caller handle that M) */
+ estr = es_strdup(estr);
+ ret->datatype = 'S';
+ ret->d.estr = estr;
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_CNum(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+
+ if(func->expr[0]->nodetype == 'N') {
+ ret->d.n = ((struct cnfnumval*)func->expr[0])->val;
+ } else if(func->expr[0]->nodetype == 'S') {
+ ret->d.n = es_str2num(((struct cnfstringval*) func->expr[0])->estr,
+ NULL);
+ } else {
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ ret->d.n = var2Number(&srcVal, NULL);
+ varFreeMembers(&srcVal);
+ }
+ ret->datatype = 'N';
+ DBGPRINTF("JSONorString: cnum node type %c result %d\n", func->expr[0]->nodetype, (int) ret->d.n);
+}
+
+static void ATTR_NONNULL()
+doFunct_ReMatch(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ char *str;
+ int retval;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ str = (char*) var2CString(&srcVal, &bMustFree);
+ retval = regexp.regexec(func->funcdata, str, 0, NULL, 0);
+ if(retval == 0)
+ ret->d.n = 1;
+ else {
+ ret->d.n = 0;
+ if(retval != REG_NOMATCH) {
+ DBGPRINTF("re_match: regexec returned error %d\n", retval);
+ }
+ }
+ ret->datatype = 'N';
+ if(bMustFree) {
+ free(str);
+ }
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_Ipv42num(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ char *str;
+
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ str = (char*)var2CString(&srcVal, &bMustFree);
+
+
+ unsigned num[4] = {0, 0, 0, 0};
+ long long value = -1;
+ size_t len = strlen(str);
+ int cyc = 0;
+ int prevdot = 0;
+ int startblank = 0;
+ int endblank = 0;
+ DBGPRINTF("rainerscript: (ipv42num) arg: '%s'\n", str);
+ for(unsigned int i = 0 ; i < len ; i++) {
+ switch(str[i]){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if(endblank == 1){
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format "
+ "(invalid space(1))\n");
+ goto done;
+ }
+ prevdot = 0;
+ startblank = 0;
+ DBGPRINTF("rainerscript: (ipv42num) cycle: %d\n", cyc);
+ num[cyc] = num[cyc]*10+(str[i]-'0');
+ break;
+ case ' ':
+ prevdot = 0;
+ if(i == 0 || startblank == 1){
+ startblank = 1;
+ break;
+ }
+ else{
+ endblank = 1;
+ break;
+ }
+ case '.':
+ if(endblank == 1){
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format "
+ "(inalid space(2))\n");
+ goto done;
+ }
+ startblank = 0;
+ if(prevdot == 1){
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format "
+ "(two dots after one another)\n");
+ goto done;
+ }
+ prevdot = 1;
+ cyc++;
+ if(cyc > 3){
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format "
+ "(too many dots)\n");
+ goto done;
+ }
+ break;
+ default:
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format (invalid charakter)\n");
+ goto done;
+ }
+ }
+ if(cyc != 3){
+ DBGPRINTF("rainerscript: (ipv42num) error: wrong IP-Address format (wrong number of dots)\n");
+ goto done;
+ }
+ value = num[0]*256*256*256+num[1]*256*256+num[2]*256+num[3];
+done:
+ DBGPRINTF("rainerscript: (ipv42num): return value:'%lld'\n",value);
+ ret->datatype = 'N';
+ ret->d.n = value;
+ varFreeMembers(&srcVal);
+ if(bMustFree)
+ free(str);
+}
+
+static void ATTR_NONNULL()
+doFunct_Int2Hex(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int success = 0;
+ char str[18];
+ es_str_t* estr = NULL;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ long long num = var2Number(&srcVal, &success);
+
+ if (!success) {
+ DBGPRINTF("rainerscript: (int2hex) couldn't access number\n");
+ estr = es_newStrFromCStr("NAN", strlen("NAN"));
+ goto done;
+ }
+
+ snprintf(str, 18, "%llx", num);
+ estr = es_newStrFromCStr(str, strlen(str));
+
+done:
+ ret->d.estr = estr;
+ ret->datatype = 'S';
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_Replace(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal[3];
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ cnfexprEval(func->expr[2], &srcVal[2], usrptr, pWti);
+ ret->d.estr = doFuncReplace(&srcVal[0], &srcVal[1], &srcVal[2]);
+ ret->datatype = 'S';
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+ varFreeMembers(&srcVal[2]);
+}
+
+static void ATTR_NONNULL()
+doFunct_Wrap(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar sourceVal;
+ struct svar wrapperVal;
+ struct svar escaperVal;
+ int freeSource, freeWrapper;
+ es_str_t *sourceStr;
+
+ cnfexprEval(func->expr[0], &sourceVal, usrptr, pWti);
+ cnfexprEval(func->expr[1], &wrapperVal, usrptr, pWti);
+ if(func->nParams == 3) {
+ cnfexprEval(func->expr[2], &escaperVal, usrptr, pWti);
+ sourceStr = doFuncReplace(&sourceVal, &wrapperVal, &escaperVal);
+ freeSource = 1;
+
+ } else {
+ sourceStr = var2String(&sourceVal, &freeSource);
+ }
+ es_str_t *wrapperStr = var2String(&wrapperVal, &freeWrapper);
+ uchar *src = es_getBufAddr(sourceStr);
+ uchar *wrapper = es_getBufAddr(wrapperStr);
+ uint lWrapper = es_strlen(wrapperStr);
+ uint lSrc = es_strlen(sourceStr);
+ uint totalLen = lSrc + 2 * lWrapper;
+ es_str_t *res = es_newStr(totalLen);
+ uchar* resBuf = es_getBufAddr(res);
+ memcpy(resBuf, wrapper, lWrapper);
+ memcpy(resBuf + lWrapper, src, lSrc);
+ memcpy(resBuf + lSrc + lWrapper, wrapper, lWrapper);
+ res->lenStr = totalLen;
+ if (freeSource) {
+ es_deleteStr(sourceStr);
+ }
+ if (freeWrapper) {
+ es_deleteStr(wrapperStr);
+ }
+
+ ret->d.estr = res;
+ ret->datatype = 'S';
+ varFreeMembers(&sourceVal);
+ varFreeMembers(&wrapperVal);
+ if(func->nParams == 3) varFreeMembers(&escaperVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_StrLen(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ es_str_t *estr;
+
+ if(func->expr[0]->nodetype == 'S') {
+ /* if we already have a string, we do not need to
+ * do one more recursive call.
+ */
+ ret->d.n = es_strlen(((struct cnfstringval*) func->expr[0])->estr);
+ } else {
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ estr = var2String(&srcVal, &bMustFree);
+ ret->d.n = es_strlen(estr);
+ if(bMustFree) {
+ es_deleteStr(estr);
+ }
+ varFreeMembers(&srcVal);
+ }
+ ret->datatype = 'N';
+}
+
+static void ATTR_NONNULL()
+doFunct_Substring(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{ //TODO: generalize parameter getter? jgerhards, 2018-02-26
+ int bMustFree;
+ struct svar srcVal[3];
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ cnfexprEval(func->expr[2], &srcVal[2], usrptr, pWti);
+ es_str_t *es = var2String(&srcVal[0], &bMustFree);
+ const int lenSrcStr = es_strlen(es);
+ int start = var2Number(&srcVal[1], NULL);
+ int subStrLen = var2Number(&srcVal[2], NULL);
+ if(start >= lenSrcStr) {
+ /* begin PAST the source string - ensure nothing is copied at all */
+ start = subStrLen = 0;
+ } else {
+ if(subStrLen < 0) {
+ subStrLen = lenSrcStr + subStrLen; /* "add" negative offset! */
+ if(subStrLen < 0) {
+ subStrLen = 0;
+ }
+ }
+ if(subStrLen > (lenSrcStr - start)) {
+ subStrLen = lenSrcStr - start;
+ }
+ }
+
+ ret->datatype = 'S';
+ ret->d.estr = es_newStrFromSubStr(es, (es_size_t)start, (es_size_t)subStrLen);
+ if(bMustFree) es_deleteStr(es);
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+ varFreeMembers(&srcVal[2]);
+}
+
+static void ATTR_NONNULL()
+doFunct_Field(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal[3];
+ int bMustFree;
+ char *str;
+ uchar *resStr;
+ int matchnbr;
+ int delim;
+ rsRetVal localRet;
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ cnfexprEval(func->expr[2], &srcVal[2], usrptr, pWti);
+ str = (char*) var2CString(&srcVal[0], &bMustFree);
+ matchnbr = var2Number(&srcVal[2], NULL);
+ if(srcVal[1].datatype == 'S') {
+ char *delimstr;
+ delimstr = (char*) es_str2cstr(srcVal[1].d.estr, NULL);
+ localRet = doExtractFieldByStr((uchar*)str, delimstr, es_strlen(srcVal[1].d.estr),
+ matchnbr, &resStr);
+ free(delimstr);
+ } else {
+ delim = var2Number(&srcVal[1], NULL);
+ localRet = doExtractFieldByChar((uchar*)str, (char) delim, matchnbr, &resStr);
+ }
+ if(localRet == RS_RET_OK) {
+ ret->d.estr = es_newStrFromCStr((char*)resStr, strlen((char*)resStr));
+ free(resStr);
+ } else if(localRet == RS_RET_FIELD_NOT_FOUND) {
+ ret->d.estr = es_newStrFromCStr("***FIELD NOT FOUND***",
+ sizeof("***FIELD NOT FOUND***")-1);
+ } else {
+ ret->d.estr = es_newStrFromCStr("***ERROR in field() FUNCTION***",
+ sizeof("***ERROR in field() FUNCTION***")-1);
+ }
+ ret->datatype = 'S';
+ if(bMustFree) free(str);
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+ varFreeMembers(&srcVal[2]);
+}
+
+static void ATTR_NONNULL()
+doFunct_Prifilt(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *const pWti __attribute__((unused)))
+{
+ struct funcData_prifilt *pPrifilt;
+
+ pPrifilt = (struct funcData_prifilt*) func->funcdata;
+ if( (pPrifilt->pmask[((smsg_t*)usrptr)->iFacility] == TABLE_NOPRI) ||
+ ((pPrifilt->pmask[((smsg_t*)usrptr)->iFacility]
+ & (1<<((smsg_t*)usrptr)->iSeverity)) == 0) )
+ ret->d.n = 0;
+ else
+ ret->d.n = 1;
+ ret->datatype = 'N';
+}
+
+static void ATTR_NONNULL()
+doFunct_Lookup(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ lookup_key_t key;
+ uint8_t lookup_key_type;
+ lookup_ref_t *lookup_table_ref;
+ lookup_t *lookup_table;
+ int bMustFree;
+
+ ret->datatype = 'S';
+ if(func->funcdata == NULL) {
+ ret->d.estr = es_newStrFromCStr("TABLE-NOT-FOUND", sizeof("TABLE-NOT-FOUND")-1);
+ return;
+ }
+ cnfexprEval(func->expr[1], &srcVal, usrptr, pWti);
+ lookup_table_ref = (lookup_ref_t*) func->funcdata;
+ pthread_rwlock_rdlock(&lookup_table_ref->rwlock);
+ lookup_table = lookup_table_ref->self;
+ if (lookup_table != NULL) {
+ lookup_key_type = lookup_table->key_type;
+ bMustFree = 0;
+ if (lookup_key_type == LOOKUP_KEY_TYPE_STRING) {
+ key.k_str = (uchar*) var2CString(&srcVal, &bMustFree);
+ } else if (lookup_key_type == LOOKUP_KEY_TYPE_UINT) {
+ key.k_uint = var2Number(&srcVal, NULL);
+ } else {
+ DBGPRINTF("program error in %s:%d: lookup_key_type unknown\n",
+ __FILE__, __LINE__);
+ key.k_uint = 0;
+ }
+ ret->d.estr = lookupKey((lookup_ref_t*)func->funcdata, key);
+ if(bMustFree) {
+ free(key.k_str);
+ }
+ } else {
+ ret->d.estr = es_newStrFromCStr("", 1);
+ }
+ pthread_rwlock_unlock(&lookup_table_ref->rwlock);
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_DynInc(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ char *str;
+
+ ret->datatype = 'N';
+ if(func->funcdata == NULL) {
+ ret->d.n = -1;
+ return;
+ }
+ cnfexprEval(func->expr[1], &srcVal, usrptr, pWti);
+ str = (char*) var2CString(&srcVal, &bMustFree);
+ ret->d.n = dynstats_inc(func->funcdata, (uchar*)str);
+ if(bMustFree) free(str);
+ varFreeMembers(&srcVal);
+}
+
+static void ATTR_NONNULL()
+doFunct_FormatTime(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal[2];
+ int bMustFree;
+ char *str;
+ int retval;
+ long long unixtime;
+ const int resMax = 64;
+ char result[resMax];
+ char *formatstr = NULL;
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+
+ unixtime = var2Number(&srcVal[0], &retval);
+
+ // Make sure that the timestamp we got can fit into
+ // time_t on older systems.
+ if (sizeof(time_t) == sizeof(int)) {
+ if (unixtime < INT_MIN || unixtime > INT_MAX) {
+ LogMsg(
+ 0, RS_RET_VAL_OUT_OF_RANGE, LOG_WARNING,
+ "Timestamp value %lld is out of range for this system (time_t is "
+ "32bits)!\n", unixtime
+ );
+ retval = 0;
+ }
+ }
+
+ // We want the string form too so we can return it as the
+ // default if we run into problems parsing the number.
+ str = (char*) var2CString(&srcVal[0], &bMustFree);
+ formatstr = (char*) es_str2cstr(srcVal[1].d.estr, NULL);
+
+ ret->datatype = 'S';
+
+ if (objUse(datetime, CORE_COMPONENT) != RS_RET_OK) {
+ ret->d.estr = es_newStr(0);
+ } else {
+ if (!retval || datetime.formatUnixTimeFromTime_t(unixtime, formatstr, result, resMax) == -1) {
+ strncpy(result, str, resMax);
+ result[resMax - 1] = '\0';
+ }
+ ret->d.estr = es_newStrFromCStr(result, strlen(result));
+ }
+
+ if (bMustFree) {
+ free(str);
+ }
+ free(formatstr);
+
+ varFreeMembers(&srcVal[0]);
+ varFreeMembers(&srcVal[1]);
+
+}
+
+/*
+ * Uses the given (current) year/month to decide which year
+ * the incoming month likely belongs in.
+ *
+ * cy - Current Year (actual)
+ * cm - Current Month (actual)
+ * im - "Incoming" Month
+ */
+static int
+estimateYear(int cy, int cm, int im) {
+ im += 12;
+
+ if ((im - cm) == 1) {
+ if (cm == 12 && im == 13)
+ return cy + 1;
+ }
+
+ if ((im - cm) > 13)
+ return cy - 1;
+
+ return cy;
+}
+
+static void ATTR_NONNULL()
+doFunct_ParseTime(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ char *str = (char*) var2CString(&srcVal, &bMustFree);
+ ret->datatype = 'N';
+ ret->d.n = 0;
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EOK);
+
+ if (objUse(datetime, CORE_COMPONENT) == RS_RET_OK) {
+ struct syslogTime s;
+ int len = strlen(str);
+ uchar *pszTS = (uchar*) str;
+ memset(&s, 0, sizeof(struct syslogTime));
+ // Attempt to parse the date/time string
+ if (datetime.ParseTIMESTAMP3339(&s, (uchar**) &pszTS, &len) == RS_RET_OK) {
+ ret->d.n = datetime.syslogTime2time_t(&s);
+ DBGPRINTF("parse_time: RFC3339 format found\n");
+ } else if (datetime.ParseTIMESTAMP3164(&s, (uchar**) &pszTS, &len,
+ NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
+ time_t t = time(NULL);
+ struct tm tm;
+ gmtime_r(&t, &tm); // Get the current UTC date
+ // Since properly formatted RFC 3164 timestamps do not have a YEAR
+ // specified, we have to assume one that seems reasonable - SW.
+ s.year = estimateYear(tm.tm_year + 1900, tm.tm_mon + 1, s.month);
+ ret->d.n = datetime.syslogTime2time_t(&s);
+ DBGPRINTF("parse_time: RFC3164 format found\n");
+ } else {
+ DBGPRINTF("parse_time: no valid format found\n");
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EINVAL);
+ }
+ }
+
+ if(bMustFree) {
+ free(str);
+ }
+ varFreeMembers(&srcVal);
+
+}
+
+static int ATTR_NONNULL(1,3,4)
+doFunc_is_time(const char *__restrict__ const str,
+ const char *__restrict__ const fmt,
+ struct svar *__restrict__ const r,
+ wti_t *pWti) {
+
+ assert(str != NULL);
+ assert(r != NULL);
+ assert(pWti != NULL);
+
+ int ret = 0;
+
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EOK);
+
+ if (objUse(datetime, CORE_COMPONENT) == RS_RET_OK) {
+ struct syslogTime s;
+ int len = strlen(str);
+ uchar *pszTS = (uchar*) str;
+
+ int numFormats = 3;
+ dateTimeFormat_t formats[] = { DATE_RFC3164, DATE_RFC3339, DATE_UNIX };
+ dateTimeFormat_t pf[] = { DATE_INVALID };
+ dateTimeFormat_t *p = formats;
+
+ // Check if a format specifier was explicitly provided
+ if (fmt != NULL) {
+ numFormats = 1;
+ *pf = getDateTimeFormatFromStr(fmt);
+ p = pf;
+ }
+
+ // Enumerate format specifier options, looking for the first match
+ for (int i = 0; i < numFormats; i++) {
+ dateTimeFormat_t f = p[i];
+
+ if (f == DATE_RFC3339) {
+ if (datetime.ParseTIMESTAMP3339(&s, (uchar**) &pszTS, &len) == RS_RET_OK) {
+ DBGPRINTF("is_time: RFC3339 format found.\n");
+ ret = 1;
+ break;
+ }
+ } else if (f == DATE_RFC3164) {
+ if (datetime.ParseTIMESTAMP3164(&s, (uchar**) &pszTS, &len,
+ NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
+ DBGPRINTF("is_time: RFC3164 format found.\n");
+ ret = 1;
+ break;
+ }
+ } else if (f == DATE_UNIX) {
+ int result;
+ var2Number(r, &result);
+
+ if (result) {
+ DBGPRINTF("is_time: UNIX format found.\n");
+ ret = 1;
+ break;
+ }
+ } else {
+ DBGPRINTF("is_time: %s is not a valid date/time format specifier!\n", fmt);
+ break;
+ }
+ }
+ }
+
+ // If not a valid date/time string, set 'errno'
+ if (ret == 0) {
+ DBGPRINTF("is_time: Invalid date-time string: %s.\n", str);
+ wtiSetScriptErrno(pWti, RS_SCRIPT_EINVAL);
+ }
+
+ return ret;
+}
+
+static void ATTR_NONNULL()
+doFunct_IsTime(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal[2];
+ int bMustFree;
+ int bMustFree2;
+ char *fmt = NULL;
+
+ cnfexprEval(func->expr[0], &srcVal[0], usrptr, pWti);
+ char *str = (char*) var2CString(&srcVal[0], &bMustFree);
+
+ bMustFree2 = 0;
+
+ // Check if the optional 2nd parameter was provided
+ if(func->nParams == 2) {
+ cnfexprEval(func->expr[1], &srcVal[1], usrptr, pWti);
+ fmt = (char*) var2CString(&srcVal[1], &bMustFree2);
+ }
+
+ ret->datatype = 'N';
+ ret->d.n = doFunc_is_time(str, fmt, &srcVal[0], pWti);
+
+ if(bMustFree) {
+ free(str);
+ }
+ if(bMustFree2) {
+ free(fmt);
+ }
+ varFreeMembers(&srcVal[0]);
+ if(func->nParams == 2) {
+ varFreeMembers(&srcVal[1]);
+ }
+}
+
+static void ATTR_NONNULL()
+doFunct_ScriptError(struct cnffunc *const func __attribute__((unused)),
+ struct svar *__restrict__ const ret,
+ void *const usrptr __attribute__((unused)),
+ wti_t *__restrict__ const pWti)
+{
+ ret->datatype = 'N';
+ ret->d.n = wtiGetScriptErrno(pWti);
+ DBGPRINTF("script_error() is %d\n", (int) ret->d.n);
+}
+
+static void ATTR_NONNULL()
+doFunct_PreviousActionSuspended(struct cnffunc *const func __attribute__((unused)),
+ struct svar *__restrict__ const ret,
+ void *const usrptr __attribute__((unused)),
+ wti_t *__restrict__ const pWti)
+{
+ ret->datatype = 'N';
+ ret->d.n = wtiGetPrevWasSuspended(pWti);
+ DBGPRINTF("previous_action_suspended() is %d\n", (int) ret->d.n);
+}
+
+static void ATTR_NONNULL()
+doFunct_num2ipv4(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ int success = 0;
+ long long num = var2Number(&srcVal, &success);
+ varFreeMembers(&srcVal);
+
+ int numip[4];
+ char str[16];
+ size_t len;
+ DBGPRINTF("rainrescript: (num2ipv4) var2Number output: '%lld\n'", num);
+ if (! success) {
+ DBGPRINTF("rainerscript: (num2ipv4) couldn't access number\n");
+ len = snprintf(str, 16, "-1");
+ goto done;
+ }
+ if(num < 0 || num > 4294967295) {
+ DBGPRINTF("rainerscript: (num2ipv4) invalid number(too big/negative); does "
+ "not represent IPv4 address\n");
+ len = snprintf(str, 16, "-1");
+ goto done;
+ }
+ for(int i = 0 ; i < 4 ; i++){
+ numip[i] = num % 256;
+ num = num / 256;
+ }
+ DBGPRINTF("rainerscript: (num2ipv4) Numbers: 1:'%d' 2:'%d' 3:'%d' 4:'%d'\n",
+ numip[0], numip[1], numip[2], numip[3]);
+ len = snprintf(str, 16, "%d.%d.%d.%d", numip[3], numip[2], numip[1], numip[0]);
+done:
+ DBGPRINTF("rainerscript: (num2ipv4) ipv4-Address: %s, length: %zu\n", str, len);
+ ret->d.estr = es_newStrFromCStr(str, len);
+ ret->datatype = 'S';
+}
+
+
+/* Perform a function call. This has been moved out of cnfExprEval in order
+ * to keep the code small and easier to maintain.
+ */
+static void ATTR_NONNULL()
+doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+
+ if(Debug) {
+ char *fname = es_str2cstr(func->fname, NULL);
+ DBGPRINTF("rainerscript: executing function id %s\n", fname);
+ free(fname);
+ }
+ if(func->fPtr == NULL) {
+ char *fname = es_str2cstr(func->fname, NULL);
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "rainerscript: internal error: NULL pointer for function named '%s'\n",
+ fname);
+ free(fname);
+ ret->datatype = 'N';
+ ret->d.n = 0;
+ } else {
+ func->fPtr(func, ret, usrptr, pWti);
+ }
+}
+
+
+/* Perform the special "exists()" function to check presence of a variable.
+ */
+static int ATTR_NONNULL()
+evalFuncExists(struct cnffuncexists *__restrict__ const fexists, void *__restrict__ const usrptr)
+{
+ int r = 0;
+ rsRetVal localRet;
+
+ if(fexists->prop.id == PROP_CEE ||
+ fexists->prop.id == PROP_LOCAL_VAR ||
+ fexists->prop.id == PROP_GLOBAL_VAR ) {
+ localRet = msgCheckVarExists((smsg_t*)usrptr, &fexists->prop);
+ if(localRet == RS_RET_OK) {
+ r = 1;
+ }
+ }
+
+ return r;
+}
+
+static void
+evalVar(struct cnfvar *__restrict__ const var, void *__restrict__ const usrptr,
+ struct svar *__restrict__ const ret)
+{
+ rs_size_t propLen;
+ uchar *pszProp = NULL;
+ unsigned short bMustBeFreed = 0;
+ rsRetVal localRet;
+ struct json_object *json;
+ uchar *cstr;
+
+ if(var->prop.id == PROP_CEE ||
+ var->prop.id == PROP_LOCAL_VAR ||
+ var->prop.id == PROP_GLOBAL_VAR ) {
+ localRet = msgGetJSONPropJSONorString((smsg_t*)usrptr, &var->prop, &json, &cstr);
+ if(json != NULL) {
+ assert(cstr == NULL);
+ ret->datatype = 'J';
+ ret->d.json = (localRet == RS_RET_OK) ? json : NULL;
+ DBGPRINTF("rainerscript: (json) var %d:%s: '%s'\n",
+ var->prop.id, var->prop.name,
+ (ret->d.json == NULL) ? "" : json_object_get_string(ret->d.json));
+ } else { /* we have a string */
+ DBGPRINTF("rainerscript: (json/string) var %d: '%s'\n", var->prop.id, cstr);
+ ret->datatype = 'S';
+ ret->d.estr = (localRet != RS_RET_OK || cstr == NULL) ?
+ es_newStr(1)
+ : es_newStrFromCStr((char*) cstr, strlen((char*) cstr));
+ free(cstr);
+ }
+ } else {
+ ret->datatype = 'S';
+ pszProp = (uchar*) MsgGetProp((smsg_t*)usrptr, NULL, &var->prop, &propLen, &bMustBeFreed, NULL);
+ ret->d.estr = es_newStrFromCStr((char*)pszProp, propLen);
+ DBGPRINTF("rainerscript: (string) var %d: '%s'\n", var->prop.id, pszProp);
+ if(bMustBeFreed)
+ free(pszProp);
+ }
+
+}
+
+/* perform a string comparision operation against a while array. Semantic is
+ * that one one comparison is true, the whole construct is true.
+ * TODO: we can obviously optimize this process. One idea is to
+ * compile a regex, which should work faster than serial comparison.
+ * Note: compiling a regex does NOT work at all. I experimented with that
+ * and it was generally 5 to 10 times SLOWER than what we do here...
+ */
+static int
+evalStrArrayCmp(es_str_t *const estr_l,
+ const struct cnfarray *__restrict__ const ar,
+ const int cmpop)
+{
+ int i;
+ int r = 0;
+ es_str_t **res;
+ if(cmpop == CMP_EQ) {
+ res = bsearch(&estr_l, ar->arr, ar->nmemb, sizeof(es_str_t*), qs_arrcmp);
+ r = res != NULL;
+ } else if(cmpop == CMP_NE) {
+ res = bsearch(&estr_l, ar->arr, ar->nmemb, sizeof(es_str_t*), qs_arrcmp);
+ r = res == NULL;
+ } else {
+ for(i = 0 ; (r == 0) && (i < ar->nmemb) ; ++i) {
+ switch(cmpop) {
+ case CMP_STARTSWITH:
+ r = es_strncmp(estr_l, ar->arr[i], es_strlen(ar->arr[i])) == 0;
+ break;
+ case CMP_STARTSWITHI:
+ r = es_strncasecmp(estr_l, ar->arr[i], es_strlen(ar->arr[i])) == 0;
+ break;
+ case CMP_CONTAINS:
+ r = es_strContains(estr_l, ar->arr[i]) != -1;
+ break;
+ case CMP_CONTAINSI:
+ r = es_strCaseContains(estr_l, ar->arr[i]) != -1;
+ break;
+ }
+ }
+ }
+ return r;
+}
+
+#define FREE_BOTH_RET \
+ varFreeMembers(&r); \
+ varFreeMembers(&l)
+
+#define COMP_NUM_BINOP(x) \
+ cnfexprEval(expr->l, &l, usrptr, pWti); \
+ cnfexprEval(expr->r, &r, usrptr, pWti); \
+ ret->datatype = 'N'; \
+ ret->d.n = var2Number(&l, &convok_l) x var2Number(&r, &convok_r); \
+ FREE_BOTH_RET
+
+#define COMP_NUM_BINOP_DIV(x) \
+ cnfexprEval(expr->l, &l, usrptr, pWti); \
+ cnfexprEval(expr->r, &r, usrptr, pWti); \
+ ret->datatype = 'N'; \
+ if((ret->d.n = var2Number(&r, &convok_r)) == 0) { \
+ /* division by zero */ \
+ } else { \
+ ret->d.n = var2Number(&l, &convok_l) x ret->d.n; \
+ } \
+ FREE_BOTH_RET
+
+/* NOTE: array as right-hand argument MUST be handled by user */
+#define PREP_TWO_STRINGS \
+ cnfexprEval(expr->l, &l, usrptr, pWti); \
+ estr_l = var2String(&l, &bMustFree2); \
+ if(expr->r->nodetype == 'S') { \
+ estr_r = ((struct cnfstringval*)expr->r)->estr;\
+ bMustFree = 0; \
+ } else if(expr->r->nodetype != 'A') { \
+ cnfexprEval(expr->r, &r, usrptr, pWti); \
+ estr_r = var2String(&r, &bMustFree); \
+ } else { \
+ /* Note: this is not really necessary, but if we do not */ \
+ /* do it, we get a very irritating compiler warning... */ \
+ estr_r = NULL; \
+ }
+
+#define FREE_TWO_STRINGS \
+ if(bMustFree) es_deleteStr(estr_r); \
+ if(expr->r->nodetype != 'S' && expr->r->nodetype != 'A') varFreeMembers(&r); \
+ if(bMustFree2) es_deleteStr(estr_l); \
+ varFreeMembers(&l)
+
+/* helper to evaluate comparison in a strcmp() like manner. Result is
+ * to be used for final truth value evaluation.
+ */
+static int eval_strcmp_like(const struct cnfexpr *__restrict__ const expr,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ es_str_t *__restrict__ estr_r, *__restrict__ estr_l;
+ int bMustFree, bMustFree2;
+ int64_t n_r, n_l;
+ int convok_r, convok_l;
+ struct svar r, l; /* memory for subexpression results */
+ int ret;
+
+ cnfexprEval(expr->l, &l, usrptr, pWti);
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ n_l = var2Number(&l, &convok_l);
+ if(convok_l) {
+ n_r = var2Number(&r, &convok_r);
+ }
+ if(convok_l && convok_r) {
+ ret = n_l - n_r;
+ } else {
+ estr_l = var2String(&l, &bMustFree);
+ estr_r = var2String(&r, &bMustFree2);
+ ret = es_strcmp(estr_l, estr_r);
+ if(bMustFree) es_deleteStr(estr_l);
+ if(bMustFree2) es_deleteStr(estr_r);
+ }
+ FREE_BOTH_RET;
+ return ret;
+}
+
+/* evaluate an expression.
+ * Note that we try to avoid malloc whenever possible (because of
+ * the large overhead it has, especially on highly threaded programs).
+ * As such, the each caller level must provide buffer space for the
+ * result on its stack during recursion. This permits the callee to store
+ * the return value without malloc. As the value is a somewhat larger
+ * struct, we could otherwise not return it without malloc.
+ * Note that we implement boolean shortcut operations. For our needs, there
+ * simply is no case where full evaluation would make any sense at all.
+ */
+void ATTR_NONNULL()
+cnfexprEval(const struct cnfexpr *__restrict__ const expr,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar r, l; /* memory for subexpression results */
+ es_str_t *__restrict__ estr_r, *__restrict__ estr_l;
+ int convok_r, convok_l;
+ int bMustFree, bMustFree2;
+ long long n_r, n_l;
+
+ DBGPRINTF("eval expr %p, type '%s'\n", expr, tokenToString(expr->nodetype));
+ switch(expr->nodetype) {
+ /* note: comparison operations are extremely similar. The code can be copyied, only
+ * places flagged with "CMP" need to be changed.
+ */
+ case CMP_EQ:
+ /* this is optimized in regard to right param as a PoC for all compOps
+ * So this is a NOT yet the copy template!
+ */
+ cnfexprEval(expr->l, &l, usrptr, pWti);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(expr->r->nodetype == 'S') {
+ ret->d.n = !es_strcmp(l.d.estr, ((struct cnfstringval*)expr->r)->estr); /*CMP*/
+ } else if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(l.d.estr, (struct cnfarray*) expr->r, CMP_EQ);
+ } else {
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ if(r.datatype == 'S') {
+ ret->d.n = !es_strcmp(l.d.estr, r.d.estr); /*CMP*/
+ } else {
+ n_l = var2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l == r.d.n); /*CMP*/
+ } else {
+ estr_r = var2String(&r, &bMustFree);
+ ret->d.n = !es_strcmp(l.d.estr, estr_r); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ varFreeMembers(&r);
+ }
+ } else if(l.datatype == 'J') {
+ estr_l = var2String(&l, &bMustFree);
+ if(expr->r->nodetype == 'S') {
+ ret->d.n = !es_strcmp(estr_l, ((struct cnfstringval*)expr->r)->estr); /*CMP*/
+ } else if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_EQ);
+ } else {
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ if(r.datatype == 'S') {
+ ret->d.n = !es_strcmp(estr_l, r.d.estr); /*CMP*/
+ } else {
+ n_l = var2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l == r.d.n); /*CMP*/
+ } else {
+ estr_r = var2String(&r, &bMustFree2);
+ ret->d.n = !es_strcmp(estr_l, estr_r); /*CMP*/
+ if(bMustFree2) es_deleteStr(estr_r);
+ }
+ }
+ varFreeMembers(&r);
+ }
+ if(bMustFree) es_deleteStr(estr_l);
+ } else {
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ if(r.datatype == 'S') {
+ n_r = var2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n == n_r); /*CMP*/
+ } else {
+ estr_l = var2String(&l, &bMustFree);
+ ret->d.n = !es_strcmp(r.d.estr, estr_l); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n == r.d.n); /*CMP*/
+ }
+ varFreeMembers(&r);
+ }
+ varFreeMembers(&l);
+ break;
+ case CMP_NE:
+ cnfexprEval(expr->l, &l, usrptr, pWti);
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(expr->r->nodetype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, ((struct cnfstringval*)expr->r)->estr); /*CMP*/
+ } else if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(l.d.estr, (struct cnfarray*) expr->r, CMP_NE);
+ } else {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr); /*CMP*/
+ } else {
+ n_l = var2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l != r.d.n); /*CMP*/
+ } else {
+ estr_r = var2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ }
+ } else if(l.datatype == 'J') {
+ estr_l = var2String(&l, &bMustFree);
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(estr_l, r.d.estr); /*CMP*/
+ } else {
+ n_l = var2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l != r.d.n); /*CMP*/
+ } else {
+ estr_r = var2String(&r, &bMustFree2);
+ ret->d.n = es_strcmp(estr_l, estr_r); /*CMP*/
+ if(bMustFree2) es_deleteStr(estr_r);
+ }
+ }
+ if(bMustFree) es_deleteStr(estr_l);
+ } else {
+ if(r.datatype == 'S') {
+ n_r = var2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n != n_r); /*CMP*/
+ } else {
+ estr_l = var2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n != r.d.n); /*CMP*/
+ }
+ }
+ FREE_BOTH_RET;
+ break;
+ case CMP_LE:
+ ret->datatype = 'N';
+ ret->d.n = eval_strcmp_like(expr, usrptr, pWti) <= 0;
+ break;
+ case CMP_GE:
+ ret->datatype = 'N';
+ ret->d.n = eval_strcmp_like(expr, usrptr, pWti) >= 0;
+ break;
+ case CMP_LT:
+ ret->datatype = 'N';
+ ret->d.n = eval_strcmp_like(expr, usrptr, pWti) < 0;
+ break;
+ case CMP_GT:
+ ret->datatype = 'N';
+ ret->d.n = eval_strcmp_like(expr, usrptr, pWti) > 0;
+ break;
+ case CMP_STARTSWITH:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_STARTSWITH);
+ bMustFree = 0;
+ } else {
+ ret->d.n = es_strncmp(estr_l, estr_r, estr_r->lenStr) == 0;
+ }
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_STARTSWITHI:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_STARTSWITHI);
+ bMustFree = 0;
+ } else {
+ ret->d.n = es_strncasecmp(estr_l, estr_r, estr_r->lenStr) == 0;
+ }
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_CONTAINS:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_CONTAINS);
+ bMustFree = 0;
+ } else {
+ ret->d.n = es_strContains(estr_l, estr_r) != -1;
+ }
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_CONTAINSI:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ if(expr->r->nodetype == 'A') {
+ ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_CONTAINSI);
+ bMustFree = 0;
+ } else {
+ ret->d.n = es_strCaseContains(estr_l, estr_r) != -1;
+ }
+ FREE_TWO_STRINGS;
+ break;
+ case OR:
+ cnfexprEval(expr->l, &l, usrptr, pWti);
+ ret->datatype = 'N';
+ if(var2Number(&l, &convok_l)) {
+ ret->d.n = 1ll;
+ } else {
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ if(var2Number(&r, &convok_r))
+ ret->d.n = 1ll;
+ else
+ ret->d.n = 0ll;
+ varFreeMembers(&r);
+ }
+ varFreeMembers(&l);
+ break;
+ case AND:
+ cnfexprEval(expr->l, &l, usrptr, pWti);
+ ret->datatype = 'N';
+ if(var2Number(&l, &convok_l)) {
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ if(var2Number(&r, &convok_r))
+ ret->d.n = 1ll;
+ else
+ ret->d.n = 0ll;
+ varFreeMembers(&r);
+ } else {
+ ret->d.n = 0ll;
+ }
+ varFreeMembers(&l);
+ break;
+ case NOT:
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ ret->datatype = 'N';
+ ret->d.n = !var2Number(&r, &convok_r);
+ varFreeMembers(&r);
+ break;
+ case 'N':
+ ret->datatype = 'N';
+ ret->d.n = ((struct cnfnumval*)expr)->val;
+ break;
+ case 'S':
+ ret->datatype = 'S';
+ ret->d.estr = es_strdup(((struct cnfstringval*)expr)->estr);
+ break;
+ case 'A':
+ /* if an array is used with "normal" operations, it just evaluates
+ * to its first element.
+ */
+ ret->datatype = 'S';
+ ret->d.estr = es_strdup(((struct cnfarray*)expr)->arr[0]);
+ break;
+ case 'V':
+ evalVar((struct cnfvar*)expr, usrptr, ret);
+ break;
+ case '&':
+ /* TODO: think about optimization, should be possible ;) */
+ PREP_TWO_STRINGS;
+ if(expr->r->nodetype == 'A') {
+ estr_r = ((struct cnfarray*)expr->r)->arr[0];
+ bMustFree = 0;
+ }
+ ret->datatype = 'S';
+ ret->d.estr = es_strdup(estr_l);
+ es_addStr(&ret->d.estr, estr_r);
+ FREE_TWO_STRINGS;
+ break;
+ case '+':
+ COMP_NUM_BINOP(+);
+ break;
+ case '-':
+ COMP_NUM_BINOP(-);
+ break;
+ case '*':
+ COMP_NUM_BINOP(*);
+ break;
+ case '/':
+ COMP_NUM_BINOP_DIV(/);
+ break;
+ case '%':
+ COMP_NUM_BINOP_DIV(%);
+ break;
+ case 'M':
+ cnfexprEval(expr->r, &r, usrptr, pWti);
+ ret->datatype = 'N';
+ ret->d.n = -var2Number(&r, &convok_r);
+ varFreeMembers(&r);
+ break;
+ case 'F':
+ doFuncCall((struct cnffunc*) expr, ret, usrptr, pWti);
+ break;
+ case S_FUNC_EXISTS:
+ ret->datatype = 'N';
+ ret->d.n = evalFuncExists((struct cnffuncexists*) expr, usrptr);
+ break;
+ default:
+ ret->datatype = 'N';
+ ret->d.n = 0ll;
+ DBGPRINTF("eval error: unknown nodetype %u['%c']\n",
+ (unsigned) expr->nodetype, (char) expr->nodetype);
+ assert(0); /* abort on debug builds, this must not happen! */
+ break;
+ }
+ DBGPRINTF("eval expr %p, return datatype '%c':%d\n", expr, ret->datatype,
+ (ret->datatype == 'N') ? (int)ret->d.n: 0);
+}
+
+//---------------------------------------------------------
+
+void
+cnfarrayContentDestruct(struct cnfarray *ar)
+{
+ unsigned short i;
+ for(i = 0 ; i < ar->nmemb ; ++i) {
+ es_deleteStr(ar->arr[i]);
+ }
+ free(ar->arr);
+}
+
+static void
+regex_destruct(struct cnffunc *func) {
+ if(func->funcdata != NULL) {
+ regexp.regfree(func->funcdata);
+ }
+}
+
+static rsRetVal
+initFunc_dyn_stats(struct cnffunc *func)
+{
+ uchar *cstr = NULL;
+ DEFiRet;
+
+ func->destructable_funcdata = 0;
+
+ if(func->nParams != 2) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ func->funcdata = NULL;
+ if(func->expr[0]->nodetype != 'S') {
+ parser_errmsg("dyn-stats bucket-name (param 1) of dyn-stats manipulating "
+ "functions like dyn_inc must be a constant string");
+ FINALIZE;
+ }
+
+ cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
+ if((func->funcdata = dynstats_findBucket(cstr)) == NULL) {
+ parser_errmsg("dyn-stats bucket '%s' not found", cstr);
+ FINALIZE;
+ }
+
+finalize_it:
+ free(cstr);
+ RETiRet;
+}
+
+static rsRetVal
+initFunc_perctile_obs(struct cnffunc *func)
+{
+ uchar *cstr = NULL;
+ DEFiRet;
+
+ func->destructable_funcdata = 0;
+ if (func->nParams != 3) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ func->funcdata = NULL;
+ if (func->expr[0]->nodetype != 'S') {
+ parser_errmsg("percentile-stats bucket-name (param 1) of perctile-stats manipulating "
+ "functions like percentile_observe must be a constant string");
+ FINALIZE;
+ }
+
+ cstr = (uchar*) es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
+ if ( (func->funcdata = perctile_findBucket(cstr)) == NULL) {
+ parser_errmsg("perctile-stats bucket '%s' not found", cstr);
+ FINALIZE;
+ }
+
+finalize_it:
+ free(cstr);
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+doFunc_percentile_obs(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ uchar *cstr = NULL;
+ struct svar srcVal;
+ int bMustFree;
+
+ ret->datatype = 'N';
+ if(func->funcdata == NULL) {
+ ret->d.n = -1;
+ return;
+ }
+
+ cnfexprEval(func->expr[1], &srcVal, usrptr, pWti);
+ cstr = (uchar*) var2CString(&srcVal, &bMustFree);
+
+ int success = 0;
+ struct svar srcVal2;
+ long long retVal;
+ cnfexprEval(func->expr[2], &srcVal2, usrptr, pWti);
+ long long val = var2Number(&srcVal2, &success);
+ if (!success) {
+ char *cstr2 = es_str2cstr(srcVal2.d.estr, NULL);
+ parser_errmsg("rainerscript: percentile_obs - didn't get a valid number: %s\n", cstr2);
+ free(cstr2);
+ retVal = 0;
+ FINALIZE;
+ }
+
+ retVal = perctile_obs(func->funcdata, cstr, val);
+
+finalize_it:
+ if (bMustFree) {
+ free(cstr);
+ }
+ varFreeMembers(&srcVal);
+ varFreeMembers(&srcVal2);
+ ret->d.n = retVal;
+ ret->datatype = 'N';
+}
+
+static rsRetVal
+initFunc_re_match_generic(struct cnffunc *const func, const unsigned flags)
+{
+ rsRetVal localRet;
+ char *regex = NULL;
+ regex_t *re;
+ DEFiRet;
+
+ if(func->nParams < 2) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ func->funcdata = NULL;
+ if(func->expr[1]->nodetype != 'S') {
+ parser_errmsg("param 2 of re_match/extract() must be a constant string");
+ FINALIZE;
+ }
+
+ CHKmalloc(re = malloc(sizeof(regex_t)));
+ func->funcdata = re;
+
+ regex = es_str2cstr(((struct cnfstringval*) func->expr[1])->estr, NULL);
+
+ if((localRet = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) {
+ int errcode;
+ if((errcode = regexp.regcomp(re, (char*) regex, REG_EXTENDED | flags)) != 0) {
+ char errbuff[512];
+ regexp.regerror(errcode, re, errbuff, sizeof(errbuff));
+ parser_errmsg("cannot compile regex '%s': %s", regex, errbuff);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else { /* regexp object could not be loaded */
+ parser_errmsg("could not load regex support - regex ignored");
+ ABORT_FINALIZE(localRet);
+ }
+
+finalize_it:
+ free(regex);
+ RETiRet;
+}
+
+static rsRetVal
+initFunc_re_match(struct cnffunc *func)
+{
+ return initFunc_re_match_generic(func, 0);
+}
+
+static rsRetVal
+initFunc_re_match_i(struct cnffunc *func)
+{
+ return initFunc_re_match_generic(func, REG_ICASE);
+}
+
+static rsRetVal
+initFunc_exec_template(struct cnffunc *func)
+{
+ char *tplName = NULL;
+ DEFiRet;
+
+ func->destructable_funcdata = 0;
+
+ if(func->nParams != 1) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ if(func->expr[0]->nodetype != 'S') {
+ parser_errmsg("exec_template(): param 1 must be a constant string");
+ FINALIZE;
+ }
+
+ tplName = es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
+ func->funcdata = tplFind(loadConf, tplName, strlen(tplName));
+ if(func->funcdata == NULL) {
+ parser_errmsg("exec_template(): template '%s' could not be found", tplName);
+ FINALIZE;
+ }
+
+
+finalize_it:
+ free(tplName);
+ RETiRet;
+}
+
+static rsRetVal
+initFunc_prifilt(struct cnffunc *func)
+{
+ struct funcData_prifilt *pData;
+ uchar *cstr;
+ DEFiRet;
+
+ if(func->nParams != 1) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ func->funcdata = NULL;
+ if(func->expr[0]->nodetype != 'S') {
+ parser_errmsg("param 1 of prifilt() must be a constant string");
+ FINALIZE;
+ }
+
+ CHKmalloc(pData = calloc(1, sizeof(struct funcData_prifilt)));
+ func->funcdata = pData;
+ cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL);
+ CHKiRet(DecodePRIFilter(cstr, pData->pmask));
+ free(cstr);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+resolveLookupTable(struct cnffunc *func)
+{
+ uchar *cstr = NULL;
+ char *fn_name = NULL;
+ DEFiRet;
+
+ func->destructable_funcdata = 0;
+
+ if(func->nParams == 0) {/*we assume first arg is lookup-table-name*/
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+ CHKmalloc(fn_name = es_str2cstr(func->fname, NULL));
+
+ func->funcdata = NULL;
+ if(func->expr[0]->nodetype != 'S') {
+ parser_errmsg("table name (param 1) of %s() must be a constant string", fn_name);
+ FINALIZE;
+ }
+
+ CHKmalloc(cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL));
+ if((func->funcdata = lookupFindTable(cstr)) == NULL) {
+ parser_errmsg("lookup table '%s' not found (used in function: %s)", cstr, fn_name);
+ FINALIZE;
+ }
+
+finalize_it:
+ free(cstr);
+ free(fn_name);
+ RETiRet;
+}
+
+struct modListNode {
+ int version;
+ struct scriptFunct *modFcts;
+ struct modListNode *next;
+};
+
+static struct modListNode *modListRoot = NULL;
+static struct modListNode *modListLast = NULL;
+
+static struct scriptFunct functions[] = {
+ {"strlen", 1, 1, doFunct_StrLen, NULL, NULL},
+ {"getenv", 1, 1, doFunct_Getenv, NULL, NULL},
+ {"num2ipv4", 1, 1, doFunct_num2ipv4, NULL, NULL},
+ {"int2hex", 1, 1, doFunct_Int2Hex, NULL, NULL},
+ {"substring", 3, 3, doFunct_Substring, NULL, NULL},
+ {"ltrim", 1, 1, doFunct_LTrim, NULL, NULL},
+ {"rtrim", 1, 1, doFunct_RTrim, NULL, NULL},
+ {"tolower", 1, 1, doFunct_ToLower, NULL, NULL},
+ {"cstr", 1, 1, doFunct_CStr, NULL, NULL},
+ {"cnum", 1, 1, doFunct_CNum, NULL, NULL},
+ {"ip42num", 1, 1, doFunct_Ipv42num, NULL, NULL},
+ {"ipv42num", 1, 1, doFunct_Ipv42num, NULL, NULL},
+ {"re_match", 2, 2, doFunct_ReMatch, initFunc_re_match, regex_destruct},
+ {"re_match_i", 2, 2, doFunct_ReMatch, initFunc_re_match_i, regex_destruct},
+ {"re_extract", 5, 5, doFunc_re_extract, initFunc_re_match, regex_destruct},
+ {"re_extract_i", 5, 5, doFunc_re_extract, initFunc_re_match_i, regex_destruct},
+ {"field", 3, 3, doFunct_Field, NULL, NULL},
+ {"exec_template", 1, 1, doFunc_exec_template, initFunc_exec_template, NULL},
+ {"prifilt", 1, 1, doFunct_Prifilt, initFunc_prifilt, NULL},
+ {"lookup", 2, 2, doFunct_Lookup, resolveLookupTable, NULL},
+ {"dyn_inc", 2, 2, doFunct_DynInc, initFunc_dyn_stats, NULL},
+ {"percentile_observe", 3, 3, doFunc_percentile_obs, initFunc_perctile_obs, NULL},
+ {"replace", 3, 3, doFunct_Replace, NULL, NULL},
+ {"wrap", 2, 3, doFunct_Wrap, NULL, NULL},
+ {"random", 1, 1, doFunct_RandomGen, NULL, NULL},
+ {"format_time", 2, 2, doFunct_FormatTime, NULL, NULL},
+ {"parse_time", 1, 1, doFunct_ParseTime, NULL, NULL},
+ {"is_time", 1, 2, doFunct_IsTime, NULL, NULL},
+ {"parse_json", 2, 2, doFunc_parse_json, NULL, NULL},
+ {"get_property", 2, 2, doFunc_get_property, NULL, NULL},
+ {"script_error", 0, 0, doFunct_ScriptError, NULL, NULL},
+ {"previous_action_suspended", 0, 0, doFunct_PreviousActionSuspended, NULL, NULL},
+ {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array
+};
+
+static rscriptFuncPtr ATTR_NONNULL()
+extractFuncPtr(const struct scriptFunct *const funct, const unsigned int nParams)
+{
+ rscriptFuncPtr retPtr = NULL;
+
+ if(funct->minParams == funct->maxParams) {
+ if(nParams == funct->maxParams) {
+ retPtr = funct->fPtr;
+ } else {
+ parser_errmsg("number of parameters for %s() must be %hu but is %d.",
+ funct->fname, funct->maxParams, nParams);
+ }
+ } else {
+ if(nParams < funct->minParams) {
+ parser_errmsg("number of parameters for %s() must be at least %hu but is %d.",
+ funct->fname, funct->minParams, nParams);
+ } else if(nParams > funct->maxParams) {
+ parser_errmsg("number of parameters for %s() must be at most %hu but is %d.",
+ funct->fname, funct->maxParams, nParams);
+ } else {
+ retPtr = funct->fPtr;
+ }
+ }
+
+ return retPtr;
+}
+
+static struct scriptFunct* ATTR_NONNULL()
+searchFunctArray(const char *const fname, struct scriptFunct *functArray)
+{
+ struct scriptFunct *retPtr = NULL;
+ int i = 0;
+ while(functArray[i].fname != NULL) {
+ if(!strcmp(fname, functArray[i].fname)){
+ retPtr = functArray + i;
+ goto done;
+ }
+ i++;
+ }
+done:
+ return retPtr;
+}
+
+static struct scriptFunct* ATTR_NONNULL()
+searchModList(const char *const fname)
+{
+ struct modListNode *modListCurr = modListRoot;
+ struct scriptFunct *foundFunct;
+
+ do {
+ foundFunct = searchFunctArray(fname, modListCurr->modFcts);
+ if(foundFunct != NULL) {
+ return foundFunct;
+ }
+ modListCurr = modListCurr->next;
+ } while(modListCurr != NULL);
+ return NULL;
+}
+
+static void
+cnffuncDestruct(struct cnffunc *func)
+{
+ unsigned short i;
+
+ for(i = 0 ; i < func->nParams ; ++i) {
+ cnfexprDestruct(func->expr[i]);
+ }
+
+ /* some functions require special destruction */
+ char *cstr = es_str2cstr(func->fname, NULL);
+ struct scriptFunct *foundFunc = searchModList(cstr);
+ free(cstr);
+ if(foundFunc->destruct != NULL) {
+ foundFunc->destruct(func);
+ }
+
+ if(func->destructable_funcdata) {
+ free(func->funcdata);
+ }
+ free(func->fname);
+}
+
+/* Destruct an expression and all sub-expressions contained in it.
+ */
+void
+cnfexprDestruct(struct cnfexpr *__restrict__ const expr)
+{
+
+ if(expr == NULL) {
+ /* this is valid and can happen during optimizer run! */
+ DBGPRINTF("cnfexprDestruct got NULL ptr - valid, so doing nothing\n");
+ return;
+ }
+
+ DBGPRINTF("cnfexprDestruct expr %p, type '%s'\n", expr, tokenToString(expr->nodetype));
+ switch(expr->nodetype) {
+ case CMP_NE:
+ case CMP_EQ:
+ case CMP_LE:
+ case CMP_GE:
+ case CMP_LT:
+ case CMP_GT:
+ case CMP_STARTSWITH:
+ case CMP_STARTSWITHI:
+ case CMP_CONTAINS:
+ case CMP_CONTAINSI:
+ case OR:
+ case AND:
+ case '&':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%': /* binary */
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ break;
+ case NOT:
+ case 'M': /* unary */
+ cnfexprDestruct(expr->r);
+ break;
+ case 'N':
+ break;
+ case 'S':
+ es_deleteStr(((struct cnfstringval*)expr)->estr);
+ break;
+ case 'V':
+ free(((struct cnfvar*)expr)->name);
+ msgPropDescrDestruct(&(((struct cnfvar*)expr)->prop));
+ break;
+ case 'F':
+ cnffuncDestruct((struct cnffunc*)expr);
+ break;
+ case 'A':
+ cnfarrayContentDestruct((struct cnfarray*)expr);
+ break;
+ default:break;
+ }
+ free(expr);
+}
+
+//---- END
+
+
+/* Evaluate an expression as a bool. This is added because expressions are
+ * mostly used inside filters, and so this function is quite common and
+ * important.
+ */
+int
+cnfexprEvalBool(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr, wti_t *const pWti)
+{
+ int convok;
+ struct svar ret;
+ cnfexprEval(expr, &ret, usrptr, pWti);
+ int retVal = var2Number(&ret, &convok);
+ varFreeMembers(&ret);
+ return retVal;
+}
+
+struct json_object*
+cnfexprEvalCollection(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr, wti_t *const pWti)
+{
+ struct svar ret;
+ void *retptr;
+ cnfexprEval(expr, &ret, usrptr, pWti);
+ if(ret.datatype == 'J') {
+ retptr = ret.d.json; /*caller is supposed to free the returned json-object*/
+ } else {
+ retptr = NULL;
+ varFreeMembers(&ret); /* we must free the element */
+ }
+ return retptr;
+}
+
+static void
+doIndent(int indent)
+{
+ int i;
+ for(i = 0 ; i < indent ; ++i)
+ dbgprintf(" ");
+}
+
+static void
+pmaskPrint(uchar *pmask, int indent)
+{
+ int i;
+ doIndent(indent);
+ dbgprintf("pmask: ");
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ if (pmask[i] == TABLE_NOPRI)
+ dbgprintf(" X ");
+ else
+ dbgprintf("%2X ", pmask[i]);
+ dbgprintf("\n");
+}
+
+static void
+cnfarrayPrint(struct cnfarray *ar, int indent)
+{
+ int i;
+ doIndent(indent); dbgprintf("ARRAY:\n");
+ for(i = 0 ; i < ar->nmemb ; ++i) {
+ doIndent(indent+1);
+ cstrPrint("string '", ar->arr[i]);
+ dbgprintf("'\n");
+ }
+}
+
+void
+cnfexprPrint(struct cnfexpr *expr, int indent)
+{
+ struct cnffunc *func;
+ char *fname;
+ int i;
+
+ switch(expr->nodetype) {
+ case CMP_EQ:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("==\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_NE:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("!=\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_LE:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("<=\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_GE:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf(">=\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_LT:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("<\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_GT:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf(">\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_CONTAINS:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("CONTAINS\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_CONTAINSI:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("CONTAINS_I\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_STARTSWITH:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("STARTSWITH\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case CMP_STARTSWITHI:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("STARTSWITH_I\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case OR:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("OR\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case AND:
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("AND\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case NOT:
+ doIndent(indent);
+ dbgprintf("NOT\n");
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ case S_FUNC_EXISTS:
+ doIndent(indent);
+ dbgprintf("exists(%s)\n", ((struct cnffuncexists*)expr)->varname);
+ break;
+ case 'S':
+ doIndent(indent);
+ cstrPrint("string '", ((struct cnfstringval*)expr)->estr);
+ dbgprintf("'\n");
+ break;
+ case 'A':
+ cnfarrayPrint((struct cnfarray*)expr, indent);
+ break;
+ case 'N':
+ doIndent(indent);
+ dbgprintf("%lld\n", ((struct cnfnumval*)expr)->val);
+ break;
+ case 'V':
+ doIndent(indent);
+ dbgprintf("var '%s'\n", ((struct cnfvar*)expr)->name);
+ break;
+ case 'F':
+ doIndent(indent);
+ func = (struct cnffunc*) expr;
+ cstrPrint("function '", func->fname);
+ fname = es_str2cstr(func->fname, NULL);
+ dbgprintf("' (name:%s, params:%hu)\n", fname, func->nParams);
+ free(fname);
+ if(func->fPtr == doFunct_Prifilt) {
+ struct funcData_prifilt *pD;
+ pD = (struct funcData_prifilt*) func->funcdata;
+ pmaskPrint(pD->pmask, indent+1);
+ }
+ for(i = 0 ; i < func->nParams ; ++i) {
+ cnfexprPrint(func->expr[i], indent+1);
+ }
+ break;
+ case '&':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case 'M':
+ if(expr->l != NULL)
+ cnfexprPrint(expr->l, indent+1);
+ doIndent(indent);
+ dbgprintf("%c\n", (char) expr->nodetype);
+ cnfexprPrint(expr->r, indent+1);
+ break;
+ default:
+ dbgprintf("error: unknown nodetype %u['%c']\n",
+ (unsigned) expr->nodetype, (char) expr->nodetype);
+ assert(0); /* abort on debug builds, this must not happen! */
+ break;
+ }
+}
+
+/* print only the given stmt
+ * if "subtree" equals 1, the full statement subtree is printed, else
+ * really only the statement.
+ */
+void
+cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
+{
+ char *cstr;
+ switch(stmt->nodetype) {
+ case S_NOP:
+ doIndent(indent); dbgprintf("NOP\n");
+ break;
+ case S_STOP:
+ doIndent(indent); dbgprintf("STOP\n");
+ break;
+ case S_CALL:
+ cstr = es_str2cstr(stmt->d.s_call.name, NULL);
+ doIndent(indent); dbgprintf("CALL [%s, queue:%d]\n", cstr,
+ stmt->d.s_call.ruleset == NULL ? 0 : 1);
+ free(cstr);
+ break;
+ case S_CALL_INDIRECT:
+ doIndent(indent); dbgprintf("CALL_INDIRECT\n");
+ cnfexprPrint(stmt->d.s_call_ind.expr, indent+1);
+ break;
+ case S_ACT:
+ doIndent(indent); dbgprintf("ACTION %d [%s:%s]\n", stmt->d.act->iActionNbr,
+ modGetName(stmt->d.act->pMod), stmt->printable);
+ break;
+ case S_IF:
+ doIndent(indent); dbgprintf("IF\n");
+ cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ if(subtree) {
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_if.t_then, indent+1);
+ if(stmt->d.s_if.t_else != NULL) {
+ doIndent(indent); dbgprintf("ELSE\n");
+ cnfstmtPrint(stmt->d.s_if.t_else, indent+1);
+ }
+ doIndent(indent); dbgprintf("END IF\n");
+ }
+ break;
+ case S_FOREACH:
+ doIndent(indent); dbgprintf("FOREACH %s IN\n", stmt->d.s_foreach.iter->var);
+ cnfexprPrint(stmt->d.s_foreach.iter->collection, indent+1);
+ if(subtree) {
+ doIndent(indent); dbgprintf("DO\n");
+ cnfstmtPrint(stmt->d.s_foreach.body, indent+1);
+ doIndent(indent); dbgprintf("END FOREACH\n");
+ }
+ break;
+ case S_SET:
+ doIndent(indent); dbgprintf("SET %s =\n",
+ stmt->d.s_set.varname);
+ cnfexprPrint(stmt->d.s_set.expr, indent+1);
+ doIndent(indent); dbgprintf("END SET\n");
+ break;
+ case S_UNSET:
+ doIndent(indent); dbgprintf("UNSET %s\n",
+ stmt->d.s_unset.varname);
+ break;
+ case S_RELOAD_LOOKUP_TABLE:
+ doIndent(indent);
+ dbgprintf("RELOAD_LOOKUP_TABLE table(%s) (stub with '%s' on error)",
+ stmt->d.s_reload_lookup_table.table_name,
+ stmt->d.s_reload_lookup_table.stub_value);
+ break;
+ case S_PRIFILT:
+ doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ pmaskPrint(stmt->d.s_prifilt.pmask, indent);
+ if(subtree) {
+ cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
+ if(stmt->d.s_prifilt.t_else != NULL) {
+ doIndent(indent); dbgprintf("ELSE\n");
+ cnfstmtPrint(stmt->d.s_prifilt.t_else, indent+1);
+ }
+ doIndent(indent); dbgprintf("END PRIFILT\n");
+ }
+ break;
+ case S_PROPFILT:
+ doIndent(indent); dbgprintf("PROPFILT\n");
+ doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
+ propIDToName(stmt->d.s_propfilt.prop.id));
+ if(stmt->d.s_propfilt.prop.id == PROP_CEE ||
+ stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR ||
+ stmt->d.s_propfilt.prop.id == PROP_GLOBAL_VAR) {
+ doIndent(indent);
+ dbgprintf("\tCEE-Prop.: '%s'\n", stmt->d.s_propfilt.prop.name);
+ }
+ doIndent(indent); dbgprintf("\tOperation: ");
+ if(stmt->d.s_propfilt.isNegated)
+ dbgprintf("NOT ");
+ dbgprintf("'%s'\n", getFIOPName(stmt->d.s_propfilt.operation));
+ if(stmt->d.s_propfilt.pCSCompValue != NULL) {
+ doIndent(indent); dbgprintf("\tValue....: '%s'\n",
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue));
+ }
+ if(subtree) {
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1);
+ doIndent(indent); dbgprintf("END PROPFILT\n");
+ }
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+}
+void
+cnfstmtPrint(struct cnfstmt *root, int indent)
+{
+ struct cnfstmt *stmt;
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ cnfstmtPrintOnly(stmt, indent, 1);
+ }
+}
+
+struct cnfnumval*
+cnfnumvalNew(const long long val)
+{
+ struct cnfnumval *numval;
+ if((numval = malloc(sizeof(struct cnfnumval))) != NULL) {
+ numval->nodetype = 'N';
+ numval->val = val;
+ }
+ return numval;
+}
+
+struct cnfstringval*
+cnfstringvalNew(es_str_t *const estr)
+{
+ struct cnfstringval *strval;
+ if((strval = malloc(sizeof(struct cnfstringval))) != NULL) {
+ strval->nodetype = 'S';
+ strval->estr = estr;
+ }
+ return strval;
+}
+
+/* creates array AND adds first element to it */
+struct cnfarray*
+cnfarrayNew(es_str_t *val)
+{
+ struct cnfarray *ar;
+ if((ar = malloc(sizeof(struct cnfarray))) != NULL) {
+ ar->nodetype = 'A';
+ ar->nmemb = 1;
+ if((ar->arr = malloc(sizeof(es_str_t*))) == NULL) {
+ free(ar);
+ ar = NULL;
+ goto done;
+ }
+ ar->arr[0] = val;
+ }
+done: return ar;
+}
+
+struct cnfarray*
+cnfarrayAdd(struct cnfarray *__restrict__ const ar, es_str_t *__restrict__ val)
+{
+ es_str_t **newptr;
+ if((newptr = realloc(ar->arr, (ar->nmemb+1)*sizeof(es_str_t*))) == NULL) {
+ DBGPRINTF("cnfarrayAdd: realloc failed, item ignored, ar->arr=%p\n", ar->arr);
+ goto done;
+ } else {
+ ar->arr = newptr;
+ ar->arr[ar->nmemb] = val;
+ ar->nmemb++;
+ }
+done: return ar;
+}
+
+/* duplicate an array (deep copy) */
+struct cnfarray*
+cnfarrayDup(struct cnfarray *old)
+{
+ int i;
+ struct cnfarray *ar;
+ ar = cnfarrayNew(es_strdup(old->arr[0]));
+ for(i = 1 ; i < old->nmemb ; ++i) {
+ cnfarrayAdd(ar, es_strdup(old->arr[i]));
+ }
+ return ar;
+}
+
+struct cnfvar*
+cnfvarNew(char *name)
+{
+ struct cnfvar *var;
+ if((var = malloc(sizeof(struct cnfvar))) != NULL) {
+ var->nodetype = 'V';
+ var->name = name;
+ msgPropDescrFill(&var->prop, (uchar*)var->name, strlen(var->name));
+ }
+ return var;
+}
+
+struct cnfstmt *
+cnfstmtNew(unsigned s_type)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = malloc(sizeof(struct cnfstmt))) != NULL) {
+ cnfstmt->nodetype = s_type;
+ cnfstmt->printable = NULL;
+ cnfstmt->next = NULL;
+ }
+ return cnfstmt;
+}
+
+/* This function disables a cnfstmt by setting it to NOP. This is
+ * useful when we detect errors late in the parsing processing, where
+ * we need to return a valid cnfstmt. The optimizer later removes the
+ * NOPs, so all is well.
+ * NOTE: this call assumes that no dynamic data structures have been
+ * allocated. If so, these MUST be freed before calling cnfstmtDisable().
+ */
+static void
+cnfstmtDisable(struct cnfstmt *cnfstmt)
+{
+ cnfstmt->nodetype = S_NOP;
+}
+
+void cnfstmtDestructLst(struct cnfstmt *root);
+
+static void cnfIteratorDestruct(struct cnfitr *itr);
+
+/* delete a single stmt */
+static void
+cnfstmtDestruct(struct cnfstmt *stmt)
+{
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ break;
+ case S_CALL:
+ es_deleteStr(stmt->d.s_call.name);
+ break;
+ case S_CALL_INDIRECT:
+ cnfexprDestruct(stmt->d.s_call_ind.expr);
+ break;
+ case S_ACT:
+ actionDestruct(stmt->d.act);
+ break;
+ case S_IF:
+ cnfexprDestruct(stmt->d.s_if.expr);
+ if(stmt->d.s_if.t_then != NULL) {
+ cnfstmtDestructLst(stmt->d.s_if.t_then);
+ }
+ if(stmt->d.s_if.t_else != NULL) {
+ cnfstmtDestructLst(stmt->d.s_if.t_else);
+ }
+ break;
+ case S_FOREACH:
+ cnfIteratorDestruct(stmt->d.s_foreach.iter);
+ cnfstmtDestructLst(stmt->d.s_foreach.body);
+ break;
+ case S_SET:
+ free(stmt->d.s_set.varname);
+ cnfexprDestruct(stmt->d.s_set.expr);
+ break;
+ case S_UNSET:
+ free(stmt->d.s_set.varname);
+ break;
+ case S_PRIFILT:
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_then);
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_else);
+ break;
+ case S_PROPFILT:
+ msgPropDescrDestruct(&stmt->d.s_propfilt.prop);
+ if(stmt->d.s_propfilt.regex_cache != NULL)
+ rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
+ if(stmt->d.s_propfilt.pCSCompValue != NULL)
+ cstrDestruct(&stmt->d.s_propfilt.pCSCompValue);
+ cnfstmtDestructLst(stmt->d.s_propfilt.t_then);
+ break;
+ case S_RELOAD_LOOKUP_TABLE:
+ if (stmt->d.s_reload_lookup_table.table_name != NULL) {
+ free(stmt->d.s_reload_lookup_table.table_name);
+ }
+ if (stmt->d.s_reload_lookup_table.stub_value != NULL) {
+ free(stmt->d.s_reload_lookup_table.stub_value);
+ }
+ break;
+ default:
+ DBGPRINTF("error: unknown stmt type during destruct %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ free(stmt->printable);
+ free(stmt);
+}
+
+/* delete a stmt and all others following it */
+void
+cnfstmtDestructLst(struct cnfstmt *root)
+{
+ struct cnfstmt *stmt, *todel;
+ for(stmt = root ; stmt != NULL ; ) {
+ todel = stmt;
+ stmt = stmt->next;
+ cnfstmtDestruct(todel);
+ }
+}
+
+struct cnfitr *
+cnfNewIterator(char *var, struct cnfexpr *collection)
+{
+ struct cnfitr* itr;
+ if ((itr = malloc(sizeof(struct cnfitr))) != NULL) {
+ itr->var = var;
+ itr->collection = collection;
+ }
+ return itr;
+}
+
+static void
+cnfIteratorDestruct(struct cnfitr *itr)
+{
+ free(itr->var);
+ if(itr->collection != NULL)
+ cnfexprDestruct(itr->collection);
+ free(itr);
+}
+
+struct cnfstmt *
+cnfstmtNewSet(char *var, struct cnfexpr *expr, int force_reset)
+{
+ propid_t propid;
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_SET)) != NULL) {
+ if(propNameToID((uchar *)var, &propid) == RS_RET_OK
+ && ( propid == PROP_CEE
+ || propid == PROP_LOCAL_VAR
+ || propid == PROP_GLOBAL_VAR)
+ ) {
+ cnfstmt->d.s_set.varname = (uchar*) var;
+ cnfstmt->d.s_set.expr = expr;
+ cnfstmt->d.s_set.force_reset = force_reset;
+ } else {
+ parser_errmsg("invalid variable '%s' in set statement.", var);
+ free(var);
+ cnfstmtDisable(cnfstmt);
+ }
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewCall(es_str_t *name)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_CALL)) != NULL) {
+ cnfstmt->d.s_call.name = name;
+ cnfstmt->d.s_call.ruleset = NULL;
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewReloadLookupTable(struct cnffparamlst *fparams)
+{
+ int nParams;
+ struct cnffparamlst *param, *nxt;
+ struct cnfstmt* cnfstmt;
+ uint8_t failed = 0;
+ if((cnfstmt = cnfstmtNew(S_RELOAD_LOOKUP_TABLE)) != NULL) {
+ nParams = 0;
+ for(param = fparams ; param != NULL ; param = param->next) {
+ ++nParams;
+ }
+ cnfstmt->d.s_reload_lookup_table.table_name = cnfstmt->d.s_reload_lookup_table.stub_value = NULL;
+ switch(nParams) {
+ case 2:
+ param = fparams->next;
+ if (param->expr->nodetype != 'S') {
+ parser_errmsg("statement ignored: reload_lookup_table(table_name, "
+ "optional:stub_value_in_case_reload_fails) "
+ "expects a litteral string for second argument\n");
+ failed = 1;
+ }
+ if ((cnfstmt->d.s_reload_lookup_table.stub_value =
+ (uchar*) es_str2cstr(((struct cnfstringval*)param->expr)->estr, NULL)) == NULL) {
+ parser_errmsg("statement ignored: reload_lookup_table statement "
+ "failed to allocate memory for lookup-table stub-value\n");
+ failed = 1;
+ }
+ CASE_FALLTHROUGH
+ case 1:
+ param = fparams;
+ if (param->expr->nodetype != 'S') {
+ parser_errmsg("statement ignored: reload_lookup_table(table_name, "
+ "optional:stub_value_in_case_reload_fails) "
+ "expects a litteral string for first argument\n");
+ failed = 1;
+ }
+ if ((cnfstmt->d.s_reload_lookup_table.table_name =
+ (uchar*) es_str2cstr(((struct cnfstringval*)param->expr)->estr, NULL)) == NULL) {
+ parser_errmsg("statement ignored: reload_lookup_table statement "
+ "failed to allocate memory for lookup-table name\n");
+ failed = 1;
+ }
+ break;
+ default:
+ parser_errmsg("statement ignored: reload_lookup_table(table_name, optional:"
+ "stub_value_in_case_reload_fails) "
+ "expected 1 or 2 arguments, but found '%d'\n", nParams);
+ failed = 1;
+ }
+ }
+ param = fparams;
+ while(param != NULL) {
+ nxt = param->next;
+ if (param->expr != NULL) cnfexprDestruct(param->expr);
+ free(param);
+ param = nxt;
+ }
+ if (failed) {
+ cnfstmt->nodetype = S_NOP;
+ if (cnfstmt->d.s_reload_lookup_table.table_name != NULL) {
+ free(cnfstmt->d.s_reload_lookup_table.table_name);
+ }
+ if (cnfstmt->d.s_reload_lookup_table.stub_value != NULL) {
+ free(cnfstmt->d.s_reload_lookup_table.stub_value);
+ }
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewUnset(char *var)
+{
+ propid_t propid;
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_UNSET)) != NULL) {
+ if(propNameToID((uchar *)var, &propid) == RS_RET_OK
+ && ( propid == PROP_CEE
+ || propid == PROP_LOCAL_VAR
+ || propid == PROP_GLOBAL_VAR)
+ ) {
+ cnfstmt->d.s_unset.varname = (uchar*) var;
+ } else {
+ parser_errmsg("invalid variable '%s' in unset statement.", var);
+ free(var);
+ cnfstmtDisable(cnfstmt);
+ }
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewContinue(void)
+{
+ return cnfstmtNew(S_NOP);
+}
+
+struct cnfstmt *
+cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)prifilt;
+ cnfstmt->d.s_prifilt.t_then = t_then;
+ cnfstmt->d.s_prifilt.t_else = NULL;
+ DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask);
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)propfilt;
+ cnfstmt->d.s_propfilt.t_then = t_then;
+ cnfstmt->d.s_propfilt.regex_cache = NULL;
+ cnfstmt->d.s_propfilt.pCSCompValue = NULL;
+ if(DecodePropFilter((uchar*)propfilt, cnfstmt) != RS_RET_OK) {
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ cnfstmtDestructLst(t_then); /* we do no longer need this */
+ }
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewAct(struct nvlst *lst)
+{
+ struct cnfstmt* cnfstmt;
+ char namebuf[256];
+ rsRetVal localRet;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL) {
+ goto done;
+ }
+ if (nvlstChkDisabled(lst)) {
+ dbgprintf("action disabled by configuration\n");
+ cnfstmt->nodetype = S_NOP;
+ }
+ localRet = actionNewInst(lst, &cnfstmt->d.act);
+ if(localRet == RS_RET_OK_WARN) {
+ parser_errmsg("warnings occurred in file '%s' around line %d",
+ cnfcurrfn, yylineno);
+ } else if(localRet != RS_RET_OK) {
+ parser_errmsg("errors occurred in file '%s' around line %d",
+ cnfcurrfn, yylineno);
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ snprintf(namebuf, sizeof(namebuf)-1, "action(type=\"%s\" ...)",
+ modGetName(cnfstmt->d.act->pMod));
+ namebuf[255] = '\0'; /* be on safe side */
+ cnfstmt->printable = (uchar*)strdup(namebuf);
+ nvlstChkUnused(lst);
+ nvlstDestruct(lst);
+done: return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewLegaAct(char *actline)
+{
+ struct cnfstmt* cnfstmt;
+ rsRetVal localRet;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL)
+ goto done;
+ cnfstmt->printable = (uchar*)strdup((char*)actline);
+ localRet = cflineDoAction(loadConf, (uchar**)&actline, &cnfstmt->d.act);
+ if(localRet != RS_RET_OK) {
+ parser_errmsg("%s occurred in file '%s' around line %d",
+ (localRet == RS_RET_OK_WARN) ? "warnings" : "errors",
+ cnfcurrfn, yylineno);
+ if(localRet != RS_RET_OK_WARN) {
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ }
+done: return cnfstmt;
+}
+
+
+/* returns 1 if the two expressions are constants, 0 otherwise
+ * if both are constants, the expression subtrees are destructed
+ * (this is an aid for constant folding optimizing)
+ */
+static int
+getConstNumber(struct cnfexpr *expr, long long *l, long long *r)
+{
+ int ret = 0;
+ cnfexprOptimize(expr->l);
+ cnfexprOptimize(expr->r);
+ if(expr->l->nodetype == 'N') {
+ if(expr->r->nodetype == 'N') {
+ ret = 1;
+ *l = ((struct cnfnumval*)expr->l)->val;
+ *r = ((struct cnfnumval*)expr->r)->val;
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ } else if(expr->r->nodetype == 'S') {
+ ret = 1;
+ *l = ((struct cnfnumval*)expr->l)->val;
+ *r = es_str2num(((struct cnfstringval*)expr->r)->estr, NULL);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ }
+ } else if(expr->l->nodetype == 'S') {
+ if(expr->r->nodetype == 'N') {
+ ret = 1;
+ *l = es_str2num(((struct cnfstringval*)expr->l)->estr, NULL);
+ *r = ((struct cnfnumval*)expr->r)->val;
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ } else if(expr->r->nodetype == 'S') {
+ ret = 1;
+ *l = es_str2num(((struct cnfstringval*)expr->l)->estr, NULL);
+ *r = es_str2num(((struct cnfstringval*)expr->r)->estr, NULL);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ }
+ }
+ return ret;
+}
+
+
+/* constant folding for string concatenation */
+static void
+constFoldConcat(struct cnfexpr *expr)
+{
+ es_str_t *estr;
+ cnfexprOptimize(expr->l);
+ cnfexprOptimize(expr->r);
+ if(expr->l->nodetype == 'S') {
+ if(expr->r->nodetype == 'S') {
+ estr = ((struct cnfstringval*)expr->l)->estr;
+ ((struct cnfstringval*)expr->l)->estr = NULL;
+ es_addStr(&estr, ((struct cnfstringval*)expr->r)->estr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ } else if(expr->r->nodetype == 'N') {
+ es_str_t *numstr;
+ estr = ((struct cnfstringval*)expr->l)->estr;
+ ((struct cnfstringval*)expr->l)->estr = NULL;
+ numstr = es_newStrFromNumber(((struct cnfnumval*)expr->r)->val);
+ es_addStr(&estr, numstr);
+ es_deleteStr(numstr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ }
+ } else if(expr->l->nodetype == 'N') {
+ if(expr->r->nodetype == 'S') {
+ estr = es_newStrFromNumber(((struct cnfnumval*)expr->l)->val);
+ es_addStr(&estr, ((struct cnfstringval*)expr->r)->estr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ } else if(expr->r->nodetype == 'N') {
+ es_str_t *numstr;
+ estr = es_newStrFromNumber(((struct cnfnumval*)expr->l)->val);
+ numstr = es_newStrFromNumber(((struct cnfnumval*)expr->r)->val);
+ es_addStr(&estr, numstr);
+ es_deleteStr(numstr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ }
+ }
+}
+
+
+/* optimize comparisons with syslog severity/facility. This is a special
+ * handler as the numerical values also support GT, LT, etc ops.
+ */
+static struct cnfexpr*
+cnfexprOptimize_CMP_severity_facility(struct cnfexpr *expr)
+{
+ struct cnffunc *func;
+
+ if(expr->l->nodetype != 'V')
+ FINALIZE;
+
+ if(!strcmp("syslogseverity", ((struct cnfvar*)expr->l)->name)) {
+ if(expr->r->nodetype == 'N') {
+ int sev = (int) ((struct cnfnumval*)expr->r)->val;
+ if(sev >= 0 && sev <= 7) {
+ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n");
+ func = cnffuncNew_prifilt(0); /* fac is irrelevant, set below... */
+ prifiltSetSeverity(func->funcdata, sev, expr->nodetype);
+ cnfexprDestruct(expr);
+ expr = (struct cnfexpr*) func;
+ } else {
+ parser_errmsg("invalid syslogseverity %d, expression will always "
+ "evaluate to FALSE", sev);
+ }
+ }
+ } else if(!strcmp("syslogfacility", ((struct cnfvar*)expr->l)->name)) {
+ if(expr->r->nodetype == 'N') {
+ int fac = (int) ((struct cnfnumval*)expr->r)->val;
+ if(fac >= 0 && fac <= 24) {
+ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n");
+ func = cnffuncNew_prifilt(0); /* fac is irrelevant, set below... */
+ prifiltSetFacility(func->funcdata, fac, expr->nodetype);
+ cnfexprDestruct(expr);
+ expr = (struct cnfexpr*) func;
+ } else {
+ parser_errmsg("invalid syslogfacility %d, expression will always "
+ "evaluate to FALSE", fac);
+ }
+ }
+ }
+finalize_it:
+ return expr;
+}
+
+/* optimize a comparison with a variable as left-hand operand
+ * NOTE: Currently support CMP_EQ, CMP_NE only and code NEEDS
+ * TO BE CHANGED fgr other comparisons!
+ */
+static struct cnfexpr*
+cnfexprOptimize_CMP_var(struct cnfexpr *expr)
+{
+ struct cnffunc *func;
+
+ if(!strcmp("syslogfacility-text", ((struct cnfvar*)expr->l)->name)) {
+ if(expr->r->nodetype == 'S') {
+ char *cstr = es_str2cstr(((struct cnfstringval*)expr->r)->estr, NULL);
+ int fac = decodeSyslogName((uchar*)cstr, syslogFacNames);
+ if(fac == -1) {
+ parser_errmsg("invalid facility '%s', expression will always "
+ "evaluate to FALSE", cstr);
+ } else {
+ /* we can actually optimize! */
+ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n");
+ func = cnffuncNew_prifilt(fac);
+ if(expr->nodetype == CMP_NE)
+ prifiltInvert(func->funcdata);
+ cnfexprDestruct(expr);
+ expr = (struct cnfexpr*) func;
+ }
+ free(cstr);
+ }
+ } else if(!strcmp("syslogseverity-text", ((struct cnfvar*)expr->l)->name)) {
+ if(expr->r->nodetype == 'S') {
+ char *cstr = es_str2cstr(((struct cnfstringval*)expr->r)->estr, NULL);
+ int sev = decodeSyslogName((uchar*)cstr, syslogPriNames);
+ if(sev == -1) {
+ parser_errmsg("invalid syslogseverity '%s', expression will always "
+ "evaluate to FALSE", cstr);
+ } else {
+ /* we can acutally optimize! */
+ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n");
+ func = cnffuncNew_prifilt(0);
+ prifiltSetSeverity(func->funcdata, sev, expr->nodetype);
+ cnfexprDestruct(expr);
+ expr = (struct cnfexpr*) func;
+ }
+ free(cstr);
+ }
+ } else {
+ expr = cnfexprOptimize_CMP_severity_facility(expr);
+ }
+ return expr;
+}
+
+static struct cnfexpr*
+cnfexprOptimize_NOT(struct cnfexpr *expr)
+{
+ struct cnffunc *func;
+
+ if(expr->r->nodetype == 'F') {
+ func = (struct cnffunc *)expr->r;
+ if(func->fPtr == doFunct_Prifilt) {
+ DBGPRINTF("optimize NOT prifilt() to inverted prifilt()\n");
+ expr->r = NULL;
+ cnfexprDestruct(expr);
+ prifiltInvert(func->funcdata);
+ expr = (struct cnfexpr*) func;
+ }
+ }
+ return expr;
+}
+
+static struct cnfexpr*
+cnfexprOptimize_AND_OR(struct cnfexpr *expr)
+{
+ struct cnffunc *funcl, *funcr;
+
+ if(expr->l->nodetype == 'F') {
+ if(expr->r->nodetype == 'F') {
+ funcl = (struct cnffunc *)expr->l;
+ funcr = (struct cnffunc *)expr->r;
+ if(funcl->fPtr == doFunct_Prifilt && funcr->fPtr == doFunct_Prifilt) {
+ DBGPRINTF("optimize combine AND/OR prifilt()\n");
+ expr->l = NULL;
+ prifiltCombine(funcl->funcdata, funcr->funcdata, expr->nodetype);
+ cnfexprDestruct(expr);
+ expr = (struct cnfexpr*) funcl;
+ }
+ }
+ }
+ return expr;
+}
+
+
+/* optimize array for EQ/NEQ comparisons. We sort the array in
+ * this case so that we can apply binary search later on.
+ */
+static inline void
+cnfexprOptimize_CMPEQ_arr(struct cnfarray *arr)
+{
+ DBGPRINTF("optimizer: sorting array of %d members for CMP_EQ/NEQ comparison\n", arr->nmemb);
+ qsort(arr->arr, arr->nmemb, sizeof(es_str_t*), qs_arrcmp);
+}
+
+
+/* (recursively) optimize an expression */
+struct cnfexpr*
+cnfexprOptimize(struct cnfexpr *expr)
+{
+ long long ln, rn;
+ struct cnfexpr *exprswap;
+
+ DBGPRINTF("optimize expr %p, type '%s'\n", expr, tokenToString(expr->nodetype));
+ switch(expr->nodetype) {
+ case '&':
+ constFoldConcat(expr);
+ break;
+ case '+':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln + rn;
+ }
+ break;
+ case '-':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln - rn;
+ }
+ break;
+ case '*':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln * rn;
+ }
+ break;
+ case '/':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ if(rn == 0) {
+ /* division by zero */
+ ((struct cnfnumval*)expr)->val = 0;
+ } else {
+ ((struct cnfnumval*)expr)->val = ln / rn;
+ }
+ }
+ break;
+ case '%':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ if(rn == 0) {
+ /* division by zero */
+ ((struct cnfnumval*)expr)->val = 0;
+ } else {
+ ((struct cnfnumval*)expr)->val = ln % rn;
+ }
+ }
+ break;
+ case CMP_NE:
+ case CMP_EQ:
+ expr->l = cnfexprOptimize(expr->l);
+ expr->r = cnfexprOptimize(expr->r);
+ if(expr->l->nodetype == 'A') {
+ if(expr->r->nodetype == 'A') {
+ parser_errmsg("warning: '==' or '<>' "
+ "comparison of two constant string "
+ "arrays makes no sense");
+ } else { /* swap for simpler execution step */
+ exprswap = expr->l;
+ expr->l = expr->r;
+ expr->r = exprswap;
+ }
+ }
+ if(expr->r->nodetype == 'A') {
+ cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r);
+ }
+ /* This should be evaluated last because it may change expr
+ * to a function.
+ */
+ if(expr->l->nodetype == 'V') {
+ expr = cnfexprOptimize_CMP_var(expr);
+ }
+ break;
+ case CMP_LE:
+ case CMP_GE:
+ case CMP_LT:
+ case CMP_GT:
+ expr->l = cnfexprOptimize(expr->l);
+ expr->r = cnfexprOptimize(expr->r);
+ expr = cnfexprOptimize_CMP_severity_facility(expr);
+ break;
+ case CMP_CONTAINS:
+ case CMP_CONTAINSI:
+ case CMP_STARTSWITH:
+ case CMP_STARTSWITHI:
+ expr->l = cnfexprOptimize(expr->l);
+ expr->r = cnfexprOptimize(expr->r);
+ break;
+ case AND:
+ case OR:
+ expr->l = cnfexprOptimize(expr->l);
+ expr->r = cnfexprOptimize(expr->r);
+ expr = cnfexprOptimize_AND_OR(expr);
+ break;
+ case NOT:
+ expr->r = cnfexprOptimize(expr->r);
+ expr = cnfexprOptimize_NOT(expr);
+ break;
+ default:/* nodetypes we cannot optimize */
+ break;
+ }
+ return expr;
+}
+
+/* removes NOPs from a statement list and returns the
+ * first non-NOP entry.
+ */
+static struct cnfstmt *
+removeNOPs(struct cnfstmt *const root)
+{
+ struct cnfstmt *stmt, *toDel, *prevstmt = NULL;
+ struct cnfstmt *newRoot = NULL;
+
+ if(root == NULL) goto done;
+ stmt = root;
+ while(stmt != NULL) {
+ if(stmt->nodetype == S_NOP) {
+ if(prevstmt != NULL)
+ /* end chain, is rebuild if more non-NOPs follow */
+ prevstmt->next = NULL;
+ toDel = stmt;
+ stmt = stmt->next;
+ cnfstmtDestruct(toDel);
+ } else {
+ if(newRoot == NULL)
+ newRoot = stmt;
+ if(prevstmt != NULL)
+ prevstmt->next = stmt;
+ prevstmt = stmt;
+ stmt = stmt->next;
+ }
+ }
+done: return newRoot;
+}
+
+static void
+cnfstmtOptimizeForeach(struct cnfstmt *stmt)
+{
+ stmt->d.s_foreach.iter->collection = cnfexprOptimize(stmt->d.s_foreach.iter->collection);
+ stmt->d.s_foreach.body = cnfstmtOptimize(stmt->d.s_foreach.body);
+}
+
+
+static void
+cnfstmtOptimizeIf(struct cnfstmt *stmt)
+{
+ struct cnfstmt *t_then, *t_else;
+ struct cnfexpr *expr;
+ struct cnffunc *func;
+ struct funcData_prifilt *prifilt;
+
+ assert(stmt->nodetype == S_IF);
+ expr = stmt->d.s_if.expr = cnfexprOptimize(stmt->d.s_if.expr);
+ stmt->d.s_if.t_then = cnfstmtOptimize(stmt->d.s_if.t_then);
+ stmt->d.s_if.t_else = cnfstmtOptimize(stmt->d.s_if.t_else);
+
+ if(stmt->d.s_if.t_then == NULL && stmt->d.s_if.t_else == NULL) {
+ /* pointless if, probably constructed by config mgmt system */
+ DBGPRINTF("optimizer: if with both empty then and else - remove\n");
+ cnfexprDestruct(stmt->d.s_if.expr);
+ /* set to NOP, this will be removed in later stage */
+ stmt->nodetype = S_NOP;
+ goto done;
+ }
+
+ assert(stmt->nodetype == S_IF);
+ if(stmt->d.s_if.expr->nodetype == 'F') {
+ func = (struct cnffunc*)expr;
+ if(func->fPtr == doFunct_Prifilt) {
+ DBGPRINTF("optimizer: change IF to PRIFILT\n");
+ t_then = stmt->d.s_if.t_then;
+ t_else = stmt->d.s_if.t_else;
+ stmt->nodetype = S_PRIFILT;
+ prifilt = (struct funcData_prifilt*) func->funcdata;
+ memcpy(stmt->d.s_prifilt.pmask, prifilt->pmask,
+ sizeof(prifilt->pmask));
+ stmt->d.s_prifilt.t_then = t_then;
+ stmt->d.s_prifilt.t_else = t_else;
+ if(func->nParams == 0)
+ stmt->printable = (uchar*)strdup("[Optimizer Result]");
+ else
+ stmt->printable = (uchar*)
+ es_str2cstr(((struct cnfstringval*)func->expr[0])->estr, NULL);
+ cnfexprDestruct(expr);
+ cnfstmtOptimizePRIFilt(stmt);
+ }
+ }
+done: return;
+}
+
+static void
+cnfstmtOptimizeAct(struct cnfstmt *stmt)
+{
+ action_t *pAct;
+
+ pAct = stmt->d.act;
+ if(!strcmp((char*)modGetName(pAct->pMod), "builtin:omdiscard")) {
+ DBGPRINTF("optimizer: replacing omdiscard by STOP\n");
+ actionDestruct(stmt->d.act);
+ stmt->nodetype = S_STOP;
+ }
+}
+
+static void
+cnfstmtOptimizePRIFilt(struct cnfstmt *stmt)
+{
+ int i;
+ int isAlways = 1;
+ struct cnfstmt *subroot, *last;
+
+ stmt->d.s_prifilt.t_then = cnfstmtOptimize(stmt->d.s_prifilt.t_then);
+
+ for(i = 0; i <= LOG_NFACILITIES; i++)
+ if(stmt->d.s_prifilt.pmask[i] != 0xff) {
+ isAlways = 0;
+ break;
+ }
+ if(!isAlways)
+ goto done;
+
+ DBGPRINTF("optimizer: removing always-true PRIFILT %p\n", stmt);
+ if(stmt->d.s_prifilt.t_else != NULL) {
+ parser_errmsg("error: always-true PRI filter has else part!\n");
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_else);
+ }
+ free(stmt->printable);
+ stmt->printable = NULL;
+ subroot = stmt->d.s_prifilt.t_then;
+ if(subroot == NULL) {
+ /* very strange, we set it to NOP, best we can do
+ * This case is NOT expected in practice
+ */
+ stmt->nodetype = S_NOP;
+ goto done;
+ }
+ for(last = subroot ; last->next != NULL ; last = last->next)
+ /* find last node in subtree */;
+ last->next = stmt->next;
+ memcpy(stmt, subroot, sizeof(struct cnfstmt));
+ free(subroot);
+
+done: return;
+}
+
+static void
+cnfstmtOptimizeReloadLookupTable(struct cnfstmt *stmt) {
+ if((stmt->d.s_reload_lookup_table.table = lookupFindTable(stmt->d.s_reload_lookup_table.table_name))
+ == NULL) {
+ parser_errmsg("lookup table '%s' not found\n", stmt->d.s_reload_lookup_table.table_name);
+ }
+}
+
+/* we abuse "optimize" a bit. Actually, we obtain a ruleset pointer, as
+ * all rulesets are only known later in the process (now!).
+ */
+static void
+cnfstmtOptimizeCall(struct cnfstmt *stmt)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ uchar *rsName;
+
+ rsName = (uchar*) es_str2cstr(stmt->d.s_call.name, NULL);
+ localRet = rulesetGetRuleset(loadConf, &pRuleset, rsName);
+ if(localRet != RS_RET_OK) {
+ /* in that case, we accept that a NOP will "survive" */
+ parser_errmsg("ruleset '%s' cannot be found\n", rsName);
+ es_deleteStr(stmt->d.s_call.name);
+ stmt->nodetype = S_NOP;
+ goto done;
+ }
+ DBGPRINTF("CALL obtained ruleset ptr %p for ruleset '%s' [hasQueue:%d]\n",
+ pRuleset, rsName, rulesetHasQueue(pRuleset));
+ if(rulesetHasQueue(pRuleset)) {
+ stmt->d.s_call.ruleset = pRuleset;
+ } else {
+ stmt->d.s_call.ruleset = NULL;
+ stmt->d.s_call.stmt = pRuleset->root;
+ }
+done:
+ free(rsName);
+ return;
+}
+/* (recursively) optimize a statement */
+struct cnfstmt *
+cnfstmtOptimize(struct cnfstmt *root)
+{
+ struct cnfstmt *stmt;
+ if(root == NULL) goto done;
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ DBGPRINTF("optimizing cnfstmt type %d\n", (int) stmt->nodetype);
+ switch(stmt->nodetype) {
+ case S_IF:
+ cnfstmtOptimizeIf(stmt);
+ break;
+ case S_FOREACH:
+ cnfstmtOptimizeForeach(stmt);
+ break;
+ case S_PRIFILT:
+ cnfstmtOptimizePRIFilt(stmt);
+ break;
+ case S_PROPFILT:
+ stmt->d.s_propfilt.t_then = cnfstmtOptimize(stmt->d.s_propfilt.t_then);
+ break;
+ case S_SET:
+ stmt->d.s_set.expr = cnfexprOptimize(stmt->d.s_set.expr);
+ break;
+ case S_ACT:
+ cnfstmtOptimizeAct(stmt);
+ break;
+ case S_CALL:
+ cnfstmtOptimizeCall(stmt);
+ break;
+ case S_CALL_INDIRECT:
+ stmt->d.s_call_ind.expr = cnfexprOptimize(stmt->d.s_call_ind.expr);
+ break;
+ case S_STOP:
+ if(stmt->next != NULL)
+ parser_warnmsg("STOP is followed by unreachable statements!\n");
+ break;
+ case S_UNSET: /* nothing to do */
+ break;
+ case S_RELOAD_LOOKUP_TABLE:
+ cnfstmtOptimizeReloadLookupTable(stmt);
+ break;
+ case S_NOP:
+ // TODO: fix optimizer, re-enable. see:
+ // https://github.com/rsyslog/rsyslog/issues/2524
+ //LogError(0, RS_RET_INTERNAL_ERROR,
+ // "optimizer error: we see a NOP, how come?");
+ dbgprintf("optimizer error: we see a NOP, how come?");
+ break;
+ default:
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "internal error: unknown stmt type %u during optimizer run\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+ root = removeNOPs(root);
+done: return root;
+}
+
+
+struct cnffparamlst *
+cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next)
+{
+ struct cnffparamlst* lst;
+ if((lst = malloc(sizeof(struct cnffparamlst))) != NULL) {
+ lst->nodetype = 'P';
+ lst->expr = expr;
+ lst->next = next;
+ }
+ return lst;
+}
+
+/* Obtain function id from name AND number of params. Issues the
+ * relevant error messages if errors are detected.
+ */
+static rscriptFuncPtr
+funcName2Ptr(char *const fname, const unsigned short nParams)
+{
+ struct scriptFunct *foundFunc = searchModList(fname);
+ if(foundFunc == NULL) {
+ parser_errmsg("function '%s' not found", fname);
+ return NULL;
+ } else {
+ return extractFuncPtr(foundFunc, nParams);
+ }
+}
+
+rsRetVal
+addMod2List(const int __attribute__((unused)) version, struct scriptFunct *functArray)
+/*version currently not used, might be needed later for versin check*/
+{
+ DEFiRet;
+ int i;
+ struct modListNode *newNode;
+ CHKmalloc(newNode = (struct modListNode*) malloc(sizeof(struct modListNode)));
+ newNode->version = 1;
+ newNode->next = NULL;
+
+ i = 0;
+ while(functArray[i].fname != NULL) {
+ if(searchModList(functArray[i].fname) != NULL) {
+ parser_errmsg("function %s defined multiple times, second time will be ignored",
+ functArray[i].fname);
+ }
+ i++;
+ }
+ newNode->modFcts = functArray;
+
+ modListLast->next = newNode;
+ modListLast = newNode;
+finalize_it:
+ RETiRet;
+}
+
+
+struct cnffunc *
+cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
+{
+ struct cnffunc* func;
+ struct cnffparamlst *param, *toDel;
+ unsigned short i;
+ unsigned short nParams;
+ char *cstr;
+
+ /* we first need to find out how many params we have */
+ nParams = 0;
+ for(param = paramlst ; param != NULL ; param = param->next)
+ ++nParams;
+ if((func = malloc(sizeof(struct cnffunc) + (nParams * sizeof(struct cnfexp*))))
+ != NULL) {
+ func->nodetype = 'F';
+ func->fname = fname;
+ func->nParams = nParams;
+ func->funcdata = NULL;
+ func->destructable_funcdata = 1;
+ cstr = es_str2cstr(fname, NULL);
+ func->fPtr = funcName2Ptr(cstr, nParams);
+
+ /* parse error if we have an unknown function */
+ if (func->fPtr == NULL) {
+ parser_errmsg("Invalid function %s", cstr);
+ }
+
+ /* shuffle params over to array (access speed!) */
+ param = paramlst;
+ for(i = 0 ; i < nParams ; ++i) {
+ func->expr[i] = param->expr;
+ toDel = param;
+ param = param->next;
+ free(toDel);
+ }
+ /* some functions require special initialization */
+ struct scriptFunct *foundFunc = searchModList(cstr);
+ if(foundFunc->initFunc != NULL) {
+ foundFunc->initFunc(func);
+ }
+ free(cstr);
+ }
+ return func;
+}
+
+
+/* A special function to create a prifilt() expression during optimization
+ * phase.
+ */
+struct cnffunc *
+cnffuncNew_prifilt(int fac)
+{
+ struct cnffunc* func;
+
+ fac >>= 3;
+ if (fac >= LOG_NFACILITIES + 1 || fac < 0)
+ return NULL;
+
+ if((func = malloc(sizeof(struct cnffunc))) != NULL) {
+ if ((func->funcdata = calloc(1, sizeof(struct funcData_prifilt))) == NULL) {
+ free(func);
+ return NULL;
+ }
+ func->nodetype = 'F';
+ func->fname = es_newStrFromCStr("prifilt", sizeof("prifilt")-1);
+ func->nParams = 0;
+ func->fPtr = doFunct_Prifilt;
+ func->destructable_funcdata = 1;
+ ((struct funcData_prifilt *)func->funcdata)->pmask[fac] = TABLE_ALLPRI;
+ }
+ return func;
+}
+
+
+/* The check-if-variable exists "exists($!var)" is a special beast and as such
+ * also needs special code (we must not evaluate the var but need its name).
+ */
+struct cnffuncexists * ATTR_NONNULL()
+cnffuncexistsNew(const char *const varname)
+{
+ struct cnffuncexists* f_exists;
+
+ if((f_exists = malloc(sizeof(struct cnffuncexists))) != NULL) {
+ f_exists->nodetype = S_FUNC_EXISTS;
+ f_exists->varname = varname;
+ msgPropDescrFill(&f_exists->prop, (uchar*)varname, strlen(varname));
+ }
+ return f_exists;
+}
+
+
+/* returns 0 if everything is OK and config parsing shall continue,
+ * and 1 if things are so wrong that config parsing shall be aborted.
+ */
+int ATTR_NONNULL()
+cnfDoInclude(const char *const name, const int optional)
+{
+ char *cfgFile;
+ const char *finalName;
+ int i;
+ int result;
+ glob_t cfgFiles;
+ int ret = 0;
+ struct stat fileInfo;
+ char errStr[1024];
+ char nameBuf[MAXFNAME+1];
+ char cwdBuf[MAXFNAME+1];
+
+ DBGPRINTF("cnfDoInclude: file: '%s', optional: %d\n", name, optional);
+ finalName = name;
+ if(stat(name, &fileInfo) == 0) {
+ /* stat usually fails if we have a wildcard - so this does NOT indicate error! */
+ if(S_ISDIR(fileInfo.st_mode)) {
+ /* if we have a directory, we need to add "*" to get its files */
+ snprintf(nameBuf, sizeof(nameBuf), "%s*", name);
+ finalName = nameBuf;
+ }
+ }
+
+ /* Use GLOB_MARK to append a trailing slash for directories. */
+ /* Use GLOB_NOMAGIC to detect wildcards that match nothing. */
+ #ifdef HAVE_GLOB_NOMAGIC
+ /* Silently ignore wildcards that match nothing */
+ result = glob(finalName, GLOB_MARK | GLOB_NOMAGIC, NULL, &cfgFiles);
+ if(result == GLOB_NOMATCH) {
+ #else
+ result = glob(finalName, GLOB_MARK, NULL, &cfgFiles);
+ if(result == GLOB_NOMATCH && containsGlobWildcard((char*)finalName)) {
+ #endif /* HAVE_GLOB_NOMAGIC */
+ goto done;
+ }
+
+ if(result == GLOB_NOSPACE || result == GLOB_ABORTED) {
+ if(optional == 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ if(getcwd(cwdBuf, sizeof(cwdBuf)) == NULL)
+ strcpy(cwdBuf, "??getcwd() failed??");
+ parser_errmsg("error accessing config file or directory '%s' "
+ "[cwd:%s]: %s", finalName, cwdBuf, errStr);
+ ret = 1;
+ }
+ goto done;
+ }
+
+ /* note: bison "stacks" the files, so we need to submit them
+ * in reverse order to the *stack* in order to get the proper
+ * parsing order. Also see
+ * http://bugzilla.adiscon.com/show_bug.cgi?id=411
+ */
+ for(i = cfgFiles.gl_pathc - 1; i >= 0 ; i--) {
+ cfgFile = cfgFiles.gl_pathv[i];
+ if(stat(cfgFile, &fileInfo) != 0) {
+ if(optional == 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ if(getcwd(cwdBuf, sizeof(cwdBuf)) == NULL)
+ strcpy(cwdBuf, "??getcwd() failed??");
+ parser_errmsg("error accessing config file or directory '%s' "
+ "[cwd: %s]: %s", cfgFile, cwdBuf, errStr);
+ ret = 1;
+ }
+ goto done;
+ }
+
+ if(S_ISREG(fileInfo.st_mode)) { /* config file */
+ DBGPRINTF("requested to include config file '%s'\n", cfgFile);
+ cnfSetLexFile(cfgFile);
+ } else if(S_ISDIR(fileInfo.st_mode)) { /* config directory */
+ DBGPRINTF("requested to include directory '%s'\n", cfgFile);
+ cnfDoInclude(cfgFile, optional);
+ } else {
+ DBGPRINTF("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
+ }
+ }
+
+done:
+ globfree(&cfgFiles);
+ return ret;
+}
+
+
+/* Process include() objects */
+void
+includeProcessCnf(struct nvlst *const lst)
+{
+ struct cnfparamvals *pvals = NULL;
+ const char *inc_file = NULL;
+ const char *text = NULL;
+ int optional = 0;
+ int abort_if_missing = 0;
+ int i;
+
+ if(lst == NULL) {
+ parser_errmsg("include() must have either 'file' or 'text' "
+ "parameter - ignored");
+ goto done;
+ }
+
+ if (nvlstChkDisabled(lst)) {
+ DBGPRINTF("include statement disabled\n");
+ goto done;
+ }
+
+ pvals = nvlstGetParams(lst, &incpblk, NULL);
+ if(pvals == NULL) {
+ goto done;
+ }
+ DBGPRINTF("include param blk after includeProcessCnf:\n");
+ cnfparamsPrint(&incpblk, pvals);
+ for(i = 0 ; i < incpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+
+ if(!strcmp(incpblk.descr[i].name, "file")) {
+ inc_file = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(incpblk.descr[i].name, "text")) {
+ text = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(incpblk.descr[i].name, "mode")) {
+ char *const md = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcmp(md, "abort-if-missing")) {
+ optional = 0;
+ abort_if_missing = 1;
+ } else if(!strcmp(md, "required")) {
+ optional = 0;
+ } else if(!strcmp(md, "optional")) {
+ optional = 1;
+ } else {
+ parser_errmsg("invalid 'mode' parameter: '%s' - ignored", md);
+ }
+ free((void*)md);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "rainerscript/include: program error, non-handled inclpblk "
+ "param '%s' in includeProcessCnf()", incpblk.descr[i].name);
+ }
+ }
+
+ if(text != NULL && inc_file != NULL) {
+ parser_errmsg("include() must have either 'file' or 'text' "
+ "parameter, but both are set - ignored");
+ goto done;
+ }
+
+ if(inc_file != NULL) {
+ if(cnfDoInclude(inc_file, optional) != 0 && abort_if_missing) {
+ fprintf(stderr, "include file '%s' mode is set to abort-if-missing "
+ "and the file is indeed missing - thus aborting rsyslog\n",
+ inc_file);
+ exit(1); /* "good exit" - during config processing, requested by user */
+ }
+ } else if(text != NULL) {
+ es_str_t *estr = es_newStrFromCStr((char*)text, strlen(text));
+ /* lex needs 2 \0 bytes as terminator indication (wtf ;-)) */
+ es_addChar(&estr, '\0');
+ es_addChar(&estr, '\0');
+ cnfAddConfigBuffer(estr, "text");
+ } else {
+ parser_errmsg("include must have either 'file' or 'text' "
+ "parameter - ignored");
+ goto done;
+ }
+
+done:
+ free((void*)text);
+ free((void*)inc_file);
+ nvlstDestruct(lst);
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &incpblk);
+ return;
+}
+
+
+void
+varDelete(const struct svar *v)
+{
+ switch(v->datatype) {
+ case 'S':
+ case 'J':
+ varFreeMembers(v);
+ break;
+ case 'A':
+ cnfarrayContentDestruct(v->d.ar);
+ free(v->d.ar);
+ break;
+ default:break;
+ }
+}
+
+void
+cnfparamvalsDestruct(const struct cnfparamvals *paramvals, const struct cnfparamblk *blk)
+{
+ int i;
+ if(paramvals == NULL)
+ return;
+ for(i = 0 ; i < blk->nParams ; ++i) {
+ if(paramvals[i].bUsed) {
+ varDelete(&paramvals[i].val);
+ }
+ }
+ free((void*)paramvals);
+}
+
+/* find the index (or -1!) for a config param by name. This is used to
+ * address the parameter array. Of course, we could use with static
+ * indices, but that would create some extra bug potential. So we
+ * resort to names. As we do this only during the initial config parsing
+ * stage the (considerable!) extra overhead is OK. -- rgerhards, 2011-07-19
+ */
+int
+cnfparamGetIdx(struct cnfparamblk *params, const char *name)
+{
+ int i;
+ for(i = 0 ; i < params->nParams ; ++i)
+ if(!strcmp(params->descr[i].name, name))
+ break;
+ if(i == params->nParams)
+ i = -1; /* not found */
+ return i;
+}
+
+
+void
+cstrPrint(const char *text, es_str_t *estr)
+{
+ char *str;
+ str = es_str2cstr(estr, NULL);
+ dbgprintf("%s%s", text, str);
+ free(str);
+}
+
+char *
+rmLeadingSpace(char *s)
+{
+ char *p;
+ for(p = s ; *p && isspace(*p) ; ++p)
+ ;
+ return(p);
+}
+
+/* init must be called once before any parsing of the script files start */
+rsRetVal
+initRainerscript(void)
+{
+ DEFiRet;
+ CHKmalloc(modListRoot = (struct modListNode*) malloc(sizeof(struct modListNode)));
+ modListRoot->version = 1;
+ modListRoot->modFcts = functions;
+ modListRoot->next = NULL;
+ modListLast = modListRoot;
+ iRet = objGetObjInterface(&obj);
+finalize_it:
+ RETiRet;
+}
+
+/* we need a function to check for octal digits */
+static inline int
+isodigit(uchar c)
+{
+ return(c >= '0' && c <= '7');
+}
+
+/**
+ * Get numerical value of a hex digit. This is a helper function.
+ * @param[in] c a character containing 0..9, A..Z, a..z anything else
+ * is an (undetected) error.
+ */
+static int
+hexDigitVal(char c)
+{
+ int r;
+ if(c < 'A')
+ r = c - '0';
+ else if(c < 'a')
+ r = c - 'A' + 10;
+ else
+ r = c - 'a' + 10;
+ return r;
+}
+
+/* Handle the actual unescaping.
+ * a helper to unescapeStr(), to help make the function easier to read.
+ */
+static void
+doUnescape(unsigned char *c, int len, int *iSrc, int iDst)
+{
+ if(c[*iSrc] == '\\') {
+ if(++(*iSrc) == len) {
+ /* error, incomplete escape, treat as single char */
+ c[iDst] = '\\';
+ }
+ /* regular case, unescape */
+ switch(c[*iSrc]) {
+ case 'a':
+ c[iDst] = '\007';
+ break;
+ case 'b':
+ c[iDst] = '\b';
+ break;
+ case 'f':
+ c[iDst] = '\014';
+ break;
+ case 'n':
+ c[iDst] = '\n';
+ break;
+ case 'r':
+ c[iDst] = '\r';
+ break;
+ case 't':
+ c[iDst] = '\t';
+ break;
+ case '\'':
+ c[iDst] = '\'';
+ break;
+ case '"':
+ c[iDst] = '"';
+ break;
+ case '?':
+ c[iDst] = '?';
+ break;
+ case '$':
+ c[iDst] = '$';
+ break;
+ case '\\':
+ c[iDst] = '\\';
+ break;
+ case 'x':
+ if( (*iSrc)+2 >= len
+ || !isxdigit(c[(*iSrc)+1])
+ || !isxdigit(c[(*iSrc)+2])) {
+ /* error, incomplete escape, use as is */
+ c[iDst] = '\\';
+ --(*iSrc);
+ }
+ c[iDst] = (hexDigitVal(c[(*iSrc)+1]) << 4) +
+ hexDigitVal(c[(*iSrc)+2]);
+ *iSrc += 2;
+ break;
+ case '0': /* octal escape */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ if( (*iSrc)+2 >= len
+ || !isodigit(c[(*iSrc)+1])
+ || !isodigit(c[(*iSrc)+2])) {
+ /* error, incomplete escape, use as is */
+ c[iDst] = '\\';
+ --(*iSrc);
+ }
+ c[iDst] = ((c[(*iSrc) ] - '0') << 6) +
+ ((c[(*iSrc)+1] - '0') << 3) +
+ ( c[(*iSrc)+2] - '0');
+ *iSrc += 2;
+ break;
+ default:
+ /* error, incomplete escape, indicate by '?' */
+ c[iDst] = '?';
+ break;
+ }
+ } else {
+ /* regular character */
+ c[iDst] = c[*iSrc];
+ }
+}
+
+void
+unescapeStr(uchar *s, int len)
+{
+ int iSrc, iDst;
+ assert(s != NULL);
+
+ /* scan for first escape sequence (if we are luky, there is none!) */
+ iSrc = 0;
+ while(iSrc < len && s[iSrc] != '\\')
+ ++iSrc;
+ /* now we have a sequence or end of string. In any case, we process
+ * all remaining characters (maybe 0!) and unescape.
+ */
+ if(iSrc != len) {
+ iDst = iSrc;
+ while(iSrc < len) {
+ doUnescape(s, len, &iSrc, iDst);
+ ++iSrc;
+ ++iDst;
+ }
+ s[iDst] = '\0';
+ }
+}
+
+const char *
+tokenval2str(const int tok)
+{
+ if(tok < 256) return "";
+ switch(tok) {
+ case NAME: return "NAME";
+ case FUNC: return "FUNC";
+ case BEGINOBJ: return "BEGINOBJ";
+ case ENDOBJ: return "ENDOBJ";
+ case BEGIN_ACTION: return "BEGIN_ACTION";
+ case BEGIN_PROPERTY: return "BEGIN_PROPERTY";
+ case BEGIN_CONSTANT: return "BEGIN_CONSTANT";
+ case BEGIN_TPL: return "BEGIN_TPL";
+ case BEGIN_INCLUDE: return "BEGIN_INCLUDE";
+ case BEGIN_RULESET: return "BEGIN_RULESET";
+ case STOP: return "STOP";
+ case SET: return "SET";
+ case UNSET: return "UNSET";
+ case CONTINUE: return "CONTINUE";
+ case CALL: return "CALL";
+ case LEGACY_ACTION: return "LEGACY_ACTION";
+ case LEGACY_RULESET: return "LEGACY_RULESET";
+ case PRIFILT: return "PRIFILT";
+ case PROPFILT: return "PROPFILT";
+ case BSD_TAG_SELECTOR: return "BSD_TAG_SELECTOR";
+ case BSD_HOST_SELECTOR: return "BSD_HOST_SELECTOR";
+ case IF: return "IF";
+ case THEN: return "THEN";
+ case ELSE: return "ELSE";
+ case OR: return "OR";
+ case AND: return "AND";
+ case NOT: return "NOT";
+ case VAR: return "VAR";
+ case STRING: return "STRING";
+ case NUMBER: return "NUMBER";
+ case CMP_EQ: return "CMP_EQ";
+ case CMP_NE: return "CMP_NE";
+ case CMP_LE: return "CMP_LE";
+ case CMP_GE: return "CMP_GE";
+ case CMP_LT: return "CMP_LT";
+ case CMP_GT: return "CMP_GT";
+ case CMP_CONTAINS: return "CMP_CONTAINS";
+ case CMP_CONTAINSI: return "CMP_CONTAINSI";
+ case CMP_STARTSWITH: return "CMP_STARTSWITH";
+ case CMP_STARTSWITHI: return "CMP_STARTSWITHI";
+ case UMINUS: return "UMINUS";
+ default: return "UNKNOWN TOKEN";
+ }
+}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
new file mode 100644
index 0000000..329f8bd
--- /dev/null
+++ b/grammar/rainerscript.h
@@ -0,0 +1,409 @@
+/* rsyslog rainerscript definitions
+ *
+ * Copyright 2011-2018 Rainer Gerhards
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INC_UTILS_H
+#define INC_UTILS_H
+#include <stdio.h>
+#include <libestr.h>
+#include <typedefs.h>
+#include <sys/types.h>
+#include <json.h>
+#include <regex.h>
+#include "typedefs.h"
+
+#define LOG_NFACILITIES 24+1 /* we copy&paste this as including rsyslog.h gets us in off64_t trouble... :-( */
+#define CNFFUNC_MAX_ARGS 32
+ /**< maximum number of arguments that any function can have (among
+ * others, this is used to size data structures).
+ */
+
+enum cnfobjType {
+ CNFOBJ_ACTION,
+ CNFOBJ_RULESET,
+ CNFOBJ_GLOBAL,
+ CNFOBJ_INPUT,
+ CNFOBJ_MODULE,
+ CNFOBJ_TPL,
+ CNFOBJ_PROPERTY,
+ CNFOBJ_CONSTANT,
+ CNFOBJ_MAINQ,
+ CNFOBJ_LOOKUP_TABLE,
+ CNFOBJ_PARSER,
+ CNFOBJ_TIMEZONE,
+ CNFOBJ_DYN_STATS,
+ CNFOBJ_PERCTILE_STATS,
+ CNFOBJ_INVALID = 0
+};
+
+const char* cnfobjType2str(enum cnfobjType ot);
+
+/* a variant type, for example used for expression evaluation
+ * 2011-07-15/rger: note that there exists a "legacy" object var,
+ * which implements the same idea, but in a suboptimal manner. I have
+ * stipped this down as much as possible, but will keep it for a while
+ * to avoid unnecessary complexity during development. TODO: in the long
+ * term, var shall be replaced by struct svar.
+ */
+struct svar{
+ union {
+ es_str_t *estr;
+ struct cnfarray *ar;
+ long long n;
+ struct json_object *json;
+ } d;
+ char datatype; /* 'N' number, 'S' string, 'J' JSON, 'A' array
+ * Note: 'A' is only supported during config phase
+ */
+};
+
+struct cnfobj {
+ enum cnfobjType objType;
+ struct nvlst *nvlst;
+ struct objlst *subobjs;
+ struct cnfstmt *script;
+};
+
+struct objlst {
+ struct objlst *next;
+ struct cnfobj *obj;
+};
+
+struct nvlst {
+ struct nvlst *next;
+ es_str_t *name;
+ struct svar val;
+ unsigned char bUsed;
+ /**< was this node used during config processing? If not, this
+ * indicates an error. After all, the user specified a setting
+ * that the software does not know.
+ */
+};
+
+/* the following structures support expressions, and may (very much later
+ * be the sole foundation for the AST.
+ *
+ * nodetypes (list not yet complete)
+ * A - (string) array
+ * F - function
+ * N - number
+ * P - fparamlst
+ * R - rule
+ * S - string
+ * V - var
+ * ... plus the S_* #define's below:
+ */
+#define S_STOP 4000
+#define S_PRIFILT 4001
+#define S_PROPFILT 4002
+#define S_IF 4003
+#define S_ACT 4004
+#define S_NOP 4005 /* usually used to disable some statement */
+#define S_SET 4006
+#define S_UNSET 4007
+#define S_CALL 4008
+#define S_FOREACH 4009
+#define S_RELOAD_LOOKUP_TABLE 4010
+#define S_CALL_INDIRECT 4011
+#define S_FUNC_EXISTS 4012 /* special case function which must get varname only */
+
+enum cnfFiltType { CNFFILT_NONE, CNFFILT_PRI, CNFFILT_PROP, CNFFILT_SCRIPT };
+const char* cnfFiltType2str(const enum cnfFiltType filttype);
+
+
+struct cnfstmt {
+ unsigned nodetype;
+ struct cnfstmt *next;
+ uchar *printable; /* printable text for debugging */
+ union {
+ struct {
+ struct cnfexpr *expr;
+ struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
+ } s_if;
+ struct {
+ uchar *varname;
+ struct cnfexpr *expr;
+ int force_reset;
+ } s_set;
+ struct {
+ uchar *varname;
+ } s_unset;
+ struct {
+ es_str_t *name;
+ struct cnfstmt *stmt;
+ ruleset_t *ruleset; /* non-NULL if the ruleset has a queue assigned */
+ } s_call;
+ struct {
+ struct cnfexpr *expr;
+ } s_call_ind;
+ struct {
+ uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
+ struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
+ } s_prifilt;
+ struct {
+ fiop_t operation;
+ regex_t *regex_cache;/* cache for compiled REs, if used */
+ struct cstr_s *pCSCompValue;/* value to "compare" against */
+ sbool isNegated;
+ msgPropDescr_t prop; /* requested property */
+ struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
+ } s_propfilt;
+ struct action_s *act;
+ struct {
+ struct cnfitr *iter;
+ struct cnfstmt *body;
+ } s_foreach;
+ struct {
+ lookup_ref_t *table;
+ uchar *table_name;
+ uchar *stub_value;
+ } s_reload_lookup_table;
+ } d;
+};
+
+struct cnfexpr {
+ unsigned nodetype;
+ struct cnfexpr *l;
+ struct cnfexpr *r;
+} __attribute__((aligned (8)));
+
+struct cnfitr {
+ char* var;
+ struct cnfexpr* collection;
+} __attribute__((aligned (8)));
+
+struct cnfnumval {
+ unsigned nodetype;
+ long long val;
+} __attribute__((aligned (8)));
+
+struct cnfstringval {
+ unsigned nodetype;
+ es_str_t *estr;
+} __attribute__((aligned (8)));
+
+struct cnfvar {
+ unsigned nodetype;
+ char *name;
+ msgPropDescr_t prop;
+} __attribute__((aligned (8)));
+
+struct cnfarray {
+ unsigned nodetype;
+ int nmemb;
+ es_str_t **arr;
+} __attribute__((aligned (8)));
+
+struct cnffparamlst {
+ unsigned nodetype; /* P */
+ struct cnffparamlst *next;
+ struct cnfexpr *expr;
+} __attribute__((aligned (8)));
+
+enum cnffuncid {
+ CNFFUNC_INVALID = 0, /**< defunct entry, do not use (should normally not be present) */
+ CNFFUNC_NAME = 1, /**< use name to call function (for future use) */
+ CNFFUNC_STRLEN,
+ CNFFUNC_SUBSTRING,
+ CNFFUNC_GETENV,
+ CNFFUNC_TOLOWER,
+ CNFFUNC_CSTR,
+ CNFFUNC_CNUM,
+ CNFFUNC_RE_MATCH,
+ CNFFUNC_RE_EXTRACT,
+ CNFFUNC_FIELD,
+ CNFFUNC_PRIFILT,
+ CNFFUNC_LOOKUP,
+ CNFFUNC_EXEC_TEMPLATE,
+ CNFFUNC_REPLACE,
+ CNFFUNC_WRAP,
+ CNFFUNC_RANDOM,
+ CNFFUNC_DYN_INC,
+ CNFFUNC_IPV42NUM,
+ CNFFUNC_NUM2IPV4,
+ CNFFUNC_INT2HEX,
+ CNFFUNC_LTRIM,
+ CNFFUNC_RTRIM,
+ CNFFUNC_FORMAT_TIME,
+ CNFFUNC_PARSE_TIME,
+ CNFFUNC_PARSE_JSON,
+ CNFFUNC_GET_PROPERTY,
+ CNFFUNC_PREVIOUS_ACTION_SUSPENDED,
+ CNFFUNC_SCRIPT_ERROR,
+ CNFFUNC_HTTP_REQUEST,
+ CNFFUNC_IS_TIME
+};
+
+typedef struct cnffunc cnffunc_t;
+typedef void (*rscriptFuncPtr) (cnffunc_t *, struct svar *, void *, wti_t *);
+
+struct cnffunc {
+ unsigned nodetype;
+ es_str_t *fname;
+ unsigned short nParams;
+ rscriptFuncPtr fPtr;
+ void *funcdata; /* global data for function-specific use (e.g. compiled regex) */
+ uint8_t destructable_funcdata;
+ struct cnfexpr *expr[];
+} __attribute__((aligned (8)));
+
+
+struct cnffuncexists {
+ unsigned nodetype;
+ const char *varname;
+ msgPropDescr_t prop;
+} __attribute__((aligned (8)));
+
+struct scriptFunct {
+ const char *fname;
+ unsigned short minParams;
+ unsigned short maxParams;
+ rscriptFuncPtr fPtr;
+ rsRetVal (*initFunc) (struct cnffunc *);
+ void (*destruct) (struct cnffunc *);
+ /* currently no optimizer entrypoint, may be added later.
+ * Since the optimizer needs metadata about functions, it does
+ * not seem practical to add such a function at the current state
+ */
+};
+
+
+/* future extensions
+<code>
+struct x {
+ int nodetype;
+};
+</code>
+*/
+
+
+/* the following defines describe the parameter block for puling
+ * config parameters. Note that the focus is on ease and saveness of
+ * use, not performance. For example, we address parameters by name
+ * instead of index, because the former is less error-prone. The (severe)
+ * performance hit does not matter, as it is a one-time hit during config
+ * load but never during actual processing. So there is really no reason
+ * to care.
+ */
+struct cnfparamdescr { /* first the param description */
+ const char *name;/**< not a es_str_t to ease definition in code */
+ ecslCmdHdrlType type;
+ unsigned flags;
+};
+/* flags for cnfparamdescr: */
+#define CNFPARAM_REQUIRED 0x0001
+#define CNFPARAM_DEPRECATED 0x0002
+
+struct cnfparamblk { /* now the actual param block use in API calls */
+ unsigned short version;
+ unsigned short nParams;
+ struct cnfparamdescr *descr;
+};
+#define CNFPARAMBLK_VERSION 1
+ /**< caller must have same version as engine -- else things may
+ * be messed up. But note that we may support multiple versions
+ * inside the engine, if at some later stage we want to do
+ * that. -- rgerhards, 2011-07-15
+ */
+struct cnfparamvals { /* the values we obtained for param descr. */
+ struct svar val;
+ unsigned char bUsed;
+};
+
+struct funcData_prifilt {
+ uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
+};
+
+/* script errno-like interface error codes: */
+#define RS_SCRIPT_EOK 0
+#define RS_SCRIPT_EINVAL 1
+
+void varFreeMembers(const struct svar *r);
+rsRetVal addMod2List(const int version, struct scriptFunct *functArray);
+void readConfFile(FILE *fp, es_str_t **str);
+struct objlst* objlstNew(struct cnfobj *obj);
+void objlstDestruct(struct objlst *lst);
+void objlstPrint(struct objlst *lst);
+struct nvlst* nvlstNewArray(struct cnfarray *ar);
+struct nvlst* nvlstNewStr(es_str_t *value);
+struct nvlst* nvlstNewStrBackticks(es_str_t *const value);
+struct nvlst* nvlstSetName(struct nvlst *lst, es_str_t *name);
+void nvlstDestruct(struct nvlst *lst);
+void nvlstPrint(struct nvlst *lst);
+void nvlstChkUnused(struct nvlst *lst);
+struct nvlst* nvlstFindName(struct nvlst *lst, es_str_t *name);
+int nvlstChkDisabled(struct nvlst *lst);
+struct cnfobj* cnfobjNew(enum cnfobjType objType, struct nvlst *lst);
+void cnfobjDestruct(struct cnfobj *o);
+void cnfobjPrint(struct cnfobj *o);
+struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r);
+void cnfexprPrint(struct cnfexpr *expr, int indent);
+void cnfexprEval(const struct cnfexpr *const expr, struct svar *ret, void *pusr, wti_t *pWti);
+int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr, wti_t *pWti);
+struct json_object* cnfexprEvalCollection(struct cnfexpr * const expr, void * const usrptr, wti_t *pWti);
+void cnfexprDestruct(struct cnfexpr *expr);
+struct cnfnumval* cnfnumvalNew(long long val);
+struct cnfstringval* cnfstringvalNew(es_str_t *estr);
+struct cnfvar* cnfvarNew(char *name);
+struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst);
+struct cnffuncexists * cnffuncexistsNew(const char *varname);
+struct cnffparamlst * cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next);
+int cnfDoInclude(const char *name, const int optional);
+int cnfparamGetIdx(struct cnfparamblk *params, const char *name);
+struct cnfparamvals* nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
+ struct cnfparamvals *vals);
+void cnfparamsPrint(const struct cnfparamblk *params, const struct cnfparamvals *vals);
+int cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals);
+void varDelete(const struct svar *v);
+void cnfparamvalsDestruct(const struct cnfparamvals *paramvals, const struct cnfparamblk *blk);
+struct cnfstmt * cnfstmtNew(unsigned s_type);
+struct cnfitr * cnfNewIterator(char *var, struct cnfexpr *collection);
+void cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree);
+void cnfstmtPrint(struct cnfstmt *stmt, int indent);
+struct cnfstmt* scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s);
+struct objlst* objlstAdd(struct objlst *root, struct cnfobj *o);
+char *rmLeadingSpace(char *s);
+struct cnfstmt * cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then);
+struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then);
+struct cnfstmt * cnfstmtNewAct(struct nvlst *lst);
+struct cnfstmt * cnfstmtNewLegaAct(char *actline);
+struct cnfstmt * cnfstmtNewSet(char *var, struct cnfexpr *expr, int force_reset);
+struct cnfstmt * cnfstmtNewUnset(char *var);
+struct cnfstmt * cnfstmtNewCall(es_str_t *name);
+struct cnfstmt * cnfstmtNewContinue(void);
+struct cnfstmt * cnfstmtNewReloadLookupTable(struct cnffparamlst *fparams);
+void cnfstmtDestructLst(struct cnfstmt *root);
+struct cnfstmt *cnfstmtOptimize(struct cnfstmt *root);
+struct cnfarray* cnfarrayNew(es_str_t *val);
+struct cnfarray* cnfarrayDup(struct cnfarray *old);
+struct cnfarray* cnfarrayAdd(struct cnfarray *ar, es_str_t *val);
+void cnfarrayContentDestruct(struct cnfarray *ar);
+const char* getFIOPName(unsigned iFIOP);
+rsRetVal initRainerscript(void);
+void unescapeStr(uchar *s, int len);
+const char * tokenval2str(int tok);
+uchar* var2CString(struct svar *__restrict__ const r, int *__restrict__ const bMustFree);
+long long var2Number(struct svar *r, int *bSuccess);
+void includeProcessCnf(struct nvlst *const lst);
+
+/* debug helper */
+void cstrPrint(const char *text, es_str_t *estr);
+
+#endif
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..8175c64
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,518 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2018-03-11.20; # 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.
+
+tab=' '
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# 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_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
+is_target_a_directory=possibly
+
+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
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) is_target_a_directory=never;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
+
+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
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+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.
+ if test -d "$dst"; then
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
+ dstdir_status=0
+ else
+ dstdir=`dirname "$dst"`
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
+ 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.
+ ;;
+ *)
+ # Note that $RANDOM variable is not portable (e.g. dash); Use it
+ # here however when possible just to lower collision chance.
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p' feature.
+ if (umask $mkdir_umask &&
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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.
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 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
+
+ oIFS=$IFS
+ IFS=/
+ set -f
+ set fnord $dstdir
+ shift
+ 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=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_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` &&
+ set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ 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 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644
index 0000000..0cb7f90
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,11251 @@
+#! /bin/sh
+## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
+## by inline-source v2014-01-03.01
+
+# libtool (GNU libtool) 2.4.6
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996-2015 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION="2.4.6 Debian-2.4.6-14"
+package_revision=2.4.6
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Run './libtool --help' for help with using this script from the
+# command line.
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# After configure completes, it has a better idea of some of the
+# shell tools we need than the defaults used by the functions shared
+# with bootstrap, so set those here where they can still be over-
+# ridden by the user, but otherwise take precedence.
+
+: ${AUTOCONF="autoconf"}
+: ${AUTOMAKE="automake"}
+
+
+## -------------------------- ##
+## Source external libraries. ##
+## -------------------------- ##
+
+# Much of our low-level functionality needs to be sourced from external
+# libraries, which are installed to $pkgauxdir.
+
+# Set a version string for this script.
+scriptversion=2015-01-20.17; # UTC
+
+# General shell script boiler plate, and helper functions.
+# Written by Gary V. Vaughan, 2004
+
+# Copyright (C) 2004-2015 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.
+
+# 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.
+
+# 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNES 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/>.
+
+# Please report bugs or propose patches to gary@gnu.org.
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Evaluate this file near the top of your script to gain access to
+# the functions and variables defined here:
+#
+# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
+#
+# If you need to override any of the default environment variable
+# settings, do that before evaluating this file.
+
+
+## -------------------- ##
+## Shell normalisation. ##
+## -------------------- ##
+
+# Some shells need a little help to be as Bourne compatible as possible.
+# Before doing anything else, make sure all that help has been provided!
+
+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
+
+# NLS nuisances: We save the old values in case they are required later.
+_G_user_locale=
+_G_safe_locale=
+for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test set = \"\${$_G_var+set}\"; then
+ save_$_G_var=\$$_G_var
+ $_G_var=C
+ export $_G_var
+ _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
+ _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
+ fi"
+done
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Make sure IFS has a sensible default
+sp=' '
+nl='
+'
+IFS="$sp $nl"
+
+# There are apparently some retarded systems that use ';' as a PATH separator!
+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
+
+
+
+## ------------------------- ##
+## Locate command utilities. ##
+## ------------------------- ##
+
+
+# func_executable_p FILE
+# ----------------------
+# Check that FILE is an executable regular file.
+func_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+}
+
+
+# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
+# --------------------------------------------
+# Search for either a program that responds to --version with output
+# containing "GNU", or else returned by CHECK_FUNC otherwise, by
+# trying all the directories in PATH with each of the elements of
+# PROGS_LIST.
+#
+# CHECK_FUNC should accept the path to a candidate program, and
+# set $func_check_prog_result if it truncates its output less than
+# $_G_path_prog_max characters.
+func_path_progs ()
+{
+ _G_progs_list=$1
+ _G_check_func=$2
+ _G_PATH=${3-"$PATH"}
+
+ _G_path_prog_max=0
+ _G_path_prog_found=false
+ _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
+ for _G_dir in $_G_PATH; do
+ IFS=$_G_save_IFS
+ test -z "$_G_dir" && _G_dir=.
+ for _G_prog_name in $_G_progs_list; do
+ for _exeext in '' .EXE; do
+ _G_path_prog=$_G_dir/$_G_prog_name$_exeext
+ func_executable_p "$_G_path_prog" || continue
+ case `"$_G_path_prog" --version 2>&1` in
+ *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
+ *) $_G_check_func $_G_path_prog
+ func_path_progs_result=$func_check_prog_result
+ ;;
+ esac
+ $_G_path_prog_found && break 3
+ done
+ done
+ done
+ IFS=$_G_save_IFS
+ test -z "$func_path_progs_result" && {
+ echo "no acceptable sed could be found in \$PATH" >&2
+ exit 1
+ }
+}
+
+
+# We want to be able to use the functions in this file before configure
+# has figured out where the best binaries are kept, which means we have
+# to search for them ourselves - except when the results are already set
+# where we skip the searches.
+
+# Unless the user overrides by setting SED, search the path for either GNU
+# sed, or the sed that truncates its output the least.
+test -z "$SED" && {
+ _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for _G_i in 1 2 3 4 5 6 7; do
+ _G_sed_script=$_G_sed_script$nl$_G_sed_script
+ done
+ echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
+ _G_sed_script=
+
+ func_check_prog_sed ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo '' >> conftest.nl
+ "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin
+ rm -f conftest.sed
+ SED=$func_path_progs_result
+}
+
+
+# Unless the user overrides by setting GREP, search the path for either GNU
+# grep, or the grep that truncates its output the least.
+test -z "$GREP" && {
+ func_check_prog_grep ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ _G_path_prog_max=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo 'GREP' >> conftest.nl
+ "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin
+ GREP=$func_path_progs_result
+}
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# All uppercase variable names are used for environment variables. These
+# variables can be overridden by the user before calling a script that
+# uses them if a suitable command of that name is not already available
+# in the command search PATH.
+
+: ${CP="cp -f"}
+: ${ECHO="printf %s\n"}
+: ${EGREP="$GREP -E"}
+: ${FGREP="$GREP -F"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+
+
+## -------------------- ##
+## Useful sed snippets. ##
+## -------------------- ##
+
+sed_dirname='s|/[^/]*$||'
+sed_basename='s|^.*/||'
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Same as above, but do not quote variable references.
+sed_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
+# that contains forward slashes, into one that contains
+# (escaped) backslashes. A very naive implementation.
+sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-'\' parameter expansions in output of sed_double_quote_subst that
+# were '\'-ed in input to the same. If an odd number of '\' preceded a
+# '$' in input to sed_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 '$'.
+_G_bs='\\'
+_G_bs2='\\\\'
+_G_bs4='\\\\\\\\'
+_G_dollar='\$'
+sed_double_backslash="\
+ s/$_G_bs4/&\\
+/g
+ s/^$_G_bs2$_G_dollar/$_G_bs&/
+ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
+ s/\n//g"
+
+
+## ----------------- ##
+## Global variables. ##
+## ----------------- ##
+
+# Except for the global variables explicitly listed below, the following
+# functions in the '^func_' namespace, and the '^require_' namespace
+# variables initialised in the 'Resource management' section, sourcing
+# this file will not pollute your global namespace with anything
+# else. There's no portable way to scope variables in Bourne shell
+# though, so actually running these functions will sometimes place
+# results into a variable named after the function, and often use
+# temporary variables in the '^_G_' namespace. If you are careful to
+# avoid using those namespaces casually in your sourcing script, things
+# should continue to work as you expect. And, of course, you can freely
+# overwrite any of the functions or variables defined here before
+# calling anything to customize them.
+
+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.
+
+# Allow overriding, eg assuming that you follow the convention of
+# putting '$debug_cmd' at the start of all your functions, you can get
+# bash to show function call trace with:
+#
+# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+debug_cmd=${debug_cmd-":"}
+exit_cmd=:
+
+# By convention, finish your script with:
+#
+# exit $exit_status
+#
+# so that you can set exit_status to non-zero if you want to indicate
+# something went wrong during execution without actually bailing out at
+# the point of failure.
+exit_status=$EXIT_SUCCESS
+
+# 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.
+progname=`$ECHO "$progpath" |$SED "$sed_basename"`
+
+# Make sure we have an absolute progpath for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
+ progdir=`cd "$progdir" && pwd`
+ progpath=$progdir/$progname
+ ;;
+ *)
+ _G_IFS=$IFS
+ IFS=${PATH_SEPARATOR-:}
+ for progdir in $PATH; do
+ IFS=$_G_IFS
+ test -x "$progdir/$progname" && break
+ done
+ IFS=$_G_IFS
+ test -n "$progdir" || progdir=`pwd`
+ progpath=$progdir/$progname
+ ;;
+esac
+
+
+## ----------------- ##
+## Standard options. ##
+## ----------------- ##
+
+# The following options affect the operation of the functions defined
+# below, and should be set appropriately depending on run-time para-
+# meters passed on the command line.
+
+opt_dry_run=false
+opt_quiet=false
+opt_verbose=false
+
+# Categories 'all' and 'none' are always available. Append any others
+# you will pass as the first argument to func_warning from your own
+# code.
+warning_categories=
+
+# By default, display warnings according to 'opt_warning_types'. Set
+# 'warning_func' to ':' to elide all warnings, or func_fatal_error to
+# treat the next displayed warning as a fatal error.
+warning_func=func_warn_and_continue
+
+# Set to 'all' to display all warnings, 'none' to suppress all
+# warnings, or a space delimited list of some subset of
+# 'warning_categories' to display only the listed warnings.
+opt_warning_types=all
+
+
+## -------------------- ##
+## Resource management. ##
+## -------------------- ##
+
+# This section contains definitions for functions that each ensure a
+# particular resource (a file, or a non-empty configuration variable for
+# example) is available, and if appropriate to extract default values
+# from pertinent package files. Call them using their associated
+# 'require_*' variable to ensure that they are executed, at most, once.
+#
+# It's entirely deliberate that calling these functions can set
+# variables that don't obey the namespace limitations obeyed by the rest
+# of this file, in order that that they be as useful as possible to
+# callers.
+
+
+# require_term_colors
+# -------------------
+# Allow display of bold text on terminals that support it.
+require_term_colors=func_require_term_colors
+func_require_term_colors ()
+{
+ $debug_cmd
+
+ test -t 1 && {
+ # COLORTERM and USE_ANSI_COLORS environment variables take
+ # precedence, because most terminfo databases neglect to describe
+ # whether color sequences are supported.
+ test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
+
+ if test 1 = "$USE_ANSI_COLORS"; then
+ # Standard ANSI escape sequences
+ tc_reset=''
+ tc_bold=''; tc_standout=''
+ tc_red=''; tc_green=''
+ tc_blue=''; tc_cyan=''
+ else
+ # Otherwise trust the terminfo database after all.
+ test -n "`tput sgr0 2>/dev/null`" && {
+ tc_reset=`tput sgr0`
+ test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
+ tc_standout=$tc_bold
+ test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
+ test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
+ test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
+ test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
+ test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
+ }
+ fi
+ }
+
+ require_term_colors=:
+}
+
+
+## ----------------- ##
+## Function library. ##
+## ----------------- ##
+
+# This section contains a variety of useful functions to call in your
+# scripts. Take note of the portable wrappers for features provided by
+# some modern shells, which will fall back to slower equivalents on
+# less featureful shells.
+
+
+# func_append VAR VALUE
+# ---------------------
+# Append VALUE onto the existing contents of VAR.
+
+ # We should try to minimise forks, especially on Windows where they are
+ # unreasonably slow, so skip the feature probes when bash or zsh are
+ # being used:
+ if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
+ : ${_G_HAVE_ARITH_OP="yes"}
+ : ${_G_HAVE_XSI_OPS="yes"}
+ # The += operator was introduced in bash 3.1
+ case $BASH_VERSION in
+ [12].* | 3.0 | 3.0*) ;;
+ *)
+ : ${_G_HAVE_PLUSEQ_OP="yes"}
+ ;;
+ esac
+ fi
+
+ # _G_HAVE_PLUSEQ_OP
+ # Can be empty, in which case the shell is probed, "yes" if += is
+ # useable or anything else if it does not work.
+ test -z "$_G_HAVE_PLUSEQ_OP" \
+ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
+ && _G_HAVE_PLUSEQ_OP=yes
+
+if test yes = "$_G_HAVE_PLUSEQ_OP"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_append ()
+ {
+ $debug_cmd
+
+ eval "$1+=\$2"
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_append ()
+ {
+ $debug_cmd
+
+ eval "$1=\$$1\$2"
+ }
+fi
+
+
+# func_append_quoted VAR VALUE
+# ----------------------------
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+if test yes = "$_G_HAVE_PLUSEQ_OP"; then
+ eval 'func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_for_eval "$2"
+ eval "$1+=\\ \$func_quote_for_eval_result"
+ }'
+else
+ func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_for_eval "$2"
+ eval "$1=\$$1\\ \$func_quote_for_eval_result"
+ }
+fi
+
+
+# func_append_uniq VAR VALUE
+# --------------------------
+# Append unique VALUE onto the existing contents of VAR, assuming
+# entries are delimited by the first character of VALUE. For example:
+#
+# func_append_uniq options " --another-option option-argument"
+#
+# will only append to $options if " --another-option option-argument "
+# is not already present somewhere in $options already (note spaces at
+# each end implied by leading space in second argument).
+func_append_uniq ()
+{
+ $debug_cmd
+
+ eval _G_current_value='`$ECHO $'$1'`'
+ _G_delim=`expr "$2" : '\(.\)'`
+
+ case $_G_delim$_G_current_value$_G_delim in
+ *"$2$_G_delim"*) ;;
+ *) func_append "$@" ;;
+ esac
+}
+
+
+# func_arith TERM...
+# ------------------
+# Set func_arith_result to the result of evaluating TERMs.
+ test -z "$_G_HAVE_ARITH_OP" \
+ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
+ && _G_HAVE_ARITH_OP=yes
+
+if test yes = "$_G_HAVE_ARITH_OP"; then
+ eval 'func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=$(( $* ))
+ }'
+else
+ func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=`expr "$@"`
+ }
+fi
+
+
+# func_basename FILE
+# ------------------
+# Set func_basename_result to FILE with everything up to and including
+# the last / stripped.
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ # If this shell supports suffix pattern removal, then use it to avoid
+ # forking. Hide the definitions single quotes in case the shell chokes
+ # on unsupported syntax...
+ _b='func_basename_result=${1##*/}'
+ _d='case $1 in
+ */*) func_dirname_result=${1%/*}$2 ;;
+ * ) func_dirname_result=$3 ;;
+ esac'
+
+else
+ # ...otherwise fall back to using sed.
+ _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
+ _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"`
+ if test "X$func_dirname_result" = "X$1"; then
+ func_dirname_result=$3
+ else
+ func_append func_dirname_result "$2"
+ fi'
+fi
+
+eval 'func_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+}'
+
+
+# func_dirname FILE APPEND NONDIR_REPLACEMENT
+# -------------------------------------------
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+eval 'func_dirname ()
+{
+ $debug_cmd
+
+ '"$_d"'
+}'
+
+
+# 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"
+# For efficiency, we do not delegate to the functions above but instead
+# duplicate the functionality here.
+eval 'func_dirname_and_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+ '"$_d"'
+}'
+
+
+# func_echo ARG...
+# ----------------
+# Echo program name prefixed message.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_echo_all ARG...
+# --------------------
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+
+# func_echo_infix_1 INFIX ARG...
+# ------------------------------
+# Echo program name, followed by INFIX on the first line, with any
+# additional lines not showing INFIX.
+func_echo_infix_1 ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ _G_infix=$1; shift
+ _G_indent=$_G_infix
+ _G_prefix="$progname: $_G_infix: "
+ _G_message=$*
+
+ # Strip color escape sequences before counting printable length
+ for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
+ do
+ test -n "$_G_tc" && {
+ _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
+ _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
+ }
+ done
+ _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes
+
+ func_echo_infix_1_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_infix_1_IFS
+ $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
+ _G_prefix=$_G_indent
+ done
+ IFS=$func_echo_infix_1_IFS
+}
+
+
+# func_error ARG...
+# -----------------
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2
+}
+
+
+# func_fatal_error ARG...
+# -----------------------
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ $debug_cmd
+
+ func_error "$*"
+ exit $EXIT_FAILURE
+}
+
+
+# func_grep EXPRESSION FILENAME
+# -----------------------------
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $debug_cmd
+
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_len STRING
+# ---------------
+# Set func_len_result to the length of STRING. STRING may not
+# start with a hyphen.
+ test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=${#1}
+ }'
+else
+ func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+ }
+fi
+
+
+# func_mkdir_p DIRECTORY-PATH
+# ---------------------------
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ $debug_cmd
+
+ _G_directory_path=$1
+ _G_dir_list=
+
+ if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
+
+ # Protect directory names starting with '-'
+ case $_G_directory_path in
+ -*) _G_directory_path=./$_G_directory_path ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$_G_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ _G_dir_list=$_G_directory_path:$_G_dir_list
+
+ # If the last portion added has no slash in it, the list is done
+ case $_G_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
+ done
+ _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
+
+ func_mkdir_p_IFS=$IFS; IFS=:
+ for _G_dir in $_G_dir_list; do
+ IFS=$func_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 "$_G_dir" 2>/dev/null || :
+ done
+ IFS=$func_mkdir_p_IFS
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$_G_directory_path" || \
+ func_fatal_error "Failed to create '$1'"
+ fi
+}
+
+
+# func_mktempdir [BASENAME]
+# -------------------------
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, BASENAME is the basename for that directory.
+func_mktempdir ()
+{
+ $debug_cmd
+
+ _G_template=${TMPDIR-/tmp}/${1-$progname}
+
+ if test : = "$opt_dry_run"; then
+ # Return a directory name, but don't create it in dry-run mode
+ _G_tmpdir=$_G_template-$$
+ else
+
+ # If mktemp works, use that first and foremost
+ _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$_G_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ _G_tmpdir=$_G_template-${RANDOM-0}$$
+
+ func_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$_G_tmpdir"
+ umask $func_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$_G_tmpdir" || \
+ func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
+ fi
+
+ $ECHO "$_G_tmpdir"
+}
+
+
+# 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.
+func_normal_abspath ()
+{
+ $debug_cmd
+
+ # These SED scripts presuppose an absolute path with a trailing slash.
+ _G_pathcar='s|^/\([^/]*\).*$|\1|'
+ _G_pathcdr='s|^/[^/]*||'
+ _G_removedotparts=':dotsl
+ s|/\./|/|g
+ t dotsl
+ s|/\.$|/|'
+ _G_collapseslashes='s|/\{1,\}|/|g'
+ _G_finalslash='s|/*$|/|'
+
+ # 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 "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_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 "$_G_pathcar"`
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_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_append 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_notquiet ARG...
+# --------------------
+# Echo program name prefixed message only when not in quiet mode.
+func_notquiet ()
+{
+ $debug_cmd
+
+ $opt_quiet || 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_relative_path SRCDIR DSTDIR
+# --------------------------------
+# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
+func_relative_path ()
+{
+ $debug_cmd
+
+ 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 -z "$func_relative_path_tlibdir"; 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 -n "$func_stripname_result"; then
+ func_append func_relative_path_result "/$func_stripname_result"
+ fi
+
+ # Normalisation. If bindir is libdir, return '.' else relative path.
+ if test -n "$func_relative_path_result"; then
+ func_stripname './' '' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ fi
+
+ test -n "$func_relative_path_result" || func_relative_path_result=.
+
+ :
+}
+
+
+# func_quote_for_eval ARG...
+# --------------------------
+# Aesthetically quote ARGs to be evaled later.
+# This function returns two values:
+# i) func_quote_for_eval_result
+# double-quoted, suitable for a subsequent eval
+# ii) func_quote_for_eval_unquoted_result
+# has all characters that are still active within double
+# quotes backslashified.
+func_quote_for_eval ()
+{
+ $debug_cmd
+
+ func_quote_for_eval_unquoted_result=
+ func_quote_for_eval_result=
+ while test 0 -lt $#; do
+ case $1 in
+ *[\\\`\"\$]*)
+ _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
+ *)
+ _G_unquoted_arg=$1 ;;
+ esac
+ if test -n "$func_quote_for_eval_unquoted_result"; then
+ func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
+ else
+ func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
+ fi
+
+ case $_G_unquoted_arg in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and variable expansion
+ # for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ _G_quoted_arg=\"$_G_unquoted_arg\"
+ ;;
+ *)
+ _G_quoted_arg=$_G_unquoted_arg
+ ;;
+ esac
+
+ if test -n "$func_quote_for_eval_result"; then
+ func_append func_quote_for_eval_result " $_G_quoted_arg"
+ else
+ func_append func_quote_for_eval_result "$_G_quoted_arg"
+ fi
+ shift
+ done
+}
+
+
+# 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 ()
+{
+ $debug_cmd
+
+ case $1 in
+ *[\\\`\"]*)
+ _G_arg=`$ECHO "$1" | $SED \
+ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
+ *)
+ _G_arg=$1 ;;
+ esac
+
+ case $_G_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.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ _G_arg=\"$_G_arg\"
+ ;;
+ esac
+
+ func_quote_for_expand_result=$_G_arg
+}
+
+
+# func_stripname PREFIX SUFFIX NAME
+# ---------------------------------
+# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
+# 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).
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_stripname ()
+ {
+ $debug_cmd
+
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary variable first.
+ func_stripname_result=$3
+ func_stripname_result=${func_stripname_result#"$1"}
+ func_stripname_result=${func_stripname_result%"$2"}
+ }'
+else
+ func_stripname ()
+ {
+ $debug_cmd
+
+ case $2 in
+ .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
+ *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
+ esac
+ }
+fi
+
+
+# func_show_eval CMD [FAIL_EXP]
+# -----------------------------
+# Unless opt_quiet 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 ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ func_quote_for_expand "$_G_cmd"
+ eval "func_notquiet $func_quote_for_expand_result"
+
+ $opt_dry_run || {
+ eval "$_G_cmd"
+ _G_status=$?
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_show_eval_locale CMD [FAIL_EXP]
+# ------------------------------------
+# Unless opt_quiet 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 ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ $opt_quiet || {
+ func_quote_for_expand "$_G_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ $opt_dry_run || {
+ eval "$_G_user_locale
+ $_G_cmd"
+ _G_status=$?
+ eval "$_G_safe_locale"
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ 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 ()
+{
+ $debug_cmd
+
+ case $1 in
+ [0-9]* | *[!a-zA-Z0-9_]*)
+ func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
+ ;;
+ * )
+ func_tr_sh_result=$1
+ ;;
+ esac
+}
+
+
+# func_verbose ARG...
+# -------------------
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $debug_cmd
+
+ $opt_verbose && func_echo "$*"
+
+ :
+}
+
+
+# func_warn_and_continue ARG...
+# -----------------------------
+# Echo program name prefixed warning message to standard error.
+func_warn_and_continue ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
+}
+
+
+# func_warning CATEGORY ARG...
+# ----------------------------
+# Echo program name prefixed warning message to standard error. Warning
+# messages can be filtered according to CATEGORY, where this function
+# elides messages where CATEGORY is not listed in the global variable
+# 'opt_warning_types'.
+func_warning ()
+{
+ $debug_cmd
+
+ # CATEGORY must be in the warning_categories list!
+ case " $warning_categories " in
+ *" $1 "*) ;;
+ *) func_internal_error "invalid warning category '$1'" ;;
+ esac
+
+ _G_category=$1
+ shift
+
+ case " $opt_warning_types " in
+ *" $_G_category "*) $warning_func ${1+"$@"} ;;
+ esac
+}
+
+
+# func_sort_ver VER1 VER2
+# -----------------------
+# 'sort -V' is not generally available.
+# Note this deviates from the version comparison in automake
+# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
+# but this should suffice as we won't be specifying old
+# version formats or redundant trailing .0 in bootstrap.conf.
+# If we did want full compatibility then we should probably
+# use m4_version_compare from autoconf.
+func_sort_ver ()
+{
+ $debug_cmd
+
+ printf '%s\n%s\n' "$1" "$2" \
+ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
+}
+
+# func_lt_ver PREV CURR
+# ---------------------
+# Return true if PREV and CURR are in the correct order according to
+# func_sort_ver, otherwise false. Use it like this:
+#
+# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
+func_lt_ver ()
+{
+ $debug_cmd
+
+ test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+#! /bin/sh
+
+# Set a version string for this script.
+scriptversion=2015-10-07.11; # UTC
+
+# A portable, pluggable option parser for Bourne shell.
+# Written by Gary V. Vaughan, 2010
+
+# Copyright (C) 2010-2015 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.
+
+# 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/>.
+
+# Please report bugs or propose patches to gary@gnu.org.
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# This file is a library for parsing options in your shell scripts along
+# with assorted other useful supporting features that you can make use
+# of too.
+#
+# For the simplest scripts you might need only:
+#
+# #!/bin/sh
+# . relative/path/to/funclib.sh
+# . relative/path/to/options-parser
+# scriptversion=1.0
+# func_options ${1+"$@"}
+# eval set dummy "$func_options_result"; shift
+# ...rest of your script...
+#
+# In order for the '--version' option to work, you will need to have a
+# suitably formatted comment like the one at the top of this file
+# starting with '# Written by ' and ending with '# warranty; '.
+#
+# For '-h' and '--help' to work, you will also need a one line
+# description of your script's purpose in a comment directly above the
+# '# Written by ' line, like the one at the top of this file.
+#
+# The default options also support '--debug', which will turn on shell
+# execution tracing (see the comment above debug_cmd below for another
+# use), and '--verbose' and the func_verbose function to allow your script
+# to display verbose messages only when your user has specified
+# '--verbose'.
+#
+# After sourcing this file, you can plug processing for additional
+# options by amending the variables from the 'Configuration' section
+# below, and following the instructions in the 'Option parsing'
+# section further down.
+
+## -------------- ##
+## Configuration. ##
+## -------------- ##
+
+# You should override these variables in your script after sourcing this
+# file so that they reflect the customisations you have added to the
+# option parser.
+
+# The usage line for option parsing errors and the start of '-h' and
+# '--help' output messages. You can embed shell variables for delayed
+# expansion at the time the message is displayed, but you will need to
+# quote other shell meta-characters carefully to prevent them being
+# expanded when the contents are evaled.
+usage='$progpath [OPTION]...'
+
+# Short help message in response to '-h' and '--help'. Add to this or
+# override it after sourcing this library to reflect the full set of
+# options your script accepts.
+usage_message="\
+ --debug enable verbose shell tracing
+ -W, --warnings=CATEGORY
+ report the warnings falling in CATEGORY [all]
+ -v, --verbose verbosely report processing
+ --version print version information and exit
+ -h, --help print short or long help message and exit
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+long_help_message="
+Warning categories include:
+ 'all' show all warnings
+ 'none' turn off all the warnings
+ 'error' warnings are treated as fatal errors"
+
+# Help message printed before fatal option parsing errors.
+fatal_help="Try '\$progname --help' for more information."
+
+
+
+## ------------------------- ##
+## Hook function management. ##
+## ------------------------- ##
+
+# This section contains functions for adding, removing, and running hooks
+# to the main code. A hook is just a named list of of function, that can
+# be run in order later on.
+
+# func_hookable FUNC_NAME
+# -----------------------
+# Declare that FUNC_NAME will run hooks added with
+# 'func_add_hook FUNC_NAME ...'.
+func_hookable ()
+{
+ $debug_cmd
+
+ func_append hookable_fns " $1"
+}
+
+
+# func_add_hook FUNC_NAME HOOK_FUNC
+# ---------------------------------
+# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must
+# first have been declared "hookable" by a call to 'func_hookable'.
+func_add_hook ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not accept hook functions." ;;
+ esac
+
+ eval func_append ${1}_hooks '" $2"'
+}
+
+
+# func_remove_hook FUNC_NAME HOOK_FUNC
+# ------------------------------------
+# Remove HOOK_FUNC from the list of functions called by FUNC_NAME.
+func_remove_hook ()
+{
+ $debug_cmd
+
+ eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
+}
+
+
+# func_run_hooks FUNC_NAME [ARG]...
+# ---------------------------------
+# Run all hook functions registered to FUNC_NAME.
+# It is assumed that the list of hook functions contains nothing more
+# than a whitespace-delimited list of legal shell function names, and
+# no effort is wasted trying to catch shell meta-characters or preserve
+# whitespace.
+func_run_hooks ()
+{
+ $debug_cmd
+
+ _G_rc_run_hooks=false
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not support hook funcions.n" ;;
+ esac
+
+ eval _G_hook_fns=\$$1_hooks; shift
+
+ for _G_hook in $_G_hook_fns; do
+ if eval $_G_hook '"$@"'; then
+ # store returned options list back into positional
+ # parameters for next 'cmd' execution.
+ eval _G_hook_result=\$${_G_hook}_result
+ eval set dummy "$_G_hook_result"; shift
+ _G_rc_run_hooks=:
+ fi
+ done
+
+ $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result
+}
+
+
+
+## --------------- ##
+## Option parsing. ##
+## --------------- ##
+
+# In order to add your own option parsing hooks, you must accept the
+# full positional parameter list in your hook function, you may remove/edit
+# any options that you action, and then pass back the remaining unprocessed
+# options in '<hooked_function_name>_result', escaped suitably for
+# 'eval'. In this case you also must return $EXIT_SUCCESS to let the
+# hook's caller know that it should pay attention to
+# '<hooked_function_name>_result'. Returning $EXIT_FAILURE signalizes that
+# arguments are left untouched by the hook and therefore caller will ignore the
+# result variable.
+#
+# Like this:
+#
+# my_options_prep ()
+# {
+# $debug_cmd
+#
+# # Extend the existing usage message.
+# usage_message=$usage_message'
+# -s, --silent don'\''t print informational messages
+# '
+# # No change in '$@' (ignored completely by this hook). There is
+# # no need to do the equivalent (but slower) action:
+# # func_quote_for_eval ${1+"$@"}
+# # my_options_prep_result=$func_quote_for_eval_result
+# false
+# }
+# func_add_hook func_options_prep my_options_prep
+#
+#
+# my_silent_option ()
+# {
+# $debug_cmd
+#
+# args_changed=false
+#
+# # Note that for efficiency, we parse as many options as we can
+# # recognise in a loop before passing the remainder back to the
+# # caller on the first unrecognised argument we encounter.
+# while test $# -gt 0; do
+# opt=$1; shift
+# case $opt in
+# --silent|-s) opt_silent=:
+# args_changed=:
+# ;;
+# # Separate non-argument short options:
+# -s*) func_split_short_opt "$_G_opt"
+# set dummy "$func_split_short_opt_name" \
+# "-$func_split_short_opt_arg" ${1+"$@"}
+# shift
+# args_changed=:
+# ;;
+# *) # Make sure the first unrecognised option "$_G_opt"
+# # is added back to "$@", we could need that later
+# # if $args_changed is true.
+# set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+# esac
+# done
+#
+# if $args_changed; then
+# func_quote_for_eval ${1+"$@"}
+# my_silent_option_result=$func_quote_for_eval_result
+# fi
+#
+# $args_changed
+# }
+# func_add_hook func_parse_options my_silent_option
+#
+#
+# my_option_validation ()
+# {
+# $debug_cmd
+#
+# $opt_silent && $opt_verbose && func_fatal_help "\
+# '--silent' and '--verbose' options are mutually exclusive."
+#
+# false
+# }
+# func_add_hook func_validate_options my_option_validation
+#
+# You'll also need to manually amend $usage_message to reflect the extra
+# options you parse. It's preferable to append if you can, so that
+# multiple option parsing hooks can be added safely.
+
+
+# func_options_finish [ARG]...
+# ----------------------------
+# Finishing the option parse loop (call 'func_options' hooks ATM).
+func_options_finish ()
+{
+ $debug_cmd
+
+ _G_func_options_finish_exit=false
+ if func_run_hooks func_options ${1+"$@"}; then
+ func_options_finish_result=$func_run_hooks_result
+ _G_func_options_finish_exit=:
+ fi
+
+ $_G_func_options_finish_exit
+}
+
+
+# func_options [ARG]...
+# ---------------------
+# All the functions called inside func_options are hookable. See the
+# individual implementations for details.
+func_hookable func_options
+func_options ()
+{
+ $debug_cmd
+
+ _G_rc_options=false
+
+ for my_func in options_prep parse_options validate_options options_finish
+ do
+ if eval func_$my_func '${1+"$@"}'; then
+ eval _G_res_var='$'"func_${my_func}_result"
+ eval set dummy "$_G_res_var" ; shift
+ _G_rc_options=:
+ fi
+ done
+
+ # Save modified positional parameters for caller. As a top-level
+ # options-parser function we always need to set the 'func_options_result'
+ # variable (regardless the $_G_rc_options value).
+ if $_G_rc_options; then
+ func_options_result=$_G_res_var
+ else
+ func_quote_for_eval ${1+"$@"}
+ func_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_options
+}
+
+
+# func_options_prep [ARG]...
+# --------------------------
+# All initialisations required before starting the option parse loop.
+# Note that when calling hook functions, we pass through the list of
+# positional parameters. If a hook function modifies that list, and
+# needs to propagate that back to rest of this script, then the complete
+# modified list must be put in 'func_run_hooks_result' before
+# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned).
+func_hookable func_options_prep
+func_options_prep ()
+{
+ $debug_cmd
+
+ # Option defaults:
+ opt_verbose=false
+ opt_warning_types=
+
+ _G_rc_options_prep=false
+ if func_run_hooks func_options_prep ${1+"$@"}; then
+ _G_rc_options_prep=:
+ # save modified positional parameters for caller
+ func_options_prep_result=$func_run_hooks_result
+ fi
+
+ $_G_rc_options_prep
+}
+
+
+# func_parse_options [ARG]...
+# ---------------------------
+# The main option parsing loop.
+func_hookable func_parse_options
+func_parse_options ()
+{
+ $debug_cmd
+
+ func_parse_options_result=
+
+ _G_rc_parse_options=false
+ # this just eases exit handling
+ while test $# -gt 0; do
+ # Defer to hook functions for initial option parsing, so they
+ # get priority in the event of reusing an option name.
+ if func_run_hooks func_parse_options ${1+"$@"}; then
+ eval set dummy "$func_run_hooks_result"; shift
+ _G_rc_parse_options=:
+ fi
+
+ # Break out of the loop if we already parsed every option.
+ test $# -gt 0 || break
+
+ _G_match_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --debug|-x) debug_cmd='set -x'
+ func_echo "enabling shell trace mode"
+ $debug_cmd
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ set dummy --warnings none ${1+"$@"}
+ shift
+ ;;
+
+ --warnings|--warning|-W)
+ if test $# = 0 && func_missing_arg $_G_opt; then
+ _G_rc_parse_options=:
+ break
+ fi
+ case " $warning_categories $1" in
+ *" $1 "*)
+ # trailing space prevents matching last $1 above
+ func_append_uniq opt_warning_types " $1"
+ ;;
+ *all)
+ opt_warning_types=$warning_categories
+ ;;
+ *none)
+ opt_warning_types=none
+ warning_func=:
+ ;;
+ *error)
+ opt_warning_types=$warning_categories
+ warning_func=func_fatal_error
+ ;;
+ *)
+ func_fatal_error \
+ "unsupported warning category: '$1'"
+ ;;
+ esac
+ shift
+ ;;
+
+ --verbose|-v) opt_verbose=: ;;
+ --version) func_version ;;
+ -\?|-h) func_usage ;;
+ --help) func_help ;;
+
+ # Separate optargs to long options (plugins may need this):
+ --*=*) func_split_equals "$_G_opt"
+ set dummy "$func_split_equals_lhs" \
+ "$func_split_equals_rhs" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate optargs to short options:
+ -W*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate non-argument short options:
+ -\?*|-h*|-v*|-x*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "-$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ --) _G_rc_parse_options=: ; break ;;
+ -*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
+ *) set dummy "$_G_opt" ${1+"$@"}; shift
+ _G_match_parse_options=false
+ break
+ ;;
+ esac
+
+ $_G_match_parse_options && _G_rc_parse_options=:
+ done
+
+
+ if $_G_rc_parse_options; then
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ func_parse_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_parse_options
+}
+
+
+# func_validate_options [ARG]...
+# ------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+func_hookable func_validate_options
+func_validate_options ()
+{
+ $debug_cmd
+
+ _G_rc_validate_options=false
+
+ # Display all warnings if -W was not given.
+ test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
+
+ if func_run_hooks func_validate_options ${1+"$@"}; then
+ # save modified positional parameters for caller
+ func_validate_options_result=$func_run_hooks_result
+ _G_rc_validate_options=:
+ fi
+
+ # Bail if the options were screwed!
+ $exit_cmd $EXIT_FAILURE
+
+ $_G_rc_validate_options
+}
+
+
+
+## ----------------- ##
+## Helper functions. ##
+## ----------------- ##
+
+# This section contains the helper functions used by the rest of the
+# hookable option parser framework in ascii-betical order.
+
+
+# func_fatal_help ARG...
+# ----------------------
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ eval \$ECHO \""$fatal_help"\"
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+
+# func_help
+# ---------
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message"
+ exit 0
+}
+
+
+# func_missing_arg ARGNAME
+# ------------------------
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ $debug_cmd
+
+ func_error "Missing argument for '$1'."
+ exit_cmd=exit
+}
+
+
+# func_split_equals STRING
+# ------------------------
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables after
+# splitting STRING at the '=' sign.
+test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=${1%%=*}
+ func_split_equals_rhs=${1#*=}
+ test "x$func_split_equals_lhs" = "x$1" \
+ && func_split_equals_rhs=
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
+ func_split_equals_rhs=
+ test "x$func_split_equals_lhs" = "x$1" \
+ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
+ }
+fi #func_split_equals
+
+
+# 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.
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_arg=${1#??}
+ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'`
+ func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
+ }
+fi #func_split_short_opt
+
+
+# func_usage
+# ----------
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
+ exit 0
+}
+
+
+# func_usage_message
+# ------------------
+# Echo short help message to standard output.
+func_usage_message ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ echo
+ $SED -n 's|^# ||
+ /^Written by/{
+ x;p;x
+ }
+ h
+ /^Written by/q' < "$progpath"
+ echo
+ eval \$ECHO \""$usage_message"\"
+}
+
+
+# func_version
+# ------------
+# Echo version message to standard output and exit.
+func_version ()
+{
+ $debug_cmd
+
+ printf '%s\n' "$progname $scriptversion"
+ $SED -n '
+ /(C)/!b go
+ :more
+ /\./!{
+ N
+ s|\n# | |
+ b more
+ }
+ :go
+ /^# Written by /,/# warranty; / {
+ s|^# ||
+ s|^# *$||
+ s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+ p
+ }
+ /^# Written by / {
+ s|^# ||
+ p
+ }
+ /^warranty; /q' < "$progpath"
+
+ exit $?
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+
+# Set a version string.
+scriptversion='(GNU libtool) 2.4.6'
+
+
+# func_echo ARG...
+# ----------------
+# Libtool also displays the current mode in messages, so override
+# funclib.sh func_echo with this custom definition.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_warning ARG...
+# -------------------
+# Libtool warnings are not categorized, so override funclib.sh
+# func_warning with this simpler definition.
+func_warning ()
+{
+ $debug_cmd
+
+ $warning_func ${1+"$@"}
+}
+
+
+## ---------------- ##
+## Options parsing. ##
+## ---------------- ##
+
+# Hook in the functions to make sure our own options are parsed during
+# the option parsing loop.
+
+usage='$progpath [OPTION]... [MODE-ARG]...'
+
+# Short help message in response to '-h'.
+usage_message="Options:
+ --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
+ --no-warnings equivalent to '-Wnone'
+ --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 more informational messages than default
+ --version print version information
+ -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
+ -h, --help, --help-all print short, long, or detailed help message
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$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. 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)
+ version: $progname $scriptversion Debian-2.4.6-14
+ automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
+ autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
+
+Report bugs to <bug-libtool@gnu.org>.
+GNU libtool home page: <http://www.gnu.org/s/libtool/>.
+General help using GNU software: <http://www.gnu.org/gethelp/>."
+ exit 0
+}
+
+
+# func_lo2o OBJECT-NAME
+# ---------------------
+# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
+# object suffix.
+
+lo2o=s/\\.lo\$/.$objext/
+o2lo=s/\\.$objext\$/.lo/
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_lo2o ()
+ {
+ case $1 in
+ *.lo) func_lo2o_result=${1%.lo}.$objext ;;
+ * ) func_lo2o_result=$1 ;;
+ esac
+ }'
+
+ # func_xform LIBOBJ-OR-SOURCE
+ # ---------------------------
+ # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
+ # suffix to a '.lo' libtool-object suffix.
+ eval 'func_xform ()
+ {
+ func_xform_result=${1%.*}.lo
+ }'
+else
+ # ...otherwise fall back to using sed.
+ func_lo2o ()
+ {
+ func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
+ }
+
+ func_xform ()
+ {
+ func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
+ }
+fi
+
+
+# func_fatal_configuration ARG...
+# -------------------------------
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func__fatal_error ${1+"$@"} \
+ "See the $PACKAGE documentation for more information." \
+ "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 yes = "$build_libtool_libs"; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test yes = "$build_old_libs"; 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
+}
+
+
+# libtool_options_prep [ARG]...
+# -----------------------------
+# Preparation for options parsed by libtool.
+libtool_options_prep ()
+{
+ $debug_mode
+
+ # Option defaults:
+ opt_config=false
+ opt_dlopen=
+ opt_dry_run=false
+ opt_help=false
+ opt_mode=
+ opt_preserve_dup_deps=false
+ opt_quiet=false
+
+ nonopt=
+ preserve_args=
+
+ _G_rc_lt_options_prep=:
+
+ # 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
+ ;;
+ *)
+ _G_rc_lt_options_prep=false
+ ;;
+ esac
+
+ if $_G_rc_lt_options_prep; then
+ # Pass back the list of options.
+ func_quote_for_eval ${1+"$@"}
+ libtool_options_prep_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_lt_options_prep
+}
+func_add_hook func_options_prep libtool_options_prep
+
+
+# libtool_parse_options [ARG]...
+# ---------------------------------
+# Provide handling for libtool specific options.
+libtool_parse_options ()
+{
+ $debug_cmd
+
+ _G_rc_lt_parse_options=false
+
+ # Perform our own loop to consume as many options as possible in
+ # each iteration.
+ while test $# -gt 0; do
+ _G_match_lt_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --dry-run|--dryrun|-n)
+ opt_dry_run=:
+ ;;
+
+ --config) func_config ;;
+
+ --dlopen|-dlopen)
+ opt_dlopen="${opt_dlopen+$opt_dlopen
+}$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_preserve_dup_deps=: ;;
+
+ --features) func_features ;;
+
+ --finish) set dummy --mode finish ${1+"$@"}; shift ;;
+
+ --help) opt_help=: ;;
+
+ --help-all) opt_help=': help-all' ;;
+
+ --mode) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_mode=$1
+ 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 $_G_opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+ shift
+ ;;
+
+ --no-silent|--no-quiet)
+ opt_quiet=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ opt_warning=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-verbose)
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --silent|--quiet)
+ opt_quiet=:
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --tag) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_tag=$1
+ func_append preserve_args " $_G_opt $1"
+ func_enable_tag "$1"
+ shift
+ ;;
+
+ --verbose|-v) opt_quiet=false
+ opt_verbose=:
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ # An option not handled by this hook function:
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_lt_parse_options=false
+ break
+ ;;
+ esac
+ $_G_match_lt_parse_options && _G_rc_lt_parse_options=:
+ done
+
+ if $_G_rc_lt_parse_options; then
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ libtool_parse_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_lt_parse_options
+}
+func_add_hook func_parse_options libtool_parse_options
+
+
+
+# libtool_validate_options [ARG]...
+# ---------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+libtool_validate_options ()
+{
+ # save first non-option argument
+ if test 0 -lt $#; then
+ nonopt=$1
+ shift
+ fi
+
+ # preserve --debug
+ test : = "$debug_cmd" || func_append preserve_args " --debug"
+
+ case $host in
+ # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
+ # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
+ *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
+ # 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
+
+ test yes != "$build_libtool_libs" \
+ && test yes != "$build_old_libs" \
+ && func_fatal_configuration "not configured to build any kind of library"
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$opt_dlopen" && test execute != "$opt_mode"; 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."
+ }
+
+ # Pass back the unparsed argument list
+ func_quote_for_eval ${1+"$@"}
+ libtool_validate_options_result=$func_quote_for_eval_result
+}
+func_add_hook func_validate_options libtool_validate_options
+
+
+# Process options as early as possible so that --help and --version
+# can return quickly.
+func_options ${1+"$@"}
+eval set dummy "$func_options_result"; shift
+
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+magic='%%%MAGIC variable%%%'
+magic_exe='%%%MAGIC EXE variable%%%'
+
+# Global variables.
+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=
+
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# func_generated_by_libtool
+# True iff stdin has been generated by Libtool. This function is only
+# a basic sanity check; it will hardly flush out determined imposters.
+func_generated_by_libtool_p ()
+{
+ $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# 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 | func_generated_by_libtool_p
+}
+
+# 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 yes = "$lalib_p"
+}
+
+# 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 ()
+{
+ test -f "$1" &&
+ $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# 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 ()
+{
+ $debug_cmd
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 yes = "$build_libtool_libs"; then
+ write_lobj=\'$2\'
+ else
+ write_lobj=none
+ fi
+
+ if test yes = "$build_old_libs"; 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) $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 ()
+{
+ $debug_cmd
+
+ 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 "$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 ()
+{
+ $debug_cmd
+
+ # 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ # awkward: cmd appends spaces to result
+ func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+ $SED -e 's/[ ]*$//' -e "$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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ $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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+ $debug_cmd
+
+ func_dll_def_p_tmp=`$SED -n \
+ -e 's/^[ ]*//' \
+ -e '/^\(;.*\)*$/d' \
+ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \
+ -e q \
+ "$1"`
+ test DEF = "$func_dll_def_p_tmp"
+}
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $debug_cmd
+
+ # 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 yes = "$build_libtool_libs" \
+ || func_fatal_configuration "cannot 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 yes = "$build_old_libs"; 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 no = "$pic_mode" && test pass_all != "$deplibs_check_method"; 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 no = "$compiler_c_o"; 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 yes = "$need_locks"; 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 warn = "$need_locks"; 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 yes = "$build_libtool_libs"; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test no != "$pic_mode"; 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 warn = "$need_locks" &&
+ 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 yes = "$suppress_opt"; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test yes = "$build_old_libs"; then
+ if test yes != "$pic_mode"; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test yes = "$compiler_c_o"; 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 warn = "$need_locks" &&
+ 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 no != "$need_locks"; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+ test compile = "$opt_mode" && 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
+ -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes)
+ -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 ()
+{
+ $debug_cmd
+
+ # 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 $opt_dry_run; then
+ # 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
+ else
+ 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
+ fi
+}
+
+test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $debug_cmd
+
+ 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_quiet && 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 finish = "$opt_mode" && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $debug_cmd
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
+ # 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=false
+ 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=: ;;
+ -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-m = "X$prev" && 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=:
+ if $isdir; 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
+ ;;
+ os2*)
+ 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 yes = "$build_old_libs"; 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=:
+ 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'`
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "'$lib' has not been installed in '$libdir'"
+ finalize=false
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test no = "$fast_install" && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if $finalize; 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_quiet || {
+ 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 install = "$opt_mode" && 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 ()
+{
+ $debug_cmd
+
+ my_outputname=$1
+ my_originator=$2
+ my_pic_p=${3-false}
+ my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; 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) $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 can'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
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test yes = "$dlself"; 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
+
+ func_show_eval '$RM "${nlist}I"'
+ if test -n "$global_symbol_to_import"; then
+ eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+ 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[];\
+"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+ LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+ for (; symbol->name; ++symbol)
+ {"
+ $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+ echo >> "$output_objdir/$my_dlsyms" "\
+ }
+}"
+ fi
+ echo >> "$output_objdir/$my_dlsyms" "\
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{ {\"$my_originator\", (void *) 0},"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {\"@INIT@\", (void *) &lt_syminit},"
+ fi
+
+ 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" ;;
+ *)
+ $my_pic_p && pic_flag_for_symtable=" $pic_flag"
+ ;;
+ 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" "${nlist}I"'
+
+ # 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_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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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_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 ()
+{
+ $debug_cmd
+
+ 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
+ case $nm_interface in
+ "MS dumpbin")
+ if func_cygming_ms_implib_p "$1" ||
+ func_cygming_gnu_implib_p "$1"
+ then
+ win32_nmres=import
+ else
+ win32_nmres=
+ fi
+ ;;
+ *)
+ 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
+ }
+ }'`
+ ;;
+ esac
+ 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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ 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 that possess that section. Heuristic: eliminate
+ # all those that 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_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 ()
+{
+ $debug_cmd
+
+ 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 ()
+{
+ $debug_cmd
+
+ f_ex_an_ar_dir=$1; shift
+ f_ex_an_ar_oldlib=$1
+ if test yes = "$lock_old_archive_extraction"; 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 yes = "$lock_old_archive_extraction"; 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 ()
+{
+ $debug_cmd
+
+ 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`
+ func_basename "$darwin_archive"
+ darwin_base_archive=$func_basename_result
+ 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 "$sed_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 where 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) $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/ that is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options that 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) $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 yes = "$fast_install"; 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 yes = "$shlibpath_overrides_runpath" && 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) $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>
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* 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_platform || defined ... */
+#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
+#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 (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
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
+# define externally_visible volatile
+#else
+# define externally_visible __attribute__((externally_visible)) volatile
+#endif
+externally_visible const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test yes = "$shlibpath_overrides_runpath" && 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 yes = "$fast_install"; 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;
+ int rval = 127;
+
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ newargz = XMALLOC (char *, (size_t) 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 (STREQ (argv[i], dumpscript_opt))
+ {
+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 (STREQ (argv[i], debug_opt))
+ {
+ lt_debug = 1;
+ continue;
+ }
+ if (STREQ (argv[i], ltwrapper_option_prefix))
+ {
+ /* 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) $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 = (int) _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];
+ size_t 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 = (size_t) (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 (STREQ (str, pat))
+ *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
+ size_t 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)
+ {
+ size_t orig_value_len = strlen (orig_value);
+ size_t 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 #' */
+ size_t len = strlen (new_value);
+ while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[--len] = '\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 ()
+{
+ $debug_cmd
+
+ case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+ *import*) : ;;
+ *) false ;;
+ esac
+}
+
+# func_suncc_cstd_abi
+# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
+# Several compiler flags select an ABI that is incompatible with the
+# Cstd library. Avoid specifying it if any are in CXXFLAGS.
+func_suncc_cstd_abi ()
+{
+ $debug_cmd
+
+ case " $compile_command " in
+ *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
+ suncc_use_cstd_abi=no
+ ;;
+ *)
+ suncc_use_cstd_abi=yes
+ ;;
+ esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $debug_cmd
+
+ 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
+ # what 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 that 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=
+ os2dllname=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=false
+ 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 yes != "$build_libtool_libs" \
+ && func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test yes = "$build_libtool_libs" && 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)
+ $preload || {
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=:
+ }
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test no = "$dlself"; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test dlprefiles = "$prev"; then
+ dlself=yes
+ elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test dlfiles = "$prev"; 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
+ ;;
+ mllvm)
+ # Clang does not use LLVM to link, so we can simply discard any
+ # '-mllvm $arg' options when doing the link step.
+ 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 none = "$pic_object" &&
+ test none = "$non_pic_object"; 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 none != "$pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; 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 dlprefiles = "$prev"; 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 none != "$non_pic_object"; 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 none = "$pic_object"; 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
+ ;;
+ os2dllname)
+ os2dllname=$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 rpath = "$prev"; 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-export-symbols = "X$arg"; 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-lc = "X$arg" || test X-lm = "X$arg"; 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-lc = "X$arg" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+ # Do not include libc due to us having libc/libc_r.
+ test X-lc = "X$arg" && 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-lc = "X$arg" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test X-lc = "X$arg" && continue
+ ;;
+ esac
+ elif test X-lc_r = "X$arg"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ func_append deplibs " $arg"
+ continue
+ ;;
+
+ -mllvm)
+ prev=mllvm
+ 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
+ ;;
+
+ -os2dllname)
+ prev=os2dllname
+ 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
+ # -fstack-protector* stack protector flags for GCC
+ # @file GCC response files
+ # -tp=* Portland pgcc target processor selection
+ # --sysroot=* for sysroot support
+ # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ # -specs=* GCC specs files
+ # -stdlib=* select c++ std lib with clang
+ # -fsanitize=* Clang/GCC memory and address sanitizer
+ # -fuse-ld=* Linker select flags for GCC
+ # -static-* direct GCC to link specific libraries statically
+ # -fcilkplus Cilk Plus language extension features for C/C++
+ -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*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus)
+ 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
+ ;;
+
+ -Z*)
+ if test os2 = "`expr $host : '.*\(os2\)'`"; then
+ # OS/2 uses -Zxxx to specify OS/2-specific options
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case $arg in
+ -Zlinker | -Zstack)
+ prev=xcompiler
+ ;;
+ esac
+ continue
+ else
+ # Otherwise treat like 'Some other compiler flag' below
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ fi
+ ;;
+
+ # 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 none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ test none = "$pic_object" || {
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; 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 dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ }
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; 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 none = "$pic_object"; 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 dlfiles = "$prev"; then
+ # This library was specified with -dlopen.
+ func_append dlfiles " $func_resolve_sysroot_result"
+ prev=
+ elif test dlprefiles = "$prev"; 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 yes = "$export_dynamic" && 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\"
+
+ # Definition is injected by LT_CONFIG during libtool generation.
+ func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
+
+ 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 lib = "$linkmode"; 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=false
+ 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 lib,link = "$linkmode,$pass"; 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 lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass"; then
+ libs=$deplibs
+ deplibs=
+ fi
+ if test prog = "$linkmode"; 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 lib,dlpreopen = "$linkmode,$pass"; 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 dlopen = "$pass"; then
+ # Collect dlpreopened libraries
+ save_deplibs=$deplibs
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=false
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append compiler_flags " $deplib"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test lib != "$linkmode" && test prog != "$linkmode"; then
+ func_warning "'-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test lib = "$linkmode"; 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 .la = "$search_ext"; then
+ found=:
+ else
+ found=false
+ fi
+ break 2
+ fi
+ done
+ done
+ if $found; then
+ # 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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=false
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+ lib=$ladir/$old_library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ else
+ # deplib doesn't seem to be a libtool library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ *.ltframework)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test lib = "$linkmode"; 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 conv = "$pass" && 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 conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test scan = "$pass"; 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 link = "$pass"; 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 conv = "$pass"; 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=false
+ 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=:
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=:
+ ;;
+ esac
+ if $valid_a_lib; then
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ else
+ 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."
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test link != "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ elif test prog = "$linkmode"; then
+ if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; 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=:
+ continue
+ ;;
+ esac # case $deplib
+
+ $found || test -f "$lib" \
+ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
+
+ # 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 lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass" ||
+ { test prog != "$linkmode" && test lib != "$linkmode"; }; then
+ test -n "$dlopen" && func_append dlfiles " $dlopen"
+ test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+ fi
+
+ if test conv = "$pass"; 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 prog != "$linkmode" && test lib != "$linkmode"; 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 yes = "$prefer_static_libs" ||
+ test built,no = "$prefer_static_libs,$installed"; }; 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 dlopen = "$pass"; then
+ test -z "$libdir" \
+ && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
+ if test -z "$dlname" ||
+ test yes != "$dlopen_support" ||
+ test no = "$build_libtool_libs"
+ 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 yes = "$installed"; 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 yes = "$hardcode_automatic" && 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 dlpreopen = "$pass"; then
+ if test -z "$libdir" && test prog = "$linkmode"; 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 lib = "$linkmode"; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test prog,link = "$linkmode,$pass"; 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 prog = "$linkmode" && test link != "$pass"; then
+ func_append newlib_search_path " $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=false
+ if test no != "$link_all_deplibs" || test -z "$library_names" ||
+ test no = "$build_libtool_libs"; then
+ linkalldeplibs=:
+ 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 $linkalldeplibs; 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 prog,link = "$linkmode,$pass"; then
+ if test -n "$library_names" &&
+ { { test no = "$prefer_static_libs" ||
+ test built,yes = "$prefer_static_libs,$installed"; } ||
+ 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 $alldeplibs &&
+ { test pass_all = "$deplibs_check_method" ||
+ { test yes = "$build_libtool_libs" &&
+ 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 built = "$use_static_libs" && test yes = "$installed"; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test no = "$use_static_libs" || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc* | *os2*)
+ # No point in relinking DLLs because paths are not encoded
+ func_append notinst_deplibs " $lib"
+ need_relink=no
+ ;;
+ *)
+ if test no = "$installed"; 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 yes = "$shouldnotlink" && test link = "$pass"; then
+ echo
+ if test prog = "$linkmode"; 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 lib = "$linkmode" &&
+ test yes = "$hardcode_into_libs"; 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* | *os2*)
+ 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 prog = "$linkmode" || test relink != "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test no = "$hardcode_direct"; 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 cannot
+ # 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 no = "$hardcode_minus_L"; then
+ case $host in
+ *-*-sunos*) add_shlibpath=$dir ;;
+ esac
+ add_dir=-L$dir
+ add=-l$name
+ elif test no = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$dir/$linklib
+ elif test yes = "$hardcode_minus_L"; 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 yes = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test yes != "$lib_linked"; 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 prog = "$linkmode"; 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 yes != "$hardcode_direct" &&
+ test yes != "$hardcode_minus_L" &&
+ test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test prog = "$linkmode" || test relink = "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$libdir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$libdir
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ add=-l$name
+ elif test yes = "$hardcode_automatic"; 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 prog = "$linkmode"; 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 prog = "$linkmode"; 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 unsupported != "$hardcode_direct"; 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 yes = "$build_libtool_libs"; then
+ # Not a shared library
+ if test pass_all != "$deplibs_check_method"; 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 cannot 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 yes = "$module"; 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 no = "$build_old_libs"; 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 lib = "$linkmode"; then
+ if test -n "$dependency_libs" &&
+ { test yes != "$hardcode_into_libs" ||
+ test yes = "$build_old_libs" ||
+ test yes = "$link_static"; }; 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 no = "$link_static" && 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 no != "$link_all_deplibs"; 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 link = "$pass"; then
+ if test prog = "$linkmode"; 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 dlpreopen = "$pass"; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test dlopen != "$pass"; then
+ test conv = "$pass" || {
+ # 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=
+ }
+
+ if test prog,link = "$linkmode,$pass"; then
+ vars="compile_deplibs finalize_deplibs"
+ else
+ vars=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
+
+ # Add Sun CC postdeps if required:
+ test CXX = "$tagname" && {
+ case $host_os in
+ linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C++ 5.9
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ func_cc_basename "$CC"
+ case $func_cc_basename_result in
+ CC* | sunCC*)
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ }
+
+ # 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 prog = "$linkmode"; then
+ dlfiles=$newdlfiles
+ fi
+ if test prog = "$linkmode" || test lib = "$linkmode"; then
+ dlprefiles=$newdlprefiles
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; 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 no = "$module" \
+ && func_fatal_help "libtool library '$output' must begin with 'lib'"
+
+ if test no != "$need_lib_prefix"; 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 pass_all != "$deplibs_check_method"; 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 no = "$dlself" \
+ || func_warning "'-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test 1 -lt "$#" \
+ && func_warning "ignoring multiple '-rpath's for a libtool library"
+
+ install_libdir=$1
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test yes = "$build_libtool_libs"; 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
+ # that has an extra 1 added just for fun
+ #
+ case $version_type in
+ # correct linux to gnu/linux during the next big refactor
+ darwin|freebsd-elf|linux|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_revision
+ ;;
+ freebsd-aout|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"
+ # On Darwin other compilers
+ case $CC in
+ nagfor*)
+ verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ ;;
+ *)
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+ esac
+ ;;
+
+ freebsd-aout)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ freebsd-elf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ irix | nonstopux)
+ if test no = "$lt_irix_increment"; 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 0 -ne "$loop"; 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 0 -ne "$loop"; 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
+ ;;
+
+ sco)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sunos)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 file systems.
+ 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 no = "$need_version"; then
+ versuffix=
+ else
+ versuffix=.0.0
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test yes,no = "$avoid_version,$need_version"; then
+ major=
+ versuffix=
+ verstring=
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test yes = "$allow_undefined"; then
+ if test unsupported = "$allow_undefined_flag"; then
+ if test yes = "$build_old_libs"; then
+ func_warning "undefined symbols not allowed in $host shared libraries; building static only"
+ build_libtool_libs=no
+ else
+ func_fatal_error "can't build $host shared library unless -no-undefined is specified"
+ fi
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag=$no_undefined_flag
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" :
+ func_append libobjs " $symfileobj"
+ test " " = "$libobjs" && libobjs=
+
+ if test relink != "$opt_mode"; 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 -n "$precious_files_regex"; 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 yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; 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 yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; 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 yes = "$build_libtool_libs"; 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 yes = "$build_libtool_need_lc"; 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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 yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ if test yes = "$want_nocaseglob"; 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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 yes = "$allow_libtool_libs_with_static_runtimes"; 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 none = "$deplibs_check_method"; 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 yes = "$droppeddeps"; then
+ if test yes = "$module"; 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 no = "$build_old_libs"; 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 no = "$allow_undefined"; 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 no = "$build_old_libs"; 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 yes = "$build_libtool_libs"; then
+ # Remove $wl instances when linking with ld.
+ # FIXME: should test the right _cmds variable.
+ case $archive_cmds in
+ *\$LD\ *) wl= ;;
+ esac
+ if test yes = "$hardcode_into_libs"; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath=$finalize_rpath
+ test relink = "$opt_mode" || 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 relink = "$opt_mode" || 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
+ func_dll_def_p "$export_symbols" || {
+ # 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
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test yes = "$always_export_symbols" || 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 yes = "$try_normal_branch" \
+ && { 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 : != "$skipped_export"; 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 : != "$skipped_export" && 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 yes = "$compiler_needs_object" &&
+ 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 yes = "$thread_safe" && 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 relink = "$opt_mode"; 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 yes = "$module" && 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 : != "$skipped_export" &&
+ 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 : != "$skipped_export" && test yes = "$with_gnu_ld"; 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 : != "$skipped_export" && test -n "$file_list_spec"; then
+ output=$output_objdir/$output_la.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test yes = "$compiler_needs_object"; 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 -z "$objlist" ||
+ 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 1 -eq "$k"; 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
+
+ ${skipped_export-false} && {
+ 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
+ }
+
+ 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_quiet || {
+ 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 relink = "$opt_mode"; 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
+
+ ${skipped_export-false} && {
+ 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
+ }
+
+ 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 yes = "$module" && 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=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ $opt_quiet || {
+ 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 relink = "$opt_mode"; 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 relink = "$opt_mode"; 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 yes = "$module" || test yes = "$export_dynamic"; then
+ # On all known operating systems, these are identical.
+ dlname=$soname
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; 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=
+ # if reload_cmds runs $LD directly, get rid of -Wl from
+ # whole_archive_flag_spec and hope we can get by with turning comma
+ # into space.
+ case $reload_cmds in
+ *\$LD[\ \$]*) wl= ;;
+ esac
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+ reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
+ 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 yes = "$build_libtool_libs" || 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
+
+ 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
+
+ test yes = "$build_libtool_libs" || {
+ 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
+ }
+
+ if test -n "$pic_flag" || test default != "$pic_mode"; 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"
+
+ $preload \
+ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
+ && 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 CXX = "$tagname"; 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 yes = "$build_old_libs"; 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@" false
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=:
+ case $host in
+ *cegcc* | *mingw32ce*)
+ # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+ wrappers_required=false
+ ;;
+ *cygwin* | *mingw* )
+ test yes = "$build_libtool_libs" || wrappers_required=false
+ ;;
+ *)
+ if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
+ wrappers_required=false
+ fi
+ ;;
+ esac
+ $wrappers_required || {
+ # 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
+ }
+
+ 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 yes = "$no_install"; 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
+
+ case $hardcode_action,$fast_install in
+ relink,*)
+ # 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"
+ ;;
+ *,yes)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+ ;;
+ *,no)
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+ ;;
+ *,needless)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=
+ ;;
+ esac
+
+ # 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
+
+ case $build_libtool_libs in
+ convenience)
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs=$convenience
+ build_libtool_libs=no
+ ;;
+ module)
+ oldobjs=$libobjs_save
+ addlibs=$old_convenience
+ build_libtool_libs=no
+ ;;
+ *)
+ oldobjs="$old_deplibs $non_pic_objects"
+ $preload && test -f "$symfileobj" \
+ && func_append oldobjs " $symfileobj"
+ addlibs=$old_convenience
+ ;;
+ esac
+
+ 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 yes = "$build_libtool_libs"; 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 -z "$oldobjs"; 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 yes = "$build_old_libs" && 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 yes = "$hardcode_automatic"; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test yes = "$installed"; 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 -n "$bindir"; 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) $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 cannot 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 no,yes = "$installed,$need_relink"; 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
+}
+
+if test link = "$opt_mode" || test relink = "$opt_mode"; then
+ func_mode_link ${1+"$@"}
+fi
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $debug_cmd
+
+ RM=$nonopt
+ files=
+ rmforce=false
+ 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=: ;;
+ -*) 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 . = "$dir"; then
+ odir=$objdir
+ else
+ odir=$dir/$objdir
+ fi
+ func_basename "$file"
+ name=$func_basename_result
+ test uninstall = "$opt_mode" && odir=$dir
+
+ # Remember odir for removal later, being careful to avoid duplicates
+ if test clean = "$opt_mode"; 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 $rmforce; 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" '$rmforce || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" '$rmforce || 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 none != "$pic_object"; 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 none != "$non_pic_object"; then
+ func_append rmfiles " $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test clean = "$opt_mode"; 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 yes = "$fast_install" && 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
+}
+
+if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
+ func_mode_uninstall ${1+"$@"}
+fi
+
+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
+# where 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:
diff --git a/m4/ac_check_define.m4 b/m4/ac_check_define.m4
new file mode 100644
index 0000000..3ed922c
--- /dev/null
+++ b/m4/ac_check_define.m4
@@ -0,0 +1,42 @@
+AC_DEFUN([AC_CHECK_DEFINED],[
+AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl
+AC_CACHE_CHECK([for $1 defined], ac_var,
+AC_TRY_COMPILE(,[
+ #ifdef $1
+ int ok;
+ #else
+ choke me
+ #endif
+],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no)))
+AS_IF([test AS_VAR_GET(ac_var) != "no"], [$2], [$3])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])
+
+AC_DEFUN([AX_CHECK_DEFINED],[
+AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$2])dnl
+AC_CACHE_CHECK([for $2 defined], ac_var,
+AC_TRY_COMPILE($1,[
+ #ifdef $2
+ int ok;
+ #else
+ choke me
+ #endif
+],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no)))
+AS_IF([test AS_VAR_GET(ac_var) != "no"], [$3], [$4])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])
+
+AC_DEFUN([AX_CHECK_FUNC],
+[AS_VAR_PUSHDEF([ac_var], [ac_cv_func_$2])dnl
+AC_CACHE_CHECK([for $2], ac_var,
+dnl AC_LANG_FUNC_LINK_TRY
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([$1
+ #undef $2
+ char $2 ();],[
+ char (*f) () = $2;
+ return f != $2; ])],
+ [AS_VAR_SET(ac_var, yes)],
+ [AS_VAR_SET(ac_var, no)])])
+AS_IF([test AS_VAR_GET(ac_var) = yes], [$3], [$4])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])# AC_CHECK_FUNC
diff --git a/m4/atomic_operations.m4 b/m4/atomic_operations.m4
new file mode 100644
index 0000000..04186b8
--- /dev/null
+++ b/m4/atomic_operations.m4
@@ -0,0 +1,66 @@
+# rsyslog
+#
+# atomic_operations.m4 - autoconf macro to check if compiler supports atomic
+# operations
+#
+# rgerhards, 2008-09-18, added based on
+# http://svn.apache.org/repos/asf/apr/apr/trunk/configure.in
+#
+#
+AC_DEFUN([RS_ATOMIC_OPERATIONS],
+[AC_CACHE_CHECK([whether the compiler provides atomic builtins], [ap_cv_atomic_builtins],
+[AC_TRY_RUN([
+#include <sys/types.h>
+int main()
+{
+ unsigned long val = 1010, tmp, *mem = &val;
+ time_t tval = 1010, ttmp, *tmem = &tval;
+
+ if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+ return 1;
+ tmp = val;
+ if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+ return 1;
+ if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+ return 1;
+ tmp = 3030;
+ if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+ return 1;
+ if (__sync_lock_test_and_set(&val, 4040) != 3030)
+ return 1;
+ mem = &tmp;
+ if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+ return 1;
+
+ if (__sync_fetch_and_add(&tval, 1010) != 1010 || tval != 2020)
+ return 1;
+ ttmp = tval;
+ if (__sync_fetch_and_sub(tmem, 1010) != ttmp || tval != 1010)
+ return 1;
+ if (__sync_sub_and_fetch(&tval, 1010) != 0 || tval != 0)
+ return 1;
+ ttmp = 3030;
+ if (__sync_val_compare_and_swap(tmem, 0, ttmp) != 0 || tval != ttmp)
+ return 1;
+ if (__sync_lock_test_and_set(&tval, 4040) != 3030)
+ return 1;
+ tmem = &ttmp;
+ if (__sync_val_compare_and_swap(&tmem, &ttmp, &tval) != &ttmp)
+ return 1;
+
+ __sync_synchronize();
+
+ if (mem != &val)
+ return 1;
+
+ if (tmem != &tval)
+ return 1;
+
+ return 0;
+}], [ap_cv_atomic_builtins=yes], [ap_cv_atomic_builtins=no], [ap_cv_atomic_builtins=no])])
+
+if test "$ap_cv_atomic_builtins" = "yes"; then
+ AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, [Define if compiler provides atomic builtins])
+fi
+
+])
diff --git a/m4/atomic_operations_64bit.m4 b/m4/atomic_operations_64bit.m4
new file mode 100644
index 0000000..9fbef0a
--- /dev/null
+++ b/m4/atomic_operations_64bit.m4
@@ -0,0 +1,53 @@
+# rsyslog
+#
+# atomic_operations.m4 - autoconf macro to check if compiler supports atomic
+# operations
+#
+# rgerhards, 2008-09-18, added based on
+# http://svn.apache.org/repos/asf/apr/apr/trunk/configure.in
+#
+#
+AC_DEFUN([RS_ATOMIC_OPERATIONS_64BIT],
+[AC_CACHE_CHECK([whether the compiler provides atomic builtins for 64 bit data types], [ap_cv_atomic_builtins_64],
+[AC_TRY_RUN([
+int main()
+{
+ unsigned long long val = 1010, tmp, *mem = &val;
+
+ if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020)
+ return 1;
+
+ tmp = val;
+
+ if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010)
+ return 1;
+
+ if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0)
+ return 1;
+
+ tmp = 3030;
+
+ if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp)
+ return 1;
+
+ if (__sync_lock_test_and_set(&val, 4040) != 3030)
+ return 1;
+
+ mem = &tmp;
+
+ if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp)
+ return 1;
+
+ __sync_synchronize();
+
+ if (mem != &val)
+ return 1;
+
+ return 0;
+}], [ap_cv_atomic_builtins_64=yes], [ap_cv_atomic_builtins_64=no], [ap_cv_atomic_builtins_64=no])])
+
+if test "$ap_cv_atomic_builtins_64" = "yes"; then
+ AC_DEFINE(HAVE_ATOMIC_BUILTINS64, 1, [Define if compiler provides 64 bit atomic builtins])
+fi
+
+])
diff --git a/m4/libtool.m4 b/m4/libtool.m4
new file mode 100644
index 0000000..a6d21ae
--- /dev/null
+++ b/m4/libtool.m4
@@ -0,0 +1,8394 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996-2001, 2003-2015 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) 2014 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 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 this program. If not, see <http://www.gnu.org/licenses/>.
+])
+
+# serial 58 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.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+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_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in @S|@*""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _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
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that 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 set != "${COLLECT_NAMES+set}"; 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\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ 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\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ 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 0 = "$lt_write_fail" && 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 yes = "$silent" &&
+ 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 that 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
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_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 set != "${COLLECT_NAMES+set}"; 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)
+
+ 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'
+ 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 0 = "$_lt_result"; 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 cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+ $AR cr 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 0 = "$_lt_result" && $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 yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; 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 no = "$lt_cv_ld_force_load"; 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 yes = "$lt_cv_ld_force_load"; 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*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; 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 yes != "$lt_cv_apple_cc_single_mod"; 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 set = "${lt_cv_aix_libpath+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 that will find a shell with a builtin
+# printf (that 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],
+[AS_HELP_STRING([--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 yes = "$GCC"; 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 where 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 no = "$enable_libtool_lock" || 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 what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ 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 what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test yes = "$lt_cv_prog_gnu_ld"; 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*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ emul=elf
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ 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-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ 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-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ 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 yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ 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*|x86_64-*-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=cr}
+_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 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+ ])
+ ])
+
+if test no = "$lt_cv_ar_at_file"; 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
+ bitrig* | 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" ## exclude from sc_useless_quotes_in_assignment
+ # 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 yes = "[$]$2"; 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 yes = "[$]$2"; 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;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+ # 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 17 != "$i" # 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 yes = "$cross_compiling"; 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 -fvisibility=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 yes != "$enable_dlopen"; 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
+ ])
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ 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 no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && 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 yes = "$lt_cv_dlopen_self"; 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 no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; 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 no = "$hard_links"; 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 where 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 yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+ # 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 no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+ test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; 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 relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+ test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; 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_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x@S|@2 in
+ x)
+ ;;
+ *:)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+ ;;
+ x:*)
+ eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+ ;;
+ *)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _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
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test yes = "$GCC"; 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`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ 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"
+ elif test -n "$lt_multi_os_dir"; then
+ 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
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+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 ia64 = "$host_cpu"; 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
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # 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'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+ # 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'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ 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%'\''`; $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$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ 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=no
+ 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 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ 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 yes = "$lt_cv_prog_gnu_ld"; 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
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # 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
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+
+# 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
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) 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* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ 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
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ 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'
+ ;;
+
+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 yes = "$with_gnu_ld"; 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=sco
+ 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 yes = "$with_gnu_ld"; 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 no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_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], [configure_time_dlsearch_path], [2],
+ [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+ [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that 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 that 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 no = "$withval" || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; 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 yes = "$with_gnu_ld"; 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 no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && 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 yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; 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_PATH_DD
+# -----------
+# find a working dd
+m4_defun([_LT_PATH_DD],
+[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+ [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _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
+# that 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.
+ if ( 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* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; 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
+ ;;
+os2*)
+ 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
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ 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 no != "$lt_cv_path_NM"; 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 -headers /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ 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 one 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 yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+ test DEF = "`$SED -n dnl
+ -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
+ -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
+ -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
+ -e q dnl Only consider the first "real" line
+ $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# 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 yes = "$GCC"; 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 ia64 = "$host_cpu"; 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
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# 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"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$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"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/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,
+ # D for any global variable and I for any imported 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};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,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
+ $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
+ if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && 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 can'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* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$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 yes = "$pipe_works"; 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_import], [lt_cv_sys_global_symbol_to_import], [1],
+ [Transform the output of nm into a list of symbols to manually relocate])
+_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_interface], [lt_cv_nm_interface], [1],
+ [The name lister interface])
+_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 yes = "$GXX"; 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 ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ 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'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+ 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 ia64 = "$host_cpu"; 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 ia64 != "$host_cpu"; 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 yes = "$GCC"; 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 ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ 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'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ 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 ia64 = "$host_cpu"; 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
+ ;;
+
+ 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'
+ case $cc_basename in
+ 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'
+ ;;
+ esac
+ ;;
+
+ 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'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ 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'
+ ;;
+ # flang / f18. f95 an alias for gfortran or flang on Debian
+ flang* | f18* | f95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _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'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny 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)='-static'
+ ;;
+ 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 that 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 GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ 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) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 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 yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ 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 yes = "$with_gnu_ld"; 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 yes = "$lt_use_gnu_ld_interface"; 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 | $SED -e 's/([^)]\+)\s\+//' 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 ia64 != "$host_cpu"; 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, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $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 linux-dietlibc = "$host_os"; 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 no = "$tmp_diet"
+ 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' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-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 yes = "$supports_anon_versioning"; 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
+ tcc*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+ ;;
+ 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 yes = "$supports_anon_versioning"; 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 cannot
+*** 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 no = "$_LT_TAGVAR(ld_shlibs, $1)"; 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 yes = "$GCC" && 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 ia64 = "$host_cpu"; 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 GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ 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) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 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
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ 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,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ 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,yes = "$with_aix_soname,$aix_use_runtimelinking"; 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 -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; 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 yes = "$with_gnu_ld"; 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
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ 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,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $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 yes = "$GCC"; 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 "x$output_objdir/$soname" = "x$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 "x$output_objdir/$soname" = "x$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 yes,no = "$GCC,$with_gnu_ld"; 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 no = "$with_gnu_ld"; 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 yes,no = "$GCC,$with_gnu_ld"; 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 no = "$with_gnu_ld"; 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 yes = "$GCC"; 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 yes = "$lt_cv_irix_exported_symbol"; 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
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ 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
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ 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* | bitrig*)
+ 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__`"; 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
+ _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'
+ 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
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 sequent = "$host_vendor"; 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 yes = "$GCC"; 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 CANNOT 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 yes = "$GCC"; 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 sni = "$host_vendor"; 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 no = "$_LT_TAGVAR(ld_shlibs, $1)" && 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 yes,yes = "$GCC,$enable_shared"; 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 what 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ 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 yes = "$enable_shared" || 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 no != "$CXX" &&
+ ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+ (test g++ != "$CXX"))); 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 yes != "$_lt_caught_CXX_error"; 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 yes = "$GXX"; 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 yes = "$GXX"; 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 yes = "$with_gnu_ld"; 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 ia64 = "$host_cpu"; 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
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ 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
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ 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,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GXX"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag=$shared_flag' $wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ 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,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ # The "-G" linker flag allows undefined symbols.
+ _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+ # 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 -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; 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 yes = "$with_gnu_ld"; 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
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared
+ # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ 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,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $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, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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)
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ 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 "x$output_objdir/$soname" = "x$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 yes = "$GXX"; 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 "x$output_objdir/$soname" = "x$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 no = "$with_gnu_ld"; 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 yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; 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 yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; 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 yes = "$supports_anon_versioning"; 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
+ ;;
+
+ openbsd* | bitrig*)
+ 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__`"; 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 yes,no = "$GXX,$with_gnu_ld"; 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 yes,no = "$GXX,$with_gnu_ld"; 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 $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 $wl-h $wl$soname -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 $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 $wl-h $wl$soname -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 CANNOT 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 no = "$_LT_TAGVAR(ld_shlibs, $1)" && 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 yes != "$_lt_caught_CXX_error"
+
+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 @S|@2 in
+ .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+ *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@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 x-L = "$p" ||
+ test x-R = "$p"; 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 no = "$pre_test_object_deps_done"; 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 no = "$pre_test_object_deps_done"; 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)=
+ ;;
+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 no = "$F77"; 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 yes != "$_lt_disable_F77"; 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ 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 yes = "$enable_shared" || 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 yes != "$_lt_disable_F77"
+
+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 no = "$FC"; 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 yes != "$_lt_disable_FC"; 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ 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 yes = "$enable_shared" || 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 yes != "$_lt_disable_FC"
+
+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 set = "${GCJFLAGS+set}" || 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 10 -lt "$lt_ac_count" && 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],
+[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_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what 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/m4/ltoptions.m4 b/m4/ltoptions.m4
new file mode 100644
index 0000000..94b0829
--- /dev/null
+++ b/m4/ltoptions.m4
@@ -0,0 +1,437 @@
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004-2005, 2007-2009, 2011-2015 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 8 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_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+ [_LT_WITH_AIX_SONAME([aix])])
+ ])
+])# _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_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+ AC_MSG_CHECKING([which variant of shared library versioning to provide])
+ AC_ARG_WITH([aix-soname],
+ [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+ [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+ [case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname],
+ [AC_CACHE_VAL([lt_cv_with_aix_soname],
+ [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+ with_aix_soname=$lt_cv_with_aix_soname])
+ AC_MSG_RESULT([$with_aix_soname])
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+ [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _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=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/m4/ltsugar.m4 b/m4/ltsugar.m4
new file mode 100644
index 0000000..48bc934
--- /dev/null
+++ b/m4/ltsugar.m4
@@ -0,0 +1,124 @@
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2015 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/m4/ltversion.m4 b/m4/ltversion.m4
new file mode 100644
index 0000000..fa04b52
--- /dev/null
+++ b/m4/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2011-2015 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 4179 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.6])
+m4_define([LT_PACKAGE_REVISION], [2.4.6])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.6'
+macro_revision='2.4.6'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
new file mode 100644
index 0000000..c6b26f8
--- /dev/null
+++ b/m4/lt~obsolete.m4
@@ -0,0 +1,99 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 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/missing b/missing
new file mode 100755
index 0000000..625aeb1
--- /dev/null
+++ b/missing
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2018 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 <https://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=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://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 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/outchannel.c b/outchannel.c
new file mode 100644
index 0000000..2f456b5
--- /dev/null
+++ b/outchannel.c
@@ -0,0 +1,303 @@
+/* This is the output channel processing code of rsyslog.
+ * Output channels - in the long term - will define how
+ * messages will be sent to whatever file or other medium.
+ * Currently, they mainly provide a way to store some file-related
+ * information (most importantly the maximum file size allowed).
+ * Please see syslogd.c for license information.
+ * begun 2005-06-21 rgerhards
+ *
+ * Copyright (C) 2005-2016 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "stringbuf.h"
+#include "outchannel.h"
+#include "rsconf.h"
+#include "debug.h"
+
+/* Constructs a outchannel list object. Returns pointer to it
+ * or NULL (if it fails).
+ */
+struct outchannel* ochConstruct(void)
+{
+ struct outchannel *pOch;
+ if((pOch = calloc(1, sizeof(struct outchannel))) == NULL)
+ return NULL;
+
+ /* basic initialisaion is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(loadConf->och.ochLast == NULL)
+ { /* we are the first element! */
+ loadConf->och.ochRoot = loadConf->och.ochLast = pOch;
+ }
+ else
+ {
+ loadConf->och.ochLast->pNext = pOch;
+ loadConf->och.ochLast = pOch;
+ }
+
+ return(pOch);
+}
+
+
+/* skips the next comma and any whitespace
+ * in front and after it.
+ */
+static void skip_Comma(char **pp)
+{
+ register char *p;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ p = *pp;
+ while(isspace((int)*p))
+ ++p;
+ if(*p == ',')
+ ++p;
+ while(isspace((int)*p))
+ ++p;
+ *pp = p;
+}
+
+/* helper to ochAddLine. Parses a comma-delimited field
+ * The field is delimited by SP or comma. Leading whitespace
+ * is "eaten" and does not become part of the field content.
+ */
+static rsRetVal get_Field(uchar **pp, uchar **pField)
+{
+ DEFiRet;
+ register uchar *p;
+ cstr_t *pStrB = NULL;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pField != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ CHKiRet(cstrConstruct(&pStrB));
+
+ /* copy the field */
+ while(*p && *p != ' ' && *p != ',') {
+ CHKiRet(cstrAppendChar(pStrB, *p++));
+ }
+
+ *pp = p;
+ cstrFinalize(pStrB);
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pField, 0));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
+
+ RETiRet;
+}
+
+
+/* helper to ochAddLine. Parses a off_t type from the
+ * input line.
+ * returns: 0 - ok, 1 - failure
+ */
+static int get_off_t(uchar **pp, off_t *pOff_t)
+{
+ register uchar *p;
+ off_t val;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pOff_t != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ val = 0;
+ while(*p && isdigit((int)*p)) {
+ val = val * 10 + (*p - '0');
+ ++p;
+ }
+
+ *pp = p;
+ *pOff_t = val;
+
+ return 0;
+}
+
+
+/* helper to ochAddLine. Parses everything from the
+ * current position to the end of line and returns it
+ * to the caller. Leading white space is removed, but
+ * not trailing.
+ */
+static rsRetVal get_restOfLine(uchar **pp, uchar **pBuf)
+{
+ DEFiRet;
+ register uchar *p;
+ cstr_t *pStrB = NULL;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pBuf != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ CHKiRet(cstrConstruct(&pStrB));
+
+ /* copy the field */
+ while(*p) {
+ CHKiRet(cstrAppendChar(pStrB, *p++));
+ }
+
+ *pp = p;
+ cstrFinalize(pStrB);
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pBuf, 0));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
+
+ RETiRet;
+}
+
+
+/* Add a new outchannel line
+ * returns pointer to new object if it succeeds, NULL otherwise.
+ * An outchannel line is primarily a set of fields delemited by commas.
+ * There might be some whitespace between the field (but not within)
+ * and the commas. This can be removed.
+ */
+struct outchannel *ochAddLine(char* pName, uchar** ppRestOfConfLine)
+{
+ struct outchannel *pOch;
+ uchar *p;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+
+ if((pOch = ochConstruct()) == NULL)
+ return NULL;
+
+ pOch->iLenName = strlen(pName);
+ pOch->pszName = (char*) malloc(pOch->iLenName + 1);
+ if(pOch->pszName == NULL) {
+ dbgprintf("ochAddLine could not alloc memory for outchannel name!");
+ pOch->iLenName = 0;
+ return NULL;
+ /* I know - we create a memory leak here - but I deem
+ * it acceptable as it is a) a very small leak b) very
+ * unlikely to happen. rgerhards 2004-11-17
+ */
+ }
+ memcpy(pOch->pszName, pName, pOch->iLenName + 1);
+
+ /* now actually parse the line */
+ p = *ppRestOfConfLine;
+ assert(p != NULL);
+
+ /* get params */
+ get_Field(&p, &pOch->pszFileTemplate);
+ if(*p) get_off_t(&p, &pOch->uSizeLimit);
+ if(*p) get_restOfLine(&p, &pOch->cmdOnSizeLimit);
+
+ *ppRestOfConfLine = p;
+ return(pOch);
+}
+
+
+/* Find a outchannel object based on name. Search
+ * currently is case-sensitive (should we change?).
+ * returns pointer to outchannel object if found and
+ * NULL otherwise.
+ * rgerhards 2004-11-17
+ */
+struct outchannel *ochFind(char *pName, int iLenName)
+{
+ struct outchannel *pOch;
+
+ assert(pName != NULL);
+
+ pOch = loadConf->och.ochRoot;
+ while(pOch != NULL &&
+ !(pOch->iLenName == iLenName &&
+ !strcmp(pOch->pszName, pName)
+ ))
+ {
+ pOch = pOch->pNext;
+ }
+ return(pOch);
+}
+
+/* Destroy the outchannel structure. This is for de-initialization
+ * at program end. Everything is deleted.
+ * rgerhards 2005-02-22
+ */
+void ochDeleteAll(void)
+{
+ struct outchannel *pOch, *pOchDel;
+
+ pOch = runConf->och.ochRoot;
+ while(pOch != NULL) {
+ dbgprintf("Delete Outchannel: Name='%s'\n ", pOch->pszName == NULL? "NULL" : pOch->pszName);
+ pOchDel = pOch;
+ pOch = pOch->pNext;
+ if(pOchDel->pszName != NULL)
+ free(pOchDel->pszName);
+ if(pOchDel->pszFileTemplate != NULL)
+ free(pOchDel->pszFileTemplate);
+ if(pOchDel->cmdOnSizeLimit != NULL)
+ free(pOchDel->cmdOnSizeLimit);
+ free(pOchDel);
+ }
+}
+
+
+/* Print the outchannel structure. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ */
+void ochPrintList(rsconf_t *cnf)
+{
+ struct outchannel *pOch;
+
+ pOch = cnf->och.ochRoot;
+ while(pOch != NULL) {
+ dbgprintf("Outchannel: Name='%s'\n", pOch->pszName == NULL? "NULL" : pOch->pszName);
+ dbgprintf("\tFile Template: '%s'\n", pOch->pszFileTemplate == NULL ? "NULL" :
+ (char*) pOch->pszFileTemplate);
+ dbgprintf("\tMax Size.....: %lu\n", (long unsigned) pOch->uSizeLimit);
+ dbgprintf("\tOnSizeLimtCmd: '%s'\n", pOch->cmdOnSizeLimit == NULL ? "NULL" :
+ (char*) pOch->cmdOnSizeLimit);
+ pOch = pOch->pNext; /* done, go next */
+ }
+}
+/* vi:set ai:
+ */
diff --git a/outchannel.h b/outchannel.h
new file mode 100644
index 0000000..23699f7
--- /dev/null
+++ b/outchannel.h
@@ -0,0 +1,38 @@
+/* This is the header for the output channel code of rsyslog.
+ * begun 2005-06-21 rgerhards
+ *
+ * Copyright(C) 2005-2012 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OUTCHANNEL_H
+#define OUTCHANNEL_H
+struct outchannel {
+ struct outchannel *pNext;
+ char *pszName;
+ int iLenName;
+ uchar *pszFileTemplate;
+ off_t uSizeLimit;
+ uchar *cmdOnSizeLimit;
+};
+
+struct outchannel* ochConstruct(void);
+struct outchannel *ochAddLine(char* pName, unsigned char** pRestOfConfLine);
+struct outchannel *ochFind(char *pName, int iLenName);
+void ochDeleteAll(void);
+void ochPrintList(rsconf_t *cnf);
+#endif /* #ifdef OUTCHANNEL_H */
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..520c7c4
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,567 @@
+/* parsing routines for the counted string class. for generic
+ * informaton see parse.h.
+ *
+ * begun 2005-09-15 rgerhards
+ *
+ * Copyright 2005-2017 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include "rsyslog.h"
+#include "net.h" /* struct NetAddr */
+#include "parse.h"
+#include "debug.h"
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+
+/**
+ * Destruct a rsPars object and its associated string.
+ * rgerhards, 2005-09-26
+ */
+rsRetVal rsParsDestruct(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if(pThis->pCStr != NULL)
+ rsCStrDestruct(&pThis->pCStr);
+ RSFREEOBJ(pThis);
+ return RS_RET_OK;
+}
+
+
+/**
+ * Construct a rsPars object.
+ */
+rsRetVal rsParsConstruct(rsParsObj **ppThis)
+{
+ rsParsObj *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (rsParsObj*) calloc(1, sizeof(rsParsObj))) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ rsSETOBJTYPE(pThis, OIDrsPars);
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+/**
+ * Construct a rsPars object and populate it with a
+ * classical zero-terinated C-String.
+ * rgerhards, 2005-09-27
+ */
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz)
+{
+ DEFiRet;
+ rsParsObj *pThis;
+ cstr_t *pCS;
+
+ assert(ppThis != NULL);
+ assert(psz != NULL);
+
+ /* create string for parser */
+ CHKiRet(rsCStrConstructFromszStr(&pCS, psz));
+
+ /* create parser */
+ if((iRet = rsParsConstruct(&pThis)) != RS_RET_OK) {
+ rsCStrDestruct(&pCS);
+ FINALIZE;
+ }
+
+ /* assign string to parser */
+ if((iRet = rsParsAssignString(pThis, pCS)) != RS_RET_OK) {
+ rsParsDestruct(pThis);
+ FINALIZE;
+ }
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+/**
+ * Assign the to-be-parsed string.
+ */
+rsRetVal rsParsAssignString(rsParsObj *pThis, cstr_t *pCStr)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ rsCHECKVALIDOBJECT(pCStr, OIDrsCStr);
+
+ pThis->pCStr = pCStr;
+ pThis->iCurrPos = 0;
+
+ return RS_RET_OK;
+}
+
+/* parse an integer. The parse pointer is advanced to the
+ * position directly after the last digit. If no digit is
+ * found at all, an error is returned and the parse pointer
+ * is NOT advanced.
+ * PORTABILITY WARNING: this function depends on the
+ * continues representation of digits inside the character
+ * set (as in ASCII).
+ * rgerhards 2005-09-27
+ */
+rsRetVal parsInt(rsParsObj *pThis, int* pInt)
+{
+ unsigned char *pC;
+ int iVal;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pInt != NULL);
+
+ iVal = 0;
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* order of checks is important, else we might do
+ * mis-addressing! (off by one)
+ */
+ if(pThis->iCurrPos >= rsCStrLen(pThis->pCStr))
+ return RS_RET_NO_MORE_DATA;
+ if(!isdigit((int)*pC))
+ return RS_RET_NO_DIGIT;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && isdigit((int)*pC)) {
+ iVal = iVal * 10 + *pC - '0';
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ *pInt = iVal;
+
+ return RS_RET_OK;
+}
+
+/* Skip everything up to a specified character.
+ * Returns with ParsePointer set BEHIND this character.
+ * Returns RS_RET_OK if found, RS_RET_NOT_FOUND if not
+ * found. In that case, the ParsePointer is moved to the
+ * last character of the string.
+ * 2005-09-19 rgerhards
+ */
+rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c)
+{
+ register unsigned char *pC;
+ DEFiRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr);
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ if(pC[pThis->iCurrPos] == c)
+ break;
+ ++pThis->iCurrPos;
+ }
+
+ /* delimiter found? */
+ if(pC[pThis->iCurrPos] == c) {
+ if(pThis->iCurrPos+1 < rsCStrLen(pThis->pCStr)) {
+ iRet = RS_RET_OK;
+ pThis->iCurrPos++; /* 'eat' delimiter */
+ } else {
+ iRet = RS_RET_FOUND_AT_STRING_END;
+ }
+ } else {
+ iRet = RS_RET_NOT_FOUND;
+ }
+
+ RETiRet;
+}
+
+/* Skip whitespace. Often used to trim parsable entries.
+ * Returns with ParsePointer set to first non-whitespace
+ * character (or at end of string).
+ * If bRequireOne is set to true, at least one whitespace
+ * must exist, else an error is returned.
+ */
+rsRetVal parsSkipWhitespace(rsParsObj *pThis)
+{
+ register unsigned char *pC;
+ int numSkipped;
+ DEFiRet;
+
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr);
+
+ numSkipped = 0;
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ if(!isspace((int)*(pC+pThis->iCurrPos)))
+ break;
+ ++pThis->iCurrPos;
+ ++numSkipped;
+ }
+
+ RETiRet;
+}
+
+/* Parse string up to a delimiter.
+ *
+ * Input:
+ * cDelim - the delimiter. Note that SP within a value always is a delimiter,
+ * so cDelim is actually an *additional* delimiter.
+ * The following two are for whitespace stripping,
+ * 0 means "no", 1 "yes"
+ * - bTrimLeading
+ * - bTrimTrailing
+ * - bConvLower - convert string to lower case?
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string - must be freed by caller!
+ */
+rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing,
+ int bConvLower)
+{
+ DEFiRet;
+ register unsigned char *pC;
+ cstr_t *pCStr = NULL;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ CHKiRet(rsCStrConstruct(&pCStr));
+
+ if(bTrimLeading)
+ parsSkipWhitespace(pThis);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) {
+ CHKiRet(cstrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC));
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ if(pThis->iCurrPos < cstrLen(pThis->pCStr)) { //BUGFIX!!
+ ++pThis->iCurrPos; /* eat delimiter */
+ }
+
+ /* We got the string, now take it and see if we need to
+ * remove anything at its end.
+ */
+ cstrFinalize(pCStr);
+
+ if(bTrimTrailing) {
+ cstrTrimTrailingWhiteSpace(pCStr);
+ }
+
+ /* done! */
+ *ppCStr = pCStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pCStr != NULL)
+ rsCStrDestruct(&pCStr);
+ }
+
+ RETiRet;
+}
+
+/* Parse a quoted string ("-some-data") from the given position.
+ * Leading whitespace before the first quote is skipped. During
+ * parsing, escape sequences are detected and converted:
+ * \\ - backslash character
+ * \" - quote character
+ * any other value \<somechar> is reserved for future use.
+ *
+ * After return, the parse pointer is paced after the trailing
+ * quote.
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string - must be freed by caller and
+ * does NOT include the quotes.
+ * rgerhards, 2005-09-19
+ */
+rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr)
+{
+ register unsigned char *pC;
+ cstr_t *pCStr = NULL;
+ DEFiRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ CHKiRet(parsSkipAfterChar(pThis, '"'));
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* OK, we most probably can obtain a value... */
+ CHKiRet(cstrConstruct(&pCStr));
+
+ while(pThis->iCurrPos < cstrLen(pThis->pCStr)) {
+ if(*pC == '"') {
+ break; /* we are done! */
+ } else if(*pC == '\\') {
+ ++pThis->iCurrPos;
+ ++pC;
+ if(pThis->iCurrPos < cstrLen(pThis->pCStr)) {
+ /* in this case, we copy the escaped character
+ * to the output buffer (but do not rely on this,
+ * we might later introduce other things, like \007!
+ */
+ CHKiRet(cstrAppendChar(pCStr, *pC));
+ }
+ } else { /* regular character */
+ CHKiRet(cstrAppendChar(pCStr, *pC));
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ if(*pC == '"') {
+ ++pThis->iCurrPos; /* 'eat' trailing quote */
+ } else {
+ /* error - improperly quoted string! */
+ cstrDestruct(&pCStr);
+ ABORT_FINALIZE(RS_RET_MISSING_TRAIL_QUOTE);
+ }
+
+ cstrFinalize(pCStr);
+
+ /* done! */
+ *ppCStr = pCStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pCStr != NULL)
+ cstrDestruct(&pCStr);
+ }
+
+ RETiRet;
+}
+
+/*
+ * Parsing routine for IPv4, IPv6 and domain name wildcards.
+ *
+ * Parses string in the format <addr>[/bits] where
+ * addr can be a IPv4 address (e.g.: 127.0.0.1), IPv6 address (e.g.: [::1]),
+ * full hostname (e.g.: localhost.localdomain) or hostname wildcard
+ * (e.g.: *.localdomain).
+ */
+rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits)
+{
+ register uchar *pC;
+ uchar *pszIP = NULL;
+ uchar *pszTmp;
+ struct addrinfo hints, *res = NULL;
+ cstr_t *pCStr;
+ DEFiRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pIP != NULL);
+ assert(pBits != NULL);
+
+ CHKiRet(cstrConstruct(&pCStr));
+
+ parsSkipWhitespace(pThis);
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* we parse everything until either '/', ',' or
+ * whitespace. Validity will be checked down below.
+ */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && *pC != '/' && *pC != ',' && !isspace((int)*pC)) {
+ if((iRet = cstrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ cstrDestruct (&pCStr);
+ FINALIZE;
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ cstrFinalize(pCStr);
+
+ /* now we have the string and must check/convert it to
+ * an NetAddr structure.
+ */
+ CHKiRet(cstrConvSzStrAndDestruct(&pCStr, &pszIP, 0));
+
+ if((*pIP = calloc(1, sizeof(struct NetAddr))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ if (*((char*)pszIP) == '[') {
+ pszTmp = (uchar*)strchr ((char*)pszIP, ']');
+ if (pszTmp == NULL) {
+ free (*pIP);
+ ABORT_FINALIZE(RS_RET_INVALID_IP);
+ }
+ *pszTmp = '\0';
+
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ switch(getaddrinfo ((char*)pszIP+1, NULL, &hints, &res)) {
+ case 0:
+ (*pIP)->addr.NetAddr = malloc (res->ai_addrlen);
+ memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo (res);
+ break;
+ case EAI_NONAME:
+ /* The "address" is not an IP prefix but a wildcard */
+ F_SET((*pIP)->flags, ADDR_NAME|ADDR_PRI6);
+ (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP+1);
+ break;
+ default:
+ free (*pIP);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(*pC == '/') {
+ /* mask bits follow, let's parse them! */
+ ++pThis->iCurrPos; /* eat slash */
+ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
+ free((*pIP)->addr.NetAddr);
+ free((*pIP)->addr.HostWildcard);
+ free (*pIP);
+ FINALIZE;
+ }
+ /* we need to refresh pointer (changed by parsInt()) */
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+ } else {
+ /* no slash, so we assume a single host (/128) */
+ *pBits = 128;
+ }
+ } else { /* now parse IPv4 */
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ switch(getaddrinfo ((char*)pszIP, NULL, &hints, &res)) {
+ case 0:
+ (*pIP)->addr.NetAddr = malloc (res->ai_addrlen);
+ memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo (res);
+ break;
+ case EAI_NONAME:
+ /* The "address" is not an IP prefix but a wildcard */
+ F_SET((*pIP)->flags, ADDR_NAME);
+ (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP);
+ break;
+ default:
+ free (*pIP);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(*pC == '/') {
+ /* mask bits follow, let's parse them! */
+ ++pThis->iCurrPos; /* eat slash */
+ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
+ free((*pIP)->addr.NetAddr);
+ free((*pIP)->addr.HostWildcard);
+ free (*pIP);
+ FINALIZE;
+ }
+ /* we need to refresh pointer (changed by parsInt()) */
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+ } else {
+ /* no slash, so we assume a single host (/32) */
+ *pBits = 32;
+ }
+ }
+
+ /* skip to next processable character */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && (*pC == ',' || isspace((int)*pC))) {
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ iRet = RS_RET_OK;
+
+finalize_it:
+ free(pszIP);
+ RETiRet;
+}
+
+
+/* tell if the parsepointer is at the end of the
+ * to-be-parsed string. Returns 1, if so, 0
+ * otherwise. rgerhards, 2005-09-27
+ */
+int parsIsAtEndOfParseString(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ return (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) ? 0 : 1;
+}
+
+
+/* return the position of the parse pointer
+ */
+int rsParsGetParsePointer(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if(pThis->iCurrPos < rsCStrLen(pThis->pCStr))
+ return pThis->iCurrPos;
+ else
+ return rsCStrLen(pThis->pCStr) - 1;
+}
+
+/* peek at the character at the parse pointer
+ * the caller must ensure that the parse pointer is not
+ * at the end of the parse buffer (e.g. by first calling
+ * parsIsAtEndOfParseString).
+ * rgerhards, 2005-09-27
+ */
+char parsPeekAtCharAtParsPtr(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pThis->iCurrPos < rsCStrLen(pThis->pCStr));
+
+ return(*(pThis->pCStr->pBuf + pThis->iCurrPos));
+}
+
+/* return the current position inside the parse object.
+ * rgerhards, 2007-07-04
+ */
+int parsGetCurrentPosition(rsParsObj *pThis)
+{
+ return pThis->iCurrPos;
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/parse.h b/parse.h
new file mode 100644
index 0000000..b8c8422
--- /dev/null
+++ b/parse.h
@@ -0,0 +1,105 @@
+/* parsing routines for the counted string class. These
+ * routines provide generic parsing aid as well some fairly
+ * complex routines targeted toward specific needs.
+ *
+ * General information - read this:
+ * All routines work on a single CStr object, which must be supplied
+ * during construction. The parse class keeps an internal pointer of
+ * where the next parse operation is to start (you could also say
+ * this is where the last parse operation stopped).
+ *
+ * Each parse operation carried out by this package starts from the
+ * parse pointer, parses the caller-requested element (e.g. an
+ * integer or delemited string) and the update the parse pointer. If
+ * the caller tries to parse beyond the end of the original string,
+ * an error is returned. In general, all functions return a parsRet
+ * error code and all require the parseObj to be the first parameter.
+ * The to-be-parsed string provided to the parse object MUST NOT be
+ * freed or modified by the caller during the lifetime of the parse
+ * object. However, the caller must free it when it is no longer needed.
+ * Optinally, the parse object can be instructed to do that. All objects
+ * returned by the parse routines must be freed by the caller. For
+ * simpler data types (like integers), the caller must provide the
+ * necessary buffer space.
+ *
+ * begun 2005-09-09 rgerhards
+ *
+ * Copyright (C) 2005-2012 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _PARSE_H_INCLUDED__
+#define _PARSE_H_INCLUDED__ 1
+
+#include "stringbuf.h"
+
+/**
+ * The parse object
+ */
+struct rsParsObject
+{
+#ifndef NDEBUG
+ rsObjID OID; /**< object ID */
+#endif
+ cstr_t *pCStr; /**< pointer to the string object we are parsing */
+ size_t iCurrPos; /**< current parsing position (char offset) */
+};
+typedef struct rsParsObject rsParsObj;
+
+
+/* BEGIN "inline"-like functions */
+/* END "inline"-like functions */
+
+int rsParsGetParsePointer(rsParsObj *pThis);
+
+/**
+ * Construct a rsPars object.
+ */
+rsRetVal rsParsConstruct(rsParsObj **ppThis);
+rsRetVal rsParsAssignString(rsParsObj *pThis, cstr_t *pCStr);
+
+/* parse an integer. The parse pointer is advanced */
+rsRetVal parsInt(rsParsObj *pThis, int* pInt);
+
+/* Skip whitespace. Often used to trim parsable entries. */
+rsRetVal parsSkipWhitespace(rsParsObj *pThis);
+
+/* Parse string up to a delimiter.
+ *
+ * Input:
+ * cDelim - the delimiter
+ * The following two are for whitespace stripping,
+ * 0 means "no", 1 "yes"
+ * - bTrimLeading
+ * - bTrimTrailing
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string
+ */
+rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading,
+int bTrimTrailing, int bConvLower);
+
+rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c);
+rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr);
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz);
+rsRetVal rsParsDestruct(rsParsObj *pThis);
+int parsIsAtEndOfParseString(rsParsObj *pThis);
+int parsGetCurrentPosition(rsParsObj *pThis);
+char parsPeekAtCharAtParsPtr(rsParsObj *pThis);
+rsRetVal parsAddrWithBits(rsParsObj *pThis, netAddr_t **pIP, int *pBits);
+
+#endif
diff --git a/platform/README b/platform/README
new file mode 100644
index 0000000..2abd8c6
--- /dev/null
+++ b/platform/README
@@ -0,0 +1,7 @@
+This subdirectory contains platform-specific files. They are maintained
+based on a best effort basis, and are not necessarily the same like the
+specific platform ships them. Some files are changed in the way the
+rsyslog projects would recommend them; some may even be outdated.
+
+Use this with care. If in doubt, please have a look at the official
+distro repos. They obviously have the gold standard for each distro.
diff --git a/platform/freebsd/rsyslogd b/platform/freebsd/rsyslogd
new file mode 100755
index 0000000..1cbcb6f
--- /dev/null
+++ b/platform/freebsd/rsyslogd
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Sample startup script for rsyslogd on FreeBSD.
+# It worked on my machine, but this does not necessarily
+# mean it works on all machines - it's not thouroughly
+# tested. Please note that it may also work on other
+# BSD variants, too.
+#
+# As of this writing, there was an issue with the mysql client
+# library on startup. If compiled with MySQL support, rsyslogd
+# would not necessarily start correctly but could eventually
+# die with a "mysql client libary not found" (or similar)
+# message. I do not know its cause neither the cure. If you
+# have one, let me know.
+#
+# ATTENTION: you need also to change the /etc/rc.config file
+# and disable stock syslogd and then enable rsyslogd!
+#
+# rgerhards 2005-08-09 <rgehards@adiscon.com>
+#
+
+# PROVIDE: rsyslogd
+# REQUIRE: mountcritremote cleanvar
+# BEFORE: SERVERS
+
+. /etc/rc.subr
+
+name="rsyslogd"
+rcvar=`set_rcvar`
+pidfile="/var/run/rsyslogd.pid"
+command="/usr/sbin/${name}"
+required_files="/etc/rsyslog.conf"
+start_precmd="rsyslogd_precmd"
+extra_commands="reload"
+
+_sockfile="/var/run/rsyslogd.sockets"
+evalargs="rc_flags=\"\`set_socketlist\` \$rc_flags\""
+altlog_proglist="named"
+
+rsyslogd_precmd()
+{
+ # Transitional symlink for old binaries
+ #
+ if [ ! -L /dev/log ]; then
+ ln -sf /var/run/log /dev/log
+ fi
+ rm -f /var/run/log
+
+ # Create default list of syslog sockets to watch
+ #
+ ( umask 022 ; > $_sockfile )
+
+ # If running named(8) or ntpd(8) chrooted, added appropriate
+ # syslog socket to list of sockets to watch.
+ #
+ for _l in $altlog_proglist; do
+ eval _ldir=\$${_l}_chrootdir
+ if checkyesno `set_rcvar $_l` && [ -n "$_ldir" ]; then
+ echo "${_ldir}/var/run/log" >> $_sockfile
+ fi
+ done
+
+ # If other sockets have been provided, change run_rc_command()'s
+ # internal copy of $rsyslogd_flags to force use of specific
+ # rsyslogd sockets.
+ #
+ if [ -s $_sockfile ]; then
+ echo "/var/run/log" >> $_sockfile
+ eval $evalargs
+ fi
+
+ return 0
+}
+
+set_socketlist()
+{
+ _socketargs=
+ for _s in `cat $_sockfile | tr '\n' ' '` ; do
+ _socketargs="-l $_s $_socketargs"
+ done
+ echo $_socketargs
+}
+load_rc_config $name
+run_rc_command "$1"
diff --git a/platform/redhat/rsyslog.conf b/platform/redhat/rsyslog.conf
new file mode 100644
index 0000000..8707713
--- /dev/null
+++ b/platform/redhat/rsyslog.conf
@@ -0,0 +1,87 @@
+# rsyslog configuration file (for Red Hat-based systems)
+# note that most of this config file uses old-style format,
+# because it is well-known AND quite suitable for simple cases
+# like we have with the default config. For more advanced
+# things, RainerScript configuration is suggested.
+#
+# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html
+# or latest version online at https://www.rsyslog.com/doc/rsyslog_conf.html
+# If you experience problems, see https://www.rsyslog.com/doc/troubleshoot.html
+
+#### MODULES ####
+
+module(load="imuxsock") # provides support for local system logging (e.g. via logger command)
+module(load="imklog") # provides kernel logging support (previously done by rklogd)
+#module(load"immark") # provides --MARK-- message capability
+
+# Provides UDP syslog reception
+# for parameters see https://www.rsyslog.com/doc/imudp.html
+#module(load="imudp") # needs to be done just once
+#input(type="imudp" port="514")
+
+# Provides TCP syslog reception
+# for parameters see https://www.rsyslog.com/doc/imtcp.html
+#module(load="imtcp") # needs to be done just once
+#input(type="imtcp" port="514")
+
+
+#### GLOBAL DIRECTIVES ####
+
+# Use default timestamp format
+$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
+
+# File syncing capability is disabled by default. This feature is usually not required,
+# not useful and an extreme performance hit
+#$ActionFileEnableSync on
+
+# Include all config files in /etc/rsyslog.d/
+$IncludeConfig /etc/rsyslog.d/*.conf
+
+
+#### RULES ####
+
+# Log all kernel messages to the console.
+# Logging much else clutters up the screen.
+#kern.* /dev/console
+
+# Log anything (except mail) of level info or higher.
+# Don't log private authentication messages!
+*.info;mail.none;authpriv.none;cron.none /var/log/messages
+
+# The authpriv file has restricted access.
+authpriv.* /var/log/secure
+
+# Log all the mail messages in one place.
+mail.* /var/log/maillog
+
+
+# Log cron stuff
+cron.* /var/log/cron
+
+# Everybody gets emergency messages
+*.emerg :omusrmsg:*
+
+# Save news errors of level crit and higher in a special file.
+uucp,news.crit /var/log/spooler
+
+# Save boot messages also to boot.log
+local7.* /var/log/boot.log
+
+
+# ### begin forwarding rule ###
+# The statement between the begin ... end define a SINGLE forwarding
+# rule. They belong together, do NOT split them. If you create multiple
+# forwarding rules, duplicate the whole block!
+# Remote Logging (we use TCP for reliable delivery)
+#
+# An on-disk queue is created for this action. If the remote host is
+# down, messages are spooled to disk and sent when it is up again.
+#$WorkDirectory /var/lib/rsyslog # where to place spool files
+#$ActionQueueFileName fwdRule1 # unique name prefix for spool files
+#$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
+#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
+#$ActionQueueType LinkedList # run asynchronously
+#$ActionResumeRetryCount -1 # infinite retries if host is down
+# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
+#*.* @@remote-host:514
+# ### end of the forwarding rule ###
diff --git a/platform/slackware/rc.rsyslogd b/platform/slackware/rc.rsyslogd
new file mode 100755
index 0000000..f5f8f45
--- /dev/null
+++ b/platform/slackware/rc.rsyslogd
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Start/stop/restart the system logging daemons.
+#
+# Written for Slackware Linux by Patrick J. Volkerding <volkerdi@slackware.com>.
+# Modded for rsyslogd by Chris Elvidge <chris@lowe.ae> Sept 2005
+#
+
+create_xconsole()
+{
+ if [ ! -e /dev/xconsole ]; then
+ mknod -m 640 /dev/xconsole p
+ else
+ chmod 0640 /dev/xconsole
+ fi
+ chown 0:0 /dev/xconsole
+}
+
+rsyslogd_start() {
+ if [ -x /usr/sbin/rsyslogd -a -x /usr/sbin/klogd ]; then
+ echo "Starting rsyslogd / klogd daemons: "
+# this one listens on the "usual" socket /dev/log
+ echo "/usr/sbin/rsyslogd -i $pidfile1"
+ /usr/sbin/rsyslogd -i "$pidfile1"
+# this one listens only to the UDP port
+ sleep 1
+ echo "/usr/sbin/rsyslogd -o -r0 -f $confile2 -i $pidfile2"
+ /usr/sbin/rsyslogd -o -r0 -f "$confile2" -i "$pidfile2"
+ sleep 1 # prevent syslogd/klogd race condition on SMP kernels
+ echo "/usr/sbin/klogd -c 3 -x"
+ # '-c 3' = display level 'error' or higher messages on console
+ # '-x' = turn off broken EIP translation
+ /usr/sbin/klogd -c 3 -x
+ fi
+}
+
+rsyslogd_stop() {
+ killall rsyslogd 2> /dev/null
+ killall klogd 2> /dev/null
+ /usr/bin/rm pidfile1 2> /dev/null
+ /usr/bin/rm pidfile2 2> /dev/null
+}
+
+rsyslogd_restart() {
+ rsyslogd_stop
+ sleep 1
+ rsyslogd_start
+}
+
+confile1=/etc/rsyslog.conf
+pidfile1=/var/run/rsyslogd.pid
+
+confile2=/etc/rsyslog.udp.conf
+pidfile2=/var/run/rsyslogd.udp.pid
+
+case "$1" in
+'start')
+ create_xconsole
+ rsyslogd_start
+ ;;
+'stop')
+ rsyslogd_stop
+ ;;
+'restart')
+ rsyslogd_restart
+ ;;
+*)
+ echo "usage $0 start|stop|restart"
+esac
diff --git a/plugins/fmhttp/Makefile.am b/plugins/fmhttp/Makefile.am
new file mode 100644
index 0000000..d4743e9
--- /dev/null
+++ b/plugins/fmhttp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = fmhttp.la
+
+fmhttp_la_SOURCES = fmhttp.c
+fmhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+fmhttp_la_LDFLAGS = -module -avoid-version
+fmhttp_la_LIBADD = $(CURL_LIBS)
diff --git a/plugins/fmhttp/Makefile.in b/plugins/fmhttp/Makefile.in
new file mode 100644
index 0000000..5bd4ab3
--- /dev/null
+++ b/plugins/fmhttp/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/fmhttp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+fmhttp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fmhttp_la_OBJECTS = fmhttp_la-fmhttp.lo
+fmhttp_la_OBJECTS = $(am_fmhttp_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 =
+fmhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(fmhttp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/fmhttp_la-fmhttp.Plo
+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 = $(fmhttp_la_SOURCES)
+DIST_SOURCES = $(fmhttp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = fmhttp.la
+fmhttp_la_SOURCES = fmhttp.c
+fmhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+fmhttp_la_LDFLAGS = -module -avoid-version
+fmhttp_la_LIBADD = $(CURL_LIBS)
+all: 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) --gnu plugins/fmhttp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/fmhttp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+fmhttp.la: $(fmhttp_la_OBJECTS) $(fmhttp_la_DEPENDENCIES) $(EXTRA_fmhttp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(fmhttp_la_LINK) -rpath $(pkglibdir) $(fmhttp_la_OBJECTS) $(fmhttp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmhttp_la-fmhttp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+fmhttp_la-fmhttp.lo: fmhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fmhttp_la-fmhttp.lo -MD -MP -MF $(DEPDIR)/fmhttp_la-fmhttp.Tpo -c -o fmhttp_la-fmhttp.lo `test -f 'fmhttp.c' || echo '$(srcdir)/'`fmhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fmhttp_la-fmhttp.Tpo $(DEPDIR)/fmhttp_la-fmhttp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fmhttp.c' object='fmhttp_la-fmhttp.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) $(fmhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fmhttp_la-fmhttp.lo `test -f 'fmhttp.c' || echo '$(srcdir)/'`fmhttp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/fmhttp_la-fmhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/fmhttp_la-fmhttp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/fmhttp/fmhttp.c b/plugins/fmhttp/fmhttp.c
new file mode 100644
index 0000000..c465b23
--- /dev/null
+++ b/plugins/fmhttp/fmhttp.c
@@ -0,0 +1,188 @@
+/* fmhttp.c
+ * This is a function module for http functions.
+ *
+ * File begun on 2018-03-16 by JGerhards
+ *
+ * Copyright 2010-2018 Rainer Gerhards, Jan Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <curl/curl.h>
+#include "errmsg.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "parserif.h"
+#include "module-template.h"
+#include "rainerscript.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_FUNCTION
+MODULE_TYPE_NOKEEP
+DEF_FMOD_STATIC_DATA
+
+struct curl_funcData {
+ const char *reply;
+ size_t replyLen;
+};
+
+/* curl callback for doFunc_http_request */
+static size_t
+curlResult(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ char *buf;
+ size_t newlen;
+ struct cnffunc *const func = (struct cnffunc *) userdata;
+ assert(func != NULL);
+ struct curl_funcData *const curlData = (struct curl_funcData*) func->funcdata;
+ assert(curlData != NULL);
+
+ if(ptr == NULL) {
+ LogError(0, RS_RET_ERR, "internal error: libcurl provided ptr=NULL");
+ return 0;
+ }
+
+ newlen = curlData->replyLen + size*nmemb;
+ if((buf = realloc((void*)curlData->reply, newlen + 1)) == NULL) {
+ LogError(errno, RS_RET_ERR, "rainerscript: realloc failed in curlResult");
+ return 0; /* abort due to failure */
+ }
+ memcpy(buf+curlData->replyLen, (char*)ptr, size*nmemb);
+ curlData->replyLen = newlen;
+ curlData->reply = buf;
+ return size*nmemb;
+}
+
+static void ATTR_NONNULL()
+doFunc_http_request(struct cnffunc *__restrict__ const func,
+ struct svar *__restrict__ const ret,
+ void *__restrict__ const usrptr,
+ wti_t *__restrict__ const pWti)
+{
+ struct svar srcVal;
+ int bMustFree;
+ cnfexprEval(func->expr[0], &srcVal, usrptr, pWti);
+ char *url = (char*) var2CString(&srcVal, &bMustFree);
+
+ int resultSet = 0;
+ CURL *handle = NULL;
+ CURLcode res;
+ assert(func != NULL);
+ struct curl_funcData *const curlData = (struct curl_funcData*) func->funcdata;
+ assert(curlData != NULL);
+ rsRetVal iRet __attribute__((unused)) = RS_RET_OK;
+
+ CHKmalloc(handle = curl_easy_init());
+ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, func);
+
+ curl_easy_setopt(handle, CURLOPT_URL, url);
+ res = curl_easy_perform(handle);
+ if(res != CURLE_OK) {
+ LogError(0, RS_RET_IO_ERROR,
+ "rainerscript: http_request to failed, URL: '%s', error %s",
+ url, curl_easy_strerror(res));
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+
+ CHKmalloc(ret->d.estr = es_newStrFromCStr(curlData->reply, curlData->replyLen));
+ ret->datatype = 'S';
+ resultSet = 1;
+
+finalize_it:
+ free((void*)curlData->reply);
+ curlData->reply = NULL;
+ curlData->replyLen = 0;
+
+ if(handle != NULL) {
+ curl_easy_cleanup(handle);
+ }
+ if(!resultSet) {
+ /* provide dummy value */
+ ret->d.n = 0;
+ ret->datatype = 'N';
+ }
+ if(bMustFree) {
+ free(url);
+ }
+ varFreeMembers(&srcVal);
+}
+
+static rsRetVal ATTR_NONNULL(1)
+initFunc_http_request(struct cnffunc *const func)
+{
+ DEFiRet;
+
+ func->destructable_funcdata = 1;
+ CHKmalloc(func->funcdata = calloc(1, sizeof(struct curl_funcData)));
+ if(func->nParams != 1) {
+ parser_errmsg("rsyslog logic error in line %d of file %s\n",
+ __LINE__, __FILE__);
+ FINALIZE;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static void ATTR_NONNULL(1)
+destructFunc_http_request(struct cnffunc *const func)
+{
+ if(func->funcdata != NULL) {
+ free((void*) ((struct curl_funcData*)func->funcdata)->reply);
+ }
+}
+
+static struct scriptFunct functions[] = {
+ {"http_request", 1, 1, doFunc_http_request, initFunc_http_request, destructFunc_http_request},
+ {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array
+};
+
+BEGINgetFunctArray
+CODESTARTgetFunctArray
+ *version = 1;
+ *functArray = functions;
+ENDgetFunctArray
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_FMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("rsyslog fmhttp init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/plugins/im3195/Makefile.am b/plugins/im3195/Makefile.am
new file mode 100644
index 0000000..5af0b6f
--- /dev/null
+++ b/plugins/im3195/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = im3195.la
+
+im3195_la_SOURCES = im3195.c
+im3195_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGGING_CFLAGS)
+im3195_la_LDFLAGS = -module -avoid-version
+im3195_la_LIBADD = $(LIBLOGGING_LIBS)
+
+EXTRA_DIST =
diff --git a/plugins/im3195/Makefile.in b/plugins/im3195/Makefile.in
new file mode 100644
index 0000000..b457a4b
--- /dev/null
+++ b/plugins/im3195/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/im3195
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+im3195_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_im3195_la_OBJECTS = im3195_la-im3195.lo
+im3195_la_OBJECTS = $(am_im3195_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 =
+im3195_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(im3195_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/im3195_la-im3195.Plo
+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 = $(im3195_la_SOURCES)
+DIST_SOURCES = $(im3195_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = im3195.la
+im3195_la_SOURCES = im3195.c
+im3195_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGGING_CFLAGS)
+im3195_la_LDFLAGS = -module -avoid-version
+im3195_la_LIBADD = $(LIBLOGGING_LIBS)
+EXTRA_DIST =
+all: 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) --gnu plugins/im3195/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/im3195/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+im3195.la: $(im3195_la_OBJECTS) $(im3195_la_DEPENDENCIES) $(EXTRA_im3195_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(im3195_la_LINK) -rpath $(pkglibdir) $(im3195_la_OBJECTS) $(im3195_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/im3195_la-im3195.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+im3195_la-im3195.lo: im3195.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(im3195_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT im3195_la-im3195.lo -MD -MP -MF $(DEPDIR)/im3195_la-im3195.Tpo -c -o im3195_la-im3195.lo `test -f 'im3195.c' || echo '$(srcdir)/'`im3195.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/im3195_la-im3195.Tpo $(DEPDIR)/im3195_la-im3195.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='im3195.c' object='im3195_la-im3195.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) $(im3195_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o im3195_la-im3195.lo `test -f 'im3195.c' || echo '$(srcdir)/'`im3195.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/im3195_la-im3195.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/im3195_la-im3195.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/im3195/im3195.c b/plugins/im3195/im3195.c
new file mode 100644
index 0000000..e8ee143
--- /dev/null
+++ b/plugins/im3195/im3195.c
@@ -0,0 +1,216 @@
+/**
+ * The rfc3195 input module.
+ *
+ * Please note that this file replaces the rfc3195d daemon that was
+ * also present in pre-v3 versions of rsyslog.
+ *
+ * WARNING: due to no demand at all for RFC3195, we have converted rfc3195d
+ * to this input module, but we have NOT conducted any testing. Also,
+ * the module does not yet properly handle the recovery case. If someone
+ * intends to put this module into production, good testing should be
+ * made and it also is a good idea to notify me that you intend to use
+ * it in production. In this case, I'll probably give the module another
+ * cleanup. I don't do this now because so far it looks just like a big
+ * waste of time. -- rgerhards, 2008-04-16
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ *
+ * Copyright (C) 2003-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <assert.h>
+#include "rsyslog.h"
+#include "dirty.h"
+#include "liblogging/liblogging.h"
+#include "liblogging/srAPI.h"
+#include "liblogging/syslogmessage.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "msg.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(prop)
+
+/* configuration settings */
+
+struct modConfData_s {
+ EMPTY_STRUCT;
+};
+
+static int listenPort = 601;
+
+/* we use a global API object below, because this listener is
+ * not very complex. As such, this hack should not harm anything.
+ * rgerhards, 2005-10-12
+ */
+static srAPIObj* pAPI;
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this module */
+
+
+/* This method is called when a message has been fully received.
+ * It passes the received message to the rsyslog main message
+ * queue. Please note that this callback is synchronous, thus
+ * liblogging will be on hold until it returns. This is important
+ * to note because in an error case we might stay in this code
+ * for an extended amount of time. So far, we think this is the
+ * best solution, but real-world experience might tell us a
+ * different truth ;)
+ */
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+static void OnReceive(srAPIObj __attribute__((unused)) *pMyAPI, srSLMGObj* pSLMG)
+{
+ uchar *pszRawMsg;
+ uchar *fromHost = (uchar*) "[unset]"; /* TODO: get hostname */
+ uchar *fromHostIP = (uchar*) "[unset]"; /* TODO: get hostname */
+
+ srSLMGGetRawMSG(pSLMG, &pszRawMsg);
+
+ parseAndSubmitMessage(fromHost, fromHostIP, pszRawMsg, strlen((char*)pszRawMsg),
+ PARSE_HOSTNAME, eFLOWCTL_FULL_DELAY, pInputName, NULL, 0, NULL);
+}
+
+
+#if 0
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+#endif
+
+
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(!pThrd->bShallStop) {
+ /* now move the listener to running state. Control will only
+ * return after SIGUSR1.
+ */
+ if((iRet = (rsRetVal) srAPIRunListener(pAPI)) != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d running liblogging listener - im3195 "
+ "is defunct", iRet);
+ FINALIZE; /* this causes im3195 to become defunct; TODO: recovery handling */
+ }
+ }
+finalize_it:
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ if((pAPI = srAPIInitLib()) == NULL) {
+ LogError(0, NO_ERRCODE, "error initializing liblogging - im3195 is defunct");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((iRet = (rsRetVal) srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d setting liblogging listen port - im3195 is defunct", iRet);
+ FINALIZE;
+ }
+
+ if((iRet = (rsRetVal) srAPISetupListener(pAPI, OnReceive)) != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d setting up liblogging listener - im3195 is defunct", iRet);
+ FINALIZE;
+ }
+
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ dbgprintf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
+ srAPIShutdownListener(pAPI);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ srAPIExitLib(pAPI); /* terminate liblogging */
+ /* global variable cleanup */
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ /* release objects we used */
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ listenPort = 601;
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"input3195listenport", 0, eCmdHdlrInt, NULL, &listenPort,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("im3195"), sizeof("im3195") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ENDmodInit
diff --git a/plugins/imdiag/Makefile.am b/plugins/imdiag/Makefile.am
new file mode 100644
index 0000000..33e86e9
--- /dev/null
+++ b/plugins/imdiag/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imdiag.la
+
+imdiag_la_SOURCES = imdiag.c
+imdiag_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imdiag_la_LDFLAGS = -module -avoid-version
+imdiag_la_LIBADD =
diff --git a/plugins/imdiag/Makefile.in b/plugins/imdiag/Makefile.in
new file mode 100644
index 0000000..69c8fd2
--- /dev/null
+++ b/plugins/imdiag/Makefile.in
@@ -0,0 +1,796 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imdiag
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imdiag_la_DEPENDENCIES =
+am_imdiag_la_OBJECTS = imdiag_la-imdiag.lo
+imdiag_la_OBJECTS = $(am_imdiag_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 =
+imdiag_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imdiag_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imdiag_la-imdiag.Plo
+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 = $(imdiag_la_SOURCES)
+DIST_SOURCES = $(imdiag_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imdiag.la
+imdiag_la_SOURCES = imdiag.c
+imdiag_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imdiag_la_LDFLAGS = -module -avoid-version
+imdiag_la_LIBADD =
+all: 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) --gnu plugins/imdiag/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imdiag/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imdiag.la: $(imdiag_la_OBJECTS) $(imdiag_la_DEPENDENCIES) $(EXTRA_imdiag_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imdiag_la_LINK) -rpath $(pkglibdir) $(imdiag_la_OBJECTS) $(imdiag_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imdiag_la-imdiag.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imdiag_la-imdiag.lo: imdiag.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imdiag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imdiag_la-imdiag.lo -MD -MP -MF $(DEPDIR)/imdiag_la-imdiag.Tpo -c -o imdiag_la-imdiag.lo `test -f 'imdiag.c' || echo '$(srcdir)/'`imdiag.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imdiag_la-imdiag.Tpo $(DEPDIR)/imdiag_la-imdiag.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imdiag.c' object='imdiag_la-imdiag.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) $(imdiag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imdiag_la-imdiag.lo `test -f 'imdiag.c' || echo '$(srcdir)/'`imdiag.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imdiag_la-imdiag.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imdiag_la-imdiag.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c
new file mode 100644
index 0000000..774939a
--- /dev/null
+++ b/plugins/imdiag/imdiag.c
@@ -0,0 +1,943 @@
+/* imdiag.c
+ * This is a testbench tool. It started out with a broader scope,
+ * but we dropped this idea. To learn about rsyslog runtime statistics
+ * have a look at impstats.
+ *
+ * File begun on 2008-07-25 by RGerhards
+ *
+ * Copyright 2008-2023 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include <semaphore.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "netstrm.h"
+#include "errmsg.h"
+#include "tcpsrv.h"
+#include "srUtils.h"
+#include "msg.h"
+#include "datetime.h"
+#include "ratelimit.h"
+#include "queue.h"
+#include "lookup.h"
+#include "net.h" /* for permittedPeers, may be removed when this is removed */
+#include "statsobj.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(tcpsrv)
+DEFobjCurrIf(tcps_sess)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(statsobj)
+
+/* Module static data */
+static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
+static permittedPeers_t *pPermPeersRoot = NULL;
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+static prop_t *pRcvDummy = NULL;
+static prop_t *pRcvIPDummy = NULL;
+
+static int max_empty_checks = 3; /* how often check for queue empty during shutdown? */
+
+statsobj_t *diagStats;
+STATSCOUNTER_DEF(potentialArtificialDelayMs, mutPotentialArtificialDelayMs)
+STATSCOUNTER_DEF(actualArtificialDelayMs, mutActualArtificialDelayMs)
+STATSCOUNTER_DEF(delayInvocationCount, mutDelayInvocationCount)
+
+static sem_t statsReportingBlocker;
+static long long statsReportingBlockStartTimeMs = 0;
+static int allowOnlyOnce = 0;
+DEF_ATOMIC_HELPER_MUT(mutAllowOnlyOnce);
+pthread_mutex_t mutStatsReporterWatch;
+pthread_cond_t statsReporterWatch;
+int statsReported = 0;
+static int abortTimeout = -1; /* for timeoutGuard - if set, abort rsyslogd after that many seconds */
+static pthread_t timeoutGuard_thrd; /* thread ID for timeoutGuard thread (if active) */
+
+/* config settings */
+struct modConfData_s {
+ EMPTY_STRUCT;
+};
+
+static flowControl_t injectmsgDelayMode = eFLOWCTL_NO_DELAY;
+static int iTCPSessMax = 20; /* max number of sessions */
+static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+static uchar *pszLstnPortFileName = NULL;
+static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
+static uchar *pszInputName = NULL; /* value for inputname property, NULL is OK and handled by core engine */
+
+
+/* callbacks */
+/* this shall go into a specific ACL module! */
+static int
+isPermittedHost(struct sockaddr __attribute__((unused)) *addr, char __attribute__((unused)) *fromHostFQDN,
+ void __attribute__((unused)) *pUsrSrv, void __attribute__((unused)) *pUsrSess)
+{
+ return 1; /* TODO: implement ACLs ... or via some other way? */
+}
+
+
+static rsRetVal
+doOpenLstnSocks(tcpsrv_t *pSrv)
+{
+ ISOBJ_TYPE_assert(pSrv, tcpsrv);
+ dbgprintf("in imdiag doOpenLstnSocks\n");
+ return tcpsrv.create_tcp_socket(pSrv);
+}
+
+
+static rsRetVal
+doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf, ssize_t *piLenRcvd, int *oserr)
+{
+ assert(pSess != NULL);
+ assert(piLenRcvd != NULL);
+
+ *piLenRcvd = lenBuf;
+ return netstrm.Rcv(pSess->pStrm, (uchar*) buf, piLenRcvd, oserr);
+}
+
+static rsRetVal
+onRegularClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ /* process any incomplete frames left over */
+ tcps_sess.PrepareClose(pSess);
+ /* Session closed */
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+
+static rsRetVal
+onErrClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+
+/* get the first word delimited by space from a given string. The pointer is
+ * advanced to after the word. Any leading spaces are discarded. If the
+ * output buffer is too small, parsing ends on buffer full condition.
+ * An empty buffer is returned if there is no more data inside the string.
+ * rgerhards, 2009-05-27
+ */
+#define TO_LOWERCASE 1
+#define NO_MODIFY 0
+static void
+getFirstWord(uchar **ppszSrc, uchar *pszBuf, size_t lenBuf, int options)
+{
+ uchar c;
+ uchar *pszSrc = *ppszSrc;
+
+ while(*pszSrc && *pszSrc == ' ')
+ ++pszSrc; /* skip to first non-space */
+
+ while(*pszSrc && *pszSrc != ' ' && lenBuf > 1) {
+ c = *pszSrc++;
+ if(options & TO_LOWERCASE)
+ c = tolower(c);
+ *pszBuf++ = c;
+ lenBuf--;
+ }
+
+ *pszBuf = '\0';
+ *ppszSrc = pszSrc;
+}
+
+
+/* send a response back to the originator
+ * rgerhards, 2009-05-27
+ */
+static rsRetVal __attribute__((format(printf, 2, 3)))
+sendResponse(tcps_sess_t *pSess, const char *const __restrict__ fmt, ...)
+{
+ va_list ap;
+ ssize_t len;
+ uchar buf[1024];
+ DEFiRet;
+
+ va_start(ap, fmt);
+ len = vsnprintf((char*)buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ CHKiRet(netstrm.Send(pSess->pStrm, buf, &len));
+
+finalize_it:
+ RETiRet;
+}
+
+/* submit a generated numeric-suffix message to the rsyslog core
+ */
+static rsRetVal
+doInjectMsg(uchar *szMsg, ratelimit_t *ratelimiter)
+{
+ smsg_t *pMsg;
+ struct syslogTime stTime;
+ time_t ttGenTime;
+ DEFiRet;
+
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetFlowControlType(pMsg, injectmsgDelayMode);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ MsgSetRcvFrom(pMsg, pRcvDummy);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pRcvIPDummy));
+ CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+/* submit a generated numeric-suffix message to the rsyslog core
+ */
+static rsRetVal
+doInjectNumericSuffixMsg(int iNum, ratelimit_t *ratelimiter)
+{
+ uchar szMsg[1024];
+ DEFiRet;
+ snprintf((char*)szMsg, sizeof(szMsg)/sizeof(uchar),
+ "<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:%8.8d:", iNum);
+ iRet = doInjectMsg(szMsg, ratelimiter);
+ RETiRet;
+}
+
+/* This function injects messages. Command format:
+ * injectmsg <fromnbr> <number-of-messages>
+ * rgerhards, 2009-05-27
+ */
+static rsRetVal
+injectMsg(uchar *pszCmd, tcps_sess_t *pSess)
+{
+ uchar wordBuf[1024];
+ int iFrom, nMsgs;
+ uchar *literalMsg;
+ int i;
+ ratelimit_t *ratelimit = NULL;
+ DEFiRet;
+
+ literalMsg = NULL;
+
+ memset(wordBuf, 0, sizeof(wordBuf));
+ CHKiRet(ratelimitNew(&ratelimit, "imdiag", "injectmsg"));
+ /* we do not check errors here! */
+ getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
+ if (ustrcmp(UCHAR_CONSTANT("literal"), wordBuf) == 0) {
+ /* user has provided content for a message */
+ ++pszCmd; /* ignore following space */
+ CHKiRet(doInjectMsg(pszCmd, ratelimit));
+ nMsgs = 1;
+ } else { /* assume 2 args, (from_idx, count) */
+ iFrom = atoi((char*)wordBuf);
+ getFirstWord(&pszCmd, wordBuf, sizeof(wordBuf), TO_LOWERCASE);
+ nMsgs = atoi((char*)wordBuf);
+ for(i = 0 ; i < nMsgs ; ++i) {
+ CHKiRet(doInjectNumericSuffixMsg(i + iFrom, ratelimit));
+ }
+ }
+ CHKiRet(sendResponse(pSess, "%d messages injected\n", nMsgs));
+
+ DBGPRINTF("imdiag: %d messages injected\n", nMsgs);
+
+finalize_it:
+ if(ratelimit != NULL)
+ ratelimitDestruct(ratelimit);
+ free(literalMsg);
+ RETiRet;
+}
+
+
+/* This function waits until all queues are drained (size = 0)
+ * To make sure it really is drained, we check multiple times. Otherwise we
+ * may just see races. Note: it is important to ensure that the size
+ * is zero multiple times in succession. Otherwise, we may just accidently
+ * hit a situation where the queue isn't filled for a while (we have seen
+ * this in practice, see https://github.com/rsyslog/rsyslog/issues/688).
+ * Note: until 2014--07-13, this checked just the main queue. However,
+ * the testbench was the sole user and checking all queues makes much more
+ * sense. So we change function semantics instead of carrying the old
+ * semantics over and crafting a new function. -- rgerhards
+ */
+static rsRetVal
+waitMainQEmpty(tcps_sess_t *pSess)
+{
+ int iPrint = 0;
+ int iPrintVerbosity = 500; // 500 default
+ int nempty = 0;
+ static unsigned lastOverallQueueSize = 1;
+ DEFiRet;
+
+ while(1) {
+ processImInternal();
+ const unsigned OverallQueueSize = PREFER_FETCH_32BIT(iOverallQueueSize);
+ if(OverallQueueSize == 0) {
+ ++nempty;
+ } else {
+ if(OverallQueueSize > 500) {
+ /* do a bit of extra sleep to not poll too frequently */
+ srSleep(0, (OverallQueueSize > 2000) ? 900000 : 100000);
+ }
+ nempty = 0;
+ }
+ if(dbgTimeoutToStderr) { /* we abuse this setting a bit ;-) */
+ if(OverallQueueSize != lastOverallQueueSize) {
+ fprintf(stderr, "imdiag: wait q_empty: qsize %d nempty %d\n",
+ OverallQueueSize, nempty);
+ lastOverallQueueSize = OverallQueueSize;
+ }
+ }
+ if(nempty > max_empty_checks)
+ break;
+ if(iPrint++ % iPrintVerbosity == 0)
+ DBGPRINTF("imdiag sleeping, wait queues drain, "
+ "curr size %d, nempty %d\n",
+ OverallQueueSize, nempty);
+ srSleep(0,100000);/* wait a little bit */
+ }
+
+ CHKiRet(sendResponse(pSess, "mainqueue empty\n"));
+ DBGPRINTF("imdiag: mainqueue empty\n");
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+awaitLookupTableReload(tcps_sess_t *pSess)
+{
+ DEFiRet;
+
+ while(1) {
+ if(lookupPendingReloadCount() == 0) {
+ break;
+ }
+ srSleep(0,500000);
+ }
+
+ CHKiRet(sendResponse(pSess, "no pending lookup-table reloads found\n"));
+ DBGPRINTF("imdiag: no pending lookup-table reloads found\n");
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+awaitHUPComplete(tcps_sess_t *pSess)
+{
+ const int max_tries = 10;
+ const int ms_to_sleep = 50;
+ const char *return_msg;
+ int b_saw_HUP = 0;
+ int tries = max_tries;
+ unsigned actual_tries = 0;
+ DEFiRet;
+
+ while(tries > 0) {
+ ++actual_tries;
+ if(get_bHadHUP() == 1) {
+ tries = max_tries;
+ b_saw_HUP = 1;
+ } else {
+ --tries;
+ }
+ srSleep(0, ms_to_sleep * 50);
+ }
+
+ if(b_saw_HUP) {
+ return_msg = "seen HUP request, looks like it has completed";
+ } else {
+ return_msg = "timeout - looks like_HUP has completed";
+ }
+ CHKiRet(sendResponse(pSess, "%s [%d tries]\n", return_msg, actual_tries));
+ DBGPRINTF("imdiag: %s\n", return_msg);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+enableDebug(tcps_sess_t *pSess)
+{
+ DEFiRet;
+
+ Debug = DEBUG_FULL;
+ debugging_on = 1;
+ dbgprintf("Note: debug turned on via imdiag\n");
+
+ CHKiRet(sendResponse(pSess, "debug enabled\n"));
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+imdiag_statsReadCallback(statsobj_t __attribute__((unused)) *const ignore_stats,
+ void __attribute__((unused)) *const ignore_ctx)
+{
+ long long waitStartTimeMs = currentTimeMills();
+ sem_wait(&statsReportingBlocker);
+ long delta = currentTimeMills() - waitStartTimeMs;
+ if ((int)ATOMIC_DEC_AND_FETCH(&allowOnlyOnce, &mutAllowOnlyOnce) < 0) {
+ sem_post(&statsReportingBlocker);
+ } else {
+ LogError(0, RS_RET_OK, "imdiag(stats-read-callback): current stats-reporting "
+ "cycle will proceed now, next reporting cycle will again be blocked");
+ }
+
+ if (pthread_mutex_lock(&mutStatsReporterWatch) == 0) {
+ statsReported = 1;
+ pthread_cond_signal(&statsReporterWatch);
+ pthread_mutex_unlock(&mutStatsReporterWatch);
+ }
+
+ if (delta > 0) {
+ STATSCOUNTER_ADD(actualArtificialDelayMs, mutActualArtificialDelayMs, delta);
+ }
+}
+
+static rsRetVal
+blockStatsReporting(tcps_sess_t *pSess) {
+ DEFiRet;
+
+ sem_wait(&statsReportingBlocker);
+ CHKiConcCtrl(pthread_mutex_lock(&mutStatsReporterWatch));
+ statsReported = 0;
+ CHKiConcCtrl(pthread_mutex_unlock(&mutStatsReporterWatch));
+ ATOMIC_STORE_0_TO_INT(&allowOnlyOnce, &mutAllowOnlyOnce);
+ statsReportingBlockStartTimeMs = currentTimeMills();
+ LogError(0, RS_RET_OK, "imdiag: blocked stats reporting");
+ CHKiRet(sendResponse(pSess, "next stats reporting call will be blocked\n"));
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(0, iRet, "imdiag: block-stats-reporting wasn't successful");
+ CHKiRet(sendResponse(pSess, "imdiag::error something went wrong\n"));
+ }
+ RETiRet;
+}
+
+static rsRetVal
+awaitStatsReport(uchar *pszCmd, tcps_sess_t *pSess) {
+ uchar subCmd[1024];
+ int blockAgain = 0;
+ DEFiRet;
+
+ memset(subCmd, 0, sizeof(subCmd));
+ getFirstWord(&pszCmd, subCmd, sizeof(subCmd), TO_LOWERCASE);
+ blockAgain = (ustrcmp(UCHAR_CONSTANT("block_again"), subCmd) == 0);
+ if (statsReportingBlockStartTimeMs > 0) {
+ long delta = currentTimeMills() - statsReportingBlockStartTimeMs;
+ if (blockAgain) {
+ ATOMIC_STORE_1_TO_INT(&allowOnlyOnce, &mutAllowOnlyOnce);
+ LogError(0, RS_RET_OK, "imdiag: un-blocking ONLY the next cycle of stats reporting");
+ } else {
+ statsReportingBlockStartTimeMs = 0;
+ LogError(0, RS_RET_OK, "imdiag: un-blocking stats reporting");
+ }
+ sem_post(&statsReportingBlocker);
+ LogError(0, RS_RET_OK, "imdiag: stats reporting unblocked");
+ STATSCOUNTER_ADD(potentialArtificialDelayMs, mutPotentialArtificialDelayMs, delta);
+ STATSCOUNTER_INC(delayInvocationCount, mutDelayInvocationCount);
+ LogError(0, RS_RET_OK, "imdiag: will now await next reporting cycle");
+ CHKiConcCtrl(pthread_mutex_lock(&mutStatsReporterWatch));
+ while (! statsReported) {
+ CHKiConcCtrl(pthread_cond_wait(&statsReporterWatch, &mutStatsReporterWatch));
+ }
+ statsReported = 0;
+ CHKiConcCtrl(pthread_mutex_unlock(&mutStatsReporterWatch));
+ if (blockAgain) {
+ statsReportingBlockStartTimeMs = currentTimeMills();
+ }
+ LogError(0, RS_RET_OK, "imdiag: stats were reported, wait complete, returning");
+ CHKiRet(sendResponse(pSess, "stats reporting was unblocked\n"));
+ } else {
+ CHKiRet(sendResponse(pSess, "imdiag::error : stats reporting was not blocked, bug?\n"));
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(0, iRet, "imdiag: stats-reporting unblock + await-run wasn't successfully completed");
+ CHKiRet(sendResponse(pSess, "imdiag::error something went wrong\n"));
+ }
+ RETiRet;
+}
+
+/* Function to handle received messages. This is our core function!
+ * rgerhards, 2009-05-24
+ */
+static rsRetVal ATTR_NONNULL()
+OnMsgReceived(tcps_sess_t *const pSess, uchar *const pRcv, const int iLenMsg)
+{
+ uchar *pszMsg;
+ uchar *pToFree = NULL;
+ uchar cmdBuf[1024];
+ DEFiRet;
+
+ assert(pSess != NULL);
+ assert(pRcv != NULL);
+
+ /* NOTE: pRcv is NOT a C-String but rather an array of characters
+ * WITHOUT a termination \0 char. So we need to convert it to one
+ * before proceeding.
+ */
+ CHKmalloc(pszMsg = calloc(1, iLenMsg + 1));
+ pToFree = pszMsg;
+ memcpy(pszMsg, pRcv, iLenMsg);
+ pszMsg[iLenMsg] = '\0';
+
+ memset(cmdBuf, 0, sizeof(cmdBuf)); /* keep valgrind happy */
+ getFirstWord(&pszMsg, cmdBuf, sizeof(cmdBuf), TO_LOWERCASE);
+
+ dbgprintf("imdiag received command '%s'\n", cmdBuf);
+ if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("getmainmsgqueuesize"))) {
+ CHKiRet(sendResponse(pSess, "%d\n", iOverallQueueSize));
+ DBGPRINTF("imdiag: %d messages in main queue\n", iOverallQueueSize);
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("waitmainqueueempty"))) {
+ CHKiRet(waitMainQEmpty(pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("awaitlookuptablereload"))) {
+ CHKiRet(awaitLookupTableReload(pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("injectmsg"))) {
+ CHKiRet(injectMsg(pszMsg, pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("blockstatsreporting"))) {
+ CHKiRet(blockStatsReporting(pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("awaitstatsreport"))) {
+ CHKiRet(awaitStatsReport(pszMsg, pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("awaithupcomplete"))) {
+ CHKiRet(awaitHUPComplete(pSess));
+ } else if(!ustrcmp(cmdBuf, UCHAR_CONSTANT("enabledebug"))) {
+ CHKiRet(enableDebug(pSess));
+ } else {
+ dbgprintf("imdiag unkown command '%s'\n", cmdBuf);
+ CHKiRet(sendResponse(pSess, "unkown command '%s'\n", cmdBuf));
+ }
+
+finalize_it:
+ free(pToFree);
+ RETiRet;
+}
+
+
+/* set permitted peer -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRoot, pszID));
+ free(pszID); /* no longer needed, but we need to free as of interface def */
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+setInjectDelayMode(void __attribute__((unused)) *pVal, uchar *const pszMode)
+{
+ DEFiRet;
+
+ if(!strcasecmp((char*)pszMode, "no")) {
+ injectmsgDelayMode = eFLOWCTL_NO_DELAY;
+ } else if(!strcasecmp((char*)pszMode, "light")) {
+ injectmsgDelayMode = eFLOWCTL_LIGHT_DELAY;
+ } else if(!strcasecmp((char*)pszMode, "full")) {
+ injectmsgDelayMode = eFLOWCTL_FULL_DELAY;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR,
+ "imdiag: invalid imdiagInjectDelayMode '%s' - ignored", pszMode);
+ }
+ free(pszMode);
+ RETiRet;
+}
+
+
+static rsRetVal
+addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ tcpLstnParams_t *cnf_params = NULL;
+ DEFiRet;
+
+ if(pOurTcpsrv != NULL) {
+ LogError(0, NO_ERRCODE, "imdiag: only a single listener is supported, "
+ "trying to add a second");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKmalloc(cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
+ CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+ CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, iTCPSessMax));
+ CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
+ CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
+ CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
+ CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
+ CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+ CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode));
+ CHKiRet(tcpsrv.SetOnMsgReceive(pOurTcpsrv, OnMsgReceived));
+ /* now set optional params, but only if they were actually configured */
+ if(pszStrmDrvrAuthMode != NULL) {
+ CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode));
+ }
+ if(pPermPeersRoot != NULL) {
+ CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot));
+ }
+
+ /* initialized, now add socket */
+ CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, cnf_params, pszInputName == NULL ?
+ UCHAR_CONSTANT("imdiag") : pszInputName));
+ CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, (uchar*)"imdiag"));
+ /* we support octect-counted frame (constant 1 below) */
+ cnf_params->pszPort = pNewVal;
+ cnf_params->bSuppOctetFram = 1;
+ CHKmalloc(cnf_params->pszLstnPortFileName = (const uchar*) strdup((const char*)pszLstnPortFileName));
+ tcpsrv.configureTCPListen(pOurTcpsrv, cnf_params);
+ cnf_params = NULL;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d trying to add listener", iRet);
+ if(pOurTcpsrv != NULL)
+ tcpsrv.Destruct(&pOurTcpsrv);
+ }
+ free(cnf_params);
+ RETiRet;
+}
+
+
+static void *
+timeoutGuard(ATTR_UNUSED void *arg)
+{
+ assert(abortTimeout != -1);
+ sigset_t sigSet;
+ time_t strtTO;
+ time_t endTO;
+
+ /* block all signals except SIGTTIN and SIGSEGV */
+ sigfillset(&sigSet);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
+
+ dbgprintf("timeoutGuard: timeout %d seconds, time %lld\n", abortTimeout, (long long) time(NULL));
+
+ time(&strtTO);
+ endTO = strtTO + abortTimeout;
+
+ while(1) {
+ int to = endTO - time(NULL);
+ dbgprintf("timeoutGuard: sleep timeout %d seconds\n", to);
+ if(to > 0) {
+ srSleep(to, 0);
+ }
+ if(time(NULL) < endTO) {
+ dbgprintf("timeoutGuard: spurios wakeup, going back to sleep, time: %lld\n",
+ (long long) time(NULL));
+ } else {
+ break;
+ }
+ }
+ dbgprintf("timeoutGuard: sleep expired, aborting\n");
+ /* note: we use fprintf to stderr intentionally! */
+
+ fprintf(stderr, "timeoutGuard: rsyslog still active after expiry of guard "
+ "period (strtTO %lld, endTO %lld, time now %lld, diff %lld), pid %d - initiating abort()\n",
+ (long long) strtTO, (long long) endTO, (long long) time(NULL), (long long) (time(NULL) - strtTO),
+ (int) glblGetOurPid());
+ fflush(stderr);
+ abort();
+}
+
+
+static rsRetVal
+setAbortTimeout(void __attribute__((unused)) *pVal, int timeout)
+{
+ DEFiRet;
+
+ if(abortTimeout != -1) {
+ LogError(0, NO_ERRCODE, "imdiag: abort timeout already set -"
+ "ignoring 2nd+ request");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(timeout <= 0) {
+ LogError(0, NO_ERRCODE, "imdiag: $IMDiagAbortTimeout must be greater "
+ "than 0 - ignored");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ abortTimeout = timeout;
+ const int iState = pthread_create(&timeoutGuard_thrd, NULL, timeoutGuard, NULL);
+ if(iState != 0) {
+ LogError(iState, NO_ERRCODE, "imdiag: error enabling timeoutGuard thread -"
+ "not guarding against system hang");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+#if 0 /* can be used to integrate into new config system */
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+#endif
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
+ iRet = tcpsrv.Run(pOurTcpsrv);
+finalize_it:
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ /* first apply some config settings */
+ if(pOurTcpsrv == NULL)
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdiag"), sizeof("imdiag") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ CHKiRet(prop.Construct(&pRcvDummy));
+ CHKiRet(prop.SetString(pRcvDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pRcvDummy));
+
+ CHKiRet(prop.Construct(&pRcvIPDummy));
+ CHKiRet(prop.SetString(pRcvIPDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pRcvIPDummy));
+
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ if(pRcvDummy != NULL)
+ prop.Destruct(&pRcvDummy);
+ if(pRcvIPDummy != NULL)
+ prop.Destruct(&pRcvIPDummy);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pOurTcpsrv != NULL)
+ iRet = tcpsrv.Destruct(&pOurTcpsrv);
+
+ if(pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&pPermPeersRoot);
+ }
+
+ /* free some globals to keep valgrind happy */
+ free(pszInputName);
+ free(pszLstnPortFileName);
+ free(pszStrmDrvrAuthMode);
+
+ statsobj.Destruct(&diagStats);
+ sem_destroy(&statsReportingBlocker);
+ DESTROY_ATOMIC_HELPER_MUT(mutAllowOnlyOnce);
+ pthread_cond_destroy(&statsReporterWatch);
+ pthread_mutex_destroy(&mutStatsReporterWatch);
+
+ /* release objects we used */
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(tcps_sess, LM_TCPSRV_FILENAME);
+ objRelease(tcpsrv, LM_TCPSRV_FILENAME);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+
+ /* clean up timeoutGuard if active */
+ if(abortTimeout != -1) {
+ int r = pthread_cancel(timeoutGuard_thrd);
+ if(r == 0) {
+ void *dummy;
+ pthread_join(timeoutGuard_thrd, &dummy);
+ }
+ }
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ iTCPSessMax = 200;
+ iStrmDrvrMode = 0;
+ free(pszInputName);
+ free(pszLstnPortFileName);
+ pszLstnPortFileName = NULL;
+ if(pszStrmDrvrAuthMode != NULL) {
+ free(pszStrmDrvrAuthMode);
+ pszStrmDrvrAuthMode = NULL;
+ }
+ return RS_RET_OK;
+}
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ pOurTcpsrv = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ const char *ci_max_empty_checks = getenv("CI_SHUTDOWN_QUEUE_EMPTY_CHECKS");
+ if(ci_max_empty_checks != NULL) {
+ int n = atoi(ci_max_empty_checks);
+ if(n > 200) {
+ LogError(0, RS_RET_PARAM_ERROR, "env var CI_SHUTDOWN_QUEUE_EMPTY_CHECKS has "
+ "value over 200, which is the maximum - capped to 200");
+ n = 200;
+ }
+ if(n > 0) {
+ max_empty_checks = n;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "env var CI_SHUTDOWN_QUEUE_EMPTY_CHECKS has "
+ "value below 1, ignored; using default instead");
+ }
+ fprintf(stderr, "rsyslogd: info: imdiag does %d empty checks due to "
+ "CI_SHUTDOWN_QUEUE_EMPTY_CHECKS\n", max_empty_checks);
+ }
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagaborttimeout"), 0, eCmdHdlrInt,
+ setAbortTimeout, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverrun"), 0, eCmdHdlrGetWord,
+ addTCPListener, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiaginjectdelaymode"), 0, eCmdHdlrGetWord,
+ setInjectDelayMode, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagmaxsessions"), 0, eCmdHdlrInt,
+ NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverstreamdrivermode"), 0,
+ eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiaglistenportfilename"), 0,
+ eCmdHdlrGetWord, NULL, &pszLstnPortFileName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverstreamdriverauthmode"), 0,
+ eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverstreamdriverpermittedpeer"), 0,
+ eCmdHdlrGetWord, setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverinputname"), 0,
+ eCmdHdlrGetWord, NULL, &pszInputName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+
+ sem_init(&statsReportingBlocker, 0, 1);
+ INIT_ATOMIC_HELPER_MUT(mutAllowOnlyOnce);
+ CHKiConcCtrl(pthread_mutex_init(&mutStatsReporterWatch, NULL));
+ CHKiConcCtrl(pthread_cond_init(&statsReporterWatch, NULL));
+
+ CHKiRet(statsobj.Construct(&diagStats));
+ CHKiRet(statsobj.SetName(diagStats, UCHAR_CONSTANT("imdiag-stats-reporting-controller")));
+ CHKiRet(statsobj.SetOrigin(diagStats, UCHAR_CONSTANT("imdiag")));
+ statsobj.SetStatsObjFlags(diagStats, STATSOBJ_FLAG_DO_PREPEND);
+ STATSCOUNTER_INIT(potentialArtificialDelayMs, mutPotentialArtificialDelayMs);
+ CHKiRet(statsobj.AddCounter(diagStats, UCHAR_CONSTANT("potentialTotalArtificialDelayInMs"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &potentialArtificialDelayMs));
+ STATSCOUNTER_INIT(actualArtificialDelayMs, mutActualArtificialDelayMs);
+ CHKiRet(statsobj.AddCounter(diagStats, UCHAR_CONSTANT("actualTotalArtificialDelayInMs"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &actualArtificialDelayMs));
+ STATSCOUNTER_INIT(delayInvocationCount, mutDelayInvocationCount);
+ CHKiRet(statsobj.AddCounter(diagStats, UCHAR_CONSTANT("delayInvocationCount"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &delayInvocationCount));
+ CHKiRet(statsobj.SetReadNotifier(diagStats, imdiag_statsReadCallback, NULL));
+ CHKiRet(statsobj.ConstructFinalize(diagStats));
+ENDmodInit
diff --git a/plugins/imdtls/Makefile.am b/plugins/imdtls/Makefile.am
new file mode 100644
index 0000000..bf544b3
--- /dev/null
+++ b/plugins/imdtls/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imdtls.la
+imdtls_la_DEPENDENCIES = ../../runtime/lmnsd_ossl.la
+imdtls_la_SOURCES = imdtls.c
+imdtls_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+imdtls_la_LDFLAGS = -module -avoid-version
+imdtls_la_LIBADD = $(OPENSSL_LIBS) ../../runtime/lmnsd_ossl.la
diff --git a/plugins/imdtls/Makefile.in b/plugins/imdtls/Makefile.in
new file mode 100644
index 0000000..03043f4
--- /dev/null
+++ b/plugins/imdtls/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imdtls
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_imdtls_la_OBJECTS = imdtls_la-imdtls.lo
+imdtls_la_OBJECTS = $(am_imdtls_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 =
+imdtls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imdtls_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imdtls_la-imdtls.Plo
+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 = $(imdtls_la_SOURCES)
+DIST_SOURCES = $(imdtls_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imdtls.la
+imdtls_la_DEPENDENCIES = ../../runtime/lmnsd_ossl.la
+imdtls_la_SOURCES = imdtls.c
+imdtls_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+imdtls_la_LDFLAGS = -module -avoid-version
+imdtls_la_LIBADD = $(OPENSSL_LIBS) ../../runtime/lmnsd_ossl.la
+all: 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) --gnu plugins/imdtls/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imdtls/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imdtls.la: $(imdtls_la_OBJECTS) $(imdtls_la_DEPENDENCIES) $(EXTRA_imdtls_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imdtls_la_LINK) -rpath $(pkglibdir) $(imdtls_la_OBJECTS) $(imdtls_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imdtls_la-imdtls.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imdtls_la-imdtls.lo: imdtls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imdtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imdtls_la-imdtls.lo -MD -MP -MF $(DEPDIR)/imdtls_la-imdtls.Tpo -c -o imdtls_la-imdtls.lo `test -f 'imdtls.c' || echo '$(srcdir)/'`imdtls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imdtls_la-imdtls.Tpo $(DEPDIR)/imdtls_la-imdtls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imdtls.c' object='imdtls_la-imdtls.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) $(imdtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imdtls_la-imdtls.lo `test -f 'imdtls.c' || echo '$(srcdir)/'`imdtls.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imdtls_la-imdtls.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imdtls_la-imdtls.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imdtls/imdtls.c b/plugins/imdtls/imdtls.c
new file mode 100644
index 0000000..6501d9c
--- /dev/null
+++ b/plugins/imdtls/imdtls.c
@@ -0,0 +1,1164 @@
+/**
+ * The dtls input module, uses OpenSSL as library to implement DTLS.
+ *
+ * \author Andre Lorbach <alorbach@adiscon.com>
+ *
+ * Copyright (C) 2023 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <poll.h>
+#include <assert.h>
+#include <time.h>
+
+// --- Include openssl headers as well
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+# include <openssl/bioerr.h>
+#endif
+#include <openssl/engine.h>
+// ---
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "msg.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "srUtils.h"
+#include "msg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "net.h"
+#include "net_ossl.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imdtls")
+
+/* defines */
+#define MAX_DTLS_CLIENTS 1024
+#define MAX_DTLS_MSGSIZE 65536
+#define DTLS_LISTEN_PORT "4433"
+// 1800 seconds = 30 minutes
+#define DTLS_DEFAULT_TIMEOUT 1800
+
+/* Module static data */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(net)
+DEFobjCurrIf(net_ossl)
+
+#define DTLS_MAX_RCVBUF 8192 /* Maximum DTLS packet is 8192 bytes which fits into Jumbo Frames. If not enabled
+ * message fragmentation (Ethernet MTU of ~ 1500 bytes) can occur.*/
+
+/* config settings */
+typedef struct configSettings_s {
+ uchar *pszBindRuleset; /* name of Ruleset to bind to */
+} configSettings_t;
+static configSettings_t cs;
+
+struct dtlsClient_s {
+ SSL* sslClient; /* DTSL (SSL) Client */
+ time_t lastActivityTime; /* Last Activity Time */
+ int clientfd; /* ClientFD */
+};
+
+// Use typedef to define a type 'dtlsClient_t' based on 'struct dtlsClient_s'
+typedef struct dtlsClient_s dtlsClient_t;
+
+struct instanceConf_s {
+ /* Network properties */
+ uchar *pszBindAddr; /* Listening IP Address */
+ uchar *pszBindPort; /* Port to bind socket to */
+ int timeout; /* Default timeout for DTLS Sessions */
+ /* Common properties */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *pszInputName;
+ prop_t *pInputName; /* InputName in property format for fast access */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ sbool bEnableLstn; /* flag to permit disabling of listener in error case */
+ statsobj_t *stats; /* listener stats */
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ /* OpenSSL properties */
+ uchar *tlscfgcmd; /* OpenSSL Config Command used to override any OpenSSL Settings */
+ permittedPeers_t *pPermPeersRoot; /* permitted peers */
+ int CertVerifyDepth; /* Verify Depth for certificate chains */
+ /* Instance Variables */
+ char *pszRcvBuf;
+ int lenRcvBuf;
+ /**< -1: empty, 0: connection closed, 1..NSD_OSSL_MAX_RCVBUF-1: data of that size present */
+ int ptrRcvBuf; /**< offset for next recv operation if 0 < lenRcvBuf < NSD_OSSL_MAX_RCVBUF */
+
+ /* OpenSSL and Config Cert vars inside net_ossl_t now */
+ net_ossl_t *pNetOssl; /* OSSL shared Config and object vars are here */
+ int nClients; /* */
+ dtlsClient_t **dtlsClients; /* Array of DTSL (SSL) Clients */
+ int sockfd; /* UDP Socket used to bind to */
+ struct sockaddr_in server_addr; /* Server Sockaddr */
+ int port; /* Server Port as integer */
+
+ int id; /* Thread ID */
+ thrdInfo_t *pThrd; /* Thread Instance Info */
+ pthread_t tid; /* the instances thread ID */
+
+ struct instanceConf_s *next;
+ struct instanceConf_s *prev;
+};
+
+/* config variables */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ uchar *pszBindRuleset; /* default name of Ruleset to bind to */
+ AuthMode drvrAuthMode; /* authenticate peer if no other name given */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+static prop_t *pInputName = NULL;
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ruleset", eCmdHdlrGetWord, 0 },
+ { "tls.authmode", eCmdHdlrString, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "address", eCmdHdlrString, 0 },
+ { "timeout", eCmdHdlrPositiveInt, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "tls.permittedpeer", eCmdHdlrArray, 0 },
+ { "tls.authmode", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "tls.tlscfgcmd", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+
+ inst->pszBindAddr = NULL;
+ inst->pszBindPort = NULL;
+ inst->timeout = 1800;
+ inst->pszBindRuleset = loadModConf->pszBindRuleset;
+ inst->pszInputName = NULL;
+ inst->pBindRuleset = NULL;
+ inst->bEnableLstn = 0;
+
+ inst->tlscfgcmd = NULL;
+ inst->pPermPeersRoot = NULL;
+ inst->CertVerifyDepth = 2;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ // Construct pNetOssl helper
+ CHKiRet(net_ossl.Construct(&inst->pNetOssl));
+ inst->pNetOssl->authMode = loadModConf->drvrAuthMode;
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+/* function to generate an error message if the ruleset cannot be found */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imdtls[%s]: ruleset '%s' not found - "
+ "using default ruleset instead",
+ inst->pszBindPort, inst->pszBindRuleset);
+}
+
+static void
+DTLSCloseSocket(instanceConf_t *inst) {
+ DBGPRINTF("imdtls: DTLSCloseSocket for %s:%d\n", inst->pszBindAddr, inst->port);
+ // Close UDP Socket
+ close(inst->sockfd);
+ inst->sockfd = 0;
+}
+
+static rsRetVal
+DTLSCreateSocket(instanceConf_t *inst) {
+ DEFiRet;
+ int optval = 1;
+ int flags;
+
+ struct in_addr ip_struct;
+ DBGPRINTF("imdtls: DTLSCreateSocket for %s:%d\n", inst->pszBindAddr, inst->port);
+
+ // Create UDP Socket
+ inst->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (inst->sockfd < 0) {
+ LogError(0, NO_ERRCODE, "imdtls: Unable to create DTLS listener,"
+ " failed to create socket, "
+ " ignoring port %d bind-address %s.",
+ inst->port, inst->pszBindAddr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ setsockopt(inst->sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ setsockopt(inst->sockfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+
+ // Set NON Blcoking Flags
+ flags = fcntl(inst->sockfd, F_GETFL, 0);
+ fcntl(inst->sockfd, F_SETFL, flags | O_NONBLOCK);
+
+ // Convert IP Address into numeric
+ if (inet_pton(AF_INET, (char*) inst->pszBindAddr, &ip_struct) <= 0) {
+ LogError(0, NO_ERRCODE, "imdtls: Unable to create DTLS listener,"
+ " invalid Bind Address, "
+ " ignoring port %d bind-address %s.",
+ inst->port, inst->pszBindAddr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // Set Server Address
+ memset(&inst->server_addr, 0, sizeof(struct sockaddr_in));
+ inst->server_addr.sin_family = AF_INET;
+ inst->server_addr.sin_port = htons(inst->port);
+ inst->server_addr.sin_addr.s_addr = htonl(ip_struct.s_addr);
+
+ // Bind UDP Socket
+ if (bind(inst->sockfd, (struct sockaddr*)&inst->server_addr, sizeof(struct sockaddr_in)) < 0) {
+ LogError(0, NO_ERRCODE, "imdtls: Unable to create DTLS listener,"
+ " unable to bind, "
+ " ignoring port %d bind-address %s.",
+ inst->port, inst->pszBindAddr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Verify Callback for X509 Certificate validation. Force visibility as this function is not called anywhere but
+* only used as callback!
+*/
+static int
+imdtls_verify_callback(int status, SSL* ssl)
+{
+ DEFiRet;
+ X509 *certpeer;
+ instanceConf_t *inst = NULL;
+
+ dbgprintf("imdtls_verify_callback: get SSL [%p]\n", (void *)ssl);
+ inst = (instanceConf_t*) SSL_get_ex_data(ssl, 2);
+
+ /* Continue check if certificate verify was valid */
+ if (status == 1) {
+ if ( ssl != NULL &&
+ inst != NULL) {
+ /* call the actual function based on current auth mode */
+ switch(inst->pNetOssl->authMode) {
+ case OSSL_AUTH_CERTNAME:
+ /* if we check the name, we must ensure the cert is valid */
+ certpeer = net_ossl_getpeercert(inst->pNetOssl, ssl, NULL);
+ dbgprintf("imdtls_verify_callback: Check peer certname[%p]=%s\n",
+ (void *)ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(inst->pNetOssl, ssl, NULL));
+ CHKiRet(net_ossl_chkpeername(inst->pNetOssl, certpeer, NULL));
+ break;
+ case OSSL_AUTH_CERTFINGERPRINT:
+ certpeer = net_ossl_getpeercert(inst->pNetOssl, ssl, NULL);
+ dbgprintf("imdtls_verify_callback: Check peer fingerprint[%p]=%s\n",
+ (void *)ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(inst->pNetOssl, ssl, NULL));
+ CHKiRet(net_ossl_peerfingerprint(inst->pNetOssl, certpeer, NULL));
+ break;
+ case OSSL_AUTH_CERTVALID:
+ certpeer = net_ossl_getpeercert(inst->pNetOssl, ssl, NULL);
+ dbgprintf("imdtls_verify_callback: Check peer valid[%p]=%s\n",
+ (void *)ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(inst->pNetOssl, ssl, NULL));
+ break;
+ case OSSL_AUTH_CERTANON:
+ dbgprintf("imdtls_verify_callback: ANON[%p]\n", (void *)ssl);
+ FINALIZE;
+ break;
+ }
+ } else {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "imdtls_verify_callback: MISSING ssl or inst!");
+ }
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("imdtls_verify_callback: FAILED\n");
+ status = 0;
+ }
+ return status;
+}
+
+
+static rsRetVal
+addListner(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
+{
+ uchar statname[64];
+ DEFiRet;
+ DBGPRINTF("imdtls: addListner ENTER\n");
+
+ if(!inst->bEnableLstn) {
+ DBGPRINTF("imdtls: DTLS Listener not started because it is disabled by config error\n");
+ FINALIZE;
+ }
+
+ inst->pszInputName = ustrdup((inst->pszInputName == NULL) ? UCHAR_CONSTANT("imdtls") : inst->pszInputName);
+ CHKiRet(prop.Construct(&inst->pInputName));
+ CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(inst->pInputName));
+
+ /* Init defaults */
+ if (inst->pszBindPort == NULL) {
+ CHKmalloc(inst->pszBindPort = ustrdup((uchar*) DTLS_LISTEN_PORT));
+ }
+
+ /* Init SSL Handles! */
+ CHKmalloc(inst->dtlsClients = (dtlsClient_t**) calloc(MAX_DTLS_CLIENTS, sizeof(dtlsClient_t*)));
+ for (int i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ CHKmalloc(inst->dtlsClients[i] = (dtlsClient_t*) calloc(1, sizeof(dtlsClient_t)));
+ }
+ inst->nClients = 0;
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&(inst->stats)));
+ snprintf((char*)statname, sizeof(statname), "%s(%s)",
+ inst->pszInputName, inst->pszBindPort);
+ statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(statsobj.SetName(inst->stats, statname));
+ CHKiRet(statsobj.SetOrigin(inst->stats, (uchar*)"imdtls"));
+ STATSCOUNTER_INIT(inst->ctrSubmit, inst->mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(inst->stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(inst->ctrSubmit)));
+ CHKiRet(statsobj.ConstructFinalize(inst->stats));
+ /* end stats counters */
+
+ // Init OpenSSL Context with DTLS_server_method
+ CHKiRet(net_ossl.osslCtxInit(inst->pNetOssl, DTLS_method()));
+
+# if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ // Init OpenSSL Cookie Callbacks
+ CHKiRet(net_ossl.osslCtxInitCookie(inst->pNetOssl));
+# endif
+ // Run openssl config commands in Context
+ CHKiRet(net_ossl_apply_tlscgfcmd(inst->pNetOssl, inst->tlscfgcmd));
+
+ // Init Socket
+ CHKiRet(DTLSCreateSocket(inst));
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "DTLS Listener for thread failed to create UDP socket "
+ "for thread %s is not functional!", inst->pszInputName);
+ } else {
+ DBGPRINTF("imdtls: DTLS Listener for thread %s added\n", inst->pszInputName);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processMsg(instanceConf_t *inst, dtlsClient_t *dtlsClient, char *msg, size_t lenMsg)
+{
+ DEFiRet;
+ smsg_t *pMsg = NULL;
+ prop_t *pProp = NULL;
+ BIO *wbio;
+ BIO_ADDR *peer_addr;
+
+ /* Get Gentime */
+ time_t ttGenTime = 0;
+ struct syslogTime stTime;
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, msg, lenMsg);
+ MsgSetInputName(pMsg, inst->pInputName);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+
+ // Obtain Sender from BIO
+ wbio = SSL_get_wbio(dtlsClient->sslClient);
+ peer_addr = BIO_ADDR_new();
+ if (BIO_dgram_get_peer(wbio, peer_addr)) {
+ char *pHostname = BIO_ADDR_hostname_string(peer_addr, 1);
+ DBGPRINTF("imdtls: processMsg Received message from %s: %s\n", pHostname, msg);
+ MsgSetRcvFromStr(pMsg, (uchar *)pHostname, strlen(pHostname), &pProp);
+ CHKiRet(prop.Destruct(&pProp));
+ OPENSSL_free(pHostname);
+ } else {
+ DBGPRINTF("imdtls: processMsg Received message from UNKNOWN: %s\n", msg);
+ }
+ BIO_ADDR_free(peer_addr);
+
+ // Update Activity
+ dtlsClient->lastActivityTime = time(NULL);
+
+ // Submit Message
+ CHKiRet(submitMsg2(pMsg));
+ STATSCOUNTER_INC(inst->ctrSubmit, inst->mutCtrSubmit);
+finalize_it:
+ RETiRet;
+}
+
+static void
+DTLScleanupSession(instanceConf_t *inst, int idx) {
+ if (inst->dtlsClients[idx]->sslClient != NULL) {
+ BIO *rbio = SSL_get_rbio(inst->dtlsClients[idx]->sslClient);
+ if (rbio) {
+ // Close socket FIRST!
+ int clientfd = -1;
+ BIO_get_fd(rbio, &clientfd);
+ if (clientfd != -1) {
+ close(clientfd);
+ }
+ }
+ SSL_free(inst->dtlsClients[idx]->sslClient);
+ DBGPRINTF("imdtls: DTLScleanupSession Socket/SSL for Client idx (%d) terminated.\n", idx);
+ }
+ inst->dtlsClients[idx]->sslClient = NULL;
+ inst->dtlsClients[idx]->lastActivityTime = 0;
+}
+
+static void
+DTLSAcceptSession(instanceConf_t *inst, int idx) {
+ int ret, err;
+ SSL* ssl = inst->dtlsClients[idx]->sslClient;
+ DBGPRINTF("imdtls: DTLSAcceptSession for Client idx (%d).\n", idx);
+
+ // Check if the handshake has already been completed
+ ret = SSL_get_state(ssl);
+ if (ret != TLS_ST_OK) {
+ // Existing client Finish handshake
+ ret = SSL_accept(ssl);
+ if (ret <= 0) {
+ err = SSL_get_error(ssl, ret);
+ if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
+ // Non-blocking operation did not complete; retry later
+ DBGPRINTF("imdtls: SSL_accept didn't complete (%d). Will retry.\n", err);
+ } else if(err == SSL_ERROR_SYSCALL) {
+ DBGPRINTF("imdtls: SSL_accept failed SSL_ERROR_SYSCALL idx (%d), removing client.\n",
+ idx);
+ net_ossl_lastOpenSSLErrorMsg(NULL, err, ssl, LOG_WARNING,
+ "DTLSHandleSessions", "SSL_accept");
+ DTLScleanupSession(inst, idx);
+ } else {
+ // An actual error occurred
+ DBGPRINTF("imdtls: SSL_accept failed (%d) idx (%d), removing client.\n", err, idx);
+ net_ossl_lastOpenSSLErrorMsg(NULL, err, ssl, LOG_ERR,
+ "DTLSHandleSessions", "SSL_accept");
+ DTLScleanupSession(inst, idx);
+ }
+ } else {
+ DBGPRINTF("imdtls: SSL_accept success idx (%d), adding client.\n", idx);
+ inst->dtlsClients[idx]->lastActivityTime = time(NULL);
+
+ int status = 1;
+ status = imdtls_verify_callback(status, ssl);
+ if (status == 0) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "imdtls: Cert Verify FAILED for DTLS client idx (%d)",idx);
+ } else {
+ DBGPRINTF("imdtls: Cert Verify SUCCESS for DTLS client idx (%d)\n", idx);
+ }
+ }
+ } else {
+ DBGPRINTF("imdtls: SSL_get_state for DTLS client idx (%d) is %d\n", idx, ret);
+ }
+}
+
+static void
+DTLSTerminateClients(instanceConf_t *inst) {
+ // Process pending Client Data first!
+ for (int i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ if (inst->dtlsClients[i]->sslClient != NULL) {
+ DTLScleanupSession(inst, i);
+ }
+ }
+}
+
+static void
+DTLSReadClient(instanceConf_t *inst, int idx, short revents) {
+ int err;
+ SSL* ssl = inst->dtlsClients[idx]->sslClient;
+ DBGPRINTF("imdtls: DEBUG Check Client activity on index %d.\n", idx);
+ if (revents & POLLIN) {
+ if (ssl == NULL) {
+ DBGPRINTF("imdtls: DTLSHandleSessions MISSING SSL OBJ for index %d.\n", idx);
+ return;
+ }
+ DBGPRINTF("imdtls: Read Client activity on index %d.\n", idx);
+ char buf[MAX_DTLS_MSGSIZE];
+ int len = 0;
+ do {
+ len = SSL_read(ssl, buf, sizeof(buf) - 1);
+ if (len > 0) {
+ buf[len] = '\0';
+ processMsg(inst, inst->dtlsClients[idx], buf, len);
+ } else {
+ err = SSL_get_error(ssl, len);
+ if (err == SSL_ERROR_WANT_READ) {
+ DBGPRINTF("imdtls: SSL_ERROR_WANT_READ flush rbio on index %d.\n", idx);
+ BIO *rbio = SSL_get_rbio(ssl);
+ BIO_flush(rbio);
+ } else if (err == SSL_ERROR_WANT_WRITE) {
+ DBGPRINTF("imdtls: SSL_ERROR_WANT_WRITE flush wbio on index %d.\n", idx);
+ BIO *wbio = SSL_get_wbio(ssl);
+ BIO_flush(wbio);
+ } else if (err == SSL_ERROR_ZERO_RETURN) {
+ DBGPRINTF("imdtls: SSL_ERROR_ZERO_RETURN on index %d.\n", idx);
+ break;
+ } else if (err == SSL_ERROR_SYSCALL) {
+ DBGPRINTF("imdtls: SSL_ERROR_SYSCALL on index %d ERRNO %d\n", idx, errno);
+ net_ossl_lastOpenSSLErrorMsg(NULL, err, ssl, LOG_ERR,
+ "DTLSReadClient", "SSL_read");
+ DTLScleanupSession(inst, idx);
+ break;
+ } else {
+ DBGPRINTF("imdtls: SSL_read error %d (%d) on idx %d, rem client.\n",
+ err, errno, idx);
+ DTLScleanupSession(inst, idx);
+ // Exit the loop if any error occurs
+ break;
+ }
+ }
+ } while (len > 0);
+ }
+}
+
+static void
+DTLSHandleSessions(instanceConf_t *inst) {
+ int fdToIndex[MAX_DTLS_CLIENTS + 1];
+ struct pollfd fds[MAX_DTLS_CLIENTS + 1];
+ int optval = 1;
+ int fdcount = 0;
+ int ret, err;
+ memset(fdToIndex, 0, sizeof(fdToIndex));
+ memset(fds, 0, sizeof(fds));
+ fds[0].fd = inst->sockfd;
+ fds[0].events = POLLIN;
+ DBGPRINTF("imdtls: DTLSHandleSessions ENTER \n");
+
+ // Create FDS Array for Polling sockets
+ for (int i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ if (inst->dtlsClients[i]->sslClient != NULL) {
+ int clientfd = -1;
+ fdcount++;
+ BIO_get_fd(SSL_get_wbio(inst->dtlsClients[i]->sslClient), &clientfd);
+ DBGPRINTF("imdtls: DTLSHandleSessions handle client %d (%d)\n", fdcount, clientfd);
+ fds[fdcount].fd = clientfd;
+ fds[fdcount].events = POLLIN;
+ fdToIndex[clientfd] = i; // Map fd to dtlsClients index
+ }
+ }
+
+ DBGPRINTF("imdtls: Waiting for poll (clients %d) ...\n", fdcount);
+ ret = poll(fds, fdcount+1, -1);
+ if(glbl.GetGlobalInputTermState() == 1) {
+ DBGPRINTF("imdtls: DTLSHandleSessions Terminate State\n");
+ return; /* terminate input! */
+ }
+ if (ret < 0) {
+ DBGPRINTF("imdtls: DTLSHandleSessions ERROR poll failed %d with err %d\n", ret , errno);
+ return;
+ }
+
+ // Process pending Client Data first!
+ DBGPRINTF("imdtls: DTLSHandleSessions handle client sockets (%d) \n", fdcount);
+ for (int i = 1; i <= fdcount; ++i) {
+ DTLSReadClient(inst, fdToIndex[fds[i].fd], fds[i].revents);
+ }
+
+ // Check session timeouts
+ for (int i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ if (inst->dtlsClients[i]->sslClient != NULL) {
+ if (difftime(time(NULL), inst->dtlsClients[i]->lastActivityTime) > inst->timeout) {
+ DBGPRINTF("imdtls: Session timeout (%d) for client index %d.\n", i, inst->timeout);
+ DTLScleanupSession(inst, i);
+ continue;
+ }
+ }
+ }
+
+ // Check MAIN socket for new connections
+ if (fds[0].revents & POLLIN) {
+ DBGPRINTF("imdtls: DTLSHandleSessions handle main socket\n");
+
+ // Create BIO Object for potential new client
+ BIO *sbio = BIO_new_dgram(inst->sockfd, BIO_NOCLOSE);
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
+
+ // Create SSL Object for new client and apply default callbacks
+ SSL *ssl = SSL_new(inst->pNetOssl->ctx);
+ SSL_set_bio(ssl, sbio, sbio);
+ SSL_set_accept_state(ssl);
+ if (inst->pNetOssl->authMode != OSSL_AUTH_CERTANON) {
+ dbgprintf("imdtls: enable certificate checking (Mode=%d, VerifyDepth=%d)\n",
+ inst->pNetOssl->authMode, inst->CertVerifyDepth);
+ net_ossl_set_ssl_verify_callback(ssl,
+ SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ if (inst->CertVerifyDepth != 0) {
+ SSL_set_verify_depth(ssl, inst->CertVerifyDepth);
+ }
+ }
+
+ // Store reference in SSL obj
+ SSL_set_ex_data(ssl, 0, NULL); /* Reserved for pTcp */
+ SSL_set_ex_data(ssl, 1, NULL); /* Reserved for permitExpiredCerts */
+ SSL_set_ex_data(ssl, 2, inst); /* Used in imdtls */
+
+ // Debug Callback for conn sbio!
+ net_ossl_set_bio_callback(sbio);
+
+ // Connect the new Client
+ BIO_ADDR *client_addr = BIO_ADDR_new();
+
+ // Start DTLS Listen and Session
+ do {
+ ret = DTLSv1_listen(ssl, client_addr);
+ if (ret > 0) {
+ dbgprintf("imdtls: DTLSHandleSessions DTLSv1_listen SUCCESS\n");
+ // Create new CLIENT socket for communication!
+ int clientfd = socket(BIO_ADDR_family(client_addr), SOCK_DGRAM, 0);
+ if (clientfd < 0) {
+ LogError(0, NO_ERRCODE, "imdtls: DTLSHandleSessions unable to create"
+ " client socket");
+ return;
+ }
+ setsockopt(clientfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ setsockopt(clientfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+ // Bind and Connect Client Socket
+ if (bind(clientfd,
+ (struct sockaddr*) &inst->server_addr, sizeof(struct sockaddr_in)) < 0) {
+ LogError(0, NO_ERRCODE, "imdtls: DTLSHandleSessions unable to bind"
+ " client socket"
+ " ignoring port %d bind-address %s.",
+ inst->port, inst->pszBindAddr);
+ return;
+ }
+ // Set new fd and set BIO to connected
+ BIO *rbio = SSL_get_rbio(ssl);
+ BIO_set_fd(rbio, clientfd, BIO_NOCLOSE);
+
+ // Set and activate timeouts
+ struct timeval timeout;
+ timeout.tv_sec = inst->timeout;
+ timeout.tv_usec = 0;
+ BIO_ctrl(rbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
+
+ // Set BIO to connected
+ ret = BIO_connect(clientfd, client_addr, 0);
+ if (ret == 0) {
+ err = SSL_get_error(ssl, ret);
+ DBGPRINTF("imdtls: DTLSHandleSessions BIO_connect ERROR %d\n", err);
+ net_ossl_lastOpenSSLErrorMsg(NULL, err, ssl, LOG_WARNING,
+ "DTLSHandleSessions", "BIO_connect");
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "imdtls: BIO_connect failed for DTLS client");
+ SSL_free(ssl);
+ } else {
+ BIO_ctrl_set_connected(rbio, client_addr);
+ DBGPRINTF("imdtls: BIO_connect succeeded.\n");
+
+ // Add to DTLS Clients
+ for (int i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ if (inst->dtlsClients[i]->sslClient == NULL) {
+ inst->dtlsClients[i]->sslClient = ssl;
+ inst->dtlsClients[i]->lastActivityTime = time(NULL);
+ DBGPRINTF("imdtls: New Client added at idx %d.\n", i);
+ DTLSAcceptSession(inst, i);
+ break;
+ }
+ }
+ }
+ break;
+ } else {
+ err = SSL_get_error(ssl, ret);
+ if ( (ret == 0 && err == SSL_ERROR_SYSCALL) ||
+ (err == SSL_ERROR_SYSCALL && errno == EAGAIN)) {
+ DBGPRINTF("imdtls: DTLSv1_listen RET %d (ERR %d / ERRNO %d), retry\n",
+ ret, err, errno);
+ // Wait little and retry DTLSv1_listen
+ srSleep(0, 100000);
+ continue;
+ } else {
+ DBGPRINTF("imdtls: DTLSv1_listen RET %d (ERR %d / ERRNO %d), abort\n",
+ ret, err, errno);
+ net_ossl_lastOpenSSLErrorMsg(NULL, err, ssl, LOG_WARNING,
+ "DTLSHandleSessions", "DTLSv1_listen");
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "imdtls: DTLSv1_listen failed for DTLS client");
+ SSL_free(ssl);
+ break;
+ }
+ }
+ }
+ while (1);
+ BIO_ADDR_free(client_addr);
+ }
+}
+
+static void*
+startDtlsHandler(void *myself) {
+ instanceConf_t *inst = (instanceConf_t *) myself;
+ DBGPRINTF("imdtls: start DtlsHandler for thread %s\n", inst->pszInputName);
+
+ /* DTLS Receiving Loop */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ DBGPRINTF("imdtls: begin handle DTSL Client Sessions\n");
+ DTLSHandleSessions(inst);
+ }
+
+ /* DTLS Terminate Sessions */
+ DBGPRINTF("imdtls: Terminate DTLS Client Sessions\n");
+ DTLSTerminateClients(inst);
+
+ DBGPRINTF("imdtls: stop DtlsHandler for thread %s\n", inst->pszInputName);
+ return NULL;
+}
+
+/* Set permitted peers. It is depending on the auth mode if this are
+ * fingerprints or names. -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+SetPermPeers(instanceConf_t *inst, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ if(pPermPeers == NULL)
+ FINALIZE;
+
+ if(inst->pNetOssl->authMode != OSSL_AUTH_CERTFINGERPRINT && inst->pNetOssl->authMode != OSSL_AUTH_CERTNAME) {
+ LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by "
+ "imdtls in the configured authentication mode - ignored");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE);
+ }
+ inst->pNetOssl->pPermPeers = pPermPeers;
+finalize_it:
+ RETiRet;
+}
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst = NULL;
+ int i,j;
+ FILE *fp;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imdtls)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imdtls:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "port")) {
+ inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "timeout")) {
+ inst->timeout = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tls.authmode")) {
+ char* pszAuthMode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(pszAuthMode, "fingerprint"))
+ inst->pNetOssl->authMode = OSSL_AUTH_CERTFINGERPRINT;
+ else if(!strcasecmp(pszAuthMode, "name"))
+ inst->pNetOssl->authMode = OSSL_AUTH_CERTNAME;
+ else if(!strcasecmp(pszAuthMode, "certvalid"))
+ inst->pNetOssl->authMode = OSSL_AUTH_CERTVALID;
+ else
+ inst->pNetOssl->authMode = OSSL_AUTH_CERTANON;
+ free(pszAuthMode);
+ } else if(!strcmp(inppblk.descr[i].name, "tls.cacert")) {
+ inst->pNetOssl->pszCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->pNetOssl->pszCAFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->pNetOssl->pszCAFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.mycert")) {
+ inst->pNetOssl->pszCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->pNetOssl->pszCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->pNetOssl->pszCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.myprivkey")) {
+ inst->pNetOssl->pszKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->pNetOssl->pszKeyFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->pNetOssl->pszKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.tlscfgcmd")) {
+ inst->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tls.permittedpeer")) {
+ for(j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ uchar *const peer = (uchar*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(net.AddPermittedPeer(&inst->pPermPeersRoot, peer));
+ free(peer);
+ }
+ } else {
+ dbgprintf("imdtls: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ /* check if no port is set. If not, we use DEFAULT of 4433 */
+ if(inst->pszBindPort == NULL) {
+ CHKmalloc(inst->pszBindPort = (uchar*)strdup("4433"));
+ }
+ inst->port = atoi((char*)inst->pszBindPort);
+ /* check if BinAddr is set. If not, we use DEFAULT of 0.0.0.0 */
+ if(inst->pszBindAddr == NULL) {
+ CHKmalloc(inst->pszBindAddr = (uchar*)strdup("0.0.0.0"));
+ }
+
+ // Assign Loaded Peers to Netossl
+ SetPermPeers(inst, inst->pPermPeersRoot);
+
+ /* all ok, ready to start up */
+ inst->bEnableLstn = -1;
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->pszBindRuleset = NULL;
+ pModConf->drvrAuthMode = OSSL_AUTH_CERTANON;
+ /* init legacy config variables */
+ cs.pszBindRuleset = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imdtls: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imdtls:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "tls.authmode")) {
+ char* pszAuthMode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(pszAuthMode, "fingerprint"))
+ loadModConf->drvrAuthMode = OSSL_AUTH_CERTFINGERPRINT;
+ else if(!strcasecmp(pszAuthMode, "name"))
+ loadModConf->drvrAuthMode = OSSL_AUTH_CERTNAME;
+ else if(!strcasecmp(pszAuthMode, "certvalid"))
+ loadModConf->drvrAuthMode = OSSL_AUTH_CERTVALID;
+ else
+ loadModConf->drvrAuthMode = OSSL_AUTH_CERTANON;
+ free(pszAuthMode);
+ } else if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imdtls: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(loadModConf->pszBindRuleset == NULL) {
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ loadModConf->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(loadModConf->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ } else {
+ if((cs.pszBindRuleset != NULL) && (cs.pszBindRuleset[0] != '\0')) {
+ LogError(0, RS_RET_DUP_PARAM, "imdtls: ruleset "
+ "set via legacy directive ignored");
+ }
+ }
+finalize_it:
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst->pszBindRuleset == NULL && pModConf->pszBindRuleset != NULL) {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(pModConf->pszBindRuleset));
+ }
+ std_checkRuleset(pModConf, inst);
+ }
+finalize_it:
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ DBGPRINTF("imdtls: activate addListners for dtls\n");
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(pModConf, inst);
+ }
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+ int i;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindPort);
+ if (inst->pszBindAddr != NULL) {
+ free(inst->pszBindAddr);
+ }
+ free(inst->pszBindRuleset);
+ free(inst->pszInputName);
+
+ // --- CleanUP OpenSSL ressources
+ // Remove SSL CLients
+ if(inst->dtlsClients != NULL) {
+ for (i = 0; i < MAX_DTLS_CLIENTS; ++i) {
+ DTLScleanupSession(inst, i);
+ free(inst->dtlsClients[i]);
+ }
+ free(inst->dtlsClients);
+ }
+
+ // DeConstruct pNetOssl helper
+ net_ossl.Destruct(&inst->pNetOssl);
+
+ // ---
+
+ if(inst->pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&inst->pPermPeersRoot);
+ }
+
+ if(inst->bEnableLstn) {
+ prop.Destruct(&inst->pInputName);
+ statsobj.Destruct(&(inst->stats));
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ free(pModConf->pszBindRuleset);
+ENDfreeCnf
+
+
+
+/* This function is called to gather input.
+ * In essence, it just starts the pool of workers. To save resources,
+ * we run one of the workers on our own thread -- otherwise that thread would
+ * just idle around and wait for the workers to finish.
+ */
+BEGINrunInput
+ instanceConf_t *inst;
+ pthread_attr_t wrkrThrdAttr;
+CODESTARTrunInput
+ pthread_attr_init(&wrkrThrdAttr);
+ pthread_attr_setstacksize(&wrkrThrdAttr, 4096*1024);
+
+ DBGPRINTF("imdtls: create dtls handling threads\n");
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst->bEnableLstn) {
+ pthread_create(&inst->tid, &wrkrThrdAttr, startDtlsHandler, inst);
+ }
+ }
+ pthread_attr_destroy(&wrkrThrdAttr);
+
+ DBGPRINTF("imdtls: starting to wait for close condition\n");
+ while(glbl.GetGlobalInputTermState() == 0) {
+ srSleep(0, 400000);
+ }
+
+ DBGPRINTF("imdtls: received close signal, signaling instance threads...\n");
+ for (inst = runModConf->root; inst != NULL; inst = inst->next) {
+ pthread_kill(inst->tid, SIGTTIN);
+ DTLSCloseSocket(inst);
+ }
+
+ DBGPRINTF("imdtls: threads signaled, waiting for join...");
+ for (inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ pthread_join(inst->tid, NULL);
+ }
+
+ DBGPRINTF("imdtls: finished threads, stopping\n");
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdtls"), sizeof("imdtls") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+/* This function is called by the framework after runInput() has been terminated. It
+ * shall free any resources and prepare the module for unload.
+ * CODEqueryEtryPt_STD_IMOD_QUERIES
+ */
+BEGINafterRun
+CODESTARTafterRun
+ /* TODO: do cleanup here ?! */
+ dbgprintf("imdtls: AfterRun\n");
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+BEGINmodExit
+CODESTARTmodExit
+ DBGPRINTF("imdtls: modExit\n");
+ /* release objects we used */
+ objRelease(net_ossl, LM_NET_OSSL_FILENAME);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("imdtls: modInit\n");
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(net_ossl, LM_NET_OSSL_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ENDmodInit
diff --git a/plugins/imfile/Makefile.am b/plugins/imfile/Makefile.am
new file mode 100644
index 0000000..6bd3e82
--- /dev/null
+++ b/plugins/imfile/Makefile.am
@@ -0,0 +1,12 @@
+pkglib_LTLIBRARIES = imfile.la
+
+if OS_AIX
+LIBMATH = -lm
+else
+LIBMATH =
+endif
+
+imfile_la_SOURCES = imfile.c siphash.c
+imfile_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+imfile_la_LDFLAGS = -module -avoid-version $(LIBFASTJSON_LIBS) $(LIBMATH)
+imfile_la_LIBADD =
diff --git a/plugins/imfile/Makefile.in b/plugins/imfile/Makefile.in
new file mode 100644
index 0000000..e145e5e
--- /dev/null
+++ b/plugins/imfile/Makefile.in
@@ -0,0 +1,809 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imfile
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imfile_la_DEPENDENCIES =
+am_imfile_la_OBJECTS = imfile_la-imfile.lo imfile_la-siphash.lo
+imfile_la_OBJECTS = $(am_imfile_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 =
+imfile_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imfile_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imfile_la-imfile.Plo \
+ ./$(DEPDIR)/imfile_la-siphash.Plo
+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 = $(imfile_la_SOURCES)
+DIST_SOURCES = $(imfile_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imfile.la
+@OS_AIX_FALSE@LIBMATH =
+@OS_AIX_TRUE@LIBMATH = -lm
+imfile_la_SOURCES = imfile.c siphash.c
+imfile_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS)
+imfile_la_LDFLAGS = -module -avoid-version $(LIBFASTJSON_LIBS) $(LIBMATH)
+imfile_la_LIBADD =
+all: 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) --gnu plugins/imfile/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imfile/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imfile.la: $(imfile_la_OBJECTS) $(imfile_la_DEPENDENCIES) $(EXTRA_imfile_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imfile_la_LINK) -rpath $(pkglibdir) $(imfile_la_OBJECTS) $(imfile_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imfile_la-imfile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imfile_la-siphash.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imfile_la-imfile.lo: imfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imfile_la-imfile.lo -MD -MP -MF $(DEPDIR)/imfile_la-imfile.Tpo -c -o imfile_la-imfile.lo `test -f 'imfile.c' || echo '$(srcdir)/'`imfile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imfile_la-imfile.Tpo $(DEPDIR)/imfile_la-imfile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imfile.c' object='imfile_la-imfile.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) $(imfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imfile_la-imfile.lo `test -f 'imfile.c' || echo '$(srcdir)/'`imfile.c
+
+imfile_la-siphash.lo: siphash.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imfile_la-siphash.lo -MD -MP -MF $(DEPDIR)/imfile_la-siphash.Tpo -c -o imfile_la-siphash.lo `test -f 'siphash.c' || echo '$(srcdir)/'`siphash.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imfile_la-siphash.Tpo $(DEPDIR)/imfile_la-siphash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='siphash.c' object='imfile_la-siphash.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) $(imfile_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imfile_la-siphash.lo `test -f 'siphash.c' || echo '$(srcdir)/'`siphash.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imfile_la-imfile.Plo
+ -rm -f ./$(DEPDIR)/imfile_la-siphash.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imfile_la-imfile.Plo
+ -rm -f ./$(DEPDIR)/imfile_la-siphash.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
new file mode 100644
index 0000000..3b0bb10
--- /dev/null
+++ b/plugins/imfile/imfile.c
@@ -0,0 +1,2992 @@
+/* imfile.c
+ *
+ * This is the input module for reading text file data. A text file is a
+ * non-binary file who's lines are delemited by the \n character.
+ *
+ * Work originally begun on 2008-02-01 by Rainer Gerhards
+ *
+ * Copyright 2008-2019 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+#include <glob.h>
+#include <poll.h>
+#include <json.h>
+#include <fnmatch.h>
+#ifdef HAVE_SYS_INOTIFY_H
+#include <sys/inotify.h>
+#include <linux/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+#include <port.h>
+#include <sys/port.h>
+#endif
+#include "rsyslog.h" /* error codes etc... */
+#include "dirty.h"
+#include "cfsysline.h" /* access to config file objects */
+#include "module-template.h" /* generic module interface code - very important, read it! */
+#include "srUtils.h" /* some utility functions */
+#include "msg.h"
+#include "stream.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "stringbuf.h"
+#include "ruleset.h"
+#include "ratelimit.h"
+#include "srUtils.h"
+#include "parserif.h"
+#include "datetime.h"
+
+#include <regex.h>
+
+/* some platforms do not have large file support :( */
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+#ifndef HAVE_LSEEK64
+# define lseek64(fd, offset, whence) lseek(fd, offset, whence)
+#endif
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imfile")
+
+/* defines */
+#define FILE_ID_HASH_SIZE 20 /* max size of a file_id hash */
+#define FILE_ID_SIZE 512 /* how many bytes are used for file-id? */
+#define FILE_DELETE_DELAY 5 /* how many seconds to wait before finally deleting a gone file */
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA /* must be present, starts static data */
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(datetime)
+
+extern int rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
+ uint8_t *out, const size_t outlen); /* see siphash.c */
+
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+#define NUM_MULTISUB 1024 /* default max number of submits */
+#define DFLT_PollInterval 10
+#define INIT_WDMAP_TAB_SIZE 1 /* default wdMap table size - is extended as needed, use 2^x value */
+#define ADD_METADATA_UNSPECIFIED -1
+
+/* If set to 1, fileTableDisplay will be compiled and used for debugging */
+#define ULTRA_DEBUG 0
+
+/* Setting GLOB_BRACE to ZERO which disables support for GLOB_BRACE if not available on current platform */
+#ifndef GLOB_BRACE
+ #define GLOB_BRACE 0
+#endif
+
+typedef struct per_minute_rate_limit_s per_minute_rate_limit_t;
+
+struct per_minute_rate_limit_s {
+ uint64_t maxBytesPerMinute;
+ uint32_t maxLinesPerMinute;
+ uint64_t bytesThisMinute; /* bytes sent so far this minute */
+ uint32_t linesThisMinute; /* lines sent to far this minute */
+ time_t rateLimitingMinute; /* minute we are currently rate limiting for */
+};
+
+static struct configSettings_s {
+ uchar *pszFileName;
+ uchar *pszFileTag;
+ uchar *pszStateFile;
+ uchar *pszBindRuleset;
+ int iPollInterval;
+ int iPersistStateInterval; /* how often if state file to be persisted? (default 0->never) */
+ int bPersistStateAfterSubmission;/* persist state file after messages have been submitted */
+ int iFacility; /* local0 */
+ int iSeverity; /* notice, as of rfc 3164 */
+ int readMode; /* mode to use for ReadMultiLine call */
+ int64 maxLinesAtOnce; /* how many lines to process in a row? */
+ uint64_t maxBytesPerMinute; /* maximum bytes per minute to send before rate limiting */
+ uint64_t maxLinesPerMinute; /* maximum lines per minute to send before rate limiting */
+ uint32_t trimLineOverBytes; /* 0: never trim line, positive number: trim line if over bytes */
+} cs;
+
+struct instanceConf_s {
+ uchar *pszFileName;
+ uchar *pszFileName_forOldStateFile; /* we unfortunately needs this to read old state files */
+ uchar *pszDirName;
+ uchar *pszFileBaseName;
+ uchar *pszTag;
+ size_t lenTag;
+ uchar *pszStateFile;
+ uchar *pszBindRuleset;
+ int nMultiSub;
+ per_minute_rate_limit_t perMinuteRateLimits;
+ int iPersistStateInterval;
+ int bPersistStateAfterSubmission;
+ int iFacility;
+ int iSeverity;
+ int readTimeout;
+ unsigned delay_perMsg;
+ sbool bRMStateOnDel;
+ uint8_t readMode;
+ uchar *startRegex;
+ uchar *endRegex;
+ regex_t start_preg; /* compiled version of startRegex */
+ regex_t end_preg; /* compiled version of endRegex */
+ sbool discardTruncatedMsg;
+ sbool msgDiscardingError;
+ sbool escapeLF;
+ sbool reopenOnTruncate;
+ sbool addCeeTag;
+ sbool addMetadata;
+ sbool freshStartTail;
+ sbool fileNotFoundError;
+ int maxLinesAtOnce;
+ uint32_t trimLineOverBytes;
+ uint32_t ignoreOlderThan;
+ int msgFlag;
+ uchar *escapeLFString;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ struct instanceConf_s *next;
+};
+
+
+/* file system objects */
+typedef struct fs_edge_s fs_edge_t;
+typedef struct fs_node_s fs_node_t;
+typedef struct act_obj_s act_obj_t;
+struct act_obj_s {
+ act_obj_t *prev;
+ act_obj_t *next;
+ fs_edge_t *edge; /* edge which this object belongs to */
+ char *name; /* full path name of active object */
+ char *basename; /* only basename */ //TODO: remove when refactoring rename support
+ char *source_name; /* if this object is target of a symlink, source_name is its name (else NULL) */
+ //char *statefile; /* base name of state file (for move operations) */
+ int wd;
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+ struct fileinfo *pfinf;
+ sbool bPortAssociated;
+ int is_deleted; /* debugging: entry deleted? */
+#endif
+ time_t timeoutBase; /* what time to calculate the timeout against? */
+ /* file dynamic data */
+ char file_id[FILE_ID_HASH_SIZE]; /* file id for this entry, once we could obtain it */
+ char file_id_prev[FILE_ID_HASH_SIZE]; /* previous file id for this entry, set if changed */
+ int in_move; /* workaround for inotify move: if set, state file must not be deleted */
+ ino_t ino; /* current inode nbr */
+ int fd; /* fd to file in order to obtain file_id (needs to be preserved across move) */
+ strm_t *pStrm; /* its stream (NULL if not assigned) */
+ int nRecords; /**< How many records did we process before persisting the stream? */
+ ratelimit_t *ratelimiter;
+ multi_submit_t multiSub;
+ int is_symlink;
+ time_t time_to_delete; /* Helper variable to DELAY the actual file delete in act_obj_unlink */
+};
+struct fs_edge_s {
+ fs_node_t *parent; /* node pointing to this edge */
+ fs_node_t *node; /* node this edge points to */
+ fs_edge_t *next;
+ uchar *name;
+ uchar *path;
+ act_obj_t *active;
+ int is_file;
+ int ninst; /* nbr of instances in instarr */
+ instanceConf_t **instarr;
+};
+struct fs_node_s {
+ fs_edge_t *edges; /* NULL in leaf nodes */
+ fs_node_t *root; /* node one level up (NULL for file system root) */
+};
+
+
+/* forward definitions */
+static rsRetVal persistStrmState(act_obj_t *);
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+static rsRetVal ATTR_NONNULL(1) pollFile(act_obj_t *act);
+static int ATTR_NONNULL() getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path);
+static void ATTR_NONNULL() act_obj_unlink(act_obj_t *act);
+static uchar * ATTR_NONNULL(1, 2) getStateFileName(const act_obj_t *, uchar *, const size_t);
+static int ATTR_NONNULL() getFullStateFileName(const uchar *const, const char *const,
+ uchar *const pszout, const size_t ilenout);
+
+
+#define OPMODE_POLLING 0
+#define OPMODE_INOTIFY 1
+#define OPMODE_FEN 2
+
+/* config variables */
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ int iPollInterval; /* number of seconds to sleep when there was no file activity */
+ int readTimeout;
+ int timeoutGranularity; /* value in ms */
+ instanceConf_t *root, *tail;
+ fs_node_t *conf_tree;
+ uint8_t opMode;
+ sbool configSetViaV2Method;
+ uchar *stateFileDirectory;
+ sbool sortFiles;
+ sbool normalizePath; /* normalize file system pathes (all start with root dir) */
+ sbool haveReadTimeouts; /* use special processing if read timeouts exist */
+ sbool bHadFileData; /* actually a global variable:
+ 1 - last call to pollFile() had data
+ 0 - last call to pollFile() had NO data
+ Must be manually reset to 0 if desired. Helper for
+ polling mode.
+ */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for run process */
+static modConfData_t *currModConf = NULL;/* modConf ptr to CURRENT mod conf (run or load) */
+
+
+#ifdef HAVE_INOTIFY_INIT
+/* We need to map watch descriptors to our actual objects. Unfortunately, the
+ * inotify API does not provide us with any cookie, so a simple O(1) algorithm
+ * cannot be done (what a shame...). We assume that maintaining the array is much
+ * less often done than looking it up, so we keep the array sorted by watch descriptor
+ * and do a binary search on the wd we get back. This is at least O(log n), which
+ * is not too bad for the anticipated use case.
+ */
+struct wd_map_s {
+ int wd; /* ascending sort key */
+ act_obj_t *act; /* point to related active object */
+};
+typedef struct wd_map_s wd_map_t;
+static wd_map_t *wdmap = NULL;
+static int nWdmap;
+static int allocMaxWdmap;
+static int ino_fd; /* fd for inotify calls */
+#endif /* #if HAVE_INOTIFY_INIT -------------------------------------------------- */
+
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+struct fileinfo {
+ struct file_obj fobj;
+ int events;
+ int port;
+};
+
+static int glport; /* Static port handle for FEN api*/
+#endif /* #if OS_SOLARIS -------------------------------------------------- */
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "pollinginterval", eCmdHdlrPositiveInt, 0 },
+ { "readtimeout", eCmdHdlrNonNegInt, 0 },
+ { "timeoutgranularity", eCmdHdlrPositiveInt, 0 },
+ { "sortfiles", eCmdHdlrBinary, 0 },
+ { "statefile.directory", eCmdHdlrString, 0 },
+ { "normalizepath", eCmdHdlrBinary, 0 },
+ { "mode", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "file", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "tag", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "severity", eCmdHdlrSeverity, 0 },
+ { "facility", eCmdHdlrFacility, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "readmode", eCmdHdlrInt, 0 },
+ { "startmsg.regex", eCmdHdlrString, 0 },
+ { "endmsg.regex", eCmdHdlrString, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "msgdiscardingerror", eCmdHdlrBinary, 0 },
+ { "escapelf", eCmdHdlrBinary, 0 },
+ { "escapelf.replacement", eCmdHdlrString, 0 },
+ { "reopenontruncate", eCmdHdlrBinary, 0 },
+ { "maxlinesatonce", eCmdHdlrInt, 0 },
+ { "trimlineoverbytes", eCmdHdlrInt, 0 },
+ { "maxsubmitatonce", eCmdHdlrInt, 0 },
+ { "removestateondelete", eCmdHdlrBinary, 0 },
+ { "persiststateinterval", eCmdHdlrInt, 0 },
+ { "persiststateaftersubmission", eCmdHdlrBinary, 0 },
+ { "deletestateonfiledelete", eCmdHdlrBinary, 0 },
+ { "delay.message", eCmdHdlrNonNegInt, 0 },
+ { "addmetadata", eCmdHdlrBinary, 0 },
+ { "addceetag", eCmdHdlrBinary, 0 },
+ { "statefile", eCmdHdlrString, CNFPARAM_DEPRECATED },
+ { "readtimeout", eCmdHdlrNonNegInt, 0 },
+ { "freshstarttail", eCmdHdlrBinary, 0},
+ { "filenotfounderror", eCmdHdlrBinary, 0},
+ { "needparse", eCmdHdlrBinary, 0},
+ { "ignoreolderthan", eCmdHdlrInt, 0},
+ { "maxbytesperminute", eCmdHdlrInt, 0},
+ { "maxlinesperminute", eCmdHdlrInt, 0}
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+
+/* Support for "old cruft" state files will potentially become optional in the
+ * future (hopefully). To prepare so, we use conditional compilation with a
+ * fixed-true condition ;-) -- rgerhards, 2018-03-28
+ * reason: https://github.com/rsyslog/rsyslog/issues/2231#issuecomment-376862280
+ */
+#define ENABLE_V1_STATE_FILE_FORMAT_SUPPORT 1
+#ifdef ENABLE_V1_STATE_FILE_FORMAT_SUPPORT
+static uchar * ATTR_NONNULL(1, 2)
+OLD_getStateFileName(const instanceConf_t *const inst,
+ uchar *const __restrict__ buf,
+ const size_t lenbuf)
+{
+ DBGPRINTF("OLD_getStateFileName trying '%s'\n", inst->pszFileName_forOldStateFile);
+ snprintf((char*)buf, lenbuf - 1, "imfile-state:%s", inst->pszFileName_forOldStateFile);
+ buf[lenbuf-1] = '\0'; /* be on the safe side... */
+ uchar *p = buf;
+ for( ; *p ; ++p) {
+ if(*p == '/')
+ *p = '-';
+ }
+ return buf;
+}
+
+
+static const uchar *
+getStateFileDir(void)
+{
+ const uchar *wrkdir;
+ assert(currModConf != NULL);
+ if(currModConf->stateFileDirectory == NULL) {
+ wrkdir = glblGetWorkDirRaw(currModConf->pConf);
+ } else {
+ wrkdir = currModConf->stateFileDirectory;
+ }
+ return(wrkdir);
+}
+
+
+/* try to open an old-style state file for given file. If the state file does not
+ * exist or cannot be read, an error is returned.
+ */
+static rsRetVal ATTR_NONNULL(1)
+OLD_openFileWithStateFile(act_obj_t *const act)
+{
+ DEFiRet;
+ strm_t *psSF = NULL;
+ uchar pszSFNam[MAXFNAME];
+ size_t lenSFNam;
+ struct stat stat_buf;
+ uchar statefile[MAXFNAME];
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+
+ uchar *const statefn = OLD_getStateFileName(inst, statefile, sizeof(statefile));
+ DBGPRINTF("OLD_openFileWithStateFile: trying to open state for '%s', state file '%s'\n",
+ act->name, statefn);
+
+ /* Get full path and file name */
+ lenSFNam = getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
+
+ /* check if the file exists */
+ if(stat((char*) pszSFNam, &stat_buf) == -1) {
+ if(errno == ENOENT) {
+ DBGPRINTF("OLD_openFileWithStateFile: NO state file (%s) exists for '%s'\n",
+ pszSFNam, act->name);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ } else {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("OLD_openFileWithStateFile: error trying to access state "
+ "file for '%s':%s\n", act->name, errStr);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ }
+
+ /* If we reach this point, we have a state file */
+
+ DBGPRINTF("old state file found - instantiating from it\n");
+ CHKiRet(strm.Construct(&psSF));
+ CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(psSF, pszSFNam, lenSFNam));
+ CHKiRet(strm.SetFileNotFoundError(psSF, inst->fileNotFoundError));
+ CHKiRet(strm.ConstructFinalize(psSF));
+
+ /* read back in the object */
+ CHKiRet(obj.Deserialize(&act->pStrm, (uchar*) "strm", psSF, NULL, act));
+ free(act->pStrm->pszFName);
+ CHKmalloc(act->pStrm->pszFName = ustrdup(act->name));
+
+ strm.CheckFileChange(act->pStrm);
+ CHKiRet(strm.SeekCurrOffs(act->pStrm));
+
+ /* we now persist the new state file and delete the old one, so we will
+ * never have to deal with the old one. */
+ persistStrmState(act);
+ unlink((char*)pszSFNam);
+
+finalize_it:
+ if(psSF != NULL)
+ strm.Destruct(&psSF);
+ RETiRet;
+}
+#endif /* #ifdef ENABLE_V1_STATE_FILE_FORMAT_SUPPORT */
+
+
+
+#if 0 // Code we can potentially use for new functionality // TODO: use or remove
+//TODO add a kind of portable asprintf:
+static const char * ATTR_NONNULL()
+gen_full_name(const char *const dirname, const char *const name)
+{
+ const size_t len_full_name = strlen(dirname) + 1 + strlen(name) + 1;
+ char *const full_name = malloc(len_full_name);
+ if(full_name == NULL)
+ return NULL;
+
+ snprintf(full_name, len_full_name, "%s/%s", dirname, name);
+ return full_name;
+}
+#endif
+
+
+#ifdef HAVE_INOTIFY_INIT
+#if ULTRA_DEBUG == 1
+static void
+dbg_wdmapPrint(const char *msg)
+{
+ int i;
+ DBGPRINTF("%s\n", msg);
+ for(i = 0 ; i < nWdmap ; ++i)
+ DBGPRINTF("wdmap[%d]: wd: %d, act %p, name: %s\n",
+ i, wdmap[i].wd, wdmap[i].act, wdmap[i].act->name);
+}
+#endif
+
+static rsRetVal
+wdmapInit(void)
+{
+ DEFiRet;
+ free(wdmap);
+ CHKmalloc(wdmap = malloc(sizeof(wd_map_t) * INIT_WDMAP_TAB_SIZE));
+ allocMaxWdmap = INIT_WDMAP_TAB_SIZE;
+ nWdmap = 0;
+finalize_it:
+ RETiRet;
+}
+
+
+/* note: we search backwards, as inotify tends to return increasing wd's */
+static rsRetVal
+wdmapAdd(int wd, act_obj_t *const act)
+{
+ wd_map_t *newmap;
+ int newmapsize;
+ int i;
+ DEFiRet;
+
+ for(i = nWdmap-1 ; i >= 0 && wdmap[i].wd > wd ; --i)
+ ; /* just scan */
+ if(i >= 0 && wdmap[i].wd == wd) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "imfile: wd %d already in wdmap!", wd);
+ ABORT_FINALIZE(RS_RET_FILE_ALREADY_IN_TABLE);
+ }
+ ++i;
+ /* i now points to the entry that is to be moved upwards (or end of map) */
+ if(nWdmap == allocMaxWdmap) {
+ newmapsize = 2 * allocMaxWdmap;
+ CHKmalloc(newmap = realloc(wdmap, sizeof(wd_map_t) * newmapsize));
+ // TODO: handle the error more intelligently? At all possible? -- 2013-10-15
+ wdmap = newmap;
+ allocMaxWdmap = newmapsize;
+ }
+ if(i < nWdmap) {
+ /* we need to shift to make room for new entry */
+ memmove(wdmap + i + 1, wdmap + i, sizeof(wd_map_t) * (nWdmap - i));
+ }
+ wdmap[i].wd = wd;
+ wdmap[i].act = act;
+ ++nWdmap;
+ DBGPRINTF("add wdmap[%d]: wd %d, act obj %p, path %s\n", i, wd, act, act->name);
+
+finalize_it:
+ RETiRet;
+}
+
+/* return wd or -1 on error */
+static int
+in_setupWatch(act_obj_t *const act, const int is_file)
+{
+ int wd = -1;
+ if(runModConf->opMode != OPMODE_INOTIFY)
+ goto done;
+
+ wd = inotify_add_watch(ino_fd, act->name,
+ (is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
+ if(wd < 0) {
+ if (errno == EACCES) { /* There is high probability of selinux denial on top-level paths */
+ DBGPRINTF("imfile: permission denied when adding watch for '%s'\n", act->name);
+ } else {
+ LogError(errno, RS_RET_IO_ERROR, "imfile: cannot watch object '%s'", act->name);
+ }
+ goto done;
+ }
+ wdmapAdd(wd, act);
+ DBGPRINTF("in_setupWatch: watch %d added for %s(object %p)\n", wd, act->name, act);
+done: return wd;
+}
+
+/* compare function for bsearch() */
+static int
+wdmap_cmp(const void *k, const void *a)
+{
+ int key = *((int*) k);
+ wd_map_t *etry = (wd_map_t*) a;
+ if(key < etry->wd)
+ return -1;
+ else if(key > etry->wd)
+ return 1;
+ else
+ return 0;
+}
+/* looks up a wdmap entry and returns it's index if found
+ * or -1 if not found.
+ */
+static wd_map_t *
+wdmapLookup(int wd)
+{
+ return bsearch(&wd, wdmap, nWdmap, sizeof(wd_map_t), wdmap_cmp);
+}
+
+
+static rsRetVal
+wdmapDel(const int wd)
+{
+ int i;
+ DEFiRet;
+
+ for(i = 0 ; i < nWdmap && wdmap[i].wd < wd ; ++i)
+ ; /* just scan */
+ if(i == nWdmap || wdmap[i].wd != wd) {
+ DBGPRINTF("wd %d shall be deleted but not in wdmap!\n", wd);
+ FINALIZE;
+ }
+
+ if(i < nWdmap-1) {
+ /* we need to shift to delete it (see comment at wdmap definition) */
+ memmove(wdmap + i, wdmap + i + 1, sizeof(wd_map_t) * (nWdmap - i - 1));
+ }
+ --nWdmap;
+ DBGPRINTF("wd %d deleted, was idx %d\n", wd, i);
+
+finalize_it:
+ RETiRet;
+}
+
+#endif // #ifdef HAVE_INOTIFY_INIT
+
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+static void ATTR_NONNULL()
+fen_setupWatch(act_obj_t *const act)
+{
+ DBGPRINTF("fen_setupWatch: enter, opMode %d\n", runModConf->opMode);
+ if(runModConf->opMode != OPMODE_FEN)
+ goto done;
+
+ DBGPRINTF("fen_setupWatch: %s\n", act->name);
+ if(act->pfinf == NULL) {
+ act->pfinf = malloc(sizeof(struct fileinfo));
+ if (act->pfinf == NULL) {
+ LogError(errno, RS_RET_OUT_OF_MEMORY, "imfile: fen_setupWatch alloc memory "
+ "for fileinfo failed ");
+ goto done;
+ }
+ if ((act->pfinf->fobj.fo_name = strdup(act->name)) == NULL) {
+ LogError(errno, RS_RET_OUT_OF_MEMORY, "imfile: fen_setupWatch alloc memory "
+ "for strdup failed ");
+ free(act->pfinf);
+ act->pfinf = NULL;
+ goto done;
+ }
+ act->pfinf->events = FILE_MODIFIED;
+ act->pfinf->port = glport;
+ act->bPortAssociated = 0;
+ }
+
+ DBGPRINTF("fen_setupWatch: bPortAssociated %d\n", act->bPortAssociated);
+ if(act->bPortAssociated) {
+ goto done;
+ }
+
+ struct stat fileInfo;
+ const int r = stat(act->name, &fileInfo);
+ if(r == -1) { /* object gone away? */
+ DBGPRINTF("fen_setupWatch: file gone away, no watch: '%s'\n", act->name);
+ goto done;
+ }
+
+ /* note: FEN watch must be re-registered each time - this is what we do now */
+ act->pfinf->fobj.fo_atime = fileInfo.st_atim;
+ act->pfinf->fobj.fo_mtime = fileInfo.st_mtim;
+ act->pfinf->fobj.fo_ctime = fileInfo.st_ctim;
+ if(port_associate(glport, PORT_SOURCE_FILE, (uintptr_t)&(act->pfinf->fobj),
+ act->pfinf->events, (void *)act) == -1) {
+ LogError(errno, RS_RET_SYS_ERR, "fen_setupWatch: Failed to associate port for file "
+ ": %s\n", act->pfinf->fobj.fo_name);
+ goto done;
+ } else {
+ /* Port successfull listening now*/
+ DBGPRINTF("fen_setupWatch: associated port for file %s\n", act->name);
+ act->bPortAssociated = 1;
+ }
+
+ DBGPRINTF("in_setupWatch: fen association added for %s\n", act->name);
+done: return;
+}
+#else
+static void ATTR_NONNULL()
+fen_setupWatch(act_obj_t *const act __attribute__((unused)))
+{
+ DBGPRINTF("fen_setupWatch: DUMMY CALLED - not on Solaris?\n");
+}
+#endif /* FEN */
+
+static void
+fs_node_print(const fs_node_t *const node, const int level)
+{
+ fs_edge_t *chld;
+ act_obj_t *act;
+ dbgprintf("node print[%2.2d]: %p edges:\n", level, node);
+
+ for(chld = node->edges ; chld != NULL ; chld = chld->next) {
+ dbgprintf("node print[%2.2d]: child %p '%s' isFile %d, path: '%s'\n",
+ level, chld->node, chld->name, chld->is_file, chld->path);
+ for(int i = 0 ; i < chld->ninst ; ++i) {
+ dbgprintf("\tinst: %p\n", chld->instarr[i]);
+ }
+ for(act = chld->active ; act != NULL ; act = act->next) {
+ dbgprintf("\tact : %p\n", act);
+ dbgprintf("\tact : %p: name '%s', wd: %d\n",
+ act, act->name, act->wd);
+ }
+ }
+ for(chld = node->edges ; chld != NULL ; chld = chld->next) {
+ fs_node_print(chld->node, level+1);
+ }
+}
+
+static sbool
+isIgnoreOlderFile(const instanceConf_t *const inst, const char *const name)
+{
+ if (inst->ignoreOlderThan)
+ {
+ struct stat stat_buf;
+ time_t tt;
+ /* skip old files */
+ datetime.GetTime(&tt);
+ if (stat((char *)name, &stat_buf) == 0 && difftime(tt, stat_buf.st_mtime) > inst->ignoreOlderThan) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* add a new file system object if it not yet exists, ignore call
+ * if it already does.
+ */
+static rsRetVal ATTR_NONNULL(1,2)
+act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
+ const ino_t ino, const int is_symlink, const char *const source)
+{
+ act_obj_t *act = NULL;
+ char basename[MAXFNAME];
+ DEFiRet;
+ int fd = -1;
+
+ DBGPRINTF("act_obj_add: edge %p, name '%s' (source '%s')\n", edge, name, source? source : "---");
+
+ if (isIgnoreOlderFile(edge->instarr[0], name)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for(act = edge->active ; act != NULL ; act = act->next) {
+ if(!strcmp(act->name, name)) {
+ if (!source || !act->source_name || !strcmp(act->source_name, source)) {
+ DBGPRINTF("active object '%s' already exists in '%s' - no need to add\n",
+ name, edge->path);
+ FINALIZE;
+ }
+ }
+ }
+ DBGPRINTF("need to add new active object '%s' in '%s' - checking if accessible\n", name, edge->path);
+ fd = open(name, O_RDONLY | O_CLOEXEC);
+ if(fd < 0) {
+ if (is_file) {
+ LogError(errno, RS_RET_ERR, "imfile: error accessing file '%s'", name);
+ } else { /* reporting only in debug for dirs as higher lvl paths are likely blocked by selinux */
+ DBGPRINTF("imfile: error accessing directory '%s'", name);
+ }
+ ABORT_FINALIZE(RS_RET_NO_FILE_ACCESS);
+ }
+ DBGPRINTF("add new active object '%s' in '%s'\n", name, edge->path);
+ CHKmalloc(act = calloc(sizeof(act_obj_t), 1));
+ CHKmalloc(act->name = strdup(name));
+ if (-1 == getBasename((uchar*)basename, (uchar*)name)) {
+ CHKmalloc(act->basename = strdup(name)); /* assume basename is same as name */
+ } else {
+ CHKmalloc(act->basename = strdup(basename));
+ }
+ act->edge = edge;
+ act->ino = ino;
+ act->fd = fd;
+ act->file_id[0] = '\0';
+ act->file_id_prev[0] = '\0';
+ act->is_symlink = is_symlink;
+ act->ratelimiter = NULL;
+ act->time_to_delete = 0;
+ if (source) { /* we are target of symlink */
+ CHKmalloc(act->source_name = strdup(source));
+ } else {
+ act->source_name = NULL;
+ }
+ #ifdef HAVE_INOTIFY_INIT
+ act->wd = in_setupWatch(act, is_file);
+ #endif
+ fen_setupWatch(act);
+ if(is_file && !is_symlink) {
+ const instanceConf_t *const inst = edge->instarr[0];// TODO: same file, multiple instances?
+ CHKiRet(ratelimitNew(&act->ratelimiter, "imfile", name));
+ CHKmalloc(act->multiSub.ppMsgs = malloc(inst->nMultiSub * sizeof(smsg_t *)));
+ act->multiSub.maxElem = inst->nMultiSub;
+ act->multiSub.nElem = 0;
+ pollFile(act);
+ }
+
+ /* all well, add to active list */
+ if(edge->active != NULL) {
+ edge->active->prev = act;
+ }
+ act->next = edge->active;
+ edge->active = act;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(act != NULL) {
+ if (act->ratelimiter != NULL)
+ ratelimitDestruct(act->ratelimiter);
+ free(act->name);
+ free(act);
+ }
+ if(fd != -1) {
+ close(fd);
+ }
+ }
+ RETiRet;
+}
+
+
+/* this walks an edges active list and detects and acts on any changes
+ * seen there. It does NOT detect newly appeared files, as they are not
+ * inside the active list!
+ */
+static void
+detect_updates(fs_edge_t *const edge)
+{
+ act_obj_t *act;
+ struct stat fileInfo;
+ int restart = 0;
+
+ for(act = edge->active ; act != NULL ; act = act->next) {
+ DBGPRINTF("detect_updates checking active obj '%s'\n", act->name);
+ // lstat() has the disadvantage, that we get "deleted" when the name has changed
+ // but inode is still the same (like with logrotate)
+ int r = lstat(act->name, &fileInfo);
+ if(r == -1) { /* object gone away? */
+ /* now let's see if the file itself already exist (e.g. rotated away) */
+ /* NOTE: this will NOT stall the file. The reason is that when a new file
+ * with the same name is detected, we will not run into this code.
+ TODO: check the full implications, there are for sure some!
+ e.g. file has been closed, so we will never have old inode (but
+ why was it closed then? --> check)
+ */
+ r = fstat(act->ino, &fileInfo);
+ if(r == -1) {
+ time_t ttNow;
+ time(&ttNow);
+ if (act->time_to_delete == 0) {
+ act->time_to_delete = ttNow;
+ }
+ /* First time we run into this code, we need to give imfile a little time to process
+ * the old file in case a process is still writing into it until the FILE_DELETE_DELAY
+ * is reached OR the inode has changed (see elseif below). In most cases, the
+ * delay will never be reached and the file will be closed when the inode has changed.
+ * Directories are deleted without delay.
+ */
+ sbool is_file = act->edge->is_file;
+ if (!is_file || act->time_to_delete + FILE_DELETE_DELAY < ttNow) {
+ DBGPRINTF("detect_updates obj gone away, unlinking: "
+ "'%s', ttDelete: %lds, ttNow:%ld isFile: %d\n",
+ act->name, ttNow - (act->time_to_delete + FILE_DELETE_DELAY), ttNow, is_file);
+ act_obj_unlink(act);
+ restart = 1;
+ } else {
+ DBGPRINTF("detect_updates obj gone away, keep '%s' open: %ld/%ld/%lds!\n",
+ act->name, act->time_to_delete, ttNow, ttNow - act->time_to_delete);
+ pollFile(act);
+ }
+ }
+ break;
+ } else if(fileInfo.st_ino != act->ino) {
+ DBGPRINTF("file '%s' inode changed from %llu to %llu, unlinking from "
+ "internal lists\n", act->name, (long long unsigned) act->ino,
+ (long long unsigned) fileInfo.st_ino);
+ act_obj_unlink(act);
+ restart = 1;
+ break;
+ }
+ }
+
+ if (restart) {
+ detect_updates(edge);
+ }
+}
+
+
+/* check if active files need to be processed. This is only needed in
+ * polling mode.
+ */
+static void ATTR_NONNULL()
+poll_active_files(fs_edge_t *const edge)
+{
+ if( runModConf->opMode != OPMODE_POLLING
+ || !edge->is_file
+ || glbl.GetGlobalInputTermState() != 0) {
+ return;
+ }
+
+ act_obj_t *act;
+ for(act = edge->active ; act != NULL ; act = act->next) {
+ fen_setupWatch(act);
+ DBGPRINTF("poll_active_files: polling '%s'\n", act->name);
+ pollFile(act);
+ }
+}
+
+static rsRetVal ATTR_NONNULL()
+process_symlink(fs_edge_t *const chld, const char *symlink)
+{
+ DEFiRet;
+ char *target;
+ CHKmalloc(target = realpath(symlink, NULL));
+ struct stat fileInfo;
+ if(lstat(target, &fileInfo) != 0) {
+ LogError(errno, RS_RET_ERR, "imfile: process_symlink: cannot stat file '%s' - ignored", target);
+ FINALIZE;
+ }
+ const int is_file = (S_ISREG(fileInfo.st_mode));
+ DBGPRINTF("process_symlink: found '%s', File: %d (config file: %d), symlink: %d\n",
+ target, is_file, chld->is_file, 0);
+ if (act_obj_add(chld, target, is_file, fileInfo.st_ino, 0, symlink) == RS_RET_OK) {
+ /* need to watch parent target as well for proper rotation support */
+ uint idx = ustrlen(chld->active->name) - ustrlen(chld->active->basename);
+ if (idx) { /* basename is different from name */
+ char parent[MAXFNAME];
+ idx--; /* move past trailing slash */
+ memcpy(parent, chld->active->name, idx);
+ parent[idx] = '\0';
+ if(lstat(parent, &fileInfo) != 0) {
+ LogError(errno, RS_RET_ERR,
+ "imfile: process_symlink: cannot stat directory '%s' - ignored", parent);
+ FINALIZE;
+ }
+ if (chld->parent->root->edges) {
+ DBGPRINTF("process_symlink: adding parent '%s' of target '%s'\n", parent, target);
+ act_obj_add(chld->parent->root->edges, parent, 0, fileInfo.st_ino, 0, NULL);
+ }
+ }
+ }
+
+finalize_it:
+ free(target);
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+poll_tree(fs_edge_t *const chld)
+{
+ struct stat fileInfo;
+ glob_t files;
+ int need_globfree = 0;
+ int issymlink;
+ DBGPRINTF("poll_tree: chld %p, name '%s', path: %s\n", chld, chld->name, chld->path);
+ detect_updates(chld);
+ const int ret = glob((char*)chld->path, runModConf->sortFiles|GLOB_BRACE, NULL, &files);
+ need_globfree = 1;
+ DBGPRINTF("poll_tree: glob returned %d\n", ret);
+ if(ret == 0) {
+ DBGPRINTF("poll_tree: processing %d files\n", (int) files.gl_pathc);
+ for(unsigned i = 0 ; i < files.gl_pathc ; i++) {
+ if(glbl.GetGlobalInputTermState() != 0) {
+ goto done;
+ }
+ char *const file = files.gl_pathv[i];
+ if(lstat(file, &fileInfo) != 0) {
+ LogError(errno, RS_RET_ERR,
+ "imfile: poll_tree cannot stat file '%s' - ignored", file);
+ continue;
+ }
+
+ if (S_ISLNK(fileInfo.st_mode)) {
+ rsRetVal slink_ret = process_symlink(chld, file);
+ if (slink_ret != RS_RET_OK) {
+ continue;
+ }
+ issymlink = 1;
+ } else {
+ issymlink = 0;
+ }
+ const int is_file = (S_ISREG(fileInfo.st_mode) || issymlink);
+ DBGPRINTF("poll_tree: found '%s', File: %d (config file: %d), symlink: %d\n",
+ file, is_file, chld->is_file, issymlink);
+ if(!is_file && S_ISREG(fileInfo.st_mode)) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING,
+ "imfile: '%s' is neither a regular file, symlink, nor a "
+ "directory - ignored", file);
+ continue;
+ }
+ if(!issymlink && (chld->is_file != is_file)) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING,
+ "imfile: '%s' is %s but %s expected - ignored",
+ file, (is_file) ? "FILE" : "DIRECTORY",
+ (chld->is_file) ? "FILE" : "DIRECTORY");
+ continue;
+ }
+ act_obj_add(chld, file, is_file, fileInfo.st_ino, issymlink, NULL);
+ }
+ }
+
+ poll_active_files(chld);
+
+done:
+ if(need_globfree) {
+ globfree(&files);
+ }
+ return;
+}
+
+#ifdef HAVE_INOTIFY_INIT // TODO: shouldn't we use that in polling as well?
+static void ATTR_NONNULL()
+poll_timeouts(fs_edge_t *const edge)
+{
+ if(edge->is_file) {
+ act_obj_t *act;
+ for(act = edge->active ; act != NULL ; act = act->next) {
+ if(act->pStrm && strmReadMultiLine_isTimedOut(act->pStrm)) {
+ DBGPRINTF("timeout occurred on %s\n", act->name);
+ pollFile(act);
+ }
+ }
+ }
+}
+#endif
+
+
+/* destruct a single act_obj object */
+static void
+act_obj_destroy(act_obj_t *const act, const int is_deleted)
+{
+ uchar *statefn;
+ uchar statefile[MAXFNAME];
+ uchar toDel[MAXFNAME];
+
+ if(act == NULL)
+ return;
+
+ DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
+ act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted,
+ act->in_move);
+ if(act->is_symlink && is_deleted) {
+ act_obj_t *target_act;
+ for(target_act = act->edge->active ; target_act != NULL ; target_act = target_act->next) {
+ if(target_act->source_name && !strcmp(target_act->source_name, act->name)) {
+ DBGPRINTF("act_obj_destroy: detect_updates for parent of target %s of %s symlink\n",
+ target_act->name, act->name);
+ detect_updates(target_act->edge->parent->root->edges);
+ break;
+ }
+ }
+ }
+ if(act->pStrm != NULL) {
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+ pollFile(act); /* get any left-over data */
+ if(inst->bRMStateOnDel) {
+ statefn = getStateFileName(act, statefile, sizeof(statefile));
+ getFullStateFileName(statefn, act->file_id, toDel, sizeof(toDel)); // TODO: check!
+ statefn = toDel;
+ }
+ persistStrmState(act);
+ strm.Destruct(&act->pStrm);
+ /* we delete state file after destruct in case strm obj initiated a write */
+ if(is_deleted && !act->in_move && inst->bRMStateOnDel) {
+ DBGPRINTF("act_obj_destroy: deleting state file %s\n", statefn);
+ unlink((char*)statefn);
+ }
+ }
+ if(act->ratelimiter != NULL) {
+ ratelimitDestruct(act->ratelimiter);
+ }
+ #ifdef HAVE_INOTIFY_INIT
+ if(act->wd != -1) {
+ inotify_rm_watch(ino_fd, act->wd);
+ wdmapDel(act->wd);
+ }
+ #endif
+ if(act->fd >= 0) {
+ close(act->fd);
+ }
+ #if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+ if(act->pfinf != NULL) {
+ free(act->pfinf->fobj.fo_name);
+ free(act->pfinf);
+ }
+ #endif
+ free(act->basename);
+ free(act->source_name);
+ free(act->multiSub.ppMsgs);
+ #if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+ act->is_deleted = 1;
+ #else
+ free(act->name);
+ free(act);
+ #endif
+}
+
+
+/* destroy complete act list starting at given node */
+static void
+act_obj_destroy_all(act_obj_t *act)
+{
+ if(act == NULL)
+ return;
+
+ DBGPRINTF("act_obj_destroy_all: act %p '%s', wd %d, pStrm %p\n", act, act->name, act->wd, act->pStrm);
+ while(act != NULL) {
+ act_obj_t *const toDel = act;
+ act = act->next;
+ act_obj_destroy(toDel, 0);
+ }
+}
+
+#if 0
+/* debug: find if ptr is still present in list */
+static void
+chk_active(const act_obj_t *act, const act_obj_t *const deleted)
+{
+ while(act != NULL) {
+ DBGPRINTF("chk_active %p vs %p\n", act, deleted);
+ if(act->prev == deleted)
+ DBGPRINTF("chk_active %p prev points to %p\n", act, deleted);
+ if(act->next == deleted)
+ DBGPRINTF("chk_active %p next points to %p\n", act, deleted);
+ act = act->next;
+ DBGPRINTF("chk_active next %p\n", act);
+ }
+}
+#endif
+
+/* unlink act object from linked list and then
+ * destruct it.
+ */
+static void ATTR_NONNULL()
+act_obj_unlink(act_obj_t *act)
+{
+ DBGPRINTF("act_obj_unlink %p: %s, pStrm %p, ttDelete: %ld\n",
+ act, act->name, act->pStrm, act->time_to_delete);
+ if(act->prev == NULL) {
+ act->edge->active = act->next;
+ } else {
+ act->prev->next = act->next;
+ }
+ if(act->next != NULL) {
+ act->next->prev = act->prev;
+ }
+ act_obj_destroy(act, 1);
+ act = NULL;
+}
+
+static void
+fs_node_destroy(fs_node_t *const node)
+{
+ fs_edge_t *edge;
+ DBGPRINTF("node destroy: %p edges:\n", node);
+
+ for(edge = node->edges ; edge != NULL ; ) {
+ detect_updates(edge);
+ fs_node_destroy(edge->node);
+ fs_edge_t *const toDel = edge;
+ edge = edge->next;
+ act_obj_destroy_all(toDel->active);
+ free(toDel->name);
+ free(toDel->path);
+ free(toDel->instarr);
+ free(toDel);
+ }
+ free(node);
+}
+
+static void ATTR_NONNULL(1, 2)
+fs_node_walk(fs_node_t *const node,
+ void (*f_usr)(fs_edge_t*const))
+{
+ DBGPRINTF("node walk: %p edges:\n", node);
+
+ fs_edge_t *edge;
+ for(edge = node->edges ; edge != NULL ; edge = edge->next) {
+ DBGPRINTF("node walk: child %p '%s'\n", edge->node, edge->name);
+ f_usr(edge);
+ fs_node_walk(edge->node, f_usr);
+ }
+}
+
+
+
+/* add a file system object to config tree (or update existing node with new monitor)
+ */
+static rsRetVal
+fs_node_add(fs_node_t *const node,
+ fs_node_t *const source,
+ const uchar *const toFind,
+ const size_t pathIdx,
+ instanceConf_t *const inst)
+{
+ DEFiRet;
+ fs_edge_t *newchld = NULL;
+ int i;
+
+ DBGPRINTF("fs_node_add(%p, '%s') enter, idx %zd\n",
+ node, toFind+pathIdx, pathIdx);
+ assert(toFind[0] != '\0');
+ for(i = pathIdx ; (toFind[i] != '\0') && (toFind[i] != '/') ; ++i)
+ /*JUST SKIP*/;
+ const int isFile = (toFind[i] == '\0') ? 1 : 0;
+ uchar ourPath[PATH_MAX];
+ if(i == 0) {
+ ourPath[0] = '/';
+ ourPath[1] = '\0';
+ } else {
+ memcpy(ourPath, toFind, i);
+ ourPath[i] = '\0';
+ }
+ const size_t nextPathIdx = i+1;
+ const size_t len = i - pathIdx;
+ uchar name[PATH_MAX];
+ memcpy(name, toFind+pathIdx, len);
+ name[len] = '\0';
+ DBGPRINTF("fs_node_add: name '%s'\n", name);
+ node->root = source;
+
+ fs_edge_t *chld;
+ for(chld = node->edges ; chld != NULL ; chld = chld->next) {
+ if(!ustrcmp(chld->name, name)) {
+ DBGPRINTF("fs_node_add(%p, '%s') found '%s'\n", chld->node, toFind, name);
+ /* add new instance */
+ instanceConf_t **instarr_new = realloc(chld->instarr,
+ sizeof(instanceConf_t*) * (chld->ninst+1));
+ CHKmalloc(instarr_new);
+ chld->instarr = instarr_new;
+ chld->ninst++;
+ chld->instarr[chld->ninst-1] = inst;
+ /* recurse */
+ if(!isFile) {
+ CHKiRet(fs_node_add(chld->node, node, toFind, nextPathIdx, inst));
+ }
+ FINALIZE;
+ }
+ }
+
+ /* could not find node --> add it */
+ DBGPRINTF("fs_node_add(%p, '%s') did not find '%s' - adding it\n",
+ node, toFind, name);
+ CHKmalloc(newchld = calloc(sizeof(fs_edge_t), 1));
+ CHKmalloc(newchld->name = ustrdup(name));
+ CHKmalloc(newchld->node = calloc(sizeof(fs_node_t), 1));
+ CHKmalloc(newchld->path = ustrdup(ourPath));
+ CHKmalloc(newchld->instarr = calloc(sizeof(instanceConf_t*), 1));
+ newchld->instarr[0] = inst;
+ newchld->is_file = isFile;
+ newchld->ninst = 1;
+ newchld->parent = node;
+
+ DBGPRINTF("fs_node_add(%p, '%s') returns %p\n", node, toFind, newchld->node);
+
+ if(!isFile) {
+ CHKiRet(fs_node_add(newchld->node, node, toFind, nextPathIdx, inst));
+ }
+
+ /* link to list */
+ newchld->next = node->edges;
+ node->edges = newchld;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(newchld != NULL) {
+ free(newchld->name);
+ free(newchld->node);
+ free(newchld->path);
+ free(newchld->instarr);
+ free(newchld);
+ }
+ }
+ RETiRet;
+}
+
+
+/* Helper function to combine statefile and state file directory
+ * This function is guranteed to work only on config data and DOES NOT
+ * open or otherwise modify disk file state.
+ */
+static int ATTR_NONNULL()
+getFullStateFileName(const uchar *const pszstatefile,
+ const char *const file_id,
+ uchar *const pszout,
+ const size_t ilenout)
+{
+ int lenout;
+ const uchar* pszstatedir;
+
+ /* Get Raw Workdir, if it is NULL we need to propper handle it */
+ pszstatedir = getStateFileDir();
+
+ /* Construct file name */
+ lenout = snprintf((char*)pszout, ilenout, "%s/%s%s%s",
+ (char*) (pszstatedir == NULL ? "." : (char*) pszstatedir), (char*)pszstatefile,
+ (*file_id == '\0') ? "" : ":", file_id);
+
+ /* return out length */
+ return lenout;
+}
+
+
+/* hash function for file-id
+ * Takes a block of data and returns a string with the hash value.
+ *
+ * Currently one provided by Aaaron Wiebe based on perl's hashing algorithm
+ * (so probably pretty generic). Not for excessively large strings!
+ * TODO: re-think the hash function!
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static void __attribute__((nonnull(1,3)))
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+get_file_id_hash(const char *data, size_t lendata,
+ char *const hash_str, const size_t len_hash_str)
+{
+ assert(len_hash_str >= 17); /* we always generate 8-byte strings */
+
+ size_t i;
+ uint8_t out[8], k[16];
+ for (i = 0; i < 16; ++i)
+ k[i] = i;
+ memset(out, 0, sizeof(out));
+ rs_siphash((const uint8_t *)data, lendata, k, out, 8);
+
+ for(i = 0 ; i < 8 ; ++i) {
+ if(2 * i+1 >= len_hash_str)
+ break;
+ snprintf(hash_str+(2*i), 3, "%2.2x", out[i]);
+ }
+}
+
+
+/* this returns the file-id for a given file
+ */
+static void ATTR_NONNULL(1)
+getFileID(act_obj_t *const act)
+{
+ char tmp_id[FILE_ID_HASH_SIZE];
+ strncpy(tmp_id, (const char*)act->file_id, FILE_ID_HASH_SIZE);
+ act->file_id[0] = '\0';
+ assert(act->fd >= 0); /* fd must have been opened at act_obj_t creation! */
+ char filedata[FILE_ID_SIZE];
+ lseek(act->fd, 0, SEEK_SET); /* Seek to beginning of file so we have correct id */
+ const int r = read(act->fd, filedata, FILE_ID_SIZE);
+ if(r == FILE_ID_SIZE) {
+ get_file_id_hash(filedata, sizeof(filedata), act->file_id, sizeof(act->file_id));
+ } else {
+ DBGPRINTF("getFileID partial or error read, ret %d\n", r);
+ }
+ if (strncmp(tmp_id, act->file_id, FILE_ID_HASH_SIZE)) {/* save the old id for cleaning purposes */
+ strncpy(act->file_id_prev, tmp_id, FILE_ID_HASH_SIZE);
+ }
+ DBGPRINTF("getFileID for '%s', file_id_hash '%s'\n", act->name, act->file_id);
+}
+
+/* this generates a state file name suitable for the given file. To avoid
+ * malloc calls, it must be passed a buffer which should be MAXFNAME large.
+ * Note: the buffer is not necessarily populated ... always ONLY use the
+ * RETURN VALUE!
+ * This function is guranteed to work only on config data and DOES NOT
+ * open or otherwise modify disk file state.
+ */
+static uchar * ATTR_NONNULL(1, 2)
+getStateFileName(const act_obj_t *const act,
+ uchar *const __restrict__ buf,
+ const size_t lenbuf)
+{
+ DBGPRINTF("getStateFileName for '%s'\n", act->name);
+ snprintf((char*)buf, lenbuf - 1, "imfile-state:%lld", (long long) act->ino);
+ DBGPRINTF("getStateFileName: state file name now is %s\n", buf);
+ return buf;
+}
+
+static rsRetVal
+checkPerMinuteRateLimits(per_minute_rate_limit_t *per_minute_rate_limits,
+ const size_t msgLen)
+{
+ DEFiRet;
+ time_t current_minute = time(NULL)/60;
+ if(per_minute_rate_limits->maxBytesPerMinute) {
+ if (per_minute_rate_limits->rateLimitingMinute == current_minute) {
+ per_minute_rate_limits->bytesThisMinute += msgLen;
+ /* if we would breach our rate limit then do not send the message. */
+ if (per_minute_rate_limits->bytesThisMinute > per_minute_rate_limits->maxBytesPerMinute) {
+ ABORT_FINALIZE(RS_RET_RATE_LIMITED);
+ }
+ } else {
+ per_minute_rate_limits->rateLimitingMinute = current_minute;
+ per_minute_rate_limits->bytesThisMinute = msgLen; /* Update count as message will be sent */
+ }
+ }
+ if(per_minute_rate_limits->maxLinesPerMinute) {
+ if (per_minute_rate_limits->rateLimitingMinute == current_minute) {
+ per_minute_rate_limits->linesThisMinute++;
+ /* if we would breach our rate limit then do not send the message. */
+ if (per_minute_rate_limits->linesThisMinute > per_minute_rate_limits->maxLinesPerMinute) {
+ ABORT_FINALIZE(RS_RET_RATE_LIMITED);
+ }
+ } else {
+ per_minute_rate_limits->rateLimitingMinute = current_minute;
+ per_minute_rate_limits->linesThisMinute = 1; /* Update count as message will be sent */
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* enqueue the read file line as a message. The provided string is
+ * not freed - this must be done by the caller.
+ */
+#define MAX_OFFSET_REPRESENTATION_NUM_BYTES 20
+static rsRetVal ATTR_NONNULL(1,2)
+enqLine(act_obj_t *const act,
+ cstr_t *const __restrict__ cstrLine,
+ const int64 strtOffs)
+{
+ DEFiRet;
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+ smsg_t *pMsg;
+ uchar file_offset[MAX_OFFSET_REPRESENTATION_NUM_BYTES+1];
+ const uchar *metadata_names[2] = {(uchar *)"filename",(uchar *)"fileoffset"} ;
+ const uchar *metadata_values[2] ;
+ const size_t msgLen = cstrLen(cstrLine);
+
+ if(msgLen == 0) {
+ /* we do not process empty lines */
+ FINALIZE;
+ }
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ if(inst->addCeeTag) {
+ /* Make sure we account for terminating null byte */
+ size_t ceeMsgSize = msgLen + CONST_LEN_CEE_COOKIE + 1;
+ char *ceeMsg;
+ CHKmalloc(ceeMsg = malloc(ceeMsgSize));
+ strcpy(ceeMsg, CONST_CEE_COOKIE);
+ strcat(ceeMsg, (char*)rsCStrGetSzStrNoNULL(cstrLine));
+ MsgSetRawMsg(pMsg, ceeMsg, ceeMsgSize);
+ free(ceeMsg);
+ } else {
+ MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStrNoNULL(cstrLine), msgLen);
+ }
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetTAG(pMsg, inst->pszTag, inst->lenTag);
+ msgSetPRI(pMsg, inst->iFacility | inst->iSeverity);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ if(inst->addMetadata) {
+ if (act->source_name) {
+ metadata_values[0] = (const uchar*)act->source_name;
+ } else {
+ metadata_values[0] = (const uchar*)act->name;
+ }
+ snprintf((char *)file_offset, MAX_OFFSET_REPRESENTATION_NUM_BYTES+1, "%lld", strtOffs);
+ metadata_values[1] = file_offset;
+ msgAddMultiMetadata(pMsg, metadata_names, metadata_values, 2);
+ }
+
+ if(inst->perMinuteRateLimits.maxBytesPerMinute || inst->perMinuteRateLimits.maxLinesPerMinute) {
+ CHKiRet(checkPerMinuteRateLimits((per_minute_rate_limit_t *)&inst->perMinuteRateLimits, msgLen));
+ }
+
+ if(inst->delay_perMsg) {
+ srSleep(inst->delay_perMsg % 1000000, inst->delay_perMsg / 1000000);
+ }
+
+ pMsg->msgFlags = pMsg->msgFlags | inst->msgFlag;
+
+ ratelimitAddMsg(act->ratelimiter, &act->multiSub, pMsg);
+finalize_it:
+ RETiRet;
+}
+/* try to open a file which has a state file. If the state file does not
+ * exist or cannot be read, an error is returned.
+ */
+static rsRetVal ATTR_NONNULL(1)
+openFileWithStateFile(act_obj_t *const act)
+{
+ DEFiRet;
+ uchar pszSFNam[MAXFNAME];
+ uchar statefile[MAXFNAME];
+ int fd = -1;
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+
+ uchar *const statefn = getStateFileName(act, statefile, sizeof(statefile));
+ getFileID(act);
+
+ getFullStateFileName(statefn, act->file_id, pszSFNam, sizeof(pszSFNam));
+ DBGPRINTF("trying to open state for '%s', state file '%s'\n", act->name, pszSFNam);
+
+ /* check if the file exists */
+ fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
+ if(fd < 0) {
+ if(errno == ENOENT) {
+ if(act->file_id[0] != '\0') {
+ DBGPRINTF("state file %s for %s does not exist - trying to see if "
+ "inode-only file exists\n", pszSFNam, act->name);
+ getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
+ fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
+ if(fd >= 0) {
+ dbgprintf("found inode-only state file, will be renamed at next persist\n");
+ }
+ }
+ if(fd < 0) {
+ DBGPRINTF("state file %s for %s does not exist - trying to see if "
+ "old-style file exists\n", pszSFNam, act->name);
+ CHKiRet(OLD_openFileWithStateFile(act));
+ FINALIZE;
+ }
+ } else {
+ LogError(errno, RS_RET_IO_ERROR,
+ "imfile error trying to access state file for '%s'",
+ act->name);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ }
+
+ DBGPRINTF("opened state file %s for %s\n", pszSFNam, act->name);
+ CHKiRet(strm.Construct(&act->pStrm));
+
+ struct json_object *jval;
+ struct json_object *json = fjson_object_from_fd(fd);
+ if(json == NULL) {
+ LogError(0, RS_RET_ERR, "imfile: error reading state file for '%s'", act->name);
+ }
+
+ /* we access some data items a bit dirty, as we need to refactor the whole
+ * thing in any case - TODO
+ */
+ /* Note: we ignore filname property - it is just an aid to the user. Most
+ * importantly it *is wrong* after a file move!
+ */
+ fjson_object_object_get_ex(json, "prev_was_nl", &jval);
+ act->pStrm->bPrevWasNL = fjson_object_get_int(jval);
+
+ fjson_object_object_get_ex(json, "curr_offs", &jval);
+ act->pStrm->iCurrOffs = fjson_object_get_int64(jval);
+
+ fjson_object_object_get_ex(json, "strt_offs", &jval);
+ act->pStrm->strtOffs = fjson_object_get_int64(jval);
+
+ fjson_object_object_get_ex(json, "prev_line_segment", &jval);
+ const uchar *const prev_line_segment = (const uchar*)fjson_object_get_string(jval);
+ if(jval != NULL) {
+ CHKiRet(rsCStrConstructFromszStr(&act->pStrm->prevLineSegment, prev_line_segment));
+ cstrFinalize(act->pStrm->prevLineSegment);
+ uchar *ret = rsCStrGetSzStrNoNULL(act->pStrm->prevLineSegment);
+ DBGPRINTF("prev_line_segment present in state file 2, is: %s\n", ret);
+ }
+
+ fjson_object_object_get_ex(json, "prev_msg_segment", &jval);
+ const uchar *const prev_msg_segment = (const uchar*)fjson_object_get_string(jval);
+ if(jval != NULL) {
+ CHKiRet(rsCStrConstructFromszStr(&act->pStrm->prevMsgSegment, prev_msg_segment));
+ cstrFinalize(act->pStrm->prevMsgSegment);
+ uchar *ret = rsCStrGetSzStrNoNULL(act->pStrm->prevMsgSegment);
+ DBGPRINTF("prev_msg_segment present in state file 2, is: %s\n", ret);
+ }
+ fjson_object_put(json);
+
+ CHKiRet(strm.SetFName(act->pStrm, (uchar*)act->name, strlen(act->name)));
+ CHKiRet(strm.SettOperationsMode(act->pStrm, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(act->pStrm, STREAMTYPE_FILE_MONITOR));
+ CHKiRet(strm.SetFileNotFoundError(act->pStrm, inst->fileNotFoundError));
+ CHKiRet(strm.ConstructFinalize(act->pStrm));
+
+ CHKiRet(strm.SeekCurrOffs(act->pStrm));
+
+finalize_it:
+ if(fd >= 0) {
+ close(fd);
+ }
+ RETiRet;
+}
+
+/* try to open a file for which no state file exists. This function does NOT
+ * check if a state file actually exists or not -- this must have been
+ * checked before calling it.
+ */
+static rsRetVal
+openFileWithoutStateFile(act_obj_t *const act)
+{
+ DEFiRet;
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+
+ DBGPRINTF("clean startup withOUT state file for '%s'\n", act->name);
+ if(act->pStrm != NULL)
+ strm.Destruct(&act->pStrm);
+ CHKiRet(strm.Construct(&act->pStrm));
+ CHKiRet(strm.SettOperationsMode(act->pStrm, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(act->pStrm, STREAMTYPE_FILE_MONITOR));
+ CHKiRet(strm.SetFName(act->pStrm, (uchar*)act->name, strlen(act->name)));
+ CHKiRet(strm.SetFileNotFoundError(act->pStrm, inst->fileNotFoundError));
+ CHKiRet(strm.ConstructFinalize(act->pStrm));
+
+ /* As a state file not exist, this is a fresh start. seek to file end
+ * when freshStartTail is on.
+ */
+ if(inst->freshStartTail) {
+ const int fd = open(act->name, O_RDONLY | O_CLOEXEC);
+ if(fd >= 0) {
+ act->pStrm->iCurrOffs = lseek64(fd, 0, SEEK_END);
+ close(fd);
+ if(act->pStrm->iCurrOffs < 0) {
+ act->pStrm->iCurrOffs = 0;
+ LogError(errno, RS_RET_ERR, "imfile: could not query current "
+ "file size for %s - 'freshStartTail' option will "
+ "be ignored, starting at begin of file", inst->pszFileName);
+ }
+ CHKiRet(strm.SeekCurrOffs(act->pStrm));
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* try to open a file. This involves checking if there is a status file and,
+ * if so, reading it in. Processing continues from the last known location.
+ */
+static rsRetVal
+openFile(act_obj_t *const act)
+{
+ DEFiRet;
+ const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+
+ CHKiRet_Hdlr(openFileWithStateFile(act)) {
+ CHKiRet(openFileWithoutStateFile(act));
+ }
+
+ DBGPRINTF("breopenOnTruncate %d for '%s'\n", inst->reopenOnTruncate, act->name);
+ CHKiRet(strm.SetbReopenOnTruncate(act->pStrm, inst->reopenOnTruncate));
+ strmSetReadTimeout(act->pStrm, inst->readTimeout);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case
+ * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27
+ */
+static void pollFileCancelCleanup(void *pArg)
+{
+ cstr_t **ppCStr = (cstr_t**) pArg;
+ if(*ppCStr != NULL)
+ rsCStrDestruct(ppCStr);
+}
+
+
+/* pollFile needs to be split due to the unfortunate pthread_cancel_push() macros. */
+static rsRetVal ATTR_NONNULL()
+pollFileReal(act_obj_t *act, cstr_t **pCStr)
+{
+ int64 strtOffs;
+ DEFiRet;
+ int64_t startOffs = 0;
+ int nProcessed = 0;
+ regex_t *start_preg = NULL, *end_preg = NULL;
+
+ DBGPRINTF("pollFileReal enter, act %p, pStrm %p, name '%s'\n", act, act->pStrm, act->name);
+ DBGPRINTF("pollFileReal enter, edge %p\n", act->edge);
+ DBGPRINTF("pollFileReal enter, edge->instarr %p\n", act->edge->instarr);
+
+ instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+
+ if(act->pStrm == NULL) {
+ CHKiRet(openFile(act)); /* open file */
+ }
+
+ start_preg = (inst->startRegex == NULL) ? NULL : &inst->start_preg;
+ end_preg = (inst->endRegex == NULL) ? NULL : &inst->end_preg;
+
+ startOffs = act->pStrm->iCurrOffs;
+ /* loop below will be exited when strmReadLine() returns EOF */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ if(inst->maxLinesAtOnce != 0 && nProcessed >= inst->maxLinesAtOnce)
+ break;
+ if((start_preg == NULL) && (end_preg == NULL)) {
+ CHKiRet(strm.ReadLine(act->pStrm, pCStr, inst->readMode, inst->escapeLF, inst->escapeLFString,
+ inst->trimLineOverBytes, &strtOffs));
+ } else {
+ CHKiRet(strmReadMultiLine(act->pStrm, pCStr, start_preg, end_preg,
+ inst->escapeLF, inst->escapeLFString, inst->discardTruncatedMsg,
+ inst->msgDiscardingError, &strtOffs));
+ }
+ ++nProcessed;
+ if(startOffs < FILE_ID_SIZE && act->pStrm->iCurrOffs >= FILE_ID_SIZE) {
+ dbgprintf("initiating state file write as sufficient data is now present; file=%s\n",
+ act->name);
+ persistStrmState(act);
+ startOffs = act->pStrm->iCurrOffs; /* disable check */
+ }
+ runModConf->bHadFileData = 1; /* this is just a flag, so set it and forget it */
+ CHKiRet(enqLine(act, *pCStr, strtOffs)); /* process line */
+ rsCStrDestruct(pCStr); /* discard string (must be done by us!) */
+ if(inst->iPersistStateInterval > 0 && ++act->nRecords >= inst->iPersistStateInterval) {
+ persistStrmState(act);
+ act->nRecords = 0;
+ }
+ }
+
+finalize_it:
+ multiSubmitFlush(&act->multiSub);
+ if(inst->bPersistStateAfterSubmission) {
+ persistStrmState(act);
+ }
+
+ if(*pCStr != NULL) {
+ rsCStrDestruct(pCStr);
+ }
+
+ RETiRet;
+}
+
+/* poll a file, need to check file rollover etc. open file if not open */
+static rsRetVal ATTR_NONNULL(1)
+pollFile(act_obj_t *const act)
+{
+ cstr_t *pCStr = NULL;
+ DEFiRet;
+ if (act->is_symlink) {
+ FINALIZE; /* no reason to poll symlink file */
+ }
+ /* Note: we must do pthread_cleanup_push() immediately, because the POSIX macros
+ * otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14
+ */
+ pthread_cleanup_push(pollFileCancelCleanup, &pCStr);
+ iRet = pollFileReal(act, &pCStr);
+ pthread_cleanup_pop(0);
+finalize_it: RETiRet;
+}
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal ATTR_NONNULL(1)
+createInstance(instanceConf_t **const pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pBindRuleset = NULL;
+
+ inst->pszBindRuleset = NULL;
+ inst->pszFileName = NULL;
+ inst->pszTag = NULL;
+ inst->pszStateFile = NULL;
+ inst->nMultiSub = NUM_MULTISUB;
+ inst->iSeverity = 5;
+ inst->iFacility = 128;
+ inst->maxLinesAtOnce = 0;
+ inst->trimLineOverBytes = 0;
+ inst->iPersistStateInterval = 0;
+ inst->perMinuteRateLimits.maxBytesPerMinute = 0;
+ inst->perMinuteRateLimits.maxLinesPerMinute = 0;
+ inst->perMinuteRateLimits.rateLimitingMinute = 0;
+ inst->perMinuteRateLimits.linesThisMinute = 0;
+ inst->perMinuteRateLimits.bytesThisMinute = 0;
+ inst->bPersistStateAfterSubmission = 0;
+ inst->readMode = 0;
+ inst->startRegex = NULL;
+ inst->endRegex = NULL;
+ inst->discardTruncatedMsg = 0;
+ inst->msgDiscardingError = 1;
+ inst->bRMStateOnDel = 1;
+ inst->escapeLF = 1;
+ inst->escapeLFString = NULL;
+ inst->reopenOnTruncate = 0;
+ inst->addMetadata = ADD_METADATA_UNSPECIFIED;
+ inst->addCeeTag = 0;
+ inst->freshStartTail = 0;
+ inst->fileNotFoundError = 1;
+ inst->readTimeout = loadModConf->readTimeout;
+ inst->delay_perMsg = 0;
+ inst->msgFlag = 0;
+ inst->ignoreOlderThan = 0;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+/* the basen(ame) buffer must be of size MAXFNAME
+ * returns the index of the slash in front of basename
+ */
+static int ATTR_NONNULL()
+getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path)
+{
+ int i;
+ int found = 0;
+ const int lenName = ustrlen(path);
+ for(i = lenName ; i >= 0 ; --i) {
+ if(path[i] == '/') {
+ /* found basename component */
+ found = 1;
+ if(i == lenName)
+ basen[0] = '\0';
+ else {
+ memcpy(basen, path+i+1, lenName-i);
+ }
+ break;
+ }
+ }
+ if (found == 1)
+ return i;
+ else {
+ return -1;
+ }
+}
+
+/* this function checks instance parameters and does some required pre-processing
+ */
+static rsRetVal ATTR_NONNULL()
+checkInstance(instanceConf_t *const inst)
+{
+ uchar curr_wd[MAXFNAME];
+ DEFiRet;
+
+ /* this is primarily for the clang static analyzer, but also
+ * guards against logic errors in the config handler.
+ */
+ if(inst->pszFileName == NULL)
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+
+ CHKmalloc(inst->pszFileName_forOldStateFile = ustrdup(inst->pszFileName));
+ if(loadModConf->normalizePath) {
+ if(inst->pszFileName[0] == '.' && inst->pszFileName[1] == '/') {
+ DBGPRINTF("imfile: removing heading './' from name '%s'\n", inst->pszFileName);
+ memmove(inst->pszFileName, inst->pszFileName+2, ustrlen(inst->pszFileName) - 1);
+ }
+
+ if(inst->pszFileName[0] != '/') {
+ if(getcwd((char*)curr_wd, MAXFNAME) == NULL || curr_wd[0] != '/') {
+ LogError(errno, RS_RET_ERR, "imfile: error querying current working "
+ "directory - can not continue with %s", inst->pszFileName);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ const size_t len_curr_wd = ustrlen(curr_wd);
+ if(len_curr_wd + ustrlen(inst->pszFileName) + 1 >= MAXFNAME) {
+ LogError(0, RS_RET_ERR, "imfile: length of configured file and current "
+ "working directory exceeds permitted size - ignoring %s",
+ inst->pszFileName);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ curr_wd[len_curr_wd] = '/';
+ strcpy((char*)curr_wd+len_curr_wd+1, (char*)inst->pszFileName);
+ free(inst->pszFileName);
+ CHKmalloc(inst->pszFileName = ustrdup(curr_wd));
+ }
+ }
+ dbgprintf("imfile: adding file monitor for '%s'\n", inst->pszFileName);
+
+ if(inst->pszTag != NULL) {
+ inst->lenTag = ustrlen(inst->pszTag);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* add a new monitor */
+static rsRetVal
+addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ if(cs.pszFileName == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can "
+ "not be created");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(cs.pszFileTag == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given, file monitor can "
+ "not be created");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ CHKiRet(createInstance(&inst));
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ CHKmalloc(inst->pszFileName = ustrdup((char*) cs.pszFileName));
+ CHKmalloc(inst->pszTag = ustrdup((char*) cs.pszFileTag));
+ if(cs.pszStateFile == NULL) {
+ inst->pszStateFile = NULL;
+ } else {
+ CHKmalloc(inst->pszStateFile = ustrdup(cs.pszStateFile));
+ }
+ inst->iSeverity = cs.iSeverity;
+ inst->iFacility = cs.iFacility;
+ if(cs.maxLinesAtOnce) {
+ if(loadModConf->opMode == OPMODE_INOTIFY) {
+ LogError(0, RS_RET_PARAM_NOT_PERMITTED,
+ "parameter \"maxLinesAtOnce\" not "
+ "permited in inotify mode - ignored");
+ } else {
+ inst->maxLinesAtOnce = cs.maxLinesAtOnce;
+ }
+ }
+ inst->trimLineOverBytes = cs.trimLineOverBytes;
+ inst->ignoreOlderThan = 0;
+ inst->iPersistStateInterval = cs.iPersistStateInterval;
+ inst->perMinuteRateLimits.maxBytesPerMinute = cs.maxBytesPerMinute;
+ inst->perMinuteRateLimits.maxLinesPerMinute = cs.maxLinesPerMinute;
+ inst->bPersistStateAfterSubmission = 0;
+ inst->readMode = cs.readMode;
+ inst->escapeLF = 0;
+ inst->escapeLFString = NULL;
+ inst->reopenOnTruncate = 0;
+ inst->addMetadata = 0;
+ inst->addCeeTag = 0;
+ inst->bRMStateOnDel = 0;
+ inst->readTimeout = loadModConf->readTimeout;
+ inst->msgFlag = 0;
+
+ CHKiRet(checkInstance(inst));
+
+ /* reset legacy system */
+ cs.iPersistStateInterval = 0;
+ resetConfigVariables(NULL, NULL); /* values are both dummies */
+
+finalize_it:
+ free(pNewVal); /* we do not need it, but we must free it! */
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imfile)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("input param blk in imfile:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "file")) {
+ inst->pszFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "statefile")) {
+ inst->pszStateFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "removestateondelete")) {
+ inst->bRMStateOnDel = (uint8_t) pvals[i].val.d.n; // TODO: duplicate!
+ } else if(!strcmp(inppblk.descr[i].name, "tag")) {
+ inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "severity")) {
+ inst->iSeverity = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "facility")) {
+ inst->iFacility = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "readmode")) {
+ inst->readMode = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "startmsg.regex")) {
+ inst->startRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "endmsg.regex")) {
+ inst->endRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) {
+ inst->discardTruncatedMsg = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "msgdiscardingerror")) {
+ inst->msgDiscardingError = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "deletestateonfiledelete")) {
+ inst->bRMStateOnDel = (sbool) pvals[i].val.d.n; // TODO: duplicate!
+ } else if(!strcmp(inppblk.descr[i].name, "addmetadata")) {
+ inst->addMetadata = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "delay.message")) {
+ inst->delay_perMsg = (unsigned) pvals[i].val.d.n;
+ } else if (!strcmp(inppblk.descr[i].name, "addceetag")) {
+ inst->addCeeTag = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "freshstarttail")) {
+ inst->freshStartTail = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "filenotfounderror")) {
+ inst->fileNotFoundError = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "escapelf")) {
+ inst->escapeLF = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "escapelf.replacement")) {
+ inst->escapeLFString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "reopenontruncate")) {
+ inst->reopenOnTruncate = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) {
+ if( loadModConf->opMode == OPMODE_INOTIFY
+ && pvals[i].val.d.n > 0) {
+ LogError(0, RS_RET_PARAM_NOT_PERMITTED,
+ "parameter \"maxLinesAtOnce\" not "
+ "permited in inotify mode - ignored");
+ } else {
+ inst->maxLinesAtOnce = pvals[i].val.d.n;
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "trimlineoverbytes")) {
+ inst->trimLineOverBytes = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ignoreolderthan")) {
+ inst->ignoreOlderThan = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "persiststateinterval")) {
+ inst->iPersistStateInterval = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxbytesperminute")) {
+ DBGPRINTF("imfile: enabling maxbytesperminute ratelimiting\n");
+ inst->perMinuteRateLimits.maxBytesPerMinute = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxlinesperminute")) {
+ DBGPRINTF("imfile: enabling maxlinesperminute ratelimiting\n");
+ inst->perMinuteRateLimits.maxLinesPerMinute = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "persiststateaftersubmission")) {
+ inst->bPersistStateAfterSubmission = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) {
+ inst->nMultiSub = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "readtimeout")) {
+ inst->readTimeout = pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "needparse")) {
+ inst->msgFlag = pvals[i].val.d.n ? NEEDS_PARSING : 0;
+ } else {
+ DBGPRINTF("program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+ i = (inst->readMode > 0) ? 1 : 0;
+ i = (NULL != inst->startRegex) ? (i+1) : i;
+ i = (NULL != inst->endRegex) ? (i+1) : i;
+ if(i > 1) {
+ LogError(0, RS_RET_PARAM_NOT_PERMITTED,
+ "only one of readMode or startmsg.regex or endmsg.regex can be set "
+ "at the same time");
+ ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED);
+ }
+
+ if(inst->startRegex != NULL) {
+ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED);
+ if(errcode != 0) {
+ char errbuff[512];
+ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff));
+ parser_errmsg("imfile: error in startmsg.regex expansion: %s", errbuff);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ if(inst->endRegex != NULL) {
+ const int errcode = regcomp(&inst->end_preg, (char*)inst->endRegex, REG_EXTENDED);
+ if(errcode != 0) {
+ char errbuff[512];
+ regerror(errcode, &inst->end_preg, errbuff, sizeof(errbuff));
+ parser_errmsg("imfile: error in endmsg.regex expansion: %s", errbuff);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ if(inst->readTimeout != 0)
+ loadModConf->haveReadTimeouts = 1;
+ iRet = checkInstance(inst);
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ currModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ loadModConf->opMode = OPMODE_POLLING;
+ loadModConf->iPollInterval = DFLT_PollInterval;
+ loadModConf->configSetViaV2Method = 0;
+ loadModConf->readTimeout = 0; /* default: no timeout */
+ loadModConf->timeoutGranularity = 1000; /* default: 1 second */
+ loadModConf->haveReadTimeouts = 0; /* default: no timeout */
+ loadModConf->normalizePath = 1;
+ loadModConf->sortFiles = GLOB_NOSORT;
+ loadModConf->stateFileDirectory = NULL;
+ loadModConf->conf_tree = calloc(sizeof(fs_node_t), 1);
+ loadModConf->conf_tree->edges = NULL;
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ cs.pszFileName = NULL;
+ cs.pszFileTag = NULL;
+ cs.pszStateFile = NULL;
+ cs.iPollInterval = DFLT_PollInterval;
+ cs.iPersistStateInterval = 0;
+ cs.iFacility = 128;
+ cs.iSeverity = 5;
+ cs.readMode = 0;
+ cs.maxLinesAtOnce = 10240;
+ cs.trimLineOverBytes = 0;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ #if defined(HAVE_PORT_SOURCE_FILE)
+ /* this means we are on Solaris, so inotify is not there */
+ loadModConf->opMode = OPMODE_FEN;
+ #elif defined(HAVE_INOTIFY_INIT)
+ loadModConf->opMode = OPMODE_INOTIFY;
+ #else
+ loadModConf->opMode = OPMODE_POLLING;
+ #endif
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imfile: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("module (global) param blk for imfile:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "pollinginterval")) {
+ loadModConf->iPollInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "readtimeout")) {
+ loadModConf->readTimeout = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "timeoutgranularity")) {
+ /* note: we need ms, thus "* 1000" */
+ loadModConf->timeoutGranularity = (int) pvals[i].val.d.n * 1000;
+ } else if(!strcmp(modpblk.descr[i].name, "sortfiles")) {
+ loadModConf->sortFiles = ((sbool) pvals[i].val.d.n) ? 0 : GLOB_NOSORT;
+ } else if(!strcmp(modpblk.descr[i].name, "statefile.directory")) {
+ loadModConf->stateFileDirectory = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "normalizepath")) {
+ loadModConf->normalizePath = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "mode")) {
+ if(!es_strconstcmp(pvals[i].val.d.estr, "polling"))
+ loadModConf->opMode = OPMODE_POLLING;
+ else if(!es_strconstcmp(pvals[i].val.d.estr, "inotify")) {
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE) /* use FEN on Solaris! */
+ loadModConf->opMode = OPMODE_FEN;
+ DBGPRINTF("inotify mode configured, but only FEN "
+ "is available on OS SOLARIS. Switching to FEN "
+ "Mode automatically\n");
+#else
+ #if defined(HAVE_INOTIFY_INIT)
+ loadModConf->opMode = OPMODE_INOTIFY;
+ #else
+ loadModConf->opMode = OPMODE_POLLING;
+ #endif
+#endif
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "fen"))
+ loadModConf->opMode = OPMODE_FEN;
+ else {
+ char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_PARAM_ERROR, "imfile: unknown "
+ "mode '%s'", cstr);
+ free(cstr);
+ }
+ } else {
+ DBGPRINTF("program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* remove all of our legacy handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->iPollInterval = cs.iPollInterval;
+ }
+ DBGPRINTF("opmode is %d, polling interval is %d\n",
+ loadModConf->opMode,
+ loadModConf->iPollInterval);
+
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pszFileName);
+ free(cs.pszFileTag);
+ free(cs.pszStateFile);
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ if(getStateFileDir() == NULL) {
+ /* this intentionally is an error message */
+ LogError(0, RS_RET_NO_WRKDIR_SET,
+ "imfile: no working or state file directory set, imfile will create "
+ "state files in the current working directory (probably "
+ "the root dir). Use global(workDirectory=\"/some/path\") "
+ "to set the working directory");
+ }
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ if(pModConf->root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS,
+ "imfile: no files configured to be monitored - "
+ "no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+
+/* note: we do access files AFTER we have dropped privileges. This is
+ * intentional, user must make sure the files have the right permissions.
+ */
+BEGINactivateCnf
+ instanceConf_t *inst;
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ currModConf = pModConf;
+ if(runModConf->root == NULL) {
+ LogError(0, NO_ERRCODE, "imfile: no file monitors configured, "
+ "input not activated.\n");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ // TODO: provide switch to turn off this warning?
+ if(!containsGlobWildcard((char*)inst->pszFileName)) {
+ if(access((char*)inst->pszFileName, R_OK) != 0) {
+ LogError(errno, RS_RET_ERR,
+ "imfile: on startup file '%s' does not exist "
+ "but is configured in static file monitor - this "
+ "may indicate a misconfiguration. If the file "
+ "appears at a later time, it will automatically "
+ "be processed. Reason", inst->pszFileName);
+ }
+ }
+ fs_node_add(runModConf->conf_tree, NULL, inst->pszFileName, 0, inst);
+ }
+
+ if(Debug) {
+ fs_node_print(runModConf->conf_tree, 0);
+ }
+
+finalize_it:
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ fs_node_destroy(pModConf->conf_tree);
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindRuleset);
+ free(inst->pszFileName);
+ free(inst->pszTag);
+ free(inst->pszStateFile);
+ free(inst->pszFileName_forOldStateFile);
+ if(inst->startRegex != NULL) {
+ regfree(&inst->start_preg);
+ free(inst->startRegex);
+ }
+ if(inst->endRegex != NULL) {
+ regfree(&inst->end_preg);
+ free(inst->endRegex);
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+
+/* initial poll run, to be used for all modes. Depending on mode, it does some
+ * further initializations (e.g. watches in inotify mode). Most importantly,
+ * it processes already-existing files, which would not otherwise be picked
+ * up in notifcation modes (inotfiy, FEN). Also, when freshStartTail is set,
+ * this run assumes that all previous existing data exists and needs not
+ * to be considered.
+ * Note: there is a race on files created *during* the run, but that race is
+ * inevitable (and thus freshStartTail is actually broken, but users still seem
+ * to want it...).
+ * rgerhards, 2018-05-17
+ */
+static void
+do_initial_poll_run(void)
+{
+ fs_node_walk(runModConf->conf_tree, poll_tree);
+
+ /* fresh start done, so disable freshStartTail for files that now will be created */
+ for(instanceConf_t *inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ inst->freshStartTail = 0;
+ }
+}
+
+
+/* Monitor files in polling mode. */
+static rsRetVal
+doPolling(void)
+{
+ DEFiRet;
+ do_initial_poll_run();
+ while(glbl.GetGlobalInputTermState() == 0) {
+ DBGPRINTF("doPolling: new poll run\n");
+ do {
+ runModConf->bHadFileData = 0;
+ fs_node_walk(runModConf->conf_tree, poll_tree);
+ DBGPRINTF("doPolling: end poll walk, hadData %d\n", runModConf->bHadFileData);
+ } while(runModConf->bHadFileData); /* warning: do...while()! */
+
+ /* Note: the additional 10ns wait is vitally important. It guards rsyslog
+ * against totally hogging the CPU if the users selects a polling interval
+ * of 0 seconds. It doesn't hurt any other valid scenario. So do not remove.
+ * rgerhards, 2008-02-14
+ */
+ DBGPRINTF("doPolling: poll going to sleep\n");
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(runModConf->iPollInterval, 10);
+ }
+
+ RETiRet;
+}
+
+#if defined(HAVE_INOTIFY_INIT)
+
+static void ATTR_NONNULL(1)
+in_dbg_showEv(const struct inotify_event *ev)
+{
+ if(!Debug)
+ return;
+ if(ev->mask & IN_IGNORED) {
+ dbgprintf("INOTIFY event: watch was REMOVED\n");
+ }
+ if(ev->mask & IN_MODIFY) {
+ dbgprintf("INOTIFY event: watch was MODIFID\n");
+ }
+ if(ev->mask & IN_ACCESS) {
+ dbgprintf("INOTIFY event: watch IN_ACCESS\n");
+ }
+ if(ev->mask & IN_ATTRIB) {
+ dbgprintf("INOTIFY event: watch IN_ATTRIB\n");
+ }
+ if(ev->mask & IN_CLOSE_WRITE) {
+ dbgprintf("INOTIFY event: watch IN_CLOSE_WRITE\n");
+ }
+ if(ev->mask & IN_CLOSE_NOWRITE) {
+ dbgprintf("INOTIFY event: watch IN_CLOSE_NOWRITE\n");
+ }
+ if(ev->mask & IN_CREATE) {
+ dbgprintf("INOTIFY event: file was CREATED: %s\n", ev->name);
+ }
+ if(ev->mask & IN_DELETE) {
+ dbgprintf("INOTIFY event: watch IN_DELETE\n");
+ }
+ if(ev->mask & IN_DELETE_SELF) {
+ dbgprintf("INOTIFY event: watch IN_DELETE_SELF\n");
+ }
+ if(ev->mask & IN_MOVE_SELF) {
+ dbgprintf("INOTIFY event: watch IN_MOVE_SELF\n");
+ }
+ if(ev->mask & IN_MOVED_FROM) {
+ dbgprintf("INOTIFY event: watch IN_MOVED_FROM, cookie %u, name '%s'\n", ev->cookie, ev->name);
+ }
+ if(ev->mask & IN_MOVED_TO) {
+ dbgprintf("INOTIFY event: watch IN_MOVED_TO, cookie %u, name '%s'\n", ev->cookie, ev->name);
+ }
+ if(ev->mask & IN_OPEN) {
+ dbgprintf("INOTIFY event: watch IN_OPEN\n");
+ }
+ if(ev->mask & IN_ISDIR) {
+ dbgprintf("INOTIFY event: watch IN_ISDIR\n");
+ }
+}
+
+
+static void ATTR_NONNULL(1, 2)
+in_handleFileEvent(struct inotify_event *ev, const wd_map_t *const etry)
+{
+ if(ev->mask & IN_MODIFY) {
+ DBGPRINTF("fs_node_notify_file_update: act->name '%s'\n", etry->act->name);
+ pollFile(etry->act);
+ } else {
+ DBGPRINTF("got non-expected inotify event:\n");
+ in_dbg_showEv(ev);
+ }
+}
+
+
+/* workaround for IN_MOVED: walk active list and prevent state file deletion of
+ * IN_MOVED_IN active object
+ * TODO: replace by a more generic solution.
+ */
+static void
+flag_in_move(fs_edge_t *const edge, const char *name_moved)
+{
+ act_obj_t *act;
+
+ for(act = edge->active ; act != NULL ; act = act->next) {
+ DBGPRINTF("checking active object %s\n", act->basename);
+ if(!strcmp(act->basename, name_moved)){
+ DBGPRINTF("found file\n");
+ act->in_move = 1;
+ break;
+ } else {
+ DBGPRINTF("name check fails, '%s' != '%s'\n", act->basename, name_moved);
+ }
+ }
+ if (!act && edge->next) {
+ flag_in_move(edge->next, name_moved);
+ }
+}
+
+static void ATTR_NONNULL(1)
+in_processEvent(struct inotify_event *ev)
+{
+ if(ev->mask & IN_IGNORED) {
+ DBGPRINTF("imfile: got IN_IGNORED event\n");
+ goto done;
+ }
+
+ DBGPRINTF("in_processEvent process Event %x for %s\n", ev->mask, ev->name);
+ const wd_map_t *const etry = wdmapLookup(ev->wd);
+ if(etry == NULL) {
+ LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_WARNING, "imfile: internal error? "
+ "inotify provided watch descriptor %d which we could not find "
+ "in our tables - ignored", ev->wd);
+ goto done;
+ }
+ DBGPRINTF("in_processEvent process Event %x is_file %d, act->name '%s'\n",
+ ev->mask, etry->act->edge->is_file, etry->act->name);
+
+ if((ev->mask & IN_MOVED_FROM)) {
+ flag_in_move(etry->act->edge->node->edges, ev->name);
+ }
+ if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO)) {
+ fs_node_walk(etry->act->edge->node, poll_tree);
+ } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
+ in_handleFileEvent(ev, etry); // esentially poll_file()!
+ } else {
+ fs_node_walk(etry->act->edge->node, poll_tree);
+ }
+done: return;
+}
+
+
+/* Monitor files in inotify mode */
+static rsRetVal
+do_inotify(void)
+{
+ char iobuf[8192];
+ int rd;
+ int currev;
+ static int last_timeout = 0;
+ struct pollfd pollfd;
+ DEFiRet;
+
+ CHKiRet(wdmapInit());
+ ino_fd = inotify_init1(IN_NONBLOCK);
+ if(ino_fd < 0) {
+ LogError(errno, RS_RET_INOTIFY_INIT_FAILED, "imfile: Init inotify "
+ "instance failed ");
+ return RS_RET_INOTIFY_INIT_FAILED;
+ }
+ DBGPRINTF("inotify fd %d\n", ino_fd);
+
+ do_initial_poll_run();
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ int r;
+
+ pollfd.fd = ino_fd;
+ pollfd.events = POLLIN;
+
+ if (runModConf->haveReadTimeouts)
+ r = poll(&pollfd, 1, runModConf->timeoutGranularity);
+ else
+ r = poll(&pollfd, 1, -1);
+
+ if (r == -1 && errno == EINTR) {
+ DBGPRINTF("do_inotify interrupted while polling on ino_fd\n");
+ continue;
+ }
+ if(r == 0) {
+ DBGPRINTF("readTimeouts are configured, checking if some apply\n");
+ if (runModConf->haveReadTimeouts) {
+ fs_node_walk(runModConf->conf_tree, poll_timeouts);
+ last_timeout = time(NULL);
+ }
+ continue;
+ } else if (r == -1) {
+ LogError(errno, RS_RET_INTERNAL_ERROR,
+ "%s:%d: unexpected error during poll timeout wait",
+ __FILE__, __LINE__);
+ /* we do not abort, as this would render the whole input defunct */
+ continue;
+ } else if(r != 1) {
+ LogError(errno, RS_RET_INTERNAL_ERROR,
+ "%s:%d: ERROR: poll returned more fds (%d) than given to it (1)",
+ __FILE__, __LINE__, r);
+ /* we do not abort, as this would render the whole input defunct */
+ continue;
+ }
+ else {
+ // process timeouts always, ino_fd may be too busy to ever have timeout occur from poll
+ if(runModConf->haveReadTimeouts) {
+ int now = time(NULL);
+ if(last_timeout + (runModConf->timeoutGranularity / 1000) > now) {
+ fs_node_walk(runModConf->conf_tree, poll_timeouts);
+ last_timeout = time(NULL);
+ }
+ }
+ rd = read(ino_fd, iobuf, sizeof(iobuf));
+ if(rd == -1 && errno == EINTR) {
+ /* This might have been our termination signal! */
+ DBGPRINTF("EINTR received during inotify, restarting poll\n");
+ continue;
+ }
+ if (rd == -1 && errno == EWOULDBLOCK) {
+ continue;
+ }
+ if(rd < 0) {
+ LogError(errno, RS_RET_IO_ERROR, "imfile: error during inotify - ignored");
+ continue;
+ }
+ currev = 0;
+ while(currev < rd) {
+ union {
+ char *buf;
+ struct inotify_event *ev;
+ } savecast;
+ savecast.buf = iobuf+currev;
+ in_dbg_showEv(savecast.ev);
+ in_processEvent(savecast.ev);
+ currev += sizeof(struct inotify_event) + savecast.ev->len;
+ }
+ }
+ }
+
+finalize_it:
+ close(ino_fd);
+ RETiRet;
+}
+
+#else /* #if HAVE_INOTIFY_INIT */
+static rsRetVal
+do_inotify(void)
+{
+ LogError(0, RS_RET_NOT_IMPLEMENTED, "imfile: mode set to inotify, but the "
+ "platform does not support inotify");
+ return RS_RET_NOT_IMPLEMENTED;
+}
+#endif /* #if HAVE_INOTIFY_INIT */
+
+
+/* --- Monitor files in FEN mode (OS_SOLARIS)*/
+#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE) /* use FEN on Solaris! */
+static void
+fen_printevent(int event)
+{
+ if (event & FILE_ACCESS) {
+ DBGPRINTF(" FILE_ACCESS");
+ }
+ if (event & FILE_MODIFIED) {
+ DBGPRINTF(" FILE_MODIFIED");
+ }
+ if (event & FILE_ATTRIB) {
+ DBGPRINTF(" FILE_ATTRIB");
+ }
+ if (event & FILE_DELETE) {
+ DBGPRINTF(" FILE_DELETE");
+ }
+ if (event & FILE_RENAME_TO) {
+ DBGPRINTF(" FILE_RENAME_TO");
+ }
+ if (event & FILE_RENAME_FROM) {
+ DBGPRINTF(" FILE_RENAME_FROM");
+ }
+ if (event & UNMOUNTED) {
+ DBGPRINTF(" UNMOUNTED");
+ }
+ if (event & MOUNTEDOVER) {
+ DBGPRINTF(" MOUNTEDOVER");
+ }
+}
+
+
+/* https://docs.oracle.com/cd/E19253-01/816-5168/port-get-3c/index.html */
+static rsRetVal
+do_fen(void)
+{
+ port_event_t portEvent;
+ struct timespec timeout;
+ DEFiRet;
+
+ /* Set port timeout to 1 second. We need to check for unmonitored files during meantime */
+ // TODO: do we need this timeout at all for equality to old code?
+ // TODO: do we need it to support the timeout feature!
+ timeout.tv_sec = 300;
+ timeout.tv_nsec = 0;
+
+ /* create port instance */
+ if((glport = port_create()) == -1) {
+ LogError(errno, RS_RET_FEN_INIT_FAILED, "do_fen INIT Port failed ");
+ return RS_RET_FEN_INIT_FAILED;
+ }
+
+ do_initial_poll_run();
+
+ DBGPRINTF("do_fen ENTER monitoring loop \n");
+ while(glbl.GetGlobalInputTermState() == 0) {
+ DBGPRINTF("do_fen loop begin... \n");
+ /* Loop through events, if there are any */
+ while (!port_get(glport, &portEvent, &timeout)) { // wie inotify-wait
+ DBGPRINTF("do_fen: received port event with ");
+ fen_printevent((int) portEvent.portev_events);
+ DBGPRINTF("\n");
+ if(portEvent.portev_source != PORT_SOURCE_FILE) {
+ LogError(errno, RS_RET_SYS_ERR, "do_fen: Event from unexpected source "
+ ": %d\n", portEvent.portev_source);
+ continue;
+ }
+ act_obj_t *const act = (act_obj_t*) portEvent.portev_user;
+ DBGPRINTF("do_fen event received: deleted %d, is_file %d, name '%s' foname '%s'\n",
+ act->is_deleted, act->edge->is_file, act->name,
+ ((struct file_obj*)portEvent.portev_object)->fo_name);
+ if(act->is_deleted) {
+ free(act->name);
+ free(act);
+ continue;
+ }
+
+ /* we need to re-associate the object */
+ act->bPortAssociated = 0;
+ fen_setupWatch(act);
+
+ if(act->edge->is_file) {
+ pollFile(act);
+ } else {
+ fs_node_walk(act->edge->node, poll_tree);
+ }
+ }
+ }
+
+ /* close port, will de-activate all file events watches associated
+ * with the port.
+ */
+ close(glport);
+ RETiRet;
+}
+#else /* #if OS_SOLARIS */
+static rsRetVal
+do_fen(void)
+{
+ LogError(0, RS_RET_NOT_IMPLEMENTED, "do_fen: mode set to fen, but the "
+ "platform does not support fen");
+ return RS_RET_NOT_IMPLEMENTED;
+}
+#endif /* #if OS_SOLARIS */
+
+
+/* This function is called by the framework to gather the input. The module stays
+ * most of its lifetime inside this function. It MUST NEVER exit this function. Doing
+ * so would end module processing and rsyslog would NOT reschedule the module. If
+ * you exit from this function, you violate the interface specification!
+ */
+BEGINrunInput
+CODESTARTrunInput
+ #if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE) /* use FEN on Solaris! */
+ if(runModConf->opMode == OPMODE_INOTIFY) {
+ DBGPRINTF("auto-adjusting 'inotify' mode to 'fen' on Solaris\n");
+ runModConf->opMode = OPMODE_FEN;
+ }
+ #endif
+ DBGPRINTF("working in %s mode\n",
+ (runModConf->opMode == OPMODE_POLLING) ? "polling" :
+ ((runModConf->opMode == OPMODE_INOTIFY) ?"inotify" : "fen"));
+ if(runModConf->opMode == OPMODE_POLLING)
+ iRet = doPolling();
+ else if(runModConf->opMode == OPMODE_INOTIFY)
+ iRet = do_inotify();
+ else if(runModConf->opMode == OPMODE_FEN)
+ iRet = do_fen();
+ else {
+ LogError(0, RS_RET_NOT_IMPLEMENTED, "imfile: unknown mode %d set",
+ runModConf->opMode);
+ return RS_RET_NOT_IMPLEMENTED;
+ }
+ DBGPRINTF("terminating upon request of rsyslog core\n");
+ENDrunInput
+
+
+/* The function is called by rsyslog before runInput() is called. It is a last chance
+ * to set up anything specific. Most importantly, it can be used to tell rsyslog if the
+ * input shall run or not. The idea is that if some config settings (or similiar things)
+ * are not OK, the input can tell rsyslog it will not execute. To do so, return
+ * RS_RET_NO_RUN or a specific error code. If RS_RET_OK is returned, rsyslog will
+ * proceed and call the runInput() entry point.
+ */
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+// TODO: refactor this into a generically-usable "atomic file creation" utility for
+// all kinds of "state files"
+static rsRetVal ATTR_NONNULL()
+atomicWriteStateFile(const char *fn, const char *content)
+{
+ DEFiRet;
+ const int fd = open(fn, O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if(fd < 0) {
+ LogError(errno, RS_RET_IO_ERROR, "imfile: cannot open state file '%s' for "
+ "persisting file state - some data will probably be duplicated "
+ "on next startup", fn);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ const size_t toWrite = strlen(content);
+ const ssize_t w = write(fd, content, toWrite);
+ if(w != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR, "imfile: partial write to state file '%s' "
+ "this may cause trouble in the future. We will try to delete the "
+ "state file, as this provides most consistent state", fn);
+ unlink(fn);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(fd >= 0) {
+ close(fd);
+ }
+ RETiRet;
+}
+
+/* This function should be called after any file ID change - that is if
+ * file grown from hash-only statefile, or was truncated, this will ensure
+ * we delete the old file so we do not make garbage in our working dir and
+ * there are no leftover statefiles which can in theory later bind to something
+ * and cause data loss.
+ * jvymazal 2019-11-27
+ */
+static void
+removeOldStatefile(const uchar *statefn, const char *hashToDelete)
+{
+ int ret;
+ uchar statefname[MAXFNAME];
+
+ getFullStateFileName(statefn, hashToDelete, statefname, sizeof(statefname));
+ DBGPRINTF("removing old state file: '%s'\n", statefname);
+ ret = unlink((const char*)statefname);
+ if(ret != 0) {
+ if (errno != ENOENT) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "imfile error trying to delete old state file: '%s' - ignoring this "
+ "error, usually this means a file no longer file is left over, but "
+ "this may also cause some real trouble. Still the best we can do ",
+ statefname);
+ } else {
+ DBGPRINTF("trying to delete no longer valid statefile '%s' which no "
+ "longer exists (probably already deleted)\n", statefname);
+ }
+ }
+}
+
+
+/* This function persists information for a specific file being monitored.
+ * To do so, it simply persists the stream object. We do NOT abort on error
+ * iRet as that makes matters worse (at least we can try persisting the others...).
+ * rgerhards, 2008-02-13
+ */
+static rsRetVal ATTR_NONNULL()
+persistStrmState(act_obj_t *const act)
+{
+ DEFiRet;
+ uchar statefile[MAXFNAME];
+ uchar statefname[MAXFNAME];
+
+ uchar *const statefn = getStateFileName(act, statefile, sizeof(statefile));
+ getFileID(act);
+ getFullStateFileName(statefn, act->file_id, statefname, sizeof(statefname));
+ DBGPRINTF("persisting state for '%s', state file '%s'\n", act->name, statefname);
+
+ struct json_object *jval = NULL;
+ struct json_object *json = NULL;
+ CHKmalloc(json = json_object_new_object());
+ jval = json_object_new_string((char*) act->name);
+ json_object_object_add(json, "filename", jval);
+ jval = json_object_new_int(strmGetPrevWasNL(act->pStrm));
+ json_object_object_add(json, "prev_was_nl", jval);
+
+ /* we access some data items a bit dirty, as we need to refactor the whole
+ * thing in any case - TODO
+ */
+ jval = json_object_new_int64(act->pStrm->iCurrOffs);
+ json_object_object_add(json, "curr_offs", jval);
+ jval = json_object_new_int64(act->pStrm->strtOffs);
+ json_object_object_add(json, "strt_offs", jval);
+
+ const uchar *const prevLineSegment = strmGetPrevLineSegment(act->pStrm);
+ if(prevLineSegment != NULL) {
+ jval = json_object_new_string((const char*) prevLineSegment);
+ json_object_object_add(json, "prev_line_segment", jval);
+ }
+
+ const uchar *const prevMsgSegment = strmGetPrevMsgSegment(act->pStrm);
+ if(prevMsgSegment != NULL) {
+ jval = json_object_new_string((const char*) prevMsgSegment);
+ json_object_object_add(json, "prev_msg_segment", jval);
+ }
+
+ const char *jstr = json_object_to_json_string_ext(json, JSON_C_TO_STRING_SPACED);
+
+ CHKiRet(atomicWriteStateFile((const char*)statefname, jstr));
+ json_object_put(json);
+
+ /* file-id changed remove the old statefile */
+ if (strncmp((const char *)act->file_id_prev, (const char *)act->file_id, FILE_ID_HASH_SIZE)) {
+ removeOldStatefile(statefn, act->file_id_prev);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "imfile: could not persist state "
+ "file %s - data may be repeated on next "
+ "startup. Is WorkDirectory set?",
+ statefname);
+ }
+
+ RETiRet;
+}
+
+/* This function is called by the framework after runInput() has been terminated. It
+ * shall free any resources and prepare the module for unload.
+ */
+BEGINafterRun
+CODESTARTafterRun
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* The following entry points are defined in module-template.h.
+ * In general, they need to be present, but you do NOT need to provide
+ * any code here.
+ */
+BEGINmodExit
+CODESTARTmodExit
+ /* release objects we used */
+ objRelease(strm, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+
+ #ifdef HAVE_INOTIFY_INIT
+ free(wdmap);
+ #endif
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* The following function shall reset all configuration variables to their
+ * default values. The code provided in modInit() below registers it to be
+ * called on "$ResetConfigVariables". You may also call it from other places,
+ * but in general this is not necessary. Once runInput() has been called, this
+ * function here is never again called.
+ */
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+
+ free(cs.pszFileName);
+ cs.pszFileName = NULL;
+ free(cs.pszFileTag);
+ cs.pszFileTag = NULL;
+ free(cs.pszStateFile);
+ cs.pszStateFile = NULL;
+
+ /* set defaults... */
+ cs.iPollInterval = DFLT_PollInterval;
+ cs.iFacility = 128; /* local0 */
+ cs.iSeverity = 5; /* notice, as of rfc 3164 */
+ cs.readMode = 0;
+ cs.maxLinesAtOnce = 10240;
+ cs.trimLineOverBytes = 0;
+
+ RETiRet;
+}
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imfile: ruleset '%s' for %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszFileName);
+}
+
+/* modInit() is called once the module is loaded. It must perform all module-wide
+ * initialization tasks. There are also a number of housekeeping tasks that the
+ * framework requires. These are handled by the macros. Please note that the
+ * complexity of processing is depending on the actual module. However, only
+ * thing absolutely necessary should be done here. Actual app-level processing
+ * is to be performed in runInput(). A good sample of what to do here may be to
+ * set some variable defaults.
+ */
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("version %s initializing\n", VERSION);
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszFileName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszFileTag, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszStateFile, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity,
+ NULL, &cs.iSeverity, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility,
+ NULL, &cs.iFacility, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt,
+ NULL, &cs.readMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilemaxlinesatonce", 0, eCmdHdlrSize,
+ NULL, &cs.maxLinesAtOnce, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletrimlineoverbytes", 0, eCmdHdlrSize,
+ NULL, &cs.trimLineOverBytes, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt,
+ NULL, &cs.iPersistStateInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
+ /* that command ads a new file! */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ /* module-global config params - will be disabled in configs that are loaded
+ * via module(...).
+ */
+ CHKiRet(regCfSysLineHdlr2((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt,
+ NULL, &cs.iPollInterval, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/imfile/siphash.c b/plugins/imfile/siphash.c
new file mode 100644
index 0000000..8d5fac7
--- /dev/null
+++ b/plugins/imfile/siphash.c
@@ -0,0 +1,185 @@
+/* SipHash reference C implementation
+ *
+ * Copyright (c) 2012-2016 Jean-Philippe Aumasson
+ * <jeanphilippe.aumasson@gmail.com>
+ * Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * Slightly adapted by rsyslog in regard to build system and code style
+ * check.
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ *
+ * For details on siphash see https://131002.net/siphash/
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+/* default: SipHash-2-4 */
+#define cROUNDS 2
+#define dROUNDS 4
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v)); \
+ (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); \
+ (p)[3] = (uint8_t)((v) >> 24);
+
+#define U64TO8_LE(p, v) \
+ U32TO8_LE((p), (uint32_t)((v))); \
+ U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define U8TO64_LE(p) \
+ (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
+ ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
+ ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
+ ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
+
+#define SIPROUND \
+ do { \
+ v0 += v1; \
+ v1 = ROTL(v1, 13); \
+ v1 ^= v0; \
+ v0 = ROTL(v0, 32); \
+ v2 += v3; \
+ v3 = ROTL(v3, 16); \
+ v3 ^= v2; \
+ v0 += v3; \
+ v3 = ROTL(v3, 21); \
+ v3 ^= v0; \
+ v2 += v1; \
+ v1 = ROTL(v1, 17); \
+ v1 ^= v2; \
+ v2 = ROTL(v2, 32); \
+ } while (0)
+
+#ifdef DEBUG
+#define TRACE \
+ do { \
+ printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \
+ (uint32_t)v0); \
+ printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \
+ (uint32_t)v1); \
+ printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \
+ (uint32_t)v2); \
+ printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \
+ (uint32_t)v3); \
+ } while (0)
+#else
+#define TRACE
+#endif
+
+extern int rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
+ uint8_t *out, const size_t outlen); /* avoid compiler warning */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+int
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
+ uint8_t *out, const size_t outlen) {
+
+ uint64_t v0 = 0x736f6d6570736575ULL;
+ uint64_t v1 = 0x646f72616e646f6dULL;
+ uint64_t v2 = 0x6c7967656e657261ULL;
+ uint64_t v3 = 0x7465646279746573ULL;
+ uint64_t k0 = U8TO64_LE(k);
+ uint64_t k1 = U8TO64_LE(k + 8);
+ uint64_t m;
+ int i;
+ const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+ const int left = inlen & 7;
+ uint64_t b = ((uint64_t)inlen) << 56;
+ assert((outlen == 8) || (outlen == 16));
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+
+ if (outlen == 16)
+ v1 ^= 0xee;
+
+ for (; in != end; in += 8) {
+ m = U8TO64_LE(in);
+ v3 ^= m;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= m;
+ }
+
+ switch (left) {
+ case 7:
+ b |= ((uint64_t)in[6]) << 48;
+ /*FALLTHROUGH*/
+ case 6:
+ b |= ((uint64_t)in[5]) << 40;
+ /*FALLTHROUGH*/
+ case 5:
+ b |= ((uint64_t)in[4]) << 32;
+ /*FALLTHROUGH*/
+ case 4:
+ b |= ((uint64_t)in[3]) << 24;
+ /*FALLTHROUGH*/
+ case 3:
+ b |= ((uint64_t)in[2]) << 16;
+ /*FALLTHROUGH*/
+ case 2:
+ b |= ((uint64_t)in[1]) << 8;
+ /*FALLTHROUGH*/
+ case 1:
+ b |= ((uint64_t)in[0]);
+ break;
+ case 0:
+ default:
+ break;
+ }
+
+ v3 ^= b;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= b;
+
+ if (outlen == 16)
+ v2 ^= 0xee;
+ else
+ v2 ^= 0xff;
+
+ TRACE;
+ for (i = 0; i < dROUNDS; ++i)
+ SIPROUND;
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ U64TO8_LE(out, b);
+
+ if (outlen == 8)
+ return 0;
+
+ v1 ^= 0xdd;
+
+ TRACE;
+ for (i = 0; i < dROUNDS; ++i)
+ SIPROUND;
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ U64TO8_LE(out + 8, b);
+
+ return 0;
+}
diff --git a/plugins/imgssapi/Makefile.am b/plugins/imgssapi/Makefile.am
new file mode 100644
index 0000000..ea01635
--- /dev/null
+++ b/plugins/imgssapi/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imgssapi.la
+
+imgssapi_la_SOURCES = imgssapi.c
+imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imgssapi_la_LDFLAGS = -module -avoid-version
+imgssapi_la_LIBADD = $(GSS_LIBS)
diff --git a/plugins/imgssapi/Makefile.in b/plugins/imgssapi/Makefile.in
new file mode 100644
index 0000000..4b920e6
--- /dev/null
+++ b/plugins/imgssapi/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imgssapi
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imgssapi_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imgssapi_la_OBJECTS = imgssapi_la-imgssapi.lo
+imgssapi_la_OBJECTS = $(am_imgssapi_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 =
+imgssapi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imgssapi_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imgssapi_la-imgssapi.Plo
+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 = $(imgssapi_la_SOURCES)
+DIST_SOURCES = $(imgssapi_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imgssapi.la
+imgssapi_la_SOURCES = imgssapi.c
+imgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imgssapi_la_LDFLAGS = -module -avoid-version
+imgssapi_la_LIBADD = $(GSS_LIBS)
+all: 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) --gnu plugins/imgssapi/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imgssapi/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imgssapi.la: $(imgssapi_la_OBJECTS) $(imgssapi_la_DEPENDENCIES) $(EXTRA_imgssapi_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imgssapi_la_LINK) -rpath $(pkglibdir) $(imgssapi_la_OBJECTS) $(imgssapi_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imgssapi_la-imgssapi.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imgssapi_la-imgssapi.lo: imgssapi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imgssapi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imgssapi_la-imgssapi.lo -MD -MP -MF $(DEPDIR)/imgssapi_la-imgssapi.Tpo -c -o imgssapi_la-imgssapi.lo `test -f 'imgssapi.c' || echo '$(srcdir)/'`imgssapi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imgssapi_la-imgssapi.Tpo $(DEPDIR)/imgssapi_la-imgssapi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imgssapi.c' object='imgssapi_la-imgssapi.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) $(imgssapi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imgssapi_la-imgssapi.lo `test -f 'imgssapi.c' || echo '$(srcdir)/'`imgssapi.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imgssapi_la-imgssapi.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imgssapi_la-imgssapi.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c
new file mode 100644
index 0000000..65eceb9
--- /dev/null
+++ b/plugins/imgssapi/imgssapi.c
@@ -0,0 +1,823 @@
+/* imgssapi.c
+ * This is the implementation of the GSSAPI input module.
+ *
+ * Note: the root gssapi code was contributed by varmojfekoj and is most often
+ * maintened by him. I am just doing the plumbing around it (I event don't have a
+ * test lab for gssapi yet... ). I am very grateful for this useful code
+ * contribution -- rgerhards, 2008-03-05
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2007, 2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <gssapi/gssapi.h>
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "srUtils.h"
+#include "gss-misc.h"
+#include "tcpsrv.h"
+#include "tcps_sess.h"
+#include "errmsg.h"
+#include "netstrm.h"
+#include "glbl.h"
+#include "debug.h"
+#include "unlimited_select.h"
+#include "rsconf.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+
+/* defines */
+#define ALLOWEDMETHOD_GSS 2
+#define ALLOWEDMETHOD_TCP 1
+
+
+/* some forward definitions - they may go away when we no longer include imtcp.c */
+static rsRetVal addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal);
+static rsRetVal actGSSListener(uchar *port);
+static int TCPSessGSSInit(void);
+static void TCPSessGSSClose(tcps_sess_t* pSess);
+static rsRetVal TCPSessGSSRecv(tcps_sess_t *pSess, void *buf, size_t buf_len, ssize_t *);
+static rsRetVal onSessAccept(tcpsrv_t *pThis, tcps_sess_t *ppSess);
+static rsRetVal OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *ppSess);
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(tcpsrv)
+DEFobjCurrIf(tcps_sess)
+DEFobjCurrIf(gssutil)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(net)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+
+static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
+static gss_cred_id_t gss_server_creds = GSS_C_NO_CREDENTIAL;
+static uchar *srvPort;
+
+/* our usr structure for the tcpsrv object */
+typedef struct gsssrv_s {
+ char allowedMethods;
+} gsssrv_t;
+
+/* our usr structure for the session object */
+typedef struct gss_sess_s {
+ OM_uint32 gss_flags;
+ gss_ctx_id_t gss_context;
+ char allowedMethods;
+} gss_sess_t;
+
+
+/* config variables */
+struct modConfData_s {
+ EMPTY_STRUCT;
+};
+
+static uchar *pszLstnPortFileName = NULL; /* file for dynamic port */
+static int iTCPSessMax = 200; /* max number of sessions */
+static char *gss_listen_service_name = NULL;
+static int bPermitPlainTcp = 0; /* plain tcp syslog allowed on GSSAPI port? */
+static int bKeepAlive = 0; /* use SO_KEEPALIVE? */
+
+
+/* methods */
+/* callbacks */
+static rsRetVal OnSessConstructFinalize(void *ppUsr)
+{
+ DEFiRet;
+ gss_sess_t **ppGSess = (gss_sess_t**) ppUsr;
+ gss_sess_t *pGSess;
+
+ assert(ppGSess != NULL);
+
+ if((pGSess = calloc(1, sizeof(gss_sess_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pGSess->gss_flags = 0;
+ pGSess->gss_context = GSS_C_NO_CONTEXT;
+ pGSess->allowedMethods = 0;
+
+ *ppGSess = pGSess;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Destruct the user session pointer for a GSSAPI session. Please note
+ * that it *is* valid to receive a NULL user pointer. In this case, the
+ * sessions is to be torn down before it was fully initialized. This
+ * happens in error cases, e.g. when the host ACL did not match.
+ * rgerhards, 2008-03-03
+ */
+static rsRetVal
+OnSessDestruct(void *ppUsr)
+{
+ DEFiRet;
+ gss_sess_t **ppGSess = (gss_sess_t**) ppUsr;
+
+ assert(ppGSess != NULL);
+ if(*ppGSess == NULL)
+ FINALIZE;
+
+ if((*ppGSess)->allowedMethods & ALLOWEDMETHOD_GSS) {
+ OM_uint32 maj_stat, min_stat;
+ maj_stat = gss_delete_sec_context(&min_stat, &(*ppGSess)->gss_context, GSS_C_NO_BUFFER);
+ if (maj_stat != GSS_S_COMPLETE)
+ gssutil.display_status((char*)"deleting context", maj_stat, min_stat);
+ }
+
+ free(*ppGSess);
+ *ppGSess = NULL;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Check if the host is permitted to send us messages.
+ * Note: the pUsrSess may be zero if the server is running in tcp-only mode!
+ */
+static int
+isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void *pUsrSrv, void*pUsrSess)
+{
+ gsssrv_t *pGSrv;
+ gss_sess_t *pGSess;
+ char allowedMethods = 0;
+
+ assert(pUsrSrv != NULL);
+ pGSrv = (gsssrv_t*) pUsrSrv;
+ pGSess = (gss_sess_t*) pUsrSess;
+
+ if((pGSrv->allowedMethods & ALLOWEDMETHOD_TCP) &&
+ net.isAllowedSender2((uchar*)"TCP", addr, (char*)fromHostFQDN, 1))
+ allowedMethods |= ALLOWEDMETHOD_TCP;
+ if((pGSrv->allowedMethods & ALLOWEDMETHOD_GSS) &&
+ net.isAllowedSender2((uchar*)"GSS", addr, (char*)fromHostFQDN, 1))
+ allowedMethods |= ALLOWEDMETHOD_GSS;
+ if(allowedMethods && pGSess != NULL)
+ pGSess->allowedMethods = allowedMethods;
+ return allowedMethods;
+}
+
+
+static rsRetVal
+onSessAccept(tcpsrv_t *pThis, tcps_sess_t *pSess)
+{
+ DEFiRet;
+ gsssrv_t *pGSrv;
+
+ pGSrv = (gsssrv_t*) pThis->pUsr;
+
+ if(pGSrv->allowedMethods & ALLOWEDMETHOD_GSS) {
+ iRet = OnSessAcceptGSS(pThis, pSess);
+ }
+
+ RETiRet;
+}
+
+
+static rsRetVal
+onRegularClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ gss_sess_t *pGSess;
+
+ assert(pSess != NULL);
+ assert(pSess->pUsr != NULL);
+ pGSess = (gss_sess_t*) pSess->pUsr;
+
+ if(pGSess->allowedMethods & ALLOWEDMETHOD_GSS)
+ TCPSessGSSClose(pSess);
+ else {
+ /* process any incomplete frames left over */
+ tcps_sess.PrepareClose(pSess);
+ /* Session closed */
+ tcps_sess.Close(pSess);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+onErrClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ gss_sess_t *pGSess;
+
+ assert(pSess != NULL);
+ assert(pSess->pUsr != NULL);
+ pGSess = (gss_sess_t*) pSess->pUsr;
+
+ if(pGSess->allowedMethods & ALLOWEDMETHOD_GSS)
+ TCPSessGSSClose(pSess);
+ else
+ tcps_sess.Close(pSess);
+
+ RETiRet;
+}
+
+
+/* open the listen sockets */
+static rsRetVal
+doOpenLstnSocks(tcpsrv_t *pSrv)
+{
+ gsssrv_t *pGSrv;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pSrv, tcpsrv);
+ pGSrv = pSrv->pUsr;
+ assert(pGSrv != NULL);
+
+ /* first apply some config settings */
+ if(pGSrv->allowedMethods) {
+ if(pGSrv->allowedMethods & ALLOWEDMETHOD_GSS) {
+ if(TCPSessGSSInit()) {
+ LogError(0, NO_ERRCODE, "GSS-API initialization failed\n");
+ pGSrv->allowedMethods &= ~(ALLOWEDMETHOD_GSS);
+ }
+ }
+ if(pGSrv->allowedMethods) {
+ /* fallback to plain TCP */
+ CHKiRet(tcpsrv.create_tcp_socket(pSrv));
+ } else {
+ ABORT_FINALIZE(RS_RET_GSS_ERR);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf, ssize_t *piLenRcvd, int *const oserr)
+{
+ DEFiRet;
+ int allowedMethods;
+ gss_sess_t *pGSess;
+
+ assert(pSess != NULL);
+ assert(pSess->pUsr != NULL);
+ pGSess = (gss_sess_t*) pSess->pUsr;
+ assert(piLenRcvd != NULL);
+
+ allowedMethods = pGSess->allowedMethods;
+ if(allowedMethods & ALLOWEDMETHOD_GSS) {
+ CHKiRet(TCPSessGSSRecv(pSess, buf, lenBuf, piLenRcvd));
+ } else {
+ *piLenRcvd = lenBuf;
+ CHKiRet(netstrm.Rcv(pSess->pStrm, (uchar*) buf, piLenRcvd, oserr));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* end callbacks */
+
+static rsRetVal
+addGSSListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ DEFiRet;
+
+ if((ustrcmp(pNewVal, UCHAR_CONSTANT("0")) == 0 && pszLstnPortFileName == NULL)
+ || ustrcmp(pNewVal, UCHAR_CONSTANT("0")) < 0) {
+ CHKmalloc(srvPort = (uchar*)strdup("514"));
+ } else {
+ srvPort = pNewVal;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+actGSSListener(uchar *port)
+{
+ DEFiRet;
+ tcpLstnParams_t *cnf_params = NULL;
+ gsssrv_t *pGSrv = NULL;
+
+ assert(pOurTcpsrv == NULL);
+ CHKmalloc(cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
+ /* first create/init the gsssrv "object" */
+ if((pGSrv = calloc(1, sizeof(gsssrv_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pGSrv->allowedMethods = ALLOWEDMETHOD_GSS;
+ if(bPermitPlainTcp)
+ pGSrv->allowedMethods |= ALLOWEDMETHOD_TCP;
+ /* gsssrv initialized */
+
+ CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+ CHKiRet(tcpsrv.SetUsrP(pOurTcpsrv, pGSrv));
+ CHKiRet(tcpsrv.SetCBOnSessConstructFinalize(pOurTcpsrv, OnSessConstructFinalize));
+ CHKiRet(tcpsrv.SetCBOnSessDestruct(pOurTcpsrv, OnSessDestruct));
+ CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
+ CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
+ CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
+ CHKiRet(tcpsrv.SetCBOnSessAccept(pOurTcpsrv, onSessAccept));
+ CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
+ CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+ CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, cnf_params, UCHAR_CONSTANT("imgssapi")));
+ CHKiRet(tcpsrv.SetKeepAlive(pOurTcpsrv, bKeepAlive));
+ CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, UCHAR_CONSTANT("imgssapi")));
+ cnf_params->pszPort = port;
+ cnf_params->bSuppOctetFram = 1;
+ tcpsrv.configureTCPListen(pOurTcpsrv, cnf_params);
+ CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
+ cnf_params = NULL;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d trying to add listener", iRet);
+ if(pOurTcpsrv != NULL)
+ tcpsrv.Destruct(&pOurTcpsrv);
+ free(pGSrv);
+ }
+ free(cnf_params);
+ RETiRet;
+}
+
+
+/* returns 0 if all went OK, -1 if it failed */
+static int TCPSessGSSInit(void)
+{
+ gss_buffer_desc name_buf;
+ gss_name_t server_name;
+ OM_uint32 maj_stat, min_stat;
+
+ if (gss_server_creds != GSS_C_NO_CREDENTIAL)
+ return 0;
+
+ name_buf.value = (gss_listen_service_name == NULL) ? (char*)"host" : gss_listen_service_name;
+ name_buf.length = strlen(name_buf.value) + 1;
+ maj_stat = gss_import_name(&min_stat, &name_buf, GSS_C_NT_HOSTBASED_SERVICE, &server_name);
+ if (maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"importing name", maj_stat, min_stat);
+ return -1;
+ }
+
+ maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
+ GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+ &gss_server_creds, NULL, NULL);
+ if (maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"acquiring credentials", maj_stat, min_stat);
+ return -1;
+ }
+
+ gss_release_name(&min_stat, &server_name);
+ dbgprintf("GSS-API initialized\n");
+ return 0;
+}
+
+
+/* returns 0 if all went OK, -1 if it failed
+ * tries to guess if the connection uses gssapi.
+ */
+static rsRetVal
+OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess)
+{
+ DEFiRet;
+ gss_buffer_desc send_tok, recv_tok;
+ gss_name_t client;
+ OM_uint32 maj_stat, min_stat, acc_sec_min_stat;
+ gss_ctx_id_t *context;
+ OM_uint32 *sess_flags;
+ int fdSess;
+ char allowedMethods;
+ gsssrv_t *pGSrv;
+ gss_sess_t *pGSess;
+ uchar *pszPeer = NULL;
+ int lenPeer = 0;
+ char *buf = NULL;
+
+ assert(pSess != NULL);
+
+ pGSrv = (gsssrv_t*) pThis->pUsr;
+ pGSess = (gss_sess_t*) pSess->pUsr;
+ allowedMethods = pGSrv->allowedMethods;
+ if(allowedMethods & ALLOWEDMETHOD_GSS) {
+ int ret = 0;
+ const size_t bufsize = glbl.GetMaxLine(runConf);
+ CHKmalloc(buf = (char*) malloc(bufsize + 1));
+
+ prop.GetString(pSess->fromHostIP, &pszPeer, &lenPeer);
+
+ dbgprintf("GSS-API Trying to accept TCP session %p from %s\n", pSess, (char *)pszPeer);
+
+ CHKiRet(netstrm.GetSock(pSess->pStrm, &fdSess)); // TODO: method access!
+ if (allowedMethods & ALLOWEDMETHOD_TCP) {
+ int len;
+ struct timeval tv;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pFds = malloc(glbl.GetFdSetSize());
+#else
+ fd_set fds;
+ fd_set *pFds = &fds;
+#endif
+
+ do {
+ FD_ZERO(pFds);
+ FD_SET(fdSess, pFds);
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = select(fdSess + 1, pFds, NULL, NULL, &tv);
+ } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ LogError(0, RS_RET_ERR, "TCP session %p from %s will be "
+ "closed, error ignored\n", pSess, (char *)pszPeer);
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ } else if (ret == 0) {
+ dbgprintf("GSS-API Reverting to plain TCP\n");
+ pGSess->allowedMethods = ALLOWEDMETHOD_TCP;
+ ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes
+ }
+
+ do {
+ ret = recv(fdSess, buf, bufsize, MSG_PEEK);
+ } while (ret < 0 && errno == EINTR);
+ if (ret <= 0) {
+ if (ret == 0) {
+ dbgprintf("GSS-API Connection closed by peer %s\n", (char *)pszPeer);
+ } else {
+ LogError(0, RS_RET_ERR, "TCP(GSS) session %p from %s will be closed, "
+ "error ignored\n", pSess, (char *)pszPeer);
+ }
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+
+ if (ret < 4) {
+ dbgprintf("GSS-API Reverting to plain TCP from %s\n", (char *)pszPeer);
+ pGSess->allowedMethods = ALLOWEDMETHOD_TCP;
+ ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes
+ } else if (ret == 4) {
+ /* The client might has been interupted after sending
+ * the data length (4B), give him another chance.
+ */
+ srSleep(1, 0);
+ do {
+ ret = recv(fdSess, buf, bufsize, MSG_PEEK);
+ } while (ret < 0 && errno == EINTR);
+ if (ret <= 0) {
+ if (ret == 0) {
+ dbgprintf("GSS-API Connection closed by peer %s\n", (char *)pszPeer);
+ } else {
+ LogError(0, NO_ERRCODE, "TCP session %p from %s will be "
+ "closed, error ignored\n", pSess, (char *)pszPeer);
+ }
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+ }
+
+ /* TODO: how does this work together with IPv6? Does it? */
+ len = ntohl((buf[0] << 24)
+ | (buf[1] << 16)
+ | (buf[2] << 8)
+ | buf[3]);
+ if ((ret - 4) < len || len == 0) {
+ dbgprintf("GSS-API Reverting to plain TCP from %s\n", (char *)pszPeer);
+ pGSess->allowedMethods = ALLOWEDMETHOD_TCP;
+ ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes
+ }
+
+ freeFdSet(pFds);
+ }
+
+ context = &pGSess->gss_context;
+ *context = GSS_C_NO_CONTEXT;
+ sess_flags = &pGSess->gss_flags;
+ do {
+ if (gssutil.recv_token(fdSess, &recv_tok) <= 0) {
+ LogError(0, NO_ERRCODE, "TCP session %p from %s will be "
+ "closed, error ignored\n", pSess, (char *)pszPeer);
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+ maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, gss_server_creds,
+ &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client,
+ NULL, &send_tok, sess_flags, NULL, NULL);
+ if (recv_tok.value) {
+ free(recv_tok.value);
+ recv_tok.value = NULL;
+ }
+ if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
+ gss_release_buffer(&min_stat, &send_tok);
+ if (*context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER);
+ if ((allowedMethods & ALLOWEDMETHOD_TCP) &&
+ (GSS_ROUTINE_ERROR(maj_stat) == GSS_S_DEFECTIVE_TOKEN)) {
+ dbgprintf("GSS-API Reverting to plain TCP from %s\n", (char *)pszPeer);
+ dbgprintf("tcp session socket with new data: #%d\n", fdSess);
+ if(tcps_sess.DataRcvd(pSess, buf, ret) != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "Tearing down TCP "
+ "Session %p from %s - see previous messages "
+ "for reason(s)\n", pSess, (char *)pszPeer);
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+ pGSess->allowedMethods = ALLOWEDMETHOD_TCP;
+ ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes
+ }
+ gssutil.display_status((char*)"accepting context", maj_stat, acc_sec_min_stat);
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+ if (send_tok.length != 0) {
+ if(gssutil.send_token(fdSess, &send_tok) < 0) {
+ gss_release_buffer(&min_stat, &send_tok);
+ LogError(0, NO_ERRCODE, "TCP session %p from %s will be "
+ "closed, error ignored\n", pSess, (char *)pszPeer);
+ if (*context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER);
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: define good error codes
+ }
+ gss_release_buffer(&min_stat, &send_tok);
+ }
+ } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+ maj_stat = gss_display_name(&min_stat, client, &recv_tok, NULL);
+ if (maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"displaying name", maj_stat, min_stat);
+ } else {
+ dbgprintf("GSS-API Accepted connection from peer %s: %s\n", (char *)pszPeer,
+ (char*) recv_tok.value);
+ }
+ gss_release_name(&min_stat, &client);
+ gss_release_buffer(&min_stat, &recv_tok);
+
+ dbgprintf("GSS-API Provided context flags:\n");
+ gssutil.display_ctx_flags(*sess_flags);
+ pGSess->allowedMethods = ALLOWEDMETHOD_GSS;
+ }
+
+finalize_it:
+ free(buf);
+ RETiRet;
+}
+
+
+/* Replaces recv() for gssapi connections.
+ */
+rsRetVal TCPSessGSSRecv(tcps_sess_t *pSess, void *buf, size_t buf_len, ssize_t *piLenRcvd)
+{
+ DEFiRet;
+ gss_buffer_desc xmit_buf, msg_buf;
+ gss_ctx_id_t *context;
+ OM_uint32 maj_stat, min_stat;
+ int fdSess;
+ int conf_state;
+ gss_sess_t *pGSess;
+
+ assert(pSess->pUsr != NULL);
+ assert(piLenRcvd != NULL);
+ pGSess = (gss_sess_t*) pSess->pUsr;
+
+ netstrm.GetSock(pSess->pStrm, &fdSess); // TODO: method access, CHKiRet!
+ if(gssutil.recv_token(fdSess, &xmit_buf) <= 0)
+ ABORT_FINALIZE(RS_RET_GSS_ERR);
+
+ context = &pGSess->gss_context;
+ maj_stat = gss_unwrap(&min_stat, *context, &xmit_buf, &msg_buf,
+ &conf_state, (gss_qop_t *) NULL);
+ if(maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"unsealing message", maj_stat, min_stat);
+ if(xmit_buf.value) {
+ free(xmit_buf.value);
+ xmit_buf.value = 0;
+ }
+ ABORT_FINALIZE(RS_RET_GSS_ERR);
+ }
+ if (xmit_buf.value) {
+ free(xmit_buf.value);
+ xmit_buf.value = 0;
+ }
+
+ *piLenRcvd = msg_buf.length < buf_len ? msg_buf.length : buf_len;
+ memcpy(buf, msg_buf.value, *piLenRcvd);
+ gss_release_buffer(&min_stat, &msg_buf);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Takes care of cleaning up gssapi stuff and then calls
+ * TCPSessClose().
+ */
+void TCPSessGSSClose(tcps_sess_t* pSess)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_ctx_id_t *context;
+ gss_sess_t *pGSess;
+
+ assert(pSess->pUsr != NULL);
+ pGSess = (gss_sess_t*) pSess->pUsr;
+
+ context = &pGSess->gss_context;
+ maj_stat = gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER);
+ if (maj_stat != GSS_S_COMPLETE)
+ gssutil.display_status((char*)"deleting context", maj_stat, min_stat);
+ *context = GSS_C_NO_CONTEXT;
+ pGSess->gss_flags = 0;
+ pGSess->allowedMethods = 0;
+
+ tcps_sess.Close(pSess);
+}
+
+
+/* Counterpart of TCPSessGSSInit(). This is called to exit the GSS system
+ * at all. It is a server-based session exit.
+ */
+static rsRetVal
+TCPSessGSSDeinit(void)
+{
+ DEFiRet;
+ OM_uint32 maj_stat, min_stat;
+
+ if (gss_server_creds != GSS_C_NO_CREDENTIAL) {
+ maj_stat = gss_release_cred(&min_stat, &gss_server_creds);
+ if (maj_stat != GSS_S_COMPLETE)
+ gssutil.display_status((char*)"releasing credentials", maj_stat, min_stat);
+ }
+ RETiRet;
+}
+
+
+#if 0 /* can be used to integrate into new config system */
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+#endif
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ /* This will fail if the priviledges are dropped. Should be
+ * moved to the '*activateCnfPrePrivDrop' section eventually.
+ */
+ actGSSListener(srvPort);
+
+ iRet = tcpsrv.Run(pOurTcpsrv);
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ if(srvPort == NULL)
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+
+ net.PrintAllowedSenders(2); /* TCP */
+ net.PrintAllowedSenders(3); /* GSS */
+finalize_it:
+ENDwillRun
+
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pOurTcpsrv != NULL)
+ iRet = tcpsrv.Destruct(&pOurTcpsrv);
+ TCPSessGSSDeinit();
+
+ /* release objects we used */
+ objRelease(tcps_sess, LM_TCPSRV_FILENAME);
+ objRelease(tcpsrv, LM_TCPSRV_FILENAME);
+ objRelease(gssutil, LM_GSSUTIL_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(netstrm, LM_NETSTRM_FILENAME);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINafterRun
+CODESTARTafterRun
+ /* do cleanup here */
+ net.clearAllowedSenders((uchar*)"TCP");
+ net.clearAllowedSenders((uchar*)"GSS");
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ if (gss_listen_service_name != NULL) {
+ free(gss_listen_service_name);
+ gss_listen_service_name = NULL;
+ }
+ if (pszLstnPortFileName != NULL) {
+ free(pszLstnPortFileName);
+ pszLstnPortFileName = NULL;
+ }
+ bPermitPlainTcp = 0;
+ iTCPSessMax = 200;
+ bKeepAlive = 0;
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ pOurTcpsrv = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgssserverpermitplaintcp", 0, eCmdHdlrBinary,
+ NULL, &bPermitPlainTcp, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgssserverrun", 0, eCmdHdlrGetWord,
+ addGSSListener, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgssserverservicename", 0, eCmdHdlrGetWord,
+ NULL, &gss_listen_service_name, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgsslistenportfilename", 0, eCmdHdlrGetWord,
+ NULL, &pszLstnPortFileName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgssservermaxsessions", 0, eCmdHdlrInt,
+ NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputgssserverkeepalive", 0, eCmdHdlrBinary,
+ NULL, &bKeepAlive, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/imjournal/Makefile.am b/plugins/imjournal/Makefile.am
new file mode 100644
index 0000000..5306130
--- /dev/null
+++ b/plugins/imjournal/Makefile.am
@@ -0,0 +1,12 @@
+pkglib_LTLIBRARIES = imjournal.la
+
+if IMJOURNAL_USE_DUMMY
+imjournal_la_SOURCES = dummy.c
+imjournal_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) -D MODNAME=imjournal
+imjournal_la_LDFLAGS = -module -avoid-version
+else
+imjournal_la_SOURCES = imjournal.c
+imjournal_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBSYSTEMD_JOURNAL_CFLAGS)
+imjournal_la_LDFLAGS = -module -avoid-version
+imjournal_la_LIBADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+endif
diff --git a/plugins/imjournal/Makefile.in b/plugins/imjournal/Makefile.in
new file mode 100644
index 0000000..ff4bd52
--- /dev/null
+++ b/plugins/imjournal/Makefile.in
@@ -0,0 +1,816 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imjournal
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@IMJOURNAL_USE_DUMMY_FALSE@imjournal_la_DEPENDENCIES = \
+@IMJOURNAL_USE_DUMMY_FALSE@ $(am__DEPENDENCIES_1)
+am__imjournal_la_SOURCES_DIST = imjournal.c dummy.c
+@IMJOURNAL_USE_DUMMY_FALSE@am_imjournal_la_OBJECTS = \
+@IMJOURNAL_USE_DUMMY_FALSE@ imjournal_la-imjournal.lo
+@IMJOURNAL_USE_DUMMY_TRUE@am_imjournal_la_OBJECTS = \
+@IMJOURNAL_USE_DUMMY_TRUE@ imjournal_la-dummy.lo
+imjournal_la_OBJECTS = $(am_imjournal_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 =
+imjournal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imjournal_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imjournal_la-dummy.Plo \
+ ./$(DEPDIR)/imjournal_la-imjournal.Plo
+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 = $(imjournal_la_SOURCES)
+DIST_SOURCES = $(am__imjournal_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imjournal.la
+@IMJOURNAL_USE_DUMMY_FALSE@imjournal_la_SOURCES = imjournal.c
+@IMJOURNAL_USE_DUMMY_TRUE@imjournal_la_SOURCES = dummy.c
+@IMJOURNAL_USE_DUMMY_FALSE@imjournal_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBSYSTEMD_JOURNAL_CFLAGS)
+@IMJOURNAL_USE_DUMMY_TRUE@imjournal_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) -D MODNAME=imjournal
+@IMJOURNAL_USE_DUMMY_FALSE@imjournal_la_LDFLAGS = -module -avoid-version
+@IMJOURNAL_USE_DUMMY_TRUE@imjournal_la_LDFLAGS = -module -avoid-version
+@IMJOURNAL_USE_DUMMY_FALSE@imjournal_la_LIBADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+all: 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) --gnu plugins/imjournal/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imjournal/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imjournal.la: $(imjournal_la_OBJECTS) $(imjournal_la_DEPENDENCIES) $(EXTRA_imjournal_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imjournal_la_LINK) -rpath $(pkglibdir) $(imjournal_la_OBJECTS) $(imjournal_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imjournal_la-dummy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imjournal_la-imjournal.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imjournal_la-imjournal.lo: imjournal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imjournal_la-imjournal.lo -MD -MP -MF $(DEPDIR)/imjournal_la-imjournal.Tpo -c -o imjournal_la-imjournal.lo `test -f 'imjournal.c' || echo '$(srcdir)/'`imjournal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imjournal_la-imjournal.Tpo $(DEPDIR)/imjournal_la-imjournal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imjournal.c' object='imjournal_la-imjournal.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) $(imjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imjournal_la-imjournal.lo `test -f 'imjournal.c' || echo '$(srcdir)/'`imjournal.c
+
+imjournal_la-dummy.lo: dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imjournal_la-dummy.lo -MD -MP -MF $(DEPDIR)/imjournal_la-dummy.Tpo -c -o imjournal_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imjournal_la-dummy.Tpo $(DEPDIR)/imjournal_la-dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='imjournal_la-dummy.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) $(imjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imjournal_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imjournal_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/imjournal_la-imjournal.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imjournal_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/imjournal_la-imjournal.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imjournal/dummy.c b/plugins/imjournal/dummy.c
new file mode 100644
index 0000000..fe8c249
--- /dev/null
+++ b/plugins/imjournal/dummy.c
@@ -0,0 +1,171 @@
+/* a dummy module to be loaded if we cannot build this module, but
+ * configure required it to be "optional".
+ *
+ * Copyright 2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+#define MODULE_NAME(x) #x
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME(MODULE_NAME(MODNAME))
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ (void) lst;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDsetModCnf
+
+
+BEGINnewActInst
+CODESTARTnewActInst
+ (void) pData;
+ (void) ppModData;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void) pMsgData;
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("dummy module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
new file mode 100644
index 0000000..cda9b4b
--- /dev/null
+++ b/plugins/imjournal/imjournal.c
@@ -0,0 +1,1496 @@
+/* The systemd journal import module
+ *
+ * To test under Linux:
+ * emmit log message into systemd journal
+ *
+ * Copyright (C) 2008-2019 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <dirent.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <systemd/sd-journal.h>
+#include <fcntl.h>
+
+#include "dirty.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "msg.h"
+#include "module-template.h"
+#include "datetime.h"
+#include "net.h"
+#include "glbl.h"
+#include "statsobj.h"
+#include "ruleset.h"
+#include "parser.h"
+#include "prop.h"
+#include "errmsg.h"
+#include "srUtils.h"
+#include "unicode-helper.h"
+#include "ratelimit.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imjournal")
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+/* Module static data */
+typedef struct journal_etry_s {
+ pthread_t tid; /* the worker's thread ID */
+ ruleset_t *pBindRuleset;
+ char* stateFile;
+ struct journalContext_s *journalContext;
+ struct journal_etry_s *next;
+} journal_etry_t;
+static journal_etry_t *journal_root = NULL;
+static int n_journal = 0;
+
+struct modConfData_s {
+ rsconf_t *pConf;
+ instanceConf_t *root, *tail;
+};
+
+static struct configSettings_s {
+ char *stateFile;
+ int fCreateMode; /* default mode to use when creating new files, e.g. stateFile */
+ int iPersistStateInterval;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ int bIgnorePrevious;
+ int bIgnoreNonValidStatefile;
+ int iDfltSeverity;
+ int iDfltFacility;
+ int bUseJnlPID;
+ char *usePid;
+ int bWorkAroundJournalBug; /* deprecated, left for backwards compatibility only */
+ int bFsync;
+ int bRemote;
+ char *dfltTag;
+} cs;
+
+static rsRetVal facilityHdlr(uchar **pp, void *pVal);
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "statefile", eCmdHdlrGetWord, 0 },
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "persiststateinterval", eCmdHdlrInt, 0 },
+ { "ignorepreviousmessages", eCmdHdlrBinary, 0 },
+ { "ignorenonvalidstatefile", eCmdHdlrBinary, 0 },
+ { "defaultseverity", eCmdHdlrSeverity, 0 },
+ { "defaultfacility", eCmdHdlrString, 0 },
+ { "usepidfromsystem", eCmdHdlrBinary, 0 },
+ { "usepid", eCmdHdlrString, 0 },
+ { "workaroundjournalbug", eCmdHdlrBinary, 0 },
+ { "fsync", eCmdHdlrBinary, 0 },
+ { "remote", eCmdHdlrBinary, 0 },
+ { "defaulttag", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "ruleset", eCmdHdlrString, 0 },
+ { "main", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+struct instanceConf_s {
+ struct instanceConf_s *next;
+ char *stateFile;
+ uchar *pszBindRuleset;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ int bMain;
+};
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+#define DFLT_persiststateinterval 10
+#define DFLT_SEVERITY pri2sev(LOG_NOTICE)
+#define DFLT_FACILITY pri2fac(LOG_USER)
+#define DFLT_TAG "journal"
+
+static int bLegacyCnfModGlobalsPermitted = 1;/* are legacy module-global config parameters permitted? */
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this module */
+static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */
+static const char *pidFieldName; /* read-only after startup */
+static int bPidFallBack;
+static ratelimit_t *ratelimiter = NULL;
+static struct {
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted)
+ STATSCOUNTER_DEF(ctrRead, mutCtrRead);
+ STATSCOUNTER_DEF(ctrDiscarded, mutCtrDiscarded);
+ STATSCOUNTER_DEF(ctrFailed, mutCtrFailed);
+ STATSCOUNTER_DEF(ctrPollFailed, mutCtrPollFailed);
+ STATSCOUNTER_DEF(ctrRotations, mutCtrRotations);
+ STATSCOUNTER_DEF(ctrRecoveryAttempts, mutCtrRecoveryAttempts);
+ uint64 ratelimitDiscardedInInterval;
+ uint64 diskUsageBytes;
+} statsCounter;
+struct journalContext_s { /* structure encapsulating all the journald_API-related stuff */
+ sd_journal *j; /* main object encapsulating journal for us, has to be used in every sd_journal*() call */
+ sbool reloaded; /* we have reloaded journal after detecting rotation */
+ sbool atHead; /* true if we are at start of journal (no seek was done) */
+ char *cursor; /* should point to last valid journald entry we processed */
+};
+
+#define MAX_JOURNAL 8
+static struct journalContext_s journalContextArray[MAX_JOURNAL] = {
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+ {NULL, 0, 1, NULL},
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for run process */
+
+#define J_PROCESS_PERIOD 1024 /* Call sd_journal_process() every 1,024 records */
+
+static rsRetVal persistJournalState(struct journalContext_s *journalContext, char* stateFile);
+static rsRetVal loadJournalState(struct journalContext_s *journalContext, char* stateFile);
+
+static rsRetVal openJournal(struct journalContext_s *journalContext) {
+
+ int r;
+ DEFiRet;
+
+ if (journalContext->j) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: opening journal when already opened.\n");
+ }
+ if ((r = sd_journal_open(&journalContext->j, cs.bRemote? 0 : SD_JOURNAL_LOCAL_ONLY)) < 0) {
+ LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_open() failed");
+ iRet = RS_RET_IO_ERROR;
+ }
+ if ((r = sd_journal_set_data_threshold(journalContext->j, glbl.GetMaxLine(runModConf->pConf))) < 0) {
+ LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_set_data_threshold() failed");
+ iRet = RS_RET_IO_ERROR;
+ }
+ journalContext->atHead = 1;
+ RETiRet;
+}
+
+/* trySave shoulod only be true if there is no journald error preceeding this call */
+static void closeJournal(struct journalContext_s *journalContext) {
+ if (!journalContext->j) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: closing NULL journal.\n");
+ }
+ sd_journal_close(journalContext->j);
+ journalContext->j = NULL; /* setting to NULL here as journald API will not do that for us... */
+}
+
+static int journalGetData(struct journalContext_s *journalContext, const char *field, const void **data, size_t *length)
+{
+ int ret;
+
+ ret = sd_journal_get_data(journalContext->j, field, data, length);
+ if (ret == -EADDRNOTAVAIL) {
+ LogError(-ret, RS_RET_ERR, "imjournal: Tried to get data without a 'next' call.\n");
+ if ((ret = sd_journal_next(journalContext->j)) < 0) {
+ LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_next() failed\n");
+ } else {
+ ret = sd_journal_get_data(journalContext->j, field, data, length);
+ }
+ }
+
+ return ret;
+}
+
+
+/* ugly workaround to handle facility numbers; values
+ * derived from names need to be eight times smaller,
+ * i.e.: 0..23
+ */
+static rsRetVal facilityHdlr(uchar **pp, void *pVal)
+{
+ DEFiRet;
+ char *p;
+
+ skipWhiteSpace(pp);
+ p = (char *) *pp;
+
+ if (isdigit((int) *p)) {
+ *((int *) pVal) = (int) strtol(p, (char **) pp, 10);
+ } else {
+ int len;
+ syslogName_t *c;
+
+ for (len = 0; p[len] && !isspace((int) p[len]); len++)
+ /* noop */;
+ for (c = syslogFacNames; c->c_name; c++) {
+ if (!strncasecmp(p, (char *) c->c_name, len)) {
+ *((int *) pVal) = pri2fac(c->c_val);
+ break;
+ }
+ }
+ *pp += len;
+ }
+
+ RETiRet;
+}
+
+
+/* Currently just replaces '\0' with ' '. Not doing so would cause
+ * the value to be truncated. New space is allocated for the resulting
+ * string.
+ */
+static rsRetVal
+sanitizeValue(const char *in, size_t len, char **out)
+{
+ char *buf, *p;
+ DEFiRet;
+
+ CHKmalloc(p = buf = malloc(len + 1));
+ memcpy(buf, in, len);
+ buf[len] = '\0';
+
+ while ((p = memchr(p, '\0', len + buf - p)) != NULL) {
+ *p++ = ' ';
+ }
+
+ *out = buf;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Read JSON part of single journald message and return it as JSON object
+ */
+static rsRetVal
+readJSONfromJournalMsg(struct journalContext_s *journalContext, struct fjson_object **json)
+{
+ DEFiRet;
+ const void *get;
+ const void *equal_sign;
+ struct fjson_object *jval;
+ size_t l;
+ long prefixlen = 0;
+
+ CHKmalloc(*json = fjson_object_new_object());
+
+ SD_JOURNAL_FOREACH_DATA(journalContext->j, get, l) {
+ char *data;
+ char *name;
+
+ /* locate equal sign, this is always present */
+ equal_sign = memchr(get, '=', l);
+
+ /* ... but we know better than to trust the specs */
+ if (equal_sign == NULL) {
+ LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
+ "returned a malformed field (has no '='): '%s'", (char*)get);
+ continue; /* skip the entry */
+ }
+
+ /* get length of journal data prefix */
+ prefixlen = ((char *)equal_sign - (char *)get);
+
+ CHKmalloc(name = strndup(get, prefixlen));
+
+ prefixlen++; /* remove '=' */
+
+ CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
+ free (name);
+ FINALIZE;
+ }
+
+ /* and save them to json object */
+ jval = fjson_object_new_string((char *)data);
+ fjson_object_object_add(*json, name, jval);
+ free (data);
+ free (name);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Try to obtain current journald cursor and save it to journalContext struct.
+ */
+static rsRetVal
+updateJournalCursor(struct journalContext_s *journalContext)
+{
+ DEFiRet;
+ char *c = NULL;
+ int r;
+
+ if ((r = sd_journal_get_cursor(journalContext->j, &c)) < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: Could not get journald cursor!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* save journal cursor (at this point we can be sure it is valid) */
+ free(journalContext->cursor);
+ journalContext->cursor = c;
+finalize_it:
+ RETiRet;
+}
+
+
+/* enqueue the the journal message into the message queue.
+ * The provided msg string is not freed - thus must be done
+ * by the caller.
+ */
+static rsRetVal
+enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *tp, struct fjson_object *json,
+int sharedJsonProperties, ruleset_t *pBindRuleset)
+{
+ struct syslogTime st;
+ smsg_t *pMsg;
+ size_t len;
+ DEFiRet;
+
+ assert(msg != NULL);
+ assert(pszTag != NULL);
+
+ if(tp == NULL) {
+ CHKiRet(msgConstruct(&pMsg));
+ } else {
+ datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
+ CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
+ }
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ len = strlen((char*)msg);
+ MsgSetRawMsg(pMsg, (char*)msg, len);
+ if(len > 0)
+ parser.SanitizeMsg(pMsg);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, pLocalHostIP);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
+ if (pBindRuleset != NULL) {
+ MsgSetRuleset(pMsg, pBindRuleset);
+ }
+ pMsg->iFacility = iFacility;
+ pMsg->iSeverity = iSeverity;
+
+ if(json != NULL) {
+ msgAddJSON(pMsg, (uchar*)"!", json, 0, sharedJsonProperties);
+ }
+
+ CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg));
+ STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+
+finalize_it:
+ if (iRet == RS_RET_DISCARDMSG) {
+ STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ } else if (iRet != RS_RET_OK) {
+ LogError(0, RS_RET_ERR, "imjournal: error during enqMsg().\n");
+ }
+
+ RETiRet;
+}
+
+
+/* Read journal log while data are available, each read() reads one journald record.
+ */
+static rsRetVal
+readjournal(struct journalContext_s *journalContext, ruleset_t *pBindRuleset)
+{
+ DEFiRet;
+
+ struct timeval tv;
+ uint64_t timestamp;
+
+ struct fjson_object *json = NULL;
+ int r;
+
+ /* Information from messages */
+ char *message = NULL;
+ char *sys_iden;
+ char *sys_iden_help = NULL;
+
+ const void *get;
+ const void *pidget;
+ size_t length;
+ size_t pidlength;
+
+ int severity = cs.iDfltSeverity;
+ int facility = cs.iDfltFacility;
+
+ /* Get message text */
+ if (journalGetData(journalContext, "MESSAGE", &get, &length) < 0) {
+ CHKmalloc(message = strdup(""));
+ } else {
+ CHKiRet(sanitizeValue(((const char *)get) + 8, length - 8, &message));
+ }
+ STATSCOUNTER_INC(statsCounter.ctrRead, statsCounter.mutCtrRead);
+
+ /* Get message severity ("priority" in journald's terminology) */
+ if (journalGetData(journalContext, "PRIORITY", &get, &length) >= 0) {
+ if (length == 10) {
+ severity = ((char *)get)[9] - '0';
+ if (severity < 0 || 7 < severity) {
+ LogError(0, RS_RET_ERR, "imjournal: the value of the 'PRIORITY' field is "
+ "out of bounds: %d, resetting", severity);
+ severity = cs.iDfltSeverity;
+ }
+ } else {
+ LogError(0, RS_RET_ERR, "The value of the 'PRIORITY' field has an "
+ "unexpected length: %zu\n", length);
+ }
+ }
+
+ /* Get syslog facility */
+ if (journalGetData(journalContext, "SYSLOG_FACILITY", &get, &length) >= 0) {
+ // Note: the journal frequently contains invalid facilities!
+ if (length == 17 || length == 18) {
+ facility = ((char *)get)[16] - '0';
+ if (length == 18) {
+ facility *= 10;
+ facility += ((char *)get)[17] - '0';
+ }
+ if (facility < 0 || 23 < facility) {
+ DBGPRINTF("The value of the 'FACILITY' field is "
+ "out of bounds: %d, resetting\n", facility);
+ facility = cs.iDfltFacility;
+ }
+ } else {
+ DBGPRINTF("The value of the 'FACILITY' field has an "
+ "unexpected length: %zu value: '%s'\n", length, (const char*)get);
+ }
+ }
+
+ /* Get message identifier, client pid and add ':' */
+ if (journalGetData(journalContext, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
+ CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
+ } else if (journalGetData(journalContext, "_COMM", &get, &length) >= 0) {
+ CHKiRet(sanitizeValue(((const char *)get) + 6, length - 6, &sys_iden));
+ } else {
+ CHKmalloc(sys_iden = strdup(cs.dfltTag));
+ }
+
+ /* trying to get PID, default is "SYSLOG_PID" property */
+ if (journalGetData(journalContext, pidFieldName, &pidget, &pidlength) >= 0) {
+ char *sys_pid;
+ int val_ofs;
+
+ val_ofs = strlen(pidFieldName) + 1; /* name + '=' */
+ CHKiRet_Hdlr(sanitizeValue(((const char *)pidget) + val_ofs, pidlength - val_ofs, &sys_pid)) {
+ free (sys_iden);
+ FINALIZE;
+ }
+ r = asprintf(&sys_iden_help, "%s[%s]:", sys_iden, sys_pid);
+ free (sys_pid);
+ } else {
+ /* this is fallback, "SYSLOG_PID" doesn't exist so trying to get "_PID" property */
+ if (bPidFallBack && journalGetData(journalContext, "_PID", &pidget, &pidlength) >= 0) {
+ char *sys_pid;
+ int val_ofs;
+
+ val_ofs = strlen("_PID") + 1; /* name + '=' */
+ CHKiRet_Hdlr(sanitizeValue(((const char *)pidget) + val_ofs, pidlength - val_ofs, &sys_pid)) {
+ free (sys_iden);
+ FINALIZE;
+ }
+ r = asprintf(&sys_iden_help, "%s[%s]:", sys_iden, sys_pid);
+ free (sys_pid);
+ } else {
+ /* there is no PID property available */
+ r = asprintf(&sys_iden_help, "%s:", sys_iden);
+ }
+ }
+
+ free (sys_iden);
+
+ if (-1 == r) {
+ STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ CHKiRet(readJSONfromJournalMsg(journalContext, &json));
+
+ /* calculate timestamp */
+ if (sd_journal_get_realtime_usec(journalContext->j, &timestamp) >= 0) {
+ tv.tv_sec = timestamp / 1000000;
+ tv.tv_usec = timestamp % 1000000;
+ }
+
+ iRet = updateJournalCursor(journalContext);
+
+ /* submit message */
+ enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json, 0, pBindRuleset);
+
+finalize_it:
+ free(sys_iden_help);
+ free(message);
+ RETiRet;
+}
+
+
+/* This function saves journal cursor into state file.
+ * It must be checked that stateFile is configured prior to calling this.
+ */
+static rsRetVal
+persistJournalState(struct journalContext_s *journalContext, char* stateFile)
+{
+ DEFiRet;
+ char tmp_sf[MAXFNAME];
+ int fd = -1;
+ size_t len;
+ ssize_t wr_ret;
+
+ DBGPRINTF("Persisting journal position, cursor: %s, at head? %d\n",
+ journalContext->cursor, journalContext->atHead);
+
+ /* first check that we have valid cursor */
+ if (!journalContext->cursor) {
+ DBGPRINTF("Journal cursor is not valid, ok...\n");
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* we create a temporary name by adding a ".tmp"
+ * suffix to the end of our state file's name
+ *
+ * we use snprintf() to safely honor the boundaries
+ * of the temporary state file name buffer by using
+ * a precision specifier, which will limit the number
+ * of bytes taken from stateFile to what will fit
+ *
+ * TODO: figure out a better way to avoid the PATH_MAX
+ * problem. The truncated stateFile with .tmp at the
+ * end is not optimal
+ */
+#define IM_SF_TMP_SUFFIX ".tmp"
+ snprintf(tmp_sf, sizeof(tmp_sf), "%.*s%s",
+ /* this calculates the max size for state file name, note that
+ * sizeof() NOT -1 is intentional - it reserves spaces for the
+ * NUL terminator.
+ */
+ (int)(sizeof(tmp_sf) - sizeof(IM_SF_TMP_SUFFIX)),
+ stateFile, IM_SF_TMP_SUFFIX);
+
+ fd = open((char*) tmp_sf, O_WRONLY|O_CREAT|O_CLOEXEC, cs.fCreateMode);
+ if (fd == -1) {
+ LogError(errno, RS_RET_FILE_OPEN_ERROR, "imjournal: open() failed for path: '%s'", tmp_sf);
+ ABORT_FINALIZE(RS_RET_FILE_OPEN_ERROR);
+ }
+
+ len = strlen(journalContext->cursor);
+ wr_ret = write(fd, journalContext->cursor, len);
+ if (wr_ret != (ssize_t)len) {
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to save cursor to: '%s',"
+ "write returned %zd, expected %zu", cs.stateFile, wr_ret, len);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* change the name of the file to the configured one */
+ if (rename(tmp_sf, stateFile) < 0) {
+ LogError(errno, iRet, "imjournal: rename() failed for new path: '%s'", stateFile);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if (cs.bFsync) {
+ if (fsync(fd) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: fsync on '%s' failed", stateFile);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ /* In order to guarantee physical write we need to force parent sync as well */
+ DIR *wd;
+ if (!(wd = opendir((char *)glbl.GetWorkDir(runModConf->pConf)))) {
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to open '%s' directory",
+ glbl.GetWorkDir(runModConf->pConf));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ if (fsync(dirfd(wd)) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: fsync on '%s' failed",
+ glbl.GetWorkDir(runModConf->pConf));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ closedir(wd);
+ }
+
+ DBGPRINTF("Persisted journal to '%s'\n", stateFile);
+
+finalize_it:
+ if (fd != -1) {
+ if (close(fd) == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "imjournal: close() failed for path: '%s'", tmp_sf);
+ iRet = RS_RET_IO_ERROR;
+ }
+ }
+ RETiRet;
+}
+
+
+static rsRetVal skipOldMessages(struct journalContext_s *journalContext);
+
+static rsRetVal
+handleRotation(struct journalContext_s *journalContext, char* stateFile)
+{
+ DEFiRet;
+ int r;
+
+ LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal files changed, reloading...\n");
+ STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
+ closeJournal(journalContext);
+
+ iRet = openJournal(journalContext);
+ if (iRet != RS_RET_OK) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* outside error scenarios we should always have a cursor available at this point */
+ if (!journalContext->cursor)
+ {
+ if (stateFile) {
+ iRet = loadJournalState(journalContext, stateFile);
+ }
+ else if (cs.bIgnorePrevious) {
+ /* Seek to the very end of the journal and ignore all older messages. */
+ iRet = skipOldMessages(journalContext);
+ }
+ FINALIZE;
+ }
+
+ if (sd_journal_seek_cursor(journalContext->j, journalContext->cursor) != 0) {
+ LogError(0, RS_RET_ERR, "imjournal: "
+ "couldn't seek to cursor `%s'\n", journalContext->cursor);
+ iRet = RS_RET_ERR;
+ }
+ journalContext->atHead = 0;
+ /* Need to advance because cursor points at last processed message */
+ if ((r = sd_journal_next(journalContext->j)) < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
+ iRet = RS_RET_ERR;
+ }
+
+finalize_it:
+ journalContext->reloaded = 1;
+ RETiRet;
+}
+
+#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
+
+static rsRetVal
+pollJournal(struct journalContext_s *journalContext, char* stateFile)
+{
+ DEFiRet;
+ int err;
+
+ err = sd_journal_wait(journalContext->j, POLL_TIMEOUT);
+ if (err == SD_JOURNAL_INVALIDATE && !journalContext->reloaded) {
+ CHKiRet(handleRotation(journalContext, stateFile));
+ }
+ else {
+ journalContext->reloaded = 0;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+skipOldMessages(struct journalContext_s *journalContext)
+{
+ int r;
+ DEFiRet;
+
+ if ((r = sd_journal_seek_tail(journalContext->j)) < 0) {
+ LogError(-r, RS_RET_ERR,
+ "imjournal: sd_journal_seek_tail() failed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ journalContext->atHead = 0;
+ if ((r = sd_journal_previous(journalContext->j)) < 0) {
+ LogError(-r, RS_RET_ERR,
+ "imjournal: sd_journal_previous() failed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* This function loads a journal cursor from the state file.
+ */
+static rsRetVal
+loadJournalState(struct journalContext_s *journalContext, char* stateFile)
+{
+ DEFiRet;
+ int r;
+ FILE *r_sf;
+
+ DBGPRINTF("Loading journal position, at head? %d, reloaded? %d\n",
+ journalContext->atHead, journalContext->reloaded);
+
+ /* if state file not exists (on very first run), skip */
+ if (access(stateFile, F_OK|R_OK) == -1 && errno == ENOENT) {
+ if (cs.bIgnorePrevious) {
+ /* Seek to the very end of the journal and ignore all older messages. */
+ skipOldMessages(journalContext);
+ }
+ LogMsg(errno, RS_RET_FILE_NOT_FOUND, LOG_NOTICE, "imjournal: No statefile exists, "
+ "%s will be created (ignore if this is first run)", stateFile);
+ FINALIZE;
+ }
+
+ if ((r_sf = fopen(stateFile, "rb")) != NULL) {
+ char readCursor[128 + 1];
+ if (fscanf(r_sf, "%128s\n", readCursor) != EOF) {
+ if (sd_journal_seek_cursor(journalContext->j, readCursor) != 0) {
+ LogError(0, RS_RET_ERR, "imjournal: "
+ "couldn't seek to cursor `%s'\n", readCursor);
+ iRet = RS_RET_ERR;
+ } else {
+ journalContext->atHead = 0;
+ char * tmp_cursor = NULL;
+ sd_journal_next(journalContext->j);
+ /*
+ * This is resolving the situation when system is after reboot and boot_id
+ * doesn't match so cursor pointing into "future".
+ * Usually sd_journal_next jump to head of journal due to journal aproximation,
+ * but when system time goes backwards and cursor is still
+ invalid, rsyslog stops logging.
+ * We use sd_journal_get_cursor to validate our cursor.
+ * When cursor is invalid we are trying to jump to the head of journal
+ * This problem with time should not affect persistent journal,
+ * but if cursor has been intentionally compromised it could stop logging even
+ * with persistent journal.
+ * */
+ if ((r = sd_journal_get_cursor(journalContext->j, &tmp_cursor)) < 0) {
+ LogError(-r, RS_RET_IO_ERROR, "imjournal: "
+ "loaded invalid cursor, seeking to the head of journal\n");
+ if ((r = sd_journal_seek_head(journalContext->j)) < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: "
+ "sd_journal_seek_head() failed, when cursor is invalid\n");
+ iRet = RS_RET_ERR;
+ }
+ journalContext->atHead = 1;
+ }
+ free(tmp_cursor);
+ }
+ } else {
+ LogError(0, RS_RET_IO_ERROR, "imjournal: "
+ "fscanf on state file `%s' failed\n", stateFile);
+ iRet = RS_RET_IO_ERROR;
+ }
+
+ fclose(r_sf);
+
+ if (iRet != RS_RET_OK && cs.bIgnoreNonValidStatefile) {
+ /* ignore state file errors */
+ iRet = RS_RET_OK;
+ LogError(0, NO_ERRCODE, "imjournal: ignoring invalid state file %s", stateFile);
+ if (cs.bIgnorePrevious) {
+ skipOldMessages(journalContext);
+ }
+ }
+ } else {
+ LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: open on state file `%s' failed\n", stateFile);
+ if (cs.bIgnorePrevious) {
+ /* Seek to the very end of the journal and ignore all older messages. */
+ skipOldMessages(journalContext);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+tryRecover(struct journalContext_s *journalContext) {
+ LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from journal error");
+ STATSCOUNTER_INC(statsCounter.ctrRecoveryAttempts, statsCounter.mutCtrRecoveryAttempts);
+ closeJournal(journalContext);
+ srSleep(0, 200000); // do not hammer machine with too-frequent retries
+ openJournal(journalContext);
+}
+
+static rsRetVal
+addListner(instanceConf_t *inst, u_int8_t index)
+{
+ DEFiRet;
+ if (index >= MAX_JOURNAL) {
+ iRet = RS_RET_NO_MORE_DATA;
+ RETiRet;
+ }
+
+ journal_etry_t *etry;
+ CHKmalloc(etry = (journal_etry_t*) calloc(1, sizeof(journal_etry_t)));
+ etry->journalContext = &journalContextArray[index];
+ if (inst) {
+ etry->pBindRuleset = inst->pBindRuleset;
+ etry->stateFile = inst->stateFile;
+ }
+ etry->next = journal_root;
+ journal_root = etry;
+ ++n_journal;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "imjournal: error %d trying to add listener", iRet);
+ free(etry);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+doRun(journal_etry_t const* etry)
+{
+ DEFiRet;
+ uint64_t count = 0;
+ char* stateFile = cs.stateFile;
+ if (etry->stateFile) {
+ stateFile = etry->stateFile;
+ }
+
+ if (stateFile) {
+ /* Load our position in the journal from the state file. */
+ CHKiRet(loadJournalState(etry->journalContext, stateFile));
+ } else if (cs.bIgnorePrevious) {
+ /* Seek to the very end of the journal and ignore all older messages. */
+ skipOldMessages(etry->journalContext);
+ }
+
+ if (cs.dfltTag == NULL) {
+ cs.dfltTag = strdup(DFLT_TAG);
+ }
+
+ if (cs.usePid && (strcmp(cs.usePid, "system") == 0)) {
+ pidFieldName = "_PID";
+ bPidFallBack = 0;
+ } else if (cs.usePid && (strcmp(cs.usePid, "syslog") == 0)) {
+ pidFieldName = "SYSLOG_PID";
+ bPidFallBack = 0;
+ } else {
+ pidFieldName = "SYSLOG_PID";
+ bPidFallBack = 1;
+ if (cs.usePid && (strcmp(cs.usePid, "both") != 0)) {
+ LogError(0, RS_RET_OK, "option \"usepid\""
+ " should contain one of system|syslog|both and no '%s'",cs.usePid);
+ }
+ }
+
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework.
+ */
+ while (glbl.GetGlobalInputTermState() == 0) {
+ int r;
+
+ r = sd_journal_next(etry->journalContext->j);
+ if (r < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
+ tryRecover(etry->journalContext);
+ continue;
+ }
+
+ if (r == 0) {
+ if (etry->journalContext->atHead) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "imjournal: "
+ "Journal indicates no msgs when positioned at head.\n");
+ }
+ /* No new messages, wait for activity. */
+ if (pollJournal(etry->journalContext, stateFile) != RS_RET_OK &&
+ !etry->journalContext->reloaded) {
+ tryRecover(etry->journalContext);
+ }
+ continue;
+ }
+
+ /*
+ * update journal disk usage before reading the new message.
+ */
+ const int e = sd_journal_get_usage(etry->journalContext->j, (uint64_t *)&statsCounter.diskUsageBytes);
+ if (e < 0) {
+ LogError(-e, RS_RET_ERR, "imjournal: sd_get_usage() failed");
+ }
+
+ if (readjournal(etry->journalContext, etry->pBindRuleset) != RS_RET_OK) {
+ tryRecover(etry->journalContext);
+ continue;
+ }
+
+ count++;
+ etry->journalContext->atHead = 0;
+ if (stateFile) { /* can't persist without a state file */
+ /* TODO: This could use some finer metric. */
+ if ((count % cs.iPersistStateInterval) == 0) {
+ persistJournalState(etry->journalContext, stateFile);
+ }
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+static void *
+RunServerThread(void *myself)
+{
+ DEFiRet;
+ journal_etry_t *const etry = (journal_etry_t*) myself;
+ iRet = doRun(etry);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "imjournal: error while stopping journal processing; "
+ "rsyslog may hang on shutdown");
+ }
+ return NULL;
+}
+
+/* support for running multiple servers on multiple threads (one server per thread) */
+static void
+startSrvWrkr(journal_etry_t *const etry)
+{
+ int r;
+ pthread_attr_t sessThrdAttr;
+
+ /* We need to temporarily block all signals because the new thread
+ * inherits our signal mask. There is a race if we do not block them
+ * now, and we have seen in practice that this race causes grief.
+ * So we 1. save the current set, 2. block evertyhing, 3. start
+ * threads, and 4 reset the current set to saved state.
+ * rgerhards, 2019-08-16
+ */
+ sigset_t sigSet, sigSetSave;
+ sigfillset(&sigSet);
+ /* enable signals we still need */
+ sigdelset(&sigSet, SIGTTIN);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_SETMASK, &sigSet, &sigSetSave);
+
+ pthread_attr_init(&sessThrdAttr);
+ pthread_attr_setstacksize(&sessThrdAttr, 4096*1024);
+ r = pthread_create(&etry->tid, &sessThrdAttr, RunServerThread, etry);
+ if(r != 0) {
+ LogError(r, NO_ERRCODE, "imjournal: error creating imjournal thread");
+ /* we do NOT abort, as other servers may run - after all, we logged an error */
+ }
+ pthread_attr_destroy(&sessThrdAttr);
+ pthread_sigmask(SIG_SETMASK, &sigSetSave, NULL);
+}
+
+/* stop server worker thread
+ */
+static void
+stopSrvWrkr(journal_etry_t *const etry)
+{
+ DBGPRINTF("Wait for thread shutdown etry %p\n", etry);
+ pthread_kill(etry->tid, SIGTTIN);
+ pthread_join(etry->tid, NULL);
+ DBGPRINTF("input %p terminated\n", etry);
+}
+
+BEGINrunInput
+CODESTARTrunInput
+ CHKiRet(ratelimitNew(&ratelimiter, "imjournal", NULL));
+ dbgprintf("imjournal: ratelimiting burst %u, interval %u\n", cs.ratelimitBurst,
+ cs.ratelimitInterval);
+ ratelimitSetLinuxLike(ratelimiter, cs.ratelimitInterval, cs.ratelimitBurst);
+ ratelimitSetNoTimeCache(ratelimiter);
+
+ /* handling old "usepidfromsystem" option */
+ if (cs.bUseJnlPID != -1) {
+ free(cs.usePid);
+ cs.usePid = strdup("system");
+ LogError(0, RS_RET_DEPRECATED,
+ "\"usepidfromsystem\" is deprecated, use \"usepid\" instead");
+ }
+
+ journal_etry_t *etry = journal_root->next;
+ while(etry != NULL) {
+ startSrvWrkr(etry);
+ etry = etry->next;
+ }
+
+ CHKiRet(doRun(journal_root));
+
+ etry = journal_root->next;
+ while(etry != NULL) {
+ stopSrvWrkr(etry);
+ etry = etry->next;
+ }
+
+finalize_it:
+ENDrunInput
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ bLegacyCnfModGlobalsPermitted = 1;
+
+ cs.bIgnoreNonValidStatefile = 1;
+ cs.iPersistStateInterval = DFLT_persiststateinterval;
+ cs.stateFile = NULL;
+ cs.fCreateMode = -1;
+ cs.ratelimitBurst = 20000;
+ cs.ratelimitInterval = 600;
+ cs.iDfltSeverity = DFLT_SEVERITY;
+ cs.iDfltFacility = DFLT_FACILITY;
+ cs.bUseJnlPID = -1;
+ cs.usePid = NULL;
+ cs.bWorkAroundJournalBug = 1;
+ cs.bFsync = 0;
+ cs.bRemote = 0;
+ cs.dfltTag = NULL;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ /* bad trick to handle old and new style config all in old-style var */
+ if(cs.stateFile != NULL && cs.stateFile[0] != '/') {
+ char *new_stateFile;
+ if (-1 == asprintf(&new_stateFile, "%s/%s",
+ (char *)glbl.GetWorkDir(loadModConf->pConf), cs.stateFile)) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ free (cs.stateFile);
+ cs.stateFile = new_stateFile;
+ }
+finalize_it:
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnf
+ instanceConf_t *inst;
+ instanceConf_t *root_inst = NULL;
+ u_int8_t index = 0;
+CODESTARTactivateCnf
+ runModConf = pModConf;
+
+ /* support statistic gathering */
+ CHKiRet(statsobj.Construct(&(statsCounter.stats)));
+ CHKiRet(statsobj.SetName(statsCounter.stats, (uchar*)"imjournal"));
+ CHKiRet(statsobj.SetOrigin(statsCounter.stats, (uchar*)"imjournal"));
+ STATSCOUNTER_INIT(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrSubmitted)));
+ STATSCOUNTER_INIT(statsCounter.ctrRead, statsCounter.mutCtrRead);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("read"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrRead)));
+ STATSCOUNTER_INIT(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("discarded"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrDiscarded)));
+ STATSCOUNTER_INIT(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("failed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrFailed)));
+ STATSCOUNTER_INIT(statsCounter.ctrPollFailed, statsCounter.mutCtrPollFailed);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("poll_failed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrPollFailed)));
+ STATSCOUNTER_INIT(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("rotations"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrRotations)));
+ STATSCOUNTER_INIT(statsCounter.ctrRecoveryAttempts, statsCounter.mutCtrRecoveryAttempts);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("recovery_attempts"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrRecoveryAttempts)));
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("ratelimit_discarded_in_interval"),
+ ctrType_Int, CTR_FLAG_NONE, &(statsCounter.ratelimitDiscardedInInterval)));
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("disk_usage_bytes"),
+ ctrType_Int, CTR_FLAG_NONE, &(statsCounter.diskUsageBytes)));
+ CHKiRet(statsobj.ConstructFinalize(statsCounter.stats));
+ /* end stats counter */
+
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ if(cs.stateFile) {
+ char *new_stateFile;
+ if (-1 == asprintf(&new_stateFile, "%s/%s", cs.stateFile, inst->pszBindRuleset)) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ free(inst->stateFile);
+ inst->stateFile = new_stateFile;;
+ }
+
+ // Only the first input module with main enabled will be treated as
+ // the main process.
+ if (inst->bMain && root_inst == NULL) {
+ root_inst = inst;
+ } else {
+ if (addListner(inst, index++) != RS_RET_OK) {
+ LogError(0, RS_RET_NO_MORE_DATA,
+ "imjournal: Can only support up to %i journals\n",
+ MAX_JOURNAL);
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ }
+ }
+ }
+
+ // Add all state files as a subfile of original cs.stateFile.
+ if(runModConf->root != NULL && cs.stateFile) {
+ char *new_stateFile;
+ if (-1 == asprintf(&new_stateFile, "%s/default", cs.stateFile)) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ // TODO(need to delete old state file and create the folder.
+ DIR *stateDir;
+ if (!(stateDir = opendir(cs.stateFile))) {
+ remove(cs.stateFile);
+ mkdir(cs.stateFile, 0700);
+ } else {
+ closedir(stateDir);
+ }
+
+ free(cs.stateFile);
+ cs.stateFile = new_stateFile;;
+ }
+
+ // Default Handlers. Will be used as the main process if no `main`
+ // property is set in the input modules.
+ if (addListner(NULL, index++) != RS_RET_OK) {
+ LogError(0, RS_RET_NO_MORE_DATA,
+ "imjournal: Can only support up to %i journals\n",
+ MAX_JOURNAL);
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ }
+
+ // Main process will be the top of journal_root.
+ if (root_inst != NULL){
+ if (addListner(root_inst, index++) != RS_RET_OK) {
+ LogError(0, RS_RET_NO_MORE_DATA,
+ "imjournal: Can only support up to %i journals\n",
+ MAX_JOURNAL);
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ }
+ }
+
+finalize_it:
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindRuleset);
+ free(inst->stateFile);
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ free(cs.stateFile);
+ free(cs.usePid);
+ free(cs.dfltTag);
+ statsobj.Destruct(&(statsCounter.stats));
+ENDfreeCnf
+
+/* open journal */
+BEGINwillRun
+ journal_etry_t *etry = journal_root;
+CODESTARTwillRun
+ while(etry != NULL) {
+ CHKiRet(openJournal(etry->journalContext));
+ etry = etry->next;
+ }
+finalize_it:
+ENDwillRun
+
+/* close journal */
+BEGINafterRun
+ journal_etry_t *etry = journal_root;
+ journal_etry_t *del;
+CODESTARTafterRun
+ while(etry != NULL) {
+ char *stateFile = cs.stateFile;
+ if (etry->stateFile) {
+ stateFile = etry->stateFile;
+ }
+ if (stateFile) { /* can't persist without a state file */
+ persistJournalState(etry->journalContext, stateFile);
+ }
+ closeJournal(etry->journalContext);
+ free(etry->journalContext->cursor);
+ // TODO: check iRet, reprot error
+ del = etry;
+ etry = etry->next;
+ free(del);
+ }
+
+ if (ratelimiter) {
+ ratelimitDestruct(ratelimiter);
+ }
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ if(pLocalHostIP != NULL)
+ prop.Destruct(&pLocalHostIP);
+
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if (pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if (Debug) {
+ dbgprintf("module (global) param blk for imjournal:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for (i = 0 ; i < modpblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(modpblk.descr[i].name, "persiststateinterval")) {
+ cs.iPersistStateInterval = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "statefile")) {
+ cs.stateFile = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "filecreatemode")) {
+ cs.fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimit.burst")) {
+ cs.ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimit.interval")) {
+ cs.ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "ignorepreviousmessages")) {
+ cs.bIgnorePrevious = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "ignorenonvalidstatefile")) {
+ cs.bIgnoreNonValidStatefile = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaultseverity")) {
+ cs.iDfltSeverity = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaultfacility")) {
+ /* ugly workaround to handle facility numbers; values
+ derived from names need to be eight times smaller */
+
+ char *fac, *p;
+
+ fac = p = es_str2cstr(pvals[i].val.d.estr, NULL);
+ facilityHdlr((uchar **) &p, (void *) &cs.iDfltFacility);
+ free(fac);
+ } else if (!strcmp(modpblk.descr[i].name, "usepidfromsystem")) {
+ cs.bUseJnlPID = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "usepid")) {
+ cs.usePid = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(modpblk.descr[i].name, "workaroundjournalbug")) {
+ cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "fsync")) {
+ cs.bFsync = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "remote")) {
+ cs.bRemote = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "defaulttag")) {
+ cs.dfltTag = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imjournal: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* File create mode is not set */
+ if (cs.fCreateMode == -1) {
+ const int fCreateMode = 0644;
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: filecreatemode is not set, "
+ "using default %04o", fCreateMode);
+ cs.fCreateMode = fCreateMode;
+ }
+
+finalize_it:
+ if (pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal ATTR_NONNULL(1)
+createInstance(instanceConf_t **const pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pBindRuleset = NULL;
+ inst->pszBindRuleset = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(inst);
+ }
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imjournal)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ DBGPRINTF("input param blk in imjournal:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "main")) {
+ inst->bMain = (int) pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ if (pvals != NULL)
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imjournal: ruleset '%s' not found - "
+ "using default ruleset instead", inst->pszBindRuleset);
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imjournal"), sizeof("imjournal") - 1));
+ CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalpersiststateinterval", 0, eCmdHdlrInt,
+ NULL, &cs.iPersistStateInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalratelimitinterval", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalratelimitburst", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitBurst, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalstatefile", 0, eCmdHdlrGetWord,
+ NULL, &cs.stateFile, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalignorepreviousmessages", 0, eCmdHdlrBinary,
+ NULL, &cs.bIgnorePrevious, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultseverity", 0, eCmdHdlrSeverity,
+ NULL, &cs.iDfltSeverity, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultfacility", 0, eCmdHdlrCustomHandler,
+ facilityHdlr, &cs.iDfltFacility, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalusepidfromsystem", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseJnlPID, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imkafka/Makefile.am b/plugins/imkafka/Makefile.am
new file mode 100644
index 0000000..c26a0be
--- /dev/null
+++ b/plugins/imkafka/Makefile.am
@@ -0,0 +1,19 @@
+pkglib_LTLIBRARIES = imkafka.la
+
+if IMKAFKA_USE_DUMMY
+imkafka_la_SOURCES = dummy.c
+imkafka_la_LDFLAGS = -module -avoid-version
+imkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -D MODNAME=imkafka
+else
+imkafka_la_SOURCES = imkafka.c
+if ENABLE_KAFKA_STATIC
+imkafka_la_LDFLAGS = -module -avoid-version -Wl,--whole-archive -l:librdkafka-static.a -Wl,--no-whole-archive -ldl -lresolv -lcurl -lssl -lpthread -lcrypto -lsasl2 -lz -llz4 -lrt -lm
+else
+imkafka_la_LDFLAGS = -module -avoid-version $(LIBRDKAFKA_LIBS) -lm
+endif
+imkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+endif
+
+imkafka_la_LIBADD =
+EXTRA_DIST =
+
diff --git a/plugins/imkafka/Makefile.in b/plugins/imkafka/Makefile.in
new file mode 100644
index 0000000..ac871b3
--- /dev/null
+++ b/plugins/imkafka/Makefile.in
@@ -0,0 +1,815 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imkafka
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imkafka_la_DEPENDENCIES =
+am__imkafka_la_SOURCES_DIST = imkafka.c dummy.c
+@IMKAFKA_USE_DUMMY_FALSE@am_imkafka_la_OBJECTS = \
+@IMKAFKA_USE_DUMMY_FALSE@ imkafka_la-imkafka.lo
+@IMKAFKA_USE_DUMMY_TRUE@am_imkafka_la_OBJECTS = imkafka_la-dummy.lo
+imkafka_la_OBJECTS = $(am_imkafka_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 =
+imkafka_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imkafka_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imkafka_la-dummy.Plo \
+ ./$(DEPDIR)/imkafka_la-imkafka.Plo
+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 = $(imkafka_la_SOURCES)
+DIST_SOURCES = $(am__imkafka_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imkafka.la
+@IMKAFKA_USE_DUMMY_FALSE@imkafka_la_SOURCES = imkafka.c
+@IMKAFKA_USE_DUMMY_TRUE@imkafka_la_SOURCES = dummy.c
+@ENABLE_KAFKA_STATIC_FALSE@@IMKAFKA_USE_DUMMY_FALSE@imkafka_la_LDFLAGS = -module -avoid-version $(LIBRDKAFKA_LIBS) -lm
+@ENABLE_KAFKA_STATIC_TRUE@@IMKAFKA_USE_DUMMY_FALSE@imkafka_la_LDFLAGS = -module -avoid-version -Wl,--whole-archive -l:librdkafka-static.a -Wl,--no-whole-archive -ldl -lresolv -lcurl -lssl -lpthread -lcrypto -lsasl2 -lz -llz4 -lrt -lm
+@IMKAFKA_USE_DUMMY_TRUE@imkafka_la_LDFLAGS = -module -avoid-version
+@IMKAFKA_USE_DUMMY_FALSE@imkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+@IMKAFKA_USE_DUMMY_TRUE@imkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -D MODNAME=imkafka
+imkafka_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/imkafka/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imkafka/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imkafka.la: $(imkafka_la_OBJECTS) $(imkafka_la_DEPENDENCIES) $(EXTRA_imkafka_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imkafka_la_LINK) -rpath $(pkglibdir) $(imkafka_la_OBJECTS) $(imkafka_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkafka_la-dummy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkafka_la-imkafka.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imkafka_la-imkafka.lo: imkafka.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkafka_la-imkafka.lo -MD -MP -MF $(DEPDIR)/imkafka_la-imkafka.Tpo -c -o imkafka_la-imkafka.lo `test -f 'imkafka.c' || echo '$(srcdir)/'`imkafka.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkafka_la-imkafka.Tpo $(DEPDIR)/imkafka_la-imkafka.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imkafka.c' object='imkafka_la-imkafka.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) $(imkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkafka_la-imkafka.lo `test -f 'imkafka.c' || echo '$(srcdir)/'`imkafka.c
+
+imkafka_la-dummy.lo: dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkafka_la-dummy.lo -MD -MP -MF $(DEPDIR)/imkafka_la-dummy.Tpo -c -o imkafka_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkafka_la-dummy.Tpo $(DEPDIR)/imkafka_la-dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='imkafka_la-dummy.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) $(imkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkafka_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imkafka_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/imkafka_la-imkafka.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imkafka_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/imkafka_la-imkafka.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imkafka/dummy.c b/plugins/imkafka/dummy.c
new file mode 100644
index 0000000..fe8c249
--- /dev/null
+++ b/plugins/imkafka/dummy.c
@@ -0,0 +1,171 @@
+/* a dummy module to be loaded if we cannot build this module, but
+ * configure required it to be "optional".
+ *
+ * Copyright 2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+#define MODULE_NAME(x) #x
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME(MODULE_NAME(MODNAME))
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ (void) lst;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDsetModCnf
+
+
+BEGINnewActInst
+CODESTARTnewActInst
+ (void) pData;
+ (void) ppModData;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void) pMsgData;
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("dummy module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/imkafka/imkafka.c b/plugins/imkafka/imkafka.c
new file mode 100644
index 0000000..6351280
--- /dev/null
+++ b/plugins/imkafka/imkafka.c
@@ -0,0 +1,904 @@
+/* imkafka.c
+ *
+ * This input plugin is a consumer for Apache Kafka.
+ *
+ * File begun on 2017-04-25 by alorbach
+ *
+ * Copyright 2008-2017 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/uio.h>
+#include <librdkafka/rdkafka.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "glbl.h"
+#include "cfsysline.h"
+#include "msg.h"
+#include "dirty.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imkafka")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(statsobj)
+
+/* forward references */
+static void * imkafkawrkr(void *myself);
+
+
+struct kafka_params {
+ const char *name;
+ const char *val;
+};
+
+/* Module static data */
+static struct configSettings_s {
+ uchar *topic;
+ uchar *consumergroup;
+ char *brokers;
+ uchar *pszBindRuleset;
+ int nConfParams;
+ struct kafka_params *confParams;
+} cs;
+
+struct instanceConf_s {
+ uchar *topic;
+ uchar *consumergroup;
+ char *brokers;
+ int64_t offset;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *pszBindRuleset; /* default name of Ruleset to bind to */
+ int bReportErrs;
+ int nConfParams;
+ struct kafka_params *confParams;
+ int bIsConnected;
+ rd_kafka_conf_t *conf;
+ rd_kafka_t *rk;
+ rd_kafka_topic_conf_t *topic_conf;
+ int partition;
+ int bIsSubscribed;
+ int nMsgParsingFlags;
+
+ struct instanceConf_s *next;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *topic;
+ uchar *consumergroup;
+ char *brokers;
+ instanceConf_t *root, *tail;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *pszBindRuleset; /* default name of Ruleset to bind to */
+};
+
+/* global data */
+pthread_attr_t wrkrThrdAttr; /* Attribute for worker threads ; read only after startup */
+static int activeKafkaworkers = 0;
+/* The following structure controls the worker threads. Global data is
+ * needed for their access.
+ */
+static struct kafkaWrkrInfo_s {
+ pthread_t tid; /* the worker's thread ID */
+ instanceConf_t *inst; /* Pointer to imkafka instance */
+} *kafkaWrkrInfo;
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this input */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ruleset", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "topic", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "broker", eCmdHdlrArray, 0 },
+ { "confparam", eCmdHdlrArray, 0 },
+ { "consumergroup", eCmdHdlrString, 0},
+ { "ruleset", eCmdHdlrString, 0 },
+ { "parsehostname", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+/* ------------------------------ callbacks ------------------------------ */
+
+
+
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+static void
+kafkaLogger(const rd_kafka_t __attribute__((unused)) *rk, int level,
+ const char *fac, const char *buf)
+{
+ DBGPRINTF("imkafka: kafka log message [%d,%s]: %s\n",
+ level, fac, buf);
+}
+
+
+/* enqueue the kafka message. The provided string is
+ * not freed - thuis must be done by the caller.
+ */
+static rsRetVal enqMsg(instanceConf_t *const __restrict__ inst,
+ rd_kafka_message_t *const __restrict__ rkmessage)
+{
+ DEFiRet;
+ smsg_t *pMsg;
+
+ if((int)rkmessage->len == 0) {
+ /* we do not process empty lines */
+ FINALIZE;
+ }
+
+DBGPRINTF("imkafka: enqMsg: Msg: %.*s\n", (int)rkmessage->len, (char *)rkmessage->payload);
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)rkmessage->payload, (int)rkmessage->len);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ pMsg->msgFlags = inst->nMsgParsingFlags;
+ /* Optional Fields */
+ if (rkmessage->key_len) {
+ DBGPRINTF("imkafka: enqMsg: Key: %.*s\n", (int)rkmessage->key_len, (char *)rkmessage->key);
+ MsgSetTAG(pMsg, (const uchar *)rkmessage->key, (int)rkmessage->key_len);
+ }
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+
+ CHKiRet(submitMsg2(pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+/**
+ * Handle Kafka Consumer Loop until all msgs are processed
+ */
+static void msgConsume (instanceConf_t *inst) {
+ rd_kafka_message_t *rkmessage = NULL;
+
+ do { /* Consume messages */
+ rkmessage = rd_kafka_consumer_poll(inst->rk, 1000); /* Block for 1000 ms max */
+ if(rkmessage == NULL) {
+ DBGPRINTF("imkafka: msgConsume EMPTY Loop on %s/%s/%s\n",
+ inst->topic, inst->consumergroup, inst->brokers);
+ goto done;
+ }
+
+ if (rkmessage->err) {
+ if (rkmessage->err == RD_KAFKA_RESP_ERR__PARTITION_EOF) {
+ /* not an error, just a regular status! */
+ DBGPRINTF("imkafka: Consumer "
+ "reached end of topic \"%s\" [%"PRId32"]"
+ "message queue offset %"PRId64"\n",
+ rd_kafka_topic_name(rkmessage->rkt),
+ rkmessage->partition,
+ rkmessage->offset);
+ goto done;
+ }
+ if (rkmessage->rkt) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: Consumer error for topic \"%s\" [%"PRId32"]"
+ "message queue offset %"PRId64": %s\n",
+ rd_kafka_topic_name(rkmessage->rkt),
+ rkmessage->partition,
+ rkmessage->offset,
+ rd_kafka_message_errstr(rkmessage));
+ } else {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: Consumer error for topic \"%s\": \"%s\"\n",
+ rd_kafka_err2str(rkmessage->err),
+ rd_kafka_message_errstr(rkmessage));
+ }
+ goto done;
+ }
+
+ DBGPRINTF("imkafka: msgConsume Loop on %s/%s/%s: [%"PRId32"], "
+ "offset %"PRId64", %zd bytes):\n",
+ rd_kafka_topic_name(rkmessage->rkt) /*inst->topic*/,
+ inst->consumergroup,
+ inst->brokers,
+ rkmessage->partition,
+ rkmessage->offset,
+ rkmessage->len);
+ enqMsg(inst, rkmessage);
+ /* Destroy message and continue */
+ rd_kafka_message_destroy(rkmessage);
+ rkmessage = NULL;
+ } while(1); /* loop broken inside */
+done:
+ /* Destroy message in case rkmessage->err was set */
+ if(rkmessage != NULL) {
+ rd_kafka_message_destroy(rkmessage);
+ }
+ return;
+}
+
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+
+ inst->brokers = NULL;
+ inst->topic = NULL;
+ inst->consumergroup = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->nConfParams = 0;
+ inst->confParams = NULL;
+ inst->pBindRuleset = NULL;
+ inst->bReportErrs = 1; /* Fixed for now */
+ inst->nMsgParsingFlags = NEEDS_PARSING;
+ inst->bIsConnected = 0;
+ inst->bIsSubscribed = 0;
+ /* Kafka objects */
+ inst->conf = NULL;
+ inst->rk = NULL;
+ inst->topic_conf = NULL;
+ inst->partition = RD_KAFKA_PARTITION_UA;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* this function checks instance parameters and does some required pre-processing
+ */
+static rsRetVal ATTR_NONNULL()
+checkInstance(instanceConf_t *const inst)
+{
+ DEFiRet;
+ char kafkaErrMsg[1024];
+
+ /* main kafka conf */
+ inst->conf = rd_kafka_conf_new();
+ if(inst->conf == NULL) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: error creating kafka conf obj: %s\n",
+ rd_kafka_err2str(rd_kafka_last_error()));
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+
+# ifdef DEBUG
+ /* enable kafka debug output */
+ if(rd_kafka_conf_set(inst->conf, "debug", RD_KAFKA_DEBUG_CONTEXTS,
+ kafkaErrMsg, sizeof(kafkaErrMsg)) != RD_KAFKA_CONF_OK) {
+ LogError(0, RS_RET_KAFKA_ERROR, "imkafka: error setting kafka debug option: %s\n", kafkaErrMsg);
+ /* DO NOT ABORT IN THIS CASE! */
+ }
+# endif
+
+ /* Set custom configuration parameters */
+ for(int i = 0 ; i < inst->nConfParams ; ++i) {
+ assert(inst->confParams+i != NULL); /* invariant: nConfParams MUST exist! */
+ DBGPRINTF("imkafka: setting custom configuration parameter: %s:%s\n",
+ inst->confParams[i].name,
+ inst->confParams[i].val);
+ if(rd_kafka_conf_set(inst->conf,
+ inst->confParams[i].name,
+ inst->confParams[i].val,
+ kafkaErrMsg, sizeof(kafkaErrMsg)) != RD_KAFKA_CONF_OK) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_PARAM_ERROR, "error setting custom configuration "
+ "parameter '%s=%s': %s",
+ inst->confParams[i].name,
+ inst->confParams[i].val, kafkaErrMsg);
+ } else {
+ DBGPRINTF("imkafka: error setting custom configuration parameter '%s=%s': %s",
+ inst->confParams[i].name,
+ inst->confParams[i].val, kafkaErrMsg);
+ }
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ }
+
+ /* Topic configuration */
+ inst->topic_conf = rd_kafka_topic_conf_new();
+
+ /* Assign kafka group id */
+ if (inst->consumergroup != NULL) {
+ DBGPRINTF("imkafka: setting consumergroup: '%s'\n", inst->consumergroup);
+ if (rd_kafka_conf_set(inst->conf, "group.id", (char*) inst->consumergroup,
+ kafkaErrMsg, sizeof(kafkaErrMsg)) != RD_KAFKA_CONF_OK) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: error assigning consumergroup %s to "
+ "kafka config: %s\n", inst->consumergroup,
+ kafkaErrMsg);
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+
+
+ /* Set default for auto offset reset */
+ if (rd_kafka_topic_conf_set(inst->topic_conf, "auto.offset.reset",
+ "smallest", kafkaErrMsg, sizeof(kafkaErrMsg)) != RD_KAFKA_CONF_OK) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: error setting kafka auto.offset.reset on %s: %s\n",
+ inst->consumergroup,
+ kafkaErrMsg);
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+ /* Consumer groups always use broker based offset storage */
+ if (rd_kafka_topic_conf_set(inst->topic_conf, "offset.store.method",
+ "broker", kafkaErrMsg, sizeof(kafkaErrMsg)) != RD_KAFKA_CONF_OK) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: error setting kafka offset.store.method on %s: %s\n",
+ inst->consumergroup,
+ kafkaErrMsg);
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+
+ /* Set default topic config for pattern-matched topics. */
+ rd_kafka_conf_set_default_topic_conf(inst->conf, inst->topic_conf);
+ }
+
+ #if RD_KAFKA_VERSION >= 0x00090001
+ rd_kafka_conf_set_log_cb(inst->conf, kafkaLogger);
+ #endif
+
+ /* Create Kafka Consumer */
+ inst->rk = rd_kafka_new(RD_KAFKA_CONSUMER, inst->conf,
+ kafkaErrMsg, sizeof(kafkaErrMsg));
+ if(inst->rk == NULL) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "imkafka: error creating kafka handle: %s\n", kafkaErrMsg);
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+ #if RD_KAFKA_VERSION < 0x00090001
+ rd_kafka_set_logger(inst->rk, kafkaLogger);
+ #endif
+
+ DBGPRINTF("imkafka: setting brokers: '%s'\n", inst->brokers);
+ if(rd_kafka_brokers_add(inst->rk, (char*)inst->brokers) == 0) {
+ if(inst->bReportErrs) {
+ LogError(0, RS_RET_KAFKA_NO_VALID_BROKERS,
+ "imkafka: no valid brokers specified: %s", inst->brokers);
+ }
+ ABORT_FINALIZE(RS_RET_KAFKA_NO_VALID_BROKERS);
+ }
+
+ /* Kafka Consumer is opened */
+ inst->bIsConnected = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(inst->rk == NULL) {
+ if(inst->conf != NULL) {
+ rd_kafka_conf_destroy(inst->conf);
+ inst->conf = NULL;
+ }
+ } else { /* inst->rk != NULL ! */
+ rd_kafka_destroy(inst->rk);
+ inst->rk = NULL;
+ }
+ }
+
+ RETiRet;
+}
+
+/* function to generate an error message if the ruleset cannot be found */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ if(inst->bReportErrs) {
+ LogError(0, NO_ERRCODE, "imkafka: ruleset '%s' not found - "
+ "using default ruleset instead",
+ inst->pszBindRuleset);
+ }
+}
+
+
+static rsRetVal ATTR_NONNULL(2)
+addConsumer(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
+{
+ DEFiRet;
+ rd_kafka_resp_err_t err;
+
+ assert(inst != NULL);
+
+ rd_kafka_topic_partition_list_t *topics = NULL;
+ DBGPRINTF("imkafka: creating kafka consumer on %s/%s/%s\n",
+ inst->topic, inst->consumergroup, inst->brokers);
+
+ /* Redirect rd_kafka_poll() to consumer_poll() */
+ rd_kafka_poll_set_consumer(inst->rk);
+
+ topics = rd_kafka_topic_partition_list_new(1);
+ rd_kafka_topic_partition_list_add(topics, (const char*)inst->topic, inst->partition);
+ DBGPRINTF("imkafka: Created topics(%d) for %s)\n",
+ topics->cnt, inst->topic);
+ if ((err = rd_kafka_subscribe(inst->rk, topics))) {
+ /* Subscription failed */
+ inst->bIsSubscribed = 0;
+ LogError(0, RS_RET_KAFKA_ERROR, "imkafka: Failed to start consuming "
+ "topics: %s\n", rd_kafka_err2str(err));
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ } else {
+ DBGPRINTF("imkafka: Successfully subscribed to %s/%s/%s\n",
+ inst->topic, inst->consumergroup, inst->brokers);
+ /* Subscription is working */
+ inst->bIsSubscribed = 1;
+ }
+finalize_it:
+ if(topics != NULL)
+ rd_kafka_topic_partition_list_destroy(topics);
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+processKafkaParam(char *const param,
+ const char **const name,
+ const char **const paramval)
+{
+ DEFiRet;
+ char *val = strstr(param, "=");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ *val = '\0'; /* terminates name */
+ ++val; /* now points to begin of value */
+ CHKmalloc(*name = strdup(param));
+ CHKmalloc(*paramval = strdup(val));
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imkafka)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imkafka:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "broker")) {
+ es_str_t *es = es_newStr(128);
+ int bNeedComma = 0;
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ if(bNeedComma)
+ es_addChar(&es, ',');
+ es_addStr(&es, pvals[i].val.d.ar->arr[j]);
+ bNeedComma = 1;
+ }
+ inst->brokers = es_str2cstr(es, NULL);
+ es_deleteStr(es);
+ } else if(!strcmp(inppblk.descr[i].name, "confparam")) {
+ inst->nConfParams = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(inst->confParams = malloc(sizeof(struct kafka_params)*inst->nConfParams));
+ for(int j = 0; j < inst->nConfParams; j++) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processKafkaParam(cstr, &inst->confParams[j].name,
+ &inst->confParams[j].val));
+ free(cstr);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "topic")) {
+ inst->topic = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "consumergroup")) {
+ inst->consumergroup = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "parsehostname")) {
+ if (pvals[i].val.d.n) {
+ inst->nMsgParsingFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ } else {
+ inst->nMsgParsingFlags = NEEDS_PARSING;
+ }
+ } else {
+ dbgprintf("imkafka: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ if(inst->brokers == NULL) {
+ CHKmalloc(inst->brokers = strdup("localhost:9092"));
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "imkafka: \"broker\" parameter not specified "
+ "using default of localhost:9092 -- this may not be what you want!");
+ }
+
+ DBGPRINTF("imkafka: newInpIns brokers=%s, topic=%s, consumergroup=%s\n",
+ inst->brokers, inst->topic, inst->consumergroup);
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->pszBindRuleset = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imkafka: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imkafka:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imkafka: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(loadModConf->pszBindRuleset == NULL) {
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ loadModConf->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(loadModConf->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ }
+finalize_it:
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst->pszBindRuleset == NULL && pModConf->pszBindRuleset != NULL) {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(pModConf->pszBindRuleset));
+ }
+ std_checkRuleset(pModConf, inst);
+ }
+finalize_it:
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ for(instanceConf_t *inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ iRet = checkInstance(inst);
+ }
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->topic);
+ free(inst->consumergroup);
+ free(inst->brokers);
+ free(inst->pszBindRuleset);
+ for(int i = 0; i < inst->nConfParams; i++) {
+ free((void*)inst->confParams[i].name);
+ free((void*)inst->confParams[i].val);
+ }
+ free((void*)inst->confParams);
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ free(pModConf->pszBindRuleset);
+ENDfreeCnf
+
+
+/* Cleanup imkafka worker threads */
+static void
+shutdownKafkaWorkers(void)
+{
+ int i;
+ instanceConf_t *inst;
+
+ assert(kafkaWrkrInfo != NULL);
+
+ DBGPRINTF("imkafka: waiting on imkafka workerthread termination\n");
+ for(i = 0 ; i < activeKafkaworkers ; ++i) {
+ pthread_join(kafkaWrkrInfo[i].tid, NULL);
+ DBGPRINTF("imkafka: Stopped worker %d\n", i);
+ }
+ free(kafkaWrkrInfo);
+ kafkaWrkrInfo = NULL;
+
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ DBGPRINTF("imkafka: stop consuming %s/%s/%s\n",
+ inst->topic, inst->consumergroup, inst->brokers);
+ rd_kafka_consumer_close(inst->rk); /* Close the consumer, committing final offsets, etc. */
+ rd_kafka_destroy(inst->rk); /* Destroy handle object */
+ DBGPRINTF("imkafka: stopped consuming %s/%s/%s\n",
+ inst->topic, inst->consumergroup, inst->brokers);
+
+ #if RD_KAFKA_VERSION < 0x00090001
+ /* Wait for kafka being destroyed in old API */
+ if (rd_kafka_wait_destroyed(10000) < 0) {
+ DBGPRINTF("imkafka: error, rd_kafka_destroy did not finish after grace "
+ "timeout (10s)!\n");
+ } else {
+ DBGPRINTF("imkafka: rd_kafka_destroy successfully finished\n");
+ }
+ #endif
+ }
+}
+
+
+/* This function is called to gather input. */
+BEGINrunInput
+ int i;
+ instanceConf_t *inst;
+CODESTARTrunInput
+ DBGPRINTF("imkafka: runInput loop started ...\n");
+ activeKafkaworkers = 0;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst->rk != NULL) {
+ ++activeKafkaworkers;
+ }
+ }
+
+ if(activeKafkaworkers == 0) {
+ LogError(0, RS_RET_ERR, "imkafka: no active inputs, input does "
+ "not run - there should have been additional error "
+ "messages given previously");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+
+ DBGPRINTF("imkafka: Starting %d imkafka workerthreads\n", activeKafkaworkers);
+ kafkaWrkrInfo = calloc(activeKafkaworkers, sizeof(struct kafkaWrkrInfo_s));
+ if (kafkaWrkrInfo == NULL) {
+ LogError(errno, RS_RET_OUT_OF_MEMORY, "imkafka: worker-info array allocation failed.");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* Start worker threads for each imkafka input source
+ */
+ i = 0;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ /* init worker info structure! */
+ kafkaWrkrInfo[i].inst = inst; /* Set reference pointer */
+ pthread_create(&kafkaWrkrInfo[i].tid, &wrkrThrdAttr, imkafkawrkr, &(kafkaWrkrInfo[i]));
+ i++;
+ }
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+
+ /* Note: the additional 10000ns wait is vitally important. It guards rsyslog
+ * against totally hogging the CPU if the users selects a polling interval
+ * of 0 seconds. It doesn't hurt any other valid scenario. So do not remove.
+ */
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(0, 100000);
+ }
+ DBGPRINTF("imkafka: terminating upon request of rsyslog core\n");
+
+ /* we need to shutdown kafak worker threads here because this operation can
+ * potentially block (e.g. when no kafka broker is available!). If this
+ * happens in runInput, the rsyslog core can cancel our thread. However,
+ * in afterRun this is not possible, because the core does not assume it
+ * can block there. -- rgerhards, 2018-10-23
+ */
+ shutdownKafkaWorkers();
+finalize_it:
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imkafka"), sizeof("imkafka") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ pthread_attr_destroy(&wrkrThrdAttr);
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ /* initialize "read-only" thread attributes */
+ pthread_attr_init(&wrkrThrdAttr);
+ pthread_attr_setstacksize(&wrkrThrdAttr, 4096*1024);
+
+ DBGPRINTF("imkafka %s using librdkafka version %s, 0x%x\n",
+ VERSION, rd_kafka_version_str(), rd_kafka_version());
+ENDmodInit
+
+/*
+* Workerthread function for a single kafka consomer
+ */
+static void *
+imkafkawrkr(void *myself)
+{
+ struct kafkaWrkrInfo_s *me = (struct kafkaWrkrInfo_s*) myself;
+ DBGPRINTF("imkafka: started kafka consumer workerthread on %s/%s/%s\n",
+ me->inst->topic, me->inst->consumergroup, me->inst->brokers);
+
+ do {
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ if(me->inst->rk == NULL) {
+ continue;
+ }
+
+ // Try to add consumer only if connected! */
+ if(me->inst->bIsConnected == 1 && me->inst->bIsSubscribed == 0 ) {
+ addConsumer(runModConf, me->inst);
+ }
+ if(me->inst->bIsSubscribed == 1 ) {
+ msgConsume(me->inst);
+ }
+ /* Note: the additional 10000ns wait is vitally important. It guards rsyslog
+ * against totally hogging the CPU if the users selects a polling interval
+ * of 0 seconds. It doesn't hurt any other valid scenario. So do not remove.
+ * rgerhards, 2008-02-14
+ */
+ if(glbl.GetGlobalInputTermState() == 0)
+ srSleep(0, 100000);
+ } while(glbl.GetGlobalInputTermState() == 0);
+
+ DBGPRINTF("imkafka: stopped kafka consumer workerthread on %s/%s/%s\n",
+ me->inst->topic, me->inst->consumergroup, me->inst->brokers);
+ return NULL;
+}
diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am
new file mode 100644
index 0000000..3626eec
--- /dev/null
+++ b/plugins/imklog/Makefile.am
@@ -0,0 +1,20 @@
+pkglib_LTLIBRARIES = imklog.la
+imklog_la_SOURCES = imklog.c imklog.h
+
+# select klog "driver"
+if ENABLE_IMKLOG_BSD
+imklog_la_SOURCES += bsd.c
+endif
+
+if ENABLE_IMKLOG_LINUX
+imklog_la_SOURCES += bsd.c
+endif
+
+imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imklog_la_LDFLAGS = -module -avoid-version
+imklog_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+imklog_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+imklog_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/imklog/Makefile.in b/plugins/imklog/Makefile.in
new file mode 100644
index 0000000..54bd041
--- /dev/null
+++ b/plugins/imklog/Makefile.in
@@ -0,0 +1,818 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+
+# select klog "driver"
+@ENABLE_IMKLOG_BSD_TRUE@am__append_1 = bsd.c
+@ENABLE_IMKLOG_LINUX_TRUE@am__append_2 = bsd.c
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_3 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_4 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/imklog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imklog_la_DEPENDENCIES =
+am__imklog_la_SOURCES_DIST = imklog.c imklog.h bsd.c
+@ENABLE_IMKLOG_BSD_TRUE@am__objects_1 = imklog_la-bsd.lo
+@ENABLE_IMKLOG_LINUX_TRUE@am__objects_2 = imklog_la-bsd.lo
+am_imklog_la_OBJECTS = imklog_la-imklog.lo $(am__objects_1) \
+ $(am__objects_2)
+imklog_la_OBJECTS = $(am_imklog_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 =
+imklog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imklog_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imklog_la-bsd.Plo \
+ ./$(DEPDIR)/imklog_la-imklog.Plo
+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 = $(imklog_la_SOURCES)
+DIST_SOURCES = $(am__imklog_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imklog.la
+imklog_la_SOURCES = imklog.c imklog.h $(am__append_1) $(am__append_2)
+imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_3)
+imklog_la_LDFLAGS = -module -avoid-version $(am__append_4)
+imklog_la_LIBADD =
+all: 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) --gnu plugins/imklog/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imklog/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imklog.la: $(imklog_la_OBJECTS) $(imklog_la_DEPENDENCIES) $(EXTRA_imklog_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imklog_la_LINK) -rpath $(pkglibdir) $(imklog_la_OBJECTS) $(imklog_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-bsd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-imklog.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imklog_la-imklog.lo: imklog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-imklog.lo -MD -MP -MF $(DEPDIR)/imklog_la-imklog.Tpo -c -o imklog_la-imklog.lo `test -f 'imklog.c' || echo '$(srcdir)/'`imklog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imklog_la-imklog.Tpo $(DEPDIR)/imklog_la-imklog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imklog.c' object='imklog_la-imklog.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) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-imklog.lo `test -f 'imklog.c' || echo '$(srcdir)/'`imklog.c
+
+imklog_la-bsd.lo: bsd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-bsd.lo -MD -MP -MF $(DEPDIR)/imklog_la-bsd.Tpo -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imklog_la-bsd.Tpo $(DEPDIR)/imklog_la-bsd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bsd.c' object='imklog_la-bsd.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) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imklog_la-bsd.Plo
+ -rm -f ./$(DEPDIR)/imklog_la-imklog.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imklog_la-bsd.Plo
+ -rm -f ./$(DEPDIR)/imklog_la-imklog.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imklog/bsd.c b/plugins/imklog/bsd.c
new file mode 100644
index 0000000..85331f2
--- /dev/null
+++ b/plugins/imklog/bsd.c
@@ -0,0 +1,329 @@
+/* combined imklog driver for BSD and Linux
+ *
+ * This contains OS-specific functionality to read the BSD
+ * or Linux kernel log. For a general overview, see head comment in
+ * imklog.c. This started out as the BSD-specific drivers, but it
+ * turned out that on modern Linux the implementation details
+ * are very small, and so we use a single driver for both OS's with
+ * a little help of conditional compilation.
+ *
+ * Copyright 2008-2023 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef OS_LINUX
+# include <sys/klog.h>
+#endif
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "debug.h"
+#include "imklog.h"
+
+/* globals */
+static int fklog = -1; /* kernel log fd */
+
+#ifndef _PATH_KLOG
+# ifdef OS_LINUX
+# define _PATH_KLOG "/proc/kmsg"
+# else
+# define _PATH_KLOG "/dev/klog"
+# endif
+#endif
+
+
+#ifdef OS_LINUX
+/* submit a message to imklog Syslog() API. In this function, we check if
+ * a kernel timestamp is present and, if so, extract and strip it.
+ * Note that this is heavily Linux specific and thus is not compiled or
+ * used for BSD.
+ * Special thanks to Lennart Poettering for suggesting on how to convert
+ * the kernel timestamp to a realtime timestamp. This method depends on
+ * the fact the the kernel timestamp is written using the monotonic clock.
+ * Shall that change (very unlikely), this code must be changed as well. Note
+ * that due to the way we generate the delta, we are unable to write the
+ * absolutely correct timestamp (system call overhead of the clock calls
+ * prevents us from doing so). However, the difference is very minor.
+ * rgerhards, 2011-06-24
+ */
+static void
+submitSyslog(modConfData_t *pModConf, syslog_pri_t pri, uchar *buf)
+{
+ long secs;
+ long usecs;
+ long secOffs;
+ long usecOffs;
+ unsigned i;
+ unsigned bufsize;
+ struct timespec monotonic, realtime;
+ struct timeval tv;
+ struct timeval *tp = NULL;
+
+ /* find end of pri */
+ int endpri = 1;
+ while(buf[endpri] != '>' && endpri < 5)
+ ++endpri;
+ if(endpri > 4 || buf[endpri + 1] != '[')
+ goto done;
+ DBGPRINTF("imklog: kernel timestamp detected, extracting it\n");
+
+ /* we now try to parse the timestamp. iff it parses, we assume
+ * it is a timestamp. Otherwise we know for sure it is no ts ;)
+ */
+ i = endpri + 2; /* space or first digit after '[' */
+ while(buf[i] && isspace(buf[i]))
+ ++i; /* skip space */
+ secs = 0;
+ while(buf[i] && isdigit(buf[i])) {
+ secs = secs * 10 + buf[i] - '0';
+ ++i;
+ }
+ if(buf[i] != '.') {
+ DBGPRINTF("no dot --> no kernel timestamp\n");
+ goto done; /* no TS! */
+ }
+
+ ++i; /* skip dot */
+ usecs = 0;
+ while(buf[i] && isdigit(buf[i])) {
+ usecs = usecs * 10 + buf[i] - '0';
+ ++i;
+ }
+ if(buf[i] != ']') {
+ DBGPRINTF("no trailing ']' --> no kernel timestamp\n");
+ goto done; /* no TS! */
+ }
+ ++i; /* skip ']' */
+
+ /* we have a timestamp */
+ DBGPRINTF("kernel timestamp is %ld %ld\n", secs, usecs);
+ if(!pModConf->bKeepKernelStamp) {
+ bufsize= strlen((char*)buf);
+ memmove(buf+endpri+1, buf+i, bufsize - i + 1);
+ }
+
+ if(!pModConf->bParseKernelStamp) {
+ DBGPRINTF("imklog/bsd: parseKernelStamp not set, ignoring kernel timestamp\n");
+ goto done;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &monotonic);
+ clock_gettime(CLOCK_REALTIME, &realtime);
+ secOffs = realtime.tv_sec - monotonic.tv_sec;
+ usecOffs = (realtime.tv_nsec - monotonic.tv_nsec) / 1000;
+ if(usecOffs < 0) {
+ secOffs--;
+ usecOffs += 1000000l;
+ }
+
+ usecs += usecOffs;
+ if(usecs > 999999l) {
+ secs++;
+ usecs -= 1000000l;
+ }
+ secs += secOffs;
+ tv.tv_sec = secs;
+ tv.tv_usec = usecs;
+ tp = &tv;
+
+done:
+ Syslog(pModConf, pri, buf, tp);
+}
+#else /* now comes the BSD "code" (just a shim) */
+static void
+submitSyslog(modConfData_t *pModConf, syslog_pri_t pri, uchar *buf)
+{
+ Syslog(pModConf, pri, buf, NULL);
+}
+#endif /* #ifdef LINUX */
+
+
+static uchar *GetPath(modConfData_t *pModConf)
+{
+ return pModConf->pszPath ? pModConf->pszPath : (uchar*) _PATH_KLOG;
+}
+
+/* open the kernel log - will be called inside the willRun() imklog
+ * entry point. -- rgerhards, 2008-04-09
+ */
+rsRetVal
+klogWillRunPrePrivDrop(modConfData_t *pModConf)
+{
+ char errmsg[2048];
+ DEFiRet;
+
+ fklog = open((char*)GetPath(pModConf), O_RDONLY, 0);
+ if (fklog < 0) {
+ imklogLogIntMsg(LOG_ERR, "imklog: cannot open kernel log (%s): %s.",
+ GetPath(pModConf), rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
+ }
+
+# ifdef OS_LINUX
+ /* Set level of kernel console messaging.. */
+ if(pModConf->console_log_level != -1) {
+ int r = klogctl(8, NULL, pModConf->console_log_level);
+ if(r != 0) {
+ imklogLogIntMsg(LOG_WARNING, "imklog: cannot set console log level: %s",
+ rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ /* make sure we do not try to re-set! */
+ pModConf->console_log_level = -1;
+ }
+ }
+# endif /* #ifdef OS_LINUX */
+
+finalize_it:
+ RETiRet;
+}
+
+/* make sure the kernel log is readable after dropping privileges
+ */
+rsRetVal
+klogWillRunPostPrivDrop(modConfData_t *pModConf)
+{
+ char errmsg[2048];
+ int r;
+ DEFiRet;
+
+ /* this normally returns EINVAL */
+ /* on an OpenVZ VM, we get EPERM */
+ r = read(fklog, NULL, 0);
+ if (r < 0 && errno != EINVAL) {
+ imklogLogIntMsg(LOG_ERR, "imklog: cannot open kernel log (%s): %s.",
+ GetPath(pModConf), rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ fklog = -1;
+ ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Read kernel log while data are available, split into lines.
+ */
+static void
+readklog(modConfData_t *pModConf)
+{
+ char *p, *q;
+ int len, i;
+ int iMaxLine;
+ uchar bufRcv[128*1024+1];
+ char errmsg[2048];
+ uchar *pRcv = NULL; /* receive buffer */
+
+ iMaxLine = klog_getMaxLine();
+
+ /* we optimize performance: if iMaxLine is below our fixed size buffer (which
+ * usually is sufficiently large), we use this buffer. if it is higher, heap memory
+ * is used. We could use alloca() to achive a similar aspect, but there are so
+ * many issues with alloca() that I do not want to take that route.
+ * rgerhards, 2008-09-02
+ */
+ if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
+ pRcv = bufRcv;
+ } else {
+ if((pRcv = (uchar*) malloc(iMaxLine + 1)) == NULL) {
+ iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */
+ pRcv = bufRcv;
+ }
+ }
+
+ len = 0;
+ for (;;) {
+ dbgprintf("imklog(BSD/Linux) waiting for kernel log line\n");
+ i = read(fklog, pRcv + len, iMaxLine - len);
+ if (i > 0) {
+ pRcv[i + len] = '\0';
+ } else {
+ if (i < 0 && errno != EINTR && errno != EAGAIN) {
+ imklogLogIntMsg(LOG_ERR,
+ "imklog: error reading kernel log - shutting down: %s",
+ rs_strerror_r(errno, errmsg, sizeof(errmsg)));
+ fklog = -1;
+ }
+ break;
+ }
+
+ for (p = (char*)pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) {
+ *q = '\0';
+ submitSyslog(pModConf, LOG_INFO, (uchar*) p);
+ }
+ len = strlen(p);
+ if (len >= iMaxLine - 1) {
+ submitSyslog(pModConf, LOG_INFO, (uchar*)p);
+ len = 0;
+ }
+ if(len > 0)
+ memmove(pRcv, p, len + 1);
+ }
+ if (len > 0)
+ submitSyslog(pModConf, LOG_INFO, pRcv);
+
+ if(pRcv != bufRcv)
+ free(pRcv);
+}
+
+
+/* to be called in the module's AfterRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal ATTR_NONNULL()
+klogAfterRun(modConfData_t *const pModConf __attribute__((unused)))
+{
+ DEFiRet;
+ if(fklog != -1)
+ close(fklog);
+# ifdef OS_LINUX
+ /* Turn on logging of messages to console, but only if a log level was speficied */
+ if(pModConf->console_log_level != -1)
+ klogctl(7, NULL, 0);
+# endif
+ RETiRet;
+}
+
+
+
+/* to be called in the module's WillRun entry point, this is the main
+ * "message pull" mechanism.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(modConfData_t *pModConf)
+{
+ DEFiRet;
+ readklog(pModConf);
+ RETiRet;
+}
+
+
+/* provide the (system-specific) default facility for internal messages
+ * rgerhards, 2008-04-14
+ */
+int
+klogFacilIntMsg(void)
+{
+ return LOG_SYSLOG;
+}
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
new file mode 100644
index 0000000..3935026
--- /dev/null
+++ b/plugins/imklog/imklog.c
@@ -0,0 +1,549 @@
+/* The kernel log module.
+ *
+ * This is an abstracted module. As Linux and BSD kernel log is conceptually the
+ * same, we do not do different input plugins for them but use
+ * imklog in both cases, just with different "backend drivers" for
+ * the different platforms. This also enables a rsyslog.conf to
+ * be used on multiple platforms without the need to take care of
+ * what the kernel log is coming from.
+ *
+ * See platform-specific files (e.g. linux.c, bsd.c) in the plugin's
+ * working directory. For other systems with similar kernel logging
+ * functionality, no new input plugin shall be written but rather a
+ * driver be developed for imklog. Please note that imklog itself is
+ * mostly concerned with handling the interface. Any real action happens
+ * in the drivers, as things may be pretty different on different
+ * platforms.
+ *
+ * Please note that this file replaces the klogd daemon that was
+ * also present in pre-v3 versions of rsyslog.
+ *
+ * To test under Linux:
+ * echo test1 > /dev/kmsg
+ *
+ * Copyright (C) 2008-2020 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#include "dirty.h"
+#include "cfsysline.h"
+#include "parserif.h"
+#include "obj.h"
+#include "msg.h"
+#include "module-template.h"
+#include "datetime.h"
+#include "imklog.h"
+#include "net.h"
+#include "glbl.h"
+#include "prop.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+#include "ruleset.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imklog")
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+
+/* config settings */
+typedef struct configSettings_s {
+ int bPermitNonKernel; /* permit logging of messages not having LOG_KERN facility */
+ int bParseKernelStamp; /* if try to parse kernel timestamps for message time */
+ int bKeepKernelStamp; /* keep the kernel timestamp in the message */
+ int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */
+ uchar *pszPath;
+ int console_log_level; /* still used for BSD */
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+} configSettings_t;
+static configSettings_t cs;
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ruleset", eCmdHdlrString, 0 },
+ { "logpath", eCmdHdlrGetWord, 0 },
+ { "permitnonkernelfacility", eCmdHdlrBinary, 0 },
+ { "consoleloglevel", eCmdHdlrInt, 0 },
+ { "parsekerneltimestamp", eCmdHdlrBinary, 0 },
+ { "keepkerneltimestamp", eCmdHdlrBinary, 0 },
+ { "internalmsgfacility", eCmdHdlrFacility, 0 },
+ { "ratelimitinterval", eCmdHdlrInt, 0 },
+ { "ratelimitburst", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+static prop_t *pInputName = NULL;
+/* there is only one global inputName for all messages generated by this module */
+static prop_t *pLocalHostIP = NULL;
+
+/** POTENTIAL COMMON CODE FOR RULESET CHECK **/
+static inline void std_mod_checkRuleset_genErrMsg(const modConfData_t *const modConf);
+static inline rsRetVal
+std_mod_checkRuleset(modConfData_t *const modConf)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ modConf->pBindRuleset = NULL; /* assume default ruleset */
+
+ if(modConf->pszBindRuleset == NULL)
+ FINALIZE;
+
+ localRet = ruleset.GetRuleset(modConf->pConf, &pRuleset, modConf->pszBindRuleset);
+ if(localRet == RS_RET_NOT_FOUND) {
+ std_mod_checkRuleset_genErrMsg(modConf);
+ }
+ CHKiRet(localRet);
+ modConf->pBindRuleset = pRuleset;
+
+finalize_it:
+ RETiRet;
+}
+/** END POTENTIAL COMMON CODE FOR RULESET CHECK **/
+static inline void
+std_mod_checkRuleset_genErrMsg(const modConfData_t *const modConf)
+{
+ LogError(0, NO_ERRCODE, "imklog: ruleset '%s' not found - "
+ "using default ruleset instead", modConf->pszBindRuleset);
+}
+
+static void
+initConfigSettings(void)
+{
+ cs.bPermitNonKernel = 0;
+ cs.bParseKernelStamp = 0;
+ cs.bKeepKernelStamp = 0;
+ cs.console_log_level = -1;
+ cs.pszPath = NULL;
+ cs.iFacilIntMsg = klogFacilIntMsg();
+}
+
+
+/* enqueue the the kernel message into the message queue.
+ * The provided msg string is not freed - thus must be done
+ * by the caller.
+ * rgerhards, 2008-04-12
+ */
+static rsRetVal
+enqMsg(uchar *const __restrict__ msg,
+ uchar* pszTag,
+ const syslog_pri_t pri,
+ struct timeval *tp,
+ ratelimit_t *ratelimiter)
+{
+ struct syslogTime st;
+ smsg_t *pMsg;
+ DEFiRet;
+
+ assert(msg != NULL);
+ assert(pszTag != NULL);
+
+ if(tp == NULL) {
+ CHKiRet(msgConstruct(&pMsg));
+ } else {
+ datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME);
+ CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec));
+ }
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsgWOSize(pMsg, (char*)msg);
+ MsgSetRuleset(pMsg, runModConf->pBindRuleset);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, pLocalHostIP);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
+ msgSetPRI(pMsg, pri);
+ ratelimitAddMsg(ratelimiter, NULL, pMsg);
+finalize_it:
+ RETiRet;
+}
+
+/* parse the PRI from a kernel message. At least BSD seems to have
+ * non-kernel messages inside the kernel log...
+ * Expected format: "<pri>". piPri is only valid if the function
+ * successfully returns. If there was a proper pri ppSz is advanced to the
+ * position right after ">".
+ * rgerhards, 2008-04-14
+ */
+static rsRetVal
+parsePRI(uchar **ppSz, syslog_pri_t *piPri)
+{
+ DEFiRet;
+ syslog_pri_t i;
+ uchar *pSz;
+
+ assert(ppSz != NULL);
+ pSz = *ppSz;
+ assert(pSz != NULL);
+ assert(piPri != NULL);
+
+ if(*pSz != '<' || !isdigit(*(pSz+1)))
+ ABORT_FINALIZE(RS_RET_INVALID_PRI);
+
+ ++pSz;
+ i = 0;
+ while(isdigit(*pSz) && i <= LOG_MAXPRI) {
+ i = i * 10 + *pSz++ - '0';
+ }
+
+ if(*pSz != '>' || i > LOG_MAXPRI)
+ ABORT_FINALIZE(RS_RET_INVALID_PRI);
+
+ /* OK, we have a valid PRI */
+ *piPri = i;
+ *ppSz = pSz + 1; /* update msg ptr to position after PRI */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* log an imklog-internal message
+ * rgerhards, 2008-04-14
+ */
+rsRetVal imklogLogIntMsg(syslog_pri_t priority, const char *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+ uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
+
+ va_start(ap, fmt);
+ vsnprintf((char*)msgBuf, sizeof(msgBuf), fmt, ap);
+ va_end(ap);
+
+ logmsgInternal(NO_ERRCODE, priority, msgBuf, 0);
+
+ RETiRet;
+}
+
+
+/* log a kernel message. If tp is non-NULL, it contains the message creation
+ * time to use.
+ * rgerhards, 2008-04-14
+ */
+rsRetVal Syslog(modConfData_t *pModConf, syslog_pri_t priority, uchar *pMsg, struct timeval *tp)
+{
+ syslog_pri_t pri;
+ int bPRISet = 0;
+ rsRetVal localRet;
+ DEFiRet;
+
+ /* then check if we have two PRIs. This can happen in case of systemd,
+ * in which case the second PRI is the right one.
+ */
+ if(pMsg[3] == '<' || (pMsg[3] == ' ' && pMsg[4] == '<')) { /* could be a pri... */
+ uchar *pMsgTmp = pMsg + ((pMsg[3] == '<') ? 3 : 4);
+ localRet = parsePRI(&pMsgTmp, &pri);
+ if(localRet == RS_RET_OK && pri >= 8 && pri <= LOG_MAXPRI) {
+ /* *this* is our PRI */
+ DBGPRINTF("imklog detected secondary PRI(%d) in klog msg\n", pri);
+ pMsg = pMsgTmp;
+ priority = pri;
+ bPRISet = 1;
+ }
+ }
+ if(!bPRISet) {
+ localRet = parsePRI(&pMsg, &priority);
+ if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK)
+ FINALIZE;
+ }
+ /* if we don't get the pri, we use whatever we were supplied */
+
+ /* ignore non-kernel messages if not permitted */
+ if(pModConf->bPermitNonKernel == 0 && pri2fac(priority) != LOG_KERN)
+ FINALIZE; /* silently ignore */
+ iRet = enqMsg((uchar*)pMsg, (uchar*) "kernel:", priority, tp, pModConf->ratelimiter);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* helper for some klog drivers which need to know the MaxLine global setting. They can
+ * not obtain it themselfs, because they are no modules and can not query the object hander.
+ * It would probably be a good idea to extend the interface to support it, but so far
+ * we create a (sufficiently valid) work-around. -- rgerhards, 2008-11-24
+ */
+int klog_getMaxLine(void)
+{
+ return glbl.GetMaxLine(runConf);
+}
+
+
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(!pThrd->bShallStop) {
+ /* klogLogKMsg() waits for the next kernel message, obtains it
+ * and then submits it to the rsyslog main queue.
+ * rgerhards, 2008-04-09
+ */
+ CHKiRet(klogLogKMsg(runModConf));
+ }
+finalize_it:
+ENDrunInput
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ pModConf->pszPath = NULL;
+ pModConf->bPermitNonKernel = 0;
+ pModConf->bParseKernelStamp = 0;
+ pModConf->bKeepKernelStamp = 0;
+ pModConf->console_log_level = -1;
+ pModConf->bKeepKernelStamp = 0;
+ pModConf->iFacilIntMsg = klogFacilIntMsg();
+ loadModConf->configSetViaV2Method = 0;
+ pModConf->ratelimiter = NULL;
+ pModConf->ratelimitBurst = 10000; /* arbitrary high limit */
+ pModConf->ratelimitInterval = 0; /* off */
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ initConfigSettings();
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imklog:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "logpath")) {
+ loadModConf->pszPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "permitnonkernelfacility")) {
+ loadModConf->bPermitNonKernel = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "parsekerneltimestamp")) {
+ loadModConf->bParseKernelStamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepkerneltimestamp")) {
+ loadModConf->bKeepKernelStamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "consoleloglevel")) {
+ loadModConf->console_log_level= (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "internalmsgfacility")) {
+ loadModConf->iFacilIntMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimitburst")) {
+ loadModConf->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimitinterval")) {
+ loadModConf->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_WARNING,
+ "imklog: RSYSLOG BUG, non-handled param '%s' in "
+ "beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* disable legacy module-global config directives */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->bPermitNonKernel = cs.bPermitNonKernel;
+ loadModConf->bParseKernelStamp = cs.bParseKernelStamp;
+ loadModConf->bKeepKernelStamp = cs.bKeepKernelStamp;
+ loadModConf->iFacilIntMsg = cs.iFacilIntMsg;
+ loadModConf->console_log_level = cs.console_log_level;
+ if((cs.pszPath == NULL) || (cs.pszPath[0] == '\0')) {
+ loadModConf->pszPath = NULL;
+ if(cs.pszPath != NULL)
+ free(cs.pszPath);
+ } else {
+ loadModConf->pszPath = cs.pszPath;
+ }
+ cs.pszPath = NULL;
+ }
+
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ std_mod_checkRuleset(pModConf);
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ iRet = klogWillRunPrePrivDrop(runModConf);
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ CHKiRet(ratelimitNew(&runModConf->ratelimiter, "imklog", NULL));
+ ratelimitSetLinuxLike(runModConf->ratelimiter,
+ runModConf->ratelimitInterval,
+ runModConf->ratelimitBurst);
+finalize_it:
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->pszBindRuleset);
+ENDfreeCnf
+
+
+BEGINwillRun
+CODESTARTwillRun
+ pLocalHostIP = glbl.GetLocalHostIP();
+ iRet = klogWillRunPostPrivDrop(runModConf);
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ ratelimitDestruct(runModConf->ratelimiter);
+ iRet = klogAfterRun(runModConf);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
+ /* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.bPermitNonKernel = 0;
+ cs.bParseKernelStamp = 0;
+ cs.bKeepKernelStamp = 0;
+ if(cs.pszPath != NULL) {
+ free(cs.pszPath);
+ cs.pszPath = NULL;
+ }
+ cs.iFacilIntMsg = klogFacilIntMsg();
+ return RS_RET_OK;
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imklog"), sizeof("imklog") - 1));
+
+ /* init legacy config settings */
+ initConfigSettings();
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogLocalipif", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"klogpath", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszPath, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrGoneAway,
+ NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary,
+ NULL, &cs.bPermitNonKernel, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"klogconsoleloglevel", 0, eCmdHdlrInt,
+ NULL, &cs.console_log_level, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"kloginternalmsgfacility", 0, eCmdHdlrFacility,
+ NULL, &cs.iFacilIntMsg, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"klogparsekerneltimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bParseKernelStamp, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"klogkeepkerneltimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bKeepKernelStamp, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h
new file mode 100644
index 0000000..0ccc320
--- /dev/null
+++ b/plugins/imklog/imklog.h
@@ -0,0 +1,77 @@
+/* imklog.h
+ * These are the definitions for the klog message generation module.
+ *
+ * File begun on 2007-12-17 by RGerhards
+ * Major change: 2008-04-09: switched to a driver interface for
+ * several platforms
+ *
+ * Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IMKLOG_H_INCLUDED
+#define IMKLOG_H_INCLUDED 1
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "ratelimit.h"
+
+/* we need to have the modConf type present in all submodules */
+struct modConfData_s {
+ rsconf_t *pConf;
+ int iFacilIntMsg;
+ uchar *pszPath;
+ int console_log_level;
+ sbool bParseKernelStamp;
+ sbool bKeepKernelStamp;
+ sbool bPermitNonKernel;
+ sbool configSetViaV2Method;
+ ratelimit_t *ratelimiter;
+ int ratelimitInterval;
+ int ratelimitBurst;
+ ruleset_t *pBindRuleset; /* ruleset to bind (use system default if unspecified) */
+ uchar *pszBindRuleset;
+};
+
+/* interface to "drivers"
+ * the platform specific drivers must implement these entry points. Only one
+ * driver may be active at any given time, thus we simply rely on the linker
+ * to resolve the addresses.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(modConfData_t *pModConf);
+rsRetVal klogAfterRun(modConfData_t *pModConf);
+rsRetVal klogWillRunPrePrivDrop(modConfData_t *pModConf);
+rsRetVal klogWillRunPostPrivDrop(modConfData_t *pModConf);
+int klogFacilIntMsg(void);
+
+/* the functions below may be called by the drivers */
+rsRetVal imklogLogIntMsg(syslog_pri_t priority, const char *fmt, ...) __attribute__((format(printf,2, 3)));
+rsRetVal Syslog(modConfData_t *pModConf, syslog_pri_t priority, uchar *msg, struct timeval *tp);
+
+/* prototypes */
+extern int klog_getMaxLine(void); /* work-around for klog drivers to get configured max line size */
+extern int InitKsyms(modConfData_t*);
+extern void DeinitKsyms(void);
+extern int InitMsyms(void);
+extern void DeinitMsyms(void);
+extern char * ExpandKadds(char *, char *);
+extern void SetParanoiaLevel(int);
+
+#endif /* #ifndef IMKLOG_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/plugins/immark/Makefile.am b/plugins/immark/Makefile.am
new file mode 100644
index 0000000..85b2e14
--- /dev/null
+++ b/plugins/immark/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = immark.la
+
+immark_la_SOURCES = immark.c immark.h
+immark_la_CPPFLAGS = $(RSRT_CFLAGS) -I$(top_srcdir) $(PTHREADS_CFLAGS)
+immark_la_LDFLAGS = -module -avoid-version
+immark_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+immark_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+immark_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/immark/Makefile.in b/plugins/immark/Makefile.in
new file mode 100644
index 0000000..3d73940
--- /dev/null
+++ b/plugins/immark/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/immark
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+immark_la_DEPENDENCIES =
+am_immark_la_OBJECTS = immark_la-immark.lo
+immark_la_OBJECTS = $(am_immark_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 =
+immark_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(immark_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/immark_la-immark.Plo
+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 = $(immark_la_SOURCES)
+DIST_SOURCES = $(immark_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = immark.la
+immark_la_SOURCES = immark.c immark.h
+immark_la_CPPFLAGS = $(RSRT_CFLAGS) -I$(top_srcdir) $(PTHREADS_CFLAGS) \
+ $(am__append_1)
+immark_la_LDFLAGS = -module -avoid-version $(am__append_2)
+immark_la_LIBADD =
+all: 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) --gnu plugins/immark/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/immark/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+immark.la: $(immark_la_OBJECTS) $(immark_la_DEPENDENCIES) $(EXTRA_immark_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(immark_la_LINK) -rpath $(pkglibdir) $(immark_la_OBJECTS) $(immark_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/immark_la-immark.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+immark_la-immark.lo: immark.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(immark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT immark_la-immark.lo -MD -MP -MF $(DEPDIR)/immark_la-immark.Tpo -c -o immark_la-immark.lo `test -f 'immark.c' || echo '$(srcdir)/'`immark.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/immark_la-immark.Tpo $(DEPDIR)/immark_la-immark.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='immark.c' object='immark_la-immark.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) $(immark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o immark_la-immark.lo `test -f 'immark.c' || echo '$(srcdir)/'`immark.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/immark_la-immark.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/immark_la-immark.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/immark/immark.c b/plugins/immark/immark.c
new file mode 100644
index 0000000..af893a3
--- /dev/null
+++ b/plugins/immark/immark.c
@@ -0,0 +1,337 @@
+/* immark.c
+ * This is the implementation of the build-in mark message input module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007-2020 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "msg.h"
+#include "srUtils.h"
+#include "glbl.h"
+#include "unicode-helper.h"
+#include "ruleset.h"
+#include "prop.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("immark")
+
+/* defines */
+#define DEFAULT_MARK_PERIOD (20 * 60)
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+static int iMarkMessagePeriod = DEFAULT_MARK_PERIOD;
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ const char *pszMarkMsgText;
+ size_t lenMarkMsgText;
+ uchar *pszBindRuleset;
+ ruleset_t *pBindRuleset;
+ int flags;
+ int bUseMarkFlag;
+ int bUseSyslogAPI;
+ int iMarkMessagePeriod;
+ sbool configSetViaV2Method;
+};
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ruleset", eCmdHdlrString, 0 },
+ { "markmessagetext", eCmdHdlrString, 0 },
+ { "use.syslogcall", eCmdHdlrBinary, 0 },
+ { "use.markflag", eCmdHdlrBinary, 0 },
+ { "interval", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+static prop_t *pInternalInputName = NULL;
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINafterRun
+CODESTARTafterRun
+ENDafterRun
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ pModConf->pszMarkMsgText = NULL;
+ pModConf->iMarkMessagePeriod = DEFAULT_MARK_PERIOD;
+ pModConf->bUseSyslogAPI = 1;
+ pModConf->bUseMarkFlag = 1;
+ pModConf->pszBindRuleset = NULL;
+ pModConf->pBindRuleset = NULL;
+ loadModConf->configSetViaV2Method = 0;
+ bLegacyCnfModGlobalsPermitted = 1;
+ENDbeginCnfLoad
+
+static rsRetVal
+checkRuleset(modConfData_t *modConf)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ if(modConf->pszBindRuleset == NULL)
+ FINALIZE;
+
+ localRet = ruleset.GetRuleset(modConf->pConf, &pRuleset, modConf->pszBindRuleset);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, NO_ERRCODE, "immark: ruleset '%s' not found - "
+ "using default ruleset instead", modConf->pszBindRuleset);
+ }
+ CHKiRet(localRet);
+ modConf->pBindRuleset = pRuleset;
+
+finalize_it:
+ RETiRet;
+}
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for immark:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "interval")) {
+ loadModConf->iMarkMessagePeriod = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "use.syslogcall")) {
+ loadModConf->bUseSyslogAPI = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "use.markflag")) {
+ loadModConf->bUseMarkFlag = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "markmessagetext")) {
+ loadModConf->pszMarkMsgText = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("immark: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* disable legacy module-global config directives */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ pModConf->iMarkMessagePeriod = iMarkMessagePeriod;
+ }
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ pModConf->flags = (pModConf->bUseMarkFlag) ? MARK : 0;
+ if(pModConf->pszMarkMsgText == NULL) {
+ pModConf->pszMarkMsgText = strdup("-- MARK --");
+ }
+ pModConf->lenMarkMsgText = strlen(pModConf->pszMarkMsgText);
+ if(pModConf->pszBindRuleset != NULL) {
+ checkRuleset(pModConf);
+ if(pModConf->bUseSyslogAPI) {
+ LogError(0, NO_ERRCODE, "immark: ruleset specified, but configured to log "
+ "via syslog call - switching to rsyslog-internal logging");
+ pModConf->bUseSyslogAPI = 0;
+ }
+ }
+ if(pModConf->iMarkMessagePeriod == 0) {
+ LogError(0, NO_ERRCODE, "immark: mark message period must not be 0, can not run");
+ ABORT_FINALIZE(RS_RET_NO_RUN); /* we can not run with this error */
+ }
+finalize_it:
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ MarkInterval = pModConf->iMarkMessagePeriod;
+ DBGPRINTF("immark set MarkInterval to %d\n", MarkInterval);
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+static rsRetVal
+injectMarkMessage(const int pri)
+{
+ smsg_t *pMsg;
+ DEFiRet;
+
+ CHKiRet(msgConstruct(&pMsg));
+ pMsg->msgFlags = loadModConf->flags;
+ MsgSetInputName(pMsg, pInternalInputName);
+ MsgSetRawMsg(pMsg, loadModConf->pszMarkMsgText,loadModConf->lenMarkMsgText);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
+ MsgSetMSGoffs(pMsg, 0);
+ MsgSetTAG(pMsg, (const uchar*)"rsyslogd:", sizeof("rsyslogd:")-1);
+ msgSetPRI(pMsg, pri);
+ MsgSetRuleset(pMsg, loadModConf->pBindRuleset);
+ submitMsg2(pMsg);
+finalize_it:
+ RETiRet;
+}
+
+/* This function is called to gather input. It must terminate only
+ * a) on failure (iRet set accordingly)
+ * b) on termination of the input module (as part of the unload process)
+ * Code begun 2007-12-12 rgerhards
+ *
+ * This code must simply spawn emit a mark message at each mark interval.
+ * We are running on our own thread, so this is extremely easy: we just
+ * sleep MarkInterval seconds and each time we awake, we inject the message.
+ * Please note that we do not do the other fancy things that sysklogd
+ * (and pre 1.20.2 releases of rsyslog) did in mark procesing. They simply
+ * do not belong here.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(1) {
+ srSleep(MarkInterval, 0); /* seconds, micro seconds */
+
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ dbgprintf("immark: injecting mark message\n");
+ if(loadModConf->bUseSyslogAPI) {
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO,
+ (uchar*)loadModConf->pszMarkMsgText, loadModConf->flags);
+ } else {
+ injectMarkMessage(LOG_SYSLOG|LOG_INFO);
+ }
+ }
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInternalInputName != NULL)
+ prop.Destruct(&pInternalInputName);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ iMarkMessagePeriod = DEFAULT_MARK_PERIOD;
+ return RS_RET_OK;
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInternalInputName));
+ CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("immark"), sizeof("immark") - 1));
+ CHKiRet(prop.ConstructFinalize(pInternalInputName));
+
+ /* legacy config handlers */
+ CHKiRet(regCfSysLineHdlr2((uchar *)"markmessageperiod", 0, eCmdHdlrInt, NULL,
+ &iMarkMessagePeriod, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/immark/immark.h b/plugins/immark/immark.h
new file mode 100644
index 0000000..bdb029b
--- /dev/null
+++ b/plugins/immark/immark.h
@@ -0,0 +1,34 @@
+/* immark.h
+ * These are the definitions for the built-in mark message generation module. This
+ * file may disappear when this has become a loadable module.
+ *
+ * File begun on 2007-12-12 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IMMARK_H_INCLUDED
+#define IMMARK_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal immark_runInput(void);
+
+#endif /* #ifndef IMMARK_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/plugins/impstats/Makefile.am b/plugins/impstats/Makefile.am
new file mode 100644
index 0000000..187bbca
--- /dev/null
+++ b/plugins/impstats/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = impstats.la
+
+impstats_la_SOURCES = impstats.c
+impstats_la_CPPFLAGS = $(RSRT_CFLAGS) -I$(top_srcdir) $(PTHREADS_CFLAGS)
+impstats_la_LDFLAGS = -module -avoid-version
+impstats_la_LIBADD =
diff --git a/plugins/impstats/Makefile.in b/plugins/impstats/Makefile.in
new file mode 100644
index 0000000..58bdf49
--- /dev/null
+++ b/plugins/impstats/Makefile.in
@@ -0,0 +1,796 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/impstats
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+impstats_la_DEPENDENCIES =
+am_impstats_la_OBJECTS = impstats_la-impstats.lo
+impstats_la_OBJECTS = $(am_impstats_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 =
+impstats_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(impstats_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/impstats_la-impstats.Plo
+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 = $(impstats_la_SOURCES)
+DIST_SOURCES = $(impstats_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = impstats.la
+impstats_la_SOURCES = impstats.c
+impstats_la_CPPFLAGS = $(RSRT_CFLAGS) -I$(top_srcdir) $(PTHREADS_CFLAGS)
+impstats_la_LDFLAGS = -module -avoid-version
+impstats_la_LIBADD =
+all: 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) --gnu plugins/impstats/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/impstats/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+impstats.la: $(impstats_la_OBJECTS) $(impstats_la_DEPENDENCIES) $(EXTRA_impstats_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(impstats_la_LINK) -rpath $(pkglibdir) $(impstats_la_OBJECTS) $(impstats_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impstats_la-impstats.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+impstats_la-impstats.lo: impstats.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impstats_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impstats_la-impstats.lo -MD -MP -MF $(DEPDIR)/impstats_la-impstats.Tpo -c -o impstats_la-impstats.lo `test -f 'impstats.c' || echo '$(srcdir)/'`impstats.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impstats_la-impstats.Tpo $(DEPDIR)/impstats_la-impstats.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='impstats.c' object='impstats_la-impstats.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) $(impstats_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impstats_la-impstats.lo `test -f 'impstats.c' || echo '$(srcdir)/'`impstats.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/impstats_la-impstats.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/impstats_la-impstats.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/impstats/impstats.c b/plugins/impstats/impstats.c
new file mode 100644
index 0000000..6dbe935
--- /dev/null
+++ b/plugins/impstats/impstats.c
@@ -0,0 +1,635 @@
+/* impstats.c
+ * A module to periodically output statistics gathered by rsyslog.
+ *
+ * Copyright 2010-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#ifdef OS_LINUX
+#include <sys/types.h>
+#include <dirent.h>
+#endif
+
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "msg.h"
+#include "srUtils.h"
+#include "unicode-helper.h"
+#include "glbl.h"
+#include "statsobj.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "parserif.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("impstats")
+
+/* defines */
+#define DEFAULT_STATS_PERIOD (5 * 60)
+#define DEFAULT_FACILITY 5 /* syslog */
+#define DEFAULT_SEVERITY 6 /* info */
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(ruleset)
+
+typedef struct configSettings_s {
+ int iStatsInterval;
+ int iFacility;
+ int iSeverity;
+ int bJSON;
+ int bCEE;
+} configSettings_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ int iStatsInterval;
+ int iFacility;
+ int iSeverity;
+ int logfd; /* fd if logging to file, or -1 if closed */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ statsFmtType_t statsFmt;
+ sbool bLogToSyslog;
+ sbool bResetCtrs;
+ sbool bBracketing;
+ char *logfile;
+ sbool configSetViaV2Method;
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+static configSettings_t cs;
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+static prop_t *pInputName = NULL;
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "interval", eCmdHdlrInt, 0 },
+ { "facility", eCmdHdlrInt, 0 },
+ { "severity", eCmdHdlrInt, 0 },
+ { "bracketing", eCmdHdlrBinary, 0 },
+ { "log.syslog", eCmdHdlrBinary, 0 },
+ { "resetcounters", eCmdHdlrBinary, 0 },
+ { "log.file", eCmdHdlrGetWord, 0 },
+ { "format", eCmdHdlrGetWord, 0 },
+ { "ruleset", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+
+/* resource use stats counters */
+#ifdef OS_LINUX
+static int st_openfiles;
+#endif
+static intctr_t st_ru_utime;
+static intctr_t st_ru_stime;
+static intctr_t st_ru_maxrss;
+static intctr_t st_ru_minflt;
+static intctr_t st_ru_majflt;
+static intctr_t st_ru_inblock;
+static intctr_t st_ru_oublock;
+static intctr_t st_ru_nvcsw;
+static intctr_t st_ru_nivcsw;
+static statsobj_t *statsobj_resources;
+
+static pthread_mutex_t hup_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+BEGINmodExit
+CODESTARTmodExit
+ prop.Destruct(&pInputName);
+ /* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+#ifdef OS_LINUX
+/* count number of open files (linux specific) */
+static void
+countOpenFiles(void)
+{
+ char proc_path[MAXFNAME];
+ DIR *dp;
+ struct dirent *files;
+
+ st_openfiles = 0;
+ snprintf(proc_path, sizeof(proc_path), "/proc/%d/fd", glblGetOurPid());
+ if((dp = opendir(proc_path)) == NULL) {
+ LogError(errno, RS_RET_ERR, "impstats: error reading %s\n", proc_path);
+ goto done;
+ }
+ while((files=readdir(dp)) != NULL) {
+ if(!strcmp(files->d_name, ".") || !strcmp(files->d_name, ".."))
+ continue;
+ st_openfiles++;
+ }
+ closedir(dp);
+
+done:
+ return;
+}
+#endif
+
+
+static void
+initConfigSettings(void)
+{
+ cs.iStatsInterval = DEFAULT_STATS_PERIOD;
+ cs.iFacility = DEFAULT_FACILITY;
+ cs.iSeverity = DEFAULT_SEVERITY;
+ cs.bJSON = 0;
+ cs.bCEE = 0;
+}
+
+
+/* actually submit a message to the rsyslog core
+ */
+static void
+doSubmitMsg(uchar *line)
+{
+ smsg_t *pMsg;
+
+ if(msgConstruct(&pMsg) != RS_RET_OK)
+ goto finalize_it;
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsgWOSize(pMsg, (char*)line);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
+ MsgSetMSGoffs(pMsg, 0);
+ MsgSetRuleset(pMsg, runModConf->pBindRuleset);
+ MsgSetTAG(pMsg, UCHAR_CONSTANT("rsyslogd-pstats:"), sizeof("rsyslogd-pstats:") - 1);
+ pMsg->iFacility = runModConf->iFacility;
+ pMsg->iSeverity = runModConf->iSeverity;
+ pMsg->msgFlags = 0;
+
+ /* we do not use rate-limiting, as the stats message always need to be emitted */
+ submitMsg2(pMsg);
+ DBGPRINTF("impstats: submit [%d,%d] msg '%s'\n", runModConf->iFacility,
+ runModConf->iSeverity, line);
+
+finalize_it:
+ return;
+}
+
+
+/* log stats message to file; limited error handling done */
+static void
+doLogToFile(const char *ln, const size_t lenLn)
+{
+ struct iovec iov[4];
+ ssize_t nwritten;
+ ssize_t nexpect;
+ time_t t;
+ char timebuf[32];
+
+ pthread_mutex_lock(&hup_mutex);
+
+ if(lenLn == 0)
+ goto done;
+
+ if(runModConf->logfd == -1) {
+ runModConf->logfd = open(runModConf->logfile, O_WRONLY|O_CREAT|O_APPEND|O_CLOEXEC, S_IRUSR|S_IWUSR);
+ if(runModConf->logfd == -1) {
+ DBGPRINTF("impstats: error opening stats file %s\n",
+ runModConf->logfile);
+ goto done;
+ } else {
+ DBGPRINTF("impstats: opened stats file %s\n",
+ runModConf->logfile);
+ }
+ }
+
+ time(&t);
+ iov[0].iov_base = ctime_r(&t, timebuf);
+ iov[0].iov_len = nexpect = strlen(iov[0].iov_base) - 1; /* -1: strip \n */
+ iov[1].iov_base = (void*)": ";
+ iov[1].iov_len = 2;
+ nexpect += 2;
+ iov[2].iov_base = (void*)ln;
+ iov[2].iov_len = lenLn;
+ nexpect += lenLn;
+ iov[3].iov_base = (void*)"\n";
+ iov[3].iov_len = 1;
+ nexpect++;
+ nwritten = writev(runModConf->logfd, iov, 4);
+
+ if(nwritten != nexpect) {
+ dbgprintf("error writing stats file %s, nwritten %lld, expected %lld\n",
+ runModConf->logfile, (long long) nwritten, (long long) nexpect);
+ }
+done:
+ pthread_mutex_unlock(&hup_mutex);
+ return;
+}
+
+
+/* submit a line to our log destinations. Line must be fully formatted as
+ * required (but may be a simple verb like "BEGIN" and "END".
+ */
+static rsRetVal
+submitLine(const char *const ln, const size_t lenLn)
+{
+ DEFiRet;
+ if(runModConf->bLogToSyslog)
+ doSubmitMsg((uchar*)ln);
+ if(runModConf->logfile != NULL)
+ doLogToFile(ln, lenLn);
+ RETiRet;
+}
+
+/* callback for statsobj
+ * Note: usrptr exists only to satisfy requirements of statsobj callback interface!
+ */
+static rsRetVal
+doStatsLine(void __attribute__((unused)) *usrptr, const char *const str)
+{
+ DEFiRet;
+ iRet = submitLine(str, strlen(str));
+ RETiRet;
+}
+
+
+/* the function to generate the actual statistics messages
+ * rgerhards, 2010-09-09
+ */
+static void
+generateStatsMsgs(void)
+{
+ struct rusage ru;
+ int r;
+ r = getrusage(RUSAGE_SELF, &ru);
+ if(r != 0) {
+ dbgprintf("impstats: getrusage() failed with error %d, zeroing out\n", errno);
+ memset(&ru, 0, sizeof(ru));
+ }
+# ifdef OS_LINUX
+ countOpenFiles();
+# endif
+ st_ru_utime = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec;
+ st_ru_stime = ru.ru_stime.tv_sec * 1000000 + ru.ru_stime.tv_usec;
+ st_ru_maxrss = ru.ru_maxrss;
+ st_ru_minflt = ru.ru_minflt;
+ st_ru_majflt = ru.ru_majflt;
+ st_ru_inblock = ru.ru_inblock;
+ st_ru_oublock = ru.ru_oublock;
+ st_ru_nvcsw = ru.ru_nvcsw;
+ st_ru_nivcsw = ru.ru_nivcsw;
+ statsobj.GetAllStatsLines(doStatsLine, NULL, runModConf->statsFmt, runModConf->bResetCtrs);
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ loadModConf->configSetViaV2Method = 0;
+ loadModConf->iStatsInterval = DEFAULT_STATS_PERIOD;
+ loadModConf->iFacility = DEFAULT_FACILITY;
+ loadModConf->iSeverity = DEFAULT_SEVERITY;
+ loadModConf->statsFmt = statsFmt_Legacy;
+ loadModConf->logfd = -1;
+ loadModConf->logfile = NULL;
+ loadModConf->pszBindRuleset = NULL;
+ loadModConf->bLogToSyslog = 1;
+ loadModConf->bBracketing = 0;
+ loadModConf->bResetCtrs = 0;
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ initConfigSettings();
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ char *mode;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for impstats:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "interval")) {
+ loadModConf->iStatsInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "facility")) {
+ loadModConf->iFacility = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "severity")) {
+ loadModConf->iSeverity = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "bracketing")) {
+ loadModConf->bBracketing = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "log.syslog")) {
+ loadModConf->bLogToSyslog = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "resetcounters")) {
+ loadModConf->bResetCtrs = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "log.file")) {
+ loadModConf->logfile = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "format")) {
+ mode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(mode, "json")) {
+ loadModConf->statsFmt = statsFmt_JSON;
+ } else if(!strcasecmp(mode, "json-elasticsearch")) {
+ loadModConf->statsFmt = statsFmt_JSON_ES;
+ } else if(!strcasecmp(mode, "cee")) {
+ loadModConf->statsFmt = statsFmt_CEE;
+ } else if(!strcasecmp(mode, "legacy")) {
+ loadModConf->statsFmt = statsFmt_Legacy;
+ } else {
+ LogError(0, RS_RET_ERR, "impstats: invalid format %s",
+ mode);
+ }
+ free(mode);
+ } else if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("impstats: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ if(loadModConf->pszBindRuleset != NULL && loadModConf->bLogToSyslog == 0) {
+ parser_warnmsg("impstats: log.syslog set to \"off\" but ruleset specified - with "
+ "these settings, the ruleset will never be used, because regular syslog "
+ "processing is turned off - ruleset parameter is ignored");
+ free(loadModConf->pszBindRuleset);
+ loadModConf->pszBindRuleset = NULL;
+ }
+
+ loadModConf->configSetViaV2Method = 1;
+ bLegacyCnfModGlobalsPermitted = 0;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->iStatsInterval = cs.iStatsInterval;
+ loadModConf->iFacility = cs.iFacility;
+ loadModConf->iSeverity = cs.iSeverity;
+ if (cs.bCEE == 1) {
+ loadModConf->statsFmt = statsFmt_CEE;
+ } else if (cs.bJSON == 1) {
+ loadModConf->statsFmt = statsFmt_JSON;
+ } else {
+ loadModConf->statsFmt = statsFmt_Legacy;
+ }
+ }
+ENDendCnfLoad
+
+
+/* we need our special version of checkRuleset(), as we do not have any instances */
+static rsRetVal
+checkRuleset(modConfData_t *modConf)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ modConf->pBindRuleset = NULL; /* assume default ruleset */
+
+ if(modConf->pszBindRuleset == NULL)
+ FINALIZE;
+
+ localRet = ruleset.GetRuleset(modConf->pConf, &pRuleset, modConf->pszBindRuleset);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, NO_ERRCODE, "impstats: ruleset '%s' not found - "
+ "using default ruleset instead", modConf->pszBindRuleset);
+ }
+ CHKiRet(localRet);
+ modConf->pBindRuleset = pRuleset;
+finalize_it:
+ RETiRet;
+}
+
+
+/* to use HUP, we need to have an instanceData type, as this was
+ * originally designed for actions. However, we do not, and cannot,
+ * use the content. The core will always provide a NULL pointer.
+ */
+typedef struct _instanceData {
+ int dummy;
+} instanceData;
+BEGINdoHUP
+CODESTARTdoHUP
+ DBGPRINTF("impstats: received HUP\n")
+ pthread_mutex_lock(&hup_mutex);
+ if(runModConf->logfd != -1) {
+ DBGPRINTF("impstats: closing log file due to HUP\n");
+ close(runModConf->logfd);
+ runModConf->logfd = -1;
+ }
+ pthread_mutex_unlock(&hup_mutex);
+ENDdoHUP
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ if(pModConf->iStatsInterval == 0) {
+ LogError(0, NO_ERRCODE, "impstats: stats interval zero not permitted, using "
+ "default of %d seconds", DEFAULT_STATS_PERIOD);
+ pModConf->iStatsInterval = DEFAULT_STATS_PERIOD;
+ }
+ checkRuleset(pModConf);
+ENDcheckCnf
+
+
+BEGINactivateCnf
+ rsRetVal localRet;
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ DBGPRINTF("impstats: stats interval %d seconds, reset %d, logToSyslog %d, logFile %s\n",
+ runModConf->iStatsInterval, runModConf->bResetCtrs, runModConf->bLogToSyslog,
+ runModConf->logfile == NULL ? "deactivated" : (char*)runModConf->logfile);
+ localRet = statsobj.EnableStats();
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "impstats: error enabling statistics gathering");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+ /* initialize our own counters */
+ CHKiRet(statsobj.Construct(&statsobj_resources));
+ CHKiRet(statsobj.SetName(statsobj_resources, (uchar*)"resource-usage"));
+ CHKiRet(statsobj.SetOrigin(statsobj_resources, (uchar*)"impstats"));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("utime"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_utime));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("stime"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_stime));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("maxrss"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_maxrss));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("minflt"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_minflt));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("majflt"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_majflt));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("inblock"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_inblock));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("oublock"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_oublock));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("nvcsw"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_nvcsw));
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("nivcsw"),
+ ctrType_IntCtr, CTR_FLAG_NONE, &st_ru_nivcsw));
+# ifdef OS_LINUX
+ CHKiRet(statsobj.AddCounter(statsobj_resources, UCHAR_CONSTANT("openfiles"),
+ ctrType_Int, CTR_FLAG_NONE, &st_openfiles));
+# endif
+ CHKiRet(statsobj.ConstructFinalize(statsobj_resources));
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "impstats: error activating module");
+ iRet = RS_RET_NO_RUN;
+ }
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ if(runModConf->logfd != -1)
+ close(runModConf->logfd);
+ free(runModConf->logfile);
+ free(runModConf->pszBindRuleset);
+ENDfreeCnf
+
+
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below. Note that we DELIBERATLY output
+ * final set of stats counters on termination request. Depending
+ * on configuration, they may not make it to the final destination...
+ */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ srSleep(runModConf->iStatsInterval, 0); /* seconds, micro seconds */
+ DBGPRINTF("impstats: woke up, generating messages\n");
+ if(runModConf->bBracketing)
+ submitLine("BEGIN", sizeof("BEGIN")-1);
+ generateStatsMsgs();
+ if(runModConf->bBracketing)
+ submitLine("END", sizeof("END")-1);
+ }
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ENDafterRun
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ initConfigSettings();
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("impstats version %s loading\n", VERSION);
+ initConfigSettings();
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ /* the pstatsinverval is an alias to support a previous screwed-up syntax... */
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatsinterval", 0, eCmdHdlrInt, NULL, &cs.iStatsInterval,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatinterval", 0, eCmdHdlrInt, NULL, &cs.iStatsInterval,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatfacility", 0, eCmdHdlrInt, NULL, &cs.iFacility,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatseverity", 0, eCmdHdlrInt, NULL, &cs.iSeverity,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatjson", 0, eCmdHdlrBinary, NULL, &cs.bJSON,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"pstatcee", 0, eCmdHdlrBinary, NULL, &cs.bCEE,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("impstats"), sizeof("impstats") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/plugins/imptcp/Makefile.am b/plugins/imptcp/Makefile.am
new file mode 100644
index 0000000..bfacc88
--- /dev/null
+++ b/plugins/imptcp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imptcp.la
+
+imptcp_la_SOURCES = imptcp.c
+imptcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imptcp_la_LDFLAGS = -module -avoid-version
+imptcp_la_LIBADD =
diff --git a/plugins/imptcp/Makefile.in b/plugins/imptcp/Makefile.in
new file mode 100644
index 0000000..a24d6fe
--- /dev/null
+++ b/plugins/imptcp/Makefile.in
@@ -0,0 +1,796 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imptcp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imptcp_la_DEPENDENCIES =
+am_imptcp_la_OBJECTS = imptcp_la-imptcp.lo
+imptcp_la_OBJECTS = $(am_imptcp_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 =
+imptcp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imptcp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imptcp_la-imptcp.Plo
+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 = $(imptcp_la_SOURCES)
+DIST_SOURCES = $(imptcp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imptcp.la
+imptcp_la_SOURCES = imptcp.c
+imptcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imptcp_la_LDFLAGS = -module -avoid-version
+imptcp_la_LIBADD =
+all: 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) --gnu plugins/imptcp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imptcp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imptcp.la: $(imptcp_la_OBJECTS) $(imptcp_la_DEPENDENCIES) $(EXTRA_imptcp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imptcp_la_LINK) -rpath $(pkglibdir) $(imptcp_la_OBJECTS) $(imptcp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imptcp_la-imptcp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imptcp_la-imptcp.lo: imptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imptcp_la-imptcp.lo -MD -MP -MF $(DEPDIR)/imptcp_la-imptcp.Tpo -c -o imptcp_la-imptcp.lo `test -f 'imptcp.c' || echo '$(srcdir)/'`imptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imptcp_la-imptcp.Tpo $(DEPDIR)/imptcp_la-imptcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imptcp.c' object='imptcp_la-imptcp.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) $(imptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imptcp_la-imptcp.lo `test -f 'imptcp.c' || echo '$(srcdir)/'`imptcp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imptcp_la-imptcp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imptcp_la-imptcp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c
new file mode 100644
index 0000000..351dee0
--- /dev/null
+++ b/plugins/imptcp/imptcp.c
@@ -0,0 +1,2676 @@
+/* imptcp.c
+ * This is a native implementation of plain tcp. It is intentionally
+ * duplicate work (imtcp). The intent is to gain very fast and simple
+ * native ptcp support, utilizing the best interfaces Linux (no cross-
+ * platform intended!) has to offer.
+ *
+ * Note that in this module we try out some new naming conventions,
+ * so it may look a bit "different" from the other modules. We are
+ * investigating if removing prefixes can help make code more readable.
+ *
+ * File begun on 2010-08-10 by RGerhards
+ *
+ * Copyright 2007-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#if !defined(HAVE_EPOLL_CREATE)
+# error imptcp requires OS support for epoll - can not build
+ /* imptcp gains speed by using modern Linux capabilities. As such,
+ * it can only be build on platforms supporting the epoll API.
+ */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/epoll.h>
+#include <sys/queue.h>
+#include <netinet/tcp.h>
+#include <stdint.h>
+#include <zlib.h>
+#include <sys/stat.h>
+#include <regex.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
+#include "rsyslog.h"
+#include "cfsysline.h"
+#include "prop.h"
+#include "dirty.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "srUtils.h"
+#include "datetime.h"
+#include "ruleset.h"
+#include "msg.h"
+#include "parserif.h"
+#include "statsobj.h"
+#include "ratelimit.h"
+#include "net.h" /* for permittedPeers, may be removed when this is removed */
+
+/* the define is from tcpsrv.h, we need to find a new (but easier!!!) abstraction layer some time ... */
+#define TCPSRV_NO_ADDTL_DELIMITER -1 /* specifies that no additional delimiter is to be used in TCP framing */
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imptcp")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+/* forward references */
+static void * wrkr(void *myself);
+
+/* unfortunately, on some platforms EAGAIN == EWOULDBOLOCK and so checking against
+ * both of them generates a gcc 8 warning for this reason. We do not want to disable
+ * the warning, so we need to work around this via a macro.
+ */
+#if EAGAIN == EWOULDBLOCK
+ #define CHK_EAGAIN_EWOULDBLOCK (errno == EAGAIN)
+#else
+ #define CHK_EAGAIN_EWOULDBLOCK (errno == EAGAIN | errno == EWOULDBLOCK)
+#endif /* #if EAGAIN == EWOULDBOLOCK */
+
+#define DFLT_wrkrMax 2
+#define DFLT_inlineDispatchThreshold 1
+
+#define COMPRESS_NEVER 0
+#define COMPRESS_SINGLE_MSG 1 /* old, single-message compression */
+/* all other settings are for stream-compression */
+#define COMPRESS_STREAM_ALWAYS 2
+
+/* config settings */
+typedef struct configSettings_s {
+ int bKeepAlive; /* support keep-alive packets */
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int bEmitMsgOnClose; /* emit an informational message on close by remote peer */
+ int bEmitMsgOnOpen;
+ int bSuppOctetFram; /* support octet-counted framing? */
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ int maxFrameSize;
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ uchar *lstnIP; /* which IP we should listen on? */
+ uchar *pszBindRuleset;
+ int wrkrMax; /* max number of workers (actually "helper workers") */
+ int iTCPSessMax; /* max open connections per instance */
+} configSettings_t;
+static configSettings_t cs;
+
+struct instanceConf_s {
+ int bKeepAlive; /* support keep-alive packets */
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int bEmitMsgOnClose;
+ int bEmitMsgOnOpen;
+ int bSuppOctetFram; /* support octet-counted framing? */
+ int bSPFramingFix;
+ int iAddtlFrameDelim;
+ int socketBacklog;
+ sbool multiLine;
+ uint8_t compressionMode;
+ uchar *pszBindPort; /* port to bind to */
+ uchar *pszLstnPortFileName; /* Name of the file with dynamic port used by testbench*/
+ uchar *pszBindAddr; /* IP to bind socket to */
+ uchar *pszBindPath; /* Path to bind socket to */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ int fCreateMode; /* file creation mode for open() */
+ uid_t fileUID; /* IDs for creation */
+ gid_t fileGID;
+ int maxFrameSize;
+ int bFailOnPerms; /* fail creation if chown fails? */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *dfltTZ;
+ sbool bUnlink;
+ sbool discardTruncatedMsg;
+ sbool flowControl;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ uchar *startRegex;
+ regex_t start_preg; /* compiled version of startRegex */
+ int iTCPSessMax; /* max open connections */
+ struct instanceConf_s *next;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ int wrkrMax;
+ int bProcessOnPoller;
+ int iTCPSessMax;
+ sbool configSetViaV2Method;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "threads", eCmdHdlrPositiveInt, 0 },
+ { "maxsessions", eCmdHdlrInt, 0 },
+ { "processOnPoller", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrString, 0 }, /* legacy: InputTCPServerRun */
+ { "address", eCmdHdlrString, 0 },
+ { "path", eCmdHdlrString, 0 },
+ { "unlink", eCmdHdlrBinary, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "fileowner", eCmdHdlrUID, 0 },
+ { "fileownernum", eCmdHdlrInt, 0 },
+ { "filegroup", eCmdHdlrGID, 0 },
+ { "filegroupnum", eCmdHdlrInt, 0 },
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "failonchownfailure", eCmdHdlrBinary, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "maxframesize", eCmdHdlrInt, 0 },
+ { "framing.delimiter.regex", eCmdHdlrString, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "defaulttz", eCmdHdlrString, 0 },
+ { "supportoctetcountedframing", eCmdHdlrBinary, 0 },
+ { "framingfix.cisco.asa", eCmdHdlrBinary, 0 },
+ { "maxsessions", eCmdHdlrInt, 0 },
+ { "notifyonconnectionclose", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionopen", eCmdHdlrBinary, 0 },
+ { "compression.mode", eCmdHdlrGetWord, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrInt, 0 },
+ { "keepalive.time", eCmdHdlrInt, 0 },
+ { "keepalive.interval", eCmdHdlrInt, 0 },
+ { "addtlframedelimiter", eCmdHdlrInt, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "multiline", eCmdHdlrBinary, 0 },
+ { "listenportfilename", eCmdHdlrString, 0 },
+ { "socketbacklog", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+/* data elements describing our running config */
+typedef struct ptcpsrv_s ptcpsrv_t;
+typedef struct ptcplstn_s ptcplstn_t;
+typedef struct ptcpsess_s ptcpsess_t;
+typedef struct epolld_s epolld_t;
+
+/* the ptcp server (listener) object
+ * Note that the object contains support for forming a linked list
+ * of them. It does not make sense to do this seperately.
+ */
+struct ptcpsrv_s {
+ ptcpsrv_t *pNext; /* linked list maintenance */
+ uchar *port; /* Port to listen to */
+ uchar *lstnIP; /* which IP we should listen on? */
+ uchar *path; /* Use a unix socket instead */
+ int fCreateMode; /* file creation mode for open() */
+ uid_t fileUID; /* IDs for creation */
+ gid_t fileGID;
+ int maxFrameSize;
+ int bFailOnPerms; /* fail creation if chown fails? */
+ sbool bUnixSocket;
+ int socketBacklog;
+ uchar *pszLstnPortFileName;
+ int iAddtlFrameDelim;
+ sbool multiLine;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ uint8_t compressionMode;
+ uchar *pszInputName;
+ uchar *dfltTZ;
+ prop_t *pInputName; /* InputName in (fast to process) property format */
+ ruleset_t *pRuleset;
+ ptcplstn_t *pLstn; /* root of our listeners */
+ ptcpsess_t *pSess; /* root of our sessions */
+ int iTCPSessCnt;
+ int iTCPSessMax;
+ pthread_mutex_t mutSessLst;
+ sbool bKeepAlive; /* support keep-alive packets */
+ sbool bEmitMsgOnClose;
+ sbool bEmitMsgOnOpen;
+ sbool bSuppOctetFram;
+ sbool bSPFramingFix;
+ sbool bUnlink;
+ sbool discardTruncatedMsg;
+ sbool flowControl;
+ ratelimit_t *ratelimiter;
+ instanceConf_t *inst;
+};
+
+/* the ptcp session object. Describes a single active session.
+ * includes support for doubly-linked list.
+ */
+struct ptcpsess_s {
+ ptcplstn_t *pLstn; /* our listener */
+ ptcpsess_t *prev, *next;
+ int sock;
+ epolld_t *epd;
+ sbool bzInitDone; /* did we do an init of zstrm already? */
+ z_stream zstrm; /* zip stream to use for tcp compression */
+ uint8_t compressionMode;
+ int iMsg; /* index of next char to store in msg */
+ int iCurrLine; /* 2nd char of current line in regex framing mode */
+ int bAtStrtOfFram; /* are we at the very beginning of a new frame? */
+ sbool bSuppOctetFram; /**< copy from listener, to speed up access */
+ sbool bSPFramingFix;
+ enum {
+ eAtStrtFram,
+ eInOctetCnt,
+ eInMsg,
+ eInMsgTruncation
+ } inputState; /* our current state */
+ int iOctetsRemain; /* Number of Octets remaining in message */
+ TCPFRAMINGMODE eFraming;
+ uchar *pMsg; /* message (fragment) received */
+ uchar *pMsg_save; /* message (fragment) save area in regex framing mode */
+ prop_t *peerName; /* host name we received messages from */
+ prop_t *peerIP;
+ const uchar *startRegex;/* cache for performance reasons */
+ int iAddtlFrameDelim; /* cache for performance reasons */
+};
+
+
+/* the ptcp listener object. Describes a single active listener.
+ */
+struct ptcplstn_s {
+ ptcpsrv_t *pSrv; /* our server */
+ ptcplstn_t *prev, *next;
+ int sock;
+ sbool bSuppOctetFram;
+ sbool bSPFramingFix;
+ epolld_t *epd;
+ statsobj_t *stats; /* listener stats */
+ intctr_t rcvdBytes;
+ intctr_t rcvdDecompressed;
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ STATSCOUNTER_DEF(ctrSessOpen, mutCtrSessOpen)
+ STATSCOUNTER_DEF(ctrSessOpenErr, mutCtrSessOpenErr)
+ STATSCOUNTER_DEF(ctrSessClose, mutCtrSessClose)
+ DEF_ATOMIC_HELPER_MUT64(mut_rcvdBytes)
+};
+
+
+/* The following structure controls the worker threads. Global data is
+ * needed for their access.
+ */
+static struct wrkrInfo_s {
+ pthread_t tid; /* the worker's thread ID */
+ long long unsigned numCalled; /* how often was this called */
+ int wrkrIdx; /* index for this worker - shortcut for thread name */
+} *wrkrInfo;
+static int wrkrRunning;
+
+
+/* type of object stored in epoll descriptor */
+typedef enum {
+ epolld_lstn,
+ epolld_sess
+} epolld_type_t;
+
+/* an epoll descriptor. contains all information necessary to process
+ * the result of epoll.
+ */
+struct epolld_s {
+ epolld_type_t typ;
+ void *ptr;
+ int sock;
+ struct epoll_event ev;
+};
+
+typedef struct io_req_s {
+ STAILQ_ENTRY(io_req_s) link;
+ epolld_t *epd;
+} io_req_t;
+
+typedef struct io_q_s {
+ STAILQ_HEAD(ioq_s, io_req_s) q;
+ STATSCOUNTER_DEF(ctrEnq, mutCtrEnq);
+ int ctrMaxSz; //TODO: discuss potential problems around concurrent reads and writes
+ int sz; //current q size
+ statsobj_t *stats;
+ pthread_mutex_t mut;
+ pthread_cond_t wakeup_worker;
+} io_q_t;
+
+/* global data */
+pthread_attr_t wrkrThrdAttr; /* Attribute for session threads; read only after startup */
+static ptcpsrv_t *pSrvRoot = NULL;
+static int epollfd = -1; /* (sole) descriptor for epoll */
+static int iMaxLine; /* maximum size of a single message */
+static io_q_t io_q;
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+static rsRetVal addLstn(ptcpsrv_t *pSrv, int sock, int isIPv6);
+
+
+/* function to suppress TSAN known-good case
+ * We do not use a mutex an epd, but we do always access it in
+ * pure sequence. Adding a mutex just to cover this "cosmetic"
+ * would result in uncesseary performance penalty.
+ */
+static void ATTR_NONNULL()
+imptcp_destruct_epd(ptcpsess_t *const pSess) {
+ free(pSess->epd);
+ pSess->epd = NULL;
+}
+
+/* some simple constructors/destructors */
+static void ATTR_NONNULL()
+destructSess(ptcpsess_t *const pSess)
+{
+ imptcp_destruct_epd(pSess);
+ free(pSess->pMsg_save);
+ free(pSess->pMsg);
+ prop.Destruct(&pSess->peerName);
+ prop.Destruct(&pSess->peerIP);
+ /* TODO: make these inits compile-time switch depending: */
+ pSess->pMsg = NULL;
+ free(pSess);
+}
+
+/* remove session from server */
+static void
+unlinkSess(ptcpsess_t *pSess) {
+ ptcpsrv_t *pSrv = pSess->pLstn->pSrv;
+ pthread_mutex_lock(&pSrv->mutSessLst);
+ pSrv->iTCPSessCnt--;
+ /* finally unlink session from structures */
+ if(pSess->next != NULL)
+ pSess->next->prev = pSess->prev;
+ if(pSess->prev == NULL) {
+ /* need to update root! */
+ pSrv->pSess = pSess->next;
+ } else {
+ pSess->prev->next = pSess->next;
+ }
+ pthread_mutex_unlock(&pSrv->mutSessLst);
+}
+
+static void
+destructSrv(ptcpsrv_t *pSrv)
+{
+ if(pSrv->ratelimiter != NULL)
+ ratelimitDestruct(pSrv->ratelimiter);
+ if(pSrv->pInputName != NULL)
+ prop.Destruct(&pSrv->pInputName);
+ pthread_mutex_destroy(&pSrv->mutSessLst);
+ free(pSrv->pszInputName);
+ free(pSrv->port);
+ free(pSrv->pszLstnPortFileName);
+ free(pSrv->path);
+ free(pSrv->lstnIP);
+ free(pSrv);
+}
+
+/****************************************** TCP SUPPORT FUNCTIONS ***********************************/
+/* We may later think about moving this into a helper library again. But the whole point
+ * so far was to keep everything related close togehter. -- rgerhards, 2010-08-10
+ */
+
+static rsRetVal startupUXSrv(ptcpsrv_t *pSrv) {
+ DEFiRet;
+ int sock;
+ int sockflags;
+ struct sockaddr_un local;
+
+ uchar *path = pSrv->path == NULL ? UCHAR_CONSTANT("") : pSrv->path;
+ DBGPRINTF("imptcp: creating listen unix socket at %s\n", path);
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(sock < 0) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: error creating unix socket");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, (char*) path, sizeof(local.sun_path)-1);
+ if (pSrv->bUnlink) {
+ unlink(local.sun_path);
+ }
+
+ /* We use non-blocking IO! */
+ if ((sockflags = fcntl(sock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent error check. */
+ sockflags = fcntl(sock, F_SETFL, sockflags);
+ }
+
+ if (sockflags == -1) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: error setting fcntl(O_NONBLOCK) on unix socket");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+
+ if (bind(sock, (struct sockaddr *)&local, SUN_LEN(&local)) < 0) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: error while binding unix socket");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+
+ if (listen(sock, pSrv->socketBacklog) < 0) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: unix socket listen error");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+
+ if(chown(local.sun_path, pSrv->fileUID, pSrv->fileGID) != 0) {
+ if(pSrv->bFailOnPerms) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: unix socket chown error");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+ }
+
+ if(chmod(local.sun_path, pSrv->fCreateMode) != 0) {
+ if(pSrv->bFailOnPerms) {
+ LogError(errno, RS_RET_ERR_CRE_AFUX, "imptcp: unix socket chmod error");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+ }
+
+ CHKiRet(addLstn(pSrv, sock, 0));
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (sock != -1) {
+ close(sock);
+ }
+ }
+
+ RETiRet;
+}
+
+/* Start up a server. That means all of its listeners are created.
+ * Does NOT yet accept/process any incoming data (but binds ports). Hint: this
+ * code is to be executed before dropping privileges.
+ */
+PRAGMA_DIAGNOSTIC_PUSH
+static rsRetVal
+startupSrv(ptcpsrv_t *pSrv)
+{
+ DEFiRet;
+ int error, maxs, on = 1;
+ int sock = -1;
+ int numSocks;
+ int sockflags;
+ struct addrinfo hints, *res = NULL, *r;
+ uchar *lstnIP;
+ int isIPv6 = 0;
+ int port_override = 0; /* if dyn port (0): use this for actually bound port */
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
+ } savecast;
+
+ if (pSrv->bUnixSocket) {
+ return startupUXSrv(pSrv);
+ }
+
+ lstnIP = pSrv->lstnIP == NULL ? UCHAR_CONSTANT("") : pSrv->lstnIP;
+
+ DBGPRINTF("imptcp: creating listen socket on server '%s', port %s\n", lstnIP, pSrv->port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = glbl.GetDefPFFamily(runModConf->pConf);
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo((char*)pSrv->lstnIP, (char*) pSrv->port, &hints, &res);
+ if(error) {
+ DBGPRINTF("error %d querying server '%s', port '%s'\n", error, pSrv->lstnIP, pSrv->port);
+ ABORT_FINALIZE(RS_RET_INVALID_PORT);
+ }
+
+ /* Count max number of sockets we may open */
+ for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++) {
+ /* EMPTY */;
+ }
+
+ numSocks = 0; /* num of sockets counter at start of array */
+ for(r = res; r != NULL ; r = r->ai_next) {
+ if(port_override != 0) {
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ if(r->ai_family == AF_INET6) {
+ savecast.ipv6->sin6_port = port_override;
+ } else {
+ savecast.ipv4->sin_port = port_override;
+ }
+ }
+ sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(sock < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) {
+ DBGPRINTF("error %d creating tcp listen socket", errno);
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ }
+ continue;
+ }
+
+ if(r->ai_family == AF_INET6) {
+ isIPv6 = 1;
+#ifdef IPV6_V6ONLY
+ int iOn = 1;
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&iOn, sizeof (iOn)) < 0) {
+ close(sock);
+ sock = -1;
+ continue;
+ }
+#endif
+ } else {
+ isIPv6 = 0;
+ }
+
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ DBGPRINTF("error %d setting tcp socket option\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* We use non-blocking IO! */
+ if((sockflags = fcntl(sock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(sock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ DBGPRINTF("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#if !defined (_AIX)
+#ifndef BSD
+ if(net.should_use_so_bsdcompat()) {
+ if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ LogError(errno, NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+#endif
+#endif
+ if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0)
+#ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+#endif
+ ) {
+ /* TODO: check if *we* bound the socket - else we *have* an error! */
+ LogError(errno, NO_ERRCODE, "Error while binding tcp socket");
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* if we bind to dynamic port (port 0 given), we will do so consistently. Thus
+ * once we got a dynamic port, we will keep it and use it for other protocols
+ * as well. As of my understanding, this should always work as the OS does not
+ * pick a port that is used by some protocol (well, at least this looks very
+ * unlikely...). If our asusmption is wrong, we should iterate until we find a
+ * combination that works - it is very unusual to have the same service listen
+ * on differnt ports on IPv4 and IPv6.
+ */
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ const int currport = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port;
+ if(currport == 0) {
+ socklen_t socklen_r = r->ai_addrlen;
+ if(getsockname(sock, r->ai_addr, &socklen_r) == -1) {
+ LogError(errno, NO_ERRCODE, "nsd_ptcp: ListenPortFileName: getsockname:"
+ "error while trying to get socket");
+ }
+ r->ai_addrlen = socklen_r;
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ port_override = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port;
+ if(pSrv->pszLstnPortFileName != NULL) {
+ FILE *fp;
+ if((fp = fopen((const char*)pSrv->pszLstnPortFileName, "w+")) == NULL) {
+ LogError(errno, RS_RET_IO_ERROR, "imptcp: ListenPortFileName: "
+ "error while trying to open file");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ if(isIPv6) {
+ fprintf(fp, "%d", ntohs(savecast.ipv6->sin6_port));
+ } else {
+ fprintf(fp, "%d", ntohs(savecast.ipv4->sin_port));
+ }
+ fclose(fp);
+ }
+ }
+
+ if(listen(sock, pSrv->socketBacklog) < 0) {
+ LogError(errno, NO_ERRCODE, "imptcp error listening on port");
+ DBGPRINTF("tcp listen error %d, suspending\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* if we reach this point, we were able to obtain a valid socket, so we can
+ * create our listener object. -- rgerhards, 2010-08-10
+ */
+ CHKiRet(addLstn(pSrv, sock, isIPv6));
+ ++numSocks;
+ }
+
+ if(numSocks != maxs) {
+ DBGPRINTF("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", numSocks, maxs);
+ }
+
+ if(numSocks == 0) {
+ DBGPRINTF("No TCP listen sockets could successfully be initialized");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
+ }
+
+finalize_it:
+ if(res != NULL) {
+ freeaddrinfo(res);
+ }
+
+ if(iRet != RS_RET_OK) {
+ if(sock != -1) {
+ close(sock);
+ }
+ }
+
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+/* Set pRemHost based on the address provided. This is to be called upon accept()ing
+ * a connection request. It must be provided by the socket we received the
+ * message on as well as a NI_MAXHOST size large character buffer for the FQDN.
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. If we detect a malicious
+ * hostname, we return RS_RET_MALICIOUS_HNAME and let the caller decide
+ * on how to deal with that.
+ * rgerhards, 2008-03-31
+ */
+static rsRetVal
+getPeerNames(prop_t **peerName, prop_t **peerIP, struct sockaddr *pAddr, sbool bUXServer)
+{
+ int error;
+ uchar szIP[NI_MAXHOST+1] = "";
+ uchar szHname[NI_MAXHOST+1] = "";
+ struct addrinfo hints, *res;
+ sbool bMaliciousHName = 0;
+
+ DEFiRet;
+
+ *peerName = NULL;
+ *peerIP = NULL;
+
+ if (bUXServer) {
+ strncpy((char *) szHname, (char *) glbl.GetLocalHostName(), NI_MAXHOST);
+ strncpy((char *) szIP, (char *) glbl.GetLocalHostIP(), NI_MAXHOST);
+ szHname[NI_MAXHOST] = '\0';
+ szIP[NI_MAXHOST] = '\0';
+ } else {
+ error = getnameinfo(pAddr, SALEN(pAddr), (char *) szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST);
+ if (error) {
+ DBGPRINTF("Malformed from address %s\n", gai_strerror(error));
+ strcpy((char *) szHname, "???");
+ strcpy((char *) szIP, "???");
+ ABORT_FINALIZE(RS_RET_INVALID_HNAME);
+ }
+
+ if (!glbl.GetDisableDNS(runConf)) {
+ error = getnameinfo(pAddr, SALEN(pAddr), (char *) szHname, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+ if (error == 0) {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_STREAM;
+ /* we now do a lookup once again. This one should fail,
+ * because we should not have obtained a non-numeric address. If
+ * we got a numeric one, someone messed with DNS!
+ */
+ if (getaddrinfo((char *) szHname, NULL, &hints, &res) == 0) {
+ freeaddrinfo(res);
+ /* OK, we know we have evil, so let's indicate this to our caller */
+ snprintf((char *) szHname, sizeof(szHname), "[MALICIOUS:IP=%s]", szIP);
+ DBGPRINTF("Malicious PTR record, IP = \"%s\" HOST = \"%s\"", szIP, szHname);
+ bMaliciousHName = 1;
+ }
+ } else {
+ strcpy((char *) szHname, (char *) szIP);
+ }
+ } else {
+ strcpy((char *) szHname, (char *) szIP);
+ }
+ }
+
+ /* We now have the names, so now let's allocate memory and store them permanently. */
+ CHKiRet(prop.Construct(peerName));
+ CHKiRet(prop.SetString(*peerName, szHname, ustrlen(szHname)));
+ CHKiRet(prop.ConstructFinalize(*peerName));
+ CHKiRet(prop.Construct(peerIP));
+ CHKiRet(prop.SetString(*peerIP, szIP, ustrlen(szIP)));
+ CHKiRet(prop.ConstructFinalize(*peerIP));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(*peerName != NULL)
+ prop.Destruct(peerName);
+ if(*peerIP != NULL)
+ prop.Destruct(peerIP);
+ }
+ if(bMaliciousHName)
+ iRet = RS_RET_MALICIOUS_HNAME;
+ RETiRet;
+}
+
+
+/* Enable KEEPALIVE handling on the socket. */
+static rsRetVal
+EnableKeepAlive(ptcplstn_t *pLstn, int sock)
+{
+ int ret;
+ int optval;
+ socklen_t optlen;
+ DEFiRet;
+
+ optval = 1;
+ optlen = sizeof(optval);
+ ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
+ if(ret < 0) {
+ dbgprintf("EnableKeepAlive socket call returns error %d\n", ret);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+# if defined(TCP_KEEPCNT)
+ if(pLstn->pSrv->iKeepAliveProbes > 0) {
+ optval = pLstn->pSrv->iKeepAliveProbes;
+ optlen = sizeof(optval);
+ ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(ret, NO_ERRCODE, "imptcp cannot set keepalive probes - ignored");
+ }
+
+# if defined(TCP_KEEPCNT)
+ if(pLstn->pSrv->iKeepAliveTime > 0) {
+ optval = pLstn->pSrv->iKeepAliveTime;
+ optlen = sizeof(optval);
+ ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(ret, NO_ERRCODE, "imptcp cannot set keepalive time - ignored");
+ }
+
+# if defined(TCP_KEEPCNT)
+ if(pLstn->pSrv->iKeepAliveIntvl > 0) {
+ optval = pLstn->pSrv->iKeepAliveIntvl;
+ optlen = sizeof(optval);
+ ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(errno, NO_ERRCODE, "imptcp cannot set keepalive intvl - ignored");
+ }
+
+ dbgprintf("KEEPALIVE enabled for socket %d\n", sock);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* accept an incoming connection request
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal ATTR_NONNULL()
+AcceptConnReq(ptcplstn_t *const pLstn, int *const newSock, prop_t **peerName, prop_t **peerIP)
+{
+ int sockflags;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ int iNewSock = -1;
+
+ DEFiRet;
+
+ *peerName = NULL; /* ensure we know if we don't have one! */
+ iNewSock = accept(pLstn->sock, (struct sockaddr*) &addr, &addrlen);
+ if(iNewSock < 0) {
+ if(CHK_EAGAIN_EWOULDBLOCK || errno == EMFILE)
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ LogError(errno, RS_RET_ACCEPT_ERR, "error accepting connection "
+ "on listen socket %d", pLstn->sock);
+ ABORT_FINALIZE(RS_RET_ACCEPT_ERR);
+ }
+ if(addrlen == 0) {
+ LogError(errno, RS_RET_ACCEPT_ERR, "AcceptConnReq could not obtain "
+ "remote peer identification on listen socket %d", pLstn->sock);
+ }
+
+ if(pLstn->pSrv->bKeepAlive)
+ EnableKeepAlive(pLstn, iNewSock);/* we ignore errors, best to do! */
+
+ CHKiRet(getPeerNames(peerName, peerIP, (struct sockaddr *) &addr, pLstn->pSrv->bUnixSocket));
+
+ /* set the new socket to non-blocking IO */
+ if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(iNewSock, F_SETFL, sockflags);
+ }
+
+ if(sockflags == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "error setting fcntl(O_NONBLOCK) on "
+ "tcp socket %d", iNewSock);
+ prop.Destruct(peerName);
+ prop.Destruct(peerIP);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ if(pLstn->pSrv->bEmitMsgOnOpen) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
+ "imptcp: connection established with host: %s",
+ propGetSzStr(*peerName));
+ }
+
+ STATSCOUNTER_INC(pLstn->ctrSessOpen, pLstn->mutCtrSessOpen);
+ *newSock = iNewSock;
+
+finalize_it:
+ DBGPRINTF("iRet: %d\n", iRet);
+ if(iRet != RS_RET_OK) {
+ if(iRet != RS_RET_NO_MORE_DATA && pLstn->pSrv->bEmitMsgOnOpen) {
+ LogError(0, NO_ERRCODE, "imptcp: connection could not be "
+ "established with host: %s",
+ *peerName == NULL ? "(could not query)"
+ : (const char*)propGetSzStr(*peerName));
+ }
+ STATSCOUNTER_INC(pLstn->ctrSessOpenErr, pLstn->mutCtrSessOpenErr);
+ /* the close may be redundant, but that doesn't hurt... */
+ if(iNewSock != -1)
+ close(iNewSock);
+ }
+
+ RETiRet;
+}
+
+
+/* This is a helper for submitting the message to the rsyslog core.
+ * It does some common processing, including resetting the various
+ * state variables to a "processed" state.
+ * Note that this function is also called if we had a buffer overflow
+ * due to a too-long message. So far, there is no indication this
+ * happened and it may be worth thinking about different handling
+ * of this case (what obviously would require a change to this
+ * function or some related code).
+ * rgerhards, 2009-04-23
+ * EXTRACT from tcps_sess.c
+ */
+static rsRetVal
+doSubmitMsg(ptcpsess_t *pThis, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub)
+{
+ smsg_t *pMsg;
+ ptcpsrv_t *pSrv;
+ DEFiRet;
+
+ if(pThis->iMsg == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+ pSrv = pThis->pLstn->pSrv;
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg);
+ MsgSetInputName(pMsg, pSrv->pInputName);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ if(pSrv->dfltTZ != NULL)
+ MsgSetDfltTZ(pMsg, (char*) pSrv->dfltTZ);
+ MsgSetFlowControlType(pMsg, pSrv->flowControl
+ ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ MsgSetRcvFrom(pMsg, pThis->peerName);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pThis->peerIP));
+ MsgSetRuleset(pMsg, pSrv->pRuleset);
+ STATSCOUNTER_INC(pThis->pLstn->ctrSubmit, pThis->pLstn->mutCtrSubmit);
+
+ ratelimitAddMsg(pSrv->ratelimiter, pMultiSub, pMsg);
+
+finalize_it:
+ /* reset status variables */
+ pThis->bAtStrtOfFram = 1;
+ pThis->iMsg = 0;
+
+ RETiRet;
+}
+
+
+/* process the data received, special case if the framing is specified via
+ * a regex. For more info see processDataRcvd().
+ */
+static rsRetVal ATTR_NONNULL()
+processDataRcvd_regexFraming(ptcpsess_t *const __restrict__ pThis,
+ char **const buff,
+ struct syslogTime *const stTime,
+ const time_t ttGenTime,
+ multi_submit_t *const pMultiSub,
+ unsigned *const __restrict__ pnMsgs)
+{
+ DEFiRet;
+ const instanceConf_t *const inst = pThis->pLstn->pSrv->inst;
+ assert(inst->startRegex != NULL);
+ const char c = **buff;
+
+ pThis->pMsg[pThis->iMsg++] = c;
+ pThis->pMsg[pThis->iMsg] = '\0';
+
+ if(pThis->iMsg == 2*iMaxLine) {
+ LogError(0, RS_RET_OVERSIZE_MSG, "imptcp: more then double max message size (%d) "
+ "received without finding frame terminator via regex - assuming "
+ "end of frame now.", pThis->iMsg+1);
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+ pThis->iMsg = 0;
+ pThis->iCurrLine = 1;
+ }
+
+
+ if(c == '\n') {
+ pThis->iCurrLine = pThis->iMsg;
+ } else {
+ const int isMatch = !regexec(&inst->start_preg, (char*)pThis->pMsg+pThis->iCurrLine, 0, NULL, 0);
+ if(isMatch) {
+ DBGPRINTF("regex match (%d), framing line: %s\n", pThis->iCurrLine, pThis->pMsg);
+ strcpy((char*)pThis->pMsg_save, (char*) pThis->pMsg+pThis->iCurrLine);
+ pThis->iMsg = pThis->iCurrLine - 1;
+
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+
+ strcpy((char*)pThis->pMsg, (char*)pThis->pMsg_save);
+ pThis->iMsg = ustrlen(pThis->pMsg_save);
+ pThis->iCurrLine = 1;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* process the data received. As TCP is stream based, we need to process the
+ * data inside a state machine. The actual data received is passed in byte-by-byte
+ * from DataRcvd, and this function here compiles messages from them and submits
+ * the end result to the queue. Introducing this function fixes a long-term bug ;)
+ * rgerhards, 2008-03-14
+ * EXTRACT from tcps_sess.c
+ */
+static rsRetVal ATTR_NONNULL(1, 2)
+processDataRcvd(ptcpsess_t *const __restrict__ pThis,
+ char **buff,
+ const int buffLen,
+ struct syslogTime *stTime,
+ const time_t ttGenTime,
+ multi_submit_t *pMultiSub,
+ unsigned *const __restrict__ pnMsgs)
+{
+ DEFiRet;
+ const char c = **buff;
+ int octetsToCopy, octetsToDiscard;
+
+ if(pThis->startRegex != NULL) {
+ processDataRcvd_regexFraming(pThis, buff, stTime, ttGenTime, pMultiSub, pnMsgs);
+ FINALIZE;
+ }
+
+ if(pThis->inputState == eAtStrtFram) {
+ if(pThis->bSuppOctetFram && isdigit((int) c)) {
+ pThis->inputState = eInOctetCnt;
+ pThis->iOctetsRemain = 0;
+ pThis->eFraming = TCP_FRAMING_OCTET_COUNTING;
+ } else if(pThis->bSPFramingFix && c == ' ') {
+ /* Cisco very occasionally sends a SP after a LF, which
+ * thrashes framing if not taken special care of. Here,
+ * we permit space *in front of the next frame* and
+ * ignore it.
+ */
+ FINALIZE;
+ } else {
+ pThis->inputState = eInMsg;
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ }
+ }
+
+ if(pThis->inputState == eInOctetCnt) {
+ uchar *propPeerName = NULL;
+ int lenPeerName = 0;
+ uchar *propPeerIP = NULL;
+ int lenPeerIP = 0;
+ if(isdigit(c)) {
+ if(pThis->iOctetsRemain <= 200000000) {
+ pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0';
+ }
+ if(pThis->iMsg < iMaxLine) {
+ *(pThis->pMsg + pThis->iMsg++) = c;
+ }
+ } else { /* done with the octet count, so this must be the SP terminator */
+ DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain);
+ prop.GetString(pThis->peerName, &propPeerName, &lenPeerName);
+ prop.GetString(pThis->peerIP, &propPeerIP, &lenPeerIP);
+ if(c != ' ') {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message "
+ "from peer: (hostname) %s, (ip) %s: delimiter is not "
+ "SP but has ASCII value %d.", propPeerName, propPeerIP, c);
+ }
+ if(pThis->iOctetsRemain < 1) {
+ /* TODO: handle the case where the octet count is 0! */
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message"
+ " from peer: (hostname) %s, (ip) %s: invalid octet count %d.",
+ propPeerName, propPeerIP, pThis->iOctetsRemain);
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ } else if(pThis->iOctetsRemain > iMaxLine) {
+ /* while we can not do anything against it, we can at least log an indication
+ * that something went wrong) -- rgerhards, 2008-03-14
+ */
+ DBGPRINTF("truncating message with %d octets - max msg size is %d\n",
+ pThis->iOctetsRemain, iMaxLine);
+ LogError(0, NO_ERRCODE, "received oversize message from peer: "
+ "(hostname) %s, (ip) %s: size is %d bytes, max msg "
+ "size is %d, truncating...", propPeerName, propPeerIP,
+ pThis->iOctetsRemain, iMaxLine);
+ }
+ if(pThis->iOctetsRemain > pThis->pLstn->pSrv->maxFrameSize) {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message "
+ "from peer: (hostname) %s, (ip) %s: frame too large: %d, "
+ "change to octet stuffing", propPeerName, propPeerIP,
+ pThis->iOctetsRemain);
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ } else {
+ pThis->iMsg = 0;
+ }
+ pThis->inputState = eInMsg;
+ }
+ } else if(pThis->inputState == eInMsgTruncation) {
+ if ((c == '\n')
+ || ((pThis->iAddtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
+ && (c == pThis->iAddtlFrameDelim))) {
+ pThis->inputState = eAtStrtFram;
+ }
+ } else {
+ assert(pThis->inputState == eInMsg);
+ if (pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) {
+ int iMsg = pThis->iMsg; /* cache value for faster access */
+ if(iMsg >= iMaxLine) {
+ /* emergency, we now need to flush, no matter if we are at end of message or not... */
+ int i = 1;
+ char currBuffChar;
+ while(i < buffLen && ((currBuffChar = (*buff)[i]) != '\n'
+ && (pThis->iAddtlFrameDelim == TCPSRV_NO_ADDTL_DELIMITER
+ || currBuffChar != pThis->iAddtlFrameDelim))) {
+ i++;
+ }
+ LogError(0, NO_ERRCODE, "imptcp %s: message received is at least %d byte larger than "
+ "max msg size; message will be split starting at: \"%.*s\"\n",
+ pThis->pLstn->pSrv->pszInputName, i, (i < 32) ? i : 32, *buff);
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ iMsg = 0;
+ ++(*pnMsgs);
+ if(pThis->pLstn->pSrv->discardTruncatedMsg == 1) {
+ pThis->inputState = eInMsgTruncation;
+ }
+ /* we might think if it is better to ignore the rest of the
+ * message than to treat it as a new one. Maybe this is a good
+ * candidate for a configuration parameter...
+ * rgerhards, 2006-12-04
+ */
+ }
+ if ((c == '\n')
+ || ((pThis->iAddtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
+ && (c == pThis->iAddtlFrameDelim))
+ ) { /* record delimiter? */
+ if(pThis->pLstn->pSrv->multiLine) {
+ if((buffLen == 1) || ((*buff)[1] == '<')) {
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ iMsg = 0; /* Reset cached value! */
+ ++(*pnMsgs);
+ pThis->inputState = eAtStrtFram;
+ } else {
+ if(iMsg < iMaxLine) {
+ pThis->pMsg[iMsg++] = c;
+ }
+ }
+ } else {
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ iMsg = 0; /* Reset cached value! */
+ ++(*pnMsgs);
+ pThis->inputState = eAtStrtFram;
+ }
+ } else {
+ /* IMPORTANT: here we copy the actual frame content to the message - for BOTH
+ * framing modes! If we have a message that is larger than the max msg size,
+ * we truncate it. This is the best we can do in light of what the engine supports.
+ * -- rgerhards, 2008-03-14
+ */
+ if(likely(iMsg < iMaxLine)) {
+ pThis->pMsg[iMsg++] = c;
+ }
+ }
+ pThis->iMsg = iMsg; /* update "real value" with cached one */
+ } else {
+ assert(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING);
+ octetsToCopy = pThis->iOctetsRemain;
+ octetsToDiscard = 0;
+ if (buffLen < octetsToCopy) {
+ octetsToCopy = buffLen;
+ }
+ if (octetsToCopy + pThis->iMsg > iMaxLine) {
+ octetsToDiscard = octetsToCopy - (iMaxLine - pThis->iMsg);
+ octetsToCopy = iMaxLine - pThis->iMsg;
+ }
+
+ memcpy(pThis->pMsg + pThis->iMsg, *buff, octetsToCopy);
+ pThis->iMsg += octetsToCopy;
+ pThis->iOctetsRemain -= (octetsToCopy + octetsToDiscard);
+ *buff += (octetsToCopy + octetsToDiscard - 1);
+ if (pThis->iOctetsRemain == 0) {
+ /* we have end of frame! */
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+ pThis->inputState = eAtStrtFram;
+ }
+ }
+
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Processes the data received via a TCP session. If there
+ * is no other way to handle it, data is discarded.
+ * Input parameter data is the data received, iLen is its
+ * len as returned from recv(). iLen must be 1 or more (that
+ * is errors must be handled by caller!). iTCPSess must be
+ * the index of the TCP session that received the data.
+ * rgerhards 2005-07-04
+ * And another change while generalizing. We now return either
+ * RS_RET_OK, which means the session should be kept open
+ * or anything else, which means it must be closed.
+ * rgerhards, 2008-03-01
+ * As a performance optimization, we pick up the timestamp here. Acutally,
+ * this *is* the *correct* reception step for all the data we received, because
+ * we have just received a bunch of data! -- rgerhards, 2009-06-16
+ * EXTRACT from tcps_sess.c
+ */
+static rsRetVal ATTR_NONNULL(1, 2)
+DataRcvdUncompressed(ptcpsess_t *pThis, char *pData, const size_t iLen, struct syslogTime *stTime, time_t ttGenTime)
+{
+ multi_submit_t multiSub;
+ smsg_t *pMsgs[CONF_NUM_MULTISUB];
+ char *pEnd;
+ unsigned nMsgs = 0;
+ DEFiRet;
+
+ assert(iLen > 0);
+
+ if(ttGenTime == 0)
+ datetime.getCurrTime(stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ multiSub.ppMsgs = pMsgs;
+ multiSub.maxElem = CONF_NUM_MULTISUB;
+ multiSub.nElem = 0;
+
+ /* We now copy the message to the session buffer. */
+ pEnd = pData + iLen; /* this is one off, which is intensional */
+
+ while(pData < pEnd) {
+ CHKiRet(processDataRcvd(pThis, &pData, pEnd - pData, stTime, ttGenTime, &multiSub, &nMsgs));
+ pData++;
+ }
+
+ iRet = multiSubmitFlush(&multiSub);
+
+ if(runConf->globals.senderKeepTrack)
+ statsRecordSender(propGetSzStr(pThis->peerName), nMsgs, ttGenTime);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+DataRcvdCompressed(ptcpsess_t *pThis, char *buf, size_t len)
+{
+ struct syslogTime stTime;
+ time_t ttGenTime;
+ int zRet; /* zlib return state */
+ unsigned outavail;
+ uchar zipBuf[64*1024]; // TODO: alloc on heap, and much larger (512KiB? batch size!)
+ DEFiRet;
+ // TODO: can we do stats counters? Even if they are not 100% correct under all cases,
+ // by simply updating the input and output sizes?
+ uint64_t outtotal;
+
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ outtotal = 0;
+
+ if(!pThis->bzInitDone) {
+ /* allocate deflate state */
+ pThis->zstrm.zalloc = Z_NULL;
+ pThis->zstrm.zfree = Z_NULL;
+ pThis->zstrm.opaque = Z_NULL;
+ zRet = inflateInit(&pThis->zstrm);
+ if(zRet != Z_OK) {
+ DBGPRINTF("imptcp: error %d returned from zlib/inflateInit()\n", zRet);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ pThis->bzInitDone = RSTRUE;
+ }
+
+ pThis->zstrm.next_in = (Bytef*) buf;
+ pThis->zstrm.avail_in = len;
+ /* run inflate() on buffer until everything has been uncompressed */
+ do {
+ DBGPRINTF("imptcp: in inflate() loop, avail_in %d, total_in %ld\n",
+ pThis->zstrm.avail_in, pThis->zstrm.total_in);
+ pThis->zstrm.avail_out = sizeof(zipBuf);
+ pThis->zstrm.next_out = zipBuf;
+ zRet = inflate(&pThis->zstrm, Z_SYNC_FLUSH); /* no bad return value */
+ //zRet = inflate(&pThis->zstrm, Z_NO_FLUSH); /* no bad return value */
+ DBGPRINTF("after inflate, ret %d, avail_out %d\n", zRet, pThis->zstrm.avail_out);
+ outavail = sizeof(zipBuf) - pThis->zstrm.avail_out;
+ if(outavail != 0) {
+ outtotal += outavail;
+ pThis->pLstn->rcvdDecompressed += outavail;
+ CHKiRet(DataRcvdUncompressed(pThis, (char*)zipBuf, outavail, &stTime, ttGenTime));
+ }
+ } while (pThis->zstrm.avail_out == 0);
+
+ dbgprintf("end of DataRcvCompress, sizes: in %lld, out %llu\n", (long long) len,
+ (long long unsigned) outtotal);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+DataRcvd(ptcpsess_t *pThis, char *pData, size_t iLen)
+{
+ struct syslogTime stTime;
+ DEFiRet;
+ ATOMIC_ADD_uint64(&pThis->pLstn->rcvdBytes, &pThis->pLstn->mut_rcvdBytes, iLen);
+ if(pThis->compressionMode >= COMPRESS_STREAM_ALWAYS)
+ iRet = DataRcvdCompressed(pThis, pData, iLen);
+ else
+ iRet = DataRcvdUncompressed(pThis, pData, iLen, &stTime, 0);
+ RETiRet;
+}
+
+
+/****************************************** --END-- TCP SUPPORT FUNCTIONS ***********************************/
+
+
+static void
+initConfigSettings(void)
+{
+ cs.bEmitMsgOnClose = 0;
+ cs.bEmitMsgOnOpen = 0;
+ cs.wrkrMax = DFLT_wrkrMax;
+ cs.bSuppOctetFram = 1;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ cs.maxFrameSize = 200000;
+ cs.pszInputName = NULL;
+ cs.pszBindRuleset = NULL;
+ cs.pszInputName = NULL;
+ cs.lstnIP = NULL;
+}
+
+
+/* add socket to the epoll set
+ */
+static rsRetVal
+addEPollSock(epolld_type_t typ, void *ptr, int sock, epolld_t **pEpd)
+{
+ DEFiRet;
+ epolld_t *epd = NULL;
+
+ CHKmalloc(epd = calloc(1, sizeof(epolld_t)));
+ epd->typ = typ;
+ epd->ptr = ptr;
+ epd->sock = sock;
+ *pEpd = epd;
+ epd->ev.events = EPOLLIN|EPOLLONESHOT;
+ epd->ev.data.ptr = (void*) epd;
+
+ if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &(epd->ev)) != 0) {
+ LogError(errno, RS_RET_EPOLL_CTL_FAILED, "os error during epoll ADD");
+ ABORT_FINALIZE(RS_RET_EPOLL_CTL_FAILED);
+ }
+
+ DBGPRINTF("imptcp: added socket %d to epoll[%d] set\n", sock, epollfd);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if (epd != NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "error: could not initialize mutex for ptcp "
+ "connection for socket: %d", sock);
+ }
+ free(epd);
+ }
+ RETiRet;
+}
+
+
+/* add a listener to the server
+ */
+static rsRetVal
+addLstn(ptcpsrv_t *pSrv, int sock, int isIPv6)
+{
+ DEFiRet;
+ ptcplstn_t *pLstn = NULL;
+ uchar statname[64];
+
+ CHKmalloc(pLstn = calloc(1, sizeof(ptcplstn_t)));
+ pLstn->pSrv = pSrv;
+ pLstn->bSuppOctetFram = pSrv->bSuppOctetFram;
+ pLstn->bSPFramingFix = pSrv->bSPFramingFix;
+ pLstn->sock = sock;
+ /* support statistics gathering */
+ uchar *inputname;
+ if(pSrv->pszInputName == NULL) {
+ inputname = (uchar*)"imptcp";
+ } else {
+ inputname = pSrv->pszInputName;
+ }
+ CHKiRet(statsobj.Construct(&(pLstn->stats)));
+ snprintf((char*)statname, sizeof(statname), "%s(%s/%s/%s)", inputname,
+ (pSrv->lstnIP == NULL) ? "*" : (char*)pSrv->lstnIP, pSrv->port,
+ isIPv6 ? "IPv6" : "IPv4");
+ statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(statsobj.SetName(pLstn->stats, statname));
+ CHKiRet(statsobj.SetOrigin(pLstn->stats, (uchar*)"imptcp"));
+ STATSCOUNTER_INIT(pLstn->ctrSubmit, pLstn->mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->ctrSubmit)));
+ STATSCOUNTER_INIT(pLstn->ctrSessOpen, pLstn->mutCtrSessOpen);
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("sessions.opened"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->ctrSessOpen)));
+ STATSCOUNTER_INIT(pLstn->ctrSessOpenErr, pLstn->mutCtrSessOpenErr);
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("sessions.openfailed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->ctrSessOpenErr)));
+ STATSCOUNTER_INIT(pLstn->ctrSessClose, pLstn->mutCtrSessClose);
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("sessions.closed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->ctrSessClose)));
+ /* the following counters are not protected by mutexes; we accept
+ * that they may not be 100% correct */
+ pLstn->rcvdBytes = 0,
+ pLstn->rcvdDecompressed = 0;
+ INIT_ATOMIC_HELPER_MUT64(pLstn->mut_rcvdBytes);
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("bytes.received"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->rcvdBytes)));
+ CHKiRet(statsobj.AddCounter(pLstn->stats, UCHAR_CONSTANT("bytes.decompressed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pLstn->rcvdDecompressed)));
+ CHKiRet(statsobj.ConstructFinalize(pLstn->stats));
+
+ CHKiRet(addEPollSock(epolld_lstn, pLstn, sock, &pLstn->epd));
+
+ /* add to start of server's listener list */
+ pLstn->prev = NULL;
+ pLstn->next = pSrv->pLstn;
+ if(pSrv->pLstn != NULL)
+ pSrv->pLstn->prev = pLstn;
+ pSrv->pLstn = pLstn;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pLstn != NULL) {
+ if(pLstn->stats != NULL)
+ statsobj.Destruct(&(pLstn->stats));
+ free(pLstn);
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* add a session to the server
+ */
+static rsRetVal
+addSess(ptcplstn_t *pLstn, int sock, prop_t *peerName, prop_t *peerIP)
+{
+ DEFiRet;
+ ptcpsess_t *pSess = NULL;
+ ptcpsrv_t *pSrv = pLstn->pSrv;
+ int pmsg_size_factor;
+
+ CHKmalloc(pSess = malloc(sizeof(ptcpsess_t)));
+ pSess->next = NULL;
+ if(pLstn->pSrv->inst->startRegex == NULL) {
+ pmsg_size_factor = 1;
+ pSess->pMsg_save = NULL;
+ } else {
+ pmsg_size_factor = 2;
+ pSess->pMsg = NULL;
+ CHKmalloc(pSess->pMsg_save = malloc(1 + iMaxLine * pmsg_size_factor));
+ }
+ CHKmalloc(pSess->pMsg = malloc(1 + iMaxLine * pmsg_size_factor));
+ pSess->pLstn = pLstn;
+ pSess->sock = sock;
+ pSess->bSuppOctetFram = pLstn->bSuppOctetFram;
+ pSess->bSPFramingFix = pLstn->bSPFramingFix;
+ pSess->inputState = eAtStrtFram;
+ pSess->iMsg = 0;
+ pSess->iCurrLine = 1;
+ pSess->bzInitDone = 0;
+ pSess->bAtStrtOfFram = 1;
+ pSess->peerName = peerName;
+ pSess->peerIP = peerIP;
+ pSess->compressionMode = pLstn->pSrv->compressionMode;
+ pSess->startRegex = pLstn->pSrv->inst->startRegex;
+ pSess->iAddtlFrameDelim = pLstn->pSrv->iAddtlFrameDelim;
+
+ /* add to start of server's listener list */
+ pSess->prev = NULL;
+
+ pthread_mutex_lock(&pSrv->mutSessLst);
+ int iTCPSessMax = pSrv->inst->iTCPSessMax;
+ if (iTCPSessMax > 0 && pSrv->iTCPSessCnt >= iTCPSessMax) {
+ pthread_mutex_unlock(&pSrv->mutSessLst);
+ LogError(0, RS_RET_MAX_SESS_REACHED,
+ "too many tcp sessions - dropping incoming request");
+ ABORT_FINALIZE(RS_RET_MAX_SESS_REACHED);
+ }
+
+ pSrv->iTCPSessCnt++;
+ pSess->next = pSrv->pSess;
+ if(pSrv->pSess != NULL)
+ pSrv->pSess->prev = pSess;
+ pSrv->pSess = pSess;
+ pthread_mutex_unlock(&pSrv->mutSessLst);
+
+ CHKiRet(addEPollSock(epolld_sess, pSess, sock, &pSess->epd));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pSess != NULL) {
+ if (pSess->next != NULL) {
+ unlinkSess(pSess);
+ }
+ free(pSess->pMsg_save);
+ free(pSess->pMsg);
+ free(pSess);
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* finish zlib buffer, to be called before closing the session.
+ */
+static rsRetVal
+doZipFinish(ptcpsess_t *pSess)
+{
+ int zRet; /* zlib return state */
+ DEFiRet;
+ unsigned outavail;
+ struct syslogTime stTime;
+ uchar zipBuf[32*1024]; // TODO: use "global" one from pSess
+
+ if(!pSess->bzInitDone)
+ goto done;
+
+ pSess->zstrm.avail_in = 0;
+ /* run inflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("doZipFinish: in inflate() loop, avail_in %d, total_in %ld\n", pSess->zstrm.avail_in,
+ pSess->zstrm.total_in);
+ pSess->zstrm.avail_out = sizeof(zipBuf);
+ pSess->zstrm.next_out = zipBuf;
+ zRet = inflate(&pSess->zstrm, Z_FINISH); /* no bad return value */
+ DBGPRINTF("after inflate, ret %d, avail_out %d\n", zRet, pSess->zstrm.avail_out);
+ outavail = sizeof(zipBuf) - pSess->zstrm.avail_out;
+ if(outavail != 0) {
+ pSess->pLstn->rcvdDecompressed += outavail;
+ CHKiRet(DataRcvdUncompressed(pSess, (char*)zipBuf, outavail, &stTime, 0));
+ // TODO: query time!
+ }
+ } while (pSess->zstrm.avail_out == 0);
+
+finalize_it:
+ zRet = inflateEnd(&pSess->zstrm);
+ if(zRet != Z_OK) {
+ DBGPRINTF("imptcp: error %d returned from zlib/inflateEnd()\n", zRet);
+ }
+
+ pSess->bzInitDone = 0;
+done: RETiRet;
+}
+
+/* close/remove a session
+ * NOTE: we do not need to remove the socket from the epoll set, as according
+ * to the epoll man page it is automatically removed on close (Q6). The only
+ * exception is duplicated file handles, which we do not create.
+ */
+static rsRetVal
+closeSess(ptcpsess_t *pSess)
+{
+ DEFiRet;
+
+ if(pSess->compressionMode >= COMPRESS_STREAM_ALWAYS)
+ doZipFinish(pSess);
+
+ const int sock = pSess->sock;
+ close(sock);
+
+ unlinkSess(pSess);
+
+ if(pSess->pLstn->pSrv->bEmitMsgOnClose) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "imptcp: session on socket %d closed "
+ "with iRet %d.\n", sock, iRet);
+ }
+ STATSCOUNTER_INC(pSess->pLstn->ctrSessClose, pSess->pLstn->mutCtrSessClose);
+
+ /* unlinked, now remove structure */
+ destructSess(pSess);
+
+ DBGPRINTF("imptcp: session on socket %d closed with iRet %d.\n", sock, iRet);
+ RETiRet;
+}
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+
+ inst->pszBindPort = NULL;
+ inst->pszBindAddr = NULL;
+ inst->pszBindPath = NULL;
+ inst->fileUID = -1;
+ inst->fileGID = -1;
+ inst->maxFrameSize = 200000;
+ inst->fCreateMode = 0644;
+ inst->bFailOnPerms = 1;
+ inst->bUnlink = 0;
+ inst->discardTruncatedMsg = 0;
+ inst->flowControl = 1;
+ inst->pszBindRuleset = NULL;
+ inst->pszInputName = NULL;
+ inst->bSuppOctetFram = 1;
+ inst->bSPFramingFix = 0;
+ inst->bKeepAlive = 0;
+ inst->iKeepAliveIntvl = 0;
+ inst->iKeepAliveProbes = 0;
+ inst->iKeepAliveTime = 0;
+ inst->bEmitMsgOnClose = 0;
+ inst->bEmitMsgOnOpen = 0;
+ inst->dfltTZ = NULL;
+ inst->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ inst->startRegex = NULL;
+ inst->pBindRuleset = NULL;
+ inst->ratelimitBurst = 10000; /* arbitrary high limit */
+ inst->ratelimitInterval = 0; /* off */
+ inst->compressionMode = COMPRESS_SINGLE_MSG;
+ inst->multiLine = 0;
+ inst->socketBacklog = 5;
+ inst->pszLstnPortFileName = NULL;
+ inst->iTCPSessMax = -1;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called when a new listener instace shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ */
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *const pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ if(pNewVal == NULL || *pNewVal == '\0') {
+ parser_errmsg("imptcp: port number must be specified, listener ignored");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+
+ /* if we reach this point, a valid port is given in pNewVal */
+ CHKiRet(createInstance(&inst));
+ CHKmalloc(inst->pszBindPort = ustrdup(pNewVal));
+ if((cs.lstnIP == NULL) || (cs.lstnIP[0] == '\0')) {
+ inst->pszBindAddr = NULL;
+ } else {
+ CHKmalloc(inst->pszBindAddr = ustrdup(cs.lstnIP));
+ }
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ if((cs.pszInputName == NULL) || (cs.pszInputName[0] == '\0')) {
+ inst->pszInputName = NULL;
+ } else {
+ CHKmalloc(inst->pszInputName = ustrdup(cs.pszInputName));
+ }
+ inst->pBindRuleset = NULL;
+ inst->bSuppOctetFram = cs.bSuppOctetFram;
+ inst->bKeepAlive = cs.bKeepAlive;
+ inst->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ inst->iKeepAliveProbes = cs.iKeepAliveProbes;
+ inst->iKeepAliveTime = cs.iKeepAliveTime;
+ inst->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ inst->bEmitMsgOnOpen = cs.bEmitMsgOnOpen;
+ inst->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ inst->maxFrameSize = cs.maxFrameSize;
+ inst->iTCPSessMax = cs.iTCPSessMax;
+
+finalize_it:
+ free(pNewVal);
+ RETiRet;
+}
+
+
+static rsRetVal
+addListner(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
+{
+ DEFiRet;
+ ptcpsrv_t *pSrv = NULL;
+
+ CHKmalloc(pSrv = calloc(1, sizeof(ptcpsrv_t)));
+ pthread_mutex_init(&pSrv->mutSessLst, NULL);
+ pSrv->ratelimiter = NULL;
+ pSrv->pSess = NULL;
+ pSrv->pLstn = NULL;
+ pSrv->inst = inst;
+ pSrv->bSuppOctetFram = inst->bSuppOctetFram;
+ pSrv->bSPFramingFix = inst->bSPFramingFix;
+ pSrv->bKeepAlive = inst->bKeepAlive;
+ pSrv->iKeepAliveIntvl = inst->iKeepAliveIntvl;
+ pSrv->iKeepAliveProbes = inst->iKeepAliveProbes;
+ pSrv->iKeepAliveTime = inst->iKeepAliveTime;
+ pSrv->bEmitMsgOnClose = inst->bEmitMsgOnClose;
+ pSrv->bEmitMsgOnOpen = inst->bEmitMsgOnOpen;
+ pSrv->compressionMode = inst->compressionMode;
+ pSrv->dfltTZ = inst->dfltTZ;
+ if (inst->pszBindPort != NULL) {
+ CHKmalloc(pSrv->port = ustrdup(inst->pszBindPort));
+ }
+ pSrv->iAddtlFrameDelim = inst->iAddtlFrameDelim;
+ pSrv->multiLine = inst->multiLine;
+ pSrv->socketBacklog = inst->socketBacklog;
+ pSrv->pszLstnPortFileName = inst->pszLstnPortFileName;
+ pSrv->maxFrameSize = inst->maxFrameSize;
+ if (inst->pszBindAddr == NULL) {
+ pSrv->lstnIP = NULL;
+ } else {
+ CHKmalloc(pSrv->lstnIP = ustrdup(inst->pszBindAddr));
+ }
+ if (inst->pszBindPath == NULL) {
+ pSrv->path = NULL;
+ } else {
+ CHKmalloc(pSrv->path = ustrdup(inst->pszBindPath));
+ CHKmalloc(pSrv->port = ustrdup(inst->pszBindPath));
+ pSrv->bUnixSocket = 1;
+ pSrv->fCreateMode = inst->fCreateMode;
+ pSrv->fileUID = inst->fileUID;
+ pSrv->fileGID = inst->fileGID;
+ pSrv->bFailOnPerms = inst->bFailOnPerms;
+ }
+
+ pSrv->bUnlink = inst->bUnlink;
+ pSrv->discardTruncatedMsg = inst->discardTruncatedMsg;
+ pSrv->flowControl = inst->flowControl;
+ pSrv->pRuleset = inst->pBindRuleset;
+ pSrv->pszInputName = ustrdup((inst->pszInputName == NULL) ? UCHAR_CONSTANT("imptcp") : inst->pszInputName);
+ pSrv->iTCPSessMax = inst->iTCPSessMax;
+ CHKiRet(prop.Construct(&pSrv->pInputName));
+ CHKiRet(prop.SetString(pSrv->pInputName, pSrv->pszInputName, ustrlen(pSrv->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(pSrv->pInputName));
+
+ CHKiRet(ratelimitNew(&pSrv->ratelimiter, "imptcp", (char*) pSrv->port));
+ ratelimitSetLinuxLike(pSrv->ratelimiter, inst->ratelimitInterval, inst->ratelimitBurst);
+ ratelimitSetThreadSafe(pSrv->ratelimiter);
+ /* add to linked list */
+ pSrv->pNext = pSrvRoot;
+ pSrvRoot = pSrv;
+
+ /* all config vars are auto-reset -- this also is very useful with the
+ * new config format effort (v6).
+ */
+ resetConfigVariables(NULL, NULL);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "error %d trying to add listener", iRet);
+ if(pSrv != NULL) {
+ destructSrv(pSrv);
+ }
+ }
+ RETiRet;
+}
+
+
+/* destroy worker pool structures and wait for workers to terminate
+ */
+static void
+startWorkerPool(void)
+{
+ int i;
+ pthread_mutex_lock(&io_q.mut); /* locking to keep Coverity happy */
+ wrkrRunning = 0;
+ pthread_mutex_unlock(&io_q.mut);
+ DBGPRINTF("imptcp: starting worker pool, %d workers\n", runModConf->wrkrMax);
+ wrkrInfo = calloc(runModConf->wrkrMax, sizeof(struct wrkrInfo_s));
+ if (wrkrInfo == NULL) {
+ LogError(errno, RS_RET_OUT_OF_MEMORY, "imptcp: worker-info array allocation failed.");
+ return;
+ }
+ for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
+ /* init worker info structure! */
+ wrkrInfo[i].wrkrIdx = i;
+ wrkrInfo[i].numCalled = 0;
+ pthread_create(&wrkrInfo[i].tid, &wrkrThrdAttr, wrkr, &(wrkrInfo[i]));
+ }
+
+}
+
+/* destroy worker pool structures and wait for workers to terminate
+ */
+static void
+stopWorkerPool(void)
+{
+ int i;
+ DBGPRINTF("imptcp: stopping worker pool\n");
+ pthread_mutex_lock(&io_q.mut);
+ pthread_cond_broadcast(&io_q.wakeup_worker); /* awake wrkr if not running */
+ pthread_mutex_unlock(&io_q.mut);
+ for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
+ pthread_join(wrkrInfo[i].tid, NULL);
+ DBGPRINTF("imptcp: info: worker %d was called %llu times\n", i, wrkrInfo[i].numCalled);
+ }
+ free(wrkrInfo);
+}
+
+
+
+/* start up all listeners
+ * This is a one-time stop once the module is set to start.
+ */
+static rsRetVal
+startupServers(void)
+{
+ DEFiRet;
+ rsRetVal localRet, lastErr;
+ int iOK;
+ int iAll;
+ ptcpsrv_t *pSrv;
+
+ iAll = iOK = 0;
+ lastErr = RS_RET_ERR;
+ pSrv = pSrvRoot;
+ while(pSrv != NULL) {
+ DBGPRINTF("imptcp: starting up server for port %s, name '%s'\n", pSrv->port, pSrv->pszInputName);
+ localRet = startupSrv(pSrv);
+ if(localRet == RS_RET_OK)
+ iOK++;
+ else
+ lastErr = localRet;
+ ++iAll;
+ pSrv = pSrv->pNext;
+ }
+
+ DBGPRINTF("imptcp: %d out of %d servers started successfully\n", iOK, iAll);
+ if(iOK == 0) /* iff all fails, we report an error */
+ iRet = lastErr;
+
+ RETiRet;
+}
+
+/* process new activity on listener. This means we need to accept a new
+ * connection.
+ */
+static rsRetVal ATTR_NONNULL()
+lstnActivity(ptcplstn_t *const pLstn)
+{
+ int newSock = -1;
+ prop_t *peerName;
+ prop_t *peerIP;
+ rsRetVal localRet;
+ DEFiRet;
+
+ DBGPRINTF("imptcp: new connection on listen socket %d\n", pLstn->sock);
+ while(glbl.GetGlobalInputTermState() == 0) {
+ localRet = AcceptConnReq(pLstn, &newSock, &peerName, &peerIP);
+ DBGPRINTF("imptcp: AcceptConnReq on listen socket %d returned %d\n", pLstn->sock, localRet);
+ if(localRet == RS_RET_NO_MORE_DATA || glbl.GetGlobalInputTermState() == 1) {
+ break;
+ }
+ CHKiRet(localRet);
+ localRet = addSess(pLstn, newSock, peerName, peerIP);
+ if(localRet != RS_RET_OK) {
+ close(newSock);
+ prop.Destruct(&peerName);
+ prop.Destruct(&peerIP);
+ ABORT_FINALIZE(localRet);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* process new activity on session. This means we need to accept data
+ * or close the session.
+ */
+static rsRetVal
+sessActivity(ptcpsess_t *const pSess, int *const continue_polling)
+{
+ int lenRcv;
+ int lenBuf;
+ uchar *peerName;
+ int lenPeer;
+ int remsock = 0; /* init just to keep compiler happy... :-( */
+ sbool bEmitOnClose = 0;
+ char rcvBuf[128*1024];
+ int runs = 0;
+ DEFiRet;
+
+ DBGPRINTF("imptcp: new activity on session socket %d\n", pSess->sock);
+
+ while(runs++ < 16) {
+ lenBuf = sizeof(rcvBuf);
+ lenRcv = recv(pSess->sock, rcvBuf, lenBuf, 0);
+
+ if(lenRcv > 0) {
+ /* have data, process it */
+ DBGPRINTF("imptcp: data(%d) on socket %d: %s\n", lenBuf, pSess->sock, rcvBuf);
+ CHKiRet(DataRcvd(pSess, rcvBuf, lenRcv));
+ } else if (lenRcv == 0) {
+ /* session was closed, do clean-up */
+ if(pSess->pLstn->pSrv->bEmitMsgOnClose) {
+ prop.GetString(pSess->peerName, &peerName, &lenPeer),
+ remsock = pSess->sock;
+ bEmitOnClose = 1;
+ }
+ *continue_polling = 0;
+ if(bEmitOnClose) {
+ LogError(0, RS_RET_PEER_CLOSED_CONN, "imptcp session %d closed by "
+ "remote peer %s.", remsock, peerName);
+ }
+ CHKiRet(closeSess(pSess)); /* close may emit more messages in strmzip mode! */
+ break;
+ } else {
+ if(CHK_EAGAIN_EWOULDBLOCK)
+ break;
+ DBGPRINTF("imptcp: error on session socket %d - closed.\n", pSess->sock);
+ *continue_polling = 0;
+ closeSess(pSess); /* try clean-up by dropping session */
+ break;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called to process a single request. This may
+ * be carried out by the main worker or a helper. It can be run
+ * concurrently.
+ */
+static void
+processWorkItem(epolld_t *epd)
+{
+
+ int continue_polling = 1;
+
+ switch(epd->typ) {
+ case epolld_lstn:
+ /* listener never stops polling (except server shutdown) */
+ lstnActivity((ptcplstn_t *) epd->ptr);
+ break;
+ case epolld_sess:
+ sessActivity((ptcpsess_t *) epd->ptr, &continue_polling);
+ break;
+ default:
+ LogError(0, RS_RET_INTERNAL_ERROR, "error: invalid epolld_type_t %d after epoll", epd->typ);
+ break;
+ }
+ if (continue_polling == 1) {
+ epoll_ctl(epollfd, EPOLL_CTL_MOD, epd->sock, &(epd->ev));
+ }
+}
+
+
+static rsRetVal
+initIoQ(void)
+{
+ DEFiRet;
+ CHKiConcCtrl(pthread_mutex_init(&io_q.mut, NULL));
+ CHKiConcCtrl(pthread_cond_init(&io_q.wakeup_worker, NULL));
+ STAILQ_INIT(&io_q.q);
+ io_q.sz = 0;
+ io_q.ctrMaxSz = 0; /* TODO: discuss this and fix potential concurrent read/write issues */
+ CHKiRet(statsobj.Construct(&io_q.stats));
+ CHKiRet(statsobj.SetName(io_q.stats, (uchar*) "io-work-q"));
+ CHKiRet(statsobj.SetOrigin(io_q.stats, (uchar*) "imptcp"));
+ STATSCOUNTER_INIT(io_q.ctrEnq, io_q.mutCtrEnq);
+ CHKiRet(statsobj.AddCounter(io_q.stats, UCHAR_CONSTANT("enqueued"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &io_q.ctrEnq));
+ CHKiRet(statsobj.AddCounter(io_q.stats, UCHAR_CONSTANT("maxqsize"),
+ ctrType_Int, CTR_FLAG_NONE, &io_q.ctrMaxSz));
+ CHKiRet(statsobj.ConstructFinalize(io_q.stats));
+finalize_it:
+ RETiRet;
+}
+
+static void
+destroyIoQ(void)
+{
+ io_req_t *n;
+ if (io_q.stats != NULL) {
+ statsobj.Destruct(&io_q.stats);
+ }
+ pthread_mutex_lock(&io_q.mut);
+ while (!STAILQ_EMPTY(&io_q.q)) {
+ n = STAILQ_FIRST(&io_q.q);
+ STAILQ_REMOVE_HEAD(&io_q.q, link);
+ LogError(0, RS_RET_INTERNAL_ERROR, "imptcp: discarded enqueued io-work to allow shutdown "
+ "- ignored");
+ free(n);
+ }
+ io_q.sz = 0;
+ pthread_mutex_unlock(&io_q.mut);
+ pthread_cond_destroy(&io_q.wakeup_worker);
+ pthread_mutex_destroy(&io_q.mut);
+}
+
+static rsRetVal
+enqueueIoWork(epolld_t *epd, int dispatchInlineIfQueueFull) {
+ io_req_t *n;
+ int dispatchInline;
+ int inlineDispatchThreshold;
+ DEFiRet;
+
+ CHKmalloc(n = malloc(sizeof(io_req_t)));
+ n->epd = epd;
+
+ inlineDispatchThreshold = DFLT_inlineDispatchThreshold * runModConf->wrkrMax;
+ dispatchInline = 0;
+
+ pthread_mutex_lock(&io_q.mut);
+ if (dispatchInlineIfQueueFull && io_q.sz > inlineDispatchThreshold) {
+ dispatchInline = 1;
+ } else {
+ STAILQ_INSERT_TAIL(&io_q.q, n, link);
+ io_q.sz++;
+ STATSCOUNTER_INC(io_q.ctrEnq, io_q.mutCtrEnq);
+ STATSCOUNTER_SETMAX_NOMUT(io_q.ctrMaxSz, io_q.sz);
+ pthread_cond_signal(&io_q.wakeup_worker);
+ }
+ pthread_mutex_unlock(&io_q.mut);
+
+ if (dispatchInline == 1) {
+ free(n);
+ processWorkItem(epd);
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (n == NULL) {
+ LogError(0, iRet, "imptcp: couldn't allocate memory to enqueue io-request - ignored");
+ }
+ }
+ RETiRet;
+}
+
+/* This function is called to process a complete workset, that
+ * is a set of events returned from epoll.
+ */
+static void
+processWorkSet(int nEvents, struct epoll_event events[])
+{
+ int iEvt;
+ int remainEvents;
+ remainEvents = nEvents;
+ epolld_t *epd;
+
+ for(iEvt = 0 ; (iEvt < nEvents) && (glbl.GetGlobalInputTermState() == 0) ; ++iEvt) {
+ epd = (epolld_t*)events[iEvt].data.ptr;
+ if(runModConf->bProcessOnPoller && remainEvents == 1) {
+ /* process self, save context switch */
+ processWorkItem(epd);
+ } else {
+ enqueueIoWork(epd, runModConf->bProcessOnPoller);
+ }
+ --remainEvents;
+ }
+}
+
+
+/* worker to process incoming requests
+ */
+static void *
+wrkr(void *myself)
+{
+ struct wrkrInfo_s *me = (struct wrkrInfo_s*) myself;
+ pthread_mutex_lock(&io_q.mut);
+ ++wrkrRunning;
+ pthread_mutex_unlock(&io_q.mut);
+
+ uchar thrdName[32];
+ snprintf((char*)thrdName, sizeof(thrdName), "imptcp/w%d", me->wrkrIdx);
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ /* set thread name - we ignore if the call fails, has no harsh consequences... */
+ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) {
+ DBGPRINTF("prctl failed, not setting thread name for '%s'\n", thrdName);
+ }
+# endif
+
+ io_req_t *n;
+ while(1) {
+ n = NULL;
+ pthread_mutex_lock(&io_q.mut);
+ if (io_q.sz == 0) {
+ --wrkrRunning;
+ if (glbl.GetGlobalInputTermState() != 0) {
+ pthread_mutex_unlock(&io_q.mut);
+ break;
+ } else {
+ DBGPRINTF("imptcp: worker %llu waiting on new work items\n",
+ (unsigned long long) me->tid);
+ pthread_cond_wait(&io_q.wakeup_worker, &io_q.mut);
+ DBGPRINTF("imptcp: worker %llu awoken\n", (unsigned long long) me->tid);
+ }
+ ++wrkrRunning;
+ }
+ if (io_q.sz > 0) {
+ n = STAILQ_FIRST(&io_q.q);
+ STAILQ_REMOVE_HEAD(&io_q.q, link);
+ io_q.sz--;
+ }
+ pthread_mutex_unlock(&io_q.mut);
+
+ if (n != NULL) {
+ ++me->numCalled;
+ processWorkItem(n->epd);
+ free(n);
+ }
+ }
+ return NULL;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ char *cstr;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imptcp)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imptcp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "port")) {
+ inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "path")) {
+ inst->pszBindPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "unlink")) {
+ inst->bUnlink = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) {
+ inst->discardTruncatedMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->flowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "fileowner")) {
+ inst->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "fileownernum")) {
+ inst->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "filegroup")) {
+ inst->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "filegroupnum")) {
+ inst->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "filecreatemode")) {
+ inst->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "failonpermsfailure")) {
+ inst->bFailOnPerms = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "maxframesize")) {
+ const int max = (int) pvals[i].val.d.n;
+ if(max <= 200000000) {
+ inst->maxFrameSize = max;
+ } else {
+ parser_errmsg("imptcp: invalid value for 'maxFrameSize' "
+ "parameter given is %d, max is 200000000", max);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "framing.delimiter.regex")) {
+ inst->startRegex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) {
+ inst->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "framingfix.cisco.asa")) {
+ inst->bSPFramingFix = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "compression.mode")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(cstr, "stream:always")) {
+ inst->compressionMode = COMPRESS_STREAM_ALWAYS;
+ } else if(!strcasecmp(cstr, "none")) {
+ inst->compressionMode = COMPRESS_NEVER;
+ } else {
+ parser_errmsg("imptcp: invalid value for 'compression.mode' "
+ "parameter (given is '%s')", cstr);
+ free(cstr);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ free(cstr);
+ } else if(!strcmp(inppblk.descr[i].name, "maxsessions")) {
+ inst->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive")) {
+ inst->bKeepAlive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.probes")) {
+ inst->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.time")) {
+ inst->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.interval")) {
+ inst->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "addtlframedelimiter")) {
+ inst->iAddtlFrameDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionclose")) {
+ inst->bEmitMsgOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionopen")) {
+ inst->bEmitMsgOnOpen = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "defaulttz")) {
+ inst->dfltTZ = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "multiline")) {
+ inst->multiLine = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "listenportfilename")) {
+ inst->pszLstnPortFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "socketbacklog")) {
+ inst->socketBacklog = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imptcp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+
+ char *bindPort = (char *) inst->pszBindPort;
+ char *bindPath = (char *) inst->pszBindPath;
+ if ((bindPort == NULL || strlen(bindPort) < 1) && (bindPath == NULL || strlen (bindPath) < 1)) {
+ parser_errmsg("imptcp: Must have either port or path defined");
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ }
+
+ if(inst->startRegex != NULL) {
+ const int errcode = regcomp(&inst->start_preg, (char*)inst->startRegex, REG_EXTENDED);
+ if(errcode != 0) {
+ char errbuff[512];
+ regerror(errcode, &inst->start_preg, errbuff, sizeof(errbuff));
+ parser_errmsg("imptcp: error in framing.delimiter.regex expansion: %s", errbuff);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ if (inst->iTCPSessMax == -1) {
+ inst->iTCPSessMax = loadModConf->iTCPSessMax;
+ }
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ loadModConf->wrkrMax = DFLT_wrkrMax;
+ loadModConf->bProcessOnPoller = 1;
+ loadModConf->configSetViaV2Method = 0;
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ initConfigSettings();
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imptcp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imptcp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "threads")) {
+ loadModConf->wrkrMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "maxsessions")) {
+ loadModConf->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "processOnPoller")) {
+ loadModConf->bProcessOnPoller = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imptcp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* remove all of our legacy handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->wrkrMax = cs.wrkrMax;
+ }
+
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pszInputName);
+ free(cs.lstnIP);
+ cs.pszInputName = NULL;
+ cs.lstnIP = NULL;
+ENDendCnfLoad
+
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imptcp: ruleset '%s' for port %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszBindPort);
+}
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ iMaxLine = glbl.GetMaxLine(runConf); /* get maximum size we currently support */
+ DBGPRINTF("imptcp: config params iMaxLine %d\n", iMaxLine);
+
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(pModConf, inst);
+ }
+ if(pSrvRoot == NULL) {
+ LogError(0, RS_RET_NO_LSTN_DEFINED, "imptcp: no ptcp server defined, module can not run.");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+# if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1)
+ DBGPRINTF("imptcp uses epoll_create1()\n");
+ epollfd = epoll_create1(EPOLL_CLOEXEC);
+ if(epollfd < 0 && errno == ENOSYS)
+# endif
+ {
+ DBGPRINTF("imptcp uses epoll_create()\n");
+ /* reading the docs, the number of epoll events passed to
+ * epoll_create() seems not to be used at all in kernels. So
+ * we just provide "a" number, happens to be 10.
+ */
+ epollfd = epoll_create(10);
+ }
+
+ if(epollfd < 0) {
+ LogError(0, RS_RET_EPOLL_CR_FAILED, "error: epoll_create() failed");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ /* start up servers, but do not yet read input data */
+ CHKiRet(startupServers());
+ DBGPRINTF("imptcp started up, but not yet receiving data\n");
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ /* nothing to do, all done pre priv drop */
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindPort);
+ free(inst->pszBindPath);
+ free(inst->pszBindAddr);
+ free(inst->pszBindRuleset);
+ free(inst->pszInputName);
+ free(inst->dfltTZ);
+ if(inst->startRegex != NULL) {
+ regfree(&inst->start_preg);
+ free(inst->startRegex);
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+ int nEvents;
+ struct epoll_event events[128];
+CODESTARTrunInput
+ initIoQ();
+ startWorkerPool();
+ DBGPRINTF("imptcp: now beginning to process input data\n");
+ while(glbl.GetGlobalInputTermState() == 0) {
+ DBGPRINTF("imptcp going on epoll_wait\n");
+ nEvents = epoll_wait(epollfd, events, sizeof(events)/sizeof(struct epoll_event), -1);
+ DBGPRINTF("imptcp: epoll returned %d events\n", nEvents);
+ processWorkSet(nEvents, events);
+ }
+ DBGPRINTF("imptcp: successfully terminated\n");
+ /* we stop the worker pool in AfterRun, in case we get cancelled for some reason (old Interface) */
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+
+/* completely shut down a server, that means closing all of its
+ * listeners and sessions.
+ */
+static void
+shutdownSrv(ptcpsrv_t *pSrv)
+{
+ ptcplstn_t *pLstn, *lstnDel;
+ ptcpsess_t *pSess, *sessDel;
+
+ /* listeners */
+ pLstn = pSrv->pLstn;
+ while(pLstn != NULL) {
+ close(pLstn->sock);
+ statsobj.Destruct(&(pLstn->stats));
+ /* now unlink listner */
+ lstnDel = pLstn;
+ pLstn = pLstn->next;
+ DBGPRINTF("imptcp shutdown listen socket %d (rcvd %lld bytes, "
+ "decompressed %lld)\n", lstnDel->sock, lstnDel->rcvdBytes,
+ lstnDel->rcvdDecompressed);
+ free(lstnDel->epd);
+ free(lstnDel);
+ }
+
+ if (pSrv->bUnixSocket && pSrv->bUnlink) {
+ unlink((char*) pSrv->path);
+ }
+
+ /* sessions */
+ pSess = pSrv->pSess;
+ while(pSess != NULL) {
+ close(pSess->sock);
+ sessDel = pSess;
+ pSess = pSess->next;
+ DBGPRINTF("imptcp shutdown session socket %d\n", sessDel->sock);
+ destructSess(sessDel);
+ }
+}
+
+
+BEGINafterRun
+ ptcpsrv_t *pSrv, *srvDel;
+CODESTARTafterRun
+ stopWorkerPool();
+ destroyIoQ();
+
+ /* we need to close everything that is still open */
+ pSrv = pSrvRoot;
+ while(pSrv != NULL) {
+ srvDel = pSrv;
+ pSrv = pSrv->pNext;
+ shutdownSrv(srvDel);
+ destructSrv(srvDel);
+ }
+
+ close(epollfd);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ pthread_attr_destroy(&wrkrThrdAttr);
+ /* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.bEmitMsgOnClose = 0;
+ cs.bEmitMsgOnOpen = 0;
+ cs.wrkrMax = DFLT_wrkrMax;
+ cs.bKeepAlive = 0;
+ cs.iKeepAliveProbes = 0;
+ cs.iKeepAliveTime = 0;
+ cs.iKeepAliveIntvl = 0;
+ cs.bSuppOctetFram = 1;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ cs.maxFrameSize = 200000;
+ free(cs.pszInputName);
+ cs.pszInputName = NULL;
+ free(cs.lstnIP);
+ cs.lstnIP = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* initialize "read-only" thread attributes */
+ pthread_attr_init(&wrkrThrdAttr);
+ pthread_attr_setstacksize(&wrkrThrdAttr, 4096*1024);
+
+ /* init legacy config settings */
+ initConfigSettings();
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverrun"), 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverkeepalive"), 0, eCmdHdlrBinary,
+ NULL, &cs.bKeepAlive, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverkeepalive_probes"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveProbes, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverkeepalive_time"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveTime, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverkeepalive_intvl"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveIntvl, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserversupportoctetcountedframing"), 0, eCmdHdlrBinary,
+ NULL, &cs.bSuppOctetFram, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpservernotifyonconnectionclose"), 0,
+ eCmdHdlrBinary, NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserveraddtlframedelimiter"), 0, eCmdHdlrInt,
+ NULL, &cs.iAddtlFrameDelim, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverinputname"), 0,
+ eCmdHdlrGetWord, NULL, &cs.pszInputName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverlistenip"), 0,
+ eCmdHdlrGetWord, NULL, &cs.lstnIP, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverbindruleset"), 0,
+ eCmdHdlrGetWord, NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
+ /* module-global parameters */
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputptcpserverhelperthreads"), 0, eCmdHdlrInt,
+ NULL, &cs.wrkrMax, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+
+/* vim:set ai:
+ */
diff --git a/plugins/imrelp/Makefile.am b/plugins/imrelp/Makefile.am
new file mode 100644
index 0000000..8c6faff
--- /dev/null
+++ b/plugins/imrelp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imrelp.la
+
+imrelp_la_SOURCES = imrelp.c
+imrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS)
+imrelp_la_LDFLAGS = -module -avoid-version
+imrelp_la_LIBADD = $(RELP_LIBS)
diff --git a/plugins/imrelp/Makefile.in b/plugins/imrelp/Makefile.in
new file mode 100644
index 0000000..d5c2dd0
--- /dev/null
+++ b/plugins/imrelp/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imrelp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imrelp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imrelp_la_OBJECTS = imrelp_la-imrelp.lo
+imrelp_la_OBJECTS = $(am_imrelp_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 =
+imrelp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imrelp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imrelp_la-imrelp.Plo
+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 = $(imrelp_la_SOURCES)
+DIST_SOURCES = $(imrelp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imrelp.la
+imrelp_la_SOURCES = imrelp.c
+imrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS)
+imrelp_la_LDFLAGS = -module -avoid-version
+imrelp_la_LIBADD = $(RELP_LIBS)
+all: 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) --gnu plugins/imrelp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imrelp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imrelp.la: $(imrelp_la_OBJECTS) $(imrelp_la_DEPENDENCIES) $(EXTRA_imrelp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imrelp_la_LINK) -rpath $(pkglibdir) $(imrelp_la_OBJECTS) $(imrelp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imrelp_la-imrelp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imrelp_la-imrelp.lo: imrelp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imrelp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imrelp_la-imrelp.lo -MD -MP -MF $(DEPDIR)/imrelp_la-imrelp.Tpo -c -o imrelp_la-imrelp.lo `test -f 'imrelp.c' || echo '$(srcdir)/'`imrelp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imrelp_la-imrelp.Tpo $(DEPDIR)/imrelp_la-imrelp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imrelp.c' object='imrelp_la-imrelp.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) $(imrelp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imrelp_la-imrelp.lo `test -f 'imrelp.c' || echo '$(srcdir)/'`imrelp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imrelp_la-imrelp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imrelp_la-imrelp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c
new file mode 100644
index 0000000..4f9295c
--- /dev/null
+++ b/plugins/imrelp/imrelp.c
@@ -0,0 +1,954 @@
+/* imrelp.c
+ *
+ * This is the implementation of the RELP input module.
+ *
+ * File begun on 2008-03-13 by RGerhards
+ *
+ * Copyright 2008-2019 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <librelp.h>
+#include "rsyslog.h"
+#include "dirty.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "net.h"
+#include "msg.h"
+#include "unicode-helper.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "glbl.h"
+#include "statsobj.h"
+#include "srUtils.h"
+#include "parserif.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imrelp")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(net)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(statsobj)
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+
+/* Module static data */
+/* config vars for legacy config system */
+static relpEngine_t *pRelpEngine; /* our relp engine */
+
+/* config settings */
+typedef struct configSettings_s {
+ uchar *pszBindRuleset; /* name of Ruleset to bind to */
+} configSettings_t;
+static configSettings_t cs;
+
+struct instanceConf_s {
+ uchar *pszBindPort; /* port to bind to */
+ uchar *pszBindAddr; /* address to bind to */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *pszInputName; /* value for inputname property */
+ prop_t *pInputName; /* InputName in property format for fast access */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to */
+ sbool bKeepAlive; /* support keep-alive packets */
+ sbool bEnableTLS;
+ sbool bEnableTLSZip;
+ sbool bEnableLstn; /* flag to permit disabling of listener in error case */
+ int dhBits;
+ size_t maxDataSize;
+ int oversizeMode;
+ uchar *pristring; /* GnuTLS priority string (NULL if not to be provided) */
+ uchar *authmode; /* TLS auth mode */
+ uchar *caCertFile;
+ uchar *myCertFile;
+ uchar *myPrivKeyFile;
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ uchar *tlscfgcmd;
+#endif
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ flowControl_t flowCtlType;
+ struct {
+ int nmemb;
+ uchar **name;
+ } permittedPeers;
+
+ struct instanceConf_s *next;
+ /* with librelp, this module does not have any own specific session
+ * or listener active data item. As a "work-around", we keep some
+ * data items inside the configuration object. To keep things
+ * decently clean, we put them all into their dedicated struct. So
+ * it is easy to judge what is actual configuration and what is
+ * dynamic runtime data. -- rgerhards, 2013-06-18
+ */
+ struct {
+ statsobj_t *stats; /* listener stats */
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ } data;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ const char *tlslib;
+ uchar *pszBindRuleset; /* default name of Ruleset to bind to */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ruleset", eCmdHdlrGetWord, 0 },
+ { "tls.tlslib", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "address", eCmdHdlrString, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrInt, 0 },
+ { "keepalive.time", eCmdHdlrInt, 0 },
+ { "keepalive.interval", eCmdHdlrInt, 0 },
+ { "maxdatasize", eCmdHdlrSize, 0 },
+ { "oversizemode", eCmdHdlrString, 0 },
+ { "flowcontrol", eCmdHdlrGetWord, 0 },
+ { "tls", eCmdHdlrBinary, 0 },
+ { "tls.permittedpeer", eCmdHdlrArray, 0 },
+ { "tls.authmode", eCmdHdlrString, 0 },
+ { "tls.dhbits", eCmdHdlrInt, 0 },
+ { "tls.prioritystring", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "tls.tlscfgcmd", eCmdHdlrString, 0 },
+ { "tls.compression", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+/* ------------------------------ callbacks ------------------------------ */
+
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wformat_nonliteral
+static void __attribute__((format(printf, 1, 2)))
+imrelp_dbgprintf(const char *fmt, ...)
+{
+ va_list ap;
+ char pszWriteBuf[32*1024+1]; //this function has to be able to
+ /*generate a buffer longer than that of r_dbgprintf, so
+ r_dbgprintf can properly truncate*/
+
+ if(!(Debug && debugging_on)) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
+ va_end(ap);
+ r_dbgprintf("imrelp.c", "%s", pszWriteBuf);
+}
+PRAGMA_DIAGNOSTIC_POP
+
+static void
+onErr(void *pUsr, char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ instanceConf_t *inst = (instanceConf_t*) pUsr;
+ LogError(0, RS_RET_RELP_AUTH_FAIL, "imrelp[%s]: error '%s', object "
+ " '%s' - input may not work as intended",
+ inst->pszBindPort, errmesg, objinfo);
+}
+
+static void
+onGenericErr(char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ LogError(0, RS_RET_RELP_ERR, "imrelp: librelp error '%s', object "
+ " '%s' - input may not work as intended", errmesg, objinfo);
+}
+
+static void
+onAuthErr(void *pUsr, char *authinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ instanceConf_t *inst = (instanceConf_t*) pUsr;
+ LogError(0, RS_RET_RELP_AUTH_FAIL, "imrelp[%s]: authentication error '%s', peer "
+ "is '%s'", inst->pszBindPort, errmesg, authinfo);
+}
+
+/* callback for receiving syslog messages. This function is invoked from the
+ * RELP engine when a syslog message arrived. It must return a relpRetVal,
+ * with anything else but RELP_RET_OK terminating the relp session. Please note
+ * that RELP_RET_OK is equal to RS_RET_OK and the other libRELP error codes
+ * are different from our rsRetVal. So we can simply use our own iRet system
+ * to fulfill the requirement.
+ * rgerhards, 2008-03-21
+ * Note: librelp 1.0.0 is required in order to receive the IP address, otherwise
+ * we will only see the hostname (twice). -- rgerhards, 2009-10-14
+ */
+static relpRetVal
+onSyslogRcv(void *pUsr, uchar *pHostname, uchar *pIP, uchar *msg, size_t lenMsg)
+{
+ prop_t *pProp = NULL;
+ smsg_t *pMsg;
+ instanceConf_t *inst = (instanceConf_t*) pUsr;
+ DEFiRet;
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, inst->pInputName);
+ MsgSetRawMsg(pMsg, (char*)msg, lenMsg);
+ MsgSetFlowControlType(pMsg, inst->flowCtlType);
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ pMsg->msgFlags = PARSE_HOSTNAME | NEEDS_PARSING;
+
+ /* TODO: optimize this, we can store it inside the session */
+ MsgSetRcvFromStr(pMsg, pHostname, ustrlen(pHostname), &pProp);
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(MsgSetRcvFromIPStr(pMsg, pIP, ustrlen(pIP), &pProp));
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(submitMsg2(pMsg));
+ STATSCOUNTER_INC(inst->data.ctrSubmit, inst->data.mutCtrSubmit);
+
+finalize_it:
+
+ RETiRet;
+}
+
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+
+ inst->pszBindPort = NULL;
+ inst->pszBindAddr = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pszInputName = NULL;
+ inst->pBindRuleset = NULL;
+ inst->bKeepAlive = 0;
+ inst->iKeepAliveIntvl = 0;
+ inst->iKeepAliveProbes = 0;
+ inst->iKeepAliveTime = 0;
+ inst->bEnableTLS = 0;
+ inst->bEnableTLSZip = 0;
+ inst->bEnableLstn = 0;
+ inst->dhBits = 0;
+ inst->pristring = NULL;
+ inst->authmode = NULL;
+ inst->permittedPeers.nmemb = 0;
+ inst->caCertFile = NULL;
+ inst->myCertFile = NULL;
+ inst->myPrivKeyFile = NULL;
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ inst->tlscfgcmd = NULL;
+#endif
+ inst->maxDataSize = 0;
+ inst->flowCtlType = eFLOWCTL_LIGHT_DELAY;
+#ifdef HAVE_RELPSRVSETOVERSIZEMODE
+ inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
+#endif
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+/* function to generate an error message if the ruleset cannot be found */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imrelp[%s]: ruleset '%s' not found - "
+ "using default ruleset instead",
+ inst->pszBindPort, inst->pszBindRuleset);
+}
+
+
+/* This function is called when a new listener instance shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ * rgerhards, 2011-05-04
+ */
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ CHKiRet(createInstance(&inst));
+
+ if(pNewVal == NULL || *pNewVal == '\0') {
+ LogError(0, NO_ERRCODE, "imrelp: port number must be specified, listener ignored");
+ }
+ if((pNewVal == NULL) || (*pNewVal == '\0')) {
+ inst->pszBindPort = NULL;
+ } else {
+ CHKmalloc(inst->pszBindPort = ustrdup(pNewVal));
+ }
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ inst->pBindRuleset = NULL;
+
+ inst->bEnableLstn = -1; /* all ok, ready to start up */
+finalize_it:
+ free(pNewVal);
+ RETiRet;
+}
+
+
+static rsRetVal
+addListner(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
+{
+ relpSrv_t *pSrv;
+ int relpRet;
+ uchar statname[64];
+ int i;
+ DEFiRet;
+
+ if(!inst->bEnableLstn) {
+ DBGPRINTF("listener not started because it is disabled by config error\n");
+ FINALIZE;
+ }
+
+ if(pRelpEngine == NULL) {
+ CHKiRet(relpEngineConstruct(&pRelpEngine));
+ CHKiRet(relpEngineSetDbgprint(pRelpEngine, (void (*)(char *, ...))imrelp_dbgprintf));
+ CHKiRet(relpEngineSetFamily(pRelpEngine, glbl.GetDefPFFamily(runModConf->pConf)));
+ CHKiRet(relpEngineSetEnableCmd(pRelpEngine, (uchar*) "syslog", eRelpCmdState_Required));
+ CHKiRet(relpEngineSetSyslogRcv2(pRelpEngine, onSyslogRcv));
+ CHKiRet(relpEngineSetOnErr(pRelpEngine, onErr));
+ CHKiRet(relpEngineSetOnGenericErr(pRelpEngine, onGenericErr));
+ CHKiRet(relpEngineSetOnAuthErr(pRelpEngine, onAuthErr));
+ if (!glbl.GetDisableDNS(runModConf->pConf)) {
+ CHKiRet(relpEngineSetDnsLookupMode(pRelpEngine, 1));
+ }
+ #if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ if(modConf->tlslib != NULL) {
+ if(relpEngineSetTLSLibByName(pRelpEngine, modConf->tlslib) != RELP_RET_OK) {
+ LogMsg(0, RS_RET_CONF_PARAM_INVLD, LOG_WARNING,
+ "imrelp: tlslib '%s' not accepted as valid by librelp - using default",
+ modConf->tlslib);
+ }
+ }
+ #endif
+ }
+
+ CHKiRet(relpEngineListnerConstruct(pRelpEngine, &pSrv));
+ CHKiRet(relpSrvSetMaxDataSize(pSrv, inst->maxDataSize));
+ CHKiRet(relpSrvSetLstnPort(pSrv, inst->pszBindPort));
+ #if defined(HAVE_RELPSRVSETLSTNADDR)
+ CHKiRet(relpSrvSetLstnAddr(pSrv, inst->pszBindAddr));
+ #endif
+
+#ifdef HAVE_RELPSRVSETOVERSIZEMODE
+ CHKiRet(relpSrvSetOversizeMode(pSrv, inst->oversizeMode));
+#endif
+ inst->pszInputName = ustrdup((inst->pszInputName == NULL) ? UCHAR_CONSTANT("imrelp") : inst->pszInputName);
+ CHKiRet(prop.Construct(&inst->pInputName));
+ CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(inst->pInputName));
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&(inst->data.stats)));
+ snprintf((char*)statname, sizeof(statname), "%s(%s)",
+ inst->pszInputName, inst->pszBindPort);
+ statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(statsobj.SetName(inst->data.stats, statname));
+ CHKiRet(statsobj.SetOrigin(inst->data.stats, (uchar*)"imrelp"));
+ STATSCOUNTER_INIT(inst->data.ctrSubmit, inst->data.mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(inst->data.stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(inst->data.ctrSubmit)));
+ CHKiRet(statsobj.ConstructFinalize(inst->data.stats));
+ /* end stats counters */
+ relpSrvSetUsrPtr(pSrv, inst);
+ relpSrvSetKeepAlive(pSrv, inst->bKeepAlive, inst->iKeepAliveIntvl,
+ inst->iKeepAliveProbes, inst->iKeepAliveTime);
+ if(inst->bEnableTLS) {
+ relpRet = relpSrvEnableTLS2(pSrv);
+ if(relpRet == RELP_RET_ERR_NO_TLS) {
+ LogError(0, RS_RET_RELP_NO_TLS,
+ "imrelp: could not activate relp TLS, librelp "
+ "does not support it (most probably GnuTLS lib "
+ "is too old)!");
+ ABORT_FINALIZE(RS_RET_RELP_NO_TLS);
+ } else if(relpRet == RELP_RET_ERR_NO_TLS_AUTH) {
+ LogError(0, RS_RET_RELP_NO_TLS_AUTH,
+ "imrelp: could not activate relp TLS with "
+ "authentication, librelp does not support it "
+ "(most probably GnuTLS lib is too old)! "
+ "Note: anonymous TLS is probably supported.");
+ ABORT_FINALIZE(RS_RET_RELP_NO_TLS_AUTH);
+ } else if(relpRet != RELP_RET_OK) {
+ LogError(0, RS_RET_RELP_ERR,
+ "imrelp: could not activate relp TLS, code %d", relpRet);
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+ if(inst->bEnableTLSZip) {
+ relpSrvEnableTLSZip2(pSrv);
+ }
+ if(inst->dhBits) {
+ relpSrvSetDHBits(pSrv, inst->dhBits);
+ }
+ relpSrvSetGnuTLSPriString(pSrv, (char*)inst->pristring);
+ if(relpSrvSetAuthMode(pSrv, (char*)inst->authmode) != RELP_RET_OK) {
+ LogError(0, RS_RET_RELP_ERR,
+ "imrelp: invalid auth mode '%s'", inst->authmode);
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+ if(relpSrvSetCACert(pSrv, (char*) inst->caCertFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpSrvSetOwnCert(pSrv, (char*) inst->myCertFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpSrvSetPrivKey(pSrv, (char*) inst->myPrivKeyFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ if (inst->tlscfgcmd != NULL) {
+ if(relpSrvSetTlsConfigCmd(pSrv, (char*) inst->tlscfgcmd) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+#endif
+ for(i = 0 ; i < inst->permittedPeers.nmemb ; ++i) {
+ relpSrvAddPermittedPeer(pSrv, (char*)inst->permittedPeers.name[i]);
+ }
+ }
+ relpRet = relpEngineListnerConstructFinalize(pRelpEngine, pSrv);
+ /* re-check error TLS error codes. librelp seems to emit them only
+ * after finalize in some cases...
+ */
+ if(relpRet == RELP_RET_ERR_NO_TLS) {
+ LogError(0, RS_RET_RELP_NO_TLS,
+ "imrelp: could not activate relp TLS listener, librelp "
+ "does not support it (most probably GnuTLS lib "
+ "is too old)!");
+ ABORT_FINALIZE(RS_RET_RELP_NO_TLS);
+ } else if(relpRet == RELP_RET_ERR_NO_TLS_AUTH) {
+ LogError(0, RS_RET_RELP_NO_TLS_AUTH,
+ "imrelp: could not activate relp TLS listener with "
+ "authentication, librelp does not support it "
+ "(most probably GnuTLS lib is too old)! "
+ "Note: anonymous TLS is probably supported.");
+ ABORT_FINALIZE(RS_RET_RELP_NO_TLS_AUTH);
+ } else if(relpRet != RELP_RET_OK) {
+ LogError(0, RS_RET_RELP_ERR,
+ "imrelp: could not activate relp listener, code %d", relpRet);
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+
+ DBGPRINTF("imrelp: max data size %zd\n", inst->maxDataSize);
+ resetConfigVariables(NULL,NULL);
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst = NULL;
+ int i,j;
+ FILE *fp;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imrelp)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imrelp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "port")) {
+ inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ #if defined(HAVE_RELPSRVSETLSTNADDR)
+ inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ #else
+ parser_errmsg("imrelp: librelp does not support input parameter 'address'; "
+ "it probably is too old (1.2.16 should be fine); ignoring setting now, "
+ "listening on all interfaces");
+ #endif
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "maxdatasize")) {
+ inst->maxDataSize = (size_t) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ if(!es_strconstcmp(pvals[i].val.d.estr, "none")) {
+ inst->flowCtlType = eFLOWCTL_NO_DELAY;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "light")) {
+ inst->flowCtlType = eFLOWCTL_LIGHT_DELAY;
+ } else if(!es_strconstcmp(pvals[i].val.d.estr, "full")) {
+ inst->flowCtlType = eFLOWCTL_FULL_DELAY;
+ } else {
+ const char *const mode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ parser_errmsg("imrelp: wrong flowcontrol parameter "
+ "value '%s', using default: 'light'; possible "
+ "values: 'no', 'light', 'full'\n", mode);
+ free((void*)mode);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "oversizemode")) {
+#ifdef HAVE_RELPSRVSETOVERSIZEMODE
+ char *mode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcmp(mode, "abort")) {
+ inst->oversizeMode = RELP_OVERSIZE_ABORT;
+ } else if(!strcmp(mode, "truncate")) {
+ inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
+ } else if(!strcmp(mode, "accept")) {
+ inst->oversizeMode = RELP_OVERSIZE_ACCEPT;
+ } else {
+ parser_errmsg("imrelp: wrong oversizeMode parameter "
+ "value %s, using default: truncate\n", mode);
+ inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
+ }
+#else
+ parser_errmsg("imrelp: parameter oversizeMode is not available in "
+ "this relp version and is therefore disabled.");
+#endif
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive")) {
+ inst->bKeepAlive = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.probes")) {
+ inst->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.time")) {
+ inst->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.interval")) {
+ inst->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "tls")) {
+ inst->bEnableTLS = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "tls.dhbits")) {
+ inst->dhBits = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "tls.prioritystring")) {
+ inst->pristring = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tls.authmode")) {
+ inst->authmode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "tls.compression")) {
+ inst->bEnableTLSZip = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "tls.cacert")) {
+ inst->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->caCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->caCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.mycert")) {
+ inst->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->myCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.myprivkey")) {
+ inst->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)inst->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ inst->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "tls.tlscfgcmd")) {
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ inst->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+#else
+ parser_errmsg("imrelp: librelp does not support input parameter 'tls.tlscfgcmd'; "
+ "it probably is too old (1.5.0 or higher should be fine); ignoring setting now.");
+#endif
+ } else if(!strcmp(inppblk.descr[i].name, "tls.permittedpeer")) {
+ inst->permittedPeers.nmemb = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(inst->permittedPeers.name =
+ malloc(sizeof(uchar*) * inst->permittedPeers.nmemb));
+ for(j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ inst->permittedPeers.name[j] = (uchar*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ }
+ } else {
+ dbgprintf("imrelp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ if(inst->myCertFile != NULL && inst->myPrivKeyFile == NULL) {
+ LogError(0, RS_RET_ERR, "imrelp: certificate file given but no corresponding "
+ "private key file - this is invalid, listener cannot be started");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(inst->myCertFile == NULL && inst->myPrivKeyFile != NULL) {
+ LogError(0, RS_RET_ERR, "imrelp: private key file given but no corresponding "
+ "certificate file - this is invalid, listener cannot be started");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ inst->bEnableLstn = -1; /* all ok, ready to start up */
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ if(iRet != RS_RET_OK) {
+ if(inst != NULL) {
+ free(inst->myCertFile);
+ inst->myCertFile = NULL;
+ free(inst->myPrivKeyFile);
+ inst->myPrivKeyFile = NULL;
+ }
+ }
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->pszBindRuleset = NULL;
+ pModConf->tlslib = NULL;
+ /* init legacy config variables */
+ cs.pszBindRuleset = NULL;
+ bLegacyCnfModGlobalsPermitted = 1;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imrelp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "ruleset")) {
+ loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "tls.tlslib")) {
+ #if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ loadModConf->tlslib = es_str2cstr(pvals[i].val.d.estr, NULL);
+ #else
+ LogError(0, RS_RET_NOT_IMPLEMENTED,
+ "imrelp warning: parameter tls.tlslib ignored - librelp does not support "
+ "this API call. Using whatever librelp was compiled with.");
+ #endif
+ } else {
+ dbgprintf("imrelp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+ /* remove all of our legacy module handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(loadModConf->pszBindRuleset == NULL) {
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ loadModConf->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(loadModConf->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ } else {
+ if((cs.pszBindRuleset != NULL) && (cs.pszBindRuleset[0] != '\0')) {
+ LogError(0, RS_RET_DUP_PARAM, "imrelp: ruleset "
+ "set via legacy directive ignored");
+ }
+ }
+finalize_it:
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+ size_t maxMessageSize;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst->pszBindRuleset == NULL && pModConf->pszBindRuleset != NULL) {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(pModConf->pszBindRuleset));
+ }
+ std_checkRuleset(pModConf, inst);
+
+
+ if(inst->maxDataSize == 0) {
+ /* We set default value for maxDataSize here because
+ * otherwise the maxMessageSize isn't set.
+ */
+ inst->maxDataSize = glbl.GetMaxLine(loadConf);
+ }
+ maxMessageSize = (size_t)glbl.GetMaxLine(loadConf);
+ if(inst->maxDataSize < maxMessageSize) {
+ LogError(0, RS_RET_INVALID_PARAMS, "error: "
+ "maxDataSize (%zu) is smaller than global parameter "
+ "maxMessageSize (%zu) - global parameter will be used.",
+ inst->maxDataSize, maxMessageSize);
+ inst->maxDataSize = maxMessageSize;
+ }
+ }
+
+finalize_it:
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(pModConf, inst);
+ }
+ if(pRelpEngine == NULL) {
+ LogError(0, RS_RET_NO_LSTN_DEFINED, "imrelp: no RELP listener defined, module can not run.");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+ int i;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindPort);
+ if (inst->pszBindAddr != NULL) {
+ free(inst->pszBindAddr);
+ }
+ free(inst->pszBindRuleset);
+ free(inst->pszInputName);
+ free(inst->pristring);
+ free(inst->authmode);
+ for(i = 0 ; i < inst->permittedPeers.nmemb ; ++i) {
+ free(inst->permittedPeers.name[i]);
+ }
+ if(inst->bEnableLstn) {
+ prop.Destruct(&inst->pInputName);
+ statsobj.Destruct(&(inst->data.stats));
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ free(pModConf->pszBindRuleset);
+ENDfreeCnf
+
+/* This is used to terminate the plugin. Note that the signal handler blocks
+ * other activity on the thread. As such, it is safe to request the stop. When
+ * we terminate, relpEngine is called, and it's select() loop interrupted. But
+ * only *after this function is done*. So we do not have a race!
+ */
+static void
+doSIGTTIN(int __attribute__((unused)) sig)
+{
+ const int bTerminate = ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
+ if(bTerminate && (pRelpEngine != NULL)) {
+ relpEngineSetStop(pRelpEngine);
+ }
+}
+
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+ sigset_t sigSet;
+ struct sigaction sigAct;
+CODESTARTrunInput
+ /* we want to support non-cancel input termination. To do so, we must signal librelp
+ * when to stop. As we run on the same thread, we need to register as SIGTTIN handler,
+ * which will be used to put the terminating condition into librelp.
+ */
+ sigfillset(&sigSet);
+ pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
+ sigemptyset(&sigSet);
+ sigaddset(&sigSet, SIGTTIN);
+ pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
+ memset(&sigAct, 0, sizeof (sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = doSIGTTIN;
+ sigaction(SIGTTIN, &sigAct, NULL);
+
+ iRet = relpEngineRun(pRelpEngine);
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ /* do cleanup here */
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ struct sigaction newAct;
+ memset(&newAct, 0, sizeof (newAct));
+ sigemptyset(&newAct.sa_mask);
+ newAct.sa_handler = SIG_IGN;
+ sigaction(SIGTTIN, &newAct, NULL);
+
+ if(pRelpEngine != NULL)
+ iRet = relpEngineDestruct(&pRelpEngine);
+
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ pRelpEngine = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ #ifndef HAVE_RELPSRVSETOVERSIZEMODE
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imrelp: librelp too old, oversizemode "
+ "defaults to \"abort\"");
+ #endif
+
+ /* register config file handlers */
+ CHKiRet(regCfSysLineHdlr2((uchar*)"inputrelpserverbindruleset", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrelpserverrun", 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/imsolaris/Makefile.am b/plugins/imsolaris/Makefile.am
new file mode 100644
index 0000000..b4ee1c2
--- /dev/null
+++ b/plugins/imsolaris/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imsolaris.la
+
+imsolaris_la_SOURCES = imsolaris.c sun_cddl.c sun_cddl.h imsolaris.h
+imsolaris_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imsolaris_la_LDFLAGS = -module -avoid-version
+imsolaris_la_LIBADD = -ldoor -lpthread
diff --git a/plugins/imsolaris/Makefile.in b/plugins/imsolaris/Makefile.in
new file mode 100644
index 0000000..e47a50c
--- /dev/null
+++ b/plugins/imsolaris/Makefile.in
@@ -0,0 +1,808 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/imsolaris
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imsolaris_la_DEPENDENCIES =
+am_imsolaris_la_OBJECTS = imsolaris_la-imsolaris.lo \
+ imsolaris_la-sun_cddl.lo
+imsolaris_la_OBJECTS = $(am_imsolaris_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 =
+imsolaris_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imsolaris_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imsolaris_la-imsolaris.Plo \
+ ./$(DEPDIR)/imsolaris_la-sun_cddl.Plo
+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 = $(imsolaris_la_SOURCES)
+DIST_SOURCES = $(imsolaris_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imsolaris.la
+imsolaris_la_SOURCES = imsolaris.c sun_cddl.c sun_cddl.h imsolaris.h
+imsolaris_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imsolaris_la_LDFLAGS = -module -avoid-version
+imsolaris_la_LIBADD = -ldoor -lpthread
+all: 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) --gnu plugins/imsolaris/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imsolaris/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imsolaris.la: $(imsolaris_la_OBJECTS) $(imsolaris_la_DEPENDENCIES) $(EXTRA_imsolaris_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imsolaris_la_LINK) -rpath $(pkglibdir) $(imsolaris_la_OBJECTS) $(imsolaris_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imsolaris_la-imsolaris.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imsolaris_la-sun_cddl.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imsolaris_la-imsolaris.lo: imsolaris.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imsolaris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imsolaris_la-imsolaris.lo -MD -MP -MF $(DEPDIR)/imsolaris_la-imsolaris.Tpo -c -o imsolaris_la-imsolaris.lo `test -f 'imsolaris.c' || echo '$(srcdir)/'`imsolaris.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imsolaris_la-imsolaris.Tpo $(DEPDIR)/imsolaris_la-imsolaris.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imsolaris.c' object='imsolaris_la-imsolaris.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) $(imsolaris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imsolaris_la-imsolaris.lo `test -f 'imsolaris.c' || echo '$(srcdir)/'`imsolaris.c
+
+imsolaris_la-sun_cddl.lo: sun_cddl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imsolaris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imsolaris_la-sun_cddl.lo -MD -MP -MF $(DEPDIR)/imsolaris_la-sun_cddl.Tpo -c -o imsolaris_la-sun_cddl.lo `test -f 'sun_cddl.c' || echo '$(srcdir)/'`sun_cddl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imsolaris_la-sun_cddl.Tpo $(DEPDIR)/imsolaris_la-sun_cddl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sun_cddl.c' object='imsolaris_la-sun_cddl.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) $(imsolaris_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imsolaris_la-sun_cddl.lo `test -f 'sun_cddl.c' || echo '$(srcdir)/'`sun_cddl.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imsolaris_la-imsolaris.Plo
+ -rm -f ./$(DEPDIR)/imsolaris_la-sun_cddl.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imsolaris_la-imsolaris.Plo
+ -rm -f ./$(DEPDIR)/imsolaris_la-sun_cddl.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imsolaris/imsolaris.c b/plugins/imsolaris/imsolaris.c
new file mode 100644
index 0000000..eff8ffb
--- /dev/null
+++ b/plugins/imsolaris/imsolaris.c
@@ -0,0 +1,437 @@
+/* imsolaris.c
+ * This input module is used to gather local log data under Solaris. This
+ * includes messages from local applications AS WELL AS the kernel log.
+ * I first considered to make all of this available via imklog, but that
+ * did not lock appropriately on second thought. So I created this module
+ * that does anything for local message recption.
+ *
+ * This module is not meant to be used on plaforms other than Solaris. As
+ * such, trying to compile it elswhere will probably fail with all sorts
+ * of errors.
+ *
+ * Some notes on the Solaris syslog mechanism:
+ * Both system (kernel) and application log messages are provided via
+ * a single message stream.
+ *
+ * Solaris checks if the syslogd is running. If so, syslog() emits messages
+ * to the log socket, only. Otherwise, it emits messages to the console.
+ * It is possible to gather these console messages as well. However, then
+ * we clutter the console.
+ * Solaris does this "syslogd alive check" in a somewhat unexpected way
+ * (at least unexpected for me): it uses the so-called "door" mechanism, a
+ * fast RPC facility. I first thought that the door API was used to submit
+ * the actual syslog messages. But this is not the case. Instead, a door
+ * call is done, and the server process inside rsyslog simply does NOTHING
+ * but return. All that Solaris sylsogd() is interested in is if the door
+ * server (we) responds and thus can be considered alive. The actual message
+ * is then submitted via the usual stream. I have to admit I do not
+ * understand why the message itself is not passed via this high-performance
+ * API. But anyhow, that's nothing I can change, so the most important thing
+ * is to note how Solaris does this thing ;)
+ * The syslog() library call checks syslogd state for *each* call (what a
+ * waste of time...) and decides each time if the message should go to the
+ * console or not. According to OpenSolaris sources, it looks like there is
+ * message loss potential when the door file is created before all data has
+ * been pulled from the stream. While I have to admit that I do not fully
+ * understand that problem, I will follow the original code advise and do
+ * one complete pull cycle on the log socket (until it has no further data
+ * available) and only thereafter create the door file and start the "regular"
+ * pull cycle. As of my understanding, there is a minimal race between the
+ * point where the intial pull cycle has ended and the door file is created,
+ * but that race is also present in OpenSolaris syslogd code, so it should
+ * not matter that much (plus, I do not know how to avoid it...)
+ *
+ * File begun on 2010-04-15 by RGerhards
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+#include <stropts.h>
+#include <sys/strlog.h>
+#include <errno.h>
+#include "dirty.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "net.h"
+#include "glbl.h"
+#include "msg.h"
+#include "prop.h"
+#include "sun_cddl.h"
+#include "datetime.h"
+#include "rsconf.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imsolaris")
+
+/* defines */
+#define PATH_LOG "/dev/log"
+
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(datetime)
+
+
+/* config settings */
+struct modConfData_s {
+ EMPTY_STRUCT;
+};
+
+static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */
+static char *LogName = NULL; /* the log socket name TODO: make configurable! */
+
+
+/* a function to replace the sun logerror() function.
+ * It generates an error message from the supplied string. The main
+ * reason for not calling logError directly is that sun_cddl.c does not
+ * know or has acces to rsyslog objects (namely errmsg) -- and we do not
+ * want to do this effort. -- rgerhards, 2010-04-19
+ */
+void
+imsolaris_logerror(int err, char *errStr)
+{
+ LogError(err, RS_RET_ERR_DOOR, "%s", errStr);
+}
+
+
+/* we try to recover a failed file by closing and re-opening
+ * it. We loop until the re-open works, but wait between each
+ * failure. If the open succeeds, we assume all is well. If it is
+ * not, we will run into the retry process with the next
+ * iteration.
+ * rgerhards, 2010-04-19
+ */
+static void
+tryRecover(void)
+{
+ int tryNum = 1;
+ int waitsecs;
+ int waitusecs;
+ rsRetVal iRet;
+
+ close(sun_Pfd.fd);
+ sun_Pfd.fd = -1;
+
+ while(1) { /* loop broken inside */
+ iRet = sun_openklog((LogName == NULL) ? PATH_LOG : LogName);
+ if(iRet == RS_RET_OK) {
+ if(tryNum > 1) {
+ LogError(0, iRet, "failure on system log socket recovered.");
+ }
+ break;
+ }
+ /* failure, so sleep a bit. We wait try*10 ms, with a max of 15 seconds */
+ if(tryNum == 1) {
+ LogError(0, iRet, "failure on system log socket, trying to recover...");
+ }
+ waitusecs = tryNum * 10000;
+ waitsecs = waitusecs / 1000000;
+ DBGPRINTF("imsolaris: try %d to recover system log socket in %d.%d seconds\n",
+ tryNum, waitsecs, waitusecs);
+ if(waitsecs > 15) {
+ waitsecs = 15;
+ waitusecs = 0;
+ } else {
+ waitusecs = waitusecs % 1000000;
+ }
+ srSleep(waitsecs, waitusecs);
+ ++tryNum;
+ }
+}
+
+
+/* This function receives data from a socket indicated to be ready
+ * to receive and submits the message received for processing.
+ * rgerhards, 2007-12-20
+ * Interface changed so that this function is passed the array index
+ * of the socket which is to be processed. This eases access to the
+ * growing number of properties. -- rgerhards, 2008-08-01
+ */
+static rsRetVal
+readLog(int fd, uchar *pRcv, int iMaxLine)
+{
+ DEFiRet;
+ struct strbuf data;
+ struct strbuf ctl;
+ struct log_ctl hdr;
+ struct timeval tim;
+ int flags;
+ smsg_t *pMsg;
+ int ret;
+ char errStr[1024];
+
+ data.buf = (char*)pRcv;
+ data.maxlen = iMaxLine;
+ ctl.maxlen = sizeof (struct log_ctl);
+ ctl.buf = (caddr_t)&hdr;
+ flags = 0;
+ ret = getmsg(fd, &ctl, &data, &flags);
+ if(ret < 0) {
+ if(errno == EINTR) {
+ FINALIZE;
+ } else {
+ int en = errno;
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("imsolaris: stream input error on fd %d: %s.\n", fd, errStr);
+ LogError(en, NO_ERRCODE, "imsolaris: stream input error: %s", errStr);
+ tryRecover();
+ }
+ } else {
+ DBGPRINTF("imsolaris: message from log stream %d: %s\n", fd, pRcv);
+ pRcv[data.len] = '\0'; /* make sure it is a valid C-String */
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)pRcv, strlen((char*)pRcv));
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ msgSetPRI(pMsg, hdr.pri);
+ pMsg->msgFlags = NEEDS_PARSING | NO_PRI_IN_RAW | IGNDATE;
+
+ /* Construct timestamp from msg ctl struct */
+ tim.tv_usec = 0;
+ tim.tv_sec = hdr.ttime;
+ datetime.timeval2syslogTime(&tim, &pMsg->tRcvdAt, TIME_IN_LOCALTIME);
+ CHKiRet(submitMsg(pMsg));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* once the system is fully initialized, we wait for new messages.
+ * We may think about replacing this with a read-loop, thus saving
+ * us the overhead of the poll.
+ * The timeout variable is the timeout to use for poll. During startup,
+ * it should be set to 0 (non-blocking) and later to -1 (infinit, blocking).
+ * This mimics the (strange) behaviour of the original syslogd.
+ * rgerhards, 2010-04-19
+ */
+static rsRetVal
+getMsgs(thrdInfo_t *pThrd, int timeout)
+{
+ DEFiRet;
+ int nfds;
+ int iMaxLine;
+ uchar *pRcv = NULL; /* receive buffer */
+ uchar bufRcv[4096+1];
+ char errStr[1024];
+
+ iMaxLine = glbl.GetMaxLine(runConf);
+
+ /* we optimize performance: if iMaxLine is below 4K (which it is in almost all
+ * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
+ * is used. We could use alloca() to achive a similar aspect, but there are so
+ * many issues with alloca() that I do not want to take that route.
+ * rgerhards, 2008-09-02
+ */
+ if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
+ pRcv = bufRcv;
+ } else {
+ CHKmalloc(pRcv = (uchar*) malloc(iMaxLine + 1));
+ }
+
+ while(pThrd->bShallStop != RSTRUE) {
+ DBGPRINTF("imsolaris: waiting for next message (timeout %d)...\n", timeout);
+ if(timeout == 0) {
+ nfds = poll(&sun_Pfd, 1, timeout); /* wait without timeout */
+
+ if(pThrd->bShallStop == RSTRUE) {
+ break;
+ }
+
+ if(nfds == 0) {
+ if(timeout == 0) {
+ DBGPRINTF("imsolaris: no more messages, getMsgs() terminates\n");
+ FINALIZE;
+ } else {
+ continue;
+ }
+ }
+
+ if(nfds < 0) {
+ if(errno != EINTR) {
+ int en = errno;
+ rs_strerror_r(en, errStr, sizeof(errStr));
+ DBGPRINTF("imsolaris: poll error: %d = %s.\n", errno, errStr);
+ LogError(en, NO_ERRCODE, "imsolaris: poll error: %s",
+ errStr);
+ }
+ continue;
+ }
+ if(sun_Pfd.revents & POLLIN) {
+ readLog(sun_Pfd.fd, pRcv, iMaxLine);
+ } else if(sun_Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
+ tryRecover();
+ }
+ } else {
+ /* if we have an infinite wait, we do not use poll at all
+ * I'd consider this a waste of time. However, I do not totally
+ * remove the code, as it may be useful if we decide at some
+ * point to provide a capability to support multiple input streams
+ * at once (this may be useful for a jail). In that case, the poll()
+ * loop would be needed, and so it doesn't make much sense to change
+ * the code to not support it. -- rgerhards, 2010-04-20
+ */
+ readLog(sun_Pfd.fd, pRcv, iMaxLine);
+ }
+
+ }
+
+finalize_it:
+ if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
+ free(pRcv);
+
+ RETiRet;
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+/* This function is called to gather input. */
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+
+ DBGPRINTF("imsolaris: doing startup poll before openeing door()\n");
+ CHKiRet(getMsgs(pThrd, 0));
+
+ /* note: sun's syslogd code claims that the door should only
+ * be opened when the log stream has been polled. So file header
+ * comment of this file for more details.
+ */
+ sun_open_door();
+ DBGPRINTF("imsolaris: starting regular poll loop\n");
+ iRet = getMsgs(pThrd, -1); /* this is the primary poll loop, infinite timeout */
+
+ DBGPRINTF("imsolaris: terminating (bShallStop=%d)\n", pThrd->bShallStop);
+finalize_it:
+ RETiRet;
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imsolaris"), sizeof("imsolaris") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ iRet = sun_openklog((LogName == NULL) ? PATH_LOG : LogName);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "error opening system log socket");
+ }
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ /* do cleanup here */
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ free(LogName);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ sun_delete_doorfiles();
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp,
+ void __attribute__((unused)) *pVal)
+{
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("imsolaris version %s initializing\n", PACKAGE_VERSION);
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imsolarislogsocketname", 0, eCmdHdlrGetWord,
+ NULL, &LogName, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imsolaris/imsolaris.h b/plugins/imsolaris/imsolaris.h
new file mode 100644
index 0000000..e73380f
--- /dev/null
+++ b/plugins/imsolaris/imsolaris.h
@@ -0,0 +1,2 @@
+rsRetVal solaris_readLog(int fd);
+void imsolaris_logerror(int err, char *errStr);
diff --git a/plugins/imsolaris/sun_cddl.c b/plugins/imsolaris/sun_cddl.c
new file mode 100644
index 0000000..6bdc31c
--- /dev/null
+++ b/plugins/imsolaris/sun_cddl.c
@@ -0,0 +1,420 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Portions Copyright 2010-2014 by Rainer Gerhards and Adiscon
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
+ * All Rights Reserved
+ */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+#include "config.h"
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <stropts.h>
+#include <assert.h>
+
+#include <sys/param.h>
+#include <sys/strlog.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <door.h>
+#include <sys/door.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "debug.h"
+#include "imsolaris.h"
+
+#define DOORFILE "/var/run/syslog_door"
+#define RELATIVE_DOORFILE "../var/run/syslog_door"
+#define OLD_DOORFILE "/etc/.syslog_door"
+
+/* Buffer to allocate for error messages: */
+#define ERRMSG_LEN 1024
+
+/* Max number of door server threads for syslogd. Since door is used
+ * to check the health of syslogd, we don't need large number of
+ * server threads.
+ */
+#define MAX_DOOR_SERVER_THR 3
+
+
+struct pollfd sun_Pfd; /* Pollfd for local log device */
+
+static int DoorFd = -1;
+static int DoorCreated = 0;
+static char *DoorFileName = DOORFILE;
+
+/* for managing door server threads */
+static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint_t door_server_cnt = 0;
+static pthread_attr_t door_thr_attr;
+
+/* the 'server' function that we export via the door. It does
+ * nothing but return.
+ */
+/*ARGSUSED*/
+static void
+server( void __attribute__((unused)) *cookie,
+ char __attribute__((unused)) *argp,
+ size_t __attribute__((unused)) arg_size,
+ door_desc_t __attribute__((unused)) *dp,
+ __attribute__((unused)) uint_t n )
+{
+ (void) door_return(NULL, 0, NULL, 0);
+ /* NOTREACHED */
+}
+
+/*ARGSUSED*/
+static void *
+create_door_thr(void __attribute__((unused)) *arg)
+{
+ (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ (void) door_return(NULL, 0, NULL, 0);
+
+ /* If there is an error in door_return(), it will return here and
+ * the thread will exit. Hence we need to decrement door_server_cnt.
+ */
+ (void) pthread_mutex_lock(&door_server_cnt_lock);
+ door_server_cnt--;
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+ return (NULL);
+}
+
+/*
+ * Manage door server thread pool.
+ */
+/*ARGSUSED*/
+static void
+door_server_pool(door_info_t __attribute__((unused)) *dip)
+{
+ (void) pthread_mutex_lock(&door_server_cnt_lock);
+ if (door_server_cnt <= MAX_DOOR_SERVER_THR &&
+ pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) {
+ door_server_cnt++;
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+ return;
+ }
+
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+}
+
+void
+sun_delete_doorfiles(void)
+{
+ struct stat sb;
+ int err;
+ char line[ERRMSG_LEN+1];
+
+ if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(DoorFileName) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed - fatal", DoorFileName);
+ imsolaris_logerror(err, line);
+ DBGPRINTF("delete_doorfiles: error: %s, "
+ "errno=%d\n", line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles: deleted %s\n", DoorFileName);
+ }
+
+ if (strcmp(DoorFileName, DOORFILE) == 0) {
+ if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed", OLD_DOORFILE);
+ DBGPRINTF("delete_doorfiles: %s\n", line);
+
+ if (err != EROFS) {
+ errno = err;
+ (void) strlcat(line, " - fatal",
+ sizeof (line));
+ imsolaris_logerror(err, line);
+ DBGPRINTF("delete_doorfiles: "
+ "error: %s, errno=%d\n",
+ line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles: unlink() "
+ "failure OK on RO file system\n");
+ }
+
+ DBGPRINTF("delete_doorfiles: deleted %s\n",
+ OLD_DOORFILE);
+ }
+ }
+
+ if (DoorFd != -1) {
+ (void) door_revoke(DoorFd);
+ }
+
+ DBGPRINTF("delete_doorfiles: revoked door: DoorFd=%d\n",
+ DoorFd);
+}
+
+
+/* Create the door file. If the filesystem
+ * containing /etc is writable, create symlinks /etc/.syslog_door
+ * to them. On systems that do not support /var/run, create
+ * /etc/.syslog_door directly.
+ */
+void
+sun_open_door(void)
+{
+ struct stat buf;
+ door_info_t info;
+ char line[ERRMSG_LEN+1];
+ int err;
+
+ /* first see if another instance of imsolaris OR another
+ * syslogd is running by trying a door call - if it succeeds,
+ * there is already one active.
+ */
+
+ if (!DoorCreated) {
+ int door;
+
+ if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
+ DBGPRINTF("open_door: %s opened "
+ "successfully\n", DoorFileName);
+
+ if (door_info(door, &info) >= 0) {
+ DBGPRINTF("open_door: "
+ "door_info:info.di_target = %ld\n",
+ info.di_target);
+
+ if (info.di_target > 0) {
+ (void) sprintf(line, "syslogd pid %ld"
+ " already running. Cannot "
+ "start another syslogd pid %ld",
+ info.di_target, getpid());
+ DBGPRINTF("open_door: error: "
+ "%s\n", line);
+ imsolaris_logerror(0, line);
+ exit(1);
+ }
+ }
+
+ (void) close(door);
+ } else {
+ if (lstat(DoorFileName, &buf) < 0) {
+ err = errno;
+
+ DBGPRINTF("open_door: lstat() of %s "
+ "failed, errno=%d\n",
+ DoorFileName, err);
+
+ if ((door = creat(DoorFileName, 0644)) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "creat() of %s failed - fatal",
+ DoorFileName);
+ DBGPRINTF("open_door: error: %s, "
+ "errno=%d\n", line,
+ err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ (void) fchmod(door,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+ DBGPRINTF("open_door: creat() of %s "
+ "succeeded\n",
+ DoorFileName);
+
+ (void) close(door);
+ }
+ }
+
+ if (strcmp(DoorFileName, DOORFILE) == 0) {
+ if (lstat(OLD_DOORFILE, &buf) == 0) {
+ DBGPRINTF("open_door: lstat() of %s "
+ "succeeded\n", OLD_DOORFILE);
+
+ if (S_ISDIR(buf.st_mode)) {
+ (void) snprintf(line, sizeof (line),
+ "%s is a directory - fatal",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door: error: "
+ "%s\n", line);
+ imsolaris_logerror(0, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: %s is not a "
+ "directory\n", OLD_DOORFILE);
+ if (unlink(OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door: %s\n",
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door: "
+ "error: %s, "
+ "errno=%d\n",
+ line, err);
+ (void) strcat(line, " - fatal");
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: unlink "
+ "failure OK on RO file "
+ "system\n");
+ }
+ } else {
+ DBGPRINTF("open_door: file %s doesn't "
+ "exist\n", OLD_DOORFILE);
+ }
+
+ if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "symlink %s -> %s failed", OLD_DOORFILE,
+ RELATIVE_DOORFILE);
+ DBGPRINTF("open_door: %s\n",
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door: error: %s, "
+ "errno=%d\n", line,
+ err);
+ (void) strcat(line, " - fatal");
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: symlink failure OK "
+ "on RO file system\n");
+ } else {
+ DBGPRINTF("open_door: symlink %s -> %s "
+ "succeeded\n",
+ OLD_DOORFILE, RELATIVE_DOORFILE);
+ }
+ }
+
+ if ((DoorFd = door_create(server, 0,
+ DOOR_REFUSE_DESC)) < 0) {
+ //???? DOOR_NO_CANEL requires newer libs??? DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
+ err = errno;
+ (void) sprintf(line, "door_create() failed - fatal");
+ DBGPRINTF("open_door: error: %s, errno=%d\n",
+ line, err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+ //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
+ DBGPRINTF("open_door: door_create() succeeded, "
+ "DoorFd=%d\n", DoorFd);
+
+ DoorCreated = 1;
+ }
+
+ (void) fdetach(DoorFileName); /* just in case... */
+
+ (void) door_server_create(door_server_pool);
+
+ if (fattach(DoorFd, DoorFileName) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line), "fattach() of fd"
+ " %d to %s failed - fatal", DoorFd, DoorFileName);
+ DBGPRINTF("open_door: error: %s, errno=%d\n",
+ line, err);
+ imsolaris_logerror(err, line);
+ sun_delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door: attached server() to %s\n",
+ DoorFileName);
+
+}
+
+
+/* Attempts to open the local log device
+ * and return a file descriptor.
+ */
+rsRetVal
+sun_openklog(char *name)
+{
+ DEFiRet;
+ int fd;
+ struct strioctl str;
+ char errBuf[1024];
+
+ if((fd = open(name, O_RDONLY)) < 0) {
+ rs_strerror_r(errno, errBuf, sizeof(errBuf));
+ DBGPRINTF("imsolaris:openklog: cannot open %s: %s\n",
+ name, errBuf);
+ ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG);
+ }
+ str.ic_cmd = I_CONSLOG;
+ str.ic_timout = 0;
+ str.ic_len = 0;
+ str.ic_dp = NULL;
+ if (ioctl(fd, I_STR, &str) < 0) {
+ rs_strerror_r(errno, errBuf, sizeof(errBuf));
+ DBGPRINTF("imsolaris:openklog: cannot register to log "
+ "console messages: %s\n", errBuf);
+ ABORT_FINALIZE(RS_RET_ERR_AQ_CONLOG);
+ }
+ sun_Pfd.fd = fd;
+ sun_Pfd.events = POLLIN;
+ DBGPRINTF("imsolaris/openklog: opened '%s' as fd %d.\n", name, fd);
+
+finalize_it:
+ RETiRet;
+}
diff --git a/plugins/imsolaris/sun_cddl.h b/plugins/imsolaris/sun_cddl.h
new file mode 100644
index 0000000..42e4b79
--- /dev/null
+++ b/plugins/imsolaris/sun_cddl.h
@@ -0,0 +1,7 @@
+rsRetVal sun_openklog(char *name);
+void prepare_sys_poll(void);
+void sun_sys_poll(void);
+void sun_open_door(void);
+void sun_delete_doorfiles(void);
+
+extern struct pollfd sun_Pfd; /* Pollfd for local log device */
diff --git a/plugins/imtcp/Makefile.am b/plugins/imtcp/Makefile.am
new file mode 100644
index 0000000..f2ab10f
--- /dev/null
+++ b/plugins/imtcp/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = imtcp.la
+
+imtcp_la_SOURCES = imtcp.c
+imtcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imtcp_la_LDFLAGS = -module -avoid-version
+imtcp_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+imtcp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+imtcp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/imtcp/Makefile.in b/plugins/imtcp/Makefile.in
new file mode 100644
index 0000000..b3aaedc
--- /dev/null
+++ b/plugins/imtcp/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/imtcp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imtcp_la_DEPENDENCIES =
+am_imtcp_la_OBJECTS = imtcp_la-imtcp.lo
+imtcp_la_OBJECTS = $(am_imtcp_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 =
+imtcp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imtcp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imtcp_la-imtcp.Plo
+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 = $(imtcp_la_SOURCES)
+DIST_SOURCES = $(imtcp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imtcp.la
+imtcp_la_SOURCES = imtcp.c
+imtcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_1)
+imtcp_la_LDFLAGS = -module -avoid-version $(am__append_2)
+imtcp_la_LIBADD =
+all: 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) --gnu plugins/imtcp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imtcp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imtcp.la: $(imtcp_la_OBJECTS) $(imtcp_la_DEPENDENCIES) $(EXTRA_imtcp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imtcp_la_LINK) -rpath $(pkglibdir) $(imtcp_la_OBJECTS) $(imtcp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imtcp_la-imtcp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imtcp_la-imtcp.lo: imtcp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imtcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imtcp_la-imtcp.lo -MD -MP -MF $(DEPDIR)/imtcp_la-imtcp.Tpo -c -o imtcp_la-imtcp.lo `test -f 'imtcp.c' || echo '$(srcdir)/'`imtcp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imtcp_la-imtcp.Tpo $(DEPDIR)/imtcp_la-imtcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imtcp.c' object='imtcp_la-imtcp.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) $(imtcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imtcp_la-imtcp.lo `test -f 'imtcp.c' || echo '$(srcdir)/'`imtcp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imtcp_la-imtcp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imtcp_la-imtcp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
new file mode 100644
index 0000000..0c31c93
--- /dev/null
+++ b/plugins/imtcp/imtcp.c
@@ -0,0 +1,1192 @@
+/* imtcp.c
+ * This is the implementation of the TCP input module.
+ *
+ * File begun on 2007-12-21 by RGerhards (extracted from syslogd.c,
+ * which at the time of the rsyslog fork was BSD-licensed)
+ *
+ * Copyright 2007-2022 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This note shall explain the calling sequence while we do not have
+ * have full RainerScript support for (TLS) sender authentication:
+ *
+ * imtcp --> tcpsrv --> netstrms (this sequence stored pPermPeers in netstrms class)
+ * then a callback (doOpenLstnSocks) into imtcp happens, which in turn calls
+ * into tcpsrv.create_tcp_socket(),
+ * which calls into netstrm.LstnInit(), which receives a pointer to netstrms obj
+ * which calls into the driver function LstnInit (again, netstrms obj passed)
+ * which finally calls back into netstrms obj's get functions to obtain the auth
+ * parameters and then applies them to the driver object instance
+ *
+ * rgerhards, 2008-05-19
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "netstrm.h"
+#include "errmsg.h"
+#include "tcpsrv.h"
+#include "ruleset.h"
+#include "rainerscript.h"
+#include "net.h"
+#include "parserif.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imtcp")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(tcpsrv)
+DEFobjCurrIf(tcps_sess)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(ruleset)
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* Module static data */
+typedef struct tcpsrv_etry_s {
+ tcpsrv_t *tcpsrv;
+ pthread_t tid; /* the worker's thread ID */
+ struct tcpsrv_etry_s *next;
+} tcpsrv_etry_t;
+static tcpsrv_etry_t *tcpsrv_root = NULL;
+static int n_tcpsrv = 0;
+
+static permittedPeers_t *pPermPeersRoot = NULL;
+
+#define FRAMING_UNSET -1
+
+/* config settings */
+static struct configSettings_s {
+ int iTCPSessMax;
+ int iTCPLstnMax;
+ int bSuppOctetFram;
+ int iStrmDrvrMode;
+ int bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int bEmitMsgOnClose;
+ int bEmitMsgOnOpen;
+ int iAddtlFrameDelim;
+ int maxFrameSize;
+ int bDisableLFDelim;
+ int discardTruncatedMsg;
+ int bUseFlowControl;
+ int bPreserveCase;
+ uchar *gnutlsPriorityString;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrPermitExpiredCerts;
+ uchar *pszInputName;
+ uchar *pszBindRuleset;
+ uchar *lstnIP; /* which IP we should listen on? */
+ uchar *lstnPortFile;
+} cs;
+
+struct instanceConf_s {
+ int iTCPSessMax;
+ int iTCPLstnMax;
+ tcpLstnParams_t *cnf_params; /**< listener config parameters */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ uchar *dfltTZ;
+ sbool bSPFramingFix;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ int maxFrameSize;
+ int bUseFlowControl;
+ int bDisableLFDelim;
+ int discardTruncatedMsg;
+ int bEmitMsgOnClose;
+ int bEmitMsgOnOpen;
+ int bPreserveCase;
+ uchar *pszStrmDrvrName; /* stream driver to use */
+ int iStrmDrvrMode;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrPermitExpiredCerts;
+ uchar *pszStrmDrvrCAFile;
+ uchar *pszStrmDrvrCRLFile;
+ uchar *pszStrmDrvrKeyFile;
+ uchar *pszStrmDrvrCertFile;
+ permittedPeers_t *pPermPeersRoot;
+ uchar *gnutlsPriorityString;
+ int iStrmDrvrExtendedCertCheck;
+ int iStrmDrvrSANPreference;
+ int iStrmTlsVerifyDepth;
+ int bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ struct instanceConf_s *next;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ int iTCPSessMax; /* max number of sessions */
+ int iTCPLstnMax; /* max number of sessions */
+ int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */
+ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */
+ int iStrmTlsVerifyDepth; /**< Verify Depth for certificate chains */
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ int maxFrameSize;
+ int bSuppOctetFram;
+ sbool bDisableLFDelim; /* disable standard LF delimiter */
+ sbool discardTruncatedMsg;
+ sbool bUseFlowControl; /* use flow control, what means indicate ourselfs a "light delayable" */
+ sbool bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ sbool bEmitMsgOnClose; /* emit an informational message on close by remote peer */
+ sbool bEmitMsgOnOpen; /* emit an informational message on close by remote peer */
+ uchar *gnutlsPriorityString;
+ uchar *pszStrmDrvrName; /* stream driver to use */
+ uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
+ uchar *pszStrmDrvrPermitExpiredCerts; /* control how to handly expired certificates */
+ uchar *pszStrmDrvrCAFile;
+ uchar *pszStrmDrvrCRLFile;
+ uchar *pszStrmDrvrKeyFile;
+ uchar *pszStrmDrvrCertFile;
+ permittedPeers_t *pPermPeersRoot;
+ sbool configSetViaV2Method;
+ sbool bPreserveCase; /* preserve case of fromhost; true by default */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "octetcountedframing", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionclose", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionopen", eCmdHdlrBinary, 0 },
+ { "addtlframedelimiter", eCmdHdlrNonNegInt, 0 },
+ { "maxframesize", eCmdHdlrInt, 0 },
+ { "maxsessions", eCmdHdlrPositiveInt, 0 },
+ { "maxlistners", eCmdHdlrPositiveInt, 0 },
+ { "maxlisteners", eCmdHdlrPositiveInt, 0 },
+ { "streamdriver.mode", eCmdHdlrNonNegInt, 0 },
+ { "streamdriver.authmode", eCmdHdlrString, 0 },
+ { "streamdriver.permitexpiredcerts", eCmdHdlrString, 0 },
+ { "streamdriver.name", eCmdHdlrString, 0 },
+ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
+ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
+ { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 },
+ { "permittedpeer", eCmdHdlrArray, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.time", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.interval", eCmdHdlrNonNegInt, 0 },
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
+ { "preservecase", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */
+ { "maxsessions", eCmdHdlrPositiveInt, 0 },
+ { "maxlisteners", eCmdHdlrPositiveInt, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionclose", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionopen", eCmdHdlrBinary, 0 },
+ { "addtlframedelimiter", eCmdHdlrNonNegInt, 0 },
+ { "maxframesize", eCmdHdlrInt, 0 },
+ { "preservecase", eCmdHdlrBinary, 0 },
+ { "listenportfilename", eCmdHdlrString, 0 },
+ { "address", eCmdHdlrString, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "defaulttz", eCmdHdlrString, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "streamdriver.mode", eCmdHdlrNonNegInt, 0 },
+ { "streamdriver.authmode", eCmdHdlrString, 0 },
+ { "streamdriver.permitexpiredcerts", eCmdHdlrString, 0 },
+ { "streamdriver.name", eCmdHdlrString, 0 },
+ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
+ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
+ { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 },
+ { "streamdriver.cafile", eCmdHdlrString, 0 },
+ { "streamdriver.keyfile", eCmdHdlrString, 0 },
+ { "streamdriver.certfile", eCmdHdlrString, 0 },
+ { "permittedpeer", eCmdHdlrArray, 0 },
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.time", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.interval", eCmdHdlrNonNegInt, 0 },
+ { "supportoctetcountedframing", eCmdHdlrBinary, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "framingfix.cisco.asa", eCmdHdlrBinary, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+/* callbacks */
+/* this shall go into a specific ACL module! */
+static int
+isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void __attribute__((unused)) *pUsrSrv,
+ void __attribute__((unused)) *pUsrSess)
+{
+ return net.isAllowedSender2(UCHAR_CONSTANT("TCP"), addr, fromHostFQDN, 1);
+}
+
+
+static rsRetVal
+doOpenLstnSocks(tcpsrv_t *pSrv)
+{
+ ISOBJ_TYPE_assert(pSrv, tcpsrv);
+ dbgprintf("in imtcp doOpenLstnSocks\n");
+ return tcpsrv.create_tcp_socket(pSrv);
+}
+
+
+static rsRetVal
+doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf, ssize_t *piLenRcvd, int *const oserr)
+{
+ assert(pSess != NULL);
+ assert(piLenRcvd != NULL);
+ *piLenRcvd = lenBuf;
+ return netstrm.Rcv(pSess->pStrm, (uchar*) buf, piLenRcvd, oserr);
+}
+
+static rsRetVal
+onRegularClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ /* process any incomplete frames left over */
+ tcps_sess.PrepareClose(pSess);
+ /* Session closed */
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+
+static rsRetVal
+onErrClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+
+/* set permitted peer -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRoot, pszID));
+ free(pszID); /* no longer needed, but we need to free as of interface def */
+finalize_it:
+ RETiRet;
+}
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst = NULL;
+
+ DEFiRet;
+ CHKmalloc(inst = (instanceConf_t*) calloc(1, sizeof(instanceConf_t)));
+ CHKmalloc(inst->cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
+ inst->next = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pszInputName = NULL;
+ inst->dfltTZ = NULL;
+ inst->cnf_params->bSuppOctetFram = -1; /* unset */
+ inst->bSPFramingFix = 0;
+ inst->ratelimitInterval = 0;
+ inst->ratelimitBurst = 10000;
+
+ inst->pszStrmDrvrName = NULL;
+ inst->pszStrmDrvrAuthMode = NULL;
+ inst->pszStrmDrvrPermitExpiredCerts = NULL;
+ inst->pszStrmDrvrCAFile = NULL;
+ inst->pszStrmDrvrCRLFile = NULL;
+ inst->pszStrmDrvrKeyFile = NULL;
+ inst->pszStrmDrvrCertFile = NULL;
+ inst->pPermPeersRoot = NULL;
+ inst->gnutlsPriorityString = NULL;
+ inst->iStrmDrvrMode = loadModConf->iStrmDrvrMode;
+ inst->iStrmDrvrExtendedCertCheck = loadModConf->iStrmDrvrExtendedCertCheck;
+ inst->iStrmDrvrSANPreference = loadModConf->iStrmDrvrSANPreference;
+ inst->iStrmTlsVerifyDepth = loadModConf->iStrmTlsVerifyDepth;
+ inst->bKeepAlive = loadModConf->bKeepAlive;
+ inst->iKeepAliveIntvl = loadModConf->iKeepAliveIntvl;
+ inst->iKeepAliveProbes = loadModConf->iKeepAliveProbes;
+ inst->iKeepAliveTime = loadModConf->iKeepAliveTime;
+ inst->iAddtlFrameDelim = loadModConf->iAddtlFrameDelim;
+ inst->maxFrameSize = loadModConf->maxFrameSize;
+ inst->bUseFlowControl = loadModConf->bUseFlowControl;
+ inst->bDisableLFDelim = loadModConf->bDisableLFDelim;
+ inst->discardTruncatedMsg = loadModConf->discardTruncatedMsg;
+ inst->bEmitMsgOnClose = loadModConf->bEmitMsgOnClose;
+ inst->bEmitMsgOnOpen = loadModConf->bEmitMsgOnOpen;
+ inst->bPreserveCase = loadModConf->bPreserveCase;
+ inst->iTCPLstnMax = loadModConf->iTCPLstnMax;
+ inst->iTCPSessMax = loadModConf->iTCPSessMax;
+
+ inst->cnf_params->pszLstnPortFileName = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(inst->cnf_params);
+ free(inst);
+ }
+ RETiRet;
+}
+
+
+/* This function is called when a new listener instace shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ * rgerhards, 2011-05-04
+ */
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ CHKiRet(createInstance(&inst));
+
+ CHKmalloc(inst->cnf_params->pszPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
+ ? (uchar*) "10514" : pNewVal));
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ if((cs.lstnIP == NULL) || (cs.lstnIP[0] == '\0')) {
+ inst->cnf_params->pszAddr = NULL;
+ } else {
+ CHKmalloc(inst->cnf_params->pszAddr = ustrdup(cs.lstnIP));
+ }
+ if((cs.lstnPortFile == NULL) || (cs.lstnPortFile[0] == '\0')) {
+ inst->cnf_params->pszLstnPortFileName = NULL;
+ } else {
+ CHKmalloc(inst->cnf_params->pszLstnPortFileName = ustrdup(cs.lstnPortFile));
+ }
+
+ if((cs.pszInputName == NULL) || (cs.pszInputName[0] == '\0')) {
+ inst->pszInputName = NULL;
+ } else {
+ CHKmalloc(inst->pszInputName = ustrdup(cs.pszInputName));
+ }
+ inst->cnf_params->bSuppOctetFram = cs.bSuppOctetFram;
+ inst->iStrmDrvrMode = cs.iStrmDrvrMode;
+ inst->bKeepAlive = cs.bKeepAlive ;
+ inst->bUseFlowControl = cs.bUseFlowControl;
+ inst->bDisableLFDelim = cs.bDisableLFDelim;
+ inst->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ inst->bPreserveCase = cs.bPreserveCase;
+ inst->iKeepAliveProbes = cs.iKeepAliveProbes;
+ inst->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ inst->iKeepAliveTime = cs.iKeepAliveTime;
+ inst->iKeepAliveTime = cs.iKeepAliveTime;
+ inst->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ inst->iTCPLstnMax = cs.iTCPLstnMax;
+ inst->iTCPSessMax = cs.iTCPSessMax;
+ inst->iStrmDrvrMode = cs.iStrmDrvrMode;
+
+finalize_it:
+ free(pNewVal);
+ RETiRet;
+}
+
+
+static rsRetVal
+addListner(modConfData_t *modConf, instanceConf_t *inst)
+{
+ DEFiRet;
+ uchar *psz; /* work variable */
+ permittedPeers_t *peers;
+
+ tcpsrv_t *pOurTcpsrv;
+ CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+ /* callbacks */
+ CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
+ CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
+ CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
+ CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
+ CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+ /* params */
+ CHKiRet(tcpsrv.SetKeepAlive(pOurTcpsrv, inst->bKeepAlive));
+ CHKiRet(tcpsrv.SetKeepAliveIntvl(pOurTcpsrv, inst->iKeepAliveIntvl));
+ CHKiRet(tcpsrv.SetKeepAliveProbes(pOurTcpsrv, inst->iKeepAliveProbes));
+ CHKiRet(tcpsrv.SetKeepAliveTime(pOurTcpsrv, inst->iKeepAliveTime));
+ CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, inst->iTCPSessMax));
+ CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, inst->iTCPLstnMax));
+ CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, inst->iStrmDrvrMode));
+ CHKiRet(tcpsrv.SetDrvrCheckExtendedKeyUsage(pOurTcpsrv, inst->iStrmDrvrExtendedCertCheck));
+ CHKiRet(tcpsrv.SetDrvrPrioritizeSAN(pOurTcpsrv, inst->iStrmDrvrSANPreference));
+ CHKiRet(tcpsrv.SetDrvrTlsVerifyDepth(pOurTcpsrv, inst->iStrmTlsVerifyDepth));
+ CHKiRet(tcpsrv.SetUseFlowControl(pOurTcpsrv, inst->bUseFlowControl));
+ CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, inst->iAddtlFrameDelim));
+ CHKiRet(tcpsrv.SetMaxFrameSize(pOurTcpsrv, inst->maxFrameSize));
+ CHKiRet(tcpsrv.SetbDisableLFDelim(pOurTcpsrv, inst->bDisableLFDelim));
+ CHKiRet(tcpsrv.SetDiscardTruncatedMsg(pOurTcpsrv, inst->discardTruncatedMsg));
+ CHKiRet(tcpsrv.SetNotificationOnRemoteClose(pOurTcpsrv, inst->bEmitMsgOnClose));
+ CHKiRet(tcpsrv.SetNotificationOnRemoteOpen(pOurTcpsrv, inst->bEmitMsgOnOpen));
+ CHKiRet(tcpsrv.SetPreserveCase(pOurTcpsrv, inst->bPreserveCase));
+ /* now set optional params, but only if they were actually configured */
+ psz = (inst->pszStrmDrvrName == NULL) ? modConf->pszStrmDrvrName : inst->pszStrmDrvrName;
+ if(psz != NULL) {
+ CHKiRet(tcpsrv.SetDrvrName(pOurTcpsrv, psz));
+ }
+ psz = (inst->pszStrmDrvrAuthMode == NULL) ? modConf->pszStrmDrvrAuthMode : inst->pszStrmDrvrAuthMode;
+ if(psz != NULL) {
+ CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, psz));
+ }
+ psz = (inst->gnutlsPriorityString == NULL)
+ ? modConf->gnutlsPriorityString : inst->gnutlsPriorityString;
+ CHKiRet(tcpsrv.SetGnutlsPriorityString(pOurTcpsrv, psz));
+ /* Call SetDrvrPermitExpiredCerts required
+ * when param is NULL default handling for ExpiredCerts is set! */
+ psz = (inst->pszStrmDrvrPermitExpiredCerts == NULL)
+ ? modConf->pszStrmDrvrPermitExpiredCerts : inst->pszStrmDrvrPermitExpiredCerts;
+ CHKiRet(tcpsrv.SetDrvrPermitExpiredCerts(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCAFile == NULL)
+ ? modConf->pszStrmDrvrCAFile : inst->pszStrmDrvrCAFile;
+ CHKiRet(tcpsrv.SetDrvrCAFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCRLFile == NULL)
+ ? modConf->pszStrmDrvrCRLFile : inst->pszStrmDrvrCRLFile;
+ CHKiRet(tcpsrv.SetDrvrCRLFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrKeyFile == NULL)
+ ? modConf->pszStrmDrvrKeyFile : inst->pszStrmDrvrKeyFile;
+ CHKiRet(tcpsrv.SetDrvrKeyFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCertFile == NULL)
+ ? modConf->pszStrmDrvrCertFile : inst->pszStrmDrvrCertFile;
+ CHKiRet(tcpsrv.SetDrvrCertFile(pOurTcpsrv, psz));
+
+ peers = (inst->pPermPeersRoot == NULL)
+ ? modConf->pPermPeersRoot : inst->pPermPeersRoot;
+ if(peers != NULL) {
+ CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, peers));
+ }
+
+ /* initialized, now add socket and listener params */
+ DBGPRINTF("imtcp: trying to add port *:%s\n", inst->cnf_params->pszPort);
+ inst->cnf_params->pRuleset = inst->pBindRuleset;
+ CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, inst->cnf_params, inst->pszInputName == NULL ?
+ UCHAR_CONSTANT("imtcp") : inst->pszInputName));
+ CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, (uchar*)"imtcp"));
+ CHKiRet(tcpsrv.SetDfltTZ(pOurTcpsrv, (inst->dfltTZ == NULL) ? (uchar*)"" : inst->dfltTZ));
+ CHKiRet(tcpsrv.SetbSPFramingFix(pOurTcpsrv, inst->bSPFramingFix));
+ CHKiRet(tcpsrv.SetLinuxLikeRatelimiters(pOurTcpsrv, inst->ratelimitInterval, inst->ratelimitBurst));
+
+ if((ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) == 0
+ && inst->cnf_params->pszLstnPortFileName == NULL)
+ || ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) < 0) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "imtcp: port 0 and no port file set -> using port 514 instead");
+ CHKmalloc(inst->cnf_params->pszPort = (uchar*)strdup("514"));
+ }
+ tcpsrv.configureTCPListen(pOurTcpsrv, inst->cnf_params);
+
+ tcpsrv_etry_t *etry;
+ CHKmalloc(etry = (tcpsrv_etry_t*) calloc(1, sizeof(tcpsrv_etry_t)));
+ etry->tcpsrv = pOurTcpsrv;
+ etry->next = tcpsrv_root;
+ tcpsrv_root = etry;
+ ++n_tcpsrv;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "imtcp: error %d trying to add listener", iRet);
+ }
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imtcp)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imtcp: required parameter are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imtcp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "port")) {
+ inst->cnf_params->pszPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ inst->cnf_params->pszAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "defaulttz")) {
+ inst->dfltTZ = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "framingfix.cisco.asa")) {
+ inst->bSPFramingFix = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.mode")) {
+ inst->iStrmDrvrMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
+ inst->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
+ inst->iStrmDrvrSANPreference = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.TlsVerifyDepth")) {
+ if (pvals[i].val.d.n >= 2) {
+ inst->iStrmTlsVerifyDepth = (int) pvals[i].val.d.n;
+ } else {
+ parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d",
+ (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.authmode")) {
+ inst->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.permitexpiredcerts")) {
+ inst->pszStrmDrvrPermitExpiredCerts = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.cafile")) {
+ inst->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.crlfile")) {
+ inst->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.keyfile")) {
+ inst->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.certfile")) {
+ inst->pszStrmDrvrCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.name")) {
+ inst->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "gnutlsprioritystring")) {
+ inst->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "permittedpeer")) {
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ uchar *const peer = (uchar*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(net.AddPermittedPeer(&inst->pPermPeersRoot, peer));
+ free(peer);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->bUseFlowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "disablelfdelimiter")) {
+ inst->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) {
+ inst->discardTruncatedMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionclose")) {
+ inst->bEmitMsgOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionopen")) {
+ inst->bEmitMsgOnOpen = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "addtlframedelimiter")) {
+ inst->iAddtlFrameDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxframesize")) {
+ const int max = (int) pvals[i].val.d.n;
+ if(max <= 200000000) {
+ inst->maxFrameSize = max;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "imtcp: invalid value for 'maxFrameSize' "
+ "parameter given is %d, max is 200000000", max);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "maxsessions")) {
+ inst->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxlisteners")) {
+ inst->iTCPLstnMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) {
+ inst->cnf_params->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive")) {
+ inst->bKeepAlive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.probes")) {
+ inst->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.time")) {
+ inst->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive.interval")) {
+ inst->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "preservecase")) {
+ inst->bPreserveCase = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "listenportfilename")) {
+ inst->cnf_params->pszLstnPortFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imtcp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ loadModConf->iTCPSessMax = 200;
+ loadModConf->iTCPLstnMax = 20;
+ loadModConf->bSuppOctetFram = 1;
+ loadModConf->iStrmDrvrMode = 0;
+ loadModConf->iStrmDrvrExtendedCertCheck = 0;
+ loadModConf->iStrmDrvrSANPreference = 0;
+ loadModConf->iStrmTlsVerifyDepth = 0;
+ loadModConf->bUseFlowControl = 1;
+ loadModConf->bKeepAlive = 0;
+ loadModConf->iKeepAliveIntvl = 0;
+ loadModConf->iKeepAliveProbes = 0;
+ loadModConf->iKeepAliveTime = 0;
+ loadModConf->bEmitMsgOnClose = 0;
+ loadModConf->bEmitMsgOnOpen = 0;
+ loadModConf->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ loadModConf->maxFrameSize = 200000;
+ loadModConf->bDisableLFDelim = 0;
+ loadModConf->discardTruncatedMsg = 0;
+ loadModConf->gnutlsPriorityString = NULL;
+ loadModConf->pszStrmDrvrName = NULL;
+ loadModConf->pszStrmDrvrAuthMode = NULL;
+ loadModConf->pszStrmDrvrPermitExpiredCerts = NULL;
+ loadModConf->pszStrmDrvrCAFile = NULL;
+ loadModConf->pszStrmDrvrCRLFile = NULL;
+ loadModConf->pszStrmDrvrKeyFile = NULL;
+ loadModConf->pszStrmDrvrCertFile = NULL;
+ loadModConf->pPermPeersRoot = NULL;
+ loadModConf->configSetViaV2Method = 0;
+ loadModConf->bPreserveCase = 1; /* default to true */
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config variables */
+ resetConfigVariables(NULL, NULL); /* dummy parameters just to fulfill interface def */
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imtcp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imtcp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "flowcontrol")) {
+ loadModConf->bUseFlowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "disablelfdelimiter")) {
+ loadModConf->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "discardtruncatedmsg")) {
+ loadModConf->discardTruncatedMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "octetcountedframing")) {
+ loadModConf->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "notifyonconnectionclose")) {
+ loadModConf->bEmitMsgOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "notifyonconnectionopen")) {
+ loadModConf->bEmitMsgOnOpen = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "addtlframedelimiter")) {
+ loadModConf->iAddtlFrameDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "maxframesize")) {
+ const int max = (int) pvals[i].val.d.n;
+ if(max <= 200000000) {
+ loadModConf->maxFrameSize = max;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "imtcp: invalid value for 'maxFrameSize' "
+ "parameter given is %d, max is 200000000", max);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "maxsessions")) {
+ loadModConf->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "maxlisteners") ||
+ !strcmp(modpblk.descr[i].name, "maxlistners")) { /* keep old name for a while */
+ loadModConf->iTCPLstnMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive")) {
+ loadModConf->bKeepAlive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.probes")) {
+ loadModConf->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.time")) {
+ loadModConf->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.interval")) {
+ loadModConf->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "gnutlsprioritystring")) {
+ loadModConf->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.mode")) {
+ loadModConf->iStrmDrvrMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
+ loadModConf->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
+ loadModConf->iStrmDrvrSANPreference = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.TlsVerifyDepth")) {
+ if (pvals[i].val.d.n >= 2) {
+ loadModConf->iStrmTlsVerifyDepth = (int) pvals[i].val.d.n;
+ } else {
+ parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d",
+ (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.authmode")) {
+ loadModConf->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.permitexpiredcerts")) {
+ loadModConf->pszStrmDrvrPermitExpiredCerts = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.cafile")) {
+ loadModConf->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.crlfile")) {
+ loadModConf->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.keyfile")) {
+ loadModConf->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.certfile")) {
+ loadModConf->pszStrmDrvrCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.name")) {
+ loadModConf->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "permittedpeer")) {
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ uchar *const peer = (uchar*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(net.AddPermittedPeer(&loadModConf->pPermPeersRoot, peer));
+ free(peer);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) {
+ loadModConf->bPreserveCase = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imtcp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* remove all of our legacy handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ pModConf->iTCPSessMax = cs.iTCPSessMax;
+ pModConf->iTCPLstnMax = cs.iTCPLstnMax;
+ pModConf->iStrmDrvrMode = cs.iStrmDrvrMode;
+ pModConf->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ pModConf->bSuppOctetFram = cs.bSuppOctetFram;
+ pModConf->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ pModConf->maxFrameSize = cs.maxFrameSize;
+ pModConf->bDisableLFDelim = cs.bDisableLFDelim;
+ pModConf->bUseFlowControl = cs.bUseFlowControl;
+ pModConf->bKeepAlive = cs.bKeepAlive;
+ pModConf->iKeepAliveProbes = cs.iKeepAliveProbes;
+ pModConf->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ pModConf->iKeepAliveTime = cs.iKeepAliveTime;
+ if(pPermPeersRoot != NULL) {
+ assert(pModConf->pPermPeersRoot == NULL);
+ pModConf->pPermPeersRoot = pPermPeersRoot;
+ pPermPeersRoot = NULL; /* memory handed over! */
+ }
+ if((cs.pszStrmDrvrAuthMode == NULL) || (cs.pszStrmDrvrAuthMode[0] == '\0')) {
+ loadModConf->pszStrmDrvrAuthMode = NULL;
+ } else {
+ loadModConf->pszStrmDrvrAuthMode = cs.pszStrmDrvrAuthMode;
+ cs.pszStrmDrvrAuthMode = NULL;
+ }
+ pModConf->bPreserveCase = cs.bPreserveCase;
+ }
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imtcp: ruleset '%s' for port %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->cnf_params->pszPort);
+}
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ if(inst->cnf_params->bSuppOctetFram == FRAMING_UNSET)
+ inst->cnf_params->bSuppOctetFram = pModConf->bSuppOctetFram;
+ }
+ if(pModConf->root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS , "imtcp: module loaded, but "
+ "no listeners defined - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(runModConf, inst);
+ }
+ if(tcpsrv_root == NULL)
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ tcpsrv_etry_t *etry = tcpsrv_root;
+ while(etry != NULL) {
+ CHKiRet(tcpsrv.ConstructFinalize(etry->tcpsrv));
+ etry = etry->next;
+ }
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ /* sorry, nothing to do here... */
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ free(pModConf->gnutlsPriorityString);
+ free(pModConf->pszStrmDrvrName);
+ free(pModConf->pszStrmDrvrAuthMode);
+ free(pModConf->pszStrmDrvrPermitExpiredCerts);
+ free(pModConf->pszStrmDrvrCAFile);
+ free(pModConf->pszStrmDrvrCRLFile);
+ free(pModConf->pszStrmDrvrKeyFile);
+ free(pModConf->pszStrmDrvrCertFile);
+ if(pModConf->pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&pModConf->pPermPeersRoot);
+ }
+
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free((void*)inst->pszBindRuleset);
+ free((void*)inst->pszStrmDrvrAuthMode);
+ free((void*)inst->pszStrmDrvrName);
+ free((void*)inst->pszStrmDrvrPermitExpiredCerts);
+ free((void*)inst->pszStrmDrvrCAFile);
+ free((void*)inst->pszStrmDrvrCRLFile);
+ free((void*)inst->pszStrmDrvrKeyFile);
+ free((void*)inst->pszStrmDrvrCertFile);
+ free((void*)inst->gnutlsPriorityString);
+ free((void*)inst->pszInputName);
+ free((void*)inst->dfltTZ);
+ if(inst->pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&inst->pPermPeersRoot);
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+static void *
+RunServerThread(void *myself)
+{
+ tcpsrv_etry_t *const etry = (tcpsrv_etry_t*) myself;
+ rsRetVal iRet;
+ iRet = tcpsrv.Run(etry->tcpsrv);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "imtcp: error while terminating server; rsyslog may hang on shutdown");
+ }
+ return NULL;
+}
+
+
+/* support for running multiple servers on multiple threads (one server per thread) */
+static void
+startSrvWrkr(tcpsrv_etry_t *const etry)
+{
+ int r;
+ pthread_attr_t sessThrdAttr;
+
+ /* We need to temporarily block all signals because the new thread
+ * inherits our signal mask. There is a race if we do not block them
+ * now, and we have seen in practice that this race causes grief.
+ * So we 1. save the current set, 2. block evertyhing, 3. start
+ * threads, and 4 reset the current set to saved state.
+ * rgerhards, 2019-08-16
+ */
+ sigset_t sigSet, sigSetSave;
+ sigfillset(&sigSet);
+ /* enable signals we still need */
+ sigdelset(&sigSet, SIGTTIN);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_SETMASK, &sigSet, &sigSetSave);
+
+ pthread_attr_init(&sessThrdAttr);
+ pthread_attr_setstacksize(&sessThrdAttr, 4096*1024);
+ r = pthread_create(&etry->tid, &sessThrdAttr, RunServerThread, etry);
+ if(r != 0) {
+ LogError(r, NO_ERRCODE, "imtcp error creating server thread");
+ /* we do NOT abort, as other servers may run - after all, we logged an error */
+ }
+ pthread_attr_destroy(&sessThrdAttr);
+ pthread_sigmask(SIG_SETMASK, &sigSetSave, NULL);
+}
+
+/* stop server worker thread
+ */
+static void
+stopSrvWrkr(tcpsrv_etry_t *const etry)
+{
+ DBGPRINTF("Wait for thread shutdown etry %p\n", etry);
+ pthread_kill(etry->tid, SIGTTIN);
+ pthread_join(etry->tid, NULL);
+ DBGPRINTF("input %p terminated\n", etry);
+}
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ tcpsrv_etry_t *etry = tcpsrv_root->next;
+ while(etry != NULL) {
+ startSrvWrkr(etry);
+ etry = etry->next;
+ }
+
+ iRet = tcpsrv.Run(tcpsrv_root->tcpsrv);
+
+ /* de-init remaining servers */
+ etry = tcpsrv_root->next;
+ while(etry != NULL) {
+ stopSrvWrkr(etry);
+ etry = etry->next;
+ }
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ net.PrintAllowedSenders(2); /* TCP */
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ tcpsrv_etry_t *etry = tcpsrv_root;
+ tcpsrv_etry_t *del;
+ while(etry != NULL) {
+ iRet = tcpsrv.Destruct(&etry->tcpsrv);
+ // TODO: check iRet, reprot error
+ del = etry;
+ etry = etry->next;
+ free(del);
+ }
+ net.clearAllowedSenders(UCHAR_CONSTANT("TCP"));
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release objects we used */
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(tcps_sess, LM_TCPSRV_FILENAME);
+ objRelease(tcpsrv, LM_TCPSRV_FILENAME);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.iTCPSessMax = 200;
+ cs.iTCPLstnMax = 20;
+ cs.bSuppOctetFram = 1;
+ cs.iStrmDrvrMode = 0;
+ cs.bUseFlowControl = 1;
+ cs.bKeepAlive = 0;
+ cs.iKeepAliveProbes = 0;
+ cs.iKeepAliveTime = 0;
+ cs.iKeepAliveIntvl = 0;
+ cs.bEmitMsgOnClose = 0;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ cs.maxFrameSize = 200000;
+ cs.bDisableLFDelim = 0;
+ cs.bPreserveCase = 1;
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+ free(cs.pszInputName);
+ cs.pszInputName = NULL;
+ free(cs.lstnPortFile);
+ cs.lstnPortFile = NULL;
+ return RS_RET_OK;
+}
+
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ tcpsrv_root = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverrun"), 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverinputname"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszInputName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverbindruleset"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
+ /* module-global config params - will be disabled in configs that are loaded
+ * via module(...).
+ */
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdriverpermittedpeer"), 0, eCmdHdlrGetWord,
+ setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdriverauthmode"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive"), 0, eCmdHdlrBinary,
+ NULL, &cs.bKeepAlive, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_probes"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveProbes, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_intvl"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveIntvl, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_time"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveTime, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpflowcontrol"), 0, eCmdHdlrBinary,
+ NULL, &cs.bUseFlowControl, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverdisablelfdelimiter"), 0, eCmdHdlrBinary,
+ NULL, &cs.bDisableLFDelim, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserveraddtlframedelimiter"), 0, eCmdHdlrInt,
+ NULL, &cs.iAddtlFrameDelim, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserversupportoctetcountedframing"), 0, eCmdHdlrBinary,
+ NULL, &cs.bSuppOctetFram, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpmaxsessions"), 0, eCmdHdlrInt,
+ NULL, &cs.iTCPSessMax, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpmaxlisteners"), 0, eCmdHdlrInt,
+ NULL, &cs.iTCPLstnMax, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpservernotifyonconnectionclose"), 0, eCmdHdlrBinary,
+ NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0, eCmdHdlrInt,
+ NULL, &cs.iStrmDrvrMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverpreservecase"), 1, eCmdHdlrBinary,
+ NULL, &cs.bPreserveCase, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverlistenportfile"), 1, eCmdHdlrGetWord,
+ NULL, &cs.lstnPortFile, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/imudp/Makefile.am b/plugins/imudp/Makefile.am
new file mode 100644
index 0000000..32d3d86
--- /dev/null
+++ b/plugins/imudp/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = imudp.la
+
+imudp_la_SOURCES = imudp.c
+imudp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imudp_la_LDFLAGS = -module -avoid-version
+imudp_la_LIBADD = $(IMUDP_LIBS)
+
+if ENABLE_LIBLOGGING_STDLOG
+imudp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+imudp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/imudp/Makefile.in b/plugins/imudp/Makefile.in
new file mode 100644
index 0000000..5b94114
--- /dev/null
+++ b/plugins/imudp/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/imudp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imudp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_imudp_la_OBJECTS = imudp_la-imudp.lo
+imudp_la_OBJECTS = $(am_imudp_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 =
+imudp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imudp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imudp_la-imudp.Plo
+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 = $(imudp_la_SOURCES)
+DIST_SOURCES = $(imudp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imudp.la
+imudp_la_SOURCES = imudp.c
+imudp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_1)
+imudp_la_LDFLAGS = -module -avoid-version $(am__append_2)
+imudp_la_LIBADD = $(IMUDP_LIBS)
+all: 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) --gnu plugins/imudp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imudp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imudp.la: $(imudp_la_OBJECTS) $(imudp_la_DEPENDENCIES) $(EXTRA_imudp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imudp_la_LINK) -rpath $(pkglibdir) $(imudp_la_OBJECTS) $(imudp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imudp_la-imudp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imudp_la-imudp.lo: imudp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imudp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imudp_la-imudp.lo -MD -MP -MF $(DEPDIR)/imudp_la-imudp.Tpo -c -o imudp_la-imudp.lo `test -f 'imudp.c' || echo '$(srcdir)/'`imudp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imudp_la-imudp.Tpo $(DEPDIR)/imudp_la-imudp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imudp.c' object='imudp_la-imudp.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) $(imudp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imudp_la-imudp.lo `test -f 'imudp.c' || echo '$(srcdir)/'`imudp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imudp_la-imudp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imudp_la-imudp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
new file mode 100644
index 0000000..982f6c4
--- /dev/null
+++ b/plugins/imudp/imudp.c
@@ -0,0 +1,1419 @@
+/* imudp.c
+ * This is the implementation of the UDP input module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include <signal.h>
+#include <poll.h>
+#ifdef HAVE_SYS_EPOLL_H
+# include <sys/epoll.h>
+#endif
+#ifdef HAVE_SCHED_H
+# include <sched.h>
+#endif
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "net.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "msg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "statsobj.h"
+#include "ratelimit.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imudp")
+
+/* defines */
+#define MAX_WRKR_THREADS 32
+
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+
+static struct lstn_s {
+ struct lstn_s *next;
+ int sock; /* socket */
+ ruleset_t *pRuleset; /* bound ruleset */
+ prop_t *pInputName;
+ statsobj_t *stats; /* listener stats */
+ ratelimit_t *ratelimiter;
+ uchar *dfltTZ;
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ STATSCOUNTER_DEF(ctrDisallowed, mutCtrDisallowed)
+} *lcnfRoot = NULL, *lcnfLast = NULL;
+
+
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+static int bDoACLCheck; /* are ACL checks neeed? Cached once immediately before listener startup */
+static int iMaxLine; /* maximum UDP message size supported */
+#define BATCH_SIZE_DFLT 32 /* do not overdo, has heavy toll on memory, especially with large msgs */
+#define TIME_REQUERY_DFLT 2
+#define SCHED_PRIO_UNSET -12345678 /* a value that indicates that the scheduling priority has not been set */
+/* config vars for legacy config system */
+static struct configSettings_s {
+ uchar *pszBindAddr; /* IP to bind socket to */
+ char *pszBindDevice; /* Device to bind socket to */
+ uchar *pszSchedPolicy; /* scheduling policy string */
+ uchar *pszBindRuleset; /* name of Ruleset to bind to */
+ int iSchedPrio; /* scheduling priority */
+ int iTimeRequery; /* how often is time to be queried inside tight recv loop? 0=always */
+} cs;
+
+struct instanceConf_s {
+ uchar *pszBindAddr; /* IP to bind socket to */
+ char *pszBindDevice; /* Device to bind socket to */
+ uchar *pszBindPort; /* Port to bind socket to */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *inputname;
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *dfltTZ;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ int rcvbuf; /* 0 means: do not set, keep OS default */
+ /* 0 means: IP_FREEBIND is disabled
+ 1 means: IP_FREEBIND enabled + warning disabled
+ 1+ means: IP+FREEBIND enabled + warning enabled */
+ int ipfreebind;
+ struct instanceConf_s *next;
+ sbool bAppendPortToInpname;
+};
+
+/* The following structure controls the worker threads. Global data is
+ * needed for their access.
+ */
+static struct wrkrInfo_s {
+ pthread_t tid; /* the worker's thread ID */
+ int id;
+ thrdInfo_t *pThrd;
+ statsobj_t *stats; /* worker thread stats */
+ STATSCOUNTER_DEF(ctrCall_recvmmsg, mutCtrCall_recvmmsg)
+ STATSCOUNTER_DEF(ctrCall_recvmsg, mutCtrCall_recvmsg)
+ STATSCOUNTER_DEF(ctrMsgsRcvd, mutCtrMsgsRcvd)
+ uchar *pRcvBuf; /* receive buffer (for a single packet) */
+# ifdef HAVE_RECVMMSG
+ struct sockaddr_storage *frominet;
+ struct mmsghdr *recvmsg_mmh;
+ struct iovec *recvmsg_iov;
+# endif
+} wrkrInfo[MAX_WRKR_THREADS];
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ uchar *pszSchedPolicy; /* scheduling policy string */
+ int iSchedPolicy; /* scheduling policy as SCHED_xxx */
+ int iSchedPrio; /* scheduling priority */
+ int iTimeRequery; /* how often is time to be queried inside tight recv loop? 0=always */
+ int batchSize; /* max nbr of input batch --> also recvmmsg() max count */
+ int8_t wrkrMax; /* max nbr of worker threads */
+ sbool configSetViaV2Method;
+ sbool bPreserveCase; /* preserves the case of fromhost; "off" by default */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "schedulingpolicy", eCmdHdlrGetWord, 0 },
+ { "schedulingpriority", eCmdHdlrInt, 0 },
+ { "batchsize", eCmdHdlrInt, 0 },
+ { "threads", eCmdHdlrPositiveInt, 0 },
+ { "timerequery", eCmdHdlrInt, 0 },
+ { "preservecase", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrArray, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */
+ { "defaulttz", eCmdHdlrString, 0 },
+ { "inputname", eCmdHdlrGetWord, 0 },
+ { "inputname.appendport", eCmdHdlrBinary, 0 },
+ { "name", eCmdHdlrGetWord, 0 },
+ { "name.appendport", eCmdHdlrBinary, 0 },
+ { "address", eCmdHdlrString, 0 },
+ { "device", eCmdHdlrString, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "rcvbufsize", eCmdHdlrSize, 0 },
+ { "ipfreebind", eCmdHdlrInt, 0 },
+ { "ruleset", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pBindRuleset = NULL;
+
+ inst->pszBindPort = NULL;
+ inst->pszBindAddr = NULL;
+ inst->pszBindDevice = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->inputname = NULL;
+ inst->bAppendPortToInpname = 0;
+ inst->ratelimitBurst = 10000; /* arbitrary high limit */
+ inst->ratelimitInterval = 0; /* off */
+ inst->rcvbuf = 0;
+ inst->ipfreebind = IPFREEBIND_ENABLED_WITH_LOG;
+ inst->dfltTZ = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* This function is called when a new listener instace shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ * rgerhards, 2011-05-04
+ */
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ CHKiRet(createInstance(&inst));
+ CHKmalloc(inst->pszBindPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
+ ? (uchar*) "514" : pNewVal));
+ if((cs.pszBindAddr == NULL) || (cs.pszBindAddr[0] == '\0')) {
+ inst->pszBindAddr = NULL;
+ } else {
+ CHKmalloc(inst->pszBindAddr = ustrdup(cs.pszBindAddr));
+ }
+ if((cs.pszBindDevice == NULL) || (cs.pszBindDevice[0] == '\0')) {
+ inst->pszBindDevice= NULL;
+ } else {
+ CHKmalloc(inst->pszBindDevice = strdup(cs.pszBindDevice));
+ }
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+
+finalize_it:
+ free(pNewVal);
+ RETiRet;
+}
+
+
+/* This function is called when a new listener shall be added. It takes
+ * the instance config description, tries to bind the socket and, if that
+ * succeeds, adds it to the list of existing listen sockets.
+ */
+static rsRetVal
+addListner(instanceConf_t *inst)
+{
+ DEFiRet;
+ uchar *bindAddr;
+ int *newSocks;
+ int iSrc;
+ struct lstn_s *newlcnfinfo;
+ uchar *bindName;
+ uchar *port;
+ uchar dispname[64], inpnameBuf[128];
+ uchar *inputname;
+
+ /* check which address to bind to. We could do this more compact, but have not
+ * done so in order to make the code more readable. -- rgerhards, 2007-12-27
+ */
+ if(inst->pszBindAddr == NULL)
+ bindAddr = NULL;
+ else if(inst->pszBindAddr[0] == '*' && inst->pszBindAddr[1] == '\0')
+ bindAddr = NULL;
+ else
+ bindAddr = inst->pszBindAddr;
+ bindName = (bindAddr == NULL) ? (uchar*)"*" : bindAddr;
+ port = (inst->pszBindPort == NULL || *inst->pszBindPort == '\0') ? (uchar*) "514" : inst->pszBindPort;
+
+ DBGPRINTF("Trying to open syslog UDP ports at %s:%s.\n", bindName, inst->pszBindPort);
+
+ newSocks = net.create_udp_socket(bindAddr, port, 1, inst->rcvbuf, 0, inst->ipfreebind, inst->pszBindDevice);
+ if(newSocks != NULL) {
+ /* we now need to add the new sockets to the existing set */
+ /* ready to copy */
+ for(iSrc = 1 ; iSrc <= newSocks[0] ; ++iSrc) {
+ struct sockaddr_in sa;
+ socklen_t salen = sizeof(sa);
+ const char *suffix;
+ CHKmalloc(newlcnfinfo = (struct lstn_s*) calloc(1, sizeof(struct lstn_s)));
+ newlcnfinfo->next = NULL;
+ newlcnfinfo->sock = newSocks[iSrc];
+ newlcnfinfo->pRuleset = inst->pBindRuleset;
+ newlcnfinfo->dfltTZ = inst->dfltTZ;
+ newlcnfinfo->ratelimiter = NULL;
+ /* query socket IPv4 vs IPv6 */
+ sa.sin_family = 0; /* just to keep CLANG static analyzer happy! */
+ if(getsockname(newlcnfinfo->sock, (struct sockaddr*) &sa, &salen) != 0) {
+ suffix = "error_getting_AF...";
+ } else {
+ if(sa.sin_family == AF_INET) {
+ suffix = "IPv4";
+ } else if(sa.sin_family == AF_INET6) {
+ suffix = "IPv6";
+ } else {
+ suffix = "AF_unknown";
+ }
+ }
+ if(inst->inputname == NULL) {
+ inputname = (uchar*)"imudp";
+ } else {
+ inputname = inst->inputname;
+ }
+ snprintf((char*)dispname, sizeof(dispname), "%s(%s/%s/%s)",
+ inputname, bindName, port, suffix);
+ dispname[sizeof(dispname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(ratelimitNew(&newlcnfinfo->ratelimiter, (char*)dispname, NULL));
+ ratelimitSetLinuxLike(newlcnfinfo->ratelimiter, inst->ratelimitInterval,
+ inst->ratelimitBurst);
+ ratelimitSetThreadSafe(newlcnfinfo->ratelimiter);
+ if(inst->bAppendPortToInpname) {
+ snprintf((char*)inpnameBuf, sizeof(inpnameBuf), "%s%s",
+ inputname, port);
+ inpnameBuf[sizeof(inpnameBuf)-1] = '\0';
+ inputname = inpnameBuf;
+ }
+ CHKiRet(prop.Construct(&newlcnfinfo->pInputName));
+ CHKiRet(prop.SetString(newlcnfinfo->pInputName,
+ inputname, ustrlen(inputname)));
+ CHKiRet(prop.ConstructFinalize(newlcnfinfo->pInputName));
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&(newlcnfinfo->stats)));
+ CHKiRet(statsobj.SetName(newlcnfinfo->stats, dispname));
+ CHKiRet(statsobj.SetOrigin(newlcnfinfo->stats, (uchar*)"imudp"));
+ STATSCOUNTER_INIT(newlcnfinfo->ctrSubmit, newlcnfinfo->mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(newlcnfinfo->stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(newlcnfinfo->ctrSubmit)));
+ STATSCOUNTER_INIT(newlcnfinfo->ctrDisallowed, newlcnfinfo->mutCtrDisallowed);
+ CHKiRet(statsobj.AddCounter(newlcnfinfo->stats, UCHAR_CONSTANT("disallowed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(newlcnfinfo->ctrDisallowed)));
+ CHKiRet(statsobj.ConstructFinalize(newlcnfinfo->stats));
+ /* link to list. Order must be preserved to take care for
+ * conflicting matches.
+ */
+ if(lcnfRoot == NULL)
+ lcnfRoot = newlcnfinfo;
+ if(lcnfLast == NULL)
+ lcnfLast = newlcnfinfo;
+ else {
+ lcnfLast->next = newlcnfinfo;
+ lcnfLast = newlcnfinfo;
+ }
+ }
+ } else {
+ LogError(0, NO_ERRCODE, "imudp: Could not create udp listener,"
+ " ignoring port %s bind-address %s.",
+ port, bindAddr);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(newlcnfinfo != NULL) {
+ if(newlcnfinfo->ratelimiter != NULL)
+ ratelimitDestruct(newlcnfinfo->ratelimiter);
+ if(newlcnfinfo->pInputName != NULL)
+ prop.Destruct(&newlcnfinfo->pInputName);
+ if(newlcnfinfo->stats != NULL)
+ statsobj.Destruct(&newlcnfinfo->stats);
+ free(newlcnfinfo);
+ }
+ /* close the rest of the open sockets as there's
+ nowhere to put them */
+ for(; iSrc <= newSocks[0]; iSrc++) {
+ close(newSocks[iSrc]);
+ }
+ }
+
+ free(newSocks);
+ RETiRet;
+}
+
+
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imudp: ruleset '%s' for %s:%s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszBindAddr == NULL ? "*" : (char*) inst->pszBindAddr,
+ inst->pszBindPort);
+}
+
+
+/* This function processes received data. It provides unified handling
+ * in cases where recvmmsg() is available and not.
+ */
+static rsRetVal
+processPacket(struct lstn_s *lstn, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
+ uchar *rcvBuf, ssize_t lenRcvBuf, struct syslogTime *stTime, time_t ttGenTime,
+ struct sockaddr_storage *frominet, socklen_t socklen, multi_submit_t *multiSub)
+{
+ DEFiRet;
+ smsg_t *pMsg = NULL;
+
+ if(lenRcvBuf == 0)
+ FINALIZE; /* this looks a bit strange, but practice shows it happens... */
+
+ /* if we reach this point, we had a good receive and can process the packet received */
+ /* check if we have a different sender than before, if so, we need to query some new values */
+ if(bDoACLCheck) {
+ socklen = sizeof(struct sockaddr_storage);
+ if(net.CmpHost(frominet, frominetPrev, socklen) != 0) {
+ memcpy(frominetPrev, frominet, socklen); /* update cache indicator */
+ /* Here we check if a host is permitted to send us syslog messages. If it isn't,
+ * we do not further process the message but log a warning (if we are
+ * configured to do this). However, if the check would require name resolution,
+ * it is postponed to the main queue. See also my blog post at
+ * http://blog.gerhards.net/2009/11/acls-imudp-and-accepting-messages.html
+ * rgerhards, 2009-11-16
+ */
+ *pbIsPermitted = net.isAllowedSender2((uchar*)"UDP",
+ (struct sockaddr *)frominet, "", 0);
+
+ if(*pbIsPermitted == 0) {
+ DBGPRINTF("msg is not from an allowed sender\n");
+ STATSCOUNTER_INC(lstn->ctrDisallowed, lstn->mutCtrDisallowed);
+ if(glbl.GetOptionDisallowWarning(runModConf->pConf)) {
+ LogError(0, NO_ERRCODE,
+ "imudp: UDP message from disallowed sender discarded");
+ }
+ }
+ }
+ } else {
+ *pbIsPermitted = 1; /* no check -> everything permitted */
+ }
+
+ DBGPRINTF("recv(%d,%d),acl:%d,msg:%.*s\n", lstn->sock, (int) lenRcvBuf, *pbIsPermitted,
+ (int)lenRcvBuf, rcvBuf);
+
+ if(*pbIsPermitted != 0) {
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, (char*)rcvBuf, lenRcvBuf);
+ MsgSetInputName(pMsg, lstn->pInputName);
+ MsgSetRuleset(pMsg, lstn->pRuleset);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ if(lstn->dfltTZ != NULL)
+ MsgSetDfltTZ(pMsg, (char*) lstn->dfltTZ);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME | NEEDS_DNSRESOL;
+ if(*pbIsPermitted == 2) {
+ pMsg->msgFlags |= NEEDS_ACLCHK_U; /* request ACL check after resolution */
+ }
+ if(runModConf->bPreserveCase) {
+ pMsg->msgFlags |= PRESERVE_CASE; /* preserve case of fromhost */
+ }
+ CHKiRet(msgSetFromSockinfo(pMsg, frominet));
+ CHKiRet(ratelimitAddMsg(lstn->ratelimiter, multiSub, pMsg));
+ STATSCOUNTER_INC(lstn->ctrSubmit, lstn->mutCtrSubmit);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pMsg != NULL && iRet != RS_RET_DISCARDMSG) {
+ msgDestruct(&pMsg);
+ }
+ }
+
+ RETiRet;
+}
+
+
+
+
+/* The following "two" functions are helpers to runInput. Actually, it is
+ * just one function. Depending on whether or not we have recvmmsg(),
+ * an appropriate version is compiled (as such we need to maintain both!).
+ */
+#ifdef HAVE_RECVMMSG
+static rsRetVal
+processSocket(struct wrkrInfo_s *pWrkr, struct lstn_s *lstn, struct sockaddr_storage *frominetPrev,
+int *pbIsPermitted)
+{
+ DEFiRet;
+ int iNbrTimeUsed;
+ time_t ttGenTime = 0; /* to avoid clang static analyzer false positive */
+ /* note: we do never use this time, because we always get a
+ * requery below on first loop iteration */
+ struct syslogTime stTime;
+ char errStr[1024];
+ smsg_t *pMsgs[CONF_NUM_MULTISUB];
+ multi_submit_t multiSub;
+ int nelem;
+ int i;
+
+ multiSub.ppMsgs = pMsgs;
+ multiSub.maxElem = CONF_NUM_MULTISUB;
+ multiSub.nElem = 0;
+ iNbrTimeUsed = 0;
+ while(1) { /* loop is terminated if we have a "bad" receive, done below in the body */
+ if(pWrkr->pThrd->bShallStop == RSTRUE)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ memset(pWrkr->recvmsg_iov, 0, runModConf->batchSize * sizeof(struct iovec));
+ memset(pWrkr->recvmsg_mmh, 0, runModConf->batchSize * sizeof(struct mmsghdr));
+ for(i = 0 ; i < runModConf->batchSize ; ++i) {
+ pWrkr->recvmsg_iov[i].iov_base = pWrkr->pRcvBuf+(i*(iMaxLine+1));
+ pWrkr->recvmsg_iov[i].iov_len = iMaxLine;
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_name = &(pWrkr->frominet[i]);
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_iov = &(pWrkr->recvmsg_iov[i]);
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_iovlen = 1;
+ }
+ nelem = recvmmsg(lstn->sock, pWrkr->recvmsg_mmh, runModConf->batchSize, 0, NULL);
+ STATSCOUNTER_INC(pWrkr->ctrCall_recvmmsg, pWrkr->mutCtrCall_recvmmsg);
+ DBGPRINTF("imudp: recvmmsg returned %d\n", nelem);
+ if(nelem < 0 && errno == ENOSYS) {
+ /* be careful: some versions of valgrind do not support recvmmsg()! */
+ DBGPRINTF("imudp: error ENOSYS on call to recvmmsg() - fall back to recvmsg\n");
+ nelem = recvmsg(lstn->sock, &(pWrkr->recvmsg_mmh[0].msg_hdr), 0);
+ STATSCOUNTER_INC(pWrkr->ctrCall_recvmsg, pWrkr->mutCtrCall_recvmsg);
+ if(nelem >= 0) {
+ pWrkr->recvmsg_mmh[0].msg_len = nelem;
+ nelem = 1;
+ }
+ }
+ if(nelem < 0) {
+ if(errno != EINTR && errno != EAGAIN) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("INET socket error: %d = %s.\n", errno, errStr);
+ LogError(errno, NO_ERRCODE, "imudp: error receiving on socket: %s", errStr);
+ }
+ ABORT_FINALIZE(RS_RET_ERR);
+ // this most often is NOT an error, state is not checked by caller!
+ }
+
+ if((runModConf->iTimeRequery == 0) || (iNbrTimeUsed++ % runModConf->iTimeRequery) == 0) {
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ }
+
+ pWrkr->ctrMsgsRcvd += nelem;
+ for(i = 0 ; i < nelem ; ++i) {
+ processPacket(lstn, frominetPrev, pbIsPermitted,
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_iov->iov_base,
+ pWrkr->recvmsg_mmh[i].msg_len, &stTime, ttGenTime, &(pWrkr->frominet[i]),
+ pWrkr->recvmsg_mmh[i].msg_hdr.msg_namelen, &multiSub);
+ }
+ }
+
+finalize_it:
+ multiSubmitFlush(&multiSub);
+ RETiRet;
+}
+#else /* we do not have recvmmsg() */
+/* This function is a helper to runInput. I have extracted it
+ * from the main loop just so that we do not have that large amount of code
+ * in a single place. This function takes a socket and pulls messages from
+ * it until the socket does not have any more waiting.
+ * rgerhards, 2008-01-08
+ * We try to read from the file descriptor until there
+ * is no more data. This is done in the hope to get better performance
+ * out of the system. However, this also means that a descriptor
+ * monopolizes processing while it contains data. This can lead to
+ * data loss in other descriptors. However, if the system is incapable of
+ * handling the workload, we will loss data in any case. So it doesn't really
+ * matter where the actual loss occurs - it is always random, because we depend
+ * on scheduling order. -- rgerhards, 2008-10-02
+ */
+static rsRetVal
+processSocket(struct wrkrInfo_s *pWrkr, struct lstn_s *lstn, struct sockaddr_storage *frominetPrev,
+int *pbIsPermitted)
+{
+ int iNbrTimeUsed;
+ time_t ttGenTime;
+ struct syslogTime stTime;
+ ssize_t lenRcvBuf;
+ struct sockaddr_storage frominet;
+ multi_submit_t multiSub;
+ smsg_t *pMsgs[CONF_NUM_MULTISUB];
+ char errStr[1024];
+ struct msghdr mh;
+ struct iovec iov[1];
+ DEFiRet;
+
+ multiSub.ppMsgs = pMsgs;
+ multiSub.maxElem = CONF_NUM_MULTISUB;
+ multiSub.nElem = 0;
+ iNbrTimeUsed = 0;
+ while(1) { /* loop is terminated if we have a bad receive, done below in the body */
+ if(pWrkr->pThrd->bShallStop == RSTRUE)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ memset(iov, 0, sizeof(iov));
+ iov[0].iov_base = pWrkr->pRcvBuf;
+ iov[0].iov_len = iMaxLine;
+ memset(&mh, 0, sizeof(mh));
+ mh.msg_name = &frominet;
+ mh.msg_namelen = sizeof(struct sockaddr_storage);
+ mh.msg_iov = iov;
+ mh.msg_iovlen = 1;
+ lenRcvBuf = recvmsg(lstn->sock, &mh, 0);
+ STATSCOUNTER_INC(pWrkr->ctrCall_recvmsg, pWrkr->mutCtrCall_recvmsg);
+ if(lenRcvBuf < 0) {
+ if(errno != EINTR && errno != EAGAIN) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("INET socket error: %d = %s.\n", errno, errStr);
+ LogError(errno, NO_ERRCODE, "imudp: error receiving on socket: %s", errStr);
+ }
+ ABORT_FINALIZE(RS_RET_ERR);
+ // this most often is NOT an error, state is not checked by caller!
+ }
+
+ ++pWrkr->ctrMsgsRcvd;
+ if((runModConf->iTimeRequery == 0) || (iNbrTimeUsed++ % runModConf->iTimeRequery) == 0) {
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ }
+
+ CHKiRet(processPacket(lstn, frominetPrev, pbIsPermitted, pWrkr->pRcvBuf, lenRcvBuf, &stTime,
+ ttGenTime, &frominet, mh.msg_namelen, &multiSub));
+ }
+
+
+finalize_it:
+ multiSubmitFlush(&multiSub);
+ RETiRet;
+}
+#endif /* #ifdef HAVE_RECVMMSG */
+
+
+/* check configured scheduling priority.
+ * Precondition: iSchedPolicy must have been set
+ */
+static rsRetVal
+checkSchedulingPriority(modConfData_t *modConf)
+{
+ DEFiRet;
+
+#ifdef HAVE_SCHED_GET_PRIORITY_MAX
+ if( modConf->iSchedPrio < sched_get_priority_min(modConf->iSchedPolicy)
+ || modConf->iSchedPrio > sched_get_priority_max(modConf->iSchedPolicy)) {
+ LogError(0, NO_ERRCODE,
+ "imudp: scheduling priority %d out of range (%d - %d)"
+ " for scheduling policy '%s' - ignoring settings",
+ modConf->iSchedPrio,
+ sched_get_priority_min(modConf->iSchedPolicy),
+ sched_get_priority_max(modConf->iSchedPolicy),
+ modConf->pszSchedPolicy);
+ ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
+ }
+finalize_it:
+#endif
+ RETiRet;
+}
+
+
+/* check scheduling policy string and, if valid, set its
+ * numeric equivalent in current load config
+ */
+static rsRetVal
+checkSchedulingPolicy(modConfData_t *modConf)
+{
+ DEFiRet;
+
+ if (0) { /* trick to use conditional compilation */
+#ifdef SCHED_FIFO
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "fifo")) {
+ modConf->iSchedPolicy = SCHED_FIFO;
+#endif
+#ifdef SCHED_RR
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "rr")) {
+ modConf->iSchedPolicy = SCHED_RR;
+#endif
+#ifdef SCHED_OTHER
+ } else if (!strcasecmp((char*)modConf->pszSchedPolicy, "other")) {
+ modConf->iSchedPolicy = SCHED_OTHER;
+#endif
+ } else {
+ LogError(errno, NO_ERRCODE,
+ "imudp: invalid scheduling policy '%s' "
+ "- ignoring setting", modConf->pszSchedPolicy);
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* checks scheduling parameters during config check phase */
+static rsRetVal
+checkSchedParam(modConfData_t *modConf)
+{
+ DEFiRet;
+
+ if(modConf->pszSchedPolicy != NULL && modConf->iSchedPrio == SCHED_PRIO_UNSET) {
+ LogError(0, RS_RET_ERR_SCHED_PARAMS,
+ "imudp: scheduling policy set, but without priority - ignoring settings");
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ } else if(modConf->pszSchedPolicy == NULL && modConf->iSchedPrio != SCHED_PRIO_UNSET) {
+ LogError(0, RS_RET_ERR_SCHED_PARAMS,
+ "imudp: scheduling priority set, but without policy - ignoring settings");
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+ } else if(modConf->pszSchedPolicy != NULL && modConf->iSchedPrio != SCHED_PRIO_UNSET) {
+ /* we have parameters set, so check them */
+ CHKiRet(checkSchedulingPolicy(modConf));
+ CHKiRet(checkSchedulingPriority(modConf));
+ } else { /* nothing set */
+ modConf->iSchedPrio = SCHED_PRIO_UNSET; /* prevents doing the activation call */
+ }
+#ifndef HAVE_PTHREAD_SETSCHEDPARAM
+ LogError(0, NO_ERRCODE,
+ "imudp: cannot set thread scheduling policy, "
+ "pthread_setschedparam() not available");
+ ABORT_FINALIZE(RS_RET_ERR_SCHED_PARAMS);
+#endif
+
+finalize_it:
+ if(iRet != RS_RET_OK)
+ modConf->iSchedPrio = SCHED_PRIO_UNSET; /* prevents doing the activation call */
+
+ RETiRet;
+}
+
+/* set the configured scheduling policy (if possible) */
+static rsRetVal
+setSchedParams(modConfData_t *modConf)
+{
+ DEFiRet;
+
+# ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ int err;
+ struct sched_param sparam;
+
+ if(modConf->iSchedPrio == SCHED_PRIO_UNSET)
+ FINALIZE;
+
+ memset(&sparam, 0, sizeof sparam);
+ sparam.sched_priority = modConf->iSchedPrio;
+ dbgprintf("imudp trying to set sched policy to '%s', prio %d\n",
+ modConf->pszSchedPolicy, modConf->iSchedPrio);
+ err = pthread_setschedparam(pthread_self(), modConf->iSchedPolicy, &sparam);
+ if(err != 0) {
+ LogError(err, NO_ERRCODE, "imudp: pthread_setschedparam() failed - ignoring");
+ }
+finalize_it:
+# endif
+
+ RETiRet;
+}
+
+
+/* This function implements the main reception loop. Depending on the environment,
+ * we either use the traditional (but slower) select() or the Linux-specific epoll()
+ * interface. ./configure settings control which one is used.
+ * rgerhards, 2009-09-09
+ */
+#if defined(HAVE_EPOLL_CREATE1) || defined(HAVE_EPOLL_CREATE)
+#define NUM_EPOLL_EVENTS 10
+static rsRetVal
+rcvMainLoop(struct wrkrInfo_s *const __restrict__ pWrkr)
+{
+ DEFiRet;
+ int nfds;
+ int efd;
+ int i;
+ struct sockaddr_storage frominetPrev;
+ int bIsPermitted;
+ struct epoll_event *udpEPollEvt = NULL;
+ struct epoll_event currEvt[NUM_EPOLL_EVENTS];
+ char errStr[1024];
+ struct lstn_s *lstn;
+ int nLstn;
+
+ /* start "name caching" algo by making sure the previous system indicator
+ * is invalidated.
+ */
+ bIsPermitted = 0;
+ memset(&frominetPrev, 0, sizeof(frominetPrev));
+
+ /* count num listeners -- do it here in order to avoid inconsistency */
+ nLstn = 0;
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next)
+ ++nLstn;
+
+ if(nLstn == 0) {
+ LogError(errno, RS_RET_ERR,
+ "imudp error: we have 0 listeners, terminating"
+ "worker thread");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKmalloc(udpEPollEvt = calloc(nLstn, sizeof(struct epoll_event)));
+
+#if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1)
+ DBGPRINTF("imudp uses epoll_create1()\n");
+ efd = epoll_create1(EPOLL_CLOEXEC);
+ if(efd < 0 && errno == ENOSYS)
+#endif
+ {
+ DBGPRINTF("imudp uses epoll_create()\n");
+ efd = epoll_create(NUM_EPOLL_EVENTS);
+ }
+
+ if(efd < 0) {
+ DBGPRINTF("epoll_create1() could not create fd\n");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* fill the epoll set - we need to do this only once, as the set
+ * can not change dyamically.
+ */
+ i = 0;
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next) {
+ if(lstn->sock != -1) {
+ udpEPollEvt[i].events = EPOLLIN | EPOLLET;
+ udpEPollEvt[i].data.ptr = lstn;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, lstn->sock, &(udpEPollEvt[i])) < 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(errno, NO_ERRCODE, "epoll_ctrl failed on fd %d with %s\n",
+ lstn->sock, errStr);
+ }
+ }
+ i++;
+ }
+
+ while(1) {
+ /* wait for io to become ready */
+ nfds = epoll_wait(efd, currEvt, NUM_EPOLL_EVENTS, -1);
+ DBGPRINTF("imudp: epoll_wait() returned with %d fds\n", nfds);
+
+ if(pWrkr->pThrd->bShallStop == RSTRUE)
+ break; /* terminate input! */
+
+ for(i = 0 ; i < nfds ; ++i) {
+ processSocket(pWrkr, currEvt[i].data.ptr, &frominetPrev, &bIsPermitted);
+ }
+ if(pWrkr->pThrd->bShallStop == RSTRUE)
+ break; /* terminate input! */
+ }
+
+finalize_it:
+ if(udpEPollEvt != NULL)
+ free(udpEPollEvt);
+
+ RETiRet;
+}
+#else /* #if HAVE_EPOLL_CREATE1 */
+/* this is the code for the select() interface */
+static rsRetVal ATTR_NONNULL()
+rcvMainLoop(struct wrkrInfo_s *const __restrict__ pWrkr)
+{
+ DEFiRet;
+ int nfds;
+ struct sockaddr_storage frominetPrev;
+ int bIsPermitted;
+ int i = 0;
+ struct lstn_s *lstn;
+
+ DBGPRINTF("imudp uses poll() [ex-select]\n");
+ /* start "name caching" algo by making sure the previous system indicator
+ * is invalidated. */
+ bIsPermitted = 0;
+ memset(&frominetPrev, 0, sizeof(frominetPrev));
+
+ /* setup poll() subsystem */
+ int nfd = 0;
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next) {
+ if(lstn->sock != -1) {
+ if(Debug) {
+ net.debugListenInfo(lstn->sock, (char*)"UDP");
+ }
+ ++nfd;
+ }
+ }
+ struct pollfd *const pollfds = calloc(nfd, sizeof(struct pollfd));
+ CHKmalloc(pollfds);
+
+ for(lstn = lcnfRoot ; lstn != NULL ; lstn = lstn->next) {
+ assert(i < nfd);
+ if (lstn->sock != -1) {
+ pollfds[i].fd = lstn->sock;
+ pollfds[i].events = POLLIN;
+ ++i;
+ }
+ }
+
+ while(1) {
+ DBGPRINTF("--------imudp calling poll() on %d fds\n", nfd);
+ nfds = poll(pollfds, nfd, -1);
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ if(nfds < 0) {
+ if(errno == EINTR) {
+ DBGPRINTF("imudp: EINTR occurred\n");
+ } else {
+ LogMsg(errno, RS_RET_POLL_ERR, LOG_WARNING, "imudp: poll "
+ "system call failed, may cause further troubles");
+ }
+ nfds = 0;
+ }
+
+ i = 0;
+ for(lstn = lcnfRoot ; nfds && lstn != NULL ; lstn = lstn->next) {
+ assert(i < nfd);
+ if(lstn->sock != -1) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM); /* terminate input! */
+ if(pollfds[i].revents & POLLIN) {
+ processSocket(pWrkr, lstn, &frominetPrev, &bIsPermitted);
+ --nfds;
+ }
+ ++i;
+ }
+ }
+ /* end of a run, back to loop for next recv() */
+ }
+
+finalize_it:
+ RETiRet;
+}
+#endif /* #if HAVE_EPOLL_CREATE1 */
+
+
+static rsRetVal
+createListner(es_str_t *port, struct cnfparamvals *pvals)
+{
+ instanceConf_t *inst;
+ int i;
+ int bAppendPortUsed = 0;
+ DEFiRet;
+
+ CHKiRet(createInstance(&inst));
+ inst->pszBindPort = (uchar*)es_str2cstr(port, NULL);
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "port")) {
+ continue; /* array, handled by caller */
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ if(inst->inputname != NULL) {
+ LogError(0, RS_RET_INVALID_PARAMS, "imudp: name and inputname "
+ "parameter specified - only one can be used");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ inst->inputname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name.appendport")) {
+ if(bAppendPortUsed) {
+ LogError(0, RS_RET_INVALID_PARAMS, "imudp: name.appendport and "
+ "inputname.appendport parameter specified - only one can be used");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ inst->bAppendPortToInpname = (int) pvals[i].val.d.n;
+ bAppendPortUsed = 1;
+ } else if(!strcmp(inppblk.descr[i].name, "inputname")) {
+ LogError(0, RS_RET_DEPRECATED , "imudp: deprecated parameter inputname "
+ "used. Suggest to use name instead");
+ if(inst->inputname != NULL) {
+ LogError(0, RS_RET_INVALID_PARAMS, "imudp: name and inputname "
+ "parameter specified - only one can be used");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ inst->inputname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "inputname.appendport")) {
+ LogError(0, RS_RET_DEPRECATED , "imudp: deprecated parameter inputname.appendport "
+ "used. Suggest to use name.appendport instead");
+ if(bAppendPortUsed) {
+ LogError(0, RS_RET_INVALID_PARAMS, "imudp: name.appendport and "
+ "inputname.appendport parameter specified - only one can be used");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ bAppendPortUsed = 1;
+ inst->bAppendPortToInpname = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "defaulttz")) {
+ inst->dfltTZ = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "device")) {
+ inst->pszBindDevice = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "rcvbufsize")) {
+ const uint64_t val = pvals[i].val.d.n;
+ if(val > 1024 * 1024 * 1024) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imudp: rcvbufsize maximum is 1 GiB, using "
+ "default instead");
+ } else {
+ inst->rcvbuf = (int) val;
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "ipfreebind")) {
+ inst->ipfreebind = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imudp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ int i;
+ int portIdx;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imudp)\n");
+
+ if((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if(Debug) {
+ dbgprintf("input param blk in imudp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ portIdx = cnfparamGetIdx(&inppblk, "port");
+ assert(portIdx != -1);
+ for(i = 0 ; i < pvals[portIdx].val.d.ar->nmemb ; ++i) {
+ createListner(pvals[portIdx].val.d.ar->arr[i], pvals);
+ }
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ loadModConf->configSetViaV2Method = 0;
+ loadModConf->wrkrMax = 1; /* conservative, but least msg reordering */
+ loadModConf->batchSize = BATCH_SIZE_DFLT;
+ loadModConf->iTimeRequery = TIME_REQUERY_DFLT;
+ loadModConf->iSchedPrio = SCHED_PRIO_UNSET;
+ loadModConf->pszSchedPolicy = NULL;
+ loadModConf->bPreserveCase = 0; /* off */
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config vars */
+ cs.pszBindRuleset = NULL;
+ cs.pszSchedPolicy = NULL;
+ cs.pszBindAddr = NULL;
+ cs.pszBindDevice = NULL;
+ cs.iSchedPrio = SCHED_PRIO_UNSET;
+ cs.iTimeRequery = TIME_REQUERY_DFLT;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+ int wrkrMax;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imudp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imudp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "timerequery")) {
+ loadModConf->iTimeRequery = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "batchsize")) {
+ loadModConf->batchSize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "schedulingpriority")) {
+ loadModConf->iSchedPrio = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "schedulingpolicy")) {
+ loadModConf->pszSchedPolicy = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "threads")) {
+ wrkrMax = (int) pvals[i].val.d.n;
+ if(wrkrMax > MAX_WRKR_THREADS) {
+ LogError(0, RS_RET_PARAM_ERROR, "imudp: configured for %d"
+ "worker threads, but maximum permitted is %d",
+ wrkrMax, MAX_WRKR_THREADS);
+ loadModConf->wrkrMax = MAX_WRKR_THREADS;
+ } else {
+ loadModConf->wrkrMax = wrkrMax;
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) {
+ loadModConf->bPreserveCase = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imudp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* remove all of our legacy handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ loadModConf->iSchedPrio = cs.iSchedPrio;
+ loadModConf->iTimeRequery = cs.iTimeRequery;
+ if((cs.pszSchedPolicy != NULL) && (cs.pszSchedPolicy[0] != '\0')) {
+ CHKmalloc(loadModConf->pszSchedPolicy = ustrdup(cs.pszSchedPolicy));
+ }
+ }
+
+finalize_it:
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pszBindRuleset);
+ free(cs.pszSchedPolicy);
+ free(cs.pszBindAddr);
+ free(cs.pszBindDevice);
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ checkSchedParam(pModConf); /* this can not cause fatal errors */
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ if(pModConf->root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS , "imudp: module loaded, but "
+ "no listeners defined - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(inst);
+ }
+ /* if we could not set up any listeners, there is no point in running... */
+ if(lcnfRoot == NULL) {
+ LogError(0, NO_ERRCODE, "imudp: no listeners could be started, "
+ "input not activated.\n");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+ int i;
+ int lenRcvBuf;
+CODESTARTactivateCnf
+ /* caching various settings */
+ iMaxLine = glbl.GetMaxLine(runConf);
+ lenRcvBuf = iMaxLine + 1;
+# ifdef HAVE_RECVMMSG
+ lenRcvBuf *= runModConf->batchSize;
+# endif
+ DBGPRINTF("imudp: config params iMaxLine %d, lenRcvBuf %d\n", iMaxLine, lenRcvBuf);
+ for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
+# ifdef HAVE_RECVMMSG
+ CHKmalloc(wrkrInfo[i].recvmsg_iov = malloc(runModConf->batchSize * sizeof(struct iovec)));
+ CHKmalloc(wrkrInfo[i].recvmsg_mmh = malloc(runModConf->batchSize * sizeof(struct mmsghdr)));
+ CHKmalloc(wrkrInfo[i].frominet = malloc(runModConf->batchSize * sizeof(struct sockaddr_storage)));
+# endif
+ CHKmalloc(wrkrInfo[i].pRcvBuf = malloc(lenRcvBuf));
+ wrkrInfo[i].id = i;
+ }
+finalize_it:
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->pszBindPort);
+ free(inst->pszBindAddr);
+ free(inst->pszBindDevice);
+ free(inst->pszBindRuleset);
+ free(inst->inputname);
+ free(inst->dfltTZ);
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+
+static void *
+wrkr(void *myself)
+{
+ struct wrkrInfo_s *pWrkr = (struct wrkrInfo_s*) myself;
+ uchar thrdName[32];
+
+ snprintf((char*)thrdName, sizeof(thrdName), "imudp(w%d)", pWrkr->id);
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ /* set thread name - we ignore if the call fails, has no harsh consequences... */
+ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) {
+ DBGPRINTF("prctl failed, not setting thread name for '%s'\n", thrdName);
+ }
+# endif
+ dbgOutputTID((char*)thrdName);
+
+ /* Note well: the setting of scheduling parameters will not work
+ * when we dropped privileges (if the user is not sufficiently
+ * privileged, of course). Howerver, we can't change the
+ * scheduling params in PrePrivDrop(), as at that point our thread
+ * is not yet created. So at least as an interim solution, we do
+ * NOT support both setting sched parameters and dropping
+ * privileges within the same instance.
+ */
+ setSchedParams(runModConf);
+
+ /* support statistics gathering */
+ statsobj.Construct(&(pWrkr->stats));
+ statsobj.SetName(pWrkr->stats, thrdName);
+ statsobj.SetOrigin(pWrkr->stats, (uchar*)"imudp");
+ STATSCOUNTER_INIT(pWrkr->ctrCall_recvmmsg, pWrkr->mutCtrCall_recvmmsg);
+ statsobj.AddCounter(pWrkr->stats, UCHAR_CONSTANT("called.recvmmsg"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkr->ctrCall_recvmmsg));
+ STATSCOUNTER_INIT(pWrkr->ctrCall_recvmsg, pWrkr->mutCtrCall_recvmsg);
+ statsobj.AddCounter(pWrkr->stats, UCHAR_CONSTANT("called.recvmsg"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkr->ctrCall_recvmsg));
+ STATSCOUNTER_INIT(pWrkr->ctrMsgsRcvd, pWrkr->mutCtrMsgsRcvd);
+ statsobj.AddCounter(pWrkr->stats, UCHAR_CONSTANT("msgs.received"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkr->ctrMsgsRcvd));
+ statsobj.ConstructFinalize(pWrkr->stats);
+
+ rcvMainLoop(pWrkr);
+
+ /* cleanup */
+ return NULL;
+}
+
+/* This function is called to gather input.
+ * In essence, it just starts the pool of workers. To save resources,
+ * we run one of the workers on our own thread -- otherwise that thread would
+ * just idle around and wait for the workers to finish.
+ */
+BEGINrunInput
+ int i;
+ pthread_attr_t wrkrThrdAttr;
+CODESTARTrunInput
+ pthread_attr_init(&wrkrThrdAttr);
+ pthread_attr_setstacksize(&wrkrThrdAttr, 4096*1024);
+ for(i = 0 ; i < runModConf->wrkrMax - 1 ; ++i) {
+ wrkrInfo[i].pThrd = pThrd;
+ pthread_create(&wrkrInfo[i].tid, &wrkrThrdAttr, wrkr, &(wrkrInfo[i]));
+ }
+ pthread_attr_destroy(&wrkrThrdAttr);
+
+ wrkrInfo[i].pThrd = pThrd;
+ wrkrInfo[i].id = i;
+ wrkr(&wrkrInfo[i]);
+
+ for(i = 0 ; i < runModConf->wrkrMax - 1 ; ++i) {
+ pthread_kill(wrkrInfo[i].tid, SIGTTIN);
+ }
+ for(i = 0 ; i < runModConf->wrkrMax - 1 ; ++i) {
+ pthread_join(wrkrInfo[i].tid, NULL);
+ }
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ net.PrintAllowedSenders(1); /* UDP */
+ net.HasRestrictions(UCHAR_CONSTANT("UDP"), &bDoACLCheck); /* UDP */
+ENDwillRun
+
+
+BEGINafterRun
+ struct lstn_s *lstn, *lstnDel;
+ int i;
+CODESTARTafterRun
+ /* do cleanup here */
+ net.clearAllowedSenders((uchar*)"UDP");
+ for(lstn = lcnfRoot ; lstn != NULL ; ) {
+ statsobj.Destruct(&(lstn->stats));
+ ratelimitDestruct(lstn->ratelimiter);
+ close(lstn->sock);
+ prop.Destruct(&lstn->pInputName);
+ lstnDel = lstn;
+ lstn = lstn->next;
+ free(lstnDel);
+ }
+ lcnfRoot = lcnfLast = NULL;
+ for(i = 0 ; i < runModConf->wrkrMax ; ++i) {
+# ifdef HAVE_RECVMMSG
+ free(wrkrInfo[i].recvmsg_iov);
+ free(wrkrInfo[i].recvmsg_mmh);
+ free(wrkrInfo[i].frominet);
+# endif
+ free(wrkrInfo[i].pRcvBuf);
+ }
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(cs.pszBindAddr);
+ cs.pszBindAddr = NULL;
+ free(cs.pszBindDevice);
+ cs.pszBindDevice = NULL;
+ free(cs.pszSchedPolicy);
+ cs.pszSchedPolicy = NULL;
+ free(cs.pszBindRuleset);
+ cs.pszBindRuleset = NULL;
+ cs.iSchedPrio = SCHED_PRIO_UNSET;
+ cs.iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+
+ DBGPRINTF("imudp: version %s initializing\n", VERSION);
+# ifdef HAVE_RECVMMSG
+ DBGPRINTF("imdup: support for recvmmsg() present\n");
+# endif
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputudpserverbindruleset", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserverrun", 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserveraddress", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindAddr, STD_LOADABLE_MODULE_ID));
+ /* module-global config params - will be disabled in configs that are loaded
+ * via module(...).
+ */
+ CHKiRet(regCfSysLineHdlr2((uchar *)"imudpschedulingpolicy", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszSchedPolicy, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"imudpschedulingpriority", 0, eCmdHdlrInt,
+ NULL, &cs.iSchedPrio, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"udpservertimerequery", 0, eCmdHdlrInt,
+ NULL, &cs.iTimeRequery, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imuxsock/Makefile.am b/plugins/imuxsock/Makefile.am
new file mode 100644
index 0000000..6bf9c20
--- /dev/null
+++ b/plugins/imuxsock/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = imuxsock.la
+
+imuxsock_la_SOURCES = imuxsock.c
+imuxsock_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imuxsock_la_LDFLAGS = -module -avoid-version
+imuxsock_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+imuxsock_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+imuxsock_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/imuxsock/Makefile.in b/plugins/imuxsock/Makefile.in
new file mode 100644
index 0000000..88cca18
--- /dev/null
+++ b/plugins/imuxsock/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/imuxsock
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imuxsock_la_DEPENDENCIES =
+am_imuxsock_la_OBJECTS = imuxsock_la-imuxsock.lo
+imuxsock_la_OBJECTS = $(am_imuxsock_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 =
+imuxsock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imuxsock_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imuxsock_la-imuxsock.Plo
+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 = $(imuxsock_la_SOURCES)
+DIST_SOURCES = $(imuxsock_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imuxsock.la
+imuxsock_la_SOURCES = imuxsock.c
+imuxsock_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -I$(top_srcdir) \
+ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_1)
+imuxsock_la_LDFLAGS = -module -avoid-version $(am__append_2)
+imuxsock_la_LIBADD =
+all: 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) --gnu plugins/imuxsock/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/imuxsock/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+imuxsock.la: $(imuxsock_la_OBJECTS) $(imuxsock_la_DEPENDENCIES) $(EXTRA_imuxsock_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imuxsock_la_LINK) -rpath $(pkglibdir) $(imuxsock_la_OBJECTS) $(imuxsock_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imuxsock_la-imuxsock.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+imuxsock_la-imuxsock.lo: imuxsock.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imuxsock_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imuxsock_la-imuxsock.lo -MD -MP -MF $(DEPDIR)/imuxsock_la-imuxsock.Tpo -c -o imuxsock_la-imuxsock.lo `test -f 'imuxsock.c' || echo '$(srcdir)/'`imuxsock.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imuxsock_la-imuxsock.Tpo $(DEPDIR)/imuxsock_la-imuxsock.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imuxsock.c' object='imuxsock_la-imuxsock.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) $(imuxsock_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imuxsock_la-imuxsock.lo `test -f 'imuxsock.c' || echo '$(srcdir)/'`imuxsock.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imuxsock_la-imuxsock.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/imuxsock_la-imuxsock.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
new file mode 100644
index 0000000..1ae550e
--- /dev/null
+++ b/plugins/imuxsock/imuxsock.c
@@ -0,0 +1,1767 @@
+/* imuxsock.c
+ * This is the implementation of the Unix sockets input module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-12-20 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifdef __sun
+#define _XPG4_2
+#endif
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#ifdef HAVE_LIBSYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+#if defined(__FreeBSD__)
+ #include <sys/param.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "net.h"
+#include "glbl.h"
+#include "msg.h"
+#include "parser.h"
+#include "prop.h"
+#include "debug.h"
+#include "ruleset.h"
+#include "unlimited_select.h"
+#include "statsobj.h"
+#include "datetime.h"
+#include "hashtable.h"
+#include "ratelimit.h"
+
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imuxsock")
+
+/* defines */
+#ifndef _PATH_LOG
+#ifdef BSD
+#define _PATH_LOG "/var/run/log"
+#else
+#define _PATH_LOG "/dev/log"
+#endif
+#endif
+#ifndef SYSTEMD_JOURNAL
+#define SYSTEMD_JOURNAL "/run/systemd/journal"
+#endif
+#ifndef SYSTEMD_PATH_LOG
+#define SYSTEMD_PATH_LOG SYSTEMD_JOURNAL "/syslog"
+#endif
+#define UNSET -1 /* to indicate a value has not been configured */
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+#if defined(_AIX)
+#define ucred ucred_t
+#endif
+/* emulate struct ucred for platforms that do not have it */
+#ifndef HAVE_SCM_CREDENTIALS
+struct ucred { int pid; uid_t uid; gid_t gid; };
+#endif
+
+/* handle some defines missing on more than one platform */
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(ruleset)
+
+
+statsobj_t *modStats;
+STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+STATSCOUNTER_DEF(ctrLostRatelimit, mutCtrLostRatelimit)
+STATSCOUNTER_DEF(ctrNumRatelimiters, mutCtrNumRatelimiters)
+
+
+/* a very simple "hash function" for process IDs - we simply use the
+ * pid itself: it is quite expected that all pids may log some time, but
+ * from a collision point of view it is likely that long-running daemons
+ * start early and so will stay right in the top spots of the
+ * collision list.
+ */
+static unsigned int
+hash_from_key_fn(void *k)
+{
+ return((unsigned) *((pid_t*) k));
+}
+
+static int
+key_equals_fn(void *key1, void *key2)
+{
+ return *((pid_t*) key1) == *((pid_t*) key2);
+}
+
+
+/* structure to describe a specific listener */
+typedef struct lstn_s {
+ uchar *sockName; /* read-only after startup */
+ prop_t *hostName; /* host-name override - if set, use this instead of actual name */
+ int fd; /* read-only after startup */
+ int flags; /* should parser parse host name? read-only after startup */
+ int flowCtl; /* flow control settings for this socket */
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ ratelimit_t *dflt_ratelimiter;/*ratelimiter to apply if none else is to be used */
+ intTiny ratelimitSev; /* severity level (and below) for which rate-limiting shall apply */
+ struct hashtable *ht; /* our hashtable for rate-limiting */
+ sbool bParseHost; /* should parser parse host name? read-only after startup */
+ sbool bCreatePath; /* auto-creation of socket directory? */
+ sbool bUseCreds; /* pull original creator credentials from socket */
+ sbool bAnnotate; /* annotate events with trusted properties */
+ sbool bParseTrusted; /* parse trusted properties */
+ sbool bWritePid; /* write original PID into tag */
+ sbool bDiscardOwnMsgs; /* discard messages that originated from ourselves */
+ sbool bUseSysTimeStamp; /* use timestamp from system (instead of from message) */
+ sbool bUnlink; /* unlink&re-create socket at start and end of processing */
+ sbool bUseSpecialParser;/* use "canned" log socket parser instead of parser chain? */
+ ruleset_t *pRuleset;
+} lstn_t;
+static lstn_t *listeners;
+
+static prop_t *pLocalHostIP = NULL; /* there is only one global IP for all internally-generated messages */
+static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */
+static int startIndexUxLocalSockets; /* process fd from that index on (used to
+ * suppress local logging. rgerhards 2005-08-01
+ * read-only after startup
+ */
+static int nfd = 1; /* number of active unix sockets (socket 0 is always reserved for the system
+ socket, even if it is not enabled. */
+static int sd_fds = 0; /* number of systemd activated sockets */
+
+#if (defined(__FreeBSD__) && (__FreeBSD_version >= 1200061))
+ #define DFLT_bUseSpecialParser 0
+#else
+ #define DFLT_bUseSpecialParser 1
+#endif
+#define DFLT_bCreatePath 0
+#define DFLT_ratelimitInterval 0
+#define DFLT_ratelimitBurst 200
+#define DFLT_ratelimitSeverity 1 /* do not rate-limit emergency messages */
+/* config vars for the legacy config system */
+static struct configSettings_s {
+ int bOmitLocalLogging;
+ uchar *pLogSockName;
+ uchar *pLogHostName; /* host name to use with this socket */
+ int bUseFlowCtl; /* use flow control or not (if yes, only LIGHT is used!) */
+ int bUseFlowCtlSysSock;
+ int bIgnoreTimestamp; /* ignore timestamps present in the incoming message? */
+ int bIgnoreTimestampSysSock;
+ int bUseSysTimeStamp; /* use timestamp from system (rather than from message) */
+ int bUseSysTimeStampSysSock; /* same, for system log socket */
+ int bWritePid; /* use credentials from recvmsg() and fixup PID in TAG */
+ int bWritePidSysSock; /* use credentials from recvmsg() and fixup PID in TAG */
+ int bCreatePath; /* auto-create socket path? */
+ unsigned int ratelimitInterval; /* interval in seconds, 0 = off */
+ unsigned int ratelimitIntervalSysSock;
+ unsigned int ratelimitBurst; /* max nbr of messages in interval */
+ unsigned int ratelimitBurstSysSock;
+ int ratelimitSeverity;
+ int ratelimitSeveritySysSock;
+ int bAnnotate; /* annotate trusted properties */
+ int bAnnotateSysSock; /* same, for system log socket */
+ int bParseTrusted; /* parse trusted properties */
+} cs;
+
+/* config vars for the v2 config system (rsyslog v6+) */
+struct instanceConf_s {
+ uchar *sockName;
+ uchar *pLogHostName; /* host name to use with this socket */
+ sbool bUseFlowCtl; /* use flow control or not (if yes, only LIGHT is used! */
+ sbool bIgnoreTimestamp; /* ignore timestamps present in the incoming message? */
+ sbool bWritePid; /* use credentials from recvmsg() and fixup PID in TAG */
+ sbool bUseSysTimeStamp; /* use timestamp from system (instead of from message) */
+ int bCreatePath; /* auto-create socket path? */
+ unsigned int ratelimitInterval; /* interval in seconds, 0 = off */
+ unsigned int ratelimitBurst; /* max nbr of messages in interval */
+ int ratelimitSeverity;
+ int bAnnotate; /* annotate trusted properties */
+ int bParseTrusted; /* parse trusted properties */
+ sbool bDiscardOwnMsgs; /* discard messages that originated from our own pid? */
+ sbool bUnlink;
+ sbool bUseSpecialParser;
+ sbool bParseHost;
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ struct instanceConf_s *next;
+};
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ uchar *pLogSockName;
+ unsigned int ratelimitIntervalSysSock;
+ unsigned int ratelimitBurstSysSock;
+ int ratelimitSeveritySysSock;
+ int bAnnotateSysSock;
+ int bParseTrusted;
+ int bUseSpecialParser;
+ int bParseHost;
+ sbool bIgnoreTimestamp; /* ignore timestamps present in the incoming message? */
+ sbool bUseFlowCtl; /* use flow control or not (if yes, only LIGHT is used! */
+ sbool bOmitLocalLogging;
+ sbool bWritePidSysSock;
+ sbool bUseSysTimeStamp;
+ sbool bDiscardOwnMsgs;
+ sbool configSetViaV2Method;
+ sbool bUnlink;
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "syssock.use", eCmdHdlrBinary, 0 },
+ { "syssock.name", eCmdHdlrGetWord, 0 },
+ { "syssock.unlink", eCmdHdlrBinary, 0 },
+ { "syssock.ignoretimestamp", eCmdHdlrBinary, 0 },
+ { "syssock.ignoreownmessages", eCmdHdlrBinary, 0 },
+ { "syssock.flowcontrol", eCmdHdlrBinary, 0 },
+ { "syssock.usesystimestamp", eCmdHdlrBinary, 0 },
+ { "syssock.annotate", eCmdHdlrBinary, 0 },
+ { "syssock.parsetrusted", eCmdHdlrBinary, 0 },
+ { "syssock.usespecialparser", eCmdHdlrBinary, 0 },
+ { "syssock.parsehostname", eCmdHdlrBinary, 0 },
+ { "syssock.usepidfromsystem", eCmdHdlrBinary, 0 },
+ { "syssock.ratelimit.interval", eCmdHdlrInt, 0 },
+ { "syssock.ratelimit.burst", eCmdHdlrInt, 0 },
+ { "syssock.ratelimit.severity", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "socket", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: addunixlistensocket */
+ { "unlink", eCmdHdlrBinary, 0 },
+ { "createpath", eCmdHdlrBinary, 0 },
+ { "parsetrusted", eCmdHdlrBinary, 0 },
+ { "ignoreownmessages", eCmdHdlrBinary, 0 },
+ { "hostname", eCmdHdlrString, 0 },
+ { "ignoretimestamp", eCmdHdlrBinary, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "usesystimestamp", eCmdHdlrBinary, 0 },
+ { "annotate", eCmdHdlrBinary, 0 },
+ { "usespecialparser", eCmdHdlrBinary, 0 },
+ { "parsehostname", eCmdHdlrBinary, 0 },
+ { "usepidfromsystem", eCmdHdlrBinary, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "ratelimit.severity", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->sockName = NULL;
+ inst->pLogHostName = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pBindRuleset = NULL;
+ inst->ratelimitInterval = DFLT_ratelimitInterval;
+ inst->ratelimitBurst = DFLT_ratelimitBurst;
+ inst->ratelimitSeverity = DFLT_ratelimitSeverity;
+ inst->bUseFlowCtl = 0;
+ inst->bUseSpecialParser = DFLT_bUseSpecialParser;
+ inst->bParseHost = UNSET;
+ inst->bIgnoreTimestamp = 1;
+ inst->bCreatePath = DFLT_bCreatePath;
+ inst->bUseSysTimeStamp = 1;
+ inst->bWritePid = 0;
+ inst->bAnnotate = 0;
+ inst->bParseTrusted = 0;
+ inst->bDiscardOwnMsgs = loadModConf->pConf->globals.bProcessInternalMessages;
+ inst->bUnlink = 1;
+ inst->next = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called when a new listen socket instance shall be added to
+ * the current config object via the legacy config system. It just shuffles
+ * all parameters to the listener in-memory instance.
+ * rgerhards, 2011-05-12
+ */
+static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+
+ if(pNewVal == NULL || pNewVal[0] == '\0') {
+ LogError(0, RS_RET_SOCKNAME_MISSING , "imuxsock: socket name must be specified, "
+ "but is not - listener not created\n");
+ if(pNewVal != NULL)
+ free(pNewVal);
+ ABORT_FINALIZE(RS_RET_SOCKNAME_MISSING);
+ }
+
+ CHKiRet(createInstance(&inst));
+ inst->sockName = pNewVal;
+ inst->ratelimitInterval = cs.ratelimitInterval;
+ inst->pLogHostName = cs.pLogHostName;
+ inst->ratelimitBurst = cs.ratelimitBurst;
+ inst->ratelimitSeverity = cs.ratelimitSeverity;
+ inst->bUseFlowCtl = cs.bUseFlowCtl;
+ inst->bIgnoreTimestamp = cs.bIgnoreTimestamp;
+ inst->bCreatePath = cs.bCreatePath;
+ inst->bUseSysTimeStamp = cs.bUseSysTimeStamp;
+ inst->bWritePid = cs.bWritePid;
+ inst->bAnnotate = cs.bAnnotate;
+ inst->bParseTrusted = cs.bParseTrusted;
+ inst->bParseHost = UNSET;
+ inst->next = NULL;
+
+ /* reset hostname for next socket */
+ cs.pLogHostName = NULL;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* add an additional listen socket.
+ * added capability to specify hostname for socket -- rgerhards, 2008-08-01
+ */
+static rsRetVal
+addListner(instanceConf_t *inst)
+{
+ DEFiRet;
+
+ if(inst->bParseHost == UNSET) {
+ if(*inst->sockName == ':') {
+ listeners[nfd].bParseHost = 1;
+ } else {
+ listeners[nfd].bParseHost = 0;
+ }
+ } else {
+ listeners[nfd].bParseHost = inst->bParseHost;
+ }
+ if(inst->pLogHostName == NULL) {
+ listeners[nfd].hostName = NULL;
+ } else {
+ CHKiRet(prop.Construct(&(listeners[nfd].hostName)));
+ CHKiRet(prop.SetString(listeners[nfd].hostName, inst->pLogHostName, ustrlen(inst->pLogHostName)));
+ CHKiRet(prop.ConstructFinalize(listeners[nfd].hostName));
+ }
+ if(inst->ratelimitInterval > 0) {
+ if((listeners[nfd].ht = create_hashtable(100, hash_from_key_fn, key_equals_fn,
+ (void(*)(void*))ratelimitDestruct)) == NULL) {
+ /* in this case, we simply turn off rate-limiting */
+ DBGPRINTF("imuxsock: turning off rate limiting because we could not "
+ "create hash table\n");
+ inst->ratelimitInterval = 0;
+ }
+ } else {
+ listeners[nfd].ht = NULL;
+ }
+ listeners[nfd].ratelimitInterval = inst->ratelimitInterval;
+ listeners[nfd].ratelimitBurst = inst->ratelimitBurst;
+ listeners[nfd].ratelimitSev = inst->ratelimitSeverity;
+ listeners[nfd].flowCtl = inst->bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
+ listeners[nfd].flags = inst->bIgnoreTimestamp ? IGNDATE : NOFLAG;
+ listeners[nfd].bCreatePath = inst->bCreatePath;
+ listeners[nfd].sockName = ustrdup(inst->sockName);
+ listeners[nfd].bUseCreds = (inst->bDiscardOwnMsgs || inst->bWritePid || inst->ratelimitInterval
+ || inst->bAnnotate || inst->bUseSysTimeStamp) ? 1 : 0;
+ listeners[nfd].bAnnotate = inst->bAnnotate;
+ listeners[nfd].bParseTrusted = inst->bParseTrusted;
+ listeners[nfd].bDiscardOwnMsgs = inst->bDiscardOwnMsgs;
+ listeners[nfd].bUnlink = inst->bUnlink;
+ listeners[nfd].bWritePid = inst->bWritePid;
+ listeners[nfd].bUseSysTimeStamp = inst->bUseSysTimeStamp;
+ listeners[nfd].bUseSpecialParser = inst->bUseSpecialParser;
+ listeners[nfd].pRuleset = inst->pBindRuleset;
+ CHKiRet(ratelimitNew(&listeners[nfd].dflt_ratelimiter, "imuxsock", NULL));
+ ratelimitSetLinuxLike(listeners[nfd].dflt_ratelimiter,
+ listeners[nfd].ratelimitInterval,
+ listeners[nfd].ratelimitBurst);
+ ratelimitSetSeverity(listeners[nfd].dflt_ratelimiter,
+ listeners[nfd].ratelimitSev);
+ nfd++;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal discardLogSockets(void)
+{
+ int i;
+
+ /* Check whether the system socket is in use */
+ if(startIndexUxLocalSockets == 0) {
+ /* Clean up rate limiting data for the system socket */
+ if(listeners[0].ht != NULL) {
+ hashtable_destroy(listeners[0].ht, 1); /* 1 => free all values automatically */
+ }
+ ratelimitDestruct(listeners[0].dflt_ratelimiter);
+ }
+
+ /* Clean up all other sockets */
+ for (i = 1; i < nfd; i++) {
+ if(listeners[i].sockName != NULL) {
+ free(listeners[i].sockName);
+ listeners[i].sockName = NULL;
+ }
+ if(listeners[i].hostName != NULL) {
+ prop.Destruct(&(listeners[i].hostName));
+ }
+ if(listeners[i].ht != NULL) {
+ hashtable_destroy(listeners[i].ht, 1); /* 1 => free all values automatically */
+ }
+ ratelimitDestruct(listeners[i].dflt_ratelimiter);
+ }
+
+ return RS_RET_OK;
+}
+
+
+/* used to create a log socket if NOT passed in via systemd.
+ */
+/* note: the linux SUN_LEN macro uses a sizeof based on a NULL pointer. This
+ * triggers UBSan warning. As such, we turn that warning off for the fuction.
+ * As it is OS-provided, there is no way to solve it ourselves. The problem
+ * may also exist on other platforms, we have just noticed it on Linux.
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static rsRetVal
+#if defined(__clang__)
+__attribute__((no_sanitize("undefined")))
+#endif
+createLogSocket(lstn_t *pLstn)
+{
+ struct sockaddr_un sunx;
+ DEFiRet;
+
+ if(pLstn->bUnlink)
+ unlink((char*)pLstn->sockName);
+ memset(&sunx, 0, sizeof(sunx));
+ sunx.sun_family = AF_UNIX;
+ if(pLstn->bCreatePath) {
+ makeFileParentDirs((uchar*)pLstn->sockName, ustrlen(pLstn->sockName), 0755, -1, -1, 0);
+ }
+ strncpy(sunx.sun_path, (char*)pLstn->sockName, sizeof(sunx.sun_path));
+ sunx.sun_path[sizeof(sunx.sun_path)-1] = '\0';
+ pLstn->fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(pLstn->fd < 0 ) {
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+ if(bind(pLstn->fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0) {
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+ if(chmod((char*)pLstn->sockName, 0666) < 0) {
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(errno, iRet, "cannot create '%s'", pLstn->sockName);
+ if(pLstn->fd != -1) {
+ close(pLstn->fd);
+ pLstn->fd = -1;
+ }
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+openLogSocket(lstn_t *pLstn)
+{
+ DEFiRet;
+# ifdef HAVE_SCM_CREDENTIALS
+ int one;
+# endif /* HAVE_SCM_CREDENTIALS */
+
+ if(pLstn->sockName[0] == '\0')
+ return -1;
+
+ pLstn->fd = -1;
+
+#ifdef HAVE_LIBSYSTEMD
+ if (sd_fds > 0) {
+ /* Check if the current socket is a systemd activated one.
+ * If so, just use it.
+ */
+ int fd;
+
+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + sd_fds; fd++) {
+ if( sd_is_socket_unix(fd, SOCK_DGRAM, -1, (const char*) pLstn->sockName, 0) == 1) {
+ /* ok, it matches -- just use as is */
+ pLstn->fd = fd;
+
+ LogMsg(0, NO_ERRCODE, LOG_INFO,
+ "imuxsock: Acquired UNIX socket '%s' (fd %d) from systemd.\n",
+ pLstn->sockName, pLstn->fd);
+ break;
+ }
+ /*
+ * otherwise it either didn't match *this* socket and
+ * we just continue to check the next one or there was
+ * an error and we will create a new socket below.
+ */
+ }
+ }
+#endif
+
+ if (pLstn->fd == -1) {
+ CHKiRet(createLogSocket(pLstn));
+ assert(pLstn->fd != -1); /* else createLogSocket() should have failed! */
+ }
+
+# ifdef HAVE_SCM_CREDENTIALS
+ if(pLstn->bUseCreds) {
+ one = 1;
+ if(setsockopt(pLstn->fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t) sizeof(one)) != 0) {
+ LogError(errno, NO_ERRCODE, "set SO_PASSCRED failed on '%s'", pLstn->sockName);
+ pLstn->bUseCreds = 0;
+ }
+// TODO: move to its own #if
+ if(setsockopt(pLstn->fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)) != 0) {
+ LogError(errno, NO_ERRCODE, "set SO_TIMESTAMP failed on '%s'", pLstn->sockName);
+ }
+ }
+# else /* HAVE_SCM_CREDENTIALS */
+ pLstn->bUseCreds = 0;
+ pLstn->bAnnotate = 0;
+# endif /* HAVE_SCM_CREDENTIALS */
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pLstn->fd != -1) {
+ close(pLstn->fd);
+ pLstn->fd = -1;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* find ratelimiter to use for this message. Currently, we use the
+ * pid, but may change to cgroup later (probably via a config switch).
+ * Returns NULL if not found or rate-limiting not activated for this
+ * listener (the latter being a performance enhancement).
+ */
+static rsRetVal
+findRatelimiter(lstn_t *pLstn, struct ucred *cred, ratelimit_t **prl)
+{
+ ratelimit_t *rl = NULL;
+ int r;
+ pid_t *keybuf;
+ char pinfobuf[512];
+ DEFiRet;
+
+ if(cred == NULL)
+ FINALIZE;
+#if 0 // TODO: check deactivated?
+ if(pLstn->ratelimitInterval == 0) {
+ *prl = NULL;
+ FINALIZE;
+ }
+#endif
+ if(pLstn->ht == NULL) {
+ *prl = NULL;
+ FINALIZE;
+ }
+
+ rl = hashtable_search(pLstn->ht, &cred->pid);
+ if(rl == NULL) {
+ /* we need to add a new ratelimiter, process not seen before! */
+ DBGPRINTF("imuxsock: no ratelimiter for pid %lu, creating one\n",
+ (unsigned long) cred->pid);
+ STATSCOUNTER_INC(ctrNumRatelimiters, mutCtrNumRatelimiters);
+ /* read process name from system */
+ char procName[256]; /* enough for any sane process name */
+ snprintf(procName, sizeof(procName), "/proc/%lu/cmdline", (unsigned long) cred->pid);
+ FILE *f = fopen(procName, "r");
+ if (f) {
+ size_t len;
+ len = fread(procName, sizeof(char), 256, f);
+ if (len > 0) {
+ snprintf(pinfobuf, sizeof(pinfobuf), "pid: %lu, name: %s",
+ (unsigned long) cred->pid, procName);
+ }
+ fclose(f);
+ }
+ else {
+ snprintf(pinfobuf, sizeof(pinfobuf), "pid: %lu",
+ (unsigned long) cred->pid);
+ }
+ pinfobuf[sizeof(pinfobuf)-1] = '\0'; /* to be on safe side */
+ CHKiRet(ratelimitNew(&rl, "imuxsock", pinfobuf));
+ ratelimitSetLinuxLike(rl, pLstn->ratelimitInterval, pLstn->ratelimitBurst);
+ ratelimitSetSeverity(rl, pLstn->ratelimitSev);
+ CHKmalloc(keybuf = malloc(sizeof(pid_t)));
+ *keybuf = cred->pid;
+ r = hashtable_insert(pLstn->ht, keybuf, rl);
+ if(r == 0)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ *prl = rl;
+ rl = NULL;
+
+finalize_it:
+ if(rl != NULL)
+ ratelimitDestruct(rl);
+ if(*prl == NULL)
+ *prl = pLstn->dflt_ratelimiter;
+ RETiRet;
+}
+
+
+/* patch correct pid into tag. bufTAG MUST be CONF_TAG_MAXSIZE long!
+ */
+static void
+fixPID(uchar *bufTAG, int *lenTag, struct ucred *cred)
+{
+ int i;
+ char bufPID[16];
+ int lenPID;
+
+ if(cred == NULL)
+ return;
+
+ lenPID = snprintf(bufPID, sizeof(bufPID), "[%lu]:", (unsigned long) cred->pid);
+
+ for(i = *lenTag ; i >= 0 && bufTAG[i] != '[' ; --i)
+ /*JUST SKIP*/;
+
+ if(i < 0)
+ i = *lenTag - 1; /* go right at end of TAG, pid was not present (-1 for ':') */
+
+ if(i + lenPID > CONF_TAG_MAXSIZE)
+ return; /* do not touch, as things would break */
+
+ memcpy(bufTAG + i, bufPID, lenPID);
+ *lenTag = i + lenPID;
+}
+
+
+/* Get an "trusted property" from the system. Returns an empty string if the
+ * property can not be obtained. Inspired by similiar functionality inside
+ * journald. Currently works with Linux /proc filesystem, only.
+ */
+static rsRetVal
+getTrustedProp(struct ucred *cred, const char *propName, uchar *buf, size_t lenBuf, int *lenProp)
+{
+ int fd;
+ int i;
+ int lenRead;
+ char namebuf[1024];
+ DEFiRet;
+
+ if(snprintf(namebuf, sizeof(namebuf), "/proc/%lu/%s", (long unsigned) cred->pid,
+ propName) >= (int) sizeof(namebuf)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((fd = open(namebuf, O_RDONLY)) == -1) {
+ DBGPRINTF("error reading '%s'\n", namebuf);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if((lenRead = read(fd, buf, lenBuf - 1)) == -1) {
+ DBGPRINTF("error reading file data for '%s'\n", namebuf);
+ close(fd);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* we strip after the first \n */
+ for(i = 0 ; i < lenRead ; ++i) {
+ if(buf[i] == '\n')
+ break;
+ else if(iscntrl(buf[i]))
+ buf[i] = ' ';
+ }
+ buf[i] = '\0';
+ *lenProp = i;
+
+ close(fd);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read the exe trusted property path (so far, /proc fs only)
+ */
+static rsRetVal
+getTrustedExe(struct ucred *cred, uchar *buf, size_t lenBuf, int* lenProp)
+{
+ int lenRead;
+ char namebuf[1024];
+ DEFiRet;
+
+ if(snprintf(namebuf, sizeof(namebuf), "/proc/%lu/exe", (long unsigned) cred->pid)
+ >= (int) sizeof(namebuf)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((lenRead = readlink(namebuf, (char*)buf, lenBuf - 1)) == -1) {
+ DBGPRINTF("error reading link '%s'\n", namebuf);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ buf[lenRead] = '\0';
+ *lenProp = lenRead;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* copy a trusted property in escaped mode. That is, the property can contain
+ * any character and so it must be properly quoted AND escaped.
+ * It is assumed the output buffer is large enough. Returns the number of
+ * characters added.
+ */
+static int
+copyescaped(uchar *dstbuf, uchar *inbuf, int inlen)
+{
+ int iDst, iSrc;
+
+ *dstbuf = '"';
+ for(iDst=1, iSrc=0 ; iSrc < inlen ; ++iDst, ++iSrc) {
+ if(inbuf[iSrc] == '"' || inbuf[iSrc] == '\\') {
+ dstbuf[iDst++] = '\\';
+ }
+ dstbuf[iDst] = inbuf[iSrc];
+ }
+ dstbuf[iDst++] = '"';
+ return iDst;
+}
+
+
+/* submit received message to the queue engine
+ * We now parse the message according to expected format so that we
+ * can also mangle it if necessary.
+ */
+static rsRetVal
+SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct timeval *ts)
+{
+ smsg_t *pMsg = NULL;
+ int lenMsg;
+ int offs;
+ int i;
+ uchar *parse;
+ syslog_pri_t pri;
+ uchar bufParseTAG[CONF_TAG_MAXSIZE];
+ struct syslogTime st;
+ time_t tt;
+ ratelimit_t *ratelimiter = NULL;
+ struct syslogTime dummyTS;
+ DEFiRet;
+
+ if(pLstn->bDiscardOwnMsgs && cred != NULL && cred->pid == glblGetOurPid()) {
+ DBGPRINTF("imuxsock: discarding message from our own pid\n");
+ FINALIZE;
+ }
+
+ /* TODO: handle format errors?? */
+ /* we need to parse the pri first, because we need the severity for
+ * rate-limiting as well.
+ */
+ parse = pRcv;
+ lenMsg = lenRcv;
+ offs = 1; /* '<' */
+
+ parse++;
+ pri = 0;
+ while(offs < lenMsg && isdigit(*parse)) {
+ pri = pri * 10 + *parse - '0';
+ ++parse;
+ ++offs;
+ }
+
+ findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
+
+ if(ts == NULL) {
+ datetime.getCurrTime(&st, &tt, TIME_IN_LOCALTIME);
+ } else {
+ datetime.timeval2syslogTime(ts, &st, TIME_IN_LOCALTIME);
+ tt = ts->tv_sec;
+ }
+
+#if 0 // TODO: think about stats counters (or wait for request...?)
+ if(ratelimiter != NULL && !withinRatelimit(ratelimiter, tt, cred->pid)) {
+ STATSCOUNTER_INC(ctrLostRatelimit, mutCtrLostRatelimit);
+ FINALIZE;
+ }
+#endif
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, &st, tt));
+
+ /* created trusted properties */
+ if(cred != NULL && pLstn->bAnnotate) {
+ uchar propBuf[1024];
+ int lenProp;
+
+ if (pLstn->bParseTrusted) {
+ struct json_object *json, *jval;
+
+#define CHKjson(operation, toBeFreed) \
+ if((operation) == NULL) { \
+ json_object_put(toBeFreed); \
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); \
+ }
+
+ CHKmalloc(json = json_object_new_object());
+ /* create value string, create field, and add it */
+ CHKjson(jval = json_object_new_int(cred->pid), json);
+ json_object_object_add(json, "pid", jval);
+ CHKjson(jval = json_object_new_int(cred->uid), json);
+ json_object_object_add(json, "uid", jval);
+ CHKjson(jval = json_object_new_int(cred->gid), json);
+ json_object_object_add(json, "gid", jval);
+ if(getTrustedProp(cred, "comm", propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ CHKjson(jval = json_object_new_string((char*)propBuf), json);
+ json_object_object_add(json, "appname", jval);
+ }
+ if(getTrustedExe(cred, propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ CHKjson(jval = json_object_new_string((char*)propBuf), json);
+ json_object_object_add(json, "exe", jval);
+ }
+ if(getTrustedProp(cred, "cmdline", propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ CHKjson(jval = json_object_new_string((char*)propBuf), json);
+ json_object_object_add(json, "cmd", jval);
+ }
+#undef CHKjson
+
+ /* as per lumberjack spec, these properties need to go into
+ * the CEE root.
+ */
+ msgAddJSON(pMsg, (uchar*)"!", json, 0, 0);
+
+ MsgSetRawMsg(pMsg, (char*)pRcv, lenRcv);
+ } else {
+ uchar msgbuf[8192];
+ uchar *pmsgbuf = msgbuf;
+ int toffs; /* offset for trusted properties */
+
+ if((unsigned) (lenRcv + 4096) >= sizeof(msgbuf)) {
+ CHKmalloc(pmsgbuf = malloc(lenRcv+4096));
+ }
+
+ memcpy(pmsgbuf, pRcv, lenRcv);
+ memcpy(pmsgbuf+lenRcv, " @[", 3);
+ toffs = lenRcv + 3; /* next free location */
+ lenProp = snprintf((char*)propBuf, sizeof(propBuf), "_PID=%lu _UID=%lu _GID=%lu",
+ (long unsigned) cred->pid, (long unsigned) cred->uid,
+ (long unsigned) cred->gid);
+ memcpy(pmsgbuf+toffs, propBuf, lenProp);
+ toffs = toffs + lenProp;
+
+ if(getTrustedProp(cred, "comm", propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ memcpy(pmsgbuf+toffs, " _COMM=", 7);
+ memcpy(pmsgbuf+toffs+7, propBuf, lenProp);
+ toffs = toffs + 7 + lenProp;
+ }
+ if(getTrustedExe(cred, propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ memcpy(pmsgbuf+toffs, " _EXE=", 6);
+ memcpy(pmsgbuf+toffs+6, propBuf, lenProp);
+ toffs = toffs + 6 + lenProp;
+ }
+ if(getTrustedProp(cred, "cmdline", propBuf, sizeof(propBuf), &lenProp) == RS_RET_OK) {
+ memcpy(pmsgbuf+toffs, " _CMDLINE=", 10);
+ toffs = toffs + 10 +
+ copyescaped(pmsgbuf+toffs+10, propBuf, lenProp);
+ }
+
+ /* finalize string */
+ pmsgbuf[toffs] = ']';
+ pmsgbuf[toffs+1] = '\0';
+
+ MsgSetRawMsg(pMsg, (char*)pmsgbuf, toffs + 1);
+ if (pmsgbuf != msgbuf) {
+ free(pmsgbuf);
+ }
+ }
+ } else {
+ /* just add the unmodified message */
+ MsgSetRawMsg(pMsg, (char*)pRcv, lenRcv);
+ }
+
+ MsgSetFlowControlType(pMsg, pLstn->flowCtl);
+ MsgSetInputName(pMsg, pInputName);
+ if(pLstn->bParseHost) {
+ pMsg->msgFlags = pLstn->flags | PARSE_HOSTNAME;
+ } else {
+ pMsg->msgFlags = pLstn->flags;
+ }
+
+ if(pLstn->bUseSpecialParser) {
+ /* this is the legacy "log socket" parser which was written on the assumption
+ * that the log socket format would be fixed. While many folks said so, it
+ * seems to be different in practice, and this is why we now have choices...
+ * rgerhards, 2015-03-03
+ */
+ parser.SanitizeMsg(pMsg);
+ lenMsg = pMsg->iLenRawMsg - offs; /* SanitizeMsg() may have changed the size */
+ msgSetPRI(pMsg, pri);
+ MsgSetAfterPRIOffs(pMsg, offs);
+
+ parse++; lenMsg--; /* '>' */
+ if(ts == NULL) {
+ if((pLstn->flags & IGNDATE)) {
+ /* in this case, we still need to find out if we have a valid
+ * datestamp or not .. and advance the parse pointer accordingly.
+ */
+ if (datetime.ParseTIMESTAMP3339(&dummyTS, &parse, &lenMsg) != RS_RET_OK) {
+ datetime.ParseTIMESTAMP3164(&dummyTS, &parse, &lenMsg,
+ NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME);
+ }
+ } else {
+ if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &parse, &lenMsg) != RS_RET_OK &&
+ datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &parse, &lenMsg,
+ NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) != RS_RET_OK) {
+ DBGPRINTF("we have a problem, invalid timestamp in msg!\n");
+ }
+ }
+ } else { /* if we pulled the time from the system, we need to update the message text */
+ uchar *tmpParse = parse; /* just to check correctness of TS */
+ if(datetime.ParseTIMESTAMP3339(&dummyTS, &tmpParse, &lenMsg) == RS_RET_OK ||
+ datetime.ParseTIMESTAMP3164(&dummyTS, &tmpParse, &lenMsg, NO_PARSE3164_TZSTRING,
+ NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
+ /* We modify the message only if it contained a valid timestamp,
+ otherwise we do not touch it at all. */
+ datetime.formatTimestamp3164(&st, (char*)parse, 0);
+ parse[15] = ' '; /* re-write \0 from fromatTimestamp3164 by SP */
+ /* update "counters" to reflect processed timestamp */
+ parse += 16;
+ }
+ }
+
+ /* pull tag */
+
+ i = 0;
+ while(lenMsg > 0 && *parse != ' ' && i < CONF_TAG_MAXSIZE - 1) {
+ bufParseTAG[i++] = *parse++;
+ --lenMsg;
+ }
+ bufParseTAG[i] = '\0'; /* terminate string */
+ if(pLstn->bWritePid)
+ fixPID(bufParseTAG, &i, cred);
+ MsgSetTAG(pMsg, bufParseTAG, i);
+ MsgSetMSGoffs(pMsg, pMsg->iLenRawMsg - lenMsg);
+ } else { /* we are configured to use regular parser chain */
+ pMsg->msgFlags |= NEEDS_PARSING;
+ }
+
+ MsgSetRcvFrom(pMsg, pLstn->hostName == NULL ? glbl.GetLocalHostNameProp() : pLstn->hostName);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pLocalHostIP));
+ MsgSetRuleset(pMsg, pLstn->pRuleset);
+ ratelimitAddMsg(ratelimiter, NULL, pMsg);
+ STATSCOUNTER_INC(ctrSubmit, mutCtrSubmit);
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pMsg != NULL)
+ msgDestruct(&pMsg);
+ }
+ RETiRet;
+}
+
+
+/* This function receives data from a socket indicated to be ready
+ * to receive and submits the message received for processing.
+ * rgerhards, 2007-12-20
+ * Interface changed so that this function is passed the array index
+ * of the socket which is to be processed. This eases access to the
+ * growing number of properties. -- rgerhards, 2008-08-01
+ */
+static rsRetVal readSocket(lstn_t *pLstn)
+{
+ DEFiRet;
+ int iRcvd;
+ int iMaxLine;
+ struct msghdr msgh;
+ struct iovec msgiov;
+ struct ucred cred;
+ struct timeval ts;
+ int cred_set = 0;
+ int ts_set = 0;
+ uchar bufRcv[4096+1];
+ uchar *pRcv = NULL; /* receive buffer */
+# ifdef HAVE_SCM_CREDENTIALS
+ /* aux is a union rather than a direct char array to force alignment with cmsghdr */
+ union {
+ char buf[128];
+ struct cmsghdr cm;
+ } aux;
+# endif
+
+ assert(pLstn->fd >= 0);
+
+ iMaxLine = glbl.GetMaxLine(runConf);
+
+ /* we optimize performance: if iMaxLine is below 4K (which it is in almost all
+ * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
+ * is used. We could use alloca() to achive a similar aspect, but there are so
+ * many issues with alloca() that I do not want to take that route.
+ * rgerhards, 2008-09-02
+ */
+ if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
+ pRcv = bufRcv;
+ } else {
+ CHKmalloc(pRcv = (uchar*) malloc(iMaxLine + 1));
+ }
+
+ memset(&msgh, 0, sizeof(msgh));
+ memset(&msgiov, 0, sizeof(msgiov));
+# ifdef HAVE_SCM_CREDENTIALS
+ if(pLstn->bUseCreds) {
+ memset(&aux, 0, sizeof(aux));
+ msgh.msg_control = &aux;
+ msgh.msg_controllen = sizeof(aux);
+ }
+# endif
+ msgiov.iov_base = (char*)pRcv;
+ msgiov.iov_len = iMaxLine;
+ msgh.msg_iov = &msgiov;
+ msgh.msg_iovlen = 1;
+/* AIXPORT : MSG_DONTWAIT not supported */
+#if defined (_AIX)
+#define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+ iRcvd = recvmsg(pLstn->fd, &msgh, MSG_DONTWAIT);
+
+ DBGPRINTF("Message from UNIX socket: #%d, size %d\n", pLstn->fd, (int) iRcvd);
+ if(iRcvd > 0) {
+# if defined(HAVE_SCM_CREDENTIALS) || defined(HAVE_SO_TIMESTAMP)
+ if(pLstn->bUseCreds) {
+ struct cmsghdr *cm;
+ for(cm = CMSG_FIRSTHDR(&msgh); cm; cm = CMSG_NXTHDR(&msgh, cm)) {
+# ifdef HAVE_SCM_CREDENTIALS
+ if( pLstn->bUseCreds
+ && cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_CREDENTIALS) {
+ memcpy(&cred, CMSG_DATA(cm), sizeof(cred));
+ cred_set = 1;
+ }
+# endif /* HAVE_SCM_CREDENTIALS */
+# if HAVE_SO_TIMESTAMP
+ if( pLstn->bUseSysTimeStamp
+ && cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
+ memcpy(&ts, CMSG_DATA(cm), sizeof(ts));
+ ts_set = 1;
+ }
+# endif /* HAVE_SO_TIMESTAMP */
+ }
+ }
+# endif /* defined(HAVE_SCM_CREDENTIALS) || defined(HAVE_SO_TIMESTAMP) */
+ CHKiRet(SubmitMsg(pRcv, iRcvd, pLstn, (cred_set ? &cred : NULL), (ts_set ? &ts : NULL)));
+ } else if(iRcvd < 0 && errno != EINTR && errno != EAGAIN) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("UNIX socket error: %d = %s.\n", errno, errStr);
+ LogError(errno, NO_ERRCODE, "imuxsock: recvfrom UNIX");
+ }
+
+finalize_it:
+ if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
+ free(pRcv);
+
+ RETiRet;
+}
+
+
+/* activate current listeners */
+static rsRetVal
+activateListeners(void)
+{
+ int actSocks;
+ int i;
+ DEFiRet;
+
+ /* Initialize the system socket only if it's in use */
+ if(startIndexUxLocalSockets == 0) {
+ /* first apply some config settings */
+ listeners[0].sockName = UCHAR_CONSTANT(_PATH_LOG);
+ if(runModConf->pLogSockName != NULL) {
+ listeners[0].sockName = runModConf->pLogSockName;
+ }
+#ifdef HAVE_LIBSYSTEMD
+ else if(sd_booted()) {
+ struct stat st;
+ if(stat(SYSTEMD_PATH_LOG, &st) != -1 && S_ISSOCK(st.st_mode)) {
+ listeners[0].sockName = (uchar*) SYSTEMD_PATH_LOG;
+ }
+ }
+#endif
+ if(runModConf->ratelimitIntervalSysSock > 0) {
+ if((listeners[0].ht = create_hashtable(100, hash_from_key_fn, key_equals_fn, NULL)) == NULL) {
+ /* in this case, we simply turn of rate-limiting */
+ LogError(0, NO_ERRCODE, "imuxsock: turning off rate limiting because "
+ "we could not create hash table\n");
+ runModConf->ratelimitIntervalSysSock = 0;
+ }
+ } else {
+ listeners[0].ht = NULL;
+ }
+ listeners[0].fd = -1;
+ listeners[0].pRuleset = NULL;
+ listeners[0].hostName = NULL;
+ listeners[0].bParseHost = 0;
+ listeners[0].bCreatePath = 0;
+ listeners[0].ratelimitInterval = runModConf->ratelimitIntervalSysSock;
+ listeners[0].ratelimitBurst = runModConf->ratelimitBurstSysSock;
+ listeners[0].ratelimitSev = runModConf->ratelimitSeveritySysSock;
+ listeners[0].bUseCreds = (runModConf->bWritePidSysSock || runModConf->ratelimitIntervalSysSock
+ || runModConf->bAnnotateSysSock || runModConf->bDiscardOwnMsgs
+ || runModConf->bUseSysTimeStamp) ? 1 : 0;
+ listeners[0].bWritePid = runModConf->bWritePidSysSock;
+ listeners[0].bAnnotate = runModConf->bAnnotateSysSock;
+ listeners[0].bParseTrusted = runModConf->bParseTrusted;
+ listeners[0].bParseHost = runModConf->bParseHost;
+ listeners[0].bUseSpecialParser = runModConf->bUseSpecialParser;
+ listeners[0].bDiscardOwnMsgs = runModConf->bDiscardOwnMsgs;
+ listeners[0].bUnlink = runModConf->bUnlink;
+ listeners[0].bUseSysTimeStamp = runModConf->bUseSysTimeStamp;
+ listeners[0].flags = runModConf->bIgnoreTimestamp ? IGNDATE : NOFLAG;
+ listeners[0].flowCtl = runModConf->bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
+ CHKiRet(ratelimitNew(&listeners[0].dflt_ratelimiter, "imuxsock", NULL));
+ ratelimitSetLinuxLike(listeners[0].dflt_ratelimiter,
+ listeners[0].ratelimitInterval,
+ listeners[0].ratelimitBurst);
+ ratelimitSetSeverity(listeners[0].dflt_ratelimiter,listeners[0].ratelimitSev);
+ }
+
+#ifdef HAVE_LIBSYSTEMD
+ sd_fds = sd_listen_fds(0);
+ if(sd_fds < 0) {
+ LogError(-sd_fds, NO_ERRCODE, "imuxsock: Failed to acquire systemd socket");
+ ABORT_FINALIZE(RS_RET_ERR_CRE_AFUX);
+ }
+#endif
+
+ /* initialize and return if will run or not */
+ actSocks = 0;
+ for (i = startIndexUxLocalSockets ; i < nfd ; i++) {
+ if(openLogSocket(&(listeners[i])) == RS_RET_OK) {
+ ++actSocks;
+ DBGPRINTF("imuxsock: Opened UNIX socket '%s' (fd %d).\n",
+ listeners[i].sockName, listeners[i].fd);
+ }
+ }
+
+ if(actSocks == 0) {
+ LogError(0, RS_RET_ERR, "imuxsock does not run because we could not "
+ "acquire any socket\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ /* init our settings */
+ pModConf->pLogSockName = NULL;
+ pModConf->bOmitLocalLogging = 0;
+ pModConf->bIgnoreTimestamp = 1;
+ pModConf->bUseFlowCtl = 0;
+ pModConf->bUseSysTimeStamp = 1;
+ pModConf->bWritePidSysSock = 0;
+ pModConf->bAnnotateSysSock = 0;
+ pModConf->bParseTrusted = 0;
+ pModConf->bParseHost = UNSET;
+ pModConf->bUseSpecialParser = DFLT_bUseSpecialParser;
+ /* if we do not process internal messages, we will see messages
+ * from ourselves, and so we need to permit this.
+ */
+ pModConf->bDiscardOwnMsgs = pConf->globals.bProcessInternalMessages;
+ pModConf->bUnlink = 1;
+ pModConf->ratelimitIntervalSysSock = DFLT_ratelimitInterval;
+ pModConf->ratelimitBurstSysSock = DFLT_ratelimitBurst;
+ pModConf->ratelimitSeveritySysSock = DFLT_ratelimitSeverity;
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* reset legacy config vars */
+ resetConfigVariables(NULL, NULL);
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imuxsock:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "syssock.use")) {
+ loadModConf->bOmitLocalLogging = ((int) pvals[i].val.d.n) ? 0 : 1;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.name")) {
+ loadModConf->pLogSockName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.ignoretimestamp")) {
+ loadModConf->bIgnoreTimestamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.ignoreownmessages")) {
+ loadModConf->bDiscardOwnMsgs = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.unlink")) {
+ loadModConf->bUnlink = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.flowcontrol")) {
+ loadModConf->bUseFlowCtl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.usesystimestamp")) {
+ loadModConf->bUseSysTimeStamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.annotate")) {
+ loadModConf->bAnnotateSysSock = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.parsetrusted")) {
+ loadModConf->bParseTrusted = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.parsehostname")) {
+ loadModConf->bParseHost = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.usespecialparser")) {
+ loadModConf->bUseSpecialParser = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.usepidfromsystem")) {
+ loadModConf->bWritePidSysSock = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.ratelimit.interval")) {
+ loadModConf->ratelimitIntervalSysSock = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.ratelimit.burst")) {
+ loadModConf->ratelimitBurstSysSock = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "syssock.ratelimit.severity")) {
+ loadModConf->ratelimitSeveritySysSock = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imuxsock: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* disable legacy module-global config directives */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imuxsock)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imuxsock: required parameter are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imuxsock:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "socket")) {
+ inst->sockName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "createpath")) {
+ inst->bCreatePath = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "parsetrusted")) {
+ inst->bParseTrusted = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ignoreownmessages")) {
+ inst->bDiscardOwnMsgs = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "unlink")) {
+ inst->bUnlink = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "hostname")) {
+ inst->pLogHostName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ignoretimestamp")) {
+ inst->bIgnoreTimestamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->bUseFlowCtl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "usesystimestamp")) {
+ inst->bUseSysTimeStamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "annotate")) {
+ inst->bAnnotate = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "usepidfromsystem")) {
+ inst->bWritePid = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "parsehostname")) {
+ inst->bParseHost = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "usespecialparser")) {
+ inst->bUseSpecialParser = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.severity")) {
+ inst->ratelimitSeverity = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imuxsock: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ /* these are used to initialize the system log socket (listeners[0]) */
+ loadModConf->bOmitLocalLogging = cs.bOmitLocalLogging;
+ loadModConf->pLogSockName = cs.pLogSockName;
+ loadModConf->bIgnoreTimestamp = cs.bIgnoreTimestampSysSock;
+ loadModConf->bUseSysTimeStamp = cs.bUseSysTimeStampSysSock;
+ loadModConf->bUseFlowCtl = cs.bUseFlowCtlSysSock;
+ loadModConf->bAnnotateSysSock = cs.bAnnotateSysSock;
+ loadModConf->bWritePidSysSock = cs.bWritePidSysSock;
+ loadModConf->bParseTrusted = cs.bParseTrusted;
+ loadModConf->ratelimitIntervalSysSock = cs.ratelimitIntervalSysSock;
+ loadModConf->ratelimitBurstSysSock = cs.ratelimitBurstSysSock;
+ loadModConf->ratelimitSeveritySysSock = cs.ratelimitSeveritySysSock;
+ }
+
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pLogHostName);
+ cs.pLogSockName = NULL;
+ cs.pLogHostName = NULL;
+ENDendCnfLoad
+
+
+/* function to generate error message if framework does not find requested ruleset */
+static void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imuxsock: ruleset '%s' for socket %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->sockName);
+}
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+ int nLstn;
+ int i;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+# ifdef OS_SOLARIS
+ /* under solaris, we must NEVER process the local log socket, because
+ * it is implemented there differently. If we used it, we would actually
+ * delete it and render the system partly unusable. So don't do that.
+ * rgerhards, 2010-03-26
+ */
+ startIndexUxLocalSockets = 1;
+# else
+ startIndexUxLocalSockets = runModConf->bOmitLocalLogging ? 1 : 0;
+# endif
+ /* we first calculate the number of listeners so that we can
+ * appropriately size the listener array. Note that we will
+ * always allocate memory for the system log socket.
+ */
+ nLstn = 0;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ ++nLstn;
+ }
+ if(nLstn > 0 || startIndexUxLocalSockets == 0) {
+ DBGPRINTF("imuxsock: allocating memory for %d listeners\n", nLstn);
+ lstn_t *const listeners_new = realloc(listeners, (1+nLstn)*sizeof(lstn_t));
+ CHKmalloc(listeners_new);
+ listeners = listeners_new;
+ for(i = 1 ; i < nLstn ; ++i) {
+ listeners[i].sockName = NULL;
+ listeners[i].fd = -1;
+ }
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(inst);
+ }
+ CHKiRet(activateListeners());
+ }
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ free(pModConf->pLogSockName);
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free(inst->sockName);
+ free(inst->pszBindRuleset);
+ free(inst->pLogHostName);
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+
+/* This function is called to gather input. */
+BEGINrunInput
+ int nfds;
+ int i;
+CODESTARTrunInput
+ struct pollfd *const pollfds = calloc(nfd, sizeof(struct pollfd));
+ CHKmalloc(pollfds);
+ if(startIndexUxLocalSockets == 1 && nfd == 1) {
+ /* No sockets were configured, no reason to run. */
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ if(startIndexUxLocalSockets == 1) {
+ pollfds[0].fd = -1;
+ }
+ for (i = startIndexUxLocalSockets; i < nfd; i++) {
+ pollfds[i].fd = listeners[i].fd;
+ pollfds[i].events = POLLIN;
+ }
+
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so.
+ */
+ while(1) {
+ DBGPRINTF("--------imuxsock calling poll() on %d fds\n", nfd);
+
+ nfds = poll(pollfds, nfd, -1);
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ if(nfds < 0) {
+ if(errno == EINTR) {
+ DBGPRINTF("imuxsock: EINTR occurred\n");
+ } else {
+ LogMsg(errno, RS_RET_POLL_ERR, LOG_WARNING, "imuxsock: poll "
+ "system call failed, may cause further troubles");
+ }
+ nfds = 0;
+ }
+
+ for (i = startIndexUxLocalSockets ; i < nfd && nfds > 0; i++) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM); /* terminate input! */
+ if(pollfds[i].revents & POLLIN) {
+ readSocket(&(listeners[i]));
+ --nfds; /* indicate we have processed one */
+ }
+ }
+ }
+
+finalize_it:
+ free(pollfds);
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+
+BEGINafterRun
+ int i;
+CODESTARTafterRun
+ /* do cleanup here */
+ if(startIndexUxLocalSockets == 1 && nfd == 1) {
+ /* No sockets were configured, no cleanup needed. */
+ return RS_RET_OK;
+ }
+
+ /* Close the UNIX sockets. */
+ for (i = 0; i < nfd; i++)
+ if (listeners[i].fd != -1)
+ close(listeners[i].fd);
+
+ /* Clean-up files. */
+ for(i = startIndexUxLocalSockets; i < nfd; i++)
+ if (listeners[i].sockName && listeners[i].fd != -1) {
+ /* If systemd passed us a socket it is systemd's job to clean it up.
+ * Do not unlink it -- we will get same socket (node) from systemd
+ * e.g. on restart again.
+ */
+ if (sd_fds > 0
+# ifdef HAVE_LIBSYSTEMD
+ && listeners[i].fd >= SD_LISTEN_FDS_START &&
+ listeners[i].fd < SD_LISTEN_FDS_START + sd_fds
+# endif
+ )
+ continue;
+
+ if(listeners[i].bUnlink) {
+ DBGPRINTF("imuxsock: unlinking unix socket file[%d] %s\n", i, listeners[i].sockName);
+ unlink((char*) listeners[i].sockName);
+ }
+ }
+
+ discardLogSockets();
+ nfd = 1;
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(listeners);
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+
+ statsobj.Destruct(&modStats);
+
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(cs.pLogSockName);
+ cs.pLogSockName = NULL;
+ free(cs.pLogHostName);
+ cs.bOmitLocalLogging = 0;
+ cs.pLogHostName = NULL;
+ cs.bIgnoreTimestamp = 1;
+ cs.bIgnoreTimestampSysSock = 1;
+ cs.bUseFlowCtl = 0;
+ cs.bUseFlowCtlSysSock = 0;
+ cs.bUseSysTimeStamp = 1;
+ cs.bUseSysTimeStampSysSock = 1;
+ cs.bWritePid = 0;
+ cs.bWritePidSysSock = 0;
+ cs.bAnnotate = 0;
+ cs.bAnnotateSysSock = 0;
+ cs.bParseTrusted = 0;
+ cs.bCreatePath = DFLT_bCreatePath;
+ cs.ratelimitInterval = DFLT_ratelimitInterval;
+ cs.ratelimitIntervalSysSock = DFLT_ratelimitInterval;
+ cs.ratelimitBurst = DFLT_ratelimitBurst;
+ cs.ratelimitBurstSysSock = DFLT_ratelimitBurst;
+ cs.ratelimitSeverity = DFLT_ratelimitSeverity;
+ cs.ratelimitSeveritySysSock = DFLT_ratelimitSeverity;
+
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ DBGPRINTF("imuxsock version %s initializing\n", PACKAGE_VERSION);
+
+ /* init legacy config vars */
+ cs.pLogSockName = NULL;
+ cs.pLogHostName = NULL; /* host name to use with this socket */
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imuxsock"), sizeof("imuxsock") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ /* right now, glbl does not permit per-instance IP address notation. As long as this
+ * is the case, it is OK to query the HostIP once here at this location. HOWEVER, the
+ * whole concept is not 100% clean and needs to be addressed on a higher layer.
+ * TODO / rgerhards, 2012-04-11
+ */
+ pLocalHostIP = glbl.GetLocalHostIP();
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketignoremsgtimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bIgnoreTimestamp, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensockethostname", 0, eCmdHdlrGetWord,
+ NULL, &cs.pLogHostName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseFlowCtl, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketannotate", 0, eCmdHdlrBinary,
+ NULL, &cs.bAnnotate, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketcreatepath", 0, eCmdHdlrBinary,
+ NULL, &cs.bCreatePath, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketusesystimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseSysTimeStamp, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketusepidfromsystem", 0, eCmdHdlrBinary,
+ NULL, &cs.bWritePid, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imuxsockratelimitinterval", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imuxsockratelimitburst", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitBurst, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imuxsockratelimitseverity", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitSeverity, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ /* the following one is a (dirty) trick: the system log socket is not added via
+ * an "addUnixListenSocket" config format. As such, it's properties can not be modified
+ * via $InputUnixListenSocket*". So we need to add a special directive
+ * for that. We should revisit all of that once we have the new config format...
+ * rgerhards, 2008-03-06
+ */
+ CHKiRet(regCfSysLineHdlr2((uchar *)"omitlocallogging", 0, eCmdHdlrBinary,
+ NULL, &cs.bOmitLocalLogging, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogsocketname", 0, eCmdHdlrGetWord,
+ NULL, &cs.pLogSockName, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bIgnoreTimestampSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogsocketflowcontrol", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseFlowCtlSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogusesystimestamp", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseSysTimeStampSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogsocketannotate", 0, eCmdHdlrBinary,
+ NULL, &cs.bAnnotateSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogparsetrusted", 0, eCmdHdlrBinary,
+ NULL, &cs.bParseTrusted, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogusepidfromsystem", 0, eCmdHdlrBinary,
+ NULL, &cs.bWritePidSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogratelimitinterval", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitIntervalSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogratelimitburst", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitBurstSysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2((uchar *)"systemlogratelimitseverity", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitSeveritySysSock, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&modStats));
+ CHKiRet(statsobj.SetName(modStats, UCHAR_CONSTANT("imuxsock")));
+ CHKiRet(statsobj.SetOrigin(modStats, UCHAR_CONSTANT("imuxsock")));
+ STATSCOUNTER_INIT(ctrSubmit, mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrSubmit));
+ STATSCOUNTER_INIT(ctrLostRatelimit, mutCtrLostRatelimit);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("ratelimit.discarded"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrLostRatelimit));
+ STATSCOUNTER_INIT(ctrNumRatelimiters, mutCtrNumRatelimiters);
+ CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("ratelimit.numratelimiters"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrNumRatelimiters));
+ CHKiRet(statsobj.ConstructFinalize(modStats));
+
+ENDmodInit
diff --git a/plugins/mmanon/Makefile.am b/plugins/mmanon/Makefile.am
new file mode 100644
index 0000000..98f0da2
--- /dev/null
+++ b/plugins/mmanon/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmanon.la
+
+mmanon_la_SOURCES = mmanon.c
+mmanon_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmanon_la_LDFLAGS = -module -avoid-version
+mmanon_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmanon/Makefile.in b/plugins/mmanon/Makefile.in
new file mode 100644
index 0000000..e3fc686
--- /dev/null
+++ b/plugins/mmanon/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmanon
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmanon_la_DEPENDENCIES =
+am_mmanon_la_OBJECTS = mmanon_la-mmanon.lo
+mmanon_la_OBJECTS = $(am_mmanon_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 =
+mmanon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmanon_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmanon_la-mmanon.Plo
+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 = $(mmanon_la_SOURCES)
+DIST_SOURCES = $(mmanon_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmanon.la
+mmanon_la_SOURCES = mmanon.c
+mmanon_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmanon_la_LDFLAGS = -module -avoid-version
+mmanon_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmanon/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmanon/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmanon.la: $(mmanon_la_OBJECTS) $(mmanon_la_DEPENDENCIES) $(EXTRA_mmanon_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmanon_la_LINK) -rpath $(pkglibdir) $(mmanon_la_OBJECTS) $(mmanon_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmanon_la-mmanon.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmanon_la-mmanon.lo: mmanon.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmanon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmanon_la-mmanon.lo -MD -MP -MF $(DEPDIR)/mmanon_la-mmanon.Tpo -c -o mmanon_la-mmanon.lo `test -f 'mmanon.c' || echo '$(srcdir)/'`mmanon.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmanon_la-mmanon.Tpo $(DEPDIR)/mmanon_la-mmanon.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmanon.c' object='mmanon_la-mmanon.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) $(mmanon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmanon_la-mmanon.lo `test -f 'mmanon.c' || echo '$(srcdir)/'`mmanon.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmanon_la-mmanon.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmanon_la-mmanon.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmanon/mmanon.c b/plugins/mmanon/mmanon.c
new file mode 100644
index 0000000..811b763
--- /dev/null
+++ b/plugins/mmanon/mmanon.c
@@ -0,0 +1,1375 @@
+/* mmanon.c
+ * anonnymize IP addresses inside the syslog message part
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+#include "hashtable.h"
+
+
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmanon")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+// enumerator for the mode
+enum mode {ZERO, RANDOMINT, SIMPLE};
+
+union node {
+ struct {
+ union node* more;
+ union node* less;
+ } pointer;
+ struct {
+ char ip_high[16];
+ char ip_low[16];
+ } ips;
+};
+
+struct ipv6_int {
+ unsigned long long high;
+ unsigned long long low;
+ };
+/* define operation modes we have */
+#define SIMPLE_MODE 0 /* just overwrite */
+#define REWRITE_MODE 1 /* rewrite IP address, canoninized */
+typedef struct _instanceData {
+ struct {
+ sbool enable;
+ int8_t bits;
+ union node* Root;
+ int randConsis;
+ enum mode mode;
+ uchar replaceChar;
+ } ipv4;
+
+ struct {
+ sbool enable;
+ uint8_t bits;
+ enum mode anonmode;
+ int randConsis;
+ struct hashtable* hash;
+ } ipv6;
+
+ struct {
+ sbool enable;
+ uint8_t bits;
+ enum mode anonmode;
+ int randConsis;
+ struct hashtable* hash;
+ } embeddedIPv4;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ unsigned randstatus;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "ipv4.enable", eCmdHdlrBinary, 0 },
+ { "ipv4.mode", eCmdHdlrGetWord, 0 },
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "ipv4.bits", eCmdHdlrPositiveInt, 0 },
+ { "ipv4.replacechar", eCmdHdlrGetChar, 0},
+ { "replacementchar", eCmdHdlrGetChar, 0},
+ { "ipv6.enable", eCmdHdlrBinary, 0 },
+ { "ipv6.anonmode", eCmdHdlrGetWord, 0 },
+ { "ipv6.bits", eCmdHdlrPositiveInt, 0 },
+ { "embeddedipv4.enable", eCmdHdlrBinary, 0 },
+ { "embeddedipv4.anonmode", eCmdHdlrGetWord, 0 },
+ { "embeddedipv4.bits", eCmdHdlrPositiveInt, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->randstatus = time(NULL);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+static void
+delTree(union node* node, const int layer)
+{
+ if(node == NULL){
+ return;
+ }
+ if(layer == 31){
+ free(node);
+ } else {
+ delTree(node->pointer.more, layer + 1);
+ delTree(node->pointer.less, layer + 1);
+ free(node);
+ }
+}
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ delTree(pData->ipv4.Root, 0);
+ if(pData->ipv6.hash != NULL) {
+ hashtable_destroy(pData->ipv6.hash, 1);
+ }
+ if(pData->embeddedIPv4.hash != NULL) {
+ hashtable_destroy(pData->embeddedIPv4.hash, 1);
+ }
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->ipv4.enable = 1;
+ pData->ipv4.bits = 16;
+ pData->ipv4.Root = NULL;
+ pData->ipv4.randConsis = 0;
+ pData->ipv4.mode = ZERO;
+ pData->ipv4.replaceChar = 'x';
+
+ pData->ipv6.enable = 1;
+ pData->ipv6.bits = 96;
+ pData->ipv6.anonmode = ZERO;
+ pData->ipv6.randConsis = 0;
+ pData->ipv6.hash = NULL;
+
+ pData->embeddedIPv4.enable = 1;
+ pData->embeddedIPv4.bits = 96;
+ pData->embeddedIPv4.anonmode = ZERO;
+ pData->embeddedIPv4.randConsis = 0;
+ pData->embeddedIPv4.hash = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmanon)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "ipv4.mode") || !strcmp(actpblk.descr[i].name, "mode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"zero",
+ sizeof("zero")-1)) {
+ pData->ipv4.mode = ZERO;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random",
+ sizeof("random")-1)) {
+ pData->ipv4.mode = RANDOMINT;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"simple",
+ sizeof("simple")-1) ||
+ !es_strbufcmp(pvals[i].val.d.estr, (uchar*)"rewrite",
+ sizeof("rewrite")-1)) {
+ pData->ipv4.mode = SIMPLE;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random-consistent",
+ sizeof("random-consistent")-1)) {
+ pData->ipv4.mode = RANDOMINT;
+ pData->ipv4.randConsis = 1;
+ } else {
+ parser_errmsg("mmanon: configuration error, unknown option for ipv4.mode, "
+ "will use \"zero\"\n");
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "ipv4.bits")) {
+ if((int8_t) pvals[i].val.d.n <= 32) {
+ pData->ipv4.bits = (int8_t) pvals[i].val.d.n;
+ } else {
+ pData->ipv4.bits = 32;
+ parser_errmsg("warning: invalid number of ipv4.bits (%d), corrected "
+ "to 32", (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "ipv4.enable")) {
+ pData->ipv4.enable = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ipv4.replacechar") || !strcmp(actpblk.descr[i].name,
+ "replacementchar")) {
+ uchar* tmp = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ pData->ipv4.replaceChar = tmp[0];
+ free(tmp);
+ } else if(!strcmp(actpblk.descr[i].name, "ipv6.enable")) {
+ pData->ipv6.enable = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ipv6.bits")) {
+ if((uint8_t) pvals[i].val.d.n <= 128) {
+ pData->ipv6.bits = (uint8_t) pvals[i].val.d.n;
+ } else {
+ pData->ipv6.bits = 128;
+ parser_errmsg("warning: invalid number of ipv6.bits (%d), corrected "
+ "to 128", (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "ipv6.anonmode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"zero",
+ sizeof("zero")-1)) {
+ pData->ipv6.anonmode = ZERO;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random",
+ sizeof("random")-1)) {
+ pData->ipv6.anonmode = RANDOMINT;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random-consistent",
+ sizeof("random-consistent")-1)) {
+ pData->ipv6.anonmode = RANDOMINT;
+ pData->ipv6.randConsis = 1;
+ } else {
+ parser_errmsg("mmanon: configuration error, unknown option for "
+ "ipv6.anonmode, will use \"zero\"\n");
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "embeddedipv4.enable")) {
+ pData->embeddedIPv4.enable = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "embeddedipv4.bits")) {
+ if((uint8_t) pvals[i].val.d.n <= 128) {
+ pData->embeddedIPv4.bits = (uint8_t) pvals[i].val.d.n;
+ } else {
+ pData->embeddedIPv4.bits = 128;
+ parser_errmsg("warning: invalid number of embeddedipv4.bits (%d), "
+ "corrected to 128", (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "embeddedipv4.anonmode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"zero",
+ sizeof("zero")-1)) {
+ pData->embeddedIPv4.anonmode = ZERO;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random",
+ sizeof("random")-1)) {
+ pData->embeddedIPv4.anonmode = RANDOMINT;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random-consistent",
+ sizeof("random-consistent")-1)) {
+ pData->embeddedIPv4.anonmode = RANDOMINT;
+ pData->embeddedIPv4.randConsis = 1;
+ } else {
+ parser_errmsg("mmanon: configuration error, unknown option for ipv6.anonmode, "
+ "will use \"zero\"\n");
+ }
+ } else {
+ parser_errmsg("mmanon: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ int bHadBitsErr = 0;
+ if(pData->ipv4.mode == SIMPLE) {
+ if(pData->ipv4.bits < 8 && pData->ipv4.bits > -1) {
+ pData->ipv4.bits = 8;
+ bHadBitsErr = 1;
+ } else if(pData->ipv4.bits < 16 && pData->ipv4.bits > 8) {
+ pData->ipv4.bits = 16;
+ bHadBitsErr = 1;
+ } else if(pData->ipv4.bits < 24 && pData->ipv4.bits > 16) {
+ pData->ipv4.bits = 24;
+ bHadBitsErr = 1;
+ } else if((pData->ipv4.bits != 32 && pData->ipv4.bits > 24) || pData->ipv4.bits < 0) {
+ pData->ipv4.bits = 32;
+ bHadBitsErr = 1;
+ }
+ if(bHadBitsErr) {
+ LogError(0, RS_RET_INVLD_ANON_BITS,
+ "mmanon: invalid number of ipv4 bits "
+ "in simple mode, corrected to %d",
+ pData->ipv4.bits);
+ }
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static int
+getHexVal(char c)
+{
+ if('0' <= c && c <= '9') {
+ return c - '0';
+ } else if('a' <= c && c <= 'f') {
+ return (c - 'a') + 10;
+ } else if('A' <= c && c <= 'F') {
+ return (c - 'A') + 10;
+ } else {
+ return -1;
+ }
+}
+
+
+/* returns 1 if valid IPv4 digit, 0 if not */
+static int
+isPosByte(const uchar *const __restrict__ buf,
+ const size_t buflen,
+ size_t *const __restrict__ nprocessed)
+{
+ int val = 0; /* Default means no byte found */
+ size_t i;
+ for(i = 0 ; i < buflen; i++) {
+ if('0' <= buf[i] && buf[i] <= '9') {
+ /* Maximum 3 digits for single IPv4 Number, we only copy up to 4 numbers
+ * but process forward to non digits */
+ if (i < 4) {
+ val = val*10 + buf[i]-'0';
+ }
+ } else
+ break;
+ }
+ *nprocessed = i;
+ /* Return 1 if more than 1 and less the 4 digits and between 0 and 255 */
+ if( i > 0 &&
+ i < 4 &&
+ (val >= 0 && val <= 255)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* 1 - is IPv4, 0 not */
+static int
+syntax_ipv4(const uchar *const __restrict__ buf,
+ const size_t buflen,
+ size_t *const __restrict__ nprocessed)
+{
+ size_t nproc = 0;
+ size_t i;
+ int r = 0;
+ if(isPosByte(buf, buflen, &i) == 0) {
+ goto done;
+ }
+ if(i >= buflen || buf[i] != '.') {
+ goto done;
+ }
+ i++;
+ if(isdigit(buf[i]) == 0 || isPosByte(buf+i, buflen-i, &nproc) == 0) {
+ goto done;
+ }
+ i += nproc;
+
+ if(i >= buflen || buf[i] != '.') {
+ goto done;
+ }
+ i++;
+ if(isdigit(buf[i]) == 0 || isPosByte(buf+i, buflen-i, &nproc) == 0) {
+ goto done;
+ }
+ i += nproc;
+
+ if(i >= buflen || buf[i] != '.') {
+ goto done;
+ }
+ i++;
+ if(isdigit(buf[i]) == 0 || isPosByte(buf+i, buflen-i, &nproc) == 0) {
+ goto done;
+ }
+ i += nproc;
+
+ *nprocessed = i;
+ r = 1;
+done:
+ return r;
+}
+
+
+static int
+isValidHexNum(const uchar *const __restrict__ buf,
+ const size_t buflen,
+ size_t *const __restrict__ nprocessed,
+ int handleDot)
+{
+ size_t idx = 0;
+ int cyc = 0;
+
+ while(idx < buflen) {
+ switch(buf[idx]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ cyc++;
+ (*nprocessed)++;
+ if(cyc == 5) {
+ goto done;
+ }
+ break;
+ case '.':
+ if(handleDot && cyc == 0) {
+ (*nprocessed)++;
+ cyc = -2;
+ }
+ goto done;
+ case ':':
+ if(cyc == 0) {
+ (*nprocessed)++;
+ cyc = -1;
+ }
+ goto done;
+ default:
+ goto done;
+ }
+ idx++;
+ }
+done:
+ return cyc;
+}
+
+
+static int
+syntax_ipv6(const uchar *const __restrict__ buf,
+ const size_t buflen,
+ size_t *const __restrict__ nprocessed)
+{
+ int lastSep = 0;
+ sbool hadAbbrev = 0;
+ sbool lastAbbrev = 0;
+ int ipParts = 0;
+ int numLen;
+ int isIP = 0;
+
+ while(*nprocessed < buflen) {
+ numLen = isValidHexNum(buf + *nprocessed, buflen - *nprocessed, nprocessed, 0);
+ if(numLen > 0 && numLen < 5) { //found a valid num
+ if((ipParts == 7 && hadAbbrev) || ipParts > 7) {
+ isIP = 0;
+ goto done;
+ }
+ if (ipParts == 0 && lastSep && !hadAbbrev) {
+ isIP = 0;
+ goto done;
+ }
+ lastSep = 0;
+ lastAbbrev = 0;
+ ipParts++;
+ } else if (numLen < 0) { //':'
+ if(lastSep) {
+ if(hadAbbrev) {
+ isIP = 0;
+ goto done;
+ } else {
+ hadAbbrev = 1;
+ lastAbbrev = 1;
+ }
+ }
+ lastSep = 1;
+ } else if (numLen == 5) { // maybe truncated with port
+ if(hadAbbrev && ipParts >= 2) {
+ isIP = 1;
+ /* we need to go back 6 chars:
+ * 5 digits plus leading ":" which designates port!
+ */
+ *nprocessed -= 6;
+ } else {
+ isIP = 0;
+ /* nprocessed need not be corrected - it's only used if isIP == 1 */
+ }
+ goto done;
+ } else { //no valid num
+ if(lastSep) {
+ if(lastAbbrev && ipParts < 8) {
+ isIP = 1;
+ goto done;
+ }
+ isIP = 0;
+ goto done;
+ }
+ if((ipParts == 8 && !hadAbbrev) || (ipParts < 8 && hadAbbrev)) {
+ isIP = 1;
+ goto done;
+ } else {
+ isIP = 0;
+ goto done;
+ }
+ }
+ if(ipParts == 8 && !hadAbbrev) {
+ isIP = 1;
+ goto done;
+ }
+ }
+
+ if((!lastSep && (ipParts == 8 && !hadAbbrev)) || (ipParts < 8 && hadAbbrev)) {
+ isIP = 1;
+ }
+
+done:
+ return isIP;
+}
+
+
+static unsigned
+ipv42num(const char *str)
+{
+ unsigned num[4] = {0, 0, 0, 0};
+ unsigned value = -1;
+ size_t len = strlen(str);
+ int cyc = 0;
+ for(unsigned i = 0 ; i < len ; i++) {
+ switch(str[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ num[cyc] = num[cyc]*10+(str[i]-'0');
+ break;
+ case '.':
+ cyc++;
+ break;
+ }
+ }
+
+ value = num[0]*256*256*256+num[1]*256*256+num[2]*256+num[3];
+ return(value);
+}
+
+
+static unsigned
+code_int(unsigned ip, wrkrInstanceData_t *pWrkrData){
+ unsigned random;
+ unsigned long long shiftIP_subst = ip;
+ // variable needed because shift operation of 32nd bit in unsigned does not work
+ switch(pWrkrData->pData->ipv4.mode) {
+ case ZERO:
+ shiftIP_subst = ((shiftIP_subst>>(pWrkrData->pData->ipv4.bits))<<(pWrkrData->pData->ipv4.bits));
+ return (unsigned)shiftIP_subst;
+ case RANDOMINT:
+ shiftIP_subst = ((shiftIP_subst>>(pWrkrData->pData->ipv4.bits))<<(pWrkrData->pData->ipv4.bits));
+ // multiply the random number between 0 and 1 with a mask of (2^n)-1:
+ random = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*
+ ((1ull<<(pWrkrData->pData->ipv4.bits))-1));
+ return (unsigned)shiftIP_subst + random;
+ case SIMPLE: //can't happen, since this case is caught at the start of anonipv4()
+ default:
+ LogError(0, RS_RET_INTERNAL_ERROR, "mmanon: unexpected code path reached in code_int function");
+ return 0;
+ }
+}
+
+
+static int
+num2ipv4(unsigned num, char *str) {
+ int numip[4];
+ size_t len;
+ for(int i = 0 ; i < 4 ; i++){
+ numip[i] = num % 256;
+ num = num / 256;
+ }
+ len = snprintf(str, 16, "%d.%d.%d.%d", numip[3], numip[2], numip[1], numip[0]);
+ return len;
+}
+
+
+static void
+getip(uchar *start, size_t end, char *address)
+{
+ size_t i;
+
+ for(i = 0; i < end; i++){
+ address[i] = *(start+i);
+ }
+ address[i] = '\0';
+}
+
+/* in case of error with malloc causing abort of function, the
+ * string at the target of address remains the same */
+static rsRetVal
+findip(char* address, wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ int i;
+ unsigned num;
+ union node* current;
+ union node* Last;
+ int MoreLess;
+ char* CurrentCharPtr;
+
+ current = pWrkrData->pData->ipv4.Root;
+ num = ipv42num(address);
+ for(i = 0; i < 31; i++){
+ if(pWrkrData->pData->ipv4.Root == NULL) {
+ CHKmalloc(current = (union node*)calloc(1, sizeof(union node)));
+ pWrkrData->pData->ipv4.Root = current;
+ }
+ Last = current;
+ if((num >> (31 - i)) & 1){
+ current = current->pointer.more;
+ MoreLess = 1;
+ } else {
+ current = current->pointer.less;
+ MoreLess = 0;
+ }
+ if(current == NULL){
+ CHKmalloc(current = (union node*)calloc(1, sizeof(union node)));
+ if(MoreLess == 1){
+ Last->pointer.more = current;
+ } else {
+ Last->pointer.less = current;
+ }
+ }
+ }
+ if(num & 1){
+ CurrentCharPtr = current->ips.ip_high;
+ } else {
+ CurrentCharPtr = current->ips.ip_low;
+ }
+ if(CurrentCharPtr[0] != '\0'){
+ strcpy(address, CurrentCharPtr);
+ } else {
+ num = code_int(num, pWrkrData);
+ num2ipv4(num, CurrentCharPtr);
+ strcpy(address, CurrentCharPtr);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+static void
+process_IPv4 (char* address, wrkrInstanceData_t *pWrkrData)
+{
+ unsigned num;
+
+ if(pWrkrData->pData->ipv4.randConsis){
+ findip(address, pWrkrData);
+ }else {
+ num = ipv42num(address);
+ num = code_int(num, pWrkrData);
+ num2ipv4(num, address);
+ }
+}
+
+
+static void
+simpleAnon(wrkrInstanceData_t *const pWrkrData, uchar *const msg, int *const hasChanged, int iplen)
+{
+ int maxidx = iplen - 1;
+
+ int j = -1;
+ for(int i = (pWrkrData->pData->ipv4.bits / 8); i > 0; i--) {
+ j++;
+ while('0' <= msg[maxidx - j] && msg[maxidx - j] <= '9') {
+ if(msg[maxidx - j] != pWrkrData->pData->ipv4.replaceChar) {
+ msg[maxidx - j] = pWrkrData->pData->ipv4.replaceChar;
+ *hasChanged = 1;
+ }
+ j++;
+ }
+ }
+}
+
+
+static void
+anonipv4(wrkrInstanceData_t *pWrkrData, uchar **msg, int *pLenMsg, int *idx, int *hasChanged)
+{
+ char address[16];
+ char caddress[16];
+ int offset = *idx;
+ uchar* msgcpy = *msg;
+ size_t iplen;
+ size_t caddresslen;
+ int oldLen = *pLenMsg;
+
+ if(syntax_ipv4((*msg) + offset, *pLenMsg - offset, &iplen)) {
+ if(pWrkrData->pData->ipv4.mode == SIMPLE) {
+ simpleAnon(pWrkrData, *msg + *idx, hasChanged, iplen);
+ *idx += iplen;
+ return;
+ }
+
+ assert(iplen < sizeof(address));
+ getip(*msg + offset, iplen, address);
+ offset += iplen;
+ strcpy(caddress, address);
+ process_IPv4(caddress, pWrkrData);
+ caddresslen = strlen(caddress);
+ *hasChanged = 1;
+
+ if(caddresslen != strlen(address)) {
+ *pLenMsg = *pLenMsg + ((int)caddresslen - (int)strlen(address));
+ *msg = (uchar*) malloc(*pLenMsg);
+ memcpy(*msg, msgcpy, *idx);
+ }
+ memcpy(*msg + *idx, caddress, caddresslen);
+ *idx = *idx + caddresslen;
+ if(*idx < *pLenMsg) {
+ memcpy(*msg + *idx, msgcpy + offset, oldLen - offset);
+ }
+ if(msgcpy != *msg) {
+ free(msgcpy);
+ }
+ }
+}
+
+
+static void
+code_ipv6_int(struct ipv6_int* ip, wrkrInstanceData_t *pWrkrData, int useEmbedded)
+{
+ unsigned long long randlow = 0;
+ unsigned long long randhigh = 0;
+ unsigned tmpRand;
+ int fullbits;
+
+ int bits = useEmbedded ? pWrkrData->pData->embeddedIPv4.bits : pWrkrData->pData->ipv6.bits;
+ enum mode anonmode = useEmbedded ? pWrkrData->pData->embeddedIPv4.anonmode : pWrkrData->pData->ipv6.anonmode;
+
+ if(bits == 128) { //has to be handled separately, since shift
+ //128 bits doesn't work on unsigned long long
+ ip->high = 0;
+ ip->low = 0;
+ } else if(bits > 64) {
+ ip->low = 0;
+ ip->high = (ip->high >> (bits - 64)) << (bits - 64);
+ } else if(bits == 64) {
+ ip->low = 0;
+ } else {
+ ip->low = (ip->low >> bits) << bits;
+ }
+ switch(anonmode) {
+ case ZERO:
+ break;
+ case RANDOMINT:
+ if(bits == 128) {
+ for(int i = 0; i < 8; i++) {
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ ip->high <<= 8;
+ ip->high |= tmpRand;
+
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ ip->low <<= 8;
+ ip->low |= tmpRand;
+ }
+ } else if(bits > 64) {
+ for(int i = 0; i < 8; i++) {
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ ip->low <<= 8;
+ ip->low |= tmpRand;
+ }
+
+ bits -= 64;
+ fullbits = bits / 8;
+ bits = bits % 8;
+ while(fullbits > 0) {
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ randhigh <<= 8;
+ randhigh |= tmpRand;
+ fullbits--;
+ }
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*((1 << bits) - 1));
+ randhigh <<= bits;
+ randhigh |= tmpRand;
+
+ ip->high |= randhigh;
+ } else if(bits == 64) {
+ for(int i = 0; i < 8; i++) {
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ ip->low <<= 8;
+ ip->low |= tmpRand;
+ }
+ } else {
+ fullbits = bits / 8;
+ bits = bits % 8;
+ while(fullbits > 0) {
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*0xff);
+ randlow <<= 8;
+ randlow |= tmpRand;
+ fullbits--;
+ }
+ tmpRand = (unsigned)((rand_r(&(pWrkrData->randstatus))/(double)RAND_MAX)*((1 << bits) - 1));
+ randlow <<= bits;
+ randlow |= tmpRand;
+
+ ip->low |= randlow;
+ }
+ break;
+ case SIMPLE: //can't happen, since this case is caught at the start of anonipv4()
+ default:
+ LogError(0, RS_RET_INTERNAL_ERROR, "mmanon: unexpected code path reached in code_int function");
+ }
+}
+
+
+//separate function from recognising ipv6, since the recognition might get more
+//complex. This function always stays
+//the same, since it always gets an valid ipv6 input
+static void
+ipv62num(char* const address, const size_t iplen, struct ipv6_int* const ip)
+{
+ int num[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ int cyc = 0;
+ int dots = 0;
+ int val;
+ unsigned i;
+
+ for(i = 0; i < iplen && dots < 2; i++) {
+ val = getHexVal(address[i]);
+ if(val == -1) {
+ dots++;
+ if(dots < 2) {
+ cyc++;
+ }
+ } else {
+ num[cyc] = num[cyc] * 16 + val;
+ dots = 0;
+ }
+ }
+ if(dots == 2) {
+ if(i < iplen - 1) {
+ int shift = 0;
+ cyc = 7;
+ for(unsigned j = iplen - 1; j >= i; j--) {
+ val = getHexVal(address[j]);
+ if(val == -1) {
+ cyc--;
+ shift = 0;
+ } else {
+ val <<= shift;
+ shift += 4;
+ num[cyc] += val;
+ }
+ }
+ } else {
+ while(cyc < 8) {
+ num[cyc] = 0;
+ cyc++;
+ }
+ }
+ }
+
+ for(i = 0; i < 4; i++) {
+ ip->high <<= 16;
+ ip->high |= num[i];
+ }
+ while(i < 8) {
+ ip->low <<= 16;
+ ip->low |= num[i];
+ i++;
+ }
+}
+
+
+static void
+num2ipv6 (struct ipv6_int* ip, char* address)
+{
+ int num[8];
+ int i;
+
+ for(i = 7; i > 3; i--) {
+ num[i] = ip->low & 0xffff;
+ ip->low >>= 16;
+ }
+ while(i > -1) {
+ num[i] = ip->high & 0xffff;
+ ip->high >>= 16;
+ i--;
+ }
+
+ snprintf(address, 40, "%x:%x:%x:%x:%x:%x:%x:%x", num[0], num[1], num[2], num[3], num[4], num[5],
+ num[6], num[7]);
+}
+
+
+static int
+keys_equal_fn(void* key1, void* key2)
+{
+ struct ipv6_int *const k1 = (struct ipv6_int*) key1;
+ struct ipv6_int *const k2 = (struct ipv6_int*) key2;
+
+ return((k1->high == k2->high) && (k1->low == k2->low));
+}
+
+
+static unsigned
+hash_from_key_fn (void* k)
+{
+ struct ipv6_int *const key = (struct ipv6_int*) k;
+ unsigned hashVal;
+
+ hashVal = (key->high & 0xFFC00000) | (key->low & 0x3FFFFF);
+ return hashVal;
+}
+
+
+static void
+num2embedded (struct ipv6_int* ip, char* address)
+{
+ int num[8];
+ int i;
+
+ for(i = 7; i > 3; i--) {
+ num[i] = ip->low & 0xffff;
+ ip->low >>= 16;
+ }
+ while(i > -1) {
+ num[i] = ip->high & 0xffff;
+ ip->high >>= 16;
+ i--;
+ }
+
+ snprintf(address, 46, "%x:%x:%x:%x:%x:%x:%d.%d.%d.%d", num[0], num[1], num[2], num[3], num[4], num[5],
+ (num[6] & 0xff00) >> 8, num[6] & 0xff, (num[7] & 0xff00) >> 8, num[7] & 0xff);
+}
+
+
+static rsRetVal
+findIPv6(struct ipv6_int* num, char* address, wrkrInstanceData_t *const pWrkrData, int useEmbedded)
+{
+ struct ipv6_int* hashKey = NULL;
+ DEFiRet;
+ struct hashtable* hash = useEmbedded? pWrkrData->pData->embeddedIPv4.hash : pWrkrData->pData->ipv6.hash;
+
+
+ if(hash == NULL) {
+ CHKmalloc(hash = create_hashtable(512, hash_from_key_fn, keys_equal_fn, NULL));
+ if(useEmbedded) {
+ pWrkrData->pData->embeddedIPv4.hash = hash;
+ } else {
+ pWrkrData->pData->ipv6.hash = hash;
+ }
+ }
+
+ char* val = (char*)(hashtable_search(hash, num));
+
+ if(val != NULL) {
+ strcpy(address, val);
+ } else {
+ CHKmalloc(hashKey = (struct ipv6_int*) malloc(sizeof(struct ipv6_int)));
+ hashKey->low = num->low;
+ hashKey->high = num->high;
+
+ if(useEmbedded) {
+ code_ipv6_int(num, pWrkrData, 1);
+ num2embedded(num, address);
+ } else {
+ code_ipv6_int(num, pWrkrData, 0);
+ num2ipv6(num, address);
+ }
+ char* hashString;
+ CHKmalloc(hashString = strdup(address));
+
+ if(!hashtable_insert(hash, hashKey, hashString)) {
+ DBGPRINTF("hashtable error: insert to %s-table failed",
+ useEmbedded ? "embedded ipv4" : "ipv6");
+ free(hashString);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ hashKey = NULL;
+ }
+finalize_it:
+ free(hashKey);
+ RETiRet;
+}
+
+
+static void
+process_IPv6 (char* address, wrkrInstanceData_t *pWrkrData, const size_t iplen)
+{
+ struct ipv6_int num = {0, 0};
+
+ ipv62num(address, iplen, &num);
+
+ if(pWrkrData->pData->ipv6.randConsis) {
+ findIPv6(&num, address, pWrkrData, 0);
+ } else {
+ code_ipv6_int(&num, pWrkrData, 0);
+ num2ipv6(&num, address);
+ }
+}
+
+
+static void
+anonipv6(wrkrInstanceData_t *pWrkrData, uchar **msg, int *pLenMsg, int *idx, int *hasChanged)
+{
+ size_t iplen = 0;
+ int offset = *idx;
+ char address[40];
+ uchar* msgcpy = *msg;
+ size_t caddresslen;
+ size_t oldLen = *pLenMsg;
+
+ int syn = syntax_ipv6(*msg + offset, *pLenMsg - offset, &iplen);
+ if(syn) {
+ assert(iplen < sizeof(address)); //has to be < instead of <= since address includes space for a '\0'
+ getip(*msg + offset, iplen, address);
+ offset += iplen;
+ process_IPv6(address, pWrkrData, iplen);
+
+ caddresslen = strlen(address);
+ *hasChanged = 1;
+
+ if(caddresslen != iplen) {
+ *pLenMsg = *pLenMsg + ((int)caddresslen - (int)iplen);
+ *msg = (uchar*) malloc(*pLenMsg);
+ memcpy(*msg, msgcpy, *idx);
+ }
+ memcpy(*msg + *idx, address, caddresslen);
+ *idx = *idx + caddresslen;
+ if(*idx < *pLenMsg) {
+ memcpy(*msg + *idx, msgcpy + offset, oldLen - offset);
+ }
+ if(msgcpy != *msg) {
+ free(msgcpy);
+ }
+ }
+}
+
+
+static size_t
+findV4Start(const uchar *const __restrict__ buf, size_t dotPos)
+{
+ while(dotPos > 0) {
+ if(buf[dotPos] == ':') {
+ return dotPos + 1;
+ }
+ dotPos--;
+ }
+ return -1; //should not happen
+}
+
+
+static int
+syntax_embedded(const uchar *const __restrict__ buf,
+ const size_t buflen,
+ size_t *const __restrict__ nprocessed,
+ size_t * v4Start)
+{
+ int lastSep = 0;
+ sbool hadAbbrev = 0;
+ int ipParts = 0;
+ int numLen;
+ int isIP = 0;
+ size_t ipv4Len;
+
+ while(*nprocessed < buflen) {
+ numLen = isValidHexNum(buf + *nprocessed, buflen - *nprocessed, nprocessed, 1);
+ if(numLen > 0) { //found a valid num
+ if((ipParts == 6 && hadAbbrev) || ipParts > 6) { //is 6 since the first part of
+ //IPv4 will also result in a valid hexvalue
+ isIP = 0;
+ goto done;
+ }
+ if (ipParts == 0 && lastSep && !hadAbbrev) {
+ isIP = 0;
+ goto done;
+ }
+ lastSep = 0;
+ ipParts++;
+ } else if (numLen == -1) { //':'
+ if(lastSep) {
+ if(hadAbbrev) {
+ isIP = 0;
+ goto done;
+ } else {
+ hadAbbrev = 1;
+ }
+ }
+ lastSep = 1;
+ } else if (numLen == -2) { //'.'
+ if (lastSep || (ipParts == 0 && hadAbbrev) || (ipParts <= 6 && !hadAbbrev)) {
+ isIP = 0;
+ goto done;
+ }
+ *v4Start = findV4Start(buf, (*nprocessed) - 1);
+ if(syntax_ipv4(buf + (*v4Start), buflen, &ipv4Len)) {
+ *nprocessed += (ipv4Len - ((*nprocessed) - (*v4Start)));
+ isIP = 1;
+ goto done;
+ } else {
+ isIP = 0;
+ goto done;
+ }
+ } else { //no valid num
+ isIP = 0;
+ goto done;
+ }
+ }
+
+ isIP = 0;
+
+done:
+ return isIP;
+}
+
+
+static void
+embedded2num(char* address, size_t v4Start, struct ipv6_int* ip)
+{
+ int num[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ int cyc = 0;
+ int dots = 0;
+ int val;
+ unsigned i;
+
+ unsigned v4Val = ipv42num(address + v4Start);
+ num[7] = v4Val & 0xffff;
+ num[6] = (v4Val & 0xffff0000) >> 16;
+
+ for(i = 0; i < v4Start && dots < 2; i++) {
+ val = getHexVal(address[i]);
+ if(val == -1) {
+ dots++;
+ if(dots < 2) {
+ cyc++;
+ }
+ } else {
+ num[cyc] = num[cyc] * 16 + val;
+ dots = 0;
+ }
+ }
+ if(dots == 2) {
+ if(i < v4Start) {
+ int shift = 0;
+ cyc = 5;
+ for(unsigned j = v4Start - 1; j >= i; j--) {
+ val = getHexVal(address[j]);
+ if(val == -1) {
+ cyc--;
+ shift = 0;
+ } else {
+ val <<= shift;
+ shift += 4;
+ num[cyc] += val;
+ }
+ }
+ } else {
+ while(cyc < 6) {
+ num[cyc] = 0;
+ cyc++;
+ }
+ }
+ }
+
+ for(i = 0; i < 4; i++) {
+ ip->high <<= 16;
+ ip->high |= num[i];
+ }
+ while(i < 8) {
+ ip->low <<= 16;
+ ip->low |= num[i];
+ i++;
+ }
+}
+
+
+static void
+process_embedded (char* address, wrkrInstanceData_t *pWrkrData, size_t v4Start)
+{
+ struct ipv6_int num = {0, 0};
+
+ embedded2num(address, v4Start, &num);
+
+ if(pWrkrData->pData->embeddedIPv4.randConsis) {
+ findIPv6(&num, address, pWrkrData, 1);
+ } else {
+ code_ipv6_int(&num, pWrkrData, 1);
+ num2embedded(&num, address);
+ }
+}
+
+
+static void
+anonEmbedded(wrkrInstanceData_t *pWrkrData, uchar **msg, int *pLenMsg, int *idx, int *hasChanged)
+{
+ size_t iplen = 0;
+ int offset = *idx;
+ char address[46];
+ uchar* msgcpy = *msg;
+ unsigned caddresslen;
+ size_t oldLen = *pLenMsg;
+ size_t v4Start;
+
+ int syn = syntax_embedded(*msg + offset, *pLenMsg - offset, &iplen, &v4Start);
+ if(syn) {
+ assert(iplen < sizeof(address));
+ getip(*msg + offset, iplen, address);
+ offset += iplen;
+ process_embedded(address, pWrkrData, v4Start);
+
+ caddresslen = strlen(address);
+ *hasChanged = 1;
+
+ if(caddresslen != iplen) {
+ *pLenMsg = *pLenMsg + ((int)caddresslen - (int)iplen);
+ *msg = (uchar*) malloc(*pLenMsg);
+ memcpy(*msg, msgcpy, *idx);
+ }
+ memcpy(*msg + *idx, address, caddresslen);
+ *idx = *idx + caddresslen;
+ if(*idx < *pLenMsg) {
+ memcpy(*msg + *idx, msgcpy + offset, oldLen - offset);
+ }
+ if(msgcpy != *msg) {
+ free(msgcpy);
+ }
+ }
+}
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *msg;
+ int lenMsg;
+ int i;
+ int hasChanged = 0;
+CODESTARTdoAction
+ lenMsg = getMSGLen(pMsg);
+ msg = (uchar*)strdup((char*)getMSG(pMsg));
+
+ for(i = 0 ; i <= lenMsg - 2 ; i++) {
+ if(pWrkrData->pData->embeddedIPv4.enable) {
+ anonEmbedded(pWrkrData, &msg, &lenMsg, &i, &hasChanged);
+ }
+ if(pWrkrData->pData->ipv4.enable) {
+ anonipv4(pWrkrData, &msg, &lenMsg, &i, &hasChanged);
+ }
+ if(pWrkrData->pData->ipv6.enable) {
+ anonipv6(pWrkrData, &msg, &lenMsg, &i, &hasChanged);
+ }
+ }
+ if(hasChanged) {
+ MsgReplaceMSG(pMsg, msg, lenMsg);
+ }
+ free(msg);
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmanon: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmaudit/Makefile.am b/plugins/mmaudit/Makefile.am
new file mode 100644
index 0000000..77b2e85
--- /dev/null
+++ b/plugins/mmaudit/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmaudit.la
+
+mmaudit_la_SOURCES = mmaudit.c
+mmaudit_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmaudit_la_LDFLAGS = -module -avoid-version
+mmaudit_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmaudit/Makefile.in b/plugins/mmaudit/Makefile.in
new file mode 100644
index 0000000..4f88459
--- /dev/null
+++ b/plugins/mmaudit/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmaudit
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmaudit_la_DEPENDENCIES =
+am_mmaudit_la_OBJECTS = mmaudit_la-mmaudit.lo
+mmaudit_la_OBJECTS = $(am_mmaudit_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 =
+mmaudit_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmaudit_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmaudit_la-mmaudit.Plo
+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 = $(mmaudit_la_SOURCES)
+DIST_SOURCES = $(mmaudit_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmaudit.la
+mmaudit_la_SOURCES = mmaudit.c
+mmaudit_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmaudit_la_LDFLAGS = -module -avoid-version
+mmaudit_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmaudit/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmaudit/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmaudit.la: $(mmaudit_la_OBJECTS) $(mmaudit_la_DEPENDENCIES) $(EXTRA_mmaudit_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmaudit_la_LINK) -rpath $(pkglibdir) $(mmaudit_la_OBJECTS) $(mmaudit_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmaudit_la-mmaudit.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmaudit_la-mmaudit.lo: mmaudit.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmaudit_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmaudit_la-mmaudit.lo -MD -MP -MF $(DEPDIR)/mmaudit_la-mmaudit.Tpo -c -o mmaudit_la-mmaudit.lo `test -f 'mmaudit.c' || echo '$(srcdir)/'`mmaudit.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmaudit_la-mmaudit.Tpo $(DEPDIR)/mmaudit_la-mmaudit.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmaudit.c' object='mmaudit_la-mmaudit.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) $(mmaudit_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmaudit_la-mmaudit.lo `test -f 'mmaudit.c' || echo '$(srcdir)/'`mmaudit.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmaudit_la-mmaudit.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmaudit_la-mmaudit.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmaudit/mmaudit.c b/plugins/mmaudit/mmaudit.c
new file mode 100644
index 0000000..61c3717
--- /dev/null
+++ b/plugins/mmaudit/mmaudit.c
@@ -0,0 +1,344 @@
+/* mmaudit.c
+ * This is a message modification module supporting Linux audit format
+ * in various settings. The module tries to identify the provided
+ * message as being a Linux audit record and, if so, converts it into
+ * cee-enhanced syslog format.
+ *
+ * NOTE WELL:
+ * Right now, we do not do any trust checks. So it is possible that a
+ * malicous user emits something that looks like an audit record and
+ * tries to fool the system with that. Solving this trust issue is NOT
+ * an easy thing to do. This will be worked on, as the lumberjack effort
+ * continues. Please consider the module in its current state as a proof
+ * of concept.
+ *
+ * File begun on 2012-02-23 by RGerhards
+ *
+ * Copyright 2013-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <json.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+
+
+/* static data */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ int dummy; /* remove when the first real parameter is needed */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("mmaudit\n");
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static void
+skipWhitespace(uchar **buf)
+{
+ while(**buf && isspace(**buf))
+ ++(*buf);
+}
+
+
+static rsRetVal
+parseName(uchar **buf, char *name, unsigned lenName)
+{
+ unsigned i;
+ skipWhitespace(buf);
+ --lenName; /* reserve space for '\0' */
+ i = 0;
+ while(**buf && **buf != '=' && lenName) {
+ name[i++] = **buf;
+ ++(*buf), --lenName;
+ }
+ name[i] = '\0';
+ return RS_RET_OK;
+}
+
+
+static rsRetVal
+parseValue(uchar **buf, char *val, unsigned lenval)
+{
+ char termc;
+ unsigned i;
+ DEFiRet;
+
+ --lenval; /* reserve space for '\0' */
+ i = 0;
+ if(**buf == '\0') {
+ FINALIZE;
+ } else if(**buf == '\'') {
+ termc = '\'';
+ ++(*buf);
+ } else if(**buf == '"') {
+ termc = '"';
+ ++(*buf);
+ } else {
+ termc = ' ';
+ }
+
+ while(**buf && **buf != termc && lenval) {
+ val[i++] = **buf;
+ ++(*buf), --lenval;
+ }
+ val[i] = '\0';
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* parse the audit record and create json structure
+ */
+static rsRetVal
+audit_parse(uchar *buf, struct json_object **jsonRoot)
+{
+ struct json_object *json;
+ struct json_object *jval;
+ char name[1024];
+ char val[1024];
+ DEFiRet;
+
+ *jsonRoot = json_object_new_object();
+ if(*jsonRoot == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ json = json_object_new_object();
+ json_object_object_add(*jsonRoot, "data", json);
+
+ while(*buf) {
+ CHKiRet(parseName(&buf, name, sizeof(name)));
+ if(*buf != '=') {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ ++buf;
+ CHKiRet(parseValue(&buf, val, sizeof(val)));
+ jval = json_object_new_string(val);
+ json_object_object_add(json, name, jval);
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *buf;
+ int typeID;
+ struct json_object *jsonRoot;
+ struct json_object *json;
+ struct json_object *jval;
+ int i;
+ char auditID[1024];
+ int bSuccess = 0;
+CODESTARTdoAction
+ /* note that we can performance-optimize the interface, but this also
+ * requires changes to the libraries. For now, we accept message
+ * duplication. -- rgerhards, 2010-12-01
+ */
+ buf = getMSG(pMsg);
+
+ while(*buf && isspace(*buf)) {
+ ++buf;
+ }
+
+ if(*buf == '\0' || strncmp((char*)buf, "type=", 5)) {
+ DBGPRINTF("mmaudit: type= undetected: '%s'\n", buf);
+ FINALIZE;
+ }
+ buf += 5;
+
+ typeID = 0;
+ while(*buf && isdigit(*buf)) {
+ typeID = typeID * 10 + *buf - '0';
+ ++buf;
+ }
+
+ if(*buf == '\0' || strncmp((char*)buf, " audit(", sizeof(" audit(")-1)) {
+ DBGPRINTF("mmaudit: audit( header not found: %s'\n", buf);
+ FINALIZE;
+ }
+ buf += sizeof(" audit(");
+
+ for(i = 0 ; i < (int) (sizeof(auditID)-2) && *buf && *buf != ')' ; ++i) {
+ auditID[i] = *buf++;
+ }
+ auditID[i] = '\0';
+ if(*buf != ')' || *(buf+1) != ':') {
+ DBGPRINTF("mmaudit: trailer '):' not found, no audit record: %s'\n", buf);
+ FINALIZE;
+ }
+ buf += 2;
+
+ audit_parse(buf, &jsonRoot);
+ if(jsonRoot == NULL) {
+ DBGPRINTF("mmaudit: audit parse error, assuming no "
+ "audit message: '%s'\n", buf);
+ FINALIZE;
+ }
+
+ /* we now need to shuffle the "outer" properties into that stream */
+ json = json_object_new_object();
+ json_object_object_add(jsonRoot, "hdr", json);
+ jval = json_object_new_string(auditID);
+ json_object_object_add(json, "auditid", jval);
+ jval = json_object_new_int(typeID);
+ json_object_object_add(json, "type", jval);
+
+ msgAddJSON(pMsg, (uchar*)"!audit", jsonRoot, 0, 0);
+ bSuccess = 1;
+
+finalize_it:
+ MsgSetParseSuccess(pMsg, bSuccess);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":mmaudit:", sizeof(":mmaudit:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":mmaudit:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ /* we call the function below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat");
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported;
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("mmaudit: msg-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/mmdblookup/Makefile.am b/plugins/mmdblookup/Makefile.am
new file mode 100644
index 0000000..bb7c156
--- /dev/null
+++ b/plugins/mmdblookup/Makefile.am
@@ -0,0 +1,14 @@
+pkglib_LTLIBRARIES = mmdblookup.la
+
+if MMDBLOOKUP_USE_DUMMY
+mmdblookup_la_SOURCES = dummy.c
+mmdblookup_la_LDFLAGS = -module -avoid-version
+else
+mmdblookup_la_SOURCES = mmdblookup.c
+mmdblookup_la_LDFLAGS = -module -avoid-version -lmaxminddb
+endif
+
+mmdblookup_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmdblookup_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmdblookup/Makefile.in b/plugins/mmdblookup/Makefile.in
new file mode 100644
index 0000000..15f2a88
--- /dev/null
+++ b/plugins/mmdblookup/Makefile.in
@@ -0,0 +1,814 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmdblookup
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmdblookup_la_DEPENDENCIES =
+am__mmdblookup_la_SOURCES_DIST = mmdblookup.c dummy.c
+@MMDBLOOKUP_USE_DUMMY_FALSE@am_mmdblookup_la_OBJECTS = \
+@MMDBLOOKUP_USE_DUMMY_FALSE@ mmdblookup_la-mmdblookup.lo
+@MMDBLOOKUP_USE_DUMMY_TRUE@am_mmdblookup_la_OBJECTS = \
+@MMDBLOOKUP_USE_DUMMY_TRUE@ mmdblookup_la-dummy.lo
+mmdblookup_la_OBJECTS = $(am_mmdblookup_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 =
+mmdblookup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmdblookup_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmdblookup_la-dummy.Plo \
+ ./$(DEPDIR)/mmdblookup_la-mmdblookup.Plo
+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 = $(mmdblookup_la_SOURCES)
+DIST_SOURCES = $(am__mmdblookup_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmdblookup.la
+@MMDBLOOKUP_USE_DUMMY_FALSE@mmdblookup_la_SOURCES = mmdblookup.c
+@MMDBLOOKUP_USE_DUMMY_TRUE@mmdblookup_la_SOURCES = dummy.c
+@MMDBLOOKUP_USE_DUMMY_FALSE@mmdblookup_la_LDFLAGS = -module -avoid-version -lmaxminddb
+@MMDBLOOKUP_USE_DUMMY_TRUE@mmdblookup_la_LDFLAGS = -module -avoid-version
+mmdblookup_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmdblookup_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmdblookup/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmdblookup/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmdblookup.la: $(mmdblookup_la_OBJECTS) $(mmdblookup_la_DEPENDENCIES) $(EXTRA_mmdblookup_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmdblookup_la_LINK) -rpath $(pkglibdir) $(mmdblookup_la_OBJECTS) $(mmdblookup_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmdblookup_la-dummy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmdblookup_la-mmdblookup.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmdblookup_la-mmdblookup.lo: mmdblookup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmdblookup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmdblookup_la-mmdblookup.lo -MD -MP -MF $(DEPDIR)/mmdblookup_la-mmdblookup.Tpo -c -o mmdblookup_la-mmdblookup.lo `test -f 'mmdblookup.c' || echo '$(srcdir)/'`mmdblookup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmdblookup_la-mmdblookup.Tpo $(DEPDIR)/mmdblookup_la-mmdblookup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmdblookup.c' object='mmdblookup_la-mmdblookup.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) $(mmdblookup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmdblookup_la-mmdblookup.lo `test -f 'mmdblookup.c' || echo '$(srcdir)/'`mmdblookup.c
+
+mmdblookup_la-dummy.lo: dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmdblookup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmdblookup_la-dummy.lo -MD -MP -MF $(DEPDIR)/mmdblookup_la-dummy.Tpo -c -o mmdblookup_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmdblookup_la-dummy.Tpo $(DEPDIR)/mmdblookup_la-dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='mmdblookup_la-dummy.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) $(mmdblookup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmdblookup_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmdblookup_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/mmdblookup_la-mmdblookup.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmdblookup_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/mmdblookup_la-mmdblookup.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmdblookup/dummy.c b/plugins/mmdblookup/dummy.c
new file mode 100644
index 0000000..1b18aef
--- /dev/null
+++ b/plugins/mmdblookup/dummy.c
@@ -0,0 +1,172 @@
+/* a dummy module to be loaded if we cannot build this module, but
+ * configure required it to be "optional".
+ *
+ * Copyright 2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define MODULE_NAME "mmdblookup" /* how are we named? */
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME(MODULE_NAME)
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData ATTR_UNUSED;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ (void) lst;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME);
+ENDsetModCnf
+
+
+BEGINnewActInst
+CODESTARTnewActInst
+ (void) pData;
+ (void) ppModData;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void) pMsgData;
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("mmdblookup: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmdblookup/mmdblookup.c b/plugins/mmdblookup/mmdblookup.c
new file mode 100644
index 0000000..f9f3c73
--- /dev/null
+++ b/plugins/mmdblookup/mmdblookup.c
@@ -0,0 +1,517 @@
+/* mmdblookup.c
+ * Parse ipaddress field of the message into structured data using
+ * MaxMindDB.
+ *
+ * Copyright 2013 Rao Chenlin.
+ * Copyright 2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+#include "maxminddb.h"
+
+#define JSON_IPLOOKUP_NAME "!iplocation"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmdblookup")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *pszKey;
+ char *pszMmdbFile;
+ struct {
+ int nmemb;
+ char **name;
+ char **varname;
+ } fieldList;
+ sbool reloadOnHup;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ MMDB_s mmdb;
+ pthread_mutex_t mmdbMutex;
+ sbool mmdb_is_open;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ /* our overall config object */
+ rsconf_t *pConf;
+ const char *container;
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "container", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* tables for interfacing with the v6 config system
+ * action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "key", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "mmdbfile", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "fields", eCmdHdlrArray, CNFPARAM_REQUIRED },
+ { "reloadonhup", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk actpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+};
+
+
+/* protype functions */
+void str_split(char **membuf);
+
+int open_mmdb(const char *file, MMDB_s *mmdb);
+void close_mmdb(MMDB_s *mmdb);
+
+
+int open_mmdb(const char *file, MMDB_s *mmdb) {
+ int status = MMDB_open(file, MMDB_MODE_MMAP, mmdb);
+ if (MMDB_SUCCESS != status) {
+ dbgprintf("Can't open %s - %s\n", file, MMDB_strerror(status));
+ if (MMDB_IO_ERROR == status) {
+ dbgprintf(" IO error: %s\n", strerror(errno));
+ }
+ LogError(0, RS_RET_SUSPENDED, "maxminddb error: cannot open database file");
+ return RS_RET_SUSPENDED;
+ }
+
+ return RS_RET_OK;
+}
+
+void close_mmdb(MMDB_s *mmdb) {
+ MMDB_close(mmdb);
+}
+
+static rsRetVal wrkr_reopen_mmdb(wrkrInstanceData_t *pWrkrData) {
+ DEFiRet;
+ pthread_mutex_lock(&pWrkrData->mmdbMutex);
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "mmdblookup: reopening MMDB file");
+ if (pWrkrData->mmdb_is_open) close_mmdb(&pWrkrData->mmdb);
+ pWrkrData->mmdb_is_open = 0;
+ CHKiRet(open_mmdb(pWrkrData->pData->pszMmdbFile, &pWrkrData->mmdb));
+ pWrkrData->mmdb_is_open = 1;
+
+finalize_it:
+ pthread_mutex_unlock(&pWrkrData->mmdbMutex);
+ RETiRet;
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free((void*)runModConf->container);
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ CHKiRet(open_mmdb(pData->pszMmdbFile, &pWrkrData->mmdb));
+ pWrkrData->mmdb_is_open = 1;
+ CHKiConcCtrl(pthread_mutex_init(&pWrkrData->mmdbMutex, NULL));
+finalize_it:
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->fieldList.name != NULL) {
+ for(int i = 0 ; i < pData->fieldList.nmemb ; ++i) {
+ free(pData->fieldList.name[i]);
+ free(pData->fieldList.varname[i]);
+ }
+ free(pData->fieldList.name);
+ free(pData->fieldList.varname);
+ }
+ free(pData->pszKey);
+ free(pData->pszMmdbFile);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if (pWrkrData->mmdb_is_open) close_mmdb(&pWrkrData->mmdb);
+ pWrkrData->mmdb_is_open = 0;
+ pthread_mutex_destroy(&pWrkrData->mmdbMutex);
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ loadModConf->container = NULL;
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "mmdblookup: error processing module "
+ "config parameters missing [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for mmdblookup:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "container")) {
+ loadModConf->container = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("mmdblookup: program error, non-handled "
+ "param '%s' in setModCnf\n", modpblk.descr[i].name);
+ }
+ }
+
+ if(loadModConf->container == NULL) {
+ CHKmalloc(loadModConf->container = strdup(JSON_IPLOOKUP_NAME));
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->pszKey = NULL;
+ pData->pszMmdbFile = NULL;
+ pData->fieldList.nmemb = 0;
+ pData->reloadOnHup = 1;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ dbgprintf("newActInst (mmdblookup)\n");
+ if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for (i = 0; i < actpblk.nParams; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(actpblk.descr[i].name, "key")) {
+ pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "mmdbfile")) {
+ pData->pszMmdbFile = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "fields")) {
+ pData->fieldList.nmemb = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->fieldList.name = calloc(pData->fieldList.nmemb, sizeof(char *)));
+ CHKmalloc(pData->fieldList.varname = calloc(pData->fieldList.nmemb, sizeof(char *)));
+ for (int j = 0; j < pvals[i].val.d.ar->nmemb; ++j) {
+ char *const param = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ char *varname = NULL;
+ char *name;
+ if(*param == ':') {
+ char *b = strchr(param+1, ':');
+ if(b == NULL) {
+ parser_errmsg("mmdblookup: missing closing colon: '%s'", param);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ *b = '\0'; /* split name & varname */
+ varname = param+1;
+ name = b+1;
+ } else {
+ name = param;
+ }
+ if(*name == '!')
+ ++name;
+ CHKmalloc(pData->fieldList.name[j] = strdup(name));
+ char vnamebuf[1024];
+ snprintf(vnamebuf, sizeof(vnamebuf),
+ "%s!%s", loadModConf->container,
+ (varname == NULL) ? name : varname);
+ CHKmalloc(pData->fieldList.varname[j] = strdup(vnamebuf));
+ free(param);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "reloadonhup")) {
+ pData->reloadOnHup = pvals[i].val.d.n;
+ } else {
+ dbgprintf("mmdblookup: program error, non-handled"
+ " param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = wrkr_reopen_mmdb(pWrkrData);
+ENDtryResume
+
+
+void
+str_split(char **membuf)
+{
+ int in_quotes = 0;
+ char *buf = *membuf;
+ char tempbuf[strlen(buf)];
+ memset(tempbuf, 0, strlen(buf));
+
+ while (*buf++ != '\0') {
+ if (in_quotes) {
+ if (*buf == '"' && *(buf - 1) != '\\') {
+ in_quotes = !in_quotes;
+ strncat(tempbuf, buf, 1);
+ } else {
+ strncat(tempbuf, buf, 1);
+ }
+ } else {
+ if (*buf == '\n' || *buf == '\t' || *buf == ' ')
+ continue;
+ if (*buf == '<') {
+ char *p = strchr(buf, '>');
+ buf = buf + (int)(p - buf);
+ strcat(tempbuf, ",");
+ } else if (*buf == '}') {
+ strcat(tempbuf, "},");
+ } else if (*buf == ']') {
+ strcat(tempbuf, "],");
+ } else if (*buf == '"' && *(buf - 1) != '\\') {
+ in_quotes = !in_quotes;
+ strncat(tempbuf, buf, 1);
+ } else {
+ strncat(tempbuf, buf, 1);
+ }
+ }
+ }
+
+ memcpy(*membuf, tempbuf, strlen(tempbuf)+1);
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ struct json_object *keyjson = NULL;
+ const char *pszValue;
+ instanceData *const pData = pWrkrData->pData;
+ json_object *total_json = NULL;
+ MMDB_entry_data_list_s *entry_data_list = NULL;
+CODESTARTdoAction
+ /* ensure file is open before beginning */
+ if (!pWrkrData->mmdb_is_open) {
+ CHKiRet(wrkr_reopen_mmdb(pWrkrData));
+ }
+
+ /* key is given, so get the property json */
+ msgPropDescr_t pProp;
+ msgPropDescrFill(&pProp, (uchar*)pData->pszKey, strlen(pData->pszKey));
+ rsRetVal localRet = msgGetJSONPropJSON(pMsg, &pProp, &keyjson);
+ msgPropDescrDestruct(&pProp);
+
+ pthread_mutex_lock(&pWrkrData->mmdbMutex);
+ if (localRet != RS_RET_OK) {
+ /* key not found in the message. nothing to do */
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ /* key found, so get the value */
+ pszValue = (char*)json_object_get_string(keyjson);
+ if(pszValue == NULL) { /* json null object returns NULL! */
+ pszValue = "";
+ }
+
+ int gai_err, mmdb_err;
+ MMDB_lookup_result_s result = MMDB_lookup_string(&pWrkrData->mmdb, pszValue, &gai_err, &mmdb_err);
+
+ if (0 != gai_err) {
+ dbgprintf("Error from call to getaddrinfo for %s - %s\n", pszValue, gai_strerror(gai_err));
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ if (MMDB_SUCCESS != mmdb_err) {
+ dbgprintf("Got an error from the maxminddb library: %s\n", MMDB_strerror(mmdb_err));
+ close_mmdb(&pWrkrData->mmdb);
+ pWrkrData->mmdb_is_open = 0;
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ if (!result.found_entry) {
+ dbgprintf("No entry found in database for '%s'\n", pszValue);
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+
+ int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
+
+ if (MMDB_SUCCESS != status) {
+ dbgprintf("Got an error looking up the entry data - %s\n", MMDB_strerror(status));
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ size_t memlen;
+ char *membuf;
+ FILE *memstream;
+ CHKmalloc(memstream = open_memstream(&membuf, &memlen));
+
+ if (entry_data_list != NULL && memstream != NULL) {
+ MMDB_dump_entry_data_list(memstream, entry_data_list, 2);
+ fflush(memstream);
+ str_split(&membuf);
+ }
+
+ DBGPRINTF("maxmindb returns: '%s'\n", membuf);
+ total_json = json_tokener_parse(membuf);
+ fclose(memstream);
+ free(membuf);
+
+ /* extract and amend fields (to message) as configured */
+ for (int i = 0 ; i < pData->fieldList.nmemb; ++i) {
+ char *strtok_save;
+ char buf[(strlen((char *)(pData->fieldList.name[i])))+1];
+ strcpy(buf, (char *)pData->fieldList.name[i]);
+
+ json_object *temp_json = total_json;
+ json_object *sub_obj = temp_json;
+ int j = 0;
+ const char *SEP = "!";
+
+ /* find lowest level JSON object */
+ char *s = strtok_r(buf, SEP, &strtok_save);
+ for (; s != NULL; j++) {
+ json_object_object_get_ex(temp_json, s, &sub_obj);
+ temp_json = sub_obj;
+ s = strtok_r(NULL, SEP, &strtok_save);
+ }
+ /* temp_json now contains the value we want to have, so set it */
+ json_object_get(temp_json);
+ msgAddJSON(pMsg, (uchar *)pData->fieldList.varname[i], temp_json, 0, 0);
+ }
+
+finalize_it:
+ pthread_mutex_unlock(&pWrkrData->mmdbMutex);
+ if(entry_data_list != NULL)
+ MMDB_free_entry_data_list(entry_data_list);
+ json_object_put(keyjson);
+ if(total_json != NULL)
+ json_object_put(total_json);
+ENDdoAction
+
+// HUP handling for the worker...
+BEGINdoHUPWrkr
+CODESTARTdoHUPWrkr
+ dbgprintf("mmdblookup: HUP received\n");
+ if (pWrkrData->pData->reloadOnHup) {
+ iRet = wrkr_reopen_mmdb(pWrkrData);
+ }
+ENDdoHUPWrkr
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_doHUPWrkr
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("mmdblookup: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmexternal/Makefile.am b/plugins/mmexternal/Makefile.am
new file mode 100644
index 0000000..e859e7d
--- /dev/null
+++ b/plugins/mmexternal/Makefile.am
@@ -0,0 +1,13 @@
+pkglib_LTLIBRARIES = mmexternal.la
+
+mmexternal_la_SOURCES = mmexternal.c
+mmexternal_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmexternal_la_LDFLAGS = -module -avoid-version
+mmexternal_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+mmexternal_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+mmexternal_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+EXTRA_DIST =
diff --git a/plugins/mmexternal/Makefile.in b/plugins/mmexternal/Makefile.in
new file mode 100644
index 0000000..8575f11
--- /dev/null
+++ b/plugins/mmexternal/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/mmexternal
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmexternal_la_DEPENDENCIES =
+am_mmexternal_la_OBJECTS = mmexternal_la-mmexternal.lo
+mmexternal_la_OBJECTS = $(am_mmexternal_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 =
+mmexternal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmexternal_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmexternal_la-mmexternal.Plo
+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 = $(mmexternal_la_SOURCES)
+DIST_SOURCES = $(mmexternal_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmexternal.la
+mmexternal_la_SOURCES = mmexternal.c
+mmexternal_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) \
+ $(am__append_1)
+mmexternal_la_LDFLAGS = -module -avoid-version $(am__append_2)
+mmexternal_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmexternal/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmexternal/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmexternal.la: $(mmexternal_la_OBJECTS) $(mmexternal_la_DEPENDENCIES) $(EXTRA_mmexternal_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmexternal_la_LINK) -rpath $(pkglibdir) $(mmexternal_la_OBJECTS) $(mmexternal_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmexternal_la-mmexternal.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmexternal_la-mmexternal.lo: mmexternal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmexternal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmexternal_la-mmexternal.lo -MD -MP -MF $(DEPDIR)/mmexternal_la-mmexternal.Tpo -c -o mmexternal_la-mmexternal.lo `test -f 'mmexternal.c' || echo '$(srcdir)/'`mmexternal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmexternal_la-mmexternal.Tpo $(DEPDIR)/mmexternal_la-mmexternal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmexternal.c' object='mmexternal_la-mmexternal.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) $(mmexternal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmexternal_la-mmexternal.lo `test -f 'mmexternal.c' || echo '$(srcdir)/'`mmexternal.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmexternal_la-mmexternal.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmexternal_la-mmexternal.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmexternal/mmexternal.c b/plugins/mmexternal/mmexternal.c
new file mode 100644
index 0000000..317420a
--- /dev/null
+++ b/plugins/mmexternal/mmexternal.c
@@ -0,0 +1,611 @@
+/* mmexternal.c
+ * This core plugin is an interface module to message modification
+ * modules written in languages other than C.
+ *
+ * Copyright 2014-2018 by Rainer Gerhards
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "module-template.h"
+#include "msg.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "glbl.h"
+#include "rsconf.h"
+
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmexternal")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ uchar *szBinary; /* name of binary to call */
+ char **aParams; /* Optional Parameters for binary command */
+ int iParams; /* Holds the count of parameters if set*/
+ int bForceSingleInst; /* only a single wrkr instance of program permitted? */
+ int inputProp; /* what to provide as input to the external program? */
+#define INPUT_MSG 0
+#define INPUT_RAWMSG 1
+#define INPUT_JSON 2
+ uchar *outputFileName; /* name of file for std[out/err] or NULL if to discard */
+ pthread_mutex_t mut; /* make sure only one instance is active */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ pid_t pid; /* pid of currently running process */
+ int fdOutput; /* it's fd (-1 if closed) */
+ int fdPipeOut; /* file descriptor to write to */
+ int fdPipeIn; /* fd we receive messages from the program (if we want to) */
+ int bIsRunning; /* is binary currently running? 0-no, 1-yes */
+ char *respBuf; /* buffer to read exernal plugin's response */
+ int maxLenRespBuf; /* (current) maximum length of response buffer */
+ int lenRespBuf; /* actual nbr of chars in response buffer */
+ int idxRespBuf; /* last char read from response buffer */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar *szBinary; /* name of binary to call */
+} configSettings_t;
+static configSettings_t cs;
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "binary", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "interface.input", eCmdHdlrString, 0 },
+ { "output", eCmdHdlrString, 0 },
+ { "forcesingleinstance", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.szBinary = NULL; /* name of binary to call */
+ENDinitConfVars
+
+/* config settings */
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->inputProp = INPUT_MSG;
+ pthread_mutex_init(&pData->mut, NULL);
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->fdPipeIn = -1;
+ pWrkrData->fdPipeOut = -1;
+ pWrkrData->fdOutput = -1;
+ pWrkrData->bIsRunning = 0;
+ pWrkrData->respBuf = NULL;
+ pWrkrData->maxLenRespBuf = 0;
+ pWrkrData->lenRespBuf = 0;
+ pWrkrData->idxRespBuf = 0;
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+ int i;
+CODESTARTfreeInstance
+ pthread_mutex_destroy(&pData->mut);
+ free(pData->szBinary);
+ free(pData->outputFileName);
+ if(pData->aParams != NULL) {
+ for (i = 0; i < pData->iParams; i++) {
+ free(pData->aParams[i]);
+ }
+ free(pData->aParams);
+ }
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ free(pWrkrData->respBuf);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+/* As this is just a debug function, we only make
+ * best effort to write the message but do *not* try very
+ * hard to handle errors. -- rgerhards, 2014-01-16
+ */
+static void
+writeOutputDebug(wrkrInstanceData_t *__restrict__ const pWrkrData,
+ const char *__restrict__ const buf,
+ const ssize_t lenBuf)
+{
+ char errStr[1024];
+ ssize_t r;
+
+ if(pWrkrData->pData->outputFileName == NULL)
+ goto done;
+
+ if(pWrkrData->fdOutput == -1) {
+ pWrkrData->fdOutput = open((char*)pWrkrData->pData->outputFileName,
+ O_WRONLY | O_APPEND | O_CREAT, 0600);
+ if(pWrkrData->fdOutput == -1) {
+ DBGPRINTF("mmexternal: error opening output file %s: %s\n",
+ pWrkrData->pData->outputFileName,
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ goto done;
+ }
+ }
+
+ r = write(pWrkrData->fdOutput, buf, (size_t) lenBuf);
+ if(r != lenBuf) {
+ DBGPRINTF("mmexternal: problem writing output file %s: bytes "
+ "requested %lld, written %lld, msg: %s\n",
+ pWrkrData->pData->outputFileName, (long long) lenBuf, (long long) r,
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+done: return;
+}
+
+
+/* Get reply from external program. Note that we *must* receive one
+ * reply for each message sent (half-duplex protocol). As such, the last
+ * char we read MUST be \n ... we cannot have multiple LF as this is
+ * forbidden by the plugin interface. We cannot have multiple responses
+ * for multiple messages, as we are in half-duplex mode! This makes
+ * things quite a bit simpler. So don't think the simple code does
+ * not handle those border-cases that are describe to cannot exist!
+ */
+static void
+processProgramReply(wrkrInstanceData_t *__restrict__ const pWrkrData, smsg_t *const pMsg)
+{
+ rsRetVal iRet;
+ char errStr[1024];
+ ssize_t r;
+ int numCharsRead;
+ char *newptr;
+
+ numCharsRead = 0;
+ do {
+ if(pWrkrData->maxLenRespBuf < numCharsRead + 256) { /* 256 to permit at least a decent read */
+ pWrkrData->maxLenRespBuf += 4096;
+ if((newptr = realloc(pWrkrData->respBuf, pWrkrData->maxLenRespBuf)) == NULL) {
+ DBGPRINTF("mmexternal: error realloc responseBuf: %s\n",
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ /* emergency - fake no update */
+ strcpy(pWrkrData->respBuf, "{}\n");
+ numCharsRead = 3;
+ break;
+ }
+ pWrkrData->respBuf = newptr;
+ }
+ r = read(pWrkrData->fdPipeIn, pWrkrData->respBuf+numCharsRead,
+ pWrkrData->maxLenRespBuf-numCharsRead-1);
+ if(r > 0) {
+ numCharsRead += r;
+ pWrkrData->respBuf[numCharsRead] = '\0'; /* space reserved in read! */
+ } else {
+ /* emergency - fake no update */
+ strcpy(pWrkrData->respBuf, "{}\n");
+ numCharsRead = 3;
+ }
+ if(Debug && r == -1) {
+ DBGPRINTF("mmexternal: error reading from external program: %s\n",
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+ } while(pWrkrData->respBuf[numCharsRead-1] != '\n');
+
+ writeOutputDebug(pWrkrData, pWrkrData->respBuf, numCharsRead);
+ /* strip LF, which is not part of the JSON message but framing */
+ pWrkrData->respBuf[numCharsRead-1] = '\0';
+ iRet = MsgSetPropsViaJSON(pMsg, (uchar*)pWrkrData->respBuf);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "mmexternal: invalid reply '%s' from program '%s'",
+ pWrkrData->respBuf, pWrkrData->pData->szBinary);
+ }
+
+ return;
+}
+
+
+
+/* execute the child process (must be called in child context
+ * after fork).
+ * Note: all output will go to std[err/out] of the **child**, so
+ * rsyslog will never see it except as script output. Do NOT
+ * use dbgprintf() or LogError() and friends.
+ */
+static void __attribute__((noreturn))
+execBinary(wrkrInstanceData_t *pWrkrData, const int fdStdin, const int fdStdOutErr)
+{
+ int i;
+ struct sigaction sigAct;
+ sigset_t set;
+ char *newenviron[] = { NULL };
+
+ if(dup2(fdStdin, STDIN_FILENO) == -1) {
+ perror("mmexternal: dup() stdin failed\n");
+ }
+ if(dup2(fdStdOutErr, STDOUT_FILENO) == -1) {
+ perror("mmexternal: dup() stdout failed\n");
+ }
+ if(dup2(fdStdOutErr, STDERR_FILENO) == -1) {
+ perror("mmexternal: dup() stderr failed\n");
+ }
+
+ /* we close all file handles as we fork soon
+ * Is there a better way to do this? - mail me! rgerhards@adiscon.com
+ */
+# ifndef VALGRIND /* we can not use this with valgrind - too many errors... */
+ for(i = 3 ; i <= 65535 ; ++i)
+ close(i);
+# endif
+
+ /* reset signal handlers to default */
+ memset(&sigAct, 0, sizeof(sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = SIG_DFL;
+ for(i = 1 ; i < NSIG ; ++i)
+ sigaction(i, &sigAct, NULL);
+ /* we need to block SIGINT, otherwise the external program is cancelled when we are
+ * stopped in debug mode.
+ */
+ sigAct.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &sigAct, NULL);
+ sigemptyset(&set);
+ sigprocmask(SIG_SETMASK, &set, NULL);
+
+ alarm(0);
+
+ /* finally exec child */
+ execve((char*)pWrkrData->pData->szBinary, pWrkrData->pData->aParams, newenviron);
+
+ /* we should never reach this point, but if we do, we complain and terminate */
+ char errstr[1024];
+ char errbuf[2048];
+ rs_strerror_r(errno, errstr, sizeof(errstr));
+ errstr[sizeof(errstr)-1] = '\0';
+ const size_t lenbuf = snprintf(errbuf, sizeof(errbuf),
+ "mmexternal: failed to execute binary '%s': %s\n",
+ pWrkrData->pData->szBinary, errstr);
+ errbuf[sizeof(errbuf)-1] = '\0';
+ if(write(2, errbuf, lenbuf) != (ssize_t) lenbuf) {
+ /* just keep static analyzers happy... */
+ exit(2);
+ }
+ exit(1);
+}
+
+
+/* creates a pipe and starts program, uses pipe as stdin for program.
+ * rgerhards, 2009-04-01
+ */
+static rsRetVal
+openPipe(wrkrInstanceData_t *pWrkrData)
+{
+ int pipestdin[2];
+ int pipestdout[2];
+ pid_t cpid;
+ DEFiRet;
+
+ if(pipe(pipestdin) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+ if(pipe(pipestdout) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ DBGPRINTF("mmexternal: executing program '%s' with '%d' parameters\n",
+ pWrkrData->pData->szBinary, pWrkrData->pData->iParams);
+
+ /* final sanity check */
+ assert(pWrkrData->pData->szBinary != NULL);
+ assert(pWrkrData->pData->aParams != NULL);
+
+ /* NO OUTPUT AFTER FORK! */
+ cpid = fork();
+ if(cpid == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_FORK);
+ }
+ pWrkrData->pid = cpid;
+
+ if(cpid == 0) {
+ /* we are now the child, just exec the binary. */
+ close(pipestdin[1]); /* close those pipe "ports" that */
+ close(pipestdout[0]); /* we don't need */
+ execBinary(pWrkrData, pipestdin[0], pipestdout[1]);
+ /*NO CODE HERE - WILL NEVER BE REACHED!*/
+ }
+
+ DBGPRINTF("mmexternal: child has pid %d\n", (int) cpid);
+ pWrkrData->fdPipeIn = dup(pipestdout[0]);
+ close(pipestdin[0]);
+ close(pipestdout[1]);
+ pWrkrData->pid = cpid;
+ pWrkrData->fdPipeOut = pipestdin[1];
+ pWrkrData->bIsRunning = 1;
+finalize_it:
+ RETiRet;
+}
+
+
+/* clean up after a terminated child
+ */
+static rsRetVal
+cleanup(wrkrInstanceData_t *pWrkrData)
+{
+ int status;
+ int ret;
+ DEFiRet;
+
+ assert(pWrkrData->bIsRunning == 1);
+ ret = waitpid(pWrkrData->pid, &status, 0);
+
+ /* waitpid will fail with errno == ECHILD if the child process has already
+ been reaped by the rsyslogd main loop (see rsyslogd.c) */
+ if(ret == pWrkrData->pid) {
+ glblReportChildProcessExit(runConf, pWrkrData->pData->szBinary, pWrkrData->pid, status);
+ }
+
+ if(pWrkrData->fdOutput != -1) {
+ close(pWrkrData->fdOutput);
+ pWrkrData->fdOutput = -1;
+ }
+ if(pWrkrData->fdPipeIn != -1) {
+ close(pWrkrData->fdPipeIn);
+ pWrkrData->fdPipeIn = -1;
+ }
+ if(pWrkrData->fdPipeOut != -1) {
+ close(pWrkrData->fdPipeOut);
+ pWrkrData->fdPipeOut = -1;
+ }
+ pWrkrData->bIsRunning = 0;
+ pWrkrData->bIsRunning = 0;
+ RETiRet;
+}
+
+
+/* try to restart the binary when it has stopped.
+ */
+static rsRetVal
+tryRestart(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ assert(pWrkrData->bIsRunning == 0);
+
+ iRet = openPipe(pWrkrData);
+ RETiRet;
+}
+
+/* write to pipe
+ * note that we do not try to run block-free. If the users fears something
+ * may block (and this not be acceptable), the action should be run on its
+ * own action queue.
+ */
+static rsRetVal
+callExtProg(wrkrInstanceData_t *__restrict__ const pWrkrData, smsg_t *__restrict__ const pMsg)
+{
+ int lenWritten;
+ int lenWrite;
+ int writeOffset;
+ int i_iov;
+ struct iovec iov[2];
+ int bFreeInputstr = 1; /* we must only free if it does not point to msg-obj mem! */
+ const uchar *inputstr = NULL; /* string to be processed by external program */
+ DEFiRet;
+
+ if(pWrkrData->pData->inputProp == INPUT_MSG) {
+ inputstr = getMSG(pMsg);
+ lenWrite = getMSGLen(pMsg);
+ bFreeInputstr = 0;
+ } else if(pWrkrData->pData->inputProp == INPUT_RAWMSG) {
+ getRawMsg(pMsg, (uchar**)&inputstr, &lenWrite);
+ bFreeInputstr = 0;
+ } else {
+ inputstr = msgGetJSONMESG(pMsg);
+ lenWrite = strlen((const char*)inputstr);
+ }
+
+ writeOffset = 0;
+ do {
+ DBGPRINTF("mmexternal: writing to prog (fd %d, offset %d): %s\n",
+ pWrkrData->fdPipeOut, (int) writeOffset, inputstr);
+ i_iov = 0;
+ if(writeOffset < lenWrite) {
+ iov[0].iov_base = (char*)inputstr+writeOffset;
+ iov[0].iov_len = lenWrite - writeOffset;
+ ++i_iov;
+ }
+ iov[i_iov].iov_base = (void*)"\n";
+ iov[i_iov].iov_len = 1;
+ lenWritten = writev(pWrkrData->fdPipeOut, iov, i_iov+1);
+ if(lenWritten == -1) {
+ switch(errno) {
+ case EPIPE:
+ LogMsg(0, RS_RET_ERR_WRITE_PIPE, LOG_WARNING,
+ "mmexternal: program '%s' (pid %ld) terminated; will be restarted",
+ pWrkrData->pData->szBinary, (long) pWrkrData->pid);
+ CHKiRet(cleanup(pWrkrData));
+ CHKiRet(tryRestart(pWrkrData));
+ writeOffset = 0;
+ break;
+ default:
+ LogError(errno, RS_RET_ERR_WRITE_PIPE, "mmexternal: error sending message to program");
+ ABORT_FINALIZE(RS_RET_ERR_WRITE_PIPE);
+ break;
+ }
+ } else {
+ writeOffset += lenWritten;
+ }
+ } while(lenWritten != lenWrite+1);
+
+ processProgramReply(pWrkrData, pMsg);
+
+finalize_it:
+ /* we need to free json input strings, only. All others point to memory
+ * inside the msg object, which is destroyed when the msg is destroyed.
+ */
+ if(bFreeInputstr) {
+ free((void*)inputstr);
+ }
+ RETiRet;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ if(pData->bForceSingleInst)
+ pthread_mutex_lock(&pData->mut);
+ if(pWrkrData->bIsRunning == 0) {
+ openPipe(pWrkrData);
+ }
+
+ iRet = callExtProg(pWrkrData, pMsg);
+
+ if(iRet != RS_RET_OK)
+ iRet = RS_RET_SUSPENDED;
+ if(pData->bForceSingleInst)
+ pthread_mutex_unlock(&pData->mut);
+ENDdoAction
+
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->szBinary = NULL;
+ pData->aParams = NULL;
+ pData->outputFileName = NULL;
+ pData->iParams = 0;
+ pData->bForceSingleInst = 0;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ const char *cstr = NULL;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "binary")) {
+ CHKiRet(split_binary_parameters(&pData->szBinary, &pData->aParams, &pData->iParams,
+ pvals[i].val.d.estr));
+ } else if(!strcmp(actpblk.descr[i].name, "output")) {
+ pData->outputFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "forcesingleinstance")) {
+ pData->bForceSingleInst = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "interface.input")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcmp(cstr, "msg"))
+ pData->inputProp = INPUT_MSG;
+ else if(!strcmp(cstr, "rawmsg"))
+ pData->inputProp = INPUT_RAWMSG;
+ else if(!strcmp(cstr, "fulljson"))
+ pData->inputProp = INPUT_JSON;
+ else {
+ LogError(0, RS_RET_INVLD_INTERFACE_INPUT,
+ "mmexternal: invalid interface.input parameter '%s'",
+ cstr);
+ ABORT_FINALIZE(RS_RET_INVLD_INTERFACE_INPUT);
+ }
+ } else {
+ DBGPRINTF("mmexternal: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ DBGPRINTF("mmexternal: bForceSingleInst %d\n", pData->bForceSingleInst);
+ DBGPRINTF("mmexternal: interface.input '%s', mode %d\n", cstr, pData->inputProp);
+CODE_STD_FINALIZERnewActInst
+ free((void*)cstr);
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(cs.szBinary);
+ cs.szBinary = NULL;
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
diff --git a/plugins/mmfields/Makefile.am b/plugins/mmfields/Makefile.am
new file mode 100644
index 0000000..08170d5
--- /dev/null
+++ b/plugins/mmfields/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmfields.la
+
+mmfields_la_SOURCES = mmfields.c
+mmfields_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmfields_la_LDFLAGS = -module -avoid-version
+mmfields_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmfields/Makefile.in b/plugins/mmfields/Makefile.in
new file mode 100644
index 0000000..faf99c3
--- /dev/null
+++ b/plugins/mmfields/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmfields
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmfields_la_DEPENDENCIES =
+am_mmfields_la_OBJECTS = mmfields_la-mmfields.lo
+mmfields_la_OBJECTS = $(am_mmfields_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 =
+mmfields_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmfields_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmfields_la-mmfields.Plo
+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 = $(mmfields_la_SOURCES)
+DIST_SOURCES = $(mmfields_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmfields.la
+mmfields_la_SOURCES = mmfields.c
+mmfields_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmfields_la_LDFLAGS = -module -avoid-version
+mmfields_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmfields/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmfields/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmfields.la: $(mmfields_la_OBJECTS) $(mmfields_la_DEPENDENCIES) $(EXTRA_mmfields_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmfields_la_LINK) -rpath $(pkglibdir) $(mmfields_la_OBJECTS) $(mmfields_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmfields_la-mmfields.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmfields_la-mmfields.lo: mmfields.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmfields_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmfields_la-mmfields.lo -MD -MP -MF $(DEPDIR)/mmfields_la-mmfields.Tpo -c -o mmfields_la-mmfields.lo `test -f 'mmfields.c' || echo '$(srcdir)/'`mmfields.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmfields_la-mmfields.Tpo $(DEPDIR)/mmfields_la-mmfields.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmfields.c' object='mmfields_la-mmfields.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) $(mmfields_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmfields_la-mmfields.lo `test -f 'mmfields.c' || echo '$(srcdir)/'`mmfields.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmfields_la-mmfields.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmfields_la-mmfields.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmfields/mmfields.c b/plugins/mmfields/mmfields.c
new file mode 100644
index 0000000..f407864
--- /dev/null
+++ b/plugins/mmfields/mmfields.c
@@ -0,0 +1,275 @@
+/* mmfields.c
+ * Parse all fields of the message into structured data inside the
+ * JSON tree.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmfields")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+/* define operation modes we have */
+#define SIMPLE_MODE 0 /* just overwrite */
+#define REWRITE_MODE 1 /* rewrite IP address, canoninized */
+typedef struct _instanceData {
+ char separator;
+ uchar *jsonRoot; /**< container where to store fields */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "separator", eCmdHdlrGetChar, 0 },
+ { "jsonroot", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->jsonRoot);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->separator = ',';
+ pData->jsonRoot = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmfields)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "separator")) {
+ pData->separator = es_getBufAddr(pvals[i].val.d.estr)[0];
+ } else if(!strcmp(actpblk.descr[i].name, "jsonroot")) {
+ pData->jsonRoot = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("mmfields: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ if(pData->jsonRoot == NULL) {
+ CHKmalloc(pData->jsonRoot = (uchar*) strdup("!"));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static rsRetVal
+extractField(instanceData *pData, uchar *msgtext, int lenMsg, int *curridx, uchar *fieldbuf)
+{
+ int i, j;
+ DEFiRet;
+ i = *curridx;
+ j = 0;
+ while(i < lenMsg && msgtext[i] != pData->separator) {
+ fieldbuf[j++] = msgtext[i++];
+ }
+ fieldbuf[j] = '\0';
+ if(i < lenMsg)
+ ++i;
+ *curridx = i;
+
+ RETiRet;
+}
+
+
+static rsRetVal
+parse_fields(instanceData *pData, smsg_t *pMsg, uchar *msgtext, int lenMsg)
+{
+ uchar fieldbuf[32*1024];
+ uchar fieldname[512];
+ struct json_object *json;
+ struct json_object *jval;
+ int field;
+ uchar *buf;
+ int currIdx = 0;
+ DEFiRet;
+
+ if(lenMsg < (int) sizeof(fieldbuf)) {
+ buf = fieldbuf;
+ } else {
+ CHKmalloc(buf = malloc(lenMsg+1));
+ }
+
+ json = json_object_new_object();
+ if(json == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ field = 1;
+ while(currIdx < lenMsg) {
+ CHKiRet(extractField(pData, msgtext, lenMsg, &currIdx, buf));
+ DBGPRINTF("mmfields: field %d: '%s'\n", field, buf);
+ snprintf((char*)fieldname, sizeof(fieldname), "f%d", field);
+ fieldname[sizeof(fieldname)-1] = '\0';
+ jval = json_object_new_string((char*)buf);
+ json_object_object_add(json, (char*)fieldname, jval);
+ field++;
+ }
+ msgAddJSON(pMsg, pData->jsonRoot, json, 0, 0);
+finalize_it:
+ if(buf != fieldbuf)
+ free(buf);
+ RETiRet;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *msg;
+ int lenMsg;
+CODESTARTdoAction
+ lenMsg = getMSGLen(pMsg);
+ msg = getMSG(pMsg);
+ iRet = parse_fields(pWrkrData->pData, pMsg, msg, lenMsg);
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmfields: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmjsonparse/Makefile.am b/plugins/mmjsonparse/Makefile.am
new file mode 100644
index 0000000..f16469d
--- /dev/null
+++ b/plugins/mmjsonparse/Makefile.am
@@ -0,0 +1,14 @@
+pkglib_LTLIBRARIES = mmjsonparse.la
+
+if OS_AIX
+LIBMATH = -lm
+else
+LIBMATH =
+endif
+
+mmjsonparse_la_SOURCES = mmjsonparse.c
+mmjsonparse_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmjsonparse_la_LDFLAGS = -module -avoid-version $(LIBFASTJSON_LIBS) $(LIBMATH)
+mmjsonparse_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmjsonparse/Makefile.in b/plugins/mmjsonparse/Makefile.in
new file mode 100644
index 0000000..eb4a976
--- /dev/null
+++ b/plugins/mmjsonparse/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmjsonparse
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmjsonparse_la_DEPENDENCIES =
+am_mmjsonparse_la_OBJECTS = mmjsonparse_la-mmjsonparse.lo
+mmjsonparse_la_OBJECTS = $(am_mmjsonparse_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 =
+mmjsonparse_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmjsonparse_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmjsonparse_la-mmjsonparse.Plo
+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 = $(mmjsonparse_la_SOURCES)
+DIST_SOURCES = $(mmjsonparse_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmjsonparse.la
+@OS_AIX_FALSE@LIBMATH =
+@OS_AIX_TRUE@LIBMATH = -lm
+mmjsonparse_la_SOURCES = mmjsonparse.c
+mmjsonparse_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmjsonparse_la_LDFLAGS = -module -avoid-version $(LIBFASTJSON_LIBS) $(LIBMATH)
+mmjsonparse_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmjsonparse/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmjsonparse/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmjsonparse.la: $(mmjsonparse_la_OBJECTS) $(mmjsonparse_la_DEPENDENCIES) $(EXTRA_mmjsonparse_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmjsonparse_la_LINK) -rpath $(pkglibdir) $(mmjsonparse_la_OBJECTS) $(mmjsonparse_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmjsonparse_la-mmjsonparse.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmjsonparse_la-mmjsonparse.lo: mmjsonparse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmjsonparse_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmjsonparse_la-mmjsonparse.lo -MD -MP -MF $(DEPDIR)/mmjsonparse_la-mmjsonparse.Tpo -c -o mmjsonparse_la-mmjsonparse.lo `test -f 'mmjsonparse.c' || echo '$(srcdir)/'`mmjsonparse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmjsonparse_la-mmjsonparse.Tpo $(DEPDIR)/mmjsonparse_la-mmjsonparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmjsonparse.c' object='mmjsonparse_la-mmjsonparse.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) $(mmjsonparse_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmjsonparse_la-mmjsonparse.lo `test -f 'mmjsonparse.c' || echo '$(srcdir)/'`mmjsonparse.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmjsonparse_la-mmjsonparse.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmjsonparse_la-mmjsonparse.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmjsonparse/mmjsonparse.c b/plugins/mmjsonparse/mmjsonparse.c
new file mode 100644
index 0000000..09430ec
--- /dev/null
+++ b/plugins/mmjsonparse/mmjsonparse.c
@@ -0,0 +1,403 @@
+/* mmjsonparse.c
+ * This is a message modification module. If give, it extracts JSON data
+ * and populates the EE event structure with it.
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * File begun on 2012-02-20 by RGerhards
+ *
+ * Copyright 2012-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <json.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "parserif.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmjsonparse")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ sbool bUseRawMsg; /**< use %rawmsg% instead of %msg% */
+ char *cookie;
+ uchar *container;
+ int lenCookie;
+ /* REMOVE dummy when real data items are to be added! */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ struct json_tokener *tokener;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "cookie", eCmdHdlrString, 0 },
+ { "container", eCmdHdlrString, 0 },
+ { "userawmsg", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ CHKmalloc(pData->container = (uchar*)strdup("!"));
+ CHKmalloc(pData->cookie = strdup(CONST_CEE_COOKIE));
+ pData->lenCookie = CONST_LEN_CEE_COOKIE;
+finalize_it:
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->tokener = json_tokener_new();
+ if(pWrkrData->tokener == NULL) {
+ LogError(0, RS_RET_ERR, "error: could not create json "
+ "tokener, cannot activate instance");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->cookie);
+ free(pData->container);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if(pWrkrData->tokener != NULL)
+ json_tokener_free(pWrkrData->tokener);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("mmjsonparse\n");
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static rsRetVal
+processJSON(wrkrInstanceData_t *pWrkrData, smsg_t *pMsg, char *buf, size_t lenBuf)
+{
+ struct json_object *json;
+ const char *errMsg;
+ DEFiRet;
+
+ assert(pWrkrData->tokener != NULL);
+ DBGPRINTF("mmjsonparse: toParse: '%s'\n", buf);
+ json_tokener_reset(pWrkrData->tokener);
+
+ json = json_tokener_parse_ex(pWrkrData->tokener, buf, lenBuf);
+ if(Debug) {
+ errMsg = NULL;
+ if(json == NULL) {
+ enum json_tokener_error err;
+
+ err = pWrkrData->tokener->err;
+ if(err != json_tokener_continue)
+ errMsg = json_tokener_error_desc(err);
+ else
+ errMsg = "Unterminated input";
+ } else if((size_t)pWrkrData->tokener->char_offset < lenBuf)
+ errMsg = "Extra characters after JSON object";
+ else if(!json_object_is_type(json, json_type_object))
+ errMsg = "JSON value is not an object";
+ if(errMsg != NULL) {
+ DBGPRINTF("mmjsonparse: Error parsing JSON '%s': %s\n",
+ buf, errMsg);
+ }
+ }
+ if(json == NULL
+ || ((size_t)pWrkrData->tokener->char_offset < lenBuf)
+ || (!json_object_is_type(json, json_type_object))) {
+ if(json != NULL) {
+ /* Release json object as we are not going to add it to pMsg */
+ json_object_put(json);
+ }
+ ABORT_FINALIZE(RS_RET_NO_CEE_MSG);
+ }
+
+ msgAddJSON(pMsg, pWrkrData->pData->container, json, 0, 0);
+finalize_it:
+ RETiRet;
+}
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *buf;
+ rs_size_t len;
+ int bSuccess = 0;
+ struct json_object *jval;
+ struct json_object *json;
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ /* note that we can performance-optimize the interface, but this also
+ * requires changes to the libraries. For now, we accept message
+ * duplication. -- rgerhards, 2010-12-01
+ */
+ if(pWrkrData->pData->bUseRawMsg)
+ getRawMsg(pMsg, &buf, &len);
+ else
+ buf = getMSG(pMsg);
+
+ while(*buf && isspace(*buf)) {
+ ++buf;
+ }
+
+ if(*buf == '\0' || strncmp((char*)buf, pData->cookie, pData->lenCookie)) {
+ DBGPRINTF("mmjsonparse: no JSON cookie: '%s'\n", buf);
+ ABORT_FINALIZE(RS_RET_NO_CEE_MSG);
+ }
+ buf += pData->lenCookie;
+ CHKiRet(processJSON(pWrkrData, pMsg, (char*) buf, strlen((char*)buf)));
+ bSuccess = 1;
+finalize_it:
+ if(iRet == RS_RET_NO_CEE_MSG) {
+ /* add buf as msg */
+ json = json_object_new_object();
+ jval = json_object_new_string((char*)buf);
+ json_object_object_add(json, "msg", jval);
+ msgAddJSON(pMsg, pData->container, json, 0, 0);
+ iRet = RS_RET_OK;
+ }
+ MsgSetParseSuccess(pMsg, bSuccess);
+ENDdoAction
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->bUseRawMsg = 0;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmjsonparse)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "cookie")) {
+ free(pData->cookie);
+ pData->cookie = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "container")) {
+ free(pData->container);
+ size_t lenvar = es_strlen(pvals[i].val.d.estr);
+ pData->container = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pData->container[0] == '$') {
+ /* pre 8.35, the container name needed to be specified without
+ * the leading $. This was confusing, so we now require a full
+ * variable name. Nevertheless, we still need to support the
+ * version without $. -- rgerhards, 2018-05-16
+ */
+ /* copy lenvar size because of \0 string terminator */
+ memmove(pData->container, pData->container+1, lenvar);
+ --lenvar;
+ }
+ if( (lenvar == 0)
+ || ( !( pData->container[0] == '!'
+ || pData->container[0] == '.'
+ || pData->container[0] == '/' ) )
+ ) {
+ parser_errmsg("mmjsonparse: invalid container name '%s', name must "
+ "start with either '$!', '$.', or '$/'", pData->container);
+ ABORT_FINALIZE(RS_RET_INVALID_VAR);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "userawmsg")) {
+ pData->bUseRawMsg = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("mmjsonparse: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->container == NULL)
+ CHKmalloc(pData->container = (uchar*) strdup("!"));
+ pData->lenCookie = strlen(pData->cookie);
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":mmjsonparse:", sizeof(":mmjsonparse:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":mmjsonparse:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ /* we call the function below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat");
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported;
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmjsonparse: module compiled with rsyslog version %s.\n", VERSION);
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("mmjsonparse: msg-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/mmnormalize/Makefile.am b/plugins/mmnormalize/Makefile.am
new file mode 100644
index 0000000..6376248
--- /dev/null
+++ b/plugins/mmnormalize/Makefile.am
@@ -0,0 +1,14 @@
+pkglib_LTLIBRARIES = mmnormalize.la
+
+if OS_AIX
+LIBMATH=-lm
+else
+LIBMATH=
+endif
+
+mmnormalize_la_SOURCES = mmnormalize.c
+mmnormalize_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGNORM_CFLAGS)
+mmnormalize_la_LDFLAGS = -module -avoid-version $(LIBLOGNORM_LIBS) $(LIBMATH)
+mmnormalize_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmnormalize/Makefile.in b/plugins/mmnormalize/Makefile.in
new file mode 100644
index 0000000..aa0da14
--- /dev/null
+++ b/plugins/mmnormalize/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmnormalize
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmnormalize_la_DEPENDENCIES =
+am_mmnormalize_la_OBJECTS = mmnormalize_la-mmnormalize.lo
+mmnormalize_la_OBJECTS = $(am_mmnormalize_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 =
+mmnormalize_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmnormalize_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmnormalize_la-mmnormalize.Plo
+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 = $(mmnormalize_la_SOURCES)
+DIST_SOURCES = $(mmnormalize_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmnormalize.la
+@OS_AIX_FALSE@LIBMATH =
+@OS_AIX_TRUE@LIBMATH = -lm
+mmnormalize_la_SOURCES = mmnormalize.c
+mmnormalize_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGNORM_CFLAGS)
+mmnormalize_la_LDFLAGS = -module -avoid-version $(LIBLOGNORM_LIBS) $(LIBMATH)
+mmnormalize_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmnormalize/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmnormalize/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmnormalize.la: $(mmnormalize_la_OBJECTS) $(mmnormalize_la_DEPENDENCIES) $(EXTRA_mmnormalize_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmnormalize_la_LINK) -rpath $(pkglibdir) $(mmnormalize_la_OBJECTS) $(mmnormalize_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmnormalize_la-mmnormalize.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmnormalize_la-mmnormalize.lo: mmnormalize.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmnormalize_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmnormalize_la-mmnormalize.lo -MD -MP -MF $(DEPDIR)/mmnormalize_la-mmnormalize.Tpo -c -o mmnormalize_la-mmnormalize.lo `test -f 'mmnormalize.c' || echo '$(srcdir)/'`mmnormalize.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmnormalize_la-mmnormalize.Tpo $(DEPDIR)/mmnormalize_la-mmnormalize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmnormalize.c' object='mmnormalize_la-mmnormalize.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) $(mmnormalize_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmnormalize_la-mmnormalize.lo `test -f 'mmnormalize.c' || echo '$(srcdir)/'`mmnormalize.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmnormalize_la-mmnormalize.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmnormalize_la-mmnormalize.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmnormalize/mmnormalize.c b/plugins/mmnormalize/mmnormalize.c
new file mode 100644
index 0000000..db69ebb
--- /dev/null
+++ b/plugins/mmnormalize/mmnormalize.c
@@ -0,0 +1,551 @@
+/* mmnormalize.c
+ * This is a message modification module. It normalizes the input message with
+ * the help of liblognorm. The message's JSON variables are updated.
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * File begun on 2010-01-01 by RGerhards
+ *
+ * Copyright 2010-2015 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <libestr.h>
+#include <json.h>
+#include <liblognorm.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "dirty.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmnormalize")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+static struct cnfparamdescr modpdescr[] = {
+ { "allowregex", eCmdHdlrBinary, 0 }
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+typedef struct _instanceData {
+ sbool bUseRawMsg; /**< use %rawmsg% instead of %msg% */
+ uchar *rule; /* rule to use */
+ uchar *rulebase; /**< name of rulebase to use */
+ ln_ctx ctxln; /**< context to be used for liblognorm */
+ char *pszPath; /**< path of normalized data */
+ msgPropDescr_t *varDescr;/**< name of variable to use */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar *rulebase; /**< name of normalization rulebase to use */
+ uchar *rule;
+ int bUseRawMsg; /**< use %rawmsg% instead of %msg% */
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "rulebase", eCmdHdlrGetWord, 0 },
+ { "rule", eCmdHdlrArray, 0 },
+ { "path", eCmdHdlrGetWord, 0 },
+ { "userawmsg", eCmdHdlrBinary, 0 },
+ { "variable", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ int allow_regex;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* callback for liblognorm error messages */
+static void
+errCallBack(void __attribute__((unused)) *cookie, const char *msg,
+ size_t __attribute__((unused)) lenMsg)
+{
+ LogError(0, RS_RET_ERR_LIBLOGNORM, "liblognorm error: %s", msg);
+}
+
+/* to be called to build the liblognorm part of the instance ONCE ALL PARAMETERS ARE CORRECT
+ * (and set within pData!).
+ */
+static rsRetVal
+buildInstance(instanceData *pData)
+{
+ DEFiRet;
+ if((pData->ctxln = ln_initCtx()) == NULL) {
+ LogError(0, RS_RET_ERR_LIBLOGNORM_INIT, "error: could not initialize "
+ "liblognorm ctx, cannot activate action");
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_INIT);
+ }
+ ln_setCtxOpts(pData->ctxln, loadModConf->allow_regex);
+ ln_setErrMsgCB(pData->ctxln, errCallBack, NULL);
+ if(pData->rule !=NULL && pData->rulebase == NULL) {
+ if(ln_loadSamplesFromString(pData->ctxln, (char*) pData->rule) !=0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rule '%s' "
+ "could not be loaded cannot activate action", pData->rule);
+ ln_exitCtx(pData->ctxln);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ free(pData->rule);
+ pData->rule = NULL;
+ } else if(pData->rule ==NULL && pData->rulebase != NULL) {
+ if(ln_loadSamples(pData->ctxln, (char*) pData->rulebase) != 0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' "
+ "could not be loaded cannot activate action", pData->rulebase);
+ ln_exitCtx(pData->ctxln);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.rulebase);
+ free(cs.rule);
+ cs.rulebase = NULL;
+ cs.rule = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->rulebase);
+ free(pData->rule);
+ ln_exitCtx(pData->ctxln);
+ free(pData->pszPath);
+ msgPropDescrDestruct(pData->varDescr);
+ free(pData->varDescr);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("mmnormalize\n");
+ dbgprintf("\tvariable='%s'\n", pData->varDescr->name);
+ dbgprintf("\trulebase='%s'\n", pData->rulebase);
+ dbgprintf("\trule='%s'\n", pData->rule);
+ dbgprintf("\tpath='%s'\n", pData->pszPath);
+ dbgprintf("\tbUseRawMsg='%d'\n", pData->bUseRawMsg);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *buf;
+ rs_size_t len;
+ int r;
+ struct json_object *json = NULL;
+ unsigned short freeBuf = 0;
+CODESTARTdoAction
+ if(pWrkrData->pData->bUseRawMsg) {
+ getRawMsg(pMsg, &buf, &len);
+ } else if (pWrkrData->pData->varDescr) {
+ buf = MsgGetProp(pMsg, NULL, pWrkrData->pData->varDescr, &len, &freeBuf, NULL);
+ } else {
+ buf = getMSG(pMsg);
+ len = getMSGLen(pMsg);
+ }
+ r = ln_normalize(pWrkrData->pData->ctxln, (char*)buf, len, &json);
+ if (freeBuf) {
+ free(buf);
+ buf = NULL;
+ }
+ if(r != 0) {
+ DBGPRINTF("error %d during ln_normalize\n", r);
+ MsgSetParseSuccess(pMsg, 0);
+ } else {
+ MsgSetParseSuccess(pMsg, 1);
+ }
+
+ msgAddJSON(pMsg, (uchar*)pWrkrData->pData->pszPath + 1, json, 0, 0);
+
+ENDdoAction
+
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->rulebase = NULL;
+ pData->rule = NULL;
+ pData->bUseRawMsg = 0;
+ pData->pszPath = strdup("$!");
+ pData->varDescr = NULL;
+}
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "mmnormalize: error processing module "
+ "config parameters missing [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for mmnormalize:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "allowregex")) {
+ loadModConf->allow_regex = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("mmnormalize: program error, non-handled "
+ "param '%s' in setModCnf\n", modpblk.descr[i].name);
+ }
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int bDestructPValsOnExit;
+ char *cstr;
+ char *varName = NULL;
+ char *buffer;
+ char *tStr;
+ int size = 0;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmnormalize)\n");
+
+ bDestructPValsOnExit = 0;
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "mmnormalize: error reading "
+ "config parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ bDestructPValsOnExit = 1;
+
+ if(Debug) {
+ dbgprintf("action param blk in mmnormalize:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "rulebase")) {
+ pData->rulebase = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "rule")) {
+ for(int j=0; j < pvals[i].val.d.ar->nmemb; ++j) {
+ tStr = (char*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ size += strlen(tStr);
+ free(tStr);
+ }
+ buffer = malloc(size + pvals[i].val.d.ar->nmemb + 1);
+ tStr = (char*)es_str2cstr(pvals[i].val.d.ar->arr[0], NULL);
+ strcpy(buffer, tStr);
+ free(tStr);
+ strcat(buffer, "\n");
+ for(int j=1; j < pvals[i].val.d.ar->nmemb; ++j) {
+ tStr = (char*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ strcat(buffer, tStr);
+ free(tStr);
+ strcat(buffer, "\n");
+ }
+ strcat(buffer, "\0");
+ pData->rule = (uchar*)buffer;
+ } else if(!strcmp(actpblk.descr[i].name, "userawmsg")) {
+ pData->bUseRawMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "variable")) {
+ varName = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "path")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (strlen(cstr) < 2) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmnormalize: valid path name should be at least "
+ "2 symbols long, got %s", cstr);
+ free(cstr);
+ } else if (cstr[0] != '$') {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmnormalize: valid path name should start with $,"
+ "got %s", cstr);
+ free(cstr);
+ } else {
+ free(pData->pszPath);
+ pData->pszPath = cstr;
+ }
+ continue;
+ } else {
+ DBGPRINTF("mmnormalize: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if (varName) {
+ if(pData->bUseRawMsg) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmnormalize: 'variable' param can't be used with 'useRawMsg'. "
+ "Ignoring 'variable', will use raw message.");
+ } else {
+ CHKmalloc(pData->varDescr = malloc(sizeof(msgPropDescr_t)));
+ CHKiRet(msgPropDescrFill(pData->varDescr, (uchar*) varName, strlen(varName)));
+ }
+ free(varName);
+ varName = NULL;
+ }
+ if(!pData->rulebase) {
+ if(!pData->rule) {
+ LogError(0, RS_RET_CONFIG_ERROR, "mmnormalize: rulebase needed. "
+ "Use option rulebase or rule.");
+ }
+ }
+ if(pData->rulebase) {
+ if(pData->rule) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "mmnormalize: only one rulebase possible, rulebase "
+ "can't be used with rule");
+ }
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ iRet = buildInstance(pData);
+CODE_STD_FINALIZERnewActInst
+ if(bDestructPValsOnExit)
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":mmnormalize:", sizeof(":mmnormalize:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ if(cs.rulebase == NULL && cs.rule == NULL) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: no normalization rulebase was specified, use "
+ "$MMNormalizeSampleDB directive first!");
+ ABORT_FINALIZE(RS_RET_NO_RULEBASE);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":mmnormalize:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ pData->rulebase = cs.rulebase;
+ pData->rule = cs.rule;
+ pData->bUseRawMsg = cs.bUseRawMsg;
+ pData->pszPath = strdup("$!"); /* old interface does not support this feature */
+ /* all config vars auto-reset! */
+ cs.bUseRawMsg = 0;
+ cs.rulebase = NULL; /* we used it up! */
+ cs.rule = NULL;
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ /* we call the function below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat"));
+ CHKiRet(buildInstance(pData));
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.rulebase = NULL;
+ cs.rule = NULL;
+ cs.bUseRawMsg = 0;
+ RETiRet;
+}
+
+/* set the rulebase name */
+static rsRetVal
+setRuleBase(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ DEFiRet;
+ cs.rulebase = pszName;
+ pszName = NULL;
+ RETiRet;
+}
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported;
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmnormalize: module compiled with rsyslog version %s.\n", VERSION);
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("mmnormalize: msg-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmnormalizerulebase", 0, eCmdHdlrGetWord,
+ setRuleBase, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmnormalizerule", 0, eCmdHdlrGetWord, NULL,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmnormalizeuserawmsg", 0, eCmdHdlrBinary,
+ NULL, &cs.bUseRawMsg, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/mmpstrucdata/Makefile.am b/plugins/mmpstrucdata/Makefile.am
new file mode 100644
index 0000000..090150a
--- /dev/null
+++ b/plugins/mmpstrucdata/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmpstrucdata.la
+
+mmpstrucdata_la_SOURCES = mmpstrucdata.c
+mmpstrucdata_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmpstrucdata_la_LDFLAGS = -module -avoid-version
+mmpstrucdata_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmpstrucdata/Makefile.in b/plugins/mmpstrucdata/Makefile.in
new file mode 100644
index 0000000..85341e2
--- /dev/null
+++ b/plugins/mmpstrucdata/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmpstrucdata
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmpstrucdata_la_DEPENDENCIES =
+am_mmpstrucdata_la_OBJECTS = mmpstrucdata_la-mmpstrucdata.lo
+mmpstrucdata_la_OBJECTS = $(am_mmpstrucdata_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 =
+mmpstrucdata_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmpstrucdata_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Plo
+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 = $(mmpstrucdata_la_SOURCES)
+DIST_SOURCES = $(mmpstrucdata_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmpstrucdata.la
+mmpstrucdata_la_SOURCES = mmpstrucdata.c
+mmpstrucdata_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmpstrucdata_la_LDFLAGS = -module -avoid-version
+mmpstrucdata_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmpstrucdata/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmpstrucdata/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmpstrucdata.la: $(mmpstrucdata_la_OBJECTS) $(mmpstrucdata_la_DEPENDENCIES) $(EXTRA_mmpstrucdata_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmpstrucdata_la_LINK) -rpath $(pkglibdir) $(mmpstrucdata_la_OBJECTS) $(mmpstrucdata_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmpstrucdata_la-mmpstrucdata.lo: mmpstrucdata.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmpstrucdata_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmpstrucdata_la-mmpstrucdata.lo -MD -MP -MF $(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Tpo -c -o mmpstrucdata_la-mmpstrucdata.lo `test -f 'mmpstrucdata.c' || echo '$(srcdir)/'`mmpstrucdata.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Tpo $(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmpstrucdata.c' object='mmpstrucdata_la-mmpstrucdata.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) $(mmpstrucdata_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmpstrucdata_la-mmpstrucdata.lo `test -f 'mmpstrucdata.c' || echo '$(srcdir)/'`mmpstrucdata.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmpstrucdata_la-mmpstrucdata.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmpstrucdata/mmpstrucdata.c b/plugins/mmpstrucdata/mmpstrucdata.c
new file mode 100644
index 0000000..5f1ca80
--- /dev/null
+++ b/plugins/mmpstrucdata/mmpstrucdata.c
@@ -0,0 +1,399 @@
+/* mmpstrucdata.c
+ * Parse all fields of the message into structured data inside the
+ * JSON tree.
+ *
+ * Copyright 2013-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmpstrucdata")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ uchar *jsonRoot; /**< container where to store fields */
+ int lowercase_SD_ID;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "jsonroot", eCmdHdlrString, 0 },
+ { "sd_name.lowercase", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->jsonRoot);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->jsonRoot = NULL;
+ pData->lowercase_SD_ID = 1;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmpstrucdata)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "jsonroot")) {
+ size_t lenvar = es_strlen(pvals[i].val.d.estr);
+ pData->jsonRoot = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pData->jsonRoot[0] == '$') {
+ /* pre 8.35, the jsonRoot name needed to be specified without
+ * the leading $. This was confusing, so we now require a full
+ * variable name. Nevertheless, we still need to support the
+ * version without $. -- rgerhards, 2018-05-16
+ */
+ /* copy lenvar size because of \0 string terminator */
+ memmove(pData->jsonRoot, pData->jsonRoot+1, lenvar);
+ --lenvar;
+ }
+ if( (lenvar == 0)
+ || ( !( pData->jsonRoot[0] == '!'
+ || pData->jsonRoot[0] == '.'
+ || pData->jsonRoot[0] == '/' ) )
+ ) {
+ parser_errmsg("mmpstrucdata: invalid jsonRoot name '%s', name must "
+ "start with either '$!', '$.', or '$/'", pData->jsonRoot);
+ ABORT_FINALIZE(RS_RET_INVALID_VAR);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "sd_name.lowercase")) {
+ pData->lowercase_SD_ID = pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "mmpstrucdata: internal program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ if(pData->jsonRoot == NULL) {
+ CHKmalloc(pData->jsonRoot = (uchar*) strdup("!"));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static rsRetVal
+parsePARAM_VALUE(uchar *sdbuf, int lenbuf, int *curridx, uchar *fieldbuf)
+{
+ int i, j;
+ DEFiRet;
+ i = *curridx;
+ j = 0;
+ while(i < lenbuf && sdbuf[i] != '"') {
+ if(sdbuf[i] == '\\') {
+ if(++i == lenbuf) {
+ fieldbuf[j++] = '\\';
+ } else {
+ if(sdbuf[i] == '"') {
+ fieldbuf[j++] = '"';
+ } else if(sdbuf[i] == '\\') {
+ fieldbuf[j++] = '\\';
+ } else if(sdbuf[i] == ']') {
+ fieldbuf[j++] = ']';
+ } else {
+ fieldbuf[j++] = '\\';
+ fieldbuf[j++] = sdbuf[i];
+ }
+ ++i;
+ }
+ } else {
+ fieldbuf[j++] = sdbuf[i++];
+ }
+ }
+ fieldbuf[j] = '\0';
+ *curridx = i;
+ RETiRet;
+}
+
+
+static rsRetVal ATTR_NONNULL()
+parseSD_NAME(instanceData *const pData, uchar *sdbuf, int lenbuf, int *curridx, uchar *namebuf)
+{
+ int i, j;
+ DEFiRet;
+ i = *curridx;
+ for(j = 0 ; i < lenbuf && j < 32; ++j) {
+ if( sdbuf[i] == '=' || sdbuf[i] == '"'
+ || sdbuf[i] == ']' || sdbuf[i] == ' ')
+ break;
+ namebuf[j] = pData->lowercase_SD_ID ? tolower(sdbuf[i]) : sdbuf[i];
+ ++i;
+ }
+ namebuf[j] = '\0';
+ *curridx = i;
+ RETiRet;
+}
+
+
+static rsRetVal ATTR_NONNULL()
+parseSD_PARAM(instanceData *const pData, uchar *sdbuf, int lenbuf, int *curridx, struct json_object *jroot)
+{
+ int i;
+ uchar pName[33];
+ uchar pVal[32*1024];
+ struct json_object *jval;
+ DEFiRet;
+
+ i = *curridx;
+ CHKiRet(parseSD_NAME(pData, sdbuf, lenbuf, &i, pName));
+ if(sdbuf[i] != '=') {
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i;
+ if(sdbuf[i] != '"') {
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i;
+ CHKiRet(parsePARAM_VALUE(sdbuf, lenbuf, &i, pVal));
+ if(sdbuf[i] != '"') {
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i;
+
+ jval = json_object_new_string((char*)pVal);
+ json_object_object_add(jroot, (char*)pName, jval);
+
+ *curridx = i;
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal ATTR_NONNULL()
+parseSD_ELEMENT(instanceData *const pData, uchar *sdbuf, int lenbuf, int *curridx, struct json_object *jroot)
+{
+ int i;
+ uchar sd_id[33];
+ struct json_object *json = NULL;
+ DEFiRet;
+
+ i = *curridx;
+ if(sdbuf[i] != '[') {
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i; /* eat '[' */
+
+ CHKiRet(parseSD_NAME(pData, sdbuf, lenbuf, &i, sd_id));
+ json = json_object_new_object();
+
+ while(i < lenbuf) {
+ if(sdbuf[i] == ']') {
+ break;
+ } else if(sdbuf[i] != ' ') {
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i;
+ while(i < lenbuf && sdbuf[i] == ' ')
+ ++i;
+ CHKiRet(parseSD_PARAM(pData, sdbuf, lenbuf, &i, json));
+ }
+
+ if(sdbuf[i] != ']') {
+ DBGPRINTF("mmpstrucdata: SD-ELEMENT does not terminate with "
+ "']': '%s'\n", sdbuf+i);
+ ABORT_FINALIZE(RS_RET_STRUC_DATA_INVLD);
+ }
+ ++i; /* eat ']' */
+ *curridx = i;
+ json_object_object_add(jroot, (char*)sd_id, json);
+finalize_it:
+ if(iRet != RS_RET_OK && json != NULL)
+ json_object_put(json);
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+parse_sd(instanceData *const pData, smsg_t *const pMsg)
+{
+ struct json_object *json, *jroot;
+ uchar *sdbuf;
+ int lenbuf;
+ int i = 0;
+ DEFiRet;
+
+ json = json_object_new_object();
+ if(json == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ MsgGetStructuredData(pMsg, &sdbuf,&lenbuf);
+ while(i < lenbuf) {
+ CHKiRet(parseSD_ELEMENT(pData, sdbuf, lenbuf, &i, json));
+ }
+
+ jroot = json_object_new_object();
+ if(jroot == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ json_object_object_add(jroot, "rfc5424-sd", json);
+ msgAddJSON(pMsg, pData->jsonRoot, jroot, 0, 0);
+finalize_it:
+ if(iRet != RS_RET_OK && json != NULL)
+ json_object_put(json);
+ RETiRet;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+CODESTARTdoAction
+ DBGPRINTF("mmpstrucdata: enter\n");
+ if(!MsgHasStructuredData(pMsg)) {
+ DBGPRINTF("mmpstrucdata: message does not have structured data\n");
+ FINALIZE;
+ }
+ /* don't check return code - we never want rsyslog to retry
+ * or suspend this action!
+ */
+ parse_sd(pWrkrData->pData, pMsg);
+finalize_it:
+ENDdoAction
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+NO_LEGACY_CONF_parseSelectorAct
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmpstrucdata: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmrm1stspace/Makefile.am b/plugins/mmrm1stspace/Makefile.am
new file mode 100644
index 0000000..47bf462
--- /dev/null
+++ b/plugins/mmrm1stspace/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmrm1stspace.la
+
+mmrm1stspace_la_SOURCES = mmrm1stspace.c
+mmrm1stspace_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmrm1stspace_la_LDFLAGS = -module -avoid-version
+mmrm1stspace_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmrm1stspace/Makefile.in b/plugins/mmrm1stspace/Makefile.in
new file mode 100644
index 0000000..1d6c8b9
--- /dev/null
+++ b/plugins/mmrm1stspace/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmrm1stspace
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmrm1stspace_la_DEPENDENCIES =
+am_mmrm1stspace_la_OBJECTS = mmrm1stspace_la-mmrm1stspace.lo
+mmrm1stspace_la_OBJECTS = $(am_mmrm1stspace_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 =
+mmrm1stspace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmrm1stspace_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Plo
+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 = $(mmrm1stspace_la_SOURCES)
+DIST_SOURCES = $(mmrm1stspace_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmrm1stspace.la
+mmrm1stspace_la_SOURCES = mmrm1stspace.c
+mmrm1stspace_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmrm1stspace_la_LDFLAGS = -module -avoid-version
+mmrm1stspace_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmrm1stspace/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmrm1stspace/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmrm1stspace.la: $(mmrm1stspace_la_OBJECTS) $(mmrm1stspace_la_DEPENDENCIES) $(EXTRA_mmrm1stspace_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmrm1stspace_la_LINK) -rpath $(pkglibdir) $(mmrm1stspace_la_OBJECTS) $(mmrm1stspace_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmrm1stspace_la-mmrm1stspace.lo: mmrm1stspace.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmrm1stspace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmrm1stspace_la-mmrm1stspace.lo -MD -MP -MF $(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Tpo -c -o mmrm1stspace_la-mmrm1stspace.lo `test -f 'mmrm1stspace.c' || echo '$(srcdir)/'`mmrm1stspace.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Tpo $(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmrm1stspace.c' object='mmrm1stspace_la-mmrm1stspace.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) $(mmrm1stspace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmrm1stspace_la-mmrm1stspace.lo `test -f 'mmrm1stspace.c' || echo '$(srcdir)/'`mmrm1stspace.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmrm1stspace_la-mmrm1stspace.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmrm1stspace/mmrm1stspace.c b/plugins/mmrm1stspace/mmrm1stspace.c
new file mode 100644
index 0000000..b40d111
--- /dev/null
+++ b/plugins/mmrm1stspace/mmrm1stspace.c
@@ -0,0 +1,178 @@
+/* mmrm1stspace.c
+ * removes leading space inside the syslog message part
+ *
+ * Copyright 2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmrm1stspace")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+/* define operation modes we have */
+typedef struct _instanceData {
+ int dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+BEGINnewActInst
+CODESTARTnewActInst
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+CODE_STD_FINALIZERnewActInst
+ENDnewActInst
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *msg;
+ int lenMsg;
+ int i;
+CODESTARTdoAction
+ lenMsg = getMSGLen(pMsg);
+ if(lenMsg > 0) {
+ msg = getMSG(pMsg);
+ if(msg[0]==' ') {
+ for(i = 1; i < lenMsg; i++) {
+ msg[i-1] = msg[i];
+ }
+ msg[i-1] = '\0';
+ lenMsg -= 1;
+ }
+ }
+ if(lenMsg != getMSGLen(pMsg))
+ setMSGLen(pMsg, lenMsg);
+ENDdoAction
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmrm1stspace: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/mmsnmptrapd/Makefile.am b/plugins/mmsnmptrapd/Makefile.am
new file mode 100644
index 0000000..ca027ca
--- /dev/null
+++ b/plugins/mmsnmptrapd/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmsnmptrapd.la
+
+mmsnmptrapd_la_SOURCES = mmsnmptrapd.c
+mmsnmptrapd_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmsnmptrapd_la_LDFLAGS = -module -avoid-version
+mmsnmptrapd_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmsnmptrapd/Makefile.in b/plugins/mmsnmptrapd/Makefile.in
new file mode 100644
index 0000000..22902df
--- /dev/null
+++ b/plugins/mmsnmptrapd/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmsnmptrapd
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmsnmptrapd_la_DEPENDENCIES =
+am_mmsnmptrapd_la_OBJECTS = mmsnmptrapd_la-mmsnmptrapd.lo
+mmsnmptrapd_la_OBJECTS = $(am_mmsnmptrapd_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 =
+mmsnmptrapd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(mmsnmptrapd_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Plo
+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 = $(mmsnmptrapd_la_SOURCES)
+DIST_SOURCES = $(mmsnmptrapd_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmsnmptrapd.la
+mmsnmptrapd_la_SOURCES = mmsnmptrapd.c
+mmsnmptrapd_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmsnmptrapd_la_LDFLAGS = -module -avoid-version
+mmsnmptrapd_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmsnmptrapd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmsnmptrapd/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmsnmptrapd.la: $(mmsnmptrapd_la_OBJECTS) $(mmsnmptrapd_la_DEPENDENCIES) $(EXTRA_mmsnmptrapd_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmsnmptrapd_la_LINK) -rpath $(pkglibdir) $(mmsnmptrapd_la_OBJECTS) $(mmsnmptrapd_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmsnmptrapd_la-mmsnmptrapd.lo: mmsnmptrapd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmsnmptrapd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmsnmptrapd_la-mmsnmptrapd.lo -MD -MP -MF $(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Tpo -c -o mmsnmptrapd_la-mmsnmptrapd.lo `test -f 'mmsnmptrapd.c' || echo '$(srcdir)/'`mmsnmptrapd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Tpo $(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmsnmptrapd.c' object='mmsnmptrapd_la-mmsnmptrapd.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) $(mmsnmptrapd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmsnmptrapd_la-mmsnmptrapd.lo `test -f 'mmsnmptrapd.c' || echo '$(srcdir)/'`mmsnmptrapd.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmsnmptrapd_la-mmsnmptrapd.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmsnmptrapd/mmsnmptrapd.c b/plugins/mmsnmptrapd/mmsnmptrapd.c
new file mode 100644
index 0000000..f7904ae
--- /dev/null
+++ b/plugins/mmsnmptrapd/mmsnmptrapd.c
@@ -0,0 +1,438 @@
+/* mmsnmptrapd.c
+ * This is a message modification module. It takes messages generated
+ * from snmptrapd and modifies them so that the look like they
+ * originated from the real originator.
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * File begun on 2011-05-05 by RGerhards
+ *
+ * Copyright 2011-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "conf.h"
+#include "msg.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmsnmptrapd")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+struct severMap_s {
+ uchar *name;
+ int code;
+ struct severMap_s *next;
+};
+
+typedef struct _instanceData {
+ uchar *pszTagName;
+ uchar *pszTagID; /* cached: name plus trailing shlash (for compares) */
+ int lenTagID; /* cached: length of tag ID, for performance reasons */
+ struct severMap_s *severMap;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar *pszTagName; /**< name of tag start value that indicates snmptrapd initiated message */
+ uchar *pszSeverityMapping; /**< severitystring to numerical code mapping for snmptrapd string */
+} configSettings_t;
+static configSettings_t cs;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.pszTagName = NULL;
+ cs.pszSeverityMapping = NULL;
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+ struct severMap_s *node, *nodeDel;
+CODESTARTfreeInstance
+ for(node = pData->severMap ; node != NULL ; ) {
+ nodeDel = node;
+ node = node->next;
+ free(nodeDel->name);
+ free(nodeDel);
+ }
+ free(pData->pszTagName);
+ free(pData->pszTagID);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("mmsnmptrapd\n");
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+/* check if a string is numeric (int) */
+static int
+isNumeric(uchar *str)
+{
+ int r = 1;
+ if(*str == '-' || *str == '+')
+ ++str;
+ while(*str) {
+ if(!isdigit(*str)) {
+ r = 0;
+ goto done;
+ }
+ ++str;
+ }
+done:
+ return r;
+}
+
+/* get a substring delimited by a character (or end of string). The
+ * string is trimmed, that is leading and trailing spaces are removed.
+ * The caller must provide a buffer which shall receive the substring.
+ * String length is returned as result. The input string is updated
+ * on exit, so that it may be used for another query starting at that
+ * position.
+ */
+static int
+getSubstring(uchar **psrc, uchar delim, uchar *dst, int lenDst)
+{
+ uchar *dstwrk = dst;
+ uchar *src = *psrc;
+ while(*src && isspace(*src)) {
+ ++src; /* trim leading spaces */
+ }
+ while(*src && *src != delim && --lenDst > 0) {
+ *dstwrk++ = *src++;
+ }
+ dstwrk--;
+ while(dstwrk > dst && isspace(*dst))
+ --dstwrk; /* trim trailing spaces */
+ *++dstwrk = '\0';
+
+ /* final results */
+ if(*src == delim)
+ ++src;
+ *psrc = src;
+ return(dstwrk - dst);
+}
+
+
+/* get string up to the next SP or '/'. Stops at max size.
+ * dst, lenDst (receive buffer) must be given. lenDst is
+ * max length on entry and actual length on exit.
+ */
+static int ATTR_NONNULL()
+getTagComponent(uchar *tag, uchar *const dst, int *const lenDst)
+{
+ int end = *lenDst - 1; /* -1 for NUL-char! */
+ int i;
+
+ i = 0;
+ if(tag[i] == '/') {
+ ++tag;
+ while(i < end && tag[i] != '\0' && tag[i] != ' ' && tag[i] != '/') {
+ dst[i] = tag[i];
+ ++i;
+ }
+ }
+ dst[i] = '\0';
+ *lenDst = i;
+ return i;
+}
+
+
+/* lookup severity code based on provided severity
+ * returns -1 if severity could not be found.
+ */
+static int
+lookupSeverityCode(instanceData *pData, uchar *sever)
+{
+ struct severMap_s *node;
+ int sevCode = -1;
+
+ for(node = pData->severMap ; node != NULL ; node = node->next) {
+ if(!ustrcmp(node->name, sever)) {
+ sevCode = node->code;
+ break;
+ }
+ }
+ return sevCode;
+}
+
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ int lenTAG;
+ int lenSever;
+ int lenHost;
+ int sevCode;
+ uchar *pszTag;
+ uchar pszSever[512];
+ uchar pszHost[512];
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ getTAG(pMsg, &pszTag, &lenTAG, LOCK_MUTEX);
+ if(strncmp((char*)pszTag, (char*)pData->pszTagID, pData->lenTagID)) {
+ DBGPRINTF("tag '%s' not matching, mmsnmptrapd ignoring this message\n",
+ pszTag);
+ FINALIZE;
+ }
+
+ lenSever = sizeof(pszSever);
+ getTagComponent(pszTag+pData->lenTagID-1, pszSever, &lenSever);
+ lenHost = sizeof(pszHost);
+ getTagComponent(pszTag+pData->lenTagID+lenSever, pszHost, &lenHost);
+ DBGPRINTF("mmsnmptrapd: sever '%s'(%d), host '%s'(%d)\n", pszSever, lenSever, pszHost,lenHost);
+
+ if(lenHost > 0 && pszHost[lenHost-1] == ':') {
+ pszHost[lenHost-1] = '\0';
+ --lenHost;
+ }
+ sevCode = lookupSeverityCode(pData, pszSever);
+ /* now apply new settings */
+ MsgSetTAG(pMsg, pData->pszTagName, pData->lenTagID);
+ MsgSetHOSTNAME(pMsg, pszHost, lenHost);
+ if(sevCode != -1)
+ pMsg->iSeverity = sevCode; /* we update like the parser does! */
+finalize_it:
+ENDdoAction
+
+
+/* Build the severity mapping table based on user-provided configuration
+ * settings.
+ */
+static rsRetVal ATTR_NONNULL()
+buildSeverityMapping(instanceData *const pData)
+{
+ uchar pszSev[512];
+ uchar pszSevCode[512];
+ int sevCode;
+ uchar *mapping;
+ struct severMap_s *node = NULL;
+ DEFiRet;
+
+ mapping = cs.pszSeverityMapping;
+
+ while(1) { /* broken inside when all entries are processed */
+ if(getSubstring(&mapping, '/', pszSev, sizeof(pszSev)) == 0) {
+ FINALIZE;
+ }
+ if(getSubstring(&mapping, ',', pszSevCode, sizeof(pszSevCode)) == 0) {
+ LogError(0, RS_RET_ERR, "error: invalid severity mapping, cannot "
+ "extract code. given: '%s'\n", cs.pszSeverityMapping);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ sevCode = atoi((char*) pszSevCode);
+ if(!isNumeric(pszSevCode))
+ sevCode = -1;
+ if(sevCode < 0 || sevCode > 7) {
+ LogError(0, RS_RET_ERR, "error: severity code %d outside of valid "
+ "range 0..7 (was string '%s')\n", sevCode, pszSevCode);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKmalloc(node = malloc(sizeof(struct severMap_s)));
+ CHKmalloc(node->name = ustrdup(pszSev));
+ node->code = sevCode;
+ /* we enqueue at the top, so the two lines below do all we need! */
+ node->next = pData->severMap;
+ pData->severMap = node;
+ node = NULL;
+ DBGPRINTF("mmsnmptrapd: severity string '%s' mapped to code %d\n",
+ pszSev, sevCode);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(node);
+ }
+ RETiRet;
+}
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":mmsnmptrapd:", sizeof(":mmsnmptrapd:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":mmsnmptrapd:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ /* we call the function below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat"));
+
+ /* finally build the instance */
+ if(cs.pszTagName == NULL) {
+ CHKmalloc(pData->pszTagName = (uchar*) strdup("snmptrapd:"));
+ CHKmalloc(pData->pszTagID = (uchar*) strdup("snmptrapd/"));
+ } else {
+ int lenTag = ustrlen(cs.pszTagName);
+ /* new tag value (with colon at the end) */
+ CHKmalloc(pData->pszTagName = malloc(lenTag + 2));
+ memcpy(pData->pszTagName, cs.pszTagName, lenTag);
+ memcpy(pData->pszTagName+lenTag, ":", 2);
+ /* tag ID for comparisions */
+ CHKmalloc(pData->pszTagID = malloc(lenTag + 2));
+ memcpy(pData->pszTagID, cs.pszTagName, lenTag);
+ memcpy(pData->pszTagID+lenTag, "/", 2);
+ free(cs.pszTagName); /* no longer needed */
+ }
+ pData->lenTagID = ustrlen(pData->pszTagID);
+ if(cs.pszSeverityMapping != NULL) {
+ CHKiRet(buildSeverityMapping(pData));
+ }
+
+ /* all config vars auto-reset! */
+ cs.pszTagName = NULL;
+ free(cs.pszSeverityMapping);
+ cs.pszSeverityMapping = NULL;
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ free(cs.pszTagName);
+ cs.pszTagName = NULL;
+ free(cs.pszSeverityMapping);
+ cs.pszSeverityMapping = NULL;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported;
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("mmsnmptrapd: msg-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+
+ /* TODO: config vars ininit can be replaced by commented-out code above in v6 */
+ cs.pszTagName = NULL;
+ cs.pszSeverityMapping = NULL;
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmsnmptrapdtag", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszTagName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmsnmptrapdseveritymapping", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszSeverityMapping, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/mmutf8fix/Makefile.am b/plugins/mmutf8fix/Makefile.am
new file mode 100644
index 0000000..2c0f283
--- /dev/null
+++ b/plugins/mmutf8fix/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmutf8fix.la
+
+mmutf8fix_la_SOURCES = mmutf8fix.c
+mmutf8fix_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmutf8fix_la_LDFLAGS = -module -avoid-version
+mmutf8fix_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmutf8fix/Makefile.in b/plugins/mmutf8fix/Makefile.in
new file mode 100644
index 0000000..f7de487
--- /dev/null
+++ b/plugins/mmutf8fix/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/mmutf8fix
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+mmutf8fix_la_DEPENDENCIES =
+am_mmutf8fix_la_OBJECTS = mmutf8fix_la-mmutf8fix.lo
+mmutf8fix_la_OBJECTS = $(am_mmutf8fix_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 =
+mmutf8fix_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(mmutf8fix_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/mmutf8fix_la-mmutf8fix.Plo
+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 = $(mmutf8fix_la_SOURCES)
+DIST_SOURCES = $(mmutf8fix_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = mmutf8fix.la
+mmutf8fix_la_SOURCES = mmutf8fix.c
+mmutf8fix_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmutf8fix_la_LDFLAGS = -module -avoid-version
+mmutf8fix_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/mmutf8fix/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/mmutf8fix/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+mmutf8fix.la: $(mmutf8fix_la_OBJECTS) $(mmutf8fix_la_DEPENDENCIES) $(EXTRA_mmutf8fix_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(mmutf8fix_la_LINK) -rpath $(pkglibdir) $(mmutf8fix_la_OBJECTS) $(mmutf8fix_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmutf8fix_la-mmutf8fix.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+mmutf8fix_la-mmutf8fix.lo: mmutf8fix.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmutf8fix_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmutf8fix_la-mmutf8fix.lo -MD -MP -MF $(DEPDIR)/mmutf8fix_la-mmutf8fix.Tpo -c -o mmutf8fix_la-mmutf8fix.lo `test -f 'mmutf8fix.c' || echo '$(srcdir)/'`mmutf8fix.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmutf8fix_la-mmutf8fix.Tpo $(DEPDIR)/mmutf8fix_la-mmutf8fix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmutf8fix.c' object='mmutf8fix_la-mmutf8fix.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) $(mmutf8fix_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmutf8fix_la-mmutf8fix.lo `test -f 'mmutf8fix.c' || echo '$(srcdir)/'`mmutf8fix.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/mmutf8fix_la-mmutf8fix.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/mmutf8fix_la-mmutf8fix.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/mmutf8fix/mmutf8fix.c b/plugins/mmutf8fix/mmutf8fix.c
new file mode 100644
index 0000000..a1a1ee3
--- /dev/null
+++ b/plugins/mmutf8fix/mmutf8fix.c
@@ -0,0 +1,339 @@
+/* mmutf8fix.c
+ * fix invalid UTF8 sequences. This is begun as a very simple replacer
+ * of non-control characters, and actually breaks some UTF-8 encoding
+ * right now. If the module turns out to be useful, it should be enhanced
+ * to support modes that really detect invalid UTF8. In the longer term
+ * it could also be evolved into an any-charset-to-UTF8 converter. But
+ * first let's see if it really gets into widespread enough use.
+ *
+ * Copyright 2013-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmutf8fix")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* define operation modes we have */
+#define MODE_CC 0 /* just fix control characters */
+#define MODE_UTF8 1 /* do real UTF-8 fixing */
+
+/* config variables */
+typedef struct _instanceData {
+ uchar replChar;
+ uint8_t mode; /* operations mode */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "replacementchar", eCmdHdlrGetChar, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->mode = MODE_UTF8;
+ pData->replChar = ' ';
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmutf8fix)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "mode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"utf-8",
+ sizeof("utf-8")-1)) {
+ pData->mode = MODE_UTF8;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"controlcharacters",
+ sizeof("controlcharacters")-1)) {
+ pData->mode = MODE_CC;
+ } else {
+ char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_INVLD_MODE,
+ "mmutf8fix: invalid mode '%s' - ignored",
+ cstr);
+ free(cstr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "replacementchar")) {
+ pData->replChar = es_getBufAddr(pvals[i].val.d.estr)[0];
+ } else {
+ dbgprintf("mmutf8fix: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static void
+doCC(instanceData *pData, uchar *msg, int lenMsg)
+{
+ int i;
+
+ for(i = 0 ; i < lenMsg ; ++i) {
+ if(msg[i] < 32 || msg[i] > 126) {
+ msg[i] = pData->replChar;
+ }
+ }
+}
+
+/* fix an invalid multibyte sequence */
+static void
+fixInvldMBSeq(instanceData *pData, uchar *msg, int lenMsg, int strtIdx, int cnt)
+{
+ int i, endIdx;
+
+ /* Actually strtIdx + cnt will not exceed msgLen,
+ but this check does bring peace of mind */
+ endIdx = strtIdx + cnt;
+ if(endIdx > lenMsg)
+ endIdx = lenMsg;
+ for(i = strtIdx ; i < endIdx ; ++i)
+ msg[i] = pData->replChar;
+}
+
+static void
+doUTF8(instanceData *pData, uchar *msg, int lenMsg)
+{
+ uchar c;
+ int8_t bytesLeft = 0;
+ uint32_t codepoint;
+ int strtIdx = 0;
+ int i;
+
+ for(i = 0 ; i < lenMsg ; ++i) {
+ c = msg[i];
+ if(bytesLeft) {
+ if((c & 0xc0) != 0x80) {
+ /* invalid continuation byte, invalidate all bytes
+ up to (but not including) the current byte
+ startIdx is always set if bytesLeft is set */
+ fixInvldMBSeq(pData, msg, lenMsg, strtIdx, i - strtIdx);
+ bytesLeft = 0;
+ goto startOfSequence;
+ } else {
+ codepoint = (codepoint << 6) | (c & 0x3f);
+ --bytesLeft;
+ if(bytesLeft == 0) {
+ int seqLen = i - strtIdx + 1;
+
+ if (
+ /* an overlong encoding? (a codepoint must use only
+ the minimum number of bytes to represent its value) */
+ (((2 == seqLen) && (codepoint < 0x80)) ||
+ ((3 == seqLen) && (codepoint < 0x800)) ||
+ ((4 == seqLen) && (codepoint < 0x10000)))
+ ||
+ /* UTF-16 surrogates? */
+ ((codepoint >= 0xD800) && (codepoint <= 0xDFFF))
+ ||
+ /* too-large codepoint? */
+ (codepoint > 0x10FFFF)
+ ) {
+ /* sequence invalid, invalidate all bytes
+ startIdx is always set if bytesLeft is set */
+ fixInvldMBSeq(pData, msg, lenMsg, strtIdx, seqLen);
+ }
+ }
+ }
+ } else {
+startOfSequence:
+ if((c & 0x80) == 0) {
+ /* 1-byte sequence, US-ASCII */
+ ; /* nothing to do, all well */
+ } else if((c & 0xe0) == 0xc0) {
+ /* 2-byte sequence */
+ strtIdx = i;
+ bytesLeft = 1;
+ codepoint = c & 0x1f;
+ } else if((c & 0xf0) == 0xe0) {
+ /* 3-byte sequence */
+ strtIdx = i;
+ bytesLeft = 2;
+ codepoint = c & 0x0f;
+ } else if((c & 0xf8) == 0xf0) {
+ /* 4-byte sequence */
+ strtIdx = i;
+ bytesLeft = 3;
+ codepoint = c & 0x07;
+ } else { /* invalid, either:
+ - stray continuation byte (0x80 <= x <= 0xBF)
+ - 5&6 byte sequence start (x >= 0xF8) forbidden by RFC3629
+ */
+ msg[i] = pData->replChar;
+ }
+ }
+ }
+ if (bytesLeft) {
+ /* invalid, there was not enough bytes to complete a sequence
+ startIdx is always set if bytesLeft is set */
+ fixInvldMBSeq(pData, msg, lenMsg, strtIdx, i - strtIdx);
+ }
+}
+
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg = ppMsg[0];
+ uchar *msg;
+ int lenMsg;
+CODESTARTdoAction
+ lenMsg = getMSGLen(pMsg);
+ msg = getMSG(pMsg);
+ if(pWrkrData->pData->mode == MODE_CC) {
+ doCC(pWrkrData->pData, msg, lenMsg);
+ } else {
+ doUTF8(pWrkrData->pData, msg, lenMsg);
+ }
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmutf8fix: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/omazureeventhubs/Makefile.am b/plugins/omazureeventhubs/Makefile.am
new file mode 100644
index 0000000..356bb88
--- /dev/null
+++ b/plugins/omazureeventhubs/Makefile.am
@@ -0,0 +1,13 @@
+pkglib_LTLIBRARIES = omazureeventhubs.la
+
+omazureeventhubs_la_SOURCES = omazureeventhubs.c
+if ENABLE_QPIDPROTON_STATIC
+omazureeventhubs_la_LDFLAGS = -module -avoid-version $(PROTON_PROACTOR_LIBS) $(PTHREADS_LIBS) $(OPENSSL_LIBS) -lm
+omazureeventhubs_la_LDFLAGS = -module -avoid-version -Wl,-whole-archive -l:libqpid-proton-proactor-static.a -l:libqpid-proton-core-static.a -Wl,--no-whole-archive $(PTHREADS_LIBS) $(OPENSSL_LIBS) ${RT_LIBS} -lsasl2
+omazureeventhubs_la_LIBADD =
+else
+omazureeventhubs_la_LDFLAGS = -module -avoid-version $(PROTON_PROACTOR_LIBS) $(PTHREADS_LIBS) $(OPENSSL_LIBS) -lm
+omazureeventhubs_la_LIBADD =
+endif
+omazureeventhubs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(PROTON_PROACTOR_CFLAGS) -Wno-error=switch
+EXTRA_DIST =
diff --git a/plugins/omazureeventhubs/Makefile.in b/plugins/omazureeventhubs/Makefile.in
new file mode 100644
index 0000000..0fd0502
--- /dev/null
+++ b/plugins/omazureeventhubs/Makefile.in
@@ -0,0 +1,802 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omazureeventhubs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omazureeventhubs_la_DEPENDENCIES =
+am_omazureeventhubs_la_OBJECTS = \
+ omazureeventhubs_la-omazureeventhubs.lo
+omazureeventhubs_la_OBJECTS = $(am_omazureeventhubs_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 =
+omazureeventhubs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(omazureeventhubs_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Plo
+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 = $(omazureeventhubs_la_SOURCES)
+DIST_SOURCES = $(omazureeventhubs_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omazureeventhubs.la
+omazureeventhubs_la_SOURCES = omazureeventhubs.c
+@ENABLE_QPIDPROTON_STATIC_FALSE@omazureeventhubs_la_LDFLAGS = -module -avoid-version $(PROTON_PROACTOR_LIBS) $(PTHREADS_LIBS) $(OPENSSL_LIBS) -lm
+@ENABLE_QPIDPROTON_STATIC_TRUE@omazureeventhubs_la_LDFLAGS = -module -avoid-version -Wl,-whole-archive -l:libqpid-proton-proactor-static.a -l:libqpid-proton-core-static.a -Wl,--no-whole-archive $(PTHREADS_LIBS) $(OPENSSL_LIBS) ${RT_LIBS} -lsasl2
+@ENABLE_QPIDPROTON_STATIC_FALSE@omazureeventhubs_la_LIBADD =
+@ENABLE_QPIDPROTON_STATIC_TRUE@omazureeventhubs_la_LIBADD =
+omazureeventhubs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(PROTON_PROACTOR_CFLAGS) -Wno-error=switch
+EXTRA_DIST =
+all: 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) --gnu plugins/omazureeventhubs/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omazureeventhubs/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omazureeventhubs.la: $(omazureeventhubs_la_OBJECTS) $(omazureeventhubs_la_DEPENDENCIES) $(EXTRA_omazureeventhubs_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omazureeventhubs_la_LINK) -rpath $(pkglibdir) $(omazureeventhubs_la_OBJECTS) $(omazureeventhubs_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omazureeventhubs_la-omazureeventhubs.lo: omazureeventhubs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omazureeventhubs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omazureeventhubs_la-omazureeventhubs.lo -MD -MP -MF $(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Tpo -c -o omazureeventhubs_la-omazureeventhubs.lo `test -f 'omazureeventhubs.c' || echo '$(srcdir)/'`omazureeventhubs.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Tpo $(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omazureeventhubs.c' object='omazureeventhubs_la-omazureeventhubs.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) $(omazureeventhubs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omazureeventhubs_la-omazureeventhubs.lo `test -f 'omazureeventhubs.c' || echo '$(srcdir)/'`omazureeventhubs.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omazureeventhubs_la-omazureeventhubs.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omazureeventhubs/omazureeventhubs.c b/plugins/omazureeventhubs/omazureeventhubs.c
new file mode 100644
index 0000000..a2bd8b3
--- /dev/null
+++ b/plugins/omazureeventhubs/omazureeventhubs.c
@@ -0,0 +1,1354 @@
+/* omazureeventhubs.c
+ * This output plugin make rsyslog talk to Azure EventHubs.
+ *
+ * Copyright 2014-2017 by Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/uio.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <math.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/time.h>
+#include <time.h>
+
+// Include Proton headers
+#include <proton/version.h>
+#include <proton/condition.h>
+#include <proton/connection.h>
+#include <proton/delivery.h>
+#include <proton/link.h>
+#include <proton/listener.h>
+#include <proton/netaddr.h>
+#include <proton/message.h>
+#include <proton/object.h>
+#include <proton/proactor.h>
+#include <proton/sasl.h>
+#include <proton/session.h>
+#include <proton/transport.h>
+#include <proton/ssl.h>
+
+// Include rsyslog headers
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+#include "datetime.h"
+#include "glbl.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omazureeventhubs")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(statsobj)
+
+statsobj_t *azureStats;
+STATSCOUNTER_DEF(ctrMessageSubmit, mutCtrMessageSubmit);
+STATSCOUNTER_DEF(ctrAzureFail, mutCtrAzureFail);
+STATSCOUNTER_DEF(ctrCacheMiss, mutCtrCacheMiss);
+STATSCOUNTER_DEF(ctrCacheEvict, mutCtrCacheEvict);
+STATSCOUNTER_DEF(ctrCacheSkip, mutCtrCacheSkip);
+STATSCOUNTER_DEF(ctrAzureAck, mutCtrAzureAck);
+STATSCOUNTER_DEF(ctrAzureMsgTooLarge, mutCtrAzureMsgTooLarge);
+STATSCOUNTER_DEF(ctrAzureQueueFull, mutCtrAzureQueueFull);
+STATSCOUNTER_DEF(ctrAzureOtherErrors, mutCtrAzureOtherErrors);
+STATSCOUNTER_DEF(ctrAzureRespTimedOut, mutCtrAzureRespTimedOut);
+STATSCOUNTER_DEF(ctrAzureRespTransport, mutCtrAzureRespTransport);
+STATSCOUNTER_DEF(ctrAzureRespBrokerDown, mutCtrAzureRespBrokerDown);
+STATSCOUNTER_DEF(ctrAzureRespAuth, mutCtrAzureRespAuth);
+STATSCOUNTER_DEF(ctrAzureRespSSL, mutCtrAzureRespSSL);
+STATSCOUNTER_DEF(ctrAzureRespOther, mutCtrAzureRespOther);
+
+#define MAX_ERRMSG 1024 /* max size of error messages that we support */
+#define MAX_DEFAULTMSGS 1024 /* Initial max size of the proton message helper array */
+
+#define SETUP_PROTON_NONE 0
+#define SETUP_PROTON_AUTOCLOSE 1
+
+/* flags for writeAzure: shall we resubmit a failed message? */
+#define RESUBMIT 1
+#define NO_RESUBMIT 0
+
+/* flags for transaction Handling */
+enum proton_submission_status
+{
+ PROTON_UNSUBMITTED = 0, // Message not submitted yet
+ PROTON_SUBMITTED, // Message submitted to proton sender instance
+ PROTON_ACCEPTED, // Message accepted from remote target
+ PROTON_REJECTED, // Message rejected from remote target (zero credit?)
+};
+
+// event_property NEEDED?
+struct event_property {
+ const char *key;
+ const char *val;
+};
+
+static pn_timestamp_t time_now(void);
+
+/* Struct for Proton Messages Listitems */
+struct s_protonmsg_entry {
+ uchar* payload;
+ size_t payload_len;
+ uchar* MsgID;
+ size_t MsgID_len;
+
+ uchar* address;
+ char status;
+};
+typedef struct s_protonmsg_entry protonmsg_entry;
+
+/* Struct for module InstanceData */
+typedef struct _instanceData {
+ uchar *amqp_address;
+ uchar *azurehost;
+ uchar *azureport;
+ uchar *azure_key_name;
+ uchar *azure_key;
+ uchar *container;
+ uchar *tplName; /* assigned output template */
+
+ int nEventProperties;
+ struct event_property *eventProperties;
+
+ uchar *statsName;
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrMessageSubmit, mutCtrMessageSubmit);
+ STATSCOUNTER_DEF(ctrAzureFail, mutCtrAzureFail);
+ STATSCOUNTER_DEF(ctrAzureAck, mutCtrAzureAck);
+ STATSCOUNTER_DEF(ctrAzureOtherErrors, mutCtrAzureOtherErrors);
+} instanceData;
+
+/* Struct for module workerInstanceData */
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+
+ protonmsg_entry **aProtonMsgs; /* dynamically sized array for transactional outputs */
+ unsigned int nProtonMsgs; /* current used proton msgs */
+ unsigned int nMaxProtonMsgs; /* current max */
+
+ int bIsConnecting; /* 1 if connecting, 0 if disconnected */
+ int bIsConnected; /* 1 if connected, 0 if disconnected */
+ int bIsSuspended; /* when broker fail, we need to suspend the action */
+ pthread_rwlock_t pnLock;
+
+ // PROTON Handles
+ pn_proactor_t *pnProactor;
+ pn_transport_t *pnTransport;
+ pn_connection_t *pnConn;
+ pn_link_t* pnSender;
+ pn_rwbytes_t pnMessageBuffer; /* Buffer for messages */
+ int pnStatus;
+
+ // Message Counters for sender link in worker instance
+ unsigned int iMsgSeq;
+ unsigned int iMaxMsgSeq;
+
+ /* The following structure controls the proton handling threads. Passes necessary pointers
+ * needed for their access.
+ */
+ sbool bThreadRunning;
+ pthread_t tid; /* the worker's thread ID */
+
+} wrkrInstanceData_t;
+
+#define INST_STATSCOUNTER_INC(inst, ctr, mut) \
+ do { \
+ if (inst->stats) { STATSCOUNTER_INC(ctr, mut); } \
+ } while(0);
+
+// QPID Proton Handler functions
+static rsRetVal proton_run_thread(wrkrInstanceData_t *pWrkrData);
+static rsRetVal proton_shutdown_thread(wrkrInstanceData_t *pWrkrData);
+static void * proton_thread(void *myInfo);
+static void handleProtonDelivery(wrkrInstanceData_t *const pWrkrData);
+static void handleProton(wrkrInstanceData_t *const pWrkrData, pn_event_t *event);
+static rsRetVal writeProton(wrkrInstanceData_t *__restrict__ const pWrkrData,
+ const actWrkrIParams_t *__restrict__ const pParam,
+ const int iMsg);
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "azurehost", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "azureport", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "azure_key_name", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "azure_key", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "amqp_address", eCmdHdlrString, 0 },
+ { "container", eCmdHdlrString, 0 },
+ { "eventproperties", eCmdHdlrArray, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "statsname", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+static void ATTR_NONNULL(1)
+protonmsg_entry_destruct(protonmsg_entry *const __restrict__ fmsgEntry) {
+ free(fmsgEntry->MsgID);
+ free(fmsgEntry->payload);
+ free(fmsgEntry->address);
+ free(fmsgEntry);
+}
+
+/* note: we need the length of message as we need to deal with
+ * non-NUL terminated strings under some circumstances.
+ */
+static protonmsg_entry * ATTR_NONNULL(1,3)
+protonmsg_entry_construct( const char *const MsgID, const size_t msgidlen,
+ const char *const msg, const size_t msglen,
+ const char *const address)
+{
+ protonmsg_entry *etry = NULL;
+
+ if((etry = malloc(sizeof(struct s_protonmsg_entry))) == NULL) {
+ return NULL;
+ }
+ etry->status = PROTON_UNSUBMITTED; // Unsubmitted default */
+
+ etry->MsgID_len = msgidlen;
+ if((etry->MsgID = (uchar*)malloc(msgidlen+1)) == NULL) {
+ free(etry);
+ return NULL;
+ }
+ memcpy(etry->MsgID, MsgID, msgidlen);
+ etry->MsgID[msgidlen] = '\0';
+
+ etry->payload_len = msglen;
+ if((etry->payload = (uchar*)malloc(msglen+1)) == NULL) {
+ free(etry->MsgID);
+ free(etry);
+ return NULL;
+ }
+ memcpy(etry->payload, msg, msglen);
+ etry->payload[msglen] = '\0';
+
+ if((etry->address = (uchar*)strdup(address)) == NULL) {
+ free(etry->MsgID);
+ free(etry->payload);
+ free(etry);
+ return NULL;
+ }
+ return etry;
+}
+
+/* Create a message with a map { "sequence" : number } encode it and return the encoded buffer. */
+static pn_message_t* proton_encode_message(wrkrInstanceData_t *const pWrkrData, protonmsg_entry* pMsgEntry) {
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ /* Construct a message with the map */
+ pn_message_t* message = pn_message();
+ // Optionally include Address?
+ // pn_message_set_address(message, (char *) pWrkrData->amqp_address);
+
+ // Send in BINARY MODE ( as Stream )
+ pn_message_set_content_type(message, (char*) "application/octect-stream");
+ pn_message_set_creation_time(message, time_now());
+ pn_message_set_inferred(message, true);
+ // Set message ID
+ pn_message_set_id(message, (pn_atom_t){
+ .type=PN_STRING,
+ .u.as_bytes.start = (char*)pMsgEntry->MsgID,
+ .u.as_bytes.size = pMsgEntry->MsgID_len
+ });
+
+ if (pData->nEventProperties > 0) {
+ // Add Event properties
+ pn_data_t *props = pn_message_properties(message);
+ pn_data_put_map(props);
+ pn_data_enter(props);
+
+ for(int i = 0 ; i < pData->nEventProperties ; ++i) {
+ DBGPRINTF("proton_encode_message: add eventproperty %s:%s\n",
+ pData->eventProperties[i].key,
+ pData->eventProperties[i].val);
+ pn_data_put_string(props, pn_bytes(strlen(pData->eventProperties[i].key),
+ pData->eventProperties[i].key));
+ pn_data_put_string(props, pn_bytes(strlen(pData->eventProperties[i].val),
+ pData->eventProperties[i].val));
+ }
+ pn_data_exit(props);
+ }
+
+ // Set message BODY
+ pn_data_t* body = pn_message_body(message);
+ pn_data_enter(body);
+ pn_data_put_binary(body, pn_bytes(pMsgEntry->payload_len, (char*)pMsgEntry->payload));
+ pn_data_exit(body);
+
+ DBGPRINTF("proton_encode_message: created message id '%s': '%.*s'\n",
+ (char*)pMsgEntry->MsgID,
+ (pMsgEntry->payload_len > 0 ? (int)pMsgEntry->payload_len-1 : 0),
+ (char*)pMsgEntry->payload);
+
+ return message;
+}
+
+static rsRetVal
+closeProton(wrkrInstanceData_t *const __restrict__ pWrkrData)
+{
+ DEFiRet;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+#ifndef NDEBUG
+ DBGPRINTF("closeProton[%p]: ENTER\n", pWrkrData);
+#endif
+ if (pWrkrData->pnSender) {
+ pn_link_close(pWrkrData->pnSender);
+ DBGPRINTF("closeProton[%p]: pn_link_close\n", pWrkrData);
+ pn_session_close(pn_link_session(pWrkrData->pnSender));
+ DBGPRINTF("closeProton[%p]: pn_session_close\n", pWrkrData);
+ }
+ if (pWrkrData->pnConn) {
+ DBGPRINTF("closeProton[%p]: pn_connection_close connection\n", pWrkrData);
+ pn_connection_close(pWrkrData->pnConn);
+ }
+
+ pWrkrData->bIsConnecting = 0;
+ pWrkrData->bIsConnected = 0;
+ pWrkrData->pnStatus = PN_EVENT_NONE;
+
+ pWrkrData->pnSender = NULL;
+ pWrkrData->pnConn = NULL;
+ pWrkrData->iMsgSeq = 0;
+ pWrkrData->iMaxMsgSeq = 0;
+
+ // Mark all remaining entries as REJECTED
+ if(pWrkrData->aProtonMsgs != NULL) {
+ for(unsigned int i = 0 ; i < pWrkrData->nProtonMsgs ; ++i) {
+ if (pWrkrData->aProtonMsgs[i] != NULL && (
+ pWrkrData->aProtonMsgs[i]->status == PROTON_UNSUBMITTED ||
+ pWrkrData->aProtonMsgs[i]->status == PROTON_SUBMITTED)
+ ) {
+ pWrkrData->aProtonMsgs[i]->status = PROTON_REJECTED;
+ DBGPRINTF("closeProton[%p]: Setting ProtonMsg %s to PROTON_REJECTED \n",
+ pWrkrData, pWrkrData->aProtonMsgs[i]->MsgID);
+ // Increment Stats Counter
+ STATSCOUNTER_INC(ctrAzureFail, mutCtrAzureFail);
+ INST_STATSCOUNTER_INC(pData, pData->ctrAzureFail, pData->mutCtrAzureFail);
+ }
+ }
+ }
+
+ FINALIZE;
+finalize_it:
+ RETiRet;
+
+}
+
+static rsRetVal
+openProton(wrkrInstanceData_t *const __restrict__ pWrkrData)
+{
+ DEFiRet;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ int pnErr = PN_OK;
+ char szAddr[PN_MAX_ADDR];
+ pn_ssl_t* pnSsl;
+#ifndef NDEBUG
+ DBGPRINTF("openProton[%p]: ENTER\n", pWrkrData);
+#endif
+ if(pWrkrData->bIsConnecting == 1 || pWrkrData->bIsConnected == 1)
+ FINALIZE;
+ pWrkrData->pnStatus = PN_EVENT_NONE;
+
+ pn_proactor_addr(szAddr, sizeof(szAddr),
+ (const char *) pData->azurehost,
+ (const char *) pData->azureport);
+
+ // Configure a transport for SSL. The transport will be freed by the proactor.
+ pWrkrData->pnTransport = pn_transport();
+ DBGPRINTF("openProton[%p]: create transport to '%s:%s'\n",
+ pWrkrData, pData->azurehost, pData->azureport);
+ pnSsl = pn_ssl(pWrkrData->pnTransport);
+ if (pnSsl != NULL) {
+ pn_ssl_domain_t* pnDomain = pn_ssl_domain(PN_SSL_MODE_CLIENT);
+ if (pData->azure_key_name != NULL && pData->azure_key != NULL) {
+ pnErr = pn_ssl_init(pnSsl, pnDomain, NULL);
+ if (pnErr) {
+ DBGPRINTF("openProton[%p]: pn_ssl_init failed for '%s:%s' with error %d: %s\n",
+ pWrkrData, pData->azurehost, pData->azureport,
+ pnErr, pn_code(pnErr));
+ }
+ pn_sasl_allowed_mechs(pn_sasl(pWrkrData->pnTransport), "PLAIN");
+ } else {
+ pnErr = pn_ssl_domain_set_peer_authentication(pnDomain, PN_SSL_ANONYMOUS_PEER, NULL);
+ if (!pnErr) {
+ pnErr = pn_ssl_init(pnSsl, pnDomain, NULL);
+ } else {
+ DBGPRINTF(
+ "openProton[%p]: pn_ssl_domain_set_peer_authentication failed with '%d'\n",
+ pWrkrData, pnErr);
+ }
+ }
+ pn_ssl_domain_free(pnDomain);
+ } else {
+ LogError(0, RS_RET_ERR, "openProton[%p]: openProton pn_ssl_init NULL", pWrkrData);
+ }
+
+ // Handle ERROR Output
+ if (pnErr) {
+ LogError(0, RS_RET_IO_ERROR, "openProton[%p]: creating transport to '%s:%s' "
+ "failed with error %d: %s\n",
+ pWrkrData, pData->azurehost, pData->azureport,
+ pnErr, pn_code(pnErr));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ // Connect to Azure Event Hubs
+ pn_proactor_connect2(pWrkrData->pnProactor, NULL, pWrkrData->pnTransport, szAddr);
+
+ // Successfully connecting
+ pWrkrData->bIsConnecting = 1;
+ pWrkrData->bIsSuspended = 0;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ closeProton(pWrkrData); // Make sure to free ressources
+ }
+ RETiRet;
+}
+
+static sbool
+proton_check_condition( pn_event_t *event,
+ wrkrInstanceData_t *const __restrict__ pWrkrData,
+ pn_condition_t *cond,
+ const char * pszReason) {
+ if (pn_condition_is_set(cond)) {
+ DBGPRINTF("proton_check_condition: %s %s: %s: %s",
+ pszReason,
+ pn_event_type_name(pn_event_type(event)),
+ pn_condition_get_name(cond),
+ pn_condition_get_description(cond));
+ LogError(0, RS_RET_ERR, "omazureeventhubs: %s %s: %s: %s",
+ pszReason,
+ pn_event_type_name(pn_event_type(event)),
+ pn_condition_get_name(cond),
+ pn_condition_get_description(cond));
+
+ // Connection can be closed
+ closeProton(pWrkrData);
+
+ // Set Worker to suspended state!
+ pWrkrData->bIsSuspended = 1;
+
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static rsRetVal
+setupProtonHandle(wrkrInstanceData_t *const __restrict__ pWrkrData, int autoclose)
+{
+ DEFiRet;
+ DBGPRINTF("omazureeventhubs[%p]: setupProtonHandle ENTER\n", pWrkrData);
+
+ pthread_rwlock_wrlock(&pWrkrData->pnLock);
+ if (autoclose == SETUP_PROTON_AUTOCLOSE && (pWrkrData->bIsConnected == 1)) {
+ DBGPRINTF("omazureeventhubs[%p]: setupProtonHandle closeProton\n", pWrkrData);
+ closeProton(pWrkrData);
+ }
+ CHKiRet(openProton(pWrkrData));
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ /* Parameter Error's cannot be resumed, so we need to disable the action */
+ if (iRet == RS_RET_PARAM_ERROR) {
+ iRet = RS_RET_DISABLE_ACTION;
+ LogError(0, iRet, "omazureeventhubs: action will be disabled due invalid "
+ "configuration parameters\n");
+ }
+ }
+ pthread_rwlock_unlock(&pWrkrData->pnLock);
+ RETiRet;
+}
+
+static rsRetVal
+writeProton(wrkrInstanceData_t *__restrict__ const pWrkrData,
+ const actWrkrIParams_t *__restrict__ const pParam,
+ const int iMsg)
+{
+ DEFiRet;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ protonmsg_entry* fmsgEntry;
+
+ // Create Unqiue Message ID
+ char szMsgID[64];
+ sprintf(szMsgID, "%d", pWrkrData->iMsgSeq);
+
+ const char* pszParamStr = (const char*)actParam(pParam, 1 /*pData->iNumTpls*/, iMsg, 0).param;
+ size_t tzParamStrLen = actParam(pParam, 1 /*pData->iNumTpls*/, iMsg, 0).lenStr;
+
+ DBGPRINTF("omazureeventhubs[%p]: writeProton for msg %d (seq %d) msg:'%.*s%s'\n",
+ pWrkrData,
+ iMsg, pWrkrData->iMsgSeq,
+ (int)(tzParamStrLen > 0 ? (tzParamStrLen > 64 ? 64 : tzParamStrLen-1) : 0),
+ pszParamStr,
+ (tzParamStrLen > 64 ? "..." : ""));
+ // Increment Message sequence number
+ pWrkrData->iMsgSeq++;
+
+ // Add message to LIST for sending
+ CHKmalloc(fmsgEntry = protonmsg_entry_construct(
+ szMsgID, sizeof(szMsgID),
+ pszParamStr,
+ tzParamStrLen,
+ (const char*)pData->amqp_address));
+ // Add to helper Array
+ pWrkrData->aProtonMsgs[iMsg] = fmsgEntry;
+finalize_it:
+ RETiRet;
+}
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ DBGPRINTF("createInstance[%p]: ENTER\n", pData);
+ pData->amqp_address = NULL;
+ pData->azurehost = NULL;
+ pData->azureport = NULL;
+ pData->azure_key_name = NULL;
+ pData->azure_key = NULL;
+ pData->container = NULL;
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ DBGPRINTF("createWrkrInstance[%p]: ENTER\n", pWrkrData);
+ pWrkrData->bIsConnecting = 0;
+ pWrkrData->bIsConnected = 0;
+ pWrkrData->bIsSuspended = 0;
+
+ // Create Proton proActor in Worker Instance
+ pWrkrData->pnProactor = pn_proactor();
+ pWrkrData->pnConn = NULL;
+ pWrkrData->pnTransport = NULL;
+ pWrkrData->pnSender = NULL;
+
+ pWrkrData->iMsgSeq = 0;
+ pWrkrData->iMaxMsgSeq = 0;
+ pWrkrData->pnMessageBuffer.start = NULL;
+
+ pWrkrData->nProtonMsgs = 0;
+ pWrkrData->nMaxProtonMsgs = MAX_DEFAULTMSGS;
+ CHKmalloc(pWrkrData->aProtonMsgs = calloc(MAX_DEFAULTMSGS, sizeof(struct s_protonmsg_entry)));
+
+ CHKiRet(pthread_rwlock_init(&pWrkrData->pnLock, NULL));
+
+ pWrkrData->bThreadRunning = 0;
+ pWrkrData->tid = 0;
+
+ // Run Proton Worker Thread now
+ proton_run_thread(pWrkrData);
+finalize_it:
+ DBGPRINTF("createWrkrInstance[%p] returned %d\n", pWrkrData, iRet);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ DBGPRINTF("freeInstance[%p]: ENTER\n", pData);
+
+ if (pData->stats) {
+ statsobj.Destruct(&pData->stats);
+ }
+
+ /* Free other mem */
+ free(pData->amqp_address);
+ free(pData->azurehost);
+ free(pData->azureport);
+ free(pData->azure_key_name);
+ free(pData->azure_key);
+ free(pData->container);
+
+ free(pData->tplName);
+ free(pData->statsName);
+ for(int i = 0 ; i < pData->nEventProperties ; ++i) {
+ free((void*) pData->eventProperties[i].key);
+ free((void*) pData->eventProperties[i].val);
+ }
+ free(pData->eventProperties);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ DBGPRINTF("freeWrkrInstance[%p]: ENTER\n", pWrkrData);
+
+ /* Closing azure first! */
+ pthread_rwlock_wrlock(&pWrkrData->pnLock);
+
+ // Close Proton Connection
+ closeProton(pWrkrData);
+
+ // Stop Proton Handle Thread
+ proton_shutdown_thread(pWrkrData);
+
+ // Free Proton Ressources
+ if (pWrkrData->pnProactor != NULL) {
+ DBGPRINTF("freeWrkrInstance[%p]: FREE proactor\n", pWrkrData);
+ pn_proactor_free(pWrkrData->pnProactor);
+ pWrkrData->pnProactor = NULL;
+ }
+ free(pWrkrData->pnMessageBuffer.start);
+
+ pthread_rwlock_unlock(&pWrkrData->pnLock);
+
+ // Free our proton helper array
+ if(pWrkrData->aProtonMsgs != NULL) {
+ for(unsigned int i = 0 ; i < pWrkrData->nProtonMsgs ; ++i) {
+ if (pWrkrData->aProtonMsgs[i] != NULL) {
+ protonmsg_entry_destruct(pWrkrData->aProtonMsgs[i]);
+ }
+ }
+ free(pWrkrData->aProtonMsgs);
+ }
+
+ pthread_rwlock_destroy(&pWrkrData->pnLock);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+BEGINtryResume
+CODESTARTtryResume
+#ifndef NDEBUG
+ DBGPRINTF("omazureeventhubs[%p]: tryResume ENTER\n", pWrkrData);
+#endif
+ if (pWrkrData->bIsConnecting == 0 && pWrkrData->bIsConnected == 0) {
+ DBGPRINTF("omazureeventhubs[%p]: tryResume setupProtonHandle\n", pWrkrData);
+ CHKiRet(setupProtonHandle(pWrkrData, SETUP_PROTON_AUTOCLOSE));
+ }
+finalize_it:
+ DBGPRINTF("omazureeventhubs[%p]: tryResume returned %d\n", pWrkrData, iRet);
+ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ /* we have nothing to do to begin a transaction */
+ DBGPRINTF("omazureeventhubs[%p]: beginTransaction ENTER\n", pWrkrData);
+ if (pWrkrData->bIsConnecting == 0 && pWrkrData->bIsConnected == 0) {
+ CHKiRet(setupProtonHandle(pWrkrData, SETUP_PROTON_NONE));
+ }
+finalize_it:
+ RETiRet;
+ENDbeginTransaction
+
+/*
+ * New Transaction action interface
+*/
+BEGINcommitTransaction
+ // instanceData *__restrict__ const pData = pWrkrData->pData;
+ unsigned i;
+ unsigned iNeedSubmission;
+ sbool bDone = 0;
+ protonmsg_entry* pMsgEntry = NULL;
+CODESTARTcommitTransaction
+#ifndef NDEBUG
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction [%d msgs] ENTER\n", pWrkrData, nParams);
+#endif
+
+ // Handle/Expand our proton helper array
+ if (nParams > pWrkrData->nMaxProtonMsgs) {
+ // Free old Array
+ if(pWrkrData->aProtonMsgs != NULL) {
+ free(pWrkrData->aProtonMsgs);
+ }
+ // Expand our proton helper array
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction expand helper array from %d to %d\n",
+ pWrkrData, pWrkrData->nMaxProtonMsgs, nParams);
+ pWrkrData->nMaxProtonMsgs = nParams; // Set new MAX
+ CHKmalloc(pWrkrData->aProtonMsgs = calloc(pWrkrData->nMaxProtonMsgs, sizeof(struct s_protonmsg_entry)));
+ }
+ // Copy count of New Messages and increase MaxMsgSeq
+ pWrkrData->nProtonMsgs = nParams;
+ pWrkrData->iMaxMsgSeq += nParams;
+
+ do {
+ iNeedSubmission = 0;
+ // Put unsubmitted messages into Proton
+ for(i = 0 ; i < nParams ; ++i) {
+ // Get reference to Proton Array Helper
+ pMsgEntry = ((protonmsg_entry*)pWrkrData->aProtonMsgs[i]);
+ if ( pMsgEntry == NULL) {
+ // Send Message to Proton
+ writeProton(pWrkrData, pParams, i);
+ } else if ( pMsgEntry->status == PROTON_REJECTED) {
+ // Reset Message Entry, it will be retried
+ pMsgEntry->status = PROTON_UNSUBMITTED;
+ }
+ }
+ bDone = 1;
+
+ // Wait 100 microseconds
+ srSleep(0, 100000);
+
+ // Verify if messages have been submitted successfully
+ for(i = 0 ; i < nParams ; ++i) {
+ // Get reference to Proton Array Helper
+ pMsgEntry = ((protonmsg_entry*)pWrkrData->aProtonMsgs[i]);
+ if (pMsgEntry != NULL) {
+ if ( pMsgEntry->status == PROTON_UNSUBMITTED) {
+ iNeedSubmission++;
+ // we need to retry check later
+ bDone = 0;
+ } else if ( pMsgEntry->status == PROTON_SUBMITTED) {
+ // we need to retry check later
+ bDone = 0;
+ }
+ }
+ }
+
+ if (iNeedSubmission > 0) {
+ if ( pWrkrData->bIsConnected == 1) {
+ int credits = pn_link_credit(pWrkrData->pnSender);
+ if (pn_link_credit(pWrkrData->pnSender) > 0) {
+ DBGPRINTF("omazureeventhubs[%p]: trigger pn_connection_wake\n",
+ pWrkrData);
+ pn_connection_wake(pWrkrData->pnConn);
+ } else {
+ DBGPRINTF("omazureeventhubs[%p]: warning pn_link_credit returned %d\n",
+ pWrkrData, credits);
+ }
+ } else {
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction Suspended=%s Connecting=%s\n",
+ pWrkrData,
+ pWrkrData->bIsSuspended == 1 ? "YES" : "NO",
+ pWrkrData->bIsConnecting == 1 ? "YES" : "NO");
+ if (pWrkrData->bIsSuspended == 1 && pWrkrData->bIsConnecting == 0) {
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+ }
+ } while (bDone == 0);
+finalize_it:
+ // Free Proton Message Helpers
+ if (pWrkrData->aProtonMsgs != NULL) {
+ for(i = 0 ; i < nParams ; ++i) {
+ if (pWrkrData->aProtonMsgs[i] != NULL) {
+ // Destroy
+ protonmsg_entry_destruct(pWrkrData->aProtonMsgs[i]);
+ pWrkrData->aProtonMsgs[i] = NULL;
+ }
+ }
+ }
+
+ /* TODO: Suspend Action if broker problems were reported in error callback */
+ if (pWrkrData->bIsSuspended == 1) {
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction failed to send messages, suspending action\n",
+ pWrkrData);
+ iRet = RS_RET_SUSPENDED;
+ }
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction failed with status %d\n", pWrkrData, iRet);
+ }
+ DBGPRINTF("omazureeventhubs[%p]: commitTransaction [%d msgs] EXIT\n", pWrkrData, nParams);
+ENDcommitTransaction
+
+static void
+setInstParamDefaults(instanceData *pData) {
+ DBGPRINTF("setInstParamDefaults[%p]: ENTER\n", pData);
+ pData->amqp_address = NULL;
+ pData->azurehost = NULL;
+ pData->azureport = NULL;
+ pData->azure_key_name = NULL;
+ pData->azure_key = NULL;
+ pData->container = NULL;
+ pData->nEventProperties = 0;
+ pData->eventProperties = NULL;
+}
+
+static rsRetVal
+processEventProperty(char *const param,
+ const char **const name,
+ const char **const paramval) {
+ DEFiRet;
+ char *val = strstr(param, "=");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ *val = '\0'; /* terminates name */
+ ++val; /* now points to begin of value */
+ CHKmalloc(*name = strdup(param));
+ CHKmalloc(*paramval = strdup(val));
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int iNumTpls;
+ DBGPRINTF("newActInst: ENTER\n");
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "amqp_address")) {
+ pData->amqp_address = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "azurehost")) {
+ pData->azurehost = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "azureport")) {
+ pData->azureport = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "azure_key_name")) {
+ pData->azure_key_name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "azure_key")) {
+ pData->azure_key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "container")) {
+ pData->container = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "eventproperties")) {
+ pData->nEventProperties = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->eventProperties = malloc(sizeof(struct event_property) *
+ pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processEventProperty(cstr, &pData->eventProperties[j].key,
+ &pData->eventProperties[j].val));
+ free(cstr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "statsname")) {
+ pData->statsName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "omazureeventhubs: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->azure_key_name == NULL || pData->azure_key == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omazureeventhubs: azure_key_name and azure_key are requires to access azure eventhubs"
+ " - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if(pData->container == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omazureeventhubs: Event Hubs \"container\" parameter (which is instance) not specified "
+ " - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if(pData->amqp_address == NULL) {
+ if(pData->azurehost == NULL) {
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "omazureeventhubs: \"azurehost\" parameter not specified "
+ "(youreventhubinstance.servicebus.windows.net- action definition invalid!");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(pData->azureport== NULL) {
+ // Set default
+ CHKmalloc(pData->azureport = (uchar *) strdup("5671"));
+ }
+
+ // Create amqps URL from parameters
+ char szAddress[1024];
+ sprintf(szAddress, "amqps://%s:%s@%s:%s/%s",
+ pData->azure_key_name,
+ pData->azure_key,
+ pData->azurehost,
+ pData->azureport,
+ pData->container);
+ CHKmalloc(pData->amqp_address = (uchar*) strdup(szAddress));
+ }
+
+ iNumTpls = 1;
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls);
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_FileFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ if (pData->statsName) {
+ CHKiRet(statsobj.Construct(&pData->stats));
+ CHKiRet(statsobj.SetName(pData->stats, (uchar *)pData->statsName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar *)"omazureeventhubs"));
+
+ /* Track following stats */
+ STATSCOUNTER_INIT(pData->ctrMessageSubmit, pData->mutCtrMessageSubmit);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrMessageSubmit));
+ STATSCOUNTER_INIT(pData->ctrAzureFail, pData->mutCtrAzureFail);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrAzureFail));
+ STATSCOUNTER_INIT(pData->ctrAzureAck, pData->mutCtrAzureAck);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"accepted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrAzureAck));
+ STATSCOUNTER_INIT(pData->ctrAzureOtherErrors, pData->mutCtrAzureOtherErrors);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"othererrors",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrAzureOtherErrors));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINmodExit
+CODESTARTmodExit
+ DBGPRINTF("modExit: ENTER\n");
+ statsobj.Destruct(&azureStats);
+ CHKiRet(objRelease(statsobj, CORE_COMPONENT));
+ DESTROY_ATOMIC_HELPER_MUT(mutClock);
+
+ objRelease(glbl, CORE_COMPONENT);
+finalize_it:
+ENDmodExit
+
+NO_LEGACY_CONF_parseSelectorAct
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+// uchar *pTmp;
+ DBGPRINTF("modInit: ENTER\n");
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+// INIT_ATOMIC_HELPER_MUT(mutClock);
+ DBGPRINTF("omazureeventhubs %s using qpid-proton library %d.%d.%d\n",
+ VERSION, PN_VERSION_MAJOR, PN_VERSION_MINOR, PN_VERSION_POINT);
+
+ CHKiRet(statsobj.Construct(&azureStats));
+ CHKiRet(statsobj.SetName(azureStats, (uchar *)"omazureeventhubs"));
+ CHKiRet(statsobj.SetOrigin(azureStats, (uchar*)"omazureeventhubs"));
+ STATSCOUNTER_INIT(ctrMessageSubmit, mutCtrMessageSubmit);
+ CHKiRet(statsobj.AddCounter(azureStats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessageSubmit));
+ STATSCOUNTER_INIT(ctrAzureFail, mutCtrAzureFail);
+ CHKiRet(statsobj.AddCounter(azureStats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrAzureFail));
+ STATSCOUNTER_INIT(ctrAzureAck, mutCtrAzureAck);
+ CHKiRet(statsobj.AddCounter(azureStats, (uchar *)"accepted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrAzureAck));
+ STATSCOUNTER_INIT(ctrAzureOtherErrors, mutCtrAzureOtherErrors);
+ CHKiRet(statsobj.AddCounter(azureStats, (uchar *)"failures_other",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrAzureOtherErrors));
+ CHKiRet(statsobj.ConstructFinalize(azureStats));
+ENDmodInit
+
+pn_timestamp_t time_now(void)
+{
+ struct timeval now;
+ if (gettimeofday(&now, NULL)) return 0;
+ return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000);
+}
+
+/*
+* Start PROTON Handling Thread
+*/
+static rsRetVal proton_run_thread(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ int iErr = 0;
+ if ( !pWrkrData->bThreadRunning) {
+ DBGPRINTF("omazureeventhubs[%p]: proton_run_thread\n", pWrkrData);
+
+ do {
+ iErr = pthread_create(&pWrkrData->tid,
+ NULL,
+ proton_thread,
+ pWrkrData);
+ if (!iErr) {
+ pWrkrData->bThreadRunning = 1;
+ DBGPRINTF("omazureeventhubs[%p]: proton_run_thread (tid %lx) created\n",
+ pWrkrData, pWrkrData->tid);
+ FINALIZE;
+ }
+ } while (iErr == EAGAIN);
+ } else {
+ DBGPRINTF("omazureeventhubs[%p]: proton_run_thread (tid %ld) already running\n",
+ pWrkrData, pWrkrData->tid);
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(0, RS_RET_SYS_ERR, "omazureeventhubs: proton_run_thread thread create failed with error: %d",
+ iErr);
+ }
+ RETiRet;
+}
+/* Stop PROTON Handling Thread
+*/
+static rsRetVal
+proton_shutdown_thread(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ if ( pWrkrData->bThreadRunning) {
+ DBGPRINTF("omazureeventhubs[%p]: STOPPING Thread\n", pWrkrData);
+ int r = pthread_cancel(pWrkrData->tid);
+ if(r == 0) {
+ pthread_join(pWrkrData->tid, NULL);
+ }
+ DBGPRINTF("omazureeventhubs[%p]: STOPPED Thread\n", pWrkrData);
+ pWrkrData->bThreadRunning = 0;
+ }
+ FINALIZE;
+finalize_it:
+ RETiRet;
+}
+
+/*
+* Workerthread function for a single ProActor Handler
+ */
+static void *
+proton_thread(void __attribute__((unused)) *pVoidWrkrData)
+{
+ wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *const) pVoidWrkrData;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+
+ DBGPRINTF("proton_thread[%p]: started protocol workerthread(%lx) for %s:%s/%s\n",
+ pWrkrData, pthread_self(), pData->azurehost, pData->azureport, pData->container);
+
+ do {
+ if ( pWrkrData->pnProactor != NULL) {
+ // Process Protocol events
+ pn_event_batch_t *events = pn_proactor_wait(pWrkrData->pnProactor);
+ pn_event_t *event;
+ while ((event = pn_event_batch_next(events))) {
+ handleProton(pWrkrData, event);
+ }
+ pn_proactor_done(pWrkrData->pnProactor, events);
+ } else {
+ // Wait 10 microseconds
+ srSleep(0, 10000);
+ }
+ } while(glbl.GetGlobalInputTermState() == 0);
+
+ DBGPRINTF("proton_thread[%p]: stopped protocol workerthread\n", pWrkrData);
+ return NULL;
+}
+
+static void
+handleProtonDelivery(wrkrInstanceData_t *const pWrkrData) {
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+
+ /* Process messages from ARRAY */
+ for(unsigned int i = 0 ; i < pWrkrData->nProtonMsgs ; ++i) {
+ protonmsg_entry* pMsgEntry = (protonmsg_entry*) pWrkrData->aProtonMsgs[i];
+ // Process Unsubmitted messages only
+ if (pMsgEntry != NULL) {
+ if (pMsgEntry->status == PROTON_UNSUBMITTED) {
+ int iCreditBalance = pn_link_credit(pWrkrData->pnSender);
+ if (iCreditBalance > 0) {
+ DBGPRINTF(
+ "handleProtonDelivery: PN_LINK_FLOW deliver '%s' @ %p:%s:%s/%s, msg:'%.*s'\n",
+ pMsgEntry->MsgID,
+ pWrkrData,
+ pData->azurehost,
+ pData->azureport,
+ pData->container,
+ (pMsgEntry->payload_len > 0 ?
+ (int)pMsgEntry->payload_len-1 : 0),
+ pMsgEntry->payload);
+
+ /* Use sent counter as unique delivery tag. */
+ pn_delivery(pWrkrData->pnSender, pn_dtag((const char *)pMsgEntry->MsgID,
+ pMsgEntry->MsgID_len));
+
+ /* Construct a message with the map */
+ pn_message_t* message = proton_encode_message(pWrkrData, pMsgEntry);
+ /*
+ * pn_message_send does performs the following steps:
+ * - call pn_message_encode2() to encode the message to a buffer
+ * - call pn_link_send() to send the encoded message bytes
+ * - call pn_link_advance() to indicate the message is complete
+ */
+ if (pn_message_send( message,
+ pWrkrData->pnSender,
+ &pWrkrData->pnMessageBuffer) < 0) {
+ LogMsg(0, NO_ERRCODE, LOG_INFO,
+ "handleProtonDelivery: PN_LINK_FLOW deliver SEND ERROR %s\n",
+ pn_error_text(pn_message_error(message)));
+ pn_message_free(message);
+ break;
+ } else {
+ DBGPRINTF("handleProtonDelivery: PN_LINK_FLOW deliver SUCCESS\n");
+ pn_message_free(message);
+ }
+
+ STATSCOUNTER_INC(ctrMessageSubmit, mutCtrMessageSubmit);
+ INST_STATSCOUNTER_INC( pData,
+ pData->ctrMessageSubmit,
+ pData->mutCtrMessageSubmit);
+ pMsgEntry->status = PROTON_SUBMITTED;
+ } else {
+ DBGPRINTF("handleProtonDelivery: sender credit balance reached %d. "
+ "extend credit for %d\n", iCreditBalance, pWrkrData->nProtonMsgs);
+ pn_link_flow(pWrkrData->pnSender, pWrkrData->nProtonMsgs);
+
+ // TODO: MAKE CONFIGUREABLE
+ // Wait 10 microseconds
+ // srSleep(0, 10000);
+ break;
+ }
+ }
+ } else {
+ // Abort further processing if pMsgEntry is NULL
+ break;
+ }
+ }
+}
+
+/* Handles PROTON Communication in this Function
+*
+*/
+#pragma GCC diagnostic ignored "-Wswitch"
+static void
+handleProton(wrkrInstanceData_t *const pWrkrData, pn_event_t *event) {
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ /* Handle Proton Events */
+ switch (pn_event_type(event)) {
+ case PN_CONNECTION_BOUND: {
+ DBGPRINTF("handleProton: PN_CONNECTION_BOUND to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ break;
+ }
+ case PN_SESSION_INIT : {
+ DBGPRINTF("handleProton: PN_SESSION_INIT to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ break;
+ }
+ case PN_LINK_INIT: {
+ DBGPRINTF("handleProton: PN_LINK_INIT to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ break;
+ }
+ case PN_LINK_REMOTE_OPEN: {
+ DBGPRINTF("handleProton: PN_LINK_REMOTE_OPEN to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ pWrkrData->bIsConnected = 1;
+ pWrkrData->bIsConnecting = 0;
+ break;
+ }
+ case PN_CONNECTION_INIT: {
+ DBGPRINTF("handleProton: PN_CONNECTION_INIT to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ pWrkrData->pnStatus = PN_CONNECTION_INIT;
+
+ // Get Connection
+ pWrkrData->pnConn = pn_event_connection(event);
+ // Set AMQP Properties
+ pn_connection_set_container(pWrkrData->pnConn, (const char *) pData->container);
+ pn_connection_set_hostname(pWrkrData->pnConn, (const char *) pData->azurehost);
+ pn_connection_set_user(pWrkrData->pnConn, (const char *) pData->azure_key_name);
+ pn_connection_set_password(pWrkrData->pnConn, (const char *) pData->azure_key);
+
+ pn_connection_open(pWrkrData->pnConn); // Open Connection
+ pn_session_t* pnSession = pn_session(pWrkrData->pnConn); // Create Session
+ pn_session_open(pnSession); // Open Session
+ pWrkrData->pnSender = pn_sender(pnSession, (char *)pData->azure_key_name); // Create Link
+
+ DBGPRINTF("handleProton: PN_CONNECTION_INIT with amqp address: %s\n",
+ pData->amqp_address);
+ pn_terminus_set_address(pn_link_target(pWrkrData->pnSender),
+ (const char *) pData->amqp_address);
+
+ pn_link_open(pWrkrData->pnSender);
+ pn_link_flow(pWrkrData->pnSender, pWrkrData->nProtonMsgs);
+ break;
+ }
+ case PN_CONNECTION_REMOTE_OPEN: {
+ DBGPRINTF("handleProton: PN_CONNECTION_REMOTE_OPEN to %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ pWrkrData->pnStatus = PN_CONNECTION_REMOTE_OPEN;
+ pn_ssl_t *ssl = pn_ssl(pn_event_transport(event));
+ if (ssl) {
+ char name[1024];
+ pn_ssl_get_protocol_name(ssl, name, sizeof(name));
+ {
+ const char *subject = pn_ssl_get_remote_subject(ssl);
+ if (subject) {
+ DBGPRINTF(
+ "handleProton: handleProton secure connection: to %s using %s\n",
+ subject, name);
+ } else {
+ DBGPRINTF(
+ "handleProton: handleProton anonymous connection: using %s\n",
+ name);
+ }
+ fflush(stdout);
+ }
+ }
+ break;
+ }
+ case PN_CONNECTION_WAKE: {
+ DBGPRINTF("handleProton: PN_CONNECTION_WAKE (%d) to %p:%s:%s/%s\n",
+ pWrkrData->nProtonMsgs,
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ /* Process messages */
+ handleProtonDelivery(pWrkrData);
+ break;
+ }
+ case PN_LINK_FLOW: {
+ pWrkrData->pnStatus = PN_LINK_FLOW;
+ /* The peer has given us some credit, now we can send messages */
+ pWrkrData->pnSender = pn_event_link(event);
+
+ /* Process messages */
+ handleProtonDelivery(pWrkrData);
+ break;
+ }
+ case PN_DELIVERY: {
+ pWrkrData->pnStatus = PN_DELIVERY;
+ /* We received acknowledgement from the peer that a message was delivered. */
+ pn_delivery_t* pDeliveryStatus = pn_event_delivery(event);
+ pn_delivery_tag_t pnTag = pn_delivery_tag(pDeliveryStatus);
+
+ if (pnTag.start != NULL) {
+ // Convert Tag into Number!
+ unsigned int iTagNum = (unsigned int) atoi((pnTag.start != NULL ? pnTag.start : ""));
+ // Calc QueueNumber from Tagnum
+ unsigned int iQueueNum = pWrkrData->nProtonMsgs - (pWrkrData->iMaxMsgSeq - iTagNum);
+ // Get proton Msg Helper (checks for out of bound array access)
+ protonmsg_entry* pMsgEntry = NULL;
+ if (pWrkrData->nMaxProtonMsgs > iQueueNum) {
+ pMsgEntry = (protonmsg_entry*) pWrkrData->aProtonMsgs[iQueueNum];
+ }
+ // Process if found
+ if (pMsgEntry != NULL) {
+ if (pn_delivery_remote_state(pDeliveryStatus) == PN_ACCEPTED) {
+ DBGPRINTF(
+ "handleProton: PN_DELIVERY SUCCESS for MSG '%s(Q %d, MAX %d)' @ %p:%s:%s/%s\n",
+ (pnTag.start != NULL ? (char*) pnTag.start : "NULL"),
+ iQueueNum,
+ pWrkrData->nMaxProtonMsgs,
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ pMsgEntry->status = PROTON_ACCEPTED;
+
+ // Increment Stats Counter
+ STATSCOUNTER_INC(ctrAzureAck, mutCtrAzureAck);
+ INST_STATSCOUNTER_INC(pData, pData->ctrAzureAck, pData->mutCtrAzureAck);
+ } else if (pn_delivery_remote_state(pDeliveryStatus) == PN_REJECTED) {
+ LogError(0, RS_RET_ERR,
+ "omazureeventhubs: PN_DELIVERY REJECTED for MSG '%s'"
+ " - @ %p:%s:%s/%s\n",
+ (pnTag.start != NULL ? (char*) pnTag.start : "NULL"),
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ pMsgEntry->status = PROTON_REJECTED;
+
+ // Increment Stats Counter
+ STATSCOUNTER_INC(ctrAzureFail, mutCtrAzureFail);
+ INST_STATSCOUNTER_INC(pData, pData->ctrAzureFail, pData->mutCtrAzureFail);
+ }
+ } else {
+ DBGPRINTF("handleProton: PN_DELIVERY MISSING MSG '%d(Q %d,MAX %d)' - @ %p:%s:%s/%s\n",
+ iTagNum,
+ iQueueNum,
+ pWrkrData->nMaxProtonMsgs,
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ STATSCOUNTER_INC(ctrAzureOtherErrors, mutCtrAzureOtherErrors);
+ INST_STATSCOUNTER_INC(pData, pData->ctrAzureOtherErrors, pData->mutCtrAzureOtherErrors);
+ }
+ } else {
+ LogError(0, RS_RET_ERR,"handleProton: PN_DELIVERY HELPER ARRAY is NULL - @ %p:%s:%s/%s\n",
+ pWrkrData, pData->azurehost, pData->azureport, pData->container);
+ STATSCOUNTER_INC(ctrAzureOtherErrors, mutCtrAzureOtherErrors);
+ INST_STATSCOUNTER_INC(pData, pData->ctrAzureOtherErrors, pData->mutCtrAzureOtherErrors);
+ }
+ break;
+ }
+ case PN_TRANSPORT_CLOSED:
+ DBGPRINTF("handleProton: transport closed for %p:%s\n", pWrkrData, pData->azurehost);
+ proton_check_condition(event, pWrkrData, pn_transport_condition(pn_event_transport(event)),
+ "transport closed");
+ break;
+ case PN_CONNECTION_REMOTE_CLOSE:
+ DBGPRINTF("handleProton: connection closed for %p:%s\n", pWrkrData, pData->azurehost);
+ proton_check_condition(event, pWrkrData, pn_connection_remote_condition(pn_event_connection(event)),
+ "connection closed");
+ break;
+ case PN_SESSION_REMOTE_CLOSE:
+ DBGPRINTF("handleProton: remote session closed for %p:%s\n", pWrkrData, pData->azurehost);
+ proton_check_condition(event, pWrkrData, pn_session_remote_condition(pn_event_session(event)),
+ "remote session closed");
+ break;
+ case PN_LINK_REMOTE_CLOSE:
+ case PN_LINK_REMOTE_DETACH:
+ DBGPRINTF("handleProton: remote link closed for %p:%s\n", pWrkrData, pData->azurehost);
+ proton_check_condition(event, pWrkrData, pn_link_remote_condition(pn_event_link(event)),
+ "remote link closed");
+ break;
+ case PN_PROACTOR_INACTIVE:
+ DBGPRINTF("handleProton: INAKTIVE for %p:%s\n", pWrkrData, pData->azurehost);
+ break;
+/* Workarround compiler warning:
+* error: enumeration value '...' not handled in switch [-Werror=switch-enum]
+*/
+#ifdef __GNU_C
+ default:
+ DBGPRINTF("handleProton: UNHANDELED EVENT %d for %p:%s\n", pn_event_type(event),
+ pWrkrData, pData->azurehost);
+ break;
+#endif
+ }
+}
diff --git a/plugins/omclickhouse/Makefile.am b/plugins/omclickhouse/Makefile.am
new file mode 100644
index 0000000..8ddd358
--- /dev/null
+++ b/plugins/omclickhouse/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omclickhouse.la
+
+omclickhouse_la_SOURCES = omclickhouse.c
+omclickhouse_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omclickhouse_la_LDFLAGS = -module -avoid-version
+omclickhouse_la_LIBADD = $(CURL_LIBS) $(LIBM)
+
+EXTRA_DIST =
diff --git a/plugins/omclickhouse/Makefile.in b/plugins/omclickhouse/Makefile.in
new file mode 100644
index 0000000..2a04c8f
--- /dev/null
+++ b/plugins/omclickhouse/Makefile.in
@@ -0,0 +1,800 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omclickhouse
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omclickhouse_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_omclickhouse_la_OBJECTS = omclickhouse_la-omclickhouse.lo
+omclickhouse_la_OBJECTS = $(am_omclickhouse_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 =
+omclickhouse_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(omclickhouse_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omclickhouse_la-omclickhouse.Plo
+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 = $(omclickhouse_la_SOURCES)
+DIST_SOURCES = $(omclickhouse_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omclickhouse.la
+omclickhouse_la_SOURCES = omclickhouse.c
+omclickhouse_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omclickhouse_la_LDFLAGS = -module -avoid-version
+omclickhouse_la_LIBADD = $(CURL_LIBS) $(LIBM)
+EXTRA_DIST =
+all: 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) --gnu plugins/omclickhouse/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omclickhouse/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omclickhouse.la: $(omclickhouse_la_OBJECTS) $(omclickhouse_la_DEPENDENCIES) $(EXTRA_omclickhouse_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omclickhouse_la_LINK) -rpath $(pkglibdir) $(omclickhouse_la_OBJECTS) $(omclickhouse_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omclickhouse_la-omclickhouse.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omclickhouse_la-omclickhouse.lo: omclickhouse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omclickhouse_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omclickhouse_la-omclickhouse.lo -MD -MP -MF $(DEPDIR)/omclickhouse_la-omclickhouse.Tpo -c -o omclickhouse_la-omclickhouse.lo `test -f 'omclickhouse.c' || echo '$(srcdir)/'`omclickhouse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omclickhouse_la-omclickhouse.Tpo $(DEPDIR)/omclickhouse_la-omclickhouse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omclickhouse.c' object='omclickhouse_la-omclickhouse.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) $(omclickhouse_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omclickhouse_la-omclickhouse.lo `test -f 'omclickhouse.c' || echo '$(srcdir)/'`omclickhouse.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omclickhouse_la-omclickhouse.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omclickhouse_la-omclickhouse.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omclickhouse/omclickhouse.c b/plugins/omclickhouse/omclickhouse.c
new file mode 100644
index 0000000..2c67e5e
--- /dev/null
+++ b/plugins/omclickhouse/omclickhouse.c
@@ -0,0 +1,1032 @@
+/* omclickhouse.c
+ * This is the https://clickhouse.yandex/ output module.
+ *
+ * Copyright 2018 Pascal Withopf and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(__FreeBSD__)
+#include <unistd.h>
+#endif
+#include <json.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "statsobj.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "obj-types.h"
+#include "ratelimit.h"
+#include "ruleset.h"
+
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omclickhouse")
+
+/* internal structures */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+statsobj_t *indexStats;
+STATSCOUNTER_DEF(indexSubmit, mutIndexSubmit)
+STATSCOUNTER_DEF(indexHTTPFail, mutIndexHTTPFail)
+STATSCOUNTER_DEF(indexHTTPReqFail, mutIndexHTTPReqFail)
+STATSCOUNTER_DEF(indexFail, mutIndexFail)
+STATSCOUNTER_DEF(indexSuccess, mutIndexSuccess)
+
+
+
+typedef struct curl_slist HEADER;
+typedef struct instanceConf_s {
+ uchar *serverBaseUrl;
+ int port;
+ uchar *user;
+ uchar *pwd;
+ long healthCheckTimeout;
+ long timeout;
+ uchar *authBuf;
+ uchar *tplName;
+ sbool useHttps;
+ sbool allowUnsignedCerts;
+ sbool skipVerifyHost;
+ int fdErrFile;
+ uchar *errorFile;
+ sbool bulkmode;
+ size_t maxbytes;
+ uchar *caCertFile;
+ uchar *myCertFile;
+ uchar *myPrivKeyFile;
+ struct instanceConf_s *next;
+} instanceData;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+};
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+
+typedef struct wrkrInstanceData {
+ PTR_ASSERT_DEF
+ instanceData *pData;
+ CURL *curlPostHandle; /* libcurl session handle for posting data to the server */
+ HEADER *curlHeader; /* json POST request info */
+ CURL *curlCheckConnHandle; /* libcurl session handle for checking the server connection */
+ int replyLen;
+ char *reply;
+ uchar *restURL;
+ struct {
+ es_str_t *data;
+ int nmemb; /* number of messages in batch (for statistics counting) */
+ } batch;
+ sbool insertErrorSent; /* needed for insert error message */
+} wrkrInstanceData_t;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrInt, 0 },
+ { "user", eCmdHdlrGetWord, 0 },
+ { "pwd", eCmdHdlrGetWord, 0 },
+ { "healthchecktimeout", eCmdHdlrInt, 0 },
+ { "timeout", eCmdHdlrInt, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "usehttps", eCmdHdlrBinary, 0 },
+ { "allowunsignedcerts", eCmdHdlrBinary, 0 },
+ { "skipverifyhost", eCmdHdlrBinary, 0 },
+ { "errorfile", eCmdHdlrGetWord, 0 },
+ { "bulkmode", eCmdHdlrBinary, 0 },
+ { "maxbytes", eCmdHdlrSize, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static rsRetVal curlSetup(wrkrInstanceData_t *pWrkrData);
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->fdErrFile = -1;
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->curlHeader = NULL;
+ pWrkrData->curlPostHandle = NULL;
+ pWrkrData->curlCheckConnHandle = NULL;
+ pWrkrData->restURL = NULL;
+ if(pData->bulkmode) {
+ if((pWrkrData->batch.data = es_newStr(1024)) == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omclickhouse: error creating batch string "
+ "turned off bulk mode\n");
+ pData->bulkmode = 0; /* at least it works */
+ }
+ }
+ pWrkrData->insertErrorSent = 0;
+
+ iRet = curlSetup(pWrkrData);
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->serverBaseUrl);
+ free(pData->user);
+ free(pData->pwd);
+ free(pData->authBuf);
+ if(pData->fdErrFile != -1)
+ close(pData->fdErrFile);
+ free(pData->errorFile);
+ free(pData->tplName);
+ free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if(pWrkrData->curlHeader != NULL) {
+ curl_slist_free_all(pWrkrData->curlHeader);
+ pWrkrData->curlHeader = NULL;
+ }
+ if(pWrkrData->curlCheckConnHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlCheckConnHandle);
+ pWrkrData->curlCheckConnHandle = NULL;
+ }
+ if(pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+ if (pWrkrData->restURL != NULL) {
+ free(pWrkrData->restURL);
+ pWrkrData->restURL = NULL;
+ }
+ es_deleteStr(pWrkrData->batch.data);
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omclickhouse\n");
+ dbgprintf("\tserver='%s'\n", pData->serverBaseUrl);
+ dbgprintf("\tport='%d'\n", pData->port);
+ dbgprintf("\tuser='%s'\n", pData->user);
+ dbgprintf("\tpwd='%s'\n", pData->pwd);
+ dbgprintf("\thealthCheckTimeout=%lu\n", pData->healthCheckTimeout);
+ dbgprintf("\ttimeout=%lu\n", pData->timeout);
+ dbgprintf("\ttemplate='%s'\n", pData->tplName);
+ dbgprintf("\tusehttps='%d'\n", pData->useHttps);
+ dbgprintf("\tallowunsignedcerts='%d'\n", pData->allowUnsignedCerts);
+ dbgprintf("\tskipverifyhost='%d'\n", pData->skipVerifyHost);
+ dbgprintf("\terrorFile='%s'\n", pData->errorFile);
+ dbgprintf("\tbulkmode='%d'\n", pData->bulkmode);
+ dbgprintf("\tmaxbytes='%zu'\n", pData->maxbytes);
+ dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
+ENDdbgPrintInstInfo
+
+
+/* checks if connection to clickhouse can be established
+ */
+static rsRetVal ATTR_NONNULL()
+checkConn(wrkrInstanceData_t *const pWrkrData)
+{
+ CURL *curl;
+ CURLcode res;
+ char errbuf[CURL_ERROR_SIZE] = "";
+ const char* healthCheckMessage ="SELECT 1";
+ DEFiRet;
+
+ pWrkrData->reply = NULL;
+ pWrkrData->replyLen = 0;
+ curl = pWrkrData->curlCheckConnHandle;
+
+
+ curl_easy_setopt(curl, CURLOPT_URL, pWrkrData->restURL);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, healthCheckMessage);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(healthCheckMessage));
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+ res = curl_easy_perform(curl);
+
+ if (res == CURLE_OK) {
+ DBGPRINTF("omclickhouse: checkConn completed with success\n");
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ DBGPRINTF("omclickhouse: checkConn failed: %s\n",
+ curl_easy_strerror(res));
+
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "omclickhouse: checkConn failed.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+
+finalize_it:
+ free(pWrkrData->reply);
+ pWrkrData->reply = NULL; /* don't leave dangling pointer */
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ dbgprintf("omclickhouse: tryResume called\n");
+ iRet = checkConn(pWrkrData);
+ENDtryResume
+
+
+/*
+ * Dumps entire bulk request and response in error log
+ */
+static rsRetVal
+getDataErrorDefault(wrkrInstanceData_t *pWrkrData, char *reply, uchar *reqmsg, char **rendered)
+{
+ DEFiRet;
+ fjson_object *req=NULL;
+ fjson_object *errRoot=NULL;
+
+ if((req=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ fjson_object_object_add(req, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ fjson_object_object_add(req, "postdata", fjson_object_new_string((char*)reqmsg));
+
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ fjson_object_object_add(errRoot, "request", req);
+ fjson_object_object_add(errRoot, "reply", fjson_object_new_string(reply));
+ *rendered = strdup((char*)fjson_object_to_json_string(errRoot));
+
+ req=NULL;
+ fjson_object_put(errRoot);
+
+ finalize_it:
+ fjson_object_put(req);
+ RETiRet;
+}
+
+
+/* write data error request/replies to separate error file
+ * Note: we open the file but never close it before exit. If it
+ * needs to be closed, HUP must be sent.
+ */
+static rsRetVal ATTR_NONNULL()
+writeDataError(wrkrInstanceData_t *const pWrkrData, uchar *const reqmsg)
+{
+ DEFiRet;
+ instanceData *pData = pWrkrData->pData;
+ char *rendered = pWrkrData->reply;
+ size_t toWrite;
+ ssize_t wrRet;
+
+ if(pData->errorFile == NULL) {
+ dbgprintf("omclickhouse: no local error logger defined - "
+ "ignoring ClickHouse error information\n");
+ FINALIZE;
+ }
+
+
+ if(pData->fdErrFile == -1) {
+ pData->fdErrFile = open((char*)pData->errorFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pData->fdErrFile == -1) {
+ LogError(errno, RS_RET_ERR, "omclickhouse: error opening error file %s",
+ pData->errorFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ if(getDataErrorDefault(pWrkrData, pWrkrData->reply, reqmsg, &rendered) != RS_RET_OK) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* we do not do real error-handling on the err file, as this finally complicates
+ * things way to much.
+ */
+ dbgprintf("omclickhouse: message sent: '%s'\n", reqmsg);
+ dbgprintf("omclickhouse: error record: '%s'\n", rendered);
+ toWrite = strlen(rendered) + 1;
+ /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid
+ * caling malloc() -- write() does NOT need '\0'!
+ */
+ rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+ wrRet = write(pData->fdErrFile, rendered, toWrite);
+ if(wrRet != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "omclickhouse: error writing error file %s, write returned %lld",
+ pData->errorFile, (long long) wrRet);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+checkResult(wrkrInstanceData_t *pWrkrData, uchar *reqmsg)
+{
+ DEFiRet;
+
+ if((strstr(pWrkrData->reply, " = DB::Exception" ) != NULL)
+ || (strstr(pWrkrData->reply, "DB::NetException" ) != NULL)
+ || (strstr(pWrkrData->reply, "DB::ParsingException" ) != NULL)) {
+ dbgprintf("omclickhouse: action failed with error: %s\n", pWrkrData->reply);
+ iRet = RS_RET_DATAFAIL;
+ }
+
+ if(iRet == RS_RET_DATAFAIL) {
+ STATSCOUNTER_INC(indexFail, mutIndexFail);
+ writeDataError(pWrkrData, reqmsg);
+ iRet = RS_RET_OK; /* we have handled the problem! */
+ }
+
+
+ if(iRet != RS_RET_OK) {
+ STATSCOUNTER_INC(indexFail, mutIndexFail);
+ }
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL(1)
+setPostURL(wrkrInstanceData_t *const pWrkrData)
+{
+ char* baseUrl;
+ es_str_t *url;
+ DEFiRet;
+ instanceData *const pData = pWrkrData->pData;
+
+ baseUrl = (char*)pData->serverBaseUrl;
+ url = es_newStrFromCStr(baseUrl, strlen(baseUrl));
+ if (url == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omclickhouse: error allocating new estr for POST url.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(pWrkrData->restURL != NULL)
+ free(pWrkrData->restURL);
+
+ pWrkrData->restURL = (uchar*)es_str2cstr(url, NULL);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_URL, pWrkrData->restURL);
+ dbgprintf("omclickhouse: using REST URL: '%s'\n", pWrkrData->restURL);
+
+finalize_it:
+ if (url != NULL)
+ es_deleteStr(url);
+ RETiRet;
+}
+
+
+/* this method computes the next data set to be added to the batch
+ * returns the expected size of adding the next message into the
+ * batched request to clickhouse
+ */
+static size_t
+computeBulkMessage(const wrkrInstanceData_t *const pWrkrData,
+ const uchar *const message, char **newMessage)
+{
+ size_t r = 0;
+ char *v;
+ if (pWrkrData->batch.nmemb != 0
+ && (v = strstr((const char *)message, "VALUES")) != NULL
+ && (v = strchr(v, '(')) != NULL
+ ) {
+ *newMessage = v;
+ r = strlen(*newMessage);
+ } else {
+ *newMessage = (char*)message;
+ r = strlen(*newMessage);
+ }
+ dbgprintf("omclickhouse: computeBulkMessage: new message part: %s\n", *newMessage);
+
+ return r;
+}
+
+
+/* This method builds the batch, that will be submitted.
+ */
+static rsRetVal
+buildBatch(wrkrInstanceData_t *pWrkrData, char *message)
+{
+ DEFiRet;
+ int length = strlen(message);
+ int r;
+
+ r = es_addBuf(&pWrkrData->batch.data, message, length);
+ if(r != 0) {
+ LogError(0, RS_RET_ERR, "omclickhouse: growing batch failed with code %d", r);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ ++pWrkrData->batch.nmemb;
+ iRet = RS_RET_OK;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static void ATTR_NONNULL()
+initializeBatch(wrkrInstanceData_t *pWrkrData)
+{
+ es_emptyStr(pWrkrData->batch.data);
+ pWrkrData->batch.nmemb = 0;
+}
+
+
+static rsRetVal ATTR_NONNULL(1, 2)
+curlPost(wrkrInstanceData_t *pWrkrData, uchar *message, int msglen, const int nmsgs)
+{
+ CURLcode code;
+ CURL *const curl = pWrkrData->curlPostHandle;
+ char errbuf[CURL_ERROR_SIZE] = "";
+ DEFiRet;
+
+ if(!strstr((char*)message, "INSERT INTO") && !pWrkrData->insertErrorSent) {
+ indexHTTPFail += nmsgs;
+ LogError(0, RS_RET_ERR, "omclickhouse: Message is no Insert query: "
+ "Message suspended: %s", (char*)message);
+ pWrkrData->insertErrorSent = 1;
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ pWrkrData->reply = NULL;
+ pWrkrData->replyLen = 0;
+
+ CHKiRet(setPostURL(pWrkrData));
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *)message);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msglen);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+ code = curl_easy_perform(curl);
+ dbgprintf("curl returned %lld\n", (long long) code);
+ if (code != CURLE_OK && code != CURLE_HTTP_RETURNED_ERROR) {
+ STATSCOUNTER_INC(indexHTTPReqFail, mutIndexHTTPReqFail);
+ indexHTTPFail += nmsgs;
+ LogError(0, RS_RET_SUSPENDED,
+ "omclickhouse: we are suspending ourselfs due "
+ "to server failure %lld: %s", (long long) code, errbuf);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if(pWrkrData->reply == NULL) {
+ dbgprintf("omclickhouse: pWrkrData reply==NULL, replyLen = '%d'\n",
+ pWrkrData->replyLen);
+ STATSCOUNTER_INC(indexSuccess, mutIndexSuccess);
+ } else {
+ dbgprintf("omclickhouse: pWrkrData replyLen = '%d'\n", pWrkrData->replyLen);
+ if(pWrkrData->replyLen > 0) {
+ pWrkrData->reply[pWrkrData->replyLen] = '\0';
+ /* Append 0 Byte if replyLen is above 0 - byte has been reserved in malloc */
+ }
+ dbgprintf("omclickhouse: pWrkrData reply: '%s'\n", pWrkrData->reply);
+ CHKiRet(checkResult(pWrkrData, message));
+ }
+
+finalize_it:
+ free(pWrkrData->reply);
+ pWrkrData->reply = NULL; /* don't leave dangling pointer */
+ RETiRet;
+}
+
+
+static rsRetVal
+submitBatch(wrkrInstanceData_t *pWrkrData)
+{
+ char *cstr = NULL;
+ DEFiRet;
+
+ cstr = es_str2cstr(pWrkrData->batch.data, NULL);
+ dbgprintf("omclickhouse: submitBatch, batch: '%s'\n", cstr);
+
+ CHKiRet(curlPost(pWrkrData, (uchar*) cstr, strlen(cstr), pWrkrData->batch.nmemb));
+
+finalize_it:
+ free(cstr);
+ RETiRet;
+}
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ if(!pWrkrData->pData->bulkmode) {
+ FINALIZE;
+ }
+
+ initializeBatch(pWrkrData);
+finalize_it:
+ENDbeginTransaction
+
+
+BEGINdoAction
+ char *batchPart = NULL;
+CODESTARTdoAction
+ dbgprintf("CODESTARTdoAction: entered\n");
+ STATSCOUNTER_INC(indexSubmit, mutIndexSubmit);
+
+ if(pWrkrData->pData->bulkmode) {
+ const size_t nBytes = computeBulkMessage(pWrkrData, ppString[0], &batchPart);
+ dbgprintf("pascal: doAction: message: %s\n", batchPart);
+
+ /* If max bytes is set and this next message will put us over the limit,
+ * submit the current buffer and reset */
+ if(pWrkrData->pData->maxbytes > 0
+ && es_strlen(pWrkrData->batch.data) + nBytes > pWrkrData->pData->maxbytes) {
+
+ dbgprintf("omclickhouse: maxbytes limit reached, submitting partial "
+ "batch of %d elements.\n", pWrkrData->batch.nmemb);
+ CHKiRet(submitBatch(pWrkrData));
+ initializeBatch(pWrkrData);
+ batchPart = (char*)ppString[0];
+ }
+
+ CHKiRet(buildBatch(pWrkrData, batchPart));
+
+ iRet = pWrkrData->batch.nmemb == 1 ? RS_RET_PREVIOUS_COMMITTED : RS_RET_DEFER_COMMIT;
+ } else {
+ CHKiRet(curlPost(pWrkrData, ppString[0], strlen((char*)ppString[0]), 1));
+ }
+finalize_it:
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+/* End Transaction only if batch data is not empty */
+ if (pWrkrData->batch.data != NULL && pWrkrData->batch.nmemb > 0) {
+ CHKiRet(submitBatch(pWrkrData));
+ } else {
+ dbgprintf("omclickhouse: endTransaction, pWrkrData->batch.data is NULL, "
+ "nothing to send. \n");
+ }
+finalize_it:
+ENDendTransaction
+
+static void ATTR_NONNULL()
+setInstParamDefaults(instanceData *const pData)
+{
+ pData->serverBaseUrl = NULL;
+ pData->port = 8123;
+ pData->user = NULL;
+ pData->pwd = NULL;
+ pData->healthCheckTimeout = 3500;
+ pData->timeout = 0;
+ pData->authBuf = NULL;
+ pData->tplName = NULL;
+ pData->useHttps = 1;
+ pData->allowUnsignedCerts = 1;
+ pData->skipVerifyHost = 0;
+ pData->errorFile = NULL;
+ pData->bulkmode = 1;
+ pData->maxbytes = 104857600; //100MB
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+}
+
+/* POST result string ... useful for debugging */
+static size_t
+curlResult(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ char *p = (char *)ptr;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t*) userdata;
+ char *buf;
+ size_t newlen;
+ newlen = pWrkrData->replyLen + size*nmemb;
+ if((buf = realloc(pWrkrData->reply, newlen + 1)) == NULL) {
+ LogError(errno, RS_RET_ERR, "omclickhouse: realloc failed in curlResult");
+ return 0; /* abort due to failure */
+ }
+ memcpy(buf+pWrkrData->replyLen, p, size*nmemb);
+ pWrkrData->replyLen = newlen;
+ pWrkrData->reply = buf;
+ return size*nmemb;
+}
+
+static void ATTR_NONNULL()
+curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle)
+{
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader);
+ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData);
+ if(pWrkrData->pData->allowUnsignedCerts)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE);
+ if(pWrkrData->pData->skipVerifyHost)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, FALSE);
+ if(pWrkrData->pData->authBuf != NULL) {
+ curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf);
+ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+ }
+
+ if(pWrkrData->pData->caCertFile) {
+ curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
+ }
+ if(pWrkrData->pData->myCertFile) {
+ curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
+ }
+ if(pWrkrData->pData->myPrivKeyFile) {
+ curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
+ }
+ /* uncomment for in-dept debuggung:
+ curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */
+}
+
+
+static void ATTR_NONNULL()
+curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ curlSetupCommon(pWrkrData, pWrkrData->curlCheckConnHandle);
+ curl_easy_setopt(pWrkrData->curlCheckConnHandle,
+ CURLOPT_TIMEOUT_MS, pWrkrData->pData->healthCheckTimeout);
+}
+
+
+static void ATTR_NONNULL(1)
+curlPostSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ curlSetupCommon(pWrkrData, pWrkrData->curlPostHandle);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_POST, 1);
+ if(pWrkrData->pData->timeout) {
+ curl_easy_setopt(pWrkrData->curlPostHandle,
+ CURLOPT_TIMEOUT_MS, pWrkrData->pData->timeout);
+ }
+}
+
+#define CONTENT_JSON "Content-Type: application/json; charset=utf-8"
+
+static rsRetVal ATTR_NONNULL()
+curlSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ DEFiRet;
+ pWrkrData->curlHeader = curl_slist_append(NULL, CONTENT_JSON);
+ CHKmalloc(pWrkrData->curlPostHandle = curl_easy_init());
+ curlPostSetup(pWrkrData);
+
+ CHKmalloc(pWrkrData->curlCheckConnHandle = curl_easy_init());
+ curlCheckConnSetup(pWrkrData);
+
+finalize_it:
+ if(iRet != RS_RET_OK && pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+computeAuthHeader(char* user, char* pwd, uchar** authBuf)
+{
+ DEFiRet;
+ int r;
+
+ es_str_t* auth = es_newStr(1024);
+ if (auth == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omclickhouse: failed to allocate es_str auth for auth header construction");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ r = es_addBuf(&auth, user, strlen(user));
+ if(r == 0)
+ r = es_addChar(&auth, ':');
+ if(r == 0 && pwd != NULL)
+ r = es_addBuf(&auth, pwd, strlen(pwd));
+ if(r == 0)
+ *authBuf = (uchar*) es_str2cstr(auth, NULL);
+
+ if (r != 0 || *authBuf == NULL) {
+ LogError(0, RS_RET_ERR, "omclickhouse: failed to build auth header\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if (auth != NULL)
+ es_deleteStr(auth);
+ RETiRet;
+}
+
+/* Build basic URL part, which includes hostname, port, user, pwd as follows:
+ * http://user:pwd@hostname:port/ based on a server param
+ * Newly creates a cstr for this purpose.
+ */
+static rsRetVal
+computeBaseUrl(const char* server, const int port, const sbool useHttps, instanceData *pData)
+{
+# define SCHEME_HTTPS "https://"
+# define SCHEME_HTTP "http://"
+
+ char portBuf[64];
+ int r = 0;
+ const char *host = server;
+ DEFiRet;
+
+ assert(server[strlen(server)-1] != '/');
+
+ es_str_t *urlBuf = es_newStr(256);
+ if (urlBuf == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omclickhouse: failed to allocate es_str urlBuf in computeBaseUrl");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* Find where the hostname/ip of the server starts. If the scheme is not specified
+ in the uri, start the buffer with a scheme corresponding to the useHttps parameter.
+ */
+ if(strcasestr(server, SCHEME_HTTP)) {
+ host = server + strlen(SCHEME_HTTP);
+ } else if(strcasestr(server, SCHEME_HTTPS)) {
+ host = server + strlen(SCHEME_HTTPS);
+ } else {
+ r = useHttps ? es_addBuf(&urlBuf, SCHEME_HTTPS, sizeof(SCHEME_HTTPS)-1) :
+ es_addBuf(&urlBuf, SCHEME_HTTP, sizeof(SCHEME_HTTP)-1);
+ }
+ if (r == 0)
+ r = es_addBuf(&urlBuf, (char *)server, strlen(server));
+ if (r == 0 && !strchr(host, ':')) {
+ snprintf(portBuf, sizeof(portBuf), ":%d", port);
+ r = es_addBuf(&urlBuf, portBuf, strlen(portBuf));
+ }
+ if (r == 0)
+ r = es_addChar(&urlBuf, '/');
+ if (r == 0)
+ pData->serverBaseUrl = (uchar*) es_str2cstr(urlBuf, NULL);
+
+ if (r != 0 || pData->serverBaseUrl == NULL) {
+ LogError(0, RS_RET_ERR, "omclickhouse: error occurred computing baseUrl from "
+ "server %s", server);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ if (urlBuf) {
+ es_deleteStr(urlBuf);
+ }
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *server = NULL;
+ int i;
+ FILE *fp;
+ char errStr[1024];
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ server = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "user")) {
+ pData->user = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ pData->pwd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "healthchecktimeout")) {
+ pData->healthCheckTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "timeout")) {
+ pData->timeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "usehttps")) {
+ pData->useHttps = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
+ pData->allowUnsignedCerts = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "skipverifyhost")) {
+ pData->skipVerifyHost = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "errorfile")) {
+ pData->errorFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "bulkmode")) {
+ pData->bulkmode = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "maxbytes")) {
+ pData->maxbytes = (size_t) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ pData->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->caCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: omclickhouse: 'tls.cacert' file %s couldn't be accessed: %s\n",
+ pData->caCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: omclickhouse: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: omclickhouse: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR, "omclickhouse: program error, "
+ "non-handled param '%s'", actpblk.descr[i].name);
+ }
+ }
+
+
+ if(pData->user == NULL && pData->pwd != NULL) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "omclickhouse: No user was specified "
+ "but a password was given.");
+ }
+
+ if(pData->user != NULL)
+ CHKiRet(computeAuthHeader((char*) pData->user, (char*) pData->pwd, &pData->authBuf));
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ " StdClickHouseFmt" : (char*)pData->tplName), OMSR_RQD_TPL_OPT_SQL));
+
+ if(server != NULL) {
+ CHKiRet(computeBaseUrl((const char*)server, pData->port, pData->useHttps, pData));
+ } else {
+ LogMsg(0, RS_RET_OK, LOG_WARNING,
+ "omclickhouse: No servers specified, using localhost");
+ CHKiRet(computeBaseUrl("localhost", pData->port, pData->useHttps,
+ pData));
+ }
+
+ /* node created, let's add to list of instance configs for the module */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = pData;
+ } else {
+ loadModConf->tail->next = pData;
+ loadModConf->tail = pData;
+ }
+
+CODE_STD_FINALIZERnewActInst
+ free(server);
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->root = pModConf->tail = NULL;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ if(pData->fdErrFile != -1) {
+ close(pData->fdErrFile);
+ pData->fdErrFile = -1;
+ }
+ENDdoHUP
+
+
+BEGINmodExit
+CODESTARTmodExit
+ curl_global_cleanup();
+ statsobj.Destruct(&indexStats);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -indexing disabled");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&indexStats));
+ CHKiRet(statsobj.SetName(indexStats, (uchar *)"omclickhouse"));
+ CHKiRet(statsobj.SetOrigin(indexStats, (uchar *)"omclickhouse"));
+ STATSCOUNTER_INIT(indexSubmit, mutIndexSubmit);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexSubmit));
+ STATSCOUNTER_INIT(indexHTTPFail, mutIndexHTTPFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.http",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexHTTPFail));
+ STATSCOUNTER_INIT(indexHTTPReqFail, mutIndexHTTPReqFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.httprequests",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexHTTPReqFail));
+ STATSCOUNTER_INIT(indexFail, mutIndexFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.clickhouse",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexFail));
+ STATSCOUNTER_INIT(indexSuccess, mutIndexSuccess);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.success",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexSuccess));
+ CHKiRet(statsobj.ConstructFinalize(indexStats));
+
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/omdtls/Makefile.am b/plugins/omdtls/Makefile.am
new file mode 100644
index 0000000..8451028
--- /dev/null
+++ b/plugins/omdtls/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = omdtls.la
+omdtls_la_DEPENDENCIES = ../../runtime/lmnsd_ossl.la
+omdtls_la_SOURCES = omdtls.c
+omdtls_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+omdtls_la_LDFLAGS = -module -avoid-version
+omdtls_la_LIBADD = $(OPENSSL_LIBS) ../../runtime/lmnsd_ossl.la
diff --git a/plugins/omdtls/Makefile.in b/plugins/omdtls/Makefile.in
new file mode 100644
index 0000000..6978ece
--- /dev/null
+++ b/plugins/omdtls/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omdtls
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_omdtls_la_OBJECTS = omdtls_la-omdtls.lo
+omdtls_la_OBJECTS = $(am_omdtls_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 =
+omdtls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omdtls_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omdtls_la-omdtls.Plo
+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 = $(omdtls_la_SOURCES)
+DIST_SOURCES = $(omdtls_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omdtls.la
+omdtls_la_DEPENDENCIES = ../../runtime/lmnsd_ossl.la
+omdtls_la_SOURCES = omdtls.c
+omdtls_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+omdtls_la_LDFLAGS = -module -avoid-version
+omdtls_la_LIBADD = $(OPENSSL_LIBS) ../../runtime/lmnsd_ossl.la
+all: 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) --gnu plugins/omdtls/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omdtls/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omdtls.la: $(omdtls_la_OBJECTS) $(omdtls_la_DEPENDENCIES) $(EXTRA_omdtls_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omdtls_la_LINK) -rpath $(pkglibdir) $(omdtls_la_OBJECTS) $(omdtls_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omdtls_la-omdtls.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omdtls_la-omdtls.lo: omdtls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omdtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omdtls_la-omdtls.lo -MD -MP -MF $(DEPDIR)/omdtls_la-omdtls.Tpo -c -o omdtls_la-omdtls.lo `test -f 'omdtls.c' || echo '$(srcdir)/'`omdtls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omdtls_la-omdtls.Tpo $(DEPDIR)/omdtls_la-omdtls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdtls.c' object='omdtls_la-omdtls.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) $(omdtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omdtls_la-omdtls.lo `test -f 'omdtls.c' || echo '$(srcdir)/'`omdtls.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omdtls_la-omdtls.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omdtls_la-omdtls.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omdtls/omdtls.c b/plugins/omdtls/omdtls.c
new file mode 100644
index 0000000..c5ba167
--- /dev/null
+++ b/plugins/omdtls/omdtls.c
@@ -0,0 +1,853 @@
+/* omdtls.c
+ * The dtls output module, uses OpenSSL as library to implement DTLS.
+ *
+ * \author Andre Lorbach <alorbach@adiscon.com>
+ *
+ * Copyright (C) 2023 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/uio.h>
+#include <sys/queue.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <math.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/time.h>
+#include <time.h>
+
+// --- Include openssl headers as well
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+# include <openssl/bioerr.h>
+#endif
+#include <openssl/engine.h>
+// ---
+
+// Include rsyslog headers
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+#include "datetime.h"
+#include "net_ossl.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omdtls")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(net_ossl)
+
+statsobj_t *dtlsStats;
+STATSCOUNTER_DEF(ctrDtlsSubmit, mutCtrDtlsSubmit);
+STATSCOUNTER_DEF(ctrDtlsFail, mutCtrDtlsFail);
+
+#define DTLS_MAX_RCVBUF 8192 /* Maximum DTLS packet is 8192 bytes which fits into Jumbo Frames. If not enabled
+ * message fragmentation (Ethernet MTU of ~ 1500 bytes) can occur.*/
+#define SETUP_DTLS_NONE 0
+#define SETUP_DTLS_AUTOCLOSE 1
+
+enum DTLSState {
+ DTLS_CONNECTED,
+ DTLS_CONNECTING,
+ DTLS_DISCONNECTED
+};
+
+/* Struct for module InstanceData */
+typedef struct _instanceData {
+ uchar *tplName; /* name of assigned template */
+
+ uchar *target;
+ uchar *port;
+
+ uchar *tlscfgcmd; /* OpenSSL Config Command used to override any OpenSSL Settings */
+ int bHaveSess; /* True if DTLS session is established */
+ int CertVerifyDepth; /* Verify Depth for certificate chains */
+
+ /* OpenSSL and Config Cert vars inside net_ossl_t now */
+ net_ossl_t *pNetOssl; /* OSSL shared Config and object vars are here */
+
+ uchar *statsName;
+ statsobj_t *stats; /* listener stats */
+ STATSCOUNTER_DEF(ctrDtlsSubmit, mutCtrDtlsSubmit)
+ STATSCOUNTER_DEF(ctrDtlsFail, mutCtrDtlsFail);
+
+ struct _instanceData *next;
+ struct _instanceData *prev;
+} instanceData;
+
+/* Struct for module workerInstanceData */
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+
+ enum DTLSState ConnectState; /* DTLS Connection State Status */
+ pthread_rwlock_t pnLock;
+
+ // DTLS Helpers
+ struct sockaddr_in dtls_client_addr; /* local bind socket*/
+ struct addrinfo* dtls_rcvr_addrinfo; /* remote receiver address */
+
+ int sockin; /* UDP Socket used to receive DTLS */
+ int sockout; /* UDP Socket used to send DTLS */
+ SSL *sslClient; /* DTSL (SSL) Client */
+} wrkrInstanceData_t;
+
+#define INST_STATSCOUNTER_INC(inst, ctr, mut) \
+ do { \
+ if (inst->stats) { STATSCOUNTER_INC(ctr, mut); } \
+ } while(0);
+
+// QPID Proton Handler functions
+static rsRetVal dtls_create_socket(wrkrInstanceData_t *const __restrict__ pWrkrData, int autoclose);
+static rsRetVal dtls_init(wrkrInstanceData_t *pWrkrData);
+static rsRetVal dtls_connect(wrkrInstanceData_t *pWrkrData);
+static rsRetVal dtls_close(wrkrInstanceData_t *pWrkrData);
+static rsRetVal dtls_send(wrkrInstanceData_t *pWrkrData, const actWrkrIParams_t *__restrict__ const pParam,
+ const int iMsg);
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "tls.authmode", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "tls.tlscfgcmd", eCmdHdlrString, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "statsname", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceData *root, *tail;
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+static rsRetVal
+dtls_create_socket(wrkrInstanceData_t *const __restrict__ pWrkrData, int autoclose)
+{
+ DEFiRet;
+ DBGPRINTF("omdtls[%p]: dtls_create_socket ENTER\n", pWrkrData);
+ pthread_rwlock_wrlock(&pWrkrData->pnLock);
+
+ if (autoclose == SETUP_DTLS_AUTOCLOSE) {
+ // Close Existing Connection
+ dtls_close(pWrkrData);
+ }
+
+ // Init & Open Connection
+ CHKiRet(dtls_init(pWrkrData));
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ /* Parameter Error's cannot be resumed, so we need to disable the action */
+ if (iRet == RS_RET_PARAM_ERROR) {
+ iRet = RS_RET_DISABLE_ACTION;
+ LogError(0, iRet, "omdtls[%p]: action will be disabled due invalid "
+ "configuration parameters\n", pWrkrData);
+ }
+ }
+ pthread_rwlock_unlock(&pWrkrData->pnLock);
+ RETiRet;
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ int i;
+CODESTARTsetModCnf
+ const struct cnfparamvals *const __restrict__ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omdtls:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omdtls: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnfPrePrivDrop
+ instanceData *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ DBGPRINTF("omdtls: activateCnfPrePrivDrop\n");
+
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ CHKiRet(net_ossl.osslCtxInit(inst->pNetOssl, DTLS_method()));
+ // Run openssl config commands in Context
+ CHKiRet(net_ossl_apply_tlscgfcmd(inst->pNetOssl, inst->tlscfgcmd));
+ }
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ DBGPRINTF("createInstance[%p]: ENTER\n", pData);
+ pData->tplName = NULL;
+ pData->target = NULL;
+ pData->port = NULL;
+ pData->tlscfgcmd = NULL;
+ pData->statsName = NULL;
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = pData;
+ } else {
+ loadModConf->tail->next = pData;
+ loadModConf->tail = pData;
+ }
+
+ // Construct pNetOssl helper
+ CHKiRet(net_ossl.Construct(&pData->pNetOssl));
+ pData->pNetOssl->authMode = OSSL_AUTH_CERTANON;
+finalize_it:
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ DBGPRINTF("createWrkrInstance[%p]: ENTER\n", pWrkrData);
+ pWrkrData->ConnectState = DTLS_DISCONNECTED;
+
+ CHKiRet(pthread_rwlock_init(&pWrkrData->pnLock, NULL));
+finalize_it:
+ DBGPRINTF("createWrkrInstance[%p] returned %d\n", pWrkrData, iRet);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ DBGPRINTF("freeInstance[%p]: ENTER\n", pData);
+
+ if (pData->stats) {
+ statsobj.Destruct(&pData->stats);
+ }
+
+ // DeConstruct pNetOssl helper
+ net_ossl.Destruct(&pData->pNetOssl);
+
+ /* Free other mem */
+ free(pData->target);
+ free(pData->port);
+ free(pData->tlscfgcmd);
+
+ free(pData->tplName);
+ free(pData->statsName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ DBGPRINTF("freeWrkrInstance[%p]: ENTER\n", pWrkrData);
+ pthread_rwlock_wrlock(&pWrkrData->pnLock);
+
+ // Close DTLS Connection
+ dtls_close(pWrkrData);
+
+ pthread_rwlock_unlock(&pWrkrData->pnLock);
+ pthread_rwlock_destroy(&pWrkrData->pnLock);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+BEGINtryResume
+CODESTARTtryResume
+ DBGPRINTF("omdtls[%p]: tryResume ENTER\n", pWrkrData);
+ if (pWrkrData->ConnectState == DTLS_DISCONNECTED) {
+ CHKiRet(dtls_create_socket(pWrkrData, SETUP_DTLS_AUTOCLOSE));
+ }
+finalize_it:
+ DBGPRINTF("omdtls[%p]: tryResume returned %d\n", pWrkrData, iRet);
+ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ /* we have nothing to do to begin a transaction */
+ DBGPRINTF("omdtls[%p]: beginTransaction ENTER\n", pWrkrData);
+ if (pWrkrData->ConnectState == DTLS_DISCONNECTED) {
+ CHKiRet(dtls_create_socket(pWrkrData, SETUP_DTLS_NONE));
+ }
+finalize_it:
+ RETiRet;
+ENDbeginTransaction
+
+/*
+ * New Transaction action interface
+*/
+BEGINcommitTransaction
+ unsigned i;
+ sbool bDone = 0;
+CODESTARTcommitTransaction
+#ifndef NDEBUG
+ DBGPRINTF("omdtls[%p]: commitTransaction [%d msgs] ENTER\n", pWrkrData, nParams);
+#endif
+ do {
+ for(i = 0 ; i < nParams ; ++i) {
+ CHKiRet(dtls_send(pWrkrData, pParams, i));
+ }
+ bDone = 1;
+ } while (bDone == 0);
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omdtls[%p]: commitTransaction failed with status %d\n", pWrkrData, iRet);
+ pWrkrData->ConnectState = DTLS_DISCONNECTED;
+ iRet = RS_RET_SUSPENDED;
+ }
+ DBGPRINTF("omdtls[%p]: commitTransaction [%d msgs] EXIT\n", pWrkrData, nParams);
+ENDcommitTransaction
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int iNumTpls;
+ FILE *fp;
+ DBGPRINTF("newActInst: ENTER\n");
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ // Create new instance and set default params
+ CHKiRet(createInstance(&pData));
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->target = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "statsname")) {
+ pData->statsName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.authmode")) {
+ char* pszAuthMode = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(pszAuthMode, "fingerprint"))
+ pData->pNetOssl->authMode = OSSL_AUTH_CERTFINGERPRINT;
+ else if(!strcasecmp(pszAuthMode, "name"))
+ pData->pNetOssl->authMode = OSSL_AUTH_CERTNAME;
+ else if(!strcasecmp(pszAuthMode, "certvalid"))
+ pData->pNetOssl->authMode = OSSL_AUTH_CERTVALID;
+ else
+ pData->pNetOssl->authMode = OSSL_AUTH_CERTANON;
+ free(pszAuthMode);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ pData->pNetOssl->pszCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->pNetOssl->pszCAFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->pNetOssl->pszCAFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->pNetOssl->pszCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->pNetOssl->pszCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->pNetOssl->pszCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->pNetOssl->pszKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->pNetOssl->pszKeyFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->pNetOssl->pszKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.tlscfgcmd")) {
+ pData->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "omdtls: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ /* check if no port is set. If so, we use DEFAULT of 433 */
+ if(pData->port == NULL) {
+ CHKmalloc(pData->port = (uchar *)strdup("443"));
+ }
+
+ iNumTpls = 1;
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls);
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_FileFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ if (pData->statsName) {
+ CHKiRet(statsobj.Construct(&pData->stats));
+ CHKiRet(statsobj.SetName(pData->stats, (uchar *)pData->statsName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar *)"omdtls"));
+
+ /* Track following stats */
+ STATSCOUNTER_INIT(pData->ctrDtlsSubmit, pData->mutCtrDtlsSubmit);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrDtlsSubmit));
+ STATSCOUNTER_INIT(pData->ctrDtlsFail, pData->mutCtrDtlsFail);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrDtlsFail));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINmodExit
+CODESTARTmodExit
+ DBGPRINTF("modExit: ENTER\n");
+ statsobj.Destruct(&dtlsStats);
+ objRelease(net_ossl, LM_NET_OSSL_FILENAME);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+NO_LEGACY_CONF_parseSelectorAct
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ DBGPRINTF("modInit: ENTER\n");
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net_ossl, LM_NET_OSSL_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ CHKiRet(statsobj.Construct(&dtlsStats));
+ CHKiRet(statsobj.SetName(dtlsStats, (uchar *)"omdtls"));
+ CHKiRet(statsobj.SetOrigin(dtlsStats, (uchar*)"omdtls"));
+ STATSCOUNTER_INIT(ctrDtlsSubmit, mutCtrDtlsSubmit);
+ CHKiRet(statsobj.AddCounter(dtlsStats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrDtlsSubmit));
+ STATSCOUNTER_INIT(ctrDtlsFail, mutCtrDtlsFail);
+ CHKiRet(statsobj.AddCounter(dtlsStats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrDtlsFail));
+
+ CHKiRet(statsobj.ConstructFinalize(dtlsStats));
+ENDmodInit
+
+/*
+* Setup socket and establish virtual Connect on a SOCKET Level for DTLS
+*/
+static rsRetVal
+dtls_send(wrkrInstanceData_t *pWrkrData, const actWrkrIParams_t *__restrict__ const pParam, const int iMsg)
+{
+ DEFiRet;
+ int iErr, sslerr;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+
+ // Get Msg String
+ const char* pszParamStr = (const char*)actParam(pParam, 1 /*pData->iNumTpls*/, iMsg, 0).param;
+ size_t tzParamStrLen = actParam(pParam, 1 /*pData->iNumTpls*/, iMsg, 0).lenStr;
+ DBGPRINTF("dtls_send[%p]: msg %d msg:'%.*s%s'\n",
+ pWrkrData,
+ iMsg,
+ (int)(tzParamStrLen > 0 ? (tzParamStrLen > 64 ? 64 : tzParamStrLen-1) : 0),
+ pszParamStr,
+ (tzParamStrLen > 64 ? "..." : ""));
+
+ iErr = SSL_write(pWrkrData->sslClient, pszParamStr, tzParamStrLen);
+ if(iErr > 0) {
+ DBGPRINTF("dtls_send[%p]: Successfully send message '%s' with %ld bytes to %s:%s\n",
+ pWrkrData, pszParamStr, tzParamStrLen, pData->target, pData->port);
+
+ // Increment Stats Counter
+ STATSCOUNTER_INC(ctrDtlsSubmit, mutCtrDtlsSubmit);
+ INST_STATSCOUNTER_INC(pData, pData->ctrDtlsSubmit, pData->mutCtrDtlsSubmit);
+ } else {
+ sslerr = SSL_get_error(pWrkrData->sslClient, iErr);
+ if (sslerr == SSL_ERROR_SYSCALL) {
+ dbgprintf("dtls_send[%p]: SSL_write failed with SSL_ERROR_SYSCALL(%s)"
+ " - Aborting Connection.\n", pWrkrData, strerror(errno));
+ net_ossl_lastOpenSSLErrorMsg(pData->target, iErr, pWrkrData->sslClient, LOG_WARNING,
+ "omdtls", "SSL_write");
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ dbgprintf("dtls_send[%p]: SSL_write failed with ERROR [%d]: %s"
+ " - Aborting Connection.\n", pWrkrData, sslerr, ERR_error_string(sslerr, NULL));
+ net_ossl_lastOpenSSLErrorMsg(pData->target, iErr, pWrkrData->sslClient, LOG_WARNING,
+ "omdtls", "SSL_write");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // Increment Stats Counter
+ STATSCOUNTER_INC(ctrDtlsFail, mutCtrDtlsFail);
+ INST_STATSCOUNTER_INC(pData, pData->ctrDtlsFail, pData->mutCtrDtlsFail);
+ }
+finalize_it:
+ DBGPRINTF("dtls_send[%p]: Exit with %d for %s:%s\n", pWrkrData, iRet, pData->target, pData->port);
+ if(iRet != RS_RET_OK) {
+ dtls_close(pWrkrData);
+ }
+ RETiRet;
+}
+
+/*
+* Setup socket and establish virtual Connect on a SOCKET Level for DTLS
+*/
+static rsRetVal
+dtls_connect(wrkrInstanceData_t *pWrkrData) {
+ DEFiRet;
+ int iErr;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ BIO *bio_client;
+ const SSL_CIPHER *sslCipher;
+
+ DBGPRINTF("dtls_connect[%p]: setup DTLS for %s:%s\n", pWrkrData, pData->target, pData->port);
+ pWrkrData->ConnectState = DTLS_CONNECTING;
+
+ // Create SSL object
+ pWrkrData->sslClient = SSL_new(pData->pNetOssl->ctx);
+ if(!pWrkrData->sslClient) {
+ dbgprintf("dtls_connect[%p]: SSL_new failed failed\n", pWrkrData);
+ net_ossl_lastOpenSSLErrorMsg(pData->target, 0, pWrkrData->sslClient, LOG_WARNING, "omdtls", "SSL_new");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // Set certifcate check callback
+ if (pData->pNetOssl->authMode != OSSL_AUTH_CERTANON) {
+ dbgprintf("dtls_connect[%p]: enable certificate checking (Mode=%d, VerifyDepth=%d)\n",
+ pWrkrData, pData->pNetOssl->authMode, pData->CertVerifyDepth);
+ /* Enable certificate valid checking */
+ net_ossl_set_ssl_verify_callback(pWrkrData->sslClient, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ if (pData->CertVerifyDepth != 0) {
+ SSL_set_verify_depth(pWrkrData->sslClient, pData->CertVerifyDepth);
+ }
+ } else {
+ dbgprintf("dtls_connect[%p]: disable certificate checking\n", pWrkrData);
+ net_ossl_set_ssl_verify_callback(pWrkrData->sslClient, SSL_VERIFY_NONE);
+ }
+
+ /* Create BIO from socket array! */
+ bio_client = BIO_new_dgram(pWrkrData->sockout, BIO_NOCLOSE);
+ if (!bio_client) {
+ net_ossl_lastOpenSSLErrorMsg(pData->target, 0, pWrkrData->sslClient, LOG_INFO,
+ "dtls_connect", "BIO_new_dgram");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &pWrkrData->dtls_client_addr);
+ SSL_set_bio(pWrkrData->sslClient, bio_client, bio_client);
+
+ /* Set debug Callback for conn BIO as well! */
+ net_ossl_set_bio_callback(bio_client);
+
+ dbgprintf("dtls_connect[%p]: Starting DTLS session ...\n", pWrkrData);
+ /* Perform handshake */
+ iErr = SSL_connect(pWrkrData->sslClient);
+ if (iErr <= 0) {
+ net_ossl_lastOpenSSLErrorMsg(pData->target, iErr, pWrkrData->sslClient, LOG_INFO,
+ "dtls_connect", "SSL_connect");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // Print Cipher info
+ sslCipher = SSL_get_current_cipher(pWrkrData->sslClient);
+ dbgprintf("dtls_connect[%p]: Cipher Version: %s Name: %s\n", pWrkrData,
+ SSL_CIPHER_get_version(sslCipher), SSL_CIPHER_get_name(sslCipher));
+
+ if(Debug) {
+ // Print Peer Certificate info
+ X509 *cert = SSL_get_peer_certificate(pWrkrData->sslClient);
+ if (cert != NULL) {
+ char *line;
+ line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ dbgprintf("dtls_connect[%p]: Subject: %s\n", pWrkrData, line);
+ OPENSSL_free(line);
+
+ line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ dbgprintf("dtls_connect[%p]: Issuer: %s\n", pWrkrData, line);
+ OPENSSL_free(line);
+ X509_free(cert);
+ } else {
+ dbgprintf("dtls_connect[%p]: No certificates.\n", pWrkrData);
+ }
+ }
+
+ /* Set reference in SSL obj */
+ SSL_set_ex_data(pWrkrData->sslClient, 0, NULL);
+ SSL_set_ex_data(pWrkrData->sslClient, 1, NULL);
+
+ /* Set and activate timeouts */
+ struct timeval timeout;
+ timeout.tv_sec = 3;
+ timeout.tv_usec = 0;
+ BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
+
+ pWrkrData->ConnectState = DTLS_CONNECTED;
+finalize_it:
+ DBGPRINTF("dtls_connect[%p]: Exit with %d for %s:%s\n", pWrkrData, iRet, pData->target, pData->port);
+ if(iRet != RS_RET_OK) {
+ pWrkrData->ConnectState = DTLS_DISCONNECTED;
+ }
+ RETiRet;
+}
+
+/*
+* Setup socket and establish virtual Connect on a SOCKET Level for DTLS
+*/
+static rsRetVal
+dtls_init(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ int iErr;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ struct addrinfo *addrResolved = NULL;
+ struct addrinfo hints;
+ DBGPRINTF("dtls_init[%p]: setup for %s:%s\n", pWrkrData, pData->target, pData->port);
+
+ // Close previous ressources if any left open
+ dtls_close(pWrkrData);
+
+ // Setup receiving Socket for DTLS
+ if((pWrkrData->sockin = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ return 1;
+ memset(&pWrkrData->dtls_client_addr, 0, sizeof(pWrkrData->dtls_client_addr));
+ pWrkrData->dtls_client_addr.sin_family = AF_INET;
+ pWrkrData->dtls_client_addr.sin_port = htons(0);
+ pWrkrData->dtls_client_addr.sin_addr.s_addr = INADDR_ANY;
+ if (bind(pWrkrData->sockin,
+ (struct sockaddr*)&pWrkrData->dtls_client_addr,
+ sizeof(pWrkrData->dtls_client_addr)) < 0) {
+ LogError(0, RS_RET_SUSPENDED, "omdtls[%p]: dtls_init Unable to bind DTLS CLient socket with errno %d",
+ pWrkrData, errno);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
+ }
+
+ // Resolve target address
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requires this */
+ hints.ai_family = glbl.GetDefPFFamily(runModConf->pConf);
+ hints.ai_socktype = SOCK_DGRAM;
+ if((iErr = (getaddrinfo((char*)pData->target, (char*)pData->port, &hints, &addrResolved))) != 0) {
+ LogError(0, RS_RET_SUSPENDED,
+ "omdtls[%p]: could not get addrinfo for hostname '%s':'%s': %s",
+ pWrkrData, pData->target, pData->port, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_ADDRESS_UNKNOWN);
+ }
+ pWrkrData->dtls_rcvr_addrinfo = addrResolved;
+ addrResolved = NULL;
+
+ // Init Socket Connection (Which technically does not connect but prepares socket for DTLS)
+ DBGPRINTF("dtls_init[%p]: Init Session to %s:%s\n", pWrkrData, pData->target, pData->port);
+
+ // Connect the UDP socket to the receiver's address
+ pWrkrData->sockout = socket(AF_INET, SOCK_DGRAM, 0);
+ if (connect(pWrkrData->sockout,
+ pWrkrData->dtls_rcvr_addrinfo->ai_addr,
+ pWrkrData->dtls_rcvr_addrinfo->ai_addrlen) < 0) {
+ LogError(0, RS_RET_SUSPENDED,
+ "dtls_init[%p]: Failed to connect to hostname '%s':'%s': %s",
+ pWrkrData, pData->target, pData->port, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // Socket Connect successfull, no continue with TLS
+ CHKiRet(dtls_connect(pWrkrData));
+
+ // We reached this position means we are ready to send!
+ pWrkrData->ConnectState = DTLS_CONNECTED;
+finalize_it:
+ DBGPRINTF("dtls_init[%p]: doTryResume %s iRet %d\n", pWrkrData, pData->target, iRet);
+ if(addrResolved != NULL) {
+ freeaddrinfo(addrResolved);
+ }
+ if(iRet != RS_RET_OK) {
+ if(pWrkrData->dtls_rcvr_addrinfo != NULL) {
+ freeaddrinfo(pWrkrData->dtls_rcvr_addrinfo);
+ pWrkrData->dtls_rcvr_addrinfo = NULL;
+ }
+ iRet = RS_RET_SUSPENDED;
+
+ // Force DTLS Disconnect State
+ dtls_close(pWrkrData);
+ // pWrkrData->ConnectState = DTLS_DISCONNECTED;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dtls_close(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ int iErr;
+ instanceData *const pData = (instanceData *const) pWrkrData->pData;
+ if (pWrkrData->ConnectState == DTLS_CONNECTED) {
+ DBGPRINTF("dtls_close[%p]: close session for %s:%s\n", pWrkrData, pData->target, pData->port);
+ if ( pWrkrData->sslClient != NULL &&
+ pWrkrData->ConnectState == DTLS_CONNECTED) {
+ iErr = SSL_shutdown(pWrkrData->sslClient);
+ if (iErr <= 0){
+ /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc:
+ * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html
+ * We do a single SSL_read which should be fine for protocol handling.
+ * No data is to be expected from the receiver side.
+ */
+ char rcvBuf[DTLS_MAX_RCVBUF];
+ SSL_read(pWrkrData->sslClient, rcvBuf, DTLS_MAX_RCVBUF);
+ }
+ SSL_free(pWrkrData->sslClient);
+ pWrkrData->sslClient = NULL;
+ }
+ }
+
+ // Close Sockets
+ if ( pWrkrData->sockout != 0) {
+ close(pWrkrData->sockout);
+ pWrkrData->sockout = 0;
+ }
+ if ( pWrkrData->sockin != 0) {
+ close(pWrkrData->sockin);
+ pWrkrData->sockin = 0;
+ }
+
+ // Free Memory
+ if(pWrkrData->dtls_rcvr_addrinfo != NULL) {
+ freeaddrinfo(pWrkrData->dtls_rcvr_addrinfo);
+ pWrkrData->dtls_rcvr_addrinfo = NULL;
+ }
+
+ // Reset Helpers
+ pWrkrData->ConnectState = DTLS_DISCONNECTED;
+FINALIZE;
+finalize_it:
+ RETiRet;
+}
diff --git a/plugins/omelasticsearch/Makefile.am b/plugins/omelasticsearch/Makefile.am
new file mode 100644
index 0000000..ddaa59a
--- /dev/null
+++ b/plugins/omelasticsearch/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omelasticsearch.la
+
+omelasticsearch_la_SOURCES = omelasticsearch.c
+omelasticsearch_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omelasticsearch_la_LDFLAGS = -module -avoid-version
+omelasticsearch_la_LIBADD = $(CURL_LIBS) $(LIBM)
+
+EXTRA_DIST =
diff --git a/plugins/omelasticsearch/Makefile.in b/plugins/omelasticsearch/Makefile.in
new file mode 100644
index 0000000..e329e68
--- /dev/null
+++ b/plugins/omelasticsearch/Makefile.in
@@ -0,0 +1,801 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omelasticsearch
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omelasticsearch_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_omelasticsearch_la_OBJECTS = omelasticsearch_la-omelasticsearch.lo
+omelasticsearch_la_OBJECTS = $(am_omelasticsearch_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 =
+omelasticsearch_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(omelasticsearch_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/omelasticsearch_la-omelasticsearch.Plo
+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 = $(omelasticsearch_la_SOURCES)
+DIST_SOURCES = $(omelasticsearch_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omelasticsearch.la
+omelasticsearch_la_SOURCES = omelasticsearch.c
+omelasticsearch_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS)
+omelasticsearch_la_LDFLAGS = -module -avoid-version
+omelasticsearch_la_LIBADD = $(CURL_LIBS) $(LIBM)
+EXTRA_DIST =
+all: 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) --gnu plugins/omelasticsearch/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omelasticsearch/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omelasticsearch.la: $(omelasticsearch_la_OBJECTS) $(omelasticsearch_la_DEPENDENCIES) $(EXTRA_omelasticsearch_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omelasticsearch_la_LINK) -rpath $(pkglibdir) $(omelasticsearch_la_OBJECTS) $(omelasticsearch_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omelasticsearch_la-omelasticsearch.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omelasticsearch_la-omelasticsearch.lo: omelasticsearch.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omelasticsearch_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omelasticsearch_la-omelasticsearch.lo -MD -MP -MF $(DEPDIR)/omelasticsearch_la-omelasticsearch.Tpo -c -o omelasticsearch_la-omelasticsearch.lo `test -f 'omelasticsearch.c' || echo '$(srcdir)/'`omelasticsearch.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omelasticsearch_la-omelasticsearch.Tpo $(DEPDIR)/omelasticsearch_la-omelasticsearch.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omelasticsearch.c' object='omelasticsearch_la-omelasticsearch.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) $(omelasticsearch_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omelasticsearch_la-omelasticsearch.lo `test -f 'omelasticsearch.c' || echo '$(srcdir)/'`omelasticsearch.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omelasticsearch_la-omelasticsearch.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omelasticsearch_la-omelasticsearch.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omelasticsearch/README b/plugins/omelasticsearch/README
new file mode 100644
index 0000000..b8bf415
--- /dev/null
+++ b/plugins/omelasticsearch/README
@@ -0,0 +1,21 @@
+How to access ElasticSearch on local machine (for testing):
+===========================================================
+see: https://github.com/mobz/elasticsearch-head
+
+How to produce an error:
+========================
+It's quite easy to get 400, if you put a wrong mapping to your
+index. That would be easy to reproduce in "normal" omelasticsearch usage
+conditions, by only altering the ES configuration:
+
+1. Make your index first. Let's call it "testindex":
+$ curl -XPUT localhost:9200/testindex/
+
+2. Put your mapping for a search type called "mytype", where you specify
+that date property should be an integer:
+$ curl -XPUT localhost:9200/testindex/mytype/_mapping -d '{"mytype":{"properties": {"timegenerated":{"type":"integer"}}}}'
+
+3. Now try to insert something where date is not an integer:
+$ curl -XPOST localhost:9200/testindex/mytype/ -d '{"timegenerated":"bla"}'
+{"error":"MapperParsingException[Failed to parse [date]]; nested: NumberFormatException[For input string: \"bla\"]; ","status":400}
+
diff --git a/plugins/omelasticsearch/omelasticsearch.c b/plugins/omelasticsearch/omelasticsearch.c
new file mode 100644
index 0000000..b297a92
--- /dev/null
+++ b/plugins/omelasticsearch/omelasticsearch.c
@@ -0,0 +1,2319 @@
+/* omelasticsearch.c
+ * This is the http://www.elasticsearch.org/ output module.
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * Copyright 2011 Nathan Scott.
+ * Copyright 2009-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(__FreeBSD__)
+#include <unistd.h>
+#endif
+#include <json.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "statsobj.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "obj-types.h"
+#include "ratelimit.h"
+#include "ruleset.h"
+
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omelasticsearch")
+
+/* internal structures */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+
+statsobj_t *indexStats;
+STATSCOUNTER_DEF(indexSubmit, mutIndexSubmit)
+STATSCOUNTER_DEF(indexHTTPFail, mutIndexHTTPFail)
+STATSCOUNTER_DEF(indexHTTPReqFail, mutIndexHTTPReqFail)
+STATSCOUNTER_DEF(checkConnFail, mutCheckConnFail)
+STATSCOUNTER_DEF(indexESFail, mutIndexESFail)
+STATSCOUNTER_DEF(indexSuccess, mutIndexSuccess)
+STATSCOUNTER_DEF(indexBadResponse, mutIndexBadResponse)
+STATSCOUNTER_DEF(indexDuplicate, mutIndexDuplicate)
+STATSCOUNTER_DEF(indexBadArgument, mutIndexBadArgument)
+STATSCOUNTER_DEF(indexBulkRejection, mutIndexBulkRejection)
+STATSCOUNTER_DEF(indexOtherResponse, mutIndexOtherResponse)
+STATSCOUNTER_DEF(rebinds, mutRebinds)
+
+static prop_t *pInputName = NULL;
+
+# define META_STRT "{\"index\":{\"_index\": \""
+# define META_STRT_CREATE "{\"create\":{" /* \"_index\": \" */
+# define META_IX "\"_index\": \""
+# define META_TYPE "\",\"_type\":\""
+# define META_PIPELINE "\",\"pipeline\":\""
+# define META_PARENT "\",\"_parent\":\""
+# define META_ID "\", \"_id\":\""
+# define META_END "\"}}\n"
+# define META_END_NOQUOTE " }}\n"
+
+typedef enum {
+ ES_WRITE_INDEX,
+ ES_WRITE_CREATE,
+ ES_WRITE_UPDATE, /* not supported */
+ ES_WRITE_UPSERT /* not supported */
+} es_write_ops_t;
+
+#define WRKR_DATA_TYPE_ES 0xBADF0001
+
+#define DEFAULT_REBIND_INTERVAL -1
+
+/* REST API for elasticsearch hits this URL:
+ * http://<hostName>:<restPort>/<searchIndex>/<searchType>
+ */
+/* bulk API uses /_bulk */
+typedef struct curl_slist HEADER;
+typedef struct instanceConf_s {
+ int defaultPort;
+ int fdErrFile; /* error file fd or -1 if not open */
+ pthread_mutex_t mutErrFile;
+ uchar **serverBaseUrls;
+ int numServers;
+ long healthCheckTimeout;
+ long indexTimeout;
+ uchar *uid;
+ uchar *pwd;
+ uchar *authBuf;
+ uchar *searchIndex;
+ uchar *searchType;
+ uchar *pipelineName;
+ sbool skipPipelineIfEmpty;
+ uchar *parent;
+ uchar *tplName;
+ uchar *timeout;
+ uchar *bulkId;
+ uchar *errorFile;
+ int esVersion;
+ sbool errorOnly;
+ sbool interleaved;
+ sbool dynSrchIdx;
+ sbool dynSrchType;
+ sbool dynParent;
+ sbool dynBulkId;
+ sbool dynPipelineName;
+ sbool bulkmode;
+ size_t maxbytes;
+ sbool useHttps;
+ sbool allowUnsignedCerts;
+ sbool skipVerifyHost;
+ uchar *caCertFile;
+ uchar *myCertFile;
+ uchar *myPrivKeyFile;
+ es_write_ops_t writeOperation;
+ sbool retryFailures;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ /* for retries */
+ ratelimit_t *ratelimiter;
+ uchar *retryRulesetName;
+ ruleset_t *retryRuleset;
+ int rebindInterval;
+ struct instanceConf_s *next;
+} instanceData;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+};
+static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
+
+typedef struct wrkrInstanceData {
+ PTR_ASSERT_DEF
+ instanceData *pData;
+ int serverIndex;
+ int replyLen;
+ size_t replyBufLen;
+ char *reply;
+ CURL *curlCheckConnHandle; /* libcurl session handle for checking the server connection */
+ CURL *curlPostHandle; /* libcurl session handle for posting data to the server */
+ HEADER *curlHeader; /* json POST request info */
+ uchar *restURL; /* last used URL for error reporting */
+ struct {
+ es_str_t *data;
+ int nmemb; /* number of messages in batch (for statistics counting) */
+ uchar *currTpl1;
+ uchar *currTpl2;
+ } batch;
+ int nOperations; /* counter used with rebindInterval */
+} wrkrInstanceData_t;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrArray, 0 },
+ { "serverport", eCmdHdlrInt, 0 },
+ { "healthchecktimeout", eCmdHdlrInt, 0 },
+ { "indextimeout", eCmdHdlrInt, 0 },
+ { "uid", eCmdHdlrGetWord, 0 },
+ { "pwd", eCmdHdlrGetWord, 0 },
+ { "searchindex", eCmdHdlrGetWord, 0 },
+ { "searchtype", eCmdHdlrGetWord, 0 },
+ { "pipelinename", eCmdHdlrGetWord, 0 },
+ { "skippipelineifempty", eCmdHdlrBinary, 0 },
+ { "parent", eCmdHdlrGetWord, 0 },
+ { "dynsearchindex", eCmdHdlrBinary, 0 },
+ { "dynsearchtype", eCmdHdlrBinary, 0 },
+ { "dynparent", eCmdHdlrBinary, 0 },
+ { "bulkmode", eCmdHdlrBinary, 0 },
+ { "maxbytes", eCmdHdlrSize, 0 },
+ { "asyncrepl", eCmdHdlrGoneAway, 0 },
+ { "usehttps", eCmdHdlrBinary, 0 },
+ { "timeout", eCmdHdlrGetWord, 0 },
+ { "errorfile", eCmdHdlrGetWord, 0 },
+ { "erroronly", eCmdHdlrBinary, 0 },
+ { "interleaved", eCmdHdlrBinary, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "dynbulkid", eCmdHdlrBinary, 0 },
+ { "dynpipelinename", eCmdHdlrBinary, 0 },
+ { "bulkid", eCmdHdlrGetWord, 0 },
+ { "allowunsignedcerts", eCmdHdlrBinary, 0 },
+ { "skipverifyhost", eCmdHdlrBinary, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "writeoperation", eCmdHdlrGetWord, 0 },
+ { "retryfailures", eCmdHdlrBinary, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "retryruleset", eCmdHdlrString, 0 },
+ { "rebindinterval", eCmdHdlrInt, 0 },
+ { "esversion.major", eCmdHdlrPositiveInt, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static rsRetVal curlSetup(wrkrInstanceData_t *pWrkrData);
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ int r;
+ pData->fdErrFile = -1;
+ if((r = pthread_mutex_init(&pData->mutErrFile, NULL)) != 0) {
+ LogError(r, RS_RET_ERR, "omelasticsearch: cannot create "
+ "error file mutex, failing this action");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+ pData->ratelimiter = NULL;
+ pData->retryRulesetName = NULL;
+ pData->retryRuleset = NULL;
+ pData->rebindInterval = DEFAULT_REBIND_INTERVAL;
+ pData->esVersion = 0;
+finalize_it:
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ pWrkrData->curlHeader = NULL;
+ pWrkrData->curlPostHandle = NULL;
+ pWrkrData->curlCheckConnHandle = NULL;
+ pWrkrData->serverIndex = 0;
+ pWrkrData->restURL = NULL;
+ if(pData->bulkmode) {
+ pWrkrData->batch.currTpl1 = NULL;
+ pWrkrData->batch.currTpl2 = NULL;
+ if((pWrkrData->batch.data = es_newStr(1024)) == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: error creating batch string "
+ "turned off bulk mode\n");
+ pData->bulkmode = 0; /* at least it works */
+ }
+ }
+ pWrkrData->nOperations = 0;
+ pWrkrData->reply = NULL;
+ pWrkrData->replyLen = 0;
+ pWrkrData->replyBufLen = 0;
+ iRet = curlSetup(pWrkrData);
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINfreeInstance
+ int i;
+CODESTARTfreeInstance
+ if(pData->fdErrFile != -1)
+ close(pData->fdErrFile);
+
+ if(loadModConf != NULL) {
+ /* we keep our instances in our own internal list - this also
+ * means we need to cleanup that list, else we cause grief.
+ */
+ instanceData *prev = NULL;
+ for(instanceData *inst = loadModConf->root ; inst != NULL ; inst = inst->next) {
+ if(inst == pData) {
+ if(loadModConf->tail == inst) {
+ loadModConf->tail = prev;
+ }
+ prev->next = inst->next;
+ /* no need to correct inst back to prev - we exit now! */
+ break;
+ } else {
+ prev = inst;
+ }
+ }
+ }
+
+ pthread_mutex_destroy(&pData->mutErrFile);
+ for(i = 0 ; i < pData->numServers ; ++i)
+ free(pData->serverBaseUrls[i]);
+ free(pData->serverBaseUrls);
+ free(pData->uid);
+ free(pData->pwd);
+ free(pData->authBuf);
+ free(pData->searchIndex);
+ free(pData->searchType);
+ free(pData->pipelineName);
+ free(pData->parent);
+ free(pData->tplName);
+ free(pData->timeout);
+ free(pData->errorFile);
+ free(pData->bulkId);
+ free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
+ free(pData->retryRulesetName);
+ if (pData->ratelimiter != NULL)
+ ratelimitDestruct(pData->ratelimiter);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if(pWrkrData->curlHeader != NULL) {
+ curl_slist_free_all(pWrkrData->curlHeader);
+ pWrkrData->curlHeader = NULL;
+ }
+ if(pWrkrData->curlCheckConnHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlCheckConnHandle);
+ pWrkrData->curlCheckConnHandle = NULL;
+ }
+ if(pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+ if (pWrkrData->restURL != NULL) {
+ free(pWrkrData->restURL);
+ pWrkrData->restURL = NULL;
+ }
+ es_deleteStr(pWrkrData->batch.data);
+ free(pWrkrData->reply);
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+ int i;
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omelasticsearch\n");
+ dbgprintf("\ttemplate='%s'\n", pData->tplName);
+ dbgprintf("\tnumServers=%d\n", pData->numServers);
+ dbgprintf("\thealthCheckTimeout=%lu\n", pData->healthCheckTimeout);
+ dbgprintf("\tindexTimeout=%lu\n", pData->indexTimeout);
+ dbgprintf("\tserverBaseUrls=");
+ for(i = 0 ; i < pData->numServers ; ++i)
+ dbgprintf("%c'%s'", i == 0 ? '[' : ' ', pData->serverBaseUrls[i]);
+ dbgprintf("]\n");
+ dbgprintf("\tdefaultPort=%d\n", pData->defaultPort);
+ dbgprintf("\tuid='%s'\n", pData->uid == NULL ? (uchar*)"(not configured)" : pData->uid);
+ dbgprintf("\tpwd=(%sconfigured)\n", pData->pwd == NULL ? "not " : "");
+ dbgprintf("\tsearch index='%s'\n", pData->searchIndex == NULL
+ ? (uchar*)"(not configured)" : pData->searchIndex);
+ dbgprintf("\tsearch type='%s'\n", pData->searchType == NULL
+ ? (uchar*)"(not configured)" : pData->searchType);
+ dbgprintf("\tpipeline name='%s'\n", pData->pipelineName);
+ dbgprintf("\tdynamic pipeline name=%d\n", pData->dynPipelineName);
+ dbgprintf("\tskipPipelineIfEmpty=%d\n", pData->skipPipelineIfEmpty);
+ dbgprintf("\tparent='%s'\n", pData->parent);
+ dbgprintf("\ttimeout='%s'\n", pData->timeout);
+ dbgprintf("\tdynamic search index=%d\n", pData->dynSrchIdx);
+ dbgprintf("\tdynamic search type=%d\n", pData->dynSrchType);
+ dbgprintf("\tdynamic parent=%d\n", pData->dynParent);
+ dbgprintf("\tuse https=%d\n", pData->useHttps);
+ dbgprintf("\tbulkmode=%d\n", pData->bulkmode);
+ dbgprintf("\tmaxbytes=%zu\n", pData->maxbytes);
+ dbgprintf("\tallowUnsignedCerts=%d\n", pData->allowUnsignedCerts);
+ dbgprintf("\tskipVerifyHost=%d\n", pData->skipVerifyHost);
+ dbgprintf("\terrorfile='%s'\n", pData->errorFile == NULL ?
+ (uchar*)"(not configured)" : pData->errorFile);
+ dbgprintf("\terroronly=%d\n", pData->errorOnly);
+ dbgprintf("\tinterleaved=%d\n", pData->interleaved);
+ dbgprintf("\tdynbulkid=%d\n", pData->dynBulkId);
+ dbgprintf("\tbulkid='%s'\n", pData->bulkId);
+ dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile);
+ dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile);
+ dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile);
+ dbgprintf("\twriteoperation='%d'\n", pData->writeOperation);
+ dbgprintf("\tretryfailures='%d'\n", pData->retryFailures);
+ dbgprintf("\tratelimit.interval='%u'\n", pData->ratelimitInterval);
+ dbgprintf("\tratelimit.burst='%u'\n", pData->ratelimitBurst);
+ dbgprintf("\trebindinterval='%d'\n", pData->rebindInterval);
+ENDdbgPrintInstInfo
+
+
+/* elasticsearch POST result string ... useful for debugging */
+static size_t
+curlResult(void *const ptr, const size_t size, const size_t nmemb, void *const userdata)
+{
+ const char *const p = (const char *)ptr;
+ wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t*) userdata;
+ char *buf;
+ const size_t size_add = size*nmemb;
+ size_t newlen;
+ PTR_ASSERT_CHK(pWrkrData, WRKR_DATA_TYPE_ES);
+ newlen = pWrkrData->replyLen + size_add;
+ if(newlen + 1 > pWrkrData->replyBufLen) {
+ if((buf = realloc(pWrkrData->reply, pWrkrData->replyBufLen + size_add + 1)) == NULL) {
+ LogError(errno, RS_RET_ERR, "omelasticsearch: realloc failed in curlResult");
+ return 0; /* abort due to failure */
+ }
+ pWrkrData->replyBufLen += size_add + 1;
+ pWrkrData->reply = buf;
+ }
+ memcpy(pWrkrData->reply+pWrkrData->replyLen, p, size_add);
+ pWrkrData->replyLen = newlen;
+ return size_add;
+}
+
+/* Build basic URL part, which includes hostname and port as follows:
+ * http://hostname:port/ based on a server param
+ * Newly creates a cstr for this purpose.
+ * Note: serverParam MUST NOT end in '/' (caller must strip if it exists)
+ */
+static rsRetVal
+computeBaseUrl(const char*const serverParam,
+ const int defaultPort,
+ const sbool useHttps,
+ uchar **baseUrl)
+{
+# define SCHEME_HTTPS "https://"
+# define SCHEME_HTTP "http://"
+
+ char portBuf[64];
+ int r = 0;
+ const char *host = serverParam;
+ DEFiRet;
+
+ assert(serverParam[strlen(serverParam)-1] != '/');
+
+ es_str_t *urlBuf = es_newStr(256);
+ if (urlBuf == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: failed to allocate es_str urlBuf in computeBaseUrl");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* Find where the hostname/ip of the server starts. If the scheme is not specified
+ in the uri, start the buffer with a scheme corresponding to the useHttps parameter.
+ */
+ if (strcasestr(serverParam, SCHEME_HTTP))
+ host = serverParam + strlen(SCHEME_HTTP);
+ else if (strcasestr(serverParam, SCHEME_HTTPS))
+ host = serverParam + strlen(SCHEME_HTTPS);
+ else
+ r = useHttps ? es_addBuf(&urlBuf, SCHEME_HTTPS, sizeof(SCHEME_HTTPS)-1) :
+ es_addBuf(&urlBuf, SCHEME_HTTP, sizeof(SCHEME_HTTP)-1);
+
+ if (r == 0) r = es_addBuf(&urlBuf, (char *)serverParam, strlen(serverParam));
+ if (r == 0 && !strchr(host, ':')) {
+ snprintf(portBuf, sizeof(portBuf), ":%d", defaultPort);
+ r = es_addBuf(&urlBuf, portBuf, strlen(portBuf));
+ }
+ if (r == 0) r = es_addChar(&urlBuf, '/');
+ if (r == 0) *baseUrl = (uchar*) es_str2cstr(urlBuf, NULL);
+
+ if (r != 0 || baseUrl == NULL) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: error occurred computing baseUrl from server %s", serverParam);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ if (urlBuf) {
+ es_deleteStr(urlBuf);
+ }
+ RETiRet;
+}
+
+static inline void
+incrementServerIndex(wrkrInstanceData_t *pWrkrData)
+{
+ pWrkrData->serverIndex = (pWrkrData->serverIndex + 1) % pWrkrData->pData->numServers;
+}
+
+
+/* checks if connection to ES can be established; also iterates over
+ * potential servers to support high availability (HA) feature. If it
+ * needs to switch server, will record new one in curl handle.
+ */
+static rsRetVal ATTR_NONNULL()
+checkConn(wrkrInstanceData_t *const pWrkrData)
+{
+# define HEALTH_URI "_cat/health"
+ CURL *curl;
+ CURLcode res;
+ es_str_t *urlBuf;
+ char* healthUrl = NULL;
+ char* serverUrl;
+ int i;
+ int r;
+ DEFiRet;
+
+ pWrkrData->replyLen = 0;
+ curl = pWrkrData->curlCheckConnHandle;
+ urlBuf = es_newStr(256);
+ if (urlBuf == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: unable to allocate buffer for health check uri.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ for(i = 0; i < pWrkrData->pData->numServers; ++i) {
+ serverUrl = (char*) pWrkrData->pData->serverBaseUrls[pWrkrData->serverIndex];
+
+ es_emptyStr(urlBuf);
+ r = es_addBuf(&urlBuf, serverUrl, strlen(serverUrl));
+ if(r == 0) r = es_addBuf(&urlBuf, HEALTH_URI, sizeof(HEALTH_URI)-1);
+ if(r == 0) healthUrl = es_str2cstr(urlBuf, NULL);
+ if(r != 0 || healthUrl == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: unable to allocate buffer for health check uri.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ curl_easy_setopt(curl, CURLOPT_URL, healthUrl);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlResult);
+ res = curl_easy_perform(curl);
+ free(healthUrl);
+
+ if (res == CURLE_OK) {
+ DBGPRINTF("omelasticsearch: checkConn %s completed with success "
+ "on attempt %d\n", serverUrl, i);
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ DBGPRINTF("omelasticsearch: checkConn %s failed on attempt %d: %s\n",
+ serverUrl, i, curl_easy_strerror(res));
+ STATSCOUNTER_INC(checkConnFail, mutCheckConnFail);
+ incrementServerIndex(pWrkrData);
+ }
+
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "omelasticsearch: checkConn failed after %d attempts.", i);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+
+finalize_it:
+ if(urlBuf != NULL)
+ es_deleteStr(urlBuf);
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ DBGPRINTF("omelasticsearch: tryResume called\n");
+ iRet = checkConn(pWrkrData);
+ENDtryResume
+
+
+/* get the current index and type for this message */
+static void ATTR_NONNULL(1)
+getIndexTypeAndParent(const instanceData *const pData, uchar **const tpls,
+ uchar **const srchIndex, uchar **const srchType, uchar **const parent,
+ uchar **const bulkId, uchar **const pipelineName)
+{
+ *srchIndex = pData->searchIndex;
+ *parent = pData->parent;
+ *srchType = pData->searchType;
+ *bulkId = pData->bulkId;
+ *pipelineName = pData->pipelineName;
+ if(tpls == NULL) {
+ goto done;
+ }
+
+ int iNumTpls = 1;
+ if(pData->dynSrchIdx) {
+ *srchIndex = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+ if(pData->dynSrchType) {
+ *srchType = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+ if(pData->dynParent) {
+ *parent = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+ if(pData->dynBulkId) {
+ *bulkId = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+ if(pData->dynPipelineName) {
+ *pipelineName = tpls[iNumTpls];
+ ++iNumTpls;
+ }
+
+done:
+ return;
+}
+
+
+static rsRetVal ATTR_NONNULL(1)
+setPostURL(wrkrInstanceData_t *const pWrkrData, uchar **const tpls)
+{
+ uchar *searchIndex = NULL;
+ uchar *searchType;
+ uchar *pipelineName;
+ uchar *parent;
+ uchar *bulkId;
+ char* baseUrl;
+ /* since 7.0, the API always requires /idx/_doc, so use that if searchType is not explicitly set */
+ uchar* actualSearchType = (uchar*)"_doc";
+ es_str_t *url;
+ int r = 0;
+ DEFiRet;
+ instanceData *const pData = pWrkrData->pData;
+ char separator;
+ const int bulkmode = pData->bulkmode;
+
+ baseUrl = (char*)pData->serverBaseUrls[pWrkrData->serverIndex];
+ url = es_newStrFromCStr(baseUrl, strlen(baseUrl));
+ if (url == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: error allocating new estr for POST url.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ separator = '?';
+
+ if(bulkmode) {
+ r = es_addBuf(&url, "_bulk", sizeof("_bulk")-1);
+ parent = NULL;
+ } else {
+ getIndexTypeAndParent(pData, tpls, &searchIndex, &searchType, &parent, &bulkId, &pipelineName);
+ if(searchIndex != NULL) {
+ r = es_addBuf(&url, (char*)searchIndex, ustrlen(searchIndex));
+ if(searchType != NULL && searchType[0] != '\0') {
+ actualSearchType = searchType;
+ }
+ if(r == 0) r = es_addChar(&url, '/');
+ if(r == 0) r = es_addBuf(&url, (char*)actualSearchType, ustrlen(actualSearchType));
+ }
+ if(pipelineName != NULL && (!pData->skipPipelineIfEmpty || pipelineName[0] != '\0')) {
+ if(r == 0) r = es_addChar(&url, separator);
+ if(r == 0) r = es_addBuf(&url, "pipeline=", sizeof("pipeline=")-1);
+ if(r == 0) r = es_addBuf(&url, (char*)pipelineName, ustrlen(pipelineName));
+ separator = '&';
+ }
+ }
+
+ if(pData->timeout != NULL) {
+ if(r == 0) r = es_addChar(&url, separator);
+ if(r == 0) r = es_addBuf(&url, "timeout=", sizeof("timeout=")-1);
+ if(r == 0) r = es_addBuf(&url, (char*)pData->timeout, ustrlen(pData->timeout));
+ separator = '&';
+ }
+
+ if(parent != NULL) {
+ if(r == 0) r = es_addChar(&url, separator);
+ if(r == 0) r = es_addBuf(&url, "parent=", sizeof("parent=")-1);
+ if(r == 0) es_addBuf(&url, (char*)parent, ustrlen(parent));
+ }
+
+ if(pWrkrData->restURL != NULL)
+ free(pWrkrData->restURL);
+
+ pWrkrData->restURL = (uchar*)es_str2cstr(url, NULL);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_URL, pWrkrData->restURL);
+ DBGPRINTF("omelasticsearch: using REST URL: '%s'\n", pWrkrData->restURL);
+
+finalize_it:
+ if (url != NULL)
+ es_deleteStr(url);
+ RETiRet;
+}
+
+
+/* this method computes the expected size of adding the next message into
+ * the batched request to elasticsearch
+ */
+static size_t
+computeMessageSize(const wrkrInstanceData_t *const pWrkrData,
+ const uchar *const message,
+ uchar **const tpls)
+{
+ size_t r = sizeof(META_END)-1 + sizeof("\n")-1;
+ if (pWrkrData->pData->writeOperation == ES_WRITE_CREATE)
+ r += sizeof(META_STRT_CREATE)-1;
+ else
+ r += sizeof(META_STRT)-1;
+
+ uchar *searchIndex = NULL;
+ uchar *searchType;
+ uchar *parent = NULL;
+ uchar *bulkId = NULL;
+ uchar *pipelineName;
+
+ getIndexTypeAndParent(pWrkrData->pData, tpls, &searchIndex, &searchType, &parent, &bulkId, &pipelineName);
+ r += ustrlen((char *)message);
+ if(searchIndex != NULL) {
+ r += ustrlen(searchIndex);
+ }
+ if(searchType != NULL) {
+ if(searchType[0] == '\0') {
+ r += 4; // "_doc"
+ } else {
+ r += ustrlen(searchType);
+ }
+ }
+ if(parent != NULL) {
+ r += sizeof(META_PARENT)-1 + ustrlen(parent);
+ }
+ if(bulkId != NULL) {
+ r += sizeof(META_ID)-1 + ustrlen(bulkId);
+ }
+ if(pipelineName != NULL && (!pWrkrData->pData->skipPipelineIfEmpty || pipelineName[0] != '\0')) {
+ r += sizeof(META_PIPELINE)-1 + ustrlen(pipelineName);
+ }
+
+ return r;
+}
+
+
+/* this method does not directly submit but builds a batch instead. It
+ * may submit, if we have dynamic index/type and the current type or
+ * index changes.
+ */
+static rsRetVal
+buildBatch(wrkrInstanceData_t *pWrkrData, uchar *message, uchar **tpls)
+{
+ int length = strlen((char *)message);
+ int r;
+ int endQuote = 1;
+ uchar *searchIndex = NULL;
+ uchar *searchType;
+ uchar *parent = NULL;
+ uchar *bulkId = NULL;
+ uchar *pipelineName;
+ DEFiRet;
+
+ getIndexTypeAndParent(pWrkrData->pData, tpls, &searchIndex, &searchType, &parent, &bulkId, &pipelineName);
+ if (pWrkrData->pData->writeOperation == ES_WRITE_CREATE) {
+ r = es_addBuf(&pWrkrData->batch.data, META_STRT_CREATE, sizeof(META_STRT_CREATE)-1);
+ endQuote = 0;
+ } else
+ r = es_addBuf(&pWrkrData->batch.data, META_STRT, sizeof(META_STRT)-1);
+ if(searchIndex != NULL) {
+ endQuote = 1;
+ if (pWrkrData->pData->writeOperation == ES_WRITE_CREATE)
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_IX, sizeof(META_IX)-1);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)searchIndex,
+ ustrlen(searchIndex));
+ if(searchType != NULL && searchType[0] != '\0') {
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_TYPE, sizeof(META_TYPE)-1);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)searchType,
+ ustrlen(searchType));
+ }
+ }
+ if(parent != NULL) {
+ endQuote = 1;
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_PARENT, sizeof(META_PARENT)-1);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)parent, ustrlen(parent));
+ }
+ if(pipelineName != NULL && (!pWrkrData->pData->skipPipelineIfEmpty || pipelineName[0] != '\0')) {
+ endQuote = 1;
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_PIPELINE, sizeof(META_PIPELINE)-1);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)pipelineName, ustrlen(pipelineName));
+ }
+ if(bulkId != NULL) {
+ endQuote = 1;
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_ID, sizeof(META_ID)-1);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)bulkId, ustrlen(bulkId));
+ }
+ if(endQuote == 0) {
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_END_NOQUOTE, sizeof(META_END_NOQUOTE)-1);
+ } else {
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, META_END, sizeof(META_END)-1);
+ }
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, (char*)message, length);
+ if(r == 0) r = es_addBuf(&pWrkrData->batch.data, "\n", sizeof("\n")-1);
+ if(r != 0) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: growing batch failed with code %d", r);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ ++pWrkrData->batch.nmemb;
+ iRet = RS_RET_OK;
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * Dumps entire bulk request and response in error log
+ */
+static rsRetVal
+getDataErrorDefault(wrkrInstanceData_t *pWrkrData,fjson_object **pReplyRoot,uchar *reqmsg,char **rendered)
+{
+ DEFiRet;
+ fjson_object *req=NULL;
+ fjson_object *errRoot=NULL;
+ fjson_object *replyRoot = *pReplyRoot;
+
+ if((req=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ fjson_object_object_add(req, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ fjson_object_object_add(req, "postdata", fjson_object_new_string((char*)reqmsg));
+
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ fjson_object_object_add(errRoot, "request", req);
+ fjson_object_object_add(errRoot, "reply", replyRoot);
+ *rendered = strdup((char*)fjson_object_to_json_string(errRoot));
+
+ req=NULL;
+ fjson_object_put(errRoot);
+
+ *pReplyRoot = NULL; /* tell caller not to delete once again! */
+
+ finalize_it:
+ fjson_object_put(req);
+ RETiRet;
+}
+
+/*
+ * Sets bulkRequestNextSectionStart pointer to next sections start in the buffer pointed by bulkRequest.
+ * Sections are marked by { and }
+ */
+static rsRetVal
+getSection(const char* bulkRequest, const char **bulkRequestNextSectionStart )
+{
+ DEFiRet;
+ char* idx =0;
+ if( (idx = strchr(bulkRequest,'\n')) != 0)/*intermediate section*/
+ {
+ *bulkRequestNextSectionStart = ++idx;
+ }
+ else
+ {
+ *bulkRequestNextSectionStart=0;
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ finalize_it:
+ RETiRet;
+}
+
+/*
+ * Sets the new string in singleRequest for one request in bulkRequest
+ * and sets lastLocation pointer to the location till which bulkrequest has been parsed.
+ * (used as input to make function thread safe.)
+ */
+static rsRetVal
+getSingleRequest(const char* bulkRequest, char** singleRequest, const char **lastLocation)
+{
+ DEFiRet;
+ const char *req = bulkRequest;
+ const char *start = bulkRequest;
+ if (getSection(req,&req)!=RS_RET_OK)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ if (getSection(req,&req)!=RS_RET_OK)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ CHKmalloc(*singleRequest = (char*) calloc (req - start+ 1 + 1,1));
+ /* (req - start+ 1 == length of data + 1 for terminal char)*/
+ memcpy(*singleRequest,start,req - start);
+ *lastLocation=req;
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * check the status of response from ES
+ */
+static int checkReplyStatus(fjson_object* ok) {
+ return (ok == NULL || !fjson_object_is_type(ok, fjson_type_int) || fjson_object_get_int(ok) < 0 ||
+ fjson_object_get_int(ok) > 299);
+}
+
+/*
+ * Context object for error file content creation or status check
+ * response_item - the full {"create":{"_index":"idxname",.....}}
+ * response_body - the inner hash of the response_item - {"_index":"idxname",...}
+ * status - the "status" field from the inner hash - "status":500
+ * should be able to use fjson_object_get_int(status) to get the http result code
+ */
+typedef struct exeContext{
+ int statusCheckOnly;
+ fjson_object *errRoot;
+ rsRetVal (*prepareErrorFileContent)(struct exeContext *ctx,int itemStatus,char *request,char *response,
+ fjson_object *response_item, fjson_object *response_body, fjson_object *status);
+ es_write_ops_t writeOperation;
+ ratelimit_t *ratelimiter;
+ ruleset_t *retryRuleset;
+ struct json_tokener *jTokener;
+} context;
+
+/*
+ * get content to be written in error file using context passed
+ */
+static rsRetVal
+parseRequestAndResponseForContext(wrkrInstanceData_t *pWrkrData,fjson_object **pReplyRoot,uchar *reqmsg,context *ctx)
+{
+ DEFiRet;
+ fjson_object *replyRoot = *pReplyRoot;
+ int i;
+ int numitems;
+ fjson_object *items=NULL, *jo_errors = NULL;
+
+ /*iterate over items*/
+ if(!fjson_object_object_get_ex(replyRoot, "items", &items)) {
+ LogError(0, RS_RET_DATAFAIL,
+ "omelasticsearch: error in elasticsearch reply: "
+ "bulkmode insert does not return array, reply is: %s",
+ pWrkrData->reply);
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+
+ numitems = fjson_object_array_length(items);
+
+ int errors = 0;
+ if(fjson_object_object_get_ex(replyRoot, "errors", &jo_errors)) {
+ errors = fjson_object_get_boolean(jo_errors);
+ if (!errors && pWrkrData->pData->retryFailures) {
+ STATSCOUNTER_ADD(indexSuccess, mutIndexSuccess, numitems);
+ return RS_RET_OK;
+ }
+ }
+
+ if (reqmsg) {
+ DBGPRINTF("omelasticsearch: Entire request %s\n", reqmsg);
+ } else {
+ DBGPRINTF("omelasticsearch: Empty request\n");
+ }
+ const char *lastReqRead= (char*)reqmsg;
+
+ DBGPRINTF("omelasticsearch: %d items in reply\n", numitems);
+ for(i = 0 ; i < numitems ; ++i) {
+
+ fjson_object *item=NULL;
+ fjson_object *result=NULL;
+ fjson_object *ok=NULL;
+ int itemStatus=0;
+ item = fjson_object_array_get_idx(items, i);
+ if(item == NULL) {
+ LogError(0, RS_RET_DATAFAIL,
+ "omelasticsearch: error in elasticsearch reply: "
+ "cannot obtain reply array item %d", i);
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+ fjson_object_object_get_ex(item, "create", &result);
+ if(result == NULL || !fjson_object_is_type(result, fjson_type_object)) {
+ fjson_object_object_get_ex(item, "index", &result);
+ if(result == NULL || !fjson_object_is_type(result, fjson_type_object)) {
+ LogError(0, RS_RET_DATAFAIL,
+ "omelasticsearch: error in elasticsearch reply: "
+ "cannot obtain 'result' item for #%d", i);
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+ }
+
+ fjson_object_object_get_ex(result, "status", &ok);
+ itemStatus = checkReplyStatus(ok);
+
+ char *request =0;
+ char *response =0;
+ if(ctx->statusCheckOnly || (NULL == lastReqRead)) {
+ if(itemStatus) {
+ DBGPRINTF("omelasticsearch: error in elasticsearch reply: item %d, "
+ "status is %d\n", i, fjson_object_get_int(ok));
+ DBGPRINTF("omelasticsearch: status check found error.\n");
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+
+ } else {
+ if(getSingleRequest(lastReqRead,&request,&lastReqRead) != RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: Couldn't get post request\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ response = (char*)fjson_object_to_json_string_ext(result, FJSON_TO_STRING_PLAIN);
+
+ if(response==NULL) {
+ free(request);/*as its has been assigned.*/
+ DBGPRINTF("omelasticsearch: Error getting fjson_object_to_string_ext. Cannot "
+ "continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /*call the context*/
+ rsRetVal ret = ctx->prepareErrorFileContent(ctx, itemStatus, request,
+ response, item, result, ok);
+
+ /*free memory in any case*/
+ free(request);
+
+ if(ret != RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: Error in preparing errorfileContent. Cannot continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * Dumps only failed requests of bulk insert
+ */
+static rsRetVal
+getDataErrorOnly(context *ctx,int itemStatus,char *request,char *response,
+ fjson_object *response_item, fjson_object *response_body, fjson_object *status)
+{
+ DEFiRet;
+ (void)response_item; /* unused */
+ (void)response_body; /* unused */
+ (void)status; /* unused */
+ if(itemStatus) {
+ fjson_object *onlyErrorResponses =NULL;
+ fjson_object *onlyErrorRequests=NULL;
+
+ if(!fjson_object_object_get_ex(ctx->errRoot, "reply", &onlyErrorResponses)) {
+ DBGPRINTF("omelasticsearch: Failed to get reply json array. Invalid context. Cannot "
+ "continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ fjson_object_array_add(onlyErrorResponses, fjson_object_new_string(response));
+
+ if(!fjson_object_object_get_ex(ctx->errRoot, "request", &onlyErrorRequests)) {
+ DBGPRINTF("omelasticsearch: Failed to get request json array. Invalid context. Cannot "
+ "continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object_array_add(onlyErrorRequests, fjson_object_new_string(request));
+
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/*
+ * Dumps all requests of bulk insert interleaved with request and response
+ */
+
+static rsRetVal
+getDataInterleaved(context *ctx,
+ int __attribute__((unused)) itemStatus,
+ char *request,
+ char *response,
+ fjson_object *response_item,
+ fjson_object *response_body,
+ fjson_object *status
+)
+{
+ DEFiRet;
+ (void)response_item; /* unused */
+ (void)response_body; /* unused */
+ (void)status; /* unused */
+ fjson_object *interleaved =NULL;
+ if(!fjson_object_object_get_ex(ctx->errRoot, "response", &interleaved)) {
+ DBGPRINTF("omelasticsearch: Failed to get response json array. Invalid context. Cannot continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object *interleavedNode=NULL;
+ /*create interleaved node that has req and response json data*/
+ if((interleavedNode=fjson_object_new_object()) == NULL)
+ {
+ DBGPRINTF("omelasticsearch: Failed to create interleaved node. Cann't continue\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ fjson_object_object_add(interleavedNode,"request", fjson_object_new_string(request));
+ fjson_object_object_add(interleavedNode,"reply", fjson_object_new_string(response));
+
+ fjson_object_array_add(interleaved, interleavedNode);
+
+
+
+ finalize_it:
+ RETiRet;
+}
+
+
+/*
+ * Dumps only failed requests of bulk insert interleaved with request and response
+ */
+
+static rsRetVal
+getDataErrorOnlyInterleaved(context *ctx,int itemStatus,char *request,char *response,
+ fjson_object *response_item, fjson_object *response_body, fjson_object *status)
+{
+ DEFiRet;
+ if (itemStatus) {
+ if(getDataInterleaved(ctx, itemStatus,request,response,
+ response_item, response_body, status)!= RS_RET_OK) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ finalize_it:
+ RETiRet;
+}
+
+/* input JSON looks like this:
+ * {"someoperation":{"field1":"value1","field2":{.....}}}
+ * output looks like this:
+ * {"writeoperation":"someoperation","field1":"value1","field2":{.....}}
+ */
+static rsRetVal
+formatBulkReqOrResp(fjson_object *jo_input, fjson_object *jo_output)
+{
+ DEFiRet;
+ fjson_object *jo = NULL;
+ struct json_object_iterator it = json_object_iter_begin(jo_input);
+ struct json_object_iterator itEnd = json_object_iter_end(jo_input);
+
+ /* set the writeoperation if not already set */
+ if (!fjson_object_object_get_ex(jo_output, "writeoperation", NULL)) {
+ const char *optype = NULL;
+ if (!json_object_iter_equal(&it, &itEnd))
+ optype = json_object_iter_peek_name(&it);
+ if (optype) {
+ jo = json_object_new_string(optype);
+ } else {
+ jo = json_object_new_string("unknown");
+ }
+ CHKmalloc(jo);
+ json_object_object_add(jo_output, "writeoperation", jo);
+ }
+ if (!json_object_iter_equal(&it, &itEnd)) {
+ /* now iterate the operation object */
+ jo = json_object_iter_peek_value(&it);
+ it = json_object_iter_begin(jo);
+ itEnd = json_object_iter_end(jo);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ const char *name = json_object_iter_peek_name(&it);
+ /* do not overwrite existing fields */
+ if (!fjson_object_object_get_ex(jo_output, name, NULL)) {
+ json_object_object_add(jo_output, name,
+ json_object_get(json_object_iter_peek_value(&it)));
+ }
+ json_object_iter_next(&it);
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* request string looks like this (other fields are "_parent" and "pipeline")
+ * "{\"create\":{\"_index\": \"rsyslog_testbench\",\"_type\":\"test-type\",
+ * \"_id\":\"FAEAFC0D17C847DA8BD6F47BC5B3800A\"}}\n
+ * {\"msgnum\":\"x00000000\",\"viaq_msg_id\":\"FAEAFC0D17C847DA8BD6F47BC5B3800A\"}\n"
+ * store the metadata header fields in the metadata object
+ * start = first \n + 1
+ * end = last \n
+ */
+static rsRetVal
+createMsgFromRequest(const char *request, context *ctx, smsg_t **msg, fjson_object *omes)
+{
+ DEFiRet;
+ fjson_object *jo_msg = NULL, *jo_metadata = NULL, *jo_request = NULL;
+ const char *datastart, *dataend;
+ size_t datalen;
+ enum json_tokener_error json_error;
+
+ *msg = NULL;
+ if (!(datastart = strchr(request, '\n')) || (datastart[1] != '{')) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: malformed original request - "
+ "could not find start of original data [%s]",
+ request);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ datalen = datastart - request;
+ json_tokener_reset(ctx->jTokener);
+ jo_metadata = json_tokener_parse_ex(ctx->jTokener, request, datalen);
+ json_error = fjson_tokener_get_error(ctx->jTokener);
+ if (!jo_metadata || (json_error != fjson_tokener_success)) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: parse error [%s] - could not convert original "
+ "request metadata header JSON back into JSON object [%s]",
+ fjson_tokener_error_desc(json_error), request);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKiRet(formatBulkReqOrResp(jo_metadata, omes));
+
+ datastart++; /* advance to '{' */
+ if (!(dataend = strchr(datastart, '\n')) || (dataend[1] != '\0')) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: malformed original request - "
+ "could not find end of original data [%s]",
+ request);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ datalen = dataend - datastart;
+ json_tokener_reset(ctx->jTokener);
+ jo_request = json_tokener_parse_ex(ctx->jTokener, datastart, datalen);
+ json_error = fjson_tokener_get_error(ctx->jTokener);
+ if (!jo_request || (json_error != fjson_tokener_success)) {
+ LogError(0, RS_RET_ERR,
+ "omelasticsearch: parse error [%s] - could not convert original "
+ "request JSON back into JSON object [%s]",
+ fjson_tokener_error_desc(json_error), request);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ CHKiRet(msgConstruct(msg));
+ MsgSetFlowControlType(*msg, eFLOWCTL_FULL_DELAY);
+ MsgSetInputName(*msg, pInputName);
+ if (fjson_object_object_get_ex(jo_request, "message", &jo_msg)) {
+ const char *rawmsg = json_object_get_string(jo_msg);
+ const size_t msgLen = (size_t)json_object_get_string_len(jo_msg);
+ MsgSetRawMsg(*msg, rawmsg, msgLen);
+ } else {
+ /* use entire data part of request as rawmsg */
+ MsgSetRawMsg(*msg, datastart, datalen);
+ }
+ MsgSetMSGoffs(*msg, 0); /* we do not have a header... */
+ MsgSetTAG(*msg, (const uchar *)"omes", 4);
+ CHKiRet(msgAddJSON(*msg, (uchar*)"!", jo_request, 0, 0));
+
+finalize_it:
+ if (jo_metadata)
+ json_object_put(jo_metadata);
+ RETiRet;
+}
+
+
+static rsRetVal
+getDataRetryFailures(context *ctx,int itemStatus,char *request,char *response,
+ fjson_object *response_item, fjson_object *response_body, fjson_object *status)
+{
+ DEFiRet;
+ fjson_object *omes = NULL, *jo = NULL;
+ int istatus = fjson_object_get_int(status);
+ int iscreateop = 0;
+ const char *optype = NULL;
+ smsg_t *msg = NULL;
+ int need_free_omes = 0;
+
+ (void)response;
+ (void)itemStatus;
+ (void)response_body;
+ CHKmalloc(omes = json_object_new_object());
+ need_free_omes = 1;
+ /* this adds metadata header fields to omes */
+ if (RS_RET_OK != (iRet = createMsgFromRequest(request, ctx, &msg, omes))) {
+ if (iRet != RS_RET_OUT_OF_MEMORY) {
+ STATSCOUNTER_INC(indexBadResponse, mutIndexBadResponse);
+ } else {
+ ABORT_FINALIZE(iRet);
+ }
+ }
+ CHKmalloc(msg);
+ /* this adds response fields as local variables to omes */
+ if (RS_RET_OK != (iRet = formatBulkReqOrResp(response_item, omes))) {
+ if (iRet != RS_RET_OUT_OF_MEMORY) {
+ STATSCOUNTER_INC(indexBadResponse, mutIndexBadResponse);
+ } else {
+ ABORT_FINALIZE(iRet);
+ }
+ }
+ if (fjson_object_object_get_ex(omes, "writeoperation", &jo)) {
+ optype = json_object_get_string(jo);
+ if (optype && !strcmp("create", optype))
+ iscreateop = 1;
+ if (optype && !strcmp("index", optype) && (ctx->writeOperation == ES_WRITE_INDEX))
+ iscreateop = 1;
+ }
+
+ if (!optype) {
+ STATSCOUNTER_INC(indexBadResponse, mutIndexBadResponse);
+ LogMsg(0, RS_RET_ERR, LOG_INFO,
+ "omelasticsearch: no recognized operation type in response [%s]",
+ response);
+ } else if ((istatus == 200) || (istatus == 201)) {
+ STATSCOUNTER_INC(indexSuccess, mutIndexSuccess);
+ } else if ((istatus == 409) && iscreateop) {
+ STATSCOUNTER_INC(indexDuplicate, mutIndexDuplicate);
+ } else if ((istatus == 400) || (istatus < 200)) {
+ STATSCOUNTER_INC(indexBadArgument, mutIndexBadArgument);
+ } else {
+ fjson_object *error = NULL, *errtype = NULL;
+ if(fjson_object_object_get_ex(omes, "error", &error) &&
+ fjson_object_object_get_ex(error, "type", &errtype)) {
+ if (istatus == 429) {
+ STATSCOUNTER_INC(indexBulkRejection, mutIndexBulkRejection);
+ } else {
+ STATSCOUNTER_INC(indexOtherResponse, mutIndexOtherResponse);
+ }
+ } else {
+ STATSCOUNTER_INC(indexBadResponse, mutIndexBadResponse);
+ LogMsg(0, RS_RET_ERR, LOG_INFO,
+ "omelasticsearch: unexpected error response [%s]",
+ response);
+ }
+ }
+
+ need_free_omes = 0;
+ CHKiRet(msgAddJSON(msg, (uchar*)".omes", omes, 0, 0));
+ MsgSetRuleset(msg, ctx->retryRuleset);
+ CHKiRet(ratelimitAddMsg(ctx->ratelimiter, NULL, msg));
+finalize_it:
+ if (need_free_omes)
+ json_object_put(omes);
+ RETiRet;
+}
+
+/*
+ * get erroronly context
+ */
+static rsRetVal
+initializeErrorOnlyConext(wrkrInstanceData_t *pWrkrData,context *ctx){
+ DEFiRet;
+ ctx->statusCheckOnly=0;
+ fjson_object *errRoot=NULL;
+ fjson_object *onlyErrorResponses =NULL;
+ fjson_object *onlyErrorRequests=NULL;
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+
+ if((onlyErrorResponses=fjson_object_new_array()) == NULL) {
+ fjson_object_put(errRoot);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if((onlyErrorRequests=fjson_object_new_array()) == NULL) {
+ fjson_object_put(errRoot);
+ fjson_object_put(onlyErrorResponses);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ fjson_object_object_add(errRoot, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ fjson_object_object_add(errRoot,"request",onlyErrorRequests);
+ fjson_object_object_add(errRoot, "reply", onlyErrorResponses);
+ ctx->errRoot = errRoot;
+ ctx->prepareErrorFileContent= &getDataErrorOnly;
+ finalize_it:
+ RETiRet;
+}
+
+/*
+ * get interleaved context
+ */
+static rsRetVal
+initializeInterleavedConext(wrkrInstanceData_t *pWrkrData,context *ctx){
+ DEFiRet;
+ ctx->statusCheckOnly=0;
+ fjson_object *errRoot=NULL;
+ fjson_object *interleaved =NULL;
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ if((interleaved=fjson_object_new_array()) == NULL) {
+ fjson_object_put(errRoot);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+
+ fjson_object_object_add(errRoot, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ fjson_object_object_add(errRoot,"response",interleaved);
+ ctx->errRoot = errRoot;
+ ctx->prepareErrorFileContent= &getDataInterleaved;
+ finalize_it:
+ RETiRet;
+}
+
+/*get interleaved context*/
+static rsRetVal
+initializeErrorInterleavedConext(wrkrInstanceData_t *pWrkrData,context *ctx){
+ DEFiRet;
+ ctx->statusCheckOnly=0;
+ fjson_object *errRoot=NULL;
+ fjson_object *interleaved =NULL;
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+ if((interleaved=fjson_object_new_array()) == NULL) {
+ fjson_object_put(errRoot);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+
+ fjson_object_object_add(errRoot, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ fjson_object_object_add(errRoot,"response",interleaved);
+ ctx->errRoot = errRoot;
+ ctx->prepareErrorFileContent= &getDataErrorOnlyInterleaved;
+ finalize_it:
+ RETiRet;
+}
+
+/*get retry failures context*/
+static rsRetVal
+initializeRetryFailuresContext(wrkrInstanceData_t *pWrkrData,context *ctx){
+ DEFiRet;
+ ctx->statusCheckOnly=0;
+ fjson_object *errRoot=NULL;
+ if((errRoot=fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR);
+
+
+ fjson_object_object_add(errRoot, "url", fjson_object_new_string((char*)pWrkrData->restURL));
+ ctx->errRoot = errRoot;
+ ctx->prepareErrorFileContent= &getDataRetryFailures;
+ CHKmalloc(ctx->jTokener = json_tokener_new());
+ finalize_it:
+ RETiRet;
+}
+
+
+/* write data error request/replies to separate error file
+ * Note: we open the file but never close it before exit. If it
+ * needs to be closed, HUP must be sent.
+ */
+static rsRetVal ATTR_NONNULL()
+writeDataError(wrkrInstanceData_t *const pWrkrData,
+ instanceData *const pData, fjson_object **const pReplyRoot,
+ uchar *const reqmsg)
+{
+ char *rendered = NULL;
+ size_t toWrite;
+ ssize_t wrRet;
+ sbool bMutLocked = 0;
+ context ctx;
+ ctx.errRoot=0;
+ ctx.writeOperation = pWrkrData->pData->writeOperation;
+ ctx.ratelimiter = pWrkrData->pData->ratelimiter;
+ ctx.retryRuleset = pWrkrData->pData->retryRuleset;
+ ctx.jTokener = NULL;
+ DEFiRet;
+
+ if(pData->errorFile == NULL) {
+ DBGPRINTF("omelasticsearch: no local error logger defined - "
+ "ignoring ES error information\n");
+ FINALIZE;
+ }
+
+ pthread_mutex_lock(&pData->mutErrFile);
+ bMutLocked = 1;
+
+ DBGPRINTF("omelasticsearch: error file mode: erroronly='%d' errorInterleaved='%d'\n",
+ pData->errorOnly, pData->interleaved);
+
+ if(pData->interleaved ==0 && pData->errorOnly ==0)/*default write*/
+ {
+ if(getDataErrorDefault(pWrkrData,pReplyRoot, reqmsg, &rendered) != RS_RET_OK) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ /*get correct context.*/
+ if(pData->interleaved && pData->errorOnly)
+ {
+ if(initializeErrorInterleavedConext(pWrkrData, &ctx) != RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: error initializing error interleaved context.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ } else if(pData->errorOnly) {
+ if(initializeErrorOnlyConext(pWrkrData, &ctx) != RS_RET_OK) {
+
+ DBGPRINTF("omelasticsearch: error initializing error only context.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(pData->interleaved) {
+ if(initializeInterleavedConext(pWrkrData, &ctx) != RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: error initializing error interleaved context.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(pData->retryFailures) {
+ if(initializeRetryFailuresContext(pWrkrData, &ctx) != RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: error initializing retry failures context.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ DBGPRINTF("omelasticsearch: None of the modes match file write. No data to write.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /*execute context*/
+ if(parseRequestAndResponseForContext(pWrkrData, pReplyRoot, reqmsg, &ctx)!= RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: error creating file content.\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKmalloc(rendered = strdup((char*)fjson_object_to_json_string(ctx.errRoot)));
+ }
+
+
+ if(pData->fdErrFile == -1) {
+ pData->fdErrFile = open((char*)pData->errorFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pData->fdErrFile == -1) {
+ LogError(errno, RS_RET_ERR, "omelasticsearch: error opening error file %s",
+ pData->errorFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ /* we do not do real error-handling on the err file, as this finally complicates
+ * things way to much.
+ */
+ DBGPRINTF("omelasticsearch: error record: '%s'\n", rendered);
+ toWrite = strlen(rendered) + 1;
+ /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid
+ * caling malloc() -- write() does NOT need '\0'!
+ */
+ rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+ wrRet = write(pData->fdErrFile, rendered, toWrite);
+ if(wrRet != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "omelasticsearch: error writing error file %s, write returned %lld",
+ pData->errorFile, (long long) wrRet);
+ }
+
+finalize_it:
+ if(bMutLocked)
+ pthread_mutex_unlock(&pData->mutErrFile);
+ free(rendered);
+ fjson_object_put(ctx.errRoot);
+ if (ctx.jTokener)
+ json_tokener_free(ctx.jTokener);
+ RETiRet;
+}
+
+
+static rsRetVal
+checkResultBulkmode(wrkrInstanceData_t *pWrkrData, fjson_object *root, uchar *reqmsg)
+{
+ DEFiRet;
+ context ctx;
+ ctx.errRoot = 0;
+ ctx.writeOperation = pWrkrData->pData->writeOperation;
+ ctx.ratelimiter = pWrkrData->pData->ratelimiter;
+ ctx.retryRuleset = pWrkrData->pData->retryRuleset;
+ ctx.statusCheckOnly=1;
+ ctx.jTokener = NULL;
+ if (pWrkrData->pData->retryFailures) {
+ ctx.statusCheckOnly=0;
+ CHKiRet(initializeRetryFailuresContext(pWrkrData, &ctx));
+ }
+ if(parseRequestAndResponseForContext(pWrkrData,&root,reqmsg,&ctx)!= RS_RET_OK) {
+ DBGPRINTF("omelasticsearch: error found in elasticsearch reply\n");
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+
+finalize_it:
+ fjson_object_put(ctx.errRoot);
+ if (ctx.jTokener)
+ json_tokener_free(ctx.jTokener);
+ RETiRet;
+}
+
+
+static rsRetVal
+checkResult(wrkrInstanceData_t *pWrkrData, uchar *reqmsg)
+{
+ fjson_object *root;
+ fjson_object *status;
+ DEFiRet;
+
+ root = fjson_tokener_parse(pWrkrData->reply);
+ if(root == NULL) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING,
+ "omelasticsearch: could not parse JSON result");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(pWrkrData->pData->bulkmode) {
+ iRet = checkResultBulkmode(pWrkrData, root, reqmsg);
+ } else {
+ if(fjson_object_object_get_ex(root, "status", &status)) {
+ iRet = RS_RET_DATAFAIL;
+ }
+ }
+
+ /* Note: we ignore errors writing the error file, as we cannot handle
+ * these in any case.
+ */
+ if(iRet == RS_RET_DATAFAIL) {
+ STATSCOUNTER_INC(indexESFail, mutIndexESFail);
+ writeDataError(pWrkrData, pWrkrData->pData, &root, reqmsg);
+ iRet = RS_RET_OK; /* we have handled the problem! */
+ }
+
+finalize_it:
+ if(root != NULL)
+ fjson_object_put(root);
+ if(iRet != RS_RET_OK) {
+ STATSCOUNTER_INC(indexESFail, mutIndexESFail);
+ }
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+initializeBatch(wrkrInstanceData_t *pWrkrData)
+{
+ es_emptyStr(pWrkrData->batch.data);
+ pWrkrData->batch.nmemb = 0;
+}
+
+static rsRetVal ATTR_NONNULL(1, 2)
+curlPost(wrkrInstanceData_t *pWrkrData, uchar *message, int msglen, uchar **tpls, const int nmsgs)
+{
+ CURLcode code;
+ CURL *const curl = pWrkrData->curlPostHandle;
+ char errbuf[CURL_ERROR_SIZE] = "";
+ DEFiRet;
+
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+
+ if ((pWrkrData->pData->rebindInterval > -1) &&
+ (pWrkrData->nOperations > pWrkrData->pData->rebindInterval)) {
+ curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
+ pWrkrData->nOperations = 0;
+ STATSCOUNTER_INC(rebinds, mutRebinds);
+ } else {
+ /* by default, reuse existing connections */
+ curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 0);
+ }
+ if ((pWrkrData->pData->rebindInterval > -1) &&
+ (pWrkrData->nOperations == pWrkrData->pData->rebindInterval)) {
+ curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
+ } else {
+ curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 0);
+ }
+
+ if(pWrkrData->pData->numServers > 1) {
+ /* needs to be called to support ES HA feature */
+ CHKiRet(checkConn(pWrkrData));
+ }
+ pWrkrData->replyLen = 0;
+ CHKiRet(setPostURL(pWrkrData, tpls));
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char *)message);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msglen);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+ code = curl_easy_perform(curl);
+ DBGPRINTF("curl returned %lld\n", (long long) code);
+ if (code != CURLE_OK && code != CURLE_HTTP_RETURNED_ERROR) {
+ STATSCOUNTER_INC(indexHTTPReqFail, mutIndexHTTPReqFail);
+ indexHTTPFail += nmsgs;
+ LogError(0, RS_RET_SUSPENDED,
+ "omelasticsearch: we are suspending ourselfs due "
+ "to server failure %lld: %s", (long long) code, errbuf);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if (pWrkrData->pData->rebindInterval > -1)
+ pWrkrData->nOperations++;
+
+ if(pWrkrData->reply == NULL) {
+ DBGPRINTF("omelasticsearch: pWrkrData reply==NULL, replyLen = '%d'\n",
+ pWrkrData->replyLen);
+ } else {
+ DBGPRINTF("omelasticsearch: pWrkrData replyLen = '%d'\n", pWrkrData->replyLen);
+ if(pWrkrData->replyLen > 0) {
+ pWrkrData->reply[pWrkrData->replyLen] = '\0';
+ /* Append 0 Byte if replyLen is above 0 - byte has been reserved in malloc */
+ }
+ DBGPRINTF("omelasticsearch: pWrkrData reply: '%s'\n", pWrkrData->reply);
+ CHKiRet(checkResult(pWrkrData, message));
+ }
+
+finalize_it:
+ incrementServerIndex(pWrkrData);
+ RETiRet;
+}
+
+static rsRetVal
+submitBatch(wrkrInstanceData_t *pWrkrData)
+{
+ char *cstr = NULL;
+ DEFiRet;
+
+ cstr = es_str2cstr(pWrkrData->batch.data, NULL);
+ dbgprintf("omelasticsearch: submitBatch, batch: '%s'\n", cstr);
+
+ CHKiRet(curlPost(pWrkrData, (uchar*) cstr, strlen(cstr), NULL, pWrkrData->batch.nmemb));
+
+finalize_it:
+ free(cstr);
+ RETiRet;
+}
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ if(!pWrkrData->pData->bulkmode) {
+ FINALIZE;
+ }
+
+ initializeBatch(pWrkrData);
+finalize_it:
+ENDbeginTransaction
+
+BEGINdoAction
+CODESTARTdoAction
+ STATSCOUNTER_INC(indexSubmit, mutIndexSubmit);
+
+ if(pWrkrData->pData->bulkmode) {
+ const size_t nBytes = computeMessageSize(pWrkrData, ppString[0], ppString);
+
+ /* If max bytes is set and this next message will put us over the limit,
+ * submit the current buffer and reset */
+ if(pWrkrData->pData->maxbytes > 0
+ && es_strlen(pWrkrData->batch.data) + nBytes > pWrkrData->pData->maxbytes ) {
+ dbgprintf("omelasticsearch: maxbytes limit reached, submitting partial "
+ "batch of %d elements.\n", pWrkrData->batch.nmemb);
+ CHKiRet(submitBatch(pWrkrData));
+ initializeBatch(pWrkrData);
+ }
+ CHKiRet(buildBatch(pWrkrData, ppString[0], ppString));
+
+ /* If there is only one item in the batch, all previous items have been
+ * submitted or this is the first item for this transaction. Return previous
+ * committed so that all items leading up to the current (exclusive)
+ * are not replayed should a failure occur anywhere else in the transaction. */
+ iRet = pWrkrData->batch.nmemb == 1 ? RS_RET_PREVIOUS_COMMITTED : RS_RET_DEFER_COMMIT;
+ } else {
+ CHKiRet(curlPost(pWrkrData, ppString[0], strlen((char*)ppString[0]),
+ ppString, 1));
+ }
+finalize_it:
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+ /* End Transaction only if batch data is not empty */
+ if (pWrkrData->batch.data != NULL && pWrkrData->batch.nmemb > 0) {
+ CHKiRet(submitBatch(pWrkrData));
+ } else {
+ dbgprintf("omelasticsearch: endTransaction, pWrkrData->batch.data is NULL, "
+ "nothing to send. \n");
+ }
+finalize_it:
+ENDendTransaction
+
+static rsRetVal
+computeAuthHeader(char* uid, char* pwd, uchar** authBuf) {
+ int r;
+ DEFiRet;
+
+ es_str_t* auth = es_newStr(1024);
+ if (auth == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY,
+ "omelasticsearch: failed to allocate es_str auth for auth header construction");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ r = es_addBuf(&auth, uid, strlen(uid));
+ if(r == 0) r = es_addChar(&auth, ':');
+ if(r == 0 && pwd != NULL) r = es_addBuf(&auth, pwd, strlen(pwd));
+ if(r == 0) *authBuf = (uchar*) es_str2cstr(auth, NULL);
+
+ if (r != 0 || *authBuf == NULL) {
+ LogError(0, RS_RET_ERR, "omelasticsearch: failed to build auth header\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if (auth != NULL)
+ es_deleteStr(auth);
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+curlSetupCommon(wrkrInstanceData_t *const pWrkrData, CURL *const handle)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader);
+ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData);
+ if(pWrkrData->pData->allowUnsignedCerts)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE);
+ if(pWrkrData->pData->skipVerifyHost)
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, FALSE);
+ if(pWrkrData->pData->authBuf != NULL) {
+ curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf);
+ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+ }
+ if(pWrkrData->pData->caCertFile)
+ curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile);
+ if(pWrkrData->pData->myCertFile)
+ curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile);
+ if(pWrkrData->pData->myPrivKeyFile)
+ curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile);
+ /* uncomment for in-dept debuggung:
+ curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */
+}
+
+static void ATTR_NONNULL()
+curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curlSetupCommon(pWrkrData, pWrkrData->curlCheckConnHandle);
+ curl_easy_setopt(pWrkrData->curlCheckConnHandle,
+ CURLOPT_TIMEOUT_MS, pWrkrData->pData->healthCheckTimeout);
+}
+
+static void ATTR_NONNULL(1)
+curlPostSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES);
+ curlSetupCommon(pWrkrData, pWrkrData->curlPostHandle);
+ curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_POST, 1);
+ curl_easy_setopt(pWrkrData->curlPostHandle,
+ CURLOPT_TIMEOUT_MS, pWrkrData->pData->indexTimeout);
+}
+
+#define CONTENT_JSON "Content-Type: application/json; charset=utf-8"
+
+static rsRetVal ATTR_NONNULL()
+curlSetup(wrkrInstanceData_t *const pWrkrData)
+{
+ DEFiRet;
+ pWrkrData->curlHeader = curl_slist_append(NULL, CONTENT_JSON);
+ CHKmalloc(pWrkrData->curlPostHandle = curl_easy_init());;
+ curlPostSetup(pWrkrData);
+
+ CHKmalloc(pWrkrData->curlCheckConnHandle = curl_easy_init());
+ curlCheckConnSetup(pWrkrData);
+
+finalize_it:
+ if(iRet != RS_RET_OK && pWrkrData->curlPostHandle != NULL) {
+ curl_easy_cleanup(pWrkrData->curlPostHandle);
+ pWrkrData->curlPostHandle = NULL;
+ }
+ RETiRet;
+}
+
+static void ATTR_NONNULL()
+setInstParamDefaults(instanceData *const pData)
+{
+ pData->serverBaseUrls = NULL;
+ pData->defaultPort = 9200;
+ pData->healthCheckTimeout = 3500;
+ pData->indexTimeout = 0;
+ pData->uid = NULL;
+ pData->pwd = NULL;
+ pData->authBuf = NULL;
+ pData->searchIndex = NULL;
+ pData->searchType = NULL;
+ pData->pipelineName = NULL;
+ pData->dynPipelineName = 0;
+ pData->skipPipelineIfEmpty = 0;
+ pData->parent = NULL;
+ pData->timeout = NULL;
+ pData->dynSrchIdx = 0;
+ pData->dynSrchType = 0;
+ pData->dynParent = 0;
+ pData->useHttps = 0;
+ pData->bulkmode = 0;
+ pData->maxbytes = 104857600; //100 MB Is the default max message size that ships with ElasticSearch
+ pData->allowUnsignedCerts = 0;
+ pData->skipVerifyHost = 0;
+ pData->tplName = NULL;
+ pData->errorFile = NULL;
+ pData->errorOnly=0;
+ pData->interleaved=0;
+ pData->dynBulkId= 0;
+ pData->bulkId = NULL;
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+ pData->writeOperation = ES_WRITE_INDEX;
+ pData->retryFailures = 0;
+ pData->ratelimitBurst = 20000;
+ pData->ratelimitInterval = 600;
+ pData->ratelimiter = NULL;
+ pData->retryRulesetName = NULL;
+ pData->retryRuleset = NULL;
+ pData->rebindInterval = DEFAULT_REBIND_INTERVAL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ char* serverParam = NULL;
+ struct cnfarray* servers = NULL;
+ int i;
+ int iNumTpls;
+ FILE *fp;
+ char errStr[1024];
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ servers = pvals[i].val.d.ar;
+ } else if(!strcmp(actpblk.descr[i].name, "errorfile")) {
+ pData->errorFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "erroronly")) {
+ pData->errorOnly = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "interleaved")) {
+ pData->interleaved = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->defaultPort = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "healthchecktimeout")) {
+ pData->healthCheckTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "indextimeout")) {
+ pData->indexTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "uid")) {
+ pData->uid = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ pData->pwd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "searchindex")) {
+ pData->searchIndex = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "searchtype")) {
+ pData->searchType = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "pipelinename")) {
+ pData->pipelineName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynpipelinename")) {
+ pData->dynPipelineName = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "skippipelineifempty")) {
+ pData->skipPipelineIfEmpty = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "parent")) {
+ pData->parent = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynsearchindex")) {
+ pData->dynSrchIdx = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dynsearchtype")) {
+ pData->dynSrchType = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dynparent")) {
+ pData->dynParent = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "bulkmode")) {
+ pData->bulkmode = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "maxbytes")) {
+ pData->maxbytes = (size_t) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) {
+ pData->allowUnsignedCerts = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "skipverifyhost")) {
+ pData->skipVerifyHost = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "timeout")) {
+ pData->timeout = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "usehttps")) {
+ pData->useHttps = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynbulkid")) {
+ pData->dynBulkId = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "bulkid")) {
+ pData->bulkId = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ pData->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->caCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.cacert' file %s couldn't be accessed: %s\n",
+ pData->caCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.mycert' file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "writeoperation")) {
+ char *writeop = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (writeop && !strcmp(writeop, "create")) {
+ pData->writeOperation = ES_WRITE_CREATE;
+ } else if (writeop && !strcmp(writeop, "index")) {
+ pData->writeOperation = ES_WRITE_INDEX;
+ } else if (writeop) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: invalid value '%s' for writeoperation: "
+ "must be one of 'index' or 'create' - using default value 'index'", writeop);
+ pData->writeOperation = ES_WRITE_INDEX;
+ }
+ free(writeop);
+ } else if(!strcmp(actpblk.descr[i].name, "retryfailures")) {
+ pData->retryFailures = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.burst")) {
+ pData->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.interval")) {
+ pData->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "retryruleset")) {
+ pData->retryRulesetName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "rebindinterval")) {
+ pData->rebindInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "esversion.major")) {
+ pData->esVersion = pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR, "omelasticsearch: program error, "
+ "non-handled param '%s'", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->pwd != NULL && pData->uid == NULL) {
+ LogError(0, RS_RET_UID_MISSING,
+ "omelasticsearch: password is provided, but no uid "
+ "- action definition invalid");
+ ABORT_FINALIZE(RS_RET_UID_MISSING);
+ }
+ if(pData->dynSrchIdx && pData->searchIndex == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: requested dynamic search index, but no "
+ "name for index template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(pData->dynSrchType && pData->searchType == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: requested dynamic search type, but no "
+ "name for type template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(pData->dynParent && pData->parent == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: requested dynamic parent, but no "
+ "name for parent template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(pData->dynBulkId && pData->bulkId == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: requested dynamic bulkid, but no "
+ "name for bulkid template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(pData->dynPipelineName && pData->pipelineName == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: requested dynamic pipeline name, but no "
+ "name for pipelineName template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if (pData->uid != NULL)
+ CHKiRet(computeAuthHeader((char*) pData->uid, (char*) pData->pwd, &pData->authBuf));
+
+ iNumTpls = 1;
+ if(pData->dynSrchIdx) ++iNumTpls;
+ if(pData->dynSrchType) ++iNumTpls;
+ if(pData->dynParent) ++iNumTpls;
+ if(pData->dynBulkId) ++iNumTpls;
+ if(pData->dynPipelineName) ++iNumTpls;
+ DBGPRINTF("omelasticsearch: requesting %d templates\n", iNumTpls);
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ " StdJSONFmt" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+
+ /* we need to request additional templates. If we have a dynamic search index,
+ * it will always be string 1. Type may be 1 or 2, depending on whether search
+ * index is dynamic as well. Rule needs to be followed throughout the module.
+ */
+ iNumTpls = 1;
+ if(pData->dynSrchIdx) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->searchIndex),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+ if(pData->dynSrchType) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->searchType),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+ if(pData->dynParent) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->parent),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+ if(pData->dynBulkId) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->bulkId),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+ if(pData->dynPipelineName) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->pipelineName),
+ OMSR_NO_RQD_TPL_OPTS));
+ ++iNumTpls;
+ }
+
+
+ if (servers != NULL) {
+ pData->numServers = servers->nmemb;
+ pData->serverBaseUrls = malloc(servers->nmemb * sizeof(uchar*));
+ if (pData->serverBaseUrls == NULL) {
+ LogError(0, RS_RET_ERR, "omelasticsearch: unable to allocate buffer "
+ "for ElasticSearch server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for(i = 0 ; i < servers->nmemb ; ++i) {
+ serverParam = es_str2cstr(servers->arr[i], NULL);
+ if (serverParam == NULL) {
+ LogError(0, RS_RET_ERR, "omelasticsearch: unable to allocate buffer "
+ "for ElasticSearch server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* Remove a trailing slash if it exists */
+ const size_t serverParamLastChar = strlen(serverParam)-1;
+ if (serverParam[serverParamLastChar] == '/') {
+ serverParam[serverParamLastChar] = '\0';
+ }
+ CHKiRet(computeBaseUrl(serverParam, pData->defaultPort, pData->useHttps,
+ pData->serverBaseUrls + i));
+ free(serverParam);
+ serverParam = NULL;
+ }
+ } else {
+ LogMsg(0, RS_RET_OK, LOG_WARNING,
+ "omelasticsearch: No servers specified, using localhost");
+ pData->numServers = 1;
+ pData->serverBaseUrls = malloc(sizeof(uchar*));
+ if (pData->serverBaseUrls == NULL) {
+ LogError(0, RS_RET_ERR, "omelasticsearch: unable to allocate buffer "
+ "for ElasticSearch server configuration.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ CHKiRet(computeBaseUrl("localhost", pData->defaultPort, pData->useHttps, pData->serverBaseUrls));
+ }
+
+ if(pData->esVersion < 8) {
+ if(pData->searchIndex == NULL)
+ pData->searchIndex = (uchar*) strdup("system");
+ if(pData->searchType == NULL)
+ pData->searchType = (uchar*) strdup("events");
+
+ if ((pData->writeOperation != ES_WRITE_INDEX) && (pData->bulkId == NULL)) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omelasticsearch: writeoperation '%d' requires bulkid", pData->writeOperation);
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ }
+
+ if (pData->retryFailures) {
+ CHKiRet(ratelimitNew(&pData->ratelimiter, "omelasticsearch", NULL));
+ ratelimitSetLinuxLike(pData->ratelimiter, pData->ratelimitInterval, pData->ratelimitBurst);
+ ratelimitSetNoTimeCache(pData->ratelimiter);
+ }
+
+ /* node created, let's add to list of instance configs for the module */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = pData;
+ } else {
+ loadModConf->tail->next = pData;
+ loadModConf->tail = pData;
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ if (serverParam)
+ free(serverParam);
+ENDnewActInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->root = pModConf->tail = NULL;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+
+ if (inst->retryRulesetName) {
+ localRet = ruleset.GetRuleset(pModConf->pConf, &pRuleset, inst->retryRulesetName);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, localRet, "omelasticsearch: retryruleset '%s' not found - "
+ "no retry ruleset will be used", inst->retryRulesetName);
+ } else {
+ inst->retryRuleset = pRuleset;
+ }
+ }
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutErrFile);
+ if(pData->fdErrFile != -1) {
+ close(pData->fdErrFile);
+ pData->fdErrFile = -1;
+ }
+ pthread_mutex_unlock(&pData->mutErrFile);
+ENDdoHUP
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ curl_global_cleanup();
+ statsobj.Destruct(&indexStats);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -elasticsearch indexing disabled");
+ ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED);
+ }
+
+ /* support statistics gathering */
+ CHKiRet(statsobj.Construct(&indexStats));
+ CHKiRet(statsobj.SetName(indexStats, (uchar *)"omelasticsearch"));
+ CHKiRet(statsobj.SetOrigin(indexStats, (uchar *)"omelasticsearch"));
+ STATSCOUNTER_INIT(indexSubmit, mutIndexSubmit);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexSubmit));
+ STATSCOUNTER_INIT(indexHTTPFail, mutIndexHTTPFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.http",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexHTTPFail));
+ STATSCOUNTER_INIT(indexHTTPReqFail, mutIndexHTTPReqFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.httprequests",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexHTTPReqFail));
+ STATSCOUNTER_INIT(checkConnFail, mutCheckConnFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.checkConn",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &checkConnFail));
+ STATSCOUNTER_INIT(indexESFail, mutIndexESFail);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.es",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexESFail));
+ STATSCOUNTER_INIT(indexSuccess, mutIndexSuccess);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.success",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexSuccess));
+ STATSCOUNTER_INIT(indexBadResponse, mutIndexBadResponse);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.bad",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexBadResponse));
+ STATSCOUNTER_INIT(indexDuplicate, mutIndexDuplicate);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.duplicate",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexDuplicate));
+ STATSCOUNTER_INIT(indexBadArgument, mutIndexBadArgument);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.badargument",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexBadArgument));
+ STATSCOUNTER_INIT(indexBulkRejection, mutIndexBulkRejection);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.bulkrejection",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexBulkRejection));
+ STATSCOUNTER_INIT(indexOtherResponse, mutIndexOtherResponse);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"response.other",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &indexOtherResponse));
+ STATSCOUNTER_INIT(rebinds, mutRebinds);
+ CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"rebinds",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &rebinds));
+ CHKiRet(statsobj.ConstructFinalize(indexStats));
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("omelasticsearch"), sizeof("omelasticsearch") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/omgssapi/Makefile.am b/plugins/omgssapi/Makefile.am
new file mode 100644
index 0000000..a57a64b
--- /dev/null
+++ b/plugins/omgssapi/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = omgssapi.la
+
+omgssapi_la_SOURCES = omgssapi.c
+omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omgssapi_la_LDFLAGS = -module -avoid-version
+omgssapi_la_LIBADD = $(GSS_LIBS)
diff --git a/plugins/omgssapi/Makefile.in b/plugins/omgssapi/Makefile.in
new file mode 100644
index 0000000..7b364ff
--- /dev/null
+++ b/plugins/omgssapi/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omgssapi
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omgssapi_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omgssapi_la_OBJECTS = omgssapi_la-omgssapi.lo
+omgssapi_la_OBJECTS = $(am_omgssapi_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 =
+omgssapi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omgssapi_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omgssapi_la-omgssapi.Plo
+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 = $(omgssapi_la_SOURCES)
+DIST_SOURCES = $(omgssapi_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omgssapi.la
+omgssapi_la_SOURCES = omgssapi.c
+omgssapi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omgssapi_la_LDFLAGS = -module -avoid-version
+omgssapi_la_LIBADD = $(GSS_LIBS)
+all: 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) --gnu plugins/omgssapi/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omgssapi/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omgssapi.la: $(omgssapi_la_OBJECTS) $(omgssapi_la_DEPENDENCIES) $(EXTRA_omgssapi_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omgssapi_la_LINK) -rpath $(pkglibdir) $(omgssapi_la_OBJECTS) $(omgssapi_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omgssapi_la-omgssapi.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omgssapi_la-omgssapi.lo: omgssapi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omgssapi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omgssapi_la-omgssapi.lo -MD -MP -MF $(DEPDIR)/omgssapi_la-omgssapi.Tpo -c -o omgssapi_la-omgssapi.lo `test -f 'omgssapi.c' || echo '$(srcdir)/'`omgssapi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omgssapi_la-omgssapi.Tpo $(DEPDIR)/omgssapi_la-omgssapi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omgssapi.c' object='omgssapi_la-omgssapi.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) $(omgssapi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omgssapi_la-omgssapi.lo `test -f 'omgssapi.c' || echo '$(srcdir)/'`omgssapi.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omgssapi_la-omgssapi.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omgssapi_la-omgssapi.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c
new file mode 100644
index 0000000..9d9d12e
--- /dev/null
+++ b/plugins/omgssapi/omgssapi.c
@@ -0,0 +1,720 @@
+/* omgssapi.c
+ * This is the implementation of the build-in forwarding output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#ifdef USE_GSSAPI
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <zlib.h>
+#include <pthread.h>
+#include <gssapi/gssapi.h>
+#include "dirty.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "template.h"
+#include "msg.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "gss-misc.h"
+#include "tcpclt.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "rsconf.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(gssutil)
+DEFobjCurrIf(tcpclt)
+
+typedef struct _instanceData {
+ char *f_hname;
+ short sock; /* file descriptor */
+ enum { /* TODO: we shoud revisit these definitions */
+ eDestFORW,
+ eDestFORW_SUSP,
+ eDestFORW_UNKN
+ } eDestState;
+ struct addrinfo *f_addr;
+ int compressionLevel; /* 0 - no compression, else level for zlib */
+ char *port;
+ tcpclt_t *pTCPClt; /* our tcpclt object */
+ gss_ctx_id_t gss_context;
+ OM_uint32 gss_flags;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+/* config data */
+
+typedef enum gss_mode_e {
+ GSSMODE_MIC,
+ GSSMODE_ENC
+} gss_mode_t;
+
+static struct configSettings_s {
+ uchar *pszTplName; /* name of the default template to use */
+ char *gss_base_service_name;
+ gss_mode_t gss_mode;
+} cs;
+
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+/* get the syslog forward port from selector_t. The passed in
+ * struct must be one that is setup for forwarding.
+ * rgerhards, 2007-06-28
+ * We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use the IANA default auf 514.
+ */
+static const char *
+getFwdSyslogPt(instanceData *pData)
+{
+ assert(pData != NULL);
+ if(pData->port == NULL)
+ return("514");
+ else
+ return(pData->port);
+}
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+OM_uint32 maj_stat, min_stat;
+CODESTARTfreeInstance
+ switch (pData->eDestState) {
+ case eDestFORW:
+ case eDestFORW_SUSP:
+ freeaddrinfo(pData->f_addr);
+ /* fall through */
+ case eDestFORW_UNKN:
+ if(pData->port != NULL)
+ free(pData->port);
+ break;
+ }
+
+ if (pData->gss_context != GSS_C_NO_CONTEXT) {
+ maj_stat = gss_delete_sec_context(&min_stat, &pData->gss_context, GSS_C_NO_BUFFER);
+ if (maj_stat != GSS_S_COMPLETE)
+ gssutil.display_status((char*)"deleting context", maj_stat, min_stat);
+ }
+ /* this is meant to be done when module is unloaded,
+ but since this module is static...
+ */
+ free(cs.gss_base_service_name);
+ cs.gss_base_service_name = NULL;
+
+ /* final cleanup */
+ tcpclt.Destruct(&pData->pTCPClt);
+ if(pData->sock >= 0)
+ close(pData->sock);
+
+ if(pData->f_hname != NULL)
+ free(pData->f_hname);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("%s", pData->f_hname);
+ENDdbgPrintInstInfo
+
+
+/* This function is called immediately before a send retry is attempted.
+ * It shall clean up whatever makes sense.
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendGSSPrepRetry(void __attribute__((unused)) *pData)
+{
+ /* in case of TCP/GSS, there is nothing to do */
+ return RS_RET_OK;
+}
+
+
+static rsRetVal TCPSendGSSInit(void *pvData)
+{
+ DEFiRet;
+ int s = -1;
+ const char *base;
+ OM_uint32 maj_stat, min_stat, init_sec_min_stat, *sess_flags, ret_flags;
+ gss_buffer_desc out_tok, in_tok;
+ gss_buffer_t tok_ptr;
+ gss_name_t target_name;
+ gss_ctx_id_t *context;
+ instanceData *pData = (instanceData *) pvData;
+
+ assert(pData != NULL);
+
+ /* if the socket is already initialized, we are done */
+ if(pData->sock > 0)
+ ABORT_FINALIZE(RS_RET_OK);
+
+ base = (cs.gss_base_service_name == NULL) ? "host" : cs.gss_base_service_name;
+ out_tok.length = strlen(pData->f_hname) + strlen(base) + 2;
+ CHKmalloc(out_tok.value = malloc(out_tok.length));
+ strcpy(out_tok.value, base);
+ strcat(out_tok.value, "@");
+ strcat(out_tok.value, pData->f_hname);
+ dbgprintf("GSS-API service name: %s\n", (char*) out_tok.value);
+
+ tok_ptr = GSS_C_NO_BUFFER;
+ context = &pData->gss_context;
+ *context = GSS_C_NO_CONTEXT;
+
+ maj_stat = gss_import_name(&min_stat, &out_tok, GSS_C_NT_HOSTBASED_SERVICE, &target_name);
+ free(out_tok.value);
+ out_tok.value = NULL;
+ out_tok.length = 0;
+
+ if (maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"parsing name", maj_stat, min_stat);
+ goto fail;
+ }
+
+ sess_flags = &pData->gss_flags;
+ *sess_flags = GSS_C_MUTUAL_FLAG;
+ if (cs.gss_mode == GSSMODE_MIC) {
+ *sess_flags |= GSS_C_INTEG_FLAG;
+ }
+ if (cs.gss_mode == GSSMODE_ENC) {
+ *sess_flags |= GSS_C_CONF_FLAG;
+ }
+ dbgprintf("GSS-API requested context flags:\n");
+ gssutil.display_ctx_flags(*sess_flags);
+
+ do {
+ maj_stat = gss_init_sec_context(&init_sec_min_stat, GSS_C_NO_CREDENTIAL, context,
+ target_name, GSS_C_NO_OID, *sess_flags, 0, NULL,
+ tok_ptr, NULL, &out_tok, &ret_flags, NULL);
+ if (tok_ptr != GSS_C_NO_BUFFER)
+ free(in_tok.value);
+
+ if (maj_stat != GSS_S_COMPLETE
+ && maj_stat != GSS_S_CONTINUE_NEEDED) {
+ gssutil.display_status((char*)"initializing context", maj_stat, init_sec_min_stat);
+ goto fail;
+ }
+
+ if (s == -1)
+ if ((s = pData->sock = tcpclt.CreateSocket(pData->f_addr)) == -1)
+ goto fail;
+
+ if (out_tok.length != 0) {
+ dbgprintf("GSS-API Sending init_sec_context token (length: %ld)\n", (long) out_tok.length);
+ if (gssutil.send_token(s, &out_tok) < 0) {
+ goto fail;
+ }
+ }
+ gss_release_buffer(&min_stat, &out_tok);
+
+ if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+ dbgprintf("GSS-API Continue needed...\n");
+ if (gssutil.recv_token(s, &in_tok) <= 0) {
+ goto fail;
+ }
+ tok_ptr = &in_tok;
+ }
+ } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+ dbgprintf("GSS-API Provided context flags:\n");
+ *sess_flags = ret_flags;
+ gssutil.display_ctx_flags(*sess_flags);
+
+ dbgprintf("GSS-API Context initialized\n");
+ gss_release_name(&min_stat, &target_name);
+
+finalize_it:
+ RETiRet;
+
+fail:
+ LogError(0, RS_RET_GSS_SENDINIT_ERROR, "GSS-API Context initialization failed\n");
+ gss_release_name(&min_stat, &target_name);
+ gss_release_buffer(&min_stat, &out_tok);
+ if (*context != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER);
+ *context = GSS_C_NO_CONTEXT;
+ }
+ if (s != -1)
+ close(s);
+ pData->sock = -1;
+ ABORT_FINALIZE(RS_RET_GSS_SENDINIT_ERROR);
+}
+
+
+static rsRetVal TCPSendGSSSend(void *pvData, char *msg, size_t len)
+{
+ int s;
+ gss_ctx_id_t *context;
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc in_buf, out_buf;
+ instanceData *pData = (instanceData *) pvData;
+
+ assert(pData != NULL);
+ assert(msg != NULL);
+ assert(len > 0);
+
+ s = pData->sock;
+ context = &pData->gss_context;
+ in_buf.value = msg;
+ in_buf.length = len;
+ maj_stat = gss_wrap(&min_stat, *context, (cs.gss_mode == GSSMODE_ENC) ? 1 : 0, GSS_C_QOP_DEFAULT,
+ &in_buf, NULL, &out_buf);
+ if (maj_stat != GSS_S_COMPLETE) {
+ gssutil.display_status((char*)"wrapping message", maj_stat, min_stat);
+ goto fail;
+ }
+
+ if (gssutil.send_token(s, &out_buf) < 0) {
+ goto fail;
+ }
+ gss_release_buffer(&min_stat, &out_buf);
+
+ return RS_RET_OK;
+
+fail:
+ close(s);
+ pData->sock = -1;
+ gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER);
+ *context = GSS_C_NO_CONTEXT;
+ gss_release_buffer(&min_stat, &out_buf);
+ dbgprintf("message not (GSS/tcp)send");
+ return RS_RET_GSS_SEND_ERROR;
+}
+
+
+/* try to resume connection if it is not ready
+ * rgerhards, 2007-08-02
+ */
+static rsRetVal doTryResume(instanceData *pData)
+{
+ DEFiRet;
+ struct addrinfo *res;
+ struct addrinfo hints;
+
+ switch (pData->eDestState) {
+ case eDestFORW_SUSP:
+ iRet = RS_RET_OK; /* the actual check happens during doAction() only */
+ pData->eDestState = eDestFORW;
+ break;
+
+ case eDestFORW_UNKN:
+ /* The remote address is not yet known and needs to be obtained */
+ dbgprintf(" %s\n", pData->f_hname);
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requests this */
+ /* TODO: this code is a duplicate from cfline() - we should later create
+ * a common function.
+ */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily(runConf);
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res) == 0) {
+ dbgprintf("%s found, resuming.\n", pData->f_hname);
+ pData->f_addr = res;
+ pData->eDestState = eDestFORW;
+ } else {
+ iRet = RS_RET_SUSPENDED;
+ }
+ break;
+ case eDestFORW:
+ /* NOOP */
+ break;
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ pthread_mutex_lock(&mutDoAct);
+ iRet = doTryResume(pWrkrData->pData);
+ pthread_mutex_unlock(&mutDoAct);
+ENDtryResume
+
+BEGINdoAction
+ char *psz = NULL; /* temporary buffering */
+ register unsigned l;
+ int iMaxLine;
+ instanceData *pData;
+CODESTARTdoAction
+ pthread_mutex_lock(&mutDoAct);
+ pData = pWrkrData->pData;
+ switch (pData->eDestState) {
+ case eDestFORW_SUSP:
+ dbgprintf("internal error in omgssapi.c, eDestFORW_SUSP in doAction()!\n");
+ iRet = RS_RET_SUSPENDED;
+ break;
+
+ case eDestFORW_UNKN:
+ dbgprintf("doAction eDestFORW_UNKN\n");
+ iRet = doTryResume(pData);
+ break;
+
+ case eDestFORW:
+ dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData), "tcp-gssapi");
+ iMaxLine = glbl.GetMaxLine(runConf);
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if((int) l > iMaxLine)
+ l = iMaxLine;
+
+ /* Check if we should compress and, if so, do it. We also
+ * check if the message is large enough to justify compression.
+ * The smaller the message, the less likely is a gain in compression.
+ * To save CPU cycles, we do not try to compress very small messages.
+ * What "very small" means needs to be configured. Currently, it is
+ * hard-coded but this may be changed to a config parameter.
+ * rgerhards, 2006-11-30
+ */
+ if(pData->compressionLevel && (l > CONF_MIN_SIZE_FOR_COMPRESS)) {
+ Bytef *out;
+ uLongf destLen = iMaxLine + iMaxLine/100 +12; /* recommended value from zlib doc */
+ uLong srcLen = l;
+ int ret;
+ /* TODO: optimize malloc sequence? -- rgerhards, 2008-09-02 */
+ CHKmalloc(out = (Bytef*) malloc(iMaxLine + iMaxLine/100 + 12));
+ out[0] = 'z';
+ out[1] = '\0';
+ ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz,
+ srcLen, pData->compressionLevel);
+ dbgprintf("Compressing message, length was %d now %d, return state %d.\n",
+ l, (int) destLen, ret);
+ if(ret != Z_OK) {
+ /* if we fail, we complain, but only in debug mode
+ * Otherwise, we are silent. In any case, we ignore the
+ * failed compression and just sent the uncompressed
+ * data, which is still valid. So this is probably the
+ * best course of action.
+ * rgerhards, 2006-11-30
+ */
+ dbgprintf("Compression failed, sending uncompressed message\n");
+ free(out);
+ } else if(destLen+1 < l) {
+ /* only use compression if there is a gain in using it! */
+ dbgprintf("there is gain in compression, so we do it\n");
+ psz = (char*) out;
+ l = destLen + 1; /* take care for the "z" at message start! */
+ } else {
+ free(out);
+ }
+ ++destLen;
+ }
+
+ CHKiRet_Hdlr(tcpclt.Send(pData->pTCPClt, pData, psz, l)) {
+ /* error! */
+ dbgprintf("error forwarding via tcp, suspending\n");
+ pData->eDestState = eDestFORW_SUSP;
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ break;
+ }
+finalize_it:
+ if((psz != NULL) && (psz != (char*) ppString[0])) {
+ /* we need to free temporary buffer, alloced above - Naoya Nakazawa, 2010-01-11 */
+ free(psz);
+ }
+ pthread_mutex_unlock(&mutDoAct);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+ int bErr;
+ struct addrinfo hints, *res;
+ TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us
+ * The first test [*p == '>'] can be skipped if a module shall only
+ * support the newer slection syntax [:modname:]. This is in fact
+ * recommended for new modules. Please note that over time this part
+ * will be handled by rsyslogd itself, but for the time being it is
+ * a good compromise to do it at the module level.
+ * rgerhards, 2007-10-15
+ */
+
+ if(!strncmp((char*) p, ":omgssapi:", sizeof(":omgssapi:") - 1)) {
+ p += sizeof(":omgssapi:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ goto finalize_it;
+
+ /* we are now after the protocol indicator. Now check if we should
+ * use compression. We begin to use a new option format for this:
+ * @(option,option)host:port
+ * The first option defined is "z[0..9]" where the digit indicates
+ * the compression level. If it is not given, 9 (best compression) is
+ * assumed. An example action statement might be:
+ * @@(z5,o)127.0.0.1:1400
+ * Which means send via TCP with medium (5) compresion (z) to the local
+ * host on port 1400. The '0' option means that octet-couting (as in
+ * IETF I-D syslog-transport-tls) is to be used for framing (this option
+ * applies to TCP-based syslog only and is ignored when specified with UDP).
+ * That is not yet implemented.
+ * rgerhards, 2006-12-07
+ */
+ if(*p == '(') {
+ /* at this position, it *must* be an option indicator */
+ do {
+ ++p; /* eat '(' or ',' (depending on when called) */
+ /* check options */
+ if(*p == 'z') { /* compression */
+ ++p; /* eat */
+ if(isdigit((int) *p)) {
+ int iLevel;
+ iLevel = *p - '0';
+ ++p; /* eat */
+ pData->compressionLevel = iLevel;
+ } else {
+ LogError(0, NO_ERRCODE, "Invalid compression level '%c' specified in "
+ "forwarding action - NOT turning on compression.",
+ *p);
+ }
+ } else if(*p == 'o') { /* octet-couting based TCP framing? */
+ ++p; /* eat */
+ /* no further options settable */
+ tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else { /* invalid option! Just skip it... */
+ LogError(0, NO_ERRCODE, "Invalid option %c in forwarding action - "
+ "ignoring.", *p);
+ ++p; /* eat invalid option */
+ }
+ /* the option processing is done. We now do a generic skip
+ * to either the next option or the end of the option
+ * block.
+ */
+ while(*p && *p != ')' && *p != ',')
+ ++p; /* just skip it */
+ } while(*p && *p == ','); /* Attention: do.. while() */
+ if(*p == ')')
+ ++p; /* eat terminator, on to next */
+ else
+ /* we probably have end of string - leave it for the rest
+ * of the code to handle it (but warn the user)
+ */
+ LogError(0, NO_ERRCODE, "Option block not terminated in gssapi forward action.");
+ }
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p)
+ /* JUST SKIP */;
+
+ pData->port = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ pData->port = malloc(i + 1);
+ if(pData->port == NULL) {
+ LogError(0, NO_ERRCODE, "Could not get memory to store syslog forwarding port, "
+ "using default port, results may not be what you intend\n");
+ /* we leave f_forw.port set to NULL, this is then handled by
+ * getFwdSyslogPt().
+ */
+ } else {
+ memcpy(pData->port, tmp, i);
+ *(pData->port + i) = '\0';
+ }
+ }
+
+
+ /* now skip to template */
+ bErr = 0;
+ while(*p && *p != ';') {
+ if(*p && *p != ';' && !isspace((int) *p)) {
+ if(bErr == 0) { /* only 1 error msg! */
+ bErr = 1;
+ errno = 0;
+ LogError(0, NO_ERRCODE, "invalid selector line (port), probably not doing "
+ "what was intended");
+ }
+ }
+ ++p;
+ }
+
+ /* TODO: make this if go away! */
+ if(*p == ';' || *p == '#' || isspace(*p)) {
+ uchar cTmp = *p;
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ *p = cTmp;
+ } else {
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ }
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (cs.pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : cs.pszTplName));
+
+ /* first set the pData->eDestState */
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requests this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily(loadConf);
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res) != 0) {
+ pData->eDestState = eDestFORW_UNKN;
+ } else {
+ pData->eDestState = eDestFORW;
+ pData->f_addr = res;
+ }
+
+ /* now create our tcpclt */
+ CHKiRet(tcpclt.Construct(&pData->pTCPClt));
+ /* and set callbacks */
+ CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendGSSInit));
+ CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendGSSSend));
+ CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendGSSPrepRetry));
+ CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing));
+
+ /* TODO: do we need to call freeInstance if we failed - this is a general question for
+ * all output modules. I'll address it lates as the interface evolves. rgerhards, 2007-07-25
+ */
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(gssutil, LM_GSSUTIL_FILENAME);
+ objRelease(tcpclt, LM_TCPCLT_FILENAME);
+
+ if(cs.pszTplName != NULL) {
+ free(cs.pszTplName);
+ cs.pszTplName = NULL;
+ }
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+/* set a new GSSMODE based on config directive */
+static rsRetVal setGSSMode(void __attribute__((unused)) *pVal, uchar *mode)
+{
+ DEFiRet;
+
+ if (!strcmp((char *) mode, "integrity")) {
+ cs.gss_mode = GSSMODE_MIC;
+ dbgprintf("GSS-API gssmode set to GSSMODE_MIC\n");
+ } else if (!strcmp((char *) mode, "encryption")) {
+ cs.gss_mode = GSSMODE_ENC;
+ dbgprintf("GSS-API gssmode set to GSSMODE_ENC\n");
+ } else {
+ LogError(0, RS_RET_INVALID_PARAMS, "unknown gssmode parameter: %s", (char *) mode);
+ iRet = RS_RET_INVALID_PARAMS;
+ }
+ free(mode);
+
+ RETiRet;
+}
+
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.gss_mode = GSSMODE_ENC;
+ free(cs.gss_base_service_name);
+ cs.gss_base_service_name = NULL;
+ free(cs.pszTplName);
+ cs.pszTplName = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(gssutil, LM_GSSUTIL_FILENAME));
+ CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME));
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"gssforwardservicename", 0, eCmdHdlrGetWord, NULL,
+ &cs.gss_base_service_name, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"gssmode", 0, eCmdHdlrGetWord, setGSSMode, &cs.gss_mode,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actiongssforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszTplName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+#endif /* #ifdef USE_GSSAPI */
+/* vi:set ai:
+ */
diff --git a/plugins/omhdfs/Makefile.am b/plugins/omhdfs/Makefile.am
new file mode 100644
index 0000000..95e6b10
--- /dev/null
+++ b/plugins/omhdfs/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = omhdfs.la
+
+omhdfs_la_SOURCES = omhdfs.c
+omhdfs_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JAVA_INCLUDES)
+omhdfs_la_LDFLAGS = -module -avoid-version -lhdfs $(JAVA_LIBS)
+omhdfs_la_LIBADD = $(RSRT_LIBS)
diff --git a/plugins/omhdfs/Makefile.in b/plugins/omhdfs/Makefile.in
new file mode 100644
index 0000000..0aaa22a
--- /dev/null
+++ b/plugins/omhdfs/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omhdfs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omhdfs_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omhdfs_la_OBJECTS = omhdfs_la-omhdfs.lo
+omhdfs_la_OBJECTS = $(am_omhdfs_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 =
+omhdfs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omhdfs_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omhdfs_la-omhdfs.Plo
+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 = $(omhdfs_la_SOURCES)
+DIST_SOURCES = $(omhdfs_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omhdfs.la
+omhdfs_la_SOURCES = omhdfs.c
+omhdfs_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JAVA_INCLUDES)
+omhdfs_la_LDFLAGS = -module -avoid-version -lhdfs $(JAVA_LIBS)
+omhdfs_la_LIBADD = $(RSRT_LIBS)
+all: 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) --gnu plugins/omhdfs/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omhdfs/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omhdfs.la: $(omhdfs_la_OBJECTS) $(omhdfs_la_DEPENDENCIES) $(EXTRA_omhdfs_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omhdfs_la_LINK) -rpath $(pkglibdir) $(omhdfs_la_OBJECTS) $(omhdfs_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhdfs_la-omhdfs.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omhdfs_la-omhdfs.lo: omhdfs.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhdfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhdfs_la-omhdfs.lo -MD -MP -MF $(DEPDIR)/omhdfs_la-omhdfs.Tpo -c -o omhdfs_la-omhdfs.lo `test -f 'omhdfs.c' || echo '$(srcdir)/'`omhdfs.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhdfs_la-omhdfs.Tpo $(DEPDIR)/omhdfs_la-omhdfs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhdfs.c' object='omhdfs_la-omhdfs.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) $(omhdfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhdfs_la-omhdfs.lo `test -f 'omhdfs.c' || echo '$(srcdir)/'`omhdfs.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omhdfs_la-omhdfs.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omhdfs_la-omhdfs.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omhdfs/omhdfs.c b/plugins/omhdfs/omhdfs.c
new file mode 100644
index 0000000..bf80cc3
--- /dev/null
+++ b/plugins/omhdfs/omhdfs.c
@@ -0,0 +1,570 @@
+/* omhdfs.c
+ * This is an output module to support Hadoop's HDFS.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <pthread.h>
+#ifdef HAVE_HDFS_H
+# include <hdfs.h>
+#endif
+#ifdef HAVE_HADOOP_HDFS_H
+# include <hadoop/hdfs.h>
+#endif
+
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "conf.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "errmsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+/* MODULE_CNFNAME("omhdfs") we need this only when we convert the module to v2 config system */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+/* global data */
+static struct hashtable *files; /* holds all file objects that we know */
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct configSettings_s {
+ uchar *fileName;
+ uchar *hdfsHost;
+ uchar *dfltTplName; /* default template name to use */
+ int hdfsPort;
+} configSettings_t;
+static configSettings_t cs;
+
+typedef struct {
+ uchar *name;
+ hdfsFS fs;
+ hdfsFile fh;
+ const char *hdfsHost;
+ tPort hdfsPort;
+ int nUsers;
+ pthread_mutex_t mut;
+} file_t;
+
+
+typedef struct _instanceData {
+ file_t *pFile;
+ uchar ioBuf[64*1024];
+ size_t offsBuf;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+/* forward definitions (down here, need data types) */
+static inline rsRetVal fileClose(file_t *pFile);
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("omhdfs: file:%s", pData->pFile->name);
+ENDdbgPrintInstInfo
+
+
+/* note that hdfsFileExists() does not work, so we did our
+ * own function to see if a pathname exists. Returns 0 if the
+ * file does not exists, something else otherwise. Note that
+ * we can also check a directroy (if that matters...)
+ */
+static int
+HDFSFileExists(hdfsFS fs, uchar *name)
+{
+ int r;
+ hdfsFileInfo *info;
+
+ info = hdfsGetPathInfo(fs, (char*)name);
+ /* if things go wrong, we assume it is because the file
+ * does not exist. We do not get too much information...
+ */
+ if(info == NULL) {
+ r = 0;
+ } else {
+ r = 1;
+ hdfsFreeFileInfo(info, 1);
+ }
+ return r;
+}
+
+static inline rsRetVal
+HDFSmkdir(hdfsFS fs, uchar *name)
+{
+ DEFiRet;
+ if(hdfsCreateDirectory(fs, (char*)name) == -1)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ---BEGIN FILE OBJECT---------------------------------------------------- */
+/* This code handles the "file object". This is split from the actual
+ * instance data, because several instances may write into the same file.
+ * If so, we need to use a single object, and also synchronize their writes.
+ * So we keep the file object separately, and just stick a reference into
+ * the instance data.
+ */
+
+static rsRetVal
+fileObjConstruct(file_t **ppFile)
+{
+ file_t *pFile;
+ DEFiRet;
+
+ CHKmalloc(pFile = malloc(sizeof(file_t)));
+ pFile->name = NULL;
+ pFile->hdfsHost = NULL;
+ pFile->fh = NULL;
+ pFile->nUsers = 0;
+
+ *ppFile = pFile;
+finalize_it:
+ RETiRet;
+}
+
+static void
+fileObjAddUser(file_t *pFile)
+{
+ /* init mutex only when second user is added */
+ ++pFile->nUsers;
+ if(pFile->nUsers == 2)
+ pthread_mutex_init(&pFile->mut, NULL);
+ DBGPRINTF("omhdfs: file %s now being used by %d actions\n", pFile->name, pFile->nUsers);
+}
+
+static rsRetVal
+fileObjDestruct(file_t **ppFile)
+{
+ file_t *pFile = *ppFile;
+ if(pFile->nUsers > 1)
+ pthread_mutex_destroy(&pFile->mut);
+ fileClose(pFile);
+ free(pFile->name);
+ free((char*)pFile->hdfsHost);
+ free(pFile->fh);
+
+ return RS_RET_OK;
+}
+
+
+/* check, and potentially create, all names inside a path */
+static rsRetVal
+filePrepare(file_t *pFile)
+{
+ uchar *p;
+ uchar *pszWork;
+ size_t len;
+ DEFiRet;
+
+ if(HDFSFileExists(pFile->fs, pFile->name))
+ FINALIZE;
+
+ /* file does not exist, create it (and eventually parent directories */
+ if(1) { // check if bCreateDirs
+ len = ustrlen(pFile->name) + 1;
+ CHKmalloc(pszWork = malloc(len));
+ memcpy(pszWork, pFile->name, len);
+ for(p = pszWork+1 ; *p ; p++)
+ if(*p == '/') {
+ /* temporarily terminate string, create dir and go on */
+ *p = '\0';
+ if(!HDFSFileExists(pFile->fs, pszWork)) {
+ CHKiRet(HDFSmkdir(pFile->fs, pszWork));
+ }
+ *p = '/';
+ }
+ free(pszWork);
+ return 0;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* this function is to be used as destructor for the
+ * hash table code.
+ */
+static void
+fileObjDestruct4Hashtable(void *ptr)
+{
+ file_t *pFile = (file_t*) ptr;
+ fileObjDestruct(&pFile);
+}
+
+
+static rsRetVal
+fileOpen(file_t *pFile)
+{
+ DEFiRet;
+
+ assert(pFile->fh == NULL);
+ if(pFile->nUsers > 1)
+ d_pthread_mutex_lock(&pFile->mut);
+
+ DBGPRINTF("omhdfs: try to connect to HDFS at host '%s', port %d\n",
+ pFile->hdfsHost, pFile->hdfsPort);
+ pFile->fs = hdfsConnect(pFile->hdfsHost, pFile->hdfsPort);
+ if(pFile->fs == NULL) {
+ DBGPRINTF("omhdfs: error can not connect to hdfs\n");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ CHKiRet(filePrepare(pFile));
+
+ pFile->fh = hdfsOpenFile(pFile->fs, (char*)pFile->name, O_WRONLY|O_APPEND, 0, 0, 0);
+ if(pFile->fh == NULL) {
+ /* maybe the file does not exist, so we try to create it now.
+ * Note that we can not use hdfsExists() because of a deficit in
+ * it: https://issues.apache.org/jira/browse/HDFS-1154
+ * As of my testing, libhdfs at least seems to return ENOENT if
+ * the file does not exist.
+ */
+ if(errno == ENOENT) {
+ DBGPRINTF("omhdfs: ENOENT trying to append to '%s', now trying create\n",
+ pFile->name);
+ pFile->fh = hdfsOpenFile(pFile->fs,
+ (char*)pFile->name, O_WRONLY|O_CREAT, 0, 0, 0);
+ }
+ }
+ if(pFile->fh == NULL) {
+ DBGPRINTF("omhdfs: failed to open %s for writing!\n", pFile->name);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+finalize_it:
+ if(pFile->nUsers > 1)
+ d_pthread_mutex_unlock(&pFile->mut);
+ RETiRet;
+}
+
+
+/* Note: lenWrite is reset to zero on successful write! */
+static rsRetVal
+fileWrite(file_t *pFile, uchar *buf, size_t *lenWrite)
+{
+ DEFiRet;
+
+ if(*lenWrite == 0)
+ FINALIZE;
+
+ if(pFile->nUsers > 1)
+ d_pthread_mutex_lock(&pFile->mut);
+
+ /* open file if not open. This must be done *here* and while mutex-protected
+ * because of HUP handling (which is async to normal processing!).
+ */
+ if(pFile->fh == NULL) {
+ fileOpen(pFile);
+ if(pFile->fh == NULL) {
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+ tSize num_written_bytes = hdfsWrite(pFile->fs, pFile->fh, buf, *lenWrite);
+ if((unsigned) num_written_bytes != *lenWrite) {
+ LogError(errno, RS_RET_ERR_HDFS_WRITE,
+ "omhdfs: failed to write %s, expected %lu bytes, "
+ "written %lu\n", pFile->name, (unsigned long) *lenWrite,
+ (unsigned long) num_written_bytes);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ *lenWrite = 0;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+fileClose(file_t *pFile)
+{
+ DEFiRet;
+
+ if(pFile->fh == NULL)
+ FINALIZE;
+
+ if(pFile->nUsers > 1)
+ d_pthread_mutex_lock(&pFile->mut);
+
+ hdfsCloseFile(pFile->fs, pFile->fh);
+ pFile->fh = NULL;
+
+ if(pFile->nUsers > 1)
+ d_pthread_mutex_unlock(&pFile->mut);
+
+finalize_it:
+ RETiRet;
+}
+
+/* ---END FILE OBJECT---------------------------------------------------- */
+
+/* This adds data to the output buffer and performs an actual write
+ * if the new data does not fit into the buffer. Note that we never write
+ * partial data records. Other actions may write into the same file, and if
+ * we would write partial records, data could become severely mixed up.
+ * Note that we must check of some new data arrived is large than our
+ * buffer. In that case, the new data will written with its own
+ * write operation.
+ */
+static rsRetVal
+addData(instanceData *pData, uchar *buf)
+{
+ size_t len;
+ DEFiRet;
+
+ len = strlen((char*)buf);
+ if(pData->offsBuf + len < sizeof(pData->ioBuf)) {
+ /* new data fits into remaining buffer */
+ memcpy((char*) pData->ioBuf + pData->offsBuf, buf, len);
+ pData->offsBuf += len;
+ } else {
+ CHKiRet(fileWrite(pData->pFile, pData->ioBuf, &pData->offsBuf));
+ if(len >= sizeof(pData->ioBuf)) {
+ CHKiRet(fileWrite(pData->pFile, buf, &len));
+ } else {
+ memcpy((char*) pData->ioBuf + pData->offsBuf, buf, len);
+ pData->offsBuf += len;
+ }
+ }
+
+ iRet = RS_RET_DEFER_COMMIT;
+finalize_it:
+ RETiRet;
+}
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->pFile = NULL;
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->pFile != NULL)
+ fileObjDestruct(&pData->pFile);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINtryResume
+ instanceData *pData = pWrkrData->pData;
+CODESTARTtryResume
+ pthread_mutex_lock(&mutDoAct);
+ fileClose(pData->pFile);
+ fileOpen(pData->pFile);
+ if(pData->pFile->fh == NULL){
+ dbgprintf("omhdfs: tried to resume file %s, but still no luck...\n",
+ pData->pFile->name);
+ iRet = RS_RET_SUSPENDED;
+ }
+ pthread_mutex_unlock(&mutDoAct);
+ENDtryResume
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ DBGPRINTF("omhdfs: beginTransaction\n");
+ENDbeginTransaction
+
+
+BEGINdoAction
+ instanceData *pData = pWrkrData->pData;
+CODESTARTdoAction
+ DBGPRINTF("omhdfs: action to to write to %s\n", pData->pFile->name);
+ pthread_mutex_lock(&mutDoAct);
+ iRet = addData(pData, ppString[0]);
+ DBGPRINTF("omhdfs: done doAction\n");
+ pthread_mutex_unlock(&mutDoAct);
+ENDdoAction
+
+
+BEGINendTransaction
+ instanceData *pData = pWrkrData->pData;
+CODESTARTendTransaction
+ DBGPRINTF("omhdfs: endTransaction\n");
+ pthread_mutex_lock(&mutDoAct);
+ if(pData->offsBuf != 0) {
+ DBGPRINTF("omhdfs: data unwritten at end of transaction, persisting...\n");
+ iRet = fileWrite(pData->pFile, pData->ioBuf, &pData->offsBuf);
+ }
+ pthread_mutex_unlock(&mutDoAct);
+ENDendTransaction
+
+
+BEGINparseSelectorAct
+ file_t *pFile;
+ int r;
+ uchar *keybuf;
+CODESTARTparseSelectorAct
+
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omhdfs:", sizeof(":omhdfs:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omhdfs:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0,
+ (cs.dfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : cs.dfltTplName));
+
+ if(cs.fileName == NULL) {
+ LogError(0, RS_RET_ERR_HDFS_OPEN, "omhdfs: no file name specified, can not continue");
+ ABORT_FINALIZE(RS_RET_FILE_NOT_SPECIFIED);
+ }
+
+ pFile = hashtable_search(files, cs.fileName);
+ if(pFile == NULL) {
+ /* we need a new file object, this one not seen before */
+ CHKiRet(fileObjConstruct(&pFile));
+ CHKmalloc(pFile->name = cs.fileName);
+ CHKmalloc(keybuf = ustrdup(cs.fileName));
+ cs.fileName = NULL; /* re-set, data passed to file object */
+ CHKmalloc(pFile->hdfsHost = strdup((cs.hdfsHost == NULL) ? "default" : (char*) cs.hdfsHost));
+ pFile->hdfsPort = cs.hdfsPort;
+ fileOpen(pFile);
+ if(pFile->fh == NULL){
+ LogError(0, RS_RET_ERR_HDFS_OPEN, "omhdfs: failed to open %s - "
+ "retrying later", pFile->name);
+ iRet = RS_RET_SUSPENDED;
+ }
+ r = hashtable_insert(files, keybuf, pFile);
+ if(r == 0)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ fileObjAddUser(pFile);
+ pData->pFile = pFile;
+ pData->offsBuf = 0;
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINdoHUP
+ file_t *pFile;
+ struct hashtable_itr *itr;
+CODESTARTdoHUP
+ DBGPRINTF("omhdfs: HUP received (file count %d)\n", hashtable_count(files));
+ /* Iterator constructor only returns a valid iterator if
+ * the hashtable is not empty */
+ itr = hashtable_iterator(files);
+ if(hashtable_count(files) > 0)
+ {
+ do {
+ pFile = (file_t *) hashtable_iterator_value(itr);
+ fileClose(pFile);
+ DBGPRINTF("omhdfs: HUP, closing file %s\n", pFile->name);
+ } while (hashtable_iterator_advance(itr));
+ }
+ENDdoHUP
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.hdfsHost = NULL;
+ cs.hdfsPort = 0;
+ free(cs.fileName);
+ cs.fileName = NULL;
+ free(cs.dfltTplName);
+ cs.dfltTplName = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(files != NULL)
+ hashtable_destroy(files, 1); /* 1 => free all values automatically */
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_doHUP
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKmalloc(files = create_hashtable(20, hash_from_string, key_equals_string,
+ fileObjDestruct4Hashtable));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"omhdfsfilename", 0, eCmdHdlrGetWord, NULL, &cs.fileName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"omhdfshost", 0, eCmdHdlrGetWord, NULL, &cs.hdfsHost, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"omhdfsport", 0, eCmdHdlrInt, NULL, &cs.hdfsPort, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"omhdfsdefaulttemplate", 0, eCmdHdlrGetWord, NULL, &cs.dfltTplName, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ DBGPRINTF("omhdfs: module compiled with rsyslog version %s.\n", VERSION);
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
diff --git a/plugins/omjournal/Makefile.am b/plugins/omjournal/Makefile.am
new file mode 100644
index 0000000..4cfbbd9
--- /dev/null
+++ b/plugins/omjournal/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omjournal.la
+
+omjournal_la_SOURCES = omjournal.c
+omjournal_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBSYSTEMD_JOURNAL_CFLAGS)
+omjournal_la_LDFLAGS = -module -avoid-version
+omjournal_la_LIBADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+
+EXTRA_DIST =
diff --git a/plugins/omjournal/Makefile.in b/plugins/omjournal/Makefile.in
new file mode 100644
index 0000000..623330d
--- /dev/null
+++ b/plugins/omjournal/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omjournal
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omjournal_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omjournal_la_OBJECTS = omjournal_la-omjournal.lo
+omjournal_la_OBJECTS = $(am_omjournal_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 =
+omjournal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omjournal_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omjournal_la-omjournal.Plo
+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 = $(omjournal_la_SOURCES)
+DIST_SOURCES = $(omjournal_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omjournal.la
+omjournal_la_SOURCES = omjournal.c
+omjournal_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBSYSTEMD_JOURNAL_CFLAGS)
+omjournal_la_LDFLAGS = -module -avoid-version
+omjournal_la_LIBADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+EXTRA_DIST =
+all: 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) --gnu plugins/omjournal/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omjournal/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omjournal.la: $(omjournal_la_OBJECTS) $(omjournal_la_DEPENDENCIES) $(EXTRA_omjournal_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omjournal_la_LINK) -rpath $(pkglibdir) $(omjournal_la_OBJECTS) $(omjournal_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omjournal_la-omjournal.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omjournal_la-omjournal.lo: omjournal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omjournal_la-omjournal.lo -MD -MP -MF $(DEPDIR)/omjournal_la-omjournal.Tpo -c -o omjournal_la-omjournal.lo `test -f 'omjournal.c' || echo '$(srcdir)/'`omjournal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omjournal_la-omjournal.Tpo $(DEPDIR)/omjournal_la-omjournal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omjournal.c' object='omjournal_la-omjournal.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) $(omjournal_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omjournal_la-omjournal.lo `test -f 'omjournal.c' || echo '$(srcdir)/'`omjournal.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omjournal_la-omjournal.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omjournal_la-omjournal.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omjournal/omjournal.c b/plugins/omjournal/omjournal.c
new file mode 100644
index 0000000..7668db9
--- /dev/null
+++ b/plugins/omjournal/omjournal.c
@@ -0,0 +1,323 @@
+/* omjournal.c
+ * send messages to the Linux Journal. This is meant to be used
+ * in cases where journal serves as the whole system log database.
+ * Note that we may get into a loop if journald re-injects messages
+ * into the syslog stream and we read that via imuxsock. Thus there
+ * is an option in imuxsock to ignore messages from ourselves
+ * (actually from our pid). So there are some module-interdependencies.
+ *
+ * Copyright 2013-2017 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "cfsysline.h"
+#include <json.h>
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include <systemd/sd-journal.h>
+#include "unicode-helper.h"
+#include <sys/uio.h>
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omjournal")
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+
+typedef struct _instanceData {
+ uchar *tplName;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+static struct cnfparamdescr actpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmjournal)\n");
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+
+ if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("ommongodb: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup(pData->tplName),
+ OMSR_TPL_AS_JSON));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+static struct iovec *
+build_iovec(size_t *retargc, struct json_object *json)
+{
+ struct iovec *iov;
+ const char *key;
+ const char *val;
+ size_t key_len;
+ size_t val_len;
+ size_t vec_len;
+ size_t i;
+
+ const size_t argc = json_object_object_length(json);
+ if(argc == 0)
+ return NULL;
+ iov = malloc( sizeof(struct iovec) * argc );
+ if(NULL == iov)
+ goto fail;
+
+ /* note: as we know the number of subobjects, we use the for loop
+ * to iterate over them instead of the _iter_ API. This is guaranteed
+ * to work. The somewhat cleaner case causes clang static analyzer to
+ * complain and we need to avoid that.
+ */
+ struct json_object_iterator it = json_object_iter_begin(json);
+ for(i = 0 ; i < argc ; ++i) {
+ key = json_object_iter_peek_name(&it);
+ val = json_object_get_string(json_object_iter_peek_value(&it));
+
+ key_len = strlen(key);
+ val_len = strlen(val);
+ // vec length is len(key=val)
+ vec_len = key_len + val_len + 1;
+
+ char *buf = malloc(vec_len + 1);
+ if(NULL == buf)
+ goto fail;
+
+ memcpy(buf, key, key_len);
+ memcpy(buf + key_len, "=", 1);
+ memcpy(buf + key_len + 1, val, val_len+1);
+
+ iov[i].iov_base = buf;
+ iov[i].iov_len = vec_len;
+
+ json_object_iter_next(&it);
+ }
+ *retargc = argc;
+ return iov;
+
+fail:
+ if( NULL == iov)
+ return NULL;
+
+ size_t j;
+ // iterate over any iovecs that were initalised above and free them.
+ for(j = 0; j < i; j++) {
+ free(iov[j].iov_base);
+ }
+
+ free(iov);
+ return NULL;
+}
+
+
+static void
+send_non_template_message(smsg_t *const __restrict__ pMsg)
+{
+ uchar *tag;
+ int lenTag;
+ int sev;
+
+ MsgGetSeverity(pMsg, &sev);
+ getTAG(pMsg, &tag, &lenTag, LOCK_MUTEX);
+ /* we can use more properties here, but let's see if there
+ * is some real user interest. We can always add later...
+ */
+ sd_journal_send("MESSAGE=%s", getMSG(pMsg),
+ "PRIORITY=%d", sev,
+ "SYSLOG_FACILITY=%d", pMsg->iFacility,
+ "SYSLOG_IDENTIFIER=%s", tag,
+ NULL);
+}
+
+static void
+send_template_message(struct json_object *const __restrict__ json)
+{
+ size_t argc;
+ struct iovec *iovec;
+ size_t i;
+
+ iovec = build_iovec(&argc, json);
+ if( NULL != iovec) {
+ sd_journal_sendv(iovec, argc);
+ for (i =0; i< argc; i++)
+ free(iovec[i].iov_base);
+ free(iovec);
+ }
+}
+
+BEGINdoAction_NoStrings
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+
+ if (pData->tplName == NULL) {
+ send_non_template_message((smsg_t*) ((void**)pMsgData)[0]);
+ } else {
+ send_template_message((struct json_object*) ((void**)pMsgData)[0]);
+ }
+ENDdoAction
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("omjournal: module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/omkafka/Makefile.am b/plugins/omkafka/Makefile.am
new file mode 100644
index 0000000..dd7b69a
--- /dev/null
+++ b/plugins/omkafka/Makefile.am
@@ -0,0 +1,18 @@
+pkglib_LTLIBRARIES = omkafka.la
+
+if OMKAFKA_USE_DUMMY
+omkafka_la_SOURCES = dummy.c
+omkafka_la_LDFLAGS = -module -avoid-version
+omkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -D MODNAME=omkafka
+else
+omkafka_la_SOURCES = omkafka.c
+if ENABLE_KAFKA_STATIC
+omkafka_la_LDFLAGS = -module -avoid-version -Wl,--whole-archive -l:librdkafka-static.a -Wl,--no-whole-archive -ldl -lresolv -lcurl -lssl -lpthread -lcrypto -lsasl2 -lz -llz4 -lrt -lm
+else
+omkafka_la_LDFLAGS = -module -avoid-version $(LIBRDKAFKA_LIBS) -lm
+endif
+omkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+endif
+
+omkafka_la_LIBADD =
+EXTRA_DIST =
diff --git a/plugins/omkafka/Makefile.in b/plugins/omkafka/Makefile.in
new file mode 100644
index 0000000..c0148d0
--- /dev/null
+++ b/plugins/omkafka/Makefile.in
@@ -0,0 +1,815 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omkafka
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omkafka_la_DEPENDENCIES =
+am__omkafka_la_SOURCES_DIST = omkafka.c dummy.c
+@OMKAFKA_USE_DUMMY_FALSE@am_omkafka_la_OBJECTS = \
+@OMKAFKA_USE_DUMMY_FALSE@ omkafka_la-omkafka.lo
+@OMKAFKA_USE_DUMMY_TRUE@am_omkafka_la_OBJECTS = omkafka_la-dummy.lo
+omkafka_la_OBJECTS = $(am_omkafka_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 =
+omkafka_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omkafka_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omkafka_la-dummy.Plo \
+ ./$(DEPDIR)/omkafka_la-omkafka.Plo
+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 = $(omkafka_la_SOURCES)
+DIST_SOURCES = $(am__omkafka_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omkafka.la
+@OMKAFKA_USE_DUMMY_FALSE@omkafka_la_SOURCES = omkafka.c
+@OMKAFKA_USE_DUMMY_TRUE@omkafka_la_SOURCES = dummy.c
+@ENABLE_KAFKA_STATIC_FALSE@@OMKAFKA_USE_DUMMY_FALSE@omkafka_la_LDFLAGS = -module -avoid-version $(LIBRDKAFKA_LIBS) -lm
+@ENABLE_KAFKA_STATIC_TRUE@@OMKAFKA_USE_DUMMY_FALSE@omkafka_la_LDFLAGS = -module -avoid-version -Wl,--whole-archive -l:librdkafka-static.a -Wl,--no-whole-archive -ldl -lresolv -lcurl -lssl -lpthread -lcrypto -lsasl2 -lz -llz4 -lrt -lm
+@OMKAFKA_USE_DUMMY_TRUE@omkafka_la_LDFLAGS = -module -avoid-version
+@OMKAFKA_USE_DUMMY_FALSE@omkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+@OMKAFKA_USE_DUMMY_TRUE@omkafka_la_CPPFLAGS = -I$(top_srcdir) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -D MODNAME=omkafka
+omkafka_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/omkafka/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omkafka/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omkafka.la: $(omkafka_la_OBJECTS) $(omkafka_la_DEPENDENCIES) $(EXTRA_omkafka_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omkafka_la_LINK) -rpath $(pkglibdir) $(omkafka_la_OBJECTS) $(omkafka_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omkafka_la-dummy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omkafka_la-omkafka.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omkafka_la-omkafka.lo: omkafka.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omkafka_la-omkafka.lo -MD -MP -MF $(DEPDIR)/omkafka_la-omkafka.Tpo -c -o omkafka_la-omkafka.lo `test -f 'omkafka.c' || echo '$(srcdir)/'`omkafka.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omkafka_la-omkafka.Tpo $(DEPDIR)/omkafka_la-omkafka.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omkafka.c' object='omkafka_la-omkafka.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) $(omkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omkafka_la-omkafka.lo `test -f 'omkafka.c' || echo '$(srcdir)/'`omkafka.c
+
+omkafka_la-dummy.lo: dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omkafka_la-dummy.lo -MD -MP -MF $(DEPDIR)/omkafka_la-dummy.Tpo -c -o omkafka_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omkafka_la-dummy.Tpo $(DEPDIR)/omkafka_la-dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='omkafka_la-dummy.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) $(omkafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omkafka_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omkafka_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/omkafka_la-omkafka.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omkafka_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/omkafka_la-omkafka.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omkafka/dummy.c b/plugins/omkafka/dummy.c
new file mode 100644
index 0000000..fe8c249
--- /dev/null
+++ b/plugins/omkafka/dummy.c
@@ -0,0 +1,171 @@
+/* a dummy module to be loaded if we cannot build this module, but
+ * configure required it to be "optional".
+ *
+ * Copyright 2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+#define MODULE_NAME(x) #x
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME(MODULE_NAME(MODNAME))
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ (void) lst;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDsetModCnf
+
+
+BEGINnewActInst
+CODESTARTnewActInst
+ (void) pData;
+ (void) ppModData;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void) pMsgData;
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("dummy module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/omkafka/omkafka.c b/plugins/omkafka/omkafka.c
new file mode 100644
index 0000000..e8eae08
--- /dev/null
+++ b/plugins/omkafka/omkafka.c
@@ -0,0 +1,2141 @@
+/* omkafka.c
+ * This output plugin make rsyslog talk to Apache Kafka.
+ *
+ * Copyright 2014-2017 by Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/uio.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <math.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <unistd.h>
+#include <librdkafka/rdkafka.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "unicode-helper.h"
+#include "datetime.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omkafka")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(statsobj)
+
+statsobj_t *kafkaStats;
+STATSCOUNTER_DEF(ctrQueueSize, mutCtrQueueSize);
+STATSCOUNTER_DEF(ctrTopicSubmit, mutCtrTopicSubmit);
+STATSCOUNTER_DEF(ctrKafkaFail, mutCtrKafkaFail);
+STATSCOUNTER_DEF(ctrCacheMiss, mutCtrCacheMiss);
+STATSCOUNTER_DEF(ctrCacheEvict, mutCtrCacheEvict);
+STATSCOUNTER_DEF(ctrCacheSkip, mutCtrCacheSkip);
+STATSCOUNTER_DEF(ctrKafkaAck, mutCtrKafkaAck);
+STATSCOUNTER_DEF(ctrKafkaMsgTooLarge, mutCtrKafkaMsgTooLarge);
+STATSCOUNTER_DEF(ctrKafkaUnknownTopic, mutCtrKafkaUnknownTopic);
+STATSCOUNTER_DEF(ctrKafkaQueueFull, mutCtrKafkaQueueFull);
+STATSCOUNTER_DEF(ctrKafkaUnknownPartition, mutCtrKafkaUnknownPartition);
+STATSCOUNTER_DEF(ctrKafkaOtherErrors, mutCtrKafkaOtherErrors);
+STATSCOUNTER_DEF(ctrKafkaRespTimedOut, mutCtrKafkaRespTimedOut);
+STATSCOUNTER_DEF(ctrKafkaRespTransport, mutCtrKafkaRespTransport);
+STATSCOUNTER_DEF(ctrKafkaRespBrokerDown, mutCtrKafkaRespBrokerDown);
+STATSCOUNTER_DEF(ctrKafkaRespAuth, mutCtrKafkaRespAuth);
+STATSCOUNTER_DEF(ctrKafkaRespSSL, mutCtrKafkaRespSSL);
+STATSCOUNTER_DEF(ctrKafkaRespOther, mutCtrKafkaRespOther);
+
+#define MAX_ERRMSG 1024 /* max size of error messages that we support */
+
+#ifndef SLIST_INIT
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef SLIST_ENTRY
+#define SLIST_ENTRY(type) \
+ struct { \
+ struct type *sle_next; /* next element */ \
+ }
+#endif
+
+#ifndef SLIST_HEAD
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+#endif
+
+#ifndef SLIST_INSERT_HEAD
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef SLIST_REMOVE_HEAD
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef SLIST_FIRST
+#define SLIST_FIRST(head) ((head)->slh_first)
+#endif
+
+#ifndef SLIST_NEXT
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+#endif
+
+#ifndef SLIST_EMPTY
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#endif
+
+#ifndef SLIST_REMOVE
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+#endif
+
+#define NO_FIXED_PARTITION -1 /* signifies that no fixed partition config exists */
+
+struct kafka_params {
+ const char *name;
+ const char *val;
+};
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+/* flags for writeKafka: shall we resubmit a failed message? */
+#define RESUBMIT 1
+#define NO_RESUBMIT 0
+
+#ifdef HAVE_ATOMIC_BUILTINS64
+static uint64 clockTopicAccess = 0;
+#else
+static unsigned clockTopicAccess = 0;
+#endif
+/* and the "tick" function */
+#ifndef HAVE_ATOMIC_BUILTINS
+static pthread_mutex_t mutClock;
+#endif
+static uint64
+getClockTopicAccess(void)
+{
+#ifdef HAVE_ATOMIC_BUILTINS64
+ return ATOMIC_INC_AND_FETCH_uint64(&clockTopicAccess, &mutClock);
+#else
+ return ATOMIC_INC_AND_FETCH_unsigned(&clockTopicAccess, &mutClock);
+#endif
+}
+
+/* Needed for Kafka timestamp librdkafka > 0.9.4 */
+#define KAFKA_TimeStamp "\"%timestamp:::date-unixtimestamp%\""
+
+static int closeTimeout = 1000;
+static pthread_mutex_t closeTimeoutMut = PTHREAD_MUTEX_INITIALIZER;
+
+/* stats callback window metrics */
+static uint64 rtt_avg_usec;
+static uint64 throttle_avg_msec;
+static uint64 int_latency_avg_usec;
+
+/* dynamic topic cache */
+struct s_dynaTopicCacheEntry {
+ uchar *pName;
+ rd_kafka_topic_t *pTopic;
+ uint64 clkTickAccessed;
+ pthread_rwlock_t lock;
+};
+typedef struct s_dynaTopicCacheEntry dynaTopicCacheEntry;
+
+/* Struct for Failed Messages Listitems */
+struct s_failedmsg_entry {
+ uchar* key;
+ uchar* payload;
+ uchar* topicname;
+ SLIST_ENTRY(s_failedmsg_entry) entries; /* List. */
+} ;
+typedef struct s_failedmsg_entry failedmsg_entry;
+
+typedef struct _instanceData {
+ uchar *topic;
+ sbool dynaKey;
+ sbool dynaTopic;
+ dynaTopicCacheEntry **dynCache;
+ pthread_mutex_t mutDynCache;
+ rd_kafka_topic_t *pTopic;
+ int iCurrElt;
+ int iCurrCacheSize;
+ int bReportErrs;
+ int iDynaTopicCacheSize;
+ uchar *tplName; /* assigned output template */
+ char *brokers;
+ sbool autoPartition;
+ int fixedPartition;
+ int nPartitions;
+ uint32_t currPartition;
+ DEF_ATOMIC_HELPER_MUT(mutCurrPartition);
+ int nConfParams;
+ struct kafka_params *confParams;
+ int nTopicConfParams;
+ struct kafka_params *topicConfParams;
+ uchar *errorFile;
+ uchar *key;
+ int bReopenOnHup;
+ int bResubmitOnFailure; /* Resubmit failed messages into kafka queue*/
+ int bKeepFailedMessages;/* Keep Failed messages in memory,
+ only works if bResubmitOnFailure is enabled */
+ uchar *failedMsgFile; /* file in which failed messages are being stored on
+ shutdown and loaded on startup */
+
+ int fdErrFile; /* error file fd or -1 if not open */
+ pthread_mutex_t mutErrFile;
+ uchar *statsFile;
+ int fdStatsFile; /* stats file fd or -1 if not open */
+ pthread_mutex_t mutStatsFile;
+ int bIsOpen;
+ int bIsSuspended; /* when broker fail, we need to suspend the action */
+ pthread_rwlock_t rkLock;
+ pthread_mutex_t mut_doAction; /* make sure one wrkr instance max in parallel */
+ rd_kafka_t *rk;
+ int closeTimeout;
+ SLIST_HEAD(failedmsg_listhead, s_failedmsg_entry) failedmsg_head;
+
+ uchar *statsName;
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrTopicSubmit, mutCtrTopicSubmit);
+ STATSCOUNTER_DEF(ctrKafkaFail, mutCtrKafkaFail);
+ STATSCOUNTER_DEF(ctrKafkaAck, mutCtrKafkaAck);
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+#define INST_STATSCOUNTER_INC(inst, ctr, mut) \
+ do { \
+ if (inst->stats) { STATSCOUNTER_INC(ctr, mut); } \
+ } while(0);
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "topic", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "dynatopic", eCmdHdlrBinary, 0 },
+ { "dynatopic.cachesize", eCmdHdlrInt, 0 },
+ { "dynakey", eCmdHdlrBinary, 0 },
+ { "partitions.auto", eCmdHdlrBinary, 0 }, /* use librdkafka's automatic partitioning function */
+ { "partitions.number", eCmdHdlrPositiveInt, 0 },
+ { "partitions.usefixed", eCmdHdlrNonNegInt, 0 }, /* expert parameter, "nails" partition */
+ { "broker", eCmdHdlrArray, 0 },
+ { "confparam", eCmdHdlrArray, 0 },
+ { "topicconfparam", eCmdHdlrArray, 0 },
+ { "errorfile", eCmdHdlrGetWord, 0 },
+ { "statsfile", eCmdHdlrGetWord, 0 },
+ { "key", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "closetimeout", eCmdHdlrPositiveInt, 0 },
+ { "reopenonhup", eCmdHdlrBinary, 0 },
+ { "resubmitonfailure", eCmdHdlrBinary, 0 }, /* Resubmit message into kafaj queue on failure */
+ { "keepfailedmessages", eCmdHdlrBinary, 0 },
+ { "failedmsgfile", eCmdHdlrGetWord, 0 },
+ { "statsname", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+static uint32_t
+getPartition(instanceData *const __restrict__ pData)
+{
+ if (pData->autoPartition) {
+ return RD_KAFKA_PARTITION_UA;
+ } else {
+ return (pData->fixedPartition == NO_FIXED_PARTITION) ?
+ ATOMIC_INC_AND_FETCH_unsigned(&pData->currPartition,
+ &pData->mutCurrPartition) % pData->nPartitions
+ : (unsigned) pData->fixedPartition;
+ }
+}
+
+/* must always be called with appropriate locks taken */
+static void
+free_topic(rd_kafka_topic_t **topic)
+{
+ if (*topic != NULL) {
+ DBGPRINTF("omkafka: closing topic %s\n", rd_kafka_topic_name(*topic));
+ rd_kafka_topic_destroy(*topic);
+ *topic = NULL;
+ }
+}
+
+static void ATTR_NONNULL(1)
+failedmsg_entry_destruct(failedmsg_entry *const __restrict__ fmsgEntry) {
+ free(fmsgEntry->key);
+ free(fmsgEntry->payload);
+ free(fmsgEntry->topicname);
+ free(fmsgEntry);
+}
+
+/* note: we need the length of message as we need to deal with
+ * non-NUL terminated strings under some circumstances.
+ */
+static failedmsg_entry * ATTR_NONNULL(3,5)
+failedmsg_entry_construct(const char *const key, const size_t keylen, const char *const msg,
+const size_t msglen, const char *const topicname)
+{
+ failedmsg_entry *etry = NULL;
+
+ if((etry = malloc(sizeof(struct s_failedmsg_entry))) == NULL) {
+ return NULL;
+ }
+
+ if (key) {
+ if((etry->key = (uchar*)malloc(keylen+1)) == NULL) {
+ free(etry);
+ return NULL;
+ }
+ memcpy(etry->key, key, keylen);
+ etry->key[keylen] = '\0';
+ } else {
+ etry->key=NULL;
+ }
+
+ if((etry->payload = (uchar*)malloc(msglen+1)) == NULL) {
+ free(etry->key);
+ free(etry);
+ return NULL;
+ }
+ memcpy(etry->payload, msg, msglen);
+ etry->payload[msglen] = '\0';
+ if((etry->topicname = (uchar*)strdup(topicname)) == NULL) {
+ free(etry->key);
+ free(etry->payload);
+ free(etry);
+ return NULL;
+ }
+ return etry;
+}
+
+/* destroy topic item */
+/* must be called with write(rkLock) */
+static void
+closeTopic(instanceData *__restrict__ const pData)
+{
+ free_topic(&pData->pTopic);
+}
+
+/* these dynaTopic* functions are only slightly modified versions of those found in omfile.c.
+ * check the sources in omfile.c for more descriptive comments about each of these functions.
+ * i will only put the bare descriptions in this one. 2015-01-09 - Tait Clarridge
+ */
+
+/* delete a cache entry from the dynamic topic cache */
+/* must be called with lock(mutDynCache) */
+static rsRetVal
+dynaTopicDelCacheEntry(instanceData *__restrict__ const pData, const int iEntry, const int bFreeEntry)
+{
+ dynaTopicCacheEntry **pCache = pData->dynCache;
+ DEFiRet;
+ assert(pCache != NULL);
+
+ if(pCache[iEntry] == NULL)
+ FINALIZE;
+ pthread_rwlock_wrlock(&pCache[iEntry]->lock);
+
+ DBGPRINTF("Removing entry %d for topic '%s' from dynaCache.\n", iEntry,
+ pCache[iEntry]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[iEntry]->pName);
+
+ if(pCache[iEntry]->pName != NULL) {
+ free(pCache[iEntry]->pName);
+ pCache[iEntry]->pName = NULL;
+ }
+
+ pthread_rwlock_unlock(&pCache[iEntry]->lock);
+
+ if(bFreeEntry) {
+ pthread_rwlock_destroy(&pCache[iEntry]->lock);
+ free(pCache[iEntry]);
+ pCache[iEntry] = NULL;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* clear the entire dynamic topic cache */
+static void
+dynaTopicFreeCacheEntries(instanceData *__restrict__ const pData)
+{
+ register int i;
+ assert(pData != NULL);
+
+ pthread_mutex_lock(&pData->mutDynCache);
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ dynaTopicDelCacheEntry(pData, i, 1);
+ }
+ pData->iCurrElt = -1; /* invalidate current element */
+ pthread_mutex_unlock(&pData->mutDynCache);
+}
+
+/* create the topic object */
+/* must be called with _atleast_ read(rkLock) */
+static rsRetVal
+createTopic(instanceData *__restrict__ const pData, const uchar *__restrict__ const newTopicName,
+rd_kafka_topic_t** topic) {
+/* Get a new topic conf */
+ rd_kafka_topic_conf_t *const topicconf = rd_kafka_topic_conf_new();
+ char errstr[MAX_ERRMSG];
+ rd_kafka_topic_t *rkt = NULL;
+ DEFiRet;
+
+ *topic = NULL;
+
+ if(topicconf == NULL) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "omkafka: error creating kafka topic conf obj: %s\n",
+ rd_kafka_err2str(rd_kafka_last_error()));
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+ for(int i = 0 ; i < pData->nTopicConfParams ; ++i) {
+ DBGPRINTF("omkafka: setting custom topic configuration parameter: %s:%s\n",
+ pData->topicConfParams[i].name,
+ pData->topicConfParams[i].val);
+ if(rd_kafka_topic_conf_set(topicconf, pData->topicConfParams[i].name,
+ pData->topicConfParams[i].val, errstr, sizeof(errstr)) != RD_KAFKA_CONF_OK) {
+ if(pData->bReportErrs) {
+ LogError(0, RS_RET_PARAM_ERROR, "error in kafka "
+ "topic conf parameter '%s=%s': %s",
+ pData->topicConfParams[i].name,
+ pData->topicConfParams[i].val, errstr);
+ } else {
+ DBGPRINTF("omkafka: setting custom topic configuration parameter '%s=%s': %s",
+ pData->topicConfParams[i].name,
+ pData->topicConfParams[i].val, errstr);
+ }
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ }
+ rkt = rd_kafka_topic_new(pData->rk, (char *)newTopicName, topicconf);
+ if(rkt == NULL) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "omkafka: error creating kafka topic: %s\n",
+ rd_kafka_err2str(rd_kafka_last_error()));
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+ *topic = rkt;
+finalize_it:
+ RETiRet;
+}
+
+/* create the topic object */
+/* must be called with write(rkLock) */
+static rsRetVal
+prepareTopic(instanceData *__restrict__ const pData, const uchar *__restrict__ const newTopicName)
+{
+ DEFiRet;
+ iRet = createTopic(pData, newTopicName, &pData->pTopic);
+ if(iRet != RS_RET_OK) {
+ if(pData->pTopic != NULL) {
+ closeTopic(pData);
+ }
+ }
+ RETiRet;
+}
+
+/* check dynamic topic cache for existence of the already created topic.
+ * if it does not exist, create a new one, or if we are currently using it
+ * as of the last message, keep using it.
+ *
+ * must be called with read(rkLock)
+ * must be called with mutDynCache locked
+ */
+static rsRetVal ATTR_NONNULL()
+prepareDynTopic(instanceData *__restrict__ const pData, const uchar *__restrict__ const newTopicName,
+ rd_kafka_topic_t** topic, pthread_rwlock_t** lock)
+{
+ uint64 ctOldest;
+ int iOldest;
+ int i;
+ int iFirstFree;
+ rsRetVal localRet;
+ dynaTopicCacheEntry **pCache;
+ dynaTopicCacheEntry *entry = NULL;
+ rd_kafka_topic_t *tmpTopic = NULL;
+ DEFiRet;
+ assert(pData != NULL);
+ assert(newTopicName != NULL);
+
+ pCache = pData->dynCache;
+ /* first check, if we still have the current topic */
+ if ((pData->iCurrElt != -1)
+ && !ustrcmp(newTopicName, pCache[pData->iCurrElt]->pName)) {
+ /* great, we are all set */
+ pCache[pData->iCurrElt]->clkTickAccessed = getClockTopicAccess();
+ entry = pCache[pData->iCurrElt];
+ STATSCOUNTER_INC(ctrCacheSkip, mutCtrCacheSkip);
+ FINALIZE;
+ }
+
+ /* ok, no luck. Now let's search the table if we find a matching spot.
+ * While doing so, we also prepare for creation of a new one.
+ */
+ pData->iCurrElt = -1;
+ iFirstFree = -1;
+ iOldest = 0;
+ ctOldest = getClockTopicAccess();
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL || pCache[i]->pName == NULL) {
+ if(iFirstFree == -1)
+ iFirstFree = i;
+ } else { /*got an element, let's see if it matches */
+ if(!ustrcmp(newTopicName, pCache[i]->pName)) {
+ /* we found our element! */
+ entry = pCache[i];
+ pData->iCurrElt = i;
+ /* update "timestamp" for LRU */
+ pCache[i]->clkTickAccessed = getClockTopicAccess();
+ FINALIZE;
+ }
+ /* did not find it - so lets keep track of the counters for LRU */
+ if(pCache[i]->clkTickAccessed < ctOldest) {
+ ctOldest = pCache[i]->clkTickAccessed;
+ iOldest = i;
+ }
+ }
+ }
+ STATSCOUNTER_INC(ctrCacheMiss, mutCtrCacheMiss);
+
+ /* invalidate iCurrElt as we may error-exit out of this function when the currrent
+ * iCurrElt has been freed or otherwise become unusable. This is a precaution, and
+ * performance-wise it may be better to do that in each of the exits. However, that
+ * is error-prone, so I prefer to do it here. -- rgerhards, 2010-03-02
+ */
+ pData->iCurrElt = -1;
+
+ if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaTopicCacheSize)) {
+ /* there is space left, so set it to that index */
+ iFirstFree = pData->iCurrCacheSize++;
+ }
+
+ if(iFirstFree == -1) {
+ dynaTopicDelCacheEntry(pData, iOldest, 0);
+ STATSCOUNTER_INC(ctrCacheEvict, mutCtrCacheEvict);
+ iFirstFree = iOldest; /* this one *is* now free ;) */
+ } else {
+ pCache[iFirstFree] = NULL;
+ }
+ /* we need to allocate memory for the cache structure */
+ if(pCache[iFirstFree] == NULL) {
+ CHKmalloc(pCache[iFirstFree] =
+ (dynaTopicCacheEntry*) calloc(1, sizeof(dynaTopicCacheEntry)));
+ CHKiRet(pthread_rwlock_init(&pCache[iFirstFree]->lock, NULL));
+ }
+
+ /* Ok, we finally can open the topic */
+ localRet = createTopic(pData, newTopicName, &tmpTopic);
+
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "Could not open dynamic topic '%s' "
+ "[state %d] - discarding message",
+ newTopicName, localRet);
+ ABORT_FINALIZE(localRet);
+ }
+
+ if((pCache[iFirstFree]->pName = ustrdup(newTopicName)) == NULL) {
+ free_topic(&tmpTopic);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pCache[iFirstFree]->pTopic = tmpTopic;
+ pCache[iFirstFree]->clkTickAccessed = getClockTopicAccess();
+ entry = pCache[iFirstFree];
+ pData->iCurrElt = iFirstFree;
+ DBGPRINTF("Added new entry %d for topic cache, topic '%s'.\n", iFirstFree, newTopicName);
+
+finalize_it:
+ if (iRet == RS_RET_OK) {
+ *topic = entry->pTopic;
+ *lock = &entry->lock;
+ }
+ RETiRet;
+}
+
+/* write data error request/replies to separate error file
+ * Note: we open the file but never close it before exit. If it
+ * needs to be closed, HUP must be sent.
+ */
+static rsRetVal
+writeDataError(instanceData *const pData,
+ const char *const __restrict__ data,
+ const size_t lenData,
+ const int kafkaErr)
+{
+ int bLocked = 0;
+ struct json_object *json = NULL;
+ DEFiRet;
+
+ if(pData->errorFile == NULL) {
+ FINALIZE;
+ }
+
+ json = json_object_new_object();
+ if(json == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ struct json_object *jval;
+ jval = json_object_new_int(kafkaErr);
+ json_object_object_add(json, "errcode", jval);
+ jval = json_object_new_string(rd_kafka_err2str(kafkaErr));
+ json_object_object_add(json, "errmsg", jval);
+ jval = json_object_new_string_len(data, lenData);
+ json_object_object_add(json, "data", jval);
+
+ struct iovec iov[2];
+ iov[0].iov_base = (void*) json_object_get_string(json);
+ iov[0].iov_len = strlen(iov[0].iov_base);
+ iov[1].iov_base = (char *) "\n";
+ iov[1].iov_len = 1;
+
+ /* we must protect the file write do operations due to other wrks & HUP */
+ pthread_mutex_lock(&pData->mutErrFile);
+ bLocked = 1;
+ if(pData->fdErrFile == -1) {
+ pData->fdErrFile = open((char*)pData->errorFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pData->fdErrFile == -1) {
+ LogError(errno, RS_RET_ERR, "omkafka: error opening error file %s",
+ pData->errorFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ /* Note: we do not do real error-handling on the err file, as this
+ * complicates things way to much.
+ */
+ const ssize_t nwritten = writev(pData->fdErrFile, iov, sizeof(iov)/sizeof(struct iovec));
+ if(nwritten != (ssize_t) iov[0].iov_len + 1) {
+ LogError(errno, RS_RET_ERR,
+ "omkafka: error writing error file, write returns %lld\n",
+ (long long) nwritten);
+ }
+
+finalize_it:
+ if(bLocked)
+ pthread_mutex_unlock(&pData->mutErrFile);
+ if(json != NULL)
+ json_object_put(json);
+ RETiRet;
+}
+
+/* write librdkafka stats object to a file
+ * Note: we open the file but never close it before exit. If it
+ * needs to be closed, HUP must be sent.
+ * Assumes pData->statsFile != NULL.
+ */
+static rsRetVal
+writeStats(instanceData *const pData,
+ char *statsData,
+ const size_t lenData)
+{
+ int bLocked = 0;
+ DEFiRet;
+
+ /* Protect the file write from operations due to other wrks & HUP */
+ pthread_mutex_lock(&pData->mutStatsFile);
+ bLocked = 1;
+ if(pData->fdStatsFile == -1) {
+ pData->fdStatsFile = open((char*)pData->statsFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(pData->fdStatsFile == -1) {
+ LogError(errno, RS_RET_ERR, "omkafka: error opening stats file %s",
+ pData->statsFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ ssize_t nwritten = write(pData->fdStatsFile, statsData, lenData);
+ nwritten += write(pData->fdStatsFile, "\n", 1);
+ if(nwritten != (ssize_t) lenData + 1) {
+ LogError(errno, RS_RET_ERR,
+ "omkafka: error writing stats file, write returns %lld, expected %lld\n",
+ (long long) nwritten, (long long)(lenData + 1));
+ }
+
+finalize_it:
+ if(bLocked)
+ pthread_mutex_unlock(&pData->mutStatsFile);
+ RETiRet;
+}
+
+/* identify and count specific types of kafka failures.
+ */
+static rsRetVal
+updateKafkaFailureCounts(rd_kafka_resp_err_t err) {
+ DEFiRet;
+ if (err == RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE) {
+ STATSCOUNTER_INC(ctrKafkaMsgTooLarge, mutCtrKafkaMsgTooLarge);
+ } else if (err == RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC) {
+ STATSCOUNTER_INC(ctrKafkaUnknownTopic, mutCtrKafkaUnknownTopic);
+ } else if (err == RD_KAFKA_RESP_ERR__QUEUE_FULL) {
+ STATSCOUNTER_INC(ctrKafkaQueueFull, mutCtrKafkaQueueFull);
+ } else if (err == RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION) {
+ STATSCOUNTER_INC(ctrKafkaUnknownPartition, mutCtrKafkaUnknownPartition);
+ } else {
+ STATSCOUNTER_INC(ctrKafkaOtherErrors, mutCtrKafkaOtherErrors);
+ }
+
+ RETiRet;
+}
+
+/* must be called with read(rkLock)
+ * b_do_resubmit tells if we shall resubmit on error or not. This is needed
+ * when we submit already resubmitted messages.
+ */
+static rsRetVal ATTR_NONNULL(1, 3)
+writeKafka(instanceData *const pData, uchar *const key, uchar *const msg,
+ uchar *const msgTimestamp, uchar *const topic, const int b_do_resubmit)
+{
+ DEFiRet;
+ const int partition = getPartition(pData);
+ rd_kafka_topic_t *rkt = NULL;
+ pthread_rwlock_t *dynTopicLock = NULL;
+ failedmsg_entry* fmsgEntry;
+ int topic_mut_locked = 0;
+ rd_kafka_resp_err_t msg_kafka_response;
+#if RD_KAFKA_VERSION >= 0x00090400
+ int64_t ttMsgTimestamp;
+#else
+ int msg_enqueue_status = 0;
+#endif
+
+ DBGPRINTF("omkafka: trying to send: key:'%s', msg:'%s', timestamp:'%s'\n",
+ key, msg, msgTimestamp);
+
+ if(pData->dynaTopic) {
+ DBGPRINTF("omkafka: topic to insert to: %s\n", topic);
+ /* ensure locking happens all inside this function */
+ pthread_mutex_lock(&pData->mutDynCache);
+ const rsRetVal localRet = prepareDynTopic(pData, topic, &rkt, &dynTopicLock);
+ if (localRet == RS_RET_OK) {
+ pthread_rwlock_rdlock(dynTopicLock);
+ topic_mut_locked = 1;
+ }
+ pthread_mutex_unlock(&pData->mutDynCache);
+ CHKiRet(localRet);
+ } else {
+ rkt = pData->pTopic;
+ }
+
+#if RD_KAFKA_VERSION >= 0x00090400
+ if (msgTimestamp == NULL) {
+ /* Resubmitted items don't have a timestamp */
+ ttMsgTimestamp = 0;
+ } else {
+ ttMsgTimestamp = atoi((char*)msgTimestamp); /* Convert timestamp into int */
+ ttMsgTimestamp *= 1000; /* Timestamp in Milliseconds for kafka */
+ }
+ DBGPRINTF("omkafka: rd_kafka_producev timestamp=%s/%" PRId64 "\n", msgTimestamp, ttMsgTimestamp);
+
+ /* Using new kafka producev API, includes Timestamp! */
+ if (key == NULL) {
+ msg_kafka_response = rd_kafka_producev(pData->rk,
+ RD_KAFKA_V_RKT(rkt),
+ RD_KAFKA_V_PARTITION(partition),
+ RD_KAFKA_V_VALUE(msg, strlen((char*)msg)),
+ RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY),
+ RD_KAFKA_V_TIMESTAMP(ttMsgTimestamp),
+ RD_KAFKA_V_KEY(NULL, 0),
+ RD_KAFKA_V_END);
+ } else {
+ DBGPRINTF("omkafka: rd_kafka_producev key=%s\n", key);
+ msg_kafka_response = rd_kafka_producev(pData->rk,
+ RD_KAFKA_V_RKT(rkt),
+ RD_KAFKA_V_PARTITION(partition),
+ RD_KAFKA_V_VALUE(msg, strlen((char*)msg)),
+ RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY),
+ RD_KAFKA_V_TIMESTAMP(ttMsgTimestamp),
+ RD_KAFKA_V_KEY(key,strlen((char*)key)),
+ RD_KAFKA_V_END);
+ }
+
+ if (msg_kafka_response != RD_KAFKA_RESP_ERR_NO_ERROR ) {
+ updateKafkaFailureCounts(msg_kafka_response);
+
+ /* Put into kafka queue, again if configured! */
+ if (pData->bResubmitOnFailure &&
+ b_do_resubmit &&
+ msg_kafka_response != RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE) {
+ DBGPRINTF("omkafka: Failed to produce to topic '%s' (rd_kafka_producev)"
+ "partition %d: '%d/%s' - adding MSG '%s' to failed for RETRY!\n",
+ rd_kafka_topic_name(rkt), partition, msg_kafka_response,
+ rd_kafka_err2str(msg_kafka_response), msg);
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct((char*) key, key ? strlen((char*)key) : 0,
+ (char*) msg, strlen((char*)msg),rd_kafka_topic_name(rkt)));
+ SLIST_INSERT_HEAD(&pData->failedmsg_head, fmsgEntry, entries);
+ } else {
+ LogError(0, RS_RET_KAFKA_PRODUCE_ERR,
+ "omkafka: Failed to produce to topic '%s' (rd_kafka_producev)"
+ "partition %d: %d/%s - KEY '%s' -MSG '%s'\n",
+ rd_kafka_topic_name(rkt), partition, msg_kafka_response,
+ rd_kafka_err2str(msg_kafka_response), key, msg);
+ }
+ }
+#else
+
+ DBGPRINTF("omkafka: rd_kafka_produce\n");
+ /* Using old kafka produce API */
+ msg_enqueue_status = rd_kafka_produce(rkt, partition, RD_KAFKA_MSG_F_COPY,
+ msg, strlen((char*)msg), key,
+ key ? strlen((char*)key) : 0,
+ NULL);
+ if(msg_enqueue_status == -1) {
+ msg_kafka_response = rd_kafka_last_error();
+ updateKafkaFailureCounts(msg_kafka_response);
+
+ /* Put into kafka queue, again if configured! */
+ if (pData->bResubmitOnFailure &&
+ b_do_resubmit &&
+ msg_kafka_response != RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE) {
+ DBGPRINTF("omkafka: Failed to produce to topic '%s' (rd_kafka_produce)"
+ "partition %d: '%d/%s' - adding MSG '%s' KEY '%s' to failed for RETRY!\n",
+ rd_kafka_topic_name(rkt), partition, msg_kafka_response,
+ rd_kafka_err2str(rd_kafka_errno2err(errno)), msg, key ? (const char*) key : "");
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct((char*) key, key ? strlen((char*)key) : 0,
+ (char*) msg, strlen((char*)msg),rd_kafka_topic_name(rkt)));
+ SLIST_INSERT_HEAD(&pData->failedmsg_head, fmsgEntry, entries);
+ } else {
+ LogError(0, RS_RET_KAFKA_PRODUCE_ERR,
+ "omkafka: Failed to produce to topic '%s' (rd_kafka_produce) "
+ "partition %d: %d/%s - MSG '%s' KEY '%s'\n",
+ rd_kafka_topic_name(rkt), partition, msg_kafka_response,
+ rd_kafka_err2str(msg_kafka_response), msg, key);
+ }
+ }
+#endif
+
+ const int callbacksCalled = rd_kafka_poll(pData->rk, 0); /* call callbacks */
+ DBGPRINTF("omkafka: writeKafka kafka outqueue length: %d, callbacks called %d\n",
+ rd_kafka_outq_len(pData->rk), callbacksCalled);
+
+#if RD_KAFKA_VERSION >= 0x00090400
+ if (msg_kafka_response != RD_KAFKA_RESP_ERR_NO_ERROR) {
+#else
+ if (msg_enqueue_status == -1) {
+#endif
+ STATSCOUNTER_INC(ctrKafkaFail, mutCtrKafkaFail);
+ INST_STATSCOUNTER_INC(pData, pData->ctrKafkaFail, pData->mutCtrKafkaFail);
+ ABORT_FINALIZE(RS_RET_KAFKA_PRODUCE_ERR);
+ /* ABORT_FINALIZE isn't absolutely necessary as of now,
+ because this is the last line anyway, but its useful to ensure
+ correctness in case we add more stuff below this line at some point*/
+ }
+
+finalize_it:
+ if(topic_mut_locked) {
+ pthread_rwlock_unlock(dynTopicLock);
+ }
+ DBGPRINTF("omkafka: writeKafka returned %d\n", iRet);
+ if(iRet != RS_RET_OK) {
+ iRet = RS_RET_SUSPENDED;
+ }
+ STATSCOUNTER_SETMAX_NOMUT(ctrQueueSize, (unsigned) rd_kafka_outq_len(pData->rk));
+ STATSCOUNTER_INC(ctrTopicSubmit, mutCtrTopicSubmit);
+ INST_STATSCOUNTER_INC(pData, pData->ctrTopicSubmit, pData->mutCtrTopicSubmit);
+ RETiRet;
+}
+
+static void
+deliveryCallback(rd_kafka_t __attribute__((unused)) *rk,
+ const rd_kafka_message_t *rkmessage,
+ void *opaque)
+{
+ instanceData *const pData = (instanceData *) opaque;
+ failedmsg_entry* fmsgEntry;
+ DEFiRet;
+
+ if (rkmessage->err) {
+ updateKafkaFailureCounts(rkmessage->err);
+
+ /* Put into kafka queue, again if configured! */
+ if (pData->bResubmitOnFailure) {
+ DBGPRINTF("omkafka: kafka delivery FAIL on Topic '%s', msg '%.*s', key '%.*s' -"
+ " adding to FAILED MSGs for RETRY!\n",
+ rd_kafka_topic_name(rkmessage->rkt),
+ (int)(rkmessage->len-1), (char*)rkmessage->payload,
+ (int)(rkmessage->key_len), (char*)rkmessage->key);
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct(rkmessage->key, rkmessage->key_len,
+ rkmessage->payload, rkmessage->len,rd_kafka_topic_name(rkmessage->rkt)));
+ SLIST_INSERT_HEAD(&pData->failedmsg_head, fmsgEntry, entries);
+ } else {
+ LogError(0, RS_RET_ERR,
+ "omkafka: kafka delivery FAIL on Topic '%s', msg '%.*s', key '%.*s'\n",
+ rd_kafka_topic_name(rkmessage->rkt),
+ (int)(rkmessage->len-1), (char*)rkmessage->payload,
+ (int)(rkmessage->key_len), (char*)rkmessage->key);
+ writeDataError(pData, (char*) rkmessage->payload, rkmessage->len, rkmessage->err);
+ }
+ STATSCOUNTER_INC(ctrKafkaFail, mutCtrKafkaFail);
+ INST_STATSCOUNTER_INC(pData, pData->ctrKafkaFail, pData->mutCtrKafkaFail);
+ } else {
+ DBGPRINTF("omkafka: kafka delivery SUCCESS on msg '%.*s'\n", (int)(rkmessage->len-1),
+ (char*)rkmessage->payload);
+ STATSCOUNTER_INC(ctrKafkaAck, mutCtrKafkaAck);
+ INST_STATSCOUNTER_INC(pData, pData->ctrKafkaAck, pData->mutCtrKafkaAck);
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omkafka: deliveryCallback returned failure %d\n", iRet);
+ }
+}
+
+/**
+ * This function looks for a json object that corresponds to the
+ * passed name and returns it is found. Otherwise returns NULL.
+ * It will be used for processing stats callback json object.
+ */
+static struct fjson_object *
+get_object(struct fjson_object *fj_obj, const char * name) {
+ struct fjson_object_iterator it = fjson_object_iter_begin(fj_obj);
+ struct fjson_object_iterator itEnd = fjson_object_iter_end(fj_obj);
+ while (!fjson_object_iter_equal (&it, &itEnd)) {
+ const char * key = fjson_object_iter_peek_name (&it);
+ struct fjson_object * val = fjson_object_iter_peek_value(&it);
+ if(!strncmp(key, name, strlen(name))){
+ return val;
+ }
+ fjson_object_iter_next (&it);
+ }
+
+ return NULL;
+}
+
+/**
+ * This function performs a two level search in stats callback json
+ * object. It iterates over broker objects and for each broker object
+ * returns desired level2 value (such as avg/min/max) for specified
+ * level1 window statistic (such as rtt/throttle/int_latency). Threshold
+ * allows skipping values that are too small, so that they don't
+ * impact on aggregate averaged value that is returned.
+ */
+static uint64
+jsonExtractWindoStats(struct fjson_object * stats_object,
+ const char * level1_obj_name, const char * level2_obj_name,
+ unsigned long skip_threshold) {
+ uint64 level2_val;
+ uint64 agg_val = 0;
+ uint64 ret_val = 0;
+ int active_brokers = 0;
+
+ struct fjson_object * brokers_obj = get_object(stats_object, "brokers");
+ if (brokers_obj == NULL) {
+ LogMsg(0, NO_ERRCODE, LOG_ERR, "jsonExtractWindowStat: failed to find brokers object");
+ return ret_val;
+ }
+
+ /* iterate over borkers to get level1 window objects at level2 (min, max, avg, etc.) */
+ struct fjson_object_iterator it = fjson_object_iter_begin(brokers_obj);
+ struct fjson_object_iterator itEnd = fjson_object_iter_end(brokers_obj);
+ while (!fjson_object_iter_equal (&it, &itEnd)) {
+ struct fjson_object * val = fjson_object_iter_peek_value(&it);
+ struct fjson_object * level1_obj = get_object(val, level1_obj_name);
+ if(level1_obj == NULL)
+ return ret_val;
+
+ struct fjson_object * level2_obj = get_object(level1_obj, level2_obj_name);
+ if(level2_obj == NULL)
+ return ret_val;
+
+ level2_val = fjson_object_get_int64(level2_obj);
+ if (level2_val > skip_threshold) {
+ agg_val += level2_val;
+ active_brokers++;
+ }
+ fjson_object_iter_next (&it);
+ }
+ if(active_brokers > 0) {
+ ret_val = agg_val/active_brokers;
+ }
+
+ return ret_val;
+}
+
+/**
+ * librdkafka will call this function after every statistics.interval.ms
+ * interval, which is specified in confParam. See the explanation at:
+ * https://github.com/edenhill/librdkafka/wiki/Statistics
+ *
+ * Here we have extracted windows stats: rtt, throttle time, and internal
+ * latency averages. These values will be logged as impstats messages.
+ */
+static int
+statsCallback(rd_kafka_t __attribute__((unused)) *rk,
+ char *json, size_t __attribute__((unused)) json_len,
+ void __attribute__((unused)) *opaque) {
+ instanceData *const pData = (instanceData *) opaque;
+ char buf[2048];
+ char handler_name[1024] = "unknown";
+ int replyq = 0;
+ int msg_cnt = 0;
+ int msg_size = 0;
+ uint64 msg_max = 0;
+ uint64 msg_size_max = 0;
+
+ struct fjson_object * stats_object = NULL;
+ struct fjson_object * fj_obj = NULL;
+
+ DBGPRINTF("omkafka: librdkafka stats callback: %s\n", json);
+
+ /* prepare fjson object from stats callback for parsing */
+ stats_object = fjson_tokener_parse(json);
+ if (stats_object == NULL) {
+ LogMsg(0, NO_ERRCODE, LOG_ERR, "statsCallback: fjson tokenizer failed:");
+ return 0;
+ }
+ enum fjson_type type = fjson_object_get_type(stats_object);
+ if (type != fjson_type_object) {
+ LogMsg(0, NO_ERRCODE, LOG_ERR, "statsCallback: json is not of type object; can't process statsCB\n");
+ return 0;
+ }
+
+ /* top level stats extraction through libfastjson based parsing */
+ fj_obj = get_object(stats_object, "name");
+ if (fj_obj != NULL)
+ snprintf(handler_name, sizeof(handler_name), "%s", (char *)fjson_object_get_string(fj_obj));
+ fj_obj = get_object(stats_object, "replyq");
+ replyq = (fj_obj == NULL) ? 0 : fjson_object_get_int(fj_obj);
+ fj_obj = get_object(stats_object, "msg_cnt");
+ msg_cnt = (fj_obj == NULL) ? 0 : fjson_object_get_int(fj_obj);
+ fj_obj = get_object(stats_object, "msg_size");
+ msg_size = (fj_obj == NULL) ? 0 : fjson_object_get_int(fj_obj);
+ fj_obj = get_object(stats_object, "msg_max");
+ msg_max = (fj_obj == NULL) ? 0 : fjson_object_get_int64(fj_obj);
+ fj_obj = get_object(stats_object, "msg_size_max");
+ msg_size_max = (fj_obj == NULL) ? 0 : fjson_object_get_int64(fj_obj);
+
+ /* window stats extraction to be picked up by impstats counters */
+ rtt_avg_usec = jsonExtractWindoStats(stats_object, "rtt", "avg", 100);
+ throttle_avg_msec = jsonExtractWindoStats(stats_object, "throttle", "avg", 0);
+ int_latency_avg_usec = jsonExtractWindoStats(stats_object, "int_latency", "avg", 0);
+ json_object_put (stats_object);
+
+ /* emit a log line to get stats visibility per librdkafka client */
+ snprintf(buf, sizeof(buf),
+ "statscb_window_stats: handler_name=%s replyq=%d msg_cnt=%d msg_size=%d "
+ "msg_max=%lld msg_size_max=%lld rtt_avg_usec=%lld throttle_avg_msec=%lld "
+ "int_latency_avg_usec=%lld",
+ handler_name, replyq, msg_cnt, msg_size, msg_max, msg_size_max,
+ rtt_avg_usec, throttle_avg_msec, int_latency_avg_usec);
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "%s\n", buf);
+
+ /* Write the entire json stats object, if requested */
+ if (pData->statsFile != NULL)
+ writeStats(pData, json, json_len);
+
+ return 0;
+}
+
+static void
+kafkaLogger(const rd_kafka_t __attribute__((unused)) *rk, int level,
+ const char *fac, const char *buf)
+{
+ DBGPRINTF("omkafka: kafka log message [%d,%s]: %s\n",
+ level, fac, buf);
+}
+
+/* should be called with write(rkLock) */
+static void
+do_rd_kafka_destroy(instanceData *const __restrict__ pData)
+{
+ if (pData->rk == NULL) {
+ DBGPRINTF("omkafka: onDestroy can't close, handle wasn't open\n");
+ goto done;
+ }
+ int queuedCount = rd_kafka_outq_len(pData->rk);
+ DBGPRINTF("omkafka: onDestroy closing - items left in outqueue: %d\n", queuedCount);
+
+ struct timespec tOut;
+ timeoutComp(&tOut, pData->closeTimeout);
+
+ while (timeoutVal(&tOut) > 0) {
+ queuedCount = rd_kafka_outq_len(pData->rk);
+ if (queuedCount > 0) {
+ /* Flush all remaining kafka messages (rd_kafka_poll is called inside) */
+ const int flushStatus = rd_kafka_flush(pData->rk, pData->closeTimeout);
+ if (flushStatus == RD_KAFKA_RESP_ERR_NO_ERROR) {
+ DBGPRINTF("omkafka: onDestroyflushed remaining '%d' messages "
+ "to kafka topic '%s'\n", queuedCount,
+ (pData->pTopic == NULL ? "NULL" : rd_kafka_topic_name(pData->pTopic))
+ );
+
+ /* Trigger callbacks a last time before shutdown */
+ const int callbacksCalled = rd_kafka_poll(pData->rk, 0); /* call callbacks */
+ DBGPRINTF("omkafka: onDestroy kafka outqueue length: %d, "
+ "callbacks called %d\n", rd_kafka_outq_len(pData->rk),
+ callbacksCalled);
+ } else /* TODO: Handle unsend messages here! */ {
+ /* timeout = RD_KAFKA_RESP_ERR__TIMED_OUT */
+ LogError(0, RS_RET_KAFKA_ERROR, "omkafka: onDestroy "
+ "Failed to send remaining '%d' messages to "
+ "topic '%s' on shutdown with error: '%s'",
+ queuedCount,
+ (pData->pTopic == NULL ? "NULL" : rd_kafka_topic_name(pData->pTopic)),
+ rd_kafka_err2str(flushStatus));
+#if RD_KAFKA_VERSION >= 0x010001ff
+ rd_kafka_purge(pData->rk, RD_KAFKA_PURGE_F_QUEUE | RD_KAFKA_PURGE_F_INFLIGHT);
+ /* Trigger callbacks a last time before shutdown */
+ const int callbacksCalled = rd_kafka_poll(pData->rk, 0); /* call callbacks */
+ DBGPRINTF("omkafka: onDestroy kafka outqueue length: %d, "
+ "callbacks called %d\n", rd_kafka_outq_len(pData->rk),
+ callbacksCalled);
+#endif
+ }
+ } else {
+ break;
+ }
+ }
+ if (queuedCount > 0) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING,
+ "omkafka: queue-drain for close timed-out took too long, "
+ "items left in outqueue: %d -- this may indicate data loss",
+ rd_kafka_outq_len(pData->rk));
+ }
+ if (pData->dynaTopic) {
+ dynaTopicFreeCacheEntries(pData);
+ } else {
+ closeTopic(pData);
+ }
+
+ /* Final destroy of kafka!*/
+ rd_kafka_destroy(pData->rk);
+
+# if RD_KAFKA_VERSION < 0x00090001
+ /* Wait for kafka being destroyed in old API */
+ if (rd_kafka_wait_destroyed(10000) < 0) {
+ LogError(0, RS_RET_ERR, "omkafka: rd_kafka_destroy did not finish after grace timeout (10s)!");
+ } else {
+ DBGPRINTF("omkafka: rd_kafka_destroy successfully finished\n");
+ }
+# endif
+
+ pData->rk = NULL;
+done: return;
+}
+
+/* should be called with write(rkLock) */
+static void
+closeKafka(instanceData *const __restrict__ pData)
+{
+ if(pData->bIsOpen) {
+ do_rd_kafka_destroy(pData);
+ pData->bIsOpen = 0;
+ }
+}
+
+static void
+errorCallback(rd_kafka_t __attribute__((unused)) *rk,
+ int __attribute__((unused)) err,
+ const char *reason,
+ void __attribute__((unused)) *opaque)
+{
+ /* Get InstanceData pointer */
+ instanceData *const pData = (instanceData *) opaque;
+
+ /* count kafka transport errors that cause action suspension */
+ if (err == RD_KAFKA_RESP_ERR__MSG_TIMED_OUT) {
+ STATSCOUNTER_INC(ctrKafkaRespTimedOut, mutCtrKafkaRespTimedOut);
+ } else if (err == RD_KAFKA_RESP_ERR__TRANSPORT) {
+ STATSCOUNTER_INC(ctrKafkaRespTransport, mutCtrKafkaRespTransport);
+ } else if (err == RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN) {
+ STATSCOUNTER_INC(ctrKafkaRespBrokerDown, mutCtrKafkaRespBrokerDown);
+ } else if (err == RD_KAFKA_RESP_ERR__AUTHENTICATION) {
+ STATSCOUNTER_INC(ctrKafkaRespAuth, mutCtrKafkaRespAuth);
+ } else if (err == RD_KAFKA_RESP_ERR__SSL) {
+ STATSCOUNTER_INC(ctrKafkaRespSSL, mutCtrKafkaRespSSL);
+ } else {
+ STATSCOUNTER_INC(ctrKafkaRespOther, mutCtrKafkaRespOther);
+ }
+
+ /* Handle common transport error codes*/
+ if (err == RD_KAFKA_RESP_ERR__MSG_TIMED_OUT ||
+ err == RD_KAFKA_RESP_ERR__TRANSPORT ||
+ err == RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN ||
+ err == RD_KAFKA_RESP_ERR__AUTHENTICATION ||
+ err == RD_KAFKA_RESP_ERR__SSL) {
+ /* Broker transport error, we need to disable the action for now!*/
+ pData->bIsSuspended = 1;
+ LogMsg(0, RS_RET_KAFKA_ERROR, LOG_WARNING,
+ "omkafka: action will suspended due to kafka error %d: %s",
+ err, rd_kafka_err2str(err));
+ } else {
+ LogError(0, RS_RET_KAFKA_ERROR, "omkafka: kafka error message: %d,'%s','%s'",
+ err, rd_kafka_err2str(err), reason);
+ }
+}
+
+
+
+#if 0 /* the stock librdkafka version in Ubuntu 14.04 LTS does NOT support metadata :-( */
+/* Note: this is a skeleton, with some code missing--> add it when it is actually implemented. */
+static int
+getConfiguredPartitions()
+{
+ struct rd_kafka_metadata *pMetadata;
+ if(rd_kafka_metadata(pData->rk, 0, rkt, &pMetadata, 8)
+ == RD_KAFKA_RESP_ERR_NO_ERROR) {
+ dbgprintf("omkafka: topic '%s' has %d partitions\n",
+ pData->topic, pMetadata->topics[0]->partition_cnt);
+ rd_kafka_metadata_destroy(pMetadata);
+ } else {
+ dbgprintf("omkafka: error reading metadata\n");
+ // TODO: handle this gracefull **when** we actually need
+ // the metadata -- or remove completely. 2014-12-12 rgerhards
+ }
+}
+#endif
+
+/* should be called with write(rkLock) */
+static rsRetVal
+openKafka(instanceData *const __restrict__ pData)
+{
+ char errstr[MAX_ERRMSG];
+ DEFiRet;
+
+ if(pData->bIsOpen)
+ FINALIZE;
+
+ pData->pTopic = NULL;
+
+ /* main conf */
+ rd_kafka_conf_t *const conf = rd_kafka_conf_new();
+ if(conf == NULL) {
+ LogError(0, RS_RET_KAFKA_ERROR, "omkafka: error creating kafka conf obj: %s\n",
+ rd_kafka_err2str(rd_kafka_last_error()));
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+
+#ifdef DEBUG
+ /* enable kafka debug output */
+ if(rd_kafka_conf_set(conf, "debug", RD_KAFKA_DEBUG_CONTEXTS,
+ errstr, sizeof(errstr)) != RD_KAFKA_CONF_OK) {
+ LogError(0, RS_RET_KAFKA_ERROR, "omkafka: error setting kafka debug option: %s\n", errstr);
+ /* DO NOT ABORT IN THIS CASE! */
+ }
+#endif
+
+ for(int i = 0 ; i < pData->nConfParams ; ++i) {
+ DBGPRINTF("omkafka: setting custom configuration parameter: %s:%s\n",
+ pData->confParams[i].name,
+ pData->confParams[i].val);
+ if(rd_kafka_conf_set(conf, pData->confParams[i].name,
+ pData->confParams[i].val, errstr, sizeof(errstr))
+ != RD_KAFKA_CONF_OK) {
+ if(pData->bReportErrs) {
+ LogError(0, RS_RET_PARAM_ERROR, "error setting custom configuration "
+ "parameter '%s=%s': %s",
+ pData->confParams[i].name,
+ pData->confParams[i].val, errstr);
+ } else {
+ DBGPRINTF("omkafka: error setting custom configuration parameter '%s=%s': %s",
+ pData->confParams[i].name,
+ pData->confParams[i].val, errstr);
+ }
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ }
+ rd_kafka_conf_set_opaque(conf, (void *) pData);
+ rd_kafka_conf_set_dr_msg_cb(conf, deliveryCallback);
+ rd_kafka_conf_set_error_cb(conf, errorCallback);
+ rd_kafka_conf_set_stats_cb(conf, statsCallback);
+# if RD_KAFKA_VERSION >= 0x00090001
+ rd_kafka_conf_set_log_cb(conf, kafkaLogger);
+# endif
+
+ char kafkaErrMsg[1024];
+ pData->rk = rd_kafka_new(RD_KAFKA_PRODUCER, conf, kafkaErrMsg, sizeof(kafkaErrMsg));
+ if(pData->rk == NULL) {
+ LogError(0, RS_RET_KAFKA_ERROR,
+ "omkafka: error creating kafka handle: %s\n", kafkaErrMsg);
+ ABORT_FINALIZE(RS_RET_KAFKA_ERROR);
+ }
+
+# if RD_KAFKA_VERSION < 0x00090001
+ rd_kafka_conf_set_log_cb(pData->rk, kafkaLogger);
+# endif
+ DBGPRINTF("omkafka setting brokers: '%s'n", pData->brokers);
+ if(rd_kafka_brokers_add(pData->rk, (char*)pData->brokers) == 0) {
+ LogError(0, RS_RET_KAFKA_NO_VALID_BROKERS,
+ "omkafka: no valid brokers specified: %s\n", pData->brokers);
+ ABORT_FINALIZE(RS_RET_KAFKA_NO_VALID_BROKERS);
+ }
+
+ pData->bIsOpen = 1;
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ pData->bReportErrs = 1;
+ } else {
+ pData->bReportErrs = 0;
+ if(pData->rk != NULL) {
+ do_rd_kafka_destroy(pData);
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+setupKafkaHandle(instanceData *const __restrict__ pData, int recreate)
+{
+ DEFiRet;
+ pthread_rwlock_wrlock(&pData->rkLock);
+ if (recreate) {
+ closeKafka(pData);
+ }
+ CHKiRet(openKafka(pData));
+ if (! pData->dynaTopic) {
+ if( pData->pTopic == NULL)
+ CHKiRet(prepareTopic(pData, pData->topic));
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (pData->rk != NULL) {
+ closeKafka(pData);
+ }
+
+ /* Parameter Error's cannot be resumed, so we need to disable the action */
+ if (iRet == RS_RET_PARAM_ERROR) {
+ iRet = RS_RET_DISABLE_ACTION;
+ LogError(0, iRet, "omkafka: action will be disabled due invalid "
+ "kafka configuration parameters\n");
+ }
+
+ }
+ pthread_rwlock_unlock(&pData->rkLock);
+ RETiRet;
+}
+
+static rsRetVal
+checkFailedMessages(instanceData *const __restrict__ pData)
+{
+ failedmsg_entry* fmsgEntry;
+ DEFiRet;
+
+ /* Loop through failed messages, reprocess them first! */
+ while (!SLIST_EMPTY(&pData->failedmsg_head)) {
+ fmsgEntry = SLIST_FIRST(&pData->failedmsg_head);
+ assert(fmsgEntry != NULL);
+ /* Put back into kafka! */
+ iRet = writeKafka(pData, (uchar*) fmsgEntry->key, (uchar*) fmsgEntry->payload, NULL,
+ fmsgEntry->topicname,NO_RESUBMIT);
+ if(iRet != RS_RET_OK) {
+ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING,
+ "omkafka: failed to deliver failed msg '%.*s' with status %d. "
+ "- suspending AGAIN!",
+ (int)(strlen((char*)fmsgEntry->payload)-1),
+ (char*)fmsgEntry->payload, iRet);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ DBGPRINTF("omkafka: successfully delivered failed msg '%.*s'.\n",
+ (int)(strlen((char*)fmsgEntry->payload)-1),
+ (char*)fmsgEntry->payload);
+ /* Note: we can use SLIST even though it is o(n), because the element
+ * in question is always either the root or the next element and
+ * SLIST_REMOVE iterates only until the element to be deleted is found.
+ * We cannot use SLIST_REMOVE_HEAD() as new elements may have been
+ * added in the delivery callback!
+ * TODO: sounds like bad logic -- why do we add and remove, just simply
+ * keep it in queue?
+ */
+ SLIST_REMOVE(&pData->failedmsg_head, fmsgEntry, s_failedmsg_entry, entries);
+ failedmsg_entry_destruct(fmsgEntry);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* This function persists failed messages into a data file, so they can
+ * be resend on next startup.
+ * alorbach, 2017-06-02
+ */
+static rsRetVal ATTR_NONNULL(1)
+persistFailedMsgs(instanceData *const __restrict__ pData)
+{
+ DEFiRet;
+ int fdMsgFile = -1;
+ ssize_t nwritten;
+
+ if(SLIST_EMPTY(&pData->failedmsg_head)) {
+ DBGPRINTF("omkafka: persistFailedMsgs: We do not need to persist failed messages.\n");
+ FINALIZE;
+ }
+
+ fdMsgFile = open((char*)pData->failedMsgFile,
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(fdMsgFile == -1) {
+ LogError(errno, RS_RET_ERR, "omkafka: persistFailedMsgs error opening failed msg file %s",
+ pData->failedMsgFile);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ while (!SLIST_EMPTY(&pData->failedmsg_head)) {
+ failedmsg_entry* fmsgEntry = SLIST_FIRST(&pData->failedmsg_head);
+ assert(fmsgEntry != NULL);
+ nwritten = write(fdMsgFile, fmsgEntry->topicname, ustrlen(fmsgEntry->topicname) );
+ if(nwritten != -1)
+ nwritten = write(fdMsgFile, "\t", 1);
+ if((nwritten != -1) && (fmsgEntry->key))
+ nwritten = write(fdMsgFile, fmsgEntry->key, ustrlen(fmsgEntry->key) );
+ if(nwritten != -1)
+ nwritten = write(fdMsgFile, "\t", 1);
+ if(nwritten != -1)
+ nwritten = write(fdMsgFile, fmsgEntry->payload, ustrlen(fmsgEntry->payload) );
+ if(nwritten == -1) {
+ LogError(errno, RS_RET_ERR, "omkafka: persistFailedMsgs error writing failed msg file");
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ DBGPRINTF("omkafka: persistFailedMsgs successfully written loaded msg '%.*s' for "
+ "topic '%s'\n", (int)(strlen((char*)fmsgEntry->payload)-1),
+ fmsgEntry->payload, fmsgEntry->topicname);
+ }
+ SLIST_REMOVE_HEAD(&pData->failedmsg_head, entries);
+ failedmsg_entry_destruct(fmsgEntry);
+ }
+
+finalize_it:
+ if(fdMsgFile != -1) {
+ close(fdMsgFile);
+ }
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "omkafka: could not persist failed messages "
+ "file %s - failed messages will be lost.",
+ (char*)pData->failedMsgFile);
+ }
+ RETiRet;
+}
+
+/* This function loads failed messages from a data file, so they can
+ * be resend after action startup.
+ * alorbach, 2017-06-06
+ */
+static rsRetVal
+loadFailedMsgs(instanceData *const __restrict__ pData)
+{
+ DEFiRet;
+ struct stat stat_buf;
+ failedmsg_entry* fmsgEntry;
+ strm_t *pstrmFMSG = NULL;
+ cstr_t *pCStr = NULL;
+ uchar *puStr;
+ char *pStrTabPos;
+ char *pStrTabPos2;
+
+ assert(pData->failedMsgFile != NULL);
+
+ /* check if the file exists */
+ if(stat((char*) pData->failedMsgFile, &stat_buf) == -1) {
+ if(errno == ENOENT) {
+ DBGPRINTF("omkafka: loadFailedMsgs failed messages file %s wasn't found, "
+ "continue startup\n", pData->failedMsgFile);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ } else {
+ LogError(errno, RS_RET_IO_ERROR,
+ "omkafka: loadFailedMsgs could not open failed messages file %s",
+ pData->failedMsgFile);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ } else {
+ DBGPRINTF("omkafka: loadFailedMsgs found failed message file %s.\n",
+ pData->failedMsgFile);
+ }
+
+ /* File exists, we can load and process it */
+ CHKiRet(strm.Construct(&pstrmFMSG));
+ CHKiRet(strm.SettOperationsMode(pstrmFMSG, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(pstrmFMSG, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(pstrmFMSG, pData->failedMsgFile, ustrlen(pData->failedMsgFile)));
+ CHKiRet(strm.ConstructFinalize(pstrmFMSG));
+
+ while(strm.ReadLine(pstrmFMSG, &pCStr, 0, 0, NULL, 0, NULL) == RS_RET_OK) {
+ if(rsCStrLen(pCStr) == 0) {
+ /* we do not process empty lines */
+ DBGPRINTF("omkafka: loadFailedMsgs msg was empty!");
+ } else {
+ puStr = rsCStrGetSzStrNoNULL(pCStr); //topic
+ pStrTabPos = index((char*)puStr, '\t'); //key
+ pStrTabPos2 = index((char*)pStrTabPos+1, '\t'); //msg
+ if ((pStrTabPos != NULL) && (pStrTabPos2 != NULL)) {
+ *pStrTabPos = '\0'; /* split string into two */
+ *pStrTabPos2 = '\0'; /* split string into two */
+ DBGPRINTF("omkafka: loadFailedMsgs successfully loaded msg '%s' for "
+ "topic '%s' key '%s' \n",
+ pStrTabPos2+1, (char*)puStr, pStrTabPos+1);
+ if (strlen(pStrTabPos+1)) {
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct(
+ pStrTabPos+1,strlen(pStrTabPos+1),
+ pStrTabPos2+1,strlen(pStrTabPos2+1),
+ (char*)puStr));
+ } else {
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct(
+ NULL,0,
+ pStrTabPos2+1,strlen(pStrTabPos2+1),
+ (char*)puStr));
+ }
+ SLIST_INSERT_HEAD(&pData->failedmsg_head, fmsgEntry, entries);
+ } else {
+ LogError(0, RS_RET_ERR, "omkafka: loadFailedMsgs droping invalid msg found: %s",
+ (char*)rsCStrGetSzStrNoNULL(pCStr));
+ }
+ }
+
+ rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */
+ }
+finalize_it:
+ if(pstrmFMSG != NULL) {
+ strm.Destruct(&pstrmFMSG);
+ }
+
+ if(iRet != RS_RET_OK) {
+ /* We ignore FILE NOT FOUND here */
+ if (iRet != RS_RET_FILE_NOT_FOUND) {
+ LogError(0, iRet, "omkafka: could not load failed messages "
+ "from file %s error %d - failed messages will not be resend.",
+ (char*)pData->failedMsgFile, iRet);
+ }
+ } else {
+ DBGPRINTF("omkafka: loadFailedMsgs unlinking '%s'\n", (char*)pData->failedMsgFile);
+ /* Delete file if still exists! */
+ const int r = unlink((char*)pData->failedMsgFile);
+ if(r != 0 && r != ENOENT) {
+ LogError(errno, RS_RET_ERR, "omkafka: loadFailedMsgs failed to remove "
+ "file \"%s\"", (char*)pData->failedMsgFile);
+ }
+ }
+
+ RETiRet;
+}
+
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutErrFile);
+ if(pData->fdErrFile != -1) {
+ close(pData->fdErrFile);
+ pData->fdErrFile = -1;
+ }
+ pthread_mutex_unlock(&pData->mutErrFile);
+ pthread_mutex_lock(&pData->mutStatsFile);
+ if(pData->fdStatsFile != -1) {
+ close(pData->fdStatsFile);
+ pData->fdStatsFile = -1;
+ }
+ pthread_mutex_unlock(&pData->mutStatsFile);
+ if (pData->bReopenOnHup) {
+ CHKiRet(setupKafkaHandle(pData, 1));
+ } else {
+ /* Optional */
+ const int callbacksCalled = rd_kafka_poll(pData->rk, 0); /* call callbacks */
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "omkafka: doHUP kafka - '%s' outqueue length: %d,"
+ "callbacks called %d\n", pData->tplName,
+ rd_kafka_outq_len(pData->rk), callbacksCalled);
+ }
+finalize_it:
+ENDdoHUP
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->currPartition = 0;
+ pData->bIsOpen = 0;
+ pData->bIsSuspended = 0;
+ pData->fdErrFile = -1;
+ pData->fdStatsFile = -1;
+ pData->pTopic = NULL;
+ pData->bReportErrs = 1;
+ pData->bReopenOnHup = 1;
+ pData->bResubmitOnFailure = 0;
+ pData->bKeepFailedMessages = 0;
+ pData->failedMsgFile = NULL;
+ SLIST_INIT(&pData->failedmsg_head);
+ CHKiRet(pthread_mutex_init(&pData->mut_doAction, NULL));
+ CHKiRet(pthread_mutex_init(&pData->mutErrFile, NULL));
+ CHKiRet(pthread_mutex_init(&pData->mutStatsFile, NULL));
+ CHKiRet(pthread_rwlock_init(&pData->rkLock, NULL));
+ CHKiRet(pthread_mutex_init(&pData->mutDynCache, NULL));
+ INIT_ATOMIC_HELPER_MUT(pData->mutCurrPartition);
+finalize_it:
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* Helpers for Failed Msg List */
+ failedmsg_entry* fmsgEntry1;
+ failedmsg_entry* fmsgEntry2;
+ if(pData->fdErrFile != -1)
+ close(pData->fdErrFile);
+ if(pData->fdStatsFile != -1)
+ close(pData->fdStatsFile);
+ /* Closing Kafka first! */
+ pthread_rwlock_wrlock(&pData->rkLock);
+ closeKafka(pData);
+ if(pData->dynaTopic && pData->dynCache != NULL) {
+ free(pData->dynCache);
+ pData->dynCache = NULL;
+ }
+ /* Persist failed messages */
+ if (pData->bResubmitOnFailure && pData->bKeepFailedMessages && pData->failedMsgFile != NULL) {
+ persistFailedMsgs(pData);
+ }
+ pthread_rwlock_unlock(&pData->rkLock);
+
+ if (pData->stats) {
+ statsobj.Destruct(&pData->stats);
+ }
+
+ /* Delete Linked List for failed msgs */
+ fmsgEntry1 = SLIST_FIRST(&pData->failedmsg_head);
+ while (fmsgEntry1 != NULL) {
+ fmsgEntry2 = SLIST_NEXT(fmsgEntry1, entries);
+ failedmsg_entry_destruct(fmsgEntry1);
+ fmsgEntry1 = fmsgEntry2;
+ }
+ SLIST_INIT(&pData->failedmsg_head);
+ /* Free other mem */
+ free(pData->errorFile);
+ free(pData->statsFile);
+ free(pData->failedMsgFile);
+ free(pData->topic);
+ free(pData->brokers);
+ free(pData->tplName);
+ free(pData->statsName);
+ for(int i = 0 ; i < pData->nConfParams ; ++i) {
+ free((void*) pData->confParams[i].name);
+ free((void*) pData->confParams[i].val);
+ }
+ free(pData->confParams);
+ for(int i = 0 ; i < pData->nTopicConfParams ; ++i) {
+ free((void*) pData->topicConfParams[i].name);
+ free((void*) pData->topicConfParams[i].val);
+ }
+ free(pData->topicConfParams);
+ DESTROY_ATOMIC_HELPER_MUT(pData->mutCurrPartition);
+ pthread_rwlock_destroy(&pData->rkLock);
+ pthread_mutex_destroy(&pData->mut_doAction);
+ pthread_mutex_destroy(&pData->mutErrFile);
+ pthread_mutex_destroy(&pData->mutStatsFile);
+ pthread_mutex_destroy(&pData->mutDynCache);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+ int iKafkaRet;
+ const struct rd_kafka_metadata *metadata;
+CODESTARTtryResume
+ pthread_mutex_lock(&pWrkrData->pData->mut_doAction); /* see doAction header comment! */
+ CHKiRet(setupKafkaHandle(pWrkrData->pData, 0));
+
+ if ((iKafkaRet = rd_kafka_metadata(pWrkrData->pData->rk, 0, NULL, &metadata, 1000))
+ != RD_KAFKA_RESP_ERR_NO_ERROR) {
+ DBGPRINTF("omkafka: tryResume failed, brokers down %d,%s\n", iKafkaRet, rd_kafka_err2str(iKafkaRet));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ DBGPRINTF("omkafka: tryResume success, %d brokers UP\n", metadata->broker_cnt);
+ /* Reset suspended state */
+ pWrkrData->pData->bIsSuspended = 0;
+ /* free mem*/
+ rd_kafka_metadata_destroy(metadata);
+ }
+
+finalize_it:
+ pthread_mutex_unlock(&pWrkrData->pData->mut_doAction); /* see doAction header comment! */
+ DBGPRINTF("omkafka: tryResume returned %d\n", iRet);
+ENDtryResume
+
+
+/* IMPORTANT NOTE on multithreading:
+ * librdkafka creates background threads itself. So omkafka basically needs to move
+ * memory buffers over to librdkafka, which then does the heavy hauling. As such, we
+ * think that it is best to run max one wrkr instance of omkafka -- otherwise we just
+ * get additional locking (contention) overhead without any real gain. As such,
+ * we use a global mutex for doAction which ensures only one worker can be active
+ * at any given time. That mutex is also used to guard utility functions (like
+ * tryResume) which may also be accessed by multiple workers in parallel.
+ * Note: shall this method be changed, the kafka connection/suspension handling needs
+ * to be refactored. The current code assumes that all workers share state information
+ * including librdkafka handles.
+ */
+BEGINdoAction
+CODESTARTdoAction
+ failedmsg_entry* fmsgEntry;
+ instanceData *const pData = pWrkrData->pData;
+ int need_unlock = 0;
+ int dynaTopicID = 0;
+ int dynaKeyID = 0;
+
+ if (pData->dynaKey) {
+ dynaKeyID=2;
+ if (pData->dynaTopic) {
+ dynaTopicID=3;
+ }
+ } else {
+ if (pData->dynaTopic) {
+ dynaTopicID=2;
+ }
+ }
+ pthread_mutex_lock(&pData->mut_doAction);
+ if (! pData->bIsOpen)
+ CHKiRet(setupKafkaHandle(pData, 0));
+
+ /* Lock here to prevent msg loss */
+ pthread_rwlock_rdlock(&pData->rkLock);
+ need_unlock = 1;
+
+ /* We need to trigger callbacks first in order to suspend the Action properly on failure */
+ const int callbacksCalled = rd_kafka_poll(pData->rk, 0); /* call callbacks */
+ DBGPRINTF("omkafka: doAction kafka outqueue length: %d, callbacks called %d\n",
+ rd_kafka_outq_len(pData->rk), callbacksCalled);
+
+ /* Reprocess failed messages! */
+ if (pData->bResubmitOnFailure) {
+ iRet = checkFailedMessages(pData);
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omkafka: doAction failed to submit FAILED messages with status %d\n", iRet);
+
+ if (pData->bResubmitOnFailure) {
+ if (pData->dynaKey || pData->key) {
+ DBGPRINTF("omkafka: also adding MSG '%.*s' for topic '%s' key '%s' "
+ "to failed for RETRY!\n",
+ (int)(strlen((char*)ppString[0])-1), ppString[0],
+ pData->dynaTopic ? ppString[dynaTopicID] : pData->topic,
+ pData->dynaKey ? ppString[dynaKeyID] : pData->key);
+ } else {
+ DBGPRINTF("omkafka: also adding MSG '%.*s' for topic '%s' "
+ "to failed for RETRY!\n",
+ (int)(strlen((char*)ppString[0])-1), ppString[0],
+ pData->dynaTopic ? ppString[dynaTopicID] : pData->topic);
+ }
+ CHKmalloc(fmsgEntry = failedmsg_entry_construct(
+ (char*) (pData->dynaKey ? ppString[dynaKeyID] : pData->key),
+ pData->dynaKey || pData->key ?
+ strlen((char*)(pData->dynaKey ? ppString[dynaKeyID] : pData->key)) : 0,
+ (char*)ppString[0], strlen((char*)ppString[0]),
+ (char*) (pData->dynaTopic ? ppString[dynaTopicID] : pData->topic)));
+ SLIST_INSERT_HEAD(&pData->failedmsg_head, fmsgEntry, entries);
+ }
+ ABORT_FINALIZE(iRet);
+ }
+ }
+
+ /* support dynamic topic */
+ iRet = writeKafka(pData, pData->dynaKey ? ppString[dynaKeyID] : pData->key, ppString[0], ppString[1],
+ pData->dynaTopic ? ppString[dynaTopicID] : pData->topic, RESUBMIT);
+
+finalize_it:
+ if(need_unlock) {
+ pthread_rwlock_unlock(&pData->rkLock);
+ }
+
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("omkafka: doAction failed with status %d\n", iRet);
+ }
+
+ /* Suspend Action if broker problems were reported in error callback */
+ if (pData->bIsSuspended) {
+ DBGPRINTF("omkafka: doAction broker failure detected, suspending action\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ pthread_mutex_unlock(&pData->mut_doAction); /* must be after last pData access! */
+ENDdoAction
+
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->topic = NULL;
+ pData->pTopic = NULL;
+ pData->dynaKey = 0;
+ pData->dynaTopic = 0;
+ pData->iDynaTopicCacheSize = 50;
+ pData->brokers = NULL;
+ pData->autoPartition = 0;
+ pData->fixedPartition = NO_FIXED_PARTITION;
+ pData->nPartitions = 1;
+ pData->nConfParams = 0;
+ pData->confParams = NULL;
+ pData->nTopicConfParams = 0;
+ pData->topicConfParams = NULL;
+ pData->errorFile = NULL;
+ pData->statsFile = NULL;
+ pData->failedMsgFile = NULL;
+ pData->key = NULL;
+ pData->closeTimeout = 2000;
+}
+
+static rsRetVal
+processKafkaParam(char *const param,
+ const char **const name,
+ const char **const paramval)
+{
+ DEFiRet;
+ char *val = strstr(param, "=");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ *val = '\0'; /* terminates name */
+ ++val; /* now points to begin of value */
+ CHKmalloc(*name = strdup(param));
+ CHKmalloc(*paramval = strdup(val));
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int iNumTpls;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "topic")) {
+ pData->topic = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "dynakey")) {
+ pData->dynaKey = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dynatopic")) {
+ pData->dynaTopic = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dynatopic.cachesize")) {
+ pData->iDynaTopicCacheSize = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "closetimeout")) {
+ pData->closeTimeout = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "partitions.auto")) {
+ pData->autoPartition = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "partitions.number")) {
+ pData->nPartitions = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "partitions.usefixed")) {
+ pData->fixedPartition = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "broker")) {
+ es_str_t *es = es_newStr(128);
+ int bNeedComma = 0;
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ if(bNeedComma)
+ es_addChar(&es, ',');
+ es_addStr(&es, pvals[i].val.d.ar->arr[j]);
+ bNeedComma = 1;
+ }
+ pData->brokers = es_str2cstr(es, NULL);
+ es_deleteStr(es);
+ } else if(!strcmp(actpblk.descr[i].name, "confparam")) {
+ pData->nConfParams = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->confParams = malloc(sizeof(struct kafka_params) *
+ pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processKafkaParam(cstr, &pData->confParams[j].name,
+ &pData->confParams[j].val));
+ free(cstr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "topicconfparam")) {
+ pData->nTopicConfParams = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->topicConfParams = malloc(sizeof(struct kafka_params) *
+ pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processKafkaParam(cstr, &pData->topicConfParams[j].name,
+ &pData->topicConfParams[j].val));
+ free(cstr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "errorfile")) {
+ pData->errorFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "statsfile")) {
+ pData->statsFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "reopenonhup")) {
+ pData->bReopenOnHup = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "resubmitonfailure")) {
+ pData->bResubmitOnFailure = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "keepfailedmessages")) {
+ pData->bKeepFailedMessages = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "failedmsgfile")) {
+ pData->failedMsgFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "statsname")) {
+ pData->statsName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "omkafka: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->brokers == NULL) {
+ CHKmalloc(pData->brokers = strdup("localhost:9092"));
+ LogMsg(0, NO_ERRCODE, LOG_INFO, "imkafka: \"broker\" parameter not specified "
+ "using default of localhost:9092 -- this may not be what you want!");
+ }
+
+ if(pData->dynaKey && pData->key == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omkafka: requested dynamic key, but no "
+ "name for key template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ if(pData->dynaTopic && pData->topic == NULL) {
+ LogError(0, RS_RET_CONFIG_ERROR,
+ "omkafka: requested dynamic topic, but no "
+ "name for topic template given - action definition invalid");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ iNumTpls = 2;
+ if(pData->dynaKey) ++iNumTpls;
+ if(pData->dynaTopic) ++iNumTpls;
+ CODE_STD_STRING_REQUESTnewActInst(iNumTpls);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_FileFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup(" KAFKA_TimeStamp"),
+ OMSR_NO_RQD_TPL_OPTS));
+ if(pData->dynaKey)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 2, ustrdup(pData->key), OMSR_NO_RQD_TPL_OPTS));
+
+ if(pData->dynaTopic) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, pData->dynaKey?3:2, ustrdup(pData->topic), OMSR_NO_RQD_TPL_OPTS));
+ CHKmalloc(pData->dynCache = (dynaTopicCacheEntry**)
+ calloc(pData->iDynaTopicCacheSize, sizeof(dynaTopicCacheEntry*)));
+ pData->iCurrElt = -1;
+ }
+
+ pthread_mutex_lock(&closeTimeoutMut);
+ if (closeTimeout < pData->closeTimeout) {
+ closeTimeout = pData->closeTimeout;
+ }
+ pthread_mutex_unlock(&closeTimeoutMut);
+
+ /* Load failed messages here (If enabled), do NOT check for IRET!*/
+ if (pData->bKeepFailedMessages && pData->failedMsgFile != NULL) {
+ loadFailedMsgs(pData);
+ }
+
+ if (pData->statsName) {
+ CHKiRet(statsobj.Construct(&pData->stats));
+ CHKiRet(statsobj.SetName(pData->stats, (uchar *)pData->statsName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar *)"omkafka"));
+
+ /* Track following stats */
+ STATSCOUNTER_INIT(pData->ctrTopicSubmit, pData->mutCtrTopicSubmit);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrTopicSubmit));
+ STATSCOUNTER_INIT(pData->ctrKafkaFail, pData->mutCtrKafkaFail);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrKafkaFail));
+ STATSCOUNTER_INIT(pData->ctrKafkaAck, pData->mutCtrKafkaAck);
+ CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"acked",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrKafkaAck));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINmodExit
+CODESTARTmodExit
+ statsobj.Destruct(&kafkaStats);
+ CHKiRet(objRelease(statsobj, CORE_COMPONENT));
+ DESTROY_ATOMIC_HELPER_MUT(mutClock);
+
+ pthread_mutex_lock(&closeTimeoutMut);
+ int timeout = closeTimeout;
+ pthread_mutex_unlock(&closeTimeoutMut);
+ pthread_mutex_destroy(&closeTimeoutMut);
+ if (rd_kafka_wait_destroyed(timeout) != 0) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING,
+ "omkafka: could not terminate librdkafka gracefully, "
+ "%d threads still remain.\n", rd_kafka_thread_cnt());
+ }
+finalize_it:
+ENDmodExit
+
+
+NO_LEGACY_CONF_parseSelectorAct
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ uchar *pTmp;
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("just because librdkafka needs it, sqrt of 4 is %f\n", sqrt(4.0));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ INIT_ATOMIC_HELPER_MUT(mutClock);
+
+ DBGPRINTF("omkafka %s using librdkafka version %s, 0x%x\n",
+ VERSION, rd_kafka_version_str(), rd_kafka_version());
+ CHKiRet(statsobj.Construct(&kafkaStats));
+ CHKiRet(statsobj.SetName(kafkaStats, (uchar *)"omkafka"));
+ CHKiRet(statsobj.SetOrigin(kafkaStats, (uchar*)"omkafka"));
+ STATSCOUNTER_INIT(ctrTopicSubmit, mutCtrTopicSubmit);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"submitted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrTopicSubmit));
+ STATSCOUNTER_INIT(ctrQueueSize, mutCtrQueueSize);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"maxoutqsize",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrQueueSize));
+ STATSCOUNTER_INIT(ctrKafkaFail, mutCtrKafkaFail);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaFail));
+ STATSCOUNTER_INIT(ctrCacheSkip, mutCtrCacheSkip);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"topicdynacache.skipped",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCacheSkip));
+ STATSCOUNTER_INIT(ctrCacheMiss, mutCtrCacheMiss);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"topicdynacache.miss",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCacheMiss));
+ STATSCOUNTER_INIT(ctrCacheEvict, mutCtrCacheEvict);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"topicdynacache.evicted",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCacheEvict));
+ STATSCOUNTER_INIT(ctrKafkaAck, mutCtrKafkaAck);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"acked",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaAck));
+ STATSCOUNTER_INIT(ctrKafkaMsgTooLarge, mutCtrKafkaMsgTooLarge);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures_msg_too_large",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaMsgTooLarge));
+ STATSCOUNTER_INIT(ctrKafkaUnknownTopic, mutCtrKafkaUnknownTopic);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures_unknown_topic",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaUnknownTopic));
+ STATSCOUNTER_INIT(ctrKafkaQueueFull, mutCtrKafkaQueueFull);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures_queue_full",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaQueueFull));
+ STATSCOUNTER_INIT(ctrKafkaUnknownPartition, mutCtrKafkaUnknownPartition);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures_unknown_partition",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaUnknownPartition));
+ STATSCOUNTER_INIT(ctrKafkaOtherErrors, mutCtrKafkaOtherErrors);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"failures_other",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaOtherErrors));
+ STATSCOUNTER_INIT(ctrKafkaRespTimedOut, mutCtrKafkaRespTimedOut);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_timed_out",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespTimedOut));
+ STATSCOUNTER_INIT(ctrKafkaRespTransport, mutCtrKafkaRespTransport);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_transport",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespTransport));
+ STATSCOUNTER_INIT(ctrKafkaRespBrokerDown, mutCtrKafkaRespBrokerDown);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_broker_down",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespBrokerDown));
+ STATSCOUNTER_INIT(ctrKafkaRespAuth, mutCtrKafkaRespAuth);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_auth",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespAuth));
+ STATSCOUNTER_INIT(ctrKafkaRespSSL, mutCtrKafkaRespSSL);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_ssl",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespSSL));
+ STATSCOUNTER_INIT(ctrKafkaRespOther, mutCtrKafkaRespOther);
+ CHKiRet(statsobj.AddCounter(kafkaStats, (uchar *)"errors_other",
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrKafkaRespOther));
+ CHKiRet(statsobj.AddCounter(kafkaStats, UCHAR_CONSTANT("rtt_avg_usec"),
+ ctrType_Int, CTR_FLAG_NONE, &rtt_avg_usec));
+ CHKiRet(statsobj.AddCounter(kafkaStats, UCHAR_CONSTANT("throttle_avg_msec"),
+ ctrType_Int, CTR_FLAG_NONE, &throttle_avg_msec));
+ CHKiRet(statsobj.AddCounter(kafkaStats, UCHAR_CONSTANT("int_latency_avg_usec"),
+ ctrType_Int, CTR_FLAG_NONE, &int_latency_avg_usec));
+ CHKiRet(statsobj.ConstructFinalize(kafkaStats));
+
+ DBGPRINTF("omkafka: Add KAFKA_TimeStamp to template system ONCE\n");
+ pTmp = (uchar*) KAFKA_TimeStamp;
+ tplAddLine(ourConf, " KAFKA_TimeStamp", &pTmp);
+ENDmodInit
diff --git a/plugins/omlibdbi/Makefile.am b/plugins/omlibdbi/Makefile.am
new file mode 100644
index 0000000..144dd66
--- /dev/null
+++ b/plugins/omlibdbi/Makefile.am
@@ -0,0 +1,12 @@
+pkglib_LTLIBRARIES = omlibdbi.la
+
+if LIBDBI_USE_DUMMY
+omlibdbi_la_SOURCES = dummy.c
+omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) -D MODNAME=omlibdbi
+omlibdbi_la_LDFLAGS = -module -avoid-version
+else
+omlibdbi_la_SOURCES = omlibdbi.c
+omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(LIBDBI_CFLAGS) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omlibdbi_la_LDFLAGS = -module -avoid-version
+omlibdbi_la_LIBADD = $(LIBDBI_LIBS)
+endif
diff --git a/plugins/omlibdbi/Makefile.in b/plugins/omlibdbi/Makefile.in
new file mode 100644
index 0000000..365e087
--- /dev/null
+++ b/plugins/omlibdbi/Makefile.in
@@ -0,0 +1,815 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omlibdbi
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@LIBDBI_USE_DUMMY_FALSE@omlibdbi_la_DEPENDENCIES = \
+@LIBDBI_USE_DUMMY_FALSE@ $(am__DEPENDENCIES_1)
+am__omlibdbi_la_SOURCES_DIST = omlibdbi.c dummy.c
+@LIBDBI_USE_DUMMY_FALSE@am_omlibdbi_la_OBJECTS = \
+@LIBDBI_USE_DUMMY_FALSE@ omlibdbi_la-omlibdbi.lo
+@LIBDBI_USE_DUMMY_TRUE@am_omlibdbi_la_OBJECTS = omlibdbi_la-dummy.lo
+omlibdbi_la_OBJECTS = $(am_omlibdbi_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 =
+omlibdbi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omlibdbi_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omlibdbi_la-dummy.Plo \
+ ./$(DEPDIR)/omlibdbi_la-omlibdbi.Plo
+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 = $(omlibdbi_la_SOURCES)
+DIST_SOURCES = $(am__omlibdbi_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omlibdbi.la
+@LIBDBI_USE_DUMMY_FALSE@omlibdbi_la_SOURCES = omlibdbi.c
+@LIBDBI_USE_DUMMY_TRUE@omlibdbi_la_SOURCES = dummy.c
+@LIBDBI_USE_DUMMY_FALSE@omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(LIBDBI_CFLAGS) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+@LIBDBI_USE_DUMMY_TRUE@omlibdbi_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) -D MODNAME=omlibdbi
+@LIBDBI_USE_DUMMY_FALSE@omlibdbi_la_LDFLAGS = -module -avoid-version
+@LIBDBI_USE_DUMMY_TRUE@omlibdbi_la_LDFLAGS = -module -avoid-version
+@LIBDBI_USE_DUMMY_FALSE@omlibdbi_la_LIBADD = $(LIBDBI_LIBS)
+all: 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) --gnu plugins/omlibdbi/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omlibdbi/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omlibdbi.la: $(omlibdbi_la_OBJECTS) $(omlibdbi_la_DEPENDENCIES) $(EXTRA_omlibdbi_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omlibdbi_la_LINK) -rpath $(pkglibdir) $(omlibdbi_la_OBJECTS) $(omlibdbi_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omlibdbi_la-dummy.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omlibdbi_la-omlibdbi.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omlibdbi_la-omlibdbi.lo: omlibdbi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omlibdbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omlibdbi_la-omlibdbi.lo -MD -MP -MF $(DEPDIR)/omlibdbi_la-omlibdbi.Tpo -c -o omlibdbi_la-omlibdbi.lo `test -f 'omlibdbi.c' || echo '$(srcdir)/'`omlibdbi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omlibdbi_la-omlibdbi.Tpo $(DEPDIR)/omlibdbi_la-omlibdbi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omlibdbi.c' object='omlibdbi_la-omlibdbi.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) $(omlibdbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omlibdbi_la-omlibdbi.lo `test -f 'omlibdbi.c' || echo '$(srcdir)/'`omlibdbi.c
+
+omlibdbi_la-dummy.lo: dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omlibdbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omlibdbi_la-dummy.lo -MD -MP -MF $(DEPDIR)/omlibdbi_la-dummy.Tpo -c -o omlibdbi_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omlibdbi_la-dummy.Tpo $(DEPDIR)/omlibdbi_la-dummy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='omlibdbi_la-dummy.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) $(omlibdbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omlibdbi_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omlibdbi_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/omlibdbi_la-omlibdbi.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omlibdbi_la-dummy.Plo
+ -rm -f ./$(DEPDIR)/omlibdbi_la-omlibdbi.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omlibdbi/dummy.c b/plugins/omlibdbi/dummy.c
new file mode 100644
index 0000000..fe8c249
--- /dev/null
+++ b/plugins/omlibdbi/dummy.c
@@ -0,0 +1,171 @@
+/* a dummy module to be loaded if we cannot build this module, but
+ * configure required it to be "optional".
+ *
+ * Copyright 2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+#define MODULE_NAME(x) #x
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME(MODULE_NAME(MODNAME))
+
+
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+typedef struct _instanceData {
+ char *dummy;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+struct modConfData_s {
+};
+
+/* modConf ptr to use for the current load process */
+static modConfData_t *loadModConf = NULL;
+/* modConf ptr to use for the current exec process */
+static modConfData_t *runModConf = NULL;
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINsetModCnf
+CODESTARTsetModCnf
+ (void) lst;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDsetModCnf
+
+
+BEGINnewActInst
+CODESTARTnewActInst
+ (void) pData;
+ (void) ppModData;
+ parser_errmsg("%s is an optional module which could not be built on your platform "
+ "please remove it from the configuration or upgrade your platform", MODULE_NAME(MODNAME));
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void) pMsgData;
+ENDdoAction
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ /* we only support the current interface specification */
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("dummy module compiled with rsyslog version %s.\n", VERSION);
+ENDmodInit
diff --git a/plugins/omlibdbi/omlibdbi.c b/plugins/omlibdbi/omlibdbi.c
new file mode 100644
index 0000000..5fd5df2
--- /dev/null
+++ b/plugins/omlibdbi/omlibdbi.c
@@ -0,0 +1,660 @@
+/* omlibdbi.c
+ * This is the implementation of the dbi output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * This depends on libdbi being present with the proper settings. Older
+ * versions do not necessarily have them. Please visit this bug tracker
+ * for details: http://bugzilla.adiscon.com/show_bug.cgi?id=31
+ *
+ * File begun on 2008-02-14 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2008-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <libgen.h>
+#include <dbi/dbi.h>
+#include "dirty.h"
+#include "syslogd-types.h"
+#include "cfsysline.h"
+#include "conf.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "debug.h"
+#include "errmsg.h"
+#include "conf.h"
+
+#undef HAVE_DBI_TXSUPP
+/* transaction support disabled in v8 -- TODO: reenable */
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omlibdbi")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+static int bDbiInitialized = 0; /* dbi_initialize() can only be called one - this keeps track of it */
+
+typedef struct _instanceData {
+ uchar *dbiDrvrDir; /* where do the dbi drivers reside? */
+ dbi_conn conn; /* handle to database */
+ uchar *drvrName; /* driver to use */
+ uchar *host; /* host to connect to */
+ uchar *usrName; /* user name for connect */
+ uchar *pwd; /* password for connect */
+ uchar *dbName; /* database to use */
+ unsigned uLastDBErrno; /* last errno returned by libdbi or 0 if all is well */
+ uchar *tplName; /* format template to use */
+ int txSupport; /* transaction support */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar *dbiDrvrDir; /* global: where do the dbi drivers reside? */
+ uchar *drvrName; /* driver to use */
+ uchar *host; /* host to connect to */
+ uchar *usrName; /* user name for connect */
+ uchar *pwd; /* password for connect */
+ uchar *dbName; /* database to use */
+} configSettings_t;
+static configSettings_t cs;
+static uchar *pszFileDfltTplName; /* name of the default template to use */
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *dbiDrvrDir; /* where do the dbi drivers reside? */
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+ { "driverdirectory", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 1 },
+ { "db", eCmdHdlrGetWord, 1 },
+ { "uid", eCmdHdlrGetWord, 1 },
+ { "pwd", eCmdHdlrGetWord, 1 },
+ { "driver", eCmdHdlrGetWord, 1 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(pszFileDfltTplName == NULL)
+ return (uchar*)" StdDBFmt";
+ else
+ return pszFileDfltTplName;
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.dbiDrvrDir = NULL;
+ cs.drvrName = NULL;
+ cs.host = NULL;
+ cs.usrName = NULL;
+ cs.pwd = NULL;
+ cs.dbName = NULL;
+ENDinitConfVars
+
+
+/* config settings */
+#ifdef HAVE_DBI_R
+static dbi_inst dbiInst;
+#endif
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* we do not like repeated message reduction inside the database */
+ENDisCompatibleWithFeature
+
+
+/* The following function is responsible for closing a
+ * database connection.
+ */
+static void closeConn(instanceData *pData)
+{
+ assert(pData != NULL);
+ if(pData->conn != NULL) { /* just to be on the safe side... */
+ dbi_conn_close(pData->conn);
+ pData->conn = NULL;
+ }
+}
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->drvrName);
+ free(pData->host);
+ free(pData->usrName);
+ free(pData->pwd);
+ free(pData->dbName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ closeConn(pWrkrData->pData);
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ENDdbgPrintInstInfo
+
+
+/* log a database error with descriptive message.
+ * We check if we have a valid database handle. If not, we simply
+ * report an error, but can not be specific. RGerhards, 2007-01-30
+ */
+static void
+reportDBError(instanceData *pData, int bSilent)
+{
+ unsigned uDBErrno;
+ char errMsg[1024];
+ const char *pszDbiErr;
+
+ assert(pData != NULL);
+
+ /* output log message */
+ errno = 0;
+ if(pData->conn == NULL) {
+ LogError(0, NO_ERRCODE, "unknown DB error occurred - could not obtain connection handle");
+ } else { /* we can ask dbi for the error description... */
+ uDBErrno = dbi_conn_error(pData->conn, &pszDbiErr);
+ snprintf(errMsg, sizeof(errMsg), "db error (%d): %s\n", uDBErrno, pszDbiErr);
+ if(bSilent || uDBErrno == pData->uLastDBErrno)
+ dbgprintf("libdbi, DBError(silent): %s\n", errMsg);
+ else {
+ pData->uLastDBErrno = uDBErrno;
+ LogError(0, NO_ERRCODE, "%s", errMsg);
+ }
+ }
+
+}
+
+
+/* The following function is responsible for initializing a connection
+ */
+static rsRetVal initConn(instanceData *pData, int bSilent)
+{
+ DEFiRet;
+ int iDrvrsLoaded;
+
+ assert(pData != NULL);
+ assert(pData->conn == NULL);
+
+ if(bDbiInitialized == 0) {
+ /* we need to init libdbi first */
+# ifdef HAVE_DBI_R
+ iDrvrsLoaded = dbi_initialize_r((char*) pData->dbiDrvrDir, &dbiInst);
+# else
+ iDrvrsLoaded = dbi_initialize((char*) pData->dbiDrvrDir);
+# endif
+ if(iDrvrsLoaded == 0) {
+ LogError(0, RS_RET_SUSPENDED, "libdbi error: libdbi or libdbi drivers not "
+ "present on this system - suspending.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else if(iDrvrsLoaded < 0) {
+ LogError(0, RS_RET_SUSPENDED, "libdbi error: libdbi could not be "
+ "initialized (do you have any dbi drivers installed?) - suspending.");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ bDbiInitialized = 1; /* we are done for the rest of our existence... */
+ }
+
+# ifdef HAVE_DBI_R
+ pData->conn = dbi_conn_new_r((char*)pData->drvrName, dbiInst);
+# else
+ pData->conn = dbi_conn_new((char*)pData->drvrName);
+# endif
+ if(pData->conn == NULL) {
+ LogError(0, RS_RET_SUSPENDED, "can not initialize libdbi connection");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else { /* we could get the handle, now on with work... */
+ /* Connect to database */
+ dbi_conn_set_option(pData->conn, "host", (char*) pData->host);
+ dbi_conn_set_option(pData->conn, "username", (char*) pData->usrName);
+
+ /* libdbi-driver-sqlite(2/3) requires to provide sqlite3_db dir which is absolute
+ path, where database file lives,
+ * and dbname, which is database file name itself. So in order to keep the config API unchanged,
+ * we split the dbname to path and filename.
+ */
+ int is_sqlite2 = !strcmp((const char *)pData->drvrName, "sqlite");
+ int is_sqlite3 = !strcmp((const char *)pData->drvrName, "sqlite3");
+ if(is_sqlite2 || is_sqlite3) {
+ char *const dn_org = strdup((char*)pData->dbName);
+ char *const dn = dirname(dn_org);
+ dbi_conn_set_option(pData->conn, is_sqlite3 ? "sqlite3_dbdir" : "sqlite_dbdir",dn);
+ free(dn_org); /* Free original buffer - dirname may return different pointer */
+
+ char *tmp = strdup((char*)pData->dbName);
+ char *bn = basename(tmp);
+ dbi_conn_set_option(pData->conn, "dbname", bn);
+ free(tmp);
+ } else {
+ dbi_conn_set_option(pData->conn, "dbname", (char*) pData->dbName);
+ }
+ if(pData->pwd != NULL)
+ dbi_conn_set_option(pData->conn, "password", (char*) pData->pwd);
+ if(dbi_conn_connect(pData->conn) < 0) {
+ reportDBError(pData, bSilent);
+ closeConn(pData); /* ignore any error we may get */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ pData->txSupport = dbi_conn_cap_get(pData->conn, "transaction_support");
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* The following function writes the current log entry
+ * to an established database connection.
+ */
+static rsRetVal
+writeDB(const uchar *psz, instanceData *const __restrict__ pData)
+{
+ DEFiRet;
+ dbi_result dbiRes = NULL;
+
+ assert(psz != NULL);
+ assert(pData != NULL);
+
+ /* see if we are ready to proceed */
+ if(pData->conn == NULL) {
+ CHKiRet(initConn(pData, 0));
+ }
+
+ /* try insert */
+ if((dbiRes = dbi_conn_query(pData->conn, (const char*)psz)) == NULL) {
+ /* error occurred, try to re-init connection and retry */
+ closeConn(pData); /* close the current handle */
+ CHKiRet(initConn(pData, 0)); /* try to re-open */
+ if((dbiRes = dbi_conn_query(pData->conn, (const char*)psz)) == NULL) { /* re-try insert */
+ /* we failed, giving up for now */
+ reportDBError(pData, 0);
+ closeConn(pData); /* free ressources */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ pData->uLastDBErrno = 0; /* reset error for error supression */
+ }
+
+ if(dbiRes != NULL)
+ dbi_result_free(dbiRes);
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ if(pWrkrData->pData->conn == NULL) {
+ iRet = initConn(pWrkrData->pData, 1);
+ }
+ENDtryResume
+
+/* transaction support 2013-03 */
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ if(pWrkrData->pData->conn == NULL) {
+ CHKiRet(initConn(pWrkrData->pData, 0));
+ }
+# ifdef HAVE_DBI_TXSUPP
+ if (pData->txSupport == 1) {
+ if (dbi_conn_transaction_begin(pData->conn) != 0) {
+ const char *emsg;
+ dbi_conn_error(pData->conn, &emsg);
+ dbgprintf("libdbi server error: begin transaction "
+ "not successful: %s\n", emsg);
+ closeConn(pData);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+# endif
+finalize_it:
+ENDbeginTransaction
+/* end transaction */
+
+BEGINdoAction
+CODESTARTdoAction
+ pthread_mutex_lock(&mutDoAct);
+ CHKiRet(writeDB(ppString[0], pWrkrData->pData));
+# ifdef HAVE_DBI_TXSUPP
+ if (pData->txSupport == 1) {
+ iRet = RS_RET_DEFER_COMMIT;
+ }
+# endif
+finalize_it:
+ pthread_mutex_unlock(&mutDoAct);
+ENDdoAction
+
+/* transaction support 2013-03 */
+BEGINendTransaction
+CODESTARTendTransaction
+# ifdef HAVE_DBI_TXSUPP
+ if (dbi_conn_transaction_commit(pData->conn) != 0) {
+ const char *emsg;
+ dbi_conn_error(pData->conn, &emsg);
+ dbgprintf("libdbi server error: transaction not committed: %s\n",
+ emsg);
+ closeConn(pData);
+ iRet = RS_RET_SUSPENDED;
+ }
+# endif
+ENDendTransaction
+/* end transaction */
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ bLegacyCnfModGlobalsPermitted = 1;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "omlibdbi: error processing "
+ "module config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omlibdbi:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pszFileDfltTplName != NULL) {
+ LogError(0, RS_RET_DUP_PARAM, "omlibdbi: warning: default template "
+ "was already set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "driverdirectory")) {
+ loadModConf->dbiDrvrDir = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omlibdbi: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+ bLegacyCnfModGlobalsPermitted = 0;
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.dbiDrvrDir);
+ free(cs.drvrName);
+ free(cs.host);
+ free(cs.usrName);
+ free(cs.pwd);
+ free(cs.dbName);
+ cs.dbiDrvrDir = NULL;
+ cs.drvrName = NULL;
+ cs.host = NULL;
+ cs.usrName = NULL;
+ cs.pwd = NULL;
+ cs.dbName = NULL;
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ free(pModConf->dbiDrvrDir);
+ENDfreeCnf
+
+
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplToUse;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ pData->host = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "db")) {
+ pData->dbName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "uid")) {
+ pData->usrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ pData->pwd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "driver")) {
+ pData->drvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omlibdbi: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ tplToUse = (pData->tplName == NULL) ? (uchar*)strdup((char*)getDfltTpl()) : pData->tplName;
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_RQD_TPL_OPT_SQL));
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(!strncmp((char*) p, ":omlibdbi:", sizeof(":omlibdbi:") - 1)) {
+ p += sizeof(":omlibdbi:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ CHKiRet(createInstance(&pData));
+ /* no create the instance based on what we currently have */
+ if(cs.drvrName == NULL) {
+ LogError(0, RS_RET_NO_DRIVERNAME, "omlibdbi: no db driver name given - action can not "
+ "be created");
+ ABORT_FINALIZE(RS_RET_NO_DRIVERNAME);
+ }
+
+ if((pData->drvrName = (uchar*) strdup((char*)cs.drvrName)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ /* NULL values are supported because drivers have different needs.
+ * They will err out on connect. -- rgerhards, 2008-02-15
+ */
+ if(cs.host != NULL)
+ CHKmalloc(pData->host = (uchar*) strdup((char*)cs.host));
+ if(cs.usrName != NULL)
+ CHKmalloc(pData->usrName = (uchar*) strdup((char*)cs.usrName));
+ if(cs.dbName != NULL)
+ CHKmalloc(pData->dbName = (uchar*) strdup((char*)cs.dbName));
+ if(cs.pwd != NULL)
+ CHKmalloc(pData->pwd = (uchar*) strdup((char*)cs.pwd));
+ if(cs.dbiDrvrDir != NULL)
+ CHKmalloc(loadModConf->dbiDrvrDir = (uchar*) strdup((char*)cs.dbiDrvrDir));
+ iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, getDfltTpl());
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* if we initialized libdbi, we now need to cleanup */
+ if(bDbiInitialized) {
+# ifdef HAVE_DBI_R
+ dbi_shutdown_r(dbiInst);
+# else
+ dbi_shutdown();
+# endif
+ }
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ free(cs.dbiDrvrDir);
+ cs.dbiDrvrDir = NULL;
+ free(cs.drvrName);
+ cs.drvrName = NULL;
+ free(cs.host);
+ cs.host = NULL;
+ free(cs.usrName);
+ cs.usrName = NULL;
+ free(cs.pwd);
+ cs.pwd = NULL;
+ free(cs.dbName);
+ cs.dbName = NULL;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+# ifndef HAVE_DBI_TXSUPP
+ DBGPRINTF("omlibdbi: no transaction support in libdbi\n");
+# endif
+ CHKiRet(regCfSysLineHdlr2((uchar *)"actionlibdbidriverdirectory", 0, eCmdHdlrGetWord, NULL, &cs.dbiDrvrDir,
+ STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionlibdbidriver", 0, eCmdHdlrGetWord, NULL, &cs.drvrName,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionlibdbihost", 0, eCmdHdlrGetWord, NULL, &cs.host,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionlibdbiusername", 0, eCmdHdlrGetWord, NULL, &cs.usrName,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionlibdbipassword", 0, eCmdHdlrGetWord, NULL, &cs.pwd,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionlibdbidbname", 0, eCmdHdlrGetWord, NULL, &cs.dbName,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ DBGPRINTF("omlibdbi compiled with version %s loaded, libdbi version %s\n", VERSION, dbi_version());
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am
new file mode 100644
index 0000000..97c9296
--- /dev/null
+++ b/plugins/ommail/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = ommail.la
+
+ommail_la_SOURCES = ommail.c
+ommail_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ommail_la_LDFLAGS = -module -avoid-version
+ommail_la_LIBADD =
diff --git a/plugins/ommail/Makefile.in b/plugins/ommail/Makefile.in
new file mode 100644
index 0000000..a352aab
--- /dev/null
+++ b/plugins/ommail/Makefile.in
@@ -0,0 +1,796 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/ommail
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+ommail_la_DEPENDENCIES =
+am_ommail_la_OBJECTS = ommail_la-ommail.lo
+ommail_la_OBJECTS = $(am_ommail_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 =
+ommail_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ommail_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/ommail_la-ommail.Plo
+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 = $(ommail_la_SOURCES)
+DIST_SOURCES = $(ommail_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = ommail.la
+ommail_la_SOURCES = ommail.c
+ommail_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ommail_la_LDFLAGS = -module -avoid-version
+ommail_la_LIBADD =
+all: 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) --gnu plugins/ommail/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/ommail/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+ommail.la: $(ommail_la_OBJECTS) $(ommail_la_DEPENDENCIES) $(EXTRA_ommail_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(ommail_la_LINK) -rpath $(pkglibdir) $(ommail_la_OBJECTS) $(ommail_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ommail_la-ommail.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+ommail_la-ommail.lo: ommail.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ommail_la-ommail.lo -MD -MP -MF $(DEPDIR)/ommail_la-ommail.Tpo -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ommail_la-ommail.Tpo $(DEPDIR)/ommail_la-ommail.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ommail.c' object='ommail_la-ommail.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) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/ommail_la-ommail.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/ommail_la-ommail.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/ommail/ommail.c b/plugins/ommail/ommail.c
new file mode 100644
index 0000000..746e516
--- /dev/null
+++ b/plugins/ommail/ommail.c
@@ -0,0 +1,902 @@
+/* ommail.c
+ *
+ * This is an implementation of a mail sending output module. So far, we
+ * only support direct SMTP, that is talking to a SMTP server. In the long
+ * term, support for using sendmail should also be implemented. Please note
+ * that the SMTP protocol implementation is a very bare one. We support
+ * RFC821/822 messages, without any authentication and any other nice
+ * features (no MIME, no nothing). It is assumed that proper firewalling
+ * and/or STMP server configuration is used together with this module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2008-04-04 by RGerhards
+ *
+ * Copyright 2008-2014 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "datetime.h"
+#include "glbl.h"
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ommail")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+
+/* we add a little support for multiple recipients. We do this via a
+ * singly-linked list, enqueued from the top. -- rgerhards, 2008-08-04
+ */
+typedef struct toRcpt_s toRcpt_t;
+struct toRcpt_s {
+ uchar *pszTo;
+ toRcpt_t *pNext;
+};
+
+typedef struct _instanceData {
+ uchar *tplName; /* format template to use */
+ uchar *constSubject; /* if non-NULL, constant string to be used as subject */
+ int8_t iMode; /* 0 - smtp, 1 - sendmail */
+ sbool bHaveSubject; /* is a subject configured? (if so, it is the second string provided by rsyslog core) */
+ sbool bEnableBody; /* is a body configured? (if so, it is the second string provided by rsyslog core) */
+ union {
+ struct {
+ uchar *pszSrv;
+ uchar *pszSrvPort;
+ uchar *pszFrom;
+ toRcpt_t *lstRcpt;
+ } smtp;
+ } md; /* mode-specific data */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ union {
+ struct {
+ char RcvBuf[1024]; /* buffer for receiving server responses */
+ size_t lenRcvBuf;
+ size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */
+ int sock; /* socket to this server (most important when we do multiple msgs per mail) */
+ } smtp;
+ } md; /* mode-specific data */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ toRcpt_t *lstRcpt;
+ uchar *pszSrv;
+ uchar *pszSrvPort;
+ uchar *pszFrom;
+ uchar *pszSubject;
+ int bEnableBody; /* should a mail body be generated? (set to 0 eg for SMS gateways) */
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "port", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "mailfrom", eCmdHdlrGetWord, CNFPARAM_REQUIRED },
+ { "mailto", eCmdHdlrArray, CNFPARAM_REQUIRED },
+ { "subject.template", eCmdHdlrGetWord, 0 },
+ { "subject.text", eCmdHdlrString, 0 },
+ { "body.enable", eCmdHdlrBinary, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.lstRcpt = NULL;
+ cs.pszSrv = NULL;
+ cs.pszSrvPort = NULL;
+ cs.pszFrom = NULL;
+ cs.pszSubject = NULL;
+ cs.bEnableBody = 1; /* should a mail body be generated? (set to 0 eg for SMS gateways) */
+ENDinitConfVars
+
+/* forward definitions (as few as possible) */
+static rsRetVal Send(int sock, const char *msg, size_t len);
+static rsRetVal readResponse(wrkrInstanceData_t *pWrkrData, int *piState, int iExpected);
+
+
+/* helpers for handling the recipient lists */
+
+/* destroy a complete recipient list */
+static void lstRcptDestruct(toRcpt_t *pRoot)
+{
+ toRcpt_t *pDel;
+
+ while(pRoot != NULL) {
+ pDel = pRoot;
+ pRoot = pRoot->pNext;
+ /* ready to disalloc */
+ free(pDel->pszTo);
+ free(pDel);
+ }
+}
+
+
+/* This function adds a recipient to the specified list.
+ * The recipient address storage is handed over -- the caller must NOT delete it.
+ */
+static rsRetVal
+addRcpt(toRcpt_t **ppLstRcpt, uchar *newRcpt)
+{
+ DEFiRet;
+ toRcpt_t *pNew = NULL;
+
+ CHKmalloc(pNew = calloc(1, sizeof(toRcpt_t)));
+
+ pNew->pszTo = newRcpt;
+ pNew->pNext = *ppLstRcpt;
+ *ppLstRcpt = pNew;
+
+ DBGPRINTF("ommail::addRcpt adds recipient %s\n", newRcpt);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(pNew);
+ free(newRcpt); /* in any case, this is no longer needed */
+ }
+
+ RETiRet;
+}
+
+/* This function is called when a new recipient email address is to be
+ * added. rgerhards, 2008-08-04
+ */
+static rsRetVal
+legacyConfAddRcpt(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ return addRcpt(&cs.lstRcpt, pNewVal);
+}
+
+
+/* output the recipient list to the mail server
+ * iStatusToCheck < 0 means no checking should happen
+ */
+static rsRetVal
+WriteRcpts(wrkrInstanceData_t *pWrkrData, uchar *pszOp, size_t lenOp, int iStatusToCheck)
+{
+ toRcpt_t *pRcpt;
+ int iState;
+ DEFiRet;
+
+ assert(lenOp != 0);
+
+ for(pRcpt = pWrkrData->pData->md.smtp.lstRcpt ; pRcpt != NULL ; pRcpt = pRcpt->pNext) {
+ DBGPRINTF("Sending '%s: <%s>'\n", pszOp, pRcpt->pszTo);
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pszOp, lenOp));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ":<", sizeof(":<") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pRcpt->pszTo, strlen((char*)pRcpt->pszTo)));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ if(iStatusToCheck >= 0)
+ CHKiRet(readResponse(pWrkrData, &iState, iStatusToCheck));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* output the recipient list in rfc2822 format
+ */
+static rsRetVal
+WriteTos(wrkrInstanceData_t *pWrkrData, uchar *pszOp, size_t lenOp)
+{
+ toRcpt_t *pRcpt;
+ int iTos;
+ DEFiRet;
+
+ assert(lenOp != 0);
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pszOp, lenOp));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ": ", sizeof(": ") - 1));
+
+ for(pRcpt = pWrkrData->pData->md.smtp.lstRcpt, iTos = 0; pRcpt != NULL ; pRcpt = pRcpt->pNext, iTos++) {
+ DBGPRINTF("Sending '%s: <%s>'\n", pszOp, pRcpt->pszTo);
+ if(iTos)
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ", ", sizeof(", ") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "<", sizeof("<") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pRcpt->pszTo, strlen((char*)pRcpt->pszTo)));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ">", sizeof(">") - 1));
+ }
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
+
+finalize_it:
+ RETiRet;
+}
+/* end helpers for handling the recipient lists */
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->constSubject = NULL;
+ pData->bEnableBody = 1;
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ if(pData->iMode == 0) {
+ free(pData->md.smtp.pszSrv);
+ free(pData->md.smtp.pszSrvPort);
+ free(pData->md.smtp.pszFrom);
+ lstRcptDestruct(pData->md.smtp.lstRcpt);
+ }
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("mail"); /* TODO: extend! */
+ENDdbgPrintInstInfo
+
+
+/* TCP support code, should probably be moved to net.c or some place else... -- rgerhards, 2008-04-04 */
+
+/* "receive" a character from the remote server. A single character
+ * is returned. Returns RS_RET_NO_MORE_DATA if the server has closed
+ * the connection and RS_RET_IO_ERROR if something goes wrong. This
+ * is a blocking read.
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+getRcvChar(wrkrInstanceData_t *pWrkrData, char *pC)
+{
+ DEFiRet;
+ ssize_t lenBuf;
+
+ if(pWrkrData->md.smtp.iRcvBuf == pWrkrData->md.smtp.lenRcvBuf) { /* buffer empty? */
+ /* yes, we need to read the next server response */
+ do {
+ lenBuf = recv(pWrkrData->md.smtp.sock, pWrkrData->md.smtp.RcvBuf,
+ sizeof(pWrkrData->md.smtp.RcvBuf), 0);
+ if(lenBuf == 0) {
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ } else if(lenBuf < 0) {
+ if(errno != EAGAIN) {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ } else {
+ /* good read */
+ pWrkrData->md.smtp.iRcvBuf = 0;
+ pWrkrData->md.smtp.lenRcvBuf = lenBuf;
+ }
+
+ } while(lenBuf < 1);
+ }
+
+ /* when we reach this point, we have a non-empty buffer */
+ *pC = pWrkrData->md.smtp.RcvBuf[pWrkrData->md.smtp.iRcvBuf++];
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* close the mail server connection
+ * rgerhards, 2008-04-08
+ */
+static rsRetVal
+serverDisconnect(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ assert(pWrkrData != NULL);
+
+ if(pWrkrData->md.smtp.sock != -1) {
+ close(pWrkrData->md.smtp.sock);
+ pWrkrData->md.smtp.sock = -1;
+ }
+
+ RETiRet;
+}
+
+
+/* open a connection to the mail server
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+serverConnect(wrkrInstanceData_t *pWrkrData)
+{
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+ const char *smtpPort;
+ const char *smtpSrv;
+ char errStr[1024];
+ instanceData *pData;
+ DEFiRet;
+
+ pData = pWrkrData->pData;
+
+ if(pData->md.smtp.pszSrv == NULL)
+ smtpSrv = "127.0.0.1";
+ else
+ smtpSrv = (char*)pData->md.smtp.pszSrv;
+
+ if(pData->md.smtp.pszSrvPort == NULL)
+ smtpPort = "25";
+ else
+ smtpPort = (char*)pData->md.smtp.pszSrvPort;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo(smtpSrv, smtpPort, &hints, &res) != 0) {
+ DBGPRINTF("error %d in getaddrinfo\n", errno);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if((pWrkrData->md.smtp.sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ DBGPRINTF("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if(connect(pWrkrData->md.smtp.sock, res->ai_addr, res->ai_addrlen) != 0) {
+ DBGPRINTF("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(pWrkrData->md.smtp.sock != -1) {
+ close(pWrkrData->md.smtp.sock);
+ pWrkrData->md.smtp.sock = -1;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* send text to the server, blocking send */
+static rsRetVal
+Send(const int sock, const char *const __restrict__ msg, const size_t len)
+{
+ DEFiRet;
+ size_t offsBuf = 0;
+ ssize_t lenSend;
+
+ assert(msg != NULL);
+
+ if(len == 0) /* it's valid, but does not make much sense ;) */
+ FINALIZE;
+
+ do {
+ lenSend = send(sock, msg + offsBuf, len - offsBuf, 0);
+ if(lenSend == -1) {
+ if(errno != EAGAIN) {
+ DBGPRINTF("message not (smtp/tcp)send, errno %d", errno);
+ ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR);
+ }
+ } else if(lenSend != (ssize_t) (len - offsBuf)) {
+ offsBuf += lenSend; /* on to next round... */
+ } else {
+ FINALIZE;
+ }
+ } while(1);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* send body text to the server, blocking send
+ * The body is special in that we must escape a leading dot inside a line
+ */
+static rsRetVal
+bodySend(wrkrInstanceData_t *pWrkrData, char *msg, size_t len)
+{
+ DEFiRet;
+ char szBuf[2048];
+ size_t iSrc;
+ size_t iBuf = 0;
+ int bHadCR = 0;
+ int bInStartOfLine = 1;
+
+ assert(pWrkrData != NULL);
+ assert(msg != NULL);
+
+ for(iSrc = 0 ; iSrc < len ; ++iSrc) {
+ if(iBuf >= sizeof(szBuf) - 1) { /* one is reserved for our extra dot */
+ CHKiRet(Send(pWrkrData->md.smtp.sock, szBuf, iBuf));
+ iBuf = 0;
+ }
+ szBuf[iBuf++] = msg[iSrc];
+ switch(msg[iSrc]) {
+ case '\r':
+ bHadCR = 1;
+ break;
+ case '\n':
+ if(bHadCR)
+ bInStartOfLine = 1;
+ bHadCR = 0;
+ break;
+ case '.':
+ if(bInStartOfLine)
+ szBuf[iBuf++] = '.'; /* space is always reserved for this! */
+ /*FALLTHROUGH*/
+ default:
+ bInStartOfLine = 0;
+ bHadCR = 0;
+ break;
+ }
+ }
+
+ if(iBuf > 0) { /* incomplete buffer to send (the *usual* case)? */
+ CHKiRet(Send(pWrkrData->md.smtp.sock, szBuf, iBuf));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read response line from server
+ */
+static rsRetVal
+readResponseLn(wrkrInstanceData_t *pWrkrData, char *pLn, size_t lenLn, size_t *const __restrict__ respLen)
+{
+ DEFiRet;
+ size_t i = 0;
+ char c;
+
+ assert(pWrkrData != NULL);
+ assert(pLn != NULL);
+
+ do {
+ CHKiRet(getRcvChar(pWrkrData, &c));
+ if(c == '\n')
+ break;
+ if(i < (lenLn - 1)) /* if line is too long, we simply discard the rest */
+ pLn[i++] = c;
+ } while(1);
+ DBGPRINTF("smtp server response: %s\n", pLn);
+ /* do not remove, this is helpful in troubleshooting SMTP probs! */
+
+finalize_it:
+ pLn[i] = '\0';
+ *respLen = i;
+ RETiRet;
+}
+
+
+/* read numerical response code from server and compare it to requried response code.
+ * If they two don't match, return RS_RET_SMTP_ERROR.
+ * rgerhards, 2008-04-07
+ */
+static rsRetVal
+readResponse(wrkrInstanceData_t *pWrkrData, int *piState, int iExpected)
+{
+ DEFiRet;
+ int bCont;
+ char buf[128];
+ size_t respLen;
+
+ assert(pWrkrData != NULL);
+ assert(piState != NULL);
+
+ bCont = 1;
+ do {
+ CHKiRet(readResponseLn(pWrkrData, buf, sizeof(buf), &respLen));
+ if(respLen < 4) /* we treat too-short responses as error */
+ ABORT_FINALIZE(RS_RET_SMTP_ERROR);
+ if(buf[3] != '-') { /* last or only response line? */
+ bCont = 0;
+ *piState = buf[0] - '0';
+ *piState = *piState * 10 + buf[1] - '0';
+ *piState = *piState * 10 + buf[2] - '0';
+ if(*piState != iExpected)
+ ABORT_FINALIZE(RS_RET_SMTP_ERROR);
+ }
+ } while(bCont);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* create a timestamp suitable for use with the Date: SMTP body header
+ * rgerhards, 2008-04-08
+ */
+static void
+mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf)
+{
+ time_t tCurr;
+ struct tm tmCurr;
+ static const char szDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ static const char szMonth[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"};
+
+ datetime.GetTime(&tCurr);
+ gmtime_r(&tCurr, &tmCurr);
+ snprintf((char*)pszBuf, lenBuf, "Date: %s, %2d %s %4d %02d:%02d:%02d +0000\r\n", szDay[tmCurr.tm_wday],
+ tmCurr.tm_mday,
+ szMonth[tmCurr.tm_mon], 1900 + tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec);
+}
+
+
+/* send a message via SMTP
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+sendSMTP(wrkrInstanceData_t *pWrkrData, uchar *body, uchar *subject)
+{
+ DEFiRet;
+ int iState; /* SMTP state */
+ instanceData *pData;
+ uchar szDateBuf[64];
+
+ pData = pWrkrData->pData;
+
+ CHKiRet(serverConnect(pWrkrData));
+ CHKiRet(readResponse(pWrkrData, &iState, 220));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "HELO ", 5));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)glbl.GetLocalHostName(),
+ strlen((char*)glbl.GetLocalHostName())));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
+ CHKiRet(readResponse(pWrkrData, &iState, 250));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "MAIL FROM:<", sizeof("MAIL FROM:<") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom)));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ CHKiRet(readResponse(pWrkrData, &iState, 250));
+
+ CHKiRet(WriteRcpts(pWrkrData, (uchar*)"RCPT TO", sizeof("RCPT TO") - 1, 250));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1));
+ CHKiRet(readResponse(pWrkrData, &iState, 354));
+
+ /* now come the data part */
+ /* header */
+ mkSMTPTimestamp(szDateBuf, sizeof(szDateBuf));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)szDateBuf, strlen((char*)szDateBuf)));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "From: <", sizeof("From: <") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom)));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+
+ CHKiRet(WriteTos(pWrkrData, (uchar*)"To", sizeof("To") - 1));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, (char*)subject, strlen((char*)subject)));
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "X-Mailer: rsyslog-ommail\r\n",
+ sizeof("x-mailer: rsyslog-ommail\r\n") - 1));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */
+
+ /* body */
+ if(pData->bEnableBody)
+ CHKiRet(bodySend(pWrkrData, (char*)body, strlen((char*) body)));
+
+ /* end of data, back to envelope transaction */
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1));
+ CHKiRet(readResponse(pWrkrData, &iState, 250));
+
+ CHKiRet(Send(pWrkrData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1));
+ CHKiRet(readResponse(pWrkrData, &iState, 221));
+
+ /* we are finished, a new connection is created for each request, so let's close it now */
+ CHKiRet(serverDisconnect(pWrkrData));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* in tryResume we check if we can connect to the server in question. If that is OK,
+ * we close the connection without doing any actual SMTP transaction. It will be
+ * reopened during the actual send process. This may not be the best way to do it if
+ * there is a problem inside the SMTP transaction. However, we can't find that out without
+ * actually initiating something, and that would be bad. The logic here helps us
+ * correctly recover from an unreachable/down mail server, which is probably the majority
+ * of problem cases. For SMTP transaction problems, we will do lots of retries, but if it
+ * is a temporary problem, it will be fixed anyhow. So I consider this implementation to
+ * be clean enough, especially as I think other approaches have other weaknesses.
+ * rgerhards, 2008-04-08
+ */
+BEGINtryResume
+CODESTARTtryResume
+ CHKiRet(serverConnect(pWrkrData));
+ CHKiRet(serverDisconnect(pWrkrData)); /* if we fail, we will never reach this line */
+finalize_it:
+ if(iRet == RS_RET_IO_ERROR)
+ iRet = RS_RET_SUSPENDED;
+ENDtryResume
+
+
+BEGINdoAction
+ uchar *subject;
+ const instanceData *const __restrict__ pData = pWrkrData->pData;
+CODESTARTdoAction
+ DBGPRINTF("ommail doAction()\n");
+
+ if(pData->constSubject != NULL)
+ subject = pData->constSubject;
+ else if(pData->bHaveSubject)
+ subject = ppString[1];
+ else
+ subject = (uchar*)"message from rsyslog";
+
+ iRet = sendSMTP(pWrkrData, ppString[0], subject);
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("error sending mail, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ENDdoAction
+
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+ pData->constSubject = NULL;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplSubject = NULL;
+ int i, j;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ pData->md.smtp.pszSrv = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->md.smtp.pszSrvPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "mailfrom")) {
+ pData->md.smtp.pszFrom = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "mailto")) {
+ for(j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ addRcpt(&(pData->md.smtp.lstRcpt),
+ (uchar*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL));
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "subject.template")) {
+ if(pData->constSubject != NULL) {
+ parser_errmsg("ommail: only one of subject.template, subject.text "
+ "can be set");
+ ABORT_FINALIZE(RS_RET_DUP_PARAM);
+ }
+ tplSubject = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "subject.text")) {
+ if(tplSubject != NULL) {
+ parser_errmsg("ommail: only one of subject.template, subject.text "
+ "can be set");
+ ABORT_FINALIZE(RS_RET_DUP_PARAM);
+ }
+ pData->constSubject = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "body.enable")) {
+ pData->bEnableBody = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("ommail: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(tplSubject == NULL) {
+ /* if no subject is configured, we need just one template string */
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ } else {
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ pData->bHaveSubject = 1;
+ /* NOTE: tplSubject memory is *handed over* down here below - do NOT free() */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, tplSubject, OMSR_NO_RQD_TPL_OPTS));
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) strdup("RSYSLOG_FileFormat"),
+ OMSR_NO_RQD_TPL_OPTS));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup((char*) pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+ if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) {
+ p += sizeof(":ommail:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ FINALIZE;
+
+ /* TODO: check strdup() result */
+
+ if(cs.pszFrom == NULL) {
+ LogError(0, RS_RET_MAIL_NO_FROM, "no sender address given - specify $ActionMailFrom");
+ ABORT_FINALIZE(RS_RET_MAIL_NO_FROM);
+ }
+ if(cs.lstRcpt == NULL) {
+ LogError(0, RS_RET_MAIL_NO_TO, "no recipient address given - specify $ActionMailTo");
+ ABORT_FINALIZE(RS_RET_MAIL_NO_TO);
+ }
+
+ pData->md.smtp.pszFrom = (uchar*) strdup((char*)cs.pszFrom);
+ pData->md.smtp.lstRcpt = cs.lstRcpt; /* we "hand over" this memory */
+ cs.lstRcpt = NULL; /* note: this is different from pre-3.21.2 versions! */
+
+ if(cs.pszSubject == NULL) {
+ /* if no subject is configured, we need just one template string */
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ } else {
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ pData->bHaveSubject = 1;
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup((char*) cs.pszSubject), OMSR_NO_RQD_TPL_OPTS));
+ }
+ if(cs.pszSrv != NULL)
+ pData->md.smtp.pszSrv = (uchar*) strdup((char*)cs.pszSrv);
+ if(cs.pszSrvPort != NULL)
+ pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)cs.pszSrvPort);
+ pData->bEnableBody = cs.bEnableBody;
+
+ /* process template */
+ iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_FileFormat");
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Free string config variables and reset them to NULL (not necessarily the default!) */
+static rsRetVal freeConfigVariables(void)
+{
+ DEFiRet;
+
+ free(cs.pszSrv);
+ cs.pszSrv = NULL;
+ free(cs.pszSrvPort);
+ cs.pszSrvPort = NULL;
+ free(cs.pszFrom);
+ cs.pszFrom = NULL;
+ lstRcptDestruct(cs.lstRcpt);
+ cs.lstRcpt = NULL;
+
+ RETiRet;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* cleanup our allocations */
+ freeConfigVariables();
+
+ /* release what we no longer need */
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.bEnableBody = 1;
+ iRet = freeConfigVariables();
+ RETiRet;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* tell which objects we need */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("ommail version %s initializing\n", VERSION);
+
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &cs.pszSrv,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &cs.pszSrvPort,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &cs.pszFrom,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, legacyConfAddRcpt, NULL,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &cs.pszSubject,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailenablebody", 0, eCmdHdlrBinary, NULL, &cs.bEnableBody,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/ommongodb/Makefile.am b/plugins/ommongodb/Makefile.am
new file mode 100644
index 0000000..1193855
--- /dev/null
+++ b/plugins/ommongodb/Makefile.am
@@ -0,0 +1,7 @@
+pkglib_LTLIBRARIES = ommongodb.la
+ommongodb_la_SOURCES = ommongodb.c
+ommongodb_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS)
+ommongodb_la_LDFLAGS = -module -avoid-version
+ommongodb_la_LIBADD = $(LIBMONGOC_LIBS)
+
+EXTRA_DIST =
diff --git a/plugins/ommongodb/Makefile.in b/plugins/ommongodb/Makefile.in
new file mode 100644
index 0000000..8a94815
--- /dev/null
+++ b/plugins/ommongodb/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/ommongodb
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+ommongodb_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_ommongodb_la_OBJECTS = ommongodb_la-ommongodb.lo
+ommongodb_la_OBJECTS = $(am_ommongodb_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 =
+ommongodb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ommongodb_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/ommongodb_la-ommongodb.Plo
+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 = $(ommongodb_la_SOURCES)
+DIST_SOURCES = $(ommongodb_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = ommongodb.la
+ommongodb_la_SOURCES = ommongodb.c
+ommongodb_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS)
+ommongodb_la_LDFLAGS = -module -avoid-version
+ommongodb_la_LIBADD = $(LIBMONGOC_LIBS)
+EXTRA_DIST =
+all: 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) --gnu plugins/ommongodb/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/ommongodb/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+ommongodb.la: $(ommongodb_la_OBJECTS) $(ommongodb_la_DEPENDENCIES) $(EXTRA_ommongodb_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(ommongodb_la_LINK) -rpath $(pkglibdir) $(ommongodb_la_OBJECTS) $(ommongodb_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ommongodb_la-ommongodb.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+ommongodb_la-ommongodb.lo: ommongodb.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommongodb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ommongodb_la-ommongodb.lo -MD -MP -MF $(DEPDIR)/ommongodb_la-ommongodb.Tpo -c -o ommongodb_la-ommongodb.lo `test -f 'ommongodb.c' || echo '$(srcdir)/'`ommongodb.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ommongodb_la-ommongodb.Tpo $(DEPDIR)/ommongodb_la-ommongodb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ommongodb.c' object='ommongodb_la-ommongodb.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) $(ommongodb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ommongodb_la-ommongodb.lo `test -f 'ommongodb.c' || echo '$(srcdir)/'`ommongodb.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/ommongodb_la-ommongodb.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/ommongodb_la-ommongodb.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/ommongodb/README b/plugins/ommongodb/README
new file mode 100644
index 0000000..2390bef
--- /dev/null
+++ b/plugins/ommongodb/README
@@ -0,0 +1,48 @@
+plugin to use MongoDB as backend.
+
+tested in ubuntu 10.04, ubuntu 10.10 and FreeBSD 11.1
+
+configuration:
+
+in your /etc/rsyslog.conf, together with other modules:
+$ModLoad ommongodb # provides mongodb support
+*.* action(type="ommongodb" db="..." collection="..." template="...")
+
+Note: if no template is specified, a default schema will be used. That schema
+contains proper data types. However, if a template is specified, only strings
+are supported. This is a restriction of the rsyslog v6 core engine. This
+changed in v7.
+
+If templates are used, it is suggested to use list-based templates. Constants
+can ONLY be inserted with list-based templates, as only these provide the
+capability to specify a field name (outname parameter).
+
+A very basic example is:
+
+*.* action(type="ommongodb" db="logs" collection="syslog")
+
+A more complex example:
+*.* action(type="ommongodb" uristr="mongodb://vulture:9091,vulture2:9091/?replicaset=Vulture&ssl=true" ssl_cert="/var/db/mongodb/mongod.pem" ssl_ca="/var/db/mongodb/ca.pem" db="logs" collection="syslog" allowed_error_codes="11000")
+
+Please see the script clean-mongo-syslog for an example of how to
+purge old records from MongoDB using PyMongo. It can be run
+daily or weekly from cron.
+
+You may also wish to index some or all of the columns in MongoDB.
+The following statements may help to create the indexes:
+
+To see the existing indexes:
+
+ db.syslog.getIndexes()
+
+To create them:
+
+ db.syslog.ensureIndex( { sys : 1 } )
+ db.syslog.ensureIndex( { time : 1 } )
+ db.syslog.ensureIndex( { syslog_fac : 1 } )
+ db.syslog.ensureIndex( { syslog_sever : 1 } )
+ db.syslog.ensureIndex( { syslog_tag : 1 } )
+ db.syslog.ensureIndex( { procid : 1 } )
+ db.syslog.ensureIndex( { pid : 1 } )
+
+
diff --git a/plugins/ommongodb/ommongodb.c b/plugins/ommongodb/ommongodb.c
new file mode 100644
index 0000000..83f3656
--- /dev/null
+++ b/plugins/ommongodb/ommongodb.c
@@ -0,0 +1,786 @@
+/* ommongodb.c
+ * Output module for mongodb.
+ *
+ * Copyright 2007-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * Copyright 2017 Jeremie Jourdin and Hugo Soszynski and aDvens
+ * Remove deprecated libmongo-client and use libmongoc (mongo-c-driver)
+ * This new library handle TLS and replicaset
+ *
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdint.h>
+#include <time.h>
+#include <json.h>
+#include "rsyslog.h"
+/* we need this to avoid issues with older versions of libbson */
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wpragmas
+PRAGMA_IGNORE_Wunknown_warning_option
+PRAGMA_IGNORE_Wunknown_attribute
+PRAGMA_IGNORE_Wexpansion_to_defined
+PRAGMA_IGNORE_Wstrict_prototypes
+PRAGMA_IGNORE_Wold_style_definition
+#include <mongoc.h>
+#include <bson.h>
+PRAGMA_DIAGNOSTIC_POP
+
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "datetime.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "parserif.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ommongodb")
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
+
+typedef struct _instanceData {
+ struct json_tokener *json_tokener; /* only if (tplName != NULL) */
+ mongoc_client_t *client;
+ mongoc_collection_t *collection;
+ bson_error_t error;
+ char *server;
+ char *port;
+ char *uristr;
+ char *ssl_ca;
+ char *ssl_cert;
+ char *uid;
+ char *pwd;
+ uint32_t allowed_error_codes[256];
+ int allowed_error_codes_nbr;
+ char *db;
+ char *collection_name;
+ char *tplName;
+ int bErrMsgPermitted; /* only one errmsg permitted per connection */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 0 },
+ { "serverport", eCmdHdlrGetWord, 0 },
+ { "uristr", eCmdHdlrGetWord, 0 },
+ { "ssl_ca", eCmdHdlrGetWord, 0 },
+ { "ssl_cert", eCmdHdlrGetWord, 0 },
+ { "uid", eCmdHdlrGetWord, 0 },
+ { "pwd", eCmdHdlrGetWord, 0 },
+ { "db", eCmdHdlrGetWord, 0 },
+ { "collection", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "allowed_error_codes", eCmdHdlrArray, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* use this to specify if select features are supported by this
+ * plugin. If not, the framework will handle that. Currently, only
+ * RepeatedMsgReduction ("last message repeated n times") is optional.
+ */
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+static void closeMongoDB(instanceData *pData)
+{
+ if(pData->client != NULL) {
+ if (pData->collection != NULL) {
+ mongoc_collection_destroy (pData->collection);
+ pData->collection = NULL;
+ }
+ mongoc_client_destroy (pData->client);
+ pData->client = NULL;
+ mongoc_cleanup ();
+ DBGPRINTF("ommongodb: Mongodb connection closed.");
+ }
+}
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ closeMongoDB(pData);
+
+ if (pData->json_tokener != NULL)
+ json_tokener_free(pData->json_tokener);
+ free(pData->server);
+ free(pData->port);
+ free(pData->ssl_ca);
+ free(pData->ssl_cert);
+ free(pData->uristr);
+ free(pData->uid);
+ free(pData->pwd);
+ free(pData->db);
+ free(pData->collection_name);
+ free(pData->tplName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ (void)pData;
+ENDdbgPrintInstInfo
+
+
+/* report error that occurred during *last* operation
+ */
+static void
+reportMongoError(instanceData *pData)
+{
+ if(pData->bErrMsgPermitted) {
+ LogError(0, RS_RET_ERR, "ommongodb: error: %s", pData->error.message);
+ pData->bErrMsgPermitted = 0;
+ }
+}
+
+
+/* The following function is responsible for initializing a
+ * MongoDB connection.
+ * Initially added 2004-10-28 mmeckelein
+ * Improved to check if server is available (ping) @kguillemot 2021-06-30
+ */
+static rsRetVal initMongoDB(instanceData *pData, int bSilent)
+{
+ DEFiRet;
+ unsigned char retval;
+
+ DBGPRINTF("ommongodb: uristr is '%s'", pData->uristr);
+ mongoc_init ();
+ pData->client = mongoc_client_new (pData->uristr);
+ if (pData->ssl_cert && pData->ssl_ca) {
+#ifdef HAVE_MONGOC_CLIENT_SET_SSL_OPTS
+ mongoc_ssl_opt_t ssl_opts;
+ memset(&ssl_opts, 0, sizeof(mongoc_ssl_opt_t));
+ ssl_opts.pem_file = pData->ssl_cert;
+ ssl_opts.ca_file = pData->ssl_ca;
+ mongoc_client_set_ssl_opts (pData->client, &ssl_opts);
+#else
+ dbgprintf("ommongodb: mongo-c-driver was not built with SSL options, ssl directives will not be used.");
+#endif
+ }
+ if(!pData->client) {
+ if(!bSilent) {
+ reportMongoError(pData);
+ dbgprintf("ommongodb: can not initialize MongoDB handle");
+ }
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ pData->collection = mongoc_client_get_collection (pData->client, pData->db, pData->collection_name);
+
+ // Try to contact server
+ bson_t *command, reply;
+ bson_error_t error;
+ command = BCON_NEW ("ping", BCON_INT32 (1));
+ retval = mongoc_client_command_simple(pData->client, pData->db, command, NULL, &reply, &error);
+ bson_destroy(&reply);
+ bson_destroy(command);
+ if( !retval ) {
+ DBGPRINTF("ommongodb: ping server error (%u): %s \n", error.code, error.message);
+ closeMongoDB(pData);
+ reportMongoError(pData);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* map syslog severity to lumberjack level
+ * TODO: consider moving this to msg.c - make some dirty "friend" references...
+ * rgerhards, 2012-03-19
+ */
+static const char *
+getLumberjackLevel(short severity)
+{
+ switch(severity) {
+ case 0: return "FATAL";
+ case 1:
+ case 2:
+ case 3: return "ERROR";
+ case 4: return "WARN";
+ case 5:
+ case 6: return "INFO";
+ case 7: return "DEBUG";
+ default:DBGPRINTF("ommongodb: invalid syslog severity %u\n", severity);
+ return "INVLD";
+ }
+}
+
+
+/* small helper: get integer power of 10 */
+static int
+i10pow(int exp)
+{
+ int r = 1;
+ while(exp > 0) {
+ r *= 10;
+ exp--;
+ }
+ return r;
+}
+/* Return a BSON document when an user hasn't specified a template.
+ * In this mode, we use the standard document format, which is somewhat
+ * aligned to cee (as described in project lumberjack). Note that this is
+ * a moving target, so we may run out of sync (and stay so to retain
+ * backward compatibility, which we consider pretty important).
+ */
+static bson_t *getDefaultBSON(smsg_t *pMsg)
+{
+ bson_t *doc = NULL;
+ char *procid; short unsigned procid_free; rs_size_t procid_len;
+ char *tag; short unsigned tag_free; rs_size_t tag_len;
+ char *pid; short unsigned pid_free; rs_size_t pid_len;
+ char *sys; short unsigned sys_free; rs_size_t sys_len;
+ char *msg; short unsigned msg_free; rs_size_t msg_len;
+ int severity, facil;
+ int64 ts_gen, ts_rcv; /* timestamps: generated, received */
+ int secfrac;
+ msgPropDescr_t cProp; /* we use internal implementation knowledge... */
+
+ cProp.id = PROP_PROGRAMNAME;
+ procid = (char*)MsgGetProp(pMsg, NULL, &cProp, &procid_len, &procid_free, NULL);
+ cProp.id = PROP_SYSLOGTAG;
+ tag = (char*)MsgGetProp(pMsg, NULL, &cProp, &tag_len, &tag_free, NULL);
+ cProp.id = PROP_PROCID;
+ pid = (char*)MsgGetProp(pMsg, NULL, &cProp, &pid_len, &pid_free, NULL);
+ cProp.id = PROP_HOSTNAME;
+ sys = (char*)MsgGetProp(pMsg, NULL, &cProp, &sys_len, &sys_free, NULL);
+ cProp.id = PROP_MSG;
+ msg = (char*)MsgGetProp(pMsg, NULL, &cProp, &msg_len, &msg_free, NULL);
+
+ /* TODO: move to datetime? Refactor in any case! rgerhards, 2012-03-30 */
+ ts_gen = (int64) datetime.syslogTime2time_t(&pMsg->tTIMESTAMP) * 1000; /* ms! */
+ DBGPRINTF("ommongodb: ts_gen is %lld\n", (long long) ts_gen);
+ DBGPRINTF("ommongodb: secfrac is %d, precision %d\n",
+ pMsg->tTIMESTAMP.secfrac,
+ pMsg->tTIMESTAMP.secfracPrecision);
+ if(pMsg->tTIMESTAMP.secfracPrecision > 3) {
+ secfrac = pMsg->tTIMESTAMP.secfrac / i10pow(pMsg->tTIMESTAMP.secfracPrecision - 3);
+ } else if(pMsg->tTIMESTAMP.secfracPrecision < 3) {
+ secfrac = pMsg->tTIMESTAMP.secfrac * i10pow(3 - pMsg->tTIMESTAMP.secfracPrecision);
+ } else {
+ secfrac = pMsg->tTIMESTAMP.secfrac;
+ }
+ ts_gen += secfrac;
+ ts_rcv = (int64) datetime.syslogTime2time_t(&pMsg->tRcvdAt) * 1000; /* ms! */
+ if(pMsg->tRcvdAt.secfracPrecision > 3) {
+ secfrac = pMsg->tRcvdAt.secfrac / i10pow(pMsg->tRcvdAt.secfracPrecision - 3);
+ } else if(pMsg->tRcvdAt.secfracPrecision < 3) {
+ secfrac = pMsg->tRcvdAt.secfrac * i10pow(3 - pMsg->tRcvdAt.secfracPrecision);
+ } else {
+ secfrac = pMsg->tRcvdAt.secfrac;
+ }
+ ts_rcv += secfrac;
+
+ /* the following need to be int, but are short, so we need to xlat */
+ severity = pMsg->iSeverity;
+ facil = pMsg->iFacility;
+
+ doc = bson_new ();
+ bson_oid_t oid;
+ bson_oid_init (&oid, NULL);
+ BSON_APPEND_OID (doc, "_id", &oid);
+ BSON_APPEND_UTF8 (doc, "sys", sys);
+ BSON_APPEND_DATE_TIME (doc, "time", ts_gen);
+ BSON_APPEND_DATE_TIME (doc, "time_rcvd", ts_rcv);
+ BSON_APPEND_UTF8 (doc, "msg", msg);
+ BSON_APPEND_INT32 (doc, "syslog_fac", facil);
+ BSON_APPEND_INT32 (doc, "syslog_sever", severity);
+ BSON_APPEND_UTF8 (doc, "syslog_tag", tag);
+ BSON_APPEND_UTF8 (doc, "procid", procid);
+ BSON_APPEND_UTF8 (doc, "pid", pid);
+ BSON_APPEND_UTF8 (doc, "level", getLumberjackLevel(pMsg->iSeverity));
+
+ if(procid_free) free(procid);
+ if(tag_free) free(tag);
+ if(pid_free) free(pid);
+ if(sys_free) free(sys);
+ if(msg_free) free(msg);
+
+ return doc;
+}
+
+static bson_t *BSONFromJSONArray(struct json_object *json);
+static bson_t *BSONFromJSONObject(struct json_object *json);
+static int BSONAppendExtendedJSON(bson_t *doc, const char *name, struct json_object *json);
+
+/* Append a BSON variant of json to doc using name. Return TRUE on success */
+static int
+BSONAppendJSONObject(bson_t *doc, const char *name, struct json_object *json)
+{
+
+ switch(json != NULL ? json_object_get_type(json) : json_type_null) {
+
+ case json_type_null:
+ return BSON_APPEND_NULL(doc, name);
+ case json_type_boolean:
+ return BSON_APPEND_BOOL(doc, name, json_object_get_boolean(json));
+ case json_type_double:
+ return BSON_APPEND_DOUBLE(doc, name, json_object_get_double(json));
+ case json_type_int: {
+ int64_t i;
+
+ i = json_object_get_int64(json);
+ if (i >= INT32_MIN && i <= INT32_MAX)
+ return BSON_APPEND_INT32(doc, name, i);
+ else
+ return BSON_APPEND_INT64(doc, name, i);
+ }
+ case json_type_object: {
+ if (BSONAppendExtendedJSON(doc, name, json) == TRUE)
+ return TRUE;
+
+ bson_t *sub;
+ int ok;
+
+ sub = BSONFromJSONObject(json);
+ if (sub == NULL)
+ return FALSE;
+ ok = BSON_APPEND_DOCUMENT(doc, name, sub);
+ bson_destroy(sub);
+ return ok;
+ }
+ case json_type_array: {
+ bson_t *sub;
+ int ok;
+
+ sub = BSONFromJSONArray(json);
+ if (sub == NULL)
+ return FALSE;
+ ok = BSON_APPEND_DOCUMENT(doc, name, sub);
+ bson_destroy(sub);
+ return ok;
+ }
+ case json_type_string: {
+ /* Convert text to ISODATE when needed */
+ if (strncmp(name, "date", 5) == 0 || strncmp(name, "time", 5) == 0 ) {
+ struct tm tm;
+ const char *datestr = json_object_get_string(json);
+ if( strptime(datestr, "%Y-%m-%dT%H:%M:%S:%Z", &tm) != NULL ||
+ strptime(datestr, "%Y-%m-%dT%H:%M:%S%Z", &tm) != NULL ||
+ strptime(datestr, "%Y-%m-%dT%H:%M:%SZ", &tm) != NULL) {
+ tm.tm_isdst = -1;
+ time_t epoch;
+ int64 ts;
+ epoch = mktime(&tm);
+ ts = 1000 * (int64) epoch;
+ return BSON_APPEND_DATE_TIME (doc, name, ts);
+ } else {
+ DBGPRINTF("Unknown date format of field '%s' : '%s' \n", name, datestr);
+ }
+ }
+ else {
+ return BSON_APPEND_UTF8(doc, name, json_object_get_string(json));
+ }
+ }
+ default:
+ return FALSE;
+ }
+}
+
+/* Note: this function assumes that at max a single sub-object exists. This
+ * may need to be extended to cover cases where multiple objects are contained.
+ * However, I am not sure about the original intent of this contribution and
+ * just came across it when refactoring the json calls. As everything seems
+ * to work since quite a while, I do not make any changes now.
+ * rgerhards, 2016-04-09
+ */
+static int
+BSONAppendExtendedJSON(bson_t *doc, const char *name, struct json_object *json)
+{
+ struct json_object_iterator itEnd = json_object_iter_end(json);
+ struct json_object_iterator it = json_object_iter_begin(json);
+
+ if (!json_object_iter_equal(&it, &itEnd)) {
+ const char *const key = json_object_iter_peek_name(&it);
+ if (strcmp(key, "$date") == 0) {
+ struct tm tm;
+ int64 ts;
+ struct json_object *val;
+
+ val = json_object_iter_peek_value(&it);
+ DBGPRINTF("ommongodb: extended json date detected %s", json_object_get_string(val));
+ tm.tm_isdst = -1;
+ strptime(json_object_get_string(val), "%Y-%m-%dT%H:%M:%S%z", &tm);
+ ts = 1000 * (int64) mktime(&tm);
+ return BSON_APPEND_DATE_TIME (doc, name, ts);
+ }
+ }
+ return FALSE;
+}
+
+/* Return a BSON variant of json, which must be a json_type_array */
+static bson_t *BSONFromJSONArray(struct json_object *json)
+{
+ /* Way more than necessary */
+ bson_t *doc = NULL;
+ size_t i, array_len;
+
+ doc = bson_new();
+ if(doc == NULL)
+ goto error;
+
+ array_len = json_object_array_length(json);
+ for (i = 0; i < array_len; i++) {
+ char buf[sizeof(size_t) * CHAR_BIT + 1];
+
+ if ((size_t)snprintf(buf, sizeof(buf), "%zu", i) >= sizeof(buf))
+ goto error;
+ if (BSONAppendJSONObject(doc, buf, json_object_array_get_idx(json, i)) == FALSE)
+ goto error;
+ }
+
+ return doc;
+
+error:
+ if(doc != NULL)
+ bson_destroy(doc);
+ return NULL;
+}
+
+/* Return a BSON variant of json, which must be a json_type_object */
+static bson_t *BSONFromJSONObject(struct json_object *json)
+{
+ bson_t *doc = NULL;
+
+ doc = bson_new();
+ if(doc == NULL)
+ return NULL;
+
+ struct json_object_iterator it = json_object_iter_begin(json);
+ struct json_object_iterator itEnd = json_object_iter_end(json);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ if (BSONAppendJSONObject(doc, json_object_iter_peek_name(&it),
+ json_object_iter_peek_value(&it)) == FALSE)
+ goto error;
+ json_object_iter_next(&it);
+ }
+
+ return doc;
+
+error:
+ if(doc != NULL)
+ bson_destroy(doc);
+ return NULL;
+
+}
+
+BEGINtryResume
+CODESTARTtryResume
+ if(pWrkrData->pData->client == NULL) {
+ iRet = initMongoDB(pWrkrData->pData, 1);
+ }
+ENDtryResume
+
+/*
+ * Check if `code` is in the allowed error codes.
+ * Return 1 if so, 0 otherwise.
+ */
+static int is_allowed_error_code(instanceData const* pData, uint32_t code)
+{
+ int i;
+
+ i = 0;
+ while (i < pData->allowed_error_codes_nbr) {
+ if (code == pData->allowed_error_codes[i])
+ return 1;
+ ++i;
+ }
+ return 0;
+}
+
+BEGINdoAction_NoStrings
+ bson_t *doc = NULL;
+ instanceData *pData;
+CODESTARTdoAction
+ pthread_mutex_lock(&mutDoAct);
+ pData = pWrkrData->pData;
+ /* see if we are ready to proceed */
+ if(pData->client == NULL) {
+ CHKiRet(initMongoDB(pData, 0));
+ }
+
+ if(pData->tplName == NULL) {
+ doc = getDefaultBSON(*(smsg_t**)pMsgData);
+ } else {
+ doc = BSONFromJSONObject(*(struct json_object **)pMsgData);
+ }
+ if(doc == NULL) {
+ dbgprintf("ommongodb: error creating BSON doc\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if (mongoc_collection_insert (pData->collection, MONGOC_INSERT_NONE, doc, NULL, &(pData->error) ) ) {
+ pData->bErrMsgPermitted = 1;
+ } else if (is_allowed_error_code(pData, pData->error.code)) {
+ dbgprintf("ommongodb: insert error: allowing error code\n");
+ } else {
+ dbgprintf("ommongodb: insert error %u : %s \n", pData->error.code, pData->error.message);
+ reportMongoError(pData);
+ /* close on insert error to permit resume */
+ closeMongoDB(pData);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+finalize_it:
+ pthread_mutex_unlock(&mutDoAct);
+ if(doc != NULL)
+ bson_destroy(doc);
+ENDdoAction
+
+
+static void setInstParamDefaults(instanceData *pData)
+{
+ pData->server = NULL;
+ pData->port = NULL;
+ pData->uristr = NULL;
+ pData->ssl_ca = NULL;
+ pData->ssl_cert = NULL;
+ pData->uid = NULL;
+ pData->pwd = NULL;
+ pData->db = NULL;
+ pData->collection = NULL;
+ pData->tplName = NULL;
+ memset (pData->allowed_error_codes, 0, 256 * sizeof(uint32_t));
+ pData->allowed_error_codes_nbr = 0;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ dbgprintf("ommongodb: Getting configuration.\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ dbgprintf("ommongodb: Parsing configuration directives.\n");
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "uristr")) {
+ pData->uristr = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "server")) {
+ pData->server = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->port = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "db")) {
+ pData->db = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "collection")) {
+ pData->collection_name = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "ssl_ca")) {
+ pData->ssl_ca = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "ssl_cert")) {
+ pData->ssl_cert = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "uid")) {
+ pData->uid = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ pData->pwd = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (char*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "allowed_error_codes")) {
+ const int maxerrcodes = sizeof(pData->allowed_error_codes) / sizeof(uint32_t);
+ pData->allowed_error_codes_nbr = pvals[i].val.d.ar->nmemb;
+ if(pData->allowed_error_codes_nbr > maxerrcodes) {
+ parser_errmsg("ommongodb: %d allowed_error_codes given, but max "
+ "supported number is %d. Only the first %d error codes will "
+ "be accepted", pData->allowed_error_codes_nbr, maxerrcodes, maxerrcodes);
+ pData->allowed_error_codes_nbr = maxerrcodes;
+ }
+ for(int j = 0 ; j < pData->allowed_error_codes_nbr ; ++j) {
+ const char *const str = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ assert(str != NULL);
+ pData->allowed_error_codes[j] = (unsigned)atoi(str);
+ free((void*)str);
+ }
+ } else {
+ dbgprintf("ommongodb: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup(pData->tplName),
+ OMSR_TPL_AS_JSON));
+ CHKmalloc(pData->json_tokener = json_tokener_new());
+ }
+
+ if(pData->db == NULL)
+ CHKmalloc(pData->db = (char*)strdup("syslog"));
+ if(pData->collection_name == NULL)
+ CHKmalloc(pData->collection_name = (char*)strdup("log"));
+
+ /*
+ * If we don't have a uristr, we need to build it
+ */
+ dbgprintf("ommongodb: Checking the uristr.\n");
+ if(pData->uristr == NULL){
+ dbgprintf("ommongodb: No uristr, building one.\n");
+ char* tmp = NULL;
+ if(pData->server == NULL)
+ CHKmalloc(pData->server = (char*)strdup("127.0.0.1"));
+ if(pData->port == NULL)
+ CHKmalloc(pData->port = (char*)strdup("27017"));
+
+ /* We need to calculate the total length of the connection uri.
+ * We will let it readable and let gcc do the optimisation for us.
+ */
+ size_t server = strlen(pData->server);
+ size_t port = strlen(pData->port);
+ size_t uid = 0;
+ size_t pwd = 0;
+ size_t uri_len = strlen("mongodb://") + server + port + 2;
+ if(pData->uid && pData->pwd){
+ uid = strlen(pData->uid);
+ pwd = strlen(pData->pwd);
+ uri_len += uid + pwd + 2;
+ }
+ if(pData->ssl_ca && pData->ssl_cert)
+ uri_len += strlen("?ssl=true"); /* "?ssl=true" & "&ssl=true" are the same size */
+
+ /*
+ * Formatting string "by hand" is a lot faster on execution than a snprintf for example.
+ */
+ CHKmalloc(pData->uristr = malloc(uri_len + 1));
+ tmp = stpncpy(pData->uristr, "mongodb://", 11);
+ if(pData->uid && pData->pwd){
+ dbgprintf("ommongodb: Adding uid & pwd to uristr.\n");
+ tmp = stpncpy(tmp, pData->uid, uid);
+ *tmp = ':';
+ ++tmp;
+ tmp = stpncpy(tmp, pData->pwd, pwd);
+ *tmp = '@';
+ ++tmp;
+ }
+ dbgprintf("ommongodb: Adding server & port to uristr.\n");
+ tmp = stpncpy(tmp, pData->server, server);
+ *tmp = ':';
+ ++tmp;
+ tmp = stpncpy(tmp, pData->port, port);
+ *tmp = '/';
+ ++tmp;
+ if(pData->ssl_ca && pData->ssl_cert){
+ dbgprintf("ommongodb: Adding ssl to uristr.\n");
+ if(pData->uid && pData->pwd)
+ tmp = stpncpy(tmp, "&ssl=true", 10);
+ else
+ tmp = stpncpy(tmp, "?ssl=true", 10);
+ }
+ *tmp = '\0';
+ }
+ dbgprintf("ommongodb: The uristr: %s\n", pData->uristr);
+ dbgprintf("ommongodb: End of the configuration.\n");
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+NO_LEGACY_CONF_parseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bJSONPassingSupported;
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("ommongodb: module compiled with rsyslog version %s.\n", VERSION);
+
+ /* check if the rsyslog core supports parameter passing code */
+ bJSONPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts",
+ &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_JSON)
+ bJSONPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */
+ }
+ if(!bJSONPassingSupported) {
+ DBGPRINTF("ommongodb: JSON-passing is not supported by rsyslog core, "
+ "can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_JSON_PASSING);
+ }
+ENDmodInit
diff --git a/plugins/ommysql/Makefile.am b/plugins/ommysql/Makefile.am
new file mode 100644
index 0000000..7bec7e4
--- /dev/null
+++ b/plugins/ommysql/Makefile.am
@@ -0,0 +1,16 @@
+pkglib_LTLIBRARIES = ommysql.la
+
+# under RHEL 7, we have an issue when gnutls is linked. For some reason
+# (autoconf magic?) we link ommysql against gnutls. I have not found the
+# root cause, but setting LIBS= below makes the problem go away. A better
+# solution would be appreciated, but for the time being this seems to
+# solve the issue.
+# more info: https://github.com/rsyslog/rsyslog/issues/408
+# rgerhards, 2015-07-08
+LIBS=
+ommysql_la_SOURCES = ommysql.c
+ommysql_la_CPPFLAGS = $(RSRT_CFLAGS) $(MYSQL_CFLAGS) $(PTHREADS_CFLAGS)
+ommysql_la_LDFLAGS = -module -avoid-version
+ommysql_la_LIBADD = $(MYSQL_LIBS)
+
+EXTRA_DIST = createDB.sql
diff --git a/plugins/ommysql/Makefile.in b/plugins/ommysql/Makefile.in
new file mode 100644
index 0000000..74496cc
--- /dev/null
+++ b/plugins/ommysql/Makefile.in
@@ -0,0 +1,806 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/ommysql
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+ommysql_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_ommysql_la_OBJECTS = ommysql_la-ommysql.lo
+ommysql_la_OBJECTS = $(am_ommysql_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 =
+ommysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ommysql_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/ommysql_la-ommysql.Plo
+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 = $(ommysql_la_SOURCES)
+DIST_SOURCES = $(ommysql_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+
+# under RHEL 7, we have an issue when gnutls is linked. For some reason
+# (autoconf magic?) we link ommysql against gnutls. I have not found the
+# root cause, but setting LIBS= below makes the problem go away. A better
+# solution would be appreciated, but for the time being this seems to
+# solve the issue.
+# more info: https://github.com/rsyslog/rsyslog/issues/408
+# rgerhards, 2015-07-08
+LIBS =
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = ommysql.la
+ommysql_la_SOURCES = ommysql.c
+ommysql_la_CPPFLAGS = $(RSRT_CFLAGS) $(MYSQL_CFLAGS) $(PTHREADS_CFLAGS)
+ommysql_la_LDFLAGS = -module -avoid-version
+ommysql_la_LIBADD = $(MYSQL_LIBS)
+EXTRA_DIST = createDB.sql
+all: 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) --gnu plugins/ommysql/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/ommysql/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+ommysql.la: $(ommysql_la_OBJECTS) $(ommysql_la_DEPENDENCIES) $(EXTRA_ommysql_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(ommysql_la_LINK) -rpath $(pkglibdir) $(ommysql_la_OBJECTS) $(ommysql_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ommysql_la-ommysql.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+ommysql_la-ommysql.lo: ommysql.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommysql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ommysql_la-ommysql.lo -MD -MP -MF $(DEPDIR)/ommysql_la-ommysql.Tpo -c -o ommysql_la-ommysql.lo `test -f 'ommysql.c' || echo '$(srcdir)/'`ommysql.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ommysql_la-ommysql.Tpo $(DEPDIR)/ommysql_la-ommysql.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ommysql.c' object='ommysql_la-ommysql.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) $(ommysql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ommysql_la-ommysql.lo `test -f 'ommysql.c' || echo '$(srcdir)/'`ommysql.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/ommysql_la-ommysql.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/ommysql_la-ommysql.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/ommysql/createDB.sql b/plugins/ommysql/createDB.sql
new file mode 100644
index 0000000..6261284
--- /dev/null
+++ b/plugins/ommysql/createDB.sql
@@ -0,0 +1,37 @@
+CREATE DATABASE Syslog;
+USE Syslog;
+CREATE TABLE SystemEvents
+(
+ ID int unsigned not null auto_increment primary key,
+ CustomerID bigint,
+ ReceivedAt datetime NULL,
+ DeviceReportedTime datetime NULL,
+ Facility smallint NULL,
+ Priority smallint NULL,
+ FromHost varchar(63) NULL,
+ Message text,
+ NTSeverity int NULL,
+ Importance int NULL,
+ EventSource varchar(60),
+ EventUser varchar(60) NULL,
+ EventCategory int NULL,
+ EventID int NULL,
+ EventBinaryData text NULL,
+ MaxAvailable int NULL,
+ CurrUsage int NULL,
+ MinUsage int NULL,
+ MaxUsage int NULL,
+ InfoUnitID int NULL ,
+ SysLogTag varchar(60),
+ EventLogType varchar(60),
+ GenericFileName VarChar(60),
+ SystemID int NULL
+);
+
+CREATE TABLE SystemEventsProperties
+(
+ ID int unsigned not null auto_increment primary key,
+ SystemEventID int NULL ,
+ ParamName varchar(255) NULL ,
+ ParamValue text NULL
+);
diff --git a/plugins/ommysql/ommysql.c b/plugins/ommysql/ommysql.c
new file mode 100644
index 0000000..37434e3
--- /dev/null
+++ b/plugins/ommysql/ommysql.c
@@ -0,0 +1,599 @@
+/* ommysql.c
+ * This is the implementation of the build-in output module for MySQL.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2021 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <netdb.h>
+#include <mysql.h>
+#include <mysqld_error.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ommysql")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ char dbsrv[MAXHOSTNAMELEN+1]; /* IP or hostname of DB server*/
+ unsigned int dbsrvPort; /* port of MySQL server */
+ char dbname[_DB_MAXDBLEN+1]; /* DB name */
+ char dbuid[_DB_MAXUNAMELEN+1]; /* DB user */
+ char dbpwd[_DB_MAXPWDLEN+1]; /* DB user's password */
+ uchar *configfile; /* MySQL Client Configuration File */
+ uchar *configsection; /* MySQL Client Configuration Section */
+ uchar *tplName; /* format template to use */
+ uchar *socket; /* MySQL socket path */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ MYSQL *hmysql; /* handle to MySQL */
+ unsigned uLastMySQLErrno; /* last errno returned by MySQL or 0 if all is well */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ int iSrvPort; /* database server port */
+ uchar *pszMySQLConfigFile; /* MySQL Client Configuration File */
+ uchar *pszMySQLConfigSection; /* MySQL Client Configuration Section */
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 1 },
+ { "db", eCmdHdlrGetWord, 1 },
+ { "uid", eCmdHdlrGetWord, 1 },
+ { "pwd", eCmdHdlrGetWord, 1 },
+ { "serverport", eCmdHdlrInt, 0 },
+ { "mysqlconfig.file", eCmdHdlrGetWord, 0 },
+ { "mysqlconfig.section", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "socket", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* we need to synchronize access to the mysql handle, because multiple threads
+ * use it and we may need to (re)init it during processing. This could lead to
+ * races with potentially wrong addresses or NULL accesses.
+ */
+pthread_rwlock_t rwlock_hmysql;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pthread_rwlock_wrlock(&rwlock_hmysql);
+ pWrkrData->hmysql = NULL;
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* The following function is responsible for closing a
+ * MySQL connection.
+ * Initially added 2004-10-28
+ */
+static void closeMySQL(wrkrInstanceData_t *pWrkrData)
+{
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ pthread_rwlock_wrlock(&rwlock_hmysql);
+ if(pWrkrData->hmysql != NULL) { /* just to be on the safe side... */
+ mysql_close(pWrkrData->hmysql);
+ pWrkrData->hmysql = NULL;
+ }
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ pthread_rwlock_rdlock(&rwlock_hmysql);
+}
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->configfile);
+ free(pData->configsection);
+ free(pData->tplName);
+ free(pData->socket);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ pthread_rwlock_rdlock(&rwlock_hmysql);
+ closeMySQL(pWrkrData);
+ mysql_thread_end();
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ENDdbgPrintInstInfo
+
+
+/* log a database error with descriptive message.
+ * We check if we have a valid MySQL handle. If not, we simply
+ * report an error, but can not be specific. RGerhards, 2007-01-30
+ */
+static void reportDBError(wrkrInstanceData_t *pWrkrData, int bSilent)
+{
+ char errMsg[512];
+ unsigned uMySQLErrno;
+
+ /* output log message */
+ errno = 0;
+ if(pWrkrData->hmysql == NULL) {
+ LogError(0, NO_ERRCODE, "ommysql: unknown DB error occurred - could not obtain MySQL handle");
+ } else { /* we can ask mysql for the error description... */
+ uMySQLErrno = mysql_errno(pWrkrData->hmysql);
+ snprintf(errMsg, sizeof(errMsg), "db error (%u): %s\n", uMySQLErrno,
+ mysql_error(pWrkrData->hmysql));
+ if(bSilent || uMySQLErrno == pWrkrData->uLastMySQLErrno)
+ dbgprintf("mysql, DBError(silent): %s\n", errMsg);
+ else {
+ pWrkrData->uLastMySQLErrno = uMySQLErrno;
+ LogError(0, NO_ERRCODE, "ommysql: %s", errMsg);
+ }
+ }
+
+ return;
+}
+
+
+/* The following function is responsible for initializing a
+ * MySQL connection.
+ * Initially added 2004-10-28 mmeckelein
+ */
+static rsRetVal initMySQL(wrkrInstanceData_t *pWrkrData, int bSilent)
+{
+ instanceData *pData;
+ DEFiRet;
+
+ assert(pWrkrData->hmysql == NULL);
+ pData = pWrkrData->pData;
+
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ pthread_rwlock_wrlock(&rwlock_hmysql);
+
+ pWrkrData->hmysql = mysql_init(NULL);
+ if(pWrkrData->hmysql == NULL) {
+ LogError(0, RS_RET_SUSPENDED, "can not initialize MySQL handle");
+ iRet = RS_RET_SUSPENDED;
+ } else { /* we could get the handle, now on with work... */
+ mysql_options(pWrkrData->hmysql,MYSQL_READ_DEFAULT_GROUP,
+ ((pData->configsection!=NULL)?(char*)pData->configsection:"client"));
+ if(pData->configfile!=NULL){
+ FILE * fp;
+ fp=fopen((char*)pData->configfile,"r");
+ int err=errno;
+ if(fp==NULL){
+ char msg[512];
+ snprintf(msg,sizeof(msg),"Could not open '%s' for reading",pData->configfile);
+ if(bSilent) {
+ char errStr[512];
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ dbgprintf("mysql configuration error(%d): %s - %s\n",err,msg,errStr);
+ } else
+ LogError(err,NO_ERRCODE,"mysql configuration error: %s\n",msg);
+ } else {
+ fclose(fp);
+ mysql_options(pWrkrData->hmysql,MYSQL_READ_DEFAULT_FILE,pData->configfile);
+ }
+ }
+ /* Connect to database */
+ if(mysql_real_connect(pWrkrData->hmysql, pData->dbsrv, pData->dbuid,
+ pData->dbpwd, pData->dbname, pData->dbsrvPort,
+ (const char *)pData->socket, 0) == NULL) {
+ reportDBError(pWrkrData, bSilent);
+ closeMySQL(pWrkrData); /* ignore any error we may get */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ if(mysql_autocommit(pWrkrData->hmysql, 0)) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "ommysql: activating autocommit failed, "
+ "some data may be duplicated\n");
+ reportDBError(pWrkrData, 0);
+ }
+ }
+
+finalize_it:
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ pthread_rwlock_rdlock(&rwlock_hmysql);
+ RETiRet;
+}
+
+
+/* The following function writes the current log entry
+ * to an established MySQL session.
+ * Initially added 2004-10-28 mmeckelein
+ */
+static rsRetVal writeMySQL(wrkrInstanceData_t *pWrkrData, const uchar *const psz)
+{
+ DEFiRet;
+
+ /* see if we are ready to proceed */
+ if(pWrkrData->hmysql == NULL) {
+ CHKiRet(initMySQL(pWrkrData, 0));
+ }
+
+ /* try insert */
+ if(mysql_query(pWrkrData->hmysql, (char*)psz)) {
+ const int mysql_err = mysql_errno(pWrkrData->hmysql);
+ /* We assume server error codes are non-recoverable, mainly data errors.
+ * This also means we need to differentiate between client and server error
+ * codes. Unfortunately, the API does not provide a specified function for
+ * this. Howerver, error codes 2000..2999 are currently client error codes.
+ * So we use this as guideline.
+ */
+ if(mysql_err < 2000 || mysql_err > 2999) {
+ reportDBError(pWrkrData, 0);
+ LogError(0, RS_RET_DATAFAIL, "The error statement was: %s", psz);
+ ABORT_FINALIZE(RS_RET_DATAFAIL);
+ }
+ /* potentially recoverable error occurred, try to re-init connection and retry */
+ closeMySQL(pWrkrData); /* close the current handle */
+ CHKiRet(initMySQL(pWrkrData, 0)); /* try to re-open */
+ if(mysql_query(pWrkrData->hmysql, (char*)psz)) { /* re-try insert */
+ /* we failed, giving up for now */
+ DBGPRINTF("ommysql: suspending due to failed write of '%s'\n", psz);
+ reportDBError(pWrkrData, 0);
+ closeMySQL(pWrkrData); /* free ressources */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ pWrkrData->uLastMySQLErrno = 0; /* reset error for error supression */
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ pthread_rwlock_rdlock(&rwlock_hmysql);
+ if(pWrkrData->hmysql == NULL) {
+ iRet = initMySQL(pWrkrData, 1);
+ }
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ // NOTHING TO DO IN HERE
+ENDbeginTransaction
+
+BEGINcommitTransaction
+CODESTARTcommitTransaction
+ DBGPRINTF("ommysql: commitTransaction\n");
+ pthread_rwlock_rdlock(&rwlock_hmysql);
+ CHKiRet(writeMySQL(pWrkrData, (uchar*)"START TRANSACTION"));
+
+ for(unsigned i = 0 ; i < nParams ; ++i) {
+ iRet = writeMySQL(pWrkrData, actParam(pParams, 1, i, 0).param);
+ if(iRet != RS_RET_OK
+ && iRet != RS_RET_DEFER_COMMIT
+ && iRet != RS_RET_PREVIOUS_COMMITTED) {
+ if(pWrkrData->hmysql == NULL) {
+ DBGPRINTF("ommysql: server error: hmysql is closed, transaction rollback "
+ "willl not be tried (it probably already happened)\n");
+ } else {
+ if(mysql_rollback(pWrkrData->hmysql) != 0) {
+ DBGPRINTF("ommysql: server error: transaction could not be rolled back\n");
+ }
+ closeMySQL(pWrkrData);
+ }
+ FINALIZE;
+ }
+ }
+
+ if(mysql_commit(pWrkrData->hmysql) != 0) {
+ DBGPRINTF("ommysql: server error: transaction not committed\n");
+ reportDBError(pWrkrData, 0);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ DBGPRINTF("ommysql: transaction committed\n");
+finalize_it:
+ pthread_rwlock_unlock(&rwlock_hmysql);
+ENDcommitTransaction
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->dbsrvPort = 0;
+ pData->configfile = NULL;
+ pData->configsection = NULL;
+ pData->tplName = NULL;
+ pData->socket = NULL;
+}
+
+
+/* note: we use the fixed-size buffers inside the config object to avoid
+ * changing too much of the previous plumbing. rgerhards, 2012-02-02
+ */
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ char *cstr;
+ size_t len;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->dbsrv)-1) {
+ parser_errmsg("ommysql: dbname parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->dbsrv)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->dbsrv, cstr, len+1);
+ free(cstr);
+ } else if(!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->dbsrvPort = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "db")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->dbname)-1) {
+ parser_errmsg("ommysql: dbname parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->dbname)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->dbname, cstr, len+1);
+ free(cstr);
+ } else if(!strcmp(actpblk.descr[i].name, "uid")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->dbuid)-1) {
+ parser_errmsg("ommysql: uid parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->dbuid)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->dbuid, cstr, len+1);
+ free(cstr);
+ } else if(!strcmp(actpblk.descr[i].name, "pwd")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->dbpwd)-1) {
+ parser_errmsg("ommysql: pwd parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->dbpwd)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->dbpwd, cstr, len+1);
+ free(cstr);
+ } else if(!strcmp(actpblk.descr[i].name, "mysqlconfig.file")) {
+ pData->configfile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "mysqlconfig.section")) {
+ pData->configsection = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "socket")) {
+ pData->socket = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("ommysql: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) strdup(" StdDBFmt"),
+ OMSR_RQD_TPL_OPT_SQL));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup((char*) pData->tplName),
+ OMSR_RQD_TPL_OPT_SQL));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ int iMySQLPropErr = 0;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us
+ * The first test [*p == '>'] can be skipped if a module shall only
+ * support the newer slection syntax [:modname:]. This is in fact
+ * recommended for new modules. Please note that over time this part
+ * will be handled by rsyslogd itself, but for the time being it is
+ * a good compromise to do it at the module level.
+ * rgerhards, 2007-10-15
+ */
+ if(*p == '>') {
+ p++; /* eat '>' '*/
+ } else if(!strncmp((char*) p, ":ommysql:", sizeof(":ommysql:") - 1)) {
+ p += sizeof(":ommysql:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ CHKiRet(createInstance(&pData));
+
+ /* rger 2004-10-28: added support for MySQL
+ * >server,dbname,userid,password
+ * Now we read the MySQL connection properties
+ * and verify that the properties are valid.
+ */
+ if(getSubString(&p, pData->dbsrv, MAXHOSTNAMELEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->dbsrv == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->dbname, _DB_MAXDBLEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->dbname == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->dbuid, _DB_MAXUNAMELEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->dbuid == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->dbpwd, _DB_MAXPWDLEN+1, ';'))
+ iMySQLPropErr++;
+ /* now check for template
+ * We specify that the SQL option must be present in the template.
+ * This is for your own protection (prevent sql injection).
+ */
+ if(*(p-1) == ';')
+ --p; /* TODO: the whole parsing of the MySQL module needs to be re-thought - but this here
+ * is clean enough for the time being -- rgerhards, 2007-07-30
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*) " StdDBFmt"));
+
+ /* If we detect invalid properties, we disable logging,
+ * because right properties are vital at this place.
+ * Retries make no sense.
+ */
+ if (iMySQLPropErr) {
+ LogError(0, RS_RET_INVALID_PARAMS, "Trouble with MySQL connection properties. "
+ "-MySQL logging disabled");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ } else {
+ pData->dbsrvPort = (unsigned) cs.iSrvPort; /* set configured port */
+ pData->configfile = cs.pszMySQLConfigFile;
+ pData->configsection = cs.pszMySQLConfigSection;
+ pData->socket = NULL;
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ pthread_rwlock_destroy(&rwlock_hmysql);
+# ifdef HAVE_MYSQL_LIBRARY_INIT
+ mysql_library_end();
+# else
+ mysql_server_end();
+# endif
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.iSrvPort = 0; /* zero is the default port */
+ free(cs.pszMySQLConfigFile);
+ cs.pszMySQLConfigFile = NULL;
+ free(cs.pszMySQLConfigSection);
+ cs.pszMySQLConfigSection = NULL;
+ RETiRet;
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ if(!bCoreSupportsBatching) {
+ LogError(0, NO_ERRCODE, "ommysql: rsyslog core too old");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* we need to init the MySQL library. If that fails, we cannot run */
+ if(
+# ifdef HAVE_MYSQL_LIBRARY_INIT
+ mysql_library_init(0, NULL, NULL)
+# else
+ mysql_server_init(0, NULL, NULL)
+# endif
+ ) {
+ LogError(0, NO_ERRCODE, "ommysql: initializing mysql client failed, plugin "
+ "can not run");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ pthread_rwlock_init(&rwlock_hmysql, NULL);
+
+ /* register our config handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionommysqlserverport", 0, eCmdHdlrInt, NULL, &cs.iSrvPort,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"ommysqlconfigfile",0,eCmdHdlrGetWord,NULL,&cs.pszMySQLConfigFile,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"ommysqlconfigsection",0,eCmdHdlrGetWord,NULL,&cs.pszMySQLConfigSection,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/plugins/ompgsql/Makefile.am b/plugins/ompgsql/Makefile.am
new file mode 100644
index 0000000..b777f38
--- /dev/null
+++ b/plugins/ompgsql/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = ompgsql.la
+
+ompgsql_la_SOURCES = ompgsql.c
+ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(PGSQL_CFLAGS) $(RSRT_CFLAGS)
+ompgsql_la_LDFLAGS = -module -avoid-version
+ompgsql_la_LIBADD = $(PGSQL_LIBS)
+
+EXTRA_DIST = createDB.sql
diff --git a/plugins/ompgsql/Makefile.in b/plugins/ompgsql/Makefile.in
new file mode 100644
index 0000000..3c702fb
--- /dev/null
+++ b/plugins/ompgsql/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/ompgsql
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+ompgsql_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_ompgsql_la_OBJECTS = ompgsql_la-ompgsql.lo
+ompgsql_la_OBJECTS = $(am_ompgsql_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 =
+ompgsql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ompgsql_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/ompgsql_la-ompgsql.Plo
+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 = $(ompgsql_la_SOURCES)
+DIST_SOURCES = $(ompgsql_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = ompgsql.la
+ompgsql_la_SOURCES = ompgsql.c
+ompgsql_la_CPPFLAGS = -I$(top_srcdir) $(PGSQL_CFLAGS) $(RSRT_CFLAGS)
+ompgsql_la_LDFLAGS = -module -avoid-version
+ompgsql_la_LIBADD = $(PGSQL_LIBS)
+EXTRA_DIST = createDB.sql
+all: 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) --gnu plugins/ompgsql/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/ompgsql/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+ompgsql.la: $(ompgsql_la_OBJECTS) $(ompgsql_la_DEPENDENCIES) $(EXTRA_ompgsql_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(ompgsql_la_LINK) -rpath $(pkglibdir) $(ompgsql_la_OBJECTS) $(ompgsql_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ompgsql_la-ompgsql.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+ompgsql_la-ompgsql.lo: ompgsql.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ompgsql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ompgsql_la-ompgsql.lo -MD -MP -MF $(DEPDIR)/ompgsql_la-ompgsql.Tpo -c -o ompgsql_la-ompgsql.lo `test -f 'ompgsql.c' || echo '$(srcdir)/'`ompgsql.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ompgsql_la-ompgsql.Tpo $(DEPDIR)/ompgsql_la-ompgsql.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompgsql.c' object='ompgsql_la-ompgsql.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) $(ompgsql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ompgsql_la-ompgsql.lo `test -f 'ompgsql.c' || echo '$(srcdir)/'`ompgsql.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/ompgsql_la-ompgsql.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/ompgsql_la-ompgsql.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/ompgsql/createDB.sql b/plugins/ompgsql/createDB.sql
new file mode 100644
index 0000000..2f1ade0
--- /dev/null
+++ b/plugins/ompgsql/createDB.sql
@@ -0,0 +1,37 @@
+CREATE DATABASE "Syslog" WITH ENCODING 'SQL_ASCII' TEMPLATE template0;
+\c Syslog;
+CREATE TABLE SystemEvents
+(
+ ID serial not null primary key,
+ CustomerID bigint,
+ ReceivedAt timestamp without time zone NULL,
+ DeviceReportedTime timestamp without time zone NULL,
+ Facility smallint NULL,
+ Priority smallint NULL,
+ FromHost varchar(63) NULL,
+ Message text,
+ NTSeverity int NULL,
+ Importance int NULL,
+ EventSource varchar(60),
+ EventUser varchar(60) NULL,
+ EventCategory int NULL,
+ EventID int NULL,
+ EventBinaryData text NULL,
+ MaxAvailable int NULL,
+ CurrUsage int NULL,
+ MinUsage int NULL,
+ MaxUsage int NULL,
+ InfoUnitID int NULL ,
+ SysLogTag varchar(60),
+ EventLogType varchar(60),
+ GenericFileName VarChar(60),
+ SystemID int NULL
+);
+
+CREATE TABLE SystemEventsProperties
+(
+ ID serial not null primary key,
+ SystemEventID int NULL ,
+ ParamName varchar(255) NULL ,
+ ParamValue text NULL
+);
diff --git a/plugins/ompgsql/ompgsql.c b/plugins/ompgsql/ompgsql.c
new file mode 100644
index 0000000..27248ff
--- /dev/null
+++ b/plugins/ompgsql/ompgsql.c
@@ -0,0 +1,580 @@
+/* ompgsql.c
+ * This is the implementation of the build-in output module for PgSQL.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-10-18 by sur5r (converted from ommysql.c)
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * The following link my be useful for the not-so-postgres literate
+ * when setting up a test environment (on Fedora):
+ * http://www.jboss.org/community/wiki/InstallPostgreSQLonFedora
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <netdb.h>
+#include <libpq-fe.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ompgsql")
+
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ char srv[MAXHOSTNAMELEN+1]; /* IP or hostname of DB server*/
+ char dbname[_DB_MAXDBLEN+1]; /* DB name */
+ char user[_DB_MAXUNAMELEN+1]; /* DB user */
+ char pass[_DB_MAXPWDLEN+1]; /* DB user's password */
+ char conninfo[_DB_MAXCONNINFOLEN+1]; /* Connection parameters or URI */
+ unsigned int trans_age;
+ unsigned int trans_commit;
+ unsigned short multi_row;
+ int port;
+ uchar *tpl; /* format template to use */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ PGconn *f_hpgsql; /* handle to PgSQL */
+ ConnStatusType eLastPgSQLStatus; /* last status from postgres */
+} wrkrInstanceData_t;
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrGetWord, 0 },
+ { "db", eCmdHdlrGetWord, 0 },
+ { "user", eCmdHdlrGetWord, 0 },
+ { "uid", eCmdHdlrGetWord, 0 },
+ { "pass", eCmdHdlrGetWord, 0 },
+ { "pwd", eCmdHdlrGetWord, 0 },
+ { "multirows", eCmdHdlrInt, 0 },
+ { "trans_size", eCmdHdlrInt, 0 },
+ { "trans_age", eCmdHdlrInt, 0 },
+ { "serverport", eCmdHdlrInt, 0 },
+ { "port", eCmdHdlrInt, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "conninfo", eCmdHdlrGetWord, 0 }
+};
+
+
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+
+static rsRetVal writePgSQL(uchar *psz, wrkrInstanceData_t *pData);
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->f_hpgsql = NULL;
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if (eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* The following function is responsible for closing a
+ * PgSQL connection.
+ */
+static void closePgSQL(wrkrInstanceData_t *pWrkrData)
+{
+ assert(pWrkrData != NULL);
+
+ if (pWrkrData->f_hpgsql != NULL) { /* just to be on the safe side... */
+ PQfinish(pWrkrData->f_hpgsql);
+ pWrkrData->f_hpgsql = NULL;
+ }
+}
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tpl);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ closePgSQL(pWrkrData);
+ENDfreeWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ENDdbgPrintInstInfo
+
+
+/* log a database error with descriptive message.
+ * We check if we have a valid handle. If not, we simply
+ * report an error, but can not be specific. RGerhards, 2007-01-30
+ */
+static void reportDBError(wrkrInstanceData_t *pWrkrData, int bSilent)
+{
+ char errMsg[512];
+ ConnStatusType ePgSQLStatus;
+
+ assert(pWrkrData != NULL);
+ bSilent = 0;
+
+ /* output log message */
+ errno = 0;
+ if (pWrkrData->f_hpgsql == NULL) {
+ LogError(0, NO_ERRCODE, "unknown DB error occurred - could not obtain PgSQL handle");
+ } else { /* we can ask pgsql for the error description... */
+ ePgSQLStatus = PQstatus(pWrkrData->f_hpgsql);
+ snprintf(errMsg, sizeof(errMsg), "db error (%d): %s\n", ePgSQLStatus,
+ PQerrorMessage(pWrkrData->f_hpgsql));
+ if (bSilent || ePgSQLStatus == pWrkrData->eLastPgSQLStatus)
+ dbgprintf("pgsql, DBError(silent): %s\n", errMsg);
+ else {
+ pWrkrData->eLastPgSQLStatus = ePgSQLStatus;
+ LogError(0, NO_ERRCODE, "%s", errMsg);
+ }
+ }
+
+ return;
+}
+
+
+/* The following function is responsible for initializing a
+ * PgSQL connection.
+ */
+static rsRetVal initPgSQL(wrkrInstanceData_t *pWrkrData, int bSilent)
+{
+ int sslStatus;
+ instanceData *pData;
+ DEFiRet;
+
+ pData = pWrkrData->pData;
+ assert(pData != NULL);
+ assert(pWrkrData->f_hpgsql == NULL);
+
+ if (strlen(pData->conninfo) > 0) {
+ /* Don't log the whole connection string, because it contains the DB password */
+ dbgprintf("initPgSQL: using connection string provided by conninfo\n");
+ pWrkrData->f_hpgsql = PQconnectdb(pData->conninfo);
+ } else {
+ dbgprintf("initPgSQL: host=%s port=%d dbname=%s uid=%s\n", pData->srv, pData->port,
+ pData->dbname, pData->user);
+
+ /* Force PostgreSQL to use ANSI-SQL conforming strings, otherwise we may
+ * get all sorts of side effects (e.g.: backslash escapes) and warnings
+ *
+ * Note: PostgreSQL versions since 9.3 have this already on by default.
+ */
+ const char *PgConnectionOptions = "-c standard_conforming_strings=on";
+
+ /* Connect to database */
+ char port[6];
+ snprintf(port, sizeof(port), "%d", pData->port);
+
+ pWrkrData->f_hpgsql = PQsetdbLogin(pData->srv, port, PgConnectionOptions, NULL,
+ pData->dbname, pData->user, pData->pass);
+ }
+
+ if (pWrkrData->f_hpgsql == NULL) {
+ reportDBError(pWrkrData, bSilent);
+ closePgSQL(pWrkrData); /* ignore any error we may get */
+ iRet = RS_RET_SUSPENDED;
+ }
+
+#ifdef HAVE_PGSSLINUSE
+ sslStatus = PQsslInUse(pWrkrData->f_hpgsql);
+#else
+ sslStatus = PQgetssl(pWrkrData->f_hpgsql) == NULL ? 0 : 1;
+#endif
+ dbgprintf("initPgSQL: ssl status: %d\n", sslStatus);
+
+ RETiRet;
+}
+
+
+/* try the insert into postgres and return if that failed or not
+ * (1 = had error, 0=ok). We do not use the standard IRET calling convention
+ * rgerhards, 2009-04-17
+ */
+static int
+tryExec(uchar *pszCmd, wrkrInstanceData_t *pWrkrData)
+{
+ PGresult *pgRet;
+ ExecStatusType execState;
+ int bHadError = 0;
+
+ /* try insert */
+ pgRet = PQexec(pWrkrData->f_hpgsql, (char*)pszCmd);
+ execState = PQresultStatus(pgRet);
+ if (execState != PGRES_COMMAND_OK && execState != PGRES_TUPLES_OK) {
+ dbgprintf("postgres query execution failed: %s\n", PQresStatus(PQresultStatus(pgRet)));
+ bHadError = 1;
+ }
+ PQclear(pgRet);
+
+ return(bHadError);
+}
+
+
+/* The following function writes the current log entry
+ * to an established PgSQL session.
+ * Enhanced function to take care of the returned error
+ * value (if there is such). Note that this may happen due to
+ * a sql format error - connection aborts were properly handled
+ * before my patch. -- rgerhards, 2009-04-17
+ */
+static rsRetVal
+writePgSQL(uchar *psz, wrkrInstanceData_t *pWrkrData)
+{
+ int bHadError = 0;
+ DEFiRet;
+
+ assert(psz != NULL);
+ assert(pWrkrData != NULL);
+
+ dbgprintf("writePgSQL: %s\n", psz);
+
+ bHadError = tryExec(psz, pWrkrData); /* try insert */
+
+ if (bHadError || (PQstatus(pWrkrData->f_hpgsql) != CONNECTION_OK)) {
+#if 0 /* re-enable once we have transaction support */
+ /* error occurred, try to re-init connection and retry */
+ int inTransaction = 0;
+ if(pData->f_hpgsql != NULL) {
+ PGTransactionStatusType xactStatus = PQtransactionStatus(pData->f_hpgsql);
+ if((xactStatus == PQTRANS_INTRANS) || (xactStatus == PQTRANS_ACTIVE)) {
+ inTransaction = 1;
+ }
+ }
+ if ( inTransaction == 0 )
+#endif
+ {
+ closePgSQL(pWrkrData); /* close the current handle */
+ CHKiRet(initPgSQL(pWrkrData, 0)); /* try to re-open */
+ bHadError = tryExec(psz, pWrkrData); /* retry */
+ }
+ if(bHadError || (PQstatus(pWrkrData->f_hpgsql) != CONNECTION_OK)) {
+ /* we failed, giving up for now */
+ reportDBError(pWrkrData, 0);
+ closePgSQL(pWrkrData); /* free ressources */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+finalize_it:
+ if (iRet == RS_RET_OK) {
+ pWrkrData->eLastPgSQLStatus = CONNECTION_OK; /* reset error for error supression */
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ if (pWrkrData->f_hpgsql == NULL) {
+ iRet = initPgSQL(pWrkrData, 1);
+ if (iRet == RS_RET_OK) {
+ /* the code above seems not to actually connect to the database. As such, we do a
+ * dummy statement (a pointless select...) to verify the connection and return
+ * success only when that statemetn succeeds. Note that I am far from being a
+ * PostgreSQL expert, so any patch that does the desired result in a more
+ * intelligent way is highly welcome. -- rgerhards, 2009-12-16
+ */
+ iRet = writePgSQL((uchar*)"select 'a' as a", pWrkrData);
+ }
+ }
+ENDtryResume
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ENDbeginTransaction
+
+
+BEGINcommitTransaction
+CODESTARTcommitTransaction
+ dbgprintf("ompgsql: beginTransaction\n");
+ if (pWrkrData->f_hpgsql == NULL)
+ initPgSQL(pWrkrData, 0);
+ CHKiRet(writePgSQL((uchar*) "BEGIN", pWrkrData)); /* TODO: make user-configurable */
+
+ for (unsigned i = 0 ; i < nParams ; ++i) {
+ iRet = writePgSQL(actParam(pParams, 1, i, 0).param, pWrkrData);
+ if (iRet != RS_RET_OK
+ && iRet != RS_RET_DEFER_COMMIT
+ && iRet != RS_RET_PREVIOUS_COMMITTED) {
+ /*if(mysql_rollback(pWrkrData->hmysql) != 0) {
+ DBGPRINTF("ommysql: server error: transaction could not be rolled back\n");
+ }*/
+ // closeMySQL(pWrkrData);
+ // FINALIZE;
+ }
+ }
+
+ CHKiRet(writePgSQL((uchar*) "COMMIT", pWrkrData)); /* TODO: make user-configurable */
+
+finalize_it:
+ if (iRet == RS_RET_OK) {
+ pWrkrData->eLastPgSQLStatus = CONNECTION_OK; /* reset error for error supression */
+ }
+
+ENDcommitTransaction
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tpl = NULL;
+ pData->multi_row = 100;
+ pData->trans_commit = 100;
+ pData->trans_age = 60;
+ pData->port = 5432;
+ strcpy(pData->user, "postgres");
+ strcpy(pData->pass, "postgres");
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ char *cstr;
+ size_t len;
+CODESTARTnewActInst
+ if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ for (i = 0 ; i < actpblk.nParams ; ++i) {
+ if (!pvals[i].bUsed)
+ continue;
+ if (!strcmp(actpblk.descr[i].name, "server")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->srv)-1) {
+ parser_errmsg("ompgsql: srv parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->srv)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->srv, cstr, len+1);
+ free(cstr);
+ } else if (!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "serverport")) {
+ pData->port = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "multirows")) {
+ pData->multi_row = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "trans_size")) {
+ pData->trans_commit = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "trans_age")) {
+ pData->trans_age = (int) pvals[i].val.d.n;
+ } else if (!strcmp(actpblk.descr[i].name, "db")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->dbname)-1) {
+ parser_errmsg("ompgsql: db parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->dbname)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->dbname, cstr, len+1);
+ free(cstr);
+ } else if ( !strcmp(actpblk.descr[i].name, "user")
+ || !strcmp(actpblk.descr[i].name, "uid")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->user)-1) {
+ parser_errmsg("ompgsql: user/uid parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->user)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->user, cstr, len+1);
+ free(cstr);
+ } else if ( !strcmp(actpblk.descr[i].name, "pass")
+ || !strcmp(actpblk.descr[i].name, "pwd")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->pass)-1) {
+ parser_errmsg("ompgsql: pass/pwd parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->pass)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->pass, cstr, len+1);
+ free(cstr);
+ } else if (!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tpl = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(actpblk.descr[i].name, "conninfo")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ len = es_strlen(pvals[i].val.d.estr);
+ if(len >= sizeof(pData->conninfo)-1) {
+ parser_errmsg("ompgsql: conninfo parameter longer than supported "
+ "maximum of %d characters", (int)sizeof(pData->conninfo)-1);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ memcpy(pData->conninfo, cstr, len+1);
+ free(cstr);
+ } else {
+ dbgprintf("ompgsql: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if (strlen(pData->conninfo) == 0 && (strlen(pData->srv) == 0 || strlen(pData->dbname) == 0)) {
+ parser_errmsg("ompgsql: must provide conninfo or server and dbname");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if (pData->tpl == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) strdup(" StdPgSQLFmt"), OMSR_RQD_TPL_OPT_SQL));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) strdup((char*) pData->tpl), OMSR_RQD_TPL_OPT_SQL));
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINparseSelectorAct
+ int iPgSQLPropErr = 0;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us
+ * The first test [*p == '>'] can be skipped if a module shall only
+ * support the newer slection syntax [:modname:]. This is in fact
+ * recommended for new modules. Please note that over time this part
+ * will be handled by rsyslogd itself, but for the time being it is
+ * a good compromise to do it at the module level.
+ * rgerhards, 2007-10-15
+ */
+
+ if (!strncmp((char*) p, ":ompgsql:", sizeof(":ompgsql:") - 1))
+ p += sizeof(":ompgsql:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ else
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+
+ /* ok, if we reach this point, we have something for us */
+ if ((iRet = createInstance(&pData)) != RS_RET_OK)
+ goto finalize_it;
+ setInstParamDefaults(pData);
+
+ /* sur5r 2007-10-18: added support for PgSQL
+ * :ompgsql:server,dbname,userid,password
+ * Now we read the PgSQL connection properties
+ * and verify that the properties are valid.
+ */
+ if (getSubString(&p, pData->srv, MAXHOSTNAMELEN+1, ','))
+ iPgSQLPropErr++;
+ dbgprintf("%p:%s\n",p,p);
+ if (*pData->srv == '\0')
+ iPgSQLPropErr++;
+ if (getSubString(&p, pData->dbname, _DB_MAXDBLEN+1, ','))
+ iPgSQLPropErr++;
+ if (*pData->dbname == '\0')
+ iPgSQLPropErr++;
+ if (getSubString(&p, pData->user, _DB_MAXUNAMELEN+1, ','))
+ iPgSQLPropErr++;
+ if (*pData->user == '\0')
+ iPgSQLPropErr++;
+ if (getSubString(&p, pData->pass, _DB_MAXPWDLEN+1, ';'))
+ iPgSQLPropErr++;
+ /* now check for template
+ * We specify that the SQL option must be present in the template.
+ * This is for your own protection (prevent sql injection).
+ */
+ if (*(p - 1) == ';') {
+ p--;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*) pData->tpl));
+ } else {
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*)" StdPgSQLFmt"));
+ }
+
+ /* If we detect invalid properties, we disable logging,
+ * because right properties are vital at this place.
+ * Retries make no sense.
+ */
+ if (iPgSQLPropErr) {
+ LogError(0, RS_RET_INVALID_PARAMS, "Trouble with PgSQL connection properties. "
+ "-PgSQL logging disabled");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+/* CODEqueryEtryPt_TXIF_OMOD_QUERIES currently no TX support! */ /* we support the transactional interface! */
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ if (!bCoreSupportsBatching) {
+ LogError(0, NO_ERRCODE, "ompgsql: rsyslog core too old");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ENDmodInit
+
+/* vi:set ai: */
diff --git a/plugins/omprog/Makefile.am b/plugins/omprog/Makefile.am
new file mode 100644
index 0000000..63fe09b
--- /dev/null
+++ b/plugins/omprog/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omprog.la
+
+omprog_la_SOURCES = omprog.c
+omprog_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omprog_la_LDFLAGS = -module -avoid-version
+omprog_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/omprog/Makefile.in b/plugins/omprog/Makefile.in
new file mode 100644
index 0000000..f54047d
--- /dev/null
+++ b/plugins/omprog/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omprog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omprog_la_DEPENDENCIES =
+am_omprog_la_OBJECTS = omprog_la-omprog.lo
+omprog_la_OBJECTS = $(am_omprog_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 =
+omprog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omprog_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omprog_la-omprog.Plo
+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 = $(omprog_la_SOURCES)
+DIST_SOURCES = $(omprog_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omprog.la
+omprog_la_SOURCES = omprog.c
+omprog_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omprog_la_LDFLAGS = -module -avoid-version
+omprog_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/omprog/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omprog/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omprog.la: $(omprog_la_OBJECTS) $(omprog_la_DEPENDENCIES) $(EXTRA_omprog_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omprog_la_LINK) -rpath $(pkglibdir) $(omprog_la_OBJECTS) $(omprog_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omprog_la-omprog.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omprog_la-omprog.lo: omprog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omprog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omprog_la-omprog.lo -MD -MP -MF $(DEPDIR)/omprog_la-omprog.Tpo -c -o omprog_la-omprog.lo `test -f 'omprog.c' || echo '$(srcdir)/'`omprog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omprog_la-omprog.Tpo $(DEPDIR)/omprog_la-omprog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omprog.c' object='omprog_la-omprog.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) $(omprog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omprog_la-omprog.lo `test -f 'omprog.c' || echo '$(srcdir)/'`omprog.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omprog_la-omprog.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omprog_la-omprog.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omprog/omprog.c b/plugins/omprog/omprog.c
new file mode 100644
index 0000000..f21169a
--- /dev/null
+++ b/plugins/omprog/omprog.c
@@ -0,0 +1,1281 @@
+/* omprog.c
+ * This output plugin enables rsyslog to execute a program and
+ * feed it the message stream as standard input.
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * File begun on 2009-04-01 by RGerhards
+ *
+ * Copyright 2009-2020 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "glbl.h"
+#include "rsconf.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omprog")
+
+extern char **environ; /* POSIX environment ptr, by std not in a header... (see man 7 environ) */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+#define NO_HUP_FORWARD -1 /* indicates that HUP should NOT be forwarded */
+#define DEFAULT_CONFIRM_TIMEOUT_MS 10000
+#define DEFAULT_CLOSE_TIMEOUT_MS 5000
+#define RESPONSE_LINE_BUFFER_SIZE 4096
+#define OUTPUT_CAPTURE_BUFFER_SIZE 4096
+#define MAX_FD_TO_CLOSE 65535
+
+typedef struct childProcessCtx {
+ int bIsRunning; /* is the program running? (if 0, next fields are uninitialized) */
+ pid_t pid; /* pid of currently running child process */
+ int fdPipeOut; /* fd for sending messages to the program */
+ int fdPipeIn; /* fd for receiving status messages from the program, or -1 */
+} childProcessCtx_t;
+
+typedef struct outputCaptureCtx {
+ uchar *szFileName; /* name of file to write the program output to, or NULL */
+ mode_t fCreateMode; /* output file creation permissions */
+ pthread_mutex_t mutStart; /* mutex for starting the output-capture thread */
+ pthread_mutex_t mutWrite; /* mutex for reopening the output file on HUP while being written */
+ pthread_mutex_t mutTerm; /* mutex for signaling the termination of the thread */
+ pthread_cond_t condTerm; /* condition for signaling the termination of the thread */
+ int bIsRunning; /* is the thread running? (if 0, next fields are uninitialized) */
+ pthread_t thrdID; /* ID of the output-capture thread */
+ int fdPipe[2]; /* pipe for capturing the output of the child processes */
+ int fdFile; /* fd of the output file (-1 if it could not be opened) */
+ int bFileErr; /* file open error occurred? (to avoid reporting too many errors) */
+ int bReadErr; /* read error occurred? (to avoid reporting too many errors) */
+ int bWriteErr; /* write error occurred? (to avoid reporting too many errors) */
+} outputCaptureCtx_t;
+
+typedef struct _instanceData {
+ uchar *szBinary; /* name of external program to call */
+ char **aParams; /* optional parameters to pass to external program */
+ int iParams; /* holds the count of parameters if set */
+ uchar *szTemplateName; /* assigned output template */
+ int bConfirmMessages; /* does the program provide feedback via stdout? */
+ long lConfirmTimeout; /* how long to wait for feedback from the program (ms) */
+ int bReportFailures; /* report failures returned by the program as warning logs? */
+ int bUseTransactions; /* send begin/end transaction marks to program? */
+ uchar *szBeginTransactionMark; /* mark message for begin transaction */
+ uchar *szCommitTransactionMark; /* mark message for commit transaction */
+ int iHUPForward; /* signal to forward on HUP (or NO_HUP_FORWARD) */
+ int bSignalOnClose; /* should send SIGTERM to program before closing pipe? */
+ long lCloseTimeout; /* how long to wait for program to terminate after closing pipe (ms) */
+ int bKillUnresponsive; /* should send SIGKILL if closeTimeout is reached? */
+ int bForceSingleInst; /* start only one instance of program, even with multiple workers? */
+ childProcessCtx_t *pSingleChildCtx; /* child process context when bForceSingleInst=true */
+ pthread_mutex_t *pSingleChildMut; /* mutex for interacting with single child process */
+ outputCaptureCtx_t *pOutputCaptureCtx; /* settings and state for the output capture thread */
+ time_t block_if_err; /* time until which interface error is not to be shown */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ childProcessCtx_t *pChildCtx; /* child process context (can be equal to pSingleChildCtx) */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar *szBinary; /* name of external program to call */
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "binary", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "confirmMessages", eCmdHdlrBinary, 0 },
+ { "confirmTimeout", eCmdHdlrInt, 0 },
+ { "reportFailures", eCmdHdlrBinary, 0 },
+ { "useTransactions", eCmdHdlrBinary, 0 },
+ { "beginTransactionMark", eCmdHdlrString, 0 },
+ { "commitTransactionMark", eCmdHdlrString, 0 },
+ { "forceSingleInstance", eCmdHdlrBinary, 0 },
+ { "hup.signal", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "signalOnClose", eCmdHdlrBinary, 0 },
+ { "closeTimeout", eCmdHdlrInt, 0 },
+ { "killUnresponsive", eCmdHdlrBinary, 0 },
+ { "output", eCmdHdlrString, 0 },
+ { "fileCreateMode", eCmdHdlrFileCreateMode, 0 }
+};
+
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* execute the external program (must be called in child context after fork).
+ */
+static __attribute__((noreturn)) void
+execBinary(const instanceData *pData, int fdStdin, int fdStdout)
+{
+ int fdOutput, maxFd, fd, sigNum;
+ struct sigaction sigAct;
+ sigset_t sigSet;
+ char errStr[1024];
+
+ if(dup2(fdStdin, STDIN_FILENO) == -1) {
+ goto failed;
+ }
+
+ if(pData->pOutputCaptureCtx != NULL) {
+ fdOutput = pData->pOutputCaptureCtx->fdPipe[1];
+ } else {
+ fdOutput = open("/dev/null", O_WRONLY);
+ if(fdOutput == -1) {
+ goto failed;
+ }
+ }
+
+ if(fdStdout != -1) {
+ /* confirmMessages enabled: redirect stdout to parent via pipe. After
+ * this point, anything written to the child's stdout will be treated
+ * by omprog as initialization feedback (see startChild). This
+ * includes debug messages (DBGPRINTF) when in debug mode. So we
+ * cannot use DBGPRINTF from this point on, except for error cases.
+ */
+ if(dup2(fdStdout, STDOUT_FILENO) == -1) {
+ goto failed;
+ }
+ } else {
+ /* confirmMessages disabled: redirect stdout to file or /dev/null */
+ if(dup2(fdOutput, STDOUT_FILENO) == -1) {
+ goto failed;
+ }
+ }
+
+ /* redirect stderr to file or /dev/null */
+ if(dup2(fdOutput, STDERR_FILENO) == -1) {
+ goto failed;
+ }
+
+ /* close the file handles the child process doesn't need (all above STDERR).
+ * The following way is simple and portable, though not perfect.
+ * See https://stackoverflow.com/a/918469 for alternatives.
+ */
+ maxFd = sysconf(_SC_OPEN_MAX);
+ if(maxFd < 0 || maxFd > MAX_FD_TO_CLOSE) {
+ maxFd = MAX_FD_TO_CLOSE;
+ }
+# ifdef VALGRIND
+ else { /* don't close valgrind reserved fds, to avoid warnings */
+ maxFd -= 10;
+ }
+# endif
+ for(fd = STDERR_FILENO + 1 ; fd <= maxFd ; ++fd) {
+ close(fd);
+ }
+
+ /* reset signal handlers to default */
+ memset(&sigAct, 0, sizeof(sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = SIG_DFL;
+ for(sigNum = 1 ; sigNum < NSIG ; ++sigNum) {
+ sigaction(sigNum, &sigAct, NULL);
+ }
+
+ /* we need to block SIGINT, otherwise our program is cancelled when we are
+ * stopped in debug mode.
+ */
+ sigAct.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &sigAct, NULL);
+ sigemptyset(&sigSet);
+ sigprocmask(SIG_SETMASK, &sigSet, NULL);
+
+ alarm(0);
+
+ /* finally exec program */
+ execve((char*)pData->szBinary, pData->aParams, environ);
+
+failed:
+ /* an error occurred: log it and exit the child process. We use the
+ * 'syslog' system call to log the error (we cannot use LogMsg/LogError,
+ * since these functions add directly to the rsyslog input queue).
+ */
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGPRINTF("omprog: failed to execute program '%s': %s\n",
+ pData->szBinary, errStr);
+ openlog("rsyslogd", 0, LOG_SYSLOG);
+ syslog(LOG_ERR, "omprog: failed to execute program '%s': %s\n",
+ pData->szBinary, errStr);
+ exit(1);
+}
+
+/* creates a pipe and starts program, uses pipe as stdin for program.
+ * rgerhards, 2009-04-01
+ */
+static rsRetVal
+openPipe(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ int pipeStdin[2] = { -1, -1 };
+ int pipeStdout[2] = { -1, -1 };
+ pid_t cpid;
+ DEFiRet;
+
+ /* open a pipe to send messages to the program */
+ if(pipe(pipeStdin) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ /* if the 'confirmMessages' setting is enabled, open a pipe to receive
+ message confirmations from the program */
+ if(pData->bConfirmMessages && pipe(pipeStdout) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ DBGPRINTF("omprog: executing program '%s' with '%d' parameters\n", pData->szBinary,
+ pData->iParams);
+
+ cpid = fork();
+ if(cpid == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_FORK);
+ }
+
+ if(cpid == 0) { /* we are now the child process: execute the program */
+ /* close the pipe ends that the child doesn't need */
+ close(pipeStdin[1]);
+ if(pipeStdout[0] != -1) {
+ close(pipeStdout[0]);
+ }
+
+ execBinary(pData, pipeStdin[0], pipeStdout[1]);
+ /* NO CODE HERE - WILL NEVER BE REACHED! */
+ }
+
+ DBGPRINTF("omprog: child has pid %d\n", (int) cpid);
+
+ /* close the pipe ends that the parent doesn't need */
+ close(pipeStdin[0]);
+ if(pipeStdout[1] != -1) {
+ close(pipeStdout[1]);
+ }
+
+ pChildCtx->fdPipeOut = pipeStdin[1]; /* we'll send messages to the program via this fd */
+ pChildCtx->fdPipeIn = pipeStdout[0]; /* we'll receive message confirmations via this fd */
+ pChildCtx->pid = cpid;
+ pChildCtx->bIsRunning = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pipeStdin[0] != -1) {
+ close(pipeStdin[0]);
+ close(pipeStdin[1]);
+ }
+ if(pipeStdout[0] != -1) {
+ close(pipeStdout[0]);
+ close(pipeStdout[1]);
+ }
+ }
+ RETiRet;
+}
+
+static void
+waitForChild(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ int status;
+ int ret;
+ long counter;
+
+ counter = pData->lCloseTimeout / 10;
+ while ((ret = waitpid(pChildCtx->pid, &status, WNOHANG)) == 0 && counter > 0) {
+ srSleep(0, 10000); /* 0 seconds, 10 milliseconds */
+ --counter;
+ }
+
+ if (ret == 0) { /* timeout reached */
+ if (!pData->bKillUnresponsive) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' (pid %ld) did not terminate "
+ "within timeout (%ld ms); ignoring it", pData->szBinary,
+ (long) pChildCtx->pid, pData->lCloseTimeout);
+ return;
+ }
+
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' (pid %ld) did not terminate "
+ "within timeout (%ld ms); killing it", pData->szBinary, (long) pChildCtx->pid,
+ pData->lCloseTimeout);
+ if (kill(pChildCtx->pid, SIGKILL) == -1) {
+ LogError(errno, RS_RET_SYS_ERR, "omprog: could not send SIGKILL to child process");
+ return;
+ }
+
+ ret = waitpid(pChildCtx->pid, &status, 0);
+ }
+
+ /* waitpid will fail with errno == ECHILD if the child process has already
+ been reaped by the rsyslogd main loop (see rsyslogd.c) */
+ if(ret == pChildCtx->pid) {
+ glblReportChildProcessExit(runConf, pData->szBinary, pChildCtx->pid, status);
+ }
+}
+
+/* close pipe and wait for child to terminate
+ */
+static void
+cleanupChild(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ assert(pChildCtx->bIsRunning);
+
+ if(pChildCtx->fdPipeIn != -1) {
+ close(pChildCtx->fdPipeIn);
+ pChildCtx->fdPipeIn = -1;
+ }
+ if(pChildCtx->fdPipeOut != -1) {
+ close(pChildCtx->fdPipeOut);
+ pChildCtx->fdPipeOut = -1;
+ }
+
+ /* wait for the child AFTER closing the pipe, so it receives EOF */
+ waitForChild(pData, pChildCtx);
+
+ pChildCtx->bIsRunning = 0;
+}
+
+/* Send SIGTERM to child process if configured to do so, close pipe
+ * and wait for child to terminate.
+ */
+static void
+terminateChild(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ DBGPRINTF("terminateChild called\n");
+ assert(pChildCtx->bIsRunning);
+
+ if (pData->bSignalOnClose) {
+ kill(pChildCtx->pid, SIGTERM);
+ }
+
+ cleanupChild(pData, pChildCtx);
+}
+
+/* write message to pipe
+ * note that we do not try to run block-free. If the user fears something
+ * may block (and this is not acceptable), the action should be run on its
+ * own action queue.
+ */
+static rsRetVal
+sendMessage(instanceData *pData, childProcessCtx_t *pChildCtx, const uchar *szMsg)
+{
+ ssize_t written;
+ size_t offset = 0;
+ DEFiRet;
+
+ const size_t len = strlen((char*)szMsg);
+
+ do {
+ written = write(pChildCtx->fdPipeOut, ((char*)szMsg) + offset, len - offset);
+ if(written == -1) {
+ if(errno == EINTR) {
+ continue; /* call interrupted: retry write */
+ }
+ if(errno == EPIPE) {
+ LogMsg(0, RS_RET_ERR_WRITE_PIPE, LOG_WARNING,
+ "omprog: program '%s' (pid %ld) terminated; will be restarted",
+ pData->szBinary, (long) pChildCtx->pid);
+ cleanupChild(pData, pChildCtx); /* force restart in tryResume() */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ LogError(errno, RS_RET_ERR_WRITE_PIPE, "omprog: error sending message to program");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ offset += written;
+ } while(offset < len);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+lineToStatusCode(instanceData *pData, const char* line)
+{
+ DEFiRet;
+
+ /* strip leading dots (.) from the line, so the program can use them as a keep-alive mechanism */
+ while(line[0] == '.') {
+ ++line;
+ }
+
+ if(strcmp(line, "OK") == 0) {
+ iRet = RS_RET_OK;
+ } else if(strcmp(line, "DEFER_COMMIT") == 0) {
+ iRet = RS_RET_DEFER_COMMIT;
+ } else if(strcmp(line, "PREVIOUS_COMMITTED") == 0) {
+ iRet = RS_RET_PREVIOUS_COMMITTED;
+ } else {
+ /* anything else is considered a recoverable error */
+ DBGPRINTF("omprog: program '%s' returned: %s\n", pData->szBinary, line);
+ if(pData->bReportFailures) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' returned: %s",
+ pData->szBinary, line);
+ }
+ iRet = RS_RET_SUSPENDED;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+readStatus(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ struct pollfd fdToPoll[1];
+ int numReady;
+ char lineBuf[RESPONSE_LINE_BUFFER_SIZE];
+ ssize_t lenRead;
+ size_t offset = 0;
+ int lineEnded = 0;
+ DEFiRet;
+
+ fdToPoll[0].fd = pChildCtx->fdPipeIn;
+ fdToPoll[0].events = POLLIN;
+
+ do {
+ numReady = poll(fdToPoll, 1, pData->lConfirmTimeout);
+ if(numReady == -1) {
+ if(errno == EINTR) {
+ continue; /* call interrupted: retry poll */
+ }
+ LogError(errno, RS_RET_SYS_ERR, "omprog: error polling for response from program");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if(numReady == 0) { /* timeout reached */
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_WARNING, "omprog: program '%s' (pid %ld) did not respond "
+ "within timeout (%ld ms); will be restarted", pData->szBinary,
+ (long) pChildCtx->pid, pData->lConfirmTimeout);
+ terminateChild(pData, pChildCtx);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ lenRead = read(pChildCtx->fdPipeIn, lineBuf + offset, sizeof(lineBuf) - offset - 1);
+ if(lenRead == -1) {
+ if(errno == EINTR) {
+ continue; /* call interrupted: retry poll + read */
+ }
+ LogError(errno, RS_RET_READ_ERR, "omprog: error reading response from program");
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if(lenRead == 0) {
+ LogMsg(0, RS_RET_READ_ERR, LOG_WARNING, "omprog: program '%s' (pid %ld) terminated; "
+ "will be restarted", pData->szBinary, (long) pChildCtx->pid);
+ cleanupChild(pData, pChildCtx);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ offset += lenRead;
+ lineBuf[offset] = '\0';
+ lineEnded = (lineBuf[offset-1] == '\n');
+
+ /* check that the program has not returned multiple lines. This should not occur if
+ * the program honors the specified interface. Otherwise, we force a restart of the
+ * program, since we have probably lost synchronism with it.
+ */
+ if(!lineEnded && strchr(lineBuf + offset - lenRead, '\n') != NULL) {
+ DBGPRINTF("omprog: program '%s' returned: %s\n", pData->szBinary, lineBuf);
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' returned a multiline response; "
+ "will be restarted", pData->szBinary);
+ if(pData->bReportFailures) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' returned: %s",
+ pData->szBinary, lineBuf);
+ }
+ terminateChild(pData, pChildCtx);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ } while(!lineEnded && offset < sizeof(lineBuf) - 1);
+
+ if(!lineEnded) {
+ DBGPRINTF("omprog: program '%s' returned: %s\n", pData->szBinary, lineBuf);
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' returned a too long response; "
+ "will be restarted", pData->szBinary);
+ if(pData->bReportFailures) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: program '%s' returned: %s",
+ pData->szBinary, lineBuf);
+ }
+ terminateChild(pData, pChildCtx);
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ lineBuf[offset-1] = '\0'; /* strip newline char */
+
+ /* NOTE: coverity does not like CHKiRet() if it is the last thing before finalize_it.
+ * Reason is that the if() inside that macro than does not lead to different code paths.
+ */
+ iRet = lineToStatusCode(pData, lineBuf);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+allocChildCtx(childProcessCtx_t **ppChildCtx)
+{
+ childProcessCtx_t *pChildCtx;
+ DEFiRet;
+
+ CHKmalloc(pChildCtx = calloc(1, sizeof(childProcessCtx_t)));
+ *ppChildCtx = pChildCtx;
+
+ pChildCtx->bIsRunning = 0;
+ pChildCtx->pid = -1;
+ pChildCtx->fdPipeOut = -1;
+ pChildCtx->fdPipeIn = -1;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+startChild(instanceData *pData, childProcessCtx_t *pChildCtx)
+{
+ DEFiRet;
+
+ assert(!pChildCtx->bIsRunning);
+
+ CHKiRet(openPipe(pData, pChildCtx));
+
+ if(pData->bConfirmMessages) {
+ /* wait for program to confirm successful initialization */
+ CHKiRet(readStatus(pData, pChildCtx));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK && pChildCtx->bIsRunning) {
+ /* if initialization has failed, terminate program */
+ terminateChild(pData, pChildCtx);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+startSingleChildOnce(instanceData *pData)
+{
+ DEFiRet;
+
+ assert(pData->bForceSingleInst);
+ CHKiConcCtrl(pthread_mutex_lock(pData->pSingleChildMut));
+
+ if(pData->pSingleChildCtx->bIsRunning)
+ goto finalize_it; /* child process already started: nothing to do */
+
+ iRet = startChild(pData, pData->pSingleChildCtx);
+
+finalize_it:
+ pthread_mutex_unlock(pData->pSingleChildMut);
+ RETiRet;
+}
+
+static void
+writeOutputToFile(outputCaptureCtx_t *pCtx, char *buf, ssize_t len)
+{
+ ssize_t written;
+ ssize_t offset = 0;
+
+ assert(pCtx->bIsRunning);
+ pthread_mutex_lock(&pCtx->mutWrite);
+
+ if(pCtx->fdFile == -1) {
+ if(pCtx->bFileErr) { /* discarding output because file couldn't be opened */
+ goto done;
+ }
+
+ pCtx->fdFile = open((char*)pCtx->szFileName, O_WRONLY | O_APPEND | O_CREAT,
+ pCtx->fCreateMode);
+ if(pCtx->fdFile == -1) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS, "omprog: error opening output file %s; "
+ "output from program will be discarded", pCtx->szFileName);
+ pCtx->bFileErr = 1; /* avoid reporting too many errors */
+ goto done;
+ }
+ }
+
+ do {
+ written = write(pCtx->fdFile, buf + offset, len - offset);
+ if(written == -1) {
+ if(errno == EINTR) {
+ continue; /* call interrupted: retry write */
+ }
+
+ if(!pCtx->bWriteErr) {
+ LogError(errno, RS_RET_SYS_ERR, "omprog: error writing to output file "
+ "(subsequent errors will not be reported)");
+ pCtx->bWriteErr = 1; /* avoid reporting too many errors */
+ }
+ break;
+ }
+
+ if(pCtx->bWriteErr) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: resumed writing to output file");
+ pCtx->bWriteErr = 0;
+ }
+
+ offset += written;
+ } while(offset < len);
+
+done:
+ pthread_mutex_unlock(&pCtx->mutWrite);
+}
+
+static void
+closeOutputFile(outputCaptureCtx_t *pCtx)
+{
+ DBGPRINTF("omprog: reopening output file upon reception of HUP signal\n");
+ pthread_mutex_lock(&pCtx->mutWrite);
+
+ if(pCtx->fdFile != -1) {
+ close(pCtx->fdFile);
+ pCtx->fdFile = -1;
+ }
+ pCtx->bFileErr = 0; /* if there was an error opening the file, we'll retry */
+
+ pthread_mutex_unlock(&pCtx->mutWrite);
+}
+
+/* This code runs in a dedicated thread. Captures the output of the child processes
+ * through a shared pipe (one reader and multiple writers), and writes the output
+ * to a file. The lines concurrently emmitted to stdout/stderr by the child processes
+ * will not appear intermingled in the output file if 1) the lines are short enough
+ * (less than PIPE_BUF bytes long: 4KB on Linux, and 512 bytes or more on other
+ * POSIX systems), and 2) the program outputs each line using a single 'write'
+ * syscall (line buffering mode). When a HUP signal is received, the output file is
+ * reopened (this provides support for external rotation of the file).
+ */
+static void *
+captureOutput(void *_pCtx) {
+ outputCaptureCtx_t *pCtx = (outputCaptureCtx_t *)_pCtx;
+ sigset_t sigSet;
+ char readBuf[OUTPUT_CAPTURE_BUFFER_SIZE];
+ ssize_t lenRead;
+
+ DBGPRINTF("omprog: starting output capture thread\n");
+
+ /* block signals for this thread (otherwise shutdown hangs on FreeBSD) */
+ sigfillset(&sigSet);
+ pthread_sigmask(SIG_SETMASK, &sigSet, NULL);
+
+ for(;;) {
+ lenRead = read(pCtx->fdPipe[0], readBuf, sizeof(readBuf));
+ if(lenRead == -1) {
+ if(errno == EINTR) {
+ continue; /* call interrupted: retry read */
+ }
+
+ if(!pCtx->bReadErr) {
+ LogError(errno, RS_RET_SYS_ERR, "omprog: error capturing output from program "
+ "(subsequent errors will not be reported)");
+ pCtx->bReadErr = 1; /* avoid reporting too many errors */
+ }
+ continue; /* continue with next line */
+ }
+
+ if(lenRead == 0) {
+ break; /* all write ends of pipe closed: exit loop and terminate thread */
+ }
+
+ if(pCtx->bReadErr) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: resumed capturing output from program");
+ pCtx->bReadErr = 0;
+ }
+
+ writeOutputToFile(pCtx, readBuf, lenRead);
+ }
+
+ DBGPRINTF("omprog: all output-capture pipe ends closed, terminating output capture thread\n");
+ pthread_mutex_lock(&pCtx->mutTerm);
+ pCtx->bIsRunning = 0;
+ pthread_cond_signal(&pCtx->condTerm);
+ pthread_mutex_unlock(&pCtx->mutTerm);
+ return NULL;
+}
+
+static rsRetVal
+allocOutputCaptureCtx(outputCaptureCtx_t **ppCtx)
+{
+ outputCaptureCtx_t *pCtx;
+ DEFiRet;
+
+ CHKmalloc(pCtx = calloc(1, sizeof(outputCaptureCtx_t)));
+ *ppCtx = pCtx;
+
+ pCtx->szFileName = NULL;
+ pCtx->fCreateMode = 0600;
+ pCtx->bIsRunning = 0;
+
+ CHKiConcCtrl(pthread_mutex_init(&pCtx->mutStart, NULL));
+ CHKiConcCtrl(pthread_mutex_init(&pCtx->mutWrite, NULL));
+ CHKiConcCtrl(pthread_mutex_init(&pCtx->mutTerm, NULL));
+ CHKiConcCtrl(pthread_cond_init(&pCtx->condTerm, NULL));
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+freeOutputCaptureCtx(outputCaptureCtx_t *pCtx) {
+ if(pCtx->szFileName != NULL) {
+ free(pCtx->szFileName);
+ }
+
+ pthread_cond_destroy(&pCtx->condTerm);
+ pthread_mutex_destroy(&pCtx->mutTerm);
+ pthread_mutex_destroy(&pCtx->mutWrite);
+ pthread_mutex_destroy(&pCtx->mutStart);
+
+ free(pCtx);
+}
+
+static rsRetVal
+startOutputCaptureOnce(outputCaptureCtx_t *pCtx)
+{
+ int pip[2] = { -1, -1 };
+ DEFiRet;
+
+ CHKiConcCtrl(pthread_mutex_lock(&pCtx->mutStart));
+
+ if(pCtx->bIsRunning)
+ goto finalize_it; /* output capture thread already started: nothing to do */
+
+ /* open a (single) pipe to capture output from (all) child processes */
+ if(pipe(pip) == -1) {
+ ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
+ }
+
+ pCtx->fdPipe[0] = pip[0];
+ pCtx->fdPipe[1] = pip[1];
+ pCtx->fdFile = -1;
+ pCtx->bFileErr = 0;
+ pCtx->bReadErr = 0;
+ pCtx->bWriteErr = 0;
+
+ /* start a thread to read lines from the pipe and write them to the output file */
+ CHKiConcCtrl(pthread_create(&pCtx->thrdID, NULL, captureOutput, (void *)pCtx));
+
+ pCtx->bIsRunning = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pip[0] != -1) {
+ close(pip[0]);
+ close(pip[1]);
+ }
+ pthread_mutex_unlock(&pCtx->mutStart);
+ RETiRet;
+}
+
+static void
+endOutputCapture(outputCaptureCtx_t *pCtx, long timeoutMs)
+{
+ struct timespec ts;
+ int bTimedOut;
+
+ assert(pCtx->bIsRunning);
+
+ /* close our write end of the output-capture pipe */
+ close(pCtx->fdPipe[1]);
+
+ /* the output capture thread will now terminate because there are no more
+ * writers attached to the output-capture pipe. However, if a child becomes
+ * unresponsive without closing its pipe end (assuming killUnresponsive=off),
+ * we would wait forever. To avoid this, we wait for the thread to terminate
+ * during a maximum timeout (we reuse the 'closeTimeout' setting for this).
+ */
+ timeoutComp(&ts, timeoutMs);
+ pthread_mutex_lock(&pCtx->mutTerm);
+ bTimedOut = 0;
+ while(pCtx->bIsRunning && !bTimedOut) {
+ if(pthread_cond_timedwait(&pCtx->condTerm, &pCtx->mutTerm, &ts) == ETIMEDOUT) {
+ bTimedOut = 1;
+ }
+ }
+ pthread_mutex_unlock(&pCtx->mutTerm);
+
+ if(bTimedOut) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: forcing termination of output capture "
+ "thread because of unresponsive child process");
+ pthread_cancel(pCtx->thrdID);
+ pCtx->bIsRunning = 0;
+ }
+
+ pthread_join(pCtx->thrdID, NULL);
+
+ /* close the read end of the output-capture pipe */
+ close(pCtx->fdPipe[0]);
+
+ /* close the output file (if it could be opened) */
+ if(pCtx->fdFile != -1) {
+ close(pCtx->fdFile);
+ }
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.szBinary = NULL; /* name of binary to call */
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->szBinary = NULL;
+ pData->szTemplateName = NULL;
+ pData->aParams = NULL;
+ pData->iParams = 0;
+ pData->bConfirmMessages = 0;
+ pData->block_if_err = 0;
+ pData->lConfirmTimeout = DEFAULT_CONFIRM_TIMEOUT_MS;
+ pData->bReportFailures = 0;
+ pData->bUseTransactions = 0;
+ pData->szBeginTransactionMark = NULL;
+ pData->szCommitTransactionMark = NULL;
+ pData->iHUPForward = NO_HUP_FORWARD;
+ pData->bSignalOnClose = 0;
+ pData->lCloseTimeout = DEFAULT_CLOSE_TIMEOUT_MS;
+ pData->bKillUnresponsive = -1;
+ pData->bForceSingleInst = 0;
+ pData->pSingleChildCtx = NULL;
+ pData->pSingleChildMut = NULL;
+ pData->pOutputCaptureCtx = NULL;
+ENDcreateInstance
+
+
+static rsRetVal
+postInitInstance(instanceData *pData)
+{
+ DEFiRet;
+
+ if(pData->bUseTransactions && pData->szBeginTransactionMark == NULL) {
+ pData->szBeginTransactionMark = (uchar*)strdup("BEGIN TRANSACTION");
+ }
+ if(pData->bUseTransactions && pData->szCommitTransactionMark == NULL) {
+ pData->szCommitTransactionMark = (uchar*)strdup("COMMIT TRANSACTION");
+ }
+ if(pData->bKillUnresponsive == -1) { /* default value: bSignalOnClose */
+ pData->bKillUnresponsive = pData->bSignalOnClose;
+ }
+
+ if(pData->pOutputCaptureCtx != NULL && pData->pOutputCaptureCtx->szFileName == NULL) {
+ LogError(0, RS_RET_CONF_PARAM_INVLD, "omprog: the 'fileCreateMode' parameter requires "
+ "specifying the 'output' parameter also");
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+
+ if(pData->bForceSingleInst) {
+ CHKmalloc(pData->pSingleChildMut = calloc(1, sizeof(pthread_mutex_t)));
+ CHKiConcCtrl(pthread_mutex_init(pData->pSingleChildMut, NULL));
+ CHKiRet(allocChildCtx(&pData->pSingleChildCtx));
+ /* do not start the child here. The config is still being parsed, and the daemon
+ has not been forked yet. When the daemon is forked, all fds will be closed! */
+ }
+
+finalize_it:
+ /* no cleanup needed on error: newActInst() will call freeInstance() */
+ RETiRet;
+}
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->pChildCtx = NULL;
+
+ if(pWrkrData->pData->pOutputCaptureCtx != NULL) {
+ CHKiRet(startOutputCaptureOnce(pWrkrData->pData->pOutputCaptureCtx));
+ }
+
+ if(pWrkrData->pData->bForceSingleInst) {
+ CHKiRet(startSingleChildOnce(pWrkrData->pData));
+ pWrkrData->pChildCtx = pData->pSingleChildCtx;
+ } else {
+ CHKiRet(allocChildCtx(&pWrkrData->pChildCtx));
+ CHKiRet(startChild(pWrkrData->pData, pWrkrData->pChildCtx));
+ }
+
+finalize_it:
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction) {
+ iRet = RS_RET_OK;
+ }
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ if(pWrkrData->pData->bForceSingleInst) {
+ CHKiConcCtrl(pthread_mutex_lock(pWrkrData->pData->pSingleChildMut));
+ }
+ if(!pWrkrData->pChildCtx->bIsRunning) {
+ CHKiRet(startChild(pWrkrData->pData, pWrkrData->pChildCtx));
+ }
+
+finalize_it:
+ if(pWrkrData->pData->bForceSingleInst) {
+ pthread_mutex_unlock(pWrkrData->pData->pSingleChildMut);
+ }
+ENDtryResume
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ if(pWrkrData->pData->bForceSingleInst) {
+ CHKiConcCtrl(pthread_mutex_lock(pWrkrData->pData->pSingleChildMut));
+ }
+ if(!pWrkrData->pData->bUseTransactions) {
+ FINALIZE;
+ }
+
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx,
+ pWrkrData->pData->szBeginTransactionMark));
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx, (uchar*) "\n"));
+
+ if(pWrkrData->pData->bConfirmMessages) {
+ CHKiRet(readStatus(pWrkrData->pData, pWrkrData->pChildCtx));
+ }
+
+finalize_it:
+ if(pWrkrData->pData->bForceSingleInst) {
+ pthread_mutex_unlock(pWrkrData->pData->pSingleChildMut);
+ }
+ENDbeginTransaction
+
+
+BEGINdoAction
+CODESTARTdoAction
+ if(pWrkrData->pData->bForceSingleInst) {
+ CHKiConcCtrl(pthread_mutex_lock(pWrkrData->pData->pSingleChildMut));
+ }
+ if(!pWrkrData->pChildCtx->bIsRunning) { /* should not occur */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ const uchar *const szMsg = ppString[0];
+ const size_t len = strlen((char*)szMsg);
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx, szMsg));
+ if(szMsg[len-1] != '\n') {
+ const time_t tt = time(NULL);
+ if(tt > pWrkrData->pData->block_if_err) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "omprog: messages must be terminated with \\n "
+ "at end of message, but this message is not: '%s'\n", ppString[0]);
+ pWrkrData->pData->block_if_err = tt + 30;
+ }
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx, (uchar*) "\n"));
+ }
+
+ if(pWrkrData->pData->bConfirmMessages) {
+ CHKiRet(readStatus(pWrkrData->pData, pWrkrData->pChildCtx));
+ } else if(pWrkrData->pData->bUseTransactions) {
+ /* ensure endTransaction will be called */
+ iRet = RS_RET_DEFER_COMMIT;
+ }
+
+finalize_it:
+ if(pWrkrData->pData->bForceSingleInst) {
+ pthread_mutex_unlock(pWrkrData->pData->pSingleChildMut);
+ }
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+ if(pWrkrData->pData->bForceSingleInst) {
+ CHKiConcCtrl(pthread_mutex_lock(pWrkrData->pData->pSingleChildMut));
+ }
+ if(!pWrkrData->pData->bUseTransactions) {
+ FINALIZE;
+ }
+
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx,
+ pWrkrData->pData->szCommitTransactionMark));
+ CHKiRet(sendMessage(pWrkrData->pData, pWrkrData->pChildCtx, (uchar*) "\n"));
+
+ if(pWrkrData->pData->bConfirmMessages) {
+ CHKiRet(readStatus(pWrkrData->pData, pWrkrData->pChildCtx));
+ }
+
+finalize_it:
+ if(pWrkrData->pData->bForceSingleInst) {
+ pthread_mutex_unlock(pWrkrData->pData->pSingleChildMut);
+ }
+ENDendTransaction
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if(!pWrkrData->pData->bForceSingleInst) {
+ if(pWrkrData->pChildCtx->bIsRunning) {
+ terminateChild(pWrkrData->pData, pWrkrData->pChildCtx);
+ }
+ free(pWrkrData->pChildCtx);
+ }
+ENDfreeWrkrInstance
+
+
+BEGINfreeInstance
+ int i;
+CODESTARTfreeInstance
+ if(pData->pSingleChildCtx != NULL) {
+ if(pData->pSingleChildCtx->bIsRunning) {
+ terminateChild(pData, pData->pSingleChildCtx);
+ }
+ free(pData->pSingleChildCtx);
+ }
+
+ if(pData->pSingleChildMut != NULL) {
+ pthread_mutex_destroy(pData->pSingleChildMut);
+ free(pData->pSingleChildMut);
+ }
+
+ if(pData->pOutputCaptureCtx != NULL) {
+ if(pData->pOutputCaptureCtx->bIsRunning) {
+ endOutputCapture(pData->pOutputCaptureCtx, pData->lCloseTimeout);
+ }
+ freeOutputCaptureCtx(pData->pOutputCaptureCtx);
+ }
+
+ free(pData->szBinary);
+ free(pData->szTemplateName);
+ free(pData->szBeginTransactionMark);
+ free(pData->szCommitTransactionMark);
+
+ if(pData->aParams != NULL) {
+ for (i = 0; i < pData->iParams; i++) {
+ free(pData->aParams[i]);
+ }
+ free(pData->aParams);
+ }
+ENDfreeInstance
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "binary")) {
+ CHKiRet(split_binary_parameters(&pData->szBinary, &pData->aParams, &pData->iParams,
+ pvals[i].val.d.estr));
+ } else if(!strcmp(actpblk.descr[i].name, "confirmMessages")) {
+ pData->bConfirmMessages = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "confirmTimeout")) {
+ pData->lConfirmTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "reportFailures")) {
+ pData->bReportFailures = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "useTransactions")) {
+ pData->bUseTransactions = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "beginTransactionMark")) {
+ pData->szBeginTransactionMark = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "commitTransactionMark")) {
+ pData->szCommitTransactionMark = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "forceSingleInstance")) {
+ pData->bForceSingleInst = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "signalOnClose")) {
+ pData->bSignalOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "closeTimeout")) {
+ pData->lCloseTimeout = (long) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "killUnresponsive")) {
+ pData->bKillUnresponsive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "hup.signal")) {
+ const char *const sig = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcmp(sig, "HUP"))
+ pData->iHUPForward = SIGHUP;
+ else if(!strcmp(sig, "USR1"))
+ pData->iHUPForward = SIGUSR1;
+ else if(!strcmp(sig, "USR2"))
+ pData->iHUPForward = SIGUSR2;
+ else if(!strcmp(sig, "INT"))
+ pData->iHUPForward = SIGINT;
+ else if(!strcmp(sig, "TERM"))
+ pData->iHUPForward = SIGTERM;
+ else {
+ LogError(0, RS_RET_CONF_PARAM_INVLD,
+ "omprog: hup.signal '%s' in hup.signal parameter", sig);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ free((void*)sig);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->szTemplateName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "output")) {
+ if(pData->pOutputCaptureCtx == NULL) {
+ CHKiRet(allocOutputCaptureCtx(&pData->pOutputCaptureCtx));
+ }
+ pData->pOutputCaptureCtx->szFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "fileCreateMode")) {
+ if(pData->pOutputCaptureCtx == NULL) {
+ CHKiRet(allocOutputCaptureCtx(&pData->pOutputCaptureCtx));
+ }
+ pData->pOutputCaptureCtx->fCreateMode = (mode_t) pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("omprog: program error, non-handled param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup(pData->szTemplateName == NULL ?
+ "RSYSLOG_FileFormat" : (char*)pData->szTemplateName), OMSR_NO_RQD_TPL_OPTS));
+
+ iRet = postInitInstance(pData);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omprog:", sizeof(":omprog:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omprog:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ if(cs.szBinary == NULL) {
+ LogError(0, RS_RET_CONF_RQRD_PARAM_MISSING, "no binary to execute specified");
+ ABORT_FINALIZE(RS_RET_CONF_RQRD_PARAM_MISSING);
+ }
+
+ CHKiRet(createInstance(&pData));
+ CHKmalloc(pData->szBinary = (uchar*) strdup((char*)cs.szBinary));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*) "RSYSLOG_FileFormat"));
+
+ iRet = postInitInstance(pData);
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ if(pData->bForceSingleInst && pData->iHUPForward != NO_HUP_FORWARD &&
+ pData->pSingleChildCtx->bIsRunning) {
+ DBGPRINTF("omprog: forwarding HUP to program '%s' (pid %ld) as signal %d\n",
+ pData->szBinary, (long) pData->pSingleChildCtx->pid, pData->iHUPForward);
+ kill(pData->pSingleChildCtx->pid, pData->iHUPForward);
+ }
+
+ if(pData->pOutputCaptureCtx != NULL && pData->pOutputCaptureCtx->bIsRunning) {
+ closeOutputFile(pData->pOutputCaptureCtx);
+ }
+ENDdoHUP
+
+
+BEGINdoHUPWrkr
+CODESTARTdoHUPWrkr
+ if(!pWrkrData->pData->bForceSingleInst && pWrkrData->pData->iHUPForward != NO_HUP_FORWARD &&
+ pWrkrData->pChildCtx->bIsRunning) {
+ DBGPRINTF("omprog: forwarding HUP to program '%s' (pid %ld) as signal %d\n",
+ pWrkrData->pData->szBinary, (long) pWrkrData->pChildCtx->pid,
+ pWrkrData->pData->iHUPForward);
+ kill(pWrkrData->pChildCtx->pid, pWrkrData->pData->iHUPForward);
+ }
+ENDdoHUPWrkr
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(cs.szBinary);
+ cs.szBinary = NULL;
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface */
+CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_doHUPWrkr
+ENDqueryEtryPt
+
+
+/* Reset legacy config variables for this module to default values.
+ */
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ free(cs.szBinary);
+ cs.szBinary = NULL;
+ RETiRet;
+}
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* tell engine which objects we need */
+
+ /* check that rsyslog core supports transactional plugins */
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ if (!bCoreSupportsBatching) {
+ LogError(0, NO_ERRCODE, "omprog: rsyslog core too old (does not support batching)");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomprogbinary", 0, eCmdHdlrGetWord, NULL, &cs.szBinary,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
diff --git a/plugins/omrelp/Makefile.am b/plugins/omrelp/Makefile.am
new file mode 100644
index 0000000..906aab4
--- /dev/null
+++ b/plugins/omrelp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = omrelp.la
+
+omrelp_la_SOURCES = omrelp.c
+omrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS)
+omrelp_la_LDFLAGS = -module -avoid-version
+omrelp_la_LIBADD = $(RELP_LIBS)
diff --git a/plugins/omrelp/Makefile.in b/plugins/omrelp/Makefile.in
new file mode 100644
index 0000000..c74c33a
--- /dev/null
+++ b/plugins/omrelp/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omrelp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omrelp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omrelp_la_OBJECTS = omrelp_la-omrelp.lo
+omrelp_la_OBJECTS = $(am_omrelp_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 =
+omrelp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omrelp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omrelp_la-omrelp.Plo
+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 = $(omrelp_la_SOURCES)
+DIST_SOURCES = $(omrelp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omrelp.la
+omrelp_la_SOURCES = omrelp.c
+omrelp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(RSRT_CFLAGS)
+omrelp_la_LDFLAGS = -module -avoid-version
+omrelp_la_LIBADD = $(RELP_LIBS)
+all: 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) --gnu plugins/omrelp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omrelp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omrelp.la: $(omrelp_la_OBJECTS) $(omrelp_la_DEPENDENCIES) $(EXTRA_omrelp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omrelp_la_LINK) -rpath $(pkglibdir) $(omrelp_la_OBJECTS) $(omrelp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omrelp_la-omrelp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omrelp_la-omrelp.lo: omrelp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omrelp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omrelp_la-omrelp.lo -MD -MP -MF $(DEPDIR)/omrelp_la-omrelp.Tpo -c -o omrelp_la-omrelp.lo `test -f 'omrelp.c' || echo '$(srcdir)/'`omrelp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omrelp_la-omrelp.Tpo $(DEPDIR)/omrelp_la-omrelp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omrelp.c' object='omrelp_la-omrelp.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) $(omrelp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omrelp_la-omrelp.lo `test -f 'omrelp.c' || echo '$(srcdir)/'`omrelp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omrelp_la-omrelp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omrelp_la-omrelp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c
new file mode 100644
index 0000000..5fc1dcc
--- /dev/null
+++ b/plugins/omrelp/omrelp.c
@@ -0,0 +1,826 @@
+/* omrelp.c
+ *
+ * This is the implementation of the RELP output module.
+ *
+ * Note that when multiple action workers are activated, we currently
+ * also create multiple actions. This may be the source of some mild
+ * message loss (!) if the worker instance is shut down while the
+ * connection to the remote system is in retry state.
+ * TODO: think if we should implement a mode where we do NOT
+ * support multiple action worker instances. This would be
+ * slower, but not have this loss opportunity. But it should
+ * definitely be optional and by default off due to the
+ * performance implications (and given the fact that message
+ * loss is pretty unlikely in usual cases).
+ *
+ *
+ * File begun on 2008-03-13 by RGerhards
+ *
+ * Copyright 2008-2019 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <librelp.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "debug.h"
+#include "parserif.h"
+#include "unicode-helper.h"
+
+#ifndef RELP_DFLT_PT
+# define RELP_DFLT_PT "514"
+#endif
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omrelp")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+
+#define DFLT_ENABLE_TLS 0
+#define DFLT_ENABLE_TLSZIP 0
+
+static relpEngine_t *pRelpEngine; /* our relp engine */
+
+typedef struct _instanceData {
+ uchar *target;
+ uchar *port;
+ int sizeWindow; /**< the RELP window size - 0=use default */
+ unsigned timeout;
+ int connTimeout;
+ unsigned rebindInterval;
+ sbool bEnableTLS;
+ sbool bEnableTLSZip;
+ sbool bHadAuthFail; /**< set on auth failure, will cause retry to disable action */
+ uchar *pristring; /* GnuTLS priority string (NULL if not to be provided) */
+ uchar *authmode;
+ uchar *caCertFile;
+ uchar *myCertFile;
+ uchar *myPrivKeyFile;
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ uchar *tlscfgcmd;
+#endif
+ uchar *tplName;
+ uchar *localClientIP;
+ struct {
+ int nmemb;
+ uchar **name;
+ } permittedPeers;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ int bInitialConnect; /* is this the initial connection request of our module? (0-no, 1-yes) */
+ int bIsConnected; /* currently connected to server? 0 - no, 1 - yes */
+ int bIsSuspended; /* currently suspended (than no more error messages) */
+ relpClt_t *pRelpClt; /* relp client for this instance */
+ unsigned nSent; /* number msgs sent - for rebind support */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t __attribute__((unused)) cs;
+
+static rsRetVal doCreateRelpClient(instanceData *pData, relpClt_t **pRelpClt);
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ const char *tlslib;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "tls.tlslib", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 1 },
+ { "tls", eCmdHdlrBinary, 0 },
+ { "tls.compression", eCmdHdlrBinary, 0 },
+ { "tls.prioritystring", eCmdHdlrString, 0 },
+ { "tls.cacert", eCmdHdlrString, 0 },
+ { "tls.mycert", eCmdHdlrString, 0 },
+ { "tls.myprivkey", eCmdHdlrString, 0 },
+ { "tls.authmode", eCmdHdlrString, 0 },
+ { "tls.tlscfgcmd", eCmdHdlrString, 0 },
+ { "tls.permittedpeer", eCmdHdlrArray, 0 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "rebindinterval", eCmdHdlrInt, 0 },
+ { "windowsize", eCmdHdlrInt, 0 },
+ { "timeout", eCmdHdlrInt, 0 },
+ { "conn.timeout", eCmdHdlrInt, 0 },
+ { "localclientip", eCmdHdlrGetWord, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+/* We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use 514 as default (what probably
+ * is not a really bright idea, but kept for backward compatibility).
+ */
+
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wformat_nonliteral
+static void __attribute__((format(printf, 1, 2)))
+omrelp_dbgprintf(const char *fmt, ...)
+{
+ va_list ap;
+ char pszWriteBuf[32*1024+1]; //this function has to be able to
+ /*generate a buffer longer than that of r_dbgprintf, so
+ r_dbgprintf can properly truncate*/
+ if(!(Debug && debugging_on)) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
+ va_end(ap);
+ r_dbgprintf("omrelp.c", "%s", pszWriteBuf);
+}
+PRAGMA_DIAGNOSTIC_POP
+
+
+static uchar *getRelpPt(instanceData *pData)
+{
+ assert(pData != NULL);
+ if(pData->port == NULL)
+ return((uchar*)RELP_DFLT_PT);
+ else
+ return(pData->port);
+}
+
+static void
+onErr(void *pUsr, char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t*) pUsr;
+ LogError(0, RS_RET_RELP_AUTH_FAIL, "omrelp[%s:%s]: error '%s', object "
+ " '%s' - action may not work as intended",
+ pWrkrData->pData->target, pWrkrData->pData->port, errmesg, objinfo);
+}
+
+static void
+onGenericErr(char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ LogError(0, RS_RET_RELP_ERR, "omrelp: librelp error '%s', object "
+ "'%s' - action may not work as intended",
+ errmesg, objinfo);
+}
+
+static void
+onAuthErr(void *pUsr, char *authinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ instanceData *pData = ((wrkrInstanceData_t*) pUsr)->pData;
+ LogError(0, RS_RET_RELP_AUTH_FAIL, "omrelp[%s:%s]: authentication error '%s', peer "
+ "is '%s' - DISABLING action", pData->target, pData->port, errmesg, authinfo);
+ pData->bHadAuthFail = 1;
+}
+
+static rsRetVal
+doCreateRelpClient(instanceData *pData, relpClt_t **pRelpClt)
+{
+ int i;
+ DEFiRet;
+
+ if(relpEngineCltConstruct(pRelpEngine, pRelpClt) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpCltSetTimeout(*pRelpClt, pData->timeout) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpCltSetConnTimeout(*pRelpClt, pData->connTimeout) != RELP_RET_OK) {
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+ if(relpCltSetWindowSize(*pRelpClt, pData->sizeWindow) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(pData->bEnableTLS) {
+ if(relpCltEnableTLS(*pRelpClt) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(pData->bEnableTLSZip) {
+ if(relpCltEnableTLSZip(*pRelpClt) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+ if(relpCltSetGnuTLSPriString(*pRelpClt, (char*) pData->pristring) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+
+
+ if(relpCltSetAuthMode(*pRelpClt, (char*) pData->authmode) != RELP_RET_OK) {
+ LogError(0, RS_RET_RELP_ERR,
+ "omrelp: invalid auth mode '%s'\n", pData->authmode);
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+
+ if(relpCltSetCACert(*pRelpClt, (char*) pData->caCertFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpCltSetOwnCert(*pRelpClt, (char*) pData->myCertFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpCltSetPrivKey(*pRelpClt, (char*) pData->myPrivKeyFile) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ if (pData->tlscfgcmd != NULL) {
+ if(relpCltSetTlsConfigCmd(*pRelpClt, (char*) pData->tlscfgcmd) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+#endif
+ for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
+ relpCltAddPermittedPeer(*pRelpClt, (char*)pData->permittedPeers.name[i]);
+ }
+ }
+ if(pData->localClientIP != NULL) {
+ if(relpCltSetClientIP(*pRelpClt, pData->localClientIP) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ }
+finalize_it:
+
+ RETiRet;
+}
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL;
+ runModConf = pModConf;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free((void*)pModConf->tlslib);
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->sizeWindow = 0;
+ pData->timeout = 90;
+ pData->connTimeout = 10;
+ pData->rebindInterval = 0;
+ pData->bEnableTLS = DFLT_ENABLE_TLS;
+ pData->bEnableTLSZip = DFLT_ENABLE_TLSZIP;
+ pData->bHadAuthFail = 0;
+ pData->pristring = NULL;
+ pData->authmode = NULL;
+ pData->localClientIP = NULL;
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ pData->tlscfgcmd = NULL;
+#endif
+ pData->permittedPeers.nmemb = 0;
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->pRelpClt = NULL;
+ iRet = doCreateRelpClient(pWrkrData->pData, &pWrkrData->pRelpClt);
+ if(relpCltSetUsrPtr(pWrkrData->pRelpClt, pWrkrData) != RELP_RET_OK)
+ LogError(0, RS_RET_NO_ERRCODE, "omrelp: error when creating relp client");
+ pWrkrData->bInitialConnect = 1;
+ pWrkrData->nSent = 0;
+ENDcreateWrkrInstance
+
+BEGINfreeInstance
+ int i;
+CODESTARTfreeInstance
+ free(pData->target);
+ free(pData->port);
+ free(pData->tplName);
+ free(pData->pristring);
+ free(pData->authmode);
+ free(pData->localClientIP);
+ free(pData->caCertFile);
+ free(pData->myCertFile);
+ free(pData->myPrivKeyFile);
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ free(pData->tlscfgcmd);
+#endif
+ if(pData->permittedPeers.name != NULL) {
+ for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
+ free(pData->permittedPeers.name[i]);
+ }
+ }
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ if(pWrkrData->pRelpClt != NULL)
+ relpEngineCltDestruct(pRelpEngine, &pWrkrData->pRelpClt);
+ENDfreeWrkrInstance
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->target = NULL;
+ pData->port = NULL;
+ pData->tplName = NULL;
+ pData->timeout = 90;
+ pData->connTimeout = 10;
+ pData->sizeWindow = 0;
+ pData->rebindInterval = 0;
+ pData->bEnableTLS = DFLT_ENABLE_TLS;
+ pData->bEnableTLSZip = DFLT_ENABLE_TLSZIP;
+ pData->pristring = NULL;
+ pData->authmode = NULL;
+ if(glbl.GetSourceIPofLocalClient() == NULL)
+ pData->localClientIP = NULL;
+ else
+ pData->localClientIP = (uchar*)strdup((char*)glbl.GetSourceIPofLocalClient());
+ pData->caCertFile = NULL;
+ pData->myCertFile = NULL;
+ pData->myPrivKeyFile = NULL;
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ pData->tlscfgcmd = NULL;
+#endif
+ pData->permittedPeers.name = NULL;
+ pData->permittedPeers.nmemb = 0;
+}
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tlslib = NULL;
+ /* create our relp engine */
+ CHKiRet(relpEngineConstruct(&pRelpEngine));
+ CHKiRet(relpEngineSetDbgprint(pRelpEngine, (void (*)(char *, ...))omrelp_dbgprintf));
+ CHKiRet(relpEngineSetOnAuthErr(pRelpEngine, onAuthErr));
+ CHKiRet(relpEngineSetOnGenericErr(pRelpEngine, onGenericErr));
+ CHKiRet(relpEngineSetOnErr(pRelpEngine, onErr));
+ CHKiRet(relpEngineSetEnableCmd(pRelpEngine, (uchar*) "syslog", eRelpCmdState_Required));
+finalize_it:
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("imrelp: error processing module config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omrelp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+ if(!strcmp(modpblk.descr[i].name, "tls.tlslib")) {
+ #if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ loadModConf->tlslib = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(relpEngineSetTLSLibByName(pRelpEngine, loadModConf->tlslib) != RELP_RET_OK) {
+ LogMsg(0, RS_RET_CONF_PARAM_INVLD, LOG_WARNING,
+ "omrelp: tlslib '%s' not accepted as valid by librelp - using default",
+ loadModConf->tlslib);
+ }
+ #else
+ LogError(0, RS_RET_NOT_IMPLEMENTED,
+ "omrelp warning: parameter tls.tlslib ignored - librelp does not support "
+ "this API call. Using whatever librelp was compiled with.");
+ #endif
+ } else {
+ dbgprintf("imfile: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i,j;
+ FILE *fp;
+ relpClt_t *pRelpClt = NULL;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->target = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "localclientip")) {
+ pData->localClientIP = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "timeout")) {
+ pData->timeout = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "conn.timeout")) {
+ pData->connTimeout = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "rebindinterval")) {
+ pData->rebindInterval = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "windowsize")) {
+ pData->sizeWindow = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "tls")) {
+ pData->bEnableTLS = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "tls.compression")) {
+ pData->bEnableTLSZip = (unsigned) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "tls.prioritystring")) {
+ pData->pristring = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) {
+ pData->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->caCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->caCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) {
+ pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myCertFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->myCertFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) {
+ pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ fp = fopen((const char*)pData->myPrivKeyFile, "r");
+ if(fp == NULL) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_NO_FILE_ACCESS,
+ "error: certificate file %s couldn't be accessed: %s\n",
+ pData->myPrivKeyFile, errStr);
+ } else {
+ fclose(fp);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tls.tlscfgcmd")) {
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ pData->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+#else
+ LogError(0, RS_RET_NOT_IMPLEMENTED, "omrelp: librelp does not support input parameter "
+ "'tls.tlscfgcmd'; it probably is too old (1.5.0 or higher should be fine); "
+ "ignoring setting now.");
+#endif
+ } else if(!strcmp(actpblk.descr[i].name, "tls.authmode")) {
+ pData->authmode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tls.permittedpeer")) {
+ pData->permittedPeers.nmemb = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(pData->permittedPeers.name =
+ malloc(sizeof(uchar*) * pData->permittedPeers.nmemb));
+ for(j = 0 ; j < pData->permittedPeers.nmemb ; ++j) {
+ pData->permittedPeers.name[j] = (uchar*)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ }
+ } else {
+ dbgprintf("omrelp: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_ForwardFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ iRet = doCreateRelpClient(pData, &pRelpClt);
+ if(pRelpClt != NULL)
+ relpEngineCltDestruct(pRelpEngine, &pRelpClt);
+
+CODE_STD_FINALIZERnewActInst
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+BEGINSetShutdownImmdtPtr
+CODESTARTSetShutdownImmdtPtr
+ relpEngineSetShutdownImmdtPtr(pRelpEngine, pPtr);
+ DBGPRINTF("omrelp: shutdownImmediate ptr now is %p\n", pPtr);
+ENDSetShutdownImmdtPtr
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("RELP/%s", pData->target);
+ENDdbgPrintInstInfo
+
+
+/* try to connect to server
+ * rgerhards, 2008-03-21
+ */
+static rsRetVal ATTR_NONNULL()
+doConnect(wrkrInstanceData_t *const pWrkrData)
+{
+ DEFiRet;
+
+ if(pWrkrData->bInitialConnect) {
+ iRet = relpCltConnect(pWrkrData->pRelpClt, glbl.GetDefPFFamily(runModConf->pConf),
+ getRelpPt(pWrkrData->pData), pWrkrData->pData->target);
+ if(iRet == RELP_RET_OK)
+ pWrkrData->bInitialConnect = 0;
+ } else {
+ iRet = relpCltReconnect(pWrkrData->pRelpClt);
+ }
+
+ if(iRet == RELP_RET_OK) {
+ pWrkrData->bIsConnected = 1;
+ } else if(iRet == RELP_RET_ERR_NO_TLS) {
+ LogError(0, iRet, "omrelp: Could not connect, librelp does NOT "
+ "support TLS (most probably GnuTLS lib "
+ "is too old)!");
+ FINALIZE;
+ } else if(iRet == RELP_RET_ERR_NO_TLS_AUTH) {
+ LogError(0, iRet, "omrelp: could not activate relp TLS with "
+ "authentication, librelp does not support it "
+ "(most probably GnuTLS lib is too old)! "
+ "Note: anonymous TLS is probably supported.");
+ FINALIZE;
+ } else {
+ if(pWrkrData->bIsSuspended == 0) {
+ LogError(0, RS_RET_RELP_ERR, "omrelp: could not connect to "
+ "remote server, librelp error %d", iRet);
+ }
+ pWrkrData->bIsConnected = 0;
+ pWrkrData->bIsSuspended = 1;
+ iRet = RS_RET_SUSPENDED;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ if(pWrkrData->pData->bHadAuthFail) {
+ ABORT_FINALIZE(RS_RET_DISABLE_ACTION);
+ }
+ iRet = doConnect(pWrkrData);
+finalize_it:
+ENDtryResume
+
+static rsRetVal
+doRebind(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ DBGPRINTF("omrelp: destructing relp client due to rebindInterval\n");
+ CHKiRet(relpEngineCltDestruct(pRelpEngine, &pWrkrData->pRelpClt));
+ pWrkrData->bIsConnected = 0;
+ CHKiRet(doCreateRelpClient(pWrkrData->pData, &pWrkrData->pRelpClt));
+ if(relpCltSetUsrPtr(pWrkrData->pRelpClt, pWrkrData) != RELP_RET_OK)
+ LogError(0, RS_RET_NO_ERRCODE, "omrelp: error when creating relp client");
+ pWrkrData->bInitialConnect = 1;
+ pWrkrData->nSent = 0;
+finalize_it:
+ RETiRet;
+}
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ DBGPRINTF("omrelp: beginTransaction\n");
+ if(!pWrkrData->bIsConnected) {
+ CHKiRet(doConnect(pWrkrData));
+ }
+ relpCltHintBurstBegin(pWrkrData->pRelpClt);
+finalize_it:
+ENDbeginTransaction
+
+BEGINdoAction
+ uchar *pMsg; /* temporary buffering */
+ size_t lenMsg;
+ relpRetVal ret;
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ dbgprintf(" %s:%s/RELP\n", pData->target, getRelpPt(pData));
+
+ if(!pWrkrData->bIsConnected) {
+ CHKiRet(doConnect(pWrkrData));
+ }
+
+ pMsg = ppString[0];
+ lenMsg = strlen((char*) pMsg); /* TODO: don't we get this? */
+
+ /* we need to truncate oversize msgs - no way around that... */
+ if((int) lenMsg > glbl.GetMaxLine(runModConf->pConf))
+ lenMsg = glbl.GetMaxLine(runModConf->pConf);
+
+ /* forward */
+ ret = relpCltSendSyslog(pWrkrData->pRelpClt, (uchar*) pMsg, lenMsg);
+ if(ret != RELP_RET_OK) {
+ LogError(0, RS_RET_RELP_ERR, "librelp error %d%s forwarding "
+ "to server %s:%s - suspending\n", ret,
+ (ret == RELP_RET_SESSION_BROKEN) ?
+ "[connection broken]" : "",
+ pData->target, getRelpPt(pData));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+
+ if(pData->rebindInterval != 0 &&
+ (++pWrkrData->nSent >= pData->rebindInterval)) {
+ doRebind(pWrkrData);
+ }
+finalize_it:
+ if(pData->bHadAuthFail)
+ iRet = RS_RET_DISABLE_ACTION;
+ if(iRet == RS_RET_OK) {
+ /* we mimic non-commit, as otherwise our endTransaction handler
+ * will not get called. While this is not 100% correct, the worst
+ * that can happen is some message duplication, something that
+ * rsyslog generally accepts and prefers over message loss.
+ */
+ iRet = RS_RET_PREVIOUS_COMMITTED;
+ } else if(iRet == RS_RET_SUSPENDED) {
+ pWrkrData->bIsSuspended = 1;
+ }
+ENDdoAction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+ DBGPRINTF("omrelp: endTransaction, connected %d\n", pWrkrData->bIsConnected);
+ if(pWrkrData->bIsConnected) {
+ relpCltHintBurstEnd(pWrkrData->pRelpClt);
+ }
+ENDendTransaction
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+ int bErr;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(!strncmp((char*) p, ":omrelp:", sizeof(":omrelp:") - 1)) {
+ p += sizeof(":omrelp:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ FINALIZE;
+
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ if(*p == '[') { /* everything is hostname upto ']' */
+ ++p; /* skip '[' */
+ for(q = p ; *p && *p != ']' ; ++p)
+ /* JUST SKIP */;
+ if(*p == ']') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ ++p; /* eat it */
+ }
+ } else { /* traditional view of hostname */
+ for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p)
+ /* JUST SKIP */;
+ }
+
+ pData->port = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ pData->port = malloc(i + 1);
+ if(pData->port == NULL) {
+ LogError(0, NO_ERRCODE, "Could not get memory to store relp port, "
+ "using default port, results may not be what you intend\n");
+ /* we leave f_forw.port set to NULL, this is then handled by getRelpPt() */
+ } else {
+ memcpy(pData->port, tmp, i);
+ *(pData->port + i) = '\0';
+ }
+ }
+
+ /* now skip to template */
+ bErr = 0;
+ while(*p && *p != ';') {
+ if(*p && *p != ';' && !isspace((int) *p)) {
+ if(bErr == 0) { /* only 1 error msg! */
+ bErr = 1;
+ errno = 0;
+ LogError(0, NO_ERRCODE, "invalid selector line (port), probably not doing "
+ "what was intended");
+ }
+ }
+ ++p;
+ }
+
+ if(*p == ';') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ CHKmalloc(pData->target = ustrdup(q));
+ *p = ';';
+ } else {
+ CHKmalloc(pData->target = ustrdup(q));
+ }
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_ForwardFormat"));
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ relpEngineDestruct(&pRelpEngine);
+
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES
+CODEqueryEtryPt_SetShutdownImmdtPtr
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* tell which objects we need */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDmodInit
diff --git a/plugins/omruleset/Makefile.am b/plugins/omruleset/Makefile.am
new file mode 100644
index 0000000..fdd91a6
--- /dev/null
+++ b/plugins/omruleset/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omruleset.la
+
+omruleset_la_SOURCES = omruleset.c
+omruleset_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omruleset_la_LDFLAGS = -module -avoid-version
+omruleset_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/omruleset/Makefile.in b/plugins/omruleset/Makefile.in
new file mode 100644
index 0000000..c559138
--- /dev/null
+++ b/plugins/omruleset/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omruleset
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omruleset_la_DEPENDENCIES =
+am_omruleset_la_OBJECTS = omruleset_la-omruleset.lo
+omruleset_la_OBJECTS = $(am_omruleset_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 =
+omruleset_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omruleset_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omruleset_la-omruleset.Plo
+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 = $(omruleset_la_SOURCES)
+DIST_SOURCES = $(omruleset_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omruleset.la
+omruleset_la_SOURCES = omruleset.c
+omruleset_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omruleset_la_LDFLAGS = -module -avoid-version
+omruleset_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/omruleset/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omruleset/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omruleset.la: $(omruleset_la_OBJECTS) $(omruleset_la_DEPENDENCIES) $(EXTRA_omruleset_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omruleset_la_LINK) -rpath $(pkglibdir) $(omruleset_la_OBJECTS) $(omruleset_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omruleset_la-omruleset.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omruleset_la-omruleset.lo: omruleset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omruleset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omruleset_la-omruleset.lo -MD -MP -MF $(DEPDIR)/omruleset_la-omruleset.Tpo -c -o omruleset_la-omruleset.lo `test -f 'omruleset.c' || echo '$(srcdir)/'`omruleset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omruleset_la-omruleset.Tpo $(DEPDIR)/omruleset_la-omruleset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omruleset.c' object='omruleset_la-omruleset.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) $(omruleset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omruleset_la-omruleset.lo `test -f 'omruleset.c' || echo '$(srcdir)/'`omruleset.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omruleset_la-omruleset.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omruleset_la-omruleset.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omruleset/omruleset.c b/plugins/omruleset/omruleset.c
new file mode 100644
index 0000000..fd0bcef
--- /dev/null
+++ b/plugins/omruleset/omruleset.c
@@ -0,0 +1,274 @@
+/* omruleset.c
+ * This is a very special output module. It permits to pass a message object
+ * to another rule set. While this is a very simple action, it enables very
+ * complex configurations, e.g. it supports high-speed "and" conditions, sending
+ * data to the same file in a non-racy way, include functionality as well as
+ * some high-performance optimizations (in case the rule sets have the necessary
+ * queue definitions). So while this code is small, it is pretty important.
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * File begun on 2009-11-02 by RGerhards
+ *
+ * Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "ruleset.h"
+#include "cfsysline.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omruleset")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+DEFobjCurrIf(ruleset);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+
+typedef struct _instanceData {
+ ruleset_t *pRuleset; /* ruleset to enqueue to */
+ uchar *pszRulesetName; /* primarily for debugging/display purposes */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ ruleset_t *pRuleset; /* ruleset to enqueue message to (NULL = Default, not recommended) */
+ uchar *pszRulesetName;
+} configSettings_t;
+static configSettings_t cs;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->pszRulesetName);
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omruleset target %s[%p]\n", (char*) pData->pszRulesetName, pData->pRuleset);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+/* Note that we change the flow control type to "no delay", because at this point in
+ * rsyslog procesing we can not really slow down the producer any longer, as we already
+ * work off a queue. So a delay would just block out execution for longer than needed.
+ */
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg;
+CODESTARTdoAction
+ CHKmalloc(pMsg = MsgDup(ppMsg[0]));
+ DBGPRINTF(":omruleset: forwarding message %p to ruleset %s[%p]\n", pMsg,
+ (char*) pWrkrData->pData->pszRulesetName, pWrkrData->pData->pRuleset);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ MsgSetRuleset(pMsg, pWrkrData->pData->pRuleset);
+ /* Note: we intentionally use submitMsg2() here, as we process messages
+ * that were already run through the rate-limiter. So it is (at least)
+ * questionable if they were rate-limited again.
+ */
+ submitMsg2(pMsg);
+finalize_it:
+ENDdoAction
+
+/* set the ruleset name */
+static rsRetVal
+setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ rsRetVal localRet;
+ DEFiRet;
+
+ localRet = ruleset.GetRuleset(ourConf, &cs.pRuleset, pszName);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, RS_RET_RULESET_NOT_FOUND, "error: ruleset '%s' not found - ignored", pszName);
+ }
+ CHKiRet(localRet);
+ cs.pszRulesetName = pszName; /* save for later display purposes */
+
+finalize_it:
+ if(iRet != RS_RET_OK) { /* cleanup needed? */
+ free(pszName);
+ }
+ RETiRet;
+}
+
+
+BEGINparseSelectorAct
+ int iTplOpts;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omruleset:", sizeof(":omruleset:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ if(cs.pRuleset == NULL) {
+ LogError(0, RS_RET_NO_RULESET, "error: no ruleset was specified, use "
+ "$ActionOmrulesetRulesetName directive first!");
+ ABORT_FINALIZE(RS_RET_NO_RULESET);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omruleset:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING,
+ "warning: omruleset is deprecated, consider "
+ "using the 'call' statement instead");
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ iTplOpts = OMSR_TPL_AS_MSG;
+ /* we call the message below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, iTplOpts, (uchar*) "RSYSLOG_FileFormat"));
+ pData->pRuleset = cs.pRuleset;
+ pData->pszRulesetName = cs.pszRulesetName;
+ cs.pRuleset = NULL;
+/* re-set, because there is a high risk of unwanted behavior if we leave it in! */
+ cs.pszRulesetName = NULL;
+/* note: we must not free, as we handed over this pointer to the instanceDat to the instanceDataa! */
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(cs.pszRulesetName);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.pRuleset = NULL;
+ free(cs.pszRulesetName);
+ cs.pszRulesetName = NULL;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported; /* does core support template passing as an array? */
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, what is not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("omruleset: msg-passing is not supported by rsyslog core, can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING,
+ "warning: omruleset is deprecated, consider "
+ "using the 'call' statement instead");
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomrulesetrulesetname", 0, eCmdHdlrGetWord,
+ setRuleset, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/omsnmp/Makefile.am b/plugins/omsnmp/Makefile.am
new file mode 100644
index 0000000..f75fb09
--- /dev/null
+++ b/plugins/omsnmp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = omsnmp.la
+
+omsnmp_la_SOURCES = omsnmp.c omsnmp.h
+omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omsnmp_la_LDFLAGS = -module -avoid-version
+omsnmp_la_LIBADD = $(SNMP_LIBS)
diff --git a/plugins/omsnmp/Makefile.in b/plugins/omsnmp/Makefile.in
new file mode 100644
index 0000000..10ab9b4
--- /dev/null
+++ b/plugins/omsnmp/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omsnmp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omsnmp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omsnmp_la_OBJECTS = omsnmp_la-omsnmp.lo
+omsnmp_la_OBJECTS = $(am_omsnmp_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 =
+omsnmp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omsnmp_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omsnmp_la-omsnmp.Plo
+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 = $(omsnmp_la_SOURCES)
+DIST_SOURCES = $(omsnmp_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omsnmp.la
+omsnmp_la_SOURCES = omsnmp.c omsnmp.h
+omsnmp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omsnmp_la_LDFLAGS = -module -avoid-version
+omsnmp_la_LIBADD = $(SNMP_LIBS)
+all: 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) --gnu plugins/omsnmp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omsnmp/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omsnmp.la: $(omsnmp_la_OBJECTS) $(omsnmp_la_DEPENDENCIES) $(EXTRA_omsnmp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omsnmp_la_LINK) -rpath $(pkglibdir) $(omsnmp_la_OBJECTS) $(omsnmp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omsnmp_la-omsnmp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omsnmp_la-omsnmp.lo: omsnmp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omsnmp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omsnmp_la-omsnmp.lo -MD -MP -MF $(DEPDIR)/omsnmp_la-omsnmp.Tpo -c -o omsnmp_la-omsnmp.lo `test -f 'omsnmp.c' || echo '$(srcdir)/'`omsnmp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omsnmp_la-omsnmp.Tpo $(DEPDIR)/omsnmp_la-omsnmp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omsnmp.c' object='omsnmp_la-omsnmp.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) $(omsnmp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omsnmp_la-omsnmp.lo `test -f 'omsnmp.c' || echo '$(srcdir)/'`omsnmp.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omsnmp_la-omsnmp.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omsnmp_la-omsnmp.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omsnmp/omsnmp.c b/plugins/omsnmp/omsnmp.c
new file mode 100644
index 0000000..fbf4dfe
--- /dev/null
+++ b/plugins/omsnmp/omsnmp.c
@@ -0,0 +1,658 @@
+/* omsnmp.c
+ *
+ * This module sends an snmp trap.
+ *
+ * Copyright 2007-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <assert.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "cfsysline.h"
+#include "module-template.h"
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include "omsnmp.h"
+#include "errmsg.h"
+#include "parserif.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omsnmp")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
+static oid objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+
+/* 4 */
+#define SNMP_SOURCETEMPLATE "\"%fromhost-ip%\""
+
+
+typedef struct _instanceData {
+ uchar *szTransport; /* Transport - Can be udp, tcp, udp6, tcp6 and other types
+ supported by NET-SNMP */
+ uchar *szTarget; /* IP/hostname of Snmp Target*/
+ uchar *szCommunity; /* Snmp Community */
+ uchar *szEnterpriseOID; /* Snmp Enterprise OID-default is (1.3.6.1.4.1.3.1.1 = enterprises.cmu.1.1) */
+ uchar *szSnmpTrapOID; /* Snmp Trap OID - default is (1.3.6.1.4.1.19406.1.2.1 =
+ ADISCON-MONITORWARE-MIB::syslogtrap) */
+ uchar *szSyslogMessageOID; /* Snmp OID used for the Syslog Message:
+ * default is 1.3.6.1.4.1.19406.1.1.2.1 - ADISCON-MONITORWARE-MIB::syslogMsg
+ * You will need the ADISCON-MONITORWARE-MIB and ADISCON-MIB mibs installed on the receiver
+ * side in order to decode this mib.
+ * Downloads of these mib files can be found here:
+ * http://www.adiscon.org/download/ADISCON-MONITORWARE-MIB.txt
+ * http://www.adiscon.org/download/ADISCON-MIB.txt
+ */
+ uchar *szSnmpV1Source; /* If PDU source property needs to be overwritten, only valid for SNMPv1*/
+
+ int iPort; /* Target Port */
+ int iSNMPVersion; /* SNMP Version to use */
+ int iTrapType; /* Snmp TrapType or GenericType */
+ int iSpecificType; /* Snmp Specific Type */
+
+ uchar *tplName; /* format template to use */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ netsnmp_session *snmpsession; /* Holds to SNMP Session, NULL if not initialized */
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ uchar* pszTransport; /* default transport */
+ uchar* pszTarget;
+ /* note using an unsigned for a port number is not a good idea from an IPv6 point of view */
+ int iPort;
+ int iSNMPVersion; /* 0 Means SNMPv1, 1 Means SNMPv2c */
+ uchar* pszCommunity;
+ uchar* pszEnterpriseOID;
+ uchar* pszSnmpTrapOID;
+ uchar* pszSyslogMessageOID;
+
+ int iSpecificType;
+ int iTrapType; /*Default is SNMP_TRAP_ENTERPRISESPECIFIC */
+ /*
+ Possible Values
+ SNMP_TRAP_COLDSTART (0)
+ SNMP_TRAP_WARMSTART (1)
+ SNMP_TRAP_LINKDOWN (2)
+ SNMP_TRAP_LINKUP (3)
+ SNMP_TRAP_AUTHFAIL (4)
+ SNMP_TRAP_EGPNEIGHBORLOSS (5)
+ SNMP_TRAP_ENTERPRISESPECIFIC (6)
+ */
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "server", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "port", eCmdHdlrInt, 0 },
+ { "transport", eCmdHdlrString, 0 },
+ { "version", eCmdHdlrInt, 0 },
+ { "community", eCmdHdlrString, 0 },
+ { "enterpriseoid", eCmdHdlrString, 0 },
+ { "trapoid", eCmdHdlrString, 0 },
+ { "messageoid", eCmdHdlrString, 0 },
+ { "snmpv1dynsource", eCmdHdlrString, 0 },
+ { "traptype", eCmdHdlrInt, 0 },
+ { "specifictype", eCmdHdlrInt, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.pszTransport = NULL;
+ cs.pszTarget = NULL;
+ cs.iPort = 0;
+ cs.iSNMPVersion = 1;
+ cs.pszCommunity = NULL;
+ cs.pszEnterpriseOID = NULL;
+ cs.pszSnmpTrapOID = NULL;
+ cs.pszSyslogMessageOID = NULL;
+ cs.iSpecificType = 0;
+ cs.iTrapType = SNMP_TRAP_ENTERPRISESPECIFIC;
+ENDinitConfVars
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->snmpsession = NULL;
+ENDcreateWrkrInstance
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("SNMPTransport: %s\n", pData->szTransport);
+ dbgprintf("SNMPTarget: %s\n", pData->szTarget);
+ dbgprintf("SNMPPort: %d\n", pData->iPort);
+ dbgprintf("SNMPVersion (0=v1, 1=v2c): %d\n", pData->iSNMPVersion);
+ dbgprintf("Community: %s\n", pData->szCommunity);
+ dbgprintf("EnterpriseOID: %s\n", pData->szEnterpriseOID);
+ dbgprintf("SnmpTrapOID: %s\n", pData->szSnmpTrapOID);
+ dbgprintf("SyslogMessageOID: %s\n", pData->szSyslogMessageOID);
+ dbgprintf("SnmpV1Source: %s\n", pData->szSnmpV1Source);
+ dbgprintf("TrapType: %d\n", pData->iTrapType);
+ dbgprintf("SpecificType: %d\n", pData->iSpecificType);
+ENDdbgPrintInstInfo
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* we are not compatible with repeated msg reduction feature, so do not allow it */
+ENDisCompatibleWithFeature
+
+/* Exit SNMP Session
+ * alorbach, 2008-02-12
+ */
+static rsRetVal
+omsnmp_exitSession(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+
+ if(pWrkrData->snmpsession != NULL) {
+ DBGPRINTF("omsnmp_exitSession: Clearing Session to '%s' on Port = '%d'\n",
+ pWrkrData->pData->szTarget, pWrkrData->pData->iPort);
+ snmp_close(pWrkrData->snmpsession);
+ pWrkrData->snmpsession = NULL;
+ }
+
+ RETiRet;
+}
+
+/* Init SNMP Session
+ * alorbach, 2008-02-12
+ */
+static rsRetVal
+omsnmp_initSession(wrkrInstanceData_t *pWrkrData)
+{
+ netsnmp_session session;
+ instanceData *pData;
+ char szTargetAndPort[MAXHOSTNAMELEN+128]; /* work buffer for specifying a full target and port string */
+ DEFiRet;
+
+ /* should not happen, but if session is not cleared yet - we do it now! */
+ if (pWrkrData->snmpsession != NULL)
+ omsnmp_exitSession(pWrkrData);
+
+ pData = pWrkrData->pData;
+
+ snprintf((char*)szTargetAndPort, sizeof(szTargetAndPort), "%s:%s:%d",
+ (pData->szTransport == NULL) ? "udp" : (char*)pData->szTransport,
+ pData->szTarget, pData->iPort == 0 ? 162 : pData->iPort);
+
+ dbgprintf( "omsnmp_initSession: ENTER - Target = '%s' on Port = '%d'\n", pData->szTarget, pData->iPort);
+
+ if (setenv("POSIXLY_CORRECT", "1", 1) == -1)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ snmp_sess_init(&session);
+ session.version = pData->iSNMPVersion;
+ session.callback = NULL; /* NOT NEEDED */
+ session.callback_magic = NULL;
+ session.peername = (char*) szTargetAndPort;
+
+ /* Set SNMP Community */
+ if (session.version == SNMP_VERSION_1 || session.version == SNMP_VERSION_2c) {
+ session.community = (unsigned char *) pData->szCommunity
+ == NULL ? (uchar*)"public" : pData->szCommunity;
+ session.community_len = strlen((char*) session.community);
+ }
+
+ pWrkrData->snmpsession = snmp_open(&session);
+ if (pWrkrData->snmpsession == NULL) {
+ LogError(0, RS_RET_SUSPENDED, "omsnmp_initSession: snmp_open to host '%s' on Port '%d' "
+ "failed\n", pData->szTarget, pData->iPort);
+ /* Stay suspended */
+ iRet = RS_RET_SUSPENDED;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal omsnmp_sendsnmp(wrkrInstanceData_t *pWrkrData, uchar *psz, uchar *pszSource)
+{
+ DEFiRet;
+
+ netsnmp_pdu *pdu = NULL;
+ oid enterpriseoid[MAX_OID_LEN];
+ size_t enterpriseoidlen = MAX_OID_LEN;
+ oid oidSyslogMessage[MAX_OID_LEN];
+ size_t oLen = MAX_OID_LEN;
+ int status;
+ char *trap = NULL;
+ const char *strErr = NULL;
+ struct sockaddr_in srcAddr;
+ instanceData *pData;
+
+ pData = pWrkrData->pData;
+ /* Init SNMP Session if necessary */
+ if (pWrkrData->snmpsession == NULL) {
+ CHKiRet(omsnmp_initSession(pWrkrData));
+ }
+
+ /* String should not be NULL */
+ assert(psz != NULL);
+ dbgprintf( "omsnmp_sendsnmp: ENTER - Syslogmessage = '%s'\n", (char*)psz);
+
+ /* If SNMP Version1 is configured !*/
+ if(pWrkrData->snmpsession->version == SNMP_VERSION_1) {
+ dbgprintf( "omsnmp_sendsnmp: Create SNMPv1 Trap - Source = '%s'\n", (char*)pszSource);
+ pdu = snmp_pdu_create(SNMP_MSG_TRAP);
+
+ /* Set enterprise */
+ if(!snmp_parse_oid(pData->szEnterpriseOID == NULL ? "1.3.6.1.4.1.3.1.1" :
+ (char*)pData->szEnterpriseOID, enterpriseoid, &enterpriseoidlen )) {
+ strErr = snmp_api_errstring(snmp_errno);
+ LogError(0, RS_RET_DISABLE_ACTION, "omsnmp_sendsnmp: Parsing EnterpriseOID "
+ "failed '%s' with error '%s' \n", pData->szSyslogMessageOID, strErr);
+ ABORT_FINALIZE(RS_RET_DISABLE_ACTION);
+ }
+ CHKmalloc(pdu->enterprise = (oid *) malloc(enterpriseoidlen * sizeof(oid)));
+ memcpy(pdu->enterprise, enterpriseoid, enterpriseoidlen * sizeof(oid));
+ pdu->enterprise_length = enterpriseoidlen;
+
+ /* Set Traptype */
+ pdu->trap_type = pData->iTrapType;
+
+ /* Set SpecificType */
+ pdu->specific_type = pData->iSpecificType;
+
+ /* Set Updtime */
+ pdu->time = get_uptime();
+
+ /* Set PDU SOurce property if available */
+ if (pszSource != NULL) {
+ if (inet_aton((const char *)pszSource, &srcAddr.sin_addr) != 0) {
+ pdu->agent_addr[0] = (srcAddr.sin_addr.s_addr) & 0xFF;
+ pdu->agent_addr[1] = (srcAddr.sin_addr.s_addr >> 8) & 0xFF;
+ pdu->agent_addr[2] = (srcAddr.sin_addr.s_addr >> 16) & 0xFF;
+ pdu->agent_addr[3] = (srcAddr.sin_addr.s_addr >> 24) & 0xFF;
+ dbgprintf( "omsnmp_sendsnmp: SNMPv1 Source Property set to %d.%d.%d.%d\n",
+ (srcAddr.sin_addr.s_addr) & 0xFF,
+ (srcAddr.sin_addr.s_addr >> 8) & 0xFF,
+ (srcAddr.sin_addr.s_addr >> 16) & 0xFF,
+ (srcAddr.sin_addr.s_addr >> 24) & 0xFF);
+ } else {
+ LogError(0, NO_ERRCODE, "omsnmp_sendsnmp: Failed to convert '%s' into a valid IPv4"
+ "address\n", pszSource);
+ }
+ }
+ }
+ /* If SNMP Version2c is configured !*/
+ else if (pWrkrData->snmpsession->version == SNMP_VERSION_2c)
+ {
+ long sysuptime;
+ char csysuptime[20];
+ dbgprintf( "omsnmp_sendsnmp: Create SNMPv2 Trap\n");
+
+ /* Create PDU */
+ pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
+
+ /* Set uptime */
+ sysuptime = get_uptime();
+ snprintf( csysuptime, sizeof(csysuptime) , "%ld", sysuptime);
+ trap = csysuptime;
+ snmp_add_var(pdu, objid_sysuptime, sizeof(objid_sysuptime) / sizeof(oid), 't', trap);
+
+ /* Now set the SyslogMessage Trap OID */
+ if ( snmp_add_var(pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid), 'o',
+ pData->szSnmpTrapOID == NULL ? "1.3.6.1.4.1.19406.1.2.1" : (char*) pData->szSnmpTrapOID
+ ) != 0) {
+ strErr = snmp_api_errstring(snmp_errno);
+ LogError(0, RS_RET_DISABLE_ACTION, "omsnmp_sendsnmp: Adding trap OID failed '%s' "
+ "with error '%s' \n", pData->szSnmpTrapOID, strErr);
+ ABORT_FINALIZE(RS_RET_DISABLE_ACTION);
+ }
+ }
+
+ /* SET TRAP PARAMETER for SyslogMessage! */
+
+ /* First create new OID object */
+ if (snmp_parse_oid(pData->szSyslogMessageOID == NULL ?
+ "1.3.6.1.4.1.19406.1.1.2.1" : (char*)pData->szSyslogMessageOID,
+ oidSyslogMessage, &oLen)) {
+ int iErrCode = snmp_add_var(pdu, oidSyslogMessage, oLen, 's', (char*) psz);
+ if (iErrCode) {
+ const char *str = snmp_api_errstring(iErrCode);
+ LogError(0, RS_RET_DISABLE_ACTION, "omsnmp_sendsnmp: Invalid SyslogMessage OID, "
+ "error code '%d' - '%s'\n", iErrCode, str );
+ ABORT_FINALIZE(RS_RET_DISABLE_ACTION);
+ }
+ } else {
+ strErr = snmp_api_errstring(snmp_errno);
+ LogError(0, RS_RET_DISABLE_ACTION, "omsnmp_sendsnmp: Parsing SyslogMessageOID failed '%s' "
+ "with error '%s' \n", pData->szSyslogMessageOID, strErr);
+
+ ABORT_FINALIZE(RS_RET_DISABLE_ACTION);
+ }
+
+ /* Send the TRAP */
+ status = snmp_send(pWrkrData->snmpsession, pdu) == 0;
+ if (status)
+ {
+ /* Debug Output! */
+ int iErrorCode = pWrkrData->snmpsession->s_snmp_errno;
+ LogError(0, RS_RET_SUSPENDED, "omsnmp_sendsnmp: snmp_send failed error '%d', "
+ "Description='%s'\n", iErrorCode*(-1), api_errors[iErrorCode*(-1)]);
+
+ /* Clear Session */
+ omsnmp_exitSession(pWrkrData);
+
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ dbgprintf( "omsnmp_sendsnmp: Successfully send SNMP Trap to %s:%d\n",
+ pData->szTarget, pData->iPort);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pdu != NULL) {
+ snmp_free_pdu(pdu);
+ }
+ }
+
+ dbgprintf( "omsnmp_sendsnmp: LEAVE\n");
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = omsnmp_initSession(pWrkrData);
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ /* Abort if the STRING is not set, should never happen */
+ if (ppString[0] == NULL) {
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+
+ /* This will generate and send the SNMP Trap */
+ iRet = omsnmp_sendsnmp(pWrkrData, ppString[0], ppString[1]);
+finalize_it:
+ENDdoAction
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ free(pData->szTarget);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ omsnmp_exitSession(pWrkrData);
+ENDfreeWrkrInstance
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+ pData->szCommunity = NULL;
+ pData->szEnterpriseOID = NULL;
+ pData->szSnmpTrapOID = NULL;
+ pData->szSyslogMessageOID = NULL;
+ pData->szSnmpV1Source = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTnewActInst(2)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "server")) {
+ pData->szTarget = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->iPort = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "transport")) {
+ pData->szTransport = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "version")) {
+ pData->iSNMPVersion = pvals[i].val.d.n;
+ if(pData->iSNMPVersion < 0 || cs.iSNMPVersion > 1)
+ pData->iSNMPVersion = 1;
+ } else if(!strcmp(actpblk.descr[i].name, "community")) {
+ pData->szCommunity = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "enterpriseoid")) {
+ pData->szEnterpriseOID = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "trapoid")) {
+ pData->szSnmpTrapOID = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "messageoid")) {
+ pData->szSyslogMessageOID = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "snmpv1dynsource")) {
+ pData->szSnmpV1Source = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "traptype")) {
+ pData->iTrapType = pvals[i].val.d.n;
+ if(cs.iTrapType < 0 || cs.iTrapType > 6) {
+ parser_errmsg("omsnmp: traptype invalid, setting to ENTERPRISESPECIFIC");
+ pData->iTrapType = SNMP_TRAP_ENTERPRISESPECIFIC;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "specifictype")) {
+ pData->iSpecificType = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("ompipe: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ /* Init NetSNMP library and read in MIB database */
+ init_snmp("rsyslog");
+
+ /* Set some defaults in the NetSNMP library */
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT, pData->iPort );
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_FileFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup((pData->szSnmpV1Source == NULL) ?
+ " SNMP_SOURCETEMPLATE" : (char*)pData->szSnmpV1Source),
+ OMSR_NO_RQD_TPL_OPTS));
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(!strncmp((char*) p, ":omsnmp:", sizeof(":omsnmp:") - 1)) {
+ p += sizeof(":omsnmp:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ FINALIZE;
+
+ /* Check Target */
+ if(cs.pszTarget == NULL) {
+ ABORT_FINALIZE( RS_RET_PARAM_ERROR );
+ } else {
+ CHKmalloc(pData->szTarget = (uchar*) strdup((char*)cs.pszTarget));
+ }
+
+ /* copy config params */
+ pData->szTransport = (uchar*) ((cs.pszTransport == NULL) ? NULL : strdup((char*)cs.pszTransport));
+ pData->szCommunity = (uchar*) ((cs.pszCommunity == NULL) ? NULL : strdup((char*)cs.pszCommunity));
+ pData->szEnterpriseOID = (uchar*) ((cs.pszEnterpriseOID == NULL) ? NULL : strdup((char*)cs.pszEnterpriseOID));
+ pData->szSnmpTrapOID = (uchar*) ((cs.pszSnmpTrapOID == NULL) ? NULL : strdup((char*)cs.pszSnmpTrapOID));
+ pData->szSyslogMessageOID = (uchar*) ((cs.pszSyslogMessageOID == NULL) ? NULL :
+ strdup((char*)cs.pszSyslogMessageOID));
+ pData->iPort = cs.iPort;
+ pData->iSpecificType = cs.iSpecificType;
+
+ /* Set SNMPVersion */
+ if ( cs.iSNMPVersion < 0 || cs.iSNMPVersion > 1) /* Set default to 1 if out of range */
+ pData->iSNMPVersion = 1;
+ else
+ pData->iSNMPVersion = cs.iSNMPVersion;
+
+ /* Copy TrapType */
+ if ( cs.iTrapType < 0 || cs.iTrapType >= 6) /* Only allow values from 0 to 6 !*/
+ pData->iTrapType = SNMP_TRAP_ENTERPRISESPECIFIC;
+ else
+ pData->iTrapType = cs.iTrapType;
+
+ /* Print Debug info */
+ dbgprintf("SNMPTransport: %s\n", pData->szTransport);
+ dbgprintf("SNMPTarget: %s\n", pData->szTarget);
+ dbgprintf("SNMPPort: %d\n", pData->iPort);
+ dbgprintf("SNMPVersion (0=v1, 1=v2c): %d\n", pData->iSNMPVersion);
+ dbgprintf("Community: %s\n", pData->szCommunity);
+ dbgprintf("EnterpriseOID: %s\n", pData->szEnterpriseOID);
+ dbgprintf("SnmpTrapOID: %s\n", pData->szSnmpTrapOID);
+ dbgprintf("SyslogMessageOID: %s\n", pData->szSyslogMessageOID);
+ dbgprintf("SnmpV1Source: %s\n", pData->szSnmpV1Source);
+ dbgprintf("TrapType: %d\n", pData->iTrapType);
+ dbgprintf("SpecificType: %d\n", pData->iSpecificType);
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (uchar*) "RSYSLOG_TraditionalForwardFormat"));
+
+ /* Init NetSNMP library and read in MIB database */
+ init_snmp("rsyslog");
+
+ /* Set some defaults in the NetSNMP library */
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT, pData->iPort );
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ free(cs.pszTarget);
+ cs.pszTarget = NULL;
+ free(cs.pszCommunity);
+ cs.pszCommunity = NULL;
+ free(cs.pszEnterpriseOID);
+ cs.pszEnterpriseOID = NULL;
+ free(cs.pszSnmpTrapOID);
+ cs.pszSnmpTrapOID = NULL;
+ free(cs.pszSyslogMessageOID);
+ cs.pszSyslogMessageOID = NULL;
+ cs.iPort = 0;
+ cs.iSNMPVersion = 1;
+ cs.iSpecificType = 0;
+ cs.iTrapType = SNMP_TRAP_ENTERPRISESPECIFIC;
+ RETiRet;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(cs.pszTarget);
+ free(cs.pszCommunity);
+ free(cs.pszEnterpriseOID);
+ free(cs.pszSnmpTrapOID);
+ free(cs.pszSyslogMessageOID);
+
+ /* release what we no longer need */
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ uchar *pTmp;
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ initConfVars();
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmptransport", 0, eCmdHdlrGetWord, NULL, &cs.pszTransport,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmptarget", 0, eCmdHdlrGetWord, NULL, &cs.pszTarget,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmptargetport", 0, eCmdHdlrInt, NULL, &cs.iPort,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmpversion", 0, eCmdHdlrInt, NULL, &cs.iSNMPVersion,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmpcommunity", 0, eCmdHdlrGetWord, NULL, &cs.pszCommunity,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmpenterpriseoid", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszEnterpriseOID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmptrapoid", 0, eCmdHdlrGetWord, NULL, &cs.pszSnmpTrapOID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmpsyslogmessageoid", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszSyslogMessageOID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmpspecifictype", 0, eCmdHdlrInt, NULL, &cs.iSpecificType,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionsnmptraptype", 0, eCmdHdlrInt, NULL, &cs.iTrapType,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+
+ DBGPRINTF("omsnmp: Add SNMP_SOURCETEMPLATE to template system ONCE\n");
+ pTmp = (uchar*) SNMP_SOURCETEMPLATE;
+ tplAddLine(ourConf, " SNMP_SOURCETEMPLATE", &pTmp);
+ENDmodInit
+/*
+ * vi:set ai:
+ */
diff --git a/plugins/omsnmp/omsnmp.h b/plugins/omsnmp/omsnmp.h
new file mode 100644
index 0000000..dcb1537
--- /dev/null
+++ b/plugins/omsnmp/omsnmp.h
@@ -0,0 +1,104 @@
+/* omsnmp.h
+ * These are the definitions for the build-in MySQL output module.
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMSNMP_H_INCLUDED
+#define OMSNMP_H_INCLUDED 1
+
+#define OMSNMP_MAXTRANSPORLENGTH 10
+#define OMSNMP_MAXPORTLENGTH 5
+#define OMSNMP_MAXCOMMUNITYLENGTH 255
+#define OMSNMP_MAXOIDLENGTH 255
+
+
+#endif /* #ifndef OMMYSQL_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
+
+#include <net-snmp/library/snmp_api.h>
+
+static const char *api_errors[-SNMPERR_MAX + 1] = {
+ "No error", /* SNMPERR_SUCCESS */
+ "Generic error", /* SNMPERR_GENERR */
+ "Invalid local port", /* SNMPERR_BAD_LOCPORT */
+ "Unknown host", /* SNMPERR_BAD_ADDRESS */
+ "Unknown session", /* SNMPERR_BAD_SESSION */
+ "Too long", /* SNMPERR_TOO_LONG */
+ "No socket", /* SNMPERR_NO_SOCKET */
+ "Cannot send V2 PDU on V1 session", /* SNMPERR_V2_IN_V1 */
+ "Cannot send V1 PDU on V2 session", /* SNMPERR_V1_IN_V2 */
+ "Bad value for non-repeaters", /* SNMPERR_BAD_REPEATERS */
+ "Bad value for max-repetitions", /* SNMPERR_BAD_REPETITIONS */
+ "Error building ASN.1 representation", /* SNMPERR_BAD_ASN1_BUILD */
+ "Failure in sendto", /* SNMPERR_BAD_SENDTO */
+ "Bad parse of ASN.1 type", /* SNMPERR_BAD_PARSE */
+ "Bad version specified", /* SNMPERR_BAD_VERSION */
+ "Bad source party specified", /* SNMPERR_BAD_SRC_PARTY */
+ "Bad destination party specified", /* SNMPERR_BAD_DST_PARTY */
+ "Bad context specified", /* SNMPERR_BAD_CONTEXT */
+ "Bad community specified", /* SNMPERR_BAD_COMMUNITY */
+ "Cannot send noAuth/Priv", /* SNMPERR_NOAUTH_DESPRIV */
+ "Bad ACL definition", /* SNMPERR_BAD_ACL */
+ "Bad Party definition", /* SNMPERR_BAD_PARTY */
+ "Session abort failure", /* SNMPERR_ABORT */
+ "Unknown PDU type", /* SNMPERR_UNKNOWN_PDU */
+ "Timeout", /* SNMPERR_TIMEOUT */
+ "Failure in recvfrom", /* SNMPERR_BAD_RECVFROM */
+ "Unable to determine contextEngineID", /* SNMPERR_BAD_ENG_ID */
+ "No securityName specified", /* SNMPERR_BAD_SEC_NAME */
+ "Unable to determine securityLevel", /* SNMPERR_BAD_SEC_LEVEL */
+ "ASN.1 parse error in message", /* SNMPERR_ASN_PARSE_ERR */
+ "Unknown security model in message", /* SNMPERR_UNKNOWN_SEC_MODEL */
+ "Invalid message (e.g. msgFlags)", /* SNMPERR_INVALID_MSG */
+ "Unknown engine ID", /* SNMPERR_UNKNOWN_ENG_ID */
+ "Unknown user name", /* SNMPERR_UNKNOWN_USER_NAME */
+ "Unsupported security level", /* SNMPERR_UNSUPPORTED_SEC_LEVEL */
+ "Authentication failure (incorrect password, community or key)", /* SNMPERR_AUTHENTICATION_FAILURE */
+ "Not in time window", /* SNMPERR_NOT_IN_TIME_WINDOW */
+ "Decryption error", /* SNMPERR_DECRYPTION_ERR */
+ "SCAPI general failure", /* SNMPERR_SC_GENERAL_FAILURE */
+ "SCAPI sub-system not configured", /* SNMPERR_SC_NOT_CONFIGURED */
+ "Key tools not available", /* SNMPERR_KT_NOT_AVAILABLE */
+ "Unknown Report message", /* SNMPERR_UNKNOWN_REPORT */
+ "USM generic error", /* SNMPERR_USM_GENERICERROR */
+ "USM unknown security name (no such user exists)", /* SNMPERR_USM_UNKNOWNSECURITYNAME */
+ "USM unsupported security level (this user has not been configured for that level of security)",
+ /* SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL */
+ "USM encryption error", /* SNMPERR_USM_ENCRYPTIONERROR */
+ "USM authentication failure (incorrect password or key)", /* SNMPERR_USM_AUTHENTICATIONFAILURE */
+ "USM parse error", /* SNMPERR_USM_PARSEERROR */
+ "USM unknown engineID", /* SNMPERR_USM_UNKNOWNENGINEID */
+ "USM not in time window", /* SNMPERR_USM_NOTINTIMEWINDOW */
+ "USM decryption error", /* SNMPERR_USM_DECRYPTIONERROR */
+ "MIB not initialized", /* SNMPERR_NOMIB */
+ "Value out of range", /* SNMPERR_RANGE */
+ "Sub-id out of range", /* SNMPERR_MAX_SUBID */
+ "Bad sub-id in object identifier", /* SNMPERR_BAD_SUBID */
+ "Object identifier too long", /* SNMPERR_LONG_OID */
+ "Bad value name", /* SNMPERR_BAD_NAME */
+ "Bad value notation", /* SNMPERR_VALUE */
+ "Unknown Object Identifier", /* SNMPERR_UNKNOWN_OBJID */
+ "No PDU in snmp_send", /* SNMPERR_NULL_PDU */
+ "Missing variables in PDU", /* SNMPERR_NO_VARS */
+ "Bad variable type", /* SNMPERR_VAR_TYPE */
+ "Out of memory (malloc failure)", /* SNMPERR_MALLOC */
+ "Kerberos related error", /* SNMPERR_KRB5 */
+};
diff --git a/plugins/omstdout/Makefile.am b/plugins/omstdout/Makefile.am
new file mode 100644
index 0000000..9f5d497
--- /dev/null
+++ b/plugins/omstdout/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omstdout.la
+
+omstdout_la_SOURCES = omstdout.c
+omstdout_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omstdout_la_LDFLAGS = -module -avoid-version
+omstdout_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/omstdout/Makefile.in b/plugins/omstdout/Makefile.in
new file mode 100644
index 0000000..0b085e6
--- /dev/null
+++ b/plugins/omstdout/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omstdout
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omstdout_la_DEPENDENCIES =
+am_omstdout_la_OBJECTS = omstdout_la-omstdout.lo
+omstdout_la_OBJECTS = $(am_omstdout_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 =
+omstdout_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omstdout_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omstdout_la-omstdout.Plo
+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 = $(omstdout_la_SOURCES)
+DIST_SOURCES = $(omstdout_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omstdout.la
+omstdout_la_SOURCES = omstdout.c
+omstdout_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omstdout_la_LDFLAGS = -module -avoid-version
+omstdout_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/omstdout/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omstdout/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omstdout.la: $(omstdout_la_OBJECTS) $(omstdout_la_DEPENDENCIES) $(EXTRA_omstdout_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omstdout_la_LINK) -rpath $(pkglibdir) $(omstdout_la_OBJECTS) $(omstdout_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omstdout_la-omstdout.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omstdout_la-omstdout.lo: omstdout.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omstdout_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omstdout_la-omstdout.lo -MD -MP -MF $(DEPDIR)/omstdout_la-omstdout.Tpo -c -o omstdout_la-omstdout.lo `test -f 'omstdout.c' || echo '$(srcdir)/'`omstdout.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omstdout_la-omstdout.Tpo $(DEPDIR)/omstdout_la-omstdout.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omstdout.c' object='omstdout_la-omstdout.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) $(omstdout_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omstdout_la-omstdout.lo `test -f 'omstdout.c' || echo '$(srcdir)/'`omstdout.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omstdout_la-omstdout.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omstdout_la-omstdout.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omstdout/omstdout.c b/plugins/omstdout/omstdout.c
new file mode 100644
index 0000000..776e0b6
--- /dev/null
+++ b/plugins/omstdout/omstdout.c
@@ -0,0 +1,372 @@
+/* omstdout.c
+ * send all output to stdout - this is primarily a test driver (but may
+ * be used for weired use cases). Not tested for robustness!
+ *
+ * NOTE: read comments in module-template.h for more specifics!
+ *
+ * File begun on 2009-03-19 by RGerhards
+ *
+ * Copyright 2009-2017 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omstdout")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ int bUseArrayInterface; /* uses action use array instead of string template interface? */
+ int bEnsureLFEnding; /* ensure that a linefeed is written at the end of EACH
+ record (test aid for nettester) */
+ uchar *templateName;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ int bUseArrayInterface; /* shall action use array instead of string template interface? */
+ int bEnsureLFEnding;
+ int templateName;
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "ensurelfending", eCmdHdlrBinary, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omstdout\n");
+ dbgprintf("\tensureLFEnding='%d'\n", pData->bEnsureLFEnding);
+ dbgprintf("\ttemplate='%s'\n", pData->templateName);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+ char **szParams;
+ char *toWrite;
+ int iParamVal;
+ int iParam;
+ int iBuf;
+ char szBuf[65564];
+ size_t len;
+ int r;
+CODESTARTdoAction
+dbgprintf("omstdout: in doAction\n");
+ if(pWrkrData->pData->bUseArrayInterface) {
+dbgprintf("omstdout: in ArrayInterface\n");
+ /* if we use array passing, we need to put together a string
+ * ourselves. At this point, please keep in mind that omstdout is
+ * primarily a testing aid. Other modules may do different processing
+ * if they would like to support downlevel versions which do not support
+ * array-passing, but also use that interface on cores who do...
+ * So this code here is also more or less an example of how to do that.
+ * rgerhards, 2009-04-03
+ */
+ szParams = (char**)(void*) (ppString[0]);
+ /* In array-passing mode, ppString[] contains a NULL-terminated array
+ * of char *pointers.
+ */
+ iParam = 0;
+ iBuf = 0;
+ while(szParams[iParam] != NULL && iBuf < (int)sizeof(szBuf)-1) {
+ if(iParam > 0)
+ szBuf[iBuf++] = ','; /* all but first need a delimiter */
+ iParamVal = 0;
+ while(szParams[iParam][iParamVal] != '\0' && iBuf < (int) sizeof(szBuf)-1) {
+ szBuf[iBuf++] = szParams[iParam][iParamVal++];
+ }
+ ++iParam;
+ }
+ szBuf[iBuf] = '\0';
+ toWrite = szBuf;
+ } else {
+dbgprintf("omstdout: in else\n");
+ toWrite = (char*) ppString[0];
+ }
+ len = strlen(toWrite);
+ /* the following if's are just to silence compiler warnings. If someone
+ * actually intends to use this module in production (why???), this code
+ * needs to be more solid. -- rgerhards, 2012-11-28
+ */
+dbgprintf("omstdout: len: %d, toWrite: %s\n", (int) len, toWrite);
+ if((r = write(1, toWrite, len)) != (int) len) { /* 1 is stdout! */
+ DBGPRINTF("omstdout: error %d writing to stdout[%zd]: %s\n",
+ r, len, toWrite);
+ }
+ if(pWrkrData->pData->bEnsureLFEnding && toWrite[len-1] != '\n') {
+ if((r = write(1, "\n", 1)) != 1) { /* write missing LF */
+ DBGPRINTF("omstdout: error %d writing \\n to stdout\n",
+ r);
+ }
+ }
+ENDdoAction
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->bEnsureLFEnding = 1;
+ pData->templateName = (uchar*) "RSYSLOG_FileFormat";
+ pData->bUseArrayInterface = 0;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ int bDestructPValsOnExit;
+ uchar *tplToUse;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omstdout)\n");
+
+ bDestructPValsOnExit = 0;
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "omstdout: error reading "
+ "config parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ bDestructPValsOnExit = 1;
+
+ if(Debug) {
+ dbgprintf("action param blk in omstdout:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ } else if(!strcmp(actpblk.descr[i].name, "ensurelfending")) {
+ pData->bEnsureLFEnding = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->templateName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("omstdout: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ //TODO: make the template a parameter
+ tplToUse = (uchar*) strdup((pData->templateName == NULL) ? "RSYSLOG_FileFormat" : (char *)pData->templateName);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
+CODE_STD_FINALIZERnewActInst
+ if(bDestructPValsOnExit)
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+
+BEGINparseSelectorAct
+ int iTplOpts;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omstdout:", sizeof(":omstdout:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omstdout:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ iTplOpts = (cs.bUseArrayInterface == 0) ? 0 : OMSR_TPL_AS_ARRAY;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, iTplOpts, (uchar*) "RSYSLOG_FileFormat"));
+ pData->bUseArrayInterface = cs.bUseArrayInterface;
+ pData->bEnsureLFEnding = cs.bEnsureLFEnding;
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.bUseArrayInterface = 0;
+ cs.bEnsureLFEnding = 1;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bArrayPassingSupported; /* does core support template passing as an array? */
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bArrayPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports array passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_ARRAY)
+ bArrayPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, what is not acceptable */
+ }
+ DBGPRINTF("omstdout: array-passing is %ssupported by rsyslog core.\n", bArrayPassingSupported ? "" : "not ");
+
+ if(bArrayPassingSupported) {
+ /* enable config comand only if core supports it */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomstdoutarrayinterface", 0, eCmdHdlrBinary, NULL,
+ &cs.bUseArrayInterface, STD_LOADABLE_MODULE_ID));
+ }
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomstdoutensurelfending", 0, eCmdHdlrBinary, NULL,
+ &cs.bEnsureLFEnding, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */
diff --git a/plugins/omtesting/Makefile.am b/plugins/omtesting/Makefile.am
new file mode 100644
index 0000000..e35c471
--- /dev/null
+++ b/plugins/omtesting/Makefile.am
@@ -0,0 +1,11 @@
+pkglib_LTLIBRARIES = omtesting.la
+
+omtesting_la_SOURCES = omtesting.c
+omtesting_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+omtesting_la_LDFLAGS = -module -avoid-version
+omtesting_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+omtesting_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+omtesting_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
diff --git a/plugins/omtesting/Makefile.in b/plugins/omtesting/Makefile.in
new file mode 100644
index 0000000..a48429f
--- /dev/null
+++ b/plugins/omtesting/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+subdir = plugins/omtesting
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omtesting_la_DEPENDENCIES =
+am_omtesting_la_OBJECTS = omtesting_la-omtesting.lo
+omtesting_la_OBJECTS = $(am_omtesting_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 =
+omtesting_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omtesting_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omtesting_la-omtesting.Plo
+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 = $(omtesting_la_SOURCES)
+DIST_SOURCES = $(omtesting_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omtesting.la
+omtesting_la_SOURCES = omtesting.c
+omtesting_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) \
+ $(RSRT_CFLAGS) $(am__append_1)
+omtesting_la_LDFLAGS = -module -avoid-version $(am__append_2)
+omtesting_la_LIBADD =
+all: 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) --gnu plugins/omtesting/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omtesting/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omtesting.la: $(omtesting_la_OBJECTS) $(omtesting_la_DEPENDENCIES) $(EXTRA_omtesting_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omtesting_la_LINK) -rpath $(pkglibdir) $(omtesting_la_OBJECTS) $(omtesting_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omtesting_la-omtesting.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omtesting_la-omtesting.lo: omtesting.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omtesting_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omtesting_la-omtesting.lo -MD -MP -MF $(DEPDIR)/omtesting_la-omtesting.Tpo -c -o omtesting_la-omtesting.lo `test -f 'omtesting.c' || echo '$(srcdir)/'`omtesting.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omtesting_la-omtesting.Tpo $(DEPDIR)/omtesting_la-omtesting.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omtesting.c' object='omtesting_la-omtesting.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) $(omtesting_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omtesting_la-omtesting.lo `test -f 'omtesting.c' || echo '$(srcdir)/'`omtesting.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omtesting_la-omtesting.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omtesting_la-omtesting.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omtesting/omtesting.c b/plugins/omtesting/omtesting.c
new file mode 100644
index 0000000..9cbfe8a
--- /dev/null
+++ b/plugins/omtesting/omtesting.c
@@ -0,0 +1,364 @@
+/* omtesting.c
+ *
+ * This module is a testing aid. It is not meant to be used in production. I have
+ * initially written it to introduce delays of custom length to action processing.
+ * This is needed for development of new message queueing methods. However, I think
+ * there are other uses for this module. For example, I can envision that it is a good
+ * thing to have an output module that requests a retry on every "n"th invocation
+ * and such things. I implement only what I need. But should further testing needs
+ * arise, it makes much sense to add them here.
+ *
+ * This module will become part of the CVS and the rsyslog project because I think
+ * it is a generally useful debugging, testing and development aid for everyone
+ * involved with rsyslog.
+ *
+ * CURRENT SUPPORTED COMMANDS:
+ *
+ * :omtesting:sleep <seconds> <microseconds>
+ *
+ * Must be specified exactly as above. Keep in mind microseconds are a millionth
+ * of a second!
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <pthread.h>
+#include "dirty.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "conf.h"
+#include "cfsysline.h"
+#include "srUtils.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omtesting")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ enum { MD_SLEEP, MD_FAIL, MD_RANDFAIL, MD_ALWAYS_SUSPEND }
+ mode;
+ int bEchoStdout;
+ int iWaitSeconds;
+ int iWaitUSeconds; /* micro-seconds (one millionth of a second, just to make sure...) */
+ int iCurrCallNbr;
+ int iFailFrequency;
+ int iResumeAfter;
+ int iCurrRetries;
+ int bFailed; /* indicates if we are already in failed state - this is necessary
+ * to work properly together with multiple worker instances.
+ */
+ pthread_mutex_t mut;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ int bEchoStdout; /* echo non-failed messages to stdout */
+} configSettings_t;
+static configSettings_t cs;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.bEchoStdout = 0;
+ENDinitConfVars
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->iWaitSeconds = 1;
+ pData->iWaitUSeconds = 0;
+ pthread_mutex_init(&pData->mut, NULL);
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("Action delays rule by %d second(s) and %d microsecond(s)\n",
+ pData->iWaitSeconds, pData->iWaitUSeconds);
+ /* do nothing */
+ENDdbgPrintInstInfo
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* we are not compatible with repeated msg reduction feature, so do not allow it */
+ENDisCompatibleWithFeature
+
+
+/* implement "fail" command in retry processing */
+static rsRetVal doFailOnResume(instanceData *pData)
+{
+ DEFiRet;
+
+ dbgprintf("fail retry curr %d, max %d\n", pData->iCurrRetries, pData->iResumeAfter);
+ if(++pData->iCurrRetries == pData->iResumeAfter) {
+ iRet = RS_RET_OK;
+ pData->bFailed = 0;
+ } else {
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+
+/* implement "fail" command */
+static rsRetVal doFail(instanceData *pData)
+{
+ DEFiRet;
+
+ dbgprintf("fail curr %d, frequency %d, bFailed %d\n", pData->iCurrCallNbr,
+ pData->iFailFrequency, pData->bFailed);
+ if(pData->bFailed) {
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ if(pData->iCurrCallNbr++ % pData->iFailFrequency == 0) {
+ pData->iCurrRetries = 0;
+ pData->bFailed = 1;
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* implement "sleep" command */
+static rsRetVal doSleep(instanceData *pData)
+{
+ DEFiRet;
+ struct timeval tvSelectTimeout;
+
+ dbgprintf("sleep(%d, %d)\n", pData->iWaitSeconds, pData->iWaitUSeconds);
+ tvSelectTimeout.tv_sec = pData->iWaitSeconds;
+ tvSelectTimeout.tv_usec = pData->iWaitUSeconds; /* microseconds */
+ select(0, NULL, NULL, NULL, &tvSelectTimeout);
+ RETiRet;
+}
+
+
+/* implement "randomfail" command */
+static rsRetVal doRandFail(void)
+{
+ DEFiRet;
+ if((randomNumber() >> 4) < (RAND_MAX >> 5)) { /* rougly same probability */
+ iRet = RS_RET_OK;
+ dbgprintf("omtesting randfail: succeeded this time\n");
+ } else {
+ iRet = RS_RET_SUSPENDED;
+ dbgprintf("omtesting randfail: failed this time\n");
+ }
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ dbgprintf("omtesting tryResume() called\n");
+ pthread_mutex_lock(&pWrkrData->pData->mut);
+ switch(pWrkrData->pData->mode) {
+ case MD_SLEEP:
+ break;
+ case MD_FAIL:
+ iRet = doFailOnResume(pWrkrData->pData);
+ break;
+ case MD_RANDFAIL:
+ iRet = doRandFail();
+ break;
+ case MD_ALWAYS_SUSPEND:
+ iRet = RS_RET_SUSPENDED;
+ }
+ pthread_mutex_unlock(&pWrkrData->pData->mut);
+ dbgprintf("omtesting tryResume() returns iRet %d\n", iRet);
+ENDtryResume
+
+
+BEGINdoAction
+ instanceData *pData;
+CODESTARTdoAction
+ dbgprintf("omtesting received msg '%s'\n", ppString[0]);
+ pData = pWrkrData->pData;
+ pthread_mutex_lock(&pData->mut);
+ switch(pData->mode) {
+ case MD_SLEEP:
+ iRet = doSleep(pData);
+ break;
+ case MD_FAIL:
+ iRet = doFail(pData);
+ break;
+ case MD_RANDFAIL:
+ iRet = doRandFail();
+ break;
+ case MD_ALWAYS_SUSPEND:
+ iRet = RS_RET_SUSPENDED;
+ break;
+ }
+
+ if(iRet == RS_RET_OK && pData->bEchoStdout) {
+ fprintf(stdout, "%s", ppString[0]);
+ fflush(stdout);
+ }
+ pthread_mutex_unlock(&pData->mut);
+ dbgprintf(":omtesting: end doAction(), iRet %d\n", iRet);
+ENDdoAction
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ pthread_mutex_destroy(&pData->mut);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINparseSelectorAct
+ int i;
+ uchar szBuf[1024];
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* code here is quick and dirty - if you like, clean it up. But keep
+ * in mind it is just a testing aid ;) -- rgerhards, 2007-12-31
+ */
+ if(!strncmp((char*) p, ":omtesting:", sizeof(":omtesting:") - 1)) {
+ p += sizeof(":omtesting:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ goto finalize_it;
+
+ /* check mode */
+ for(i = 0 ; *p && !isspace((char) *p) && ((unsigned) i < sizeof(szBuf) - 1) ; ++i) {
+ szBuf[i] = (uchar) *p++;
+ }
+ szBuf[i] = '\0';
+ if(isspace(*p))
+ ++p;
+
+ dbgprintf("omtesting command: '%s'\n", szBuf);
+ if(!strcmp((char*) szBuf, "sleep")) {
+ /* parse seconds */
+ for(i = 0 ; *p && !isspace(*p) && ((unsigned) i < sizeof(szBuf) - 1) ; ++i) {
+ szBuf[i] = *p++;
+ }
+ szBuf[i] = '\0';
+ if(isspace(*p))
+ ++p;
+ pData->iWaitSeconds = atoi((char*) szBuf);
+ /* parse microseconds */
+ for(i = 0 ; *p && !isspace(*p) && ((unsigned) i < sizeof(szBuf) - 1) ; ++i) {
+ szBuf[i] = *p++;
+ }
+ szBuf[i] = '\0';
+ if(isspace(*p))
+ ++p;
+ pData->iWaitUSeconds = atoi((char*) szBuf);
+ pData->mode = MD_SLEEP;
+ } else if(!strcmp((char*) szBuf, "fail")) {
+ /* "fail fail-freqency resume-after"
+ * fail-frequency specifies how often doAction() fails
+ * resume-after speicifes how fast tryResume() should come back with success
+ * all numbers being "times called"
+ */
+ /* parse fail-frequence */
+ for(i = 0 ; *p && !isspace(*p) && ((unsigned) i < sizeof(szBuf) - 1) ; ++i) {
+ szBuf[i] = *p++;
+ }
+ szBuf[i] = '\0';
+ if(isspace(*p))
+ ++p;
+ pData->iFailFrequency = atoi((char*) szBuf);
+ /* parse resume-after */
+ for(i = 0 ; *p && !isspace(*p) && ((unsigned) i < sizeof(szBuf) - 1) ; ++i) {
+ szBuf[i] = *p++;
+ }
+ szBuf[i] = '\0';
+ if(isspace(*p))
+ ++p;
+ pData->iResumeAfter = atoi((char*) szBuf);
+ pData->iCurrCallNbr = 1;
+ pData->mode = MD_FAIL;
+ } else if(!strcmp((char*) szBuf, "randfail")) {
+ pData->mode = MD_RANDFAIL;
+ } else if(!strcmp((char*) szBuf, "always_suspend")) {
+ pData->mode = MD_ALWAYS_SUSPEND;
+ } else {
+ dbgprintf("invalid mode '%s', doing 'sleep 1 0' - fix your config\n", szBuf);
+ }
+
+ pData->bEchoStdout = cs.bEchoStdout;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (uchar*)"RSYSLOG_TraditionalForwardFormat"));
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomtestingechostdout", 0, eCmdHdlrBinary, NULL,
+ &cs.bEchoStdout, STD_LOADABLE_MODULE_ID));
+ /* we seed the random-number generator in any case... */
+ srand(time(NULL));
+ENDmodInit
+/*
+ * vi:set ai:
+ */
diff --git a/plugins/omudpspoof/Makefile.am b/plugins/omudpspoof/Makefile.am
new file mode 100644
index 0000000..79c495a
--- /dev/null
+++ b/plugins/omudpspoof/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omudpspoof.la
+
+omudpspoof_la_SOURCES = omudpspoof.c
+omudpspoof_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(UDPSPOOF_CFLAGS)
+omudpspoof_la_LDFLAGS = -module -avoid-version
+omudpspoof_la_LIBADD = $(UDPSPOOF_LIBS)
+
+EXTRA_DIST =
diff --git a/plugins/omudpspoof/Makefile.in b/plugins/omudpspoof/Makefile.in
new file mode 100644
index 0000000..3babfc7
--- /dev/null
+++ b/plugins/omudpspoof/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omudpspoof
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+omudpspoof_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_omudpspoof_la_OBJECTS = omudpspoof_la-omudpspoof.lo
+omudpspoof_la_OBJECTS = $(am_omudpspoof_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 =
+omudpspoof_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omudpspoof_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omudpspoof_la-omudpspoof.Plo
+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 = $(omudpspoof_la_SOURCES)
+DIST_SOURCES = $(omudpspoof_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omudpspoof.la
+omudpspoof_la_SOURCES = omudpspoof.c
+omudpspoof_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(UDPSPOOF_CFLAGS)
+omudpspoof_la_LDFLAGS = -module -avoid-version
+omudpspoof_la_LIBADD = $(UDPSPOOF_LIBS)
+EXTRA_DIST =
+all: 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) --gnu plugins/omudpspoof/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omudpspoof/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omudpspoof.la: $(omudpspoof_la_OBJECTS) $(omudpspoof_la_DEPENDENCIES) $(EXTRA_omudpspoof_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omudpspoof_la_LINK) -rpath $(pkglibdir) $(omudpspoof_la_OBJECTS) $(omudpspoof_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omudpspoof_la-omudpspoof.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omudpspoof_la-omudpspoof.lo: omudpspoof.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omudpspoof_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omudpspoof_la-omudpspoof.lo -MD -MP -MF $(DEPDIR)/omudpspoof_la-omudpspoof.Tpo -c -o omudpspoof_la-omudpspoof.lo `test -f 'omudpspoof.c' || echo '$(srcdir)/'`omudpspoof.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omudpspoof_la-omudpspoof.Tpo $(DEPDIR)/omudpspoof_la-omudpspoof.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omudpspoof.c' object='omudpspoof_la-omudpspoof.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) $(omudpspoof_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omudpspoof_la-omudpspoof.lo `test -f 'omudpspoof.c' || echo '$(srcdir)/'`omudpspoof.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omudpspoof_la-omudpspoof.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omudpspoof_la-omudpspoof.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omudpspoof/omudpspoof.c b/plugins/omudpspoof/omudpspoof.c
new file mode 100644
index 0000000..4c4f9d8
--- /dev/null
+++ b/plugins/omudpspoof/omudpspoof.c
@@ -0,0 +1,819 @@
+/* omudpspoof.c
+ *
+ * This is a udp-based output module that support spoofing.
+ *
+ * This file builds on UDP spoofing code contributed by
+ * David Lang <david@lang.hm>. I then created a "real" rsyslog module
+ * out of that code and omfwd. I decided to make it a separate module because
+ * omfwd already mixes up too many things (TCP & UDP & a different modes,
+ * this has historic reasons), it would not be a good idea to also add
+ * spoofing to it. And, looking at the requirements, there is little in
+ * common between omfwd and this module.
+ *
+ * Note: I have briefly checked libnet source code and I somewhat have the feeling
+ * that under some circumstances we may get into trouble with the lib. For
+ * example, it registers an atexit() handler, which should not play nicely
+ * with our dynamically loaded modules. Anyhow, I refrain from looking deeper
+ * at libnet code, especially as testing does not show any real issues. If some
+ * occur, it may be easier to modify libnet for dynamic load environments than
+ * using a work-around (as a side not, libnet looks somewhat unmaintained, the CVS
+ * I can see on sourceforge dates has no updates done less than 7 years ago).
+ * On the other hand, it looks like libnet is thread safe (at least is appropriately
+ * compiled, which I hope the standard packages are). So I do not guard calls to
+ * it with my own mutex calls.
+ * rgerhards, 2009-07-10
+ *
+ * Copyright 2009 David Lang (spoofing code)
+ * Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "template.h"
+#include "msg.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "dirty.h"
+#include "unicode-helper.h"
+#include "debug.h"
+
+
+#include <libnet.h>
+#define _BSD_SOURCE 1
+#define __BSD_SOURCE 1
+#define __FAVOR_BSD 1
+
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omudpspoof")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+
+typedef struct _instanceData {
+ uchar *tplName; /* name of assigned template */
+ uchar *host;
+ uchar *port;
+ uchar *sourceTpl;
+ int mtu;
+ u_short sourcePortStart; /* for sorce port iteration */
+ u_short sourcePortEnd;
+ int bReportLibnetInitErr; /* help prevent multiple error messages on init err */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ libnet_t *libnet_handle;
+ u_short sourcePort;
+ int *pSockArray; /* sockets to use for UDP */
+ struct addrinfo *f_addr;
+ char errbuf[LIBNET_ERRBUF_SIZE];
+} wrkrInstanceData_t;
+
+#define DFLT_SOURCE_PORT_START 32000
+#define DFLT_SOURCE_PORT_END 42000
+
+typedef struct configSettings_s {
+ uchar *tplName; /* name of the default template to use */
+ uchar *pszSourceNameTemplate; /* name of the template containing the spoofing address */
+ uchar *pszTargetHost;
+ uchar *pszTargetPort;
+ int iSourcePortStart;
+ int iSourcePortEnd;
+} configSettings_t;
+static configSettings_t cs;
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 1 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "sourcetemplate", eCmdHdlrGetWord, 0 },
+ { "sourceport.start", eCmdHdlrInt, 0 },
+ { "sourceport.end", eCmdHdlrInt, 0 },
+ { "mtu", eCmdHdlrInt, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.tplName = NULL;
+ cs.pszSourceNameTemplate = NULL;
+ cs.pszTargetHost = NULL;
+ cs.pszTargetPort = NULL;
+ cs.iSourcePortStart = DFLT_SOURCE_PORT_START;
+ cs.iSourcePortEnd = DFLT_SOURCE_PORT_END;
+ENDinitConfVars
+
+
+/* add some variables needed for libnet */
+pthread_mutex_t mutLibnet;
+
+/* forward definitions */
+static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData);
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(cs.tplName == NULL)
+ return (uchar*)"RSYSLOG_TraditionalForwardFormat";
+ else
+ return cs.tplName;
+}
+
+
+/* set the default template to be used
+ * This is a module-global parameter, and as such needs special handling. It needs to
+ * be coordinated with values set via the v2 config system (rsyslog v6+). What we do
+ * is we do not permit this directive after the v2 config system has been used to set
+ * the parameter.
+ */
+static rsRetVal
+setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal)
+{
+ DEFiRet;
+
+ if(loadModConf != NULL && loadModConf->tplName != NULL) {
+ free(newVal);
+ LogError(0, RS_RET_ERR, "omudpspoof default template already set via module "
+ "global parameter - can no longer be changed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ free(cs.tplName);
+ cs.tplName = newVal;
+finalize_it:
+ RETiRet;
+}
+
+/* Close the UDP sockets.
+ * rgerhards, 2009-05-29
+ */
+static rsRetVal
+closeUDPSockets(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ if(pWrkrData->pSockArray != NULL) {
+ net.closeUDPListenSockets(pWrkrData->pSockArray);
+ pWrkrData->pSockArray = NULL;
+ freeaddrinfo(pWrkrData->f_addr);
+ pWrkrData->f_addr = NULL;
+ }
+ RETiRet;
+}
+
+
+/* get the syslog forward port
+ * We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use the IANA default auf 514.
+ * rgerhards, 2007-06-28
+ */
+static inline uchar *getFwdPt(instanceData *pData)
+{
+ return (pData->port == NULL) ? UCHAR_CONSTANT("514") : pData->port;
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omudpspoof:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(cs.tplName != NULL) {
+ LogError(0, RS_RET_DUP_PARAM, "omudpspoof: warning: default template "
+ "was already set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else {
+ dbgprintf("omudpspoof: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.tplName);
+ cs.tplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->mtu = 1500;
+ pData->bReportLibnetInitErr = 1;
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ pWrkrData->libnet_handle = NULL;
+ pWrkrData->sourcePort = pData->sourcePortStart;
+ENDcreateWrkrInstance
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* final cleanup */
+ free(pData->tplName);
+ free(pData->port);
+ free(pData->host);
+ free(pData->sourceTpl);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ closeUDPSockets(pWrkrData);
+ if(pWrkrData->libnet_handle != NULL)
+ libnet_destroy(pWrkrData->libnet_handle);
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("%s", pData->host);
+ENDdbgPrintInstInfo
+
+
+/* Send a message via UDP
+ * Note: libnet is not thread-safe, so we need to ensure that only one
+ * instance ever is calling libnet code.
+ * rgehards, 2007-12-20
+ */
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+#endif
+static rsRetVal
+UDPSend(wrkrInstanceData_t *pWrkrData, uchar *pszSourcename, char *msg, size_t len)
+{
+ struct addrinfo *r;
+ int lsent = 0;
+ int bSendSuccess;
+ instanceData *pData;
+ struct sockaddr_in *tempaddr,source_ip;
+ libnet_ptag_t ip;
+ libnet_ptag_t udp;
+ sbool bNeedUnlock = 0;
+ /* hdrOffs = fragmentation flags + offset (in bytes)
+ * divided by 8 */
+ unsigned msgOffs, hdrOffs;
+ unsigned maxPktLen, pktLen, udpPktLen;
+ uint16_t ip_id;
+ DEFiRet;
+
+ if(pWrkrData->pSockArray == NULL) {
+ CHKiRet(doTryResume(pWrkrData));
+ }
+ pData = pWrkrData->pData;
+
+ if(len > 65528) {
+ DBGPRINTF("omudpspoof: msg with length %d truncated to 64k: '%.768s'\n",
+ (int) len, msg);
+ len = 65528;
+ }
+
+ ip = udp = 0;
+ if(pWrkrData->sourcePort++ >= pData->sourcePortEnd){
+ pWrkrData->sourcePort = pData->sourcePortStart;
+ }
+
+ /* We need a non-zero id number for the IP headers,
+ * otherwise libnet will increase it after each
+ * build_ipv4, breaking the fragments */
+ ip_id = (uint16_t)libnet_get_prand(LIBNET_PR16);
+
+ inet_pton(AF_INET, (char*)pszSourcename, &(source_ip.sin_addr));
+ bSendSuccess = RSFALSE;
+ d_pthread_mutex_lock(&mutLibnet);
+ bNeedUnlock = 1;
+ for (r = pWrkrData->f_addr; r && bSendSuccess == RSFALSE ; r = r->ai_next) {
+ tempaddr = (struct sockaddr_in *)r->ai_addr;
+ /* Getting max payload size (must be multiple of 8) */
+ maxPktLen = (pData->mtu - LIBNET_IPV4_H) & ~0x07;
+ msgOffs = 0;
+ /* We're doing (payload size - UDP header size) and not
+ * checking if it's a multiple of 8 because we know the
+ * header is 8 bytes long */
+ if(len > (maxPktLen - LIBNET_UDP_H) ) {
+ hdrOffs = IP_MF;
+ pktLen = maxPktLen - LIBNET_UDP_H;
+ udpPktLen = len;
+ } else {
+ hdrOffs = 0;
+ pktLen = len;
+ udpPktLen = len;
+ }
+ DBGPRINTF("omudpspoof: stage 1: MF:%d, msgOffs %d, hdrOffs %d, pktLen %d, udpPktLen %d, maxPktLen %d\n",
+ (hdrOffs & IP_MF) >> 13, (hdrOffs & 0x1FFF) << 3, hdrOffs, pktLen, udpPktLen, maxPktLen);
+ libnet_clear_packet(pWrkrData->libnet_handle);
+
+ /* note: libnet does need ports in host order NOT in network byte order! -- rgerhards, 2009-11-12 */
+ udp = libnet_build_udp(
+ pWrkrData->sourcePort, /* source port */
+ ntohs(tempaddr->sin_port), /* destination port */
+ udpPktLen+LIBNET_UDP_H, /* packet length - use the FULL UDP Packet Length here */
+ 0, /* checksum */
+ (u_char*)msg, /* payload */
+ pktLen, /* payload size */
+ pWrkrData->libnet_handle, /* libnet handle */
+ udp); /* libnet id */
+ if (udp == -1) {
+ DBGPRINTF("omudpspoof: can't build UDP header: %s\n",
+ libnet_geterror(pWrkrData->libnet_handle));
+ }
+
+ ip = libnet_build_ipv4(
+ LIBNET_IPV4_H+LIBNET_UDP_H+pktLen, /* length */
+ 0, /* TOS */
+ ip_id, /* IP ID */
+ hdrOffs, /* IP Frag */
+ 64, /* TTL */
+ IPPROTO_UDP, /* protocol */
+ 0, /* checksum */
+ source_ip.sin_addr.s_addr,
+ tempaddr->sin_addr.s_addr,
+ NULL, /* payload */
+ 0, /* payload size */
+ pWrkrData->libnet_handle, /* libnet handle */
+ ip); /* libnet id */
+ if (ip == -1) {
+ DBGPRINTF("omudpspoof: can't build IP header: %s\n",
+ libnet_geterror(pWrkrData->libnet_handle));
+ }
+
+ // Disable UDP Checksum CALC if Packjet exceeds MTU
+ if(len > (maxPktLen - LIBNET_UDP_H) ) {
+ libnet_toggle_checksum(pWrkrData->libnet_handle, udp, 1);
+ }
+ /* Write it to the wire. */
+ lsent = libnet_write(pWrkrData->libnet_handle);
+ if(lsent != (int) (LIBNET_IPV4_H+LIBNET_UDP_H+pktLen)) {
+ /* note: access to fd is a libnet internal. If a newer version of libnet does
+ * not expose that member, we should simply remove it. However, while it is there
+ * it is useful for consolidating with strace output.
+ */
+ DBGPRINTF("omudpspoof: write error (total len %d): pktLen %d, sent %d, fd %d: %s\n",
+ (int) len, LIBNET_IPV4_H+LIBNET_UDP_H+pktLen, lsent, pWrkrData->libnet_handle->fd,
+ libnet_geterror(pWrkrData->libnet_handle));
+ if(lsent != -1) {
+ bSendSuccess = RSTRUE;
+ }
+ } else {
+ bSendSuccess = RSTRUE;
+ }
+ msgOffs += pktLen;
+
+ /* We need to get rid of the UDP header to build the other fragments */
+ libnet_clear_packet(pWrkrData->libnet_handle);
+ ip = LIBNET_PTAG_INITIALIZER;
+ while(len > msgOffs ) { /* loop until all payload is sent */
+ /* check if there will be more fragments */
+ if((len - msgOffs) > maxPktLen) {
+ /* In IP's eyes, the UDP header in the first packet
+ * needs to be in the offset, so we add its size to
+ * the payload offset here */
+ hdrOffs = IP_MF + (msgOffs + LIBNET_UDP_H)/8;
+ pktLen = maxPktLen;
+ } else {
+ /* See above */
+ hdrOffs = (msgOffs + LIBNET_UDP_H)/8;
+ pktLen = len - msgOffs;
+ }
+ DBGPRINTF("omudpspoof: stage 2: MF:%d, hdrOffs %d, pktLen %d\n",
+ (hdrOffs & IP_MF) >> 13, (hdrOffs & 0x1FFF) << 3, pktLen);
+ ip = libnet_build_ipv4(
+ LIBNET_IPV4_H + pktLen, /* length */
+ 0, /* TOS */
+ ip_id, /* IP ID */
+ hdrOffs, /* IP Frag */
+ 64, /* TTL */
+ IPPROTO_UDP, /* protocol */
+ 0, /* checksum */
+ source_ip.sin_addr.s_addr,
+ tempaddr->sin_addr.s_addr,
+ (uint8_t*)(msg+msgOffs), /* payload */
+ pktLen, /* payload size */
+ pWrkrData->libnet_handle, /* libnet handle */
+ ip); /* libnet id */
+ if (ip == -1) {
+ DBGPRINTF("omudpspoof: can't build IP fragment header: %s\n",
+ libnet_geterror(pWrkrData->libnet_handle));
+ }
+ /* Write it to the wire. */
+ lsent = libnet_write(pWrkrData->libnet_handle);
+ if(lsent != (int) (LIBNET_IPV4_H+pktLen)) {
+ DBGPRINTF("omudpspoof: fragment write error len %d, sent %d: %s\n",
+ (int) (LIBNET_IPV4_H+LIBNET_UDP_H+len), lsent,
+ libnet_geterror(pWrkrData->libnet_handle));
+ bSendSuccess = RSFALSE;
+ continue;
+ }
+ msgOffs += pktLen;
+ }
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pWrkrData->libnet_handle != NULL) {
+ libnet_destroy(pWrkrData->libnet_handle);
+ pWrkrData->libnet_handle = NULL;
+ }
+ }
+ if(bNeedUnlock) {
+ d_pthread_mutex_unlock(&mutLibnet);
+ }
+ RETiRet;
+}
+#ifdef _GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+/* try to resume connection if it is not ready
+ * rgerhards, 2007-08-02
+ */
+static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData)
+{
+ int iErr;
+ struct addrinfo *res;
+ struct addrinfo hints;
+ instanceData *pData;
+ DEFiRet;
+
+ if(pWrkrData->pSockArray != NULL)
+ FINALIZE;
+ pData = pWrkrData->pData;
+
+ if(pWrkrData->libnet_handle == NULL) {
+ /* Initialize the libnet library. Root priviledges are required.
+ * this initializes a IPv4 socket to use for forging UDP packets.
+ */
+ pWrkrData->libnet_handle = libnet_init(
+ LIBNET_RAW4, /* injection type */
+ NULL, /* network interface */
+ pWrkrData->errbuf); /* errbuf */
+
+ if(pWrkrData->libnet_handle == NULL) {
+ if(pData->bReportLibnetInitErr) {
+ LogError(0, RS_RET_ERR_LIBNET_INIT, "omudpsoof: error "
+ "initializing libnet - are you running as root?");
+ pData->bReportLibnetInitErr = 0;
+ }
+ ABORT_FINALIZE(RS_RET_ERR_LIBNET_INIT);
+ }
+ }
+ DBGPRINTF("omudpspoof: libnit_init() ok\n");
+ pData->bReportLibnetInitErr = 1;
+
+ /* The remote address is not yet known and needs to be obtained */
+ DBGPRINTF("omudpspoof trying resume for '%s'\n", pData->host);
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requires this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily(runModConf->pConf);
+ hints.ai_socktype = SOCK_DGRAM;
+ if((iErr = (getaddrinfo((char*)pData->host, (char*)getFwdPt(pData), &hints, &res))) != 0) {
+ DBGPRINTF("could not get addrinfo for hostname '%s':'%s': %d%s\n",
+ pData->host, getFwdPt(pData), iErr, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ DBGPRINTF("%s found, resuming.\n", pData->host);
+ pWrkrData->f_addr = res;
+ pWrkrData->pSockArray = net.create_udp_socket((uchar*)pData->host, NULL, 0, 0, 0, 0, NULL);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pWrkrData->f_addr != NULL) {
+ freeaddrinfo(pWrkrData->f_addr);
+ pWrkrData->f_addr = NULL;
+ }
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pWrkrData);
+ENDtryResume
+
+BEGINdoAction
+ char *psz; /* temporary buffering */
+ unsigned l;
+ int iMaxLine;
+CODESTARTdoAction
+ CHKiRet(doTryResume(pWrkrData));
+
+ DBGPRINTF(" %s:%s/omudpspoof, src '%s', msg strt '%.256s'\n", pWrkrData->pData->host,
+ getFwdPt(pWrkrData->pData), ppString[1], ppString[0]);
+
+ iMaxLine = glbl.GetMaxLine(runModConf->pConf);
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if((int) l > iMaxLine)
+ l = iMaxLine;
+
+ CHKiRet(UDPSend(pWrkrData, ppString[1], psz, l));
+
+finalize_it:
+ENDdoAction
+
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+ pData->sourcePortStart = DFLT_SOURCE_PORT_START;
+ pData->sourcePortEnd = DFLT_SOURCE_PORT_END;
+ pData->host = NULL;
+ pData->port = NULL;
+ pData->sourceTpl = (uchar*) strdup("RSYSLOG_omudpspoofDfltSourceTpl");
+ pData->mtu = 1500;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplToUse;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omudpspoof)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "omudpspoof: mandatory "
+ "parameters missing");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omudpspoof:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->host = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "sourcetemplate")) {
+ free(pData->sourceTpl);
+ pData->sourceTpl = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "sourceport.start")) {
+ pData->sourcePortStart = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "sourceport.end")) {
+ pData->sourcePortEnd = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "mtu")) {
+ pData->mtu = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("omudpspoof: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ CODE_STD_STRING_REQUESTnewActInst(2)
+
+ tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->sourceTpl), OMSR_NO_RQD_TPL_OPTS));
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ uchar *sourceTpl;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omudpspoof:", sizeof(":omudpspoof:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omudpspoof:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ sourceTpl = (cs.pszSourceNameTemplate == NULL) ? UCHAR_CONSTANT("RSYSLOG_omudpspoofDfltSourceTpl")
+ : cs.pszSourceNameTemplate;
+
+ if(cs.pszTargetHost == NULL) {
+ LogError(0, NO_ERRCODE, "No $ActionOMUDPSpoofTargetHost given, can not continue "
+ "with this action.");
+ ABORT_FINALIZE(RS_RET_HOST_NOT_SPECIFIED);
+ }
+
+ /* fill instance properties */
+ CHKmalloc(pData->host = ustrdup(cs.pszTargetHost));
+ if(cs.pszTargetPort == NULL)
+ pData->port = NULL;
+ else
+ CHKmalloc(pData->port = ustrdup(cs.pszTargetPort));
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(sourceTpl), OMSR_NO_RQD_TPL_OPTS));
+ pData->sourcePortStart = cs.iSourcePortStart;
+ pData->sourcePortEnd = cs.iSourcePortEnd;
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (cs.tplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : cs.tplName));
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* a common function to free our configuration variables - used both on exit
+ * and on $ResetConfig processing. -- rgerhards, 2008-05-16
+ */
+static void
+freeConfigVars(void)
+{
+ free(cs.tplName);
+ cs.tplName = NULL;
+ free(cs.pszTargetHost);
+ cs.pszTargetHost = NULL;
+ free(cs.pszTargetPort);
+ cs.pszTargetPort = NULL;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* destroy the libnet state needed for forged UDP sources */
+ pthread_mutex_destroy(&mutLibnet);
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ freeConfigVars();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2008-03-28
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ freeConfigVars();
+ /* we now must reset all non-string values */
+ cs.iSourcePortStart = DFLT_SOURCE_PORT_START;
+ cs.iSourcePortEnd = DFLT_SOURCE_PORT_END;
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net,LM_NET_FILENAME));
+
+ pthread_mutex_init(&mutLibnet, NULL);
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspoofdefaulttemplate", 0, eCmdHdlrGetWord,
+ setLegacyDfltTpl, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspoofsourcenametemplate", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszSourceNameTemplate, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspooftargethost", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszTargetHost, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspooftargetport", 0, eCmdHdlrGetWord, NULL,
+ &cs.pszTargetPort, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspoofsourceportstart", 0, eCmdHdlrInt, NULL,
+ &cs.iSourcePortStart, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionomudpspoofsourceportend", 0, eCmdHdlrInt, NULL,
+ &cs.iSourcePortEnd, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/omuxsock/Makefile.am b/plugins/omuxsock/Makefile.am
new file mode 100644
index 0000000..997232d
--- /dev/null
+++ b/plugins/omuxsock/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omuxsock.la
+
+omuxsock_la_SOURCES = omuxsock.c
+omuxsock_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omuxsock_la_LDFLAGS = -module -avoid-version
+omuxsock_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/omuxsock/Makefile.in b/plugins/omuxsock/Makefile.in
new file mode 100644
index 0000000..bb8beef
--- /dev/null
+++ b/plugins/omuxsock/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/omuxsock
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+omuxsock_la_DEPENDENCIES =
+am_omuxsock_la_OBJECTS = omuxsock_la-omuxsock.lo
+omuxsock_la_OBJECTS = $(am_omuxsock_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 =
+omuxsock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(omuxsock_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/omuxsock_la-omuxsock.Plo
+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 = $(omuxsock_la_SOURCES)
+DIST_SOURCES = $(omuxsock_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = omuxsock.la
+omuxsock_la_SOURCES = omuxsock.c
+omuxsock_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omuxsock_la_LDFLAGS = -module -avoid-version
+omuxsock_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/omuxsock/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/omuxsock/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+omuxsock.la: $(omuxsock_la_OBJECTS) $(omuxsock_la_DEPENDENCIES) $(EXTRA_omuxsock_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(omuxsock_la_LINK) -rpath $(pkglibdir) $(omuxsock_la_OBJECTS) $(omuxsock_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omuxsock_la-omuxsock.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+omuxsock_la-omuxsock.lo: omuxsock.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omuxsock_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omuxsock_la-omuxsock.lo -MD -MP -MF $(DEPDIR)/omuxsock_la-omuxsock.Tpo -c -o omuxsock_la-omuxsock.lo `test -f 'omuxsock.c' || echo '$(srcdir)/'`omuxsock.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omuxsock_la-omuxsock.Tpo $(DEPDIR)/omuxsock_la-omuxsock.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omuxsock.c' object='omuxsock_la-omuxsock.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) $(omuxsock_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omuxsock_la-omuxsock.lo `test -f 'omuxsock.c' || echo '$(srcdir)/'`omuxsock.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/omuxsock_la-omuxsock.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/omuxsock_la-omuxsock.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/omuxsock/omuxsock.c b/plugins/omuxsock/omuxsock.c
new file mode 100644
index 0000000..99fbc22
--- /dev/null
+++ b/plugins/omuxsock/omuxsock.c
@@ -0,0 +1,454 @@
+/* omuxsock.c
+ * This is the implementation of datgram unix domain socket forwarding.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2010-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "srUtils.h"
+#include "template.h"
+#include "msg.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omuxsock")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+
+#define INVLD_SOCK -1
+
+typedef struct _instanceData {
+ permittedPeers_t *pPermPeers;
+ uchar *sockName;
+ int sock;
+ struct sockaddr_un addr;
+} instanceData;
+
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+/* config data */
+typedef struct configSettings_s {
+ uchar *tplName; /* name of the default template to use */
+ uchar *sockName; /* name of the default template to use */
+} configSettings_t;
+static configSettings_t cs;
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.tplName = NULL;
+ cs.sockName = NULL;
+ENDinitConfVars
+
+
+static rsRetVal doTryResume(instanceData *pData);
+
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(cs.tplName == NULL)
+ return (uchar*)"RSYSLOG_TraditionalForwardFormat";
+ else
+ return cs.tplName;
+}
+
+/* set the default template to be used
+ * This is a module-global parameter, and as such needs special handling. It needs to
+ * be coordinated with values set via the v2 config system (rsyslog v6+). What we do
+ * is we do not permit this directive after the v2 config system has been used to set
+ * the parameter.
+ */
+static rsRetVal
+setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal)
+{
+ DEFiRet;
+
+ if(loadModConf != NULL && loadModConf->tplName != NULL) {
+ free(newVal);
+ LogError(0, RS_RET_ERR, "omuxsock default template already set via module "
+ "global parameter - can no longer be changed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ free(cs.tplName);
+ cs.tplName = newVal;
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+closeSocket(instanceData *pData)
+{
+ DEFiRet;
+ if(pData->sock != INVLD_SOCK) {
+ close(pData->sock);
+ pData->sock = INVLD_SOCK;
+ }
+ RETiRet;
+}
+
+
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omuxsock:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(cs.tplName != NULL) {
+ LogError(0, RS_RET_DUP_PARAM, "omuxsock: default template "
+ "was already set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else {
+ dbgprintf("omuxsock: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.tplName);
+ cs.tplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->sock = INVLD_SOCK;
+ENDcreateInstance
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* final cleanup */
+ closeSocket(pData);
+ free(pData->sockName);
+ENDfreeInstance
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("%s", pData->sockName);
+ENDdbgPrintInstInfo
+
+
+/* Send a message via UDP
+ * rgehards, 2007-12-20
+ */
+static rsRetVal sendMsg(instanceData *pData, char *msg, size_t len)
+{
+ DEFiRet;
+ unsigned lenSent = 0;
+
+ if(pData->sock == INVLD_SOCK) {
+ CHKiRet(doTryResume(pData));
+ }
+
+ if(pData->sock != INVLD_SOCK) {
+ lenSent = sendto(pData->sock, msg, len, 0, (const struct sockaddr *)&pData->addr,
+ sizeof(pData->addr));
+ if(lenSent != len) {
+ int eno = errno;
+ char errStr[1024];
+ DBGPRINTF("omuxsock suspending: sendto(), socket %d, error: %d = %s.\n",
+ pData->sock, eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* open socket to remote system
+ */
+static rsRetVal
+openSocket(instanceData *pData)
+{
+ DEFiRet;
+ assert(pData->sock == INVLD_SOCK);
+
+ if((pData->sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ char errStr[1024];
+ int eno = errno;
+ DBGPRINTF("error %d creating AF_UNIX/SOCK_DGRAM: %s.\n",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ pData->sock = INVLD_SOCK;
+ ABORT_FINALIZE(RS_RET_NO_SOCKET);
+
+ }
+
+ /* set up server address structure */
+ memset(&pData->addr, 0, sizeof(pData->addr));
+ pData->addr.sun_family = AF_UNIX;
+ strncpy(pData->addr.sun_path, (char*)pData->sockName, sizeof(pData->addr.sun_path));
+ pData->addr.sun_path[sizeof(pData->addr.sun_path)-1] = '\0';
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ closeSocket(pData);
+ }
+ RETiRet;
+}
+
+
+
+/* try to resume connection if it is not ready
+ */
+static rsRetVal doTryResume(instanceData *pData)
+{
+ DEFiRet;
+
+ DBGPRINTF("omuxsock trying to resume\n");
+ closeSocket(pData);
+ iRet = openSocket(pData);
+
+ if(iRet != RS_RET_OK) {
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pWrkrData->pData);
+ENDtryResume
+
+BEGINdoAction
+ char *psz = NULL; /* temporary buffering */
+ register unsigned l;
+ int iMaxLine;
+CODESTARTdoAction
+ pthread_mutex_lock(&mutDoAct);
+ CHKiRet(doTryResume(pWrkrData->pData));
+
+ iMaxLine = glbl.GetMaxLine(runModConf->pConf);
+
+ DBGPRINTF(" omuxsock:%s\n", pWrkrData->pData->sockName);
+
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if((int) l > iMaxLine)
+ l = iMaxLine;
+
+ CHKiRet(sendMsg(pWrkrData->pData, psz, l));
+
+finalize_it:
+ pthread_mutex_unlock(&mutDoAct);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omuxsock:", sizeof(":omuxsock:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omuxsock:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, getDfltTpl()));
+
+ if(cs.sockName == NULL) {
+ LogError(0, RS_RET_NO_SOCK_CONFIGURED, "No output socket configured for omuxsock\n");
+ ABORT_FINALIZE(RS_RET_NO_SOCK_CONFIGURED);
+ }
+
+ pData->sockName = cs.sockName;
+ cs.sockName = NULL; /* pData is now owner and will fee it */
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* a common function to free our configuration variables - used both on exit
+ * and on $ResetConfig processing. -- rgerhards, 2008-05-16
+ */
+static void
+freeConfigVars(void)
+{
+ free(cs.tplName);
+ cs.tplName = NULL;
+ free(cs.sockName);
+ cs.sockName = NULL;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+
+ freeConfigVars();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2008-03-28
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ freeConfigVars();
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"omuxsockdefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl,
+ NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"omuxsocksocket", 0, eCmdHdlrGetWord, NULL, &cs.sockName, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/pmciscoios/Makefile.am b/plugins/pmciscoios/Makefile.am
new file mode 100644
index 0000000..23a08ba
--- /dev/null
+++ b/plugins/pmciscoios/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmciscoios.la
+
+pmciscoios_la_SOURCES = pmciscoios.c
+pmciscoios_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmciscoios_la_LDFLAGS = -module -avoid-version
+pmciscoios_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/pmciscoios/Makefile.in b/plugins/pmciscoios/Makefile.in
new file mode 100644
index 0000000..6bcc8ce
--- /dev/null
+++ b/plugins/pmciscoios/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/pmciscoios
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmciscoios_la_DEPENDENCIES =
+am_pmciscoios_la_OBJECTS = pmciscoios_la-pmciscoios.lo
+pmciscoios_la_OBJECTS = $(am_pmciscoios_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 =
+pmciscoios_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmciscoios_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmciscoios_la-pmciscoios.Plo
+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 = $(pmciscoios_la_SOURCES)
+DIST_SOURCES = $(pmciscoios_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmciscoios.la
+pmciscoios_la_SOURCES = pmciscoios.c
+pmciscoios_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmciscoios_la_LDFLAGS = -module -avoid-version
+pmciscoios_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/pmciscoios/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/pmciscoios/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmciscoios.la: $(pmciscoios_la_OBJECTS) $(pmciscoios_la_DEPENDENCIES) $(EXTRA_pmciscoios_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmciscoios_la_LINK) -rpath $(pkglibdir) $(pmciscoios_la_OBJECTS) $(pmciscoios_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmciscoios_la-pmciscoios.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmciscoios_la-pmciscoios.lo: pmciscoios.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmciscoios_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmciscoios_la-pmciscoios.lo -MD -MP -MF $(DEPDIR)/pmciscoios_la-pmciscoios.Tpo -c -o pmciscoios_la-pmciscoios.lo `test -f 'pmciscoios.c' || echo '$(srcdir)/'`pmciscoios.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmciscoios_la-pmciscoios.Tpo $(DEPDIR)/pmciscoios_la-pmciscoios.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmciscoios.c' object='pmciscoios_la-pmciscoios.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) $(pmciscoios_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmciscoios_la-pmciscoios.lo `test -f 'pmciscoios.c' || echo '$(srcdir)/'`pmciscoios.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmciscoios_la-pmciscoios.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmciscoios_la-pmciscoios.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/pmciscoios/pmciscoios.c b/plugins/pmciscoios/pmciscoios.c
new file mode 100644
index 0000000..ac0c93f
--- /dev/null
+++ b/plugins/pmciscoios/pmciscoios.c
@@ -0,0 +1,294 @@
+/* pmrciscoios.c
+ * This is a parser module for CISCO IOS "syslog" format.
+ *
+ * File begun on 2014-07-07 by RGerhards
+ *
+ * Copyright 2014-2015 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.ciscoios")
+MODULE_CNFNAME("pmciscoios")
+
+/* internal structures */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* parser instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "present.origin", eCmdHdlrBinary, 0 },
+ { "present.xr", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+struct instanceConf_s {
+ int bOriginPresent; /* is ORIGIN field present? */
+ int bXrPresent; /* is XR? */
+};
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->bOriginPresent = 0;
+ inst->bXrPresent = 0;
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ dbgprintf("pmciscoios: free parser instance %p\n", pInst);
+ENDfreeParserInst
+
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewParserInst
+ DBGPRINTF("newParserInst (pmciscoios)\n");
+
+ inst = NULL;
+ CHKiRet(createInstance(&inst));
+
+ if(lst == NULL)
+ FINALIZE; /* just set defaults, no param block! */
+
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("parser param blk in pmciscoios:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "present.origin")) {
+ inst->bOriginPresent = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "present.xr")) {
+ inst->bXrPresent = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("pmciscoios: program error, non-handled "
+ "param '%s'\n", parserpblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ if(iRet != RS_RET_OK)
+ freeParserInst(inst);
+ENDnewParserInst
+
+
+BEGINparse2
+ uchar *p2parse;
+ long long msgcounter;
+ int lenMsg;
+ int i;
+ int iHostname = 0;
+ uchar bufParseTAG[512];
+ uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE]; /* used by origin */
+CODESTARTparse2
+ DBGPRINTF("Message will now be parsed by pmciscoios\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+
+ /* first obtain the MESSAGE COUNTER. It must be numeric up until
+ * the ": " terminator sequence
+ */
+ msgcounter = 0;
+ while(lenMsg > 0 && (*p2parse >= '0' && *p2parse <= '9') ) {
+ msgcounter = msgcounter * 10 + *p2parse - '0';
+ ++p2parse, --lenMsg;
+ }
+ DBGPRINTF("pmciscoios: msgcntr %lld\n", msgcounter);
+
+ /* delimiter check */
+ if(lenMsg < 2 || *p2parse != ':' || *(p2parse+1) != ' ') {
+ DBGPRINTF("pmciscoios: fail after seqno: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ p2parse += 2;
+
+ /* ORIGIN (optional) */
+ if(pInst->bOriginPresent) {
+ iHostname = 0;
+ while( lenMsg > 1
+ && !(*p2parse == ':' && *(p2parse+1) == ' ') /* IPv6 is e.g. "::1" (loopback) */
+ && iHostname < (int) sizeof(bufParseHOSTNAME) - 1 ) {
+ bufParseHOSTNAME[iHostname++] = *p2parse++;
+ --lenMsg;
+ }
+ bufParseHOSTNAME[iHostname] = '\0';
+ /* delimiter check */
+ if(lenMsg < 2 || *(p2parse+1) != ' ') {
+ DBGPRINTF("pmciscoios: fail after origin: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ p2parse += 2;
+ }
+
+ /* XR RSP (optional) */
+ if(pInst->bXrPresent) {
+ while( lenMsg > 1
+ && !(*p2parse == ':')) {
+ --lenMsg;
+ ++p2parse;
+ }
+ /* delimiter check */
+ if(lenMsg < 2) {
+ DBGPRINTF("pmciscoios: fail after XR: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ p2parse += 1;
+ }
+
+ /* TIMESTAMP */
+ if(p2parse[0] == '*' || p2parse[0] == '.') p2parse++;
+ if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, PARSE3164_TZSTRING,
+ NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
+ if(pMsg->dfltTZ[0] != '\0')
+ applyDfltTZ(&pMsg->tTIMESTAMP, pMsg->dfltTZ);
+ } else {
+ DBGPRINTF("pmciscoios: fail at timestamp: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ /* Note: date parser strips ": ", so we cannot do the delimiter check here */
+
+ /* XR RSP (optional) */
+ if(pInst->bXrPresent) {
+ while( lenMsg > 1
+ && !(*p2parse == '%')) {
+ --lenMsg;
+ p2parse++;
+ }
+ /* delimiter check */
+ if(lenMsg < 2) {
+ DBGPRINTF("pmciscoios: fail after XR tag search: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ }
+
+ /* parse SYSLOG TAG. must always start with '%', else we have a field mismatch */
+ if(lenMsg < 1 || *p2parse != '%') {
+ DBGPRINTF("pmciscoios: fail at tag begin (no '%%'): '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ i = 0;
+ while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < (int) sizeof(bufParseTAG) - 2) {
+ bufParseTAG[i++] = *p2parse++;
+ --lenMsg;
+ }
+ /* delimiter check */
+ if(pInst->bXrPresent) p2parse++;
+ if(lenMsg < 2 || *p2parse != ':' || *(p2parse+1) != ' ') {
+ DBGPRINTF("pmciscoios: fail after tag: '%s'\n", p2parse);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ ++p2parse;
+ bufParseTAG[i++] = ':';
+ bufParseTAG[i] = '\0'; /* terminate string */
+
+ /* if we reach this point, we have a wellformed message and can persist the values */
+ MsgSetTAG(pMsg, bufParseTAG, i);
+ /* if bOriginPresent !=0 iHostname gets initialized */
+ if(pInst->bOriginPresent)
+ MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, iHostname);
+ MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg);
+ setProtocolVersion(pMsg, MSG_LEGACY_PROTOCOL);
+finalize_it:
+ENDparse2
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("pmciscoios parser init called\n");
+ENDmodInit
diff --git a/plugins/pmlastmsg/Makefile.am b/plugins/pmlastmsg/Makefile.am
new file mode 100644
index 0000000..f360243
--- /dev/null
+++ b/plugins/pmlastmsg/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmlastmsg.la
+
+pmlastmsg_la_SOURCES = pmlastmsg.c
+pmlastmsg_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmlastmsg_la_LDFLAGS = -module -avoid-version
+pmlastmsg_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/pmlastmsg/Makefile.in b/plugins/pmlastmsg/Makefile.in
new file mode 100644
index 0000000..207579f
--- /dev/null
+++ b/plugins/pmlastmsg/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/pmlastmsg
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmlastmsg_la_DEPENDENCIES =
+am_pmlastmsg_la_OBJECTS = pmlastmsg_la-pmlastmsg.lo
+pmlastmsg_la_OBJECTS = $(am_pmlastmsg_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 =
+pmlastmsg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmlastmsg_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmlastmsg_la-pmlastmsg.Plo
+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 = $(pmlastmsg_la_SOURCES)
+DIST_SOURCES = $(pmlastmsg_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmlastmsg.la
+pmlastmsg_la_SOURCES = pmlastmsg.c
+pmlastmsg_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmlastmsg_la_LDFLAGS = -module -avoid-version
+pmlastmsg_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/pmlastmsg/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/pmlastmsg/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmlastmsg.la: $(pmlastmsg_la_OBJECTS) $(pmlastmsg_la_DEPENDENCIES) $(EXTRA_pmlastmsg_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmlastmsg_la_LINK) -rpath $(pkglibdir) $(pmlastmsg_la_OBJECTS) $(pmlastmsg_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmlastmsg_la-pmlastmsg.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmlastmsg_la-pmlastmsg.lo: pmlastmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmlastmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmlastmsg_la-pmlastmsg.lo -MD -MP -MF $(DEPDIR)/pmlastmsg_la-pmlastmsg.Tpo -c -o pmlastmsg_la-pmlastmsg.lo `test -f 'pmlastmsg.c' || echo '$(srcdir)/'`pmlastmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmlastmsg_la-pmlastmsg.Tpo $(DEPDIR)/pmlastmsg_la-pmlastmsg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmlastmsg.c' object='pmlastmsg_la-pmlastmsg.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) $(pmlastmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmlastmsg_la-pmlastmsg.lo `test -f 'pmlastmsg.c' || echo '$(srcdir)/'`pmlastmsg.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmlastmsg_la-pmlastmsg.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmlastmsg_la-pmlastmsg.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/pmlastmsg/pmlastmsg.c b/plugins/pmlastmsg/pmlastmsg.c
new file mode 100644
index 0000000..7916515
--- /dev/null
+++ b/plugins/pmlastmsg/pmlastmsg.c
@@ -0,0 +1,169 @@
+/* pmlastmsg.c
+ * This is a parser module specifically for those horrible
+ * "<PRI>last message repeated n times" messages notoriously generated
+ * by some syslog implementations. Note that this parser should be placed
+ * on top of the parser stack -- it takes out only these messages and
+ * leaves all others for processing by the other parsers.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-07-13 by RGerhards
+ *
+ * Copyright 2014-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.lastline")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* parse a legay-formatted syslog message.
+ */
+BEGINparse
+ uchar *p2parse;
+ int lenMsg;
+#define OpeningText "last message repeated "
+#define ClosingText " times"
+CODESTARTparse
+ dbgprintf("Message will now be parsed by \"last message repated n times\" parser.\n");
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+
+ /* check if this message is of the type we handle in this (very limited) parser */
+ /* first, we permit SP */
+ while(lenMsg && *p2parse == ' ') {
+ --lenMsg;
+ ++p2parse;
+ }
+ if((unsigned) lenMsg < sizeof(OpeningText)-1 + sizeof(ClosingText)-1 + 1) {
+ /* too short, can not be "our" message */
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ if(strncasecmp((char*) p2parse, OpeningText, sizeof(OpeningText)-1) != 0) {
+ /* wrong opening text */
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ lenMsg -= sizeof(OpeningText) - 1;
+ p2parse += sizeof(OpeningText) - 1;
+
+ /* now we need an integer --> digits */
+ while(lenMsg && isdigit(*p2parse)) {
+ --lenMsg;
+ ++p2parse;
+ }
+
+ if(lenMsg != sizeof(ClosingText)-1) {
+ /* size must fit, else it is not "our" message... */
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ if(strncasecmp((char*) p2parse, ClosingText, lenMsg) != 0) {
+ /* wrong closing text */
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+
+ /* OK, now we know we need to process this message, so we do that
+ * (and it is fairly simple in our case...)
+ */
+ DBGPRINTF("pmlastmsg detected a \"last message repeated n times\" message\n");
+
+ setProtocolVersion(pMsg, MSG_LEGACY_PROTOCOL);
+ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime));
+ MsgSetMSGoffs(pMsg, pMsg->offAfterPRI); /* we don't have a header! */
+ MsgSetTAG(pMsg, (uchar*)"", 0);
+
+finalize_it:
+ENDparse
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ dbgprintf("lastmsg parser init called, compiled with version %s\n", VERSION);
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+
+
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/pmnormalize/Makefile.am b/plugins/pmnormalize/Makefile.am
new file mode 100644
index 0000000..e286760
--- /dev/null
+++ b/plugins/pmnormalize/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmnormalize.la
+
+pmnormalize_la_SOURCES = pmnormalize.c
+pmnormalize_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGNORM_CFLAGS) -I ../../tools
+pmnormalize_la_LDFLAGS = -module -avoid-version $(LIBLOGNORM_LIBS)
+pmnormalize_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/pmnormalize/Makefile.in b/plugins/pmnormalize/Makefile.in
new file mode 100644
index 0000000..432b109
--- /dev/null
+++ b/plugins/pmnormalize/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/pmnormalize
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmnormalize_la_DEPENDENCIES =
+am_pmnormalize_la_OBJECTS = pmnormalize_la-pmnormalize.lo
+pmnormalize_la_OBJECTS = $(am_pmnormalize_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 =
+pmnormalize_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(pmnormalize_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmnormalize_la-pmnormalize.Plo
+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 = $(pmnormalize_la_SOURCES)
+DIST_SOURCES = $(pmnormalize_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmnormalize.la
+pmnormalize_la_SOURCES = pmnormalize.c
+pmnormalize_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBLOGNORM_CFLAGS) -I ../../tools
+pmnormalize_la_LDFLAGS = -module -avoid-version $(LIBLOGNORM_LIBS)
+pmnormalize_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/pmnormalize/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/pmnormalize/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmnormalize.la: $(pmnormalize_la_OBJECTS) $(pmnormalize_la_DEPENDENCIES) $(EXTRA_pmnormalize_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmnormalize_la_LINK) -rpath $(pkglibdir) $(pmnormalize_la_OBJECTS) $(pmnormalize_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmnormalize_la-pmnormalize.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmnormalize_la-pmnormalize.lo: pmnormalize.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmnormalize_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmnormalize_la-pmnormalize.lo -MD -MP -MF $(DEPDIR)/pmnormalize_la-pmnormalize.Tpo -c -o pmnormalize_la-pmnormalize.lo `test -f 'pmnormalize.c' || echo '$(srcdir)/'`pmnormalize.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmnormalize_la-pmnormalize.Tpo $(DEPDIR)/pmnormalize_la-pmnormalize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmnormalize.c' object='pmnormalize_la-pmnormalize.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) $(pmnormalize_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmnormalize_la-pmnormalize.lo `test -f 'pmnormalize.c' || echo '$(srcdir)/'`pmnormalize.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmnormalize_la-pmnormalize.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmnormalize_la-pmnormalize.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/pmnormalize/pmnormalize.c b/plugins/pmnormalize/pmnormalize.c
new file mode 100644
index 0000000..4d3ad76
--- /dev/null
+++ b/plugins/pmnormalize/pmnormalize.c
@@ -0,0 +1,270 @@
+/* pmnormalize.c
+ * This is a parser module for parsing incoming messages using liblognorm.
+ *
+ * File begun on 2017-03-03 by Pascal Withopf.
+ *
+ * Copyright 2014-2019 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <liblognorm.h>
+#include <json.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.pmnormalize")
+MODULE_CNFNAME("pmnormalize")
+
+/* internal structures */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* parser instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "rulebase", eCmdHdlrGetWord, 0 },
+ { "rule", eCmdHdlrArray, 0 },
+ { "undefinedpropertyerror", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+struct instanceConf_s {
+ sbool undefPropErr;
+ char *rulebase;
+ char *rule;
+ ln_ctx ctxln; /*context to be used for liblognorm*/
+ char *pszPath; /*path of normalized data*/
+};
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->undefPropErr = 0;
+ inst->rulebase = NULL;
+ inst->rule = NULL;
+ inst->ctxln = NULL;
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+/* callback for liblognorm error messages */
+static void
+errCallBack(void __attribute__((unused)) *cookie, const char *msg,
+ size_t __attribute__((unused)) lenMsg)
+{
+ LogError(0, RS_RET_ERR_LIBLOGNORM, "liblognorm error: %s", msg);
+}
+
+/* to be called to build the liblognorm part of the instance ONCE ALL PARAMETERS ARE CORRECT
+ * (and set within inst!).
+ */
+static rsRetVal
+buildInstance(instanceConf_t *inst)
+{
+ DEFiRet;
+ if((inst->ctxln = ln_initCtx()) == NULL) {
+ LogError(0, RS_RET_ERR_LIBLOGNORM_INIT, "error: could not initialize "
+ "liblognorm ctx, cannot activate action");
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_INIT);
+ }
+ ln_setErrMsgCB(inst->ctxln, errCallBack, NULL);
+
+ if(inst->rule != NULL && inst->rulebase == NULL) {
+ if(ln_loadSamplesFromString(inst->ctxln, inst->rule) !=0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' "
+ "could not be loaded, cannot activate action", inst->rule);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ } else if(inst->rulebase != NULL && inst->rule == NULL) {
+ if(ln_loadSamples(inst->ctxln, (char*) inst->rulebase) != 0) {
+ LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' "
+ "could not be loaded, cannot activate action", inst->rulebase);
+ ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD);
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ dbgprintf("pmnormalize: free parser instance %p\n", pInst);
+ free(pInst->rulebase);
+ free(pInst->rule);
+ if(pInst->ctxln != NULL) {
+ ln_exitCtx(pInst->ctxln);
+ }
+ENDfreeParserInst
+
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewParserInst
+ DBGPRINTF("newParserInst (pmnormalize)\n");
+
+ inst = NULL;
+ CHKiRet(createInstance(&inst));
+
+ if(lst == NULL)
+ FINALIZE; /* just set defaults, no param block! */
+
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("parser param blk in pmnormalize:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "undefinedpropertyerror")) {
+ inst->undefPropErr = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "rulebase")) {
+ inst->rulebase = (char *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(parserpblk.descr[i].name, "rule")) {
+ es_str_t *rules;
+ CHKmalloc(rules = es_newStr(128));
+ for(int j=0; j < pvals[i].val.d.ar->nmemb; ++j) {
+ CHKiRet(es_addStr(&rules, pvals[i].val.d.ar->arr[j]));
+ CHKiRet(es_addChar(&rules, '\n'));
+ }
+ inst->rule = (char*)es_str2cstr(rules, NULL);
+ if(rules != NULL)
+ es_deleteStr(rules);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR ,
+ "pmnormalize: program error, non-handled param '%s'",
+ parserpblk.descr[i].name);
+ }
+ }
+ if(!inst->rulebase && !inst->rule) {
+ LogError(0, RS_RET_CONFIG_ERROR, "pmnormalize: you need to specify "
+ "either parameter 'rule' or 'rulebase'.");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ if(inst->rulebase && inst->rule) {
+ LogError(0, RS_RET_CONFIG_ERROR, "pmnormalize: you need to specify "
+ "one of the parameters 'rule' and 'rulebase', but not both");
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+
+ iRet = buildInstance(inst);
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ if(iRet != RS_RET_OK && inst != NULL)
+ freeParserInst(inst);
+ENDnewParserInst
+
+
+BEGINparse2
+ uchar *buf;
+ rs_size_t len;
+ int r;
+ struct json_object *json = NULL;
+CODESTARTparse2
+ DBGPRINTF("Message will now be parsed by pmnormalize\n");
+ /*Msg OffSet needs to be set*/
+ MsgSetMSGoffs(pMsg, 0);
+
+ getRawMsg(pMsg, &buf, &len);
+ r = ln_normalize(pInst->ctxln, (char*)buf, len, &json);
+ if(r != 0) {
+ DBGPRINTF("error %d during ln_normalize\n", r);
+ if(pInst->undefPropErr) {
+ LogError(0, RS_RET_ERR, "error %d during ln_normalize; "
+ "json: %s\n", r, fjson_object_to_json_string(json));
+ }
+ fjson_object_put(json);
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ } else {
+ iRet = MsgSetPropsViaJSON_Object(pMsg, json);
+ }
+finalize_it:
+ENDparse2
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("pmnormalize parser init called\n");
+ENDmodInit
diff --git a/plugins/pmnull/Makefile.am b/plugins/pmnull/Makefile.am
new file mode 100644
index 0000000..eb310a1
--- /dev/null
+++ b/plugins/pmnull/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = pmnull.la
+
+pmnull_la_SOURCES = pmnull.c
+pmnull_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmnull_la_LDFLAGS = -module -avoid-version
+pmnull_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/pmnull/Makefile.in b/plugins/pmnull/Makefile.in
new file mode 100644
index 0000000..5723f2e
--- /dev/null
+++ b/plugins/pmnull/Makefile.in
@@ -0,0 +1,797 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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 = plugins/pmnull
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/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)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+pmnull_la_DEPENDENCIES =
+am_pmnull_la_OBJECTS = pmnull_la-pmnull.lo
+pmnull_la_OBJECTS = $(am_pmnull_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 =
+pmnull_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(pmnull_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pmnull_la-pmnull.Plo
+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 = $(pmnull_la_SOURCES)
+DIST_SOURCES = $(pmnull_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = pmnull.la
+pmnull_la_SOURCES = pmnull.c
+pmnull_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools
+pmnull_la_LDFLAGS = -module -avoid-version
+pmnull_la_LIBADD =
+EXTRA_DIST =
+all: 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) --gnu plugins/pmnull/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/pmnull/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+
+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}; \
+ }
+
+pmnull.la: $(pmnull_la_OBJECTS) $(pmnull_la_DEPENDENCIES) $(EXTRA_pmnull_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pmnull_la_LINK) -rpath $(pkglibdir) $(pmnull_la_OBJECTS) $(pmnull_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmnull_la-pmnull.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+pmnull_la-pmnull.lo: pmnull.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmnull_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmnull_la-pmnull.lo -MD -MP -MF $(DEPDIR)/pmnull_la-pmnull.Tpo -c -o pmnull_la-pmnull.lo `test -f 'pmnull.c' || echo '$(srcdir)/'`pmnull.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmnull_la-pmnull.Tpo $(DEPDIR)/pmnull_la-pmnull.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmnull.c' object='pmnull_la-pmnull.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) $(pmnull_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmnull_la-pmnull.lo `test -f 'pmnull.c' || echo '$(srcdir)/'`pmnull.c
+
+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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+
+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-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pmnull_la-pmnull.Plo
+ -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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/pmnull_la-pmnull.Plo
+ -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-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# 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/plugins/pmnull/pmnull.c b/plugins/pmnull/pmnull.c
new file mode 100644
index 0000000..df389d7
--- /dev/null
+++ b/plugins/pmnull/pmnull.c
@@ -0,0 +1,187 @@
+/* pmnull.c
+ * This is a parser module for CISCO IOS "syslog" format.
+ *
+ * File begun on 2014-07-07 by RGerhards
+ *
+ * Copyright 2014-2015 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.pmnull")
+MODULE_CNFNAME("pmnull")
+
+/* internal structures */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* parser instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "tag", eCmdHdlrString, 0 },
+ { "syslogfacility", eCmdHdlrFacility, 0 },
+ { "syslogseverity", eCmdHdlrSeverity, 0 }
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+struct instanceConf_s {
+ const char *tag;
+ size_t lenTag;
+ int pri;
+};
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->tag = NULL;
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ dbgprintf("pmnull: free parser instance %p\n", pInst);
+ENDfreeParserInst
+
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+ int syslogfacility = 1; /* default as of rfc3164 */
+ int syslogseverity = 5; /* default as of rfc3164 */
+CODESTARTnewParserInst
+ DBGPRINTF("newParserInst (pmnull)\n");
+
+ inst = NULL;
+ CHKiRet(createInstance(&inst));
+
+ if(lst == NULL)
+ FINALIZE; /* just set defaults, no param block! */
+
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("parser param blk in pmnull:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "tag")) {
+ inst->tag = (const char *) es_str2cstr(pvals[i].val.d.estr, NULL);
+ inst->lenTag = strlen(inst->tag);
+ } else if(!strcmp(parserpblk.descr[i].name, "syslogfacility")) {
+ syslogfacility = pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "syslogseverity")) {
+ syslogseverity = pvals[i].val.d.n;
+ } else {
+ dbgprintf("pmnull: program error, non-handled "
+ "param '%s'\n", parserpblk.descr[i].name);
+ }
+ }
+ inst->pri = syslogfacility*8 + syslogseverity;
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ if(iRet != RS_RET_OK)
+ freeParserInst(inst);
+ENDnewParserInst
+
+
+BEGINparse2
+CODESTARTparse2
+ DBGPRINTF("Message will now be parsed by pmnull\n");
+ if(pInst->tag != NULL) {
+ MsgSetTAG(pMsg, (uchar *)pInst->tag, pInst->lenTag);
+ }
+ msgSetPRI(pMsg, pInst->pri);
+ MsgSetMSGoffs(pMsg, 0);
+ENDparse2
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("pmnull parser init called\n");
+ENDmodInit
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
new file mode 100644
index 0000000..f1f5c4c
--- /dev/null
+++ b/runtime/Makefile.am
@@ -0,0 +1,318 @@
+sbin_PROGRAMS =
+man_MANS =
+noinst_LIBRARIES =
+noinst_LTLIBRARIES = librsyslog.la
+pkglib_LTLIBRARIES =
+#pkglib_LTLIBRARIES = librsyslog.la
+
+librsyslog_la_SOURCES = \
+ rsyslog.c \
+ rsyslog.h \
+ typedefs.h \
+ dnscache.c \
+ dnscache.h \
+ unicode-helper.h \
+ atomic.h \
+ batch.h \
+ syslogd-types.h \
+ module-template.h \
+ im-helper.h \
+ obj-types.h \
+ sigprov.h \
+ cryprov.h \
+ nsd.h \
+ glbl.h \
+ glbl.c \
+ unlimited_select.h \
+ conf.c \
+ conf.h \
+ janitor.c \
+ janitor.h \
+ rsconf.c \
+ rsconf.h \
+ parser.h \
+ parser.c \
+ strgen.h \
+ strgen.c \
+ msg.c \
+ msg.h \
+ linkedlist.c \
+ linkedlist.h \
+ objomsr.c \
+ objomsr.h \
+ stringbuf.c \
+ stringbuf.h \
+ datetime.c \
+ datetime.h \
+ srutils.c \
+ srUtils.h \
+ errmsg.c \
+ errmsg.h \
+ operatingstate.c \
+ operatingstate.h \
+ debug.c \
+ debug.h \
+ obj.c \
+ obj.h \
+ modules.c \
+ modules.h \
+ statsobj.c \
+ statsobj.h \
+ dynstats.c \
+ dynstats.h \
+ perctile_ringbuf.c \
+ perctile_ringbuf.h \
+ perctile_stats.c \
+ perctile_stats.h \
+ statsobj.h \
+ stream.c \
+ stream.h \
+ var.c \
+ var.h \
+ wtp.c \
+ wtp.h \
+ wti.c \
+ wti.h \
+ queue.c \
+ queue.h \
+ ruleset.c \
+ ruleset.h \
+ prop.c \
+ prop.h \
+ ratelimit.c \
+ ratelimit.h \
+ lookup.c \
+ lookup.h \
+ cfsysline.c \
+ cfsysline.h \
+ \
+ ../action.h \
+ ../action.c \
+ ../threads.c \
+ ../threads.h \
+ \
+ ../parse.c \
+ ../parse.h \
+ \
+ hashtable.c \
+ hashtable.h \
+ hashtable_itr.c \
+ hashtable_itr.h \
+ hashtable_private.h \
+ \
+ ../outchannel.c \
+ ../outchannel.h \
+ ../template.c \
+ ../template.h \
+ timezones.c \
+ timezones.h
+# the files with ../ we need to work on - so that they either become part of the
+# runtime or will no longer be needed. -- rgerhards, 2008-06-13
+#
+#if OS_LINUX
+#librsyslog_la_SOURCES += \
+#endif
+
+if WITH_MODDIRS
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\"
+else
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I\$(top_srcdir) -I\$(top_srcdir)/grammar
+endif
+#librsyslog_la_LDFLAGS = -module -avoid-version
+librsyslog_la_CPPFLAGS += $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) ${LIBESTR_CFLAGS}
+librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) $(LIBFASTJSON_LIBS) ${LIBESTR_LIBS} -lm
+
+if ENABLE_LIBLOGGING_STDLOG
+librsyslog_la_CPPFLAGS += ${LIBLOGGING_STDLOG_CFLAGS}
+librsyslog_la_LIBADD += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+librsyslog_la_CPPFLAGS += -I\$(top_srcdir)/tools
+
+#
+# regular expression support
+#
+if ENABLE_REGEXP
+pkglib_LTLIBRARIES += lmregexp.la
+lmregexp_la_SOURCES = regexp.c regexp.h
+lmregexp_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmregexp_la_LDFLAGS = -module -avoid-version
+lmregexp_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmregexp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmregexp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+endif
+
+#
+# zlib support
+#
+pkglib_LTLIBRARIES += lmzlibw.la
+lmzlibw_la_SOURCES = zlibw.c zlibw.h
+lmzlibw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmzlibw_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS)
+lmzlibw_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmzlibw_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmzlibw_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+
+#
+# basic network support, needed for rsyslog startup (e.g. our own system name)
+#
+pkglib_LTLIBRARIES += lmnet.la
+lmnet_la_SOURCES = net.c net.h
+lmnet_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmnet_la_LDFLAGS = -module -avoid-version ../compat/compat_la-getifaddrs.lo
+lmnet_la_LIBADD =
+
+if ENABLE_INET
+pkglib_LTLIBRARIES += lmnetstrms.la
+if ENABLE_LIBLOGGING_STDLOG
+lmnet_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmnet_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+# network stream master class and stream factory
+lmnetstrms_la_SOURCES = netstrms.c netstrms.h \
+ netstrm.c netstrm.h \
+ nssel.c nssel.h \
+ nspoll.c nspoll.h
+lmnetstrms_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmnetstrms_la_LDFLAGS = -module -avoid-version
+lmnetstrms_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmnetstrms_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmnetstrms_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+# netstream drivers
+
+# plain tcp driver - main driver
+pkglib_LTLIBRARIES += lmnsd_ptcp.la
+lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h \
+ nsdsel_ptcp.c nsdsel_ptcp.h \
+ nsdpoll_ptcp.c nsdpoll_ptcp.h
+lmnsd_ptcp_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmnsd_ptcp_la_LDFLAGS = -module -avoid-version
+lmnsd_ptcp_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmnsd_ptcp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmnsd_ptcp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+endif # if ENABLE_INET
+
+#
+# openssl base and netstream driver
+#
+if ENABLE_OPENSSL
+# noinst_LTLIBRARIES += lmnsd_ossl.la
+pkglib_LTLIBRARIES += lmnsd_ossl.la
+lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h nsd_ossl.c nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h
+lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+lmnsd_ossl_la_LDFLAGS = -module -avoid-version
+lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS)
+
+endif
+
+#
+# GnuTLS netstream driver
+#
+if ENABLE_GNUTLS
+pkglib_LTLIBRARIES += lmnsd_gtls.la
+lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_gtls.h
+lmnsd_gtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GNUTLS_CFLAGS)
+lmnsd_gtls_la_LDFLAGS = -module -avoid-version
+lmnsd_gtls_la_LIBADD = $(GNUTLS_LIBS)
+endif
+
+#
+# support library for libgcrypt
+#
+if ENABLE_LIBGCRYPT
+ noinst_LTLIBRARIES += libgcry.la
+ libgcry_la_SOURCES = libgcry.c libgcry_common.c libgcry.h
+ libgcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+ pkglib_LTLIBRARIES += lmcry_gcry.la
+ lmcry_gcry_la_DEPENDENCIES = libgcry.la
+ lmcry_gcry_la_SOURCES = lmcry_gcry.c lmcry_gcry.h
+ lmcry_gcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+ lmcry_gcry_la_LDFLAGS = -module -avoid-version
+ lmcry_gcry_la_LIBADD = libgcry.la $(LIBGCRYPT_LIBS)
+endif
+
+#
+# support library for zstd
+#
+if ENABLE_LIBZSTD
+pkglib_LTLIBRARIES += lmzstdw.la
+ lmzstdw_la_SOURCES = zstdw.c zstdw.h
+ lmzstdw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ lmzstdw_la_LDFLAGS = -module -avoid-version $(ZSTD_LIBS)
+ lmzstdw_la_LIBADD = -lzstd
+endif
+
+
+#
+# gssapi support
+#
+if ENABLE_GSSAPI
+pkglib_LTLIBRARIES += lmgssutil.la
+lmgssutil_la_SOURCES = gss-misc.c gss-misc.h
+lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmgssutil_la_LDFLAGS = -module -avoid-version
+lmgssutil_la_LIBADD = $(GSS_LIBS)
+endif
+
+pkglib_LTLIBRARIES += lmtcpsrv.la lmtcpclt.la
+#
+#
+# TCP (stream) server support
+#
+lmtcpsrv_la_SOURCES = \
+ tcps_sess.c \
+ tcps_sess.h \
+ tcpsrv.c \
+ tcpsrv.h
+lmtcpsrv_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmtcpsrv_la_LDFLAGS = -module -avoid-version
+lmtcpsrv_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmtcpsrv_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmtcpsrv_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+#
+# TCP (stream) client support
+#
+lmtcpclt_la_SOURCES = \
+ tcpclt.c \
+ tcpclt.h
+lmtcpclt_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+lmtcpclt_la_LDFLAGS = -module -avoid-version
+lmtcpclt_la_LIBADD =
+
+if ENABLE_LIBLOGGING_STDLOG
+lmtcpclt_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+lmtcpclt_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+
+#
+# support library for Guardtime KSI-LS12
+#
+if ENABLE_KSI_LS12
+ pkglib_LTLIBRARIES += lmsig_ksi_ls12.la
+ lmsig_ksi_ls12_la_SOURCES = lmsig_ksi-ls12.c lmsig_ksi-ls12.h lib_ksils12.c \
+ lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h
+ lmsig_ksi_ls12_la_CPPFLAGS = $(RSRT_CFLAGS) $(GT_KSI_LS12_CFLAGS)
+ lmsig_ksi_ls12_la_LDFLAGS = -module -avoid-version $(GT_KSI_LS12_LIBS)
+endif
diff --git a/runtime/Makefile.in b/runtime/Makefile.in
new file mode 100644
index 0000000..60c71f5
--- /dev/null
+++ b/runtime/Makefile.in
@@ -0,0 +1,2110 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+sbin_PROGRAMS =
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = ${LIBLOGGING_STDLOG_CFLAGS}
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+
+#
+# regular expression support
+#
+@ENABLE_REGEXP_TRUE@am__append_3 = lmregexp.la
+@ENABLE_LIBLOGGING_STDLOG_TRUE@@ENABLE_REGEXP_TRUE@am__append_4 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@@ENABLE_REGEXP_TRUE@am__append_5 = $(LIBLOGGING_STDLOG_LIBS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_6 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_7 = $(LIBLOGGING_STDLOG_LIBS)
+
+# netstream drivers
+
+# plain tcp driver - main driver
+@ENABLE_INET_TRUE@am__append_8 = lmnetstrms.la lmnsd_ptcp.la
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_9 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_10 = $(LIBLOGGING_STDLOG_LIBS)
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_11 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_12 = $(LIBLOGGING_STDLOG_LIBS)
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_13 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_14 = $(LIBLOGGING_STDLOG_LIBS)
+
+#
+# openssl base and netstream driver
+#
+# noinst_LTLIBRARIES += lmnsd_ossl.la
+@ENABLE_OPENSSL_TRUE@am__append_15 = lmnsd_ossl.la
+
+#
+# GnuTLS netstream driver
+#
+@ENABLE_GNUTLS_TRUE@am__append_16 = lmnsd_gtls.la
+
+#
+# support library for libgcrypt
+#
+@ENABLE_LIBGCRYPT_TRUE@am__append_17 = libgcry.la
+@ENABLE_LIBGCRYPT_TRUE@am__append_18 = lmcry_gcry.la
+
+#
+# support library for zstd
+#
+@ENABLE_LIBZSTD_TRUE@am__append_19 = lmzstdw.la
+
+#
+# gssapi support
+#
+@ENABLE_GSSAPI_TRUE@am__append_20 = lmgssutil.la
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_21 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_22 = $(LIBLOGGING_STDLOG_LIBS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_23 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_24 = $(LIBLOGGING_STDLOG_LIBS)
+
+#
+# support library for Guardtime KSI-LS12
+#
+@ENABLE_KSI_LS12_TRUE@am__append_25 = lmsig_ksi_ls12.la
+subdir = runtime
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)"
+PROGRAMS = $(sbin_PROGRAMS)
+LIBRARIES = $(noinst_LIBRARIES)
+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; }; \
+ }
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
+libgcry_la_LIBADD =
+am__libgcry_la_SOURCES_DIST = libgcry.c libgcry_common.c libgcry.h
+@ENABLE_LIBGCRYPT_TRUE@am_libgcry_la_OBJECTS = libgcry_la-libgcry.lo \
+@ENABLE_LIBGCRYPT_TRUE@ libgcry_la-libgcry_common.lo
+libgcry_la_OBJECTS = $(am_libgcry_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 =
+@ENABLE_LIBGCRYPT_TRUE@am_libgcry_la_rpath =
+am__DEPENDENCIES_1 =
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__DEPENDENCIES_2 = \
+@ENABLE_LIBLOGGING_STDLOG_TRUE@ $(am__DEPENDENCIES_1)
+librsyslog_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_librsyslog_la_OBJECTS = librsyslog_la-rsyslog.lo \
+ librsyslog_la-dnscache.lo librsyslog_la-glbl.lo \
+ librsyslog_la-conf.lo librsyslog_la-janitor.lo \
+ librsyslog_la-rsconf.lo librsyslog_la-parser.lo \
+ librsyslog_la-strgen.lo librsyslog_la-msg.lo \
+ librsyslog_la-linkedlist.lo librsyslog_la-objomsr.lo \
+ librsyslog_la-stringbuf.lo librsyslog_la-datetime.lo \
+ librsyslog_la-srutils.lo librsyslog_la-errmsg.lo \
+ librsyslog_la-operatingstate.lo librsyslog_la-debug.lo \
+ librsyslog_la-obj.lo librsyslog_la-modules.lo \
+ librsyslog_la-statsobj.lo librsyslog_la-dynstats.lo \
+ librsyslog_la-perctile_ringbuf.lo \
+ librsyslog_la-perctile_stats.lo librsyslog_la-stream.lo \
+ librsyslog_la-var.lo librsyslog_la-wtp.lo librsyslog_la-wti.lo \
+ librsyslog_la-queue.lo librsyslog_la-ruleset.lo \
+ librsyslog_la-prop.lo librsyslog_la-ratelimit.lo \
+ librsyslog_la-lookup.lo librsyslog_la-cfsysline.lo \
+ ../librsyslog_la-action.lo ../librsyslog_la-threads.lo \
+ ../librsyslog_la-parse.lo librsyslog_la-hashtable.lo \
+ librsyslog_la-hashtable_itr.lo ../librsyslog_la-outchannel.lo \
+ ../librsyslog_la-template.lo librsyslog_la-timezones.lo
+librsyslog_la_OBJECTS = $(am_librsyslog_la_OBJECTS)
+am__lmcry_gcry_la_SOURCES_DIST = lmcry_gcry.c lmcry_gcry.h
+@ENABLE_LIBGCRYPT_TRUE@am_lmcry_gcry_la_OBJECTS = \
+@ENABLE_LIBGCRYPT_TRUE@ lmcry_gcry_la-lmcry_gcry.lo
+lmcry_gcry_la_OBJECTS = $(am_lmcry_gcry_la_OBJECTS)
+lmcry_gcry_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmcry_gcry_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_LIBGCRYPT_TRUE@am_lmcry_gcry_la_rpath = -rpath $(pkglibdir)
+@ENABLE_GSSAPI_TRUE@lmgssutil_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__lmgssutil_la_SOURCES_DIST = gss-misc.c gss-misc.h
+@ENABLE_GSSAPI_TRUE@am_lmgssutil_la_OBJECTS = \
+@ENABLE_GSSAPI_TRUE@ lmgssutil_la-gss-misc.lo
+lmgssutil_la_OBJECTS = $(am_lmgssutil_la_OBJECTS)
+lmgssutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmgssutil_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_GSSAPI_TRUE@am_lmgssutil_la_rpath = -rpath $(pkglibdir)
+lmnet_la_DEPENDENCIES =
+am_lmnet_la_OBJECTS = lmnet_la-net.lo
+lmnet_la_OBJECTS = $(am_lmnet_la_OBJECTS)
+lmnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmnet_la_LDFLAGS) $(LDFLAGS) -o $@
+lmnetstrms_la_DEPENDENCIES =
+am__lmnetstrms_la_SOURCES_DIST = netstrms.c netstrms.h netstrm.c \
+ netstrm.h nssel.c nssel.h nspoll.c nspoll.h
+@ENABLE_INET_TRUE@am_lmnetstrms_la_OBJECTS = \
+@ENABLE_INET_TRUE@ lmnetstrms_la-netstrms.lo \
+@ENABLE_INET_TRUE@ lmnetstrms_la-netstrm.lo \
+@ENABLE_INET_TRUE@ lmnetstrms_la-nssel.lo \
+@ENABLE_INET_TRUE@ lmnetstrms_la-nspoll.lo
+lmnetstrms_la_OBJECTS = $(am_lmnetstrms_la_OBJECTS)
+lmnetstrms_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmnetstrms_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_INET_TRUE@am_lmnetstrms_la_rpath = -rpath $(pkglibdir)
+@ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_DEPENDENCIES = \
+@ENABLE_GNUTLS_TRUE@ $(am__DEPENDENCIES_1)
+am__lmnsd_gtls_la_SOURCES_DIST = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c \
+ nsdsel_gtls.h
+@ENABLE_GNUTLS_TRUE@am_lmnsd_gtls_la_OBJECTS = \
+@ENABLE_GNUTLS_TRUE@ lmnsd_gtls_la-nsd_gtls.lo \
+@ENABLE_GNUTLS_TRUE@ lmnsd_gtls_la-nsdsel_gtls.lo
+lmnsd_gtls_la_OBJECTS = $(am_lmnsd_gtls_la_OBJECTS)
+lmnsd_gtls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmnsd_gtls_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_GNUTLS_TRUE@am_lmnsd_gtls_la_rpath = -rpath $(pkglibdir)
+@ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_DEPENDENCIES = \
+@ENABLE_OPENSSL_TRUE@ $(am__DEPENDENCIES_1)
+am__lmnsd_ossl_la_SOURCES_DIST = net_ossl.c net_ossl.h nsd_ossl.c \
+ nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h
+@ENABLE_OPENSSL_TRUE@am_lmnsd_ossl_la_OBJECTS = \
+@ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-net_ossl.lo \
+@ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-nsd_ossl.lo \
+@ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-nsdsel_ossl.lo
+lmnsd_ossl_la_OBJECTS = $(am_lmnsd_ossl_la_OBJECTS)
+lmnsd_ossl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmnsd_ossl_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_OPENSSL_TRUE@am_lmnsd_ossl_la_rpath = -rpath $(pkglibdir)
+lmnsd_ptcp_la_DEPENDENCIES =
+am__lmnsd_ptcp_la_SOURCES_DIST = nsd_ptcp.c nsd_ptcp.h nsdsel_ptcp.c \
+ nsdsel_ptcp.h nsdpoll_ptcp.c nsdpoll_ptcp.h
+@ENABLE_INET_TRUE@am_lmnsd_ptcp_la_OBJECTS = \
+@ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsd_ptcp.lo \
+@ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsdsel_ptcp.lo \
+@ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsdpoll_ptcp.lo
+lmnsd_ptcp_la_OBJECTS = $(am_lmnsd_ptcp_la_OBJECTS)
+lmnsd_ptcp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmnsd_ptcp_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_INET_TRUE@am_lmnsd_ptcp_la_rpath = -rpath $(pkglibdir)
+lmregexp_la_DEPENDENCIES =
+am__lmregexp_la_SOURCES_DIST = regexp.c regexp.h
+@ENABLE_REGEXP_TRUE@am_lmregexp_la_OBJECTS = lmregexp_la-regexp.lo
+lmregexp_la_OBJECTS = $(am_lmregexp_la_OBJECTS)
+lmregexp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmregexp_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_REGEXP_TRUE@am_lmregexp_la_rpath = -rpath $(pkglibdir)
+lmsig_ksi_ls12_la_LIBADD =
+am__lmsig_ksi_ls12_la_SOURCES_DIST = lmsig_ksi-ls12.c lmsig_ksi-ls12.h \
+ lib_ksils12.c lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h
+@ENABLE_KSI_LS12_TRUE@am_lmsig_ksi_ls12_la_OBJECTS = \
+@ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo \
+@ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lib_ksils12.lo \
+@ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lib_ksi_queue.lo
+lmsig_ksi_ls12_la_OBJECTS = $(am_lmsig_ksi_ls12_la_OBJECTS)
+lmsig_ksi_ls12_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(lmsig_ksi_ls12_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
+@ENABLE_KSI_LS12_TRUE@am_lmsig_ksi_ls12_la_rpath = -rpath $(pkglibdir)
+lmtcpclt_la_DEPENDENCIES =
+am_lmtcpclt_la_OBJECTS = lmtcpclt_la-tcpclt.lo
+lmtcpclt_la_OBJECTS = $(am_lmtcpclt_la_OBJECTS)
+lmtcpclt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmtcpclt_la_LDFLAGS) $(LDFLAGS) -o $@
+lmtcpsrv_la_DEPENDENCIES =
+am_lmtcpsrv_la_OBJECTS = lmtcpsrv_la-tcps_sess.lo \
+ lmtcpsrv_la-tcpsrv.lo
+lmtcpsrv_la_OBJECTS = $(am_lmtcpsrv_la_OBJECTS)
+lmtcpsrv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmtcpsrv_la_LDFLAGS) $(LDFLAGS) -o $@
+lmzlibw_la_DEPENDENCIES =
+am_lmzlibw_la_OBJECTS = lmzlibw_la-zlibw.lo
+lmzlibw_la_OBJECTS = $(am_lmzlibw_la_OBJECTS)
+lmzlibw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmzlibw_la_LDFLAGS) $(LDFLAGS) -o $@
+lmzstdw_la_DEPENDENCIES =
+am__lmzstdw_la_SOURCES_DIST = zstdw.c zstdw.h
+@ENABLE_LIBZSTD_TRUE@am_lmzstdw_la_OBJECTS = lmzstdw_la-zstdw.lo
+lmzstdw_la_OBJECTS = $(am_lmzstdw_la_OBJECTS)
+lmzstdw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(lmzstdw_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_LIBZSTD_TRUE@am_lmzstdw_la_rpath = -rpath $(pkglibdir)
+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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ../$(DEPDIR)/librsyslog_la-action.Plo \
+ ../$(DEPDIR)/librsyslog_la-outchannel.Plo \
+ ../$(DEPDIR)/librsyslog_la-parse.Plo \
+ ../$(DEPDIR)/librsyslog_la-template.Plo \
+ ../$(DEPDIR)/librsyslog_la-threads.Plo \
+ ./$(DEPDIR)/libgcry_la-libgcry.Plo \
+ ./$(DEPDIR)/libgcry_la-libgcry_common.Plo \
+ ./$(DEPDIR)/librsyslog_la-cfsysline.Plo \
+ ./$(DEPDIR)/librsyslog_la-conf.Plo \
+ ./$(DEPDIR)/librsyslog_la-datetime.Plo \
+ ./$(DEPDIR)/librsyslog_la-debug.Plo \
+ ./$(DEPDIR)/librsyslog_la-dnscache.Plo \
+ ./$(DEPDIR)/librsyslog_la-dynstats.Plo \
+ ./$(DEPDIR)/librsyslog_la-errmsg.Plo \
+ ./$(DEPDIR)/librsyslog_la-glbl.Plo \
+ ./$(DEPDIR)/librsyslog_la-hashtable.Plo \
+ ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo \
+ ./$(DEPDIR)/librsyslog_la-janitor.Plo \
+ ./$(DEPDIR)/librsyslog_la-linkedlist.Plo \
+ ./$(DEPDIR)/librsyslog_la-lookup.Plo \
+ ./$(DEPDIR)/librsyslog_la-modules.Plo \
+ ./$(DEPDIR)/librsyslog_la-msg.Plo \
+ ./$(DEPDIR)/librsyslog_la-obj.Plo \
+ ./$(DEPDIR)/librsyslog_la-objomsr.Plo \
+ ./$(DEPDIR)/librsyslog_la-operatingstate.Plo \
+ ./$(DEPDIR)/librsyslog_la-parser.Plo \
+ ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo \
+ ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo \
+ ./$(DEPDIR)/librsyslog_la-prop.Plo \
+ ./$(DEPDIR)/librsyslog_la-queue.Plo \
+ ./$(DEPDIR)/librsyslog_la-ratelimit.Plo \
+ ./$(DEPDIR)/librsyslog_la-rsconf.Plo \
+ ./$(DEPDIR)/librsyslog_la-rsyslog.Plo \
+ ./$(DEPDIR)/librsyslog_la-ruleset.Plo \
+ ./$(DEPDIR)/librsyslog_la-srutils.Plo \
+ ./$(DEPDIR)/librsyslog_la-statsobj.Plo \
+ ./$(DEPDIR)/librsyslog_la-stream.Plo \
+ ./$(DEPDIR)/librsyslog_la-strgen.Plo \
+ ./$(DEPDIR)/librsyslog_la-stringbuf.Plo \
+ ./$(DEPDIR)/librsyslog_la-timezones.Plo \
+ ./$(DEPDIR)/librsyslog_la-var.Plo \
+ ./$(DEPDIR)/librsyslog_la-wti.Plo \
+ ./$(DEPDIR)/librsyslog_la-wtp.Plo \
+ ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo \
+ ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo \
+ ./$(DEPDIR)/lmnet_la-net.Plo \
+ ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo \
+ ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo \
+ ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo \
+ ./$(DEPDIR)/lmnetstrms_la-nssel.Plo \
+ ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo \
+ ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo \
+ ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo \
+ ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo \
+ ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo \
+ ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo \
+ ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo \
+ ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo \
+ ./$(DEPDIR)/lmregexp_la-regexp.Plo \
+ ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo \
+ ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo \
+ ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo \
+ ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo \
+ ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo \
+ ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo \
+ ./$(DEPDIR)/lmzlibw_la-zlibw.Plo \
+ ./$(DEPDIR)/lmzstdw_la-zstdw.Plo
+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 = $(libgcry_la_SOURCES) $(librsyslog_la_SOURCES) \
+ $(lmcry_gcry_la_SOURCES) $(lmgssutil_la_SOURCES) \
+ $(lmnet_la_SOURCES) $(lmnetstrms_la_SOURCES) \
+ $(lmnsd_gtls_la_SOURCES) $(lmnsd_ossl_la_SOURCES) \
+ $(lmnsd_ptcp_la_SOURCES) $(lmregexp_la_SOURCES) \
+ $(lmsig_ksi_ls12_la_SOURCES) $(lmtcpclt_la_SOURCES) \
+ $(lmtcpsrv_la_SOURCES) $(lmzlibw_la_SOURCES) \
+ $(lmzstdw_la_SOURCES)
+DIST_SOURCES = $(am__libgcry_la_SOURCES_DIST) $(librsyslog_la_SOURCES) \
+ $(am__lmcry_gcry_la_SOURCES_DIST) \
+ $(am__lmgssutil_la_SOURCES_DIST) $(lmnet_la_SOURCES) \
+ $(am__lmnetstrms_la_SOURCES_DIST) \
+ $(am__lmnsd_gtls_la_SOURCES_DIST) \
+ $(am__lmnsd_ossl_la_SOURCES_DIST) \
+ $(am__lmnsd_ptcp_la_SOURCES_DIST) \
+ $(am__lmregexp_la_SOURCES_DIST) \
+ $(am__lmsig_ksi_ls12_la_SOURCES_DIST) $(lmtcpclt_la_SOURCES) \
+ $(lmtcpsrv_la_SOURCES) $(lmzlibw_la_SOURCES) \
+ $(am__lmzstdw_la_SOURCES_DIST)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+man_MANS =
+noinst_LIBRARIES =
+noinst_LTLIBRARIES = librsyslog.la $(am__append_17)
+
+#
+# zlib support
+#
+
+#
+# basic network support, needed for rsyslog startup (e.g. our own system name)
+#
+pkglib_LTLIBRARIES = $(am__append_3) lmzlibw.la lmnet.la \
+ $(am__append_8) $(am__append_15) $(am__append_16) \
+ $(am__append_18) $(am__append_19) $(am__append_20) lmtcpsrv.la \
+ lmtcpclt.la $(am__append_25)
+#pkglib_LTLIBRARIES = librsyslog.la
+librsyslog_la_SOURCES = \
+ rsyslog.c \
+ rsyslog.h \
+ typedefs.h \
+ dnscache.c \
+ dnscache.h \
+ unicode-helper.h \
+ atomic.h \
+ batch.h \
+ syslogd-types.h \
+ module-template.h \
+ im-helper.h \
+ obj-types.h \
+ sigprov.h \
+ cryprov.h \
+ nsd.h \
+ glbl.h \
+ glbl.c \
+ unlimited_select.h \
+ conf.c \
+ conf.h \
+ janitor.c \
+ janitor.h \
+ rsconf.c \
+ rsconf.h \
+ parser.h \
+ parser.c \
+ strgen.h \
+ strgen.c \
+ msg.c \
+ msg.h \
+ linkedlist.c \
+ linkedlist.h \
+ objomsr.c \
+ objomsr.h \
+ stringbuf.c \
+ stringbuf.h \
+ datetime.c \
+ datetime.h \
+ srutils.c \
+ srUtils.h \
+ errmsg.c \
+ errmsg.h \
+ operatingstate.c \
+ operatingstate.h \
+ debug.c \
+ debug.h \
+ obj.c \
+ obj.h \
+ modules.c \
+ modules.h \
+ statsobj.c \
+ statsobj.h \
+ dynstats.c \
+ dynstats.h \
+ perctile_ringbuf.c \
+ perctile_ringbuf.h \
+ perctile_stats.c \
+ perctile_stats.h \
+ statsobj.h \
+ stream.c \
+ stream.h \
+ var.c \
+ var.h \
+ wtp.c \
+ wtp.h \
+ wti.c \
+ wti.h \
+ queue.c \
+ queue.h \
+ ruleset.c \
+ ruleset.h \
+ prop.c \
+ prop.h \
+ ratelimit.c \
+ ratelimit.h \
+ lookup.c \
+ lookup.h \
+ cfsysline.c \
+ cfsysline.h \
+ \
+ ../action.h \
+ ../action.c \
+ ../threads.c \
+ ../threads.h \
+ \
+ ../parse.c \
+ ../parse.h \
+ \
+ hashtable.c \
+ hashtable.h \
+ hashtable_itr.c \
+ hashtable_itr.h \
+ hashtable_private.h \
+ \
+ ../outchannel.c \
+ ../outchannel.h \
+ ../template.c \
+ ../template.h \
+ timezones.c \
+ timezones.h
+
+#librsyslog_la_LDFLAGS = -module -avoid-version
+@WITH_MODDIRS_FALSE@librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS \
+@WITH_MODDIRS_FALSE@ -D_PATH_MODDIR=\"$(pkglibdir)/\" \
+@WITH_MODDIRS_FALSE@ -I\$(top_srcdir) -I\$(top_srcdir)/grammar \
+@WITH_MODDIRS_FALSE@ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+@WITH_MODDIRS_FALSE@ $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) \
+@WITH_MODDIRS_FALSE@ ${LIBESTR_CFLAGS} $(am__append_1) \
+@WITH_MODDIRS_FALSE@ -I\$(top_srcdir)/tools
+# the files with ../ we need to work on - so that they either become part of the
+# runtime or will no longer be needed. -- rgerhards, 2008-06-13
+#
+#if OS_LINUX
+#librsyslog_la_SOURCES += \
+#endif
+#librsyslog_la_LDFLAGS = -module -avoid-version
+@WITH_MODDIRS_TRUE@librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS \
+@WITH_MODDIRS_TRUE@ -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" \
+@WITH_MODDIRS_TRUE@ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+@WITH_MODDIRS_TRUE@ $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) \
+@WITH_MODDIRS_TRUE@ ${LIBESTR_CFLAGS} $(am__append_1) \
+@WITH_MODDIRS_TRUE@ -I\$(top_srcdir)/tools
+librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) \
+ $(LIBFASTJSON_LIBS) ${LIBESTR_LIBS} -lm $(am__append_2)
+@ENABLE_REGEXP_TRUE@lmregexp_la_SOURCES = regexp.c regexp.h
+@ENABLE_REGEXP_TRUE@lmregexp_la_CPPFLAGS = $(PTHREADS_CFLAGS) \
+@ENABLE_REGEXP_TRUE@ $(RSRT_CFLAGS) $(am__append_4)
+@ENABLE_REGEXP_TRUE@lmregexp_la_LDFLAGS = -module -avoid-version \
+@ENABLE_REGEXP_TRUE@ $(am__append_5)
+@ENABLE_REGEXP_TRUE@lmregexp_la_LIBADD =
+lmzlibw_la_SOURCES = zlibw.c zlibw.h
+lmzlibw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_6)
+lmzlibw_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS) \
+ $(am__append_7)
+lmzlibw_la_LIBADD =
+lmnet_la_SOURCES = net.c net.h
+lmnet_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_9)
+lmnet_la_LDFLAGS = -module -avoid-version \
+ ../compat/compat_la-getifaddrs.lo $(am__append_10)
+lmnet_la_LIBADD =
+
+# network stream master class and stream factory
+@ENABLE_INET_TRUE@lmnetstrms_la_SOURCES = netstrms.c netstrms.h \
+@ENABLE_INET_TRUE@ netstrm.c netstrm.h \
+@ENABLE_INET_TRUE@ nssel.c nssel.h \
+@ENABLE_INET_TRUE@ nspoll.c nspoll.h
+
+@ENABLE_INET_TRUE@lmnetstrms_la_CPPFLAGS = $(PTHREADS_CFLAGS) \
+@ENABLE_INET_TRUE@ $(RSRT_CFLAGS) $(am__append_11)
+@ENABLE_INET_TRUE@lmnetstrms_la_LDFLAGS = -module -avoid-version \
+@ENABLE_INET_TRUE@ $(am__append_12)
+@ENABLE_INET_TRUE@lmnetstrms_la_LIBADD =
+@ENABLE_INET_TRUE@lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h \
+@ENABLE_INET_TRUE@ nsdsel_ptcp.c nsdsel_ptcp.h \
+@ENABLE_INET_TRUE@ nsdpoll_ptcp.c nsdpoll_ptcp.h
+
+@ENABLE_INET_TRUE@lmnsd_ptcp_la_CPPFLAGS = $(PTHREADS_CFLAGS) \
+@ENABLE_INET_TRUE@ $(RSRT_CFLAGS) $(am__append_13)
+@ENABLE_INET_TRUE@lmnsd_ptcp_la_LDFLAGS = -module -avoid-version \
+@ENABLE_INET_TRUE@ $(am__append_14)
+@ENABLE_INET_TRUE@lmnsd_ptcp_la_LIBADD =
+@ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h nsd_ossl.c nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h
+@ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS)
+@ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_LDFLAGS = -module -avoid-version
+@ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS)
+@ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_gtls.h
+@ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GNUTLS_CFLAGS)
+@ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_LDFLAGS = -module -avoid-version
+@ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_LIBADD = $(GNUTLS_LIBS)
+@ENABLE_LIBGCRYPT_TRUE@libgcry_la_SOURCES = libgcry.c libgcry_common.c libgcry.h
+@ENABLE_LIBGCRYPT_TRUE@libgcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+@ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_DEPENDENCIES = libgcry.la
+@ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_SOURCES = lmcry_gcry.c lmcry_gcry.h
+@ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+@ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_LDFLAGS = -module -avoid-version
+@ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_LIBADD = libgcry.la $(LIBGCRYPT_LIBS)
+@ENABLE_LIBZSTD_TRUE@lmzstdw_la_SOURCES = zstdw.c zstdw.h
+@ENABLE_LIBZSTD_TRUE@lmzstdw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+@ENABLE_LIBZSTD_TRUE@lmzstdw_la_LDFLAGS = -module -avoid-version $(ZSTD_LIBS)
+@ENABLE_LIBZSTD_TRUE@lmzstdw_la_LIBADD = -lzstd
+@ENABLE_GSSAPI_TRUE@lmgssutil_la_SOURCES = gss-misc.c gss-misc.h
+@ENABLE_GSSAPI_TRUE@lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+@ENABLE_GSSAPI_TRUE@lmgssutil_la_LDFLAGS = -module -avoid-version
+@ENABLE_GSSAPI_TRUE@lmgssutil_la_LIBADD = $(GSS_LIBS)
+#
+#
+# TCP (stream) server support
+#
+lmtcpsrv_la_SOURCES = \
+ tcps_sess.c \
+ tcps_sess.h \
+ tcpsrv.c \
+ tcpsrv.h
+
+lmtcpsrv_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_21)
+lmtcpsrv_la_LDFLAGS = -module -avoid-version $(am__append_22)
+lmtcpsrv_la_LIBADD =
+
+#
+# TCP (stream) client support
+#
+lmtcpclt_la_SOURCES = \
+ tcpclt.c \
+ tcpclt.h
+
+lmtcpclt_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \
+ $(am__append_23)
+lmtcpclt_la_LDFLAGS = -module -avoid-version $(am__append_24)
+lmtcpclt_la_LIBADD =
+@ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_SOURCES = lmsig_ksi-ls12.c lmsig_ksi-ls12.h lib_ksils12.c \
+@ENABLE_KSI_LS12_TRUE@ lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h
+
+@ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_CPPFLAGS = $(RSRT_CFLAGS) $(GT_KSI_LS12_CFLAGS)
+@ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_LDFLAGS = -module -avoid-version $(GT_KSI_LS12_LIBS)
+all: 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) --gnu runtime/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu runtime/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+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
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+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}; \
+ }
+
+libgcry.la: $(libgcry_la_OBJECTS) $(libgcry_la_DEPENDENCIES) $(EXTRA_libgcry_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(am_libgcry_la_rpath) $(libgcry_la_OBJECTS) $(libgcry_la_LIBADD) $(LIBS)
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ../$(DEPDIR)
+ @: > ../$(DEPDIR)/$(am__dirstamp)
+../librsyslog_la-action.lo: ../$(am__dirstamp) \
+ ../$(DEPDIR)/$(am__dirstamp)
+../librsyslog_la-threads.lo: ../$(am__dirstamp) \
+ ../$(DEPDIR)/$(am__dirstamp)
+../librsyslog_la-parse.lo: ../$(am__dirstamp) \
+ ../$(DEPDIR)/$(am__dirstamp)
+../librsyslog_la-outchannel.lo: ../$(am__dirstamp) \
+ ../$(DEPDIR)/$(am__dirstamp)
+../librsyslog_la-template.lo: ../$(am__dirstamp) \
+ ../$(DEPDIR)/$(am__dirstamp)
+
+librsyslog.la: $(librsyslog_la_OBJECTS) $(librsyslog_la_DEPENDENCIES) $(EXTRA_librsyslog_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(librsyslog_la_OBJECTS) $(librsyslog_la_LIBADD) $(LIBS)
+
+lmcry_gcry.la: $(lmcry_gcry_la_OBJECTS) $(lmcry_gcry_la_DEPENDENCIES) $(EXTRA_lmcry_gcry_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmcry_gcry_la_LINK) $(am_lmcry_gcry_la_rpath) $(lmcry_gcry_la_OBJECTS) $(lmcry_gcry_la_LIBADD) $(LIBS)
+
+lmgssutil.la: $(lmgssutil_la_OBJECTS) $(lmgssutil_la_DEPENDENCIES) $(EXTRA_lmgssutil_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmgssutil_la_LINK) $(am_lmgssutil_la_rpath) $(lmgssutil_la_OBJECTS) $(lmgssutil_la_LIBADD) $(LIBS)
+
+lmnet.la: $(lmnet_la_OBJECTS) $(lmnet_la_DEPENDENCIES) $(EXTRA_lmnet_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmnet_la_LINK) -rpath $(pkglibdir) $(lmnet_la_OBJECTS) $(lmnet_la_LIBADD) $(LIBS)
+
+lmnetstrms.la: $(lmnetstrms_la_OBJECTS) $(lmnetstrms_la_DEPENDENCIES) $(EXTRA_lmnetstrms_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmnetstrms_la_LINK) $(am_lmnetstrms_la_rpath) $(lmnetstrms_la_OBJECTS) $(lmnetstrms_la_LIBADD) $(LIBS)
+
+lmnsd_gtls.la: $(lmnsd_gtls_la_OBJECTS) $(lmnsd_gtls_la_DEPENDENCIES) $(EXTRA_lmnsd_gtls_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmnsd_gtls_la_LINK) $(am_lmnsd_gtls_la_rpath) $(lmnsd_gtls_la_OBJECTS) $(lmnsd_gtls_la_LIBADD) $(LIBS)
+
+lmnsd_ossl.la: $(lmnsd_ossl_la_OBJECTS) $(lmnsd_ossl_la_DEPENDENCIES) $(EXTRA_lmnsd_ossl_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmnsd_ossl_la_LINK) $(am_lmnsd_ossl_la_rpath) $(lmnsd_ossl_la_OBJECTS) $(lmnsd_ossl_la_LIBADD) $(LIBS)
+
+lmnsd_ptcp.la: $(lmnsd_ptcp_la_OBJECTS) $(lmnsd_ptcp_la_DEPENDENCIES) $(EXTRA_lmnsd_ptcp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmnsd_ptcp_la_LINK) $(am_lmnsd_ptcp_la_rpath) $(lmnsd_ptcp_la_OBJECTS) $(lmnsd_ptcp_la_LIBADD) $(LIBS)
+
+lmregexp.la: $(lmregexp_la_OBJECTS) $(lmregexp_la_DEPENDENCIES) $(EXTRA_lmregexp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmregexp_la_LINK) $(am_lmregexp_la_rpath) $(lmregexp_la_OBJECTS) $(lmregexp_la_LIBADD) $(LIBS)
+
+lmsig_ksi_ls12.la: $(lmsig_ksi_ls12_la_OBJECTS) $(lmsig_ksi_ls12_la_DEPENDENCIES) $(EXTRA_lmsig_ksi_ls12_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmsig_ksi_ls12_la_LINK) $(am_lmsig_ksi_ls12_la_rpath) $(lmsig_ksi_ls12_la_OBJECTS) $(lmsig_ksi_ls12_la_LIBADD) $(LIBS)
+
+lmtcpclt.la: $(lmtcpclt_la_OBJECTS) $(lmtcpclt_la_DEPENDENCIES) $(EXTRA_lmtcpclt_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmtcpclt_la_LINK) -rpath $(pkglibdir) $(lmtcpclt_la_OBJECTS) $(lmtcpclt_la_LIBADD) $(LIBS)
+
+lmtcpsrv.la: $(lmtcpsrv_la_OBJECTS) $(lmtcpsrv_la_DEPENDENCIES) $(EXTRA_lmtcpsrv_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmtcpsrv_la_LINK) -rpath $(pkglibdir) $(lmtcpsrv_la_OBJECTS) $(lmtcpsrv_la_LIBADD) $(LIBS)
+
+lmzlibw.la: $(lmzlibw_la_OBJECTS) $(lmzlibw_la_DEPENDENCIES) $(EXTRA_lmzlibw_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmzlibw_la_LINK) -rpath $(pkglibdir) $(lmzlibw_la_OBJECTS) $(lmzlibw_la_LIBADD) $(LIBS)
+
+lmzstdw.la: $(lmzstdw_la_OBJECTS) $(lmzstdw_la_DEPENDENCIES) $(EXTRA_lmzstdw_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(lmzstdw_la_LINK) $(am_lmzstdw_la_rpath) $(lmzstdw_la_OBJECTS) $(lmzstdw_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f ../*.$(OBJEXT)
+ -rm -f ../*.lo
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/librsyslog_la-action.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/librsyslog_la-outchannel.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/librsyslog_la-parse.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/librsyslog_la-template.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/librsyslog_la-threads.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcry_la-libgcry.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcry_la-libgcry_common.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-cfsysline.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-conf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-datetime.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-dnscache.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-dynstats.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-errmsg.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-glbl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-janitor.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-linkedlist.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-lookup.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-modules.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-msg.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-obj.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-objomsr.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-operatingstate.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-perctile_stats.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-prop.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-ratelimit.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-rsconf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-rsyslog.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-ruleset.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-srutils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-statsobj.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-stream.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-strgen.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-stringbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-timezones.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-var.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-wti.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-wtp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmgssutil_la-gss-misc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnet_la-net.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-netstrm.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-netstrms.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-nspoll.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-nssel.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmregexp_la-regexp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmzlibw_la-zlibw.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmzstdw_la-zstdw.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+libgcry_la-libgcry.lo: libgcry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgcry_la-libgcry.lo -MD -MP -MF $(DEPDIR)/libgcry_la-libgcry.Tpo -c -o libgcry_la-libgcry.lo `test -f 'libgcry.c' || echo '$(srcdir)/'`libgcry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgcry_la-libgcry.Tpo $(DEPDIR)/libgcry_la-libgcry.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libgcry.c' object='libgcry_la-libgcry.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) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgcry_la-libgcry.lo `test -f 'libgcry.c' || echo '$(srcdir)/'`libgcry.c
+
+libgcry_la-libgcry_common.lo: libgcry_common.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgcry_la-libgcry_common.lo -MD -MP -MF $(DEPDIR)/libgcry_la-libgcry_common.Tpo -c -o libgcry_la-libgcry_common.lo `test -f 'libgcry_common.c' || echo '$(srcdir)/'`libgcry_common.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgcry_la-libgcry_common.Tpo $(DEPDIR)/libgcry_la-libgcry_common.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libgcry_common.c' object='libgcry_la-libgcry_common.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) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgcry_la-libgcry_common.lo `test -f 'libgcry_common.c' || echo '$(srcdir)/'`libgcry_common.c
+
+librsyslog_la-rsyslog.lo: rsyslog.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-rsyslog.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-rsyslog.Tpo -c -o librsyslog_la-rsyslog.lo `test -f 'rsyslog.c' || echo '$(srcdir)/'`rsyslog.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-rsyslog.Tpo $(DEPDIR)/librsyslog_la-rsyslog.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslog.c' object='librsyslog_la-rsyslog.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-rsyslog.lo `test -f 'rsyslog.c' || echo '$(srcdir)/'`rsyslog.c
+
+librsyslog_la-dnscache.lo: dnscache.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-dnscache.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-dnscache.Tpo -c -o librsyslog_la-dnscache.lo `test -f 'dnscache.c' || echo '$(srcdir)/'`dnscache.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-dnscache.Tpo $(DEPDIR)/librsyslog_la-dnscache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnscache.c' object='librsyslog_la-dnscache.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-dnscache.lo `test -f 'dnscache.c' || echo '$(srcdir)/'`dnscache.c
+
+librsyslog_la-glbl.lo: glbl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-glbl.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-glbl.Tpo -c -o librsyslog_la-glbl.lo `test -f 'glbl.c' || echo '$(srcdir)/'`glbl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-glbl.Tpo $(DEPDIR)/librsyslog_la-glbl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='glbl.c' object='librsyslog_la-glbl.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-glbl.lo `test -f 'glbl.c' || echo '$(srcdir)/'`glbl.c
+
+librsyslog_la-conf.lo: conf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-conf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-conf.Tpo -c -o librsyslog_la-conf.lo `test -f 'conf.c' || echo '$(srcdir)/'`conf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-conf.Tpo $(DEPDIR)/librsyslog_la-conf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf.c' object='librsyslog_la-conf.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-conf.lo `test -f 'conf.c' || echo '$(srcdir)/'`conf.c
+
+librsyslog_la-janitor.lo: janitor.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-janitor.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-janitor.Tpo -c -o librsyslog_la-janitor.lo `test -f 'janitor.c' || echo '$(srcdir)/'`janitor.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-janitor.Tpo $(DEPDIR)/librsyslog_la-janitor.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='janitor.c' object='librsyslog_la-janitor.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-janitor.lo `test -f 'janitor.c' || echo '$(srcdir)/'`janitor.c
+
+librsyslog_la-rsconf.lo: rsconf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-rsconf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-rsconf.Tpo -c -o librsyslog_la-rsconf.lo `test -f 'rsconf.c' || echo '$(srcdir)/'`rsconf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-rsconf.Tpo $(DEPDIR)/librsyslog_la-rsconf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsconf.c' object='librsyslog_la-rsconf.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-rsconf.lo `test -f 'rsconf.c' || echo '$(srcdir)/'`rsconf.c
+
+librsyslog_la-parser.lo: parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-parser.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-parser.Tpo -c -o librsyslog_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-parser.Tpo $(DEPDIR)/librsyslog_la-parser.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser.c' object='librsyslog_la-parser.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c
+
+librsyslog_la-strgen.lo: strgen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-strgen.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-strgen.Tpo -c -o librsyslog_la-strgen.lo `test -f 'strgen.c' || echo '$(srcdir)/'`strgen.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-strgen.Tpo $(DEPDIR)/librsyslog_la-strgen.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strgen.c' object='librsyslog_la-strgen.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-strgen.lo `test -f 'strgen.c' || echo '$(srcdir)/'`strgen.c
+
+librsyslog_la-msg.lo: msg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-msg.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-msg.Tpo -c -o librsyslog_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-msg.Tpo $(DEPDIR)/librsyslog_la-msg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msg.c' object='librsyslog_la-msg.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+
+librsyslog_la-linkedlist.lo: linkedlist.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-linkedlist.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-linkedlist.Tpo -c -o librsyslog_la-linkedlist.lo `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-linkedlist.Tpo $(DEPDIR)/librsyslog_la-linkedlist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linkedlist.c' object='librsyslog_la-linkedlist.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-linkedlist.lo `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c
+
+librsyslog_la-objomsr.lo: objomsr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-objomsr.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-objomsr.Tpo -c -o librsyslog_la-objomsr.lo `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-objomsr.Tpo $(DEPDIR)/librsyslog_la-objomsr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='objomsr.c' object='librsyslog_la-objomsr.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-objomsr.lo `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c
+
+librsyslog_la-stringbuf.lo: stringbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-stringbuf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-stringbuf.Tpo -c -o librsyslog_la-stringbuf.lo `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-stringbuf.Tpo $(DEPDIR)/librsyslog_la-stringbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stringbuf.c' object='librsyslog_la-stringbuf.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-stringbuf.lo `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c
+
+librsyslog_la-datetime.lo: datetime.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-datetime.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-datetime.Tpo -c -o librsyslog_la-datetime.lo `test -f 'datetime.c' || echo '$(srcdir)/'`datetime.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-datetime.Tpo $(DEPDIR)/librsyslog_la-datetime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='datetime.c' object='librsyslog_la-datetime.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-datetime.lo `test -f 'datetime.c' || echo '$(srcdir)/'`datetime.c
+
+librsyslog_la-srutils.lo: srutils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-srutils.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-srutils.Tpo -c -o librsyslog_la-srutils.lo `test -f 'srutils.c' || echo '$(srcdir)/'`srutils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-srutils.Tpo $(DEPDIR)/librsyslog_la-srutils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='srutils.c' object='librsyslog_la-srutils.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-srutils.lo `test -f 'srutils.c' || echo '$(srcdir)/'`srutils.c
+
+librsyslog_la-errmsg.lo: errmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-errmsg.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-errmsg.Tpo -c -o librsyslog_la-errmsg.lo `test -f 'errmsg.c' || echo '$(srcdir)/'`errmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-errmsg.Tpo $(DEPDIR)/librsyslog_la-errmsg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='errmsg.c' object='librsyslog_la-errmsg.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-errmsg.lo `test -f 'errmsg.c' || echo '$(srcdir)/'`errmsg.c
+
+librsyslog_la-operatingstate.lo: operatingstate.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-operatingstate.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-operatingstate.Tpo -c -o librsyslog_la-operatingstate.lo `test -f 'operatingstate.c' || echo '$(srcdir)/'`operatingstate.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-operatingstate.Tpo $(DEPDIR)/librsyslog_la-operatingstate.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='operatingstate.c' object='librsyslog_la-operatingstate.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-operatingstate.lo `test -f 'operatingstate.c' || echo '$(srcdir)/'`operatingstate.c
+
+librsyslog_la-debug.lo: debug.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-debug.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-debug.Tpo -c -o librsyslog_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-debug.Tpo $(DEPDIR)/librsyslog_la-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='debug.c' object='librsyslog_la-debug.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+
+librsyslog_la-obj.lo: obj.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-obj.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-obj.Tpo -c -o librsyslog_la-obj.lo `test -f 'obj.c' || echo '$(srcdir)/'`obj.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-obj.Tpo $(DEPDIR)/librsyslog_la-obj.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='obj.c' object='librsyslog_la-obj.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-obj.lo `test -f 'obj.c' || echo '$(srcdir)/'`obj.c
+
+librsyslog_la-modules.lo: modules.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-modules.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-modules.Tpo -c -o librsyslog_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-modules.Tpo $(DEPDIR)/librsyslog_la-modules.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules.c' object='librsyslog_la-modules.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c
+
+librsyslog_la-statsobj.lo: statsobj.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-statsobj.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-statsobj.Tpo -c -o librsyslog_la-statsobj.lo `test -f 'statsobj.c' || echo '$(srcdir)/'`statsobj.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-statsobj.Tpo $(DEPDIR)/librsyslog_la-statsobj.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='statsobj.c' object='librsyslog_la-statsobj.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-statsobj.lo `test -f 'statsobj.c' || echo '$(srcdir)/'`statsobj.c
+
+librsyslog_la-dynstats.lo: dynstats.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-dynstats.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-dynstats.Tpo -c -o librsyslog_la-dynstats.lo `test -f 'dynstats.c' || echo '$(srcdir)/'`dynstats.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-dynstats.Tpo $(DEPDIR)/librsyslog_la-dynstats.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynstats.c' object='librsyslog_la-dynstats.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-dynstats.lo `test -f 'dynstats.c' || echo '$(srcdir)/'`dynstats.c
+
+librsyslog_la-perctile_ringbuf.lo: perctile_ringbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-perctile_ringbuf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-perctile_ringbuf.Tpo -c -o librsyslog_la-perctile_ringbuf.lo `test -f 'perctile_ringbuf.c' || echo '$(srcdir)/'`perctile_ringbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-perctile_ringbuf.Tpo $(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='perctile_ringbuf.c' object='librsyslog_la-perctile_ringbuf.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-perctile_ringbuf.lo `test -f 'perctile_ringbuf.c' || echo '$(srcdir)/'`perctile_ringbuf.c
+
+librsyslog_la-perctile_stats.lo: perctile_stats.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-perctile_stats.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-perctile_stats.Tpo -c -o librsyslog_la-perctile_stats.lo `test -f 'perctile_stats.c' || echo '$(srcdir)/'`perctile_stats.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-perctile_stats.Tpo $(DEPDIR)/librsyslog_la-perctile_stats.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='perctile_stats.c' object='librsyslog_la-perctile_stats.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-perctile_stats.lo `test -f 'perctile_stats.c' || echo '$(srcdir)/'`perctile_stats.c
+
+librsyslog_la-stream.lo: stream.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-stream.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-stream.Tpo -c -o librsyslog_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-stream.Tpo $(DEPDIR)/librsyslog_la-stream.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stream.c' object='librsyslog_la-stream.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c
+
+librsyslog_la-var.lo: var.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-var.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-var.Tpo -c -o librsyslog_la-var.lo `test -f 'var.c' || echo '$(srcdir)/'`var.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-var.Tpo $(DEPDIR)/librsyslog_la-var.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='var.c' object='librsyslog_la-var.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-var.lo `test -f 'var.c' || echo '$(srcdir)/'`var.c
+
+librsyslog_la-wtp.lo: wtp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-wtp.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-wtp.Tpo -c -o librsyslog_la-wtp.lo `test -f 'wtp.c' || echo '$(srcdir)/'`wtp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-wtp.Tpo $(DEPDIR)/librsyslog_la-wtp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wtp.c' object='librsyslog_la-wtp.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-wtp.lo `test -f 'wtp.c' || echo '$(srcdir)/'`wtp.c
+
+librsyslog_la-wti.lo: wti.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-wti.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-wti.Tpo -c -o librsyslog_la-wti.lo `test -f 'wti.c' || echo '$(srcdir)/'`wti.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-wti.Tpo $(DEPDIR)/librsyslog_la-wti.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wti.c' object='librsyslog_la-wti.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-wti.lo `test -f 'wti.c' || echo '$(srcdir)/'`wti.c
+
+librsyslog_la-queue.lo: queue.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-queue.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-queue.Tpo -c -o librsyslog_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-queue.Tpo $(DEPDIR)/librsyslog_la-queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue.c' object='librsyslog_la-queue.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c
+
+librsyslog_la-ruleset.lo: ruleset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-ruleset.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-ruleset.Tpo -c -o librsyslog_la-ruleset.lo `test -f 'ruleset.c' || echo '$(srcdir)/'`ruleset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-ruleset.Tpo $(DEPDIR)/librsyslog_la-ruleset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ruleset.c' object='librsyslog_la-ruleset.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-ruleset.lo `test -f 'ruleset.c' || echo '$(srcdir)/'`ruleset.c
+
+librsyslog_la-prop.lo: prop.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-prop.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-prop.Tpo -c -o librsyslog_la-prop.lo `test -f 'prop.c' || echo '$(srcdir)/'`prop.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-prop.Tpo $(DEPDIR)/librsyslog_la-prop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prop.c' object='librsyslog_la-prop.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-prop.lo `test -f 'prop.c' || echo '$(srcdir)/'`prop.c
+
+librsyslog_la-ratelimit.lo: ratelimit.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-ratelimit.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-ratelimit.Tpo -c -o librsyslog_la-ratelimit.lo `test -f 'ratelimit.c' || echo '$(srcdir)/'`ratelimit.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-ratelimit.Tpo $(DEPDIR)/librsyslog_la-ratelimit.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ratelimit.c' object='librsyslog_la-ratelimit.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-ratelimit.lo `test -f 'ratelimit.c' || echo '$(srcdir)/'`ratelimit.c
+
+librsyslog_la-lookup.lo: lookup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-lookup.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-lookup.Tpo -c -o librsyslog_la-lookup.lo `test -f 'lookup.c' || echo '$(srcdir)/'`lookup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-lookup.Tpo $(DEPDIR)/librsyslog_la-lookup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lookup.c' object='librsyslog_la-lookup.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-lookup.lo `test -f 'lookup.c' || echo '$(srcdir)/'`lookup.c
+
+librsyslog_la-cfsysline.lo: cfsysline.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-cfsysline.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-cfsysline.Tpo -c -o librsyslog_la-cfsysline.lo `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-cfsysline.Tpo $(DEPDIR)/librsyslog_la-cfsysline.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cfsysline.c' object='librsyslog_la-cfsysline.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-cfsysline.lo `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c
+
+../librsyslog_la-action.lo: ../action.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../librsyslog_la-action.lo -MD -MP -MF ../$(DEPDIR)/librsyslog_la-action.Tpo -c -o ../librsyslog_la-action.lo `test -f '../action.c' || echo '$(srcdir)/'`../action.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/librsyslog_la-action.Tpo ../$(DEPDIR)/librsyslog_la-action.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../action.c' object='../librsyslog_la-action.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../librsyslog_la-action.lo `test -f '../action.c' || echo '$(srcdir)/'`../action.c
+
+../librsyslog_la-threads.lo: ../threads.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../librsyslog_la-threads.lo -MD -MP -MF ../$(DEPDIR)/librsyslog_la-threads.Tpo -c -o ../librsyslog_la-threads.lo `test -f '../threads.c' || echo '$(srcdir)/'`../threads.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/librsyslog_la-threads.Tpo ../$(DEPDIR)/librsyslog_la-threads.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../threads.c' object='../librsyslog_la-threads.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../librsyslog_la-threads.lo `test -f '../threads.c' || echo '$(srcdir)/'`../threads.c
+
+../librsyslog_la-parse.lo: ../parse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../librsyslog_la-parse.lo -MD -MP -MF ../$(DEPDIR)/librsyslog_la-parse.Tpo -c -o ../librsyslog_la-parse.lo `test -f '../parse.c' || echo '$(srcdir)/'`../parse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/librsyslog_la-parse.Tpo ../$(DEPDIR)/librsyslog_la-parse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../parse.c' object='../librsyslog_la-parse.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../librsyslog_la-parse.lo `test -f '../parse.c' || echo '$(srcdir)/'`../parse.c
+
+librsyslog_la-hashtable.lo: hashtable.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-hashtable.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-hashtable.Tpo -c -o librsyslog_la-hashtable.lo `test -f 'hashtable.c' || echo '$(srcdir)/'`hashtable.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-hashtable.Tpo $(DEPDIR)/librsyslog_la-hashtable.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hashtable.c' object='librsyslog_la-hashtable.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-hashtable.lo `test -f 'hashtable.c' || echo '$(srcdir)/'`hashtable.c
+
+librsyslog_la-hashtable_itr.lo: hashtable_itr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-hashtable_itr.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-hashtable_itr.Tpo -c -o librsyslog_la-hashtable_itr.lo `test -f 'hashtable_itr.c' || echo '$(srcdir)/'`hashtable_itr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-hashtable_itr.Tpo $(DEPDIR)/librsyslog_la-hashtable_itr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hashtable_itr.c' object='librsyslog_la-hashtable_itr.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-hashtable_itr.lo `test -f 'hashtable_itr.c' || echo '$(srcdir)/'`hashtable_itr.c
+
+../librsyslog_la-outchannel.lo: ../outchannel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../librsyslog_la-outchannel.lo -MD -MP -MF ../$(DEPDIR)/librsyslog_la-outchannel.Tpo -c -o ../librsyslog_la-outchannel.lo `test -f '../outchannel.c' || echo '$(srcdir)/'`../outchannel.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/librsyslog_la-outchannel.Tpo ../$(DEPDIR)/librsyslog_la-outchannel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../outchannel.c' object='../librsyslog_la-outchannel.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../librsyslog_la-outchannel.lo `test -f '../outchannel.c' || echo '$(srcdir)/'`../outchannel.c
+
+../librsyslog_la-template.lo: ../template.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../librsyslog_la-template.lo -MD -MP -MF ../$(DEPDIR)/librsyslog_la-template.Tpo -c -o ../librsyslog_la-template.lo `test -f '../template.c' || echo '$(srcdir)/'`../template.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/librsyslog_la-template.Tpo ../$(DEPDIR)/librsyslog_la-template.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../template.c' object='../librsyslog_la-template.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../librsyslog_la-template.lo `test -f '../template.c' || echo '$(srcdir)/'`../template.c
+
+librsyslog_la-timezones.lo: timezones.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-timezones.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-timezones.Tpo -c -o librsyslog_la-timezones.lo `test -f 'timezones.c' || echo '$(srcdir)/'`timezones.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-timezones.Tpo $(DEPDIR)/librsyslog_la-timezones.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timezones.c' object='librsyslog_la-timezones.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) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-timezones.lo `test -f 'timezones.c' || echo '$(srcdir)/'`timezones.c
+
+lmcry_gcry_la-lmcry_gcry.lo: lmcry_gcry.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmcry_gcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmcry_gcry_la-lmcry_gcry.lo -MD -MP -MF $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Tpo -c -o lmcry_gcry_la-lmcry_gcry.lo `test -f 'lmcry_gcry.c' || echo '$(srcdir)/'`lmcry_gcry.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Tpo $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lmcry_gcry.c' object='lmcry_gcry_la-lmcry_gcry.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) $(lmcry_gcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmcry_gcry_la-lmcry_gcry.lo `test -f 'lmcry_gcry.c' || echo '$(srcdir)/'`lmcry_gcry.c
+
+lmgssutil_la-gss-misc.lo: gss-misc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmgssutil_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmgssutil_la-gss-misc.lo -MD -MP -MF $(DEPDIR)/lmgssutil_la-gss-misc.Tpo -c -o lmgssutil_la-gss-misc.lo `test -f 'gss-misc.c' || echo '$(srcdir)/'`gss-misc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmgssutil_la-gss-misc.Tpo $(DEPDIR)/lmgssutil_la-gss-misc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gss-misc.c' object='lmgssutil_la-gss-misc.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) $(lmgssutil_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmgssutil_la-gss-misc.lo `test -f 'gss-misc.c' || echo '$(srcdir)/'`gss-misc.c
+
+lmnet_la-net.lo: net.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnet_la-net.lo -MD -MP -MF $(DEPDIR)/lmnet_la-net.Tpo -c -o lmnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnet_la-net.Tpo $(DEPDIR)/lmnet_la-net.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net.c' object='lmnet_la-net.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) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c
+
+lmnetstrms_la-netstrms.lo: netstrms.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-netstrms.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-netstrms.Tpo -c -o lmnetstrms_la-netstrms.lo `test -f 'netstrms.c' || echo '$(srcdir)/'`netstrms.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-netstrms.Tpo $(DEPDIR)/lmnetstrms_la-netstrms.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netstrms.c' object='lmnetstrms_la-netstrms.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) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-netstrms.lo `test -f 'netstrms.c' || echo '$(srcdir)/'`netstrms.c
+
+lmnetstrms_la-netstrm.lo: netstrm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-netstrm.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-netstrm.Tpo -c -o lmnetstrms_la-netstrm.lo `test -f 'netstrm.c' || echo '$(srcdir)/'`netstrm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-netstrm.Tpo $(DEPDIR)/lmnetstrms_la-netstrm.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netstrm.c' object='lmnetstrms_la-netstrm.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) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-netstrm.lo `test -f 'netstrm.c' || echo '$(srcdir)/'`netstrm.c
+
+lmnetstrms_la-nssel.lo: nssel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-nssel.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-nssel.Tpo -c -o lmnetstrms_la-nssel.lo `test -f 'nssel.c' || echo '$(srcdir)/'`nssel.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-nssel.Tpo $(DEPDIR)/lmnetstrms_la-nssel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nssel.c' object='lmnetstrms_la-nssel.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) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-nssel.lo `test -f 'nssel.c' || echo '$(srcdir)/'`nssel.c
+
+lmnetstrms_la-nspoll.lo: nspoll.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-nspoll.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-nspoll.Tpo -c -o lmnetstrms_la-nspoll.lo `test -f 'nspoll.c' || echo '$(srcdir)/'`nspoll.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-nspoll.Tpo $(DEPDIR)/lmnetstrms_la-nspoll.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nspoll.c' object='lmnetstrms_la-nspoll.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) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-nspoll.lo `test -f 'nspoll.c' || echo '$(srcdir)/'`nspoll.c
+
+lmnsd_gtls_la-nsd_gtls.lo: nsd_gtls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_gtls_la-nsd_gtls.lo -MD -MP -MF $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Tpo -c -o lmnsd_gtls_la-nsd_gtls.lo `test -f 'nsd_gtls.c' || echo '$(srcdir)/'`nsd_gtls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Tpo $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_gtls.c' object='lmnsd_gtls_la-nsd_gtls.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) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_gtls_la-nsd_gtls.lo `test -f 'nsd_gtls.c' || echo '$(srcdir)/'`nsd_gtls.c
+
+lmnsd_gtls_la-nsdsel_gtls.lo: nsdsel_gtls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_gtls_la-nsdsel_gtls.lo -MD -MP -MF $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Tpo -c -o lmnsd_gtls_la-nsdsel_gtls.lo `test -f 'nsdsel_gtls.c' || echo '$(srcdir)/'`nsdsel_gtls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Tpo $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_gtls.c' object='lmnsd_gtls_la-nsdsel_gtls.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) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_gtls_la-nsdsel_gtls.lo `test -f 'nsdsel_gtls.c' || echo '$(srcdir)/'`nsdsel_gtls.c
+
+lmnsd_ossl_la-net_ossl.lo: net_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-net_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-net_ossl.Tpo -c -o lmnsd_ossl_la-net_ossl.lo `test -f 'net_ossl.c' || echo '$(srcdir)/'`net_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-net_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net_ossl.c' object='lmnsd_ossl_la-net_ossl.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) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-net_ossl.lo `test -f 'net_ossl.c' || echo '$(srcdir)/'`net_ossl.c
+
+lmnsd_ossl_la-nsd_ossl.lo: nsd_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-nsd_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Tpo -c -o lmnsd_ossl_la-nsd_ossl.lo `test -f 'nsd_ossl.c' || echo '$(srcdir)/'`nsd_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_ossl.c' object='lmnsd_ossl_la-nsd_ossl.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) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-nsd_ossl.lo `test -f 'nsd_ossl.c' || echo '$(srcdir)/'`nsd_ossl.c
+
+lmnsd_ossl_la-nsdsel_ossl.lo: nsdsel_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-nsdsel_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Tpo -c -o lmnsd_ossl_la-nsdsel_ossl.lo `test -f 'nsdsel_ossl.c' || echo '$(srcdir)/'`nsdsel_ossl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_ossl.c' object='lmnsd_ossl_la-nsdsel_ossl.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) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-nsdsel_ossl.lo `test -f 'nsdsel_ossl.c' || echo '$(srcdir)/'`nsdsel_ossl.c
+
+lmnsd_ptcp_la-nsd_ptcp.lo: nsd_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ptcp_la-nsd_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Tpo -c -o lmnsd_ptcp_la-nsd_ptcp.lo `test -f 'nsd_ptcp.c' || echo '$(srcdir)/'`nsd_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_ptcp.c' object='lmnsd_ptcp_la-nsd_ptcp.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) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ptcp_la-nsd_ptcp.lo `test -f 'nsd_ptcp.c' || echo '$(srcdir)/'`nsd_ptcp.c
+
+lmnsd_ptcp_la-nsdsel_ptcp.lo: nsdsel_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ptcp_la-nsdsel_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Tpo -c -o lmnsd_ptcp_la-nsdsel_ptcp.lo `test -f 'nsdsel_ptcp.c' || echo '$(srcdir)/'`nsdsel_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_ptcp.c' object='lmnsd_ptcp_la-nsdsel_ptcp.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) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ptcp_la-nsdsel_ptcp.lo `test -f 'nsdsel_ptcp.c' || echo '$(srcdir)/'`nsdsel_ptcp.c
+
+lmnsd_ptcp_la-nsdpoll_ptcp.lo: nsdpoll_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ptcp_la-nsdpoll_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Tpo -c -o lmnsd_ptcp_la-nsdpoll_ptcp.lo `test -f 'nsdpoll_ptcp.c' || echo '$(srcdir)/'`nsdpoll_ptcp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdpoll_ptcp.c' object='lmnsd_ptcp_la-nsdpoll_ptcp.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) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ptcp_la-nsdpoll_ptcp.lo `test -f 'nsdpoll_ptcp.c' || echo '$(srcdir)/'`nsdpoll_ptcp.c
+
+lmregexp_la-regexp.lo: regexp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmregexp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmregexp_la-regexp.lo -MD -MP -MF $(DEPDIR)/lmregexp_la-regexp.Tpo -c -o lmregexp_la-regexp.lo `test -f 'regexp.c' || echo '$(srcdir)/'`regexp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmregexp_la-regexp.Tpo $(DEPDIR)/lmregexp_la-regexp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regexp.c' object='lmregexp_la-regexp.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) $(lmregexp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmregexp_la-regexp.lo `test -f 'regexp.c' || echo '$(srcdir)/'`regexp.c
+
+lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo: lmsig_ksi-ls12.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Tpo -c -o lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo `test -f 'lmsig_ksi-ls12.c' || echo '$(srcdir)/'`lmsig_ksi-ls12.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lmsig_ksi-ls12.c' object='lmsig_ksi_ls12_la-lmsig_ksi-ls12.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) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo `test -f 'lmsig_ksi-ls12.c' || echo '$(srcdir)/'`lmsig_ksi-ls12.c
+
+lmsig_ksi_ls12_la-lib_ksils12.lo: lib_ksils12.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lib_ksils12.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Tpo -c -o lmsig_ksi_ls12_la-lib_ksils12.lo `test -f 'lib_ksils12.c' || echo '$(srcdir)/'`lib_ksils12.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib_ksils12.c' object='lmsig_ksi_ls12_la-lib_ksils12.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) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lib_ksils12.lo `test -f 'lib_ksils12.c' || echo '$(srcdir)/'`lib_ksils12.c
+
+lmsig_ksi_ls12_la-lib_ksi_queue.lo: lib_ksi_queue.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lib_ksi_queue.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Tpo -c -o lmsig_ksi_ls12_la-lib_ksi_queue.lo `test -f 'lib_ksi_queue.c' || echo '$(srcdir)/'`lib_ksi_queue.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib_ksi_queue.c' object='lmsig_ksi_ls12_la-lib_ksi_queue.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) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lib_ksi_queue.lo `test -f 'lib_ksi_queue.c' || echo '$(srcdir)/'`lib_ksi_queue.c
+
+lmtcpclt_la-tcpclt.lo: tcpclt.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpclt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpclt_la-tcpclt.lo -MD -MP -MF $(DEPDIR)/lmtcpclt_la-tcpclt.Tpo -c -o lmtcpclt_la-tcpclt.lo `test -f 'tcpclt.c' || echo '$(srcdir)/'`tcpclt.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpclt_la-tcpclt.Tpo $(DEPDIR)/lmtcpclt_la-tcpclt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpclt.c' object='lmtcpclt_la-tcpclt.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) $(lmtcpclt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpclt_la-tcpclt.lo `test -f 'tcpclt.c' || echo '$(srcdir)/'`tcpclt.c
+
+lmtcpsrv_la-tcps_sess.lo: tcps_sess.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpsrv_la-tcps_sess.lo -MD -MP -MF $(DEPDIR)/lmtcpsrv_la-tcps_sess.Tpo -c -o lmtcpsrv_la-tcps_sess.lo `test -f 'tcps_sess.c' || echo '$(srcdir)/'`tcps_sess.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpsrv_la-tcps_sess.Tpo $(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcps_sess.c' object='lmtcpsrv_la-tcps_sess.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) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpsrv_la-tcps_sess.lo `test -f 'tcps_sess.c' || echo '$(srcdir)/'`tcps_sess.c
+
+lmtcpsrv_la-tcpsrv.lo: tcpsrv.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpsrv_la-tcpsrv.lo -MD -MP -MF $(DEPDIR)/lmtcpsrv_la-tcpsrv.Tpo -c -o lmtcpsrv_la-tcpsrv.lo `test -f 'tcpsrv.c' || echo '$(srcdir)/'`tcpsrv.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpsrv_la-tcpsrv.Tpo $(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpsrv.c' object='lmtcpsrv_la-tcpsrv.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) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpsrv_la-tcpsrv.lo `test -f 'tcpsrv.c' || echo '$(srcdir)/'`tcpsrv.c
+
+lmzlibw_la-zlibw.lo: zlibw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzlibw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmzlibw_la-zlibw.lo -MD -MP -MF $(DEPDIR)/lmzlibw_la-zlibw.Tpo -c -o lmzlibw_la-zlibw.lo `test -f 'zlibw.c' || echo '$(srcdir)/'`zlibw.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmzlibw_la-zlibw.Tpo $(DEPDIR)/lmzlibw_la-zlibw.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zlibw.c' object='lmzlibw_la-zlibw.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) $(lmzlibw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmzlibw_la-zlibw.lo `test -f 'zlibw.c' || echo '$(srcdir)/'`zlibw.c
+
+lmzstdw_la-zstdw.lo: zstdw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzstdw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmzstdw_la-zstdw.lo -MD -MP -MF $(DEPDIR)/lmzstdw_la-zstdw.Tpo -c -o lmzstdw_la-zstdw.lo `test -f 'zstdw.c' || echo '$(srcdir)/'`zstdw.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmzstdw_la-zstdw.Tpo $(DEPDIR)/lmzstdw_la-zstdw.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zstdw.c' object='lmzstdw_la-zstdw.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) $(lmzstdw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmzstdw_la-zstdw.lo `test -f 'zstdw.c' || echo '$(srcdir)/'`zstdw.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(PROGRAMS) $(LIBRARIES) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)"; 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:
+
+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)
+ -rm -f ../$(DEPDIR)/$(am__dirstamp)
+ -rm -f ../$(am__dirstamp)
+
+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-noinstLIBRARIES \
+ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ../$(DEPDIR)/librsyslog_la-action.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-outchannel.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-parse.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-template.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-threads.Plo
+ -rm -f ./$(DEPDIR)/libgcry_la-libgcry.Plo
+ -rm -f ./$(DEPDIR)/libgcry_la-libgcry_common.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-cfsysline.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-conf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-datetime.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-debug.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-dnscache.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-dynstats.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-errmsg.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-glbl.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-hashtable.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-janitor.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-linkedlist.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-lookup.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-modules.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-msg.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-obj.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-objomsr.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-operatingstate.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-parser.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-prop.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-queue.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-ratelimit.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-srutils.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-statsobj.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-stream.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-strgen.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-stringbuf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-timezones.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-var.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-wti.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-wtp.Plo
+ -rm -f ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo
+ -rm -f ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo
+ -rm -f ./$(DEPDIR)/lmnet_la-net.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-nssel.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmregexp_la-regexp.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo
+ -rm -f ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo
+ -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo
+ -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo
+ -rm -f ./$(DEPDIR)/lmzlibw_la-zlibw.Plo
+ -rm -f ./$(DEPDIR)/lmzstdw_la-zstdw.Plo
+ -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-pkglibLTLIBRARIES 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 -f ../$(DEPDIR)/librsyslog_la-action.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-outchannel.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-parse.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-template.Plo
+ -rm -f ../$(DEPDIR)/librsyslog_la-threads.Plo
+ -rm -f ./$(DEPDIR)/libgcry_la-libgcry.Plo
+ -rm -f ./$(DEPDIR)/libgcry_la-libgcry_common.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-cfsysline.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-conf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-datetime.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-debug.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-dnscache.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-dynstats.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-errmsg.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-glbl.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-hashtable.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-janitor.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-linkedlist.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-lookup.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-modules.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-msg.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-obj.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-objomsr.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-operatingstate.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-parser.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-prop.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-queue.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-ratelimit.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-srutils.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-statsobj.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-stream.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-strgen.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-stringbuf.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-timezones.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-var.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-wti.Plo
+ -rm -f ./$(DEPDIR)/librsyslog_la-wtp.Plo
+ -rm -f ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo
+ -rm -f ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo
+ -rm -f ./$(DEPDIR)/lmnet_la-net.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo
+ -rm -f ./$(DEPDIR)/lmnetstrms_la-nssel.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo
+ -rm -f ./$(DEPDIR)/lmregexp_la-regexp.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo
+ -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo
+ -rm -f ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo
+ -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo
+ -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo
+ -rm -f ./$(DEPDIR)/lmzlibw_la-zlibw.Plo
+ -rm -f ./$(DEPDIR)/lmzstdw_la-zstdw.Plo
+ -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-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLIBRARIES \
+ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \
+ 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-pkglibLTLIBRARIES \
+ 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 \
+ tags tags-am uninstall uninstall-am \
+ uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+# 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/runtime/atomic.h b/runtime/atomic.h
new file mode 100644
index 0000000..06af1dc
--- /dev/null
+++ b/runtime/atomic.h
@@ -0,0 +1,265 @@
+/* This header supplies atomic operations. So far, we rely on GCC's
+ * atomic builtins. During configure, we check if atomic operatons are
+ * available. If they are not, I am making the necessary provisioning to live without them if
+ * they are not available. Please note that you should only use the macros
+ * here if you think you can actually live WITHOUT an explicit atomic operation,
+ * because in the non-presence of them, we simply do it without atomicitiy.
+ * Which, for word-aligned data types, usually (but only usually!) should work.
+ *
+ * We are using the functions described in
+ * http:/gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html
+ *
+ * THESE MACROS MUST ONLY BE USED WITH WORD-SIZED DATA TYPES!
+ *
+ * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_ATOMIC_H
+#define INCLUDED_ATOMIC_H
+#include <time.h>
+#include "typedefs.h"
+
+/* for this release, we disable atomic calls because there seem to be some
+ * portability problems and we can not fix that without destabilizing the build.
+ * They simply came in too late. -- rgerhards, 2008-04-02
+ */
+#ifdef HAVE_ATOMIC_BUILTINS
+# define ATOMIC_SUB(data, val, phlpmut) __sync_fetch_and_sub(data, val)
+# define ATOMIC_SUB_unsigned(data, val, phlpmut) __sync_fetch_and_sub(data, val)
+# define ATOMIC_ADD(data, val) __sync_fetch_and_add(&(data), val)
+# define ATOMIC_INC(data, phlpmut) ((void) __sync_fetch_and_add(data, 1))
+# define ATOMIC_INC_AND_FETCH_int(data, phlpmut) __sync_fetch_and_add(data, 1)
+# define ATOMIC_INC_AND_FETCH_unsigned(data, phlpmut) __sync_fetch_and_add(data, 1)
+# define ATOMIC_DEC(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1))
+# define ATOMIC_DEC_AND_FETCH(data, phlpmut) __sync_sub_and_fetch(data, 1)
+# define ATOMIC_FETCH_32BIT(data, phlpmut) ((int) __sync_fetch_and_and(data, 0xffffffff))
+# define ATOMIC_FETCH_32BIT_unsigned(data, phlpmut) ((int) __sync_fetch_and_and(data, 0xffffffff))
+# define ATOMIC_STORE_1_TO_32BIT(data) __sync_lock_test_and_set(&(data), 1)
+# define ATOMIC_STORE_0_TO_INT(data, phlpmut) __sync_fetch_and_and(data, 0)
+# define ATOMIC_STORE_1_TO_INT(data, phlpmut) __sync_fetch_and_or(data, 1)
+# define ATOMIC_OR_INT_TO_INT(data, phlpmut, val) __sync_fetch_and_or((data), (val))
+# define ATOMIC_CAS(data, oldVal, newVal, phlpmut) __sync_bool_compare_and_swap(data, (oldVal), (newVal))
+# define ATOMIC_CAS_time_t(data, oldVal, newVal, phlpmut) __sync_bool_compare_and_swap(data, (oldVal), (newVal))
+# define ATOMIC_CAS_VAL(data, oldVal, newVal, phlpmut) __sync_val_compare_and_swap(data, (oldVal), (newVal));
+
+ /* functions below are not needed if we have atomics */
+# define DEF_ATOMIC_HELPER_MUT(x)
+# define INIT_ATOMIC_HELPER_MUT(x)
+# define DESTROY_ATOMIC_HELPER_MUT(x)
+
+ /* the following operations should preferrably be done atomic, but it is
+ * not fatal if not -- that means we can live with some missed updates. So be
+ * sure to use these macros only if that really does not matter!
+ */
+# define PREFER_ATOMIC_INC(data) ((void) __sync_fetch_and_add(&(data), 1))
+# define PREFER_FETCH_32BIT(data) ((unsigned) __sync_fetch_and_and(&(data), 0xffffffff))
+# define PREFER_STORE_0_TO_INT(data) __sync_fetch_and_and(data, 0)
+# define PREFER_STORE_1_TO_INT(data) __sync_fetch_and_or(data, 1)
+#else
+ /* note that we gained parctical proof that theoretical problems DO occur
+ * if we do not properly address them. See this blog post for details:
+ * http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html
+ * The bottom line is that if there are no atomics available, we should NOT
+ * simply go ahead and do without them - use mutexes or other things. The
+ * code needs to be checked against all those cases. -- rgerhards, 2009-01-30
+ */
+ #include <pthread.h>
+# define ATOMIC_INC(data, phlpmut) { \
+ pthread_mutex_lock(phlpmut); \
+ ++(*(data)); \
+ pthread_mutex_unlock(phlpmut); \
+ }
+
+# define ATOMIC_STORE_0_TO_INT(data, hlpmut) { \
+ pthread_mutex_lock(hlpmut); \
+ *(data) = 0; \
+ pthread_mutex_unlock(hlpmut); \
+ }
+
+# define ATOMIC_STORE_1_TO_INT(data, hlpmut) { \
+ pthread_mutex_lock(hlpmut); \
+ *(data) = 1; \
+ pthread_mutex_unlock(hlpmut); \
+ }
+
+# define ATOMIC_OR_INT_TO_INT(data, hlpmut, val) { \
+ pthread_mutex_lock(hlpmut); \
+ *(data) = val; \
+ pthread_mutex_unlock(hlpmut); \
+ }
+
+ static inline int
+ ATOMIC_CAS(int *data, int oldVal, int newVal, pthread_mutex_t *phlpmut) {
+ int bSuccess;
+ pthread_mutex_lock(phlpmut);
+ if(*data == oldVal) {
+ *data = newVal;
+ bSuccess = 1;
+ } else {
+ bSuccess = 0;
+ }
+ pthread_mutex_unlock(phlpmut);
+ return(bSuccess);
+ }
+
+ static inline int
+ ATOMIC_CAS_time_t(time_t *data, time_t oldVal, time_t newVal, pthread_mutex_t *phlpmut) {
+ int bSuccess;
+ pthread_mutex_lock(phlpmut);
+ if(*data == oldVal) {
+ *data = newVal;
+ bSuccess = 1;
+ } else {
+ bSuccess = 0;
+ }
+ pthread_mutex_unlock(phlpmut);
+ return(bSuccess);
+ }
+
+
+ static inline int
+ ATOMIC_CAS_VAL(int *data, int oldVal, int newVal, pthread_mutex_t *phlpmut) {
+ int val;
+ pthread_mutex_lock(phlpmut);
+ if(*data == oldVal) {
+ *data = newVal;
+ }
+ val = *data;
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+# define ATOMIC_DEC(data, phlpmut) { \
+ pthread_mutex_lock(phlpmut); \
+ --(*(data)); \
+ pthread_mutex_unlock(phlpmut); \
+ }
+
+ static inline int
+ ATOMIC_INC_AND_FETCH_int(int *data, pthread_mutex_t *phlpmut) {
+ int val;
+ pthread_mutex_lock(phlpmut);
+ val = ++(*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+ static inline unsigned
+ ATOMIC_INC_AND_FETCH_unsigned(unsigned *data, pthread_mutex_t *phlpmut) {
+ unsigned val;
+ pthread_mutex_lock(phlpmut);
+ val = ++(*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+ static inline int
+ ATOMIC_DEC_AND_FETCH(int *data, pthread_mutex_t *phlpmut) {
+ int val;
+ pthread_mutex_lock(phlpmut);
+ val = --(*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+ static inline int
+ ATOMIC_FETCH_32BIT(int *data, pthread_mutex_t *phlpmut) {
+ int val;
+ pthread_mutex_lock(phlpmut);
+ val = (*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+ static inline int
+ ATOMIC_FETCH_32BIT_unsigned(unsigned *data, pthread_mutex_t *phlpmut) {
+ int val;
+ pthread_mutex_lock(phlpmut);
+ val = (*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+ static inline void
+ ATOMIC_SUB(int *data, int val, pthread_mutex_t *phlpmut) {
+ pthread_mutex_lock(phlpmut);
+ (*data) -= val;
+ pthread_mutex_unlock(phlpmut);
+ }
+
+ static inline void
+ ATOMIC_SUB_unsigned(unsigned *data, int val, pthread_mutex_t *phlpmut) {
+ pthread_mutex_lock(phlpmut);
+ (*data) -= val;
+ pthread_mutex_unlock(phlpmut);
+ }
+# define DEF_ATOMIC_HELPER_MUT(x) pthread_mutex_t x;
+# define INIT_ATOMIC_HELPER_MUT(x) pthread_mutex_init(&(x), NULL);
+# define DESTROY_ATOMIC_HELPER_MUT(x) pthread_mutex_destroy(&(x));
+
+# define PREFER_ATOMIC_INC(data) ((void) ++data)
+# define PREFER_FETCH_32BIT(data) ((unsigned) (data))
+# define PREFER_STORE_0_TO_INT(data) (*(data) = 0)
+# define PREFER_STORE_1_TO_INT(data) (*(data) = 1)
+
+#endif
+
+/* we need to handle 64bit atomics seperately as some platforms have
+ * 32 bit atomics, but not 64 bit ones... -- rgerhards, 2010-12-01
+ */
+#ifdef HAVE_ATOMIC_BUILTINS64
+# define ATOMIC_INC_uint64(data, phlpmut) ((void) __sync_fetch_and_add(data, 1))
+# define ATOMIC_ADD_uint64(data, phlpmut, value) ((void) __sync_fetch_and_add(data, value))
+# define ATOMIC_DEC_uint64(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1))
+# define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __sync_fetch_and_add(data, 1)
+
+# define DEF_ATOMIC_HELPER_MUT64(x)
+# define INIT_ATOMIC_HELPER_MUT64(x)
+# define DESTROY_ATOMIC_HELPER_MUT64(x)
+#else
+# define ATOMIC_INC_uint64(data, phlpmut) { \
+ pthread_mutex_lock(phlpmut); \
+ ++(*(data)); \
+ pthread_mutex_unlock(phlpmut); \
+ }
+# define ATOMIC_ADD_uint64(data, phlpmut, value) { \
+ pthread_mutex_lock(phlpmut); \
+ *data += value; \
+ pthread_mutex_unlock(phlpmut); \
+ }
+# define ATOMIC_DEC_uint64(data, phlpmut) { \
+ pthread_mutex_lock(phlpmut); \
+ --(*(data)); \
+ pthread_mutex_unlock(phlpmut); \
+ }
+
+ static inline unsigned
+ ATOMIC_INC_AND_FETCH_uint64(uint64 *data, pthread_mutex_t *phlpmut) {
+ uint64 val;
+ pthread_mutex_lock(phlpmut);
+ val = ++(*data);
+ pthread_mutex_unlock(phlpmut);
+ return(val);
+ }
+
+# define DEF_ATOMIC_HELPER_MUT64(x) pthread_mutex_t x;
+# define INIT_ATOMIC_HELPER_MUT64(x) pthread_mutex_init(&(x), NULL)
+# define DESTROY_ATOMIC_HELPER_MUT64(x) pthread_mutex_destroy(&(x))
+#endif /* #ifdef HAVE_ATOMIC_BUILTINS64 */
+
+#endif /* #ifndef INCLUDED_ATOMIC_H */
diff --git a/runtime/batch.h b/runtime/batch.h
new file mode 100644
index 0000000..c1bef80
--- /dev/null
+++ b/runtime/batch.h
@@ -0,0 +1,129 @@
+/* Definition of the batch_t data structure.
+ * I am not sure yet if this will become a full-blown object. For now, this header just
+ * includes the object definition and is not accompanied by code.
+ *
+ * Copyright 2009-2013 by Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef BATCH_H_INCLUDED
+#define BATCH_H_INCLUDED
+
+#include <string.h>
+#include <stdlib.h>
+#include "msg.h"
+
+/* enum for batch states. Actually, we violate a layer here, in that we assume that a batch is used
+ * for action processing. So far, this seems acceptable, the status is simply ignored inside the
+ * main message queue. But over time, it could potentially be useful to split the two.
+ * rgerhad, 2009-05-12
+ */
+#define BATCH_STATE_RDY 0 /* object ready for processing */
+#define BATCH_STATE_BAD 1 /* unrecoverable failure while processing, do NOT resubmit to same action */
+#define BATCH_STATE_SUB 2 /* message submitted for processing, outcome yet unknown */
+#define BATCH_STATE_COMM 3 /* message successfully commited */
+#define BATCH_STATE_DISC 4 /* discarded - processed OK, but do not submit to any other action */
+typedef unsigned char batch_state_t;
+
+
+/* an object inside a batch, including any information (state!) needed for it to "life".
+ */
+struct batch_obj_s {
+ smsg_t *pMsg;
+};
+
+/* the batch
+ * This object is used to dequeue multiple user pointers which are than handed over
+ * to processing. The size of elements is fixed after queue creation, but may be
+ * modified by config variables (better said: queue properties).
+ * Note that a "user pointer" in rsyslog context so far always is a message
+ * object. We stick to the more generic term because queues may potentially hold
+ * other types of objects, too.
+ * rgerhards, 2009-05-12
+ * Note that nElem is not necessarily equal to nElemDeq. This is the case when we
+ * discard some elements (because of configuration) during dequeue processing. As
+ * all Elements are only deleted when the batch is processed, we can not immediately
+ * delete them. So we need to keep their number that we can delete them when the batch
+ * is completed (else, the whole process does not work correctly).
+ */
+struct batch_s {
+ int maxElem; /* maximum number of elements that this batch supports */
+ int nElem; /* actual number of element in this entry */
+ int nElemDeq; /* actual number of elements dequeued (and thus to be deleted) - see comment above! */
+ qDeqID deqID; /* ID of dequeue operation that generated this batch */
+ batch_obj_t *pElem; /* batch elements */
+ batch_state_t *eltState;/* state (array!) for individual objects.
+ NOTE: we have moved this out of batch_obj_t because we
+ get a *much* better cache hit ratio this way. So do not
+ move it back into this structure! Note that this is really
+ a HUGE saving, even if it doesn't look so (both profiler
+ data as well as practical tests indicate that!).
+ */
+};
+
+
+/* get number of msgs for this batch */
+#define batchNumMsgs(pBatch) ((pBatch)->nElem)
+
+
+/* set the status of the i-th batch element. Note that once the status is
+ * DISC, it will never be reset. So this function can NOT be used to initialize
+ * the state table. -- rgerhards, 2010-06-10
+ */
+static inline void __attribute__((unused))
+batchSetElemState(batch_t * const pBatch, const int i, const batch_state_t newState) {
+ if(pBatch->eltState[i] != BATCH_STATE_DISC)
+ pBatch->eltState[i] = newState;
+}
+
+
+/* check if an element is a valid entry. We do NOT verify if the
+ * element index is valid. -- rgerhards, 2010-06-10
+ */
+#define batchIsValidElem(pBatch, i) ((pBatch)->eltState[(i)] != BATCH_STATE_DISC)
+
+
+/* free members of a batch "object". Note that we can not do the usual
+ * destruction as the object typically is allocated on the stack and so the
+ * object itself cannot be freed! -- rgerhards, 2010-06-15
+ */
+static inline void __attribute__((unused))
+batchFree(batch_t * const pBatch) {
+ free(pBatch->pElem);
+ free(pBatch->eltState);
+}
+
+
+/* initialiaze a batch "object". The record must already exist,
+ * we "just" initialize it. The max number of elements must be
+ * provided. -- rgerhards, 2010-06-15
+ */
+static inline rsRetVal __attribute__((unused))
+batchInit(batch_t *const pBatch, const int maxElem)
+{
+ DEFiRet;
+ pBatch->maxElem = maxElem;
+ CHKmalloc(pBatch->pElem = calloc((size_t)maxElem, sizeof(batch_obj_t)));
+ CHKmalloc(pBatch->eltState = calloc((size_t)maxElem, sizeof(batch_state_t)));
+finalize_it:
+ RETiRet;
+}
+
+#endif /* #ifndef BATCH_H_INCLUDED */
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c
new file mode 100644
index 0000000..34b1cd7
--- /dev/null
+++ b/runtime/cfsysline.c
@@ -0,0 +1,1081 @@
+/* cfsysline.c
+ * Implementation of the configuration system line object.
+ *
+ * File begun on 2007-07-30 by RGerhards
+ *
+ * Copyright (C) 2007-2020 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "rsyslog.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "conf.h"
+#include "errmsg.h"
+#include "srUtils.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+#include "parserif.h"
+
+
+/* static data */
+DEFobjCurrIf(obj)
+
+linkedList_t llCmdList; /* this is NOT a pointer - no typo here ;) */
+
+/* --------------- START functions for handling canned syntaxes --------------- */
+
+
+/* parse a character from the config line
+ * added 2007-07-17 by rgerhards
+ * TODO: enhance this function to handle different classes of characters
+ * HINT: check if char is ' and, if so, use 'c' where c may also be things
+ * like \t etc.
+ */
+static rsRetVal doGetChar(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ /* if we are not at a '\0', we have our new char - no validity checks here... */
+ if(**pp == '\0') {
+ LogError(0, RS_RET_NOT_FOUND, "No character available");
+ iRet = RS_RET_NOT_FOUND;
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((uchar*)pVal) = **pp;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, **pp));
+ }
+ ++(*pp); /* eat processed char */
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse a number from the configuration line. This is more or less
+ * a shell to call the custom handler.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal doCustomHdlr(uchar **pp, rsRetVal (*pSetHdlr)(uchar**, void*), void *pVal)
+{
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(pSetHdlr(pp, pVal));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse a number from the configuration line. This functions just parses
+ * the number and does NOT call any handlers or set any values. It is just
+ * for INTERNAL USE by other parse functions!
+ * rgerhards, 2008-01-08
+ */
+static rsRetVal parseIntVal(uchar **pp, int64 *pVal)
+{
+ DEFiRet;
+ uchar *p;
+ int64 i;
+ int bWasNegative;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pVal != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+ p = *pp;
+
+ if(*p == '-') {
+ bWasNegative = 1;
+ ++p; /* eat it */
+ } else {
+ bWasNegative = 0;
+ }
+
+ if(!isdigit((int) *p)) {
+ errno = 0;
+ LogError(0, RS_RET_INVALID_INT, "invalid number");
+ ABORT_FINALIZE(RS_RET_INVALID_INT);
+ }
+
+ /* pull value */
+ for(i = 0 ; *p && (isdigit((int) *p) || *p == '.' || *p == ',') ; ++p) {
+ if(isdigit((int) *p)) {
+ i = i * 10 + *p - '0';
+ }
+ }
+
+ if(bWasNegative)
+ i *= -1;
+
+ *pVal = i;
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse a size from the configuration line. This is basically an integer
+ * syntax, but modifiers may be added after the integer (e.g. 1k to mean
+ * 1024). The size must immediately follow the number. Note that the
+ * param value must be int64!
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal doGetSize(uchar **pp, rsRetVal (*pSetHdlr)(void*, int64), void *pVal)
+{
+ DEFiRet;
+ int64 i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(parseIntVal(pp, &i));
+
+ /* we now check if the next character is one of our known modifiers.
+ * If so, we accept it as such. If not, we leave it alone. tera and
+ * above does not make any sense as that is above a 32-bit int value.
+ */
+ switch(**pp) {
+ /* traditional binary-based definitions */
+ case 'k': i *= 1024; ++(*pp); break;
+ case 'm': i *= 1024 * 1024; ++(*pp); break;
+ case 'g': i *= 1024 * 1024 * 1024; ++(*pp); break;
+ case 't': i *= (int64) 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* tera */
+ case 'p': i *= (int64) 1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* peta */
+ case 'e': i *= (int64) 1024 * 1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* exa */
+ /* and now the "new" 1000-based definitions */
+ case 'K': i *= 1000; ++(*pp); break;
+ case 'M': i *= 1000000; ++(*pp); break;
+ case 'G': i *= 1000000000; ++(*pp); break;
+ /* we need to use the multiplication below because otherwise
+ * the compiler gets an error during constant parsing */
+ case 'T': i *= (int64) 1000 * 1000000000; ++(*pp); break; /* tera */
+ case 'P': i *= (int64) 1000000 * 1000000000; ++(*pp); break; /* peta */
+ case 'E': i *= (int64) 1000000000 * 1000000000; ++(*pp); break; /* exa */
+ }
+
+ /* done */
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int64*)pVal) = i;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, i));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse a number from the configuration line.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ uchar *p;
+ DEFiRet;
+ int64 i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(doGetSize(pp, NULL,&i));
+ p = *pp;
+ if(i > 2147483648ll) { /*2^31*/
+ LogError(0, RS_RET_INVALID_VALUE,
+ "value %lld too large for integer argument.", i);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = (int) i;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, (int) i));
+ }
+
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and interpret a $FileCreateMode and $umask line. This function
+ * pulls the creation mode and, if successful, stores it
+ * into the global variable so that the rest of rsyslogd
+ * opens files with that mode. Any previous value will be
+ * overwritten.
+ * HINT: if we store the creation mode in selector_t, we
+ * can even specify multiple modes simply be virtue of
+ * being placed in the right section of rsyslog.conf
+ * rgerhards, 2007-07-4 (happy independence day to my US friends!)
+ * Parameter **pp has a pointer to the current config line.
+ * On exit, it will be updated to the processed position.
+ */
+static rsRetVal doFileCreateMode(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ uchar *p;
+ DEFiRet;
+ int iVal;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+ p = *pp;
+
+ /* for now, we parse and accept only octal numbers
+ * Sequence of tests is important, we are using boolean shortcuts
+ * to avoid addressing invalid memory!
+ */
+ if(!( (*p == '0')
+ && (*(p+1) && *(p+1) >= '0' && *(p+1) <= '7')
+ && (*(p+2) && *(p+2) >= '0' && *(p+2) <= '7')
+ && (*(p+3) && *(p+3) >= '0' && *(p+3) <= '7') ) ) {
+ LogError(0, RS_RET_INVALID_VALUE, "value must be octal (e.g 0644).");
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+
+ /* we reach this code only if the octal number is ok - so we can now
+ * compute the value.
+ */
+ iVal = (*(p+1)-'0') * 64 + (*(p+2)-'0') * 8 + (*(p+3)-'0');
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = iVal;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, iVal));
+ }
+
+ p += 4; /* eat the octal number */
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and interpret an on/off inside a config file line. This is most
+ * often used for boolean options, but of course it may also be used
+ * for other things. The passed-in pointer is updated to point to
+ * the first unparsed character on exit. Function emits error messages
+ * if the value is neither on or off. It returns 0 if the option is off,
+ * 1 if it is on and another value if there was an error.
+ * rgerhards, 2007-07-15
+ */
+static int doParseOnOffOption(uchar **pp)
+{
+ uchar *pOptStart;
+ uchar szOpt[32];
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ pOptStart = *pp;
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ if(getSubString(pp, (char*) szOpt, sizeof(szOpt), ' ') != 0) {
+ LogError(0, NO_ERRCODE, "Invalid $-configline - could not extract on/off option");
+ return -1;
+ }
+
+ if(!strcmp((char*)szOpt, "on")) {
+ return 1;
+ } else if(!strcmp((char*)szOpt, "off")) {
+ return 0;
+ } else {
+ LogError(0, NO_ERRCODE, "Option value must be on or off, but is '%s'", (char*)pOptStart);
+ return -1;
+ }
+}
+
+
+/* extract a groupname and return its gid.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ struct group *pgBuf = NULL;
+ struct group gBuf;
+ DEFiRet;
+ uchar szName[256];
+ int bufSize = 1024;
+ char * stringBuf = NULL;
+ int err;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "could not extract group name: %s\n", (char*)szName);
+ exit(1); /* good exit */
+ } else {
+ LogError(0, RS_RET_NOT_FOUND, "could not extract group name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ }
+
+ do {
+ char *p;
+
+ /* Increase bufsize and try again.*/
+ bufSize *= 2;
+ CHKmalloc(p = realloc(stringBuf, bufSize));
+ stringBuf = p;
+ err = getgrnam_r((char*)szName, &gBuf, stringBuf, bufSize, &pgBuf);
+ } while((pgBuf == NULL) && (err == ERANGE));
+
+ if(pgBuf == NULL) {
+ if (err != 0) {
+ LogError(err, RS_RET_NOT_FOUND, "Query for group '%s' resulted in an error",
+ szName);
+ } else {
+ LogError(0, RS_RET_NOT_FOUND, "ID for group '%s' could not be found", szName);
+ }
+ iRet = RS_RET_NOT_FOUND;
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "ID for group '%s' could not be found or error\n", szName);
+ exit(1); /* good exit */
+ }
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((gid_t*)pVal) = pgBuf->gr_gid;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, pgBuf->gr_gid));
+ }
+ dbgprintf("gid %d obtained for group '%s'\n", (int) pgBuf->gr_gid, szName);
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ free(stringBuf);
+ RETiRet;
+}
+
+
+/* extract a username and return its uid.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal doGetUID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ struct passwd *ppwBuf;
+ struct passwd pwBuf;
+ DEFiRet;
+ uchar szName[256];
+ char stringBuf[2048]; /* I hope this is large enough... */
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "could not extract user name: %s\n", (char*)szName);
+ exit(1); /* good exit */
+ } else {
+ LogError(0, RS_RET_NOT_FOUND, "could not extract user name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ }
+
+ getpwnam_r((char*)szName, &pwBuf, stringBuf, sizeof(stringBuf), &ppwBuf);
+
+ if(ppwBuf == NULL) {
+ if(loadConf->globals.abortOnIDResolutionFail) {
+ fprintf(stderr, "ID for user '%s' could not be found or error\n", (char*)szName);
+ exit(1); /* good exit */
+ } else {
+ LogError(0, RS_RET_NOT_FOUND, "ID for user '%s' could not be found or error", (char*)szName);
+ iRet = RS_RET_NOT_FOUND;
+ }
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((uid_t*)pVal) = ppwBuf->pw_uid;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, ppwBuf->pw_uid));
+ }
+ dbgprintf("uid %d obtained for user '%s'\n", (int) ppwBuf->pw_uid, szName);
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and process an binary cofig option. pVal must be
+ * a pointer to an integer which is to receive the option
+ * value.
+ * rgerhards, 2007-07-15
+ */
+static rsRetVal doBinaryOptionLine(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
+{
+ int iOption;
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if((iOption = doParseOnOffOption(pp)) == -1)
+ return RS_RET_ERR; /* nothing left to do */
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = iOption;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, iOption));
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* parse a whitespace-delimited word from the provided string. This is a
+ * helper function for a number of syntaxes. The parsed value is returned
+ * in ppStrB (which must be provided by caller).
+ * rgerhards, 2008-02-14
+ */
+static rsRetVal
+getWord(uchar **pp, cstr_t **ppStrB)
+{
+ DEFiRet;
+ uchar *p;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(ppStrB != NULL);
+
+ CHKiRet(cstrConstruct(ppStrB));
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ /* parse out the word */
+ p = *pp;
+
+ while(*p && !isspace((int) *p)) {
+ CHKiRet(cstrAppendChar(*ppStrB, *p++));
+ }
+ cstrFinalize(*ppStrB);
+
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and a word config line option. A word is a consequtive
+ * sequence of non-whitespace characters. pVal must be
+ * a pointer to a string which is to receive the option
+ * value. The returned string must be freed by the caller.
+ * rgerhards, 2007-09-07
+ * To facilitate multiple instances of the same command line
+ * directive, doGetWord() now checks if pVal is already a
+ * non-NULL pointer. If so, we assume it was created by a previous
+ * incarnation and is automatically freed. This happens only when
+ * no custom handler is defined. If it is, the customer handler
+ * must do the cleanup. I have checked and this was al also memory
+ * leak with some code. Obviously, not a large one. -- rgerhards, 2007-12-20
+ * Just to clarify: if pVal is parsed to a custom handler, this handler
+ * is responsible for freeing pVal. -- rgerhards, 2008-03-20
+ */
+static rsRetVal doGetWord(uchar **pp, rsRetVal (*pSetHdlr)(void*, uchar*), void *pVal)
+{
+ DEFiRet;
+ cstr_t *pStrB = NULL;
+ uchar *pNewVal;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(getWord(pp, &pStrB));
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pNewVal, 0));
+
+ DBGPRINTF("doGetWord: get newval '%s' (len %d), hdlr %p\n",
+ pNewVal, (int) ustrlen(pNewVal), pSetHdlr);
+ /* we got the word, now set it */
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ if(*((uchar**)pVal) != NULL)
+ free(*((uchar**)pVal)); /* free previous entry */
+ *((uchar**)pVal) = pNewVal; /* set new one */
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, pNewVal));
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
+
+ RETiRet;
+}
+
+
+/* parse a syslog name from the string. This is the generic code that is
+ * called by the facility/severity functions. Note that we do not check the
+ * validity of numerical values, something that should probably change over
+ * time (TODO). -- rgerhards, 2008-02-14
+ */
+static rsRetVal
+doSyslogName(uchar **pp, rsRetVal (*pSetHdlr)(void*, int),
+ void *pVal, syslogName_t *pNameTable)
+{
+ DEFiRet;
+ cstr_t *pStrB;
+ int iNewVal;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(getWord(pp, &pStrB)); /* get word */
+ iNewVal = decodeSyslogName(cstrGetSzStrNoNULL(pStrB), pNameTable);
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = iNewVal; /* set new one */
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, iNewVal));
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ if(pStrB != NULL)
+ rsCStrDestruct(&pStrB);
+
+ RETiRet;
+}
+
+
+/* Implements the facility syntax.
+ * rgerhards, 2008-02-14
+ */
+static rsRetVal
+doFacility(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
+{
+ DEFiRet;
+ iRet = doSyslogName(pp, pSetHdlr, pVal, syslogFacNames);
+ RETiRet;
+}
+
+
+static rsRetVal
+doGoneAway(__attribute__((unused)) uchar **pp,
+ __attribute__((unused)) rsRetVal (*pSetHdlr)(void*, int),
+ __attribute__((unused)) void *pVal)
+{
+ parser_warnmsg("config directive is no longer supported -- ignored");
+ return RS_RET_CMD_GONE_AWAY;
+}
+
+/* Implements the severity syntax.
+ * rgerhards, 2008-02-14
+ */
+static rsRetVal
+doSeverity(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
+{
+ DEFiRet;
+ iRet = doSyslogName(pp, pSetHdlr, pVal, syslogPriNames);
+ RETiRet;
+}
+
+
+/* --------------- END functions for handling canned syntaxes --------------- */
+
+/* destructor for cslCmdHdlr
+ * pThis is actually a cslCmdHdlr_t, but we do not cast it as all we currently
+ * need to do is free it.
+ */
+static rsRetVal cslchDestruct(void *pThis)
+{
+ assert(pThis != NULL);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor for cslCmdHdlr
+ */
+static rsRetVal cslchConstruct(cslCmdHdlr_t **ppThis)
+{
+ cslCmdHdlr_t *pThis;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ if((pThis = calloc(1, sizeof(cslCmdHdlr_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+finalize_it:
+ *ppThis = pThis;
+ RETiRet;
+}
+
+/* destructor for linked list keys. As we do not use any dynamic memory,
+ * we simply return. However, this entry point must be defined for the
+ * linkedList class to make sure we have not forgotten a destructor.
+ * rgerhards, 2007-11-21
+ */
+static rsRetVal cslchKeyDestruct(void __attribute__((unused)) *pData)
+{
+ return RS_RET_OK;
+}
+
+
+/* Key compare operation for linked list class. This compares two
+ * owner cookies (void *).
+ * rgerhards, 2007-11-21
+ */
+static int cslchKeyCompare(void *pKey1, void *pKey2)
+{
+ if(pKey1 == pKey2)
+ return 0;
+ else
+ if(pKey1 < pKey2)
+ return -1;
+ else
+ return 1;
+}
+
+
+/* set data members for this object
+ */
+static rsRetVal cslchSetEntry(cslCmdHdlr_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData,
+int *permitted)
+{
+ assert(pThis != NULL);
+ assert(eType != eCmdHdlrInvalid);
+
+ pThis->eType = eType;
+ pThis->cslCmdHdlr = pHdlr;
+ pThis->pData = pData;
+ pThis->permitted = permitted;
+
+ return RS_RET_OK;
+}
+
+
+/* call the specified handler
+ */
+static rsRetVal cslchCallHdlr(cslCmdHdlr_t *pThis, uchar **ppConfLine)
+{
+ DEFiRet;
+ rsRetVal (*pHdlr)() = NULL;
+ assert(pThis != NULL);
+ assert(ppConfLine != NULL);
+
+ switch(pThis->eType) {
+ case eCmdHdlrCustomHandler:
+ pHdlr = doCustomHdlr;
+ break;
+ case eCmdHdlrUID:
+ pHdlr = doGetUID;
+ break;
+ case eCmdHdlrGID:
+ pHdlr = doGetGID;
+ break;
+ case eCmdHdlrBinary:
+ pHdlr = doBinaryOptionLine;
+ break;
+ case eCmdHdlrFileCreateMode:
+ pHdlr = doFileCreateMode;
+ break;
+ case eCmdHdlrInt:
+ pHdlr = doGetInt;
+ break;
+ case eCmdHdlrSize:
+ pHdlr = doGetSize;
+ break;
+ case eCmdHdlrGetChar:
+ pHdlr = doGetChar;
+ break;
+ case eCmdHdlrFacility:
+ pHdlr = doFacility;
+ break;
+ case eCmdHdlrSeverity:
+ pHdlr = doSeverity;
+ break;
+ case eCmdHdlrGetWord:
+ pHdlr = doGetWord;
+ break;
+ case eCmdHdlrGoneAway:
+ pHdlr = doGoneAway;
+ break;
+ /* some non-legacy handler (used in v6+ solely) */
+ case eCmdHdlrInvalid:
+ case eCmdHdlrNonNegInt:
+ case eCmdHdlrPositiveInt:
+ case eCmdHdlrString:
+ case eCmdHdlrArray:
+ case eCmdHdlrQueueType:
+ default:
+ dbgprintf("error: command handler type %d not implemented in legacy system\n", pThis->eType);
+ iRet = RS_RET_NOT_IMPLEMENTED;
+ goto finalize_it;
+ }
+
+ /* we got a pointer to the handler, so let's call it */
+ assert(pHdlr != NULL);
+ CHKiRet(pHdlr(ppConfLine, pThis->cslCmdHdlr, pThis->pData));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ---------------------------------------------------------------------- *
+ * now come the handlers for cslCmd_t
+ * ---------------------------------------------------------------------- */
+
+/* destructor for a cslCmd list key (a string as of now)
+ */
+static rsRetVal cslcKeyDestruct(void *pData)
+{
+ free(pData); /* we do not need to cast as all we do is free it anyway... */
+ return RS_RET_OK;
+}
+
+/* destructor for cslCmd
+ */
+static rsRetVal cslcDestruct(void *pData)
+{
+ cslCmd_t *pThis = (cslCmd_t*) pData;
+
+ assert(pThis != NULL);
+
+ llDestroy(&pThis->llCmdHdlrs);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor for cslCmd
+ */
+static rsRetVal cslcConstruct(cslCmd_t **ppThis, int bChainingPermitted)
+{
+ cslCmd_t *pThis;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ if((pThis = calloc(1, sizeof(cslCmd_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->bChainingPermitted = bChainingPermitted;
+
+ CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, cslchKeyDestruct, cslchKeyCompare));
+
+finalize_it:
+ *ppThis = pThis;
+ RETiRet;
+}
+
+
+/* add a handler entry to a known command
+ */
+static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData,
+void *pOwnerCookie, int *permitted)
+{
+ DEFiRet;
+ cslCmdHdlr_t *pCmdHdlr = NULL;
+
+ assert(pThis != NULL);
+
+ CHKiRet(cslchConstruct(&pCmdHdlr));
+ CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData, permitted));
+ CHKiRet(llAppend(&pThis->llCmdHdlrs, pOwnerCookie, pCmdHdlr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pHdlr != NULL)
+ cslchDestruct(pCmdHdlr);
+ }
+
+ RETiRet;
+}
+
+
+/* function that registers cfsysline handlers.
+ * The supplied pCmdName is copied and a new buffer is allocated. This
+ * buffer is automatically destroyed when the element is freed, the
+ * caller does not need to take care of that. The caller must, however,
+ * free pCmdName if he allocated it dynamically! -- rgerhards, 2007-08-09
+ * Parameter permitted has been added to support the v2 config system. With it,
+ * we can tell the legacy system (us here!) to check if a config directive is
+ * still permitted. For example, the v2 system will disable module global
+ * parameters if the are supplied via the native v2 callbacks. In order not
+ * to break exisiting modules, we have renamed the rgCfSysLinHdlr routine to
+ * version 2 and added a new one with the original name. It just calls the
+ * v2 function and supplies a "don't care (NULL)" pointer as this argument.
+ * rgerhards, 2012-06-26
+ */
+rsRetVal regCfSysLineHdlr2(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(),
+void *pData, void *pOwnerCookie, int *permitted)
+{
+ DEFiRet;
+ cslCmd_t *pThis;
+ uchar *pMyCmdName;
+
+ iRet = llFind(&llCmdList, (void *) pCmdName, (void*) &pThis);
+ if(iRet == RS_RET_NOT_FOUND) {
+ /* new command */
+ CHKiRet(cslcConstruct(&pThis, bChainingPermitted));
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, permitted)) {
+ cslcDestruct(pThis);
+ FINALIZE;
+ }
+ /* important: add to list, AFTER everything else is OK. Else
+ * we mess up things in the error case.
+ */
+ if((pMyCmdName = (uchar*) strdup((char*)pCmdName)) == NULL) {
+ cslcDestruct(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ CHKiRet_Hdlr(llAppend(&llCmdList, pMyCmdName, (void*) pThis)) {
+ cslcDestruct(pThis);
+ FINALIZE;
+ }
+ } else {
+ /* command already exists, are we allowed to chain? */
+ if(pThis->bChainingPermitted == 0 || bChainingPermitted == 0) {
+ ABORT_FINALIZE(RS_RET_CHAIN_NOT_PERMITTED);
+ }
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, permitted)) {
+ cslcDestruct(pThis);
+ FINALIZE;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal regCfSysLineHdlr(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(),
+void *pData, void *pOwnerCookie)
+{
+ DEFiRet;
+ iRet = regCfSysLineHdlr2(pCmdName, bChainingPermitted, eType, pHdlr, pData, pOwnerCookie, NULL);
+ RETiRet;
+}
+
+
+rsRetVal unregCfSysLineHdlrs(void)
+{
+ return llDestroy(&llCmdList);
+}
+
+
+/* helper function for unregCfSysLineHdlrs4Owner(). This is used to see if there is
+ * a handler of this owner inside the element and, if so, remove it. Please note that
+ * it keeps track of a pointer to the last linked list entry, as this is needed to
+ * remove an entry from the list.
+ * rgerhards, 2007-11-21
+ */
+DEFFUNC_llExecFunc(unregHdlrsHeadExec)
+{
+ DEFiRet;
+ cslCmd_t *pListHdr = (cslCmd_t*) pData;
+ int iNumElts;
+
+ /* first find element */
+ CHKiRet(llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam));
+
+ /* now go back and check how many elements are left */
+ CHKiRet(llGetNumElts(&(pListHdr->llCmdHdlrs), &iNumElts));
+
+ if(iNumElts == 0) {
+ /* nothing left in header, so request to delete it */
+ iRet = RS_RET_OK_DELETE_LISTENTRY;
+ }
+
+finalize_it:
+ RETiRet;
+}
+/* unregister and destroy cfSysLineHandlers for a specific owner. This method is
+ * most importantly used before unloading a loadable module providing some handlers.
+ * The full list of handlers is searched. If the to-be removed handler was the only
+ * handler for a directive name, the directive header, too, is deleted.
+ * rgerhards, 2007-11-21
+ */
+rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie)
+{
+ DEFiRet;
+ /* we need to walk through all directive names, as the linked list
+ * class does not provide a way to just search the lower-level handlers.
+ */
+ iRet = llExecFunc(&llCmdList, unregHdlrsHeadExec, pOwnerCookie);
+ if(iRet == RS_RET_NOT_FOUND) {
+ /* It is not considered an error if a module had no
+ hanlers registered. */
+ iRet = RS_RET_OK;
+ }
+
+ RETiRet;
+}
+
+
+/* process a cfsysline command (based on handler structure)
+ * param "p" is a pointer to the command line after the command. Should be
+ * updated.
+ */
+rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p)
+{
+ DEFiRet;
+ rsRetVal iRetLL; /* for linked list handling */
+ cslCmd_t *pCmd;
+ cslCmdHdlr_t *pCmdHdlr;
+ linkedListCookie_t llCookieCmdHdlr;
+ uchar *pHdlrP; /* the handler's private p (else we could only call one handler) */
+ int bWasOnceOK; /* was the result of an handler at least once RS_RET_OK? */
+ uchar *pOKp = NULL; /* returned conf line pointer when it was OK */
+
+ iRet = llFind(&llCmdList, (void *) pCmdName, (void*) &pCmd);
+
+ if(iRet == RS_RET_NOT_FOUND) {
+ LogError(0, RS_RET_NOT_FOUND, "invalid or yet-unknown config file command '%s' - "
+ "have you forgotten to load a module?", pCmdName);
+ }
+
+ if(iRet != RS_RET_OK)
+ goto finalize_it;
+
+ llCookieCmdHdlr = NULL;
+ bWasOnceOK = 0;
+ while((iRetLL = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void*)&pCmdHdlr)) == RS_RET_OK) {
+ /* for the time being, we ignore errors during handlers. The
+ * reason is that handlers are independent. An error in one
+ * handler does not necessarily mean that another one will
+ * fail, too. Later, we might add a config variable to control
+ * this behaviour (but I am not sure if that is really
+ * necessary). -- rgerhards, 2007-07-31
+ */
+ pHdlrP = *p;
+ if(pCmdHdlr->permitted != NULL && !*(pCmdHdlr->permitted)) {
+ LogError(0, RS_RET_PARAM_NOT_PERMITTED, "command '%s' is currently not "
+ "permitted - did you already set it via a RainerScript command (v6+ config)?",
+ pCmdName);
+ ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED);
+ } else if((iRet = cslchCallHdlr(pCmdHdlr, &pHdlrP)) == RS_RET_OK) {
+ bWasOnceOK = 1;
+ pOKp = pHdlrP;
+ }
+ }
+
+ if(bWasOnceOK == 1) {
+ *p = pOKp;
+ iRet = RS_RET_OK;
+ }
+
+ if(iRetLL != RS_RET_END_OF_LINKEDLIST)
+ iRet = iRetLL;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* debug print the command handler structure
+ */
+void dbgPrintCfSysLineHandlers(void)
+{
+ cslCmd_t *pCmd;
+ cslCmdHdlr_t *pCmdHdlr;
+ linkedListCookie_t llCookieCmd;
+ linkedListCookie_t llCookieCmdHdlr;
+ uchar *pKey;
+
+ dbgprintf("System Line Configuration Commands:\n");
+ llCookieCmd = NULL;
+ while(llGetNextElt(&llCmdList, &llCookieCmd, (void*)&pCmd) == RS_RET_OK) {
+ llGetKey(llCookieCmd, (void*) &pKey); /* TODO: using the cookie is NOT clean! */
+ dbgprintf("\tCommand '%s':\n", pKey);
+ llCookieCmdHdlr = NULL;
+ while(llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void*)&pCmdHdlr) == RS_RET_OK) {
+ dbgprintf("\t\ttype : %d\n", pCmdHdlr->eType);
+ dbgprintf("\t\tpData: 0x%lx\n", (unsigned long) pCmdHdlr->pData);
+ dbgprintf("\t\tHdlr : 0x%lx\n", (unsigned long) pCmdHdlr->cslCmdHdlr);
+ dbgprintf("\t\tOwner: 0x%lx\n", (unsigned long) llCookieCmdHdlr->pKey);
+ dbgprintf("\n");
+ }
+ }
+ dbgprintf("\n");
+}
+
+
+/* our init function. TODO: remove once converted to a class
+ */
+rsRetVal
+cfsyslineInit(void)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+
+ CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp));
+
+finalize_it:
+ RETiRet;
+}
diff --git a/runtime/cfsysline.h b/runtime/cfsysline.h
new file mode 100644
index 0000000..44e85ca
--- /dev/null
+++ b/runtime/cfsysline.h
@@ -0,0 +1,62 @@
+/* Definition of the cfsysline (config file system line) object.
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CFSYSLINE_H_INCLUDED
+#define CFSYSLINE_H_INCLUDED
+
+#include "linkedlist.h"
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct cslCmdHdlr_s { /* config file sysline parse entry */
+ ecslConfObjType __attribute__((deprecated)) eConfObjType; /* which config object is this for? */
+ ecslCmdHdrlType eType; /* which type of handler is this? */
+ rsRetVal (*cslCmdHdlr)(); /* function pointer to use with handler (params depending on eType) */
+ void *pData; /* user-supplied data pointer */
+ int *permitted; /* is this parameter currently permitted? (NULL=don't check) */
+};
+typedef struct cslCmdHdlr_s cslCmdHdlr_t;
+
+
+/* this is the list of known configuration commands with pointers to
+ * their handlers.
+ * The short name is cslc (Configfile SysLine Command)
+ */
+struct cslCmd_s { /* config file sysline parse entry */
+ int bChainingPermitted; /* may multiple handlers be chained for this command? */
+ linkedList_t llCmdHdlrs; /* linked list of command handlers */
+};
+typedef struct cslCmd_s cslCmd_t;
+
+/* prototypes */
+rsRetVal regCfSysLineHdlr(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(),
+ void *pData, void *pOwnerCookie);
+rsRetVal regCfSysLineHdlr2(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(),
+ void *pData, void *pOwnerCookie, int *permitted);
+rsRetVal unregCfSysLineHdlrs(void);
+rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie);
+rsRetVal processCfSysLineCommand(uchar *pCmd, uchar **p);
+rsRetVal cfsyslineInit(void);
+void dbgPrintCfSysLineHandlers(void);
+
+#endif /* #ifndef CFSYSLINE_H_INCLUDED */
diff --git a/runtime/conf.c b/runtime/conf.c
new file mode 100644
index 0000000..5eee37e
--- /dev/null
+++ b/runtime/conf.c
@@ -0,0 +1,640 @@
+/* The config file handler (not yet a real object)
+ *
+ * This file is based on an excerpt from syslogd.c, which dates back
+ * much later. I began the file on 2008-02-19 as part of the modularization
+ * effort. Over time, a clean abstration will become even more important
+ * because the config file handler will by dynamically be loaded and be
+ * kept in memory only as long as the config file is actually being
+ * processed. Thereafter, it shall be unloaded. -- rgerhards
+ * Please note that the original syslogd.c source was under BSD license
+ * at the time of the rsyslog fork from sysklogd.
+ *
+ * Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define CFGLNSIZ 64*1024 /* the maximum size of a configuration file line, after re-combination */
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include <dirent.h>
+#include <glob.h>
+#include <sys/types.h>
+#ifdef HAVE_LIBGEN_H
+# ifndef OS_SOLARIS
+# include <libgen.h>
+# endif
+#endif
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "parse.h"
+#include "action.h"
+#include "template.h"
+#include "cfsysline.h"
+#include "modules.h"
+#include "outchannel.h"
+#include "stringbuf.h"
+#include "conf.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "net.h"
+#include "ruleset.h"
+#include "rsconf.h"
+#include "unicode-helper.h"
+#include "rainerscript.h"
+
+#ifdef OS_SOLARIS
+# define NAME_MAX MAXNAMELEN
+#endif
+
+/* forward definitions */
+
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(module)
+DEFobjCurrIf(net)
+DEFobjCurrIf(ruleset)
+
+int bConfStrictScoping = 0; /* force strict scoping during config processing? */
+
+
+/* The following module-global variables are used for building
+ * tag and host selector lines during startup and config reload.
+ * This is stored as a global variable pool because of its ease. It is
+ * also fairly compatible with multi-threading as the stratup code must
+ * be run in a single thread anyways. So there can be no race conditions.
+ * rgerhards 2005-10-18
+ */
+EHostnameCmpMode eDfltHostnameCmpMode = HN_NO_COMP;
+cstr_t *pDfltHostnameCmp = NULL;
+cstr_t *pDfltProgNameCmp = NULL;
+
+
+/* process a $ModLoad config line. */
+static rsRetVal
+doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
+{
+ DEFiRet;
+ uchar szName[512];
+ uchar *pModName;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+ if(getSubString(pp, (char*) szName, sizeof(szName), ' ') != 0) {
+ LogError(0, RS_RET_NOT_FOUND, "could not extract module name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ /* this below is a quick and dirty hack to provide compatibility with the
+ * $ModLoad MySQL forward compatibility statement. This needs to be supported
+ * for legacy format.
+ */
+ if(!strcmp((char*) szName, "MySQL"))
+ pModName = (uchar*) "ommysql.so";
+ else
+ pModName = szName;
+
+ CHKiRet(module.Load(pModName, 1, NULL));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* remove leading spaces from name; this "fixes" some anomalies in
+ * getSubString(), but I was not brave enough to fix the former as
+ * it has many other callers... -- rgerhards, 2013-05-27
+ */
+static void
+ltrim(char *src)
+{
+ char *dst = src;
+ while(isspace(*src))
+ ++src; /*SKIP*/;
+ if(dst != src) {
+ while(*src != '\0')
+ *dst++ = *src++;
+ *dst = '\0';
+ }
+}
+
+/* parse and interpret a $-config line that starts with
+ * a name (this is common code). It is parsed to the name
+ * and then the proper sub-function is called to handle
+ * the actual directive.
+ * rgerhards 2004-11-17
+ * rgerhards 2005-06-21: previously only for templates, now
+ * generalized.
+ */
+static rsRetVal
+doNameLine(uchar **pp, void* pVal)
+{
+ DEFiRet;
+ uchar *p;
+ enum eDirective eDir;
+ char szName[128];
+
+ assert(pp != NULL);
+ p = *pp;
+ assert(p != NULL);
+
+ PRAGMA_DIAGNOSTIC_PUSH
+ PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast;
+ /* this time, pVal actually is NOT a pointer! It is save to case, as
+ * the enum was written to it, so there can be no loss of bits (ptr is larger).
+ */
+ eDir = (enum eDirective) pVal;
+ PRAGMA_DIAGNOSTIC_POP
+
+ if(getSubString(&p, szName, sizeof(szName), ',') != 0) {
+ LogError(0, RS_RET_NOT_FOUND, "Invalid config line: could not extract name - line ignored");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ ltrim(szName);
+ if(*p == ',')
+ ++p; /* comma was eaten */
+
+ /* we got the name - now we pass name & the rest of the string
+ * to the subfunction. It makes no sense to do further
+ * parsing here, as this is in close interaction with the
+ * respective subsystem. rgerhards 2004-11-17
+ */
+
+ switch(eDir) {
+ case DIR_TEMPLATE:
+ tplAddLine(loadConf, szName, &p);
+ break;
+ case DIR_OUTCHANNEL:
+ ochAddLine(szName, &p);
+ break;
+ case DIR_ALLOWEDSENDER:
+ net.addAllowedSenderLine(szName, &p);
+ break;
+ default:/* we do this to avoid compiler warning - not all
+ * enum values call this function, so an incomplete list
+ * is quite ok (but then we should not run into this code,
+ * so at least we log a debug warning).
+ */
+ dbgprintf("INTERNAL ERROR: doNameLine() called with invalid eDir %d.\n",
+ eDir);
+ break;
+ }
+
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and interpret a system-directive in the config line
+ * A system directive is one that starts with a "$" sign. It offers
+ * extended configuration parameters.
+ * 2004-11-17 rgerhards
+ */
+static rsRetVal
+cfsysline(uchar *p)
+{
+ DEFiRet;
+ uchar szCmd[64];
+
+ assert(p != NULL);
+ errno = 0;
+ if(getSubString(&p, (char*) szCmd, sizeof(szCmd), ' ') != 0) {
+ LogError(0, RS_RET_NOT_FOUND, "Invalid $-configline "
+ "- could not extract command - line ignored\n");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ /* we now try and see if we can find the command in the registered
+ * list of cfsysline handlers. -- rgerhards, 2007-07-31
+ */
+ CHKiRet(processCfSysLineCommand(szCmd, &p));
+
+ /* now check if we have some extra characters left on the line - that
+ * should not be the case. Whitespace is OK, but everything else should
+ * trigger a warning (that may be an indication of undesired behaviour).
+ * An exception, of course, are comments (starting with '#').
+ * rgerhards, 2007-07-04
+ */
+ skipWhiteSpace(&p);
+
+ if(*p && *p != '#') { /* we have a non-whitespace, so let's complain */
+ LogError(0, NO_ERRCODE,
+ "error: extra characters in config line ignored: '%s'", p);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Helper to cfline() and its helpers. Parses a template name
+ * from an "action" line. Must be called with the Line pointer
+ * pointing to the first character after the semicolon.
+ * rgerhards 2004-11-19
+ * changed function to work with OMSR. -- rgerhards, 2007-07-27
+ * the default template is to be used when no template is specified.
+ */
+rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName)
+{
+ uchar *p;
+ uchar *tplName = NULL;
+ cstr_t *pStrB = NULL;
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pOMSR != NULL);
+
+ p =*pp;
+ /* a template must follow - search it and complain, if not found */
+ skipWhiteSpace(&p);
+ if(*p == ';')
+ ++p; /* eat it */
+ else if(*p != '\0' && *p != '#') {
+ LogError(0, RS_RET_ERR, "invalid character in selector line - ';template' expected");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ skipWhiteSpace(&p); /* go to begin of template name */
+
+ if(*p == '\0' || *p == '#') {
+ /* no template specified, use the default */
+ /* TODO: check NULL ptr */
+ tplName = (uchar*) strdup((char*)dfltTplName);
+ } else {
+ /* template specified, pick it up */
+ CHKiRet(cstrConstruct(&pStrB));
+
+ /* now copy the string */
+ while(*p && *p != '#' && !isspace((int) *p)) {
+ CHKiRet(cstrAppendChar(pStrB, *p));
+ ++p;
+ }
+ cstrFinalize(pStrB);
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &tplName, 0));
+ }
+
+ CHKiRet(OMSRsetEntry(pOMSR, iEntry, tplName, iTplOpts));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(tplName);
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
+
+ *pp = p;
+
+ RETiRet;
+}
+
+/* Helper to cfline(). Parses a file name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template.
+ * rgerhards 2004-11-18
+ * parameter pFileName must point to a buffer large enough
+ * to hold the largest possible filename.
+ * rgerhards, 2007-07-25
+ * updated to include OMSR pointer -- rgerhards, 2007-07-27
+ * updated to include template name -- rgerhards, 2008-03-28
+ * rgerhards, 2010-01-19: file names end at the first space
+ */
+rsRetVal
+cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl)
+{
+ register uchar *pName;
+ int i;
+ DEFiRet;
+
+ assert(pOMSR != NULL);
+
+ pName = pFileName;
+ i = 1; /* we start at 1 so that we reseve space for the '\0'! */
+ while(*p && *p != ';' && *p != ' ' && i < MAXFNAME) {
+ *pName++ = *p++;
+ ++i;
+ }
+ *pName = '\0';
+
+ iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, pszTpl);
+
+ RETiRet;
+}
+
+
+/* Decode a traditional PRI filter */
+/* GPLv3 - stems back to sysklogd */
+rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[])
+{
+ uchar *p;
+ register uchar *q;
+ register int i, i2;
+ uchar *bp;
+ int pri; /* this MUST be int, as -1 is used to convey an error state */
+ int singlpri = 0;
+ int ignorepri = 0;
+ uchar buf[2048]; /* buffer for facility and priority names */
+ uchar xbuf[200];
+ DEFiRet;
+
+ assert(pline != NULL);
+
+ dbgprintf("Decoding traditional PRI filter '%s'\n", pline);
+
+ for (i = 0; i <= LOG_NFACILITIES; i++) {
+ pmask[i] = TABLE_NOPRI;
+ }
+
+ /* scan through the list of selectors */
+ for (p = pline; *p && *p != '\t' && *p != ' ';) {
+ /* find the end of this facility name list */
+ for (q = p; *q && *q != '\t' && *q++ != '.'; )
+ continue;
+
+ /* collect priority name */
+ for (bp = buf; *q && !strchr("\t ,;", *q) && bp < buf+sizeof(buf)-1 ; )
+ *bp++ = *q++;
+ *bp = '\0';
+
+ /* skip cruft */
+ if(*q) {
+ while (strchr(",;", *q))
+ q++;
+ }
+
+ /* decode priority name */
+ if ( *buf == '!' ) {
+ ignorepri = 1;
+ /* copy below is ok, we can NOT go off the allocated area */
+ for (bp=buf; *(bp+1); bp++)
+ *bp=*(bp+1);
+ *bp='\0';
+ } else {
+ ignorepri = 0;
+ }
+ if ( *buf == '=' ) {
+ singlpri = 1;
+ pri = decodeSyslogName(&buf[1], syslogPriNames);
+ }
+ else { singlpri = 0;
+ pri = decodeSyslogName(buf, syslogPriNames);
+ }
+
+ if (pri < 0) {
+ snprintf((char*) xbuf, sizeof(xbuf), "unknown priority name \"%s\"", buf);
+ LogError(0, RS_RET_ERR, "%s", xbuf);
+ return RS_RET_ERR;
+ }
+
+ /* scan facilities */
+ while (*p && !strchr("\t .;", *p)) {
+ for (bp = buf; *p && !strchr("\t ,;.", *p) && bp < buf+sizeof(buf)-1 ; )
+ *bp++ = *p++;
+ *bp = '\0';
+ if (*buf == '*') {
+ for (i = 0; i <= LOG_NFACILITIES; i++) {
+ if ( pri == INTERNAL_NOPRI ) {
+ if ( ignorepri )
+ pmask[i] = TABLE_ALLPRI;
+ else
+ pmask[i] = TABLE_NOPRI;
+ }
+ else if ( singlpri ) {
+ if ( ignorepri )
+ pmask[i] &= ~(1<<pri);
+ else
+ pmask[i] |= (1<<pri);
+ } else {
+ if ( pri == TABLE_ALLPRI ) {
+ if ( ignorepri )
+ pmask[i] = TABLE_NOPRI;
+ else
+ pmask[i] = TABLE_ALLPRI;
+ } else {
+ if ( ignorepri )
+ for (i2= 0; i2 <= pri; ++i2)
+ pmask[i] &= ~(1<<i2);
+ else
+ for (i2= 0; i2 <= pri; ++i2)
+ pmask[i] |= (1<<i2);
+ }
+ }
+ }
+ } else {
+ i = decodeSyslogName(buf, syslogFacNames);
+ if (i < 0) {
+
+ snprintf((char*) xbuf, sizeof(xbuf), "unknown facility name \"%s\"", buf);
+ LogError(0, RS_RET_ERR, "%s", xbuf);
+ return RS_RET_ERR;
+ }
+
+ if ( pri == INTERNAL_NOPRI ) {
+ if ( ignorepri )
+ pmask[i >> 3] = TABLE_ALLPRI;
+ else
+ pmask[i >> 3] = TABLE_NOPRI;
+ } else if ( singlpri ) {
+ if ( ignorepri )
+ pmask[i >> 3] &= ~(1<<pri);
+ else
+ pmask[i >> 3] |= (1<<pri);
+ } else {
+ if ( pri == TABLE_ALLPRI ) {
+ if ( ignorepri )
+ pmask[i >> 3] = TABLE_NOPRI;
+ else
+ pmask[i >> 3] = TABLE_ALLPRI;
+ } else {
+ if ( ignorepri )
+ for (i2= 0; i2 <= pri; ++i2)
+ pmask[i >> 3] &= ~(1<<i2);
+ else
+ for (i2= 0; i2 <= pri; ++i2)
+ pmask[i >> 3] |= (1<<i2);
+ }
+ }
+ }
+ while (*p == ',' || *p == ' ')
+ p++;
+ }
+
+ p = q;
+ }
+
+ RETiRet;
+}
+
+
+/* process the action part of a selector line
+ * rgerhards, 2007-08-01
+ */
+rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
+{
+ modInfo_t *pMod;
+ cfgmodules_etry_t *node;
+ omodStringRequest_t *pOMSR;
+ int bHadWarning = 0;
+ action_t *pAction = NULL;
+ void *pModData;
+ DEFiRet;
+
+ assert(p != NULL);
+ assert(ppAction != NULL);
+
+ /* loop through all modules and see if one picks up the line */
+ node = module.GetNxtCnfType(conf, NULL, eMOD_OUT);
+ /* Note: clang static analyzer reports that node maybe == NULL. However, this is
+ * not possible, because we have the built-in output modules which are always
+ * present. Anyhow, we guard this by an assert. -- rgerhards, 2010-12-16
+ */
+ assert(node != NULL);
+ while(node != NULL) {
+ pOMSR = NULL;
+ pMod = node->pMod;
+ iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR);
+ dbgprintf("tried selector action for %s: %d\n", module.GetName(pMod), iRet);
+ if(iRet == RS_RET_OK_WARN) {
+ bHadWarning = 1;
+ iRet = RS_RET_OK;
+ }
+ if(iRet == RS_RET_OK) {
+ if((iRet = addAction(&pAction, pMod, pModData, pOMSR, NULL, NULL)) == RS_RET_OK) {
+ /* here check if the module is compatible with select features
+ * (currently, we have no such features!) */
+ conf->actions.nbrActions++; /* one more active action! */
+ }
+ break;
+ } else if(iRet != RS_RET_CONFLINE_UNPROCESSED) {
+ /* In this case, the module would have handled the config
+ * line, but some error occurred while doing so. This error should
+ * already by reported by the module. We do not try any other
+ * modules on this line, because we found the right one.
+ * rgerhards, 2007-07-24
+ */
+ dbgprintf("error %d parsing config line\n", (int) iRet);
+ break;
+ }
+ node = module.GetNxtCnfType(conf, node, eMOD_OUT);
+ }
+
+ *ppAction = pAction;
+ if(iRet == RS_RET_OK && bHadWarning)
+ iRet = RS_RET_OK_WARN;
+ RETiRet;
+}
+
+
+/* return the current number of active actions
+ * rgerhards, 2008-07-28
+ */
+static rsRetVal
+GetNbrActActions(rsconf_t *conf, int *piNbrActions)
+{
+ DEFiRet;
+ assert(piNbrActions != NULL);
+ *piNbrActions = conf->actions.nbrActions;
+ RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(conf)
+CODESTARTobjQueryInterface(conf)
+ if(pIf->ifVersion != confCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->doNameLine = doNameLine;
+ pIf->cfsysline = cfsysline;
+ pIf->doModLoad = doModLoad;
+ pIf->GetNbrActActions = GetNbrActActions;
+
+finalize_it:
+ENDobjQueryInterface(conf)
+
+
+/* Reset config variables to default values.
+ * rgerhards, 2010-07-23
+ */
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ bConfStrictScoping = 0;
+ return RS_RET_OK;
+}
+
+
+/* exit our class
+ * rgerhards, 2008-03-11
+ */
+BEGINObjClassExit(conf, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(conf)
+ /* free no-longer needed module-global variables */
+ if(pDfltHostnameCmp != NULL) {
+ rsCStrDestruct(&pDfltHostnameCmp);
+ }
+
+ if(pDfltProgNameCmp != NULL) {
+ rsCStrDestruct(&pDfltProgNameCmp);
+ }
+
+ /* release objects we no longer need */
+ objRelease(module, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDObjClassExit(conf)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-29
+ */
+BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ /* request objects we use */
+ CHKiRet(objUse(module, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* These commands will NOT be supported -- the new v6.3 config system provides
+ * far better methods. We will remove the related code soon. -- rgerhards, 2012-01-09
+ */
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+NULL, NULL));
+ENDObjClassInit(conf)
diff --git a/runtime/conf.h b/runtime/conf.h
new file mode 100644
index 0000000..96c5711
--- /dev/null
+++ b/runtime/conf.h
@@ -0,0 +1,73 @@
+/* Definitions for config file handling (not yet an object).
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_CONF_H
+#define INCLUDED_CONF_H
+#include "action.h"
+
+/* definitions used for doNameLine to differentiate between different command types
+ * (with otherwise identical code). This is a left-over from the previous config
+ * system. It stays, because it is still useful. So do not wonder why it looks
+ * somewhat strange (at least its name). -- rgerhards, 2007-08-01
+ */
+enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2};
+extern ecslConfObjType currConfObj;
+extern int bConfStrictScoping; /* force strict scoping during config processing? */
+
+/* interfaces */
+BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*doNameLine)(uchar **pp, void* pVal);
+ rsRetVal (*cfsysline)(uchar *p);
+ rsRetVal (*doModLoad)(uchar **pp, __attribute__((unused)) void* pVal);
+ rsRetVal (*GetNbrActActions)(rsconf_t *conf, int *);
+ /* version 4 -- 2010-07-23 rgerhards */
+ /* "just" added global variables
+ * FYI: we reconsider repacking as a non-object, as only the core currently
+ * accesses this module. The current object structure complicates things without
+ * any real benefit.
+ */
+ /* version 5 -- 2011-04-19 rgerhards */
+ /* complete revamp, we now use the rsconf object */
+ /* version 6 -- 2011-07-06 rgerhards */
+ /* again a complete revamp, using flex/bison based parser now */
+ENDinterface(conf)
+#define confCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
+/* in Version 3, entry point "ReInitConf()" was removed, as we do not longer need
+ * to support restart-type HUP -- rgerhards, 2009-07-15
+ */
+
+
+/* prototypes */
+PROTOTYPEObj(conf);
+
+
+/* TODO: the following 2 need to go in conf obj interface... */
+rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts,
+ uchar *dfltTplName);
+rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts,
+ uchar *pszTpl);
+
+rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[]);
+rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction);
+extern EHostnameCmpMode eDfltHostnameCmpMode;
+extern cstr_t *pDfltHostnameCmp;
+extern cstr_t *pDfltProgNameCmp;
+
+#endif /* #ifndef INCLUDED_CONF_H */
diff --git a/runtime/cryprov.h b/runtime/cryprov.h
new file mode 100644
index 0000000..9829b1b
--- /dev/null
+++ b/runtime/cryprov.h
@@ -0,0 +1,48 @@
+/* The interface definition for (file) crypto providers.
+ *
+ * This is just an abstract driver interface, which needs to be
+ * implemented by concrete classes.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_CRYPROV_H
+#define INCLUDED_CRYPROV_H
+
+/* we unfortunately need to have two different param names depending on the
+ * context in which parameters are set. Other than (re/over)engineering the core
+ * interface, we just define some values to keep track of that.
+ */
+#define CRYPROV_PARAMTYPE_REGULAR 0
+#define CRYPROV_PARAMTYPE_DISK 1
+
+/* interface */
+BEGINinterface(cryprov) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(void *ppThis);
+ rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst, int paramType);
+ rsRetVal (*Destruct)(void *ppThis);
+ rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData, char openMode);
+ rsRetVal (*Encrypt)(void *pFileInstData, uchar *buf, size_t *lenBuf);
+ rsRetVal (*Decrypt)(void *pFileInstData, uchar *buf, size_t *lenBuf);
+ rsRetVal (*OnFileClose)(void *pFileInstData, off64_t offsLogfile);
+ rsRetVal (*DeleteStateFiles)(uchar *logfn);
+ rsRetVal (*GetBytesLeftInBlock)(void *pFileInstData, ssize_t *left);
+ void (*SetDeleteOnClose)(void *pFileInstData, int val);
+ENDinterface(cryprov)
+#define cryprovCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+#endif /* #ifndef INCLUDED_CRYPROV_H */
diff --git a/runtime/datetime.c b/runtime/datetime.c
new file mode 100644
index 0000000..22dc7d0
--- /dev/null
+++ b/runtime/datetime.c
@@ -0,0 +1,1413 @@
+/* The datetime object. It contains date and time related functions.
+ *
+ * Module begun 2008-03-05 by Rainer Gerhards, based on some code
+ * from syslogd.c. The main intension was to move code out of syslogd.c
+ * in a useful manner. It is still undecided if all functions will continue
+ * to stay here or some will be moved into parser modules (once we have them).
+ *
+ * Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "modules.h"
+#include "datetime.h"
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "errmsg.h"
+#include "rsconf.h"
+#include "timezones.h"
+
+/* static data */
+DEFobjStaticHelpers
+
+/* the following table of ten powers saves us some computation */
+static const int tenPowers[6] = { 1, 10, 100, 1000, 10000, 100000 };
+
+/* the following table saves us from computing an additional date to get
+ * the ordinal day of the year - at least from 1967-2099
+ * Note: non-2038+ compliant systems (Solaris) will generate compiler
+ * warnings on the post 2038-rollover years.
+ */
+static const int yearInSec_startYear = 1967;
+/* for x in $(seq 1967 2099) ; do
+ * printf %s', ' $(date --date="Dec 31 ${x} UTC 23:59:59" +%s)
+ * done |fold -w 70 -s */
+static const long long yearInSecs[] = {
+ -63158401, -31536001, -1, 31535999, 63071999, 94694399, 126230399,
+ 157766399, 189302399, 220924799, 252460799, 283996799, 315532799,
+ 347155199, 378691199, 410227199, 441763199, 473385599, 504921599,
+ 536457599, 567993599, 599615999, 631151999, 662687999, 694223999,
+ 725846399, 757382399, 788918399, 820454399, 852076799, 883612799,
+ 915148799, 946684799, 978307199, 1009843199, 1041379199, 1072915199,
+ 1104537599, 1136073599, 1167609599, 1199145599, 1230767999,
+ 1262303999, 1293839999, 1325375999, 1356998399, 1388534399,
+ 1420070399, 1451606399, 1483228799, 1514764799, 1546300799,
+ 1577836799, 1609459199, 1640995199, 1672531199, 1704067199,
+ 1735689599, 1767225599, 1798761599, 1830297599, 1861919999,
+ 1893455999, 1924991999, 1956527999, 1988150399, 2019686399,
+ 2051222399, 2082758399, 2114380799, 2145916799, 2177452799,
+ 2208988799, 2240611199, 2272147199, 2303683199, 2335219199,
+ 2366841599, 2398377599, 2429913599, 2461449599, 2493071999,
+ 2524607999, 2556143999, 2587679999, 2619302399, 2650838399,
+ 2682374399, 2713910399, 2745532799, 2777068799, 2808604799,
+ 2840140799, 2871763199, 2903299199, 2934835199, 2966371199,
+ 2997993599, 3029529599, 3061065599, 3092601599, 3124223999,
+ 3155759999, 3187295999, 3218831999, 3250454399, 3281990399,
+ 3313526399, 3345062399, 3376684799, 3408220799, 3439756799,
+ 3471292799, 3502915199, 3534451199, 3565987199, 3597523199,
+ 3629145599, 3660681599, 3692217599, 3723753599, 3755375999,
+ 3786911999, 3818447999, 3849983999, 3881606399, 3913142399,
+ 3944678399, 3976214399, 4007836799, 4039372799, 4070908799,
+ 4102444799};
+
+/* note ramge is 1969 -> 2100 because it needs to access previous/next year */
+/* for x in $(seq 1969 2100) ; do
+ * printf %s', ' $(date --date="Dec 28 ${x} UTC 12:00:00" +%V)
+ * done | fold -w 70 -s */
+static const int weeksInYear[] = {
+ 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52,
+ 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52,
+ 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52,
+ 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52,
+ 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52,
+ 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52,
+ 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52,
+ 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52,
+};
+
+static const char* monthNames[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/* ------------------------------ methods ------------------------------ */
+
+
+/**
+ * Convert struct timeval to syslog_time
+ */
+static void
+timeval2syslogTime(struct timeval *tp, struct syslogTime *t, const int inUTC)
+{
+ struct tm *tm;
+ struct tm tmBuf;
+ long lBias;
+ time_t secs;
+
+#if defined(__hpux)
+ struct timezone tz;
+# endif
+ secs = tp->tv_sec;
+ if(inUTC)
+ tm = gmtime_r(&secs, &tmBuf);
+ else
+ tm = localtime_r(&secs, &tmBuf);
+
+ t->year = tm->tm_year + 1900;
+ t->month = tm->tm_mon + 1;
+ t->day = tm->tm_mday;
+ t->wday = tm->tm_wday;
+ t->hour = tm->tm_hour;
+ t->minute = tm->tm_min;
+ t->second = tm->tm_sec;
+ t->secfrac = tp->tv_usec;
+ t->secfracPrecision = 6;
+
+ if(inUTC) {
+ t->OffsetMode = '+';
+ lBias = 0;
+ } else {
+# if defined(__sun)
+ /* Solaris uses a different method of exporting the time zone.
+ * It is UTC - localtime, which is the opposite sign of mins east of GMT.
+ */
+ lBias = -(tm->tm_isdst ? altzone : timezone);
+# elif defined(__hpux)
+ lBias = tz.tz_dsttime ? - tz.tz_minuteswest : 0;
+# elif defined(_AIX)
+ /* AIXPORT : IBM documentation notice that 'extern long timezone'
+ * is setted after calling tzset.
+ * Recent version of AIX, localtime_r call inside tzset.
+ */
+ if (tm->tm_isdst) tzset();
+ lBias = - timezone;
+# else
+ lBias = tm->tm_gmtoff;
+# endif
+ if(lBias < 0) {
+ t->OffsetMode = '-';
+ lBias *= -1;
+ } else
+ t->OffsetMode = '+';
+ }
+ t->OffsetHour = lBias / 3600;
+ t->OffsetMinute = (lBias % 3600) / 60;
+ t->timeType = TIME_TYPE_RFC5424; /* we have a high precision timestamp */
+ t->inUTC = inUTC;
+}
+
+/**
+ * Get the current date/time in the best resolution the operating
+ * system has to offer (well, actually at most down to the milli-
+ * second level.
+ *
+ * The date and time is returned in separate fields as this is
+ * most portable and removes the need for additional structures
+ * (but I have to admit it is somewhat "bulky";)).
+ *
+ * Obviously, *t must not be NULL...
+ *
+ * rgerhards, 2008-10-07: added ttSeconds to provide a way to
+ * obtain the second-resolution UNIX timestamp. This is needed
+ * in some situations to minimize time() calls (namely when doing
+ * output processing). This can be left NULL if not needed.
+ */
+static void getCurrTime(struct syslogTime *t, time_t *ttSeconds, const int inUTC)
+{
+ struct timeval tp;
+/* AIXPORT : fix build error : "tm_gmtoff" is not a member of "struct tm"
+ * Choose the HPUX code path, only for this function.
+ * This is achieved by adding a check to _AIX wherever _hpux is checked
+ */
+
+
+#if defined(__hpux) || defined(_AIX)
+ struct timezone tz;
+# endif
+
+ assert(t != NULL);
+#if defined(__hpux) || defined(_AIX)
+ /* TODO: check this: under HP UX, the tz information is actually valid
+ * data. So we need to obtain and process it there.
+ */
+ gettimeofday(&tp, &tz);
+# else
+ gettimeofday(&tp, NULL);
+# endif
+ if(ttSeconds != NULL)
+ *ttSeconds = tp.tv_sec;
+
+ timeval2syslogTime(&tp, t, inUTC);
+}
+
+
+/* A fast alternative to getCurrTime() and time() that only obtains
+ * a timestamp like time() does. I was told that gettimeofday(), at
+ * least under Linux, is much faster than time() and I could confirm
+ * this testing. So I created that function as a replacement.
+ * rgerhards, 2009-11-12
+ */
+time_t
+getTime(time_t *ttSeconds)
+{
+ struct timeval tp;
+
+ if(gettimeofday(&tp, NULL) == -1)
+ return -1;
+
+ if(ttSeconds != NULL)
+ *ttSeconds = tp.tv_sec;
+ return tp.tv_sec;
+}
+
+dateTimeFormat_t getDateTimeFormatFromStr(const char * const __restrict__ s) {
+ assert(s != NULL);
+
+ if (strcmp(s, "date-rfc3164") == 0)
+ return DATE_RFC3164;
+ if (strcmp(s, "date-rfc3339") == 0)
+ return DATE_RFC3339;
+ if (strcmp(s, "date-unix") == 0)
+ return DATE_UNIX;
+
+ return DATE_INVALID;
+}
+
+/*******************************************************************
+ * BEGIN CODE-LIBLOGGING *
+ *******************************************************************
+ * Code in this section is borrowed from liblogging. This is an
+ * interim solution. Once liblogging is fully integrated, this is
+ * to be removed (see http://www.monitorware.com/liblogging for
+ * more details. 2004-11-16 rgerhards
+ *
+ * Please note that the orginal liblogging code is modified so that
+ * it fits into the context of the current version of syslogd.c.
+ *
+ * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!!
+ */
+
+
+/**
+ * Parse a 32 bit integer number from a string. We do not permit
+ * integer overruns, this the guard against INT_MAX.
+ *
+ * \param ppsz Pointer to the Pointer to the string being parsed. It
+ * must be positioned at the first digit. Will be updated
+ * so that on return it points to the first character AFTER
+ * the integer parsed.
+ * \param pLenStr pointer to string length, decremented on exit by
+ * characters processed
+ * Note that if an empty string (len < 1) is passed in,
+ * the method always returns zero.
+ * \retval The number parsed.
+ */
+static int
+srSLMGParseInt32(uchar** ppsz, int *pLenStr)
+{
+ register int i;
+
+ i = 0;
+ while(*pLenStr > 0 && **ppsz >= '0' && **ppsz <= '9' && i < INT_MAX/10-1) {
+ i = i * 10 + **ppsz - '0';
+ ++(*ppsz);
+ --(*pLenStr);
+ }
+
+ return i;
+}
+
+
+/**
+ * Parse a TIMESTAMP-3339.
+ * updates the parse pointer position. The pTime parameter
+ * is guranteed to be updated only if a new valid timestamp
+ * could be obtained (restriction added 2008-09-16 by rgerhards).
+ * This method now also checks the maximum string length it is passed.
+ * If a *valid* timestamp is found, the string length is decremented
+ * by the number of characters processed. If it is not a valid timestamp,
+ * the length is kept unmodified. -- rgerhards, 2009-09-23
+ */
+static rsRetVal
+ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr)
+{
+ uchar *pszTS = *ppszTS;
+ /* variables to temporarily hold time information while we parse */
+ int year;
+ int month;
+ int day;
+ int hour; /* 24 hour clock */
+ int minute;
+ int second;
+ int secfrac; /* fractional seconds (must be 32 bit!) */
+ int secfracPrecision;
+ char OffsetMode; /* UTC offset + or - */
+ int OffsetHour; /* UTC offset in hours */
+ int OffsetMinute; /* UTC offset in minutes */
+ int lenStr;
+ /* end variables to temporarily hold time information while we parse */
+ DEFiRet;
+
+ assert(pTime != NULL);
+ assert(ppszTS != NULL);
+ assert(pszTS != NULL);
+
+ lenStr = *pLenStr;
+ year = srSLMGParseInt32(&pszTS, &lenStr);
+
+ /* We take the liberty to accept slightly malformed timestamps e.g. in
+ * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course,
+ * with the current state of affairs, we would never run into this code
+ * here because at postion 11, there is no "T" in such cases ;)
+ */
+ if(lenStr == 0 || *pszTS++ != '-' || year < 0 || year >= 2100) {
+ DBGPRINTF("ParseTIMESTAMP3339: invalid year: %d, pszTS: '%c'\n", year, *pszTS);
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ }
+ --lenStr;
+ month = srSLMGParseInt32(&pszTS, &lenStr);
+ if(month < 1 || month > 12)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != '-')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ day = srSLMGParseInt32(&pszTS, &lenStr);
+ if(day < 1 || day > 31)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != 'T')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
+ if(hour < 0 || hour > 23)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != ':')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ minute = srSLMGParseInt32(&pszTS, &lenStr);
+ if(minute < 0 || minute > 59)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != ':')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ second = srSLMGParseInt32(&pszTS, &lenStr);
+ if(second < 0 || second > 60)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ /* Now let's see if we have secfrac */
+ if(lenStr > 0 && *pszTS == '.') {
+ --lenStr;
+ uchar *pszStart = ++pszTS;
+ secfrac = srSLMGParseInt32(&pszTS, &lenStr);
+ secfracPrecision = (int) (pszTS - pszStart);
+ } else {
+ secfracPrecision = 0;
+ secfrac = 0;
+ }
+
+ /* check the timezone */
+ if(lenStr == 0)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(*pszTS == 'Z') {
+ --lenStr;
+ pszTS++; /* eat Z */
+ OffsetMode = 'Z';
+ OffsetHour = 0;
+ OffsetMinute = 0;
+ } else if((*pszTS == '+') || (*pszTS == '-')) {
+ OffsetMode = *pszTS;
+ --lenStr;
+ pszTS++;
+
+ OffsetHour = srSLMGParseInt32(&pszTS, &lenStr);
+ if(OffsetHour < 0 || OffsetHour > 23)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS != ':')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ pszTS++;
+ OffsetMinute = srSLMGParseInt32(&pszTS, &lenStr);
+ if(OffsetMinute < 0 || OffsetMinute > 59)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else {
+ /* there MUST be TZ information */
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ }
+
+ /* OK, we actually have a 3339 timestamp, so let's indicated this */
+ if(lenStr > 0) {
+ if(*pszTS != ' ') /* if it is not a space, it can not be a "good" time - 2010-02-22 rgerhards */
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ ++pszTS; /* just skip past it */
+ --lenStr;
+ }
+
+ /* we had success, so update parse pointer and caller-provided timestamp */
+ *ppszTS = pszTS;
+ pTime->timeType = 2;
+ pTime->year = year;
+ pTime->month = month;
+ pTime->day = day;
+ pTime->hour = hour;
+ pTime->minute = minute;
+ pTime->second = second;
+ pTime->secfrac = secfrac;
+ pTime->secfracPrecision = secfracPrecision;
+ pTime->OffsetMode = OffsetMode;
+ pTime->OffsetHour = OffsetHour;
+ pTime->OffsetMinute = OffsetMinute;
+ *pLenStr = lenStr;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/**
+ * Parse a TIMESTAMP-3164. The pTime parameter
+ * is guranteed to be updated only if a new valid timestamp
+ * could be obtained (restriction added 2008-09-16 by rgerhards). This
+ * also means the caller *must* provide a valid (probably current)
+ * timstamp in pTime when calling this function. a 3164 timestamp contains
+ * only partial information and only that partial information is updated.
+ * So the "output timestamp" is a valid timestamp only if the "input
+ * timestamp" was valid, too. The is actually an optimization, as it
+ * permits us to use a pre-acquired timestamp and thus avoids to do
+ * a (costly) time() call. Thanks to David Lang for insisting on
+ * time() call reduction ;).
+ * This method now also checks the maximum string length it is passed.
+ * If a *valid* timestamp is found, the string length is decremented
+ * by the number of characters processed. If it is not a valid timestamp,
+ * the length is kept unmodified. -- rgerhards, 2009-09-23
+ *
+ * We support this format:
+ * [yyyy] Mon mm [yyyy] hh:mm:ss[.subsec][ [yyyy ]/[TZSTRING:]]
+ * Note that [yyyy] and [.subsec] are non-standard but frequently occur.
+ * Also [yyyy] can only occur once -- if it occurs twice, we flag the
+ * timestamp as invalid. if bParseTZ is true, we try to obtain a
+ * TZSTRING. Note that in this case it MUST be terminated by a colon
+ * (Cisco format). This option is a bit dangerous, as it could already
+ * by the tag. So it MUST only be enabled in specialised parsers.
+ * subsec, [yyyy] in front, TZSTRING was added in 2014-07-08 rgerhards
+ * Similarly, we try to detect a year after the timestamp if
+ * bDetectYearAfterTime is set. This is mutally exclusive with bParseTZ.
+ * Note: bDetectYearAfterTime will misdetect hostnames in the range
+ * 2000..2100 as years, so this option should explicitly be turned on
+ * and is not meant for general consumption.
+ */
+static rsRetVal
+ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr,
+ const int bParseTZ,
+ const int bDetectYearAfterTime)
+{
+ /* variables to temporarily hold time information while we parse */
+ int month;
+ int day;
+ int year = 0; /* 0 means no year provided */
+ int hour; /* 24 hour clock */
+ int minute;
+ int second;
+ int secfrac; /* fractional seconds (must be 32 bit!) */
+ int secfracPrecision;
+ char tzstring[16];
+ char OffsetMode = '\0'; /* UTC offset: \0 -> indicate no update */
+ char OffsetHour = '\0'; /* UTC offset in hours */
+ int OffsetMinute = 0; /* UTC offset in minutes */
+ /* end variables to temporarily hold time information while we parse */
+ int lenStr;
+ uchar *pszTS;
+ DEFiRet;
+
+ assert(ppszTS != NULL);
+ pszTS = *ppszTS;
+ assert(pszTS != NULL);
+ assert(pTime != NULL);
+ assert(pLenStr != NULL);
+ lenStr = *pLenStr;
+
+ if(lenStr < 3)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ /* first check if we have a year in front of the timestamp. some devices (e.g. Brocade)
+ * do this. As it is pretty straightforward to detect and chance of misinterpretation
+ * is low, we try to parse it.
+ */
+ if(*pszTS >= '0' && *pszTS <= '9') {
+ /* OK, either we have a prepended year or an invalid format! */
+ year = srSLMGParseInt32(&pszTS, &lenStr);
+ if(year < 1970 || year > 2100 || *pszTS != ' ')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ ++pszTS; /* skip SP */
+ }
+
+ /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec),
+ * we may see the following character sequences occur:
+ *
+ * J(an/u(n/l)), Feb, Ma(r/y), A(pr/ug), Sep, Oct, Nov, Dec
+ *
+ * We will use this for parsing, as it probably is the
+ * fastest way to parse it.
+ *
+ * 2009-08-17: we now do case-insensitive comparisons, as some devices obviously do not
+ * obey to the RFC-specified case. As we need to guess in any case, we can ignore case
+ * in the first place -- rgerhards
+ *
+ * 2005-07-18, well sometimes it pays to be a bit more verbose, even in C...
+ * Fixed a bug that lead to invalid detection of the data. The issue was that
+ * we had an if(++pszTS == 'x') inside of some of the consturcts below. However,
+ * there were also some elseifs (doing the same ++), which than obviously did not
+ * check the orginal character but the next one. Now removed the ++ and put it
+ * into the statements below. Was a really nasty bug... I didn't detect it before
+ * june, when it first manifested. This also lead to invalid parsing of the rest
+ * of the message, as the time stamp was not detected to be correct. - rgerhards
+ */
+ switch(*pszTS++)
+ {
+ case 'j':
+ case 'J':
+ if(*pszTS == 'a' || *pszTS == 'A') {
+ ++pszTS;
+ if(*pszTS == 'n' || *pszTS == 'N') {
+ ++pszTS;
+ month = 1;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else if(*pszTS == 'u' || *pszTS == 'U') {
+ ++pszTS;
+ if(*pszTS == 'n' || *pszTS == 'N') {
+ ++pszTS;
+ month = 6;
+ } else if(*pszTS == 'l' || *pszTS == 'L') {
+ ++pszTS;
+ month = 7;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'f':
+ case 'F':
+ if(*pszTS == 'e' || *pszTS == 'E') {
+ ++pszTS;
+ if(*pszTS == 'b' || *pszTS == 'B') {
+ ++pszTS;
+ month = 2;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'm':
+ case 'M':
+ if(*pszTS == 'a' || *pszTS == 'A') {
+ ++pszTS;
+ if(*pszTS == 'r' || *pszTS == 'R') {
+ ++pszTS;
+ month = 3;
+ } else if(*pszTS == 'y' || *pszTS == 'Y') {
+ ++pszTS;
+ month = 5;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'a':
+ case 'A':
+ if(*pszTS == 'p' || *pszTS == 'P') {
+ ++pszTS;
+ if(*pszTS == 'r' || *pszTS == 'R') {
+ ++pszTS;
+ month = 4;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else if(*pszTS == 'u' || *pszTS == 'U') {
+ ++pszTS;
+ if(*pszTS == 'g' || *pszTS == 'G') {
+ ++pszTS;
+ month = 8;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 's':
+ case 'S':
+ if(*pszTS == 'e' || *pszTS == 'E') {
+ ++pszTS;
+ if(*pszTS == 'p' || *pszTS == 'P') {
+ ++pszTS;
+ month = 9;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'o':
+ case 'O':
+ if(*pszTS == 'c' || *pszTS == 'C') {
+ ++pszTS;
+ if(*pszTS == 't' || *pszTS == 'T') {
+ ++pszTS;
+ month = 10;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'n':
+ case 'N':
+ if(*pszTS == 'o' || *pszTS == 'O') {
+ ++pszTS;
+ if(*pszTS == 'v' || *pszTS == 'V') {
+ ++pszTS;
+ month = 11;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ case 'd':
+ case 'D':
+ if(*pszTS == 'e' || *pszTS == 'E') {
+ ++pszTS;
+ if(*pszTS == 'c' || *pszTS == 'C') {
+ ++pszTS;
+ month = 12;
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ } else
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ break;
+ default:
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ }
+
+ lenStr -= 3;
+
+ /* done month */
+
+ if(lenStr == 0 || *pszTS++ != ' ')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+
+ /* we accept a slightly malformed timestamp when receiving. This is
+ * we accept one-digit days
+ */
+ if(*pszTS == ' ') {
+ --lenStr;
+ ++pszTS;
+ }
+
+ day = srSLMGParseInt32(&pszTS, &lenStr);
+ if(day < 1 || day > 31)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != ' ')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+
+ /* time part */
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
+ if(year == 0 && hour > 1970 && hour < 2100) {
+ /* if so, we assume this actually is a year. This is a format found
+ * e.g. in Cisco devices.
+ * (if you read this 2100+ trying to fix a bug, congratulate me
+ * to how long the code survived - me no longer ;)) -- rgerhards, 2008-11-18
+ */
+ year = hour;
+
+ /* re-query the hour, this time it must be valid */
+ if(lenStr == 0 || *pszTS++ != ' ')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ hour = srSLMGParseInt32(&pszTS, &lenStr);
+ }
+
+ if(hour < 0 || hour > 23)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != ':')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ minute = srSLMGParseInt32(&pszTS, &lenStr);
+ if(minute < 0 || minute > 59)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ if(lenStr == 0 || *pszTS++ != ':')
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ --lenStr;
+ second = srSLMGParseInt32(&pszTS, &lenStr);
+ if(second < 0 || second > 60)
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+
+ /* as an extension e.g. found in CISCO IOS, we support sub-second resultion.
+ * It's presence is indicated by a dot immediately following the second.
+ */
+ if(lenStr > 0 && *pszTS == '.') {
+ --lenStr;
+ uchar *pszStart = ++pszTS;
+ secfrac = srSLMGParseInt32(&pszTS, &lenStr);
+ secfracPrecision = (int) (pszTS - pszStart);
+ } else {
+ secfracPrecision = 0;
+ secfrac = 0;
+ }
+
+ /* try to parse the TZSTRING if we are instructed to do so */
+ if(bParseTZ && lenStr > 2 && *pszTS == ' ') {
+ int i;
+ for( ++pszTS, --lenStr, i = 0
+ ; lenStr > 0 && i < (int) sizeof(tzstring) - 1 && *pszTS != ':' && *pszTS != ' '
+ ; --lenStr)
+ tzstring[i++] = *pszTS++;
+ if(i > 0) {
+ /* found TZ, apply it */
+ tzinfo_t* tzinfo;
+ tzstring[i] = '\0';
+ if((tzinfo = glblFindTimezone(runConf, (char*) tzstring)) == NULL) {
+ DBGPRINTF("ParseTIMESTAMP3164: invalid TZ string '%s' -- ignored\n",
+ tzstring);
+ } else {
+ OffsetMode = tzinfo->offsMode;
+ OffsetHour = tzinfo->offsHour;
+ OffsetMinute = tzinfo->offsMin;
+ }
+ }
+ }
+ if(bDetectYearAfterTime && year == 0 && lenStr > 5 && *pszTS == ' ') {
+ int j;
+ int y = 0;
+ for(j = 1 ; j < 5 ; ++j) {
+ if(pszTS[j] < '0' || pszTS[j] > '9')
+ break;
+ y = 10 * y + pszTS[j] - '0';
+ }
+ if(lenStr > 6 && pszTS[5] != ' ')
+ y = 0; /* no year! */
+ if(2000 <= y && y < 2100) {
+ year = y;
+ pszTS += 5; /* we need to preserve the SP, checked below */
+ lenStr -= 5;
+ }
+ }
+
+ /* we provide support for an extra ":" after the date. While this is an
+ * invalid format, it occurs frequently enough (e.g. with Cisco devices)
+ * to permit it as a valid case. -- rgerhards, 2008-09-12
+ */
+ if(lenStr > 0 && *pszTS == ':') {
+ ++pszTS; /* just skip past it */
+ --lenStr;
+ }
+ if(lenStr > 0) {
+ if(*pszTS != ' ') /* if it is not a space, it can not be a "good" time - 2010-02-22 rgerhards */
+ ABORT_FINALIZE(RS_RET_INVLD_TIME);
+ ++pszTS; /* just skip past it */
+ --lenStr;
+ }
+
+ /* we had success, so update parse pointer and caller-provided timestamp
+ * fields we do not have are not updated in the caller's timestamp. This
+ * is the reason why the caller must pass in a correct timestamp.
+ */
+ *ppszTS = pszTS; /* provide updated parse position back to caller */
+ pTime->timeType = 1;
+ pTime->month = month;
+ if(year > 0)
+ pTime->year = year; /* persist year if detected */
+ pTime->day = day;
+ pTime->hour = hour;
+ pTime->minute = minute;
+ pTime->second = second;
+ pTime->secfrac = secfrac;
+ pTime->secfracPrecision = secfracPrecision;
+ if(OffsetMode != '\0') { /* need to update TZ info? */
+ pTime->OffsetMode = OffsetMode;
+ pTime->OffsetHour = OffsetHour;
+ pTime->OffsetMinute = OffsetMinute;
+ }
+ *pLenStr = lenStr;
+
+finalize_it:
+ RETiRet;
+}
+
+void
+applyDfltTZ(struct syslogTime *pTime, char *tz)
+{
+ pTime->OffsetMode = tz[0];
+ pTime->OffsetHour = (tz[1] - '0') * 10 + (tz[2] - '0');
+ pTime->OffsetMinute = (tz[4] - '0') * 10 + (tz[5] - '0');
+
+}
+
+/*******************************************************************
+ * END CODE-LIBLOGGING *
+ *******************************************************************/
+
+/**
+ * Format a syslogTimestamp into format required by MySQL.
+ * We are using the 14 digits format. For example 20041111122600
+ * is interpreted as '2004-11-11 12:26:00'.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occurred.
+ */
+static int
+formatTimestampToMySQL(struct syslogTime *ts, char* pBuf)
+{
+ /* currently we do not consider localtime/utc. This may later be
+ * added. If so, I recommend using a property replacer option
+ * and/or a global configuration option. However, we should wait
+ * on user requests for this feature before doing anything.
+ * rgerhards, 2007-06-26
+ */
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ pBuf[0] = (ts->year / 1000) % 10 + '0';
+ pBuf[1] = (ts->year / 100) % 10 + '0';
+ pBuf[2] = (ts->year / 10) % 10 + '0';
+ pBuf[3] = ts->year % 10 + '0';
+ pBuf[4] = (ts->month / 10) % 10 + '0';
+ pBuf[5] = ts->month % 10 + '0';
+ pBuf[6] = (ts->day / 10) % 10 + '0';
+ pBuf[7] = ts->day % 10 + '0';
+ pBuf[8] = (ts->hour / 10) % 10 + '0';
+ pBuf[9] = ts->hour % 10 + '0';
+ pBuf[10] = (ts->minute / 10) % 10 + '0';
+ pBuf[11] = ts->minute % 10 + '0';
+ pBuf[12] = (ts->second / 10) % 10 + '0';
+ pBuf[13] = ts->second % 10 + '0';
+ pBuf[14] = '\0';
+ return 15;
+
+}
+
+static int
+formatTimestampToPgSQL(struct syslogTime *ts, char *pBuf)
+{
+ /* see note in formatTimestampToMySQL, applies here as well */
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ pBuf[0] = (ts->year / 1000) % 10 + '0';
+ pBuf[1] = (ts->year / 100) % 10 + '0';
+ pBuf[2] = (ts->year / 10) % 10 + '0';
+ pBuf[3] = ts->year % 10 + '0';
+ pBuf[4] = '-';
+ pBuf[5] = (ts->month / 10) % 10 + '0';
+ pBuf[6] = ts->month % 10 + '0';
+ pBuf[7] = '-';
+ pBuf[8] = (ts->day / 10) % 10 + '0';
+ pBuf[9] = ts->day % 10 + '0';
+ pBuf[10] = ' ';
+ pBuf[11] = (ts->hour / 10) % 10 + '0';
+ pBuf[12] = ts->hour % 10 + '0';
+ pBuf[13] = ':';
+ pBuf[14] = (ts->minute / 10) % 10 + '0';
+ pBuf[15] = ts->minute % 10 + '0';
+ pBuf[16] = ':';
+ pBuf[17] = (ts->second / 10) % 10 + '0';
+ pBuf[18] = ts->second % 10 + '0';
+ pBuf[19] = '\0';
+ return 19;
+}
+
+
+/**
+ * Format a syslogTimestamp to just the fractional seconds.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occurred.
+ * The buffer must be at least 7 bytes large.
+ * rgerhards, 2008-06-06
+ */
+static int
+formatTimestampSecFrac(struct syslogTime *ts, char* pBuf)
+{
+ int iBuf;
+ int power;
+ int secfrac;
+ short digit;
+
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ iBuf = 0;
+ if(ts->secfracPrecision > 0)
+ {
+ power = tenPowers[(ts->secfracPrecision - 1) % 6];
+ secfrac = ts->secfrac;
+ while(power > 0) {
+ digit = secfrac / power;
+ secfrac -= digit * power;
+ power /= 10;
+ pBuf[iBuf++] = digit + '0';
+ }
+ } else {
+ pBuf[iBuf++] = '0';
+ }
+ pBuf[iBuf] = '\0';
+
+ return iBuf;
+}
+
+
+/**
+ * Format a syslogTimestamp to a RFC3339 timestamp string (as
+ * specified in syslog-protocol).
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occurred.
+ */
+static int
+formatTimestamp3339(struct syslogTime *ts, char* pBuf)
+{
+ int iBuf;
+ int power;
+ int secfrac;
+ short digit;
+
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ /* start with fixed parts */
+ /* year yyyy */
+ pBuf[0] = (ts->year / 1000) % 10 + '0';
+ pBuf[1] = (ts->year / 100) % 10 + '0';
+ pBuf[2] = (ts->year / 10) % 10 + '0';
+ pBuf[3] = ts->year % 10 + '0';
+ pBuf[4] = '-';
+ /* month */
+ pBuf[5] = (ts->month / 10) % 10 + '0';
+ pBuf[6] = ts->month % 10 + '0';
+ pBuf[7] = '-';
+ /* day */
+ pBuf[8] = (ts->day / 10) % 10 + '0';
+ pBuf[9] = ts->day % 10 + '0';
+ pBuf[10] = 'T';
+ /* hour */
+ pBuf[11] = (ts->hour / 10) % 10 + '0';
+ pBuf[12] = ts->hour % 10 + '0';
+ pBuf[13] = ':';
+ /* minute */
+ pBuf[14] = (ts->minute / 10) % 10 + '0';
+ pBuf[15] = ts->minute % 10 + '0';
+ pBuf[16] = ':';
+ /* second */
+ pBuf[17] = (ts->second / 10) % 10 + '0';
+ pBuf[18] = ts->second % 10 + '0';
+
+ iBuf = 19; /* points to next free entry, now it becomes dynamic! */
+
+ if(ts->secfracPrecision > 0) {
+ pBuf[iBuf++] = '.';
+ power = tenPowers[(ts->secfracPrecision - 1) % 6];
+ secfrac = ts->secfrac;
+ while(power > 0) {
+ digit = secfrac / power;
+ secfrac -= digit * power;
+ power /= 10;
+ pBuf[iBuf++] = digit + '0';
+ }
+ }
+
+ if(ts->OffsetMode == 'Z') {
+ pBuf[iBuf++] = 'Z';
+ } else {
+ pBuf[iBuf++] = ts->OffsetMode;
+ pBuf[iBuf++] = (ts->OffsetHour / 10) % 10 + '0';
+ pBuf[iBuf++] = ts->OffsetHour % 10 + '0';
+ pBuf[iBuf++] = ':';
+ pBuf[iBuf++] = (ts->OffsetMinute / 10) % 10 + '0';
+ pBuf[iBuf++] = ts->OffsetMinute % 10 + '0';
+ }
+
+ pBuf[iBuf] = '\0';
+
+ return iBuf;
+}
+
+/**
+ * Format a syslogTimestamp to a RFC3164 timestamp sring.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string termnator). If 0 is returend, an error occurred.
+ * rgerhards, 2010-03-05: Added support to for buggy 3164 dates,
+ * where a zero-digit is written instead of a space for the first
+ * day character if day < 10. syslog-ng seems to do that, and some
+ * parsing scripts (in migration cases) rely on that.
+ */
+static int
+formatTimestamp3164(struct syslogTime *ts, char* pBuf, int bBuggyDay)
+{
+ int iDay;
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ pBuf[0] = monthNames[(ts->month - 1)% 12][0];
+ pBuf[1] = monthNames[(ts->month - 1) % 12][1];
+ pBuf[2] = monthNames[(ts->month - 1) % 12][2];
+ pBuf[3] = ' ';
+ iDay = (ts->day / 10) % 10; /* we need to write a space if the first digit is 0 */
+ pBuf[4] = (bBuggyDay || iDay > 0) ? iDay + '0' : ' ';
+ pBuf[5] = ts->day % 10 + '0';
+ pBuf[6] = ' ';
+ pBuf[7] = (ts->hour / 10) % 10 + '0';
+ pBuf[8] = ts->hour % 10 + '0';
+ pBuf[9] = ':';
+ pBuf[10] = (ts->minute / 10) % 10 + '0';
+ pBuf[11] = ts->minute % 10 + '0';
+ pBuf[12] = ':';
+ pBuf[13] = (ts->second / 10) % 10 + '0';
+ pBuf[14] = ts->second % 10 + '0';
+ pBuf[15] = '\0';
+ return 16; /* traditional: number of bytes written */
+}
+
+
+/**
+ * convert syslog timestamp to time_t
+ * Note: it would be better to use something similar to mktime() here.
+ * Unfortunately, mktime() semantics are problematic: first of all, it
+ * works on local time, on the machine's time zone. In syslog, we have
+ * to deal with multiple time zones at once, so we cannot plainly rely
+ * on the local zone, and so we cannot rely on mktime(). One solution would
+ * be to refactor all time-related functions so that they are all guarded
+ * by a mutex to ensure TZ consistency (which would also enable us to
+ * change the TZ at will for specific function calls). But that would
+ * potentially mean a lot of overhead.
+ * Also, mktime() has some side effects, at least setting of tzname. With
+ * a refactoring as described above that should probably not be a problem,
+ * but would also need more work. For some more thoughts on this topic,
+ * have a look here:
+ * http://stackoverflow.com/questions/18355101/is-standard-c-mktime-thread-safe-on-linux
+ * In conclusion, we keep our own code for generating the unix timestamp.
+ * rgerhards, 2016-03-02
+ */
+static time_t
+syslogTime2time_t(const struct syslogTime *ts)
+{
+ long MonthInDays, NumberOfYears, NumberOfDays;
+ int utcOffset;
+ time_t TimeInUnixFormat;
+
+ if(ts->year < 1970 || ts->year > 2100) {
+ TimeInUnixFormat = 0;
+ LogError(0, RS_RET_ERR, "syslogTime2time_t: invalid year %d "
+ "in timestamp - returning 1970-01-01 instead", ts->year);
+ goto done;
+ }
+
+ /* Counting how many Days have passed since the 01.01 of the
+ * selected Year (Month level), according to the selected Month*/
+
+ switch(ts->month)
+ {
+ case 1:
+ MonthInDays = 0; //until 01 of January
+ break;
+ case 2:
+ MonthInDays = 31; //until 01 of February - leap year handling down below!
+ break;
+ case 3:
+ MonthInDays = 59; //until 01 of March
+ break;
+ case 4:
+ MonthInDays = 90; //until 01 of April
+ break;
+ case 5:
+ MonthInDays = 120; //until 01 of Mai
+ break;
+ case 6:
+ MonthInDays = 151; //until 01 of June
+ break;
+ case 7:
+ MonthInDays = 181; //until 01 of July
+ break;
+ case 8:
+ MonthInDays = 212; //until 01 of August
+ break;
+ case 9:
+ MonthInDays = 243; //until 01 of September
+ break;
+ case 10:
+ MonthInDays = 273; //until 01 of Oktober
+ break;
+ case 11:
+ MonthInDays = 304; //until 01 of November
+ break;
+ case 12:
+ MonthInDays = 334; //until 01 of December
+ break;
+ default: /* this cannot happen (and would be a program error)
+ * but we need the code to keep the compiler silent.
+ */
+ MonthInDays = 0; /* any value fits ;) */
+ break;
+ }
+ /* adjust for leap years */
+ if((ts->year % 100 != 0 && ts->year % 4 == 0) || (ts->year == 2000)) {
+ if(ts->month > 2)
+ MonthInDays++;
+ }
+
+
+ /* 1) Counting how many Years have passed since 1970
+ 2) Counting how many Days have passed since the 01.01 of the selected Year
+ (Day level) according to the Selected Month and Day. Last day doesn't count,
+ it should be until last day
+ 3) Calculating this period (NumberOfDays) in seconds*/
+
+ NumberOfYears = ts->year - yearInSec_startYear - 1;
+ NumberOfDays = MonthInDays + ts->day - 1;
+ TimeInUnixFormat = (time_t) (yearInSecs[NumberOfYears] + 1) + NumberOfDays * 86400;
+
+ /*Add Hours, minutes and seconds */
+ TimeInUnixFormat += ts->hour*60*60;
+ TimeInUnixFormat += ts->minute*60;
+ TimeInUnixFormat += ts->second;
+ /* do UTC offset */
+ utcOffset = ts->OffsetHour*3600 + ts->OffsetMinute*60;
+ if(ts->OffsetMode == '+')
+ utcOffset *= -1; /* if timestamp is ahead, we need to "go back" to UTC */
+ TimeInUnixFormat += utcOffset;
+done:
+ return TimeInUnixFormat;
+}
+
+
+/**
+ * format a timestamp as a UNIX timestamp; subsecond resolution is
+ * discarded.
+ * Note that this code can use some refactoring. I decided to use it
+ * because mktime() requires an upfront TZ update as it works on local
+ * time. In any case, it is worth reconsidering to move to mktime() or
+ * some other method.
+ * Important: pBuf must point to a buffer of at least 11 bytes.
+ * rgerhards, 2012-03-29
+ */
+static int
+formatTimestampUnix(struct syslogTime *ts, char *pBuf)
+{
+ snprintf(pBuf, 11, "%u", (unsigned) syslogTime2time_t(ts));
+ return 11;
+}
+
+/* 0 - Sunday, 1, Monday, ...
+ * Note that we cannot use strftime() and helpers as they rely on the TZ
+ * variable (again, arghhhh). So we need to do it ourselves...
+ * Note: in the year 2100, this algorithm does not work correctly (due to
+ * leap time rules. To fix it then (*IF* this code really still exists then),
+ * just use 2100 as new anchor year and adapt the initial day number.
+ */
+int getWeekdayNbr(struct syslogTime *ts)
+{
+ int wday;
+ int g, f;
+
+ g = ts->year;
+ if(ts->month < 3) {
+ g--;
+ f = ts->month + 13;
+ } else {
+ f = ts->month + 1;
+ }
+ wday = ((36525*g)/100) + ((306*f)/10) + ts->day - 621049;
+ wday %= 7;
+ return wday;
+}
+
+/* getOrdinal - 1-366 day of the year
+ * I've given little thought to leap seconds here.
+ */
+int getOrdinal(struct syslogTime *ts)
+{
+ int yday;
+ time_t thistime;
+ time_t previousyears;
+ int utcOffset;
+ time_t seconds_into_year;
+
+ if(ts->year < 1970 || ts->year > 2100) {
+ yday = 0;
+ LogError(0, RS_RET_ERR, "getOrdinal: invalid year %d "
+ "in timestamp - returning 1970-01-01 instead", ts->year);
+ goto done;
+ }
+
+ thistime = syslogTime2time_t(ts);
+
+ previousyears = (time_t) yearInSecs[ts->year - yearInSec_startYear - 1];
+
+ /* adjust previous years to match UTC offset */
+ utcOffset = ts->OffsetHour*3600 + ts->OffsetMinute*60;
+ if(ts->OffsetMode == '+')
+ utcOffset += -1; /* if timestamp is ahead, we need to "go back" to UTC */
+ previousyears += utcOffset;
+
+ /* subtract seconds from previous years */
+ seconds_into_year = thistime - previousyears;
+
+ /* divide by seconds in a day and truncate to int */
+ yday = seconds_into_year / 86400;
+done:
+ return yday;
+}
+
+/* getWeek - 1-52 week of the year */
+int getWeek(struct syslogTime *ts)
+{
+ int weekNum;
+ struct syslogTime yt;
+ int curDow;
+ int jan1Dow;
+ int curYearDay;
+
+ /* initialize a timestamp for january 1st of the current year */
+ yt.year = ts->year;
+ yt.month = 1;
+ yt.day = 1;
+ yt.hour = 0;
+ yt.minute = 0;
+ yt.second = 0;
+ yt.secfracPrecision = 0;
+ yt.secfrac = 0;
+ yt.OffsetMinute = ts->OffsetMinute;
+ yt.OffsetHour = ts->OffsetHour;
+ yt.OffsetMode = ts->OffsetMode;
+ yt.timeType = TIME_TYPE_RFC3164; /* low-res time */
+
+ /* get current day in year, current day of week
+ * and the day of week of 1/1 */
+ curYearDay = getOrdinal(ts);
+ curDow = getWeekdayNbr(ts);
+ jan1Dow = getWeekdayNbr(&yt);
+
+ /* calculate week of year for given date by pinning 1/1 as start
+ * of year, then going back and adjusting for the actual week day. */
+ weekNum = ((curYearDay + 6) / 7);
+ if (curDow < jan1Dow) {
+ ++weekNum;
+ }
+ return weekNum;
+}
+
+/* getISOWeek - 1-53 week of the year */
+int getISOWeek(struct syslogTime *ts, int *year)
+{
+ int weekNum;
+ int curDow;
+ int curYearDay;
+
+ /* get current day in year, current day of week
+ * and the day of week of 1/1 */
+ curYearDay = getOrdinal(ts);
+ curDow = getWeekdayNbr(ts);
+
+ /* map from 0 - Sunday, 1, Monday to 1, Monday, 7 - Sunday */
+ if (curDow == 0) {
+ curDow = 7;
+ }
+ /* make ordinal in range 1-366 */
+ curYearDay++;
+
+ weekNum = (10 + curYearDay - curDow) / 7;
+ *year = ts->year;
+ if (weekNum == 0) {
+ /* this is actually W52 or W53 of previous year */
+ weekNum = weeksInYear[ts->year - 1 - 1969];
+ *year = ts->year - 1;
+ } else if (weekNum > weeksInYear[ts->year - 1969]) {
+ /* this is actually W01 of next year */
+ weekNum = 1;
+ *year = ts->year + 1;
+ }
+
+ return weekNum;
+}
+
+void
+timeConvertToUTC(const struct syslogTime *const __restrict__ local,
+ struct syslogTime *const __restrict__ utc)
+{
+ struct timeval tp;
+ tp.tv_sec = syslogTime2time_t(local);
+ tp.tv_usec = local->secfrac;
+ timeval2syslogTime(&tp, utc, 1);
+}
+
+/**
+ * Format a UNIX timestamp.
+ */
+static int
+formatUnixTimeFromTime_t(time_t unixtime, const char *format, char *pBuf,
+ __attribute__((unused)) uint pBufMax) {
+
+ struct tm lt;
+
+ assert(format != NULL);
+ assert(pBuf != NULL);
+
+ // Convert to struct tm
+ if (gmtime_r(&unixtime, &lt) == NULL) {
+ DBGPRINTF("Unexpected error calling gmtime_r().\n");
+ return -1;
+ }
+
+ // Do our conversions
+ if (strcmp(format, "date-rfc3164") == 0) {
+ assert(pBufMax >= 16);
+
+ // Unlikely to run into this situation, but you never know...
+ if (lt.tm_mon < 0 || lt.tm_mon > 11) {
+ DBGPRINTF("lt.tm_mon is out of range. Value: %d\n", lt.tm_mon);
+ return -1;
+ }
+
+ // MMM dd HH:mm:ss
+ sprintf(pBuf, "%s %2d %.2d:%.2d:%.2d",
+ monthNames[lt.tm_mon], lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec
+ );
+ } else if (strcmp(format, "date-rfc3339") == 0) {
+ assert(pBufMax >= 26);
+
+ // YYYY-MM-DDTHH:mm:ss+00:00
+ sprintf(pBuf, "%d-%.2d-%.2dT%.2d:%.2d:%.2dZ",
+ lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec
+ );
+ }
+
+ return strlen(pBuf);
+}
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(datetime)
+CODESTARTobjQueryInterface(datetime)
+ if(pIf->ifVersion != datetimeCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->getCurrTime = getCurrTime;
+ pIf->GetTime = getTime;
+ pIf->timeval2syslogTime = timeval2syslogTime;
+ pIf->ParseTIMESTAMP3339 = ParseTIMESTAMP3339;
+ pIf->ParseTIMESTAMP3164 = ParseTIMESTAMP3164;
+ pIf->formatTimestampToMySQL = formatTimestampToMySQL;
+ pIf->formatTimestampToPgSQL = formatTimestampToPgSQL;
+ pIf->formatTimestampSecFrac = formatTimestampSecFrac;
+ pIf->formatTimestamp3339 = formatTimestamp3339;
+ pIf->formatTimestamp3164 = formatTimestamp3164;
+ pIf->formatTimestampUnix = formatTimestampUnix;
+ pIf->syslogTime2time_t = syslogTime2time_t;
+ pIf->formatUnixTimeFromTime_t = formatUnixTimeFromTime_t;
+finalize_it:
+ENDobjQueryInterface(datetime)
+
+
+/* Initialize the datetime class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(datetime, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ENDObjClassInit(datetime)
+
+/* vi:set ai:
+ */
diff --git a/runtime/datetime.h b/runtime/datetime.h
new file mode 100644
index 0000000..ee13e2b
--- /dev/null
+++ b/runtime/datetime.h
@@ -0,0 +1,100 @@
+/* The datetime object. Contains time-related functions.
+ *
+ * Copyright 2008-2015 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_DATETIME_H
+#define INCLUDED_DATETIME_H
+
+/* TODO: define error codes */
+#define NO_ERRCODE -1
+
+/* the datetime object */
+typedef struct datetime_s {
+ char dummy;
+} datetime_t;
+
+typedef enum {
+ DATE_INVALID = -1,
+ DATE_RFC3164 = 0,
+ DATE_RFC3339 = 1,
+ DATE_UNIX = 2,
+} dateTimeFormat_t;
+
+/* interfaces */
+BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */
+ void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds, const int inUTC);
+ rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS, int*);
+ rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int*, const int bParseTZ,
+ const int bDetectYearAfterTime);
+ int (*formatTimestampToMySQL)(struct syslogTime *ts, char* pDst);
+ int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst);
+ int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf);
+ int (*formatTimestamp3164)(struct syslogTime *ts, char* pBuf, int);
+ int (*formatTimestampSecFrac)(struct syslogTime *ts, char* pBuf);
+ /* v3, 2009-11-12 */
+ time_t (*GetTime)(time_t *ttSeconds);
+ /* v6, 2011-06-20 , v10, 2016-01-12*/
+ void (*timeval2syslogTime)(struct timeval *tp, struct syslogTime *t, const int inUTC);
+ /* v7, 2012-03-29 */
+ int (*formatTimestampUnix)(struct syslogTime *ts, char*pBuf);
+ time_t (*syslogTime2time_t)(const struct syslogTime *ts);
+ /* v11, 2017-10-05 */
+ int (*formatUnixTimeFromTime_t)(time_t time, const char *format, char *pBuf, uint pBufMax);
+ENDinterface(datetime)
+#define datetimeCURR_IF_VERSION 11 /* increment whenever you change the interface structure! */
+/* interface changes:
+ * 1 - initial version
+ * 2 - not compatible to 1 - bugfix required ParseTIMESTAMP3164 to accept char ** as
+ * last parameter. Did not try to remain compatible as this is not something any
+ * third-party module should call. -- rgerhards, 2008.-09-12
+ * 3 - taken by v5 branch!
+ * 4 - formatTimestamp3164 takes a third int parameter
+ * 5 - merge of versions 3 + 4 (2010-03-09)
+ * 6 - see above
+ * 8 - ParseTIMESTAMP3164 has addtl parameter to permit TZ string parsing
+ * 9 - ParseTIMESTAMP3164 has addtl parameter to permit year parsing
+ * 10 - functions having addtl paramater inUTC to emit time in UTC:
+ * timeval2syslogTime, getCurrtime
+ * 11 - Add formatUnixTimeFromTime_t
+ */
+
+#define PARSE3164_TZSTRING 1
+#define NO_PARSE3164_TZSTRING 0
+
+#define PERMIT_YEAR_AFTER_TIME 1
+#define NO_PERMIT_YEAR_AFTER_TIME 0
+
+/* two defines for functions that create timestamps either in local
+ * time or UTC.
+ */
+#define TIME_IN_UTC 1
+#define TIME_IN_LOCALTIME 0
+
+/* prototypes */
+PROTOTYPEObj(datetime);
+void applyDfltTZ(struct syslogTime *pTime, char *tz);
+int getWeekdayNbr(struct syslogTime *ts);
+int getOrdinal(struct syslogTime *ts);
+int getWeek(struct syslogTime *ts);
+int getISOWeek(struct syslogTime *ts, int *year);
+void timeConvertToUTC(const struct syslogTime *const __restrict__ local, struct syslogTime *const __restrict__ utc);
+time_t getTime(time_t *ttSeconds);
+dateTimeFormat_t getDateTimeFormatFromStr(const char * const __restrict__ s);
+
+#endif /* #ifndef INCLUDED_DATETIME_H */
diff --git a/runtime/debug.c b/runtime/debug.c
new file mode 100644
index 0000000..6e6c9fd
--- /dev/null
+++ b/runtime/debug.c
@@ -0,0 +1,478 @@
+/* debug.c
+ *
+ * This file proides debug support.
+ *
+ * File begun on 2008-01-22 by RGerhards
+ *
+ * Some functions are controlled by environment variables:
+ *
+ * RSYSLOG_DEBUGLOG if set, a debug log file is written to that location
+ * RSYSLOG_DEBUG specific debug options
+ *
+ * For details, visit doc/debug.html
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h" /* autotools! */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <pthread.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
+#endif
+#if _POSIX_TIMERS <= 0
+#include <sys/time.h>
+#endif
+
+#include "rsyslog.h"
+#include "debug.h"
+#include "cfsysline.h"
+#include "obj.h"
+
+
+/* static data (some time to be replaced) */
+DEFobjCurrIf(obj)
+int Debug = DEBUG_OFF; /* debug flag - read-only after startup */
+int debugging_on = 0; /* read-only, except on sig USR1 */
+int dbgTimeoutToStderr = 0;
+static int bPrintTime = 1; /* print a timestamp together with debug message */
+static int bOutputTidToStderr = 0;/* output TID to stderr on thread creation */
+char *pszAltDbgFileName = NULL; /* if set, debug output is *also* sent to here */
+int altdbg = -1; /* and the handle for alternate debug output */
+int stddbg = 1; /* the handle for regular debug output, set to stdout if not forking, -1 otherwise */
+static uint64_t dummy_errcount = 0; /* just to avoid some static analyzer complaints */
+static pthread_key_t keyThrdName;
+
+
+/* output the current thread ID to "relevant" places
+ * (what "relevant" means is determinded by various ways)
+ */
+void
+dbgOutputTID(char* name __attribute__((unused)))
+{
+# if defined(HAVE_SYSCALL) && defined(HAVE_SYS_gettid)
+ if(bOutputTidToStderr)
+ fprintf(stderr, "thread tid %u, name '%s'\n",
+ (unsigned)syscall(SYS_gettid), name);
+ DBGPRINTF("thread created, tid %u, name '%s'\n",
+ (unsigned)syscall(SYS_gettid), name);
+# endif
+}
+
+
+/* build a string with the thread name. If none is set, the thread ID is
+ * used instead. Caller must provide buffer space.
+ */
+static void ATTR_NONNULL()
+dbgGetThrdName(char *const pszBuf, const size_t lenBuf, const pthread_t thrdID)
+{
+ assert(pszBuf != NULL);
+
+ const char *const thrdName = pthread_getspecific(keyThrdName);
+ if(thrdName == NULL) {
+ snprintf(pszBuf, lenBuf, "%lx", (long) thrdID);
+ } else {
+ snprintf(pszBuf, lenBuf, "%-15s", thrdName);
+ }
+}
+
+
+/* set a name for the current thread */
+void ATTR_NONNULL()
+dbgSetThrdName(const uchar *const pszName)
+{
+ (void) pthread_setspecific(keyThrdName, strdup((char*) pszName));
+}
+
+
+/* destructor for thread name (called by pthreads!) */
+static void dbgThrdNameDestruct(void *arg)
+{
+ free(arg);
+}
+
+
+/* write the debug message. This is a helper to dbgprintf and dbgoprint which
+ * contains common code. added 2008-09-26 rgerhards
+ * Note: We need to split the function due to the bad nature of POSIX
+ * cancel cleanup handlers.
+ */
+static void DBGL_UNUSED
+dbgprint(obj_t *pObj, char *pszMsg, const char *pszFileName, const size_t lenMsg)
+{
+ uchar *pszObjName = NULL;
+ static pthread_t ptLastThrdID = 0;
+ static int bWasNL = 0;
+ char pszThrdName[64]; /* 64 is to be on the safe side, anything over 20 is bad... */
+ char pszWriteBuf[32*1024];
+ size_t lenCopy;
+ size_t offsWriteBuf = 0;
+ size_t lenWriteBuf;
+ struct timespec t;
+# if _POSIX_TIMERS <= 0
+ struct timeval tv;
+# endif
+
+ if(pObj != NULL) {
+ pszObjName = obj.GetName(pObj);
+ }
+
+ /* The bWasNL handler does not really work. It works if no thread
+ * switching occurs during non-NL messages. Else, things are messed
+ * up. Anyhow, it works well enough to provide useful help during
+ * getting this up and running. It is questionable if the extra effort
+ * is worth fixing it, giving the limited appliability. -- rgerhards, 2005-10-25
+ * I have decided that it is not worth fixing it - especially as it works
+ * pretty well. -- rgerhards, 2007-06-15
+ */
+ if(ptLastThrdID != pthread_self()) {
+ if(!bWasNL) {
+ pszWriteBuf[0] = '\n';
+ offsWriteBuf = 1;
+ bWasNL = 1;
+ }
+ ptLastThrdID = pthread_self();
+ }
+
+ dbgGetThrdName(pszThrdName, sizeof(pszThrdName), ptLastThrdID);
+
+ if(bWasNL) {
+ if(bPrintTime) {
+# if _POSIX_TIMERS > 0
+ /* this is the "regular" code */
+ clock_gettime(CLOCK_REALTIME, &t);
+# else
+ gettimeofday(&tv, NULL);
+ t.tv_sec = tv.tv_sec;
+ t.tv_nsec = tv.tv_usec * 1000;
+# endif
+ lenWriteBuf = snprintf(pszWriteBuf+offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf,
+ "%4.4ld.%9.9ld:", (long) (t.tv_sec % 10000), t.tv_nsec);
+ offsWriteBuf += lenWriteBuf;
+ }
+
+ lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf,
+ "%s: ", pszThrdName);
+ offsWriteBuf += lenWriteBuf;
+ /* print object name header if we have an object */
+ if(pszObjName != NULL) {
+ lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf,
+ "%s: ", pszObjName);
+ offsWriteBuf += lenWriteBuf;
+ }
+ lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf,
+ "%s: ", pszFileName);
+ offsWriteBuf += lenWriteBuf;
+ }
+ if(lenMsg > sizeof(pszWriteBuf) - offsWriteBuf)
+ lenCopy = sizeof(pszWriteBuf) - offsWriteBuf;
+ else
+ lenCopy = lenMsg;
+ memcpy(pszWriteBuf + offsWriteBuf, pszMsg, lenCopy);
+ offsWriteBuf += lenCopy;
+ /* the write is included in an "if" just to silence compiler
+ * warnings. Here, we really don't care if the write fails, we
+ * have no good response to that in any case... -- rgerhards, 2012-11-28
+ */
+ if(stddbg != -1) {
+ if(write(stddbg, pszWriteBuf, offsWriteBuf)) {
+ ++dummy_errcount;
+ }
+ }
+ if(altdbg != -1) {
+ if(write(altdbg, pszWriteBuf, offsWriteBuf)) {
+ ++dummy_errcount;
+ }
+ }
+
+ bWasNL = (pszMsg[lenMsg - 1] == '\n') ? 1 : 0;
+}
+
+
+static int DBGL_UNUSED
+checkDbgFile(const char *srcname)
+{
+ if(glblDbgFilesNum == 0) {
+ return 1;
+ }
+ if(glblDbgWhitelist) {
+ if(bsearch(srcname, glblDbgFiles, glblDbgFilesNum, sizeof(char*), bs_arrcmp_glblDbgFiles) == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ if(bsearch(srcname, glblDbgFiles, glblDbgFilesNum, sizeof(char*), bs_arrcmp_glblDbgFiles) != NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+}
+/* print some debug output when an object is given
+ * This is mostly a copy of dbgprintf, but I do not know how to combine it
+ * into a single function as we have variable arguments and I don't know how to call
+ * from one vararg function into another. I don't dig in this, it is OK for the
+ * time being. -- rgerhards, 2008-01-29
+ */
+#ifndef DEBUGLESS
+void
+r_dbgoprint( const char *srcname, obj_t *pObj, const char *fmt, ...)
+{
+ va_list ap;
+ char pszWriteBuf[32*1024];
+ size_t lenWriteBuf;
+
+ if(!(Debug && debugging_on))
+ return;
+
+ if(!checkDbgFile(srcname)) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
+ va_end(ap);
+ if(lenWriteBuf >= sizeof(pszWriteBuf)) {
+ /* prevent buffer overrruns and garbagge display */
+ pszWriteBuf[sizeof(pszWriteBuf) - 5] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 4] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 3] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 2] = '\n';
+ pszWriteBuf[sizeof(pszWriteBuf) - 1] = '\0';
+ lenWriteBuf = sizeof(pszWriteBuf);
+ }
+ dbgprint(pObj, pszWriteBuf, srcname, lenWriteBuf);
+}
+#endif
+
+/* print some debug output when no object is given
+ * WARNING: duplicate code, see dbgoprint above!
+ */
+#ifndef DEBUGLESS
+void
+r_dbgprintf(const char *srcname, const char *fmt, ...)
+{
+ va_list ap;
+ char pszWriteBuf[32*1024];
+ size_t lenWriteBuf;
+
+ if(!(Debug && debugging_on)) {
+ return;
+ }
+
+ if(!checkDbgFile(srcname)) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
+ va_end(ap);
+ if(lenWriteBuf >= sizeof(pszWriteBuf)) {
+ /* prevent buffer overrruns and garbagge display */
+ pszWriteBuf[sizeof(pszWriteBuf) - 5] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 4] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 3] = '.';
+ pszWriteBuf[sizeof(pszWriteBuf) - 2] = '\n';
+ pszWriteBuf[sizeof(pszWriteBuf) - 1] = '\0';
+ lenWriteBuf = sizeof(pszWriteBuf);
+ }
+ dbgprint(NULL, pszWriteBuf, srcname, lenWriteBuf);
+}
+#endif
+
+/* support system to set debug options at runtime */
+
+
+/* parse a param/value pair from the current location of the
+ * option string. Returns 1 if an option was found, 0
+ * otherwise. 0 means there are NO MORE options to be
+ * processed. -- rgerhards, 2008-02-28
+ */
+static int ATTR_NONNULL()
+dbgGetRTOptNamVal(const uchar **const ppszOpt, uchar **const ppOptName)
+{
+ assert(ppszOpt != NULL);
+ assert(*ppszOpt != NULL);
+ int bRet = 0;
+ const uchar *p = *ppszOpt;
+ size_t i;
+ static uchar optname[128] = "";
+
+ /* skip whitespace */
+ while(*p && isspace(*p))
+ ++p;
+
+ /* name: up until whitespace */
+ i = 0;
+ while(i < (sizeof(optname) - 1) && *p && !isspace(*p)) {
+ optname[i++] = *p++;
+ }
+
+ if(i > 0) {
+ bRet = 1;
+ optname[i] = '\0';
+ }
+
+ /* done */
+ *ppszOpt = p;
+ *ppOptName = optname;
+ return bRet;
+}
+
+
+/* report fd used for debug log. This is needed in case of
+ * auto-backgrounding, where the debug log shall not be closed.
+ */
+int
+dbgGetDbglogFd(void)
+{
+ return altdbg;
+}
+
+/* read in the runtime options
+ * rgerhards, 2008-02-28
+ */
+static void
+dbgGetRuntimeOptions(void)
+{
+ const uchar *pszOpts;
+ uchar *optname;
+
+ /* set some defaults */
+ if((pszOpts = (uchar*) getenv("RSYSLOG_DEBUG")) != NULL) {
+ /* we have options set, so let's process them */
+ while(dbgGetRTOptNamVal(&pszOpts, &optname)) {
+ if(!strcasecmp((char*)optname, "help")) {
+ fprintf(stderr,
+ "rsyslogd " VERSION " runtime debug support - help requested, "
+ "rsyslog terminates\n\nenvironment variables:\n"
+ "additional logfile: export RSYSLOG_DEBUGFILE=\"/path/to/file\"\n"
+ "to set: export RSYSLOG_DEBUG=\"cmd cmd cmd\"\n\n"
+ "Commands are (all case-insensitive):\n"
+ "help (this list, terminates rsyslogd)\n"
+ "NoLogTimestamp\n"
+ "Nostdout\n"
+ "OutputTidToStderr\n"
+ "DebugOnDemand - enables debugging on USR1, but does not turn on output\n"
+ "\nSee debug.html in your doc set or https://www.rsyslog.com for details\n");
+ exit(1);
+ } else if(!strcasecmp((char*)optname, "debug")) {
+ /* this is earlier in the process than the -d option, as such it
+ * allows us to spit out debug messages from the very beginning.
+ */
+ Debug = DEBUG_FULL;
+ debugging_on = 1;
+ } else if(!strcasecmp((char*)optname, "debugondemand")) {
+ /* Enables debugging, but turns off debug output */
+ Debug = DEBUG_ONDEMAND;
+ debugging_on = 1;
+ dbgprintf("Note: debug on demand turned on via configuration file, "
+ "use USR1 signal to activate.\n");
+ debugging_on = 0;
+ } else if(!strcasecmp((char*)optname, "nologtimestamp")) {
+ bPrintTime = 0;
+ } else if(!strcasecmp((char*)optname, "nostdout")) {
+ stddbg = -1;
+ } else if(!strcasecmp((char*)optname, "outputtidtostderr")) {
+ bOutputTidToStderr = 1;
+ } else {
+ fprintf(stderr, "rsyslogd " VERSION " error: invalid debug option '%s' "
+ "- ignored\n", optname);
+ }
+ }
+ }
+}
+
+
+void
+dbgSetDebugLevel(int level)
+{
+ Debug = level;
+ debugging_on = (level == DEBUG_FULL) ? 1 : 0;
+}
+
+void
+dbgSetDebugFile(uchar *fn)
+{
+ if(altdbg != -1) {
+ dbgprintf("switching to debug file %s\n", fn);
+ close(altdbg);
+ }
+ if((altdbg = open((char*)fn, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, S_IRUSR|S_IWUSR)) == -1) {
+ fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n", strerror(errno));
+ }
+}
+
+/* end support system to set debug options at runtime */
+
+rsRetVal dbgClassInit(void)
+{
+ rsRetVal iRet; /* do not use DEFiRet, as this makes calls into the debug system! */
+
+
+ (void) pthread_key_create(&keyThrdName, dbgThrdNameDestruct);
+
+ /* while we try not to use any of the real rsyslog code (to avoid infinite loops), we
+ * need to have the ability to query object names. Thus, we need to obtain a pointer to
+ * the object interface. -- rgerhards, 2008-02-29
+ */
+ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
+
+ const char *dbgto2stderr;
+ dbgto2stderr = getenv("RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR");
+ dbgTimeoutToStderr = (dbgto2stderr != NULL && !strcmp(dbgto2stderr, "on")) ? 1 : 0;
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslogd: NOTE: RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR activated\n");
+ }
+ dbgGetRuntimeOptions(); /* init debug system from environment */
+ pszAltDbgFileName = getenv("RSYSLOG_DEBUGLOG");
+
+ if(pszAltDbgFileName != NULL) {
+ /* we have a secondary file, so let's open it) */
+ if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, S_IRUSR|S_IWUSR))
+ == -1) {
+ fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n",
+ strerror(errno));
+ }
+ }
+
+ dbgSetThrdName((uchar*)"main thread");
+
+finalize_it:
+ return(iRet);
+}
+
+
+rsRetVal dbgClassExit(void)
+{
+ pthread_key_delete(keyThrdName);
+ if(altdbg != -1)
+ close(altdbg);
+ return RS_RET_OK;
+}
diff --git a/runtime/debug.h b/runtime/debug.h
new file mode 100644
index 0000000..13c93cb
--- /dev/null
+++ b/runtime/debug.h
@@ -0,0 +1,78 @@
+/* debug.h
+ *
+ * Definitions for the debug module.
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DEBUG_H_INCLUDED
+#define DEBUG_H_INCLUDED
+
+#include <pthread.h>
+#include "obj-types.h"
+
+/* some settings for various debug modes */
+#define DEBUG_OFF 0
+#define DEBUG_ONDEMAND 1
+#define DEBUG_FULL 2
+
+/* external static data elements (some time to be replaced) */
+extern int Debug; /* debug flag - read-only after startup */
+extern int debugging_on; /* read-only, except on sig USR1 */
+extern int stddbg; /* the handle for regular debug output, set to stdout if not forking, -1 otherwise */
+extern int dbgTimeoutToStderr;
+
+
+/* prototypes */
+rsRetVal dbgClassInit(void);
+rsRetVal dbgClassExit(void);
+void dbgSetDebugFile(uchar *fn);
+void dbgSetDebugLevel(int level);
+void dbgSetThrdName(const uchar *pszName);
+void dbgOutputTID(char* name);
+int dbgGetDbglogFd(void);
+
+/* external data */
+extern char *pszAltDbgFileName; /* if set, debug output is *also* sent to here */
+extern int altdbg; /* and the handle for alternate debug output */
+
+/* macros */
+#ifdef DEBUGLESS
+# define DBGL_UNUSED __attribute__((__unused__))
+ static inline void r_dbgoprint(const char DBGL_UNUSED *srcname, obj_t DBGL_UNUSED *pObj,
+ const char DBGL_UNUSED *fmt, ...) {}
+ static inline void r_dbgprintf(const char DBGL_UNUSED *srcname, const char DBGL_UNUSED *fmt, ...) {}
+#else
+# define DBGL_UNUSED
+ void r_dbgoprint(const char *srcname, obj_t *pObj, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
+ void r_dbgprintf(const char *srcname, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+#endif
+
+#define DBGPRINTF(...) if(Debug) { r_dbgprintf(__FILE__, __VA_ARGS__); }
+#define DBGOPRINT(...) if(Debug) { r_dbgoprint(__FILE__, __VA_ARGS__); }
+#define dbgprintf(...) r_dbgprintf(__FILE__, __VA_ARGS__)
+#define dbgoprint(...) r_dbgoprint(__FILE__, __VA_ARGS__)
+
+/* things originally introduced for now removed rtinst */
+#define d_pthread_mutex_lock(x) pthread_mutex_lock(x)
+#define d_pthread_mutex_trylock(x) pthread_mutex_trylock(x)
+#define d_pthread_mutex_unlock(x) pthread_mutex_unlock(x)
+#define d_pthread_cond_wait(cond, mut) pthread_cond_wait(cond, mut)
+#define d_pthread_cond_timedwait(cond, mut, to) pthread_cond_timedwait(cond, mut, to)
+
+#endif /* #ifndef DEBUG_H_INCLUDED */
diff --git a/runtime/dnscache.c b/runtime/dnscache.c
new file mode 100644
index 0000000..7dd0aab
--- /dev/null
+++ b/runtime/dnscache.c
@@ -0,0 +1,472 @@
+/* dnscache.c
+ * Implementation of a real DNS cache
+ *
+ * File begun on 2011-06-06 by RGerhards
+ * The initial implementation is far from being optimal. The idea is to
+ * first get somethting that'S functionally OK, and then evolve the algorithm.
+ * In any case, even the initial implementaton is far faster than what we had
+ * before. -- rgerhards, 2011-06-06
+ *
+ * Copyright 2011-2019 by Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "syslogd-types.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "obj.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "hashtable.h"
+#include "prop.h"
+#include "dnscache.h"
+#include "rsconf.h"
+
+/* module data structures */
+struct dnscache_entry_s {
+ struct sockaddr_storage addr;
+ prop_t *fqdn;
+ prop_t *fqdnLowerCase;
+ prop_t *localName; /* only local name, without domain part (if configured so) */
+ prop_t *ip;
+ time_t validUntil;
+ struct dnscache_entry_s *next;
+ unsigned nUsed;
+};
+typedef struct dnscache_entry_s dnscache_entry_t;
+struct dnscache_s {
+ pthread_rwlock_t rwlock;
+ struct hashtable *ht;
+ unsigned nEntries;
+};
+typedef struct dnscache_s dnscache_t;
+
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+static dnscache_t dnsCache;
+static prop_t *staticErrValue;
+
+
+/* Our hash function.
+ */
+static unsigned int
+hash_from_key_fn(void *k)
+{
+ int len = 0;
+ uchar *rkey; /* we treat this as opaque bytes */
+ unsigned hashval = 1;
+
+ switch (((struct sockaddr *)k)->sa_family) {
+ case AF_INET:
+ len = sizeof (struct in_addr);
+ rkey = (uchar*) &(((struct sockaddr_in *)k)->sin_addr);
+ break;
+ case AF_INET6:
+ len = sizeof (struct in6_addr);
+ rkey = (uchar*) &(((struct sockaddr_in6 *)k)->sin6_addr);
+ break;
+ default:
+ dbgprintf("hash_from_key_fn: unknown address family!\n");
+ len = 0;
+ rkey = NULL;
+ }
+ while(len--)
+ hashval = hashval * 33 + *rkey++;
+
+ return hashval;
+}
+
+
+static int
+key_equals_fn(void *key1, void *key2)
+{
+ int RetVal = 0;
+
+ if(((struct sockaddr *)key1)->sa_family != ((struct sockaddr *)key2)->sa_family) {
+ return 0;
+ }
+ switch (((struct sockaddr *)key1)->sa_family) {
+ case AF_INET:
+ RetVal = !memcmp(&((struct sockaddr_in *)key1)->sin_addr,
+ &((struct sockaddr_in *)key2)->sin_addr, sizeof (struct in_addr));
+ break;
+ case AF_INET6:
+ RetVal = !memcmp(&((struct sockaddr_in6 *)key1)->sin6_addr,
+ &((struct sockaddr_in6 *)key2)->sin6_addr, sizeof (struct in6_addr));
+ break;
+ }
+
+ return RetVal;
+}
+
+/* destruct a cache entry.
+ * Precondition: entry must already be unlinked from list
+ */
+static void ATTR_NONNULL()
+entryDestruct(dnscache_entry_t *const etry)
+{
+ if(etry->fqdn != NULL)
+ prop.Destruct(&etry->fqdn);
+ if(etry->fqdnLowerCase != NULL)
+ prop.Destruct(&etry->fqdnLowerCase);
+ if(etry->localName != NULL)
+ prop.Destruct(&etry->localName);
+ if(etry->ip != NULL)
+ prop.Destruct(&etry->ip);
+ free(etry);
+}
+
+/* init function (must be called once) */
+rsRetVal
+dnscacheInit(void)
+{
+ DEFiRet;
+ if((dnsCache.ht = create_hashtable(100, hash_from_key_fn, key_equals_fn,
+ (void(*)(void*))entryDestruct)) == NULL) {
+ DBGPRINTF("dnscache: error creating hash table!\n");
+ ABORT_FINALIZE(RS_RET_ERR); // TODO: make this degrade, but run!
+ }
+ dnsCache.nEntries = 0;
+ pthread_rwlock_init(&dnsCache.rwlock, NULL);
+ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ prop.Construct(&staticErrValue);
+ prop.SetString(staticErrValue, (uchar*)"???", 3);
+ prop.ConstructFinalize(staticErrValue);
+finalize_it:
+ RETiRet;
+}
+
+/* deinit function (must be called once) */
+rsRetVal
+dnscacheDeinit(void)
+{
+ DEFiRet;
+ prop.Destruct(&staticErrValue);
+ hashtable_destroy(dnsCache.ht, 1); /* 1 => free all values automatically */
+ pthread_rwlock_destroy(&dnsCache.rwlock);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ RETiRet;
+}
+
+
+/* This is a cancel-safe getnameinfo() version, because we learned
+ * (via drd/valgrind) that getnameinfo() seems to have some issues
+ * when being cancelled, at least if the module was dlloaded.
+ * rgerhards, 2008-09-30
+ */
+static int
+mygetnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ int iCancelStateSave;
+ int i;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ i = getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ pthread_setcancelstate(iCancelStateSave, NULL);
+ return i;
+}
+
+
+/* get only the local part of the hostname and set it in cache entry */
+static void
+setLocalHostName(dnscache_entry_t *etry)
+{
+ uchar *fqdnLower;
+ uchar *p;
+ int i;
+ uchar hostbuf[NI_MAXHOST];
+
+ if(glbl.GetPreserveFQDN()) {
+ prop.AddRef(etry->fqdnLowerCase);
+ etry->localName = etry->fqdnLowerCase;
+ goto done;
+ }
+
+ /* strip domain, if configured for this entry */
+ fqdnLower = propGetSzStr(etry->fqdnLowerCase);
+ p = (uchar*)strchr((char*)fqdnLower, '.'); /* find start of domain name "machine.example.com" */
+ if(p == NULL) { /* do we have a domain part? */
+ prop.AddRef(etry->fqdnLowerCase); /* no! */
+ etry->localName = etry->fqdnLowerCase;
+ goto done;
+ }
+
+ i = p - fqdnLower; /* length of hostname */
+ memcpy(hostbuf, fqdnLower, i);
+ hostbuf[i] = '\0';
+
+ /* at this point, we have not found anything, so we again use the
+ * already-created complete full name property.
+ */
+ prop.AddRef(etry->fqdnLowerCase);
+ etry->localName = etry->fqdnLowerCase;
+done: return;
+}
+
+
+/* resolve an address.
+ *
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. We do by default not
+ * discard message where we detected malicouos DNS PTR records. However,
+ * there is a user-configurabel option that will tell us if
+ * we should abort. For this, the return value tells the caller if the
+ * message should be processed (1) or discarded (0).
+ */
+static rsRetVal ATTR_NONNULL()
+resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry)
+{
+ DEFiRet;
+ int error;
+ sigset_t omask, nmask;
+ struct addrinfo hints, *res;
+ char szIP[80]; /* large enough for IPv6 */
+ char fqdnBuf[NI_MAXHOST];
+ rs_size_t fqdnLen;
+ rs_size_t i;
+
+ error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *)addr),
+ (char*) szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST);
+ if(error) {
+ dbgprintf("Malformed from address %s\n", gai_strerror(error));
+ ABORT_FINALIZE(RS_RET_INVALID_SOURCE);
+ }
+
+ if(!glbl.GetDisableDNS(runConf)) {
+ sigemptyset(&nmask);
+ sigaddset(&nmask, SIGHUP);
+ pthread_sigmask(SIG_BLOCK, &nmask, &omask);
+
+ error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *) addr),
+ fqdnBuf, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+
+ if(error == 0) {
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+
+ /* we now do a lookup once again. This one should fail,
+ * because we should not have obtained a non-numeric address. If
+ * we got a numeric one, someone messed with DNS!
+ */
+ if(getaddrinfo (fqdnBuf, NULL, &hints, &res) == 0) {
+ freeaddrinfo (res);
+ /* OK, we know we have evil. The question now is what to do about
+ * it. One the one hand, the message might probably be intended
+ * to harm us. On the other hand, losing the message may also harm us.
+ * Thus, the behaviour is controlled by the $DropMsgsWithMaliciousDnsPTRRecords
+ * option. If it tells us we should discard, we do so, else we proceed,
+ * but log an error message together with it.
+ * time being, we simply drop the name we obtained and use the IP - that one
+ * is OK in any way. We do also log the error message. rgerhards, 2007-07-16
+ */
+ if(glbl.GetDropMalPTRMsgs(runConf) == 1) {
+ LogError(0, RS_RET_MALICIOUS_ENTITY,
+ "Malicious PTR record, message dropped "
+ "IP = \"%s\" HOST = \"%s\"",
+ szIP, fqdnBuf);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
+ ABORT_FINALIZE(RS_RET_MALICIOUS_ENTITY);
+ }
+
+ /* Please note: we deal with a malicous entry. Thus, we have crafted
+ * the snprintf() below so that all text is in front of the entry - maybe
+ * it contains characters that make the message unreadable
+ * (OK, I admit this is more or less impossible, but I am paranoid...)
+ * rgerhards, 2007-07-16
+ */
+ LogError(0, NO_ERRCODE,
+ "Malicious PTR record (message accepted, but used IP "
+ "instead of PTR name: IP = \"%s\" HOST = \"%s\"",
+ szIP, fqdnBuf);
+
+ error = 1; /* that will trigger using IP address below. */
+ } else {/* we have a valid entry, so let's create the respective properties */
+ fqdnLen = strlen(fqdnBuf);
+ prop.CreateStringProp(&etry->fqdn, (uchar*)fqdnBuf, fqdnLen);
+ for(i = 0 ; i < fqdnLen ; ++i)
+ fqdnBuf[i] = tolower(fqdnBuf[i]);
+ prop.CreateStringProp(&etry->fqdnLowerCase, (uchar*)fqdnBuf, fqdnLen);
+ }
+ }
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
+ }
+
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ strcpy(szIP, "?error.obtaining.ip?");
+ error = 1; /* trigger hostname copies below! */
+ }
+
+ prop.CreateStringProp(&etry->ip, (uchar*)szIP, strlen(szIP));
+
+ if(error || glbl.GetDisableDNS(runConf)) {
+ dbgprintf("Host name for your address (%s) unknown\n", szIP);
+ prop.AddRef(etry->ip);
+ etry->fqdn = etry->ip;
+ prop.AddRef(etry->ip);
+ etry->fqdnLowerCase = etry->ip;
+ }
+
+ setLocalHostName(etry);
+
+ RETiRet;
+}
+
+
+static rsRetVal ATTR_NONNULL()
+addEntry(struct sockaddr_storage *const addr, dnscache_entry_t **const pEtry)
+{
+ int r;
+ dnscache_entry_t *etry = NULL;
+ DEFiRet;
+
+ /* entry still does not exist, so add it */
+ struct sockaddr_storage *const keybuf = malloc(sizeof(struct sockaddr_storage));
+ CHKmalloc(keybuf);
+ CHKmalloc(etry = malloc(sizeof(dnscache_entry_t)));
+ resolveAddr(addr, etry);
+ assert(etry != NULL);
+ memcpy(&etry->addr, addr, SALEN((struct sockaddr*) addr));
+ etry->nUsed = 0;
+ if(runConf->globals.dnscacheEnableTTL) {
+ etry->validUntil = time(NULL) + runConf->globals.dnscacheDefaultTTL;
+ }
+
+ memcpy(keybuf, addr, sizeof(struct sockaddr_storage));
+
+ r = hashtable_insert(dnsCache.ht, keybuf, etry);
+ if(r == 0) {
+ DBGPRINTF("dnscache: inserting element failed\n");
+ }
+ *pEtry = etry;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(keybuf);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal ATTR_NONNULL(1, 5)
+findEntry(struct sockaddr_storage *const addr,
+ prop_t **const fqdn, prop_t **const fqdnLowerCase,
+ prop_t **const localName, prop_t **const ip)
+{
+ DEFiRet;
+
+ pthread_rwlock_rdlock(&dnsCache.rwlock);
+ dnscache_entry_t * etry = hashtable_search(dnsCache.ht, addr);
+ DBGPRINTF("findEntry: 1st lookup found %p\n", etry);
+
+ if(etry == NULL || (runConf->globals.dnscacheEnableTTL && (etry->validUntil <= time(NULL)))) {
+ pthread_rwlock_unlock(&dnsCache.rwlock);
+ pthread_rwlock_wrlock(&dnsCache.rwlock);
+ etry = hashtable_search(dnsCache.ht, addr); /* re-query, might have changed */
+ DBGPRINTF("findEntry: 2nd lookup found %p\n", etry);
+ if(etry == NULL || (runConf->globals.dnscacheEnableTTL && (etry->validUntil <= time(NULL)))) {
+ if(etry != NULL) {
+ DBGPRINTF("hashtable: entry timed out, discarding it; "
+ "valid until %lld, now %lld\n",
+ (long long) etry->validUntil, (long long) time(NULL));
+ dnscache_entry_t *const deleted = hashtable_remove(dnsCache.ht, addr);
+ if(deleted != etry) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "dnscache %d: removed different "
+ "hashtable entry than expected - please report issue; "
+ "rsyslog version is %s", __LINE__, VERSION);
+ }
+ entryDestruct(etry);
+ }
+ /* now entry doesn't exist in any case, so let's (re)create it */
+ CHKiRet(addEntry(addr, &etry));
+ }
+ }
+
+ prop.AddRef(etry->ip);
+ *ip = etry->ip;
+ if(fqdn != NULL) {
+ prop.AddRef(etry->fqdn);
+ *fqdn = etry->fqdn;
+ }
+ if(fqdnLowerCase != NULL) {
+ prop.AddRef(etry->fqdnLowerCase);
+ *fqdnLowerCase = etry->fqdnLowerCase;
+ }
+ if(localName != NULL) {
+ prop.AddRef(etry->localName);
+ *localName = etry->localName;
+ }
+
+finalize_it:
+ pthread_rwlock_unlock(&dnsCache.rwlock);
+ RETiRet;
+}
+
+
+/* This is the main function: it looks up an entry and returns it's name
+ * and IP address. If the entry is not yet inside the cache, it is added.
+ * If the entry can not be resolved, an error is reported back. If fqdn
+ * or fqdnLowerCase are NULL, they are not set.
+ */
+rsRetVal ATTR_NONNULL(1, 5)
+dnscacheLookup(struct sockaddr_storage *const addr,
+ prop_t **const fqdn, prop_t **const fqdnLowerCase,
+ prop_t **const localName, prop_t **const ip)
+{
+ DEFiRet;
+
+ iRet = findEntry(addr, fqdn, fqdnLowerCase, localName, ip);
+
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("dnscacheLookup failed with iRet %d\n", iRet);
+ prop.AddRef(staticErrValue);
+ *ip = staticErrValue;
+ if(fqdn != NULL) {
+ prop.AddRef(staticErrValue);
+ *fqdn = staticErrValue;
+ }
+ if(fqdnLowerCase != NULL) {
+ prop.AddRef(staticErrValue);
+ *fqdnLowerCase = staticErrValue;
+ }
+ if(localName != NULL) {
+ prop.AddRef(staticErrValue);
+ *localName = staticErrValue;
+ }
+ }
+ RETiRet;
+}
diff --git a/runtime/dnscache.h b/runtime/dnscache.h
new file mode 100644
index 0000000..0ec1dbc
--- /dev/null
+++ b/runtime/dnscache.h
@@ -0,0 +1,31 @@
+/* Definitions for dnscache module.
+ *
+ * Copyright 2011-2019 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_DNSCACHE_H
+#define INCLUDED_DNSCACHE_H
+
+rsRetVal dnscacheInit(void);
+rsRetVal dnscacheDeinit(void);
+rsRetVal ATTR_NONNULL(1, 5) dnscacheLookup(struct sockaddr_storage *const addr,
+ prop_t **const fqdn, prop_t **const fqdnLowerCase,
+ prop_t **const localName, prop_t **const ip);
+
+#endif /* #ifndef INCLUDED_DNSCACHE_H */
diff --git a/runtime/dynstats.c b/runtime/dynstats.c
new file mode 100644
index 0000000..1bdba57
--- /dev/null
+++ b/runtime/dynstats.c
@@ -0,0 +1,622 @@
+/*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "rsconf.h"
+#include "unicode-helper.h"
+
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(statsobj)
+
+#define DYNSTATS_PARAM_NAME "name"
+#define DYNSTATS_PARAM_RESETTABLE "resettable"
+#define DYNSTATS_PARAM_MAX_CARDINALITY "maxCardinality"
+#define DYNSTATS_PARAM_UNUSED_METRIC_LIFE "unusedMetricLife" /* in seconds */
+
+#define DYNSTATS_DEFAULT_RESETTABILITY 1
+#define DYNSTATS_DEFAULT_MAX_CARDINALITY 2000
+#define DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE 3600 /* seconds */
+
+#define DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH 100
+#define DYNSTATS_METRIC_NAME_SEPARATOR '.'
+#define DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING 1.25
+
+static struct cnfparamdescr modpdescr[] = {
+ { DYNSTATS_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED },
+ { DYNSTATS_PARAM_RESETTABLE, eCmdHdlrBinary, 0 },
+ { DYNSTATS_PARAM_MAX_CARDINALITY, eCmdHdlrPositiveInt, 0},
+ { DYNSTATS_PARAM_UNUSED_METRIC_LIFE, eCmdHdlrPositiveInt, 0} /* in minutes */
+};
+
+static struct cnfparamblk modpblk =
+{
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+rsRetVal
+dynstatsClassInit(void) {
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+finalize_it:
+ RETiRet;
+}
+
+static void
+dynstats_destroyCtr(dynstats_ctr_t *ctr) {
+ statsobj.DestructUnlinkedCounter(ctr->pCtr);
+ free(ctr->metric);
+ free(ctr);
+}
+
+static void /* assumes exclusive access to bucket */
+dynstats_destroyCountersIn(dynstats_bucket_t *b, htable *table, dynstats_ctr_t *ctrs) {
+ dynstats_ctr_t *ctr;
+ int ctrs_purged = 0;
+ hashtable_destroy(table, 0);
+ while (ctrs != NULL) {
+ ctr = ctrs;
+ ctrs = ctrs->next;
+ dynstats_destroyCtr(ctr);
+ ctrs_purged++;
+ }
+ STATSCOUNTER_ADD(b->ctrMetricsPurged, b->mutCtrMetricsPurged, ctrs_purged);
+ ATOMIC_SUB_unsigned(&b->metricCount, ctrs_purged, &b->mutMetricCount);
+}
+
+static void /* assumes exclusive access to bucket */
+dynstats_destroyCounters(dynstats_bucket_t *b) {
+ statsobj.UnlinkAllCounters(b->stats);
+ dynstats_destroyCountersIn(b, b->table, b->ctrs);
+}
+
+static void
+dynstats_destroyBucket(dynstats_buckets_t *bkts, dynstats_bucket_t* b) {
+ pthread_rwlock_wrlock(&b->lock);
+ dynstats_destroyCounters(b);
+ dynstats_destroyCountersIn(b, b->survivor_table, b->survivor_ctrs);
+ statsobj.Destruct(&b->stats);
+ free(b->name);
+ pthread_rwlock_unlock(&b->lock);
+ pthread_rwlock_destroy(&b->lock);
+ pthread_mutex_destroy(&b->mutMetricCount);
+ statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
+ statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
+ statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
+ statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
+ statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
+ statsobj.DestructCounter(bkts->global_stats, b->pPurgeTriggeredCtr);
+ free(b);
+}
+
+static rsRetVal
+dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar* name) {
+ uchar *metric_name_buff, *metric_suffix;
+ const uchar *suffix_litteral;
+ int name_len;
+ DEFiRet;
+
+ name_len = ustrlen(name);
+ CHKmalloc(metric_name_buff = malloc((name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar)));
+
+ strcpy((char*)metric_name_buff, (char*)name);
+ metric_suffix = metric_name_buff + name_len;
+ *metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR;
+ metric_suffix++;
+
+ suffix_litteral = UCHAR_CONSTANT("ops_overflow");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrOpsOverflow),
+ &b->pOpsOverflowCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("new_metric_add");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrNewMetricAdd),
+ &b->pNewMetricAddCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("no_metric");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrNoMetric),
+ &b->pNoMetricCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("metrics_purged");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrMetricsPurged),
+ &b->pMetricsPurgedCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("ops_ignored");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrOpsIgnored),
+ &b->pOpsIgnoredCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("purge_triggered");
+ ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrPurgeTriggered),
+ &b->pPurgeTriggeredCtr, 1));
+
+finalize_it:
+ free(metric_name_buff);
+ if (iRet != RS_RET_OK) {
+ if (b->pOpsOverflowCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
+ }
+ if (b->pNewMetricAddCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr);
+ }
+ if (b->pNoMetricCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr);
+ }
+ if (b->pMetricsPurgedCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr);
+ }
+ if (b->pOpsIgnoredCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr);
+ }
+ if (b->pPurgeTriggeredCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pPurgeTriggeredCtr);
+ }
+ }
+ RETiRet;
+}
+
+static void
+no_op_free(void __attribute__((unused)) *ignore) {}
+
+static rsRetVal /* assumes exclusive access to bucket */
+dynstats_rebuildSurvivorTable(dynstats_bucket_t *b) {
+ htable *survivor_table = NULL;
+ htable *new_table = NULL;
+ size_t htab_sz;
+ DEFiRet;
+
+ htab_sz = (size_t) (DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING * b->maxCardinality + 1);
+ if (b->table == NULL) {
+ CHKmalloc(survivor_table = create_hashtable(htab_sz, hash_from_string, key_equals_string,
+ no_op_free));
+ }
+ CHKmalloc(new_table = create_hashtable(htab_sz, hash_from_string, key_equals_string, no_op_free));
+ statsobj.UnlinkAllCounters(b->stats);
+ if (b->survivor_table != NULL) {
+ dynstats_destroyCountersIn(b, b->survivor_table, b->survivor_ctrs);
+ }
+ b->survivor_table = (b->table == NULL) ? survivor_table : b->table;
+ b->survivor_ctrs = b->ctrs;
+ b->table = new_table;
+ b->ctrs = NULL;
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to evict "
+ "TTL-expired metrics of dyn-stats bucket named: %s", b->name);
+ if (new_table == NULL) {
+ LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to "
+ "initialize hash-table for dyn-stats bucket named: %s", b->name);
+ } else {
+ assert(0); /* "can" not happen -- triggers Coverity CID 184307:
+ hashtable_destroy(new_table, 0);
+ We keep this as guard should code above change in the future */
+ }
+ if (b->table == NULL) {
+ if (survivor_table == NULL) {
+ LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to initialize "
+ "ttl-survivor hash-table for dyn-stats bucket named: %s", b->name);
+ } else {
+ hashtable_destroy(survivor_table, 0);
+ }
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+dynstats_resetBucket(dynstats_bucket_t *b) {
+ DEFiRet;
+ pthread_rwlock_wrlock(&b->lock);
+ CHKiRet(dynstats_rebuildSurvivorTable(b));
+ STATSCOUNTER_INC(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered);
+ timeoutComp(&b->metricCleanupTimeout, b->unusedMetricLife);
+finalize_it:
+ pthread_rwlock_unlock(&b->lock);
+ RETiRet;
+}
+
+static void
+dynstats_resetIfExpired(dynstats_bucket_t *b) {
+ long timeout;
+ pthread_rwlock_rdlock(&b->lock);
+ timeout = timeoutVal(&b->metricCleanupTimeout);
+ pthread_rwlock_unlock(&b->lock);
+ if (timeout == 0) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "dynstats: bucket '%s' is being reset", b->name);
+ dynstats_resetBucket(b);
+ }
+}
+
+static void
+dynstats_readCallback(statsobj_t __attribute__((unused)) *ignore, void *b) {
+ dynstats_buckets_t *bkts;
+ bkts = &runConf->dynstats_buckets;
+
+ pthread_rwlock_rdlock(&bkts->lock);
+ dynstats_resetIfExpired((dynstats_bucket_t *) b);
+ pthread_rwlock_unlock(&bkts->lock);
+}
+
+static rsRetVal
+dynstats_initNewBucketStats(dynstats_bucket_t *b) {
+ DEFiRet;
+
+ CHKiRet(statsobj.Construct(&b->stats));
+ CHKiRet(statsobj.SetOrigin(b->stats, UCHAR_CONSTANT("dynstats.bucket")));
+ CHKiRet(statsobj.SetName(b->stats, b->name));
+ CHKiRet(statsobj.SetReportingNamespace(b->stats, UCHAR_CONSTANT("values")));
+ statsobj.SetReadNotifier(b->stats, dynstats_readCallback, b);
+ CHKiRet(statsobj.ConstructFinalize(b->stats));
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+dynstats_newBucket(const uchar* name, uint8_t resettable, uint32_t maxCardinality, uint32_t unusedMetricLife) {
+ dynstats_bucket_t *b;
+ dynstats_buckets_t *bkts;
+ uint8_t lock_initialized, metric_count_mutex_initialized;
+ pthread_rwlockattr_t bucket_lock_attr;
+ DEFiRet;
+
+ lock_initialized = metric_count_mutex_initialized = 0;
+ b = NULL;
+
+ bkts = &loadConf->dynstats_buckets;
+
+ if (bkts->initialized) {
+ CHKmalloc(b = calloc(1, sizeof(dynstats_bucket_t)));
+ b->resettable = resettable;
+ b->maxCardinality = maxCardinality;
+ b->unusedMetricLife = 1000 * unusedMetricLife;
+ CHKmalloc(b->name = ustrdup(name));
+
+ pthread_rwlockattr_init(&bucket_lock_attr);
+#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
+ pthread_rwlockattr_setkind_np(&bucket_lock_attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+#endif
+
+ pthread_rwlock_init(&b->lock, &bucket_lock_attr);
+ lock_initialized = 1;
+ pthread_mutex_init(&b->mutMetricCount, NULL);
+ metric_count_mutex_initialized = 1;
+
+ CHKiRet(dynstats_initNewBucketStats(b));
+
+ CHKiRet(dynstats_resetBucket(b));
+
+ CHKiRet(dynstats_addBucketMetrics(bkts, b, name));
+
+ pthread_rwlock_wrlock(&bkts->lock);
+ if (bkts->list == NULL) {
+ bkts->list = b;
+ } else {
+ b->next = bkts->list;
+ bkts->list = b;
+ }
+ pthread_rwlock_unlock(&bkts->lock);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket creation failed, as "
+ "global-initialization of buckets was unsuccessful");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (metric_count_mutex_initialized) {
+ pthread_mutex_destroy(&b->mutMetricCount);
+ }
+ if (lock_initialized) {
+ pthread_rwlock_destroy(&b->lock);
+ }
+ if (b != NULL) {
+ dynstats_destroyBucket(bkts, b);
+ }
+ }
+ RETiRet;
+}
+
+rsRetVal
+dynstats_processCnf(struct cnfobj *o) {
+ struct cnfparamvals *pvals;
+ short i;
+ uchar *name = NULL;
+ uint8_t resettable = DYNSTATS_DEFAULT_RESETTABILITY;
+ uint32_t maxCardinality = DYNSTATS_DEFAULT_MAX_CARDINALITY;
+ uint32_t unusedMetricLife = DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &modpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_NAME)) {
+ CHKmalloc(name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_RESETTABLE)) {
+ resettable = (pvals[i].val.d.n != 0);
+ } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_MAX_CARDINALITY)) {
+ maxCardinality = (uint32_t) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_UNUSED_METRIC_LIFE)) {
+ unusedMetricLife = (uint32_t) pvals[i].val.d.n;
+ } else {
+ dbgprintf("dyn_stats: program error, non-handled "
+ "param '%s'\n", modpblk.descr[i].name);
+ }
+ }
+ if (name != NULL) {
+ CHKiRet(dynstats_newBucket(name, resettable, maxCardinality, unusedMetricLife));
+ }
+
+finalize_it:
+ free(name);
+ cnfparamvalsDestruct(pvals, &modpblk);
+ RETiRet;
+}
+
+rsRetVal
+dynstats_initCnf(dynstats_buckets_t *bkts) {
+ DEFiRet;
+
+ bkts->initialized = 0;
+
+ bkts->list = NULL;
+ CHKiRet(statsobj.Construct(&bkts->global_stats));
+ CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("dynstats")));
+ CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global")));
+ CHKiRet(statsobj.SetReportingNamespace(bkts->global_stats, UCHAR_CONSTANT("values")));
+ CHKiRet(statsobj.ConstructFinalize(bkts->global_stats));
+ pthread_rwlock_init(&bkts->lock, NULL);
+
+ bkts->initialized = 1;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ statsobj.Destruct(&bkts->global_stats);
+ }
+ RETiRet;
+}
+
+void
+dynstats_destroyAllBuckets(void) {
+ dynstats_buckets_t *bkts;
+ dynstats_bucket_t *b;
+ bkts = &runConf->dynstats_buckets;
+ if (bkts->initialized) {
+ pthread_rwlock_wrlock(&bkts->lock);
+ while(1) {
+ b = bkts->list;
+ if (b == NULL) {
+ break;
+ } else {
+ bkts->list = b->next;
+ dynstats_destroyBucket(bkts, b);
+ }
+ }
+ statsobj.Destruct(&bkts->global_stats);
+ pthread_rwlock_unlock(&bkts->lock);
+ pthread_rwlock_destroy(&bkts->lock);
+ }
+}
+
+dynstats_bucket_t *
+dynstats_findBucket(const uchar* name) {
+ dynstats_buckets_t *bkts;
+ dynstats_bucket_t *b;
+ bkts = &loadConf->dynstats_buckets;
+ if (bkts->initialized) {
+ pthread_rwlock_rdlock(&bkts->lock);
+ b = bkts->list;
+ while(b != NULL) {
+ if (! ustrcmp(name, b->name)) {
+ break;
+ }
+ b = b->next;
+ }
+ pthread_rwlock_unlock(&bkts->lock);
+ } else {
+ b = NULL;
+ LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket lookup failed, as global-initialization "
+ "of buckets was unsuccessful");
+ }
+
+ return b;
+}
+
+static rsRetVal
+dynstats_createCtr(dynstats_bucket_t *b, const uchar* metric, dynstats_ctr_t **ctr) {
+ DEFiRet;
+
+ CHKmalloc(*ctr = calloc(1, sizeof(dynstats_ctr_t)));
+ CHKmalloc((*ctr)->metric = ustrdup(metric));
+ STATSCOUNTER_INIT((*ctr)->ctr, (*ctr)->mutCtr);
+ CHKiRet(statsobj.AddManagedCounter(b->stats, metric, ctrType_IntCtr,
+ b->resettable ? CTR_FLAG_MUST_RESET : CTR_FLAG_NONE,
+ &(*ctr)->ctr, &(*ctr)->pCtr, 0));
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if ((*ctr) != NULL) {
+ free((*ctr)->metric);
+ free(*ctr);
+ *ctr = NULL;
+ }
+ }
+ RETiRet;
+}
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" /* TODO: how can we fix these warnings? */
+#endif
+static rsRetVal
+dynstats_addNewCtr(dynstats_bucket_t *b, const uchar* metric, uint8_t doInitialIncrement) {
+ dynstats_ctr_t *ctr;
+ dynstats_ctr_t *found_ctr, *survivor_ctr, *effective_ctr;
+ int created;
+ uchar *copy_of_key = NULL;
+ DEFiRet;
+
+ created = 0;
+ ctr = NULL;
+
+ if ((unsigned) ATOMIC_FETCH_32BIT_unsigned(&b->metricCount, &b->mutMetricCount) >= b->maxCardinality) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ CHKiRet(dynstats_createCtr(b, metric, &ctr));
+
+ pthread_rwlock_wrlock(&b->lock);
+ found_ctr = (dynstats_ctr_t*) hashtable_search(b->table, ctr->metric);
+ if (found_ctr != NULL) {
+ if (doInitialIncrement) {
+ STATSCOUNTER_INC(found_ctr->ctr, found_ctr->mutCtr);
+ }
+ } else {
+ copy_of_key = ustrdup(ctr->metric);
+ if (copy_of_key != NULL) {
+ survivor_ctr = (dynstats_ctr_t*) hashtable_search(b->survivor_table, ctr->metric);
+ if (survivor_ctr == NULL) {
+ effective_ctr = ctr;
+ } else {
+ effective_ctr = survivor_ctr;
+ if (survivor_ctr->prev != NULL) {
+ survivor_ctr->prev->next = survivor_ctr->next;
+ }
+ if (survivor_ctr->next != NULL) {
+ survivor_ctr->next->prev = survivor_ctr->prev;
+ }
+ if (survivor_ctr == b->survivor_ctrs) {
+ b->survivor_ctrs = survivor_ctr->next;
+ }
+ }
+ if ((created = hashtable_insert(b->table, copy_of_key, effective_ctr))) {
+ statsobj.AddPreCreatedCtr(b->stats, effective_ctr->pCtr);
+ }
+ }
+ if (created) {
+ if (b->ctrs != NULL) {
+ b->ctrs->prev = effective_ctr;
+ }
+ effective_ctr->prev = NULL;
+ effective_ctr->next = b->ctrs;
+ b->ctrs = effective_ctr;
+ if (doInitialIncrement) {
+ STATSCOUNTER_INC(effective_ctr->ctr, effective_ctr->mutCtr);
+ }
+ }
+ }
+ pthread_rwlock_unlock(&b->lock);
+
+ if (found_ctr != NULL) {
+ //ignore
+ } else if (created && (effective_ctr != survivor_ctr)) {
+ ATOMIC_INC(&b->metricCount, &b->mutMetricCount);
+ STATSCOUNTER_INC(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd);
+ } else if (! created) {
+ if (copy_of_key != NULL) {
+ free(copy_of_key);
+ }
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+finalize_it:
+ if (((! created) || (effective_ctr != ctr)) && (ctr != NULL)) {
+ dynstats_destroyCtr(ctr);
+ }
+ RETiRet;
+}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+rsRetVal
+dynstats_inc(dynstats_bucket_t *b, uchar* metric) {
+ dynstats_ctr_t *ctr;
+ DEFiRet;
+
+ if (! GatherStats) {
+ FINALIZE;
+ }
+
+ if (ustrlen(metric) == 0) {
+ STATSCOUNTER_INC(b->ctrNoMetric, b->mutCtrNoMetric);
+ FINALIZE;
+ }
+
+ if (pthread_rwlock_tryrdlock(&b->lock) == 0) {
+ ctr = (dynstats_ctr_t *) hashtable_search(b->table, metric);
+ if (ctr != NULL) {
+ STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr);
+ }
+ pthread_rwlock_unlock(&b->lock);
+ } else {
+ ABORT_FINALIZE(RS_RET_NOENTRY);
+ }
+
+ if (ctr == NULL) {
+ CHKiRet(dynstats_addNewCtr(b, metric, 1));
+ }
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (iRet == RS_RET_NOENTRY) {
+ /* NOTE: this is not tested (because it requires very strong orchestration to
+ guarantee contended lock for testing) */
+ STATSCOUNTER_INC(b->ctrOpsIgnored, b->mutCtrOpsIgnored);
+ } else {
+ STATSCOUNTER_INC(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
+ }
+ }
+ RETiRet;
+}
+
diff --git a/runtime/dynstats.h b/runtime/dynstats.h
new file mode 100644
index 0000000..a8986f4
--- /dev/null
+++ b/runtime/dynstats.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_DYNSTATS_H
+#define INCLUDED_DYNSTATS_H
+
+#include "hashtable.h"
+
+typedef struct hashtable htable;
+
+struct dynstats_ctr_s {
+ STATSCOUNTER_DEF(ctr, mutCtr);
+ ctr_t *pCtr;
+ uchar *metric;
+ /* linked list ptr */
+ struct dynstats_ctr_s *next;
+ struct dynstats_ctr_s *prev;
+};
+
+struct dynstats_bucket_s {
+ htable *table;
+ uchar *name;
+ pthread_rwlock_t lock;
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow);
+ ctr_t *pOpsOverflowCtr;
+ STATSCOUNTER_DEF(ctrNewMetricAdd, mutCtrNewMetricAdd);
+ ctr_t *pNewMetricAddCtr;
+ STATSCOUNTER_DEF(ctrNoMetric, mutCtrNoMetric);
+ ctr_t *pNoMetricCtr;
+ STATSCOUNTER_DEF(ctrMetricsPurged, mutCtrMetricsPurged);
+ ctr_t *pMetricsPurgedCtr;
+ STATSCOUNTER_DEF(ctrOpsIgnored, mutCtrOpsIgnored);
+ ctr_t *pOpsIgnoredCtr;
+ STATSCOUNTER_DEF(ctrPurgeTriggered, mutCtrPurgeTriggered);
+ ctr_t *pPurgeTriggeredCtr;
+ struct dynstats_bucket_s *next; /* linked list ptr */
+ struct dynstats_ctr_s *ctrs;
+ /*survivor objects are used to keep counter values around for upto unused-ttl duration,
+ so in case it is accessed within (ttl - 2 * ttl) time-period we can re-store the
+ accumulator value from this */
+ struct dynstats_ctr_s *survivor_ctrs;
+ htable *survivor_table;
+
+ uint32_t maxCardinality;
+ uint32_t metricCount;
+ pthread_mutex_t mutMetricCount;
+ uint32_t unusedMetricLife;
+ uint32_t lastResetTs;
+ struct timespec metricCleanupTimeout;
+ uint8_t resettable;
+};
+
+struct dynstats_buckets_s {
+ struct dynstats_bucket_s *list;
+ statsobj_t *global_stats;
+ pthread_rwlock_t lock;
+ uint8_t initialized;
+};
+
+rsRetVal dynstats_initCnf(dynstats_buckets_t *b);
+rsRetVal dynstats_processCnf(struct cnfobj *o);
+dynstats_bucket_t * dynstats_findBucket(const uchar* name);
+rsRetVal dynstats_inc(dynstats_bucket_t *bucket, uchar* metric);
+void dynstats_destroyAllBuckets(void);
+void dynstats_resetExpired(void);
+rsRetVal dynstatsClassInit(void);
+
+#endif /* #ifndef INCLUDED_DYNSTATS_H */
diff --git a/runtime/errmsg.c b/runtime/errmsg.c
new file mode 100644
index 0000000..ecc0452
--- /dev/null
+++ b/runtime/errmsg.c
@@ -0,0 +1,288 @@
+/* The errmsg object.
+ *
+ * Module begun 2008-03-05 by Rainer Gerhards, based on some code
+ * from syslogd.c. I converted this module to lgpl and have checked that
+ * all contributors agreed to that step.
+ * Now moving to ASL 2.0, and contributor checks tell that there is no need
+ * to take further case, as the code now boils to be either my own or, a few lines,
+ * of the original BSD-licenses sysklogd code. rgerhards, 2012-01-16
+ *
+ * Copyright 2008-2018 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "msg.h"
+#include "errmsg.h"
+#include "operatingstate.h"
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "rsconf.h"
+
+/* static data */
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+static int bHadErrMsgs; /* indicates if we had error messages since reset of this flag
+ * This is used to abort a run if the config is unclean.
+ */
+
+static int fdOversizeMsgLog = -1;
+static pthread_mutex_t oversizeMsgLogMut = PTHREAD_MUTEX_INITIALIZER;
+
+/* ------------------------------ methods ------------------------------ */
+
+/* Resets the error message flag. Must be done before processing config
+ * files.
+ */
+void
+resetErrMsgsFlag(void)
+{
+ bHadErrMsgs = 0;
+}
+
+int
+hadErrMsgs(void)
+{
+ return bHadErrMsgs;
+}
+
+/* We now receive three parameters: one is the internal error code
+ * which will also become the error message number, the second is
+ * errno - if it is non-zero, the corresponding error message is included
+ * in the text and finally the message text itself. Note that it is not
+ * 100% clean to use the internal errcode, as it may be reached from
+ * multiple actual error causes. However, it is much better than having
+ * no error code at all (and in most cases, a single internal error code
+ * maps to a specific error event).
+ * rgerhards, 2008-06-27
+ */
+static void
+doLogMsg(const int iErrno, const int iErrCode, const int severity, const char *msg)
+{
+ char buf[2048];
+ char errStr[1024];
+
+ dbgprintf("Called LogMsg, msg: %s\n", msg);
+ osf_write(OSF_TAG_MSG, msg);
+
+ if(iErrno != 0) {
+ rs_strerror_r(iErrno, errStr, sizeof(errStr));
+ if(iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) {
+ snprintf(buf, sizeof(buf), "%s: %s [v%s]", msg, errStr, VERSION);
+ } else {
+ snprintf(buf, sizeof(buf), "%s: %s [v%s try https://www.rsyslog.com/e/%d ]",
+ msg, errStr, VERSION, iErrCode * -1);
+ }
+ } else {
+ if(iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) {
+ snprintf(buf, sizeof(buf), "%s [v%s]", msg, VERSION);
+ } else {
+ snprintf(buf, sizeof(buf), "%s [v%s try https://www.rsyslog.com/e/%d ]", msg,
+ VERSION, iErrCode * -1);
+ }
+ }
+ buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
+ errno = 0;
+
+ const int msglen = (int) strlen(buf);
+ if(msglen > glblGetMaxLine(ourConf)) {
+ /* in extreme cases, our error messages may be longer than the configured
+ * max message size. If so, we just truncate without further indication, as
+ * anything else would probably lead to a death loop on error messages.
+ * Note that we do not split, as we really do not anticipate there is
+ * much value in supporting extremely short max message sizes - we assume
+ * it's just a testbench thing. -- rgerhards, 2018-05-11
+ */
+ buf[glblGetMaxLine(ourConf)] = '\0'; /* space must be available! */
+ }
+
+ glblErrLogger(severity, iErrCode, (uchar*)buf);
+
+ if(severity == LOG_ERR)
+ bHadErrMsgs = 1;
+}
+
+/* We now receive three parameters: one is the internal error code
+ * which will also become the error message number, the second is
+ * errno - if it is non-zero, the corresponding error message is included
+ * in the text and finally the message text itself. Note that it is not
+ * 100% clean to use the internal errcode, as it may be reached from
+ * multiple actual error causes. However, it is much better than having
+ * no error code at all (and in most cases, a single internal error code
+ * maps to a specific error event).
+ * rgerhards, 2008-06-27
+ */
+void __attribute__((format(printf, 3, 4)))
+LogError(const int iErrno, const int iErrCode, const char *fmt, ... )
+{
+ va_list ap;
+ char buf[2048];
+ int lenBuf;
+
+ va_start(ap, fmt);
+ lenBuf = vsnprintf(buf, sizeof(buf), fmt, ap);
+ if(lenBuf < 0) {
+ strncpy(buf, "error message lost due to problem with vsnprintf", sizeof(buf));
+ }
+ va_end(ap);
+ buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
+
+ doLogMsg(iErrno, iErrCode, LOG_ERR, buf);
+}
+
+/* We now receive three parameters: one is the internal error code
+ * which will also become the error message number, the second is
+ * errno - if it is non-zero, the corresponding error message is included
+ * in the text and finally the message text itself. Note that it is not
+ * 100% clean to use the internal errcode, as it may be reached from
+ * multiple actual error causes. However, it is much better than having
+ * no error code at all (and in most cases, a single internal error code
+ * maps to a specific error event).
+ * rgerhards, 2008-06-27
+ */
+void __attribute__((format(printf, 4, 5)))
+LogMsg(const int iErrno, const int iErrCode, const int severity, const char *fmt, ... )
+{
+ va_list ap;
+ char buf[2048];
+ int lenBuf;
+
+ va_start(ap, fmt);
+ lenBuf = vsnprintf(buf, sizeof(buf), fmt, ap);
+ if(lenBuf < 0) {
+ strncpy(buf, "error message lost due to problem with vsnprintf", sizeof(buf));
+ }
+ va_end(ap);
+ buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */
+
+ doLogMsg(iErrno, iErrCode, severity, buf);
+}
+
+
+/* Write an oversize message to the oversize message error log.
+ * We do NOT handle errors during writing that log other than emitting
+ * yet another error message. The reason is that there really is nothing
+ * else that we could do in that case.
+ * rgerhards, 2018-05-03
+ */
+rsRetVal ATTR_NONNULL()
+writeOversizeMessageLog(const smsg_t *const pMsg)
+{
+ struct json_object *json = NULL;
+ char *rendered = NULL;
+ struct json_object *jval;
+ uchar *buf;
+ size_t toWrite;
+ ssize_t wrRet;
+ int dummy;
+ int mutexLocked = 0;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pMsg, msg);
+
+ if(glblGetOversizeMsgErrorFile(runConf) == NULL) {
+ FINALIZE;
+ }
+
+ pthread_mutex_lock(&oversizeMsgLogMut);
+ mutexLocked = 1;
+
+ if(fdOversizeMsgLog == -1) {
+ fdOversizeMsgLog = open((char*)glblGetOversizeMsgErrorFile(runConf),
+ O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(fdOversizeMsgLog == -1) {
+ LogError(errno, RS_RET_ERR, "error opening oversize message log file %s",
+ glblGetOversizeMsgErrorFile(runConf));
+ FINALIZE;
+ }
+ }
+
+ assert(fdOversizeMsgLog != -1);
+ json = json_object_new_object();
+ if(json == NULL) {
+ FINALIZE;
+ }
+
+ getRawMsg(pMsg, &buf, &dummy);
+ jval = json_object_new_string((char*)buf);
+ json_object_object_add(json, "rawmsg", jval);
+
+ getInputName(pMsg, &buf, &dummy);
+ jval = json_object_new_string((char*)buf);
+ json_object_object_add(json, "input", jval);
+
+ CHKmalloc(rendered = strdup((char*)fjson_object_to_json_string(json)));
+
+ toWrite = strlen(rendered) + 1;
+ /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid
+ * calling malloc() -- write() does NOT need '\0'!
+ */
+ rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+ wrRet = write(fdOversizeMsgLog, rendered, toWrite);
+ if(wrRet != (ssize_t) toWrite) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "error writing oversize message log file %s, write returned %lld",
+ glblGetOversizeMsgErrorFile(runConf), (long long) wrRet);
+ }
+
+finalize_it:
+ free(rendered);
+ if(mutexLocked) {
+ pthread_mutex_unlock(&oversizeMsgLogMut);
+ }
+ if(json != NULL) {
+ fjson_object_put(json);
+ }
+ RETiRet;
+}
+
+
+void
+errmsgDoHUP(void)
+{
+ pthread_mutex_lock(&oversizeMsgLogMut);
+ if(fdOversizeMsgLog != -1) {
+ close(fdOversizeMsgLog);
+ fdOversizeMsgLog = -1;
+ }
+ pthread_mutex_unlock(&oversizeMsgLogMut);
+}
+
+
+void
+errmsgExit(void)
+{
+ if(fdOversizeMsgLog != -1) {
+ close(fdOversizeMsgLog);
+ }
+}
diff --git a/runtime/errmsg.h b/runtime/errmsg.h
new file mode 100644
index 0000000..aad002b
--- /dev/null
+++ b/runtime/errmsg.h
@@ -0,0 +1,38 @@
+/* The errmsg object. It is used to emit error message inside rsyslog.
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_ERRMSG_H
+#define INCLUDED_ERRMSG_H
+
+#include "obj-types.h"
+
+#define NO_ERRCODE -1
+
+/* prototypes */
+void errmsgExit(void);
+void errmsgDoHUP(void);
+void resetErrMsgsFlag(void);
+int hadErrMsgs(void);
+void __attribute__((format(printf, 3, 4))) LogError(const int iErrno, const int iErrCode, const char *fmt, ... );
+void __attribute__((format(printf, 4, 5)))
+ LogMsg(const int iErrno, const int iErrCode, const int severity, const char *fmt, ... );
+rsRetVal ATTR_NONNULL() writeOversizeMessageLog(const smsg_t *const pMsg);
+
+#endif /* #ifndef INCLUDED_ERRMSG_H */
diff --git a/runtime/glbl.c b/runtime/glbl.c
new file mode 100644
index 0000000..6b4cb29
--- /dev/null
+++ b/runtime/glbl.c
@@ -0,0 +1,1523 @@
+/* glbl.c - this module holds global defintions and data items.
+ * These are shared among the runtime library. Their use should be
+ * limited to cases where it is actually needed. The main intension for
+ * implementing them was support for the transistion from v2 to v4
+ * (with fully modular design), but it turned out that there may also
+ * be some other good use cases besides backwards-compatibility.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "unicode-helper.h"
+#include "cfsysline.h"
+#include "glbl.h"
+#include "prop.h"
+#include "atomic.h"
+#include "errmsg.h"
+#include "action.h"
+#include "parserif.h"
+#include "rainerscript.h"
+#include "srUtils.h"
+#include "operatingstate.h"
+#include "net.h"
+#include "rsconf.h"
+#include "queue.h"
+#include "dnscache.h"
+#include "parser.h"
+#include "timezones.h"
+
+/* some defaults */
+#ifndef DFLT_NETSTRM_DRVR
+# define DFLT_NETSTRM_DRVR ((uchar*)"ptcp")
+#endif
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+
+/* static data
+ * For this object, these variables are obviously what makes the "meat" of the
+ * class...
+ */
+
+static struct cnfobj *mainqCnfObj = NULL;/* main queue object, to be used later in startup sequence */
+static int bPreserveFQDN = 0; /* should FQDNs always be preserved? */
+static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */
+static int propLocalIPIF_set = 0; /* is propLocalIPIF already set? */
+static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
+static prop_t *propLocalHostNameToDelete = NULL;/* see GenerateLocalHostName function hdr comment! */
+static uchar *LocalHostName = NULL;/* our hostname - read-only after startup, except HUP */
+static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */
+static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */
+static uchar *LocalDomain = NULL;/* our local domain name - read-only after startup, except HUP */
+static int iMaxLine = 8096;
+int bTerminateInputs = 0; /* global switch that inputs shall terminate ASAP (1=> terminate) */
+int glblUnloadModules = 1;
+char** glblDbgFiles = NULL;
+size_t glblDbgFilesNum = 0;
+int glblDbgWhitelist = 1;
+int glblPermitCtlC = 0;
+
+pid_t glbl_ourpid;
+#ifndef HAVE_ATOMIC_BUILTINS
+DEF_ATOMIC_HELPER_MUT(mutTerminateInputs);
+#endif
+#ifdef USE_UNLIMITED_SELECT
+static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* size of select() bitmask in bytes */
+#endif
+static uchar *SourceIPofLocalClient = NULL; /* [ar] Source IP for local client to be used on multihomed host */
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfparamdescr[] = {
+ { "workdirectory", eCmdHdlrString, 0 },
+ { "operatingstatefile", eCmdHdlrString, 0 },
+ { "dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0 },
+ { "localhostname", eCmdHdlrGetWord, 0 },
+ { "preservefqdn", eCmdHdlrBinary, 0 },
+ { "debug.onshutdown", eCmdHdlrBinary, 0 },
+ { "debug.logfile", eCmdHdlrString, 0 },
+ { "debug.gnutls", eCmdHdlrNonNegInt, 0 },
+ { "debug.unloadmodules", eCmdHdlrBinary, 0 },
+ { "defaultnetstreamdrivercafile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdrivercrlfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdriverkeyfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdrivercertfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdriver", eCmdHdlrString, 0 },
+ { "netstreamdrivercaextrafiles", eCmdHdlrString, 0 },
+ { "maxmessagesize", eCmdHdlrSize, 0 },
+ { "oversizemsg.errorfile", eCmdHdlrGetWord, 0 },
+ { "oversizemsg.report", eCmdHdlrBinary, 0 },
+ { "oversizemsg.input.mode", eCmdHdlrGetWord, 0 },
+ { "reportchildprocessexits", eCmdHdlrGetWord, 0 },
+ { "action.reportsuspension", eCmdHdlrBinary, 0 },
+ { "action.reportsuspensioncontinuation", eCmdHdlrBinary, 0 },
+ { "parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0 },
+ { "parser.droptrailinglfonreception", eCmdHdlrBinary, 0 },
+ { "parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0 },
+ { "parser.spacelfonreceive", eCmdHdlrBinary, 0 },
+ { "parser.escape8bitcharactersonreceive", eCmdHdlrBinary, 0},
+ { "parser.escapecontrolcharactertab", eCmdHdlrBinary, 0},
+ { "parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0 },
+ { "parser.parsehostnameandtag", eCmdHdlrBinary, 0 },
+ { "parser.permitslashinprogramname", eCmdHdlrBinary, 0 },
+ { "stdlog.channelspec", eCmdHdlrString, 0 },
+ { "janitor.interval", eCmdHdlrPositiveInt, 0 },
+ { "senders.reportnew", eCmdHdlrBinary, 0 },
+ { "senders.reportgoneaway", eCmdHdlrBinary, 0 },
+ { "senders.timeoutafter", eCmdHdlrPositiveInt, 0 },
+ { "senders.keeptrack", eCmdHdlrBinary, 0 },
+ { "inputs.timeout.shutdown", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.group.keepsupplemental", eCmdHdlrBinary, 0 },
+ { "privdrop.group.id", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.group.name", eCmdHdlrGID, 0 },
+ { "privdrop.user.id", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.user.name", eCmdHdlrUID, 0 },
+ { "net.ipprotocol", eCmdHdlrGetWord, 0 },
+ { "net.acladdhostnameonfail", eCmdHdlrBinary, 0 },
+ { "net.aclresolvehostname", eCmdHdlrBinary, 0 },
+ { "net.enabledns", eCmdHdlrBinary, 0 },
+ { "net.permitACLwarning", eCmdHdlrBinary, 0 },
+ { "abortonuncleanconfig", eCmdHdlrBinary, 0 },
+ { "abortonfailedqueuestartup", eCmdHdlrBinary, 0 },
+ { "variables.casesensitive", eCmdHdlrBinary, 0 },
+ { "environment", eCmdHdlrArray, 0 },
+ { "processinternalmessages", eCmdHdlrBinary, 0 },
+ { "umask", eCmdHdlrFileCreateMode, 0 },
+ { "security.abortonidresolutionfail", eCmdHdlrBinary, 0 },
+ { "internal.developeronly.options", eCmdHdlrInt, 0 },
+ { "internalmsg.ratelimit.interval", eCmdHdlrPositiveInt, 0 },
+ { "internalmsg.ratelimit.burst", eCmdHdlrPositiveInt, 0 },
+ { "internalmsg.severity", eCmdHdlrSeverity, 0 },
+ { "errormessagestostderr.maxnumber", eCmdHdlrPositiveInt, 0 },
+ { "shutdown.enable.ctlc", eCmdHdlrBinary, 0 },
+ { "default.action.queue.timeoutshutdown", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutenqueue", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutshutdown", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutenqueue", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
+ { "reverselookup.cache.ttl.default", eCmdHdlrNonNegInt, 0 },
+ { "reverselookup.cache.ttl.enable", eCmdHdlrBinary, 0 },
+ { "parser.supportcompressionextension", eCmdHdlrBinary, 0 },
+ { "shutdown.queue.doublesize", eCmdHdlrBinary, 0 },
+ { "debug.files", eCmdHdlrArray, 0 },
+ { "debug.whitelist", eCmdHdlrBinary, 0 },
+ { "libcapng.default", eCmdHdlrBinary, 0 },
+ { "libcapng.enable", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk paramblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescr)/sizeof(struct cnfparamdescr),
+ cnfparamdescr
+ };
+
+static struct cnfparamvals *cnfparamvals = NULL;
+/* we need to support multiple calls into our param block, so we need
+ * to persist the current settings. Note that this must be re-set
+ * each time a new config load begins (TODO: create interface?)
+ */
+
+int
+glblGetMaxLine(rsconf_t *cnf)
+{
+ /* glblGetMaxLine might be invoked before our configuration exists */
+ return((cnf != NULL) ? cnf->globals.iMaxLine : iMaxLine);
+}
+
+
+int
+GetGnuTLSLoglevel(rsconf_t *cnf)
+{
+ return(cnf->globals.iGnuTLSLoglevel);
+}
+
+/* define a macro for the simple properties' set and get functions
+ * (which are always the same). This is only suitable for pretty
+ * simple cases which require neither checks nor memory allocation.
+ */
+#define SIMP_PROP(nameFunc, nameVar, dataType) \
+ SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+ SIMP_PROP_SET(nameFunc, nameVar, dataType)
+#define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
+static rsRetVal Set##nameFunc(dataType newVal) \
+{ \
+ nameVar = newVal; \
+ return RS_RET_OK; \
+}
+#define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+static dataType Get##nameFunc(void) \
+{ \
+ return(nameVar); \
+}
+
+SIMP_PROP(PreserveFQDN, bPreserveFQDN, int)
+SIMP_PROP(mainqCnfObj, mainqCnfObj, struct cnfobj *)
+#ifdef USE_UNLIMITED_SELECT
+SIMP_PROP(FdSetSize, iFdSetSize, int)
+#endif
+
+#undef SIMP_PROP
+#undef SIMP_PROP_SET
+#undef SIMP_PROP_GET
+
+/* This is based on the previous SIMP_PROP but as a getter it uses
+ * additional parameter specifying the configuration it belongs to.
+ * The setter uses loadConf
+ */
+#define SIMP_PROP(nameFunc, nameVar, dataType) \
+ SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+ SIMP_PROP_SET(nameFunc, nameVar, dataType)
+#define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
+static rsRetVal Set##nameFunc(dataType newVal) \
+{ \
+ loadConf->globals.nameVar = newVal; \
+ return RS_RET_OK; \
+}
+#define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+static dataType Get##nameFunc(rsconf_t *cnf) \
+{ \
+ return(cnf->globals.nameVar); \
+}
+
+SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int)
+SIMP_PROP(DisableDNS, bDisableDNS, int)
+SIMP_PROP(ParserEscapeControlCharactersCStyle, parser.bParserEscapeCCCStyle, int)
+SIMP_PROP(ParseHOSTNAMEandTAG, parser.bParseHOSTNAMEandTAG, int)
+SIMP_PROP(OptionDisallowWarning, optionDisallowWarning, int)
+/* We omit setter on purpose, because we want to customize it */
+SIMP_PROP_GET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrCRLF, pszDfltNetstrmDrvrCRLF, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*)
+SIMP_PROP_GET(NetstrmDrvrCAExtraFiles, pszNetstrmDrvrCAExtraFiles, uchar*)
+SIMP_PROP_GET(ParserControlCharacterEscapePrefix, parser.cCCEscapeChar, uchar)
+SIMP_PROP_GET(ParserDropTrailingLFOnReception, parser.bDropTrailingLF, int)
+SIMP_PROP_GET(ParserEscapeControlCharactersOnReceive, parser.bEscapeCCOnRcv, int)
+SIMP_PROP_GET(ParserSpaceLFOnReceive, parser.bSpaceLFOnRcv, int)
+SIMP_PROP_GET(ParserEscape8BitCharactersOnReceive, parser.bEscape8BitChars, int)
+SIMP_PROP_GET(ParserEscapeControlCharacterTab, parser.bEscapeTab, int)
+
+#undef SIMP_PROP
+#undef SIMP_PROP_SET
+#undef SIMP_PROP_GET
+
+/* return global input termination status
+ * rgerhards, 2009-07-20
+ */
+static int GetGlobalInputTermState(void)
+{
+ return ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
+}
+
+
+/* set global termination state to "terminate". Note that this is a
+ * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20
+ */
+static void SetGlobalInputTermination(void)
+{
+ ATOMIC_STORE_1_TO_INT(&bTerminateInputs, &mutTerminateInputs);
+}
+
+
+/* set the local host IP address to a specific string. Helper to
+ * small set of functions. No checks done, caller must ensure it is
+ * ok to call. Most importantly, the IP address must not already have
+ * been set. -- rgerhards, 2012-03-21
+ */
+static rsRetVal
+storeLocalHostIPIF(uchar *myIP)
+{
+ DEFiRet;
+ if(propLocalIPIF != NULL) {
+ CHKiRet(prop.Destruct(&propLocalIPIF));
+ }
+ CHKiRet(prop.Construct(&propLocalIPIF));
+ CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP)));
+ CHKiRet(prop.ConstructFinalize(propLocalIPIF));
+ DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP);
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is used to set the IP address that is to be
+ * reported for the local host. Note that in order to ease things
+ * for the v6 config interface, we do not allow this to be set more
+ * than once.
+ * rgerhards, 2012-03-21
+ */
+static rsRetVal
+setLocalHostIPIF(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ uchar myIP[128];
+ rsRetVal localRet;
+ DEFiRet;
+
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ if(propLocalIPIF_set) {
+ LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set "
+ "and cannot be reset; place it at TOP OF rsyslog.conf!");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int) sizeof(myIP));
+ if(localRet != RS_RET_OK) {
+ LogError(0, RS_RET_ERR, "$LocalHostIPIF: IP address for interface "
+ "'%s' cannnot be obtained - ignoring directive", pNewVal);
+ } else {
+ storeLocalHostIPIF(myIP);
+ }
+
+
+finalize_it:
+ free(pNewVal); /* no longer needed -> is in prop! */
+ RETiRet;
+}
+
+
+/* This function is used to set the global work directory name.
+ * It verifies that the provided directory actually exists and
+ * emits an error message if not.
+ * rgerhards, 2011-02-16
+ */
+static rsRetVal setWorkDir(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ size_t lenDir;
+ int i;
+ struct stat sb;
+ DEFiRet;
+
+ /* remove trailing slashes */
+ lenDir = ustrlen(pNewVal);
+ i = lenDir - 1;
+ while(i > 0 && pNewVal[i] == '/') {
+ --i;
+ }
+
+ if(i < 0) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: empty value "
+ "- directive ignored");
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ if(i != (int) lenDir - 1) {
+ pNewVal[i+1] = '\0';
+ LogError(0, RS_RET_WRN_WRKDIR, "$WorkDirectory: trailing slashes "
+ "removed, new value is '%s'", pNewVal);
+ }
+
+ if(stat((char*) pNewVal, &sb) != 0) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s can not be "
+ "accessed, probably does not exist - directive ignored", pNewVal);
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ if(!S_ISDIR(sb.st_mode)) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s not a directory - directive ignored",
+ pNewVal);
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ free(loadConf->globals.pszWorkDir);
+ loadConf->globals.pszWorkDir = pNewVal;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+setDfltNetstrmDrvrCAF(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ free(loadConf->globals.pszDfltNetstrmDrvrCAF);
+ loadConf->globals.pszDfltNetstrmDrvrCAF = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercafile file '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setNetstrmDrvrCAExtraFiles(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ char* token;
+ int error = 0;
+ free(loadConf->globals.pszNetstrmDrvrCAExtraFiles);
+
+ token = strtok((char*)pNewVal, ",");
+ // Here, fopen per strtok ...
+ while(token != NULL) {
+ fp = fopen((const char*)token, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: netstreamdrivercaextrafiles file '%s' "
+ "could not be accessed", token);
+ error = 1;
+ } else {
+ fclose(fp);
+ }
+ token = strtok(NULL, ",");
+ }
+ if(!error) {
+ loadConf->globals.pszNetstrmDrvrCAExtraFiles = pNewVal;
+ } else {
+ loadConf->globals.pszNetstrmDrvrCAExtraFiles = NULL;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvrCRLF(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ free(loadConf->globals.pszDfltNetstrmDrvrCRLF);
+ loadConf->globals.pszDfltNetstrmDrvrCRLF = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercrlfile file '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+
+static rsRetVal
+setDfltNetstrmDrvrCertFile(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+
+ free(loadConf->globals.pszDfltNetstrmDrvrCertFile);
+ loadConf->globals.pszDfltNetstrmDrvrCertFile = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercertfile '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvrKeyFile(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+
+ free(loadConf->globals.pszDfltNetstrmDrvrKeyFile);
+ loadConf->globals.pszDfltNetstrmDrvrKeyFile = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdriverkeyfile '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvr(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ free(loadConf->globals.pszDfltNetstrmDrvr);
+ loadConf->globals.pszDfltNetstrmDrvr = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserControlCharacterEscapePrefix(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.cCCEscapeChar = *pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserDropTrailingLFOnReception(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bDropTrailingLF = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscapeControlCharactersOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscapeCCOnRcv = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserSpaceLFOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bSpaceLFOnRcv = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscape8BitCharactersOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscape8BitChars = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscapeControlCharacterTab(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscapeTab = pNewVal;
+ RETiRet;
+}
+
+/* This function is used both by legacy and RainerScript conf. It is a real setter. */
+static void
+setMaxLine(const int64_t iNew)
+{
+ if(iNew < 128) {
+ LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize tried to set "
+ "to %lld, but cannot be less than 128 - set to 128 "
+ "instead", (long long) iNew);
+ loadConf->globals.iMaxLine = 128;
+ } else if(iNew > (int64_t) INT_MAX) {
+ LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize larger than "
+ "INT_MAX (%d) - reduced to INT_MAX", INT_MAX);
+ loadConf->globals.iMaxLine = INT_MAX;
+ } else {
+ loadConf->globals.iMaxLine = (int) iNew;
+ }
+}
+
+
+
+static rsRetVal
+legacySetMaxMessageSize(void __attribute__((unused)) *pVal, int64_t iNew)
+{
+ setMaxLine(iNew);
+ return RS_RET_OK;
+}
+
+static rsRetVal
+setDebugFile(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ DEFiRet;
+ dbgSetDebugFile(pNewVal);
+ free(pNewVal);
+ RETiRet;
+}
+
+static rsRetVal
+setDebugLevel(void __attribute__((unused)) *pVal, int level)
+{
+ DEFiRet;
+ dbgSetDebugLevel(level);
+ dbgprintf("debug level %d set via config file\n", level);
+ dbgprintf("This is rsyslog version " VERSION "\n");
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+setOversizeMsgInputMode(const uchar *const mode)
+{
+ DEFiRet;
+ if(!strcmp((char*)mode, "truncate")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
+ } else if(!strcmp((char*)mode, "split")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Split;
+ } else if(!strcmp((char*)mode, "accept")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
+ } else {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
+ }
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+setReportChildProcessExits(const uchar *const mode)
+{
+ DEFiRet;
+ if(!strcmp((char*)mode, "none")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_NONE;
+ } else if(!strcmp((char*)mode, "errors")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
+ } else if(!strcmp((char*)mode, "all")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ALL;
+ } else {
+ LogError(0, RS_RET_CONF_PARAM_INVLD,
+ "invalid value '%s' for global parameter reportChildProcessExits -- ignored",
+ mode);
+ iRet = RS_RET_CONF_PARAM_INVLD;
+ }
+ RETiRet;
+}
+
+static int
+getDefPFFamily(rsconf_t *cnf)
+{
+ return cnf->globals.iDefPFFamily;
+}
+
+/* return our local IP.
+ * If no local IP is set, "127.0.0.1" is selected *and* set. This
+ * is an intensional side effect that we do in order to keep things
+ * consistent and avoid config errors (this will make us not accept
+ * setting the local IP address once a module has obtained it - so
+ * it forces the $LocalHostIPIF directive high up in rsyslog.conf)
+ * rgerhards, 2012-03-21
+ */
+static prop_t*
+GetLocalHostIP(void)
+{
+ assert(propLocalIPIF != NULL);
+ return(propLocalIPIF);
+}
+
+
+/* set our local hostname. Free previous hostname, if it was already set.
+ * Note that we do now do this in a thread. As such, the method here
+ * is NOT 100% clean. If we run into issues, we need to think about
+ * refactoring the whole way we handle the local host name processing.
+ * Possibly using a PROP might be the right solution then.
+ */
+static rsRetVal
+SetLocalHostName(uchar *const newname)
+{
+ uchar *toFree;
+ if(LocalHostName == NULL || strcmp((const char*)LocalHostName, (const char*) newname)) {
+ toFree = LocalHostName;
+ LocalHostName = newname;
+ } else {
+ toFree = newname;
+ }
+ free(toFree);
+ return RS_RET_OK;
+}
+
+
+/* return our local hostname. if it is not set, "[localhost]" is returned
+ */
+uchar*
+glblGetLocalHostName(void)
+{
+ uchar *pszRet;
+
+ if(LocalHostNameOverride != NULL) {
+ pszRet = LocalHostNameOverride;
+ goto done;
+ }
+
+ if(LocalHostName == NULL)
+ pszRet = (uchar*) "[localhost]";
+ else {
+ if(GetPreserveFQDN() == 1)
+ pszRet = LocalFQDNName;
+ else
+ pszRet = LocalHostName;
+ }
+done:
+ return(pszRet);
+}
+
+
+/* return the name of the file where oversize messages are written to
+ */
+uchar*
+glblGetOversizeMsgErrorFile(rsconf_t *cnf)
+{
+ return cnf->globals.oversizeMsgErrorFile;
+}
+
+const uchar*
+glblGetOperatingStateFile(rsconf_t *cnf)
+{
+ return cnf->globals.operatingStateFile;
+}
+
+/* return the mode with which oversize messages will be put forward
+ */
+int
+glblGetOversizeMsgInputMode(rsconf_t *cnf)
+{
+ return cnf->globals.oversizeMsgInputMode;
+}
+
+int
+glblReportOversizeMessage(rsconf_t *cnf)
+{
+ return cnf->globals.reportOversizeMsg;
+}
+
+
+/* logs a message indicating that a child process has terminated.
+ * If name != NULL, prints it as the program name.
+ */
+void
+glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status)
+{
+ DBGPRINTF("waitpid for child %ld returned status: %2.2x\n", (long) pid, status);
+
+ if(cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_NONE
+ || (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_ERRORS
+ && WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
+ return;
+ }
+
+ if(WIFEXITED(status)) {
+ int severity = WEXITSTATUS(status) == 0 ? LOG_INFO : LOG_WARNING;
+ if(name != NULL) {
+ LogMsg(0, NO_ERRCODE, severity, "program '%s' (pid %ld) exited with status %d",
+ name, (long) pid, WEXITSTATUS(status));
+ } else {
+ LogMsg(0, NO_ERRCODE, severity, "child process (pid %ld) exited with status %d",
+ (long) pid, WEXITSTATUS(status));
+ }
+ } else if(WIFSIGNALED(status)) {
+ if(name != NULL) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "program '%s' (pid %ld) terminated by signal %d",
+ name, (long) pid, WTERMSIG(status));
+ } else {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "child process (pid %ld) terminated by signal %d",
+ (long) pid, WTERMSIG(status));
+ }
+ }
+}
+
+
+/* set our local domain name. Free previous domain, if it was already set.
+ */
+static rsRetVal
+SetLocalDomain(uchar *newname)
+{
+ free(LocalDomain);
+ LocalDomain = newname;
+ return RS_RET_OK;
+}
+
+
+/* return our local hostname. if it is not set, "[localhost]" is returned
+ */
+static uchar*
+GetLocalDomain(void)
+{
+ return LocalDomain;
+}
+
+
+/* generate the local hostname property. This must be done after the hostname info
+ * has been set as well as PreserveFQDN.
+ * rgerhards, 2009-06-30
+ * NOTE: This function tries to avoid locking by not destructing the previous value
+ * immediately. This is so that current readers can continue to use the previous name.
+ * Otherwise, we would need to use read/write locks to protect the update process.
+ * In order to do so, we save the previous value and delete it when we are called again
+ * the next time. Note that this in theory is racy and can lead to a double-free.
+ * In practice, however, the window of exposure to trigger this is extremely short
+ * and as this functions is very infrequently being called (on HUP), the trigger
+ * condition for this bug is so highly unlikely that it never occurs in practice.
+ * Probably if you HUP rsyslog every few milliseconds, but who does that...
+ * To further reduce risk potential, we do only update the property when there
+ * actually is a hostname change, which makes it even less likely.
+ * rgerhards, 2013-10-28
+ */
+static rsRetVal
+GenerateLocalHostNameProperty(void)
+{
+ uchar *pszPrev;
+ int lenPrev;
+ prop_t *hostnameNew;
+ uchar *pszName;
+ DEFiRet;
+
+ if(propLocalHostNameToDelete != NULL)
+ prop.Destruct(&propLocalHostNameToDelete);
+
+ if(LocalHostNameOverride == NULL) {
+ if(LocalHostName == NULL)
+ pszName = (uchar*) "[localhost]";
+ else {
+ if(GetPreserveFQDN() == 1)
+ pszName = LocalFQDNName;
+ else
+ pszName = LocalHostName;
+ }
+ } else { /* local hostname is overriden via config */
+ pszName = LocalHostNameOverride;
+ }
+ DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName);
+
+ if(propLocalHostName == NULL)
+ pszPrev = (uchar*)""; /* make sure strcmp() below does not match */
+ else
+ prop.GetString(propLocalHostName, &pszPrev, &lenPrev);
+
+ if(ustrcmp(pszPrev, pszName)) {
+ /* we need to update */
+ CHKiRet(prop.Construct(&hostnameNew));
+ CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName)));
+ CHKiRet(prop.ConstructFinalize(hostnameNew));
+ propLocalHostNameToDelete = propLocalHostName;
+ propLocalHostName = hostnameNew;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* return our local hostname as a string property
+ */
+static prop_t*
+GetLocalHostNameProp(void)
+{
+ return(propLocalHostName);
+}
+
+
+static rsRetVal
+SetLocalFQDNName(uchar *newname)
+{
+ free(LocalFQDNName);
+ LocalFQDNName = newname;
+ return RS_RET_OK;
+}
+
+/* return the current localhost name as FQDN (requires FQDN to be set)
+ * TODO: we should set the FQDN ourselfs in here!
+ */
+static uchar*
+GetLocalFQDNName(void)
+{
+ return(LocalFQDNName == NULL ? (uchar*) "[localhost]" : LocalFQDNName);
+}
+
+
+/* return the current working directory */
+static uchar*
+GetWorkDir(rsconf_t *cnf)
+{
+ return(cnf->globals.pszWorkDir == NULL ? (uchar*) "" : cnf->globals.pszWorkDir);
+}
+
+/* return the "raw" working directory, which means
+ * NULL if unset.
+ */
+const uchar *
+glblGetWorkDirRaw(rsconf_t *cnf)
+{
+ return cnf->globals.pszWorkDir;
+}
+
+/* return the current default netstream driver */
+static uchar*
+GetDfltNetstrmDrvr(rsconf_t *cnf)
+{
+ return(cnf->globals.pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : cnf->globals.pszDfltNetstrmDrvr);
+}
+
+/* [ar] Source IP for local client to be used on multihomed host */
+static rsRetVal
+SetSourceIPofLocalClient(uchar *newname)
+{
+ if(SourceIPofLocalClient != NULL) {
+ free(SourceIPofLocalClient); }
+ SourceIPofLocalClient = newname;
+ return RS_RET_OK;
+}
+
+static uchar*
+GetSourceIPofLocalClient(void)
+{
+ return(SourceIPofLocalClient);
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(glbl)
+CODESTARTobjQueryInterface(glbl)
+ if(pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->GetWorkDir = GetWorkDir;
+ pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty;
+ pIf->GetLocalHostNameProp = GetLocalHostNameProp;
+ pIf->GetLocalHostIP = GetLocalHostIP;
+ pIf->SetGlobalInputTermination = SetGlobalInputTermination;
+ pIf->GetGlobalInputTermState = GetGlobalInputTermState;
+ pIf->GetSourceIPofLocalClient = GetSourceIPofLocalClient; /* [ar] */
+ pIf->SetSourceIPofLocalClient = SetSourceIPofLocalClient; /* [ar] */
+ pIf->GetDefPFFamily = getDefPFFamily;
+ pIf->GetDisableDNS = GetDisableDNS;
+ pIf->GetMaxLine = glblGetMaxLine;
+ pIf->GetOptionDisallowWarning = GetOptionDisallowWarning;
+ pIf->GetDfltNetstrmDrvrCAF = GetDfltNetstrmDrvrCAF;
+ pIf->GetDfltNetstrmDrvrCRLF = GetDfltNetstrmDrvrCRLF;
+ pIf->GetDfltNetstrmDrvrCertFile = GetDfltNetstrmDrvrCertFile;
+ pIf->GetDfltNetstrmDrvrKeyFile = GetDfltNetstrmDrvrKeyFile;
+ pIf->GetDfltNetstrmDrvr = GetDfltNetstrmDrvr;
+ pIf->GetNetstrmDrvrCAExtraFiles = GetNetstrmDrvrCAExtraFiles;
+ pIf->GetParserControlCharacterEscapePrefix = GetParserControlCharacterEscapePrefix;
+ pIf->GetParserDropTrailingLFOnReception = GetParserDropTrailingLFOnReception;
+ pIf->GetParserEscapeControlCharactersOnReceive = GetParserEscapeControlCharactersOnReceive;
+ pIf->GetParserSpaceLFOnReceive = GetParserSpaceLFOnReceive;
+ pIf->GetParserEscape8BitCharactersOnReceive = GetParserEscape8BitCharactersOnReceive;
+ pIf->GetParserEscapeControlCharacterTab = GetParserEscapeControlCharacterTab;
+ pIf->GetLocalHostName = glblGetLocalHostName;
+ pIf->SetLocalHostName = SetLocalHostName;
+#define SIMP_PROP(name) \
+ pIf->Get##name = Get##name; \
+ pIf->Set##name = Set##name;
+ SIMP_PROP(PreserveFQDN);
+ SIMP_PROP(DropMalPTRMsgs);
+ SIMP_PROP(mainqCnfObj);
+ SIMP_PROP(LocalFQDNName)
+ SIMP_PROP(LocalDomain)
+ SIMP_PROP(ParserEscapeControlCharactersCStyle)
+ SIMP_PROP(ParseHOSTNAMEandTAG)
+#ifdef USE_UNLIMITED_SELECT
+ SIMP_PROP(FdSetSize)
+#endif
+#undef SIMP_PROP
+finalize_it:
+ENDobjQueryInterface(glbl)
+
+/* Reset config variables to default values.
+ * rgerhards, 2008-04-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(loadConf->globals.pszDfltNetstrmDrvr);
+ loadConf->globals.pszDfltNetstrmDrvr = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCAF);
+ loadConf->globals.pszDfltNetstrmDrvrCAF = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCRLF);
+ loadConf->globals.pszDfltNetstrmDrvrCRLF = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrKeyFile);
+ loadConf->globals.pszDfltNetstrmDrvrKeyFile = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCertFile);
+ loadConf->globals.pszDfltNetstrmDrvrCertFile = NULL;
+ free(LocalHostNameOverride);
+ LocalHostNameOverride = NULL;
+ free(loadConf->globals.oversizeMsgErrorFile);
+ loadConf->globals.oversizeMsgErrorFile = NULL;
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
+ free(loadConf->globals.pszWorkDir);
+ loadConf->globals.pszWorkDir = NULL;
+ free((void*)loadConf->globals.operatingStateFile);
+ loadConf->globals.operatingStateFile = NULL;
+ loadConf->globals.bDropMalPTRMsgs = 0;
+ bPreserveFQDN = 0;
+ loadConf->globals.iMaxLine = 8192;
+ loadConf->globals.reportOversizeMsg = 1;
+ loadConf->globals.parser.cCCEscapeChar = '#';
+ loadConf->globals.parser.bDropTrailingLF = 1;
+ loadConf->globals.parser.bEscapeCCOnRcv = 1; /* default is to escape control characters */
+ loadConf->globals.parser.bSpaceLFOnRcv = 0;
+ loadConf->globals.parser.bEscape8BitChars = 0; /* default is not to escape control characters */
+ loadConf->globals.parser.bEscapeTab = 1; /* default is to escape tab characters */
+ loadConf->globals.parser.bParserEscapeCCCStyle = 0;
+#ifdef USE_UNLIMITED_SELECT
+ iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask);
+#endif
+ return RS_RET_OK;
+}
+
+
+/* Prepare for new config
+ */
+void
+glblPrepCnf(void)
+{
+ free(mainqCnfObj);
+ mainqCnfObj = NULL;
+ free(cnfparamvals);
+ cnfparamvals = NULL;
+}
+
+/* handle the timezone() object. Each incarnation adds one additional
+ * zone info to the global table of time zones.
+ */
+
+int
+bs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
+{
+ return strcmp((char*)s1, *(char**)s2);
+}
+
+
+
+/* handle a global config object. Note that multiple global config statements
+ * are permitted (because of plugin support), so once we got a param block,
+ * we need to hold to it.
+ * rgerhards, 2011-07-19
+ */
+void
+glblProcessCnf(struct cnfobj *o)
+{
+ int i;
+
+ cnfparamvals = nvlstGetParams(o->nvlst, &paramblk, cnfparamvals);
+ if(cnfparamvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing global "
+ "config parameters [global(...)]");
+ goto done;
+ }
+ if(Debug) {
+ dbgprintf("glbl param blk after glblProcessCnf:\n");
+ cnfparamsPrint(&paramblk, cnfparamvals);
+ }
+
+ /* The next thing is a bit hackish and should be changed in higher
+ * versions. There are a select few parameters which we need to
+ * act on immediately. These are processed here.
+ */
+ for(i = 0 ; i < paramblk.nParams ; ++i) {
+ if(!cnfparamvals[i].bUsed)
+ continue;
+ if(!strcmp(paramblk.descr[i].name, "processinternalmessages")) {
+ loadConf->globals.bProcessInternalMessages = (int) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ } else if(!strcmp(paramblk.descr[i].name, "internal.developeronly.options")) {
+ loadConf->globals.glblDevOptions = (uint64_t) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ } else if(!strcmp(paramblk.descr[i].name, "stdlog.channelspec")) {
+#ifndef ENABLE_LIBLOGGING_STDLOG
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with liblogging-stdlog support. "
+ "The 'stdlog.channelspec' parameter "
+ "is ignored. Note: the syslog API is used instead.\n");
+#else
+ loadConf->globals.stdlog_chanspec = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ /* we need to re-open with the new channel */
+ stdlog_close(loadConf->globals.stdlog_hdl);
+ loadConf->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG,
+ (char*) loadConf->globals.stdlog_chanspec);
+ cnfparamvals[i].bUsed = TRUE;
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "operatingstatefile")) {
+ if(loadConf->globals.operatingStateFile != NULL) {
+ LogError(errno, RS_RET_PARAM_ERROR,
+ "error: operatingStateFile already set to '%s' - "
+ "new value ignored", loadConf->globals.operatingStateFile);
+ } else {
+ loadConf->globals.operatingStateFile =
+ (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ osf_open();
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
+ loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ }
+ }
+done: return;
+}
+
+/* Set mainq parameters. Note that when this is not called, we'll use the
+ * legacy parameter config. mainq parameters can only be set once.
+ */
+void
+glblProcessMainQCnf(struct cnfobj *o)
+{
+ if(mainqCnfObj == NULL) {
+ mainqCnfObj = o;
+ } else {
+ LogError(0, RS_RET_ERR, "main_queue() object can only be specified "
+ "once - all but first ignored\n");
+ }
+}
+
+/* destruct the main q cnf object after it is no longer needed. This is
+ * also used to do some final checks.
+ */
+void
+glblDestructMainqCnfObj(void)
+{
+ /* Only destruct if not NULL! */
+ if (mainqCnfObj != NULL) {
+ nvlstChkUnused(mainqCnfObj->nvlst);
+ cnfobjDestruct(mainqCnfObj);
+ mainqCnfObj = NULL;
+ }
+}
+
+static int
+qs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
+{
+ return strcmp(*((char**)s1), *((char**)s2));
+}
+
+/* set an environment variable */
+static rsRetVal
+do_setenv(const char *const var)
+{
+ char varname[128];
+ const char *val = var;
+ size_t i;
+ DEFiRet;
+
+ for(i = 0 ; *val != '=' ; ++i, ++val) {
+ if(i == sizeof(varname)-i) {
+ parser_errmsg("environment variable name too long "
+ "[max %zu chars] or malformed entry: '%s'",
+ sizeof(varname)-1, var);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+ if(*val == '\0') {
+ parser_errmsg("environment variable entry is missing "
+ "equal sign (for value): '%s'", var);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+ varname[i] = *val;
+ }
+ varname[i] = '\0';
+ ++val;
+ DBGPRINTF("do_setenv, var '%s', val '%s'\n", varname, val);
+
+ if(setenv(varname, val, 1) != 0) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg("error setting environment variable "
+ "'%s' to '%s': %s", varname, val, errStr);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This processes the "regular" parameters which are to be set after the
+ * config has been fully loaded.
+ */
+rsRetVal
+glblDoneLoadCnf(void)
+{
+ int i;
+ unsigned char *cstr;
+ DEFiRet;
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ sortTimezones(loadConf);
+ DBGPRINTF("Timezone information table (%d entries):\n", loadConf->timezones.ntzinfos);
+ displayTimezones(loadConf);
+
+ if(cnfparamvals == NULL)
+ goto finalize_it;
+
+ for(i = 0 ; i < paramblk.nParams ; ++i) {
+ if(!cnfparamvals[i].bUsed)
+ continue;
+ if(!strcmp(paramblk.descr[i].name, "workdirectory")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setWorkDir(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "libcapng.default")) {
+#ifdef ENABLE_LIBCAPNG
+ loadConf->globals.bAbortOnFailedLibcapngSetup = (int) cnfparamvals[i].val.d.n;
+#else
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with libcap-ng support.");
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "libcapng.enable")) {
+#ifdef ENABLE_LIBCAPNG
+ loadConf->globals.bCapabilityDropEnabled = (int) cnfparamvals[i].val.d.n;
+#else
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with libcap-ng support.");
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "variables.casesensitive")) {
+ const int val = (int) cnfparamvals[i].val.d.n;
+ fjson_global_do_case_sensitive_comparison(val);
+ DBGPRINTF("global/config: set case sensitive variables to %d\n",
+ val);
+ } else if(!strcmp(paramblk.descr[i].name, "localhostname")) {
+ free(LocalHostNameOverride);
+ LocalHostNameOverride = (uchar*)
+ es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriverkeyfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrKeyFile(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercertfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCertFile(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercafile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCAF(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercrlfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCRLF(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriver")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvr(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "netstreamdrivercaextrafiles")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setNetstrmDrvrCAExtraFiles(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "preservefqdn")) {
+ bPreserveFQDN = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name,
+ "dropmsgswithmaliciousdnsptrrecords")) {
+ loadConf->globals.bDropMalPTRMsgs = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "action.reportsuspension")) {
+ loadConf->globals.bActionReportSuspension = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "action.reportsuspensioncontinuation")) {
+ loadConf->globals.bActionReportSuspensionCont = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "maxmessagesize")) {
+ setMaxLine(cnfparamvals[i].val.d.n);
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.errorfile")) {
+ free(loadConf->globals.oversizeMsgErrorFile);
+ loadConf->globals.oversizeMsgErrorFile = (uchar*)es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.report")) {
+ loadConf->globals.reportOversizeMsg = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.input.mode")) {
+ const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setOversizeMsgInputMode((uchar*) tmp);
+ free((void*)tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "reportchildprocessexits")) {
+ const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setReportChildProcessExits((uchar*) tmp);
+ free((void*)tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.onshutdown")) {
+ loadConf->globals.debugOnShutdown = (int) cnfparamvals[i].val.d.n;
+ LogError(0, RS_RET_OK, "debug: onShutdown set to %d", loadConf->globals.debugOnShutdown);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.gnutls")) {
+ loadConf->globals.iGnuTLSLoglevel = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.unloadmodules")) {
+ glblUnloadModules = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "parser.controlcharacterescapeprefix")) {
+ uchar* tmp = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setParserControlCharacterEscapePrefix(NULL, tmp);
+ free(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.droptrailinglfonreception")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserDropTrailingLFOnReception(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscapeControlCharactersOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.spacelfonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserSpaceLFOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escape8bitcharactersonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscape8BitCharactersOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactertab")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscapeControlCharacterTab(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ SetParserEscapeControlCharactersCStyle(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.parsehostnameandtag")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ SetParseHOSTNAMEandTAG(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.permitslashinprogramname")) {
+ loadConf->globals.parser.bPermitSlashInProgramname = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.logfile")) {
+ if(pszAltDbgFileName == NULL) {
+ pszAltDbgFileName = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ /* can actually happen if debug system also opened altdbg */
+ if(altdbg != -1) {
+ close(altdbg);
+ }
+ if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY
+ |O_CLOEXEC, S_IRUSR|S_IWUSR)) == -1) {
+ LogError(0, RS_RET_ERR, "debug log file '%s' could not be opened",
+ pszAltDbgFileName);
+ }
+ }
+ LogError(0, RS_RET_OK, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg);
+ } else if(!strcmp(paramblk.descr[i].name, "janitor.interval")) {
+ loadConf->globals.janitorInterval = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.ipprotocol")) {
+ char *proto = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ if(!strcmp(proto, "unspecified")) {
+ loadConf->globals.iDefPFFamily = PF_UNSPEC;
+ } else if(!strcmp(proto, "ipv4-only")) {
+ loadConf->globals.iDefPFFamily = PF_INET;
+ } else if(!strcmp(proto, "ipv6-only")) {
+ loadConf->globals.iDefPFFamily = PF_INET6;
+ } else{
+ LogError(0, RS_RET_ERR, "invalid net.ipprotocol "
+ "parameter '%s' -- ignored", proto);
+ }
+ free(proto);
+ } else if(!strcmp(paramblk.descr[i].name, "senders.reportnew")) {
+ loadConf->globals.reportNewSenders = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) {
+ loadConf->globals.reportGoneAwaySenders = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) {
+ loadConf->globals.senderStatsTimeout = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.keeptrack")) {
+ loadConf->globals.senderKeepTrack = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "inputs.timeout.shutdown")) {
+ loadConf->globals.inputTimeoutShutdown = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.keepsupplemental")) {
+ loadConf->globals.gidDropPrivKeepSupplemental = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.id")) {
+ loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.name")) {
+ loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.user.id")) {
+ loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.user.name")) {
+ loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
+ loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) {
+ loadConf->globals.ACLAddHostnameOnFail = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) {
+ loadConf->globals.ACLDontResolve = !((int) cnfparamvals[i].val.d.n);
+ } else if(!strcmp(paramblk.descr[i].name, "net.enabledns")) {
+ SetDisableDNS(!((int) cnfparamvals[i].val.d.n));
+ } else if(!strcmp(paramblk.descr[i].name, "net.permitwarning")) {
+ SetOptionDisallowWarning(!((int) cnfparamvals[i].val.d.n));
+ } else if(!strcmp(paramblk.descr[i].name, "abortonuncleanconfig")) {
+ loadConf->globals.bAbortOnUncleanConfig = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "abortonfailedqueuestartup")) {
+ loadConf->globals.bAbortOnFailedQueueStartup = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.burst")) {
+ loadConf->globals.intMsgRateLimitBurst = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.interval")) {
+ loadConf->globals.intMsgRateLimitItv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.severity")) {
+ loadConf->globals.intMsgsSeverityFilter = (int) cnfparamvals[i].val.d.n;
+ if((loadConf->globals.intMsgsSeverityFilter < 0) ||
+ (loadConf->globals.intMsgsSeverityFilter > 7)) {
+ parser_errmsg("invalid internalmsg.severity value");
+ loadConf->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER;
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "environment")) {
+ for(int j = 0 ; j < cnfparamvals[i].val.d.ar->nmemb ; ++j) {
+ char *const var = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
+ do_setenv(var);
+ free(var);
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "errormessagestostderr.maxnumber")) {
+ loadConf->globals.maxErrMsgToStderr = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.files")) {
+ free(glblDbgFiles); /* "fix" Coverity false positive */
+ glblDbgFilesNum = cnfparamvals[i].val.d.ar->nmemb;
+ glblDbgFiles = (char**) malloc(cnfparamvals[i].val.d.ar->nmemb * sizeof(char*));
+ for(int j = 0 ; j < cnfparamvals[i].val.d.ar->nmemb ; ++j) {
+ glblDbgFiles[j] = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
+ }
+ qsort(glblDbgFiles, glblDbgFilesNum, sizeof(char*), qs_arrcmp_glblDbgFiles);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.whitelist")) {
+ glblDbgWhitelist = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "shutdown.queue.doublesize")) {
+ loadConf->globals.shutdownQueueDoubleSize = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "umask")) {
+ loadConf->globals.umask = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "shutdown.enable.ctlc")) {
+ loadConf->globals.permitCtlC = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutshutdown")) {
+ loadConf->globals.actq_dflt_toQShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutactioncompletion")) {
+ loadConf->globals.actq_dflt_toActShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutenqueue")) {
+ loadConf->globals.actq_dflt_toEnq = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutworkerthreadshutdown")) {
+ loadConf->globals.actq_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutshutdown")) {
+ loadConf->globals.ruleset_dflt_toQShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutactioncompletion")) {
+ loadConf->globals.ruleset_dflt_toActShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutenqueue")) {
+ loadConf->globals.ruleset_dflt_toEnq = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutworkerthreadshutdown")) {
+ loadConf->globals.ruleset_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.default")) {
+ loadConf->globals.dnscacheDefaultTTL = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.enable")) {
+ loadConf->globals.dnscacheEnableTTL = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "parser.supportcompressionextension")) {
+ loadConf->globals.bSupportCompressionExtension = cnfparamvals[i].val.d.n;
+ } else {
+ dbgprintf("glblDoneLoadCnf: program error, non-handled "
+ "param '%s'\n", paramblk.descr[i].name);
+ }
+ }
+
+ if(loadConf->globals.debugOnShutdown && Debug != DEBUG_FULL) {
+ Debug = DEBUG_ONDEMAND;
+ stddbg = -1;
+ }
+
+finalize_it:
+ /* we have now read the config. We need to query the local host name now
+ * as it was set by the config.
+ *
+ * Note: early messages are already emited, and have "[localhost]" as
+ * hostname. These messages are currently in iminternal queue. Once they
+ * are taken from that queue, the hostname will be adapted.
+ */
+ queryLocalHostname(loadConf);
+ RETiRet;
+}
+
+
+/* Initialize the glbl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ /* intialize properties */
+ storeLocalHostIPIF((uchar*)"127.0.0.1");
+
+ /* config handlers are never unregistered and need not be - we are always loaded ;) */
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugfile", 0, eCmdHdlrGetWord, setDebugFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debuglevel", 0, eCmdHdlrInt, setDebugLevel, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, SetDropMalPTRMsgs,
+ NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, setDfltNetstrmDrvr, NULL,
+ NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCAF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercrlfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCRLF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrKeyFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCertFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"netstreamdrivercaextrafiles", 0, eCmdHdlrGetWord, setNetstrmDrvrCAExtraFiles,
+ NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrGoneAway, NULL, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, legacySetMaxMessageSize, NULL, NULL));
+
+ /* Deprecated parser config options */
+ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar,
+ setParserControlCharacterEscapePrefix, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary,
+ setParserDropTrailingLFOnReception, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary,
+ setParserEscapeControlCharactersOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"spacelfonreceive", 0, eCmdHdlrBinary,
+ setParserSpaceLFOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary,
+ setParserEscape8BitCharactersOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary,
+ setParserEscapeControlCharacterTab, NULL, NULL));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, NULL));
+
+ INIT_ATOMIC_HELPER_MUT(mutTerminateInputs);
+ENDObjClassInit(glbl)
+
+
+/* Exit the glbl class.
+ * rgerhards, 2008-04-17
+ */
+BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
+ free(LocalDomain);
+ free(LocalHostName);
+ free(LocalHostNameOverride);
+ free(LocalFQDNName);
+ objRelease(prop, CORE_COMPONENT);
+ if(propLocalHostNameToDelete != NULL)
+ prop.Destruct(&propLocalHostNameToDelete);
+ DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs);
+ENDObjClassExit(glbl)
diff --git a/runtime/glbl.h b/runtime/glbl.h
new file mode 100644
index 0000000..d75d867
--- /dev/null
+++ b/runtime/glbl.h
@@ -0,0 +1,159 @@
+/* Definition of globally-accessible data items.
+ *
+ * This module provides access methods to items of global scope. Most often,
+ * these globals serve as defaults to initialize local settings. Currently,
+ * many of them are either constants or global variable references. However,
+ * this module provides the necessary hooks to change that at any time.
+ *
+ * Please note that there currently is no glbl.c file as we do not yet
+ * have any implementations.
+ *
+ * Copyright 2008-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GLBL_H_INCLUDED
+#define GLBL_H_INCLUDED
+
+#include <sys/types.h>
+#ifdef ENABLE_LIBLOGGING_STDLOG
+#include <liblogging/stdlog.h>
+#endif
+#include "rainerscript.h"
+#include "prop.h"
+
+#define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */
+#define glblOversizeMsgInputMode_Truncate 0
+#define glblOversizeMsgInputMode_Split 1
+#define glblOversizeMsgInputMode_Accept 2
+
+extern pid_t glbl_ourpid;
+
+/* interfaces */
+BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
+ uchar* (*GetWorkDir)(rsconf_t *cnf);
+ int (*GetMaxLine)(rsconf_t *cnf);
+#define SIMP_PROP(name, dataType) \
+ dataType (*Get##name)(void); \
+ rsRetVal (*Set##name)(dataType);
+ SIMP_PROP(OptimizeUniProc, int)
+ SIMP_PROP(PreserveFQDN, int)
+ SIMP_PROP(LocalFQDNName, uchar*)
+ SIMP_PROP(mainqCnfObj, struct cnfobj*)
+ SIMP_PROP(LocalHostName, uchar*)
+ SIMP_PROP(LocalDomain, uchar*)
+ /* added v3, 2009-06-30 */
+ rsRetVal (*GenerateLocalHostNameProperty)(void);
+ prop_t* (*GetLocalHostNameProp)(void);
+ /* added v4, 2009-07-20 */
+ int (*GetGlobalInputTermState)(void);
+ void (*SetGlobalInputTermination)(void);
+ /* added v5, 2009-11-03 */
+ /* note: v4, v5 are already used by more recent versions, so we need to skip them! */
+ /* added v6, 2009-11-16 as part of varmojfekoj's "unlimited select()" patch
+ * Note that it must be always present, otherwise the interface would have different
+ * versions depending on compile settings, what is not acceptable.
+ * Use this property with care, it is only truly available if UNLIMITED_SELECT is enabled
+ * (I did not yet further investigate the details, because that code hopefully can be removed
+ * at some later stage).
+ */
+ SIMP_PROP(FdSetSize, int)
+ /* v7: was neeeded to mean v5+v6 - do NOT add anything else for that version! */
+ /* next change is v9! */
+ /* v8 - 2012-03-21 */
+ prop_t* (*GetLocalHostIP)(void);
+ uchar* (*GetSourceIPofLocalClient)(void); /* [ar] */
+ rsRetVal (*SetSourceIPofLocalClient)(uchar*); /* [ar] */
+ /* v9 - 2015-01-12 SetMaxLine method removed */
+ /* v10 - global variables should be moved to the rsconf_t data structure, so
+ * dynamic configuration reload can be introduced. This is why each getter needs additional
+ * parameter specifying a configuration it belongs to(either loadConf or runConf)
+ */
+#undef SIMP_PROP
+#define SIMP_PROP(name, dataType) \
+ dataType (*Get##name)(rsconf_t *cnf); \
+ rsRetVal (*Set##name)(dataType);
+
+ SIMP_PROP(DropMalPTRMsgs, int)
+ SIMP_PROP(DfltNetstrmDrvrCAF, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCRLF, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCertFile, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrKeyFile, uchar*)
+ SIMP_PROP(DfltNetstrmDrvr, uchar*)
+ SIMP_PROP(DefPFFamily, int)
+ SIMP_PROP(DisableDNS, int)
+ SIMP_PROP(NetstrmDrvrCAExtraFiles, uchar*)
+ SIMP_PROP(ParserControlCharacterEscapePrefix, uchar)
+ SIMP_PROP(ParserDropTrailingLFOnReception, int)
+ SIMP_PROP(ParserEscapeControlCharactersOnReceive, int)
+ SIMP_PROP(ParserSpaceLFOnReceive, int)
+ SIMP_PROP(ParserEscape8BitCharactersOnReceive, int)
+ SIMP_PROP(ParserEscapeControlCharacterTab, int)
+ SIMP_PROP(ParserEscapeControlCharactersCStyle, int)
+ SIMP_PROP(ParseHOSTNAMEandTAG, int)
+ SIMP_PROP(OptionDisallowWarning, int)
+
+#undef SIMP_PROP
+ENDinterface(glbl)
+#define glblCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */
+/* version 2 had PreserveFQDN added - rgerhards, 2008-12-08 */
+
+/* the remaining prototypes */
+PROTOTYPEObj(glbl);
+
+extern int glblUnloadModules;
+extern short janitorInterval;
+extern char** glblDbgFiles;
+extern size_t glblDbgFilesNum;
+extern int glblDbgWhitelist;
+extern int glblPermitCtlC;
+extern int bTerminateInputs;
+#ifndef HAVE_ATOMIC_BUILTINS
+extern DEF_ATOMIC_HELPER_MUT(mutTerminateInputs);
+#endif
+
+/* Developer options enable some strange things for developer-only testing.
+ * These should never be enabled in a user build, except if explicitly told
+ * by a developer. The options are acutally flags, so they should be powers
+ * of two. Flag assignment may change between versions, **backward
+ * compatibility is NOT necessary**.
+ * rgerhards, 2018-04-28
+ */
+#define DEV_OPTION_KEEP_RUNNING_ON_HARD_CONF_ERROR 1
+#define DEV_OPTION_8_1905_HANG_TEST 2 // TODO: remove - temporary for bughunt
+
+#define glblGetOurPid() glbl_ourpid
+#define glblSetOurPid(pid) { glbl_ourpid = (pid); }
+
+void glblPrepCnf(void);
+void glblProcessCnf(struct cnfobj *o);
+void glblProcessMainQCnf(struct cnfobj *o);
+void glblDestructMainqCnfObj(void);
+rsRetVal glblDoneLoadCnf(void);
+const uchar * glblGetWorkDirRaw(rsconf_t *cnf);
+int GetGnuTLSLoglevel(rsconf_t *cnf);
+int glblGetMaxLine(rsconf_t *cnf);
+int bs_arrcmp_glblDbgFiles(const void *s1, const void *s2);
+uchar* glblGetOversizeMsgErrorFile(rsconf_t *cnf);
+const uchar* glblGetOperatingStateFile(rsconf_t *cnf);
+int glblGetOversizeMsgInputMode(rsconf_t *cnf);
+int glblReportOversizeMessage(rsconf_t *cnf);
+void glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status);
+uchar *glblGetLocalHostName(void);
+
+#endif /* #ifndef GLBL_H_INCLUDED */
diff --git a/runtime/gss-misc.c b/runtime/gss-misc.c
new file mode 100644
index 0000000..cb7ca9b
--- /dev/null
+++ b/runtime/gss-misc.c
@@ -0,0 +1,315 @@
+/* gss-misc.c
+ * This is a miscellaneous helper class for gss-api features.
+ *
+ * Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <gssapi/gssapi.h>
+#include "dirty.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "gss-misc.h"
+#include "debug.h"
+#include "glbl.h"
+#include "unlimited_select.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+static void display_status_(char *m, OM_uint32 code, int type)
+{
+ OM_uint32 maj_stat, min_stat, msg_ctx = 0;
+ gss_buffer_desc msg;
+
+ do {
+ maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NO_OID, &msg_ctx, &msg);
+ if (maj_stat != GSS_S_COMPLETE) {
+ LogError(0, NO_ERRCODE, "GSS-API error in gss_display_status called from <%s>\n", m);
+ break;
+ } else {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "GSS-API error %s: %s\n", m, (char *) msg.value);
+ buf[sizeof(buf) - 1] = '\0';
+ LogError(0, NO_ERRCODE, "%s", buf);
+ }
+ if (msg.length != 0)
+ gss_release_buffer(&min_stat, &msg);
+ } while (msg_ctx);
+}
+
+
+static void display_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+ display_status_(m, maj_stat, GSS_C_GSS_CODE);
+ display_status_(m, min_stat, GSS_C_MECH_CODE);
+}
+
+
+static void display_ctx_flags(OM_uint32 flags)
+{
+ if (flags & GSS_C_DELEG_FLAG)
+ dbgprintf("GSS_C_DELEG_FLAG\n");
+ if (flags & GSS_C_MUTUAL_FLAG)
+ dbgprintf("GSS_C_MUTUAL_FLAG\n");
+ if (flags & GSS_C_REPLAY_FLAG)
+ dbgprintf("GSS_C_REPLAY_FLAG\n");
+ if (flags & GSS_C_SEQUENCE_FLAG)
+ dbgprintf("GSS_C_SEQUENCE_FLAG\n");
+ if (flags & GSS_C_CONF_FLAG)
+ dbgprintf("GSS_C_CONF_FLAG\n");
+ if (flags & GSS_C_INTEG_FLAG)
+ dbgprintf("GSS_C_INTEG_FLAG\n");
+}
+
+
+static int read_all(int fd, char *buf, unsigned int nbyte)
+{
+ int ret;
+ char *ptr;
+ struct timeval tv;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pRfds = malloc(glbl.GetFdSetSize());
+
+ if (pRfds == NULL)
+ return -1;
+#else
+ fd_set rfds;
+ fd_set *pRfds = &rfds;
+#endif
+
+ for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+ FD_ZERO(pRfds);
+ FD_SET(fd, pRfds);
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ if ((ret = select(FD_SETSIZE, pRfds, NULL, NULL, &tv)) <= 0
+ || !FD_ISSET(fd, pRfds)) {
+ freeFdSet(pRfds);
+ return ret;
+ }
+ ret = recv(fd, ptr, nbyte, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ freeFdSet(pRfds);
+ return (ret);
+ } else if (ret == 0) {
+ freeFdSet(pRfds);
+ return (ptr - buf);
+ }
+ }
+
+ freeFdSet(pRfds);
+ return (ptr - buf);
+}
+
+
+static int write_all(int fd, char *buf, unsigned int nbyte)
+{
+ int ret;
+ char *ptr;
+
+ for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+ ret = send(fd, ptr, nbyte, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ return (ret);
+ } else if (ret == 0) {
+ return (ptr - buf);
+ }
+ }
+
+ return (ptr - buf);
+}
+
+
+static int recv_token(int s, gss_buffer_t tok)
+{
+ int ret;
+ unsigned char lenbuf[4] = "xxx"; // initialized to make clang static analyzer happy
+ unsigned int len;
+
+ ret = read_all(s, (char *) lenbuf, 4);
+ if (ret < 0) {
+ LogError(0, NO_ERRCODE, "GSS-API error reading token length");
+ return -1;
+ } else if (!ret) {
+ return 0;
+ } else if (ret != 4) {
+ LogError(0, NO_ERRCODE, "GSS-API error reading token length");
+ return -1;
+ }
+
+ len = ((lenbuf[0] << 24)
+ | (lenbuf[1] << 16)
+ | (lenbuf[2] << 8)
+ | lenbuf[3]);
+ tok->length = ntohl(len);
+
+ tok->value = (char *) malloc(tok->length ? tok->length : 1);
+ if (tok->length && tok->value == NULL) {
+ LogError(0, NO_ERRCODE, "Out of memory allocating token data\n");
+ return -1;
+ }
+
+ ret = read_all(s, (char *) tok->value, tok->length);
+ if (ret < 0) {
+ LogError(0, NO_ERRCODE, "GSS-API error reading token data");
+ free(tok->value);
+ return -1;
+ } else if (ret != (int) tok->length) {
+ LogError(0, NO_ERRCODE, "GSS-API error reading token data");
+ free(tok->value);
+ return -1;
+ }
+
+ return 1;
+}
+
+
+static int send_token(int s, gss_buffer_t tok)
+{
+ int ret;
+ unsigned char lenbuf[4];
+ unsigned int len;
+
+ if (tok->length > 0xffffffffUL)
+ abort(); /* TODO: we need to reconsider this, abort() is not really
+ a solution - degrade, but keep running */
+ len = htonl(tok->length);
+ lenbuf[0] = (len >> 24) & 0xff;
+ lenbuf[1] = (len >> 16) & 0xff;
+ lenbuf[2] = (len >> 8) & 0xff;
+ lenbuf[3] = len & 0xff;
+
+ ret = write_all(s, (char *) lenbuf, 4);
+ if (ret < 0) {
+ LogError(0, NO_ERRCODE, "GSS-API error sending token length");
+ return -1;
+ } else if (ret != 4) {
+ LogError(0, NO_ERRCODE, "GSS-API error sending token length");
+ return -1;
+ }
+
+ ret = write_all(s, tok->value, tok->length);
+ if (ret < 0) {
+ LogError(0, NO_ERRCODE, "GSS-API error sending token data");
+ return -1;
+ } else if (ret != (int) tok->length) {
+ LogError(0, NO_ERRCODE, "GSS-API error sending token data");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(gssutil)
+CODESTARTobjQueryInterface(gssutil)
+ if(pIf->ifVersion != gssutilCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->recv_token = recv_token;
+ pIf->send_token = send_token;
+ pIf->display_status = display_status;
+ pIf->display_ctx_flags = display_ctx_flags;
+
+finalize_it:
+ENDobjQueryInterface(gssutil)
+
+
+/* exit our class
+ * rgerhards, 2008-03-10
+ */
+BEGINObjClassExit(gssutil, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(gssutil)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(gssutil)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-29
+ */
+BEGINAbstractObjClassInit(gssutil, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDObjClassInit(gssutil)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ gssutilClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(gssutilClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
diff --git a/runtime/gss-misc.h b/runtime/gss-misc.h
new file mode 100644
index 0000000..4c8a5ec
--- /dev/null
+++ b/runtime/gss-misc.h
@@ -0,0 +1,44 @@
+/* Definitions for gssutil class. This implements a session of the
+ * plain TCP server.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef GSS_MISC_H_INCLUDED
+#define GSS_MISC_H_INCLUDED 1
+
+#include <gssapi/gssapi.h>
+#include "obj.h"
+
+/* interfaces */
+BEGINinterface(gssutil) /* name must also be changed in ENDinterface macro! */
+ int (*recv_token)(int s, gss_buffer_t tok);
+ int (*send_token)(int s, gss_buffer_t tok);
+ void (*display_status)(char *m, OM_uint32 maj_stat, OM_uint32 min_stat);
+ void (*display_ctx_flags)(OM_uint32 flags);
+ENDinterface(gssutil)
+#define gssutilCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(gssutil);
+
+/* the name of our library binary */
+#define LM_GSSUTIL_FILENAME "lmgssutil"
+
+#endif /* #ifndef GSS_MISC_H_INCLUDED */
diff --git a/runtime/hashtable.c b/runtime/hashtable.c
new file mode 100644
index 0000000..4673a50
--- /dev/null
+++ b/runtime/hashtable.c
@@ -0,0 +1,341 @@
+/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+/* taken from http://www.cl.cam.ac.uk/~cwc22/hashtable/ */
+
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/* this code has several warnings, but we ignore them because
+ * this seems to work and we do not want to engage in that code body. If
+ * we really run into troubles, it is better to change to libfastjson, which
+ * we should do in the medium to long term anyhow...
+ */
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+/*
+Credit for primes table: Aaron Krowne
+http://br.endernet.org/~akrowne/
+http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+
+#define MAX_LOAD_FACTOR 65 /* to get real factor, divide by 100! */
+
+/* compute max load. We use a constant factor of 0.65, but do
+ * everything times 100, so that we do not need floats.
+ */
+static inline unsigned
+getLoadLimit(unsigned size)
+{
+ return (unsigned int) ((unsigned long long) size * MAX_LOAD_FACTOR) / 100;
+}
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashf) (void*),
+ int (*eqf) (void*,void*), void (*dest)(void*))
+{
+ struct hashtable *h;
+ unsigned int pindex, size = primes[0];
+ /* Check requested hashtable isn't too large */
+ if (minsize > (1u << 30)) return NULL;
+ /* Enforce size as prime */
+ for (pindex=0; pindex < prime_table_length; pindex++) {
+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+ }
+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
+ if (NULL == h) return NULL; /*oom*/
+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
+ memset(h->table, 0, size * sizeof(struct entry *));
+ h->tablelength = size;
+ h->primeindex = pindex;
+ h->entrycount = 0;
+ h->hashfn = hashf;
+ h->eqfn = eqf;
+ h->dest = dest;
+ h->loadlimit = getLoadLimit(size);
+ return h;
+}
+
+/*****************************************************************************/
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+unsigned int
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+hash(struct hashtable *h, void *k)
+{
+ /* Aim to protect against poor hash functions by adding logic here
+ * - logic taken from java 1.4 hashtable source */
+ unsigned int i = h->hashfn(k);
+ i += ~(i << 9);
+ i ^= ((i >> 14) | (i << 18)); /* >>> */
+ i += (i << 4);
+ i ^= ((i >> 10) | (i << 22)); /* >>> */
+ return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+ /* Double the size of the table to accomodate more entries */
+ struct entry **newtable;
+ struct entry *e;
+ struct entry **pE;
+ unsigned int newsize, i, idx;
+ /* Check we're not hitting max capacity */
+ if (h->primeindex == (prime_table_length - 1)) return 0;
+ newsize = primes[++(h->primeindex)];
+
+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+ if (NULL != newtable)
+ {
+ memset(newtable, 0, newsize * sizeof(struct entry *));
+ /* This algorithm is not 'stable'. ie. it reverses the list
+ * when it transfers entries between the tables */
+ for (i = 0; i < h->tablelength; i++) {
+ while (NULL != (e = h->table[i])) {
+ h->table[i] = e->next;
+ idx = indexFor(newsize,e->h);
+ e->next = newtable[idx];
+ newtable[idx] = e;
+ }
+ }
+ free(h->table);
+ h->table = newtable;
+ }
+ /* Plan B: realloc instead */
+ else
+ {
+ newtable = (struct entry **)
+ realloc(h->table, newsize * sizeof(struct entry *));
+ if (NULL == newtable) { (h->primeindex)--; return 0; }
+ h->table = newtable;
+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+ for (i = 0; i < h->tablelength; i++) {
+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+ idx = indexFor(newsize,e->h);
+ if (idx == i)
+ {
+ pE = &(e->next);
+ }
+ else
+ {
+ *pE = e->next;
+ e->next = newtable[idx];
+ newtable[idx] = e;
+ }
+ }
+ }
+ }
+ h->tablelength = newsize;
+ h->loadlimit = getLoadLimit(newsize);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ return h->entrycount;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+ /* This method allows duplicate keys - but they shouldn't be used */
+ unsigned int idx;
+ struct entry *e;
+ if (++(h->entrycount) > h->loadlimit)
+ {
+ /* Ignore the return value. If expand fails, we should
+ * still try cramming just this value into the existing table
+ * -- we may not have memory for a larger table, but one more
+ * element may be ok. Next time we insert, we'll try expanding again.*/
+ hashtable_expand(h);
+ }
+ e = (struct entry *)malloc(sizeof(struct entry));
+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+ e->h = hash(h,k);
+ idx = indexFor(h->tablelength,e->h);
+ e->k = k;
+ e->v = v;
+ e->next = h->table[idx];
+ h->table[idx] = e;
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+ struct entry *e;
+ unsigned int hashvalue, idx;
+ hashvalue = hash(h,k);
+ idx = indexFor(h->tablelength,hashvalue);
+ e = h->table[idx];
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+ /* TODO: consider compacting the table when the load factor drops enough,
+ * or provide a 'compact' method. */
+
+ struct entry *e;
+ struct entry **pE;
+ void *v;
+ unsigned int hashvalue, idx;
+
+ hashvalue = hash(h,k);
+ idx = indexFor(h->tablelength,hash(h,k));
+ pE = &(h->table[idx]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ {
+ f = e;
+ e = e->next;
+ freekey(f->k);
+ if(h->dest == NULL)
+ free(f->v);
+ else
+ h->dest(f->v);
+ free(f);
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+ free(h);
+}
+
+/* some generic hash functions */
+
+/* one provided by Aaaron Wiebe based on perl's hashing algorithm
+ * (so probably pretty generic). Not for excessively large strings!
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+unsigned __attribute__((nonnull(1))) int
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+hash_from_string(void *k)
+{
+ char *rkey = (char*) k;
+ unsigned hashval = 1;
+
+ while (*rkey)
+ hashval = hashval * 33 + *rkey++;
+
+ return hashval;
+}
+
+
+int
+key_equals_string(void *key1, void *key2)
+{
+ /* we must return true IF the keys are equal! */
+ return !strcmp(key1, key2);
+}
+
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+*/
diff --git a/runtime/hashtable.h b/runtime/hashtable.h
new file mode 100644
index 0000000..4a55d67
--- /dev/null
+++ b/runtime/hashtable.h
@@ -0,0 +1,202 @@
+/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ * struct hashtable *h;
+ * struct some_key *k;
+ * struct some_value *v;
+ *
+ * static unsigned int hash_from_key_fn( void *k );
+ * static int keys_equal_fn ( void *key1, void *key2 );
+ *
+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ * k = (struct some_key *) malloc(sizeof(struct some_key));
+ * v = (struct some_value *) malloc(sizeof(struct some_value));
+ *
+ * (initialise k and v to suitable values)
+ *
+ * if (! hashtable_insert(h,k,v) )
+ * { exit(-1); }
+ *
+ * if (NULL == (found = hashtable_search(h,k) ))
+ * { printf("not found!"); }
+ *
+ * if (NULL == (found = hashtable_remove(h,k) ))
+ * { printf("Not found\n"); }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name create_hashtable
+ * @param minsize minimum initial size of hashtable
+ * @param hashfunction function for hashing keys
+ * @param key_eq_fn function for determining key equality
+ * @param dest destructor for value entries (NULL -> use free())
+ * @return newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashfunction) (void*),
+ int (*key_eq_fn) (void*,void*), void (*dest) (void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name hashtable_insert
+ * @param h the hashtable to insert into
+ * @param k the key - hashtable claims ownership and will free on removal
+ * @param v the value - does not claim ownership
+ * @return non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+ return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name hashtable_search
+ * @param h the hashtable to search
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name hashtable_remove
+ * @param h the hashtable to remove the item from
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name hashtable_count
+ * @param h the hashtable
+ * @return the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name hashtable_destroy
+ * @param h the hashtable
+ * @param free_values whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+ */
+unsigned __attribute__((nonnull(1))) int hash_from_string(void *k) ;
+int key_equals_string(void *key1, void *key2);
+
+#endif /* __HASHTABLE_CWC22_H__ */
diff --git a/runtime/hashtable_itr.c b/runtime/hashtable_itr.c
new file mode 100644
index 0000000..a065f12
--- /dev/null
+++ b/runtime/hashtable_itr.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) return itr;
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+ return itr;
+}
+
+/*****************************************************************************/
+/* key - return the key of the (key,value) pair at the current position */
+/* value - return the value of the (key,value) pair at the current position */
+
+#if 0 /* these are now inline functions! */
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{ return i->e->k; }
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{ return i->e->v; }
+#endif
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ if (NULL == itr->e) return 0; /* stupidity check */
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ return -1;
+ }
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ return 0;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ return 0;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ return -1;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ return -1;
+ }
+ parent = e;
+ e = e->next;
+ }
+ return 0;
+}
+
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+*/
diff --git a/runtime/hashtable_itr.h b/runtime/hashtable_itr.h
new file mode 100644
index 0000000..91dee6e
--- /dev/null
+++ b/runtime/hashtable_itr.h
@@ -0,0 +1,103 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+#define hashtable_iterator_key(i) ((i)->e->k)
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+#define hashtable_iterator_value(i) ((i)->e->v)
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ * h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+*/
diff --git a/runtime/hashtable_private.h b/runtime/hashtable_private.h
new file mode 100644
index 0000000..4a2d978
--- /dev/null
+++ b/runtime/hashtable_private.h
@@ -0,0 +1,75 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+
+/*****************************************************************************/
+struct entry
+{
+ void *k, *v;
+ unsigned int h;
+ struct entry *next;
+};
+
+struct hashtable {
+ unsigned int tablelength;
+ struct entry **table;
+ unsigned int entrycount;
+ unsigned int loadlimit;
+ unsigned int primeindex;
+ unsigned int (*hashfn) (void *k);
+ int (*eqfn) (void *k1, void *k2);
+ void (*dest) (void *v); /* destructor for values, if NULL use free() */
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+#define indexFor(tablelength, hashvalue) ((hashvalue) % (tablelength))
+
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * 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.
+ *
+ * * Neither the name of the original author; nor the names of any 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.
+*/
diff --git a/runtime/im-helper.h b/runtime/im-helper.h
new file mode 100644
index 0000000..7ba1d25
--- /dev/null
+++ b/runtime/im-helper.h
@@ -0,0 +1,62 @@
+/* im-helper.h
+ * This file contains helper constructs that save time writing input modules. It
+ * assumes some common field names and plumbing. It is intended to be used together
+ * with module-template.h
+ *
+ * File begun on 2011-05-04 by RGerhards
+ *
+ * Copyright 2011-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef IM_HELPER_H_INCLUDED
+#define IM_HELPER_H_INCLUDED 1
+
+
+/* The following function provides a complete implementation to check a
+ * ruleset and set the actual ruleset pointer. The macro assumes that
+ * standard field names are used. A functon std_checkRuleset_genErrMsg()
+ * must be defined to generate error messages in case the ruleset cannot
+ * be found.
+ */
+static inline void std_checkRuleset_genErrMsg(modConfData_t *modConf, instanceConf_t *inst);
+static inline rsRetVal
+std_checkRuleset(modConfData_t *modConf, instanceConf_t *inst)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ inst->pBindRuleset = NULL; /* assume default ruleset */
+
+ if(inst->pszBindRuleset == NULL)
+ FINALIZE;
+
+ localRet = ruleset.GetRuleset(modConf->pConf, &pRuleset, inst->pszBindRuleset);
+ if(localRet == RS_RET_NOT_FOUND) {
+ std_checkRuleset_genErrMsg(modConf, inst);
+ }
+ CHKiRet(localRet);
+ inst->pBindRuleset = pRuleset;
+
+finalize_it:
+ RETiRet;
+}
+
+#endif /* #ifndef IM_HELPER_H_INCLUDED */
diff --git a/runtime/janitor.c b/runtime/janitor.c
new file mode 100644
index 0000000..e7a6bd3
--- /dev/null
+++ b/runtime/janitor.c
@@ -0,0 +1,103 @@
+/* janitor.c - rsyslog's janitor
+ *
+ * The rsyslog janitor can be used to periodically clean out
+ * resources. It was initially developed to close files that
+ * were not written to for some time (omfile plugin), but has
+ * a generic interface that can be used for all similar tasks.
+ *
+ * Module begun 2014-05-15 by Rainer Gerhards
+ *
+ * Copyright (C) 2014-2015 by Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "rsyslog.h"
+#include "janitor.h"
+
+static struct janitorEtry *janitorRoot = NULL; /* TODO: move to runConf? */
+static pthread_mutex_t janitorMut = PTHREAD_MUTEX_INITIALIZER;
+
+rsRetVal
+janitorAddEtry(void (*cb)(void*), const char *id, void *pUsr)
+{
+ struct janitorEtry *etry = NULL;
+ DEFiRet;
+ CHKmalloc(etry = malloc(sizeof(struct janitorEtry)));
+ CHKmalloc(etry->id = strdup(id));
+ etry->pUsr = pUsr;
+ etry->cb = cb;
+ etry->next = janitorRoot;
+ pthread_mutex_lock(&janitorMut);
+ janitorRoot = etry;
+ pthread_mutex_unlock(&janitorMut);
+ DBGPRINTF("janitor: entry %p, id '%s' added\n", etry, id);
+finalize_it:
+ if(iRet != RS_RET_OK && etry != NULL)
+ free(etry);
+ RETiRet;
+}
+
+rsRetVal
+janitorDelEtry(const char *__restrict__ const id)
+{
+ struct janitorEtry *curr, *prev = NULL;
+ DEFiRet;
+
+ pthread_mutex_lock(&janitorMut);
+ for(curr = janitorRoot ; curr != NULL ; curr = curr->next) {
+ if(!strcmp(curr->id, id)) {
+ if(prev == NULL) {
+ janitorRoot = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ free(curr->id);
+ free(curr);
+ DBGPRINTF("janitor: deleted entry '%s'\n", id);
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+ prev = curr;
+ }
+ DBGPRINTF("janitor: to be deleted entry '%s' not found\n", id);
+ iRet = RS_RET_NOT_FOUND;
+finalize_it:
+ pthread_mutex_unlock(&janitorMut);
+ RETiRet;
+}
+
+/* run the janitor; all entries are processed */
+void
+janitorRun(void)
+{
+ struct janitorEtry *curr;
+
+ dbgprintf("janitorRun() called\n");
+ pthread_mutex_lock(&janitorMut);
+ for(curr = janitorRoot ; curr != NULL ; curr = curr->next) {
+ DBGPRINTF("janitor: processing entry %p, id '%s'\n",
+ curr, curr->id);
+ curr->cb(curr->pUsr);
+ }
+ pthread_mutex_unlock(&janitorMut);
+}
diff --git a/runtime/janitor.h b/runtime/janitor.h
new file mode 100644
index 0000000..69a2bd5
--- /dev/null
+++ b/runtime/janitor.h
@@ -0,0 +1,35 @@
+/* rsyslog's janitor
+ *
+ * Copyright (C) 2014 by Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_JANITOR_H
+#define INCLUDED_JANITOR_H
+
+struct janitorEtry {
+ struct janitorEtry *next;
+ char *id; /* ID used to remove entry */
+ void (*cb)(void *pUsr);
+ void *pUsr; /* user-settable pointer (passed to callback) */
+};
+
+rsRetVal janitorAddEtry(void (*cb)(void*), const char *id, void *pUsr);
+rsRetVal janitorDelEtry(const char *__restrict__ const id);
+void janitorRun(void);
+
+#endif /* #ifndef INCLUDED_JANITOR_H */
diff --git a/runtime/lib_ksi_queue.c b/runtime/lib_ksi_queue.c
new file mode 100644
index 0000000..f407156
--- /dev/null
+++ b/runtime/lib_ksi_queue.c
@@ -0,0 +1,220 @@
+#include <malloc.h>
+#include <time.h>
+#include <errno.h>
+#include "lib_ksi_queue.h"
+
+RingBuffer* RingBuffer_new(size_t size) {
+ RingBuffer *p = calloc(1, sizeof (RingBuffer));
+ if (!p)
+ return NULL;
+
+ p->buffer = calloc(size, sizeof (void*));
+ p->size = size;
+ return p;
+}
+
+void RingBuffer_free(RingBuffer* this) {
+ if (this->buffer != NULL)
+ free(this->buffer);
+ free(this);
+}
+
+static bool RingBuffer_grow(RingBuffer* this) {
+ void **pTmp = calloc(this->size * RB_GROW_FACTOR, sizeof (void*));
+ void *pTmpItem = NULL;
+ if (!pTmp)
+ return false;
+
+ for (size_t i = 0; i < this->size; ++i) {
+ RingBuffer_popFront(this, &pTmpItem);
+ pTmp[i] = pTmpItem;
+ }
+
+ free(this->buffer);
+ this->buffer = pTmp;
+ this->head = 0;
+ this->tail = this->size;
+ this->count = this->size;
+ this->size = this->size * RB_GROW_FACTOR;
+ return true;
+}
+
+bool RingBuffer_pushBack(RingBuffer* this, void* item) {
+
+ if (this->size == this->count && !RingBuffer_grow(this))
+ return false;
+
+ if(this->size == 0)
+ return false;
+
+ this->buffer[this->tail] = item;
+ this->tail = (this->tail + 1) % this->size;
+ this->count += 1;
+ return true;
+}
+
+bool RingBuffer_popFront(RingBuffer* this, void** item) {
+ if (this->count == 0)
+ return false;
+
+ *item = this->buffer[this->head];
+ this->buffer[this->head] = NULL;
+ this->count -= 1;
+ this->head = (this->head + 1) % this->size;
+ return true;
+}
+
+bool RingBuffer_peekFront(RingBuffer* this, void** item) {
+ if (this->count == 0)
+ return false;
+
+ *item = this->buffer[this->head];
+ return true;
+}
+
+size_t RingBuffer_count(RingBuffer* this) {
+ return this->count;
+}
+
+bool RingBuffer_getItem(RingBuffer* this, size_t index, void** item) {
+ if (this->count == 0 || index >= this->count)
+ return false;
+
+ *item = this->buffer[(this->head + index) % this->size];
+ return true;
+}
+
+
+ProtectedQueue* ProtectedQueue_new(size_t queueSize) {
+ ProtectedQueue *p = calloc(1, sizeof (ProtectedQueue));
+ if (!p)
+ return NULL;
+
+ pthread_mutex_init(&p->mutex, 0);
+ p->bStop = false;
+ p->workItems = RingBuffer_new(queueSize);
+ return p;
+}
+
+void ProtectedQueue_free(ProtectedQueue* this) {
+ pthread_mutex_destroy(&this->mutex);
+ pthread_cond_destroy(&this->condition);
+ this->bStop = true;
+ RingBuffer_free(this->workItems);
+ free(this);
+}
+
+/// Signal stop. All threads waiting in FetchItme will be returned false from FetchItem
+
+void ProtectedQueue_stop(ProtectedQueue* this) {
+ this->bStop = true;
+ pthread_cond_broadcast(&this->condition);
+}
+
+/// Atomically adds an item into work item queue and releases a thread waiting
+/// in FetchItem
+
+bool ProtectedQueue_addItem(ProtectedQueue* this, void* item) {
+ bool ret = false;
+
+ if (this->bStop)
+ return false;
+
+ pthread_mutex_lock(&this->mutex);
+ if ((ret = RingBuffer_pushBack(this->workItems, item)) == true)
+ pthread_cond_signal(&this->condition);
+ pthread_mutex_unlock(&this->mutex);
+ return ret;
+}
+
+bool ProtectedQueue_peekFront(ProtectedQueue* this, void** item) {
+ bool ret;
+ pthread_mutex_lock(&this->mutex);
+ ret = RingBuffer_peekFront(this->workItems, item);
+ pthread_mutex_unlock(&this->mutex);
+ return ret;
+}
+
+bool ProtectedQueue_popFront(ProtectedQueue* this, void** item) {
+ bool ret;
+ pthread_mutex_lock(&this->mutex);
+ ret = RingBuffer_popFront(this->workItems, item);
+ pthread_mutex_unlock(&this->mutex);
+ return ret;
+}
+
+size_t ProtectedQueue_popFrontBatch(ProtectedQueue* this, void** items, size_t bufSize) {
+ size_t i;
+ pthread_mutex_lock(&this->mutex);
+ for (i = 0; RingBuffer_count(this->workItems) > 0 && i < bufSize; ++i)
+ RingBuffer_popFront(this->workItems, items[i]);
+ pthread_mutex_unlock(&this->mutex);
+ return i;
+}
+
+bool ProtectedQueue_getItem(ProtectedQueue* this, size_t index, void** item) {
+ bool ret=false;
+ pthread_mutex_lock(&this->mutex);
+ ret=RingBuffer_getItem(this->workItems, index, item);
+ pthread_mutex_unlock(&this->mutex);
+ return ret;
+}
+
+/* Waits for a new work item or timeout (if specified). Returns 0 in case of exit
+ * condition, 1 if item became available and ETIMEDOUT in case of timeout. */
+int ProtectedQueue_waitForItem(ProtectedQueue* this, void** item, uint64_t timeout) {
+ struct timespec ts;
+ pthread_mutex_lock(&this->mutex);
+
+ if (timeout > 0) {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += timeout / 1000LL;
+ ts.tv_nsec += (timeout % 1000LL)*1000LL;
+ }
+
+ if (timeout) {
+ if (pthread_cond_timedwait(&this->condition, &this->mutex, &ts) == ETIMEDOUT) {
+ pthread_mutex_unlock(&this->mutex);
+ return ETIMEDOUT;
+ }
+ } else
+ pthread_cond_wait(&this->condition, &this->mutex);
+ if (this->bStop) {
+ pthread_mutex_unlock(&this->mutex);
+ return 0;
+ }
+
+ if (RingBuffer_count(this->workItems) != 0 && item != NULL)
+ RingBuffer_popFront(this->workItems, item);
+
+ pthread_mutex_unlock(&this->mutex);
+
+ return 1;
+}
+
+size_t ProtectedQueue_count(ProtectedQueue* this) {
+ size_t nCount;
+ pthread_mutex_lock(&this->mutex);
+ nCount = RingBuffer_count(this->workItems);
+ pthread_mutex_unlock(&this->mutex);
+ return nCount;
+}
+
+void *worker_thread_main(void *arg) {
+ int res;
+ void* item;
+ WorkerThreadContext* tc = (WorkerThreadContext*) arg;
+
+ while (1) {
+ item = NULL;
+ res = ProtectedQueue_waitForItem(tc->queue, &item, tc->timeout);
+ if (tc->queue->bStop)
+ return NULL;
+
+ if (res == ETIMEDOUT) {
+ if (!tc->timeoutFunc())
+ return NULL;
+ } else if (item != NULL && !tc->workerFunc(item))
+ return NULL;
+ }
+}
diff --git a/runtime/lib_ksi_queue.h b/runtime/lib_ksi_queue.h
new file mode 100644
index 0000000..20ad680
--- /dev/null
+++ b/runtime/lib_ksi_queue.h
@@ -0,0 +1,53 @@
+#ifndef INCLUDED_LIBRSKSI_QUEUE_H
+#define INCLUDED_LIBRSKSI_QUEUE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#define RB_GROW_FACTOR 2
+
+typedef struct RingBuffer_st {
+ void **buffer;
+ size_t size;
+ size_t count;
+ size_t head;
+ size_t tail;
+} RingBuffer;
+
+RingBuffer* RingBuffer_new(size_t size);
+void RingBuffer_free(RingBuffer* this);
+bool RingBuffer_pushBack(RingBuffer* this, void* item);
+bool RingBuffer_popFront(RingBuffer* this, void** item);
+bool RingBuffer_peekFront(RingBuffer* this, void** item);
+bool RingBuffer_getItem(RingBuffer* this, size_t index, void** item);
+size_t RingBuffer_count(RingBuffer* this);
+
+typedef struct ProtectedQueue_st {
+ bool bStop;
+ RingBuffer *workItems;
+ pthread_mutex_t mutex;
+ pthread_cond_t condition;
+} ProtectedQueue;
+
+ProtectedQueue* ProtectedQueue_new(size_t queueSize);
+void ProtectedQueue_free(ProtectedQueue* this);
+void ProtectedQueue_stop(ProtectedQueue* this);
+bool ProtectedQueue_addItem(ProtectedQueue* this, void* item);
+bool ProtectedQueue_peekFront(ProtectedQueue* this, void** item);
+bool ProtectedQueue_popFront(ProtectedQueue* this, void** item);
+size_t ProtectedQueue_popFrontBatch(ProtectedQueue* this, void** items, size_t bufSize);
+int ProtectedQueue_waitForItem(ProtectedQueue* this, void** item, uint64_t timeout);
+size_t ProtectedQueue_count(ProtectedQueue* this);
+bool ProtectedQueue_getItem(ProtectedQueue* this, size_t index, void** item);
+
+typedef struct WorkerThreadContext_st {
+ bool (*workerFunc)(void*);
+ bool (*timeoutFunc)(void);
+ ProtectedQueue* queue;
+ unsigned timeout;
+} WorkerThreadContext;
+
+void *worker_thread_main(void *arg);
+
+#endif //INCLUDED_LIBRSKSI_QUEUE_H
diff --git a/runtime/lib_ksils12.c b/runtime/lib_ksils12.c
new file mode 100644
index 0000000..489f7fd
--- /dev/null
+++ b/runtime/lib_ksils12.c
@@ -0,0 +1,2173 @@
+/* lib_ksils12.c - rsyslog's KSI-LS12 support library
+ *
+ * Regarding the online algorithm for Merkle tree signing. Expected
+ * calling sequence is:
+ *
+ * sigblkConstruct
+ * for each signature block:
+ * sigblkInitKSI
+ * for each record:
+ * sigblkAddRecordKSI
+ * sigblkFinishKSI
+ * sigblkDestruct
+ *
+ * Obviously, the next call after sigblkFinsh must either be to
+ * sigblkInitKSI or sigblkDestruct (if no more signature blocks are
+ * to be emitted, e.g. on file close). sigblkDestruct saves state
+ * information (most importantly last block hash) and sigblkConstruct
+ * reads (or initilizes if not present) it.
+ *
+ * Copyright 2013-2018 Adiscon GmbH and Guardtime, Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include <ksi/ksi.h>
+#include <ksi/tlv_element.h>
+#include <ksi/hash.h>
+#include <ksi/net_async.h>
+#include <ksi/net_ha.h>
+#include <ksi/net_uri.h>
+#include <ksi/signature_builder.h>
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "lib_ksils12.h"
+#include "lib_ksi_queue.h"
+
+#ifndef VERSION
+#define VERSION "no-version"
+#endif
+
+#define KSI_BUF_SIZE 4096
+
+static const char *blockFileSuffix = ".logsig.parts/blocks.dat";
+static const char *sigFileSuffix = ".logsig.parts/block-signatures.dat";
+static const char *ls12FileSuffix = ".logsig";
+static const char *blockCloseReason = "com.guardtime.blockCloseReason";
+
+
+#define LS12_FILE_HEADER "LOGSIG12"
+#define LS12_BLOCKFILE_HEADER "LOG12BLK"
+#define LS12_SIGFILE_HEADER "LOG12SIG"
+#define LS12_SIGNATURE_TIMEOUT 60
+
+/* Worker queue item type identifier */
+typedef enum QITEM_type_en {
+ QITEM_SIGNATURE_REQUEST = 0x00,
+ QITEM_CLOSE_FILE,
+ QITEM_NEW_FILE,
+ QITEM_QUIT
+} QITEM_type;
+
+/* Worker queue item status identifier */
+typedef enum QITEM_status_en {
+ /* State assigned to any item added to queue (initial state). */
+ QITEM_WAITING = 0x00,
+
+ /* State assigned to #QITEM_SIGNATURE_REQUEST item when it is sent out. */
+ QITEM_SENT,
+
+ /* State assigned to #QITEM_SIGNATURE_REQUEST item when request failed or succeeded. */
+ QITEM_DONE
+} QITEM_status;
+
+
+/* Worker queue job item */
+typedef struct QueueItem_st {
+ QITEM_type type;
+ QITEM_status status;
+ KSI_DataHash *root;
+ FILE *file; /* To keep track of the target signature file. */
+ uint64_t intarg1; /* Block time limit or record count or not used. */
+ uint64_t intarg2; /* Level of the sign request or not used. */
+ KSI_AsyncHandle *respHandle;
+ int ksi_status;
+ time_t request_time;
+} QueueItem;
+
+static bool queueAddCloseFile(rsksictx ctx, ksifile kf);
+static bool queueAddNewFile(rsksictx ctx, ksifile kf);
+static bool queueAddQuit(rsksictx ctx);
+static bool queueAddSignRequest(rsksictx ctx, ksifile kf, KSI_DataHash *root, unsigned level);
+static int sigblkFinishKSINoSignature(ksifile ksi, const char *reason);
+
+void *signer_thread(void *arg);
+
+static void __attribute__((format(printf, 2, 3)))
+report(rsksictx ctx, const char *errmsg, ...) {
+ char buf[1024];
+ int r;
+ va_list args;
+ va_start(args, errmsg);
+
+ r = vsnprintf(buf, sizeof (buf), errmsg, args);
+ buf[sizeof(buf)-1] = '\0';
+ va_end(args);
+
+ if(ctx->logFunc == NULL)
+ return;
+
+ if(r>0 && r<(int)sizeof(buf))
+ ctx->logFunc(ctx->usrptr, (uchar*)buf);
+ else
+ ctx->logFunc(ctx->usrptr, (uchar*)errmsg);
+}
+
+static void
+reportErr(rsksictx ctx, const char *const errmsg)
+{
+ if(ctx->errFunc == NULL)
+ goto done;
+ ctx->errFunc(ctx->usrptr, (uchar*)errmsg);
+done: return;
+}
+
+static const char *
+level2str(int level) {
+ switch (level) {
+ case KSI_LOG_DEBUG: return "DEBUG";
+ case KSI_LOG_INFO: return "INFO";
+ case KSI_LOG_NOTICE: return "NOTICE";
+ case KSI_LOG_WARN: return "WARN";
+ case KSI_LOG_ERROR: return "ERROR";
+ default: return "UNKNOWN LOG LEVEL";
+ }
+}
+
+void
+reportKSIAPIErr(rsksictx ctx, ksifile ksi, const char *apiname, int ecode)
+{
+ char errbuf[4096];
+ char ksi_errbuf[4096];
+ KSI_ERR_getBaseErrorMessage(ctx->ksi_ctx, ksi_errbuf, sizeof(ksi_errbuf), NULL, NULL);
+ snprintf(errbuf, sizeof(errbuf), "%s[%s:%d]: %s (%s)",
+ (ksi == NULL) ? (uchar*) "" : ksi->blockfilename,
+ apiname, ecode, KSI_getErrorString(ecode), ksi_errbuf);
+
+ errbuf[sizeof(errbuf)-1] = '\0';
+ reportErr(ctx, errbuf);
+}
+
+void
+rsksisetErrFunc(rsksictx ctx, void (*func)(void*, uchar *), void *usrptr)
+{
+ ctx->usrptr = usrptr;
+ ctx->errFunc = func;
+}
+
+void
+rsksisetLogFunc(rsksictx ctx, void (*func)(void*, uchar *), void *usrptr)
+{
+ ctx->usrptr = usrptr;
+ ctx->logFunc = func;
+}
+
+static ksifile
+rsksifileConstruct(rsksictx ctx) {
+ ksifile ksi = NULL;
+ if ((ksi = calloc(1, sizeof (struct ksifile_s))) == NULL)
+ goto done;
+ ksi->ctx = ctx;
+ ksi->hashAlg = ctx->hashAlg;
+ ksi->blockTimeLimit = ctx->blockTimeLimit;
+ ksi->blockSizeLimit = 1 << (ctx->effectiveBlockLevelLimit - 1);
+ ksi->bKeepRecordHashes = ctx->bKeepRecordHashes;
+ ksi->bKeepTreeHashes = ctx->bKeepTreeHashes;
+ ksi->lastLeaf[0] = ctx->hashAlg;
+
+done:
+ return ksi;
+}
+
+/* return the actual length in to-be-written octets of an integer */
+static uint8_t
+tlvGetIntSize(uint64_t val) {
+ uint8_t n = 0;
+ while (val != 0) {
+ val >>= 8;
+ n++;
+ }
+ return n;
+}
+
+static int
+tlvWriteOctetString(FILE *f, const uint8_t *data, uint16_t len) {
+ if (fwrite(data, len, 1, f) != 1)
+ return RSGTE_IO;
+ return 0;
+}
+
+static int
+tlvWriteHeader8(FILE *f, int flags, uint8_t tlvtype, int len) {
+ unsigned char buf[2];
+ assert((flags & RSGT_TYPE_MASK) == 0);
+ assert((tlvtype & RSGT_TYPE_MASK) == tlvtype);
+ buf[0] = (flags & ~RSGT_FLAG_TLV16) | tlvtype;
+ buf[1] = len & 0xff;
+
+ return tlvWriteOctetString(f, buf, 2);
+}
+
+static int
+tlvWriteHeader16(FILE *f, int flags, uint16_t tlvtype, uint16_t len)
+{
+ uint16_t typ;
+ unsigned char buf[4];
+ assert((flags & RSGT_TYPE_MASK) == 0);
+ assert((tlvtype >> 8 & RSGT_TYPE_MASK) == (tlvtype >> 8));
+ typ = ((flags | RSGT_FLAG_TLV16) << 8) | tlvtype;
+
+ buf[0] = typ >> 8;
+ buf[1] = typ & 0xff;
+ buf[2] = (len >> 8) & 0xff;
+ buf[3] = len & 0xff;
+
+ return tlvWriteOctetString(f, buf, 4);
+}
+
+static int
+tlvGetHeaderSize(uint16_t tag, size_t size) {
+ if (tag <= RSGT_TYPE_MASK && size <= 0xff)
+ return 2;
+ if ((tag >> 8) <= RSGT_TYPE_MASK && size <= 0xffff)
+ return 4;
+ return 0;
+}
+
+static int
+tlvWriteHeader(FILE *f, int flags, uint16_t tlvtype, uint16_t len) {
+ int headersize = tlvGetHeaderSize(tlvtype, flags);
+ if (headersize == 2)
+ return tlvWriteHeader8(f, flags, tlvtype, len);
+ else if (headersize == 4)
+ return tlvWriteHeader16(f, flags, tlvtype, len);
+ else
+ return 0;
+}
+
+static int
+tlvWriteOctetStringTLV(FILE *f, int flags, uint16_t tlvtype, const uint8_t *data, uint16_t len) {
+ if (tlvWriteHeader(f, flags, tlvtype, len) != 0)
+ return RSGTE_IO;
+
+ if (fwrite(data, len, 1, f) != 1)
+ return RSGTE_IO;
+
+ return 0;
+}
+
+static int
+tlvWriteInt64TLV(FILE *f, int flags, uint16_t tlvtype, uint64_t val) {
+ unsigned char buf[8];
+ uint8_t count = tlvGetIntSize(val);
+ uint64_t nTmp;
+
+ if (tlvWriteHeader(f, flags, tlvtype, count) != 0)
+ return RSGTE_IO;
+
+ nTmp = val;
+ for (int i = count - 1; i >= 0; i--) {
+ buf[i] = 0xFF & nTmp;
+ nTmp = nTmp >> 8;
+ }
+
+ if (fwrite(buf, count, 1, f) != 1)
+ return RSGTE_IO;
+
+ return 0;
+}
+
+static int
+tlvWriteHashKSI(ksifile ksi, uint16_t tlvtype, KSI_DataHash *rec) {
+ int r;
+ const unsigned char *imprint;
+ size_t imprint_len;
+ r = KSI_DataHash_getImprint(rec, &imprint, &imprint_len);
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_getImprint", r);
+ return r;
+ }
+
+ return tlvWriteOctetStringTLV(ksi->blockFile, 0, tlvtype, imprint, imprint_len);
+}
+
+static int
+tlvWriteBlockHdrKSI(ksifile ksi) {
+ unsigned tlvlen;
+ uint8_t hash_algo = ksi->hashAlg;
+ int r;
+
+ tlvlen = 2 + 1 /* hash algo TLV */ +
+ 2 + KSI_getHashLength(ksi->hashAlg) /* iv */ +
+ 2 + KSI_getHashLength(ksi->lastLeaf[0]) + 1;
+ /* last hash */;
+
+ /* write top-level TLV object block-hdr */
+ CHKr(tlvWriteHeader(ksi->blockFile, 0x00, 0x0901, tlvlen));
+
+ /* hash-algo */
+ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x01, &hash_algo, 1));
+
+ /* block-iv */
+ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x02,
+ ksi->IV, KSI_getHashLength(ksi->hashAlg)));
+
+ /* last-hash */
+ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x03,
+ ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1));
+done:
+ return r;
+}
+
+static int
+tlvWriteKSISigLS12(FILE *outfile, size_t record_count, uchar *der, uint16_t lenDer) {
+ int r = 0;
+ int totalSize = 2 + tlvGetIntSize(record_count) + 4 + lenDer;
+
+ CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize));
+ CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count));
+ CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x0905, der, lenDer));
+done:
+ return r;
+}
+
+static int
+tlvWriteNoSigLS12(FILE *outfile, size_t record_count, const KSI_DataHash *hash, const char *errorText) {
+ int r = 0;
+ int totalSize = 0;
+ int noSigSize = 0;
+ const unsigned char *imprint = NULL;
+ size_t imprintLen = 0;
+
+ KSI_DataHash_getImprint(hash, &imprint, &imprintLen);
+
+ noSigSize = 2 + imprintLen + (errorText ? (2 + strlen(errorText) + 1) : 0);
+ totalSize = 2 + tlvGetIntSize(record_count) + 2 + noSigSize;
+
+ CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize));
+ CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count));
+ CHKr(tlvWriteHeader(outfile, 0x00, 0x02, noSigSize));
+ CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x01, imprint, imprintLen));
+ if (errorText)
+ CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x02, (uint8_t*) errorText, strlen(errorText) + 1));
+done:
+ return r;
+}
+
+static int
+tlvCreateMetadata(ksifile ksi, uint64_t record_index, const char *key,
+ const char *value, unsigned char *buffer, size_t *len) {
+ int r = 0;
+ KSI_TlvElement *metadata = NULL, *attrib_tlv = NULL;
+ KSI_Utf8String *key_tlv = NULL, *value_tlv = NULL;
+ KSI_Integer *index_tlv = NULL;
+
+ CHKr(KSI_TlvElement_new(&metadata));
+ metadata->ftlv.tag = 0x0911;
+
+ CHKr(KSI_Integer_new(ksi->ctx->ksi_ctx, record_index, &index_tlv));
+ CHKr(KSI_TlvElement_setInteger(metadata, 0x01, index_tlv));
+
+ CHKr(KSI_TlvElement_new(&attrib_tlv));
+ attrib_tlv->ftlv.tag = 0x02;
+
+ CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, key, strlen(key) + 1, &key_tlv));
+ CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x01, key_tlv));
+
+ CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, value, strlen(value) + 1, &value_tlv));
+ CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x02, value_tlv));
+
+ CHKr(KSI_TlvElement_setElement(metadata, attrib_tlv));
+
+ CHKr(KSI_TlvElement_serialize(metadata, buffer, 0xFFFF, len, 0));
+
+done:
+ if (metadata) KSI_TlvElement_free(metadata);
+ if (attrib_tlv) KSI_TlvElement_free(attrib_tlv);
+ if (key_tlv) KSI_Utf8String_free(key_tlv);
+ if (value_tlv) KSI_Utf8String_free(value_tlv);
+ if (index_tlv) KSI_Integer_free(index_tlv);
+
+ return r;
+}
+
+#define KSI_FILE_AMOUNT_INC 32
+
+static int
+rsksiExpandRegisterIfNeeded(rsksictx ctx, size_t inc) {
+ int ret = RSGTE_INTERNAL;
+ ksifile *tmp = NULL;
+
+ if (ctx == NULL || inc == 0) {
+ return RSGTE_INTERNAL;
+ }
+
+ if (ctx->ksiCount < ctx->ksiCapacity) {
+ return RSGTE_SUCCESS;
+ }
+
+ /* If needed allocate memory for the buffer. */
+ tmp = (ksifile*)realloc(ctx->ksi, sizeof(ksifile) * (ctx->ksiCapacity + inc));
+ if (tmp == NULL) {
+ ret = RSGTE_OOM;
+ goto done;
+ }
+
+ /* Make sure that allocated pointers are all set to NULL. */
+ memset(tmp + ctx->ksiCapacity, 0, sizeof(ksifile) * inc);
+
+ /* Update buffer capacity. */
+ ctx->ksiCapacity += inc;
+ ctx->ksi = tmp;
+ tmp = NULL;
+ ret = RSGTE_SUCCESS;
+
+done:
+ free(tmp);
+ return ret;
+}
+
+static int
+rsksiRegisterKsiFile(rsksictx ctx, ksifile ksi) {
+ int ret = RSGTE_INTERNAL;
+
+ if (ctx == NULL || ksi == NULL) {
+ return RSGTE_INTERNAL;
+ }
+
+ /* To be extra sure that ksifile buffer is initialized correctly, clear variables. */
+ if (ctx->ksi == NULL) {
+ ctx->ksiCount = 0;
+ ctx->ksiCapacity = 0;
+ }
+
+ ret = rsksiExpandRegisterIfNeeded(ctx, KSI_FILE_AMOUNT_INC);
+ if (ret != RSGTE_SUCCESS) goto done;
+
+ ctx->ksi[ctx->ksiCount] = ksi;
+ ctx->ksiCount++;
+ ret = RSGTE_SUCCESS;
+
+done:
+ return ret;
+}
+
+static int
+rsksiDeregisterKsiFile(rsksictx ctx, ksifile ksi) {
+ int ret = RSGTE_INTERNAL;
+ size_t i = 0;
+
+ if (ctx == NULL || ksi == NULL) {
+ return RSGTE_INTERNAL;
+ }
+
+
+ for (i = 0; i < ctx->ksiCount; i++) {
+ if (ctx->ksi[i] != NULL && ctx->ksi[i] == ksi) {
+ size_t lastElement = ctx->ksiCount - 1;
+
+ if (i != lastElement) {
+ ctx->ksi[i] = ctx->ksi[lastElement];
+ }
+
+ ctx->ksi[lastElement] = NULL;
+
+ ctx->ksiCount--;
+ ret = RSGTE_SUCCESS;
+ goto done;
+ }
+ }
+
+done:
+ return ret;
+}
+
+/* support for old platforms - graceful degrade */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+/* read rsyslog log state file; if we cannot access it or the
+ * contents looks invalid, we flag it as non-present (and thus
+ * begin a new hash chain).
+ * The context is initialized accordingly.
+ */
+static bool
+ksiReadStateFile(ksifile ksi) {
+ int fd = -1;
+ struct rsksistatefile sf;
+ bool ret = false;
+
+ fd = open((char*)ksi->statefilename, O_RDONLY|O_NOCTTY|O_CLOEXEC, 0600);
+ if (fd == -1)
+ goto done;
+
+ if (read(fd, &sf, sizeof (sf)) != sizeof (sf)) goto done;
+ if (strncmp(sf.hdr, "KSISTAT10", 9)) goto done;
+
+ if (KSI_getHashLength(sf.hashID) != sf.lenHash ||
+ KSI_getHashLength(sf.hashID) > KSI_MAX_IMPRINT_LEN - 1)
+ goto done;
+
+ if (read(fd, ksi->lastLeaf + 1, sf.lenHash) != sf.lenHash)
+ goto done;
+
+ ksi->lastLeaf[0] = sf.hashID;
+ ret = true;
+
+done:
+ if (!ret) {
+ memset(ksi->lastLeaf, 0, sizeof (ksi->lastLeaf));
+ ksi->lastLeaf[0] = ksi->hashAlg;
+ }
+
+ if (fd != -1)
+ close(fd);
+ return ret;
+}
+
+/* persist all information that we need to re-open and append
+ * to a log signature file.
+ */
+static void
+ksiWwriteStateFile(ksifile ksi)
+{
+ int fd;
+ struct rsksistatefile sf;
+
+ fd = open((char*)ksi->statefilename,
+ O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, ksi->ctx->fCreateMode);
+ if(fd == -1)
+ goto done;
+ if (ksi->ctx->fileUID != (uid_t) - 1 || ksi->ctx->fileGID != (gid_t) - 1) {
+ /* we need to set owner/group */
+ if (fchown(fd, ksi->ctx->fileUID, ksi->ctx->fileGID) != 0) {
+ report(ksi->ctx, "lmsig_ksi: chown for file '%s' failed: %s",
+ ksi->statefilename, strerror(errno));
+ }
+ }
+
+ memcpy(sf.hdr, "KSISTAT10", 9);
+ sf.hashID = ksi->hashAlg;
+ sf.lenHash = KSI_getHashLength(ksi->lastLeaf[0]);
+ /* if the write fails, we cannot do anything against that. We check
+ * the condition just to keep the compiler happy.
+ */
+ if(write(fd, &sf, sizeof(sf))){};
+ if (write(fd, ksi->lastLeaf + 1, sf.lenHash)) {
+ };
+ close(fd);
+done:
+ return;
+}
+
+
+static int
+ksiCloseSigFile(ksifile ksi) {
+ fclose(ksi->blockFile);
+ ksi->blockFile = NULL;
+ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS)
+ queueAddCloseFile(ksi->ctx, ksi);
+
+ ksiWwriteStateFile(ksi);
+ return 0;
+}
+
+static int mkpath(char* path, mode_t mode, uid_t uid, gid_t gid) {
+
+ if(path == NULL)
+ return 1;
+
+ for (char *p = strchr(path + 1, '/'); p; p = strchr(p + 1, '/')) {
+ *p = '\0';
+ if (mkdir(path, mode) == 0) {
+ if (uid != (uid_t) -1 || gid != (uid_t) -1) {
+ if (chown(path, uid, gid)) {
+ LogError(errno, RS_RET_IO_ERROR,
+ "ksils12 signatures: could not change to "
+ "configured owner - files may be unaccessible");
+ }
+ }
+ }
+ else if (errno != EEXIST) {
+ *p = '/';
+ return -1;
+ }
+
+ *p = '/';
+ }
+ return 0;
+}
+
+static FILE*
+ksiCreateFile(rsksictx ctx, const char *path, uid_t uid, gid_t gid, int mode, bool lockit, const char* header) {
+ int fd = -1;
+ struct stat stat_st;
+ FILE *f = NULL;
+ struct flock lock = {F_WRLCK, SEEK_SET, 0, 0, 0};
+
+ if(path ==NULL)
+ return NULL;
+
+ if (mkpath((char*) path, ctx->fDirCreateMode, ctx->dirUID, ctx->dirGID) != 0) {
+ report(ctx, "ksiCreateFile: mkpath failed for %s", path);
+ goto done;
+ }
+
+ fd = open(path, O_RDWR | O_APPEND | O_NOCTTY | O_CLOEXEC, 0600);
+ if (fd == -1) {
+ fd = open(path, O_RDWR | O_CREAT | O_NOCTTY | O_CLOEXEC, mode);
+ if (fd == -1) {
+ report(ctx, "creating file '%s' failed: %s", path, strerror(errno));
+ goto done;
+ }
+
+ if (uid != (uid_t) - 1 || gid != (gid_t) - 1) {
+ if (fchown(fd, uid, gid) != 0) {
+ report(ctx, "lmsig_ksi: chown for file '%s' failed: %s",
+ path, strerror(errno));
+ }
+ }
+ }
+
+ if (lockit && fcntl(fd, F_SETLK, &lock) != 0)
+ report(ctx, "fcntl error: %s", strerror(errno));
+
+ f = fdopen(fd, "a");
+ if (f == NULL) {
+ report(ctx, "fdopen for '%s' failed: %s", path, strerror(errno));
+ goto done;
+ }
+
+ setvbuf(f, NULL, _IOFBF, KSI_BUF_SIZE);
+
+ if (fstat(fd, &stat_st) == -1) {
+ reportErr(ctx, "ksiOpenSigFile: can not stat file");
+ goto done;
+ }
+
+ if (stat_st.st_size == 0 && header != NULL) {
+ if(fwrite(header, strlen(header), 1, f) != 1) {
+ report(ctx, "ksiOpenSigFile: fwrite for file %s failed: %s",
+ path, strerror(errno));
+ goto done;
+ }
+ }
+ /* Write header immediately as when using dynafile it is possible that the same
+ * file is opened 2x in sequence (caused by small dynafile cache where files are
+ * frequently closed and reopened). If the header already exists double header is
+ * not written. The content of the file is ordered by signer thread.
+ */
+ fflush(f);
+done:
+ return f;
+}
+
+static void handle_ksi_config(rsksictx ctx, KSI_AsyncService *as, KSI_Config *config) {
+ int res = KSI_UNKNOWN_ERROR;
+ KSI_Integer *intValue = NULL;
+
+ if (KSI_Config_getMaxRequests(config, &intValue) == KSI_OK && intValue != NULL) {
+ ctx->max_requests = KSI_Integer_getUInt64(intValue);
+ report(ctx, "KSI gateway has reported a max requests value of %llu",
+ (long long unsigned) ctx->max_requests);
+
+ if(as) {
+ /* libksi expects size_t. */
+ size_t optValue = 0;
+
+ optValue = ctx->max_requests;
+ res = KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_MAX_REQUEST_COUNT,
+ (void*)optValue);
+ if(res != KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_setOption(max_request)", res);
+
+ optValue = 3 * ctx->max_requests * ctx->blockSigTimeout;
+ KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE,
+ (void*)optValue);
+ }
+ }
+
+ intValue = NULL;
+ if(KSI_Config_getMaxLevel(config, &intValue) == KSI_OK && intValue != NULL) {
+ uint64_t newLevel = 0;
+ newLevel = KSI_Integer_getUInt64(intValue);
+ report(ctx, "KSI gateway has reported a max level value of %llu",
+ (long long unsigned) newLevel);
+ newLevel=MIN(newLevel, ctx->blockLevelLimit);
+ if(ctx->effectiveBlockLevelLimit != newLevel) {
+ report(ctx, "Changing the configured block level limit from %llu to %llu",
+ (long long unsigned) ctx->effectiveBlockLevelLimit,
+ (long long unsigned) newLevel);
+ ctx->effectiveBlockLevelLimit = newLevel;
+ }
+ else if(newLevel < 2) {
+ report(ctx, "KSI gateway has reported an invalid level limit value (%llu), "
+ "plugin disabled", (long long unsigned) newLevel);
+ ctx->disabled = true;
+ }
+ }
+
+ intValue = NULL;
+ if (KSI_Config_getAggrPeriod(config, &intValue) == KSI_OK && intValue != NULL) {
+ uint64_t newThreadSleep = 0;
+ newThreadSleep = KSI_Integer_getUInt64(intValue);
+ report(ctx, "KSI gateway has reported an aggregation period value of %llu",
+ (long long unsigned) newThreadSleep);
+
+ newThreadSleep = MIN(newThreadSleep, ctx->threadSleepms);
+ if(ctx->threadSleepms != newThreadSleep) {
+ report(ctx, "Changing async signer thread sleep from %llu to %llu",
+ (long long unsigned) ctx->threadSleepms,
+ (long long unsigned) newThreadSleep);
+ ctx->threadSleepms = newThreadSleep;
+ }
+ }
+}
+
+static int
+isAggrConfNeeded(rsksictx ctx) {
+ time_t now = 0;
+
+ now = time(NULL);
+
+ if ((uint64_t)ctx->tConfRequested + ctx->confInterval <= (uint64_t)now || ctx->tConfRequested == 0) {
+ ctx->tConfRequested = now;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* note: if file exists, the last hash for chaining must
+ * be read from file.
+ */
+static int
+ksiOpenSigFile(ksifile ksi) {
+ int r = 0, tmpRes = 0;
+ const char *header;
+ FILE* signatureFile = NULL;
+
+ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS)
+ header = LS12_BLOCKFILE_HEADER;
+ else
+ header = LS12_FILE_HEADER;
+
+ ksi->blockFile = ksiCreateFile(ksi->ctx, (char*) ksi->blockfilename, ksi->ctx->fileUID,
+ ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, header);
+
+ if (ksi->blockFile == NULL) {
+ r = RSGTE_IO;
+ goto done;
+ }
+
+ /* create the file for ksi signatures if needed */
+ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
+ signatureFile = ksiCreateFile(ksi->ctx, (char*) ksi->ksifilename, ksi->ctx->fileUID,
+ ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, LS12_SIGFILE_HEADER);
+
+ if (signatureFile == NULL) {
+ r = RSGTE_IO;
+ goto done;
+ }
+
+ ksi->sigFile = signatureFile;
+ queueAddNewFile(ksi->ctx, ksi);
+ }
+
+ /* we now need to obtain the last previous hash, so that
+ * we can continue the hash chain. We do not check for error
+ * as a state file error can be recovered by graceful degredation.
+ */
+ ksiReadStateFile(ksi);
+
+ if (ksi->ctx->syncMode == LOGSIG_SYNCHRONOUS) {
+ if (isAggrConfNeeded(ksi->ctx)) {
+ KSI_Config *config = NULL;
+
+ tmpRes = KSI_receiveAggregatorConfig(ksi->ctx->ksi_ctx, &config);
+ if (tmpRes == KSI_OK) {
+ handle_ksi_config(ksi->ctx, NULL, config);
+ } else {
+ reportKSIAPIErr(ksi->ctx, NULL, "KSI_receiveAggregatorConfig", tmpRes);
+ }
+ KSI_Config_free(config);
+ }
+ }
+
+done: return r;
+}
+
+/*
+ * As of some Linux and security expert I spoke to, /dev/urandom
+ * provides very strong random numbers, even if it runs out of
+ * entropy. As far as he knew, this is save for all applications
+ * (and he had good proof that I currently am not permitted to
+ * reproduce). -- rgerhards, 2013-03-04
+ */
+static void
+seedIVKSI(ksifile ksi)
+{
+ int hashlen;
+ int fd;
+ const char *rnd_device = ksi->ctx->random_source ? ksi->ctx->random_source : "/dev/urandom";
+
+ hashlen = KSI_getHashLength(ksi->hashAlg);
+ ksi->IV = malloc(hashlen); /* do NOT zero-out! */
+ /* if we cannot obtain data from /dev/urandom, we use whatever
+ * is present at the current memory location as random data. Of
+ * course, this is very weak and we should consider a different
+ * option, especially when not running under Linux (for Linux,
+ * unavailability of /dev/urandom is just a theoretic thing, it
+ * will always work...). -- TODO -- rgerhards, 2013-03-06
+ */
+ if ((fd = open(rnd_device, O_RDONLY)) >= 0) {
+ if(read(fd, ksi->IV, hashlen) == hashlen) {}; /* keep compiler happy */
+ close(fd);
+ }
+}
+
+static int
+create_signer_thread(rsksictx ctx) {
+ int r;
+ if (ctx->signer_state != SIGNER_STARTED) {
+ if ((r = pthread_mutex_init(&ctx->module_lock, 0)))
+ report(ctx, "pthread_mutex_init: %s", strerror(r));
+ ctx->signer_queue = ProtectedQueue_new(10);
+
+ ctx->signer_state = SIGNER_INIT;
+ if ((r = pthread_create(&ctx->signer_thread, NULL, signer_thread, ctx))) {
+ report(ctx, "pthread_create: %s", strerror(r));
+ ctx->signer_state = SIGNER_IDLE;
+ return RSGTE_INTERNAL;
+ }
+
+ /* Lock until init. */
+ while(*((volatile int*)&ctx->signer_state) & SIGNER_INIT);
+
+ if (ctx->signer_state != SIGNER_STARTED) {
+ return RSGTE_INTERNAL;
+ }
+ }
+
+ return RSGTE_SUCCESS;
+}
+
+rsksictx
+rsksiCtxNew(void) {
+ rsksictx ctx;
+ ctx = calloc(1, sizeof (struct rsksictx_s));
+ KSI_CTX_new(&ctx->ksi_ctx); // TODO: error check (probably via a generic macro?)
+ ctx->hasher = NULL;
+ ctx->hashAlg = KSI_getHashAlgorithmByName("default");
+ ctx->blockTimeLimit = 0;
+ ctx->bKeepTreeHashes = false;
+ ctx->bKeepRecordHashes = true;
+ ctx->max_requests = (1 << 8);
+ ctx->blockSigTimeout = 10;
+ ctx->confInterval = 3600;
+ ctx->tConfRequested = 0;
+ ctx->threadSleepms = 1000;
+ ctx->errFunc = NULL;
+ ctx->usrptr = NULL;
+ ctx->fileUID = -1;
+ ctx->fileGID = -1;
+ ctx->dirUID = -1;
+ ctx->dirGID = -1;
+ ctx->fCreateMode = 0644;
+ ctx->fDirCreateMode = 0700;
+#if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22
+ ctx->roundCount = 0;
+ ctx->bRoundLock = 0;
+#endif
+ ctx->syncMode = LOGSIG_SYNCHRONOUS;
+ ctx->signer_state = SIGNER_IDLE;
+ ctx->disabled = false;
+ ctx->ksi = NULL;
+
+ /*if (pthread_mutex_init(&ctx->module_lock, 0))
+ report(ctx, "pthread_mutex_init: %s", strerror(errno));
+ ctx->signer_queue = ProtectedQueue_new(10);*/
+
+ /* Creating a thread this way works only in daemon mode but not when being run
+ interactively when not forked */
+ /*ret = pthread_atfork(NULL, NULL, create_signer_thread);
+ if (ret != 0)
+ report(ctx, "pthread_atfork error: %s", strerror(ret));*/
+
+ return ctx;
+}
+
+static
+int rsksiStreamLogger(void *logCtx, int logLevel, const char *message)
+{
+ char time_buf[32];
+ struct tm *tm_info;
+ time_t timer;
+ FILE *f = (FILE *)logCtx;
+
+ timer = time(NULL);
+
+ tm_info = localtime(&timer);
+ if (tm_info == NULL) {
+ return KSI_UNKNOWN_ERROR;
+ }
+
+ if (f != NULL) {
+ flockfile(f); /* for thread safety */
+ if (strftime(time_buf, sizeof(time_buf), "%d.%m.%Y %H:%M:%S", tm_info)) {
+ if (fprintf(f, "%s [%s] %lu - %s\n", level2str(logLevel),
+ time_buf, pthread_self(), message) > 0) { }
+ }
+ funlockfile(f);
+ }
+
+ return KSI_OK;
+}
+
+int
+rsksiInitModule(rsksictx ctx) {
+ int res = 0;
+
+ if(ctx->debugFileName != NULL) {
+ ctx->debugFile = fopen(ctx->debugFileName, "w");
+ if(ctx->debugFile) {
+ res = KSI_CTX_setLoggerCallback(ctx->ksi_ctx, rsksiStreamLogger, ctx->debugFile);
+ if (res != KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res);
+ res = KSI_CTX_setLogLevel(ctx->ksi_ctx, ctx->debugLevel);
+ if (res != KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "Unable to set log level", res);
+ }
+ else {
+ report(ctx, "Could not open logfile %s: %s", ctx->debugFileName, strerror(errno));
+ }
+ }
+
+ KSI_CTX_setOption(ctx->ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void*)((size_t)ctx->hmacAlg));
+
+ return create_signer_thread(ctx);
+}
+
+/* either returns ksifile object or NULL if something went wrong */
+ksifile
+rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn)
+{
+ int ret = RSGTE_INTERNAL;
+ ksifile ksi;
+ char fn[MAXFNAME+1];
+
+ if (ctx->disabled)
+ return NULL;
+
+ pthread_mutex_lock(&ctx->module_lock);
+
+ /* The thread cannot be be created in rsksiCtxNew because in daemon mode the
+ process forks after rsksiCtxNew and the thread disappears */
+ if (ctx->signer_state != SIGNER_STARTED) {
+ ret = rsksiInitModule(ctx);
+ if (ret != RSGTE_SUCCESS) {
+ report(ctx, "Unable to init. KSI module, signing service disabled");
+ ctx->disabled = true;
+ pthread_mutex_unlock(&ctx->module_lock);
+ return NULL;
+ }
+ }
+
+ if ((ksi = rsksifileConstruct(ctx)) == NULL)
+ goto done;
+
+ snprintf(fn, sizeof (fn), "%s.ksistate", logfn);
+ fn[MAXFNAME] = '\0'; /* be on safe side */
+ ksi->statefilename = (uchar*) strdup(fn);
+
+ if (ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
+ /* filename for blocks of hashes*/
+ snprintf(fn, sizeof (fn), "%s%s", logfn, blockFileSuffix);
+ fn[MAXFNAME] = '\0'; /* be on safe side */
+ ksi->blockfilename = (uchar*) strdup(fn);
+
+ /* filename for KSI signatures*/
+ snprintf(fn, sizeof (fn), "%s%s", logfn, sigFileSuffix);
+ fn[MAXFNAME] = '\0'; /* be on safe side */
+ ksi->ksifilename = (uchar*) strdup(fn);
+ } else if (ctx->syncMode == LOGSIG_SYNCHRONOUS) {
+ snprintf(fn, sizeof (fn), "%s%s", logfn, ls12FileSuffix);
+ fn[MAXFNAME] = '\0'; /* be on safe side */
+ ksi->blockfilename = (uchar*) strdup(fn);
+ }
+
+ if (ksiOpenSigFile(ksi) != 0) {
+ reportErr(ctx, "signature file open failed");
+ /* Free memory */
+ free(ksi);
+ ksi = NULL;
+ }
+
+done:
+ /* Register ksi file in rsksictx for keeping track of block timeouts. */
+ rsksiRegisterKsiFile(ctx, ksi);
+ pthread_mutex_unlock(&ctx->module_lock);
+ return ksi;
+}
+
+
+/* Returns RSGTE_SUCCESS on success, error code otherwise. If algo is unknown or
+ * is not trusted, default hash function is used.
+ */
+int
+rsksiSetHashFunction(rsksictx ctx, char *algName) {
+ if (ctx == NULL || algName == NULL) {
+ return RSGTE_INTERNAL;
+ }
+
+ int r, id = KSI_getHashAlgorithmByName(algName);
+ if (!KSI_isHashAlgorithmSupported(id)) {
+ report(ctx, "Hash function '%s' is not supported - using default", algName);
+ ctx->hashAlg = KSI_getHashAlgorithmByName("default");
+ } else {
+ if(!KSI_isHashAlgorithmTrusted(id)) {
+ report(ctx, "Hash function '%s' is not trusted - using default", algName);
+ ctx->hashAlg = KSI_getHashAlgorithmByName("default");
+ }
+ else
+ ctx->hashAlg = id;
+ }
+
+ if ((r = KSI_DataHasher_open(ctx->ksi_ctx, ctx->hashAlg, &ctx->hasher)) != KSI_OK) {
+ reportKSIAPIErr(ctx, NULL, "KSI_DataHasher_open", r);
+ ctx->disabled = true;
+ return r;
+ }
+
+ return RSGTE_SUCCESS;
+}
+
+int
+rsksiSetHmacFunction(rsksictx ctx, char *algName) {
+ int id = KSI_getHashAlgorithmByName(algName);
+ if (!KSI_isHashAlgorithmSupported(id)) {
+ report(ctx, "HMAC function '%s' is not supported - using default", algName);
+ ctx->hmacAlg = KSI_getHashAlgorithmByName("default");
+ } else {
+ if(!KSI_isHashAlgorithmTrusted(id)) {
+ report(ctx, "HMAC function '%s' is not trusted - using default", algName);
+ ctx->hmacAlg = KSI_getHashAlgorithmByName("default");
+ }
+ else
+ ctx->hmacAlg = id;
+ }
+ return 0;
+}
+
+int
+rsksifileDestruct(ksifile ksi) {
+ int r = 0;
+ rsksictx ctx = NULL;
+ if (ksi == NULL)
+ return RSGTE_INTERNAL;
+
+ pthread_mutex_lock(&ksi->ctx->module_lock);
+
+ ctx = ksi->ctx;
+
+ /* Deregister ksifile so it is not used by signer thread anymore. Note that files are not closed yet! */
+ rsksiDeregisterKsiFile(ctx, ksi);
+
+ if (!ksi->disabled && ksi->bInBlk) {
+ sigblkAddMetadata(ksi, blockCloseReason, "Block closed due to file closure.");
+ r = sigblkFinishKSI(ksi);
+ }
+ /* Note that block file is closed immediately but signature file will be closed
+ * by the signer thread scheduled by signer thread work queue.
+ */
+ if(!ksi->disabled)
+ r = ksiCloseSigFile(ksi);
+ free(ksi->blockfilename);
+ free(ksi->statefilename);
+ free(ksi->ksifilename);
+
+ free(ksi);
+
+ pthread_mutex_unlock(&ctx->module_lock);
+ return r;
+}
+
+/* This can only be used when signer thread has terminated or within the thread. */
+static void
+rsksifileForceFree(ksifile ksi) {
+ if (ksi == NULL) return;
+
+ if (ksi->sigFile != NULL) fclose(ksi->sigFile);
+ if (ksi->blockFile != NULL) fclose(ksi->blockFile);
+ free(ksi->blockfilename);
+ free(ksi->statefilename);
+ free(ksi->ksifilename);
+ free(ksi);
+ return;
+}
+
+/* This can only be used when signer thread has terminated or within the thread. */
+static void
+rsksictxForceFreeSignatures(rsksictx ctx) {
+ size_t i = 0;
+
+ if (ctx == NULL || ctx->ksi == NULL) return;
+
+ for (i = 0; i < ctx->ksiCount; i++) {
+ if (ctx->ksi[i] != NULL) {
+ rsksifileForceFree(ctx->ksi[i]);
+ ctx->ksi[i] = NULL;
+ }
+ }
+
+ ctx->ksiCount = 0;
+ return;
+}
+
+/* This can only be used when signer thread has terminated or within the thread. */
+static int
+rsksictxForceCloseWithoutSig(rsksictx ctx, const char *reason) {
+ size_t i = 0;
+ if (ctx == NULL || ctx->ksi == NULL) return RSGTE_INTERNAL;
+ for (i = 0; i < ctx->ksiCount; i++) {
+ if (ctx->ksi[i] != NULL) {
+ int ret = RSGTE_INTERNAL;
+
+ /* Only if block contains records, create metadata, close the block and add
+ * no signature marker. Closing block without record will produce redundant
+ * blocks that needs to be signed afterward.
+ */
+ if (ctx->ksi[i]->nRecords > 0) {
+ ret = sigblkFinishKSINoSignature(ctx->ksi[i], reason);
+ if (ret != RSGTE_SUCCESS) return ret;
+ }
+
+ /* Free files and remove object from the list. */
+ rsksifileForceFree(ctx->ksi[i]);
+ ctx->ksi[i] = NULL;
+ }
+ }
+
+ ctx->ksiCount = 0;
+ return RSGTE_SUCCESS;
+}
+
+void
+rsksiCtxDel(rsksictx ctx) {
+ if (ctx == NULL)
+ return;
+
+ /* Note that even in sync. mode signer thread is created and needs to be closed
+ * correctly.
+ */
+ if (ctx->signer_state == SIGNER_STARTED) {
+ queueAddQuit(ctx);
+ /* Wait until thread closes to be able to safely free the resources. */
+ pthread_join(ctx->signer_thread, NULL);
+ ProtectedQueue_free(ctx->signer_queue);
+ pthread_mutex_destroy(&ctx->module_lock);
+ }
+
+ free(ctx->aggregatorUri);
+ free(ctx->aggregatorId);
+ free(ctx->aggregatorKey);
+ free(ctx->debugFileName);
+
+ if (ctx->random_source)
+ free(ctx->random_source);
+
+ KSI_DataHasher_free(ctx->hasher);
+ KSI_CTX_free(ctx->ksi_ctx);
+
+ if(ctx->debugFile!=NULL)
+ fclose(ctx->debugFile);
+
+ /* After signer thread is terminated there should be no open signature files,
+ * but to be extra sure that all files are closed, recheck the list of opened
+ * signature files.
+ */
+ rsksictxForceFreeSignatures(ctx);
+ free(ctx->ksi);
+
+ free(ctx);
+}
+
+/* new sigblk is initialized, but maybe in existing ctx */
+void
+sigblkInitKSI(ksifile ksi)
+{
+ if(ksi == NULL) goto done;
+ seedIVKSI(ksi);
+ memset(ksi->roots, 0, sizeof (ksi->roots));
+ ksi->nRoots = 0;
+ ksi->nRecords = 0;
+ ksi->bInBlk = 1;
+ ksi->blockStarted = time(NULL); //TODO: maybe milli/nanoseconds should be used
+ ksi->blockSizeLimit = 1 << (ksi->ctx->effectiveBlockLevelLimit - 1);
+
+ /* flush the optional debug file when starting a new block */
+ if(ksi->ctx->debugFile != NULL)
+ fflush(ksi->ctx->debugFile);
+
+done:
+ return;
+}
+
+int
+sigblkCreateMask(ksifile ksi, KSI_DataHash **m) {
+ int r = 0;
+
+ CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
+ CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1));
+ CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->IV, KSI_getHashLength(ksi->hashAlg)));
+ CHKr(KSI_DataHasher_close(ksi->ctx->hasher, m));
+
+done:
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r);
+ r = RSGTE_HASH_CREATE;
+ }
+ return r;
+}
+int
+sigblkCreateHash(ksifile ksi, KSI_DataHash **out, const uchar *rec, const size_t len) {
+ int r = 0;
+
+ CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
+ CHKr(KSI_DataHasher_add(ksi->ctx->hasher, rec, len));
+ CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out));
+
+done:
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r);
+ r = RSGTE_HASH_CREATE;
+ }
+
+ return r;
+}
+
+
+int
+sigblkHashTwoNodes(ksifile ksi, KSI_DataHash **out, KSI_DataHash *left, KSI_DataHash *right,
+ uint8_t level) {
+ int r = 0;
+
+ CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
+ CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, left));
+ CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, right));
+ CHKr(KSI_DataHasher_add(ksi->ctx->hasher, &level, 1));
+ CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out));
+
+done:
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_create", r);
+ r = RSGTE_HASH_CREATE;
+ }
+
+ return r;
+}
+int
+sigblkAddMetadata(ksifile ksi, const char *key, const char *value) {
+ unsigned char buffer[0xFFFF];
+ size_t encoded_size = 0;
+ int ret = 0;
+
+ tlvCreateMetadata(ksi, ksi->nRecords, key, value, buffer, &encoded_size);
+ sigblkAddLeaf(ksi, buffer, encoded_size, true);
+
+ return ret;
+}
+
+int
+sigblkAddRecordKSI(ksifile ksi, const uchar *rec, const size_t len) {
+ int ret = 0;
+ if (ksi == NULL || ksi->disabled)
+ return 0;
+
+ pthread_mutex_lock(&ksi->ctx->module_lock);
+
+ if ((ret = sigblkAddLeaf(ksi, rec, len, false)) != 0)
+ goto done;
+
+ if (ksi->nRecords == ksi->blockSizeLimit) {
+ sigblkFinishKSI(ksi);
+ sigblkInitKSI(ksi);
+ }
+
+done:
+ pthread_mutex_unlock(&ksi->ctx->module_lock);
+ return ret;
+}
+
+
+int
+sigblkAddLeaf(ksifile ksi, const uchar *leafData, const size_t leafLength, bool metadata) {
+
+ KSI_DataHash *mask, *leafHash, *treeNode, *tmpTreeNode;
+ uint8_t j;
+ const unsigned char *pTmp;
+ size_t len;
+
+ int r = 0;
+
+ if (ksi == NULL || ksi->disabled) goto done;
+ CHKr(sigblkCreateMask(ksi, &mask));
+ CHKr(sigblkCreateHash(ksi, &leafHash, leafData, leafLength));
+
+ if(ksi->nRecords == 0)
+ tlvWriteBlockHdrKSI(ksi);
+
+ /* metadata record has to be written into the block file too*/
+ if (metadata)
+ tlvWriteOctetString(ksi->blockFile, leafData, leafLength);
+
+ if (ksi->bKeepRecordHashes)
+ tlvWriteHashKSI(ksi, 0x0902, leafHash);
+
+ /* normal leaf and metadata record are hashed in different order */
+ if (!metadata) { /* hash leaf */
+ if ((r = sigblkHashTwoNodes(ksi, &treeNode, mask, leafHash, 1)) != 0) goto done;
+ } else {
+ if ((r = sigblkHashTwoNodes(ksi, &treeNode, leafHash, mask, 1)) != 0) goto done;
+ }
+
+ /* persists x here if Merkle tree needs to be persisted! */
+ if(ksi->bKeepTreeHashes)
+ tlvWriteHashKSI(ksi, 0x0903, treeNode);
+
+ KSI_DataHash_getImprint(treeNode, &pTmp, &len);
+ memcpy(ksi->lastLeaf, pTmp, len);
+
+ for(j = 0 ; j < ksi->nRoots ; ++j) {
+ if (ksi->roots[j] == NULL) {
+ ksi->roots[j] = treeNode;
+ treeNode = NULL;
+ break;
+ } else if (treeNode != NULL) {
+ /* hash interim node */
+ tmpTreeNode = treeNode;
+ r = sigblkHashTwoNodes(ksi, &treeNode, ksi->roots[j], tmpTreeNode, j + 2);
+ KSI_DataHash_free(ksi->roots[j]);
+ ksi->roots[j] = NULL;
+ KSI_DataHash_free(tmpTreeNode);
+ if (r != 0) goto done;
+ if(ksi->bKeepTreeHashes)
+ tlvWriteHashKSI(ksi, 0x0903, treeNode);
+ }
+ }
+ if (treeNode != NULL) {
+ /* new level, append "at the top" */
+ ksi->roots[ksi->nRoots] = treeNode;
+ ++ksi->nRoots;
+ assert(ksi->nRoots < MAX_ROOTS);
+ treeNode = NULL;
+ }
+ ++ksi->nRecords;
+
+ /* cleanup (x is cleared as part of the roots array) */
+ KSI_DataHash_free(mask);
+ KSI_DataHash_free(leafHash);
+
+done:
+ return r;
+}
+
+static int
+sigblkCheckTimeOut(rsksictx ctx) {
+ int ret = RSGTE_INTERNAL;
+ time_t now;
+ char buf[KSI_BUF_SIZE];
+ size_t i = 0;
+
+ if (ctx == NULL) {
+ return RSGTE_INTERNAL;
+ }
+
+ pthread_mutex_lock(&ctx->module_lock);
+
+ if (ctx->ksi == NULL || ctx->disabled || !ctx->blockTimeLimit) {
+ ret = RSGTE_SUCCESS;
+ goto done;
+ }
+
+ now = time(NULL);
+
+ for (i = 0; i < ctx->ksiCount; i++) {
+ ksifile ksi = ctx->ksi[i];
+
+ if (ksi == NULL) continue; /* To avoide unexpected crash. */
+ if (!ksi->bInBlk) continue; /* Not inside a block, nothing to close nor sign. */
+ if ((time_t) (ksi->blockStarted + ctx->blockTimeLimit) > now) continue;
+
+ snprintf(buf, KSI_BUF_SIZE, "Block closed due to reaching time limit %d", ctx->blockTimeLimit);
+ sigblkAddMetadata(ksi, blockCloseReason, buf);
+ sigblkFinishKSI(ksi);
+ sigblkInitKSI(ksi);
+ }
+
+done:
+ pthread_mutex_unlock(&ctx->module_lock);
+ return ret;
+}
+
+
+static int
+sigblkSign(ksifile ksi, KSI_DataHash *hash, int level)
+{
+ unsigned char *der = NULL;
+ size_t lenDer = 0;
+ int r = KSI_OK;
+ int ret = 0;
+ KSI_Signature *sig = NULL;
+
+ /* Sign the root hash. */
+ r = KSI_Signature_signAggregated(ksi->ctx->ksi_ctx, hash, level, &sig);
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_createAggregated", r);
+ ret = 1;
+ goto signing_done;
+ }
+
+ /* Serialize Signature. */
+ r = KSI_Signature_serialize(sig, &der, &lenDer);
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_serialize", r);
+ ret = 1;
+ lenDer = 0;
+ goto signing_done;
+ }
+
+signing_done:
+ /* if signing failed the signature will be written as zero size */
+ if (r == KSI_OK) {
+ r = tlvWriteKSISigLS12(ksi->blockFile, ksi->nRecords, der, lenDer);
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteKSISigLS12", r);
+ ret = 1;
+ }
+ } else
+ r = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, hash, KSI_getErrorString(r));
+
+ if (r != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteBlockSigKSI", r);
+ ret = 1;
+ }
+
+ if (sig != NULL)
+ KSI_Signature_free(sig);
+ if (der != NULL)
+ KSI_free(der);
+ return ret;
+}
+
+unsigned
+sigblkCalcLevel(unsigned leaves) {
+ unsigned level = 0;
+ unsigned c = leaves;
+ while (c > 1) {
+ level++;
+ c >>= 1;
+ }
+
+ if (1 << level < (int)leaves)
+ level++;
+
+ return level;
+}
+
+static int
+sigblkFinishTree(ksifile ksi, KSI_DataHash **hsh) {
+ int ret = RSGTE_INTERNAL;
+ KSI_DataHash *root = NULL;
+ KSI_DataHash *rootDel = NULL;
+ int8_t j = 0;
+
+ if (ksi == NULL || hsh == NULL) {
+ goto done;
+ }
+
+ if (ksi->nRecords == 0) {
+ ret = RSGTE_SUCCESS;
+ goto done;
+ }
+
+ root = NULL;
+ for(j = 0 ; j < ksi->nRoots ; ++j) {
+ if(root == NULL) {
+ root = ksi->roots[j];
+ ksi->roots[j] = NULL;
+ } else if (ksi->roots[j] != NULL) {
+ rootDel = root;
+ root = NULL;
+ ret = sigblkHashTwoNodes(ksi, &root, ksi->roots[j], rootDel, j + 2);
+ KSI_DataHash_free(ksi->roots[j]);
+ ksi->roots[j] = NULL;
+ KSI_DataHash_free(rootDel);
+ rootDel = NULL;
+ if(ksi->bKeepTreeHashes) {
+ tlvWriteHashKSI(ksi, 0x0903, root);
+ }
+ if(ret != KSI_OK) goto done; /* checks sigblkHashTwoNodes() result! */
+ }
+ }
+
+ *hsh = root;
+ root = NULL;
+ ret = RSGTE_SUCCESS;
+
+done:
+ KSI_DataHash_free(root);
+ KSI_DataHash_free(rootDel);
+ return ret;
+}
+
+
+int
+sigblkFinishKSI(ksifile ksi)
+{
+ KSI_DataHash *root = NULL;
+ int ret = RSGTE_INTERNAL;
+ unsigned level = 0;
+
+ if (ksi == NULL) {
+ goto done;
+ }
+
+ if (ksi->nRecords == 0) {
+ ret = RSGTE_SUCCESS;
+ goto done;
+ }
+
+ ret = sigblkFinishTree(ksi, &root);
+ if (ret != RSGTE_SUCCESS) goto done;
+
+ //Multiplying leaves count by 2 to account for blinding masks
+ level=sigblkCalcLevel(2 * ksi->nRecords);
+
+ //in case of async mode we append the root hash to signer queue
+ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
+ ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, NULL);
+ if (ret != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
+ goto done;
+ }
+
+ queueAddSignRequest(ksi->ctx, ksi, root, level);
+ root = NULL;
+ } else {
+ sigblkSign(ksi, root, level);
+ }
+
+ ret = RSGTE_SUCCESS;
+
+done:
+ KSI_DataHash_free(root);
+ free(ksi->IV);
+ ksi->IV = NULL;
+ ksi->bInBlk = 0;
+ return ret;
+}
+
+static int
+sigblkFinishKSINoSignature(ksifile ksi, const char *reason)
+{
+ KSI_DataHash *root = NULL;
+ int ret = RSGTE_INTERNAL;
+
+ if (ksi == NULL || ksi->ctx == NULL ||
+ (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS && ksi->sigFile == NULL) ||
+ ksi->blockFile == NULL || reason == NULL) {
+ goto done;
+ }
+
+ ret = sigblkAddMetadata(ksi, blockCloseReason, reason);
+ if (ret != RSGTE_SUCCESS) goto done;
+
+ ret = sigblkFinishTree(ksi, &root);
+ if (ret != RSGTE_SUCCESS) goto done;
+
+ ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, reason);
+ if (ret != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
+ goto done;
+ }
+
+ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
+ ret = tlvWriteNoSigLS12(ksi->sigFile, ksi->nRecords, root, reason);
+ if (ret != KSI_OK) {
+ reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
+ goto done;
+ }
+ }
+
+ ret = RSGTE_SUCCESS;
+
+done:
+ KSI_DataHash_free(root);
+ free(ksi->IV);
+ ksi->IV=NULL;
+ ksi->bInBlk = 0;
+ return ret;
+}
+
+int
+rsksiSetAggregator(rsksictx ctx, char *uri, char *loginid, char *key) {
+ int r;
+ char *strTmp, *strTmpUri;
+
+ /* only use the strings if they are not empty */
+ ctx->aggregatorUri = (uri != NULL && strlen(uri) != 0) ? strdup(uri) : NULL;
+ ctx->aggregatorId = (loginid != NULL && strlen(loginid) != 0) ? strdup(loginid) : NULL;
+ ctx->aggregatorKey = (key != NULL && strlen(key) != 0) ? strdup(key) : NULL;
+
+ /* split the URI string up for possible HA endpoints */
+ strTmp = ctx->aggregatorUri;
+ while((strTmpUri = strsep(&strTmp, "|") ) != NULL) {
+ if(ctx->aggregatorEndpointCount >= KSI_CTX_HA_MAX_SUBSERVICES) {
+ report(ctx, "Maximum number (%d) of service endoints reached, ignoring endpoint: %s",
+ KSI_CTX_HA_MAX_SUBSERVICES, strTmpUri);
+ }
+ else {
+ ctx->aggregatorEndpoints[ctx->aggregatorEndpointCount] = strTmpUri;
+ ctx->aggregatorEndpointCount++;
+ }
+ }
+
+ r = KSI_CTX_setAggregator(ctx->ksi_ctx, ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey);
+ if(r != KSI_OK) {
+ ctx->disabled = true;
+ reportKSIAPIErr(ctx, NULL, "KSI_CTX_setAggregator", r);
+ return KSI_INVALID_ARGUMENT;
+ }
+
+ return r;
+}
+
+
+int
+rsksiSetDebugFile(rsksictx ctx, char *val) {
+ if(!val)
+ return KSI_INVALID_ARGUMENT;
+
+ ctx->debugFileName=strdup(val);
+ return KSI_OK;
+}
+
+static bool
+add_queue_item(rsksictx ctx, QITEM_type type, KSI_DataHash *root, FILE *sigFile, uint64_t intarg1, uint64_t intarg2) {
+ QueueItem *qi = (QueueItem*) malloc(sizeof (QueueItem));
+ if (!qi) {
+ ctx->disabled = true;
+ return false;
+ }
+
+ qi->root = root;
+ qi->file = sigFile;
+
+ qi->type = type;
+ qi->status = QITEM_WAITING;
+ qi->intarg1 = intarg1;
+ qi->intarg2 = intarg2;
+ qi->respHandle = NULL;
+ qi->ksi_status = KSI_UNKNOWN_ERROR;
+ qi->request_time = time(NULL);
+ if (ProtectedQueue_addItem(ctx->signer_queue, qi) == false) {
+ ctx->disabled = true;
+ free(qi);
+ return false;
+ }
+ return true;
+}
+
+static bool
+queueAddCloseFile(rsksictx ctx, ksifile ksi) {
+ return add_queue_item(ctx, QITEM_CLOSE_FILE, NULL, ksi->sigFile, 0, 0);
+}
+
+static bool
+queueAddNewFile(rsksictx ctx, ksifile ksi) {
+ return add_queue_item(ctx, QITEM_NEW_FILE, NULL, ksi->sigFile, time(NULL) + ctx->blockTimeLimit, 0);
+}
+
+static bool
+queueAddQuit(rsksictx ctx) {
+ return add_queue_item(ctx, QITEM_QUIT, NULL, NULL, 0, 0);
+}
+
+static bool
+queueAddSignRequest(rsksictx ctx, ksifile ksi, KSI_DataHash *root, unsigned level) {
+ return add_queue_item(ctx, QITEM_SIGNATURE_REQUEST, root, ksi->sigFile, ksi->nRecords, level);
+}
+
+static bool
+save_response(rsksictx ctx, FILE* outfile, QueueItem *item) {
+ bool ret = false;
+ KSI_Signature *sig = NULL;
+ unsigned char *raw = NULL;
+ size_t raw_len;
+ int res = KSI_OK;
+
+ if(item->respHandle != NULL && item->ksi_status == KSI_OK) {
+ CHECK_KSI_API(KSI_AsyncHandle_getSignature(item->respHandle, &sig), ctx,
+ "KSI_AsyncHandle_getSignature");
+ CHECK_KSI_API(KSI_Signature_serialize(sig, &raw, &raw_len), ctx,
+ "KSI_Signature_serialize");
+ tlvWriteKSISigLS12(outfile, item->intarg1, raw, raw_len);
+ KSI_free(raw);
+ }
+ else {
+ tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(item->ksi_status));
+ }
+ ret = true;
+
+cleanup:
+ if(res != KSI_OK)
+ tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(res));
+
+ KSI_Signature_free(sig);
+
+ return ret;
+}
+
+static KSI_DataHash* clone_hash(KSI_CTX *ksi_ctx, const KSI_DataHash* hash) {
+ int res = KSI_UNKNOWN_ERROR;
+ const unsigned char *imprint = NULL;
+ size_t imprint_len = 0;
+ KSI_DataHash* tmp = NULL;
+
+ if (hash == NULL) return NULL;
+ res = KSI_DataHash_getImprint(hash, &imprint, &imprint_len);
+ if (res != KSI_OK) return NULL;
+ res = KSI_DataHash_fromImprint(ksi_ctx, imprint, imprint_len, &tmp);
+ if (res != KSI_OK) return NULL;
+
+ return tmp;
+}
+
+static bool
+process_requests_async(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) {
+ bool ret = false;
+ QueueItem *item = NULL;
+ int res = KSI_OK, tmpRes;
+ KSI_AsyncHandle *reqHandle = NULL;
+ KSI_AsyncHandle *respHandle = NULL;
+ KSI_DataHash *clonedHash = NULL;
+ KSI_AggregationReq *req = NULL;
+ KSI_Config *config = NULL;
+ KSI_Integer *level;
+ long extError;
+ KSI_Utf8String *errorMsg;
+ int state, ksi_status;
+ unsigned i;
+ size_t p;
+
+ KSI_AsyncService_getPendingCount(as, &p);
+
+ /* Check if there are pending/available responses and associate them with the request items */
+ while(true) {
+ respHandle = NULL;
+ item = NULL;
+ tmpRes=KSI_AsyncService_run(as, &respHandle, &p);
+ if(tmpRes!=KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_run", tmpRes);
+
+ if (respHandle == NULL) { /* nothing received */
+ break;
+ }
+
+#if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22
+ if (p != 0 && ctx->roundCount > 0) {
+ ctx->roundCount--;
+ } else {
+ ctx->bRoundLock = 0;
+ ctx->roundCount = 0;
+ }
+#endif
+ state = KSI_ASYNC_STATE_UNDEFINED;
+
+ CHECK_KSI_API(KSI_AsyncHandle_getState(respHandle, &state), ctx, "KSI_AsyncHandle_getState");
+
+ if(state == KSI_ASYNC_STATE_PUSH_CONFIG_RECEIVED) {
+ res = KSI_AsyncHandle_getConfig(respHandle, &config);
+ if(res == KSI_OK) {
+ handle_ksi_config(ctx, as, config);
+ KSI_AsyncHandle_free(respHandle);
+ } else
+ reportKSIAPIErr(ctx, NULL, "KSI_AsyncHandle_getConfig", res);
+ }
+ else if(state == KSI_ASYNC_STATE_RESPONSE_RECEIVED) {
+ CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void**)&item), ctx,
+ "KSI_AsyncHandle_getRequestCtx");
+ item->respHandle = respHandle;
+ item->ksi_status = KSI_OK;
+ }
+ else if(state == KSI_ASYNC_STATE_ERROR) {
+ CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void**)&item), ctx,
+ "KSI_AsyncHandle_getRequestCtx");
+ errorMsg = NULL;
+ KSI_AsyncHandle_getError(respHandle, &ksi_status);
+ KSI_AsyncHandle_getExtError(respHandle, &extError);
+ KSI_AsyncHandle_getErrorMessage(respHandle, &errorMsg);
+ report(ctx, "Asynchronous request returned error %s (%d), %lu %s",
+ KSI_getErrorString(ksi_status), ksi_status, extError,
+ errorMsg ? KSI_Utf8String_cstr(errorMsg) : "");
+ KSI_AsyncHandle_free(respHandle);
+
+ if(item)
+ item->ksi_status = ksi_status;
+ }
+
+ if(item)
+ item->status = QITEM_DONE;
+ }
+
+ KSI_AsyncService_getPendingCount(as, &p);
+
+ /* Send all the new requests in the back of the queue to the server */
+ for(i = 0; i < ProtectedQueue_count(ctx->signer_queue); i++) {
+ item = NULL;
+ if(!ProtectedQueue_getItem(ctx->signer_queue, i, (void**)&item) || !item)
+ continue;
+ /* ingore non request queue items */
+ if(item->type != QITEM_SIGNATURE_REQUEST)
+ continue;
+
+ /* stop at first processed item */
+ if(item->status != QITEM_WAITING)
+ continue;
+
+ /* Due to a bug in libksi it is possible that async signer may send out
+ * more signing requests than permitted by the gateway. Workaround is to
+ * keep track of signing requests here.
+ */
+#if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22
+ if (ctx->roundCount >= ctx->max_requests) ctx->bRoundLock = 1;
+ if (ctx->bRoundLock) break;
+#endif
+
+
+ /* The data hash is produced in another thread by another KSI_CTX and
+ * libksi internal uses KSI_DataHash cache to reduce the amount of
+ * memory allocations by recycling old objects. Lets clone the hash
+ * value with current KSI_CTX as we can not be sure that this thread is
+ * not affecting the data hash cache operated by another thread.
+ */
+ clonedHash = clone_hash(ksi_ctx, item->root);
+ CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &req), ctx, "KSI_AggregationReq_new");
+ CHECK_KSI_API(KSI_AggregationReq_setRequestHash((KSI_AggregationReq*)req,
+ clonedHash), ctx,
+ "KSI_AggregationReq_setRequestHash");
+ clonedHash = NULL;
+ CHECK_KSI_API(KSI_Integer_new(ksi_ctx, item->intarg2, &level), ctx,
+ "KSI_Integer_new");
+ CHECK_KSI_API(KSI_AggregationReq_setRequestLevel(req, level), ctx,
+ "KSI_AggregationReq_setRequestLevel");
+ CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, req, &reqHandle), ctx,
+ "KSI_AsyncAggregationHandle_new");
+ CHECK_KSI_API(KSI_AsyncHandle_setRequestCtx(reqHandle, (void*)item, NULL), ctx,
+ "KSI_AsyncRequest_setRequestContext");
+ res = KSI_AsyncService_addRequest(as, reqHandle); /* this can fail because of throttling */
+
+ if (res == KSI_OK) {
+ item->status = QITEM_SENT;
+#if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22
+ ctx->roundCount++;
+#endif
+ } else {
+ reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addRequest", res);
+ KSI_AsyncHandle_free(reqHandle);
+ item->status = QITEM_DONE;
+ item->ksi_status = res;
+ break;
+ }
+
+ if (i != 0 && i % ctx->max_requests == 0) {
+ CHECK_KSI_API(KSI_AsyncService_run(as, NULL, NULL), ctx,
+ "KSI_AsyncService_run");
+ }
+ }
+ CHECK_KSI_API(KSI_AsyncService_run(as, NULL, NULL), ctx,
+ "KSI_AsyncService_run");
+
+ /* Save all consequent fulfilled responses in the front of the queue to the signature file */
+ while(ProtectedQueue_count(ctx->signer_queue)) {
+ item = NULL;
+ if(!ProtectedQueue_getItem(ctx->signer_queue, 0, (void**)&item))
+ break;
+
+ if(!item) {
+ ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
+ continue;
+ }
+
+ /* stop at first non request queue item (maybe file close/open, quit) */
+ if(item->type!=QITEM_SIGNATURE_REQUEST)
+ break;
+
+ /* stop at first unfinished queue item because the signatures need to be ordered */
+ if(item->status != QITEM_DONE)
+ break;
+
+ ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
+ save_response(ctx, item->file, item);
+ fflush(item->file);
+ /* the main thread has to be locked when the hash is freed to avoid a race condition */
+ /* TODO: this need more elegant solution, hash should be detached from creation context*/
+ pthread_mutex_lock(&ctx->module_lock);
+ KSI_DataHash_free(item->root);
+ KSI_AsyncHandle_free(item->respHandle);
+ free(item);
+ pthread_mutex_unlock(&ctx->module_lock);
+ }
+
+ ret = true;
+
+cleanup:
+ KSI_DataHash_free(clonedHash);
+ KSI_AsyncService_getPendingCount(as, &p);
+ return ret;
+}
+
+/* This can only be used when signer thread has terminated or within the thread. */
+static bool
+rsksictxCloseAllPendingBlocksWithoutSignature(rsksictx ctx, const char *reason) {
+ bool ret = false;
+ QueueItem *item = NULL;
+ int res = KSI_OK;
+
+ /* Save all consequent fulfilled responses in the front of the queue to the signature file */
+ while(ProtectedQueue_count(ctx->signer_queue)) {
+ item = NULL;
+ ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
+
+ if(item == NULL) {
+ continue;
+ }
+
+ /* Skip non request queue item. */
+ if(item->type == QITEM_SIGNATURE_REQUEST) {
+ res = tlvWriteNoSigLS12(item->file, item->intarg1, item->root, reason);
+ if (res != KSI_OK) {
+ reportKSIAPIErr(ctx, NULL, "tlvWriteNoSigLS12", res);
+ ret = false;
+ goto cleanup;
+ }
+ fflush(item->file);
+ }
+
+ KSI_DataHash_free(item->root);
+ KSI_AsyncHandle_free(item->respHandle);
+ free(item);
+ }
+
+ ret = true;
+
+cleanup:
+ return ret;
+}
+
+
+static void
+request_async_config(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) {
+ KSI_Config *cfg = NULL;
+ KSI_AsyncHandle *cfgHandle = NULL;
+ KSI_AggregationReq *cfgReq = NULL;
+ int res;
+ bool bSuccess = false;
+
+ CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &cfgReq), ctx, "KSI_AggregationReq_new");
+ CHECK_KSI_API(KSI_Config_new(ksi_ctx, &cfg), ctx, "KSI_Config_new");
+ CHECK_KSI_API(KSI_AggregationReq_setConfig(cfgReq, cfg), ctx, "KSI_AggregationReq_setConfig");
+ CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, cfgReq, &cfgHandle), ctx,
+ "KSI_AsyncAggregationHandle_new");
+ CHECK_KSI_API(KSI_AsyncService_addRequest(as, cfgHandle), ctx, "KSI_AsyncService_addRequest");
+
+ bSuccess = true;
+
+cleanup:
+ if(!bSuccess) {
+ if(cfgHandle)
+ KSI_AsyncHandle_free(cfgHandle);
+ else if(cfgReq)
+ KSI_AggregationReq_free(cfgReq);
+ else if(cfg)
+ KSI_Config_free(cfg);
+ }
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+void *signer_thread(void *arg) {
+ int res = KSI_UNKNOWN_ERROR;
+ rsksictx ctx = (rsksictx) arg;
+ KSI_CTX *ksi_ctx = NULL;
+ KSI_AsyncService *as = NULL;
+ size_t size_t_value = 0;
+ size_t ksiFileCount = 0;
+ int endpoints = 0;
+ bool bSleep = true;
+
+
+ CHECK_KSI_API(KSI_CTX_new(&ksi_ctx), ctx, "KSI_CTX_new");
+ CHECK_KSI_API(KSI_CTX_setAggregator(ksi_ctx,
+ ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey),
+ ctx, "KSI_CTX_setAggregator");
+
+ if(ctx->debugFile) {
+ res = KSI_CTX_setLoggerCallback(ksi_ctx, rsksiStreamLogger, ctx->debugFile);
+ if (res != KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res);
+ res = KSI_CTX_setLogLevel(ksi_ctx, ctx->debugLevel);
+ if (res != KSI_OK)
+ reportKSIAPIErr(ctx, NULL, "Unable to set log level", res);
+ }
+
+ CHECK_KSI_API(KSI_CTX_setOption(ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void*)((size_t)ctx->hmacAlg)),
+ ctx, "KSI_CTX_setOption");
+
+ res = KSI_SigningHighAvailabilityService_new(ksi_ctx, &as);
+ if (res != KSI_OK) {
+ reportKSIAPIErr(ctx, NULL, "KSI_SigningAsyncService_new", res);
+ }
+ else {
+ int i = 0;
+ for (i = 0; i < ctx->aggregatorEndpointCount; i++) {
+ res = KSI_AsyncService_addEndpoint(as,
+ ctx->aggregatorEndpoints[i], ctx->aggregatorId, ctx->aggregatorKey);
+ if (res != KSI_OK) {
+ //This can fail if the protocol is not supported by async api.
+ reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addEndpoint", res);
+ continue;
+ }
+
+ endpoints++;
+ }
+ }
+
+ if(endpoints == 0) { /* no endpoint accepted, deleting the service */
+ report(ctx, "No endpoints added, signing service disabled");
+ ctx->disabled = true;
+ KSI_AsyncService_free(as);
+ as=NULL;
+ goto cleanup;
+ }
+
+ /* Lets use buffer value, as libksi requires size_t. */
+ size_t_value = ctx->max_requests;
+ KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE,
+ (void*)size_t_value);
+ size_t_value = ctx->blockSigTimeout;
+ KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_SND_TIMEOUT,
+ (void*)size_t_value);
+
+
+ ctx->signer_state = SIGNER_STARTED;
+ while (true) {
+ QueueItem *item = NULL;
+
+ if (isAggrConfNeeded(ctx)) {
+ request_async_config(ctx, ksi_ctx, as);
+ }
+
+ /* Wait for a work item or timeout*/
+ if (bSleep) {
+ ProtectedQueue_waitForItem(ctx->signer_queue, NULL, ctx->threadSleepms);
+ }
+ bSleep = true;
+
+ /* Check for block time limit. */
+ sigblkCheckTimeOut(ctx);
+
+ /* in case there are no items go around*/
+ if (ProtectedQueue_count(ctx->signer_queue) == 0) {
+ process_requests_async(ctx, ksi_ctx, as);
+ continue;
+ }
+
+ /* process signing requests only if there is an open signature file */
+ if(ksiFileCount > 0) {
+ /* check for pending/unsent requests in asynchronous service */
+ if(!process_requests_async(ctx, ksi_ctx, as)) {
+ // probably fatal error, disable signing, error should be already reported
+ ctx->disabled = true;
+ goto cleanup;
+ }
+ }
+ /* if there are sig. requests still in the front, then we have to start over*/
+ if (ProtectedQueue_peekFront(ctx->signer_queue, (void**) &item)
+ && item->type == QITEM_SIGNATURE_REQUEST)
+ continue;
+
+ /* Handle other types of work items */
+ if (ProtectedQueue_popFront(ctx->signer_queue, (void**) &item) != 0) {
+ /* There is no point to sleep after processing non request type item
+ * as there is great possibility that next item can already be
+ * processed. */
+ bSleep = false;
+
+ if (item->type == QITEM_CLOSE_FILE) {
+ if (item->file) {
+ fclose(item->file);
+ item->file = NULL;
+ }
+
+ if (ksiFileCount > 0) ksiFileCount--;
+ } else if (item->type == QITEM_NEW_FILE) {
+ ksiFileCount++;
+ } else if (item->type == QITEM_QUIT) {
+ free(item);
+
+ /* Will look into work queue for pending KSI signatures and will output
+ * unsigned block marker instead of actual KSI signature to finalize this
+ * thread quickly.
+ */
+ rsksictxCloseAllPendingBlocksWithoutSignature(ctx,
+ "Signing not finished due to sudden closure of lmsig_ksi-ls12 module.");
+ rsksictxForceCloseWithoutSig(ctx,
+ "Block closed due to sudden closure of lmsig_ksi-ls12 module.");
+
+ goto cleanup;
+ }
+
+ free(item);
+ }
+ }
+
+cleanup:
+
+ KSI_AsyncService_free(as);
+ KSI_CTX_free(ksi_ctx);
+ ctx->signer_state = SIGNER_STOPPED;
+
+ return NULL;
+}
+#pragma GCC diagnostic push
diff --git a/runtime/lib_ksils12.h b/runtime/lib_ksils12.h
new file mode 100644
index 0000000..c85ff85
--- /dev/null
+++ b/runtime/lib_ksils12.h
@@ -0,0 +1,250 @@
+/* lib_ksils12.h - rsyslog's KSI-LS12 support library
+ *
+ * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_KSILS12_H
+#define INCLUDED_KSILS12_H
+#include <ksi/ksi.h>
+
+#include "lib_ksi_queue.h"
+
+#define MAX_ROOTS 64
+
+/* Flags and record types for TLV handling */
+#define RSGT_FLAG_NONCRIT 0x20
+#define RSGT_FLAG_FORWARD 0x40
+#define RSGT_TYPE_MASK 0x1f
+#define RSGT_FLAG_TLV16 0x80
+
+/* check return state of operation and abort, if non-OK */
+#define CHKr(code) if((r = code) != 0) goto done
+
+/* check the return value of a ksi api call and log a message in case of error */
+#define CHECK_KSI_API(code, context, msg) if((res = code) != 0) do { \
+ reportKSIAPIErr(context, NULL, msg, res); \
+ goto cleanup; \
+ } while (0)
+
+
+typedef enum LOGSIG_SyncMode_en {
+ /** The block hashes and ksi signatures in one file */
+ LOGSIG_ASYNCHRONOUS = 0x00,
+ /** The block hashes and ksi signatures split into separate files */
+ LOGSIG_SYNCHRONOUS = 0x01
+} LOGSIG_SyncMode;
+
+enum {
+ /* Signer state assigned before the signer thread is initialized. State remains
+ * until thread initialization begins. In case of system failure to create new
+ * thread state remains the same.
+ */
+ SIGNER_IDLE = 0x01,
+
+ /* Signer state assigned while signer thread initialization is in progress.
+ */
+ SIGNER_INIT = 0x02,
+
+ /* Signer state assigned when signer thread is initialized and ready to work.
+ */
+ SIGNER_STARTED = 0x04,
+
+ /* Thread state assigned when signer thread is being closed (signer thread returns).
+ */
+ SIGNER_STOPPED = 0x08
+};
+
+/* Max number of roots inside the forest. This permits blocks of up to
+ * 2^MAX_ROOTS records. We assume that 64 is sufficient for all use
+ * cases ;) [and 64 is not really a waste of memory, so we do not even
+ * try to work with reallocs and such...]
+ */
+
+typedef struct rsksictx_s *rsksictx;
+typedef struct ksifile_s *ksifile;
+typedef struct ksierrctx_s ksierrctx_t;
+
+
+/* context for gt calls. This primarily serves as a container for the
+ * config settings. The actual file-specific data is kept in ksifile.
+ */
+struct rsksictx_s {
+ KSI_CTX *ksi_ctx; /* libksi's context object */
+ KSI_DataHasher *hasher;
+ KSI_HashAlgorithm hashAlg;
+ KSI_HashAlgorithm hmacAlg;
+ uint8_t bKeepRecordHashes;
+ uint8_t bKeepTreeHashes;
+ uint64_t confInterval;
+ time_t tConfRequested;
+ uint64_t blockLevelLimit;
+ uint32_t blockTimeLimit;
+ uint32_t blockSigTimeout;
+ uint32_t effectiveBlockLevelLimit; /* level limit adjusted by gateway settings */
+ uint32_t threadSleepms;
+ uint8_t syncMode;
+ uid_t fileUID; /* IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int fCreateMode; /* mode to use when creating files */
+ int fDirCreateMode; /* mode to use when creating files */
+ char* aggregatorUri;
+ char* aggregatorId;
+ char* aggregatorKey;
+ char* aggregatorEndpoints[KSI_CTX_HA_MAX_SUBSERVICES];
+ int aggregatorEndpointCount;
+ char* random_source;
+ pthread_mutex_t module_lock;
+ pthread_t signer_thread;
+ ProtectedQueue *signer_queue;
+#if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22
+ size_t roundCount; /* Count of signing requests in round. */
+ uint8_t bRoundLock; /* A lock for async. signer. */
+#endif
+ int signer_state;
+ uint8_t disabled; /* permits to disable the plugin --> set to 1 */
+
+ ksifile *ksi; /* List of signature files for keeping track of block timeouts. */
+ size_t ksiCapacity;
+ size_t ksiCount;
+
+ char *debugFileName;
+ int debugLevel;
+ FILE *debugFile;
+ uint64_t max_requests;
+ void (*errFunc)(void *, unsigned char*);
+ void (*logFunc)(void *, unsigned char*);
+ void *usrptr; /* for error function */
+};
+
+/* this describes a file, as far as librsksi is concerned */
+struct ksifile_s {
+ /* the following data items are mirrored from rsksictx to
+ * increase cache hit ratio (they are frequently accesed).
+ */
+ KSI_HashAlgorithm hashAlg;
+ uint8_t bKeepRecordHashes;
+ uint8_t bKeepTreeHashes;
+ uint64_t blockSizeLimit;
+ uint32_t blockTimeLimit;
+ /* end mirrored properties */
+ uint8_t disabled; /* permits to disable this file --> set to 1 */
+ uint8_t *IV; /* initial value for blinding masks */
+ unsigned char lastLeaf[KSI_MAX_IMPRINT_LEN]; /* last leaf hash (maybe of previous block)
+ --> preserve on term */
+ unsigned char *blockfilename;
+ unsigned char *ksifilename;
+ unsigned char *statefilename;
+ uint64_t nRecords; /* current number of records in current block */
+ uint64_t bInBlk; /* are we currently inside a blk --> need to finish on close */
+ time_t blockStarted;
+ int8_t nRoots;
+ /* algo engineering: roots structure is split into two arrays
+ * in order to improve cache hits.
+ */
+ KSI_DataHash *roots[MAX_ROOTS];
+ /* data members for the associated TLV file */
+ FILE *blockFile;
+ FILE *sigFile; /* Note that this may only be closed by signer thread or when signer thread has terminated. */
+ rsksictx ctx;
+};
+
+/* the following defines the ksistate file record. Currently, this record
+ * is fixed, we may change that over time.
+ */
+struct rsksistatefile {
+ char hdr[9]; /* must be "KSISTAT10" */
+ uint8_t hashID;
+ uint8_t lenHash;
+ /* after that, the hash value is contained within the file */
+};
+
+/* error states */
+#define RSGTE_SUCCESS 0 /* Success state */
+#define RSGTE_IO 1 /* any kind of io error */
+#define RSGTE_FMT 2 /* data fromat error */
+#define RSGTE_INVLTYP 3 /* invalid TLV type record (unexcpected at this point) */
+#define RSGTE_OOM 4 /* ran out of memory */
+#define RSGTE_LEN 5 /* error related to length records */
+#define RSGTE_SIG_EXTEND 6/* error extending signature */
+#define RSGTE_INVLD_RECCNT 7/* mismatch between actual records and records
+ given in block-sig record */
+#define RSGTE_INVLHDR 8/* invalid file header */
+#define RSGTE_EOF 9 /* specific EOF */
+#define RSGTE_MISS_REC_HASH 10 /* record hash missing when expected */
+#define RSGTE_MISS_TREE_HASH 11 /* tree hash missing when expected */
+#define RSGTE_INVLD_REC_HASH 12 /* invalid record hash (failed verification) */
+#define RSGTE_INVLD_TREE_HASH 13 /* invalid tree hash (failed verification) */
+#define RSGTE_INVLD_REC_HASHID 14 /* invalid record hash ID (failed verification) */
+#define RSGTE_INVLD_TREE_HASHID 15 /* invalid tree hash ID (failed verification) */
+#define RSGTE_MISS_BLOCKSIG 16 /* block signature record missing when expected */
+#define RSGTE_INVLD_SIGNATURE 17 /* Signature is invalid (KSI_Signature_verifyDataHash)*/
+#define RSGTE_TS_CREATEHASH 18 /* error creating HASH (KSI_DataHash_create) */
+#define RSGTE_TS_DERENCODE 19 /* error DER-Encoding a timestamp */
+#define RSGTE_HASH_CREATE 20 /* error creating a hash */
+#define RSGTE_END_OF_SIG 21 /* unexpected end of signature - more log line exist */
+#define RSGTE_END_OF_LOG 22 /* unexpected end of log file - more signatures exist */
+#define RSGTE_EXTRACT_HASH 23 /* error extracting hashes for record */
+#define RSGTE_CONFIG_ERROR 24 /* Configuration error */
+#define RSGTE_NETWORK_ERROR 25 /* Network error */
+#define RSGTE_MISS_KSISIG 26 /* KSI signature missing */
+#define RSGTE_INTERNAL 27 /* Internal error */
+
+#define getIVLenKSI(bh) (hashOutputLengthOctetsKSI((bh)->hashID))
+#define rsksiSetBlockLevelLimit(ctx, limit) ((ctx)->blockLevelLimit = (ctx)->effectiveBlockLevelLimit = limit)
+#define rsksiSetBlockTimeLimit(ctx, limit) ((ctx)->blockTimeLimit = limit)
+#define rsksiSetBlockSigTimeout(ctx, val) ((ctx)->blockSigTimeout = val)
+#define rsksiSetConfInterval(ctx, val) ((ctx)->confInterval = val)
+#define rsksiSetKeepRecordHashes(ctx, val) ((ctx)->bKeepRecordHashes = val)
+#define rsksiSetKeepTreeHashes(ctx, val) ((ctx)->bKeepTreeHashes = val)
+#define rsksiSetFileFormat(ctx, val) ((ctx)->fileFormat = val)
+#define rsksiSetSyncMode(ctx, val) ((ctx)->syncMode = val)
+#define rsksiSetRandomSource(ctx, val) ((ctx)->random_source = strdup(val))
+#define rsksiSetFileUID(ctx, val) ((ctx)->fileUID = val) /* IDs for creation */
+#define rsksiSetDirUID(ctx, val) ((ctx)->dirUID = val)
+#define rsksiSetFileGID(ctx, val) ((ctx)->fileGID= val)
+#define rsksiSetDirGID(ctx, val) ((ctx)->dirGID = val)
+#define rsksiSetCreateMode(ctx, val) ((ctx)->fCreateMode= val)
+#define rsksiSetDirCreateMode(ctx, val) ((ctx)->fDirCreateMode = val)
+#define rsksiSetDebugLevel(ctx, val) ((ctx)->debugLevel = val)
+
+
+int rsksiSetDebugFile(rsksictx ctx, char *val);
+int rsksiSetAggregator(rsksictx ctx, char *uri, char *loginid, char *key);
+int rsksiSetHashFunction(rsksictx ctx, char *algName);
+int rsksiSetHmacFunction(rsksictx ctx, char *algName);
+int rsksiInitModule(rsksictx ctx);
+rsksictx rsksiCtxNew(void);
+void rsksisetErrFunc(rsksictx ctx, void (*func)(void*, unsigned char *), void *usrptr);
+void rsksisetLogFunc(rsksictx ctx, void (*func)(void*, unsigned char *), void *usrptr);
+void reportKSIAPIErr(rsksictx ctx, ksifile ksi, const char *apiname, int ecode);
+ksifile rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn);
+int rsksifileDestruct(ksifile ksi);
+void rsksiCtxDel(rsksictx ctx);
+void sigblkInitKSI(ksifile ksi);
+int sigblkAddRecordKSI(ksifile ksi, const unsigned char *rec, const size_t len);
+int sigblkAddLeaf(ksifile ksi, const unsigned char *rec, const size_t len, bool metadata);
+unsigned sigblkCalcLevel(unsigned leaves);
+int sigblkFinishKSI(ksifile ksi);
+int sigblkAddMetadata(ksifile ksi, const char *key, const char *value);
+int sigblkCreateMask(ksifile ksi, KSI_DataHash **m);
+int sigblkCreateHash(ksifile ksi, KSI_DataHash **r, const unsigned char *rec, const size_t len);
+int sigblkHashTwoNodes(ksifile ksi, KSI_DataHash **node, KSI_DataHash *m, KSI_DataHash *r, uint8_t level);
+
+#endif /* #ifndef INCLUDED_KSILS12_H */
diff --git a/runtime/libgcry.c b/runtime/libgcry.c
new file mode 100644
index 0000000..c5a8171
--- /dev/null
+++ b/runtime/libgcry.c
@@ -0,0 +1,765 @@
+/* gcry.c - rsyslog's libgcrypt based crypto provider
+ *
+ * Copyright 2013-2018 Adiscon GmbH.
+ *
+ * We need to store some additional information in support of encryption.
+ * For this, we create a side-file, which is named like the actual log
+ * file, but with the suffix ".encinfo" appended. It contains the following
+ * records:
+ * IV:<hex> The initial vector used at block start. Also indicates start
+ * start of block.
+ * END:<int> The end offset of the block, as uint64_t in decimal notation.
+ * This is used during encryption to know when the current
+ * encryption block ends.
+ * For the current implementation, there must always be an IV record
+ * followed by an END record. Each records is LF-terminated. Record
+ * types can simply be extended in the future by specifying new
+ * types (like "IV") before the colon.
+ * To identify a file as rsyslog encryption info file, it must start with
+ * the line "FILETYPE:rsyslog-enrcyption-info"
+ * There are some size constraints: the recordtype must be 31 bytes at
+ * most and the actual value (between : and LF) must be 1023 bytes at most.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <gcrypt.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "debug.h"
+#include "libgcry.h"
+
+#define READBUF_SIZE 4096 /* size of the read buffer */
+
+static rsRetVal rsgcryBlkBegin(gcryfile gf);
+
+int
+rsgcryAlgoname2Algo(char *const __restrict__ algoname)
+{
+ if(!strcmp((char*)algoname, "3DES")) return GCRY_CIPHER_3DES;
+ if(!strcmp((char*)algoname, "CAST5")) return GCRY_CIPHER_CAST5;
+ if(!strcmp((char*)algoname, "BLOWFISH")) return GCRY_CIPHER_BLOWFISH;
+ if(!strcmp((char*)algoname, "AES128")) return GCRY_CIPHER_AES128;
+ if(!strcmp((char*)algoname, "AES192")) return GCRY_CIPHER_AES192;
+ if(!strcmp((char*)algoname, "AES256")) return GCRY_CIPHER_AES256;
+ if(!strcmp((char*)algoname, "TWOFISH")) return GCRY_CIPHER_TWOFISH;
+ if(!strcmp((char*)algoname, "TWOFISH128")) return GCRY_CIPHER_TWOFISH128;
+ if(!strcmp((char*)algoname, "ARCFOUR")) return GCRY_CIPHER_ARCFOUR;
+ if(!strcmp((char*)algoname, "DES")) return GCRY_CIPHER_DES;
+ if(!strcmp((char*)algoname, "SERPENT128")) return GCRY_CIPHER_SERPENT128;
+ if(!strcmp((char*)algoname, "SERPENT192")) return GCRY_CIPHER_SERPENT192;
+ if(!strcmp((char*)algoname, "SERPENT256")) return GCRY_CIPHER_SERPENT256;
+ if(!strcmp((char*)algoname, "RFC2268_40")) return GCRY_CIPHER_RFC2268_40;
+ if(!strcmp((char*)algoname, "SEED")) return GCRY_CIPHER_SEED;
+ if(!strcmp((char*)algoname, "CAMELLIA128")) return GCRY_CIPHER_CAMELLIA128;
+ if(!strcmp((char*)algoname, "CAMELLIA192")) return GCRY_CIPHER_CAMELLIA192;
+ if(!strcmp((char*)algoname, "CAMELLIA256")) return GCRY_CIPHER_CAMELLIA256;
+ return GCRY_CIPHER_NONE;
+}
+
+int
+rsgcryModename2Mode(char *const __restrict__ modename)
+{
+ if(!strcmp((char*)modename, "ECB")) return GCRY_CIPHER_MODE_ECB;
+ if(!strcmp((char*)modename, "CFB")) return GCRY_CIPHER_MODE_CFB;
+ if(!strcmp((char*)modename, "CBC")) return GCRY_CIPHER_MODE_CBC;
+ if(!strcmp((char*)modename, "STREAM")) return GCRY_CIPHER_MODE_STREAM;
+ if(!strcmp((char*)modename, "OFB")) return GCRY_CIPHER_MODE_OFB;
+ if(!strcmp((char*)modename, "CTR")) return GCRY_CIPHER_MODE_CTR;
+# ifdef GCRY_CIPHER_MODE_AESWRAP
+ if(!strcmp((char*)modename, "AESWRAP")) return GCRY_CIPHER_MODE_AESWRAP;
+# endif
+ return GCRY_CIPHER_MODE_NONE;
+}
+static rsRetVal
+eiWriteRec(gcryfile gf, const char *recHdr, size_t lenRecHdr, const char *buf, size_t lenBuf)
+{
+ struct iovec iov[3];
+ ssize_t nwritten, towrite;
+ DEFiRet;
+
+ iov[0].iov_base = (void*)recHdr;
+ iov[0].iov_len = lenRecHdr;
+ iov[1].iov_base = (void*)buf;
+ iov[1].iov_len = lenBuf;
+ iov[2].iov_base = (void*)"\n";
+ iov[2].iov_len = 1;
+ towrite = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
+ nwritten = writev(gf->fd, iov, sizeof(iov)/sizeof(struct iovec));
+ if(nwritten != towrite) {
+ DBGPRINTF("eiWrite%s: error writing file, towrite %d, "
+ "nwritten %d\n", recHdr, (int) towrite, (int) nwritten);
+ ABORT_FINALIZE(RS_RET_EI_WR_ERR);
+ }
+ DBGPRINTF("encryption info file %s: written %s, len %d\n",
+ recHdr, gf->eiName, (int) nwritten);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+eiOpenRead(gcryfile gf)
+{
+ DEFiRet;
+ gf->fd = open((char*)gf->eiName, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+ if(gf->fd == -1) {
+ ABORT_FINALIZE(errno == ENOENT ? RS_RET_EI_NO_EXISTS : RS_RET_EI_OPN_ERR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+eiRead(gcryfile gf)
+{
+ ssize_t nRead;
+ DEFiRet;
+
+ if(gf->readBuf == NULL) {
+ CHKmalloc(gf->readBuf = malloc(READBUF_SIZE));
+ }
+
+ nRead = read(gf->fd, gf->readBuf, READBUF_SIZE);
+ if(nRead <= 0) { /* TODO: provide specific EOF case? */
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ gf->readBufMaxIdx = (int16_t) nRead;
+ gf->readBufIdx = 0;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* returns EOF on any kind of error */
+static int
+eiReadChar(gcryfile gf)
+{
+ int c;
+
+ if(gf->readBufIdx >= gf->readBufMaxIdx) {
+ if(eiRead(gf) != RS_RET_OK) {
+ c = EOF;
+ goto finalize_it;
+ }
+ }
+ c = gf->readBuf[gf->readBufIdx++];
+finalize_it:
+ return c;
+}
+
+
+static rsRetVal
+eiCheckFiletype(gcryfile gf)
+{
+ char hdrBuf[128];
+ size_t toRead, didRead;
+ sbool bNeedClose = 0;
+ DEFiRet;
+
+ if(gf->fd == -1) {
+ CHKiRet(eiOpenRead(gf));
+ assert(gf->fd != -1); /* cannot happen after successful return */
+ bNeedClose = 1;
+ }
+
+ if(Debug) memset(hdrBuf, 0, sizeof(hdrBuf)); /* for dbgprintf below! */
+ toRead = sizeof("FILETYPE:")-1 + sizeof(RSGCRY_FILETYPE_NAME)-1 + 1;
+ didRead = read(gf->fd, hdrBuf, toRead);
+ if(bNeedClose) {
+ close(gf->fd);
+ gf->fd = -1;
+ }
+ DBGPRINTF("eiCheckFiletype read %zd bytes: '%s'\n", didRead, hdrBuf);
+ if( didRead != toRead
+ || strncmp(hdrBuf, "FILETYPE:" RSGCRY_FILETYPE_NAME "\n", toRead))
+ iRet = RS_RET_EI_INVLD_FILE;
+finalize_it:
+ RETiRet;
+}
+
+/* rectype/value must be EIF_MAX_*_LEN+1 long!
+ * returns 0 on success or something else on error/EOF
+ */
+static rsRetVal
+eiGetRecord(gcryfile gf, char *rectype, char *value)
+{
+ unsigned short i, j;
+ int c;
+ DEFiRet;
+
+ c = eiReadChar(gf);
+ if(c == EOF) { ABORT_FINALIZE(RS_RET_NO_DATA); }
+ for(i = 0 ; i < EIF_MAX_RECTYPE_LEN ; ++i) {
+ if(c == ':' || c == EOF)
+ break;
+ rectype[i] = c;
+ c = eiReadChar(gf);
+ }
+ if(c != ':') { ABORT_FINALIZE(RS_RET_ERR); }
+ rectype[i] = '\0';
+ j = 0;
+ for(++i ; i < EIF_MAX_VALUE_LEN ; ++i, ++j) {
+ c = eiReadChar(gf);
+ if(c == '\n' || c == EOF)
+ break;
+ value[j] = c;
+ }
+ if(c != '\n') { ABORT_FINALIZE(RS_RET_ERR); }
+ value[j] = '\0';
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+eiGetIV(gcryfile gf, uchar *iv, size_t leniv)
+{
+ char rectype[EIF_MAX_RECTYPE_LEN+1];
+ char value[EIF_MAX_VALUE_LEN+1];
+ size_t valueLen;
+ unsigned short i, j;
+ unsigned char nibble;
+ DEFiRet;
+
+ CHKiRet(eiGetRecord(gf, rectype, value));
+ const char *const cmp_IV = "IV"; // work-around for static analyzer
+ if(strcmp(rectype, cmp_IV)) {
+ DBGPRINTF("no IV record found when expected, record type "
+ "seen is '%s'\n", rectype);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ valueLen = strlen(value);
+ if(valueLen/2 != leniv) {
+ DBGPRINTF("length of IV is %zd, expected %zd\n",
+ valueLen/2, leniv);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for(i = j = 0 ; i < valueLen ; ++i) {
+ if(value[i] >= '0' && value[i] <= '9')
+ nibble = value[i] - '0';
+ else if(value[i] >= 'a' && value[i] <= 'f')
+ nibble = value[i] - 'a' + 10;
+ else {
+ DBGPRINTF("invalid IV '%s'\n", value);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(i % 2 == 0)
+ iv[j] = nibble << 4;
+ else
+ iv[j++] |= nibble;
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+eiGetEND(gcryfile gf, off64_t *offs)
+{
+ char rectype[EIF_MAX_RECTYPE_LEN+1];
+ char value[EIF_MAX_VALUE_LEN+1];
+ DEFiRet;
+
+ CHKiRet(eiGetRecord(gf, rectype, value));
+ const char *const const_END = "END"; // clang static analyzer work-around
+ if(strcmp(rectype, const_END)) {
+ DBGPRINTF("no END record found when expected, record type "
+ "seen is '%s'\n", rectype);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ *offs = atoll(value);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+eiOpenAppend(gcryfile gf)
+{
+ rsRetVal localRet;
+ DEFiRet;
+ localRet = eiCheckFiletype(gf);
+ if(localRet == RS_RET_OK) {
+ gf->fd = open((char*)gf->eiName,
+ O_WRONLY|O_APPEND|O_NOCTTY|O_CLOEXEC, 0600);
+ if(gf->fd == -1) {
+ ABORT_FINALIZE(RS_RET_EI_OPN_ERR);
+ }
+ } else if(localRet == RS_RET_EI_NO_EXISTS) {
+ /* looks like we need to create a new file */
+ gf->fd = open((char*)gf->eiName,
+ O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600);
+ if(gf->fd == -1) {
+ ABORT_FINALIZE(RS_RET_EI_OPN_ERR);
+ }
+ CHKiRet(eiWriteRec(gf, "FILETYPE:", 9, RSGCRY_FILETYPE_NAME,
+ sizeof(RSGCRY_FILETYPE_NAME)-1));
+ } else {
+ gf->fd = -1;
+ ABORT_FINALIZE(localRet);
+ }
+ DBGPRINTF("encryption info file %s: opened as #%d\n",
+ gf->eiName, gf->fd);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal __attribute__((nonnull(2)))
+eiWriteIV(gcryfile gf, const uchar *const iv)
+{
+ static const char hexchars[16] =
+ {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+ unsigned iSrc, iDst;
+ char hex[4096];
+ DEFiRet;
+
+ if(gf->blkLength > sizeof(hex)/2) {
+ DBGPRINTF("eiWriteIV: crypto block len way too large, aborting "
+ "write");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for(iSrc = iDst = 0 ; iSrc < gf->blkLength ; ++iSrc) {
+ hex[iDst++] = hexchars[iv[iSrc]>>4];
+ hex[iDst++] = hexchars[iv[iSrc]&0x0f];
+ }
+
+ iRet = eiWriteRec(gf, "IV:", 3, hex, gf->blkLength*2);
+finalize_it:
+ RETiRet;
+}
+
+/* we do not return an error state, as we MUST close the file,
+ * no matter what happens.
+ */
+static void
+eiClose(gcryfile gf, off64_t offsLogfile)
+{
+ char offs[21];
+ size_t len;
+ if(gf->fd == -1)
+ return;
+ if(gf->openMode == 'w') {
+ /* 2^64 is 20 digits, so the snprintf buffer is large enough */
+ len = snprintf(offs, sizeof(offs), "%lld", (long long) offsLogfile);
+ eiWriteRec(gf, "END:", 4, offs, len);
+ }
+ gcry_cipher_close(gf->chd);
+ free(gf->readBuf);
+ close(gf->fd);
+ gf->fd = -1;
+ DBGPRINTF("encryption info file %s: closed\n", gf->eiName);
+}
+
+/* this returns the number of bytes left inside the block or -1, if the block
+ * size is unbounded. The function automatically handles end-of-block and begins
+ * to read the next block in this case.
+ */
+rsRetVal
+gcryfileGetBytesLeftInBlock(gcryfile gf, ssize_t *left)
+{
+ DEFiRet;
+ if(gf->bytesToBlkEnd == 0) {
+ DBGPRINTF("libgcry: end of current crypto block\n");
+ gcry_cipher_close(gf->chd);
+ CHKiRet(rsgcryBlkBegin(gf));
+ }
+ *left = gf->bytesToBlkEnd;
+finalize_it:
+ // TODO: remove once this code is sufficiently well-proven
+ DBGPRINTF("gcryfileGetBytesLeftInBlock returns %lld, iRet %d\n", (long long) *left, iRet);
+ RETiRet;
+}
+
+/* this is a special functon for use by the rsyslog disk queue subsystem. It
+ * needs to have the capability to delete state when a queue file is rolled
+ * over. This simply generates the file name and deletes it. It must take care
+ * of "all" state files, which currently happens to be a single one.
+ */
+rsRetVal
+gcryfileDeleteState(uchar *logfn)
+{
+ char fn[MAXFNAME+1];
+ DEFiRet;
+ snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX);
+ fn[MAXFNAME] = '\0'; /* be on save side */
+ DBGPRINTF("crypto provider deletes state file '%s' on request\n", fn);
+ unlink(fn);
+ RETiRet;
+}
+
+static rsRetVal
+gcryfileConstruct(gcryctx ctx, gcryfile *pgf, uchar *logfn)
+{
+ char fn[MAXFNAME+1];
+ gcryfile gf;
+ DEFiRet;
+
+ CHKmalloc(gf = calloc(1, sizeof(struct gcryfile_s)));
+ gf->ctx = ctx;
+ gf->fd = -1;
+ snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX);
+ fn[MAXFNAME] = '\0'; /* be on save side */
+ gf->eiName = (uchar*) strdup(fn);
+ *pgf = gf;
+finalize_it:
+ RETiRet;
+}
+
+
+gcryctx
+gcryCtxNew(void)
+{
+ gcryctx ctx;
+ ctx = calloc(1, sizeof(struct gcryctx_s));
+ if(ctx != NULL) {
+ ctx->algo = GCRY_CIPHER_AES128;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ }
+ return ctx;
+}
+
+int
+gcryfileDestruct(gcryfile gf, off64_t offsLogfile)
+{
+ int r = 0;
+ if(gf == NULL)
+ goto done;
+
+ DBGPRINTF("libgcry: close file %s\n", gf->eiName);
+ eiClose(gf, offsLogfile);
+ if(gf->bDeleteOnClose) {
+ DBGPRINTF("unlink file '%s' due to bDeleteOnClose set\n", gf->eiName);
+ unlink((char*)gf->eiName);
+ }
+ free(gf->eiName);
+ free(gf);
+done: return r;
+}
+void
+rsgcryCtxDel(gcryctx ctx)
+{
+ if(ctx != NULL) {
+ free(ctx->key);
+ free(ctx);
+ }
+}
+
+static void
+addPadding(gcryfile pF, uchar *buf, size_t *plen)
+{
+ unsigned i;
+ size_t nPad;
+ nPad = (pF->blkLength - *plen % pF->blkLength) % pF->blkLength;
+ DBGPRINTF("libgcry: addPadding %zd chars, blkLength %zd, mod %zd, pad %zd\n",
+ *plen, pF->blkLength, *plen % pF->blkLength, nPad);
+ for(i = 0 ; i < nPad ; ++i)
+ buf[(*plen)+i] = 0x00;
+ (*plen)+= nPad;
+}
+
+static void ATTR_NONNULL()
+removePadding(uchar *const buf, size_t *const plen)
+{
+ const size_t len = *plen;
+ size_t iSrc, iDst;
+
+ iSrc = 0;
+ /* skip to first NUL */
+ while(iSrc < len && buf[iSrc] == '\0') {
+ ++iSrc;
+ }
+ iDst = iSrc;
+
+ while(iSrc < len) {
+ if(buf[iSrc] != 0x00)
+ buf[iDst++] = buf[iSrc];
+ ++iSrc;
+ }
+
+ *plen = iDst;
+}
+
+/* returns 0 on succes, positive if key length does not match and key
+ * of return value size is required.
+ */
+int
+rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen)
+{
+ uint16_t reqKeyLen;
+ int r;
+
+ reqKeyLen = gcry_cipher_get_algo_keylen(ctx->algo);
+ if(keyLen != reqKeyLen) {
+ r = reqKeyLen;
+ goto done;
+ }
+ ctx->keyLen = keyLen;
+ ctx->key = malloc(keyLen);
+ memcpy(ctx->key, key, keyLen);
+ r = 0;
+done: return r;
+}
+
+rsRetVal
+rsgcrySetMode(gcryctx ctx, uchar *modename)
+{
+ int mode;
+ DEFiRet;
+
+ mode = rsgcryModename2Mode((char *)modename);
+ if(mode == GCRY_CIPHER_MODE_NONE) {
+ ABORT_FINALIZE(RS_RET_CRY_INVLD_MODE);
+ }
+ ctx->mode = mode;
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal
+rsgcrySetAlgo(gcryctx ctx, uchar *algoname)
+{
+ int algo;
+ DEFiRet;
+
+ algo = rsgcryAlgoname2Algo((char *)algoname);
+ if(algo == GCRY_CIPHER_NONE) {
+ ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO);
+ }
+ ctx->algo = algo;
+finalize_it:
+ RETiRet;
+}
+
+/* We use random numbers to initiate the IV. Rsyslog runtime will ensure
+ * we get a sufficiently large number.
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static rsRetVal
+#if defined(__clang__)
+__attribute__((no_sanitize("shift"))) /* IV shift causes known overflow */
+#endif
+seedIV(gcryfile gf, uchar **iv)
+{
+ long rndnum = 0; /* keep compiler happy -- this value is always overriden */
+ DEFiRet;
+
+ CHKmalloc(*iv = calloc(1, gf->blkLength));
+ for(size_t i = 0 ; i < gf->blkLength; ++i) {
+ const int shift = (i % 4) * 8;
+ if(shift == 0) { /* need new random data? */
+ rndnum = randomNumber();
+ }
+ (*iv)[i] = 0xff & ((rndnum & (255u << shift)) >> shift);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+readIV(gcryfile gf, uchar **iv)
+{
+ rsRetVal localRet;
+ DEFiRet;
+
+ if(gf->fd == -1) {
+ while(gf->fd == -1) {
+ localRet = eiOpenRead(gf);
+ if(localRet == RS_RET_EI_NO_EXISTS) {
+ /* wait until it is created */
+ srSleep(0, 10000);
+ } else {
+ CHKiRet(localRet);
+ }
+ }
+ CHKiRet(eiCheckFiletype(gf));
+ }
+ *iv = malloc(gf->blkLength); /* do NOT zero-out! */
+ iRet = eiGetIV(gf, *iv, (size_t) gf->blkLength);
+finalize_it:
+ RETiRet;
+}
+
+/* this tries to read the END record. HOWEVER, no such record may be
+ * present, which is the case if we handle a currently-written to queue
+ * file. On the other hand, the queue file may contain multiple blocks. So
+ * what we do is try to see if there is a block end or not - and set the
+ * status accordingly. Note that once we found no end-of-block, we will never
+ * retry. This is because that case can never happen under current queue
+ * implementations. -- gerhards, 2013-05-16
+ */
+static rsRetVal
+readBlkEnd(gcryfile gf)
+{
+ off64_t blkEnd;
+ DEFiRet;
+
+ iRet = eiGetEND(gf, &blkEnd);
+ if(iRet == RS_RET_OK) {
+ gf->bytesToBlkEnd = (ssize_t) blkEnd;
+ } else if(iRet == RS_RET_NO_DATA) {
+ gf->bytesToBlkEnd = -1;
+ } else {
+ FINALIZE;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Read the block begin metadata and set our state variables accordingly. Can also
+ * be used to init the first block in write case.
+ */
+static rsRetVal
+rsgcryBlkBegin(gcryfile gf)
+{
+ gcry_error_t gcryError;
+ uchar *iv = NULL;
+ DEFiRet;
+ const char openMode = gf->openMode;
+
+ gcryError = gcry_cipher_open(&gf->chd, gf->ctx->algo, gf->ctx->mode, 0);
+ if (gcryError) {
+ DBGPRINTF("gcry_cipher_open failed: %s/%s\n",
+ gcry_strsource(gcryError), gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ gcryError = gcry_cipher_setkey(gf->chd, gf->ctx->key, gf->ctx->keyLen);
+ if (gcryError) {
+ DBGPRINTF("gcry_cipher_setkey failed: %s/%s\n",
+ gcry_strsource(gcryError), gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(openMode == 'r') {
+ readIV(gf, &iv);
+ readBlkEnd(gf);
+ } else {
+ CHKiRet(seedIV(gf, &iv));
+ }
+
+ gcryError = gcry_cipher_setiv(gf->chd, iv, gf->blkLength);
+ if (gcryError) {
+ DBGPRINTF("gcry_cipher_setiv failed: %s/%s\n",
+ gcry_strsource(gcryError), gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if(openMode == 'w') {
+ CHKiRet(eiOpenAppend(gf));
+ CHKiRet(eiWriteIV(gf, iv));
+ }
+finalize_it:
+ free(iv);
+ RETiRet;
+}
+
+rsRetVal
+rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname, char openMode)
+{
+ gcryfile gf = NULL;
+ DEFiRet;
+
+ CHKiRet(gcryfileConstruct(ctx, &gf, fname));
+ gf->openMode = openMode;
+ gf->blkLength = gcry_cipher_get_algo_blklen(ctx->algo);
+ CHKiRet(rsgcryBlkBegin(gf));
+ *pgf = gf;
+finalize_it:
+ if(iRet != RS_RET_OK && gf != NULL)
+ gcryfileDestruct(gf, -1);
+ RETiRet;
+}
+
+rsRetVal
+rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len)
+{
+ int gcryError;
+ DEFiRet;
+
+ if(*len == 0)
+ FINALIZE;
+
+ addPadding(pF, buf, len);
+ gcryError = gcry_cipher_encrypt(pF->chd, buf, *len, NULL, 0);
+ if(gcryError) {
+ dbgprintf("gcry_cipher_encrypt failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* TODO: handle multiple blocks
+ * test-read END record; if present, store offset, else unbounded (current active block)
+ * when decrypting, check if bound is reached. If yes, split into two blocks, get new IV for
+ * second one.
+ */
+rsRetVal
+rsgcryDecrypt(gcryfile pF, uchar *buf, size_t *len)
+{
+ gcry_error_t gcryError;
+ DEFiRet;
+
+ if(pF->bytesToBlkEnd != -1)
+ pF->bytesToBlkEnd -= *len;
+ gcryError = gcry_cipher_decrypt(pF->chd, buf, *len, NULL, 0);
+ if(gcryError) {
+ DBGPRINTF("gcry_cipher_decrypt failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ removePadding(buf, len);
+ // TODO: remove dbgprintf once things are sufficently stable -- rgerhards, 2013-05-16
+ dbgprintf("libgcry: decrypted, bytesToBlkEnd %lld, buffer is now '%50.50s'\n",
+ (long long) pF->bytesToBlkEnd, buf);
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* module-init dummy for potential later use */
+int
+rsgcryInit(void)
+{
+ return 0;
+}
+
+/* module-deinit dummy for potential later use */
+void
+rsgcryExit(void)
+{
+ return;
+}
diff --git a/runtime/libgcry.h b/runtime/libgcry.h
new file mode 100644
index 0000000..15fce71
--- /dev/null
+++ b/runtime/libgcry.h
@@ -0,0 +1,87 @@
+/* libgcry.h - rsyslog's guardtime support library
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LIBGCRY_H
+#define INCLUDED_LIBGCRY_H
+#include <stdint.h>
+#include <gcrypt.h>
+
+struct gcryctx_s {
+ uchar *key;
+ size_t keyLen;
+ int algo;
+ int mode;
+};
+typedef struct gcryctx_s *gcryctx;
+typedef struct gcryfile_s *gcryfile;
+
+/* this describes a file, as far as libgcry is concerned */
+struct gcryfile_s {
+ gcry_cipher_hd_t chd; /* cypher handle */
+ size_t blkLength; /* size of low-level crypto block */
+ uchar *eiName; /* name of .encinfo file */
+ int fd; /* descriptor of .encinfo file (-1 if not open) */
+ char openMode; /* 'r': read, 'w': write */
+ gcryctx ctx;
+ uchar *readBuf;
+ int16_t readBufIdx;
+ int16_t readBufMaxIdx;
+ int8_t bDeleteOnClose; /* for queue support, similar to stream subsys */
+ ssize_t bytesToBlkEnd; /* number of bytes remaining in current crypto block
+ -1 means -> no end (still being writen to, queue files),
+ 0 means -> end of block, new one must be started. */
+};
+
+int gcryGetKeyFromFile(const char *fn, char **key, unsigned *keylen);
+int rsgcryInit(void);
+void rsgcryExit(void);
+int rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen);
+rsRetVal rsgcrySetMode(gcryctx ctx, uchar *algoname);
+rsRetVal rsgcrySetAlgo(gcryctx ctx, uchar *modename);
+gcryctx gcryCtxNew(void);
+void rsgcryCtxDel(gcryctx ctx);
+int gcryfileDestruct(gcryfile gf, off64_t offsLogfile);
+rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname, char openMode);
+rsRetVal rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len);
+rsRetVal rsgcryDecrypt(gcryfile pF, uchar *buf, size_t *len);
+int gcryGetKeyFromProg(char *cmd, char **key, unsigned *keylen);
+rsRetVal gcryfileDeleteState(uchar *fn);
+rsRetVal gcryfileGetBytesLeftInBlock(gcryfile gf, ssize_t *left);
+int rsgcryModename2Mode(char *const __restrict__ modename);
+int rsgcryAlgoname2Algo(char *const __restrict__ algoname);
+
+/* error states */
+#define RSGCRYE_EI_OPEN 1 /* error opening .encinfo file */
+#define RSGCRYE_OOM 4 /* ran out of memory */
+
+#define EIF_MAX_RECTYPE_LEN 31 /* max length of record types */
+#define EIF_MAX_VALUE_LEN 1023 /* max length of value types */
+#define RSGCRY_FILETYPE_NAME "rsyslog-enrcyption-info"
+#define ENCINFO_SUFFIX ".encinfo"
+
+/* Note: gf may validly be NULL, e.g. if file has not yet been opened! */
+static inline void __attribute__((unused))
+gcryfileSetDeleteOnClose(gcryfile gf, const int val)
+{
+ if(gf != NULL)
+ gf->bDeleteOnClose = val;
+}
+
+#endif /* #ifndef INCLUDED_LIBGCRY_H */
diff --git a/runtime/libgcry_common.c b/runtime/libgcry_common.c
new file mode 100644
index 0000000..1cc56fe
--- /dev/null
+++ b/runtime/libgcry_common.c
@@ -0,0 +1,200 @@
+/* libgcry_common.c
+ * This file hosts functions both being used by the rsyslog runtime as
+ * well as tools who do not use the runtime (so we can maintain the
+ * code at a single place).
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <gcrypt.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "rsyslog.h" /* we need data typedefs */
+#include "libgcry.h"
+
+
+/* read a key from a key file
+ * @param[out] key - key buffer, must be freed by caller
+ * @param[out] keylen - length of buffer
+ * @returns 0 if OK, something else otherwise (we do not use
+ * iRet as this is also called from non-rsyslog w/o runtime)
+ * on error, errno is set and can be queried
+ * The key length is limited to 64KiB to prevent DoS.
+ * Note well: key is a blob, not a C string (NUL may be present!)
+ */
+int
+gcryGetKeyFromFile(const char *const fn, char **const key, unsigned *const keylen)
+{
+ struct stat sb;
+ int r = -1;
+
+ const int fd = open(fn, O_RDONLY);
+ if(fd < 0) goto done;
+ if(fstat(fd, &sb) == -1) goto done;
+ if(sb.st_size > 64*1024) {
+ errno = EMSGSIZE;
+ goto done;
+ }
+ if((*key = malloc(sb.st_size)) == NULL) goto done;
+ if(read(fd, *key, sb.st_size) != sb.st_size) goto done;
+ *keylen = sb.st_size;
+ r = 0;
+done:
+ if(fd >= 0) {
+ close(fd);
+ }
+ return r;
+}
+
+
+/* execute the child process (must be called in child context
+ * after fork).
+ */
+
+static void
+execKeyScript(char *cmd, int pipefd[])
+{
+ char *newargv[] = { NULL };
+ char *newenviron[] = { NULL };
+
+ dup2(pipefd[0], STDIN_FILENO);
+ dup2(pipefd[1], STDOUT_FILENO);
+
+ /* finally exec child */
+fprintf(stderr, "pre execve: %s\n", cmd);
+ execve(cmd, newargv, newenviron);
+ /* switch to?
+ execlp((char*)program, (char*) program, (char*)arg, NULL);
+ */
+
+ /* we should never reach this point, but if we do, we terminate */
+ return;
+}
+
+
+static int
+openPipe(char *cmd, int *fd)
+{
+ int pipefd[2];
+ pid_t cpid;
+ int r;
+
+ if(pipe(pipefd) == -1) {
+ r = 1; goto done;
+ }
+
+ cpid = fork();
+ if(cpid == -1) {
+ r = 1; goto done;
+ }
+
+ if(cpid == 0) {
+ /* we are the child */
+ execKeyScript(cmd, pipefd);
+ exit(1);
+ }
+
+ close(pipefd[1]);
+ *fd = pipefd[0];
+ r = 0;
+done: return r;
+}
+
+
+/* Read a character from the program's output. */
+// TODO: highly unoptimized version, should be used in buffered
+// mode
+static int
+readProgChar(int fd, char *c)
+{
+ int r;
+ if(read(fd, c, 1) != 1) {
+ r = 1; goto done;
+ }
+ r = 0;
+done: return r;
+}
+
+/* Read a line from the script. Line is terminated by LF, which
+ * is NOT put into the buffer.
+ * buf must be 64KiB
+ */
+static int
+readProgLine(int fd, char *buf)
+{
+ char c;
+ int r;
+ unsigned i;
+
+ for(i = 0 ; i < 64*1024 ; ++i) {
+ if((r = readProgChar(fd, &c)) != 0) goto done;
+ if(c == '\n')
+ break;
+ buf[i] = c;
+ };
+ if(i >= 64*1024) {
+ r = 1; goto done;
+ }
+ buf[i] = '\0';
+ r = 0;
+done: return r;
+}
+static int
+readProgKey(int fd, char *buf, unsigned keylen)
+{
+ char c;
+ int r;
+ unsigned i;
+
+ for(i = 0 ; i < keylen ; ++i) {
+ if((r = readProgChar(fd, &c)) != 0) goto done;
+ buf[i] = c;
+ };
+ r = 0;
+done: return r;
+}
+
+int
+gcryGetKeyFromProg(char *cmd, char **key, unsigned *keylen)
+{
+ int r;
+ int fd;
+ char rcvBuf[64*1024];
+
+ if((r = openPipe(cmd, &fd)) != 0) goto done;
+ if((r = readProgLine(fd, rcvBuf)) != 0) goto done;
+ if(strcmp(rcvBuf, "RSYSLOG-KEY-PROVIDER:0")) {
+ r = 2; goto done;
+ }
+ if((r = readProgLine(fd, rcvBuf)) != 0) goto done;
+ *keylen = atoi(rcvBuf);
+ if((*key = malloc(*keylen)) == NULL) {
+ r = -1; goto done;
+ }
+ if((r = readProgKey(fd, *key, *keylen)) != 0) goto done;
+done: return r;
+}
diff --git a/runtime/linkedlist.c b/runtime/linkedlist.c
new file mode 100644
index 0000000..7088737
--- /dev/null
+++ b/runtime/linkedlist.c
@@ -0,0 +1,415 @@
+/* linkedlist.c
+ * This file set implements a generic linked list object. It can be used
+ * wherever a linke list is required.
+ *
+ * NOTE: we do not currently provide a constructor and destructor for the
+ * object itself as we assume it will always be part of another strucuture.
+ * Having a pointer to it, I think, does not really make sense but costs
+ * performance. Consequently, there is is llInit() and llDestroy() and they
+ * do what a constructor and destructur do, except for creating the
+ * linkedList_t structure itself.
+ *
+ * File begun on 2007-07-31 by RGerhards
+ *
+ * Copyright (C) 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "linkedlist.h"
+
+
+/* Initialize an existing linkedList_t structure
+ * pKey destructor may be zero to take care of non-keyed lists.
+ */
+rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(void*), rsRetVal (*pKeyDestructor)(void*),
+int (*pCmpOp)(void*,void*))
+{
+ assert(pThis != NULL);
+ assert(pEltDestructor != NULL);
+
+ pThis->pEltDestruct = pEltDestructor;
+ pThis->pKeyDestruct = pKeyDestructor;
+ pThis->cmpOp = pCmpOp;
+ pThis->pKey = NULL;
+ pThis->iNumElts = 0;
+ pThis->pRoot = NULL;
+ pThis->pLast = NULL;
+
+ return RS_RET_OK;
+};
+
+
+/* llDestroyEltData - destroys a list element
+ * It is a separate function as the
+ * functionality is needed in multiple code-pathes.
+ */
+static rsRetVal llDestroyElt(linkedList_t *pList, llElt_t *pElt)
+{
+ DEFiRet;
+
+ assert(pList != NULL);
+ assert(pElt != NULL);
+
+ /* we ignore errors during destruction, as we need to try
+ * free the element in any case.
+ */
+ if(pElt->pData != NULL)
+ pList->pEltDestruct(pElt->pData);
+ if(pElt->pKey != NULL)
+ pList->pKeyDestruct(pElt->pKey);
+ free(pElt);
+ pList->iNumElts--; /* one less */
+
+ RETiRet;
+}
+
+
+/* llDestroy - destroys a COMPLETE linkedList
+ */
+rsRetVal llDestroy(linkedList_t *pThis)
+{
+ DEFiRet;
+ llElt_t *pElt;
+
+ assert(pThis != NULL);
+
+ pElt = pThis->pRoot;
+ while(pElt != NULL) {
+ /* keep the list structure in a consistent state as
+ * the destructor bellow may reference it again
+ */
+ pThis->pRoot = pElt->pNext;
+ if(pElt->pNext == NULL)
+ pThis->pLast = NULL;
+
+ /* we ignore errors during destruction, as we need to try
+ * finish the linked list in any case.
+ */
+ llDestroyElt(pThis, pElt);
+ pElt = pThis->pRoot;
+ }
+
+ RETiRet;
+}
+
+/* llDestroyRootElt - destroy the root element but otherwise
+ * keeps this list intact. -- rgerhards, 2007-08-03
+ */
+rsRetVal llDestroyRootElt(linkedList_t *pThis)
+{
+ DEFiRet;
+ llElt_t *pPrev;
+
+ if(pThis->pRoot == NULL) {
+ ABORT_FINALIZE(RS_RET_EMPTY_LIST);
+ }
+
+ pPrev = pThis->pRoot;
+ if(pPrev->pNext == NULL) {
+ /* it was the only list element */
+ pThis->pLast = NULL;
+ pThis->pRoot = NULL;
+ } else {
+ /* there are other list elements */
+ pThis->pRoot = pPrev->pNext;
+ }
+
+ CHKiRet(llDestroyElt(pThis, pPrev));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get next user data element of a linked list. The caller must also
+ * provide a "cookie" to the function. On initial call, it must be
+ * NULL. Other than that, the caller is not allowed to to modify the
+ * cookie. In the current implementation, the cookie is an actual
+ * pointer to the current list element, but this is nothing that the
+ * caller should rely on.
+ */
+rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr)
+{
+ llElt_t *pElt;
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(ppElt != NULL);
+ assert(ppUsr != NULL);
+
+ pElt = *ppElt;
+
+ pElt = (pElt == NULL) ? pThis->pRoot : pElt->pNext;
+
+ if(pElt == NULL) {
+ iRet = RS_RET_END_OF_LINKEDLIST;
+ } else {
+ *ppUsr = pElt->pData;
+ }
+
+ *ppElt = pElt;
+
+ RETiRet;
+}
+
+
+/* return the key of an Elt
+ * rgerhards, 2007-09-11: note that ppDatea is actually a void**,
+ * but I need to make it a void* to avoid lots of compiler warnings.
+ * It will be converted later down in the code.
+ */
+rsRetVal llGetKey(llElt_t *pThis, void *ppData)
+{
+ assert(pThis != NULL);
+ assert(ppData != NULL);
+
+ *(void**) ppData = pThis->pKey;
+
+ return RS_RET_OK;
+}
+
+
+/* construct a new llElt_t
+ */
+static rsRetVal llEltConstruct(llElt_t **ppThis, void *pKey, void *pData)
+{
+ DEFiRet;
+ llElt_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (llElt_t*) calloc(1, sizeof(llElt_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->pKey = pKey;
+ pThis->pData = pData;
+
+finalize_it:
+ *ppThis = pThis;
+ RETiRet;
+}
+
+
+/* append a user element to the end of the linked list. This includes setting a key. If no
+ * key is desired, simply pass in a NULL pointer for it.
+ */
+rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData)
+{
+ llElt_t *pElt;
+ DEFiRet;
+
+ CHKiRet(llEltConstruct(&pElt, pKey, pData));
+
+ pThis->iNumElts++; /* one more */
+ if(pThis->pLast == NULL) {
+ pThis->pRoot = pElt;
+ } else {
+ pThis->pLast->pNext = pElt;
+ }
+ pThis->pLast = pElt;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* unlink a requested element. As we have singly-linked lists, the
+ * caller also needs to pass in the previous element (or NULL, if it is the
+ * root element).
+ * rgerhards, 2007-11-21
+ */
+static rsRetVal llUnlinkElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev)
+{
+ assert(pElt != NULL);
+
+ if(pEltPrev == NULL) { /* root element? */
+ pThis->pRoot = pElt->pNext;
+ } else { /* regular element */
+ pEltPrev->pNext = pElt->pNext;
+ }
+
+ if(pElt == pThis->pLast)
+ pThis->pLast = pEltPrev;
+
+ return RS_RET_OK;
+}
+
+
+/* unlinks and immediately deletes an element. Previous element must
+ * be given (or zero if the root element is to be deleted).
+ * rgerhards, 2007-11-21
+ */
+static rsRetVal llUnlinkAndDelteElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev)
+{
+ DEFiRet;
+
+ assert(pElt != NULL);
+
+ CHKiRet(llUnlinkElt(pThis, pElt, pEltPrev));
+ CHKiRet(llDestroyElt(pThis, pElt));
+
+finalize_it:
+ RETiRet;
+}
+
+/* find a user element based on the provided key - this is the
+ * internal variant, which also tracks the last element pointer
+ * before the found element. This is necessary to delete elements.
+ * NULL means there is no element in front of it, aka the found elt
+ * is the root elt.
+ * rgerhards, 2007-11-21
+ */
+static rsRetVal llFindElt(linkedList_t *pThis, void *pKey, llElt_t **ppElt, llElt_t **ppEltPrev)
+{
+ DEFiRet;
+ llElt_t *pElt;
+ llElt_t *pEltPrev = NULL;
+ int bFound = 0;
+
+ assert(pThis != NULL);
+ assert(pKey != NULL);
+ assert(ppElt != NULL);
+ assert(ppEltPrev != NULL);
+
+ pElt = pThis->pRoot;
+ while(pElt != NULL && bFound == 0) {
+ if(pThis->cmpOp(pKey, pElt->pKey) == 0)
+ bFound = 1;
+ else {
+ pEltPrev = pElt;
+ pElt = pElt->pNext;
+ }
+ }
+
+ if(bFound == 1) {
+ *ppElt = pElt;
+ *ppEltPrev = pEltPrev;
+ } else
+ iRet = RS_RET_NOT_FOUND;
+
+ RETiRet;
+}
+
+
+/* find a user element based on the provided key
+ */
+rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData)
+{
+ DEFiRet;
+ llElt_t *pElt;
+ llElt_t *pEltPrev;
+
+ CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev));
+
+ /* if we reach this point, we have found the element */
+ *ppData = pElt->pData;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* find a delete an element based on user-provided key. The element is
+ * delete, the caller does not receive anything. If we need to receive
+ * the element before destruction, we may implement an llFindAndUnlink()
+ * at that time.
+ * rgerhards, 2007-11-21
+ */
+rsRetVal llFindAndDelete(linkedList_t *pThis, void *pKey)
+{
+ DEFiRet;
+ llElt_t *pElt;
+ llElt_t *pEltPrev;
+
+ CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev));
+
+ /* if we reach this point, we have found an element */
+ CHKiRet(llUnlinkAndDelteElt(pThis, pElt, pEltPrev));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* provide the count of linked list elements
+ */
+rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(piCnt != NULL);
+
+ *piCnt = pThis->iNumElts;
+
+ RETiRet;
+}
+
+
+/* execute a function on all list members. The functions receives a
+ * user-supplied parameter, which may be either a simple value
+ * or a pointer to a structure with more data. If the user-supplied
+ * function does not return RS_RET_OK, this function here terminates.
+ * rgerhards, 2007-08-02
+ * rgerhards, 2007-11-21: added functionality to delete a list element.
+ * If the called user function returns RS_RET_OK_DELETE_LISTENTRY the current element
+ * is deleted.
+ */
+rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam)
+{
+ DEFiRet;
+ rsRetVal iRetLL;
+ void *pData;
+ linkedListCookie_t llCookie = NULL;
+ linkedListCookie_t llCookiePrev = NULL; /* previous list element (needed for deletion, NULL = at root) */
+
+ assert(pThis != NULL);
+ assert(pFunc != NULL);
+
+ while((iRetLL = llGetNextElt(pThis, &llCookie, (void**)&pData)) == RS_RET_OK) {
+ iRet = pFunc(pData, pParam);
+ if(iRet == RS_RET_OK_DELETE_LISTENTRY) {
+ /* delete element */
+ CHKiRet(llUnlinkAndDelteElt(pThis, llCookie, llCookiePrev));
+ /* we need to revert back, as we have just deleted the current element.
+ * So the actual current element is the one before it, which happens to be
+ * stored in llCookiePrev. -- rgerhards, 2007-11-21
+ */
+ llCookie = llCookiePrev;
+ } else if (iRet != RS_RET_OK) {
+ FINALIZE;
+ }
+ llCookiePrev = llCookie;
+ }
+
+ if(iRetLL != RS_RET_END_OF_LINKEDLIST)
+ iRet = iRetLL;
+
+finalize_it:
+ RETiRet;
+}
+
+/* vim:set ai:
+ */
diff --git a/runtime/linkedlist.h b/runtime/linkedlist.h
new file mode 100644
index 0000000..1cd3a14
--- /dev/null
+++ b/runtime/linkedlist.h
@@ -0,0 +1,71 @@
+/* Definition of the linkedlist object.
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LINKEDLIST_H_INCLUDED
+#define LINKEDLIST_H_INCLUDED
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct llElt_s { /* config file sysline parse entry */
+ struct llElt_s *pNext;
+ void *pKey; /* key for this element */
+ void *pData; /* user-supplied data pointer */
+};
+typedef struct llElt_s llElt_t;
+
+
+/* this is the list of known configuration commands with pointers to
+ * their handlers.
+ * The short name is cslc (Configfile SysLine Command)
+ */
+struct linkedList_s { /* config file sysline parse entry */
+ int iNumElts; /* number of elements in list */
+ rsRetVal (*pEltDestruct)(void*pData); /* destructor for user pointer in llElt_t's */
+ rsRetVal (*pKeyDestruct)(void*pKey); /* destructor for key pointer in llElt_t's */
+ int (*cmpOp)(void*, void*); /* pointer to key compare operation function, retval like strcmp */
+ void *pKey; /* the list key (searchable, if set) */
+ llElt_t *pRoot; /* list root */
+ llElt_t *pLast; /* list tail */
+};
+typedef struct linkedList_s linkedList_t;
+
+typedef llElt_t* linkedListCookie_t; /* this type avoids exposing internals and keeps us flexible */
+
+/* prototypes */
+rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(), rsRetVal (*pKeyDestructor)(), int (*pCmpOp)());
+rsRetVal llDestroy(linkedList_t *pThis);
+rsRetVal llDestroyRootElt(linkedList_t *pThis);
+rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr);
+rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData);
+rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData);
+rsRetVal llGetKey(llElt_t *pThis, void *ppData);
+rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt);
+rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam);
+rsRetVal llFindAndDelete(linkedList_t *pThis, void *pKey);
+/* use the macro below to define a function that will be executed by
+ * llExecFunc()
+ */
+#define DEFFUNC_llExecFunc(funcName)\
+ static rsRetVal funcName(void __attribute__((unused)) *pData, void __attribute__((unused)) *pParam)
+
+#endif /* #ifndef LINKEDLIST_H_INCLUDED */
diff --git a/runtime/lmcry_gcry.c b/runtime/lmcry_gcry.c
new file mode 100644
index 0000000..21cfaff
--- /dev/null
+++ b/runtime/lmcry_gcry.c
@@ -0,0 +1,339 @@
+/* lmcry_gcry.c
+ *
+ * An implementation of the cryprov interface for libgcrypt.
+ *
+ * Copyright 2013-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "cryprov.h"
+#include "parserif.h"
+#include "libgcry.h"
+#include "lmcry_gcry.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfpdescrRegular[] = {
+ { "cry.key", eCmdHdlrGetWord, 0 },
+ { "cry.keyfile", eCmdHdlrGetWord, 0 },
+ { "cry.keyprogram", eCmdHdlrGetWord, 0 },
+ { "cry.mode", eCmdHdlrGetWord, 0 }, /* CBC, ECB, etc */
+ { "cry.algo", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk pblkRegular =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescrRegular)/sizeof(struct cnfparamdescr),
+ cnfpdescrRegular
+ };
+
+static struct cnfparamdescr cnfpdescrQueue[] = {
+ { "queue.cry.key", eCmdHdlrGetWord, 0 },
+ { "queue.cry.keyfile", eCmdHdlrGetWord, 0 },
+ { "queue.cry.keyprogram", eCmdHdlrGetWord, 0 },
+ { "queue.cry.mode", eCmdHdlrGetWord, 0 }, /* CBC, ECB, etc */
+ { "queue.cry.algo", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk pblkQueue =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescrQueue)/sizeof(struct cnfparamdescr),
+ cnfpdescrQueue
+ };
+
+
+#if 0
+static void
+errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ LogError(0, RS_RET_CRYPROV_ERR, "Crypto Provider"
+ "Error: %s - disabling encryption", emsg);
+}
+#endif
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(lmcry_gcry)
+ CHKmalloc(pThis->ctx = gcryCtxNew());
+finalize_it:
+ENDobjConstruct(lmcry_gcry)
+
+
+/* destructor for the lmcry_gcry object */
+BEGINobjDestruct(lmcry_gcry) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(lmcry_gcry)
+ rsgcryCtxDel(pThis->ctx);
+ENDobjDestruct(lmcry_gcry)
+
+
+/* apply all params from param block to us. This must be called
+ * after construction, but before the OnFileOpen() entry point.
+ * Defaults are expected to have been set during construction.
+ */
+static rsRetVal
+SetCnfParam(void *pT, struct nvlst *lst, int paramType)
+{
+ lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
+ int i, r;
+ unsigned keylen = 0;
+ uchar *key = NULL;
+ uchar *keyfile = NULL;
+ uchar *keyprogram = NULL;
+ uchar *algo = NULL;
+ uchar *mode = NULL;
+ int nKeys; /* number of keys (actually methods) specified */
+ struct cnfparamvals *pvals;
+ struct cnfparamblk *pblk;
+ DEFiRet;
+
+ pblk = (paramType == CRYPROV_PARAMTYPE_REGULAR ) ? &pblkRegular : &pblkQueue;
+ nKeys = 0;
+ pvals = nvlstGetParams(lst, pblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error crypto provider gcryconfig parameters]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if(Debug) {
+ dbgprintf("param blk in lmcry_gcry:\n");
+ cnfparamsPrint(pblk, pvals);
+ }
+
+ for(i = 0 ; i < pblk->nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblk->descr[i].name, "cry.key") ||
+ !strcmp(pblk->descr[i].name, "queue.cry.key")) {
+ key = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ ++nKeys;
+ } else if(!strcmp(pblk->descr[i].name, "cry.keyfile") ||
+ !strcmp(pblk->descr[i].name, "queue.cry.keyfile")) {
+ keyfile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ ++nKeys;
+ } else if(!strcmp(pblk->descr[i].name, "cry.keyprogram") ||
+ !strcmp(pblk->descr[i].name, "queue.cry.keyprogram")) {
+ keyprogram = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ ++nKeys;
+ } else if(!strcmp(pblk->descr[i].name, "cry.mode") ||
+ !strcmp(pblk->descr[i].name, "queue.cry.mode")) {
+ mode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk->descr[i].name, "cry.algo") ||
+ !strcmp(pblk->descr[i].name, "queue.cry.algo")) {
+ algo = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("lmcry_gcry: program error, non-handled "
+ "param '%s'\n", pblk->descr[i].name);
+ }
+ }
+ if(algo != NULL) {
+ iRet = rsgcrySetAlgo(pThis->ctx, algo);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "cry.algo '%s' is not know/supported", algo);
+ FINALIZE;
+ }
+ }
+ if(mode != NULL) {
+ iRet = rsgcrySetMode(pThis->ctx, mode);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "cry.mode '%s' is not know/supported", mode);
+ FINALIZE;
+ }
+ }
+ /* note: key must be set AFTER algo/mode is set (as it depends on them) */
+ if(nKeys != 1) {
+ LogError(0, RS_RET_INVALID_PARAMS, "excactly one of the following "
+ "parameters can be specified: cry.key, cry.keyfile, cry.keyprogram\n");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ if(key != NULL) {
+ LogError(0, RS_RET_ERR, "Note: specifying an actual key directly from the "
+ "config file is highly insecure - DO NOT USE FOR PRODUCTION");
+ keylen = strlen((char*)key);
+ }
+ if(keyfile != NULL) {
+ r = gcryGetKeyFromFile((char*)keyfile, (char**)&key, &keylen);
+ if(r != 0) {
+ LogError(errno, RS_RET_ERR, "error reading keyfile %s",
+ keyfile);
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ }
+ if(keyprogram != NULL) {
+ r = gcryGetKeyFromProg((char*)keyprogram, (char**)&key, &keylen);
+ if(r != 0) {
+ LogError(0, RS_RET_ERR, "error %d obtaining key from program %s\n",
+ r, keyprogram);
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+ }
+
+ /* if we reach this point, we have a valid key */
+ r = rsgcrySetKey(pThis->ctx, key, keylen);
+ if(r > 0) {
+ LogError(0, RS_RET_INVALID_PARAMS, "Key length %d expected, but "
+ "key of length %d given", r, keylen);
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ }
+
+finalize_it:
+ free(key);
+ free(keyfile);
+ free(algo);
+ free(keyprogram);
+ free(mode);
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, pblk);
+ RETiRet;
+}
+
+static void
+SetDeleteOnClose(void *pF, int val)
+{
+ gcryfileSetDeleteOnClose(pF, val);
+}
+
+static rsRetVal
+GetBytesLeftInBlock(void *pF, ssize_t *left)
+{
+ return gcryfileGetBytesLeftInBlock((gcryfile) pF, left);
+}
+
+static rsRetVal
+DeleteStateFiles(uchar *logfn)
+{
+ return gcryfileDeleteState(logfn);
+}
+
+static rsRetVal
+OnFileOpen(void *pT, uchar *fn, void *pGF, char openMode)
+{
+ lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
+ gcryfile *pgf = (gcryfile*) pGF;
+ DEFiRet;
+ DBGPRINTF("lmcry_gcry: open file '%s', mode '%c'\n", fn, openMode);
+
+ iRet = rsgcryInitCrypt(pThis->ctx, pgf, fn, openMode);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "Encryption Provider"
+ "Error: cannot open .encinfo file - disabling log file");
+ }
+ RETiRet;
+}
+
+static rsRetVal
+Decrypt(void *pF, uchar *rec, size_t *lenRec)
+{
+ DEFiRet;
+ iRet = rsgcryDecrypt(pF, rec, lenRec);
+
+ RETiRet;
+}
+
+
+static rsRetVal
+Encrypt(void *pF, uchar *rec, size_t *lenRec)
+{
+ DEFiRet;
+ iRet = rsgcryEncrypt(pF, rec, lenRec);
+
+ RETiRet;
+}
+
+static rsRetVal
+OnFileClose(void *pF, off64_t offsLogfile)
+{
+ DEFiRet;
+ gcryfileDestruct(pF, offsLogfile);
+
+ RETiRet;
+}
+
+BEGINobjQueryInterface(lmcry_gcry)
+CODESTARTobjQueryInterface(lmcry_gcry)
+ if(pIf->ifVersion != cryprovCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->Construct = (rsRetVal(*)(void*)) lmcry_gcryConstruct;
+ pIf->SetCnfParam = SetCnfParam;
+ pIf->SetDeleteOnClose = SetDeleteOnClose;
+ pIf->Destruct = (rsRetVal(*)(void*)) lmcry_gcryDestruct;
+ pIf->OnFileOpen = OnFileOpen;
+ pIf->Encrypt = Encrypt;
+ pIf->Decrypt = Decrypt;
+ pIf->OnFileClose = OnFileClose;
+ pIf->DeleteStateFiles = DeleteStateFiles;
+ pIf->GetBytesLeftInBlock = GetBytesLeftInBlock;
+finalize_it:
+ENDobjQueryInterface(lmcry_gcry)
+
+
+BEGINObjClassExit(lmcry_gcry, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(lmcry_gcry)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+
+ rsgcryExit();
+ENDObjClassExit(lmcry_gcry)
+
+
+BEGINObjClassInit(lmcry_gcry, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ if(rsgcryInit() != 0) {
+ LogError(0, RS_RET_CRYPROV_ERR, "error initializing "
+ "crypto provider - cannot encrypt");
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+ENDObjClassInit(lmcry_gcry)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ lmcry_gcryClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(lmcry_gcryClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
diff --git a/runtime/lmcry_gcry.h b/runtime/lmcry_gcry.h
new file mode 100644
index 0000000..f9c854b
--- /dev/null
+++ b/runtime/lmcry_gcry.h
@@ -0,0 +1,39 @@
+/* An implementation of the cryprov interface for libgcrypt.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LMCRY_GCRY_H
+#define INCLUDED_LMCRY_GCRY_H
+#include "cryprov.h"
+
+/* interface is defined in cryprov.h, we just implement it! */
+#define lmcry_gcryCURR_IF_VERSION cryprovCURR_IF_VERSION
+typedef cryprov_if_t lmcry_gcry_if_t;
+
+/* the lmcry_gcry object */
+struct lmcry_gcry_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ gcryctx ctx;
+};
+typedef struct lmcry_gcry_s lmcry_gcry_t;
+
+/* prototypes */
+PROTOTYPEObj(lmcry_gcry);
+
+#endif /* #ifndef INCLUDED_LMCRY_GCRY_H */
diff --git a/runtime/lmsig_ksi-ls12.c b/runtime/lmsig_ksi-ls12.c
new file mode 100644
index 0000000..0336bc2
--- /dev/null
+++ b/runtime/lmsig_ksi-ls12.c
@@ -0,0 +1,346 @@
+/* lmsig_ksi-ls12.c
+ *
+ * An implementation of the sigprov interface for KSI-LS12.
+ *
+ * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "sigprov.h"
+#include "lmsig_ksi-ls12.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfpdescr[] = {
+ { "sig.hashfunction", eCmdHdlrGetWord, 0 },
+ { "sig.aggregator.url", eCmdHdlrGetWord, CNFPARAM_REQUIRED},
+ { "sig.aggregator.user", eCmdHdlrGetWord, 0},
+ { "sig.aggregator.key", eCmdHdlrGetWord, 0},
+ { "sig.aggregator.hmacAlg", eCmdHdlrGetWord, 0 },
+ { "sig.block.levelLimit", eCmdHdlrSize, CNFPARAM_REQUIRED},
+ { "sig.block.timeLimit", eCmdHdlrInt, 0},
+ { "sig.block.signtimeout", eCmdHdlrInt, 0},
+ { "sig.confinterval", eCmdHdlrInt, 0},
+ { "sig.keeprecordhashes", eCmdHdlrBinary, 0 },
+ { "sig.keeptreehashes", eCmdHdlrBinary, 0},
+ { "sig.fileformat", eCmdHdlrString, 0},
+ { "sig.syncmode", eCmdHdlrString, 0},
+ { "sig.randomsource", eCmdHdlrString, 0},
+ { "sig.debugfile", eCmdHdlrString, 0},
+ { "sig.debuglevel", eCmdHdlrInt, 0},
+ { "dirowner", eCmdHdlrUID, 0}, /* legacy: dirowner */
+ { "dirownernum", eCmdHdlrInt, 0 }, /* legacy: dirownernum */
+ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */
+ { "dirgroupnum", eCmdHdlrInt, 0 }, /* legacy: dirgroupnum */
+ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */
+ { "fileownernum", eCmdHdlrInt, 0 }, /* legacy: fileownernum */
+ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */
+ { "filegroupnum", eCmdHdlrInt, 0 }, /* legacy: filegroupnum */
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 } /* legacy: filecreatemode */
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescr)/sizeof(struct cnfparamdescr),
+ cnfpdescr
+ };
+
+
+static void
+errfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ LogError(0, RS_RET_SIGPROV_ERR, "KSI Signature Provider"
+ "Error: %s", emsg);
+}
+
+static void
+logfunc(__attribute__((unused)) void *usrptr, uchar *emsg)
+{
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
+ "KSI/LS12 Signature Provider: %s", emsg);
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(lmsig_ksi_ls12)
+ pThis->ctx = rsksiCtxNew();
+ rsksisetErrFunc(pThis->ctx, errfunc, NULL);
+ rsksisetLogFunc(pThis->ctx, logfunc, NULL);
+ENDobjConstruct(lmsig_ksi_ls12)
+
+
+/* destructor for the lmsig_ksi object */
+BEGINobjDestruct(lmsig_ksi_ls12) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(lmsig_ksi_ls12)
+ rsksiCtxDel(pThis->ctx);
+ENDobjDestruct(lmsig_ksi_ls12)
+
+#define REPORT_PARAM_MISSING(param) \
+ do { \
+ pThis->ctx->disabled = true; \
+ LogError(0, RS_RET_ERR, "%s missing - signing disabled", param); \
+ /* TODO: ABORT_FINALIZE actually is useless because the return value is not checked by the caller*/ \
+ ABORT_FINALIZE(RS_RET_KSI_ERR); \
+ } while(0)
+
+
+
+/* apply all params from param block to us. This must be called
+ * after construction, but before the OnFileOpen() entry point.
+ * Defaults are expected to have been set during construction.
+ */
+static rsRetVal
+SetCnfParam(void *pT, struct nvlst *lst)
+{
+ char *ag_uri = NULL, *ag_loginid = NULL, *ag_key = NULL;
+ char *hash=NULL, *hmac = NULL;
+ lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t*) pT;
+ int i;
+ uchar *cstr;
+ struct cnfparamvals *pvals;
+ DEFiRet;
+ pvals = nvlstGetParams(lst, &pblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_ERR, "Failed to load configuration - signing disabled");
+ pThis->ctx->disabled=true;
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if(Debug) {
+ dbgprintf("sig param blk in lmsig_ksi:\n");
+ cnfparamsPrint(&pblk, pvals);
+ }
+
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblk.descr[i].name, "sig.hashfunction")) {
+ hash = (char*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.url")) {
+ ag_uri = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.user")) {
+ ag_loginid = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.key")) {
+ ag_key = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.hmacAlg")) {
+ hmac = (char*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.levelLimit")) {
+ if (pvals[i].val.d.n < 2) {
+ LogError(0, RS_RET_ERR, "sig.block.levelLimit "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockLevelLimit(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.timeLimit")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.block.timeLimit "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockTimeLimit(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.confinterval")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.confinterval "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetConfInterval(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if (!strcmp(pblk.descr[i].name, "sig.keeprecordhashes")) {
+ rsksiSetKeepRecordHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "sig.block.signtimeout")) {
+ if (pvals[i].val.d.n < 0) {
+ LogError(0, RS_RET_ERR, "sig.block.signtimeout "
+ "%llu invalid - signing disabled", pvals[i].val.d.n);
+ pThis->ctx->disabled = true;
+ } else {
+ rsksiSetBlockSigTimeout(pThis->ctx, pvals[i].val.d.n);
+ }
+ } else if(!strcmp(pblk.descr[i].name, "sig.keeptreehashes")) {
+ rsksiSetKeepTreeHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "sig.syncmode")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (!strcasecmp((char*) cstr, "sync")) rsksiSetSyncMode(pThis->ctx, LOGSIG_SYNCHRONOUS);
+ else if (!strcasecmp((char*) cstr, "async")) rsksiSetSyncMode(pThis->ctx, LOGSIG_ASYNCHRONOUS);
+ else LogError(0, RS_RET_ERR, "sig.syncmode '%s' unknown - using default", cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.randomsource")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ rsksiSetRandomSource(pThis->ctx, (char*) cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.debugfile")) {
+ cstr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ rsksiSetDebugFile(pThis->ctx, (char*) cstr);
+ free(cstr);
+ } else if (!strcmp(pblk.descr[i].name, "sig.debuglevel")) {
+ rsksiSetDebugLevel(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirowner")) {
+ rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirownernum")) {
+ rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirgroup")) {
+ rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dirgroupnum")) {
+ rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "fileowner")) {
+ rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "fileownernum")) {
+ rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filegroup")) {
+ rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filegroupnum")) {
+ rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "dircreatemode")) {
+ rsksiSetDirCreateMode(pThis->ctx, pvals[i].val.d.n);
+ } else if (!strcmp(pblk.descr[i].name, "filecreatemode")) {
+ rsksiSetCreateMode(pThis->ctx, pvals[i].val.d.n);
+ } else {
+ DBGPRINTF("lmsig_ksi: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+ }
+
+ if(rsksiSetHashFunction(pThis->ctx, hash ? hash : (char*) "default") != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+ if(rsksiSetHmacFunction(pThis->ctx, hmac ? hmac : (char*) "default") != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+ if(rsksiSetAggregator(pThis->ctx, ag_uri, ag_loginid, ag_key) != KSI_OK) {
+ ABORT_FINALIZE(RS_RET_KSI_ERR);
+ }
+
+finalize_it:
+ free(ag_uri);
+ free(ag_loginid);
+ free(ag_key);
+ free(hash);
+ free(hmac);
+
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &pblk);
+ RETiRet;
+}
+
+
+static rsRetVal
+OnFileOpen(void *pT, uchar *fn, void *pGF) {
+ lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t*) pT;
+ ksifile *pgf = (ksifile*) pGF;
+ DEFiRet;
+ /* note: if *pgf is set to NULL, this auto-disables GT functions */
+ *pgf = rsksiCtxOpenFile(pThis->ctx, fn);
+ sigblkInitKSI(*pgf);
+ RETiRet;
+}
+
+/* Note: we assume that the record is terminated by a \n.
+ * As of the GuardTime paper, \n is not part of the signed
+ * message, so we subtract one from the record size. This
+ * may cause issues with non-standard formats, but let's
+ * see how things evolve (the verifier will not work in
+ * any case when the records are not \n delimited...).
+ * rgerhards, 2013-03-17
+ */
+static rsRetVal
+OnRecordWrite(void *pF, uchar *rec, rs_size_t lenRec)
+{
+ DEFiRet;
+ DBGPRINTF("lmsig_ksi-ls12: onRecordWrite (%d): %s\n", lenRec - 1, rec);
+ sigblkAddRecordKSI(pF, rec, lenRec - 1);
+
+ RETiRet;
+}
+
+static rsRetVal
+OnFileClose(void *pF)
+{
+ DEFiRet;
+ DBGPRINTF("lmsig_ksi_ls12: onFileClose\n");
+ rsksifileDestruct(pF);
+
+ RETiRet;
+}
+
+BEGINobjQueryInterface(lmsig_ksi_ls12)
+CODESTARTobjQueryInterface(lmsig_ksi_ls12)
+ if (pIf->ifVersion != sigprovCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->Construct = (rsRetVal(*)(void*)) lmsig_ksi_ls12Construct;
+ pIf->SetCnfParam = SetCnfParam;
+ pIf->Destruct = (rsRetVal(*)(void*)) lmsig_ksi_ls12Destruct;
+ pIf->OnFileOpen = OnFileOpen;
+ pIf->OnRecordWrite = OnRecordWrite;
+ pIf->OnFileClose = OnFileClose;
+finalize_it:
+ENDobjQueryInterface(lmsig_ksi_ls12)
+
+
+BEGINObjClassExit(lmsig_ksi_ls12, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(lmsig_ksi_ls12)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(lmsig_ksi_ls12)
+
+
+BEGINObjClassInit(lmsig_ksi_ls12, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDObjClassInit(lmsig_ksi_ls12)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+lmsig_ksi_ls12ClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+CHKiRet(lmsig_ksi_ls12ClassInit(pModInfo));
+ENDmodInit
diff --git a/runtime/lmsig_ksi-ls12.h b/runtime/lmsig_ksi-ls12.h
new file mode 100644
index 0000000..3ac5cce
--- /dev/null
+++ b/runtime/lmsig_ksi-ls12.h
@@ -0,0 +1,40 @@
+/* An implementation of the sigprov interface for KSI-LS12.
+ *
+ * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LMSIG_LS12_KSI_H
+#define INCLUDED_LMSIG_LS12_KSI_H
+#include "sigprov.h"
+#include "lib_ksils12.h"
+
+/* interface is defined in sigprov.h, we just implement it! */
+#define lmsig_ksi_ls12CURR_IF_VERSION sigprovCURR_IF_VERSION
+typedef sigprov_if_t lmsig_ksi_ls12_if_t;
+
+/* the lmsig_ksi object */
+struct lmsig_ksi_ls12_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ rsksictx ctx; /* librsksi context - contains all we need */
+};
+typedef struct lmsig_ksi_ls12_s lmsig_ksi_ls12_t;
+
+/* prototypes */
+PROTOTYPEObj(lmsig_ksi_ls12);
+
+#endif /* #ifndef INCLUDED_LMSIG_LS12_KSI_H */
diff --git a/runtime/lookup.c b/runtime/lookup.c
new file mode 100644
index 0000000..4408581
--- /dev/null
+++ b/runtime/lookup.c
@@ -0,0 +1,1093 @@
+/* lookup.c
+ * Support for lookup tables in RainerScript.
+ *
+ * Copyright 2013-2023 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <json.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "lookup.h"
+#include "msg.h"
+#include "rsconf.h"
+#include "dirty.h"
+#include "unicode-helper.h"
+
+PRAGMA_IGNORE_Wdeprecated_declarations
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+/* forward definitions */
+static rsRetVal lookupReadFile(lookup_t *pThis, const uchar* name, const uchar* filename);
+static void lookupDestruct(lookup_t *pThis);
+
+/* static data */
+/* tables for interfacing with the v6 config system (as far as we need to) */
+static struct cnfparamdescr modpdescr[] = {
+ { "name", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "file", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "reloadOnHUP", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* internal data-types */
+typedef struct uint32_index_val_s {
+ uint32_t index;
+ uchar *val;
+} uint32_index_val_t;
+
+const char * reloader_prefix = "lkp_tbl_reloader:";
+
+static void *
+lookupTableReloader(void *self);
+
+static void
+lookupStopReloader(lookup_ref_t *pThis);
+
+
+/* create a new lookup table object AND include it in our list of
+ * lookup tables.
+ */
+static rsRetVal
+lookupNew(lookup_ref_t **ppThis)
+{
+ lookup_ref_t *pThis = NULL;
+ lookup_t *t = NULL;
+ DEFiRet;
+
+ CHKmalloc(pThis = calloc(1, sizeof(lookup_ref_t)));
+ CHKmalloc(t = calloc(1, sizeof(lookup_t)));
+ pThis->do_reload = pThis->do_stop = 0;
+ pThis->reload_on_hup = 1; /*DO reload on HUP (default)*/
+
+ pThis->next = NULL;
+ if(loadConf->lu_tabs.root == NULL) {
+ loadConf->lu_tabs.root = pThis;
+ } else {
+ loadConf->lu_tabs.last->next = pThis;
+ }
+ loadConf->lu_tabs.last = pThis;
+
+ pThis->self = t;
+
+ *ppThis = pThis;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(errno, iRet, "a lookup table could not be initialized");
+ free(t);
+ free(pThis);
+ }
+ RETiRet;
+}
+
+/* activate a lookup table entry once rsyslog is ready to do so */
+static rsRetVal
+lookupActivateTable(lookup_ref_t *pThis)
+{
+ DEFiRet;
+ int initialized = 0;
+
+ DBGPRINTF("lookupActivateTable called\n");
+ CHKiConcCtrl(pthread_rwlock_init(&pThis->rwlock, NULL));
+ initialized++; /*1*/
+ CHKiConcCtrl(pthread_mutex_init(&pThis->reloader_mut, NULL));
+ initialized++; /*2*/
+ CHKiConcCtrl(pthread_cond_init(&pThis->run_reloader, NULL));
+ initialized++; /*3*/
+ CHKiConcCtrl(pthread_attr_init(&pThis->reloader_thd_attr));
+ initialized++; /*4*/
+ pThis->do_reload = pThis->do_stop = 0;
+ CHKiConcCtrl(pthread_create(&pThis->reloader, &pThis->reloader_thd_attr,
+ lookupTableReloader, pThis));
+ initialized++; /*5*/
+
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(errno, iRet, "a lookup table could not be activated: "
+ "failed at init-step %d (please enable debug logs for details)",
+ initialized);
+ /* Can not happen with current code, but might occur in the future when
+ * an error-condition as added after step 5. If we leave it in, Coverity
+ * scan complains. So we comment it out but do not remove the code.
+ * Triggered by CID 185426
+ if (initialized > 4) lookupStopReloader(pThis);
+ */
+ if (initialized > 3) pthread_attr_destroy(&pThis->reloader_thd_attr);
+ if (initialized > 2) pthread_cond_destroy(&pThis->run_reloader);
+ if (initialized > 1) pthread_mutex_destroy(&pThis->reloader_mut);
+ if (initialized > 0) pthread_rwlock_destroy(&pThis->rwlock);
+ }
+ RETiRet;
+}
+
+/*must be called with reloader_mut acquired*/
+static void ATTR_NONNULL()
+freeStubValueForReloadFailure(lookup_ref_t *const pThis)
+{
+ if (pThis->stub_value_for_reload_failure != NULL) {
+ free(pThis->stub_value_for_reload_failure);
+ pThis->stub_value_for_reload_failure = NULL;
+ }
+}
+
+static void
+lookupStopReloader(lookup_ref_t *pThis) {
+ pthread_mutex_lock(&pThis->reloader_mut);
+ freeStubValueForReloadFailure(pThis);
+ pThis->do_reload = 0;
+ pThis->do_stop = 1;
+ pthread_cond_signal(&pThis->run_reloader);
+ pthread_mutex_unlock(&pThis->reloader_mut);
+ pthread_join(pThis->reloader, NULL);
+}
+
+static void
+lookupRefDestruct(lookup_ref_t *pThis)
+{
+ lookupStopReloader(pThis);
+ pthread_mutex_destroy(&pThis->reloader_mut);
+ pthread_cond_destroy(&pThis->run_reloader);
+ pthread_attr_destroy(&pThis->reloader_thd_attr);
+
+ pthread_rwlock_destroy(&pThis->rwlock);
+ lookupDestruct(pThis->self);
+ free(pThis->name);
+ free(pThis->filename);
+ free(pThis);
+}
+
+static void
+destructTable_str(lookup_t *pThis) {
+ uint32_t i = 0;
+ lookup_string_tab_entry_t *entries = pThis->table.str->entries;
+ for (i = 0; i < pThis->nmemb; i++) {
+ free(entries[i].key);
+ }
+ free(entries);
+ free(pThis->table.str);
+}
+
+
+static void
+destructTable_arr(lookup_t *pThis) {
+ free(pThis->table.arr->interned_val_refs);
+ free(pThis->table.arr);
+}
+
+static void
+destructTable_sparseArr(lookup_t *pThis) {
+ free(pThis->table.sprsArr->entries);
+ free(pThis->table.sprsArr);
+}
+
+static void
+lookupDestruct(lookup_t *pThis) {
+ uint32_t i;
+
+ if (pThis == NULL) return;
+
+ if (pThis->type == STRING_LOOKUP_TABLE) {
+ destructTable_str(pThis);
+ } else if (pThis->type == ARRAY_LOOKUP_TABLE) {
+ destructTable_arr(pThis);
+ } else if (pThis->type == SPARSE_ARRAY_LOOKUP_TABLE) {
+ destructTable_sparseArr(pThis);
+ } else if (pThis->type == STUBBED_LOOKUP_TABLE) {
+ /*nothing to be done*/
+ }
+
+ for (i = 0; i < pThis->interned_val_count; i++) {
+ free(pThis->interned_vals[i]);
+ }
+ free(pThis->interned_vals);
+ free(pThis->nomatch);
+ free(pThis);
+}
+
+void
+lookupInitCnf(lookup_tables_t *lu_tabs)
+{
+ lu_tabs->root = NULL;
+ lu_tabs->last = NULL;
+}
+
+void
+lookupDestroyCnf(void)
+{
+ lookup_ref_t *luref, *luref_next;
+ for(luref = runConf->lu_tabs.root ; luref != NULL ; ) {
+ luref_next = luref->next;
+ lookupRefDestruct(luref);
+ luref = luref_next;
+ }
+}
+
+/* comparison function for qsort() */
+static int
+qs_arrcmp_strtab(const void *s1, const void *s2)
+{
+ return ustrcmp(((lookup_string_tab_entry_t*)s1)->key, ((lookup_string_tab_entry_t*)s2)->key);
+}
+
+static int
+qs_arrcmp_ustrs(const void *s1, const void *s2)
+{
+ return ustrcmp(*(uchar**)s1, *(uchar**)s2);
+}
+
+static int
+qs_arrcmp_uint32_index_val(const void *s1, const void *s2)
+{
+ uint32_t first_value = ((uint32_index_val_t*)s1)->index;
+ uint32_t second_value = ((uint32_index_val_t*)s2)->index;
+ if (first_value < second_value) {
+ return -1;
+ }
+ return first_value - second_value;
+}
+
+static int
+qs_arrcmp_sprsArrtab(const void *s1, const void *s2)
+{
+ uint32_t first_value = ((lookup_sparseArray_tab_entry_t*)s1)->key;
+ uint32_t second_value = ((lookup_sparseArray_tab_entry_t*)s2)->key;
+ if (first_value < second_value) {
+ return -1;
+ }
+ return first_value - second_value;
+}
+
+/* comparison function for bsearch() and string array compare
+ * this is for the string lookup table type
+ */
+static int
+bs_arrcmp_strtab(const void *s1, const void *s2)
+{
+ return strcmp((char*)s1, (char*)((lookup_string_tab_entry_t*)s2)->key);
+}
+
+static int
+bs_arrcmp_str(const void *s1, const void *s2)
+{
+ return ustrcmp((uchar*)s1, *(uchar**)s2);
+}
+
+static int
+bs_arrcmp_sprsArrtab(const void *s1, const void *s2)
+{
+ uint32_t key = *(uint32_t*)s1;
+ uint32_t array_member_value = ((lookup_sparseArray_tab_entry_t*)s2)->key;
+ if (key < array_member_value) {
+ return -1;
+ }
+ return key - array_member_value;
+}
+
+static inline const char*
+defaultVal(lookup_t *pThis) {
+ return (pThis->nomatch == NULL) ? "" : (const char*) pThis->nomatch;
+}
+
+/* lookup_fn for different types of tables */
+static es_str_t*
+lookupKey_stub(lookup_t *pThis, lookup_key_t __attribute__((unused)) key) {
+ return es_newStrFromCStr((char*) pThis->nomatch, ustrlen(pThis->nomatch));
+}
+
+static es_str_t*
+lookupKey_str(lookup_t *pThis, lookup_key_t key) {
+ lookup_string_tab_entry_t *entry;
+ const char *r;
+ if(pThis->nmemb == 0) {
+ entry = NULL;
+ } else {
+ assert(pThis->table.str->entries);
+ entry = bsearch(key.k_str, pThis->table.str->entries, pThis->nmemb,
+ sizeof(lookup_string_tab_entry_t), bs_arrcmp_strtab);
+ }
+ if(entry == NULL) {
+ r = defaultVal(pThis);
+ } else {
+ r = (const char*)entry->interned_val_ref;
+ }
+ return es_newStrFromCStr(r, strlen(r));
+}
+
+static es_str_t*
+lookupKey_arr(lookup_t *pThis, lookup_key_t key) {
+ const char *r;
+ uint32_t uint_key = key.k_uint;
+ if ((pThis->nmemb == 0) || (uint_key < pThis->table.arr->first_key)) {
+ r = defaultVal(pThis);
+ } else {
+ uint32_t idx = uint_key - pThis->table.arr->first_key;
+ if (idx >= pThis->nmemb) {
+ r = defaultVal(pThis);
+ } else {
+ r = (char*) pThis->table.arr->interned_val_refs[idx];
+ }
+ }
+
+ return es_newStrFromCStr(r, strlen(r));
+}
+
+typedef int (comp_fn_t)(const void *s1, const void *s2);
+
+static void *
+bsearch_lte(const void *key, const void *base, size_t nmemb, size_t size, comp_fn_t *comp_fn)
+{
+ size_t l, u, idx;
+ const void *p;
+ int comparison;
+
+ l = 0;
+ u = nmemb;
+ if (l == u) {
+ return NULL;
+ }
+ while (l < u) {
+ idx = (l + u) / 2;
+ p = (void *) (((const char *) base) + (idx * size));
+ comparison = (*comp_fn)(key, p);
+ if (comparison < 0)
+ u = idx;
+ else if (comparison > 0)
+ l = idx + 1;
+ else
+ return (void *) p;
+ }
+ if (comparison < 0) {
+ if (idx == 0) {
+ return NULL;
+ }
+ idx--;
+ }
+ return (void *) (((const char *) base) + ( idx * size));
+}
+
+static es_str_t*
+lookupKey_sprsArr(lookup_t *pThis, lookup_key_t key) {
+ lookup_sparseArray_tab_entry_t *entry;
+ const char *r;
+ if (pThis->nmemb == 0) {
+ entry = NULL;
+ } else {
+ entry = bsearch_lte(&key.k_uint, pThis->table.sprsArr->entries, pThis->nmemb,
+ sizeof(lookup_sparseArray_tab_entry_t), bs_arrcmp_sprsArrtab);
+ }
+
+ if(entry == NULL) {
+ r = defaultVal(pThis);
+ } else {
+ r = (const char*)entry->interned_val_ref;
+ }
+ return es_newStrFromCStr(r, strlen(r));
+}
+
+/* builders for different table-types */
+
+#define NO_INDEX_ERROR(type, name) \
+ LogError(0, RS_RET_INVALID_VALUE, "'%s' lookup table named: '%s' has record(s) without 'index' "\
+"field", type, name); \
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+
+static rsRetVal
+build_StringTable(lookup_t *pThis, struct json_object *jtab, const uchar* name) {
+ uint32_t i;
+ struct json_object *jrow, *jindex, *jvalue;
+ uchar *value, *canonicalValueRef;
+ DEFiRet;
+
+ pThis->table.str = NULL;
+ CHKmalloc(pThis->table.str = calloc(1, sizeof(lookup_string_tab_t)));
+ if (pThis->nmemb > 0) {
+ CHKmalloc(pThis->table.str->entries = calloc(pThis->nmemb, sizeof(lookup_string_tab_entry_t)));
+
+ for(i = 0; i < pThis->nmemb; i++) {
+ jrow = json_object_array_get_idx(jtab, i);
+ jindex = json_object_object_get(jrow, "index");
+ jvalue = json_object_object_get(jrow, "value");
+ if (jindex == NULL || json_object_is_type(jindex, json_type_null)) {
+ NO_INDEX_ERROR("string", name);
+ }
+ CHKmalloc(pThis->table.str->entries[i].key = ustrdup((uchar*) json_object_get_string(jindex)));
+ value = (uchar*) json_object_get_string(jvalue);
+ uchar **found = (uchar**) bsearch(value, pThis->interned_vals,
+ pThis->interned_val_count, sizeof(uchar*), bs_arrcmp_str);
+ if(found == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "lookup.c:build_StringTable(): "
+ "internal error, bsearch returned NULL for '%s'", value);
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ // I give up, I see no way to remove false positive -- rgerhards, 2017-10-24
+ #ifndef __clang_analyzer__
+ canonicalValueRef = *found;
+ if(canonicalValueRef == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "lookup.c:build_StringTable(): "
+ "internal error, canonicalValueRef returned from bsearch "
+ "is NULL for '%s'", value);
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ pThis->table.str->entries[i].interned_val_ref = canonicalValueRef;
+ #endif
+ }
+ qsort(pThis->table.str->entries, pThis->nmemb, sizeof(lookup_string_tab_entry_t), qs_arrcmp_strtab);
+ }
+
+ pThis->lookup = lookupKey_str;
+ pThis->key_type = LOOKUP_KEY_TYPE_STRING;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+build_ArrayTable(lookup_t *pThis, struct json_object *jtab, const uchar *name) {
+ uint32_t i;
+ struct json_object *jrow, *jindex, *jvalue;
+ uchar *canonicalValueRef;
+ uint32_t prev_index, _index;
+ uint8_t prev_index_set;
+ uint32_index_val_t *indexes = NULL;
+ DEFiRet;
+
+ prev_index_set = 0;
+
+ pThis->table.arr = NULL;
+ CHKmalloc(pThis->table.arr = calloc(1, sizeof(lookup_array_tab_t)));
+ if (pThis->nmemb > 0) {
+ CHKmalloc(indexes = calloc(pThis->nmemb, sizeof(uint32_index_val_t)));
+ CHKmalloc(pThis->table.arr->interned_val_refs = calloc(pThis->nmemb, sizeof(uchar*)));
+
+ for(i = 0; i < pThis->nmemb; i++) {
+ jrow = json_object_array_get_idx(jtab, i);
+ jindex = json_object_object_get(jrow, "index");
+ jvalue = json_object_object_get(jrow, "value");
+ if (jindex == NULL || json_object_is_type(jindex, json_type_null)) {
+ NO_INDEX_ERROR("array", name);
+ }
+ indexes[i].index = (uint32_t) json_object_get_int(jindex);
+ indexes[i].val = (uchar*) json_object_get_string(jvalue);
+ }
+ qsort(indexes, pThis->nmemb, sizeof(uint32_index_val_t), qs_arrcmp_uint32_index_val);
+ for(i = 0; i < pThis->nmemb; i++) {
+ _index = indexes[i].index;
+ if (prev_index_set == 0) {
+ prev_index = _index;
+ prev_index_set = 1;
+ pThis->table.arr->first_key = _index;
+ } else {
+ if (_index != ++prev_index) {
+ LogError(0, RS_RET_INVALID_VALUE, "'array' lookup table name: '%s' "
+ "has non-contiguous members between index '%d' and '%d'",
+ name, prev_index, _index);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+ }
+ uchar *const *const canonicalValueRef_ptr = bsearch(indexes[i].val, pThis->interned_vals,
+ pThis->interned_val_count, sizeof(uchar*), bs_arrcmp_str);
+ if(canonicalValueRef_ptr == NULL) {
+ LogError(0, RS_RET_ERR, "BUG: canonicalValueRef not found in "
+ "build_ArrayTable(), %s:%d", __FILE__, __LINE__);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ canonicalValueRef = *canonicalValueRef_ptr;
+ assert(canonicalValueRef != NULL);
+ pThis->table.arr->interned_val_refs[i] = canonicalValueRef;
+ }
+ }
+
+ pThis->lookup = lookupKey_arr;
+ pThis->key_type = LOOKUP_KEY_TYPE_UINT;
+
+finalize_it:
+ free(indexes);
+ RETiRet;
+}
+
+static rsRetVal
+build_SparseArrayTable(lookup_t *pThis, struct json_object *jtab, const uchar* name) {
+ uint32_t i;
+ struct json_object *jrow, *jindex, *jvalue;
+ uchar *value, *canonicalValueRef;
+ DEFiRet;
+
+ pThis->table.str = NULL;
+ CHKmalloc(pThis->table.sprsArr = calloc(1, sizeof(lookup_sparseArray_tab_t)));
+ if (pThis->nmemb > 0) {
+ CHKmalloc(pThis->table.sprsArr->entries = calloc(pThis->nmemb, sizeof(lookup_sparseArray_tab_entry_t)));
+
+ for(i = 0; i < pThis->nmemb; i++) {
+ jrow = json_object_array_get_idx(jtab, i);
+ jindex = json_object_object_get(jrow, "index");
+ jvalue = json_object_object_get(jrow, "value");
+ if (jindex == NULL || json_object_is_type(jindex, json_type_null)) {
+ NO_INDEX_ERROR("sparseArray", name);
+ }
+ pThis->table.sprsArr->entries[i].key = (uint32_t) json_object_get_int(jindex);
+ value = (uchar*) json_object_get_string(jvalue);
+ uchar *const *const canonicalValueRef_ptr = bsearch(value, pThis->interned_vals,
+ pThis->interned_val_count, sizeof(uchar*), bs_arrcmp_str);
+ if(canonicalValueRef_ptr == NULL) {
+ LogError(0, RS_RET_ERR, "BUG: canonicalValueRef not found in "
+ "build_SparseArrayTable(), %s:%d", __FILE__, __LINE__);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ canonicalValueRef = *canonicalValueRef_ptr;
+ assert(canonicalValueRef != NULL);
+ pThis->table.sprsArr->entries[i].interned_val_ref = canonicalValueRef;
+ }
+ qsort(pThis->table.sprsArr->entries, pThis->nmemb, sizeof(lookup_sparseArray_tab_entry_t),
+ qs_arrcmp_sprsArrtab);
+ }
+
+ pThis->lookup = lookupKey_sprsArr;
+ pThis->key_type = LOOKUP_KEY_TYPE_UINT;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+lookupBuildStubbedTable(lookup_t *pThis, const uchar* stub_val) {
+ DEFiRet;
+
+ CHKmalloc(pThis->nomatch = ustrdup(stub_val));
+ pThis->lookup = lookupKey_stub;
+ pThis->type = STUBBED_LOOKUP_TABLE;
+ pThis->key_type = LOOKUP_KEY_TYPE_NONE;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+lookupBuildTable_v1(lookup_t *pThis, struct json_object *jroot, const uchar* name) {
+ struct json_object *jnomatch, *jtype, *jtab;
+ struct json_object *jrow, *jvalue;
+ const char *table_type, *nomatch_value;
+ const uchar **all_values;
+ const uchar *curr, *prev;
+ uint32_t i, j;
+ uint32_t uniq_values;
+
+ DEFiRet;
+ all_values = NULL;
+
+ jnomatch = json_object_object_get(jroot, "nomatch");
+ jtype = json_object_object_get(jroot, "type");
+ jtab = json_object_object_get(jroot, "table");
+ if (jtab == NULL || !json_object_is_type(jtab, json_type_array)) {
+ LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' has invalid table definition", name);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+ pThis->nmemb = json_object_array_length(jtab);
+ table_type = json_object_get_string(jtype);
+ if (table_type == NULL) {
+ table_type = "string";
+ }
+
+ CHKmalloc(all_values = malloc(pThis->nmemb * sizeof(uchar*)));
+
+ /* before actual table can be loaded, prepare all-value list and remove duplicates*/
+ for(i = 0; i < pThis->nmemb; i++) {
+ jrow = json_object_array_get_idx(jtab, i);
+ jvalue = json_object_object_get(jrow, "value");
+ if (jvalue == NULL || json_object_is_type(jvalue, json_type_null)) {
+ LogError(0, RS_RET_INVALID_VALUE, "'%s' lookup table named: '%s' has record(s) "
+ "without 'value' field", table_type, name);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+ all_values[i] = (const uchar*) json_object_get_string(jvalue);
+ }
+ qsort(all_values, pThis->nmemb, sizeof(uchar*), qs_arrcmp_ustrs);
+ uniq_values = 1;
+ for(i = 1; i < pThis->nmemb; i++) {
+ curr = all_values[i];
+ prev = all_values[i - 1];
+ if (ustrcmp(prev, curr) != 0) {
+ uniq_values++;
+ }
+ }
+
+ if (pThis->nmemb > 0) {
+ CHKmalloc(pThis->interned_vals = malloc(uniq_values * sizeof(uchar*)));
+ j = 0;
+ CHKmalloc(pThis->interned_vals[j++] = ustrdup(all_values[0]));
+ for(i = 1; i < pThis->nmemb ; ++i) {
+ curr = all_values[i];
+ prev = all_values[i - 1];
+ if (ustrcmp(prev, curr) != 0) {
+ CHKmalloc(pThis->interned_vals[j++] = ustrdup(all_values[i]));
+ }
+ }
+ pThis->interned_val_count = uniq_values;
+ }
+ /* uniq values captured (sorted) */
+
+ nomatch_value = json_object_get_string(jnomatch);
+ if (nomatch_value != NULL) {
+ CHKmalloc(pThis->nomatch = (uchar*) strdup(nomatch_value));
+ }
+
+ if (strcmp(table_type, "array") == 0) {
+ pThis->type = ARRAY_LOOKUP_TABLE;
+ CHKiRet(build_ArrayTable(pThis, jtab, name));
+ } else if (strcmp(table_type, "sparseArray") == 0) {
+ pThis->type = SPARSE_ARRAY_LOOKUP_TABLE;
+ CHKiRet(build_SparseArrayTable(pThis, jtab, name));
+ } else if (strcmp(table_type, "string") == 0) {
+ pThis->type = STRING_LOOKUP_TABLE;
+ CHKiRet(build_StringTable(pThis, jtab, name));
+ } else {
+ LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' uses unupported "
+ "type: '%s'", name, table_type);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+finalize_it:
+ if (all_values != NULL) free(all_values);
+ RETiRet;
+}
+
+static rsRetVal
+lookupBuildTable(lookup_t *pThis, struct json_object *jroot, const uchar* name)
+{
+ struct json_object *jversion;
+ int version = 1;
+
+ DEFiRet;
+
+ jversion = json_object_object_get(jroot, "version");
+ if (jversion != NULL && !json_object_is_type(jversion, json_type_null)) {
+ version = json_object_get_int(jversion);
+ } else {
+ LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' doesn't specify version "
+ "(will use default value: %d)", name, version);
+ }
+ if (version == 1) {
+ CHKiRet(lookupBuildTable_v1(pThis, jroot, name));
+ } else {
+ LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' uses unsupported "
+ "version: %d", name, version);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* find a lookup table. This is a naive O(n) algo, but this really
+ * doesn't matter as it is called only a few times during config
+ * load. The function returns either a pointer to the requested
+ * table or NULL, if not found.
+ */
+lookup_ref_t * ATTR_NONNULL()
+lookupFindTable(uchar *name)
+{
+ lookup_ref_t *curr;
+
+ for(curr = loadConf->lu_tabs.root ; curr != NULL ; curr = curr->next) {
+ if(!ustrcmp(curr->name, name))
+ break;
+ }
+ return curr;
+}
+
+
+/* this reloads a lookup table. This is done while the engine is running,
+ * as such the function must ensure proper locking and proper order of
+ * operations (so that nothing can interfere). If the table cannot be loaded,
+ * the old table is continued to be used.
+ */
+static rsRetVal
+lookupReloadOrStub(lookup_ref_t *pThis, const uchar* stub_val) {
+ lookup_t *newlu, *oldlu; /* dummy to be able to use support functions without
+ affecting current settings. */
+ DEFiRet;
+
+ oldlu = pThis->self;
+ newlu = NULL;
+
+ DBGPRINTF("reload requested for lookup table '%s'\n", pThis->name);
+ CHKmalloc(newlu = calloc(1, sizeof(lookup_t)));
+ if (stub_val == NULL) {
+ CHKiRet(lookupReadFile(newlu, pThis->name, pThis->filename));
+ } else {
+ CHKiRet(lookupBuildStubbedTable(newlu, stub_val));
+ }
+ /* all went well, copy over data members */
+ pthread_rwlock_wrlock(&pThis->rwlock);
+ pThis->self = newlu;
+ pthread_rwlock_unlock(&pThis->rwlock);
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (stub_val == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "lookup table '%s' could not be reloaded from file '%s'",
+ pThis->name, pThis->filename);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "lookup table '%s' could not be stubbed with value '%s'",
+ pThis->name, stub_val);
+ }
+ lookupDestruct(newlu);
+ } else {
+ if (stub_val == NULL) {
+ LogMsg(0, RS_RET_OK, LOG_INFO, "lookup table '%s' reloaded from file '%s'",
+ pThis->name, pThis->filename);
+ } else {
+ LogError(0, RS_RET_OK, "lookup table '%s' stubbed with value '%s'",
+ pThis->name, stub_val);
+ }
+ lookupDestruct(oldlu);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+lookupDoStub(lookup_ref_t *pThis, const uchar* stub_val)
+{
+ int already_stubbed = 0;
+ DEFiRet;
+ pthread_rwlock_rdlock(&pThis->rwlock);
+ if (pThis->self->type == STUBBED_LOOKUP_TABLE &&
+ ustrcmp(pThis->self->nomatch, stub_val) == 0)
+ already_stubbed = 1;
+ pthread_rwlock_unlock(&pThis->rwlock);
+ if (! already_stubbed) {
+ LogError(0, RS_RET_OK, "stubbing lookup table '%s' with value '%s'",
+ pThis->name, stub_val);
+ CHKiRet(lookupReloadOrStub(pThis, stub_val));
+ } else {
+ LogError(0, RS_RET_OK, "lookup table '%s' is already stubbed with value '%s'",
+ pThis->name, stub_val);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static uint8_t
+lookupIsReloadPending(lookup_ref_t *pThis) {
+ uint8_t reload_pending;
+ pthread_mutex_lock(&pThis->reloader_mut);
+ reload_pending = pThis->do_reload;
+ pthread_mutex_unlock(&pThis->reloader_mut);
+ return reload_pending;
+}
+
+/* note: stub_val_if_reload_fails may or may not be NULL */
+rsRetVal ATTR_NONNULL(1)
+lookupReload(lookup_ref_t *const pThis, const uchar *const stub_val_if_reload_fails)
+{
+ uint8_t locked = 0;
+ int lock_errno = 0;
+ DEFiRet;
+ assert(pThis != NULL);
+ if ((lock_errno = pthread_mutex_trylock(&pThis->reloader_mut)) == 0) {
+ locked = 1;
+ /*so it doesn't leak memory in situation where 2 reload requests are issued back to back*/
+ freeStubValueForReloadFailure(pThis);
+ if (stub_val_if_reload_fails != NULL) {
+ CHKmalloc(pThis->stub_value_for_reload_failure = ustrdup(stub_val_if_reload_fails));
+ }
+ pThis->do_reload = 1;
+ pthread_cond_signal(&pThis->run_reloader);
+ } else {
+ LogError(lock_errno, RS_RET_INTERNAL_ERROR, "attempt to trigger "
+ "reload of lookup table '%s' failed (not stubbing)", pThis->name);
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ /* we can choose to stub the table here, but it'll hurt because
+ the table reloader may take time to complete the reload
+ and stubbing because of a concurrent reload message may
+ not be desirable (except in very tightly controled environments
+ where reload-triggering messages pushed are timed accurately
+ and an idempotency-filter is used to reject re-deliveries) */
+ }
+finalize_it:
+ if (locked) {
+ pthread_mutex_unlock(&pThis->reloader_mut);
+ }
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+lookupDoReload(lookup_ref_t *pThis)
+{
+ DEFiRet;
+ iRet = lookupReloadOrStub(pThis, NULL);
+ if ((iRet != RS_RET_OK) &&
+ (pThis->stub_value_for_reload_failure != NULL)) {
+ iRet = lookupDoStub(pThis, pThis->stub_value_for_reload_failure);
+ }
+ freeStubValueForReloadFailure(pThis);
+ RETiRet;
+}
+
+void *
+lookupTableReloader(void *self)
+{
+ lookup_ref_t *pThis = (lookup_ref_t*) self;
+ pthread_mutex_lock(&pThis->reloader_mut);
+ while(1) {
+ if (pThis->do_stop) {
+ break;
+ } else if (pThis->do_reload) {
+ lookupDoReload(pThis);
+ pThis->do_reload = 0;
+ } else {
+ pthread_cond_wait(&pThis->run_reloader, &pThis->reloader_mut);
+ }
+ }
+ pthread_mutex_unlock(&pThis->reloader_mut);
+ return NULL;
+}
+
+/* reload all lookup tables on HUP */
+void
+lookupDoHUP(void)
+{
+ lookup_ref_t *luref;
+ for(luref = runConf->lu_tabs.root ; luref != NULL ; luref = luref->next) {
+ if (luref->reload_on_hup) {
+ lookupReload(luref, NULL);
+ }
+ }
+}
+
+/* activate lookup table system config
+ * most importantly, this means tarting the lookup table reloader thread in the
+ * right process space - it is a difference if we fork or not!
+ */
+void
+lookupActivateConf(void)
+{
+ DBGPRINTF("lookup tables: activate config \n");
+ lookup_ref_t *luref;
+ for(luref = runConf->lu_tabs.root ; luref != NULL ; luref = luref->next) {
+ DBGPRINTF("lookup actiate: processing %p\n", luref);
+ lookupActivateTable(luref);
+ }
+ DBGPRINTF("lookup tables: activate done\n");
+}
+
+uint
+lookupPendingReloadCount(void)
+{
+ uint pending_reload_count = 0;
+ lookup_ref_t *luref;
+ for(luref = runConf->lu_tabs.root ; luref != NULL ; luref = luref->next) {
+ if (lookupIsReloadPending(luref)) {
+ pending_reload_count++;
+ }
+ }
+ return pending_reload_count;
+}
+
+
+/* returns either a pointer to the value (read only!) or NULL
+ * if either the key could not be found or an error occurred.
+ * Note that an estr_t object is returned. The caller is
+ * responsible for freeing it.
+ */
+es_str_t *
+lookupKey(lookup_ref_t *pThis, lookup_key_t key)
+{
+ es_str_t *estr;
+ lookup_t *t;
+ pthread_rwlock_rdlock(&pThis->rwlock);
+ t = pThis->self;
+ estr = t->lookup(t, key);
+ pthread_rwlock_unlock(&pThis->rwlock);
+ return estr;
+}
+
+
+/* note: widely-deployed json_c 0.9 does NOT support incremental
+ * parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS,
+ * we read the file into one big memory buffer and parse it at once.
+ * While this is not very elegant, it will not pose any real issue
+ * for "reasonable" lookup tables (and "unreasonably" large ones
+ * will probably have other issues as well...).
+ */
+static rsRetVal ATTR_NONNULL()
+lookupReadFile(lookup_t *const pThis, const uchar *const name, const uchar *const filename)
+{
+ struct json_tokener *tokener = NULL;
+ struct json_object *json = NULL;
+ char *iobuf = NULL;
+ int fd = -1;
+ ssize_t nread;
+ struct stat sb;
+ DEFiRet;
+
+
+ if((fd = open((const char*) filename, O_RDONLY)) == -1) {
+ LogError(errno, RS_RET_FILE_NOT_FOUND,
+ "lookup table file '%s' could not be opened", filename);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ }
+
+ if(fstat(fd, &sb) == -1) {
+ LogError(errno, RS_RET_FILE_NOT_FOUND,
+ "lookup table file '%s' stat failed", filename);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ }
+
+ CHKmalloc(iobuf = malloc(sb.st_size));
+
+ tokener = json_tokener_new();
+ nread = read(fd, iobuf, sb.st_size);
+ if(nread != (ssize_t) sb.st_size) {
+ LogError(errno, RS_RET_READ_ERR,
+ "lookup table file '%s' read error", filename);
+ ABORT_FINALIZE(RS_RET_READ_ERR);
+ }
+
+ json = json_tokener_parse_ex(tokener, iobuf, sb.st_size);
+ if(json == NULL) {
+ LogError(0, RS_RET_JSON_PARSE_ERR,
+ "lookup table file '%s' json parsing error",
+ filename);
+ ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR);
+ }
+ free(iobuf); /* early free to sever resources*/
+ iobuf = NULL; /* make sure no double-free */
+
+ /* got json object, now populate our own in-memory structure */
+ CHKiRet(lookupBuildTable(pThis, json, name));
+
+finalize_it:
+ if (fd != -1) {
+ close(fd);
+ }
+ free(iobuf);
+ if(tokener != NULL)
+ json_tokener_free(tokener);
+ if(json != NULL)
+ json_object_put(json);
+ RETiRet;
+}
+
+
+rsRetVal
+lookupTableDefProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ lookup_ref_t *lu;
+ short i;
+#ifdef HAVE_PTHREAD_SETNAME_NP
+ char *reloader_thd_name = NULL;
+ int thd_name_len = 0;
+#endif
+ DEFiRet;
+ lu = NULL;
+
+ pvals = nvlstGetParams(o->nvlst, &modpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ DBGPRINTF("lookupTableDefProcessCnf params:\n");
+ cnfparamsPrint(&modpblk, pvals);
+
+ CHKiRet(lookupNew(&lu));
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "file")) {
+ CHKmalloc(lu->filename = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if(!strcmp(modpblk.descr[i].name, "name")) {
+ CHKmalloc(lu->name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if(!strcmp(modpblk.descr[i].name, "reloadOnHUP")) {
+ lu->reload_on_hup = (pvals[i].val.d.n != 0);
+ } else {
+ dbgprintf("lookup_table: program error, non-handled "
+ "param '%s'\n", modpblk.descr[i].name);
+ }
+ }
+ const uchar *const lu_name = lu->name; /* we need a const to keep TSAN happy :-( */
+ const uchar *const lu_filename = lu->filename; /* we need a const to keep TSAN happy :-( */
+ if(lu_name == NULL || lu_filename == NULL) {
+ iRet = RS_RET_INTERNAL_ERROR;
+ LogError(0, iRet, "internal error: lookup table name not set albeit being mandatory");
+ ABORT_FINALIZE(iRet);
+ }
+#ifdef HAVE_PTHREAD_SETNAME_NP
+ thd_name_len = ustrlen(lu_name) + strlen(reloader_prefix) + 1;
+ CHKmalloc(reloader_thd_name = malloc(thd_name_len));
+ strcpy(reloader_thd_name, reloader_prefix);
+ strcpy(reloader_thd_name + strlen(reloader_prefix), (char*) lu_name);
+ reloader_thd_name[thd_name_len - 1] = '\0';
+#if defined(__NetBSD__)
+ pthread_setname_np(lu->reloader, "%s", reloader_thd_name);
+#elif defined(__APPLE__)
+ pthread_setname_np(reloader_thd_name); // must check
+#else
+ pthread_setname_np(lu->reloader, reloader_thd_name);
+#endif
+#endif
+ CHKiRet(lookupReadFile(lu->self, lu_name, lu_filename));
+ LogMsg(0, RS_RET_OK, LOG_INFO, "lookup table '%s' loaded from file '%s'",
+ lu_name, lu->filename);
+
+finalize_it:
+#ifdef HAVE_PTHREAD_SETNAME_NP
+ free(reloader_thd_name);
+#endif
+ cnfparamvalsDestruct(pvals, &modpblk);
+ if (iRet != RS_RET_OK) {
+ if (lu != NULL) {
+ lookupDestruct(lu->self);
+ lu->self = NULL;
+ }
+ }
+ RETiRet;
+}
+
+void
+lookupClassExit(void)
+{
+ objRelease(glbl, CORE_COMPONENT);
+}
+
+rsRetVal
+lookupClassInit(void)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+finalize_it:
+ RETiRet;
+}
diff --git a/runtime/lookup.h b/runtime/lookup.h
new file mode 100644
index 0000000..7c0aa28
--- /dev/null
+++ b/runtime/lookup.h
@@ -0,0 +1,116 @@
+/* header for lookup.c
+ *
+ * Copyright 2013-2023 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_LOOKUP_H
+#define INCLUDED_LOOKUP_H
+#include <libestr.h>
+
+#define STRING_LOOKUP_TABLE 1
+#define ARRAY_LOOKUP_TABLE 2
+#define SPARSE_ARRAY_LOOKUP_TABLE 3
+#define STUBBED_LOOKUP_TABLE 4
+
+#define LOOKUP_KEY_TYPE_STRING 1
+#define LOOKUP_KEY_TYPE_UINT 2
+#define LOOKUP_KEY_TYPE_NONE 3
+
+struct lookup_tables_s {
+ lookup_ref_t *root; /* the root of the template list */
+ lookup_ref_t *last; /* points to the last element of the template list */
+};
+
+struct lookup_array_tab_s {
+ uint32_t first_key;
+ uchar **interned_val_refs;
+};
+
+struct lookup_sparseArray_tab_entry_s {
+ uint32_t key;
+ uchar *interned_val_ref;
+};
+
+struct lookup_sparseArray_tab_s {
+ lookup_sparseArray_tab_entry_t *entries;
+};
+
+struct lookup_string_tab_entry_s {
+ uchar *key;
+ uchar *interned_val_ref;
+};
+
+struct lookup_string_tab_s {
+ lookup_string_tab_entry_t *entries;
+};
+
+struct lookup_ref_s {
+ pthread_rwlock_t rwlock; /* protect us in case of dynamic reloads */
+ uchar *name;
+ uchar *filename;
+ lookup_t *self;
+ lookup_ref_t *next;
+ /* reload specific attributes */
+ pthread_mutex_t reloader_mut; /* signaling + access to reload-flow variables*/
+ /* rwlock(above) may be acquired inside critical-section reloader_mut guards */
+ pthread_cond_t run_reloader;
+ pthread_t reloader;
+ pthread_attr_t reloader_thd_attr;
+ uchar *stub_value_for_reload_failure;
+ uint8_t do_reload;
+ uint8_t do_stop;
+ uint8_t reload_on_hup;
+};
+
+typedef es_str_t* (lookup_fn_t)(lookup_t*, lookup_key_t);
+
+/* a single lookup table */
+struct lookup_s {
+ uint32_t nmemb;
+ uint8_t type;
+ uint8_t key_type;
+ union {
+ lookup_string_tab_t *str;
+ lookup_array_tab_t *arr;
+ lookup_sparseArray_tab_t *sprsArr;
+ } table;
+ uint32_t interned_val_count;
+ uchar **interned_vals;
+ uchar *nomatch;
+ lookup_fn_t *lookup;
+};
+
+union lookup_key_u {
+ uchar* k_str;
+ uint32_t k_uint;
+};
+
+/* prototypes */
+void lookupInitCnf(lookup_tables_t *lu_tabs);
+rsRetVal lookupTableDefProcessCnf(struct cnfobj *o);
+lookup_ref_t *lookupFindTable(uchar *name);
+es_str_t * lookupKey(lookup_ref_t *pThis, lookup_key_t key);
+void lookupDestroyCnf(void);
+void lookupClassExit(void);
+void lookupDoHUP(void);
+rsRetVal lookupReload(lookup_ref_t *pThis, const uchar *stub_value_if_reload_fails);
+uint lookupPendingReloadCount(void);
+rsRetVal lookupClassInit(void);
+void lookupActivateConf(void);
+
+#endif /* #ifndef INCLUDED_LOOKUP_H */
diff --git a/runtime/module-template.h b/runtime/module-template.h
new file mode 100644
index 0000000..9c9cbd1
--- /dev/null
+++ b/runtime/module-template.h
@@ -0,0 +1,1250 @@
+/* module-template.h
+ * This header contains macros that can be used to implement the
+ * plumbing of modules.
+ *
+ * File begun on 2007-07-25 by RGerhards
+ *
+ * Copyright 2007-2015 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MODULE_TEMPLATE_H_INCLUDED
+#define MODULE_TEMPLATE_H_INCLUDED 1
+
+#include "modules.h"
+#include "obj.h"
+#include "objomsr.h"
+#include "threads.h"
+
+/* macro to define standard output-module static data members
+ */
+#define DEF_MOD_STATIC_DATA \
+ static __attribute__((unused)) rsRetVal (*omsdRegCFSLineHdlr)(uchar *pCmdName, int bChainingPermitted, \
+ ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie);
+
+#define DEF_OMOD_STATIC_DATA \
+ DEF_MOD_STATIC_DATA \
+ DEFobjCurrIf(obj) \
+ static __attribute__((unused)) int bCoreSupportsBatching;
+#define DEF_IMOD_STATIC_DATA \
+ DEF_MOD_STATIC_DATA \
+ DEFobjCurrIf(obj)
+#define DEF_LMOD_STATIC_DATA \
+ DEF_MOD_STATIC_DATA
+#define DEF_PMOD_STATIC_DATA \
+ DEFobjCurrIf(obj) \
+ DEF_MOD_STATIC_DATA
+#define DEF_SMOD_STATIC_DATA \
+ DEFobjCurrIf(obj) \
+ DEF_MOD_STATIC_DATA
+#define DEF_FMOD_STATIC_DATA \
+ DEFobjCurrIf(obj) \
+ DEF_MOD_STATIC_DATA
+
+
+/* Macro to define the module type. Each module can only have a single type. If
+ * a module provides multiple types, several separate modules must be created which
+ * then should share a single library containing the majority of code. This macro
+ * must be present in each module. -- rgerhards, 2007-12-14
+ * Note that MODULE_TYPE_TESTBENCH is reserved for testbenches, but
+ * declared in their own header files (because the rest does not need these
+ * defines). -- rgerhards, 2008-06-13
+ */
+#define MODULE_TYPE(x)\
+static rsRetVal modGetType(eModType_t *modType) \
+ { \
+ *modType = x; \
+ return RS_RET_OK;\
+ }
+
+#define MODULE_TYPE_INPUT MODULE_TYPE(eMOD_IN)
+#define MODULE_TYPE_OUTPUT MODULE_TYPE(eMOD_OUT)
+#define MODULE_TYPE_PARSER MODULE_TYPE(eMOD_PARSER)
+#define MODULE_TYPE_STRGEN MODULE_TYPE(eMOD_STRGEN)
+#define MODULE_TYPE_FUNCTION MODULE_TYPE(eMOD_FUNCTION)
+#define MODULE_TYPE_LIB \
+ DEF_LMOD_STATIC_DATA \
+ MODULE_TYPE(eMOD_LIB)
+
+/* Macro to define whether the module should be kept dynamically linked.
+ */
+#define MODULE_KEEP_TYPE(x)\
+static rsRetVal modGetKeepType(eModKeepType_t *modKeepType) \
+ { \
+ *modKeepType = x; \
+ return RS_RET_OK;\
+ }
+#define MODULE_TYPE_NOKEEP MODULE_KEEP_TYPE(eMOD_NOKEEP)
+#define MODULE_TYPE_KEEP MODULE_KEEP_TYPE(eMOD_KEEP)
+
+/* macro to define a unique module id. This must be able to fit in a void*. The
+ * module id must be unique inside a running rsyslogd application. It is used to
+ * track ownership of several objects. Most importantly, when the module is
+ * unloaded the module id value is used to find what needs to be destroyed.
+ * We currently use a pointer to modExit() as the module id. This sounds to be
+ * reasonable save, as each module must have this entry point AND there is no valid
+ * reason for twice this entry point being in memory.
+ * rgerhards, 2007-11-21
+ */
+#define STD_LOADABLE_MODULE_ID ((void*) modExit)
+
+
+/* macro to implement the "modGetID()" interface function
+ * rgerhards 2007-11-21
+ */
+#define DEFmodGetID \
+static rsRetVal modGetID(void **pID) \
+ { \
+ *pID = STD_LOADABLE_MODULE_ID;\
+ return RS_RET_OK;\
+ }
+
+/* macro to provide the v6 config system module name
+ */
+#define MODULE_CNFNAME(name) \
+static rsRetVal modGetCnfName(uchar **cnfName) \
+ { \
+ *cnfName = (uchar*) name; \
+ return RS_RET_OK;\
+ }
+
+
+/* to following macros are used to generate function headers and standard
+ * functionality. It works as follows (described on the sample case of
+ * createInstance()):
+ *
+ * BEGINcreateInstance
+ * ... custom variable definitions (on stack) ... (if any)
+ * CODESTARTcreateInstance
+ * ... custom code ... (if any)
+ * ENDcreateInstance
+ */
+
+/* createInstance()
+ */
+#define BEGINcreateInstance \
+static rsRetVal createInstance(instanceData **ppData)\
+ {\
+ DEFiRet; /* store error code here */\
+ instanceData *pData; /* use this to point to data elements */
+
+#define CODESTARTcreateInstance \
+ if((pData = calloc(1, sizeof(instanceData))) == NULL) {\
+ *ppData = NULL;\
+ return RS_RET_OUT_OF_MEMORY;\
+ }
+
+#define ENDcreateInstance \
+ *ppData = pData;\
+ RETiRet;\
+}
+
+/* freeInstance()
+ * This is the cleanup function for the module instance. It is called immediately before
+ * the module instance is destroyed (unloaded). The module should do any cleanup
+ * here, e.g. close file, free instantance heap memory and the like. Control will
+ * not be passed back to the module once this function is finished. Keep in mind,
+ * however, that other instances may still be loaded and used. So do not destroy
+ * anything that may be used by another instance. If you have such a ressource, you
+ * currently need to do the instance counting yourself.
+ */
+#define BEGINfreeInstance \
+static rsRetVal freeInstance(void* pModData)\
+{\
+ DEFiRet;\
+ instanceData *pData;
+
+#define CODESTARTfreeInstance \
+ pData = (instanceData*) pModData;
+
+#define ENDfreeInstance \
+ if(pData != NULL)\
+ free(pData); /* we need to free this in any case */\
+ RETiRet;\
+}
+
+/* createWrkrInstance()
+ */
+#define BEGINcreateWrkrInstance \
+static rsRetVal createWrkrInstance(wrkrInstanceData_t **ppWrkrData, instanceData *pData)\
+ {\
+ DEFiRet; /* store error code here */\
+ wrkrInstanceData_t *pWrkrData; /* use this to point to data elements */
+
+#define CODESTARTcreateWrkrInstance \
+ if((pWrkrData = calloc(1, sizeof(wrkrInstanceData_t))) == NULL) {\
+ *ppWrkrData = NULL;\
+ return RS_RET_OUT_OF_MEMORY;\
+ } \
+ pWrkrData->pData = pData;
+
+#define ENDcreateWrkrInstance \
+ *ppWrkrData = pWrkrData;\
+ RETiRet;\
+}
+
+/* freeWrkrInstance */
+#define BEGINfreeWrkrInstance \
+static rsRetVal freeWrkrInstance(void* pd)\
+{\
+ DEFiRet;\
+ wrkrInstanceData_t *pWrkrData;
+
+#define CODESTARTfreeWrkrInstance \
+ pWrkrData = (wrkrInstanceData_t*) pd;
+
+#define ENDfreeWrkrInstance \
+ if(pWrkrData != NULL)\
+ free(pWrkrData); /* we need to free this in any case */\
+ RETiRet;\
+}
+
+
+/* isCompatibleWithFeature()
+ */
+#define BEGINisCompatibleWithFeature \
+static rsRetVal isCompatibleWithFeature(syslogFeature __attribute__((unused)) eFeat)\
+{\
+ rsRetVal iRet = RS_RET_INCOMPATIBLE; \
+
+#define CODESTARTisCompatibleWithFeature
+
+#define ENDisCompatibleWithFeature \
+ RETiRet;\
+}
+
+
+/* beginTransaction()
+ * introduced in v4.3.3 -- rgerhards, 2009-04-27
+ */
+#define BEGINbeginTransaction \
+static rsRetVal beginTransaction(wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ DEFiRet;
+
+#define CODESTARTbeginTransaction /* currently empty, but may be extended */
+
+#define ENDbeginTransaction \
+ RETiRet;\
+}
+
+
+/* commitTransaction()
+ * Commits a transaction. Note that beginTransaction() must have been
+ * called before this entry point. It receives the full batch of messages
+ * to be processed in pParam parameter.
+ * introduced in v8.1.3 -- rgerhards, 2013-12-04
+ */
+#define BEGINcommitTransaction \
+static rsRetVal commitTransaction(wrkrInstanceData_t __attribute__((unused)) *const pWrkrData, \
+ actWrkrIParams_t *const pParams, const unsigned nParams)\
+{\
+ DEFiRet;
+
+#define CODESTARTcommitTransaction /* currently empty, but may be extended */
+
+#define ENDcommitTransaction \
+ RETiRet;\
+}
+
+/* endTransaction()
+ * introduced in v4.3.3 -- rgerhards, 2009-04-27
+ */
+#define BEGINendTransaction \
+static rsRetVal endTransaction(wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ DEFiRet;
+
+#define CODESTARTendTransaction /* currently empty, but may be extended */
+
+#define ENDendTransaction \
+ RETiRet;\
+}
+
+
+/* doAction()
+ */
+#define BEGINdoAction \
+static rsRetVal doAction(void * pMsgData, wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ uchar **ppString = (uchar **) pMsgData; \
+ DEFiRet;
+
+#define CODESTARTdoAction \
+ /* ppString may be NULL if the output module requested no strings */
+
+#define ENDdoAction \
+ RETiRet;\
+}
+
+/* below is a variant of doAction where the passed-in data is not the common
+ * case of string.
+ */
+#define BEGINdoAction_NoStrings \
+static rsRetVal doAction(void * pMsgData, wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ DEFiRet;
+
+
+/* dbgPrintInstInfo()
+ * Extra comments:
+ * Print debug information about this instance.
+ */
+#define BEGINdbgPrintInstInfo \
+static rsRetVal dbgPrintInstInfo(void *pModData)\
+{\
+ DEFiRet;\
+ instanceData *pData = NULL;
+
+#define CODESTARTdbgPrintInstInfo \
+ pData = (instanceData*) pModData; \
+ (void)pData; /* prevent compiler warning if unused! */
+
+#define ENDdbgPrintInstInfo \
+ RETiRet;\
+}
+
+
+/* parseSelectorAct()
+ * Extra comments:
+ * try to process a selector action line. Checks if the action
+ * applies to this module and, if so, processed it. If not, it
+ * is left untouched. The driver will then call another module.
+ * On exit, ppModData must point to instance data. Also, a string
+ * request object must be created and filled. A macro is defined
+ * for that.
+ * For the most usual case, we have defined a macro below.
+ * If more than one string is requested, the macro can be used together
+ * with own code that overwrites the entry count. In this case, the
+ * macro must come before the own code. It is recommended to be
+ * placed right after CODESTARTparseSelectorAct.
+ */
+#define BEGINparseSelectorAct \
+static rsRetVal parseSelectorAct(uchar **pp, void **ppModData, omodStringRequest_t **ppOMSR)\
+{\
+ DEFiRet;\
+ uchar *p;\
+ instanceData *pData = NULL;
+
+#define CODESTARTparseSelectorAct \
+ assert(pp != NULL);\
+ assert(ppModData != NULL);\
+ assert(ppOMSR != NULL);\
+ p = *pp;
+
+#define CODE_STD_STRING_REQUESTparseSelectorAct(NumStrReqEntries) \
+ CHKiRet(OMSRconstruct(ppOMSR, NumStrReqEntries));
+
+#define CODE_STD_FINALIZERparseSelectorAct \
+finalize_it: ATTR_UNUSED; /* semi-colon needed according to gcc doc! */\
+ if(iRet == RS_RET_OK || iRet == RS_RET_OK_WARN || iRet == RS_RET_SUSPENDED) {\
+ *ppModData = pData;\
+ *pp = p;\
+ } else {\
+ /* cleanup, we failed */\
+ if(*ppOMSR != NULL) {\
+ OMSRdestruct(*ppOMSR);\
+ *ppOMSR = NULL;\
+ }\
+ if(pData != NULL) {\
+ freeInstance(pData);\
+ } \
+ }
+
+#define ENDparseSelectorAct \
+ RETiRet;\
+}
+
+/* a special replacement macro for modules that do not support legacy config at all */
+#define NO_LEGACY_CONF_parseSelectorAct \
+static rsRetVal parseSelectorAct(uchar **pp ATTR_UNUSED, void **ppModData ATTR_UNUSED, \
+ omodStringRequest_t **ppOMSR ATTR_UNUSED)\
+{\
+ return RS_RET_LEGA_ACT_NOT_SUPPORTED;\
+}
+
+/* newActInst()
+ * Extra comments:
+ * This creates a new instance of a the action that implements the call.
+ * This is part of the conf2 (rsyslog v6) config system. It is called by
+ * the core when an action object has been obtained. The output module
+ * must then verify parameters and create a new action instance (if
+ * parameters are acceptable) or return an error code.
+ * On exit, ppModData must point to instance data. Also, a string
+ * request object must be created and filled. A macro is defined
+ * for that.
+ * For the most usual case, we have defined a macro below.
+ * If more than one string is requested, the macro can be used together
+ * with own code that overwrites the entry count. In this case, the
+ * macro must come before the own code. It is recommended to be
+ * placed right after CODESTARTnewActInst.
+ */
+#define BEGINnewActInst \
+static rsRetVal newActInst(uchar __attribute__((unused)) *modName, \
+ struct nvlst __attribute__((unused)) *lst, void **ppModData, \
+ omodStringRequest_t **ppOMSR)\
+{\
+ DEFiRet;\
+ instanceData *pData = NULL; \
+ *ppOMSR = NULL;
+
+#define CODESTARTnewActInst \
+
+#define CODE_STD_STRING_REQUESTnewActInst(NumStrReqEntries) \
+ CHKiRet(OMSRconstruct(ppOMSR, NumStrReqEntries));
+
+#define CODE_STD_FINALIZERnewActInst \
+finalize_it:\
+ if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {\
+ *ppModData = pData;\
+ } else {\
+ /* cleanup, we failed */\
+ if(*ppOMSR != NULL) {\
+ OMSRdestruct(*ppOMSR);\
+ *ppOMSR = NULL;\
+ }\
+ if(pData != NULL) {\
+ freeInstance(pData);\
+ } \
+ }
+
+#define ENDnewActInst \
+ RETiRet;\
+}
+
+
+/* newInpInst()
+ * This is basically the equivalent to newActInst() for creating input
+ * module (listener) instances.
+ */
+#define BEGINnewInpInst \
+static rsRetVal newInpInst(struct nvlst *lst)\
+{\
+ DEFiRet;
+
+#define CODESTARTnewInpInst \
+
+#define CODE_STD_FINALIZERnewInpInst
+
+#define ENDnewInpInst \
+ RETiRet;\
+}
+
+
+
+/* newParserInst()
+ * This is basically the equivalent to newActInst() for creating parser
+ * module (listener) instances.
+ */
+#define BEGINnewParserInst \
+static rsRetVal newParserInst(struct nvlst *lst, void *pinst)\
+{\
+ instanceConf_t *inst; \
+ DEFiRet;
+
+#define CODESTARTnewParserInst \
+
+#define CODE_STD_FINALIZERnewParserInst
+
+#define ENDnewParserInst \
+ if(iRet == RS_RET_OK) \
+ *((instanceConf_t**)pinst) = inst; \
+ RETiRet;\
+}
+
+
+/* freeParserInst */
+#define BEGINfreeParserInst \
+static rsRetVal freeParserInst(void* pi)\
+{\
+ DEFiRet;\
+ instanceConf_t *pInst;
+
+#define CODESTARTfreeParserInst\
+ pInst = (instanceConf_t*) pi;
+
+#define ENDfreeParserInst\
+ if(pInst != NULL)\
+ free(pInst);\
+ RETiRet;\
+}
+
+/* tryResume()
+ * This entry point is called to check if a module can resume operations. This
+ * happens when a module requested that it be suspended. In suspended state,
+ * the engine periodically tries to resume the module. If that succeeds, normal
+ * processing continues. If not, the module will not be called unless a
+ * tryResume() call succeeds.
+ * Returns RS_RET_OK, if resumption succeeded, RS_RET_SUSPENDED otherwise
+ * rgerhard, 2007-08-02
+ */
+#define BEGINtryResume \
+static rsRetVal tryResume(wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ DEFiRet;
+
+#define CODESTARTtryResume \
+ assert(pWrkrData != NULL);
+
+#define ENDtryResume \
+ RETiRet;\
+}
+
+
+/* initConfVars() - initialize pre-v6.3-config variables
+ */
+#define BEGINinitConfVars \
+static rsRetVal initConfVars(void)\
+{\
+ DEFiRet;
+
+#define CODESTARTinitConfVars
+
+#define ENDinitConfVars \
+ RETiRet;\
+}
+
+
+/* queryEtryPt()
+ */
+#define BEGINqueryEtryPt \
+DEFmodGetID \
+static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\
+{\
+ DEFiRet;
+
+#define CODESTARTqueryEtryPt \
+ if((name == NULL) || (pEtryPoint == NULL)) {\
+ return RS_RET_PARAM_ERROR;\
+ } \
+ *pEtryPoint = NULL;
+
+#define ENDqueryEtryPt \
+ if(iRet == RS_RET_OK)\
+ if(*pEtryPoint == NULL) { \
+ dbgprintf("entry point '%s' not present in module\n", name); \
+ iRet = RS_RET_MODULE_ENTRY_POINT_NOT_FOUND;\
+ } \
+ RETiRet;\
+}
+
+/* the following definition is the standard block for queryEtryPt for all types
+ * of modules. It should be included in any module, and typically is so by calling
+ * the module-type specific macros.
+ */
+#define CODEqueryEtryPt_STD_MOD_QUERIES \
+ if(!strcmp((char*) name, "modExit")) {\
+ *pEtryPoint = modExit;\
+ } else if(!strcmp((char*) name, "modGetID")) {\
+ *pEtryPoint = modGetID;\
+ } else if(!strcmp((char*) name, "getType")) {\
+ *pEtryPoint = modGetType;\
+ } else if(!strcmp((char*) name, "getKeepType")) {\
+ *pEtryPoint = modGetKeepType;\
+ }
+
+/* the following definition is the standard block for queryEtryPt for output
+ * modules WHICH DO NOT SUPPORT TRANSACTIONS.
+ */
+#define CODEqueryEtryPt_STD_OMOD_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "doAction")) {\
+ *pEtryPoint = doAction;\
+ } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\
+ *pEtryPoint = dbgPrintInstInfo;\
+ } else if(!strcmp((char*) name, "freeInstance")) {\
+ *pEtryPoint = freeInstance;\
+ } else if(!strcmp((char*) name, "parseSelectorAct")) {\
+ *pEtryPoint = parseSelectorAct;\
+ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\
+ *pEtryPoint = isCompatibleWithFeature;\
+ } else if(!strcmp((char*) name, "tryResume")) {\
+ *pEtryPoint = tryResume;\
+ }
+
+/* the following definition is the standard block for queryEtryPt for output
+ * modules using the transaction interface.
+ */
+#define CODEqueryEtryPt_STD_OMODTX_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "beginTransaction")) {\
+ *pEtryPoint = beginTransaction;\
+ } else if(!strcmp((char*) name, "commitTransaction")) {\
+ *pEtryPoint = commitTransaction;\
+ } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\
+ *pEtryPoint = dbgPrintInstInfo;\
+ } else if(!strcmp((char*) name, "freeInstance")) {\
+ *pEtryPoint = freeInstance;\
+ } else if(!strcmp((char*) name, "parseSelectorAct")) {\
+ *pEtryPoint = parseSelectorAct;\
+ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\
+ *pEtryPoint = isCompatibleWithFeature;\
+ } else if(!strcmp((char*) name, "tryResume")) {\
+ *pEtryPoint = tryResume;\
+ }
+
+/* standard queries for output module interface in rsyslog v8+ */
+#define CODEqueryEtryPt_STD_OMOD8_QUERIES \
+ else if(!strcmp((char*) name, "createWrkrInstance")) {\
+ *pEtryPoint = createWrkrInstance;\
+ } else if(!strcmp((char*) name, "freeWrkrInstance")) {\
+ *pEtryPoint = freeWrkrInstance;\
+ }
+
+/* the following definition is queryEtryPt block that must be added
+ * if an output module supports the transactional interface.
+ * rgerhards, 2009-04-27
+ */
+#define CODEqueryEtryPt_TXIF_OMOD_QUERIES \
+ else if(!strcmp((char*) name, "beginTransaction")) {\
+ *pEtryPoint = beginTransaction;\
+ } else if(!strcmp((char*) name, "endTransaction")) {\
+ *pEtryPoint = endTransaction;\
+ }
+
+
+/* the following definition is a queryEtryPt block that must be added
+ * if a non-output module supports "isCompatibleWithFeature".
+ * rgerhards, 2009-07-20
+ */
+#define CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES \
+ else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\
+ *pEtryPoint = isCompatibleWithFeature;\
+ }
+
+
+/* the following definition is the standard block for queryEtryPt for INPUT
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_IMOD_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "runInput")) {\
+ *pEtryPoint = runInput;\
+ } else if(!strcmp((char*) name, "willRun")) {\
+ *pEtryPoint = willRun;\
+ } else if(!strcmp((char*) name, "afterRun")) {\
+ *pEtryPoint = afterRun;\
+ }
+
+
+/* the following block is to be added for modules that support the v2
+ * config system. The config name is also provided.
+ */
+#define CODEqueryEtryPt_STD_CONF2_QUERIES \
+ else if(!strcmp((char*) name, "beginCnfLoad")) {\
+ *pEtryPoint = beginCnfLoad;\
+ } else if(!strcmp((char*) name, "endCnfLoad")) {\
+ *pEtryPoint = endCnfLoad;\
+ } else if(!strcmp((char*) name, "checkCnf")) {\
+ *pEtryPoint = checkCnf;\
+ } else if(!strcmp((char*) name, "activateCnf")) {\
+ *pEtryPoint = activateCnf;\
+ } else if(!strcmp((char*) name, "freeCnf")) {\
+ *pEtryPoint = freeCnf;\
+ } \
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+
+/* the following block is to be added for modules that support v2
+ * module global parameters [module(...)]
+ */
+#define CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES \
+ else if(!strcmp((char*) name, "setModCnf")) {\
+ *pEtryPoint = setModCnf;\
+ } \
+
+/* the following block is to be added for output modules that support the v2
+ * config system. The config name is also provided.
+ */
+#define CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES \
+ else if(!strcmp((char*) name, "newActInst")) {\
+ *pEtryPoint = newActInst;\
+ } \
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+
+
+/* the following block is to be added for input modules that support the v2
+ * config system. The config name is also provided.
+ */
+#define CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES \
+ else if(!strcmp((char*) name, "newInpInst")) {\
+ *pEtryPoint = newInpInst;\
+ } \
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+
+
+/* the following block is to be added for modules that require
+ * pre priv drop activation support.
+ */
+#define CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES \
+ else if(!strcmp((char*) name, "activateCnfPrePrivDrop")) {\
+ *pEtryPoint = activateCnfPrePrivDrop;\
+ }
+
+/* the following block is to be added for modules that support
+ * their config name. This is required for the rsyslog v6 config
+ * system, especially for outout modules which do not require
+ * the new set of begin/end config settings.
+ */
+#define CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES \
+ else if(!strcmp((char*) name, "getModCnfName")) {\
+ *pEtryPoint = modGetCnfName;\
+ }
+
+/* the following definition is the standard block for queryEtryPt for LIBRARY
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_LIB_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES
+
+/* the following definition is the standard block for queryEtryPt for PARSER
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_PMOD_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "parse")) {\
+ *pEtryPoint = parse;\
+ } else if(!strcmp((char*) name, "GetParserName")) {\
+ *pEtryPoint = GetParserName;\
+ }
+
+/* the following definition is the standard block for queryEtryPt for PARSER
+ * modules obeying the v2+ config interface.
+ */
+#define CODEqueryEtryPt_STD_PMOD2_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "parse2")) {\
+ *pEtryPoint = parse2;\
+ } else if(!strcmp((char*) name, "GetParserName")) {\
+ *pEtryPoint = GetParserName;\
+ } else if(!strcmp((char*) name, "newParserInst")) {\
+ *pEtryPoint = newParserInst;\
+ } else if(!strcmp((char*) name, "freeParserInst")) {\
+ *pEtryPoint = freeParserInst;\
+ } \
+ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+
+
+
+/* the following definition is the standard block for queryEtryPt for rscript function
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_FMOD_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "getFunctArray")) {\
+ *pEtryPoint = getFunctArray;\
+ }
+
+/* the following definition is the standard block for queryEtryPt for Strgen
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_SMOD_QUERIES \
+ CODEqueryEtryPt_STD_MOD_QUERIES \
+ else if(!strcmp((char*) name, "strgen")) {\
+ *pEtryPoint = strgen;\
+ } else if(!strcmp((char*) name, "GetName")) {\
+ *pEtryPoint = GetStrgenName;\
+ }
+
+/* modInit()
+ * This has an extra parameter, which is the specific name of the modInit
+ * function. That is needed for built-in modules, which must have unique
+ * names in order to link statically. Please note that this is always only
+ * the case with modInit() and NO other entry point. The reason is that only
+ * modInit() is visible form a linker/loader point of view. All other entry
+ * points are passed via rsyslog-internal query functions and are defined
+ * static inside the modules source. This is an important concept, as it allows
+ * us to support different interface versions within a single module. (Granted,
+ * we do not currently have different interface versions, so we can not put
+ * it to a test - but our firm believe is that we can do all abstraction needed...)
+ *
+ * Extra Comments:
+ * initialize the module
+ *
+ * Later, much more must be done. So far, we only return a pointer
+ * to the queryEtryPt() function
+ * TODO: do interface version checking & handshaking
+ * iIfVersRequetsed is the version of the interface specification that the
+ * caller would like to see being used. ipIFVersProvided is what we
+ * decide to provide.
+ * rgerhards, 2007-11-21: see modExit() comment below for important information
+ * on the need to initialize static data with code. modInit() may be called on a
+ * cached, left-in-memory copy of a previous incarnation.
+ */
+#define BEGINmodInit(uniqName) \
+rsRetVal __attribute__((unused)) modInit##uniqName(int iIFVersRequested __attribute__((unused)), \
+int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), \
+modInfo_t __attribute__((unused)) *pModInfo);\
+rsRetVal __attribute__((unused)) modInit##uniqName(int iIFVersRequested __attribute__((unused)), \
+int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), \
+modInfo_t __attribute__((unused)) *pModInfo)\
+{\
+ DEFiRet; \
+ rsRetVal (*pObjGetObjInterface)(obj_if_t *pIf);
+
+#define CODESTARTmodInit \
+ assert(pHostQueryEtryPt != NULL);\
+ iRet = pHostQueryEtryPt((uchar*)"objGetObjInterface", &pObjGetObjInterface); \
+ if((iRet != RS_RET_OK) || (pQueryEtryPt == NULL) || (ipIFVersProvided == NULL) || \
+ (pObjGetObjInterface == NULL)) { \
+ return (iRet == RS_RET_OK) ? RS_RET_PARAM_ERROR : iRet; \
+ } \
+ /* now get the obj interface so that we can access other objects */ \
+ CHKiRet(pObjGetObjInterface(&obj));
+
+/* do those initializations necessary for legacy config variables */
+#define INITLegCnfVars \
+ initConfVars();
+
+#define ENDmodInit \
+finalize_it:\
+ *pQueryEtryPt = queryEtryPt;\
+ RETiRet;\
+}
+
+
+/* now come some check functions, which enable a standard way of obtaining feature
+ * information from the core. feat is the to-be-tested feature and featVar is a
+ * variable that receives the result (0-not support, 1-supported).
+ * This must be a macro, so that it is put into the output's code. Otherwise, we
+ * would need to rely on a library entry point, which is what we intend to avoid ;)
+ * rgerhards, 2009-04-27
+ */
+#define INITChkCoreFeature(featVar, feat) \
+{ \
+ rsRetVal MACRO_Ret; \
+ rsRetVal (*pQueryCoreFeatureSupport)(int*, unsigned); \
+ int bSupportsIt; \
+ featVar = 0; \
+ MACRO_Ret = pHostQueryEtryPt((uchar*)"queryCoreFeatureSupport", &pQueryCoreFeatureSupport); \
+ if(MACRO_Ret == RS_RET_OK) { \
+ /* found entry point, so let's see if core supports it */ \
+ CHKiRet((*pQueryCoreFeatureSupport)(&bSupportsIt, feat)); \
+ if(bSupportsIt) \
+ featVar = 1; \
+ } else if(MACRO_Ret != RS_RET_ENTRY_POINT_NOT_FOUND) { \
+ ABORT_FINALIZE(MACRO_Ret); /* Something else went wrong, what is not acceptable */ \
+ } \
+}
+
+
+
+/* definitions for host API queries */
+#define CODEmodInit_QueryRegCFSLineHdlr \
+ CHKiRet(pHostQueryEtryPt((uchar*)"regCfSysLineHdlr", &omsdRegCFSLineHdlr));
+
+
+/* modExit()
+ * This is the counterpart to modInit(). It destroys a module and makes it ready for
+ * unloading. It is similiar to freeInstance() for the instance data. Please note that
+ * this entry point needs to free any module-global data structures and registrations.
+ * For example, the CfSysLineHandlers a module has registered need to be unregistered
+ * here. This entry point is only called immediately before unloading of the module. So
+ * it is likely to be destroyed. HOWEVER, the caller may decide to keep the module cached.
+ * So a module must never assume that it is actually destroyed. A call to modInit() may
+ * happen immediately after modExit(). So a module can NOT assume that static data elements
+ * are being re-initialized by the loader - this must always be done by module code itself.
+ * It is suggested to do this in modInit(). - rgerhards, 2007-11-21
+ */
+#define BEGINmodExit \
+static rsRetVal modExit(void)\
+{\
+ DEFiRet;
+
+#define CODESTARTmodExit
+
+#define ENDmodExit \
+ RETiRet;\
+}
+
+
+/* beginCnfLoad()
+ * This is a function tells an input module that a new config load begins.
+ * The core passes in a handle to the new module-specific module conf to
+ * the module. -- rgerards, 2011-05-03
+ */
+#define BEGINbeginCnfLoad \
+static rsRetVal beginCnfLoad(modConfData_t **ptr, __attribute__((unused)) rsconf_t *pConf)\
+{\
+ modConfData_t *pModConf; \
+ DEFiRet;
+
+#define CODESTARTbeginCnfLoad \
+ if((pModConf = calloc(1, sizeof(modConfData_t))) == NULL) {\
+ *ptr = NULL;\
+ return RS_RET_OUT_OF_MEMORY;\
+ }
+
+#define ENDbeginCnfLoad \
+ *ptr = pModConf;\
+ RETiRet;\
+}
+
+
+/* setModCnf()
+ * This function permits to set module global parameters via the v2 config
+ * interface. It may be called multiple times, but parameters must not be
+ * set in a conflicting way. The module must use its current config load
+ * context when processing the directives.
+ * Note that lst may be NULL, especially if the module is loaded via the
+ * legacy config system. The module must check for this.
+ * NOTE: This entry point must only be implemented if module global
+ * parameters are actually required.
+ */
+#define BEGINsetModCnf \
+static rsRetVal setModCnf(struct nvlst *lst)\
+{\
+ DEFiRet;
+
+#define CODESTARTsetModCnf
+
+#define ENDsetModCnf \
+ RETiRet;\
+}
+
+
+/* endCnfLoad()
+ * This is a function tells an input module that the current config load ended.
+ * It gets a last chance to make changes to its in-memory config object. After
+ * this call, the config object must no longer be changed.
+ * The pModConf pointer passed into the module must no longer be used.
+ * rgerards, 2011-05-03
+ */
+#define BEGINendCnfLoad \
+static rsRetVal endCnfLoad(modConfData_t *ptr)\
+{\
+ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTendCnfLoad
+
+#define ENDendCnfLoad \
+ RETiRet;\
+}
+
+
+/* checkCnf()
+ * Check the provided config object for errors, inconsistencies and other things
+ * that do not work out.
+ * NOTE: no part of the config must be activated, so some checks that require
+ * activation can not be done in this entry point. They must be done in the
+ * activateConf() stage, where the caller must also be prepared for error
+ * returns.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINcheckCnf \
+static rsRetVal checkCnf(modConfData_t *ptr)\
+{\
+ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTcheckCnf
+
+#define ENDcheckCnf \
+ RETiRet;\
+}
+
+
+/* activateCnfPrePrivDrop()
+ * Initial config activation, before dropping privileges. This is an optional
+ * entry points that should only be implemented by those module that really need
+ * it. Processing should be limited to the minimum possible. Main activation
+ * should happen in the normal activateCnf() call.
+ * rgerhards, 2011-05-06
+ */
+#define BEGINactivateCnfPrePrivDrop \
+static rsRetVal activateCnfPrePrivDrop(modConfData_t *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTactivateCnfPrePrivDrop
+
+#define ENDactivateCnfPrePrivDrop \
+ RETiRet;\
+}
+
+
+/* activateCnf()
+ * This activates the provided config, and may report errors if they are detected
+ * during activation.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINactivateCnf \
+static rsRetVal activateCnf(modConfData_t *ptr)\
+{\
+ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTactivateCnf
+
+#define ENDactivateCnf \
+ RETiRet;\
+}
+
+
+/* freeCnf()
+ * This is a function tells an input module that it must free all data
+ * associated with the passed-in module config.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINfreeCnf \
+static rsRetVal freeCnf(void *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTfreeCnf
+
+#define ENDfreeCnf \
+ if(pModConf != NULL)\
+ free(pModConf); /* we need to free this in any case */\
+ RETiRet;\
+}
+
+
+/* runInput()
+ * This is the main function for input modules. It is used to gather data from the
+ * input source and submit it to the message queue. Each runInput() instance has its own
+ * thread. This is handled by the rsyslog engine. It needs to spawn off new threads only
+ * if there is a module-internal need to do so.
+ */
+#define BEGINrunInput \
+static rsRetVal runInput(thrdInfo_t __attribute__((unused)) *pThrd)\
+{\
+ DEFiRet;
+
+#define CODESTARTrunInput \
+ dbgSetThrdName((uchar*)__FILE__); /* we need to provide something better later */
+
+#define ENDrunInput \
+ RETiRet;\
+}
+
+
+/* willRun()
+ * This is a function that will be replaced in the longer term. It is used so
+ * that a module can tell the caller if it will run or not. This is to be replaced
+ * when we introduce input module instances. However, these require config syntax
+ * changes and I may (or may not... ;)) hold that until another config file
+ * format is available. -- rgerhards, 2007-12-17
+ * returns RS_RET_NO_RUN if it will not run (RS_RET_OK or error otherwise)
+ */
+#define BEGINwillRun \
+static rsRetVal willRun(void)\
+{\
+ DEFiRet;
+
+#define CODESTARTwillRun
+
+#define ENDwillRun \
+ RETiRet;\
+}
+
+
+/* afterRun()
+ * This function is called after an input module has been run and its thread has
+ * been terminated. It shall do any necessary cleanup.
+ * This is expected to evolve into a freeInstance type of call once the input module
+ * interface evolves to support multiple instances.
+ * rgerhards, 2007-12-17
+ */
+#define BEGINafterRun \
+static rsRetVal afterRun(void)\
+{\
+ DEFiRet;
+
+#define CODESTARTafterRun
+
+#define ENDafterRun \
+ RETiRet;\
+}
+
+
+/* doHUP()
+ * This function is optional. Currently, it is available to output plugins
+ * only, but may be made available to other types of plugins in the future.
+ * A plugin does not need to define this entry point. If if does, it gets
+ * called when a HUP at the action level is to be done. A plugin should register
+ * this function so that it can close files, connection or other ressources
+ * on HUP - if it can be assume the user wanted to do this as a part of HUP
+ * processing. Note that the name "HUP" has historical reasons, it stems back
+ * to the infamous SIGHUP which was sent to restart a syslogd. We still retain
+ * that legacy, but may move this to a different signal.
+ * rgerhards, 2008-10-22
+ */
+#define CODEqueryEtryPt_doHUP \
+ else if(!strcmp((char*) name, "doHUP")) {\
+ *pEtryPoint = doHUP;\
+ }
+#define BEGINdoHUP \
+static rsRetVal doHUP(instanceData __attribute__((unused)) *pData)\
+{\
+ DEFiRet;
+
+#define CODESTARTdoHUP
+
+#define ENDdoHUP \
+ RETiRet;\
+}
+
+
+/* doHUPWrkr()
+ * This is like doHUP(), but on an action worker level.
+ * rgerhards, 2015-03-25
+ */
+#define CODEqueryEtryPt_doHUPWrkr \
+ else if(!strcmp((char*) name, "doHUPWrkr")) {\
+ *pEtryPoint = doHUPWrkr;\
+ }
+#define BEGINdoHUPWrkr \
+static rsRetVal doHUPWrkr(wrkrInstanceData_t __attribute__((unused)) *pWrkrData)\
+{\
+ DEFiRet;
+
+#define CODESTARTdoHUPWrkr
+
+#define ENDdoHUPWrkr \
+ RETiRet;\
+}
+
+
+/* SetShutdownImmdtPtr()
+ * This function is optional. If defined by an output plugin, it is called
+ * each time the action is invoked to set the "ShutdownImmediate" pointer,
+ * which is used during termination to indicate the action should shutdown
+ * as quickly as possible.
+ */
+#define CODEqueryEtryPt_SetShutdownImmdtPtr \
+ else if(!strcmp((char*) name, "SetShutdownImmdtPtr")) {\
+ *pEtryPoint = SetShutdownImmdtPtr;\
+ }
+#define BEGINSetShutdownImmdtPtr \
+static rsRetVal SetShutdownImmdtPtr(instanceData __attribute__((unused)) *pData, int *pPtr)\
+{\
+ DEFiRet;
+
+#define CODESTARTSetShutdownImmdtPtr
+
+#define ENDSetShutdownImmdtPtr \
+ RETiRet;\
+}
+
+
+/* parse() - main entry point of parser modules (v1 config interface)
+ */
+#define BEGINparse \
+static rsRetVal parse(smsg_t *pMsg)\
+{\
+ DEFiRet;
+
+#define CODESTARTparse \
+ assert(pMsg != NULL);
+
+#define ENDparse \
+ RETiRet;\
+}
+
+
+/* parse2() - main entry point of parser modules (v2+ config interface)
+ */
+#define BEGINparse2 \
+static rsRetVal parse2(instanceConf_t *const pInst, smsg_t *pMsg)\
+{\
+ DEFiRet;
+
+#define CODESTARTparse2 \
+ assert(pInst != NULL);\
+ assert(pMsg != NULL);
+
+#define ENDparse2 \
+ RETiRet;\
+}
+
+
+/* strgen() - main entry point of parser modules
+ * Note that we do NOT use size_t as this permits us to store the
+ * values directly into optimized heap structures.
+ * ppBuf is the buffer pointer
+ * pLenBuf is the current max size of this buffer
+ * pStrLen is an output parameter that MUST hold the length
+ * of the generated string on exit (this is cached)
+ */
+#define BEGINstrgen \
+static rsRetVal strgen(smsg_t *const pMsg, actWrkrIParams_t *const iparam) \
+{\
+ DEFiRet;
+
+#define CODESTARTstrgen \
+ assert(pMsg != NULL);
+
+#define ENDstrgen \
+ RETiRet;\
+}
+
+
+
+/* getFunctArray() - main entry point of parser modules
+ * Note that we do NOT use size_t as this permits us to store the
+ * values directly into optimized heap structures.
+ * ppBuf is the buffer pointer
+ * pLenBuf is the current max size of this buffer
+ * pStrLen is an output parameter that MUST hold the length
+ * of the generated string on exit (this is cached)
+ */
+#define BEGINgetFunctArray \
+static rsRetVal getFunctArray(int *const version, const struct scriptFunct**const functArray) \
+{\
+ DEFiRet;
+
+#define CODESTARTgetFunctArray
+
+#define ENDgetFunctArray \
+ RETiRet;\
+}
+
+
+/* function to specify the parser name. This is done via a single command which
+ * receives a ANSI string as parameter.
+ */
+#define PARSER_NAME(x) \
+static rsRetVal GetParserName(uchar **ppSz)\
+{\
+ *ppSz = UCHAR_CONSTANT(x);\
+ return RS_RET_OK;\
+}
+
+
+
+/* function to specify the strgen name. This is done via a single command which
+ * receives a ANSI string as parameter.
+ */
+#define STRGEN_NAME(x) \
+static rsRetVal GetStrgenName(uchar **ppSz)\
+{\
+ *ppSz = UCHAR_CONSTANT(x);\
+ return RS_RET_OK;\
+}
+
+#endif /* #ifndef MODULE_TEMPLATE_H_INCLUDED */
+
+/* vim:set ai:
+ */
diff --git a/runtime/modules.c b/runtime/modules.c
new file mode 100644
index 0000000..b39bd9f
--- /dev/null
+++ b/runtime/modules.c
@@ -0,0 +1,1488 @@
+/* modules.c
+ * This is the implementation of syslogd modules object.
+ * This object handles plug-ins and build-in modules of all kind.
+ *
+ * Modules are reference-counted. Anyone who access a module must call
+ * Use() before any function is accessed and Release() when he is done.
+ * When the reference count reaches 0, rsyslog unloads the module (that
+ * may be changed in the future to cache modules). Rsyslog does NOT
+ * unload modules with a reference count > 0, even if the unload
+ * method is called!
+ *
+ * File begun on 2007-07-22 by RGerhards
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#ifdef OS_BSD
+# include "libgen.h"
+#endif
+
+#include <dlfcn.h> /* TODO: replace this with the libtools equivalent! */
+
+#include <unistd.h>
+#include <sys/file.h>
+
+#include "rsyslog.h"
+#include "rainerscript.h"
+#include "cfsysline.h"
+#include "rsconf.h"
+#include "modules.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "strgen.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(strgen)
+
+static modInfo_t *pLoadedModules = NULL; /* list of currently-loaded modules */
+static modInfo_t *pLoadedModulesLast = NULL; /* tail-pointer */
+
+/* already dlopen()-ed libs */
+static struct dlhandle_s *pHandles = NULL;
+
+static uchar *pModDir; /* directory where loadable modules are found */
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "load", eCmdHdlrGetWord, 1 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+typedef rsRetVal (*pModInit_t)(int,int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_t*);
+
+/* we provide a set of dummy functions for modules that do not support the
+ * some interfaces.
+ * On the commit feature: As the modules do not support it, they commit each message they
+ * receive, and as such the dummies can always return RS_RET_OK without causing
+ * harm. This simplifies things as in action processing we do not need to check
+ * if the transactional entry points exist.
+ */
+static rsRetVal
+dummyBeginTransaction(__attribute__((unused)) void * dummy)
+{
+ return RS_RET_OK;
+}
+static rsRetVal
+dummyEndTransaction(__attribute__((unused)) void * dummy)
+{
+ return RS_RET_OK;
+}
+static rsRetVal
+dummyIsCompatibleWithFeature(__attribute__((unused)) syslogFeature eFeat)
+{
+ return RS_RET_INCOMPATIBLE;
+}
+static rsRetVal
+dummynewActInst(uchar *modName, struct nvlst __attribute__((unused)) *dummy1,
+ void __attribute__((unused)) **dummy2, omodStringRequest_t __attribute__((unused)) **dummy3)
+{
+ LogError(0, RS_RET_CONFOBJ_UNSUPPORTED, "config objects are not "
+ "supported by module '%s' -- legacy config options "
+ "MUST be used instead", modName);
+ return RS_RET_CONFOBJ_UNSUPPORTED;
+}
+
+#ifdef DEBUG
+/* we add some home-grown support to track our users (and detect who does not free us). In
+ * the long term, this should probably be migrated into debug.c (TODO). -- rgerhards, 2008-03-11
+ */
+
+/* add a user to the current list of users (always at the root) */
+static void
+modUsrAdd(modInfo_t *pThis, const char *pszUsr)
+{
+ modUsr_t *pUsr;
+
+ if((pUsr = calloc(1, sizeof(modUsr_t))) == NULL)
+ goto finalize_it;
+
+ if((pUsr->pszFile = strdup(pszUsr)) == NULL) {
+ free(pUsr);
+ goto finalize_it;
+ }
+
+ if(pThis->pModUsrRoot != NULL) {
+ pUsr->pNext = pThis->pModUsrRoot;
+ }
+ pThis->pModUsrRoot = pUsr;
+
+finalize_it:
+ return;
+}
+
+
+/* remove a user from the current user list
+ * rgerhards, 2008-03-11
+ */
+static void
+modUsrDel(modInfo_t *pThis, const char *pszUsr)
+{
+ modUsr_t *pUsr;
+ modUsr_t *pPrev = NULL;
+
+ for(pUsr = pThis->pModUsrRoot ; pUsr != NULL ; pUsr = pUsr->pNext) {
+ if(!strcmp(pUsr->pszFile, pszUsr))
+ break;
+ else
+ pPrev = pUsr;
+ }
+
+ if(pUsr == NULL) {
+ dbgprintf("oops - tried to delete user %s from module %s and it wasn't registered as one...\n",
+ pszUsr, pThis->pszName);
+ } else {
+ if(pPrev == NULL) {
+ /* This was at the root! */
+ pThis->pModUsrRoot = pUsr->pNext;
+ } else {
+ pPrev->pNext = pUsr->pNext;
+ }
+ /* free ressources */
+ free(pUsr->pszFile);
+ free(pUsr);
+ pUsr = NULL; /* just to make sure... */
+ }
+}
+
+
+/* print a short list all all source files using the module in question
+ * rgerhards, 2008-03-11
+ */
+static void
+modUsrPrint(modInfo_t *pThis)
+{
+ modUsr_t *pUsr;
+
+ for(pUsr = pThis->pModUsrRoot ; pUsr != NULL ; pUsr = pUsr->pNext) {
+ dbgprintf("\tmodule %s is currently in use by file %s\n",
+ pThis->pszName, pUsr->pszFile);
+ }
+}
+
+
+/* print all loaded modules and who is accessing them. This is primarily intended
+ * to be called at end of run to detect "module leaks" and who is causing them.
+ * rgerhards, 2008-03-11
+ */
+static void
+modUsrPrintAll(void)
+{
+ modInfo_t *pMod;
+
+ for(pMod = pLoadedModules ; pMod != NULL ; pMod = pMod->pNext) {
+ dbgprintf("printing users of loadable module %s, refcount %u, ptr %p, type %d\n",
+ pMod->pszName, pMod->uRefCnt, pMod, pMod->eType);
+ modUsrPrint(pMod);
+ }
+}
+
+#endif /* #ifdef DEBUG */
+
+
+/* Construct a new module object
+ */
+static rsRetVal moduleConstruct(modInfo_t **pThis)
+{
+ modInfo_t *pNew;
+
+ if((pNew = calloc(1, sizeof(modInfo_t))) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ /* OK, we got the element, now initialize members that should
+ * not be zero-filled.
+ */
+
+ *pThis = pNew;
+ return RS_RET_OK;
+}
+
+
+/* Destructs a module object. The object must not be linked to the
+ * linked list of modules. Please note that all other dependencies on this
+ * modules must have been removed before (e.g. CfSysLineHandlers!)
+ */
+static void moduleDestruct(modInfo_t *pThis)
+{
+ assert(pThis != NULL);
+ free(pThis->pszName);
+ free(pThis->cnfName);
+ if(pThis->pModHdlr != NULL) {
+# ifdef VALGRIND
+ DBGPRINTF("moduleDestruct: compiled with valgrind, do "
+ "not unload module\n");
+# else
+ if(glblUnloadModules) {
+ if(pThis->eKeepType == eMOD_NOKEEP) {
+ dlclose(pThis->pModHdlr);
+ }
+ } else {
+ DBGPRINTF("moduleDestruct: not unloading module "
+ "due to user configuration\n");
+ }
+# endif
+ }
+
+ free(pThis);
+}
+
+
+/* This enables a module to query the core for specific features.
+ * rgerhards, 2009-04-22
+ */
+static rsRetVal queryCoreFeatureSupport(int *pBool, unsigned uFeat)
+{
+ DEFiRet;
+
+ if(pBool == NULL)
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+
+ *pBool = (uFeat & CORE_FEATURE_BATCHING) ? 1 : 0;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* The following function is the queryEntryPoint for host-based entry points.
+ * Modules may call it to get access to core interface functions. Please note
+ * that utility functions can be accessed via shared libraries - at least this
+ * is my current shool of thinking.
+ * Please note that the implementation as a query interface allows one to take
+ * care of plug-in interface version differences. -- rgerhards, 2007-07-31
+ * ... but often it better not to use a new interface. So we now add core
+ * functions here that a plugin may request. -- rgerhards, 2009-04-22
+ */
+static rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)())
+{
+ DEFiRet;
+
+ if((name == NULL) || (pEtryPoint == NULL))
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+
+ if(!strcmp((char*) name, "regCfSysLineHdlr")) {
+ *pEtryPoint = regCfSysLineHdlr;
+ } else if(!strcmp((char*) name, "objGetObjInterface")) {
+ *pEtryPoint = objGetObjInterface;
+ } else if(!strcmp((char*) name, "OMSRgetSupportedTplOpts")) {
+ *pEtryPoint = OMSRgetSupportedTplOpts;
+ } else if(!strcmp((char*) name, "queryCoreFeatureSupport")) {
+ *pEtryPoint = queryCoreFeatureSupport;
+ } else {
+ *pEtryPoint = NULL; /* to be on the safe side */
+ ABORT_FINALIZE(RS_RET_ENTRY_POINT_NOT_FOUND);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the name of a module
+ */
+uchar *
+modGetName(modInfo_t *pThis)
+{
+ return((pThis->pszName == NULL) ? (uchar*) "" : pThis->pszName);
+}
+
+
+/* get the state-name of a module. The state name is its name
+ * together with a short description of the module state (which
+ * is pulled from the module itself.
+ * rgerhards, 2007-07-24
+ * TODO: the actual state name is not yet pulled
+ */
+static uchar *modGetStateName(modInfo_t *pThis)
+{
+ return(modGetName(pThis));
+}
+
+
+/* Add a module to the loaded module linked list
+ */
+static void ATTR_NONNULL()
+addModToGlblList(modInfo_t *const pThis)
+{
+ assert(pThis != NULL);
+
+ if(pLoadedModules == NULL) {
+ pLoadedModules = pLoadedModulesLast = pThis;
+ } else {
+ /* there already exist entries */
+ pThis->pPrev = pLoadedModulesLast;
+ pLoadedModulesLast->pNext = pThis;
+ pLoadedModulesLast = pThis;
+ }
+}
+
+
+/* ready module for config processing. this includes checking if the module
+ * is already in the config, so this function may return errors. Returns a
+ * pointer to the last module inthe current config. That pointer needs to
+ * be passed to addModToCnfLst() when it is called later in the process.
+ */
+rsRetVal
+readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast)
+{
+ cfgmodules_etry_t *pNew = NULL;
+ cfgmodules_etry_t *pLast;
+ DEFiRet;
+ assert(pThis != NULL);
+
+ if(loadConf == NULL) {
+ FINALIZE; /* we are in an early init state */
+ }
+
+ /* check for duplicates and, as a side-activity, identify last node */
+ pLast = loadConf->modules.root;
+ if(pLast != NULL) {
+ while(1) { /* loop broken inside */
+ if(pLast->pMod == pThis) {
+ DBGPRINTF("module '%s' already in this config\n", modGetName(pThis));
+ if(strncmp((char*)modGetName(pThis), "builtin:", sizeof("builtin:")-1)) {
+ LogError(0, RS_RET_MODULE_ALREADY_IN_CONF,
+ "module '%s' already in this config, cannot be added\n", modGetName(pThis));
+ ABORT_FINALIZE(RS_RET_MODULE_ALREADY_IN_CONF);
+ }
+ FINALIZE;
+ }
+ if(pLast->next == NULL)
+ break;
+ pLast = pLast->next;
+ }
+ }
+
+ /* if we reach this point, pLast is the tail pointer and this module is new
+ * inside the currently loaded config. So, iff it is an input module, let's
+ * pass it a pointer which it can populate with a pointer to its module conf.
+ */
+
+ CHKmalloc(pNew = malloc(sizeof(cfgmodules_etry_t)));
+ pNew->canActivate = 1;
+ pNew->next = NULL;
+ pNew->pMod = pThis;
+
+ if(pThis->beginCnfLoad != NULL) {
+ CHKiRet(pThis->beginCnfLoad(&pNew->modCnf, loadConf));
+ }
+
+ *ppLast = pLast;
+ *ppNew = pNew;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ free(pNew);
+ }
+ RETiRet;
+}
+
+
+/* abort the creation of a module entry without adding it to the
+ * module list. Needed to prevent mem leaks.
+ */
+static inline void
+abortCnfUse(cfgmodules_etry_t **pNew)
+{
+ if(pNew != NULL) {
+ free(*pNew);
+ *pNew = NULL;
+ }
+}
+
+
+/* Add a module to the config module list for current loadConf.
+ * Requires last pointer obtained by readyModForCnf().
+ * The module pointer is handed over to this function. It is no
+ * longer available to caller one we are called.
+ */
+rsRetVal ATTR_NONNULL(1)
+addModToCnfList(cfgmodules_etry_t **const pNew, cfgmodules_etry_t *const pLast)
+{
+ DEFiRet;
+ assert(*pNew != NULL);
+
+ if(loadConf == NULL) {
+ abortCnfUse(pNew);
+ FINALIZE; /* we are in an early init state */
+ }
+
+ if(pLast == NULL) {
+ loadConf->modules.root = *pNew;
+ } else {
+ /* there already exist entries */
+ pLast->next = *pNew;
+ }
+
+finalize_it:
+ *pNew = NULL;
+ RETiRet;
+}
+
+
+/* Get the next module pointer - this is used to traverse the list.
+ * The function returns the next pointer or NULL, if there is no next one.
+ * The last object must be provided to the function. If NULL is provided,
+ * it starts at the root of the list. Even in this case, NULL may be
+ * returned - then, the list is empty.
+ * rgerhards, 2007-07-23
+ */
+static modInfo_t *GetNxt(modInfo_t *pThis)
+{
+ modInfo_t *pNew;
+
+ if(pThis == NULL)
+ pNew = pLoadedModules;
+ else
+ pNew = pThis->pNext;
+
+ return(pNew);
+}
+
+
+/* this function is like GetNxt(), but it returns pointers to
+ * the configmodules entry, which than can be used to obtain the
+ * actual module pointer. Note that it returns those for
+ * modules of specific type only. Only modules from the provided
+ * config are returned. Note that processing speed could be improved,
+ * but this is really not relevant, as config file loading is not really
+ * something we are concerned about in regard to runtime.
+ */
+static cfgmodules_etry_t
+*GetNxtCnfType(rsconf_t *cnf, cfgmodules_etry_t *node, eModType_t rqtdType)
+{
+ if(node == NULL) { /* start at beginning of module list */
+ node = cnf->modules.root;
+ } else {
+ node = node->next;
+ }
+
+ if(rqtdType != eMOD_ANY) { /* if any, we already have the right one! */
+ while(node != NULL && node->pMod->eType != rqtdType) {
+ node = node->next;
+ }
+ }
+
+ return node;
+}
+
+
+/* Find a module with the given conf name and type. Returns NULL if none
+ * can be found, otherwise module found.
+ */
+static modInfo_t *
+FindWithCnfName(rsconf_t *cnf, uchar *name, eModType_t rqtdType)
+{
+ cfgmodules_etry_t *node;
+
+ ;
+ for( node = cnf->modules.root
+ ; node != NULL
+ ; node = node->next) {
+ if(node->pMod->eType != rqtdType || node->pMod->cnfName == NULL)
+ continue;
+ if(!strcasecmp((char*)node->pMod->cnfName, (char*)name))
+ break;
+ }
+
+ return node == NULL ? NULL : node->pMod;
+}
+
+
+/* Prepare a module for unloading.
+ * This is currently a dummy, to be filled when we have a plug-in
+ * interface - rgerhards, 2007-08-09
+ * rgerhards, 2007-11-21:
+ * When this function is called, all instance-data must already have
+ * been destroyed. In the case of output modules, this happens when the
+ * rule set is being destroyed. When we implement other module types, we
+ * need to think how we handle it there (and if we have any instance data).
+ * rgerhards, 2008-03-10: reject unload request if the module has a reference
+ * count > 0.
+ */
+static rsRetVal
+modPrepareUnload(modInfo_t *pThis)
+{
+ DEFiRet;
+ void *pModCookie;
+
+ assert(pThis != NULL);
+
+ if(pThis->uRefCnt > 0) {
+ dbgprintf("rejecting unload of module '%s' because it has a refcount of %d\n",
+ pThis->pszName, pThis->uRefCnt);
+ ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED);
+ }
+
+ CHKiRet(pThis->modGetID(&pModCookie));
+ pThis->modExit(); /* tell the module to get ready for unload */
+ CHKiRet(unregCfSysLineHdlrs4Owner(pModCookie));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Add an already-loaded module to the module linked list. This function does
+ * everything needed to fully initialize the module.
+ */
+static rsRetVal
+doModInit(pModInit_t modInit, uchar *name, void *pModHdlr, modInfo_t **pNewModule)
+{
+ rsRetVal localRet;
+ modInfo_t *pNew = NULL;
+ uchar *pName;
+ strgen_t *pStrgen; /* used for strgen modules */
+ rsRetVal (*GetName)(uchar**);
+ rsRetVal (*modGetType)(eModType_t *pType);
+ rsRetVal (*modGetKeepType)(eModKeepType_t *pKeepType);
+ struct dlhandle_s *pHandle = NULL;
+ rsRetVal (*getModCnfName)(uchar **cnfName);
+ uchar *cnfName;
+ DEFiRet;
+
+ assert(modInit != NULL);
+
+ if((iRet = moduleConstruct(&pNew)) != RS_RET_OK) {
+ pNew = NULL;
+ FINALIZE;
+ }
+
+ CHKiRet((*modInit)(CURR_MOD_IF_VERSION, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt, pNew));
+
+ if(pNew->iIFVers != CURR_MOD_IF_VERSION) {
+ ABORT_FINALIZE(RS_RET_MISSING_INTERFACE);
+ }
+
+ /* We now poll the module to see what type it is. We do this only once as this
+ * can never change in the lifetime of an module. -- rgerhards, 2007-12-14
+ */
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getType", &modGetType));
+ CHKiRet((*modGetType)(&pNew->eType));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getKeepType", &modGetKeepType));
+ CHKiRet((*modGetKeepType)(&pNew->eKeepType));
+ dbgprintf("module %s of type %d being loaded (keepType=%d).\n", name, pNew->eType, pNew->eKeepType);
+
+ /* OK, we know we can successfully work with the module. So we now fill the
+ * rest of the data elements. First we load the interfaces common to all
+ * module types.
+ */
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modGetID", &pNew->modGetID));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"modExit", &pNew->modExit));
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"isCompatibleWithFeature", &pNew->isCompatibleWithFeature);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ pNew->isCompatibleWithFeature = dummyIsCompatibleWithFeature;
+ else if(localRet != RS_RET_OK)
+ ABORT_FINALIZE(localRet);
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"setModCnf", &pNew->setModCnf);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ pNew->setModCnf = NULL;
+ else if(localRet != RS_RET_OK)
+ ABORT_FINALIZE(localRet);
+
+ /* optional calls for new config system */
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"getModCnfName", &getModCnfName);
+ if(localRet == RS_RET_OK) {
+ if(getModCnfName(&cnfName) == RS_RET_OK)
+ pNew->cnfName = (uchar*) strdup((char*)cnfName);
+ /**< we do not care if strdup() fails, we can accept that */
+ else
+ pNew->cnfName = NULL;
+ dbgprintf("module config name is '%s'\n", cnfName);
+ }
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"beginCnfLoad", &pNew->beginCnfLoad);
+ if(localRet == RS_RET_OK) {
+ dbgprintf("module %s supports rsyslog v6 config interface\n", name);
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"endCnfLoad", &pNew->endCnfLoad));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeCnf", &pNew->freeCnf));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"checkCnf", &pNew->checkCnf));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"activateCnf", &pNew->activateCnf));
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"activateCnfPrePrivDrop", &pNew->activateCnfPrePrivDrop);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->activateCnfPrePrivDrop = NULL;
+ } else {
+ CHKiRet(localRet);
+ }
+ } else if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->beginCnfLoad = NULL; /* flag as non-present */
+ } else {
+ ABORT_FINALIZE(localRet);
+ }
+ /* ... and now the module-specific interfaces */
+ switch(pNew->eType) {
+ case eMOD_IN:
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"runInput", &pNew->mod.im.runInput));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun));
+ pNew->mod.im.bCanRun = 0;
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"newInpInst", &pNew->mod.im.newInpInst);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.im.newInpInst = NULL;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUP", &pNew->doHUP);
+ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ ABORT_FINALIZE(localRet);
+
+ break;
+ case eMOD_OUT:
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"dbgPrintInstInfo", &pNew->dbgPrintInstInfo));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"createWrkrInstance",
+ &pNew->mod.om.createWrkrInstance));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeWrkrInstance",
+ &pNew->mod.om.freeWrkrInstance));
+
+ /* try load optional interfaces */
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUP", &pNew->doHUP);
+ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ ABORT_FINALIZE(localRet);
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUPWrkr", &pNew->doHUPWrkr);
+ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ ABORT_FINALIZE(localRet);
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"SetShutdownImmdtPtr",
+ &pNew->mod.om.SetShutdownImmdtPtr);
+ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ ABORT_FINALIZE(localRet);
+
+ pNew->mod.om.supportsTX = 1;
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"beginTransaction", &pNew->mod.om.beginTransaction);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.beginTransaction = dummyBeginTransaction;
+ pNew->mod.om.supportsTX = 0;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"doAction",
+ &pNew->mod.om.doAction);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.doAction = NULL;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"commitTransaction",
+ &pNew->mod.om.commitTransaction);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.commitTransaction = NULL;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ if(pNew->mod.om.doAction == NULL && pNew->mod.om.commitTransaction == NULL) {
+ LogError(0, RS_RET_INVLD_OMOD,
+ "module %s does neither provide doAction() "
+ "nor commitTransaction() interface - cannot "
+ "load", name);
+ ABORT_FINALIZE(RS_RET_INVLD_OMOD);
+ }
+
+ if(pNew->mod.om.commitTransaction != NULL) {
+ if(pNew->mod.om.doAction != NULL){
+ LogError(0, RS_RET_INVLD_OMOD,
+ "module %s provides both doAction() "
+ "and commitTransaction() interface, using "
+ "commitTransaction()", name);
+ pNew->mod.om.doAction = NULL;
+ }
+ if(pNew->mod.om.beginTransaction == NULL){
+ LogError(0, RS_RET_INVLD_OMOD,
+ "module %s provides both commitTransaction() "
+ "but does not provide beginTransaction() - "
+ "cannot load", name);
+ ABORT_FINALIZE(RS_RET_INVLD_OMOD);
+ }
+ }
+
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction",
+ &pNew->mod.om.endTransaction);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.endTransaction = dummyEndTransaction;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"newActInst", &pNew->mod.om.newActInst);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.newActInst = dummynewActInst;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+ break;
+ case eMOD_LIB:
+ break;
+ case eMOD_PARSER:
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"parse2",
+ &pNew->mod.pm.parse2);
+ if(localRet == RS_RET_OK) {
+ pNew->mod.pm.parse = NULL;
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"newParserInst",
+ &pNew->mod.pm.newParserInst));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeParserInst",
+ &pNew->mod.pm.freeParserInst));
+ } else if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.pm.parse2 = NULL;
+ pNew->mod.pm.newParserInst = NULL;
+ pNew->mod.pm.freeParserInst = NULL;
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parse", &pNew->mod.pm.parse));
+ } else {
+ ABORT_FINALIZE(localRet);
+ }
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"GetParserName", &GetName));
+ CHKiRet(GetName(&pName));
+ CHKiRet(parserConstructViaModAndName(pNew, pName, NULL));
+ break;
+ case eMOD_STRGEN:
+ /* first, we need to obtain the strgen object. We could not do that during
+ * init as that would have caused class bootstrap issues which are not
+ * absolutely necessary. Note that we can call objUse() multiple times, it
+ * handles that.
+ */
+ CHKiRet(objUse(strgen, CORE_COMPONENT));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"strgen", &pNew->mod.sm.strgen));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"GetName", &GetName));
+ CHKiRet(GetName(&pName));
+ CHKiRet(strgen.Construct(&pStrgen));
+ CHKiRet(strgen.SetName(pStrgen, pName));
+ CHKiRet(strgen.SetModPtr(pStrgen, pNew));
+ CHKiRet(strgen.ConstructFinalize(pStrgen));
+ break;
+ case eMOD_FUNCTION:
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getFunctArray", &pNew->mod.fm.getFunctArray));
+ int version;
+ struct scriptFunct *functArray;
+ pNew->mod.fm.getFunctArray(&version, &functArray);
+ dbgprintf("LLL: %s\n", functArray[0].fname);
+ addMod2List(version, functArray);
+ break;
+ case eMOD_ANY: /* this is mostly to keep the compiler happy! */
+ DBGPRINTF("PROGRAM ERROR: eMOD_ANY set as module type\n");
+ assert(0);
+ break;
+ }
+
+ pNew->pszName = (uchar*) strdup((char*)name); /* we do not care if strdup() fails, we can accept that */
+ pNew->pModHdlr = pModHdlr;
+ if(pModHdlr == NULL) {
+ pNew->eLinkType = eMOD_LINK_STATIC;
+ } else {
+ pNew->eLinkType = eMOD_LINK_DYNAMIC_LOADED;
+
+ /* if we need to keep the linked module, save it */
+ if (pNew->eKeepType == eMOD_KEEP) {
+ /* see if we have this one already */
+ for (pHandle = pHandles; pHandle; pHandle = pHandle->next) {
+ if (!strcmp((char *)name, (char *)pHandle->pszName))
+ break;
+ }
+
+ /* not found, create it */
+ if (!pHandle) {
+ if((pHandle = malloc(sizeof (*pHandle))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ if((pHandle->pszName = (uchar*) strdup((char*)name)) == NULL) {
+ free(pHandle);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pHandle->pModHdlr = pModHdlr;
+ pHandle->next = pHandles;
+
+ pHandles = pHandle;
+ }
+ }
+ }
+
+ /* we initialized the structure, now let's add it to the linked list of modules */
+ addModToGlblList(pNew);
+ *pNewModule = pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ moduleDestruct(pNew);
+ *pNewModule = NULL;
+ }
+
+ RETiRet;
+}
+
+/* Print loaded modules. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ * This only works if the dbgprintf() subsystem is initialized.
+ * TODO: update for new input modules!
+ */
+static void modPrintList(void)
+{
+ modInfo_t *pMod;
+
+ pMod = GetNxt(NULL);
+ while(pMod != NULL) {
+ dbgprintf("Loaded Module: Name='%s', IFVersion=%d, ",
+ (char*) modGetName(pMod), pMod->iIFVers);
+ dbgprintf("type=");
+ switch(pMod->eType) {
+ case eMOD_OUT:
+ dbgprintf("output");
+ break;
+ case eMOD_IN:
+ dbgprintf("input");
+ break;
+ case eMOD_LIB:
+ dbgprintf("library");
+ break;
+ case eMOD_PARSER:
+ dbgprintf("parser");
+ break;
+ case eMOD_STRGEN:
+ dbgprintf("strgen");
+ break;
+ case eMOD_FUNCTION:
+ dbgprintf("function");
+ break;
+ case eMOD_ANY: /* this is mostly to keep the compiler happy! */
+ DBGPRINTF("PROGRAM ERROR: eMOD_ANY set as module type\n");
+ assert(0);
+ break;
+ }
+ dbgprintf(" module.\n");
+ dbgprintf("Entry points:\n");
+ dbgprintf("\tqueryEtryPt: 0x%lx\n", (unsigned long) pMod->modQueryEtryPt);
+ dbgprintf("\tdbgPrintInstInfo: 0x%lx\n", (unsigned long) pMod->dbgPrintInstInfo);
+ dbgprintf("\tfreeInstance: 0x%lx\n", (unsigned long) pMod->freeInstance);
+ dbgprintf("\tbeginCnfLoad: 0x%lx\n", (unsigned long) pMod->beginCnfLoad);
+ dbgprintf("\tSetModCnf: 0x%lx\n", (unsigned long) pMod->setModCnf);
+ dbgprintf("\tcheckCnf: 0x%lx\n", (unsigned long) pMod->checkCnf);
+ dbgprintf("\tactivateCnfPrePrivDrop: 0x%lx\n", (unsigned long) pMod->activateCnfPrePrivDrop);
+ dbgprintf("\tactivateCnf: 0x%lx\n", (unsigned long) pMod->activateCnf);
+ dbgprintf("\tfreeCnf: 0x%lx\n", (unsigned long) pMod->freeCnf);
+ switch(pMod->eType) {
+ case eMOD_OUT:
+ dbgprintf("Output Module Entry Points:\n");
+ dbgprintf("\tdoAction: %p\n", pMod->mod.om.doAction);
+ dbgprintf("\tparseSelectorAct: %p\n", pMod->mod.om.parseSelectorAct);
+ dbgprintf("\tnewActInst: %p\n", (pMod->mod.om.newActInst == dummynewActInst) ?
+ NULL : pMod->mod.om.newActInst);
+ dbgprintf("\ttryResume: %p\n", pMod->tryResume);
+ dbgprintf("\tdoHUP: %p\n", pMod->doHUP);
+ dbgprintf("\tBeginTransaction: %p\n", ((pMod->mod.om.beginTransaction ==
+ dummyBeginTransaction) ? NULL : pMod->mod.om.beginTransaction));
+ dbgprintf("\tEndTransaction: %p\n", ((pMod->mod.om.endTransaction ==
+ dummyEndTransaction) ? NULL : pMod->mod.om.endTransaction));
+ break;
+ case eMOD_IN:
+ dbgprintf("Input Module Entry Points\n");
+ dbgprintf("\trunInput: 0x%lx\n", (unsigned long) pMod->mod.im.runInput);
+ dbgprintf("\twillRun: 0x%lx\n", (unsigned long) pMod->mod.im.willRun);
+ dbgprintf("\tafterRun: 0x%lx\n", (unsigned long) pMod->mod.im.afterRun);
+ break;
+ case eMOD_LIB:
+ break;
+ case eMOD_PARSER:
+ dbgprintf("Parser Module Entry Points\n");
+ dbgprintf("\tparse: 0x%lx\n", (unsigned long) pMod->mod.pm.parse);
+ break;
+ case eMOD_STRGEN:
+ dbgprintf("Strgen Module Entry Points\n");
+ dbgprintf("\tstrgen: 0x%lx\n", (unsigned long) pMod->mod.sm.strgen);
+ break;
+ case eMOD_FUNCTION:
+ dbgprintf("Function Module Entry Points\n");
+ dbgprintf("\tgetFunctArray: 0x%lx\n", (unsigned long) pMod->mod.fm.getFunctArray);
+ break;
+ case eMOD_ANY: /* this is mostly to keep the compiler happy! */
+ break;
+ }
+ dbgprintf("\n");
+ pMod = GetNxt(pMod); /* done, go next */
+ }
+}
+
+
+/* HUP all modules that support it - except for actions, which
+ * need (and have) specialised HUP handling.
+ */
+void
+modDoHUP(void)
+{
+ modInfo_t *pMod;
+
+ pthread_mutex_lock(&mutObjGlobalOp);
+ pMod = GetNxt(NULL);
+ while(pMod != NULL) {
+ if(pMod->eType != eMOD_OUT && pMod->doHUP != NULL) {
+ DBGPRINTF("HUPing module %s\n", (char*) modGetName(pMod));
+ pMod->doHUP(NULL);
+ }
+ pMod = GetNxt(pMod); /* done, go next */
+ }
+ pthread_mutex_unlock(&mutObjGlobalOp);
+}
+
+
+/* unlink and destroy a module. The caller must provide a pointer to the module
+ * itself as well as one to its immediate predecessor.
+ * rgerhards, 2008-02-26
+ */
+static rsRetVal
+modUnlinkAndDestroy(modInfo_t **ppThis)
+{
+ DEFiRet;
+ modInfo_t *pThis;
+
+ assert(ppThis != NULL);
+ pThis = *ppThis;
+ assert(pThis != NULL);
+
+ pthread_mutex_lock(&mutObjGlobalOp);
+
+ /* first check if we are permitted to unload */
+ if(pThis->eType == eMOD_LIB) {
+ if(pThis->uRefCnt > 0) {
+ dbgprintf("module %s NOT unloaded because it still has a refcount of %u\n",
+ pThis->pszName, pThis->uRefCnt);
+ ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED);
+ }
+ }
+
+ /* we need to unlink the module before we can destruct it -- rgerhards, 2008-02-26 */
+ if(pThis->pPrev == NULL) {
+ /* module is root, so we need to set a new root */
+ pLoadedModules = pThis->pNext;
+ } else {
+ pThis->pPrev->pNext = pThis->pNext;
+ }
+
+ if(pThis->pNext == NULL) {
+ pLoadedModulesLast = pThis->pPrev;
+ } else {
+ pThis->pNext->pPrev = pThis->pPrev;
+ }
+
+ /* finally, we are ready for the module to go away... */
+ dbgprintf("Unloading module %s\n", modGetName(pThis));
+ CHKiRet(modPrepareUnload(pThis));
+ *ppThis = pThis->pNext;
+
+ moduleDestruct(pThis);
+
+finalize_it:
+ pthread_mutex_unlock(&mutObjGlobalOp);
+ RETiRet;
+}
+
+
+/* unload all loaded modules of a specific type (use eMOD_ALL if you want to
+ * unload all module types). The unload happens only if the module is no longer
+ * referenced. So some modules may survive this call.
+ * rgerhards, 2008-03-11
+ */
+static rsRetVal
+modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload)
+{
+ DEFiRet;
+ modInfo_t *pModCurr; /* module currently being processed */
+
+ pModCurr = GetNxt(NULL);
+ while(pModCurr != NULL) {
+ if(modLinkTypesToUnload == eMOD_LINK_ALL || pModCurr->eLinkType == modLinkTypesToUnload) {
+ if(modUnlinkAndDestroy(&pModCurr) == RS_RET_MODULE_STILL_REFERENCED) {
+ pModCurr = GetNxt(pModCurr);
+ } else {
+ /* Note: if the module was successfully unloaded, it has updated the
+ * pModCurr pointer to the next module. However, the unload process may
+ * still have indirectly referenced the pointer list in a way that the
+ * unloaded module is not aware of. So we restart the unload process
+ * to make sure we do not fall into a trap (what we did ;)). The
+ * performance toll is minimal. -- rgerhards, 2008-04-28
+ */
+ pModCurr = GetNxt(NULL);
+ }
+ } else {
+ pModCurr = GetNxt(pModCurr);
+ }
+ }
+
+ RETiRet;
+}
+
+/* find module with given name in global list */
+static rsRetVal
+findModule(uchar *pModName, int iModNameLen, modInfo_t **pMod)
+{
+ modInfo_t *pModInfo;
+ uchar *pModNameCmp;
+ DEFiRet;
+
+ pModInfo = GetNxt(NULL);
+ while(pModInfo != NULL) {
+ if(!strncmp((char *) pModName, (char *) (pModNameCmp = modGetName(pModInfo)), iModNameLen) &&
+ (!*(pModNameCmp + iModNameLen) || !strcmp((char *) pModNameCmp + iModNameLen, ".so"))) {
+ dbgprintf("Module '%s' found\n", pModName);
+ break;
+ }
+ pModInfo = GetNxt(pModInfo);
+ }
+ *pMod = pModInfo;
+ RETiRet;
+}
+
+
+/* load a module and initialize it, based on doModLoad() from conf.c
+ * rgerhards, 2008-03-05
+ * varmojfekoj added support for dynamically loadable modules on 2007-08-13
+ * rgerhards, 2007-09-25: please note that the non-threadsafe function dlerror() is
+ * called below. This is ok because modules are currently only loaded during
+ * configuration file processing, which is executed on a single thread. Should we
+ * change that design at any stage (what is unlikely), we need to find a
+ * replacement.
+ * rgerhards, 2011-04-27:
+ * Parameter "bConfLoad" tells us if the load was triggered by a config handler, in
+ * which case we need to tie the loaded module to the current config. If bConfLoad == 0,
+ * the system loads a module for internal reasons, this is not directly tied to a
+ * configuration. We could also think if it would be useful to add only certain types
+ * of modules, but the current implementation at least looks simpler.
+ * Note: pvals = NULL means legacy config system
+ */
+static rsRetVal ATTR_NONNULL(1)
+Load(uchar *const pModName, const sbool bConfLoad, struct nvlst *const lst)
+{
+ size_t iPathLen, iModNameLen;
+ int bHasExtension;
+ void *pModHdlr;
+ pModInit_t pModInit;
+ modInfo_t *pModInfo;
+ cfgmodules_etry_t *pNew = NULL;
+ cfgmodules_etry_t *pLast = NULL;
+ uchar *pModDirCurr, *pModDirNext;
+ int iLoadCnt;
+ struct dlhandle_s *pHandle = NULL;
+ uchar pathBuf[PATH_MAX+1];
+ uchar *pPathBuf = pathBuf;
+ size_t lenPathBuf = sizeof(pathBuf);
+ rsRetVal localRet;
+ cstr_t *load_err_msg = NULL;
+ DEFiRet;
+
+ assert(pModName != NULL);
+ DBGPRINTF("Requested to load module '%s'\n", pModName);
+
+ iModNameLen = strlen((char*)pModName);
+ /* overhead for a full path is potentially 1 byte for a slash,
+ * three bytes for ".so" and one byte for '\0'.
+ */
+# define PATHBUF_OVERHEAD 1 + iModNameLen + 3 + 1
+
+ pthread_mutex_lock(&mutObjGlobalOp);
+
+ if(iModNameLen > 3 && !strcmp((char *) pModName + iModNameLen - 3, ".so")) {
+ iModNameLen -= 3;
+ bHasExtension = RSTRUE;
+ } else
+ bHasExtension = RSFALSE;
+
+ CHKiRet(findModule(pModName, iModNameLen, &pModInfo));
+ if(pModInfo != NULL) {
+ DBGPRINTF("Module '%s' already loaded\n", pModName);
+ if(bConfLoad) {
+ localRet = readyModForCnf(pModInfo, &pNew, &pLast);
+ if(pModInfo->setModCnf != NULL && localRet == RS_RET_OK) {
+ if(!strncmp((char*)pModName, "builtin:", sizeof("builtin:")-1)) {
+ if(pModInfo->bSetModCnfCalled) {
+ LogError(0, RS_RET_DUP_PARAM,
+ "parameters for built-in module %s already set - ignored\n",
+ pModName);
+ ABORT_FINALIZE(RS_RET_DUP_PARAM);
+ } else {
+ /* for built-in moules, we need to call setModConf,
+ * because there is no way to set parameters at load
+ * time for obvious reasons...
+ */
+ if(lst != NULL)
+ pModInfo->setModCnf(lst);
+ pModInfo->bSetModCnfCalled = 1;
+ }
+ } else {
+ /* regular modules need to be added to conf list (for
+ * builtins, this happend during initial load).
+ */
+ addModToCnfList(&pNew, pLast);
+ }
+ }
+ }
+ FINALIZE;
+ }
+
+ pModDirCurr = (uchar *)((pModDir == NULL) ? _PATH_MODDIR : (char *)pModDir);
+ pModDirNext = NULL;
+ pModHdlr = NULL;
+ iLoadCnt = 0;
+ do { /* now build our load module name */
+ if(*pModName == '/' || *pModName == '.') {
+ if(lenPathBuf < PATHBUF_OVERHEAD) {
+ if(pPathBuf != pathBuf) /* already malloc()ed memory? */
+ free(pPathBuf);
+ /* we always alloc enough memory for everything we potentiall need to add */
+ lenPathBuf = PATHBUF_OVERHEAD;
+ CHKmalloc(pPathBuf = malloc(lenPathBuf));
+ }
+ *pPathBuf = '\0'; /* we do not need to append the path - its already in the module name */
+ iPathLen = 0;
+ } else {
+ *pPathBuf = '\0';
+
+ iPathLen = strlen((char *)pModDirCurr);
+ pModDirNext = (uchar *)strchr((char *)pModDirCurr, ':');
+ if(pModDirNext)
+ iPathLen = (size_t)(pModDirNext - pModDirCurr);
+
+ if(iPathLen == 0) {
+ if(pModDirNext) {
+ pModDirCurr = pModDirNext + 1;
+ continue;
+ }
+ break;
+ } else if(iPathLen > lenPathBuf - PATHBUF_OVERHEAD) {
+ if(pPathBuf != pathBuf) /* already malloc()ed memory? */
+ free(pPathBuf);
+ /* we always alloc enough memory for everything we potentiall need to add */
+ lenPathBuf = iPathLen + PATHBUF_OVERHEAD;
+ CHKmalloc(pPathBuf = malloc(lenPathBuf));
+ }
+
+ memcpy((char *) pPathBuf, (char *)pModDirCurr, iPathLen);
+ if((pPathBuf[iPathLen - 1] != '/')) {
+ /* we have space, made sure in previous check */
+ pPathBuf[iPathLen++] = '/';
+ }
+ pPathBuf[iPathLen] = '\0';
+
+ if(pModDirNext)
+ pModDirCurr = pModDirNext + 1;
+ }
+
+ /* ... add actual name ... */
+ strncat((char *) pPathBuf, (char *) pModName, lenPathBuf - iPathLen - 1);
+
+ /* now see if we have an extension and, if not, append ".so" */
+ if(!bHasExtension) {
+ /* we do not have an extension and so need to add ".so"
+ * TODO: I guess this is highly importable, so we should change the
+ * algo over time... -- rgerhards, 2008-03-05
+ */
+ strncat((char *) pPathBuf, ".so", lenPathBuf - strlen((char*) pPathBuf) - 1);
+ }
+
+ /* complete load path constructed, so ... GO! */
+ dbgprintf("loading module '%s'\n", pPathBuf);
+
+ /* see if we have this one already */
+ for (pHandle = pHandles; pHandle; pHandle = pHandle->next) {
+ if (!strcmp((char *)pModName, (char *)pHandle->pszName)) {
+ pModHdlr = pHandle->pModHdlr;
+ break;
+ }
+ }
+
+ /* not found, try to dynamically link it */
+ if (!pModHdlr) {
+ pModHdlr = dlopen((char *) pPathBuf, RTLD_NOW);
+ }
+
+ if(pModHdlr == NULL) {
+ char errmsg[4096];
+ snprintf(errmsg, sizeof(errmsg), "%strying to load module %s: %s",
+ (load_err_msg == NULL) ? "" : " //////// ",
+ pPathBuf, dlerror());
+ if(load_err_msg == NULL) {
+ rsCStrConstructFromszStr(&load_err_msg, (uchar*)errmsg);
+ } else {
+ rsCStrAppendStr(load_err_msg, (uchar*)errmsg);
+ }
+ }
+
+ iLoadCnt++;
+
+ } while(pModHdlr == NULL && *pModName != '/' && pModDirNext);
+
+ if(load_err_msg != NULL) {
+ cstrFinalize(load_err_msg);
+ }
+
+ if(!pModHdlr) {
+ LogError(0, RS_RET_MODULE_LOAD_ERR_DLOPEN, "could not load module '%s', errors: %s", pModName,
+ (load_err_msg == NULL) ? "NONE SEEN???" : (const char*) cstrGetSzStrNoNULL(load_err_msg));
+ ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_DLOPEN);
+ }
+ if(!(pModInit = (pModInit_t)dlsym(pModHdlr, "modInit"))) {
+ LogError(0, RS_RET_MODULE_LOAD_ERR_NO_INIT,
+ "could not load module '%s', dlsym: %s\n", pPathBuf, dlerror());
+ dlclose(pModHdlr);
+ ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_NO_INIT);
+ }
+ if((iRet = doModInit(pModInit, (uchar*) pModName, pModHdlr, &pModInfo)) != RS_RET_OK) {
+ LogError(0, RS_RET_MODULE_LOAD_ERR_INIT_FAILED,
+ "could not load module '%s', rsyslog error %d\n", pPathBuf, iRet);
+ dlclose(pModHdlr);
+ ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED);
+ }
+
+ if(bConfLoad) {
+ readyModForCnf(pModInfo, &pNew, &pLast);
+ if(pModInfo->setModCnf != NULL) {
+ if(lst != NULL) {
+ localRet = pModInfo->setModCnf(lst);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet,
+ "module '%s', failed processing config parameters",
+ pPathBuf);
+ ABORT_FINALIZE(localRet);
+ }
+ }
+ pModInfo->bSetModCnfCalled = 1;
+ }
+ addModToCnfList(&pNew, pLast);
+ }
+
+finalize_it:
+ if(load_err_msg != NULL) {
+ cstrDestruct(&load_err_msg);
+ }
+ if(pPathBuf != pathBuf) /* used malloc()ed memory? */
+ free(pPathBuf);
+ if(iRet != RS_RET_OK)
+ abortCnfUse(&pNew);
+ free(pNew); /* is NULL again if properly consumed, else clean up */
+ pthread_mutex_unlock(&mutObjGlobalOp);
+ RETiRet;
+}
+
+
+/* the v6+ way of loading modules: process a "module(...)" directive.
+ * rgerhards, 2012-06-20
+ */
+rsRetVal
+modulesProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ uchar *cnfModName = NULL;
+ int typeIdx;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &pblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ DBGPRINTF("modulesProcessCnf params:\n");
+ cnfparamsPrint(&pblk, pvals);
+ typeIdx = cnfparamGetIdx(&pblk, "load");
+ if(pvals[typeIdx].bUsed == 0) {
+ LogError(0, RS_RET_CONF_RQRD_PARAM_MISSING, "module type missing");
+ ABORT_FINALIZE(RS_RET_CONF_RQRD_PARAM_MISSING);
+ }
+
+ cnfModName = (uchar*)es_str2cstr(pvals[typeIdx].val.d.estr, NULL);
+ iRet = Load(cnfModName, 1, o->nvlst);
+
+finalize_it:
+ free(cnfModName);
+ cnfparamvalsDestruct(pvals, &pblk);
+ RETiRet;
+}
+
+
+/* set the default module load directory. A NULL value may be provided, in
+ * which case any previous value is deleted but no new one set. The caller-provided
+ * string is duplicated. If it needs to be freed, that's the caller's duty.
+ * rgerhards, 2008-03-07
+ */
+static rsRetVal
+SetModDir(uchar *pszModDir)
+{
+ DEFiRet;
+
+ dbgprintf("setting default module load directory '%s'\n", pszModDir);
+ if(pModDir != NULL) {
+ free(pModDir);
+ }
+
+ pModDir = (uchar*) strdup((char*)pszModDir);
+
+ RETiRet;
+}
+
+
+/* Reference-Counting object access: add 1 to the current reference count. Must be
+ * called by anyone interested in using a module. -- rgerhards, 20080-03-10
+ */
+static rsRetVal
+Use(const char *srcFile, modInfo_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ pThis->uRefCnt++;
+ dbgprintf("source file %s requested reference for module '%s', reference count now %u\n",
+ srcFile, pThis->pszName, pThis->uRefCnt);
+
+# ifdef DEBUG
+ modUsrAdd(pThis, srcFile);
+# endif
+
+ RETiRet;
+
+}
+
+
+/* Reference-Counting object access: subract one from the current refcount. Must
+ * by called by anyone who no longer needs a module. If count reaches 0, the
+ * module is unloaded. -- rgerhards, 20080-03-10
+ */
+static rsRetVal
+Release(const char *srcFile, modInfo_t **ppThis)
+{
+ DEFiRet;
+ modInfo_t *pThis;
+
+ assert(ppThis != NULL);
+ pThis = *ppThis;
+ assert(pThis != NULL);
+ if(pThis->uRefCnt == 0) {
+ /* oops, we are already at 0? */
+ dbgprintf("internal error: module '%s' already has a refcount of 0 (released by %s)!\n",
+ pThis->pszName, srcFile);
+ } else {
+ --pThis->uRefCnt;
+ dbgprintf("file %s released module '%s', reference count now %u\n",
+ srcFile, pThis->pszName, pThis->uRefCnt);
+# ifdef DEBUG
+ modUsrDel(pThis, srcFile);
+ modUsrPrint(pThis);
+# endif
+ }
+
+ if(pThis->uRefCnt == 0) {
+ /* we have a zero refcount, so we must unload the module */
+ dbgprintf("module '%s' has zero reference count, unloading...\n", pThis->pszName);
+ modUnlinkAndDestroy(&pThis);
+ /* we must NOT do a *ppThis = NULL, because ppThis now points into freed memory!
+ * If in doubt, see obj.c::ReleaseObj() for how we are called.
+ */
+ }
+
+ RETiRet;
+
+}
+
+
+/* exit our class
+ * rgerhards, 2008-03-11
+ */
+BEGINObjClassExit(module, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(module)
+ /* release objects we no longer need */
+ free(pModDir);
+# ifdef DEBUG
+ modUsrPrintAll(); /* debug aid - TODO: integrate with debug.c, at least the settings! */
+# endif
+ENDObjClassExit(module)
+
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(module)
+CODESTARTobjQueryInterface(module)
+ if(pIf->ifVersion != moduleCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->GetNxt = GetNxt;
+ pIf->GetNxtCnfType = GetNxtCnfType;
+ pIf->GetName = modGetName;
+ pIf->GetStateName = modGetStateName;
+ pIf->PrintList = modPrintList;
+ pIf->FindWithCnfName = FindWithCnfName;
+ pIf->UnloadAndDestructAll = modUnloadAndDestructAll;
+ pIf->doModInit = doModInit;
+ pIf->SetModDir = SetModDir;
+ pIf->Load = Load;
+ pIf->Use = Use;
+ pIf->Release = Release;
+finalize_it:
+ENDobjQueryInterface(module)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-03-05
+ */
+BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ uchar *pModPath;
+
+ /* use any module load path specified in the environment */
+ if((pModPath = (uchar*) getenv("RSYSLOG_MODDIR")) != NULL) {
+ SetModDir(pModPath);
+ }
+
+ /* now check if another module path was set via the command line (-M)
+ * if so, that overrides the environment. Please note that we must use
+ * a global setting here because the command line parser can NOT call
+ * into the module object, because it is not initialized at that point. So
+ * instead a global setting is changed and we pick it up as soon as we
+ * initialize -- rgerhards, 2008-04-04
+ */
+ if(glblModPath != NULL) {
+ SetModDir(glblModPath);
+ }
+
+ /* request objects we use */
+ENDObjClassInit(module)
+
+/* vi:set ai:
+ */
diff --git a/runtime/modules.h b/runtime/modules.h
new file mode 100644
index 0000000..f1c940e
--- /dev/null
+++ b/runtime/modules.h
@@ -0,0 +1,213 @@
+/* modules.h
+ *
+ * Definition for build-in and plug-ins module handler. This file is the base
+ * for all dynamically loadable module support. In theory, in v3 all modules
+ * are dynamically loaded, in practice we currently do have a few build-in
+ * once. This may become removed.
+ *
+ * The loader keeps track of what is loaded. For library modules, it is also
+ * used to find objects (libraries) and to obtain the queryInterface function
+ * for them. A reference count is maintened for libraries, so that they are
+ * unloaded only when nobody still accesses them.
+ *
+ * File begun on 2007-07-22 by RGerhards
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef MODULES_H_INCLUDED
+#define MODULES_H_INCLUDED 1
+
+#include "objomsr.h"
+#include "rainerscript.h"
+
+
+/* the following define defines the current version of the module interface.
+ * It can be used by any module which want's to simply prevent version conflicts
+ * and does not intend to do specific old-version emulations.
+ * rgerhards, 2008-03-04
+ * version 3 adds modInfo_t ptr to call of modInit -- rgerhards, 2008-03-10
+ * version 4 removes needUDPSocket OM callback -- rgerhards, 2008-03-22
+ * version 5 changes the way parsing works for input modules. This is
+ * an important change, parseAndSubmitMessage() goes away. Other
+ * module types are not affected. -- rgerhards, 2008-10-09
+ * version 6 introduces scoping support (starting with the output
+ * modules) -- rgerhards, 2010-07-27
+ */
+#define CURR_MOD_IF_VERSION 6
+
+typedef enum eModType_ {
+ eMOD_IN = 0, /* input module */
+ eMOD_OUT = 1, /* output module */
+ eMOD_LIB = 2, /* library module */
+ eMOD_PARSER = 3,/* parser module */
+ eMOD_STRGEN = 4,/* strgen module */
+ eMOD_FUNCTION = 5, /*rscript function module*/
+ eMOD_ANY = 6 /* meta-name for "any type of module" -- to be used in function calls */
+} eModType_t;
+
+
+#ifdef DEBUG
+typedef struct modUsr_s {
+ struct modUsr_s *pNext;
+ char *pszFile;
+} modUsr_t;
+#endif
+
+
+/* how is this module linked? */
+typedef enum eModLinkType_ {
+ eMOD_LINK_STATIC,
+ eMOD_LINK_DYNAMIC_UNLOADED, /* dynalink module, currently not loaded */
+ eMOD_LINK_DYNAMIC_LOADED, /* dynalink module, currently loaded */
+ eMOD_LINK_ALL /* special: all linkage types, e.g. for unload */
+} eModLinkType_t;
+
+/* remember which shared libs we dlopen()-ed */
+struct dlhandle_s {
+ uchar *pszName;
+ void *pModHdlr;
+ struct dlhandle_s *next;
+};
+
+/* should this module be kept linked? */
+typedef enum eModKeepType_ {
+ eMOD_NOKEEP,
+ eMOD_KEEP
+} eModKeepType_t;
+
+struct modInfo_s {
+ struct modInfo_s *pPrev; /* support for creating a double linked module list */
+ struct modInfo_s *pNext; /* support for creating a linked module list */
+ int iIFVers; /* Interface version of module */
+ eModType_t eType; /* type of this module */
+ eModLinkType_t eLinkType;
+ eModKeepType_t eKeepType; /* keep the module dynamically linked on unload */
+ uchar* pszName; /* printable module name, e.g. for dbgprintf */
+ uchar* cnfName; /* name to be used in config statements (e.g. 'name="omusrmsg"') */
+ unsigned uRefCnt; /* reference count for this module; 0 -> may be unloaded */
+ sbool bSetModCnfCalled;/* is setModCnf already called? Needed for built-in modules */
+ /* functions supported by all types of modules */
+ rsRetVal (*modInit)(int, int*, rsRetVal(**)(void*)); /* initialize the module */
+ /* be sure to support version handshake! */
+ rsRetVal (*modQueryEtryPt)(uchar *name, rsRetVal (**EtryPoint)()); /* query entry point addresses */
+ rsRetVal (*isCompatibleWithFeature)(syslogFeature);
+ rsRetVal (*freeInstance)(void*);/* called before termination or module unload */
+ rsRetVal (*dbgPrintInstInfo)(void*);/* called before termination or module unload */
+ rsRetVal (*tryResume)(void*);/* called to see if module actin can be resumed now */
+ rsRetVal (*modExit)(void); /* called before termination or module unload */
+ rsRetVal (*modGetID)(void **); /* get its unique ID from module */
+ rsRetVal (*doHUP)(void *); /* HUP handler, action level */
+ rsRetVal (*doHUPWrkr)(void *); /* HUP handler, wrkr instance level */
+ /* v2 config system specific */
+ rsRetVal (*beginCnfLoad)(void*newCnf, rsconf_t *pConf);
+ rsRetVal (*setModCnf)(struct nvlst *lst);
+ rsRetVal (*endCnfLoad)(void*Cnf);
+ rsRetVal (*checkCnf)(void*Cnf);
+ rsRetVal (*activateCnfPrePrivDrop)(void*Cnf);
+ rsRetVal (*activateCnf)(void*Cnf); /* make provided config the running conf */
+ rsRetVal (*freeCnf)(void*Cnf);
+ /* end v2 config system specific */
+ union {
+ struct {/* data for input modules */
+/* TODO: remove? */rsRetVal (*willRun)(void); /* check if the current config will be able to run*/
+ rsRetVal (*runInput)(thrdInfo_t*); /* function to gather input and submit to queue */
+ rsRetVal (*afterRun)(thrdInfo_t*); /* function to gather input and submit to queue */
+ rsRetVal (*newInpInst)(struct nvlst *lst);
+ int bCanRun; /* cached value of whether willRun() succeeded */
+ } im;
+ struct {/* data for output modules */
+ /* below: perform the configured action
+ */
+ rsRetVal (*beginTransaction)(void*);
+ rsRetVal (*commitTransaction)(void *const, actWrkrIParams_t *const, const unsigned);
+ rsRetVal (*doAction)(void** params, void*pWrkrData);
+ rsRetVal (*endTransaction)(void*);
+ rsRetVal (*parseSelectorAct)(uchar**, void**,omodStringRequest_t**);
+ rsRetVal (*newActInst)(uchar *modName, struct nvlst *lst, void **, omodStringRequest_t **);
+ rsRetVal (*SetShutdownImmdtPtr)(void *pData, void *pPtr);
+ rsRetVal (*createWrkrInstance)(void*ppWrkrData, void*pData);
+ rsRetVal (*freeWrkrInstance)(void*pWrkrData);
+ sbool supportsTX; /* set if the module supports transactions */
+ } om;
+ struct { /* data for library modules */
+ char dummy;
+ } lm;
+ struct { /* data for parser modules */
+ rsRetVal (*newParserInst)(struct nvlst *lst, void *pinst);
+ rsRetVal (*freeParserInst)(void *pinst);
+ rsRetVal (*parse2)(instanceConf_t *const, smsg_t*);
+ rsRetVal (*parse)(smsg_t*);
+ } pm;
+ struct { /* data for strgen modules */
+ rsRetVal (*strgen)(const smsg_t*const, actWrkrIParams_t *const iparam);
+ } sm;
+ struct { /* data for rscript modules */
+ rsRetVal (*getFunctArray)(int *const, struct scriptFunct**);
+ } fm;
+ } mod;
+ void *pModHdlr; /* handler to the dynamic library holding the module */
+# ifdef DEBUG
+ /* we add some home-grown support to track our users (and detect who does not free us). */
+ modUsr_t *pModUsrRoot;
+# endif
+};
+
+
+/* interfaces */
+BEGINinterface(module) /* name must also be changed in ENDinterface macro! */
+ modInfo_t *(*GetNxt)(modInfo_t *pThis);
+ cfgmodules_etry_t *(*GetNxtCnfType)(rsconf_t *cnf, cfgmodules_etry_t *pThis, eModType_t rqtdType);
+ uchar *(*GetName)(modInfo_t *pThis);
+ uchar *(*GetStateName)(modInfo_t *pThis);
+ rsRetVal (*Use)(const char *srcFile, modInfo_t *pThis);
+ /**< must be called before a module is used (ref counting) */
+ rsRetVal (*Release)(const char *srcFile, modInfo_t **ppThis); /**< release a module (ref counting) */
+ void (*PrintList)(void);
+ rsRetVal (*UnloadAndDestructAll)(eModLinkType_t modLinkTypesToUnload);
+ rsRetVal (*doModInit)(rsRetVal (*modInit)(), uchar *name, void *pModHdlr, modInfo_t **pNew);
+ rsRetVal (*Load)(uchar *name, sbool bConfLoad, struct nvlst *lst);
+ rsRetVal (*SetModDir)(uchar *name);
+ modInfo_t *(*FindWithCnfName)(rsconf_t *cnf, uchar *name, eModType_t rqtdType); /* added v3, 2011-07-19 */
+ENDinterface(module)
+#define moduleCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */
+/* Changes:
+ * v2
+ * - added param bCondLoad to Load call - 2011-04-27
+ * - removed GetNxtType, added GetNxtCnfType - 2011-04-27
+ * v3 (see above)
+ * v4
+ * - added third parameter to Load() - 2012-06-20
+ */
+
+/* prototypes */
+PROTOTYPEObj(module);
+/* in v6, we go back to in-core static link for core objects, at least those
+ * that are not called from plugins.
+ * ... and we need to know that none of the module functions are called from plugins!
+ * rgerhards, 2012-09-24
+ */
+rsRetVal modulesProcessCnf(struct cnfobj *o);
+uchar *modGetName(modInfo_t *pThis);
+rsRetVal ATTR_NONNULL(1) addModToCnfList(cfgmodules_etry_t **pNew, cfgmodules_etry_t *pLast);
+rsRetVal readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast);
+void modDoHUP(void);
+
+#endif /* #ifndef MODULES_H_INCLUDED */
diff --git a/runtime/msg.c b/runtime/msg.c
new file mode 100644
index 0000000..b35bc1d
--- /dev/null
+++ b/runtime/msg.c
@@ -0,0 +1,5476 @@
+/* msg.c
+ * The msg object. Implementation of all msg-related functions
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#define SYSLOG_NAMES
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYSINFO_UPTIME
+#include <sys/sysinfo.h>
+#endif
+#include <netdb.h>
+#include <libestr.h>
+#include <json.h>
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
+#ifdef USE_LIBUUID
+# include <uuid/uuid.h>
+#endif
+#include <errno.h>
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "template.h"
+#include "msg.h"
+#include "datetime.h"
+#include "glbl.h"
+#include "regexp.h"
+#include "atomic.h"
+#include "unicode-helper.h"
+#include "ruleset.h"
+#include "prop.h"
+#include "net.h"
+#include "var.h"
+#include "rsconf.h"
+#include "parserif.h"
+#include "errmsg.h"
+
+#define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */
+
+/* inlines */
+extern void msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri);
+
+/* TODO: move the global variable root to the config object - had no time to to it
+ * right now before vacation -- rgerhards, 2013-07-22
+ */
+static pthread_mutex_t glblVars_lock;
+struct json_object *global_var_root = NULL;
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(regexp)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+DEFobjCurrIf(var)
+
+static const char *one_digit[10] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+static const char *two_digits[100] = {
+ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
+ "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
+ "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
+ "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
+ "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
+ "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
+ "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
+ "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
+ "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
+ "90", "91", "92", "93", "94", "95", "96", "97", "98", "99"};
+
+static const char *wdayNames[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+
+/* Table of days in a year, needed for getYearDay */
+static const char *daysInYear[366] = {
+ "001", "002", "003", "004", "005", "006", "007", "008", "009",
+ "010", "011", "012", "013", "014", "015", "016", "017", "018", "019",
+ "020", "021", "022", "023", "024", "025", "026", "027", "028", "029",
+ "030", "031", "032", "033", "034", "035", "036", "037", "038", "039",
+ "040", "041", "042", "043", "044", "045", "046", "047", "048", "049",
+ "050", "051", "052", "053", "054", "055", "056", "057", "058", "059",
+ "060", "061", "062", "063", "064", "065", "066", "067", "068", "069",
+ "070", "071", "072", "073", "074", "075", "076", "077", "078", "079",
+ "080", "081", "082", "083", "084", "085", "086", "087", "088", "089",
+ "090", "091", "092", "093", "094", "095", "096", "097", "098", "099",
+ "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
+ "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
+ "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
+ "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
+ "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
+ "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
+ "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
+ "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
+ "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
+ "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
+ "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
+ "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
+ "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
+ "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
+ "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
+ "250", "251", "252", "253", "254", "255", "256", "257", "258", "259",
+ "260", "261", "262", "263", "264", "265", "266", "267", "268", "269",
+ "270", "271", "272", "273", "274", "275", "276", "277", "278", "279",
+ "280", "281", "282", "283", "284", "285", "286", "287", "288", "289",
+ "290", "291", "292", "293", "294", "295", "296", "297", "298", "299",
+ "300", "301", "302", "303", "304", "305", "306", "307", "308", "309",
+ "310", "311", "312", "313", "314", "315", "316", "317", "318", "319",
+ "320", "321", "322", "323", "324", "325", "326", "327", "328", "329",
+ "330", "331", "332", "333", "334", "335", "336", "337", "338", "339",
+ "340", "341", "342", "343", "344", "345", "346", "347", "348", "349",
+ "350", "351", "352", "353", "354", "355", "356", "357", "358", "359",
+ "360", "361", "362", "363", "364", "365", "366"};
+
+/* The following is a table of supported years. This permits us
+ * to avoid dynamic memory allocation. Note that the time-based
+ * algos need to be upgraded after the year 2099 in any case.
+ * Quite honestly, I don't expect that this is a real problem ;)
+ */
+static const char *years[] = {
+ "1967", "1968", "1969", "1970", "1971", "1972", "1973", "1974",
+ "1975", "1976", "1977", "1978", "1979", "1980", "1981", "1982",
+ "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990",
+ "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998",
+ "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006",
+ "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014",
+ "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022",
+ "2023", "2024", "2025", "2026", "2027", "2028", "2029", "2030",
+ "2031", "2032", "2033", "2034", "2035", "2036", "2037", "2038",
+ "2039", "2040", "2041", "2042", "2043", "2044", "2045", "2046",
+ "2047", "2048", "2049", "2050", "2051", "2052", "2053", "2054",
+ "2055", "2056", "2057", "2058", "2059", "2060", "2061", "2062",
+ "2063", "2064", "2065", "2066", "2067", "2068", "2069", "2070",
+ "2071", "2072", "2073", "2074", "2075", "2076", "2077", "2078",
+ "2079", "2080", "2081", "2082", "2083", "2084", "2085", "2086",
+ "2087", "2088", "2089", "2090", "2091", "2092", "2093", "2094",
+ "2095", "2096", "2097", "2098", "2099" };
+
+static struct {
+ uchar *pszName;
+} syslog_pri_names[200] = {
+ { UCHAR_CONSTANT("0") },
+ { UCHAR_CONSTANT("1") },
+ { UCHAR_CONSTANT("2") },
+ { UCHAR_CONSTANT("3") },
+ { UCHAR_CONSTANT("4") },
+ { UCHAR_CONSTANT("5") },
+ { UCHAR_CONSTANT("6") },
+ { UCHAR_CONSTANT("7") },
+ { UCHAR_CONSTANT("8") },
+ { UCHAR_CONSTANT("9") },
+ { UCHAR_CONSTANT("10") },
+ { UCHAR_CONSTANT("11") },
+ { UCHAR_CONSTANT("12") },
+ { UCHAR_CONSTANT("13") },
+ { UCHAR_CONSTANT("14") },
+ { UCHAR_CONSTANT("15") },
+ { UCHAR_CONSTANT("16") },
+ { UCHAR_CONSTANT("17") },
+ { UCHAR_CONSTANT("18") },
+ { UCHAR_CONSTANT("19") },
+ { UCHAR_CONSTANT("20") },
+ { UCHAR_CONSTANT("21") },
+ { UCHAR_CONSTANT("22") },
+ { UCHAR_CONSTANT("23") },
+ { UCHAR_CONSTANT("24") },
+ { UCHAR_CONSTANT("25") },
+ { UCHAR_CONSTANT("26") },
+ { UCHAR_CONSTANT("27") },
+ { UCHAR_CONSTANT("28") },
+ { UCHAR_CONSTANT("29") },
+ { UCHAR_CONSTANT("30") },
+ { UCHAR_CONSTANT("31") },
+ { UCHAR_CONSTANT("32") },
+ { UCHAR_CONSTANT("33") },
+ { UCHAR_CONSTANT("34") },
+ { UCHAR_CONSTANT("35") },
+ { UCHAR_CONSTANT("36") },
+ { UCHAR_CONSTANT("37") },
+ { UCHAR_CONSTANT("38") },
+ { UCHAR_CONSTANT("39") },
+ { UCHAR_CONSTANT("40") },
+ { UCHAR_CONSTANT("41") },
+ { UCHAR_CONSTANT("42") },
+ { UCHAR_CONSTANT("43") },
+ { UCHAR_CONSTANT("44") },
+ { UCHAR_CONSTANT("45") },
+ { UCHAR_CONSTANT("46") },
+ { UCHAR_CONSTANT("47") },
+ { UCHAR_CONSTANT("48") },
+ { UCHAR_CONSTANT("49") },
+ { UCHAR_CONSTANT("50") },
+ { UCHAR_CONSTANT("51") },
+ { UCHAR_CONSTANT("52") },
+ { UCHAR_CONSTANT("53") },
+ { UCHAR_CONSTANT("54") },
+ { UCHAR_CONSTANT("55") },
+ { UCHAR_CONSTANT("56") },
+ { UCHAR_CONSTANT("57") },
+ { UCHAR_CONSTANT("58") },
+ { UCHAR_CONSTANT("59") },
+ { UCHAR_CONSTANT("60") },
+ { UCHAR_CONSTANT("61") },
+ { UCHAR_CONSTANT("62") },
+ { UCHAR_CONSTANT("63") },
+ { UCHAR_CONSTANT("64") },
+ { UCHAR_CONSTANT("65") },
+ { UCHAR_CONSTANT("66") },
+ { UCHAR_CONSTANT("67") },
+ { UCHAR_CONSTANT("68") },
+ { UCHAR_CONSTANT("69") },
+ { UCHAR_CONSTANT("70") },
+ { UCHAR_CONSTANT("71") },
+ { UCHAR_CONSTANT("72") },
+ { UCHAR_CONSTANT("73") },
+ { UCHAR_CONSTANT("74") },
+ { UCHAR_CONSTANT("75") },
+ { UCHAR_CONSTANT("76") },
+ { UCHAR_CONSTANT("77") },
+ { UCHAR_CONSTANT("78") },
+ { UCHAR_CONSTANT("79") },
+ { UCHAR_CONSTANT("80") },
+ { UCHAR_CONSTANT("81") },
+ { UCHAR_CONSTANT("82") },
+ { UCHAR_CONSTANT("83") },
+ { UCHAR_CONSTANT("84") },
+ { UCHAR_CONSTANT("85") },
+ { UCHAR_CONSTANT("86") },
+ { UCHAR_CONSTANT("87") },
+ { UCHAR_CONSTANT("88") },
+ { UCHAR_CONSTANT("89") },
+ { UCHAR_CONSTANT("90") },
+ { UCHAR_CONSTANT("91") },
+ { UCHAR_CONSTANT("92") },
+ { UCHAR_CONSTANT("93") },
+ { UCHAR_CONSTANT("94") },
+ { UCHAR_CONSTANT("95") },
+ { UCHAR_CONSTANT("96") },
+ { UCHAR_CONSTANT("97") },
+ { UCHAR_CONSTANT("98") },
+ { UCHAR_CONSTANT("99") },
+ { UCHAR_CONSTANT("100") },
+ { UCHAR_CONSTANT("101") },
+ { UCHAR_CONSTANT("102") },
+ { UCHAR_CONSTANT("103") },
+ { UCHAR_CONSTANT("104") },
+ { UCHAR_CONSTANT("105") },
+ { UCHAR_CONSTANT("106") },
+ { UCHAR_CONSTANT("107") },
+ { UCHAR_CONSTANT("108") },
+ { UCHAR_CONSTANT("109") },
+ { UCHAR_CONSTANT("110") },
+ { UCHAR_CONSTANT("111") },
+ { UCHAR_CONSTANT("112") },
+ { UCHAR_CONSTANT("113") },
+ { UCHAR_CONSTANT("114") },
+ { UCHAR_CONSTANT("115") },
+ { UCHAR_CONSTANT("116") },
+ { UCHAR_CONSTANT("117") },
+ { UCHAR_CONSTANT("118") },
+ { UCHAR_CONSTANT("119") },
+ { UCHAR_CONSTANT("120") },
+ { UCHAR_CONSTANT("121") },
+ { UCHAR_CONSTANT("122") },
+ { UCHAR_CONSTANT("123") },
+ { UCHAR_CONSTANT("124") },
+ { UCHAR_CONSTANT("125") },
+ { UCHAR_CONSTANT("126") },
+ { UCHAR_CONSTANT("127") },
+ { UCHAR_CONSTANT("128") },
+ { UCHAR_CONSTANT("129") },
+ { UCHAR_CONSTANT("130") },
+ { UCHAR_CONSTANT("131") },
+ { UCHAR_CONSTANT("132") },
+ { UCHAR_CONSTANT("133") },
+ { UCHAR_CONSTANT("134") },
+ { UCHAR_CONSTANT("135") },
+ { UCHAR_CONSTANT("136") },
+ { UCHAR_CONSTANT("137") },
+ { UCHAR_CONSTANT("138") },
+ { UCHAR_CONSTANT("139") },
+ { UCHAR_CONSTANT("140") },
+ { UCHAR_CONSTANT("141") },
+ { UCHAR_CONSTANT("142") },
+ { UCHAR_CONSTANT("143") },
+ { UCHAR_CONSTANT("144") },
+ { UCHAR_CONSTANT("145") },
+ { UCHAR_CONSTANT("146") },
+ { UCHAR_CONSTANT("147") },
+ { UCHAR_CONSTANT("148") },
+ { UCHAR_CONSTANT("149") },
+ { UCHAR_CONSTANT("150") },
+ { UCHAR_CONSTANT("151") },
+ { UCHAR_CONSTANT("152") },
+ { UCHAR_CONSTANT("153") },
+ { UCHAR_CONSTANT("154") },
+ { UCHAR_CONSTANT("155") },
+ { UCHAR_CONSTANT("156") },
+ { UCHAR_CONSTANT("157") },
+ { UCHAR_CONSTANT("158") },
+ { UCHAR_CONSTANT("159") },
+ { UCHAR_CONSTANT("160") },
+ { UCHAR_CONSTANT("161") },
+ { UCHAR_CONSTANT("162") },
+ { UCHAR_CONSTANT("163") },
+ { UCHAR_CONSTANT("164") },
+ { UCHAR_CONSTANT("165") },
+ { UCHAR_CONSTANT("166") },
+ { UCHAR_CONSTANT("167") },
+ { UCHAR_CONSTANT("168") },
+ { UCHAR_CONSTANT("169") },
+ { UCHAR_CONSTANT("170") },
+ { UCHAR_CONSTANT("171") },
+ { UCHAR_CONSTANT("172") },
+ { UCHAR_CONSTANT("173") },
+ { UCHAR_CONSTANT("174") },
+ { UCHAR_CONSTANT("175") },
+ { UCHAR_CONSTANT("176") },
+ { UCHAR_CONSTANT("177") },
+ { UCHAR_CONSTANT("178") },
+ { UCHAR_CONSTANT("179") },
+ { UCHAR_CONSTANT("180") },
+ { UCHAR_CONSTANT("181") },
+ { UCHAR_CONSTANT("182") },
+ { UCHAR_CONSTANT("183") },
+ { UCHAR_CONSTANT("184") },
+ { UCHAR_CONSTANT("185") },
+ { UCHAR_CONSTANT("186") },
+ { UCHAR_CONSTANT("187") },
+ { UCHAR_CONSTANT("188") },
+ { UCHAR_CONSTANT("189") },
+ { UCHAR_CONSTANT("190") },
+ { UCHAR_CONSTANT("191") },
+ { UCHAR_CONSTANT("192") },
+ { UCHAR_CONSTANT("193") },
+ { UCHAR_CONSTANT("194") },
+ { UCHAR_CONSTANT("195") },
+ { UCHAR_CONSTANT("196") },
+ { UCHAR_CONSTANT("197") },
+ { UCHAR_CONSTANT("198") },
+ { UCHAR_CONSTANT("199") }
+ };
+static char hexdigit[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+#if defined(_AIX)
+/* AIXPORT : replace facility names with aso and caa only for AIX */
+static const char *syslog_fac_names[LOG_NFACILITIES] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr",
+ "news", "uucp", "cron", "authpriv", "ftp", "aso", "audit",
+ "alert", "caa", "local0", "local1", "local2", "local3",
+ "local4", "local5", "local6", "local7", "invld" };
+/* length of the facility names string (for optimizatiions) */
+static short len_syslog_fac_names[LOG_NFACILITIES] = { 4, 4, 4, 6, 4, 6, 3,
+ 4, 4, 4, 8, 3, 3, 5,
+ 5, 3, 6, 6, 6, 6,
+ 6, 6, 6, 6, 5 };
+
+#else
+/*syslog facility names (as of RFC5424) */
+static const char *syslog_fac_names[LOG_NFACILITIES] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr",
+ "news", "uucp", "cron", "authpriv", "ftp", "ntp", "audit",
+ "alert", "clock", "local0", "local1", "local2", "local3",
+ "local4", "local5", "local6", "local7", "invld" };
+/* length of the facility names string (for optimizatiions) */
+static short len_syslog_fac_names[LOG_NFACILITIES] = { 4, 4, 4, 6, 4, 6, 3,
+ 4, 4, 4, 8, 3, 3, 5,
+ 5, 5, 6, 6, 6, 6,
+ 6, 6, 6, 6, 5 };
+#endif
+
+/* table of severity names (in numerical order)*/
+static const char *syslog_severity_names[8] = { "emerg", "alert", "crit", "err", "warning", "notice", "info",
+ "debug" };
+static short len_syslog_severity_names[8] = { 5, 5, 4, 3, 7, 6, 4, 5 };
+
+/* numerical values as string - this is the most efficient approach to convert severity
+ * and facility values to a numerical string... -- rgerhars, 2009-06-17
+ */
+
+static const char *syslog_number_names[LOG_NFACILITIES] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "10", "11", "12", "13", "14",
+ "15", "16", "17", "18", "19", "20", "21", "22", "23", "24" };
+
+/* global variables */
+#if defined(HAVE_MALLOC_TRIM) && !defined(HAVE_ATOMIC_BUILTINS)
+static pthread_mutex_t mutTrimCtr; /* mutex to handle malloc trim */
+#endif
+
+/* some forward declarations */
+static int getAPPNAMELen(smsg_t * const pM, sbool bLockMutex);
+static rsRetVal jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf,
+ struct json_object **parent, int bCreate);
+static uchar * jsonPathGetLeaf(uchar *name, int lenName);
+struct json_object *jsonDeepCopy(struct json_object *src);
+static json_bool jsonVarExtract(struct json_object* root, const char *key, struct json_object **value);
+void getRawMsgAfterPRI(smsg_t * const pM, uchar **pBuf, int *piLen);
+
+
+/* the locking and unlocking implementations: */
+static inline void
+MsgLock(smsg_t *pThis)
+{
+ #if DEV_DEBUG == 1
+ dbgprintf("MsgLock(0x%lx)\n", (unsigned long) pThis);
+ #endif
+ pthread_mutex_lock(&pThis->mut);
+}
+static inline void
+MsgUnlock(smsg_t *pThis)
+{
+ #if DEV_DEBUG == 1
+ dbgprintf("MsgUnlock(0x%lx)\n", (unsigned long) pThis);
+ #endif
+ pthread_mutex_unlock(&pThis->mut);
+}
+
+
+/* set RcvFromIP name in msg object WITHOUT calling AddRef.
+ * rgerhards, 2013-01-22
+ */
+static inline void
+MsgSetRcvFromIPWithoutAddRef(smsg_t *pThis, prop_t *new)
+{
+ if(pThis->pRcvFromIP != NULL)
+ prop.Destruct(&pThis->pRcvFromIP);
+ pThis->pRcvFromIP = new;
+}
+
+
+/* set RcvFrom name in msg object WITHOUT calling AddRef.
+ * rgerhards, 2013-01-22
+ */
+static void MsgSetRcvFromWithoutAddRef(smsg_t *pThis, prop_t *new)
+{
+ assert(pThis != NULL);
+
+ if(pThis->msgFlags & NEEDS_DNSRESOL) {
+ if(pThis->rcvFrom.pfrominet != NULL)
+ free(pThis->rcvFrom.pfrominet);
+ pThis->msgFlags &= ~NEEDS_DNSRESOL;
+ } else {
+ if(pThis->rcvFrom.pRcvFrom != NULL)
+ prop.Destruct(&pThis->rcvFrom.pRcvFrom);
+ }
+ pThis->rcvFrom.pRcvFrom = new;
+}
+
+
+/* rgerhards 2012-04-18: set associated ruleset (by ruleset name)
+ * pRuleset pointer inside msg is updated. If ruleset cannot be found,
+ * no update is done and an error message emitted.
+ */
+static void ATTR_NONNULL()
+MsgSetRulesetByName(smsg_t * const pMsg, cstr_t *const rulesetName)
+{
+ uchar *const rs_name = rsCStrGetSzStrNoNULL(rulesetName);
+ const rsRetVal localRet =
+ rulesetGetRuleset(runConf, &(pMsg->pRuleset), rs_name);
+
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "msg: ruleset '%s' could not be found and could not "
+ "be assigned to message object. This possibly leads to the message "
+ "being processed incorrectly. We cannot do anything against this, but "
+ "wanted to let you know.", rs_name);
+ }
+}
+
+/* do a DNS reverse resolution, if not already done, reflect status
+ * rgerhards, 2009-11-16
+ */
+static rsRetVal
+resolveDNS(smsg_t * const pMsg) {
+ rsRetVal localRet;
+ prop_t *propFromHost = NULL;
+ prop_t *ip;
+ prop_t *localName;
+ DEFiRet;
+
+ MsgLock(pMsg);
+ CHKiRet(objUse(net, CORE_COMPONENT));
+ if(pMsg->msgFlags & NEEDS_DNSRESOL) {
+ if (pMsg->msgFlags & PRESERVE_CASE) {
+ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, NULL, &localName, &ip);
+ } else {
+ localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip);
+ }
+ if(localRet == RS_RET_OK) {
+ /* we pass down the props, so no need for AddRef */
+ MsgSetRcvFromWithoutAddRef(pMsg, localName);
+ MsgSetRcvFromIPWithoutAddRef(pMsg, ip);
+ }
+ }
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* best we can do: remove property */
+ MsgSetRcvFromStr(pMsg, UCHAR_CONSTANT(""), 0, &propFromHost);
+ prop.Destruct(&propFromHost);
+ }
+ MsgUnlock(pMsg);
+ if(propFromHost != NULL)
+ prop.Destruct(&propFromHost);
+ RETiRet;
+}
+
+
+void
+getInputName(const smsg_t * const pM, uchar **ppsz, int *const plen)
+{
+ if(pM == NULL || pM->pInputName == NULL) {
+ *ppsz = UCHAR_CONSTANT("");
+ *plen = 0;
+ } else {
+ prop.GetString(pM->pInputName, ppsz, plen);
+ }
+}
+
+
+static uchar*
+getRcvFromIP(smsg_t * const pM)
+{
+ uchar *psz;
+ int len;
+ if(pM == NULL) {
+ psz = UCHAR_CONSTANT("");
+ } else {
+ resolveDNS(pM); /* make sure we have a resolved entry */
+ if(pM->pRcvFromIP == NULL)
+ psz = UCHAR_CONSTANT("");
+ else
+ prop.GetString(pM->pRcvFromIP, &psz, &len);
+ }
+ return psz;
+}
+
+
+/* map a property name (string) to a property ID */
+rsRetVal
+propNameToID(const uchar *const pName, propid_t *const pPropID)
+{
+ DEFiRet;
+
+ /* sometimes there are aliases to the original MonitoWare
+ * property names. These come after || in the ifs below. */
+ if(!strcasecmp((char*) pName, "msg")) {
+ *pPropID = PROP_MSG;
+ } else if(!strcasecmp((char*) pName, "timestamp")
+ || !strcasecmp((char*) pName, "timereported")) {
+ *pPropID = PROP_TIMESTAMP;
+ } else if(!strcasecmp((char*) pName, "hostname") || !strcasecmp((char*) pName, "source")) {
+ *pPropID = PROP_HOSTNAME;
+ } else if(!strcasecmp((char*) pName, "syslogtag")) {
+ *pPropID = PROP_SYSLOGTAG;
+ } else if(!strcasecmp((char*) pName, "rawmsg")) {
+ *pPropID = PROP_RAWMSG;
+ } else if(!strcasecmp((char*) pName, "rawmsg-after-pri")) {
+ *pPropID = PROP_RAWMSG_AFTER_PRI;
+ } else if(!strcasecmp((char*) pName, "inputname")) {
+ *pPropID = PROP_INPUTNAME;
+ } else if(!strcasecmp((char*) pName, "fromhost")) {
+ *pPropID = PROP_FROMHOST;
+ } else if(!strcasecmp((char*) pName, "fromhost-ip")) {
+ *pPropID = PROP_FROMHOST_IP;
+ } else if(!strcasecmp((char*) pName, "pri")) {
+ *pPropID = PROP_PRI;
+ } else if(!strcasecmp((char*) pName, "pri-text")) {
+ *pPropID = PROP_PRI_TEXT;
+ } else if(!strcasecmp((char*) pName, "iut")) {
+ *pPropID = PROP_IUT;
+ } else if(!strcasecmp((char*) pName, "syslogfacility")) {
+ *pPropID = PROP_SYSLOGFACILITY;
+ } else if(!strcasecmp((char*) pName, "syslogfacility-text")) {
+ *pPropID = PROP_SYSLOGFACILITY_TEXT;
+ } else if(!strcasecmp((char*) pName, "syslogseverity") || !strcasecmp((char*) pName, "syslogpriority")) {
+ *pPropID = PROP_SYSLOGSEVERITY;
+ } else if(!strcasecmp((char*) pName, "syslogseverity-text") ||
+ !strcasecmp((char*) pName, "syslogpriority-text")) {
+ *pPropID = PROP_SYSLOGSEVERITY_TEXT;
+ } else if(!strcasecmp((char*) pName, "timegenerated")) {
+ *pPropID = PROP_TIMEGENERATED;
+ } else if(!strcasecmp((char*) pName, "programname")) {
+ *pPropID = PROP_PROGRAMNAME;
+ } else if(!strcasecmp((char*) pName, "protocol-version")) {
+ *pPropID = PROP_PROTOCOL_VERSION;
+ } else if(!strcasecmp((char*) pName, "structured-data")) {
+ *pPropID = PROP_STRUCTURED_DATA;
+ } else if(!strcasecmp((char*) pName, "app-name")) {
+ *pPropID = PROP_APP_NAME;
+ } else if(!strcasecmp((char*) pName, "procid")) {
+ *pPropID = PROP_PROCID;
+ } else if(!strcasecmp((char*) pName, "msgid")) {
+ *pPropID = PROP_MSGID;
+ } else if(!strcasecmp((char*) pName, "jsonmesg")) {
+ *pPropID = PROP_JSONMESG;
+ } else if(!strcasecmp((char*) pName, "parsesuccess")) {
+ *pPropID = PROP_PARSESUCCESS;
+#ifdef USE_LIBUUID
+ } else if(!strcasecmp((char*) pName, "uuid")) {
+ *pPropID = PROP_UUID;
+#endif
+ /* here start system properties (those, that do not relate to the message itself */
+ } else if(!strcasecmp((char*) pName, "$NOW")) {
+ *pPropID = PROP_SYS_NOW;
+ } else if(!strcasecmp((char*) pName, "$YEAR")) {
+ *pPropID = PROP_SYS_YEAR;
+ } else if(!strcasecmp((char*) pName, "$MONTH")) {
+ *pPropID = PROP_SYS_MONTH;
+ } else if(!strcasecmp((char*) pName, "$DAY")) {
+ *pPropID = PROP_SYS_DAY;
+ } else if(!strcasecmp((char*) pName, "$HOUR")) {
+ *pPropID = PROP_SYS_HOUR;
+ } else if(!strcasecmp((char*) pName, "$HHOUR")) {
+ *pPropID = PROP_SYS_HHOUR;
+ } else if(!strcasecmp((char*) pName, "$QHOUR")) {
+ *pPropID = PROP_SYS_QHOUR;
+ } else if(!strcasecmp((char*) pName, "$MINUTE")) {
+ *pPropID = PROP_SYS_MINUTE;
+ } else if(!strcasecmp((char*) pName, "$WDAY")) {
+ *pPropID = PROP_SYS_WDAY;
+ } else if(!strcasecmp((char*) pName, "$now-utc")) {
+ *pPropID = PROP_SYS_NOW_UTC;
+ } else if(!strcasecmp((char*) pName, "$year-utc")) {
+ *pPropID = PROP_SYS_YEAR_UTC;
+ } else if(!strcasecmp((char*) pName, "$month-utc")) {
+ *pPropID = PROP_SYS_MONTH_UTC;
+ } else if(!strcasecmp((char*) pName, "$day-utc")) {
+ *pPropID = PROP_SYS_DAY_UTC;
+ } else if(!strcasecmp((char*) pName, "$hour-utc")) {
+ *pPropID = PROP_SYS_HOUR_UTC;
+ } else if(!strcasecmp((char*) pName, "$hhour-utc")) {
+ *pPropID = PROP_SYS_HHOUR_UTC;
+ } else if(!strcasecmp((char*) pName, "$qhour-utc")) {
+ *pPropID = PROP_SYS_QHOUR_UTC;
+ } else if(!strcasecmp((char*) pName, "$minute-utc")) {
+ *pPropID = PROP_SYS_MINUTE_UTC;
+ } else if(!strcasecmp((char*) pName, "$wday-utc")) {
+ *pPropID = PROP_SYS_WDAY_UTC;
+ } else if(!strcasecmp((char*) pName, "$now-unixtimestamp")) {
+ *pPropID = PROP_SYS_NOW_UXTIMESTAMP;
+ } else if(!strcasecmp((char*) pName, "$MYHOSTNAME")) {
+ *pPropID = PROP_SYS_MYHOSTNAME;
+ } else if(!strcasecmp((char*) pName, "$!all-json")) {
+ *pPropID = PROP_CEE_ALL_JSON;
+ } else if(!strcasecmp((char*) pName, "$!all-json-plain")) {
+ *pPropID = PROP_CEE_ALL_JSON_PLAIN;
+ } else if(!strcasecmp((char*) pName, "$BOM")) {
+ *pPropID = PROP_SYS_BOM;
+ } else if(!strcasecmp((char*) pName, "$UPTIME")) {
+ *pPropID = PROP_SYS_UPTIME;
+ } else if(!strncmp((char*) pName, "$!", 2) || pName[0] == '!') {
+ *pPropID = PROP_CEE;
+ } else if(!strncmp((char*) pName, "$.", 2) || pName[0] == '.') {
+ *pPropID = PROP_LOCAL_VAR;
+ } else if(!strncmp((char*) pName, "$/", 2) || pName[0] == '/') {
+ *pPropID = PROP_GLOBAL_VAR;
+ } else {
+ DBGPRINTF("PROP_INVALID for name '%s'\n", pName);
+ *pPropID = PROP_INVALID;
+ iRet = RS_RET_VAR_NOT_FOUND;
+ }
+
+ RETiRet;
+}
+
+
+/* map a property ID to a name string (useful for displaying) */
+uchar *propIDToName(propid_t propID)
+{
+ switch(propID) {
+ case PROP_MSG:
+ return UCHAR_CONSTANT("msg");
+ case PROP_TIMESTAMP:
+ return UCHAR_CONSTANT("timestamp");
+ case PROP_HOSTNAME:
+ return UCHAR_CONSTANT("hostname");
+ case PROP_SYSLOGTAG:
+ return UCHAR_CONSTANT("syslogtag");
+ case PROP_RAWMSG:
+ return UCHAR_CONSTANT("rawmsg");
+ case PROP_RAWMSG_AFTER_PRI:
+ return UCHAR_CONSTANT("rawmsg-after-pri");
+ case PROP_INPUTNAME:
+ return UCHAR_CONSTANT("inputname");
+ case PROP_FROMHOST:
+ return UCHAR_CONSTANT("fromhost");
+ case PROP_FROMHOST_IP:
+ return UCHAR_CONSTANT("fromhost-ip");
+ case PROP_PRI:
+ return UCHAR_CONSTANT("pri");
+ case PROP_PRI_TEXT:
+ return UCHAR_CONSTANT("pri-text");
+ case PROP_IUT:
+ return UCHAR_CONSTANT("iut");
+ case PROP_SYSLOGFACILITY:
+ return UCHAR_CONSTANT("syslogfacility");
+ case PROP_SYSLOGFACILITY_TEXT:
+ return UCHAR_CONSTANT("syslogfacility-text");
+ case PROP_SYSLOGSEVERITY:
+ return UCHAR_CONSTANT("syslogseverity");
+ case PROP_SYSLOGSEVERITY_TEXT:
+ return UCHAR_CONSTANT("syslogseverity-text");
+ case PROP_TIMEGENERATED:
+ return UCHAR_CONSTANT("timegenerated");
+ case PROP_PROGRAMNAME:
+ return UCHAR_CONSTANT("programname");
+ case PROP_PROTOCOL_VERSION:
+ return UCHAR_CONSTANT("protocol-version");
+ case PROP_STRUCTURED_DATA:
+ return UCHAR_CONSTANT("structured-data");
+ case PROP_APP_NAME:
+ return UCHAR_CONSTANT("app-name");
+ case PROP_PROCID:
+ return UCHAR_CONSTANT("procid");
+ case PROP_MSGID:
+ return UCHAR_CONSTANT("msgid");
+ case PROP_JSONMESG:
+ return UCHAR_CONSTANT("jsonmesg");
+ case PROP_PARSESUCCESS:
+ return UCHAR_CONSTANT("parsesuccess");
+#ifdef USE_LIBUUID
+ case PROP_UUID:
+ return UCHAR_CONSTANT("uuid");
+#endif
+ case PROP_SYS_NOW:
+ return UCHAR_CONSTANT("$NOW");
+ case PROP_SYS_YEAR:
+ return UCHAR_CONSTANT("$YEAR");
+ case PROP_SYS_MONTH:
+ return UCHAR_CONSTANT("$MONTH");
+ case PROP_SYS_DAY:
+ return UCHAR_CONSTANT("$DAY");
+ case PROP_SYS_HOUR:
+ return UCHAR_CONSTANT("$HOUR");
+ case PROP_SYS_HHOUR:
+ return UCHAR_CONSTANT("$HHOUR");
+ case PROP_SYS_QHOUR:
+ return UCHAR_CONSTANT("$QHOUR");
+ case PROP_SYS_MINUTE:
+ return UCHAR_CONSTANT("$MINUTE");
+ case PROP_SYS_NOW_UTC:
+ return UCHAR_CONSTANT("$NOW-UTC");
+ case PROP_SYS_YEAR_UTC:
+ return UCHAR_CONSTANT("$YEAR-UTC");
+ case PROP_SYS_MONTH_UTC:
+ return UCHAR_CONSTANT("$MONTH-UTC");
+ case PROP_SYS_DAY_UTC:
+ return UCHAR_CONSTANT("$DAY-UTC");
+ case PROP_SYS_HOUR_UTC:
+ return UCHAR_CONSTANT("$HOUR-UTC");
+ case PROP_SYS_HHOUR_UTC:
+ return UCHAR_CONSTANT("$HHOUR-UTC");
+ case PROP_SYS_QHOUR_UTC:
+ return UCHAR_CONSTANT("$QHOUR-UTC");
+ case PROP_SYS_MINUTE_UTC:
+ return UCHAR_CONSTANT("$MINUTE-UTC");
+ case PROP_SYS_WDAY:
+ return UCHAR_CONSTANT("$WDAY");
+ case PROP_SYS_WDAY_UTC:
+ return UCHAR_CONSTANT("$WDAY-UTC");
+ case PROP_SYS_NOW_UXTIMESTAMP:
+ return UCHAR_CONSTANT("$NOW-UNIXTIMESTAMP");
+ case PROP_SYS_MYHOSTNAME:
+ return UCHAR_CONSTANT("$MYHOSTNAME");
+ case PROP_CEE_ALL_JSON:
+ return UCHAR_CONSTANT("$!all-json");
+ case PROP_CEE_ALL_JSON_PLAIN:
+ return UCHAR_CONSTANT("$!all-json-plain");
+ case PROP_SYS_BOM:
+ return UCHAR_CONSTANT("$BOM");
+ case PROP_SYS_UPTIME:
+ return UCHAR_CONSTANT("$UPTIME");
+ case PROP_CEE:
+ return UCHAR_CONSTANT("*CEE-based property*");
+ case PROP_LOCAL_VAR:
+ return UCHAR_CONSTANT("*LOCAL_VARIABLE*");
+ case PROP_GLOBAL_VAR:
+ return UCHAR_CONSTANT("*GLOBAL_VARIABLE*");
+ default:
+ return UCHAR_CONSTANT("*invalid property id*");
+ }
+}
+
+
+/* This is common code for all Constructors. It is defined in an
+ * inline'able function so that we can save a function call in the
+ * actual constructors (otherwise, the msgConstruct would need
+ * to call msgConstructWithTime(), which would require a
+ * function call). Now, both can use this inline function. This
+ * enables us to be optimal, but still have the code just once.
+ * the new object or NULL if no such object could be allocated.
+ * An object constructed via this function should only be destroyed
+ * via "msgDestruct()". This constructor does not query system time
+ * itself but rather uses a user-supplied value. This enables the caller
+ * to do some tricks to save processing time (done, for example, in the
+ * udp input).
+ * NOTE: this constructor does NOT call calloc(), as we have many bytes
+ * inside the structure which do not need to be cleared. bzero() will
+ * heavily thrash the cache, so we do the init manually (which also
+ * is the right thing to do with pointers, as they are not neccessarily
+ * a binary 0 on all machines [but today almost always...]).
+ * rgerhards, 2008-10-06
+ */
+static rsRetVal
+msgBaseConstruct(smsg_t **ppThis)
+{
+ DEFiRet;
+ smsg_t *pM;
+
+ assert(ppThis != NULL);
+ CHKmalloc(pM = malloc(sizeof(smsg_t)));
+ objConstructSetObjInfo(pM); /* intialize object helper entities */
+
+ /* initialize members in ORDER they appear in structure (think "cache line"!) */
+ pM->flowCtlType = 0;
+ pM->bParseSuccess = 0;
+ pM->iRefCount = 1;
+ pM->iSeverity = LOG_DEBUG;
+ pM->iFacility = LOG_INVLD;
+ pM->iLenPROGNAME = -1;
+ pM->offAfterPRI = 0;
+ pM->offMSG = -1;
+ pM->iProtocolVersion = 0;
+ pM->msgFlags = 0;
+ pM->iLenRawMsg = 0;
+ pM->iLenMSG = 0;
+ pM->iLenTAG = 0;
+ pM->iLenHOSTNAME = 0;
+ pM->pszRawMsg = NULL;
+ pM->pszHOSTNAME = NULL;
+ pM->pszRcvdAt3164 = NULL;
+ pM->pszRcvdAt3339 = NULL;
+ pM->pszRcvdAt_MySQL = NULL;
+ pM->pszRcvdAt_PgSQL = NULL;
+ pM->pszTIMESTAMP3164 = NULL;
+ pM->pszTIMESTAMP3339 = NULL;
+ pM->pszTIMESTAMP_MySQL = NULL;
+ pM->pszTIMESTAMP_PgSQL = NULL;
+ pM->pszStrucData = NULL;
+ pM->lenStrucData = 0;
+ pM->pCSAPPNAME = NULL;
+ pM->pCSPROCID = NULL;
+ pM->pCSMSGID = NULL;
+ pM->pInputName = NULL;
+ pM->pRcvFromIP = NULL;
+ pM->rcvFrom.pRcvFrom = NULL;
+ pM->pRuleset = NULL;
+ pM->json = NULL;
+ pM->localvars = NULL;
+ pM->dfltTZ[0] = '\0';
+ memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt));
+ memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP));
+ pM->TAG.pszTAG = NULL;
+ pM->pszTimestamp3164[0] = '\0';
+ pM->pszTimestamp3339[0] = '\0';
+ pM->pszTIMESTAMP_SecFrac[0] = '\0';
+ pM->pszRcvdAt_SecFrac[0] = '\0';
+ pM->pszTIMESTAMP_Unix[0] = '\0';
+ pM->pszRcvdAt_Unix[0] = '\0';
+ pM->pszUUID = NULL;
+ pthread_mutex_init(&pM->mut, NULL);
+
+ #if DEV_DEBUG == 1
+ dbgprintf("msgConstruct\t0x%x, ref 1\n", (int)pM);
+ #endif
+
+ *ppThis = pM;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* "Constructor" for a msg "object". Returns a pointer to
+ * the new object or NULL if no such object could be allocated.
+ * An object constructed via this function should only be destroyed
+ * via "msgDestruct()". This constructor does not query system time
+ * itself but rather uses a user-supplied value. This enables the caller
+ * to do some tricks to save processing time (done, for example, in the
+ * udp input).
+ * rgerhards, 2008-10-06
+ */
+rsRetVal msgConstructWithTime(smsg_t **ppThis, const struct syslogTime *stTime, const time_t ttGenTime)
+{
+ DEFiRet;
+
+ CHKiRet(msgBaseConstruct(ppThis));
+ (*ppThis)->ttGenTime = ttGenTime;
+ memcpy(&(*ppThis)->tRcvdAt, stTime, sizeof(struct syslogTime));
+ memcpy(&(*ppThis)->tTIMESTAMP, stTime, sizeof(struct syslogTime));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* "Constructor" for a msg "object". Returns a pointer to
+ * the new object or NULL if no such object could be allocated.
+ * An object constructed via this function should only be destroyed
+ * via "msgDestruct()". This constructor, for historical reasons,
+ * also sets the two timestamps to the current time.
+ */
+rsRetVal msgConstruct(smsg_t **ppThis)
+{
+ DEFiRet;
+
+ CHKiRet(msgBaseConstruct(ppThis));
+ /* we initialize both timestamps to contain the current time, so that they
+ * are consistent. Also, this saves us from doing any further time calls just
+ * to obtain a timestamp. The memcpy() should not really make a difference,
+ * especially as I think there is no codepath currently where it would not be
+ * required (after I have cleaned up the pathes ;)). -- rgerhards, 2008-10-02
+ */
+ datetime.getCurrTime(&((*ppThis)->tRcvdAt), &((*ppThis)->ttGenTime), TIME_IN_LOCALTIME);
+ memcpy(&(*ppThis)->tTIMESTAMP, &(*ppThis)->tRcvdAt, sizeof(struct syslogTime));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Special msg constructor, to be used when an object is deserialized.
+ * we do only the base init as we know the properties will be set in
+ * any case by the deserializer. We still do the "inexpensive" inits
+ * just to be on the safe side. The whole process needs to be
+ * refactored together with the msg serialization subsystem.
+ */
+rsRetVal
+msgConstructForDeserializer(smsg_t **ppThis)
+{
+ return msgBaseConstruct(ppThis);
+}
+
+
+/* some free handlers for (slightly) complicated cases... All of them may be called
+ * with an empty element.
+ */
+static inline void freeTAG(smsg_t *pThis)
+{
+ if(pThis->iLenTAG >= CONF_TAG_BUFSIZE)
+ free(pThis->TAG.pszTAG);
+}
+static inline void freeHOSTNAME(smsg_t *pThis)
+{
+ if(pThis->iLenHOSTNAME >= CONF_HOSTNAME_BUFSIZE)
+ free(pThis->pszHOSTNAME);
+}
+
+
+rsRetVal msgDestruct(smsg_t **ppThis)
+{
+ DEFiRet;
+ smsg_t *pThis;
+ int currRefCount;
+# ifdef HAVE_MALLOC_TRIM
+ int currCnt;
+# endif
+CODESTARTobjDestruct(msg)
+ #if DEV_DEBUG == 1
+ dbgprintf("msgDestruct\t0x%lx, "
+ "Ref now: %d\n", (unsigned long)pThis, pThis->iRefCount - 1);
+ #endif
+# ifdef HAVE_ATOMIC_BUILTINS
+ currRefCount = ATOMIC_DEC_AND_FETCH(&pThis->iRefCount, NULL);
+# else
+ MsgLock(pThis);
+ currRefCount = --pThis->iRefCount;
+# endif
+ if(currRefCount == 0)
+ {
+ #if DEV_DEBUG == 1
+ dbgprintf("msgDestruct\t0x%lx, RefCount now 0, doing DESTROY\n",
+ (unsigned long)pThis);
+ #endif
+ if(pThis->pszRawMsg != pThis->szRawMsg)
+ free(pThis->pszRawMsg);
+ freeTAG(pThis);
+ freeHOSTNAME(pThis);
+ if(pThis->pInputName != NULL)
+ prop.Destruct(&pThis->pInputName);
+ if((pThis->msgFlags & NEEDS_DNSRESOL) == 0) {
+ if(pThis->rcvFrom.pRcvFrom != NULL)
+ prop.Destruct(&pThis->rcvFrom.pRcvFrom);
+ } else {
+ free(pThis->rcvFrom.pfrominet);
+ }
+ if(pThis->pRcvFromIP != NULL)
+ prop.Destruct(&pThis->pRcvFromIP);
+ free(pThis->pszRcvdAt3164);
+ free(pThis->pszRcvdAt3339);
+ free(pThis->pszRcvdAt_MySQL);
+ free(pThis->pszRcvdAt_PgSQL);
+ free(pThis->pszTIMESTAMP_MySQL);
+ free(pThis->pszTIMESTAMP_PgSQL);
+ free(pThis->pszStrucData);
+ if(pThis->iLenPROGNAME >= CONF_PROGNAME_BUFSIZE)
+ free(pThis->PROGNAME.ptr);
+ if(pThis->pCSAPPNAME != NULL)
+ rsCStrDestruct(&pThis->pCSAPPNAME);
+ if(pThis->pCSPROCID != NULL)
+ rsCStrDestruct(&pThis->pCSPROCID);
+ if(pThis->pCSMSGID != NULL)
+ rsCStrDestruct(&pThis->pCSMSGID);
+ if(pThis->json != NULL)
+ json_object_put(pThis->json);
+ if(pThis->localvars != NULL)
+ json_object_put(pThis->localvars);
+ if(pThis->pszUUID != NULL)
+ free(pThis->pszUUID);
+# ifndef HAVE_ATOMIC_BUILTINS
+ MsgUnlock(pThis);
+# endif
+ pthread_mutex_destroy(&pThis->mut);
+ /* now we need to do our own optimization. Testing has shown that at least the glibc
+ * malloc() subsystem returns memory to the OS far too late in our case. So we need
+ * to help it a bit, by calling malloc_trim(), which will tell the alloc subsystem
+ * to consolidate and return to the OS. We keep 128K for our use, as a safeguard
+ * to too-frequent reallocs. But more importantly, we call this hook only every
+ * 100,000 messages (which is an approximation, as we do not work with atomic
+ * operations on the counter. --- rgerhards, 2009-06-22.
+ */
+# ifdef HAVE_MALLOC_TRIM
+ { /* standard C requires a new block for a new variable definition!
+ * To simplify matters, we use modulo arithmetic and live with the fact
+ * that we trim too often when the counter wraps.
+ */
+ static unsigned iTrimCtr = 1;
+ currCnt = ATOMIC_INC_AND_FETCH_unsigned(&iTrimCtr, &mutTrimCtr);
+ if(currCnt % 100000 == 0) {
+ malloc_trim(128*1024);
+ }
+ }
+# endif
+ } else {
+# ifndef HAVE_ATOMIC_BUILTINS
+ MsgUnlock(pThis);
+# endif
+ pThis = NULL; /* tell framework not to destructing the object! */
+ }
+ENDobjDestruct(msg)
+
+/* The macros below are used in MsgDup(). I use macros
+ * to keep the fuction code somewhat more readyble. It is my
+ * replacement for inline functions in CPP
+ */
+#define tmpCOPYSZ(name) \
+ if(pOld->psz##name != NULL) { \
+ if((pNew->psz##name = srUtilStrDup(pOld->psz##name, pOld->iLen##name)) == NULL) {\
+ msgDestruct(&pNew);\
+ return NULL;\
+ }\
+ pNew->iLen##name = pOld->iLen##name;\
+ }
+
+/* copy the CStr objects.
+ * if the old value is NULL, we do not need to do anything because we
+ * initialized the new value to NULL via calloc().
+ */
+#define tmpCOPYCSTR(name) \
+ if(pOld->pCS##name != NULL) {\
+ if(rsCStrConstructFromCStr(&(pNew->pCS##name), pOld->pCS##name) != RS_RET_OK) {\
+ msgDestruct(&pNew);\
+ return NULL;\
+ }\
+ cstrFinalize(pNew->pCS##name); \
+ }
+/* Constructs a message object by duplicating another one.
+ * Returns NULL if duplication failed. We do not need to lock the
+ * message object here, because a fully-created msg object is never
+ * allowed to be manipulated. For this, MsgDup() must be used, so MsgDup()
+ * can never run into a situation where the message object is being
+ * modified while its content is copied - it's forbidden by definition.
+ * rgerhards, 2007-07-10
+ */
+smsg_t* MsgDup(smsg_t* pOld)
+{
+ smsg_t* pNew;
+ rsRetVal localRet;
+
+ assert(pOld != NULL);
+
+ if(msgConstructWithTime(&pNew, &pOld->tTIMESTAMP, pOld->ttGenTime) != RS_RET_OK) {
+ return NULL;
+ }
+
+ /* now copy the message properties */
+ pNew->iRefCount = 1;
+ pNew->iSeverity = pOld->iSeverity;
+ pNew->iFacility = pOld->iFacility;
+ pNew->msgFlags = pOld->msgFlags;
+ pNew->iProtocolVersion = pOld->iProtocolVersion;
+ pNew->tRcvdAt = pOld->tRcvdAt;
+ pNew->offMSG = pOld->offMSG;
+ pNew->iLenRawMsg = pOld->iLenRawMsg;
+ pNew->iLenMSG = pOld->iLenMSG;
+ pNew->iLenTAG = pOld->iLenTAG;
+ pNew->iLenHOSTNAME = pOld->iLenHOSTNAME;
+ if((pOld->msgFlags & NEEDS_DNSRESOL)) {
+ localRet = msgSetFromSockinfo(pNew, pOld->rcvFrom.pfrominet);
+ if(localRet != RS_RET_OK) {
+ /* if something fails, we accept loss of this property, it is
+ * better than losing the whole message.
+ */
+ pNew->msgFlags &= ~NEEDS_DNSRESOL;
+ pNew->rcvFrom.pRcvFrom = NULL; /* make sure no dangling values */
+ }
+ } else {
+ if(pOld->rcvFrom.pRcvFrom != NULL) {
+ pNew->rcvFrom.pRcvFrom = pOld->rcvFrom.pRcvFrom;
+ prop.AddRef(pNew->rcvFrom.pRcvFrom);
+ }
+ }
+ if(pOld->pRcvFromIP != NULL) {
+ pNew->pRcvFromIP = pOld->pRcvFromIP;
+ prop.AddRef(pNew->pRcvFromIP);
+ }
+ if(pOld->pInputName != NULL) {
+ pNew->pInputName = pOld->pInputName;
+ prop.AddRef(pNew->pInputName);
+ }
+ if(pOld->iLenTAG > 0) {
+ if(pOld->iLenTAG < CONF_TAG_BUFSIZE) {
+ memcpy(pNew->TAG.szBuf, pOld->TAG.szBuf, pOld->iLenTAG + 1);
+ } else {
+ if((pNew->TAG.pszTAG = srUtilStrDup(pOld->TAG.pszTAG, pOld->iLenTAG)) == NULL) {
+ msgDestruct(&pNew);
+ return NULL;
+ }
+ pNew->iLenTAG = pOld->iLenTAG;
+ }
+ }
+ if(pOld->pszRawMsg == pOld->szRawMsg) {
+ memcpy(pNew->szRawMsg, pOld->szRawMsg, pOld->iLenRawMsg + 1);
+ pNew->pszRawMsg = pNew->szRawMsg;
+ } else {
+ tmpCOPYSZ(RawMsg);
+ }
+ if(pOld->pszHOSTNAME == NULL) {
+ pNew->pszHOSTNAME = NULL;
+ } else {
+ if(pOld->iLenHOSTNAME < CONF_HOSTNAME_BUFSIZE) {
+ memcpy(pNew->szHOSTNAME, pOld->szHOSTNAME, pOld->iLenHOSTNAME + 1);
+ pNew->pszHOSTNAME = pNew->szHOSTNAME;
+ } else {
+ tmpCOPYSZ(HOSTNAME);
+ }
+ }
+ if(pOld->pszStrucData == NULL) {
+ pNew->pszStrucData = NULL;
+ } else {
+ pNew->pszStrucData = (uchar*)strdup((char*)pOld->pszStrucData);
+ pNew->lenStrucData = pOld->lenStrucData;
+ }
+
+ tmpCOPYCSTR(APPNAME);
+ tmpCOPYCSTR(PROCID);
+ tmpCOPYCSTR(MSGID);
+
+ if(pOld->json != NULL)
+ pNew->json = jsonDeepCopy(pOld->json);
+ if(pOld->localvars != NULL)
+ pNew->localvars = jsonDeepCopy(pOld->localvars);
+
+ /* we do not copy all other cache properties, as we do not even know
+ * if they are needed once again. So we let them re-create if needed.
+ */
+
+ return pNew;
+}
+#undef tmpCOPYSZ
+#undef tmpCOPYCSTR
+
+
+/* This method serializes a message object. That means the whole
+ * object is modified into text form. That text form is suitable for
+ * later reconstruction of the object by calling MsgDeSerialize().
+ * The most common use case for this method is the creation of an
+ * on-disk representation of the message object.
+ * We do not serialize the cache properties. We re-create them when needed.
+ * This saves us a lot of memory. Performance is no concern, as serializing
+ * is a so slow operation that recration of the caches does not count. Also,
+ * we do not serialize --currently none--, as this is only a helper variable
+ * during msg construction - and never again used later.
+ * rgerhards, 2008-01-03
+ */
+static rsRetVal MsgSerialize(smsg_t *pThis, strm_t *pStrm)
+{
+ uchar *psz;
+ int len;
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pStrm != NULL);
+
+ /* then serialize elements */
+ CHKiRet(obj.BeginSerialize(pStrm, (obj_t*) pThis));
+ objSerializeSCALAR(pStrm, iProtocolVersion, SHORT);
+ objSerializeSCALAR(pStrm, iSeverity, SHORT);
+ objSerializeSCALAR(pStrm, iFacility, SHORT);
+ objSerializeSCALAR(pStrm, msgFlags, INT);
+ objSerializeSCALAR(pStrm, ttGenTime, INT);
+ objSerializeSCALAR(pStrm, tRcvdAt, SYSLOGTIME);
+ objSerializeSCALAR(pStrm, tTIMESTAMP, SYSLOGTIME);
+
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszTAG"), PROPTYPE_PSZ, (void*)
+ ((pThis->iLenTAG < CONF_TAG_BUFSIZE) ? pThis->TAG.szBuf : pThis->TAG.pszTAG)));
+
+ objSerializePTR(pStrm, pszRawMsg, PSZ);
+ objSerializePTR(pStrm, pszHOSTNAME, PSZ);
+ getInputName(pThis, &psz, &len);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszInputName"), PROPTYPE_PSZ, (void*) psz));
+ psz = getRcvFrom(pThis);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFrom"), PROPTYPE_PSZ, (void*) psz));
+ psz = getRcvFromIP(pThis);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFromIP"), PROPTYPE_PSZ, (void*) psz));
+ psz = pThis->pszStrucData;
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszStrucData"), PROPTYPE_PSZ, (void*) psz));
+ if(pThis->json != NULL) {
+ MsgLock(pThis);
+ psz = (uchar*) json_object_get_string(pThis->json);
+ MsgUnlock(pThis);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("json"), PROPTYPE_PSZ, (void*) psz));
+ }
+ if(pThis->localvars != NULL) {
+ MsgLock(pThis);
+ psz = (uchar*) json_object_get_string(pThis->localvars);
+ MsgUnlock(pThis);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("localvars"), PROPTYPE_PSZ, (void*) psz));
+ }
+
+ objSerializePTR(pStrm, pCSAPPNAME, CSTR);
+ objSerializePTR(pStrm, pCSPROCID, CSTR);
+ objSerializePTR(pStrm, pCSMSGID, CSTR);
+
+ objSerializePTR(pStrm, pszUUID, PSZ);
+
+ if(pThis->pRuleset != NULL) {
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRuleset"), PROPTYPE_PSZ,
+ rulesetGetName(pThis->pRuleset)));
+ }
+
+ /* offset must be serialized after pszRawMsg, because we need that to obtain the correct
+ * MSG size.
+ */
+ objSerializeSCALAR(pStrm, offMSG, INT);
+
+ CHKiRet(obj.EndSerialize(pStrm));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This is a helper for MsgDeserialize that re-inits the var object. This
+ * whole construct should be replaced, var is really ready to be retired.
+ * But as an interim help during refactoring let's introduce this function
+ * here (and thus NOT as method of var object!). -- rgerhads, 2012-11-06
+ */
+static void
+reinitVar(var_t *pVar)
+{
+ rsCStrDestruct(&pVar->pcsName); /* no longer needed */
+ if(pVar->varType == VARTYPE_STR) {
+ if(pVar->val.pStr != NULL)
+ rsCStrDestruct(&pVar->val.pStr);
+ }
+}
+/* deserialize the message again
+ * we deserialize the properties in the same order that we serialized them. Except
+ * for some checks to cover downlevel version, we do not need to do all these
+ * CPU intense name checkings.
+ */
+#define isProp(name) !rsCStrSzStrCmp(pVar->pcsName, (uchar*) name, sizeof(name) - 1)
+rsRetVal
+MsgDeserialize(smsg_t * const pMsg, strm_t *pStrm)
+{
+ prop_t *myProp;
+ prop_t *propRcvFrom = NULL;
+ prop_t *propRcvFromIP = NULL;
+ struct json_tokener *tokener;
+ var_t *pVar = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ CHKiRet(var.Construct(&pVar));
+ CHKiRet(var.ConstructFinalize(pVar));
+
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ if(isProp("iProtocolVersion")) {
+ setProtocolVersion(pMsg, pVar->val.num);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("iSeverity")) {
+ pMsg->iSeverity = pVar->val.num;
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("iFacility")) {
+ pMsg->iFacility = pVar->val.num;
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("msgFlags")) {
+ pMsg->msgFlags = pVar->val.num;
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("ttGenTime")) {
+ pMsg->ttGenTime = pVar->val.num;
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("tRcvdAt")) {
+ memcpy(&pMsg->tRcvdAt, &pVar->val.vSyslogTime, sizeof(struct syslogTime));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("tTIMESTAMP")) {
+ memcpy(&pMsg->tTIMESTAMP, &pVar->val.vSyslogTime, sizeof(struct syslogTime));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszTAG")) {
+ MsgSetTAG(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszRawMsg")) {
+ MsgSetRawMsg(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszHOSTNAME")) {
+ MsgSetHOSTNAME(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszInputName")) {
+ /* we need to create a property */
+ CHKiRet(prop.Construct(&myProp));
+ CHKiRet(prop.SetString(myProp, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr)));
+ CHKiRet(prop.ConstructFinalize(myProp));
+ MsgSetInputName(pMsg, myProp);
+ prop.Destruct(&myProp);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszRcvFrom")) {
+ MsgSetRcvFromStr(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr), &propRcvFrom);
+ prop.Destruct(&propRcvFrom);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszRcvFromIP")) {
+ MsgSetRcvFromIPStr(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr),
+ &propRcvFromIP);
+ prop.Destruct(&propRcvFromIP);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszStrucData")) {
+ MsgSetStructuredData(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("json")) {
+ tokener = json_tokener_new();
+ pMsg->json = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr),
+ cstrLen(pVar->val.pStr));
+ json_tokener_free(tokener);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("localvars")) {
+ tokener = json_tokener_new();
+ pMsg->localvars = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr),
+ cstrLen(pVar->val.pStr));
+ json_tokener_free(tokener);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pCSAPPNAME")) {
+ MsgSetAPPNAME(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pCSPROCID")) {
+ MsgSetPROCID(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pCSMSGID")) {
+ MsgSetMSGID(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszUUID")) {
+ pMsg->pszUUID = ustrdup(rsCStrGetSzStrNoNULL(pVar->val.pStr));
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ if(isProp("pszRuleset")) {
+ MsgSetRulesetByName(pMsg, pVar->val.pStr);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
+ /* "offMSG" must always be our last field, so we use this as an
+ * indicator if the sequence is correct. This is a bit questionable,
+ * but on the other hand it works decently AND we will probably replace
+ * the whole persisted format soon in any case. -- rgerhards, 2012-11-06
+ */
+ if(!isProp("offMSG")) {
+ DBGPRINTF("error property: %s\n", rsCStrGetSzStrNoNULL(pVar->pcsName));
+ ABORT_FINALIZE(RS_RET_DS_PROP_SEQ_ERR);
+ }
+ MsgSetMSGoffs(pMsg, pVar->val.num);
+finalize_it:
+ if(pVar != NULL)
+ var.Destruct(&pVar);
+ if(Debug && iRet != RS_RET_OK) {
+ dbgprintf("MsgDeserialize error %d\n", iRet);
+ }
+ RETiRet;
+}
+#undef isProp
+
+
+/* Increment reference count - see description of the "msg"
+ * structure for details. As a convenience to developers,
+ * this method returns the msg pointer that is passed to it.
+ * It is recommended that it is called as follows:
+ *
+ * pSecondMsgPointer = MsgAddRef(pOrgMsgPointer);
+ */
+smsg_t *MsgAddRef(smsg_t * const pM)
+{
+ assert(pM != NULL);
+# ifdef HAVE_ATOMIC_BUILTINS
+ ATOMIC_INC(&pM->iRefCount, NULL);
+# else
+ MsgLock(pM);
+ pM->iRefCount++;
+ MsgUnlock(pM);
+# endif
+ #if DEV_DEBUG == 1
+ dbgprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount);
+ #endif
+ return(pM);
+}
+
+
+/* This functions tries to acquire the PROCID from TAG. Its primary use is
+ * when a legacy syslog message has been received and should be forwarded as
+ * syslog-protocol (or the PROCID is requested for any other reason).
+ * In legacy syslog, the PROCID is considered to be the character sequence
+ * between the first [ and the first ]. This usually are digits only, but we
+ * do not check that. However, if there is no closing ], we do not assume we
+ * can obtain a PROCID. Take in mind that not every legacy syslog message
+ * actually has a PROCID.
+ * rgerhards, 2005-11-24
+ * THIS MUST be called with the message lock locked.
+ */
+static rsRetVal acquirePROCIDFromTAG(smsg_t * const pM)
+{
+ register int i;
+ uchar *pszTag;
+ DEFiRet;
+
+ assert(pM != NULL);
+
+ if(pM->pCSPROCID != NULL)
+ return RS_RET_OK; /* we are already done ;) */
+
+ if(msgGetProtocolVersion(pM) != 0)
+ return RS_RET_OK; /* we can only emulate if we have legacy format */
+
+ pszTag = (uchar*) ((pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG);
+
+ /* find first '['... */
+ i = 0;
+ while((i < pM->iLenTAG) && (pszTag[i] != '['))
+ ++i;
+ if(!(i < pM->iLenTAG))
+ return RS_RET_OK; /* no [, so can not emulate... */
+
+ ++i; /* skip '[' */
+
+ /* now obtain the PROCID string... */
+ CHKiRet(cstrConstruct(&pM->pCSPROCID));
+ while((i < pM->iLenTAG) && (pszTag[i] != ']')) {
+ CHKiRet(cstrAppendChar(pM->pCSPROCID, pszTag[i]));
+ ++i;
+ }
+
+ if(!(i < pM->iLenTAG)) {
+ /* oops... it looked like we had a PROCID, but now it has
+ * turned out this is not true. In this case, we need to free
+ * the buffer and simply return. Note that this is NOT an error
+ * case!
+ */
+ cstrDestruct(&pM->pCSPROCID);
+ FINALIZE;
+ }
+
+ /* OK, finally we could obtain a PROCID. So let's use it ;) */
+ cstrFinalize(pM->pCSPROCID);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Parse and set the "programname" for a given MSG object. Programname
+ * is a BSD concept, it is the tag without any instance-specific information.
+ * Precisely, the programname is terminated by either (whichever occurs first):
+ * - end of tag
+ * - nonprintable character
+ * - ':'
+ * - '['
+ * - '/'
+ * The above definition has been taken from the FreeBSD syslogd sources.
+ *
+ * The program name is not parsed by default, because it is infrequently-used.
+ * IMPORTANT: A locked message object must be provided, else a crash will occur.
+ * rgerhards, 2005-10-19
+ */
+static rsRetVal
+acquireProgramName(smsg_t * const pM)
+{
+ int i;
+ uchar *pszTag, *pszProgName;
+ DEFiRet;
+
+ assert(pM != NULL);
+ pszTag = (uchar*) ((pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG);
+ for( i = 0
+ ; (i < pM->iLenTAG) && isprint((int) pszTag[i])
+ && (pszTag[i] != '\0') && (pszTag[i] != ':')
+ && (pszTag[i] != '[')
+ && (runConf->globals.parser.bPermitSlashInProgramname || (pszTag[i] != '/'))
+ ; ++i)
+ ; /* just search end of PROGNAME */
+ if(i < CONF_PROGNAME_BUFSIZE) {
+ pszProgName = pM->PROGNAME.szBuf;
+ } else {
+ CHKmalloc(pM->PROGNAME.ptr = malloc(i+1));
+ pszProgName = pM->PROGNAME.ptr;
+ }
+ memcpy((char*)pszProgName, (char*)pszTag, i);
+ pszProgName[i] = '\0';
+ pM->iLenPROGNAME = i;
+finalize_it:
+ RETiRet;
+}
+
+
+/* Access methods - dumb & easy, not a comment for each ;)
+ */
+void setProtocolVersion(smsg_t * const pM, int iNewVersion)
+{
+ assert(pM != NULL);
+ if(iNewVersion != 0 && iNewVersion != 1) {
+ dbgprintf("Tried to set unsupported protocol version %d - changed to 0.\n", iNewVersion);
+ iNewVersion = 0;
+ }
+ pM->iProtocolVersion = iNewVersion;
+}
+
+/* note: string is taken from constant pool, do NOT free */
+static const char *getProtocolVersionString(smsg_t * const pM)
+{
+ assert(pM != NULL);
+ return(pM->iProtocolVersion ? "1" : "0");
+}
+
+void
+msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri)
+{
+ if(pri > LOG_MAXPRI)
+ pri = LOG_PRI_INVLD;
+ pMsg->iFacility = pri2fac(pri),
+ pMsg->iSeverity = pri2sev(pri);
+}
+
+#ifdef USE_LIBUUID
+/* note: libuuid seems not to be thread-safe, so we need
+ * to get some safeguards in place.
+ */
+static pthread_mutex_t mutUUID = PTHREAD_MUTEX_INITIALIZER;
+
+static void call_uuid_generate(uuid_t uuid)
+{
+ pthread_mutex_lock(&mutUUID);
+ pthread_cleanup_push(mutexCancelCleanup, &mutUUID);
+ uuid_generate(uuid);
+ pthread_cleanup_pop(1);
+}
+
+static void msgSetUUID(smsg_t * const pM)
+{
+ size_t lenRes = sizeof(uuid_t) * 2 + 1;
+ char hex_char [] = "0123456789ABCDEF";
+ unsigned int byte_nbr;
+ uuid_t uuid;
+
+ dbgprintf("[MsgSetUUID] START, lenRes %llu\n", (long long unsigned) lenRes);
+ assert(pM != NULL);
+
+ if((pM->pszUUID = (uchar*) malloc(lenRes)) == NULL) {
+ pM->pszUUID = (uchar *)"";
+ } else {
+ call_uuid_generate(uuid);
+ for (byte_nbr = 0; byte_nbr < sizeof (uuid_t); byte_nbr++) {
+ pM->pszUUID[byte_nbr * 2 + 0] = hex_char[uuid [byte_nbr] >> 4];
+ pM->pszUUID[byte_nbr * 2 + 1] = hex_char[uuid [byte_nbr] & 15];
+ }
+
+ pM->pszUUID[lenRes-1] = '\0';
+ dbgprintf("[MsgSetUUID] UUID : %s LEN: %d \n", pM->pszUUID, (int)lenRes);
+ }
+ dbgprintf("[MsgSetUUID] END\n");
+}
+
+static void getUUID(smsg_t * const pM, uchar **pBuf, int *piLen)
+{
+ dbgprintf("[getUUID] START\n");
+ if(pM == NULL) {
+ dbgprintf("[getUUID] pM is NULL\n");
+ *pBuf= UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ if(pM->pszUUID == NULL) {
+ dbgprintf("[getUUID] pM->pszUUID is NULL\n");
+ MsgLock(pM);
+ /* re-query, things may have changed in the mean time... */
+ if(pM->pszUUID == NULL)
+ msgSetUUID(pM);
+ MsgUnlock(pM);
+ } else { /* UUID already there we reuse it */
+ dbgprintf("[getUUID] pM->pszUUID already exists\n");
+ }
+ *pBuf = pM->pszUUID;
+ *piLen = sizeof(uuid_t) * 2;
+ }
+ dbgprintf("[getUUID] END\n");
+}
+#endif
+
+int ATTR_NONNULL()
+getRawMsgLen(const smsg_t *const pMsg)
+{
+ return (pMsg->pszRawMsg == NULL) ? 0 : pMsg->iLenRawMsg;
+}
+
+void
+getRawMsg(const smsg_t * const pM, uchar **pBuf, int *piLen)
+{
+ if(pM == NULL) {
+ *pBuf= UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ if(pM->pszRawMsg == NULL) {
+ *pBuf= UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ *pBuf = pM->pszRawMsg;
+ *piLen = pM->iLenRawMsg;
+ }
+ }
+}
+
+void
+getRawMsgAfterPRI(smsg_t * const pM, uchar **pBuf, int *piLen)
+{
+ if(pM == NULL) {
+ *pBuf= UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ if(pM->pszRawMsg == NULL) {
+ *pBuf= UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ /* unfortunately, pM->offAfterPRI seems NOT to be
+ * correct/consistent in all cases. imuxsock and imudp
+ * seem to have other values than imptcp. Testbench
+ * covers some of that. As a work-around, we caluculate
+ * the value ourselfes here. -- rgerhards, 2015-10-09
+ */
+ size_t offAfterPRI = 0;
+ if(pM->pszRawMsg[0] == '<') { /* do we have a PRI? */
+ if(pM->pszRawMsg[2] == '>')
+ offAfterPRI = 3;
+ else if(pM->pszRawMsg[3] == '>')
+ offAfterPRI = 4;
+ else if(pM->pszRawMsg[4] == '>')
+ offAfterPRI = 5;
+ }
+ *pBuf = pM->pszRawMsg + offAfterPRI;
+ *piLen = pM->iLenRawMsg - offAfterPRI;
+ }
+ }
+}
+
+
+/* note: setMSGLen() is only for friends who really know what they
+ * do. Setting an invalid length can be desasterous!
+ */
+void setMSGLen(smsg_t * const pM, int lenMsg)
+{
+ pM->iLenMSG = lenMsg;
+}
+
+int getMSGLen(smsg_t * const pM)
+{
+ return((pM == NULL) ? 0 : pM->iLenMSG);
+}
+
+uchar *getMSG(smsg_t * const pM)
+{
+ uchar *ret;
+ if(pM == NULL)
+ ret = UCHAR_CONSTANT("");
+ else {
+ if(pM->iLenMSG == 0)
+ ret = UCHAR_CONSTANT("");
+ else
+ ret = pM->pszRawMsg + pM->offMSG;
+ }
+ return ret;
+}
+
+
+/* Get PRI value as integer */
+int
+getPRIi(const smsg_t * const pM)
+{
+ syslog_pri_t pri = (pM->iFacility << 3) + (pM->iSeverity);
+ if(pri > 191)
+ pri = LOG_PRI_INVLD;
+ return pri;
+}
+
+
+/* Get PRI value in text form
+ */
+const char *
+getPRI(smsg_t * const pM)
+{
+ /* PRI is a number in the range 0..191. Thus, we use a simple lookup table to obtain the
+ * string value. It looks a bit clumpsy here in code ;)
+ */
+ int iPRI;
+
+ if(pM == NULL)
+ return "";
+
+ iPRI = getPRIi(pM);
+ return (iPRI > 191) ? "invld" : (char*)syslog_pri_names[iPRI].pszName;
+}
+
+
+static const char *
+formatISOWeekOrYear(enum tplFormatTypes eFmt, struct syslogTime *pTm)
+{
+ if(pTm->year >= 1970 && pTm->year <= 2099) {
+ int isoWeekYear;
+ int isoWeek;
+
+ isoWeek = getISOWeek(pTm, &isoWeekYear);
+
+ if (eFmt == tplFmtISOWeek) {
+ return two_digits[isoWeek];
+ } else {
+ return years[isoWeekYear - 1967];
+ }
+ } else {
+ return "YEAR OUT OF RANGE(1970-2099)";
+ }
+}
+
+const char *
+getTimeReported(smsg_t * const pM, enum tplFormatTypes eFmt)
+{
+ if(pM == NULL)
+ return "";
+
+ switch(eFmt) {
+ case tplFmtDefault:
+ case tplFmtRFC3164Date:
+ case tplFmtRFC3164BuggyDate:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP3164 == NULL) {
+ pM->pszTIMESTAMP3164 = pM->pszTimestamp3164;
+ datetime.formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164,
+ (eFmt == tplFmtRFC3164BuggyDate));
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP3164);
+ case tplFmtMySQLDate:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP_MySQL == NULL) {
+ if((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestampToMySQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_MySQL);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP_MySQL);
+ case tplFmtPgSQLDate:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP_PgSQL == NULL) {
+ if((pM->pszTIMESTAMP_PgSQL = malloc(21)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestampToPgSQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_PgSQL);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP_PgSQL);
+ case tplFmtRFC3339Date:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP3339 == NULL) {
+ pM->pszTIMESTAMP3339 = pM->pszTimestamp3339;
+ datetime.formatTimestamp3339(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP3339);
+ case tplFmtUnixDate:
+ MsgLock(pM);
+ if(pM->pszTIMESTAMP_Unix[0] == '\0') {
+ datetime.formatTimestampUnix(&pM->tTIMESTAMP, pM->pszTIMESTAMP_Unix);
+ }
+ MsgUnlock(pM);
+ return(pM->pszTIMESTAMP_Unix);
+ case tplFmtSecFrac:
+ if(pM->pszTIMESTAMP_SecFrac[0] == '\0') {
+ MsgLock(pM);
+ /* re-check, may have changed while we did not hold lock */
+ if(pM->pszTIMESTAMP_SecFrac[0] == '\0') {
+ datetime.formatTimestampSecFrac(&pM->tTIMESTAMP, pM->pszTIMESTAMP_SecFrac);
+ }
+ MsgUnlock(pM);
+ }
+ return(pM->pszTIMESTAMP_SecFrac);
+ case tplFmtWDayName:
+ return wdayNames[getWeekdayNbr(&pM->tTIMESTAMP)];
+ case tplFmtWDay:
+ return one_digit[getWeekdayNbr(&pM->tTIMESTAMP)];
+ case tplFmtMonth:
+ return two_digits[(int)pM->tTIMESTAMP.month];
+ case tplFmtYear:
+ if(pM->tTIMESTAMP.year >= 1967 && pM->tTIMESTAMP.year <= 2099)
+ return years[pM->tTIMESTAMP.year - 1967];
+ else
+ return "YEAR OUT OF RANGE(1967-2099)";
+ case tplFmtDay:
+ return two_digits[(int)pM->tTIMESTAMP.day];
+ case tplFmtHour:
+ return two_digits[(int)pM->tTIMESTAMP.hour];
+ case tplFmtMinute:
+ return two_digits[(int)pM->tTIMESTAMP.minute];
+ case tplFmtSecond:
+ return two_digits[(int)pM->tTIMESTAMP.second];
+ case tplFmtTZOffsHour:
+ return two_digits[(int)pM->tTIMESTAMP.OffsetHour];
+ case tplFmtTZOffsMin:
+ return two_digits[(int)pM->tTIMESTAMP.OffsetMinute];
+ case tplFmtTZOffsDirection:
+ return (pM->tTIMESTAMP.OffsetMode == '+')? "+" : "-";
+ case tplFmtOrdinal:
+ return daysInYear[getOrdinal(&pM->tTIMESTAMP)];
+ case tplFmtWeek:
+ return two_digits[getWeek(&pM->tTIMESTAMP)];
+ case tplFmtISOWeek:
+ case tplFmtISOWeekYear:
+ return formatISOWeekOrYear(eFmt, &pM->tTIMESTAMP);
+ }
+ return "INVALID eFmt OPTION!";
+}
+
+
+
+static const char *getTimeUTC(struct syslogTime *const __restrict__ pTmIn,
+ const enum tplFormatTypes eFmt,
+ unsigned short *const __restrict__ pbMustBeFreed)
+{
+ struct syslogTime tUTC;
+ char *retbuf = NULL;
+
+ timeConvertToUTC(pTmIn, &tUTC);
+ struct syslogTime *const pTm = &tUTC;
+
+ switch(eFmt) {
+ case tplFmtDefault:
+ if((retbuf = malloc(16)) != NULL) {
+ datetime.formatTimestamp3164(pTm, retbuf, 0);
+ }
+ break;
+ case tplFmtMySQLDate:
+ if((retbuf = malloc(15)) != NULL) {
+ datetime.formatTimestampToMySQL(pTm, retbuf);
+ }
+ break;
+ case tplFmtPgSQLDate:
+ if((retbuf = malloc(21)) != NULL) {
+ datetime.formatTimestampToPgSQL(pTm, retbuf);
+ }
+ break;
+ case tplFmtRFC3164Date:
+ case tplFmtRFC3164BuggyDate:
+ if((retbuf = malloc(16)) != NULL) {
+ datetime.formatTimestamp3164(pTm, retbuf, (eFmt == tplFmtRFC3164BuggyDate));
+ }
+ break;
+ case tplFmtRFC3339Date:
+ if((retbuf = malloc(33)) != NULL) {
+ datetime.formatTimestamp3339(pTm, retbuf);
+ }
+ break;
+ case tplFmtUnixDate:
+ if((retbuf = malloc(12)) != NULL) {
+ datetime.formatTimestampUnix(pTm, retbuf);
+ }
+ break;
+ case tplFmtSecFrac:
+ if((retbuf = malloc(7)) != NULL) {
+ datetime.formatTimestampSecFrac(pTm, retbuf);
+ }
+ break;
+ case tplFmtWDayName:
+ retbuf = strdup(wdayNames[getWeekdayNbr(pTm)]);
+ break;
+ case tplFmtWDay:
+ retbuf = strdup(one_digit[getWeekdayNbr(pTm)]);
+ break;
+ case tplFmtMonth:
+ retbuf = strdup(two_digits[(int)pTm->month]);
+ break;
+ case tplFmtYear:
+ if(pTm->year >= 1967 && pTm->year <= 2099)
+ retbuf = strdup(years[pTm->year - 1967]);
+ else
+ retbuf = strdup("YEAR OUT OF RANGE(1967-2099)");
+ break;
+ case tplFmtDay:
+ retbuf = strdup(two_digits[(int)pTm->day]);
+ break;
+ case tplFmtHour:
+ retbuf = strdup(two_digits[(int)pTm->hour]);
+ break;
+ case tplFmtMinute:
+ retbuf = strdup(two_digits[(int)pTm->minute]);
+ break;
+ case tplFmtSecond:
+ retbuf = strdup(two_digits[(int)pTm->second]);
+ break;
+ case tplFmtTZOffsHour:
+ retbuf = strdup(two_digits[(int)pTm->OffsetHour]);
+ break;
+ case tplFmtTZOffsMin:
+ retbuf = strdup(two_digits[(int)pTm->OffsetMinute]);
+ break;
+ case tplFmtTZOffsDirection:
+ retbuf = strdup((pTm->OffsetMode == '+')? "+" : "-");
+ break;
+ case tplFmtOrdinal:
+ retbuf = strdup(daysInYear[getOrdinal(pTm)]);
+ break;
+ case tplFmtWeek:
+ retbuf = strdup(two_digits[getWeek(pTm)]);
+ break;
+ case tplFmtISOWeek:
+ case tplFmtISOWeekYear:
+ retbuf = strdup(formatISOWeekOrYear(eFmt, pTm));
+ break;
+ }
+
+ if(retbuf == NULL) {
+ retbuf = (char*)"internal error: invalid eFmt option or malloc problem";
+ *pbMustBeFreed = 0;
+ } else {
+ *pbMustBeFreed = 1;
+ }
+ return retbuf;
+}
+
+static const char *
+getTimeGenerated(smsg_t *const __restrict__ pM,
+ const enum tplFormatTypes eFmt)
+{
+ struct syslogTime *const pTm = &pM->tRcvdAt;
+ if(pM == NULL)
+ return "";
+
+ switch(eFmt) {
+ case tplFmtDefault:
+ MsgLock(pM);
+ if(pM->pszRcvdAt3164 == NULL) {
+ if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestamp3164(pTm, pM->pszRcvdAt3164, 0);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt3164);
+ case tplFmtMySQLDate:
+ MsgLock(pM);
+ if(pM->pszRcvdAt_MySQL == NULL) {
+ if((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestampToMySQL(pTm, pM->pszRcvdAt_MySQL);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt_MySQL);
+ case tplFmtPgSQLDate:
+ MsgLock(pM);
+ if(pM->pszRcvdAt_PgSQL == NULL) {
+ if((pM->pszRcvdAt_PgSQL = malloc(21)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestampToPgSQL(pTm, pM->pszRcvdAt_PgSQL);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt_PgSQL);
+ case tplFmtRFC3164Date:
+ case tplFmtRFC3164BuggyDate:
+ MsgLock(pM);
+ if(pM->pszRcvdAt3164 == NULL) {
+ if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestamp3164(pTm, pM->pszRcvdAt3164,
+ (eFmt == tplFmtRFC3164BuggyDate));
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt3164);
+ case tplFmtRFC3339Date:
+ MsgLock(pM);
+ if(pM->pszRcvdAt3339 == NULL) {
+ if((pM->pszRcvdAt3339 = malloc(33)) == NULL) {
+ MsgUnlock(pM);
+ return "";
+ }
+ datetime.formatTimestamp3339(pTm, pM->pszRcvdAt3339);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt3339);
+ case tplFmtUnixDate:
+ MsgLock(pM);
+ if(pM->pszRcvdAt_Unix[0] == '\0') {
+ datetime.formatTimestampUnix(pTm, pM->pszRcvdAt_Unix);
+ }
+ MsgUnlock(pM);
+ return(pM->pszRcvdAt_Unix);
+ case tplFmtSecFrac:
+ if(pM->pszRcvdAt_SecFrac[0] == '\0') {
+ MsgLock(pM);
+ /* re-check, may have changed while we did not hold lock */
+ if(pM->pszRcvdAt_SecFrac[0] == '\0') {
+ datetime.formatTimestampSecFrac(pTm, pM->pszRcvdAt_SecFrac);
+ }
+ MsgUnlock(pM);
+ }
+ return(pM->pszRcvdAt_SecFrac);
+ case tplFmtWDayName:
+ return wdayNames[getWeekdayNbr(pTm)];
+ case tplFmtWDay:
+ return one_digit[getWeekdayNbr(pTm)];
+ case tplFmtMonth:
+ return two_digits[(int)pTm->month];
+ case tplFmtYear:
+ if(pTm->year >= 1967 && pTm->year <= 2099)
+ return years[pTm->year - 1967];
+ else
+ return "YEAR OUT OF RANGE(1967-2099)";
+ case tplFmtDay:
+ return two_digits[(int)pTm->day];
+ case tplFmtHour:
+ return two_digits[(int)pTm->hour];
+ case tplFmtMinute:
+ return two_digits[(int)pTm->minute];
+ case tplFmtSecond:
+ return two_digits[(int)pTm->second];
+ case tplFmtTZOffsHour:
+ return two_digits[(int)pTm->OffsetHour];
+ case tplFmtTZOffsMin:
+ return two_digits[(int)pTm->OffsetMinute];
+ case tplFmtTZOffsDirection:
+ return (pTm->OffsetMode == '+')? "+" : "-";
+ case tplFmtOrdinal:
+ return daysInYear[getOrdinal(pTm)];
+ case tplFmtWeek:
+ return two_digits[getWeek(pTm)];
+ case tplFmtISOWeek:
+ case tplFmtISOWeekYear:
+ return formatISOWeekOrYear(eFmt, pTm);
+ }
+ return "INVALID eFmt OPTION!";
+}
+
+
+static const char *getSeverity(smsg_t * const pM)
+{
+ const char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ if(pM->iSeverity > 7) {
+ name = "invld";
+ } else {
+ name = syslog_number_names[pM->iSeverity];
+ }
+
+ return name;
+}
+
+
+static const char *getSeverityStr(smsg_t * const pM)
+{
+ const char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ if(pM->iSeverity > 7) {
+ name = "invld";
+ } else {
+ name = syslog_severity_names[pM->iSeverity];
+ }
+
+ return name;
+}
+
+static const char *getFacility(smsg_t * const pM)
+{
+ const char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ if(pM->iFacility > 23) {
+ name = "invld";
+ } else {
+ name = syslog_number_names[pM->iFacility];
+ }
+
+ return name;
+}
+
+static const char *getFacilityStr(smsg_t * const pM)
+{
+ const char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ if(pM->iFacility > 23) {
+ name = "invld";
+ } else {
+ name = syslog_fac_names[pM->iFacility];
+ }
+
+ return name;
+}
+
+
+/* set flow control state (if not called, the default - NO_DELAY - is used)
+ * This needs no locking because it is only done while the object is
+ * not fully constructed (which also means you must not call this
+ * method after the msg has been handed over to a queue).
+ * rgerhards, 2008-03-14
+ */
+rsRetVal
+MsgSetFlowControlType(smsg_t * const pMsg, flowControl_t eFlowCtl)
+{
+ DEFiRet;
+ assert(pMsg != NULL);
+ assert(eFlowCtl == eFLOWCTL_NO_DELAY || eFlowCtl == eFLOWCTL_LIGHT_DELAY || eFlowCtl == eFLOWCTL_FULL_DELAY);
+
+ pMsg->flowCtlType = eFlowCtl;
+
+ RETiRet;
+}
+
+/* set offset after which PRI in raw msg starts
+ * rgerhards, 2009-06-16
+ */
+rsRetVal
+MsgSetAfterPRIOffs(smsg_t * const pMsg, int offs)
+{
+ assert(pMsg != NULL);
+ pMsg->offAfterPRI = offs;
+ return RS_RET_OK;
+}
+
+
+/* rgerhards 2004-11-24: set APP-NAME in msg object
+ * This is not locked, because it either is called during message
+ * construction (where we need no locking) or later as part of a function
+ * which already obtained the lock. So in general, this function here must
+ * only be called when it it safe to do so without it aquiring a lock.
+ */
+rsRetVal ATTR_NONNULL(1,2)
+MsgSetAPPNAME(smsg_t *__restrict__ const pMsg, const char *pszAPPNAME)
+{
+ DEFiRet;
+ assert(pMsg != NULL);
+ if(pszAPPNAME[0] == '\0') {
+ pszAPPNAME = "-"; /* RFC5424 NIL value */
+ }
+ if(pMsg->pCSAPPNAME == NULL) {
+ /* we need to obtain the object first */
+ CHKiRet(rsCStrConstruct(&pMsg->pCSAPPNAME));
+ }
+ /* if we reach this point, we have the object */
+ CHKiRet(rsCStrSetSzStr(pMsg->pCSAPPNAME, (uchar*) pszAPPNAME));
+ cstrFinalize(pMsg->pCSAPPNAME);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* rgerhards 2004-11-24: set PROCID in msg object
+ */
+rsRetVal MsgSetPROCID(smsg_t *__restrict__ const pMsg, const char* pszPROCID)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pMsg, msg);
+ if(pMsg->pCSPROCID == NULL) {
+ /* we need to obtain the object first */
+ CHKiRet(cstrConstruct(&pMsg->pCSPROCID));
+ }
+ /* if we reach this point, we have the object */
+ CHKiRet(rsCStrSetSzStr(pMsg->pCSPROCID, (uchar*) pszPROCID));
+ cstrFinalize(pMsg->pCSPROCID);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check if we have a procid, and, if not, try to acquire/emulate it.
+ * This must be called WITHOUT the message lock being held.
+ * rgerhards, 2009-06-26
+ */
+static void preparePROCID(smsg_t * const pM, sbool bLockMutex)
+{
+ if(pM->pCSPROCID == NULL) {
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+ /* re-query, things may have changed in the mean time... */
+ if(pM->pCSPROCID == NULL)
+ acquirePROCIDFromTAG(pM);
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+ }
+}
+
+
+#if 0
+/* rgerhards, 2005-11-24
+ */
+static int getPROCIDLen(smsg_t *pM, sbool bLockMutex)
+{
+ assert(pM != NULL);
+ preparePROCID(pM, bLockMutex);
+ return (pM->pCSPROCID == NULL) ? 1 : rsCStrLen(pM->pCSPROCID);
+}
+#endif
+
+
+/* rgerhards, 2005-11-24
+ */
+char *getPROCID(smsg_t * const pM, sbool bLockMutex)
+{
+ uchar *pszRet;
+
+ ISOBJ_TYPE_assert(pM, msg);
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+ preparePROCID(pM, MUTEX_ALREADY_LOCKED);
+ if(pM->pCSPROCID == NULL)
+ pszRet = UCHAR_CONSTANT("-");
+ else
+ pszRet = rsCStrGetSzStrNoNULL(pM->pCSPROCID);
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+ return (char*) pszRet;
+}
+
+
+/* rgerhards 2004-11-24: set MSGID in msg object
+ */
+rsRetVal MsgSetMSGID(smsg_t * const pMsg, const char* pszMSGID)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pMsg, msg);
+ if(pMsg->pCSMSGID == NULL) {
+ /* we need to obtain the object first */
+ CHKiRet(rsCStrConstruct(&pMsg->pCSMSGID));
+ }
+ /* if we reach this point, we have the object */
+ CHKiRet(rsCStrSetSzStr(pMsg->pCSMSGID, (uchar*) pszMSGID));
+ cstrFinalize(pMsg->pCSMSGID);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Return state of last parser. If it had success, "OK" is returned, else
+ * "FAIL". All from the constant pool.
+ */
+static const char *getParseSuccess(smsg_t * const pM)
+{
+ return (pM->bParseSuccess) ? "OK" : "FAIL";
+}
+
+
+/* al, 2011-07-26: LockMsg to avoid race conditions
+ */
+static const char *getMSGID(smsg_t * const pM)
+{
+ if (pM->pCSMSGID == NULL) {
+ return "-";
+ }
+ else {
+ MsgLock(pM);
+ char* pszreturn = (char*) rsCStrGetSzStrNoNULL(pM->pCSMSGID);
+ MsgUnlock(pM);
+ return pszreturn;
+ }
+}
+
+/* rgerhards 2012-03-15: set parser success (an integer, acutally bool)
+ */
+void MsgSetParseSuccess(smsg_t * const pMsg, int bSuccess)
+{
+ assert(pMsg != NULL);
+ pMsg->bParseSuccess = bSuccess;
+}
+
+
+/* return full message as a json string */
+const uchar*
+msgGetJSONMESG(smsg_t *__restrict__ const pMsg)
+{
+ struct json_object *json;
+ struct json_object *jval;
+ uchar *pRes; /* result pointer */
+ rs_size_t bufLen = -1; /* length of string or -1, if not known */
+
+ json = json_object_new_object();
+
+ jval = json_object_new_string((char*)getMSG(pMsg));
+ json_object_object_add(json, "msg", jval);
+
+ getRawMsg(pMsg, &pRes, &bufLen);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "rawmsg", jval);
+
+ pRes = (uchar*)getTimeReported(pMsg, tplFmtRFC3339Date);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "timereported", jval);
+
+ jval = json_object_new_string(getHOSTNAME(pMsg));
+ json_object_object_add(json, "hostname", jval);
+
+ getTAG(pMsg, &pRes, &bufLen, LOCK_MUTEX);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "syslogtag", jval);
+
+ getInputName(pMsg, &pRes, &bufLen);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "inputname", jval);
+
+ jval = json_object_new_string((char*)getRcvFrom(pMsg));
+ json_object_object_add(json, "fromhost", jval);
+
+ jval = json_object_new_string((char*)getRcvFromIP(pMsg));
+ json_object_object_add(json, "fromhost-ip", jval);
+
+ jval = json_object_new_string(getPRI(pMsg));
+ json_object_object_add(json, "pri", jval);
+
+ jval = json_object_new_string(getFacility(pMsg));
+ json_object_object_add(json, "syslogfacility", jval);
+
+ jval = json_object_new_string(getSeverity(pMsg));
+ json_object_object_add(json, "syslogseverity", jval);
+
+ pRes = (uchar*)getTimeGenerated(pMsg, tplFmtRFC3339Date);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "timegenerated", jval);
+
+ jval = json_object_new_string((char*)getProgramName(pMsg, LOCK_MUTEX));
+ json_object_object_add(json, "programname", jval);
+
+ jval = json_object_new_string(getProtocolVersionString(pMsg));
+ json_object_object_add(json, "protocol-version", jval);
+
+ MsgGetStructuredData(pMsg, &pRes, &bufLen);
+ jval = json_object_new_string((char*)pRes);
+ json_object_object_add(json, "structured-data", jval);
+
+ jval = json_object_new_string(getAPPNAME(pMsg, LOCK_MUTEX));
+ json_object_object_add(json, "app-name", jval);
+
+ jval = json_object_new_string(getPROCID(pMsg, LOCK_MUTEX));
+ json_object_object_add(json, "procid", jval);
+
+ jval = json_object_new_string(getMSGID(pMsg));
+ json_object_object_add(json, "msgid", jval);
+
+#ifdef USE_LIBUUID
+ if(pMsg->pszUUID == NULL) {
+ jval = NULL;
+ } else {
+ getUUID(pMsg, &pRes, &bufLen);
+ jval = json_object_new_string((char*)pRes);
+ }
+ json_object_object_add(json, "uuid", jval);
+#endif
+
+ json_object_object_add(json, "$!", json_object_get(pMsg->json));
+
+ pRes = (uchar*) strdup(json_object_get_string(json));
+ json_object_put(json);
+ return pRes;
+}
+
+/* rgerhards 2009-06-12: set associated ruleset
+ */
+void MsgSetRuleset(smsg_t * const pMsg, ruleset_t *pRuleset)
+{
+ assert(pMsg != NULL);
+ pMsg->pRuleset = pRuleset;
+}
+
+
+/* set TAG in msg object
+ * (rewritten 2009-06-18 rgerhards)
+ */
+void MsgSetTAG(smsg_t *__restrict__ const pMsg, const uchar* pszBuf, const size_t lenBuf)
+{
+ uchar *pBuf;
+ assert(pMsg != NULL);
+
+ freeTAG(pMsg);
+
+ pMsg->iLenTAG = lenBuf;
+ if(pMsg->iLenTAG < CONF_TAG_BUFSIZE) {
+ /* small enough: use fixed buffer (faster!) */
+ pBuf = pMsg->TAG.szBuf;
+ } else {
+ if((pBuf = (uchar*) malloc(pMsg->iLenTAG + 1)) == NULL) {
+ /* truncate message, better than completely loosing it... */
+ pBuf = pMsg->TAG.szBuf;
+ pMsg->iLenTAG = CONF_TAG_BUFSIZE - 1;
+ } else {
+ pMsg->TAG.pszTAG = pBuf;
+ }
+ }
+
+ memcpy(pBuf, pszBuf, pMsg->iLenTAG);
+ pBuf[pMsg->iLenTAG] = '\0'; /* this also works with truncation! */
+}
+
+
+/* This function tries to emulate the TAG if none is
+ * set. Its primary purpose is to provide an old-style TAG
+ * when a syslog-protocol message has been received. Then,
+ * the tag is APP-NAME "[" PROCID "]". The function first checks
+ * if there is a TAG and, if not, if it can emulate it.
+ * rgerhards, 2005-11-24
+ */
+static void ATTR_NONNULL(1)
+tryEmulateTAG(smsg_t *const pM, const sbool bLockMutex)
+{
+ size_t lenTAG;
+ uchar bufTAG[CONF_TAG_MAXSIZE];
+ assert(pM != NULL);
+
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+ if(pM->iLenTAG > 0) {
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+ return; /* done, no need to emulate */
+ }
+
+ if(msgGetProtocolVersion(pM) == 1) {
+ if(!strcmp(getPROCID(pM, MUTEX_ALREADY_LOCKED), "-")) {
+ /* no process ID, use APP-NAME only */
+ MsgSetTAG(pM, (uchar*) getAPPNAME(pM, MUTEX_ALREADY_LOCKED),
+ getAPPNAMELen(pM, MUTEX_ALREADY_LOCKED));
+ } else {
+ /* now we can try to emulate */
+ lenTAG = snprintf((char*)bufTAG, CONF_TAG_MAXSIZE, "%s[%s]",
+ getAPPNAME(pM, MUTEX_ALREADY_LOCKED), getPROCID(pM, MUTEX_ALREADY_LOCKED));
+ bufTAG[sizeof(bufTAG)-1] = '\0'; /* just to make sure... */
+ MsgSetTAG(pM, bufTAG, lenTAG);
+ }
+ /* Signal change in TAG for acquireProgramName */
+ pM->iLenPROGNAME = -1;
+ }
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+}
+
+
+void ATTR_NONNULL(2,3)
+getTAG(smsg_t * const pM, uchar **const ppBuf, int *const piLen, const sbool bLockMutex)
+{
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+
+ if(pM == NULL) {
+ *ppBuf = UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ if(pM->iLenTAG == 0)
+ tryEmulateTAG(pM, MUTEX_ALREADY_LOCKED);
+ if(pM->iLenTAG == 0) {
+ *ppBuf = UCHAR_CONSTANT("");
+ *piLen = 0;
+ } else {
+ *ppBuf = (pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG;
+ *piLen = pM->iLenTAG;
+ }
+ }
+
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+}
+
+
+int getHOSTNAMELen(smsg_t * const pM)
+{
+ if(pM == NULL)
+ return 0;
+ else
+ if(pM->pszHOSTNAME == NULL) {
+ resolveDNS(pM);
+ if(pM->rcvFrom.pRcvFrom == NULL)
+ return 0;
+ else
+ return prop.GetStringLen(pM->rcvFrom.pRcvFrom);
+ } else
+ return pM->iLenHOSTNAME;
+}
+
+
+const char *getHOSTNAME(smsg_t * const pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszHOSTNAME == NULL) {
+ resolveDNS(pM);
+ if(pM->rcvFrom.pRcvFrom == NULL) {
+ return "";
+ } else {
+ uchar *psz;
+ int len;
+ prop.GetString(pM->rcvFrom.pRcvFrom, &psz, &len);
+ return (char*) psz;
+ }
+ } else {
+ return (char*) pM->pszHOSTNAME;
+ }
+}
+
+
+uchar *getRcvFrom(smsg_t * const pM)
+{
+ uchar *psz;
+ int len;
+
+ if(pM == NULL) {
+ psz = UCHAR_CONSTANT("");
+ } else {
+ resolveDNS(pM);
+ if(pM->rcvFrom.pRcvFrom == NULL)
+ psz = UCHAR_CONSTANT("");
+ else
+ prop.GetString(pM->rcvFrom.pRcvFrom, &psz, &len);
+ }
+ return psz;
+}
+
+
+/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object
+ */
+rsRetVal MsgSetStructuredData(smsg_t * const pMsg, const char* pszStrucData)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pMsg, msg);
+ free(pMsg->pszStrucData);
+ CHKmalloc(pMsg->pszStrucData = (uchar*)strdup(pszStrucData));
+ pMsg->lenStrucData = strlen(pszStrucData);
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the "STRUCTURED-DATA" as sz string, including length */
+void
+MsgGetStructuredData(smsg_t * const pM, uchar **pBuf, rs_size_t *len)
+{
+ MsgLock(pM);
+ if(pM->pszStrucData == NULL) {
+ *pBuf = UCHAR_CONSTANT("-"),
+ *len = 1;
+ } else {
+ *pBuf = pM->pszStrucData,
+ *len = pM->lenStrucData;
+ }
+ MsgUnlock(pM);
+}
+
+/* get the "programname" as sz string
+ * rgerhards, 2005-10-19
+ */
+uchar * ATTR_NONNULL(1)
+getProgramName(smsg_t *const pM, const sbool bLockMutex)
+{
+ if(bLockMutex == LOCK_MUTEX) {
+ MsgLock(pM);
+ }
+
+ if(pM->iLenPROGNAME == -1) {
+ if(pM->iLenTAG == 0) {
+ uchar *pRes;
+ rs_size_t bufLen = -1;
+ getTAG(pM, &pRes, &bufLen, MUTEX_ALREADY_LOCKED);
+ }
+ acquireProgramName(pM);
+ }
+
+ if(bLockMutex == LOCK_MUTEX) {
+ MsgUnlock(pM);
+ }
+ return (pM->iLenPROGNAME < CONF_PROGNAME_BUFSIZE) ? pM->PROGNAME.szBuf
+ : pM->PROGNAME.ptr;
+}
+
+
+
+/* check if we have a APPNAME, and, if not, try to acquire/emulate it.
+ * rgerhards, 2009-06-26
+ */
+static void ATTR_NONNULL(1)
+prepareAPPNAME(smsg_t *const pM, const sbool bLockMutex)
+{
+ if(pM->pCSAPPNAME == NULL) {
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+
+ /* re-query as things might have changed during locking */
+ if(pM->pCSAPPNAME == NULL) {
+ if(msgGetProtocolVersion(pM) == 0) {
+ /* only then it makes sense to emulate */
+ MsgSetAPPNAME(pM, (char*)getProgramName(pM, MUTEX_ALREADY_LOCKED));
+ }
+ }
+
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+ }
+}
+
+/* rgerhards, 2005-11-24
+ */
+char *getAPPNAME(smsg_t * const pM, const sbool bLockMutex)
+{
+ uchar *pszRet;
+
+ assert(pM != NULL);
+ if(bLockMutex == LOCK_MUTEX)
+ MsgLock(pM);
+ prepareAPPNAME(pM, MUTEX_ALREADY_LOCKED);
+ if(pM->pCSAPPNAME == NULL)
+ pszRet = UCHAR_CONSTANT("");
+ else
+ pszRet = rsCStrGetSzStrNoNULL(pM->pCSAPPNAME);
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
+ return (char*)pszRet;
+}
+
+/* rgerhards, 2005-11-24
+ */
+static int getAPPNAMELen(smsg_t * const pM, const sbool bLockMutex)
+{
+ assert(pM != NULL);
+ prepareAPPNAME(pM, bLockMutex);
+ return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME);
+}
+
+/* rgerhards 2008-09-10: set pszInputName in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-16
+ */
+void MsgSetInputName(smsg_t *pThis, prop_t *inputName)
+{
+ assert(pThis != NULL);
+
+ prop.AddRef(inputName);
+ if(pThis->pInputName != NULL)
+ prop.Destruct(&pThis->pInputName);
+ pThis->pInputName = inputName;
+}
+
+/* Set default TZ. Note that at most 7 chars are set, as we would
+ * otherwise overrun our buffer!
+ */
+void MsgSetDfltTZ(smsg_t *pThis, char *tz)
+{
+ strncpy(pThis->dfltTZ, tz, 7);
+ pThis->dfltTZ[7] = '\0'; /* ensure 0-Term in case of overflow! */
+}
+
+
+/* Set the pfrominet socket store, so that we can obtain the peer at some
+ * later time. Note that we do not check if pRcvFrom is already set, so this
+ * function must only be called during message creation.
+ * NOTE: msgFlags is NOT set. While this is somewhat a violation of layers,
+ * it is done because it gains us some performance. So the caller must make
+ * sure the message flags are properly maintained. For all current callers,
+ * this is always the case and without extra effort required.
+ * rgerhards, 2009-11-17
+ */
+rsRetVal
+msgSetFromSockinfo(smsg_t *pThis, struct sockaddr_storage *sa){
+ DEFiRet;
+ assert(pThis->rcvFrom.pRcvFrom == NULL);
+
+ CHKmalloc(pThis->rcvFrom.pfrominet = malloc(sizeof(struct sockaddr_storage)));
+ memcpy(pThis->rcvFrom.pfrominet, sa, sizeof(struct sockaddr_storage));
+
+finalize_it:
+ RETiRet;
+}
+
+/* rgerhards 2008-09-10: set RcvFrom name in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-30
+ */
+void MsgSetRcvFrom(smsg_t *pThis, prop_t *new)
+{
+ prop.AddRef(new);
+ MsgSetRcvFromWithoutAddRef(pThis, new);
+}
+
+
+/* This is used to set the property via a string. This function should not be
+ * called if there is a reliable way for a caller to make sure that the
+ * same name can be used across multiple messages. However, if it can not
+ * ensure that, calling this function is the second best thing, because it
+ * will re-use the previously created property if it contained the same
+ * name (but it works only for the immediate previous).
+ * rgerhards, 2009-06-31
+ */
+void MsgSetRcvFromStr(smsg_t * const pThis, const uchar *psz, const int len, prop_t **ppProp)
+{
+ assert(pThis != NULL);
+ assert(ppProp != NULL);
+
+ prop.CreateOrReuseStringProp(ppProp, psz, len);
+ MsgSetRcvFrom(pThis, *ppProp);
+}
+
+
+/* set RcvFromIP name in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-30
+ */
+rsRetVal MsgSetRcvFromIP(smsg_t *pThis, prop_t *new)
+{
+ assert(pThis != NULL);
+
+ prop.AddRef(new);
+ MsgSetRcvFromIPWithoutAddRef(pThis, new);
+ return RS_RET_OK;
+}
+
+
+/* This is used to set the property via a string. This function should not be
+ * called if there is a reliable way for a caller to make sure that the
+ * same name can be used across multiple messages. However, if it can not
+ * ensure that, calling this function is the second best thing, because it
+ * will re-use the previously created property if it contained the same
+ * name (but it works only for the immediate previous).
+ * rgerhards, 2009-06-31
+ */
+rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+
+ CHKiRet(prop.CreateOrReuseStringProp(ppProp, psz, len));
+ MsgSetRcvFromIP(pThis, *ppProp);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* rgerhards 2004-11-09: set HOSTNAME in msg object
+ * rgerhards, 2007-06-21:
+ * Does not return anything. If an error occurs, the hostname is
+ * simply not set. I have changed this behaviour. The only problem
+ * we can run into is memory shortage. If we have such, it is better
+ * to loose the hostname than the full message. So we silently ignore
+ * that problem and hope that memory will be available the next time
+ * we need it. The rest of the code already knows how to handle an
+ * unset HOSTNAME.
+ */
+void MsgSetHOSTNAME(smsg_t *pThis, const uchar* pszHOSTNAME, const int lenHOSTNAME)
+{
+ assert(pThis != NULL);
+
+ freeHOSTNAME(pThis);
+
+ pThis->iLenHOSTNAME = lenHOSTNAME;
+ if(pThis->iLenHOSTNAME < CONF_HOSTNAME_BUFSIZE) {
+ /* small enough: use fixed buffer (faster!) */
+ pThis->pszHOSTNAME = pThis->szHOSTNAME;
+ } else if((pThis->pszHOSTNAME = (uchar*) malloc(pThis->iLenHOSTNAME + 1)) == NULL) {
+ /* truncate message, better than completely loosing it... */
+ pThis->pszHOSTNAME = pThis->szHOSTNAME;
+ pThis->iLenHOSTNAME = CONF_HOSTNAME_BUFSIZE - 1;
+ }
+
+ memcpy(pThis->pszHOSTNAME, pszHOSTNAME, pThis->iLenHOSTNAME);
+ pThis->pszHOSTNAME[pThis->iLenHOSTNAME] = '\0'; /* this also works with truncation! */
+}
+
+
+/* set the offset of the MSG part into the raw msg buffer
+ * Note that the offset may be higher than the length of the raw message
+ * (exactly by one). This can happen if we have a message that does not
+ * contain any MSG part.
+ */
+void MsgSetMSGoffs(smsg_t * const pMsg, int offs)
+{
+ ISOBJ_TYPE_assert(pMsg, msg);
+ pMsg->offMSG = offs;
+ if(offs > pMsg->iLenRawMsg) {
+ assert((int)offs - 1 == pMsg->iLenRawMsg);
+ pMsg->iLenMSG = 0;
+ } else {
+ pMsg->iLenMSG = pMsg->iLenRawMsg - offs;
+ }
+}
+
+
+/* replace the MSG part of a message. The update actually takes place inside
+ * rawmsg.
+ * There are two cases: either the new message will be larger than the new msg
+ * or it will be less than or equal. If it is less than or equal, we can utilize
+ * the previous message buffer. If it is larger, we can utilize the smsg_t-included
+ * message buffer if it fits in there. If this is not the case, we need to alloc
+ * a new, larger, chunk and copy over the data to it. Note that this function is
+ * (hopefully) relatively seldom being called, so some performance impact is
+ * uncritical. In any case, pszMSG is copied, so if it was dynamically allocated,
+ * the caller is responsible for freeing it.
+ * rgerhards, 2009-06-23
+ */
+rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar* pszMSG, int lenMSG)
+{
+ int lenNew;
+ uchar *bufNew;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, msg);
+ assert(pszMSG != NULL);
+
+ lenNew = pThis->iLenRawMsg + lenMSG - pThis->iLenMSG;
+ if(lenMSG > pThis->iLenMSG && lenNew >= CONF_RAWMSG_BUFSIZE) {
+ /* we have lost our "bet" and need to alloc a new buffer ;) */
+ CHKmalloc(bufNew = malloc(lenNew + 1));
+ memcpy(bufNew, pThis->pszRawMsg, pThis->offMSG);
+ if(pThis->pszRawMsg != pThis->szRawMsg)
+ free(pThis->pszRawMsg);
+ pThis->pszRawMsg = bufNew;
+ }
+
+ if(lenMSG > 0)
+ memcpy(pThis->pszRawMsg + pThis->offMSG, pszMSG, lenMSG);
+ pThis->pszRawMsg[lenNew] = '\0'; /* this also works with truncation! */
+ pThis->iLenRawMsg = lenNew;
+ pThis->iLenMSG = lenMSG;
+
+finalize_it:
+ RETiRet;
+}
+
+/* truncate the (raw) message to configured max size.
+ * The function makes sure that the stored rawmsg remains
+ * properly terminated by '\0'.
+ */
+void ATTR_NONNULL()
+MsgTruncateToMaxSize(smsg_t *const pThis)
+{
+ ISOBJ_TYPE_assert(pThis, msg);
+ const int maxMsgSize = glblGetMaxLine(runConf);
+ assert(pThis->iLenRawMsg > maxMsgSize);
+
+ const int deltaSize = pThis->iLenRawMsg - maxMsgSize;
+ pThis->pszRawMsg[maxMsgSize] = '\0';
+ pThis->iLenRawMsg = maxMsgSize;
+ if(pThis->iLenMSG < deltaSize) {
+ pThis->iLenMSG = 0;
+ } else {
+ pThis->iLenMSG -= deltaSize;
+ }
+}
+
+/* set raw message in message object. Size of message is provided.
+ * The function makes sure that the stored rawmsg is properly
+ * terminated by '\0'.
+ * rgerhards, 2009-06-16
+ */
+void ATTR_NONNULL()
+MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMsg)
+{
+ ISOBJ_TYPE_assert(pThis, msg);
+ int deltaSize;
+ if(pThis->pszRawMsg != pThis->szRawMsg)
+ free(pThis->pszRawMsg);
+
+ deltaSize = (int) lenMsg - pThis->iLenRawMsg; /* value < 0 in truncation case! */
+ pThis->iLenRawMsg = lenMsg;
+ if(pThis->iLenRawMsg < CONF_RAWMSG_BUFSIZE) {
+ /* small enough: use fixed buffer (faster!) */
+ pThis->pszRawMsg = pThis->szRawMsg;
+ } else if((pThis->pszRawMsg = (uchar*) malloc(pThis->iLenRawMsg + 1)) == NULL) {
+ /* truncate message, better than completely loosing it... */
+ pThis->pszRawMsg = pThis->szRawMsg;
+ pThis->iLenRawMsg = CONF_RAWMSG_BUFSIZE - 1;
+ }
+
+ memcpy(pThis->pszRawMsg, pszRawMsg, pThis->iLenRawMsg);
+ pThis->pszRawMsg[pThis->iLenRawMsg] = '\0'; /* this also works with truncation! */
+ /* correct other information */
+ if(pThis->iLenRawMsg > pThis->offMSG)
+ pThis->iLenMSG += deltaSize;
+ else
+ pThis->iLenMSG = 0;
+}
+
+
+/* set raw message in message object. Size of message is not provided. This
+ * function should only be used when it is unavoidable (and over time we should
+ * try to remove it altogether).
+ * rgerhards, 2009-06-16
+ */
+void MsgSetRawMsgWOSize(smsg_t * const pMsg, char* pszRawMsg)
+{
+ MsgSetRawMsg(pMsg, pszRawMsg, strlen(pszRawMsg));
+}
+
+
+/* create textual representation of facility and severity.
+ * The variable pRes must point to a user-supplied buffer of
+ * at least 20 characters.
+ */
+static uchar *
+textpri(const smsg_t *const __restrict__ pMsg)
+{
+ int lenfac = len_syslog_fac_names[pMsg->iFacility];
+ int lensev = len_syslog_severity_names[pMsg->iSeverity];
+ int totlen = lenfac + 1 + lensev + 1;
+ char *pRes = malloc(totlen);
+ if(pRes != NULL) {
+ memcpy(pRes, syslog_fac_names[pMsg->iFacility], lenfac);
+ pRes[lenfac] = '.';
+ memcpy(pRes+lenfac+1, syslog_severity_names[pMsg->iSeverity], lensev+1 /* for \0! */);
+ }
+ return (uchar*)pRes;
+}
+
+
+/* This function returns the current date in different
+ * variants. It is used to construct the $NOW series of
+ * system properties. The returned buffer must be freed
+ * by the caller when no longer needed. If the function
+ * can not allocate memory, it returns a NULL pointer.
+ * Added 2007-07-10 rgerhards
+ */
+typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR,
+ NOW_HHOUR, NOW_QHOUR, NOW_MINUTE, NOW_WDAY } eNOWType;
+#define tmpBUFSIZE 16 /* size of formatting buffer */
+static uchar *getNOW(eNOWType eNow, struct syslogTime *t, const int inUTC)
+{
+ uchar *pBuf;
+ struct syslogTime tt;
+
+ if((pBuf = (uchar*) malloc(tmpBUFSIZE)) == NULL) {
+ return NULL;
+ }
+
+ if(t == NULL) { /* can happen if called via script engine */
+ datetime.getCurrTime(&tt, NULL, inUTC);
+ t = &tt;
+ }
+
+ if(t->year == 0 || t->inUTC != inUTC) { /* not yet set! */
+ datetime.getCurrTime(t, NULL, inUTC);
+ }
+
+ switch(eNow) {
+ case NOW_NOW:
+ memcpy(pBuf, two_digits[t->year/100], 2);
+ memcpy(pBuf+2, two_digits[t->year%100], 2);
+ pBuf[4] = '-';
+ memcpy(pBuf+5, two_digits[(int)t->month], 2);
+ pBuf[7] = '-';
+ memcpy(pBuf+8, two_digits[(int)t->day], 3);
+ break;
+ case NOW_YEAR:
+ memcpy(pBuf, two_digits[t->year/100], 2);
+ memcpy(pBuf+2, two_digits[t->year%100], 3);
+ break;
+ case NOW_MONTH:
+ memcpy(pBuf, two_digits[(int)t->month], 3);
+ break;
+ case NOW_DAY:
+ memcpy(pBuf, two_digits[(int)t->day], 3);
+ break;
+ case NOW_HOUR:
+ memcpy(pBuf, two_digits[(int)t->hour], 3);
+ break;
+ case NOW_HHOUR:
+ memcpy(pBuf, two_digits[t->minute/30], 3);
+ break;
+ case NOW_QHOUR:
+ memcpy(pBuf, two_digits[t->minute/15], 3);
+ break;
+ case NOW_MINUTE:
+ memcpy(pBuf, two_digits[(int)t->minute], 3);
+ break;
+ case NOW_WDAY:
+ memcpy(pBuf, one_digit[(int)t->wday], 2);
+ break;
+ }
+
+ return(pBuf);
+}
+#undef tmpBUFSIZE /* clean up */
+
+
+/* helper function to obtain correct JSON root and mutex depending on
+ * property type (essentially based on the property id. If a non-json
+ * property id is given the function errors out.
+ * Note well: jroot points to a pointer to a (ptr to a) json object.
+ * This is necessary because the caller needs a pointer to where the
+ * json object pointer is stored, that in turn is necessary because
+ * while the address of the actual pointer stays stable, the actual
+ * content is volatile until the caller has locked the variable tree,
+ * which we DO NOT do to keep calling semantics simple.
+ */
+static rsRetVal ATTR_NONNULL()
+getJSONRootAndMutex(smsg_t *const pMsg, const propid_t id,
+ struct json_object ***const jroot, pthread_mutex_t **const mut)
+{
+ DEFiRet;
+ assert(jroot != NULL); /* asserts also help static analyzer! */
+ assert(mut != NULL);
+ assert(*mut == NULL); /* caller shall have initialized this one! */
+ assert(id == PROP_CEE || id == PROP_LOCAL_VAR || id == PROP_GLOBAL_VAR);
+
+ if(id == PROP_CEE) {
+ *mut = &pMsg->mut;
+ *jroot = &pMsg->json;
+ } else if(id == PROP_LOCAL_VAR) {
+ *mut = &pMsg->mut;
+ *jroot = &pMsg->localvars;
+ } else if(id == PROP_GLOBAL_VAR) {
+ *mut = &glblVars_lock;
+ *jroot = &global_var_root;
+ } else {
+ LogError(0, RS_RET_NON_JSON_PROP, "internal error: "
+ "getJSONRootAndMutex; invalid property id %d", id);
+ iRet = RS_RET_NON_JSON_PROP;
+ }
+
+ RETiRet;
+}
+
+/* basically same function, but does not use property id, but the the
+ * variable name type indicator (char after starting $, e.g. $!myvar --> CEE)
+ */
+static rsRetVal ATTR_NONNULL()
+getJSONRootAndMutexByVarChar(smsg_t *const pMsg, const char c,
+ struct json_object ***const jroot, pthread_mutex_t **const mut)
+{
+ DEFiRet;
+ propid_t id;
+ assert(c == '!' || c == '.' || c == '/');
+
+ switch(c) {
+ case '!':
+ id = PROP_CEE;
+ break;
+ case '.':
+ id = PROP_LOCAL_VAR;
+ break;
+ case '/':
+ id = PROP_GLOBAL_VAR;
+ break;
+ default:
+ LogError(0, RS_RET_NON_JSON_PROP, "internal error: "
+ "getJSONRootAndMutex; invalid indicator char %c(%2.2x)", c, c);
+ ABORT_FINALIZE(RS_RET_NON_JSON_PROP);
+ break;
+ }
+ iRet = getJSONRootAndMutex(pMsg, id, jroot, mut);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Get a JSON-Property as string value (used for various types of JSON-based vars) */
+rsRetVal
+getJSONPropVal(smsg_t * const pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen,
+ unsigned short *pbMustBeFreed)
+{
+ uchar *leaf;
+ struct json_object **jroot;
+ struct json_object *parent;
+ struct json_object *field;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ *pRes = NULL;
+ CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut));
+ pthread_mutex_lock(mut);
+
+ if(*jroot == NULL) FINALIZE;
+
+ if(!strcmp((char*)pProp->name, "!")) {
+ field = *jroot;
+ } else {
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0));
+ if(jsonVarExtract(parent, (char*)leaf, &field) == FALSE)
+ field = NULL;
+ }
+ if(field != NULL) {
+ *pRes = (uchar*) strdup(json_object_get_string(field));
+ *buflen = (int) ustrlen(*pRes);
+ *pbMustBeFreed = 1;
+ }
+
+finalize_it:
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ if(*pRes == NULL) {
+ /* could not find any value, so set it to empty */
+ *pRes = (unsigned char*)"";
+ *pbMustBeFreed = 0;
+ }
+ RETiRet;
+}
+
+
+/* Get a JSON-based-variable as native json object, except
+ * when it is string type, in which case a string is returned.
+ * This is an optimization to not use JSON when not strictly
+ * necessary. This in turn is helpful, as calling json-c is
+ * *very* expensive due to our need for locking and deep
+ * copies.
+ * The caller needs to check pjson and pcstr: one of them
+ * is non-NULL and contains the return value. Note that
+ * the caller is responsible for freeing the string pointer
+ * it if is being returned.
+ */
+rsRetVal
+msgGetJSONPropJSONorString(smsg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson,
+ uchar **pcstr)
+{
+ struct json_object **jroot;
+ uchar *leaf;
+ struct json_object *parent;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ *pjson = NULL, *pcstr = NULL;
+
+ CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut));
+ pthread_mutex_lock(mut);
+ if(!strcmp((char*)pProp->name, "!")) {
+ *pjson = *jroot;
+ FINALIZE;
+ }
+ if(*jroot == NULL) {
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0));
+ if(jsonVarExtract(parent, (char*)leaf, pjson) == FALSE) {
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ if(*pjson == NULL) {
+ /* we had a NULL json object and represent this as empty string */
+ *pcstr = (uchar*) strdup("");
+ } else {
+ if(json_object_get_type(*pjson) == json_type_string) {
+ *pcstr = (uchar*) strdup(json_object_get_string(*pjson));
+ *pjson = NULL;
+ }
+ }
+
+finalize_it:
+ /* we need a deep copy, as another thread may modify the object */
+ if(*pjson != NULL)
+ *pjson = jsonDeepCopy(*pjson);
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ RETiRet;
+}
+
+
+
+/* Get a JSON-based-variable as native json object */
+rsRetVal
+msgGetJSONPropJSON(smsg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson)
+{
+ struct json_object **jroot;
+ uchar *leaf;
+ struct json_object *parent;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ *pjson = NULL;
+
+ CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut));
+ pthread_mutex_lock(mut);
+
+ if(!strcmp((char*)pProp->name, "!")) {
+ *pjson = *jroot;
+ FINALIZE;
+ }
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0));
+ if(jsonVarExtract(parent, (char*)leaf, pjson) == FALSE) {
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+finalize_it:
+ /* we need a deep copy, as another thread may modify the object */
+ if(*pjson != NULL)
+ *pjson = jsonDeepCopy(*pjson);
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ RETiRet;
+}
+
+
+/* Helper for jsonAddVal(), to be called onces we know there are actually
+ * json escapes inside the string. If so, this function takes over.
+ * Splitting the functions permits us to make some performance optimizations.
+ * For further details, see jsonAddVal().
+ */
+static rsRetVal ATTR_NONNULL(1, 4)
+jsonAddVal_escaped(uchar *const pSrc,
+ const unsigned buflen,
+ const unsigned len_none_escaped_head,
+ es_str_t **dst,
+ const int escapeAll)
+{
+ unsigned char c;
+ es_size_t i;
+ char numbuf[4];
+ unsigned ni;
+ unsigned char nc;
+ int j;
+ uchar wrkbuf[100000];
+ size_t dst_realloc_size;
+ size_t dst_size;
+ uchar *dst_base;
+ uchar *dst_w;
+ uchar *newbuf;
+ DEFiRet;
+
+ assert(len_none_escaped_head <= buflen);
+ /* first copy over unescaped head string */
+ if(len_none_escaped_head+10 > sizeof(wrkbuf)) {
+ dst_size = 2 * len_none_escaped_head;
+ CHKmalloc(dst_base = malloc(dst_size));
+ } else {
+ dst_size = sizeof(wrkbuf);
+ dst_base = wrkbuf;
+ }
+ dst_realloc_size = dst_size - 10; /* some buffer for escaping */
+ dst_w = dst_base;
+ memcpy(dst_w, pSrc, len_none_escaped_head);
+ dst_w += len_none_escaped_head;
+
+ /* now do the escaping */
+ for(i = len_none_escaped_head ; i < buflen ; ++i) {
+ const size_t dst_offset = dst_w - dst_base;
+ if(dst_offset >= dst_realloc_size) {
+ const size_t new_size = 2 * dst_size;
+ if(dst_base == wrkbuf) {
+ CHKmalloc(newbuf = malloc(new_size));
+ memcpy(newbuf, dst_base, dst_offset);
+ } else {
+ CHKmalloc(newbuf = realloc(dst_base, new_size));
+ }
+ dst_size = new_size;
+ dst_realloc_size = new_size - 10; /* some buffer for escaping */
+ dst_base = newbuf;
+ dst_w = dst_base + dst_offset;
+ }
+ c = pSrc[i];
+ if( (c >= 0x30 && c <= 0x5b)
+ || (c >= 0x23 && c <= 0x2e)
+ || (c >= 0x5d /* && c <= 0x10FFFF*/)
+ || c == 0x20 || c == 0x21) {
+ /* no need to escape */
+ *dst_w++ = c;
+ } else {
+ /* we must escape, try RFC4627-defined special sequences first */
+ switch(c) {
+ case '\0':
+ *dst_w++ = '\\';
+ *dst_w++ = 'u';
+ *dst_w++ = '0';
+ *dst_w++ = '0';
+ *dst_w++ = '0';
+ *dst_w++ = '0';
+ break;
+ case '\"':
+ *dst_w++ = '\\';
+ *dst_w++ = '"';
+ break;
+ case '/':
+ *dst_w++ = '\\';
+ *dst_w++ = '/';
+ break;
+ case '\\':
+ if (escapeAll == RSFALSE) {
+ ni = i + 1;
+ if (ni <= buflen) {
+ nc = pSrc[ni];
+
+ /* Attempt to not double encode */
+ if ( nc == '"' || nc == '/' || nc == '\\' || nc == 'b' || nc == 'f'
+ || nc == 'n' || nc == 'r' || nc == 't' || nc == 'u') {
+ *dst_w++ = c;
+ *dst_w++ = nc;
+ i = ni;
+ break;
+ }
+ }
+ }
+ *dst_w++ = '\\';
+ *dst_w++ = '\\';
+ break;
+ case '\010':
+ *dst_w++ = '\\';
+ *dst_w++ = 'b';
+ break;
+ case '\014':
+ *dst_w++ = '\\';
+ *dst_w++ = 'f';
+ break;
+ case '\n':
+ *dst_w++ = '\\';
+ *dst_w++ = 'n';
+ break;
+ case '\r':
+ *dst_w++ = '\\';
+ *dst_w++ = 'r';
+ break;
+ case '\t':
+ *dst_w++ = '\\';
+ *dst_w++ = 't';
+ break;
+ default:
+ /* TODO : proper Unicode encoding (see header comment) */
+ for(j = 0 ; j < 4 ; ++j) {
+ numbuf[3-j] = hexdigit[c % 16];
+ c = c / 16;
+ }
+ *dst_w++ = '\\';
+ *dst_w++ = 'u';
+ *dst_w++ = numbuf[0];
+ *dst_w++ = numbuf[1];
+ *dst_w++ = numbuf[2];
+ *dst_w++ = numbuf[3];
+ break;
+ }
+ }
+ }
+ if(*dst == NULL) {
+ *dst = es_newStrFromBuf((char *) dst_base, dst_w - dst_base);
+ } else {
+ es_addBuf(dst, (const char *) dst_base, dst_w - dst_base);
+ }
+finalize_it:
+ if(dst_base != wrkbuf) {
+ free(dst_base);
+ }
+ RETiRet;
+}
+
+
+/* Encode a JSON value and add it to provided string. Note that
+ * the string object may be NULL. In this case, it is created
+ * if and only if escaping is needed. if escapeAll is false, previously
+ * escaped strings are left as is
+ */
+static rsRetVal ATTR_NONNULL(1, 3)
+jsonAddVal(uchar *const pSrc, const unsigned buflen, es_str_t **dst, const int escapeAll)
+{
+ es_size_t i;
+ DEFiRet;
+
+ for(i = 0 ; i < buflen ; ++i) {
+ const uchar c = pSrc[i];
+ if(! ( (c >= 0x30 && c <= 0x5b)
+ || (c >= 0x23 && c <= 0x2e)
+ || (c >= 0x5d /* && c <= 0x10FFFF*/)
+ || c == 0x20 || c == 0x21)
+ ) {
+ iRet = jsonAddVal_escaped(pSrc, buflen, i, dst, escapeAll);
+ FINALIZE;
+ }
+ }
+ if(*dst != NULL) {
+ es_addBuf(dst, (const char *) pSrc, buflen);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* encode a property in JSON escaped format. This is a helper
+ * to MsgGetProp. It needs to update all provided parameters.
+ * For performance reasons, we begin to copy the string only
+ * when we recognice that we actually need to do some escaping.
+ * rgerhards, 2012-03-16
+ */
+static rsRetVal
+jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen, int escapeAll)
+{
+ unsigned buflen;
+ uchar *pSrc;
+ es_str_t *dst = NULL;
+ DEFiRet;
+
+ pSrc = *ppRes;
+ buflen = (*pBufLen == -1) ? (int) ustrlen(pSrc) : *pBufLen;
+ CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll));
+
+ if(dst != NULL) {
+ /* we updated the string and need to replace the
+ * previous data.
+ */
+ if(*pbMustBeFreed)
+ free(*ppRes);
+ *ppRes = (uchar*)es_str2cstr(dst, NULL);
+ *pbMustBeFreed = 1;
+ *pBufLen = -1;
+ es_deleteStr(dst);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Format a property as JSON field, that means
+ * "name"="value"
+ * where value is JSON-escaped (here we assume that the name
+ * only contains characters from the valid character set).
+ * Note: this function duplicates code from jsonEncode().
+ * TODO: these two functions should be combined, at least if
+ * that makes any sense from a performance PoV - definitely
+ * something to consider at a later stage. rgerhards, 2012-04-19
+ */
+static rsRetVal ATTR_NONNULL()
+jsonField(const struct templateEntry *const pTpe,
+ uchar **const ppRes,
+ unsigned short *const pbMustBeFreed,
+ int *const pBufLen,
+ int escapeAll)
+{
+ unsigned buflen;
+ uchar *pSrc;
+ es_str_t *dst = NULL;
+ int is_numeric = 1;
+ DEFiRet;
+
+ pSrc = *ppRes;
+ buflen = (*pBufLen == -1) ? (int) ustrlen(pSrc) : *pBufLen;
+dbgprintf("jsonEncode: datatype: %u, onEmpty: %u val %*s\n", (unsigned) pTpe->data.field.options.dataType,
+(unsigned) pTpe->data.field.options.onEmpty, buflen, pSrc);
+ if(buflen == 0) {
+ if(pTpe->data.field.options.onEmpty == TPE_DATAEMPTY_SKIP) {
+ FINALIZE;
+ }
+ is_numeric = 0;
+ }
+ /* we hope we have only few escapes... */
+ dst = es_newStr(buflen+pTpe->lenFieldName+15);
+ es_addChar(&dst, '"');
+ es_addBuf(&dst, (char*)pTpe->fieldName, pTpe->lenFieldName);
+ es_addBufConstcstr(&dst, "\":");
+ if(buflen == 0 && pTpe->data.field.options.onEmpty == TPE_DATAEMPTY_NULL) {
+ es_addBufConstcstr(&dst, "null");
+ } else {
+ if(pTpe->data.field.options.dataType == TPE_DATATYPE_AUTO) {
+ for(unsigned i = 0 ; i < buflen ; ++i) {
+ if(pSrc[i] < '0' || pSrc[i] > '9') {
+ is_numeric = 0;
+ break;
+ }
+ }
+ if(!is_numeric) {
+ es_addChar(&dst, '"');
+ }
+ CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll));
+ if(!is_numeric) {
+ es_addChar(&dst, '"');
+ }
+ } else if(pTpe->data.field.options.dataType == TPE_DATATYPE_STRING) {
+ es_addChar(&dst, '"');
+ CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll));
+ es_addChar(&dst, '"');
+ } else if(pTpe->data.field.options.dataType == TPE_DATATYPE_NUMBER) {
+ if(buflen == 0) {
+ es_addChar(&dst, '0');
+ } else {
+ CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll));
+ }
+ } else if(pTpe->data.field.options.dataType == TPE_DATATYPE_BOOL) {
+ if(buflen == 1 && *pSrc == '0') {
+ es_addBufConstcstr(&dst, "false");
+ } else {
+ es_addBufConstcstr(&dst, "true");
+ }
+ }
+ }
+
+ if(*pbMustBeFreed)
+ free(*ppRes);
+ /* we know we do not have \0 chars - so the size does not change */
+ *pBufLen = es_strlen(dst);
+ *ppRes = (uchar*)es_str2cstr(dst, NULL);
+ *pbMustBeFreed = 1;
+ es_deleteStr(dst);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function returns a string-representation of the
+ * requested message property. This is a generic function used
+ * to abstract properties so that these can be easier
+ * queried. Returns NULL if property could not be found.
+ * Actually, this function is a big if..elseif. What it does
+ * is simply to map property names (from MonitorWare) to the
+ * message object data fields.
+ *
+ * In case we need string forms of propertis we do not
+ * yet have in string form, we do a memory allocation that
+ * is sufficiently large (in all cases). Once the string
+ * form has been obtained, it is saved until the Msg object
+ * is finally destroyed. This is so that we save the processing
+ * time in the (likely) case that this property is requested
+ * again. It also saves us a lot of dynamic memory management
+ * issues in the upper layers, because we so can guarantee that
+ * the buffer will remain static AND available during the lifetime
+ * of the object. Please note that both the max size allocation as
+ * well as keeping things in memory might like look like a
+ * waste of memory (some might say it actually is...) - we
+ * deliberately accept this because performance is more important
+ * to us ;)
+ * rgerhards 2004-11-18
+ * Parameter "bMustBeFreed" is set by this function. It tells the
+ * caller whether or not the string returned must be freed by the
+ * caller itself. It is is 0, the caller MUST NOT free it. If it is
+ * 1, the caller MUST free it. Handling this wrongly leads to either
+ * a memory leak of a program abort (do to double-frees or frees on
+ * the constant memory pool). So be careful to do it right.
+ * rgerhards 2004-11-23
+ * regular expression support contributed by Andres Riancho merged
+ * on 2005-09-13
+ * changed so that it now an be called without a template entry (NULL).
+ * In this case, only the (unmodified) property is returned. This will
+ * be used in selector line processing.
+ * rgerhards 2005-09-15
+ */
+/* a quick helper to save some writing: */
+#define RET_OUT_OF_MEMORY { *pbMustBeFreed = 0;\
+ *pPropLen = sizeof("**OUT OF MEMORY**") - 1; \
+ return(UCHAR_CONSTANT("**OUT OF MEMORY**"));}
+uchar *MsgGetProp(smsg_t *__restrict__ const pMsg, struct templateEntry *__restrict__ const pTpe,
+ msgPropDescr_t *pProp, rs_size_t *__restrict__ const pPropLen,
+ unsigned short *__restrict__ const pbMustBeFreed, struct syslogTime * const ttNow)
+{
+ uchar *pRes; /* result pointer */
+ rs_size_t bufLen = -1; /* length of string or -1, if not known */
+ uchar *pBufStart;
+ uchar *pBuf;
+ int iLen;
+ short iOffs;
+ enum tplFormatTypes datefmt;
+ int bDateInUTC;
+
+ assert(pMsg != NULL);
+ assert(pbMustBeFreed != NULL);
+
+#ifdef FEATURE_REGEXP
+ /* Variables necessary for regular expression matching */
+ size_t nmatch = 10;
+ regmatch_t pmatch[10];
+#endif
+
+ *pbMustBeFreed = 0;
+
+ switch(pProp->id) {
+ case PROP_MSG:
+ pRes = getMSG(pMsg);
+ bufLen = getMSGLen(pMsg);
+ break;
+ case PROP_TIMESTAMP:
+ if(pTpe != NULL) {
+ datefmt = pTpe->data.field.eDateFormat;
+ bDateInUTC = pTpe->data.field.options.bDateInUTC;
+ } else {
+ datefmt = tplFmtDefault;
+ bDateInUTC = 0;
+ }
+ if(bDateInUTC) {
+ pRes = (uchar*)getTimeUTC(&pMsg->tTIMESTAMP, datefmt, pbMustBeFreed);
+ } else {
+ pRes = (uchar*)getTimeReported(pMsg, datefmt);
+ }
+ break;
+ case PROP_HOSTNAME:
+ pRes = (uchar*)getHOSTNAME(pMsg);
+ bufLen = getHOSTNAMELen(pMsg);
+ break;
+ case PROP_SYSLOGTAG:
+ getTAG(pMsg, &pRes, &bufLen, LOCK_MUTEX);
+ break;
+ case PROP_RAWMSG:
+ getRawMsg(pMsg, &pRes, &bufLen);
+ break;
+ case PROP_RAWMSG_AFTER_PRI:
+ getRawMsgAfterPRI(pMsg, &pRes, &bufLen);
+ break;
+ case PROP_INPUTNAME:
+ getInputName(pMsg, &pRes, &bufLen);
+ break;
+ case PROP_FROMHOST:
+ pRes = getRcvFrom(pMsg);
+ break;
+ case PROP_FROMHOST_IP:
+ pRes = getRcvFromIP(pMsg);
+ break;
+ case PROP_PRI:
+ pRes = (uchar*)getPRI(pMsg);
+ break;
+ case PROP_PRI_TEXT:
+ pRes = textpri(pMsg);
+ if(pRes == NULL)
+ RET_OUT_OF_MEMORY;
+ *pbMustBeFreed = 1;
+ break;
+ case PROP_IUT:
+ pRes = UCHAR_CONSTANT("1"); /* always 1 for syslog messages (a MonitorWare thing;)) */
+ bufLen = 1;
+ break;
+ case PROP_SYSLOGFACILITY:
+ pRes = (uchar*)getFacility(pMsg);
+ break;
+ case PROP_SYSLOGFACILITY_TEXT:
+ pRes = (uchar*)getFacilityStr(pMsg);
+ break;
+ case PROP_SYSLOGSEVERITY:
+ pRes = (uchar*)getSeverity(pMsg);
+ break;
+ case PROP_SYSLOGSEVERITY_TEXT:
+ pRes = (uchar*)getSeverityStr(pMsg);
+ break;
+ case PROP_TIMEGENERATED:
+ if(pTpe != NULL) {
+ datefmt = pTpe->data.field.eDateFormat;
+ bDateInUTC = pTpe->data.field.options.bDateInUTC;
+ } else {
+ datefmt = tplFmtDefault;
+ bDateInUTC = 0;
+ }
+ if(bDateInUTC) {
+ pRes = (uchar*)getTimeUTC(&pMsg->tRcvdAt, datefmt, pbMustBeFreed);
+ } else {
+ pRes = (uchar*)getTimeGenerated(pMsg, datefmt);
+ }
+ break;
+ case PROP_PROGRAMNAME:
+ pRes = getProgramName(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_PROTOCOL_VERSION:
+ pRes = (uchar*)getProtocolVersionString(pMsg);
+ break;
+ case PROP_STRUCTURED_DATA:
+ MsgGetStructuredData(pMsg, &pRes, &bufLen);
+ break;
+ case PROP_APP_NAME:
+ pRes = (uchar*)getAPPNAME(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_PROCID:
+ pRes = (uchar*)getPROCID(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_MSGID:
+ pRes = (uchar*)getMSGID(pMsg);
+ break;
+ case PROP_JSONMESG:
+ pRes = (uchar*)msgGetJSONMESG(pMsg);
+ *pbMustBeFreed = 1;
+ break;
+#ifdef USE_LIBUUID
+ case PROP_UUID:
+ getUUID(pMsg, &pRes, &bufLen);
+ break;
+#endif
+ case PROP_PARSESUCCESS:
+ pRes = (uchar*)getParseSuccess(pMsg);
+ break;
+ case PROP_SYS_NOW:
+ if((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 10;
+ }
+ break;
+ case PROP_SYS_YEAR:
+ if((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 4;
+ }
+ break;
+ case PROP_SYS_MONTH:
+ if((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_DAY:
+ if((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_HOUR:
+ if((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_HHOUR:
+ if((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_QHOUR:
+ if((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_MINUTE:
+ if((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_NOW_UTC:
+ if((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 10;
+ }
+ break;
+ case PROP_SYS_YEAR_UTC:
+ if((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 4;
+ }
+ break;
+ case PROP_SYS_MONTH_UTC:
+ if((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_DAY_UTC:
+ if((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_HOUR_UTC:
+ if((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_HHOUR_UTC:
+ if((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_QHOUR_UTC:
+ if((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_MINUTE_UTC:
+ if((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 2;
+ }
+ break;
+ case PROP_SYS_WDAY:
+ if((pRes = getNOW(NOW_WDAY, ttNow, TIME_IN_LOCALTIME)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 1;
+ }
+ break;
+ case PROP_SYS_WDAY_UTC:
+ if((pRes = getNOW(NOW_WDAY, ttNow, TIME_IN_UTC)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ *pbMustBeFreed = 1;
+ bufLen = 1;
+ }
+ break;
+ case PROP_SYS_NOW_UXTIMESTAMP:
+ if((pRes = malloc(16)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ } else {
+ snprintf((char*) pRes, 16-1, "%lld", (long long) getTime(NULL));
+ pRes[16-1] = '\0';
+ *pbMustBeFreed = 1;
+ bufLen = -1;
+ }
+ break;
+ case PROP_SYS_MYHOSTNAME:
+ pRes = glbl.GetLocalHostName();
+ break;
+ case PROP_CEE_ALL_JSON:
+ case PROP_CEE_ALL_JSON_PLAIN:
+ if(pMsg->json == NULL) {
+ pRes = (uchar*) "{}";
+ bufLen = 2;
+ *pbMustBeFreed = 0;
+ } else {
+ const char *jstr;
+ MsgLock(pMsg);
+ int jflag = 0;
+ if(pProp->id == PROP_CEE_ALL_JSON) {
+ jflag = JSON_C_TO_STRING_SPACED;
+ } else if(pProp->id == PROP_CEE_ALL_JSON_PLAIN) {
+ jflag = JSON_C_TO_STRING_PLAIN;
+ }
+ jstr = json_object_to_json_string_ext(pMsg->json, jflag);
+ MsgUnlock(pMsg);
+ if(jstr == NULL) {
+ RET_OUT_OF_MEMORY;
+ }
+ pRes = (uchar*)strdup(jstr);
+ if(pRes == NULL) {
+ RET_OUT_OF_MEMORY;
+ }
+ *pbMustBeFreed = 1;
+ }
+ break;
+ case PROP_CEE:
+ case PROP_LOCAL_VAR:
+ case PROP_GLOBAL_VAR:
+ getJSONPropVal(pMsg, pProp, &pRes, &bufLen, pbMustBeFreed);
+ break;
+ case PROP_SYS_BOM:
+ pRes = (uchar*) "\xEF\xBB\xBF";
+ *pbMustBeFreed = 0;
+ break;
+ case PROP_SYS_UPTIME:
+# ifndef HAVE_SYSINFO_UPTIME
+ /* An alternative on some systems (eg Solaris) is to scan
+ * /var/adm/utmpx for last boot time.
+ */
+ pRes = (uchar*) "UPTIME NOT available on this system";
+ *pbMustBeFreed = 0;
+
+# elif defined(__FreeBSD__)
+
+ {
+ struct timespec tp;
+
+ if((pRes = (uchar*) malloc(32)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ }
+
+ if(clock_gettime(CLOCK_UPTIME, &tp) == -1) {
+ free(pRes);
+ *pPropLen = sizeof("**SYSCALL FAILED**") - 1;
+ return(UCHAR_CONSTANT("**SYSCALL FAILED**"));
+ }
+
+ *pbMustBeFreed = 1;
+
+ snprintf((char*) pRes, 32, "%ld", tp.tv_sec);
+ }
+
+# else
+
+ {
+ struct sysinfo s_info;
+
+ if((pRes = (uchar*) malloc(32)) == NULL) {
+ RET_OUT_OF_MEMORY;
+ }
+
+ if(sysinfo(&s_info) < 0) {
+ free(pRes);
+ *pPropLen = sizeof("**SYSCALL FAILED**") - 1;
+ return(UCHAR_CONSTANT("**SYSCALL FAILED**"));
+ }
+
+ *pbMustBeFreed = 1;
+
+ snprintf((char*) pRes, 32, "%ld", s_info.uptime);
+ }
+# endif
+ break;
+ default:
+ /* there is no point in continuing, we may even otherwise render the
+ * error message unreadable. rgerhards, 2007-07-10
+ */
+ dbgprintf("invalid property id: '%d'\n", pProp->id);
+ *pbMustBeFreed = 0;
+ *pPropLen = sizeof("**INVALID PROPERTY NAME**") - 1;
+ return UCHAR_CONSTANT("**INVALID PROPERTY NAME**");
+ }
+
+ /* If we did not receive a template pointer, we are already done... */
+ if(pTpe == NULL || !pTpe->bComplexProcessing) {
+ *pPropLen = (bufLen == -1) ? (int) ustrlen(pRes) : bufLen;
+ return pRes;
+ }
+
+ /* Now check if we need to make "temporary" transformations (these
+ * are transformations that do not go back into the message -
+ * memory must be allocated for them!).
+ */
+
+ /* substring extraction */
+ /* first we check if we need to extract by field number
+ * rgerhards, 2005-12-22
+ */
+ if(pTpe->data.field.has_fields == 1) {
+ size_t iCurrFld;
+ uchar *pFld;
+ uchar *pFldEnd;
+ /* first, skip to the field in question. The field separator
+ * is always one character and is stored in the template entry.
+ */
+ iCurrFld = 1;
+ pFld = pRes;
+ while(*pFld && iCurrFld < pTpe->data.field.iFieldNr) {
+ /* skip fields until the requested field or end of string is found */
+ while(*pFld && (uchar) *pFld != pTpe->data.field.field_delim)
+ ++pFld; /* skip to field terminator */
+ if(*pFld == pTpe->data.field.field_delim) {
+ ++pFld; /* eat it */
+#ifdef STRICT_GPLV3
+ if (pTpe->data.field.field_expand != 0) {
+ while (*pFld == pTpe->data.field.field_delim) {
+ ++pFld;
+ }
+ }
+#endif
+ ++iCurrFld;
+ }
+ }
+ dbgprintf("field requested %d, field found %d\n", pTpe->data.field.iFieldNr, (int) iCurrFld);
+
+ if(iCurrFld == pTpe->data.field.iFieldNr) {
+ /* field found, now extract it */
+ /* first of all, we need to find the end */
+ pFldEnd = pFld;
+ while(*pFldEnd && *pFldEnd != pTpe->data.field.field_delim)
+ ++pFldEnd;
+ --pFldEnd; /* we are already at the delimiter - so we need to
+ * step back a little not to copy it as part of the field. */
+ /* we got our end pointer, now do the copy */
+ /* TODO: code copied from below, this is a candidate for a separate function */
+ iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
+ pBufStart = pBuf = malloc(iLen + 1);
+ if(pBuf == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ /* now copy */
+ memcpy(pBuf, pFld, iLen);
+ bufLen = iLen;
+ pBuf[iLen] = '\0'; /* terminate it */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBufStart;
+ *pbMustBeFreed = 1;
+ } else {
+ /* field not found, return error */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ *pPropLen = sizeof("**FIELD NOT FOUND**") - 1;
+ return UCHAR_CONSTANT("**FIELD NOT FOUND**");
+ }
+#ifdef FEATURE_REGEXP
+ } else {
+ /* Check for regular expressions */
+ if (pTpe->data.field.has_regex != 0) {
+ if (pTpe->data.field.has_regex == 2) {
+ /* Could not compile regex before! */
+ if (*pbMustBeFreed == 1) {
+ free(pRes);
+ *pbMustBeFreed = 0;
+ }
+ *pPropLen = sizeof("**NO MATCH** **BAD REGULAR EXPRESSION**") - 1;
+ return UCHAR_CONSTANT("**NO MATCH** **BAD REGULAR EXPRESSION**");
+ }
+
+ dbgprintf("string to match for regex is: %s\n", pRes);
+
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ short iTry = 0;
+ uchar bFound = 0;
+ iOffs = 0;
+ /* first see if we find a match, iterating through the series of
+ * potential matches over the string.
+ */
+ while(!bFound) {
+ int iREstat;
+ iREstat = regexp.regexec(&pTpe->data.field.re, (char*)(pRes + iOffs),
+ nmatch, pmatch, 0);
+ dbgprintf("regexec return is %d\n", iREstat);
+ if(iREstat == 0) {
+ if(pmatch[0].rm_so == -1) {
+ dbgprintf("oops ... start offset of successful "
+ "regexec is -1\n");
+ break;
+ }
+ if(iTry == pTpe->data.field.iMatchToUse) {
+ bFound = 1;
+ } else {
+ dbgprintf("regex found at offset %d, new offset %d, "
+ "tries %d\n", iOffs,
+ (int) (iOffs + pmatch[0].rm_eo), iTry);
+ iOffs += pmatch[0].rm_eo;
+ ++iTry;
+ }
+ } else {
+ break;
+ }
+ }
+ dbgprintf("regex: end search, found %d\n", bFound);
+ if(!bFound) {
+ /* we got no match! */
+ if(pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) {
+ if (*pbMustBeFreed == 1) {
+ free(pRes);
+ *pbMustBeFreed = 0;
+ }
+ if(pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR) {
+ bufLen = sizeof("**NO MATCH**") - 1;
+ pRes = UCHAR_CONSTANT("**NO MATCH**");
+ } else if(pTpe->data.field.nomatchAction ==
+ TPL_REGEX_NOMATCH_USE_ZERO) {
+ bufLen = 1;
+ pRes = UCHAR_CONSTANT("0");
+ } else {
+ bufLen = 0;
+ pRes = UCHAR_CONSTANT("");
+ }
+ }
+ } else {
+ /* Match- but did it match the one we wanted? */
+ /* we got no match! */
+ if(pmatch[pTpe->data.field.iSubMatchToUse].rm_so == -1) {
+ if(pTpe->data.field.nomatchAction !=
+ TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) {
+ if (*pbMustBeFreed == 1) {
+ free(pRes);
+ *pbMustBeFreed = 0;
+ }
+ if(pTpe->data.field.nomatchAction ==
+ TPL_REGEX_NOMATCH_USE_DFLTSTR) {
+ bufLen = sizeof("**NO MATCH**") - 1;
+ pRes = UCHAR_CONSTANT("**NO MATCH**");
+ } else if(pTpe->data.field.nomatchAction ==
+ TPL_REGEX_NOMATCH_USE_ZERO) {
+ bufLen = 1;
+ pRes = UCHAR_CONSTANT("0");
+ } else {
+ bufLen = 0;
+ pRes = UCHAR_CONSTANT("");
+ }
+ }
+ }
+ /* OK, we have a usable match - we now need to malloc pB */
+ int iLenBuf;
+ uchar *pB;
+
+ iLenBuf = pmatch[pTpe->data.field.iSubMatchToUse].rm_eo
+ - pmatch[pTpe->data.field.iSubMatchToUse].rm_so;
+ pB = malloc(iLenBuf + 1);
+
+ if (pB == NULL) {
+ if (*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+
+ /* Lets copy the matched substring to the buffer */
+ memcpy(pB, pRes + iOffs + pmatch[pTpe->data.field.iSubMatchToUse].rm_so,
+ iLenBuf);
+ bufLen = iLenBuf;
+ pB[iLenBuf] = '\0';/* terminate string, did not happen before */
+
+ if (*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pB;
+ *pbMustBeFreed = 1;
+ }
+ } else {
+ /* we could not load regular expression support. This is quite unexpected at
+ * this stage of processing (after all, the config parser found it), but so
+ * it is. We return an error in that case. -- rgerhards, 2008-03-07
+ */
+ dbgprintf("could not get regexp object pointer, so regexp can not be evaluated\n");
+ if (*pbMustBeFreed == 1) {
+ free(pRes);
+ *pbMustBeFreed = 0;
+ }
+ *pPropLen = sizeof("***REGEXP NOT AVAILABLE***") - 1;
+ return UCHAR_CONSTANT("***REGEXP NOT AVAILABLE***");
+ }
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+
+ if(pTpe->data.field.iFromPos != 0 || pTpe->data.field.iToPos != 0) {
+ /* we need to obtain a private copy */
+ int iFrom, iTo;
+ uchar *pSb;
+ iFrom = pTpe->data.field.iFromPos;
+ iTo = pTpe->data.field.iToPos;
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ if(pTpe->data.field.options.bFromPosEndRelative) {
+ iFrom = (bufLen < iFrom) ? 0 : bufLen - iFrom;
+ iTo = (bufLen < iTo)? 0 : bufLen - iTo;
+ } else {
+ /* need to zero-base to and from (they are 1-based!) */
+ if(iFrom > 0)
+ --iFrom;
+ if(iTo > 0) {
+ --iTo;
+ } else if(iTo < 0) {
+ /* note: we ADD negative value, 0-based (-1)! */
+ iTo = bufLen - 1 + iTo;
+ if(iTo < 0) {
+ iTo = 0;
+ }
+ }
+ }
+ if(iFrom >= bufLen) {
+ DBGPRINTF("msgGetProp: iFrom %d >= buflen %d, returning empty string\n",
+ iFrom, bufLen);
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = (uchar*) "";
+ *pbMustBeFreed = 0;
+ bufLen = 0;
+ } else if(iFrom == 0 && iTo >= bufLen && pTpe->data.field.options.bFixedWidth == 0) {
+ /* in this case, the requested string is a superset of what we already have,
+ * so there is no need to do any processing. This is a frequent case for size-limited
+ * fields like TAG in the default forwarding template (so it is a useful optimization
+ * to check for this condition ;)). -- rgerhards, 2009-07-09
+ */
+ ; /*DO NOTHING*/
+ } else {
+ if(iTo >= bufLen) /* iTo is very large, if no to-position is set in the template! */
+ if (pTpe->data.field.options.bFixedWidth == 0)
+ iTo = bufLen - 1;
+
+ iLen = iTo - iFrom + 1; /* the +1 is for an actual char, NOT \0! */
+ pBufStart = pBuf = malloc(iLen + 1);
+ if(pBuf == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ pSb = pRes;
+ if(iFrom) {
+ /* skip to the start of the substring (can't do pointer arithmetic
+ * because the whole string might be smaller!!)
+ */
+ while(*pSb && iFrom) {
+ --iFrom;
+ ++pSb;
+ }
+ }
+ /* OK, we are at the begin - now let's copy... */
+ bufLen = iLen;
+ while(iLen) {
+ if (*pSb) {
+ *pBuf++ = *pSb;
+ ++pSb;
+ } else {
+ *pBuf++ = ' ';
+ }
+ --iLen;
+ }
+ *pBuf = '\0';
+ bufLen -= iLen; /* subtract remaining length if the string was smaller! */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBufStart;
+ *pbMustBeFreed = 1;
+ }
+ }
+
+ /* now check if we need to do our "SP if first char is non-space" hack logic */
+ if(*pRes && pTpe->data.field.options.bSPIffNo1stSP) {
+ /* here, we always destruct the buffer and return a new one */
+ uchar cFirst = *pRes; /* save first char */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = (cFirst == ' ') ? UCHAR_CONSTANT("") : UCHAR_CONSTANT(" ");
+ bufLen = (cFirst == ' ') ? 0 : 1;
+ *pbMustBeFreed = 0;
+ }
+
+ if(*pRes) {
+ /* case conversations (should go after substring, because so we are able to
+ * work on the smallest possible buffer).
+ */
+ if(pTpe->data.field.eCaseConv != tplCaseConvNo) {
+ /* we need to obtain a private copy */
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ uchar *pBStart;
+ uchar *pB;
+ uchar *pSrc;
+ pBStart = pB = malloc(bufLen + 1);
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ pSrc = pRes;
+ while(*pSrc) {
+ *pB++ = (pTpe->data.field.eCaseConv == tplCaseConvUpper) ?
+ (uchar)toupper((int)*pSrc) : (uchar)tolower((int)*pSrc);
+ /* currently only these two exist */
+ ++pSrc;
+ }
+ *pB = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBStart;
+ *pbMustBeFreed = 1;
+ }
+
+ /* now do control character dropping/escaping/replacement
+ * Only one of these can be used. If multiple options are given, the
+ * result is random (though currently there obviously is an order of
+ * preferrence, see code below. But this is NOT guaranteed.
+ * RGerhards, 2006-11-17
+ * We must copy the strings if we modify them, because they may either
+ * point to static memory or may point into the message object, in which
+ * case we would actually modify the original property (which of course
+ * is wrong).
+ * This was found and fixed by varmojefkoj on 2007-09-11
+ */
+ if(pTpe->data.field.options.bDropCC) {
+ int iLenBuf = 0;
+ uchar *pSrc = pRes;
+ uchar *pDstStart;
+ uchar *pDst;
+ uchar bDropped = 0;
+
+ while(*pSrc) {
+ if(!iscntrl((int) *pSrc++))
+ iLenBuf++;
+ else
+ bDropped = 1;
+ }
+
+ if(bDropped) {
+ pDst = pDstStart = malloc(iLenBuf + 1);
+ if(pDst == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ for(pSrc = pRes; *pSrc; pSrc++) {
+ if(!iscntrl((int) *pSrc))
+ *pDst++ = *pSrc;
+ }
+ *pDst = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pDstStart;
+ bufLen = iLenBuf;
+ *pbMustBeFreed = 1;
+ }
+ } else if(pTpe->data.field.options.bSpaceCC) {
+ uchar *pSrc;
+ uchar *pDstStart;
+ uchar *pDst;
+
+ if(*pbMustBeFreed == 1) {
+ /* in this case, we already work on dynamic
+ * memory, so there is no need to copy it - we can
+ * modify it in-place without any harm. This is a
+ * performance optiomization.
+ */
+ for(pDst = pRes; *pDst; pDst++) {
+ if(iscntrl((int) *pDst))
+ *pDst = ' ';
+ }
+ } else {
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ pDst = pDstStart = malloc(bufLen + 1);
+ if(pDst == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ for(pSrc = pRes; *pSrc; pSrc++) {
+ if(iscntrl((int) *pSrc))
+ *pDst++ = ' ';
+ else
+ *pDst++ = *pSrc;
+ }
+ *pDst = '\0';
+ pRes = pDstStart;
+ *pbMustBeFreed = 1;
+ }
+ } else if(pTpe->data.field.options.bEscapeCC) {
+ /* we must first count how many control charactes are
+ * present, because we need this to compute the new string
+ * buffer length. While doing so, we also compute the string
+ * length.
+ */
+ int iNumCC = 0;
+ int iLenBuf = 0;
+ uchar *pSrc;
+ uchar *pB;
+
+ for(pB = pRes ; *pB ; ++pB) {
+ ++iLenBuf;
+ if(iscntrl((int) *pB))
+ ++iNumCC;
+ }
+
+ if(iNumCC > 0) { /* if 0, there is nothing to escape, so we are done */
+ /* OK, let's do the escaping... */
+ uchar *pBStart;
+ uchar szCCEsc[8]; /* buffer for escape sequence */
+ int i;
+
+ iLenBuf += iNumCC * 4;
+ pBStart = pB = malloc(iLenBuf + 1);
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ for(pSrc = pRes; *pSrc; pSrc++) {
+ if(iscntrl((int) *pSrc)) {
+ snprintf((char*)szCCEsc, sizeof(szCCEsc), "#%3.3d", *pSrc);
+ for(i = 0 ; i < 4 ; ++i)
+ *pB++ = szCCEsc[i];
+ } else {
+ *pB++ = *pSrc;
+ }
+ }
+ *pB = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBStart;
+ bufLen = -1;
+ *pbMustBeFreed = 1;
+ }
+ }
+ }
+
+ /* Take care of spurious characters to make the property safe
+ * for a path definition
+ */
+ if(pTpe->data.field.options.bSecPathDrop || pTpe->data.field.options.bSecPathReplace) {
+ if(pTpe->data.field.options.bSecPathDrop) {
+ int iLenBuf = 0;
+ uchar *pSrc = pRes;
+ uchar *pDstStart;
+ uchar *pDst;
+ uchar bDropped = 0;
+
+ while(*pSrc) {
+ if(*pSrc++ != '/')
+ iLenBuf++;
+ else
+ bDropped = 1;
+ }
+
+ if(bDropped) {
+ pDst = pDstStart = malloc(iLenBuf + 1);
+ if(pDst == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ for(pSrc = pRes; *pSrc; pSrc++) {
+ if(*pSrc != '/')
+ *pDst++ = *pSrc;
+ }
+ *pDst = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pDstStart;
+ bufLen = -1; /* TODO: can we do better? */
+ *pbMustBeFreed = 1;
+ }
+ } else {
+ uchar *pSrc;
+ uchar *pDstStart;
+ uchar *pDst;
+
+ if(*pbMustBeFreed == 1) {
+ /* here, again, we can modify the string as we already obtained
+ * a private buffer. As we do not change the size of that buffer,
+ * in-place modification is possible. This is a performance
+ * enhancement.
+ */
+ for(pDst = pRes; *pDst; pDst++) {
+ if(*pDst == '/')
+ *pDst++ = '_';
+ }
+ } else {
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ pDst = pDstStart = malloc(bufLen + 1);
+ if(pDst == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ for(pSrc = pRes; *pSrc; pSrc++) {
+ if(*pSrc == '/')
+ *pDst++ = '_';
+ else
+ *pDst++ = *pSrc;
+ }
+ *pDst = '\0';
+ /* we must NOT check if it needs to be freed, because we have done
+ * this in the if above. So if we come to hear, the pSrc string needs
+ * not to be freed (and we do not need to care about it).
+ */
+ pRes = pDstStart;
+ *pbMustBeFreed = 1;
+ }
+ }
+
+ /* check for "." and ".." (note the parenthesis in the if condition!) */
+ if(*pRes == '\0') {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = UCHAR_CONSTANT("_");
+ bufLen = 1;
+ *pbMustBeFreed = 0;
+ } else if((*pRes == '.') && (*(pRes + 1) == '\0' || (*(pRes + 1) == '.' && *(pRes + 2) == '\0'))) {
+ uchar *pTmp = pRes;
+
+ if(*(pRes + 1) == '\0')
+ pRes = UCHAR_CONSTANT("_");
+ else
+ pRes = UCHAR_CONSTANT("_.");;
+ if(*pbMustBeFreed == 1)
+ free(pTmp);
+ *pbMustBeFreed = 0;
+ }
+ }
+
+ /* Now drop last LF if present (pls note that this must not be done
+ * if bEscapeCC was set)!
+ */
+ if(pTpe->data.field.options.bDropLastLF && !pTpe->data.field.options.bEscapeCC) {
+ int iLn;
+ uchar *pB;
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ iLn = bufLen;
+ if(iLn > 0 && *(pRes + iLn - 1) == '\n') {
+ /* we have a LF! */
+ /* check if we need to obtain a private copy */
+ if(*pbMustBeFreed == 0) {
+ /* ok, original copy, need a private one */
+ pB = malloc(iLn + 1);
+ if(pB == NULL) {
+ RET_OUT_OF_MEMORY;
+ }
+ memcpy(pB, pRes, iLn - 1);
+ pRes = pB;
+ *pbMustBeFreed = 1;
+ }
+ *(pRes + iLn - 1) = '\0'; /* drop LF ;) */
+ --bufLen;
+ }
+ }
+
+ /* Now everything is squased as much as possible and more or less ready to
+ * go. This is the perfect place to compress any remaining spaces, if so
+ * instructed by the user/config.
+ */
+ if(pTpe->data.field.options.bCompressSP) {
+ int needCompress = 0;
+ int hadSP = 0;
+ uchar *pB;
+ if(*pbMustBeFreed == 0) {
+ for(pB = pRes ; *pB && needCompress == 0 ; ++pB) {
+ if(*pB == ' ') {
+ if(hadSP) {
+ uchar *const tmp = ustrdup(pRes);
+ if(tmp == NULL)
+ /* better not compress than
+ * loose message. */
+ break;
+ *pbMustBeFreed = 1;
+ pRes = tmp;
+ needCompress = 1;
+ } else {
+ hadSP = 1;
+ }
+ }
+ }
+ } else {
+ /* If we can modify the buffer in any case, we
+ * do NOT check if we actually need to compress,
+ * but "just do it" - that's the quickest way
+ * to get it done.
+ */
+ needCompress = 1;
+ }
+ if(needCompress) {
+ hadSP = 0;
+ uchar *pDst = pRes;
+ int needCopy = 0;
+ for(pB = pRes ; *pB ; ++pB) {
+ if(*pB == ' ') {
+ if(hadSP) {
+ needCopy = 1;
+ } else {
+ hadSP = 1;
+ if(needCopy)
+ *pDst = *pB;
+ ++pDst;
+ }
+ } else {
+ hadSP = 0;
+ if(needCopy)
+ *pDst = *pB;
+ ++pDst;
+ }
+ }
+ *pDst = '\0';
+ bufLen = pDst - pRes;
+ }
+ }
+
+ /* finally, we need to check if the property should be formatted in CSV or JSON.
+ * For CSV we use RFC 4180, and always use double quotes. As of this writing,
+ * this should be the last action carried out on the property, but in the
+ * future there may be reasons to change that. -- rgerhards, 2009-04-02
+ */
+ if(pTpe->data.field.options.bCSV) {
+ /* we need to obtain a private copy, as we need to at least add the double quotes */
+ int iBufLen;
+ uchar *pBStart;
+ uchar *pDst;
+ uchar *pSrc;
+ if(bufLen == -1)
+ bufLen = ustrlen(pRes);
+ iBufLen = bufLen;
+ /* the malloc may be optimized, we currently use the worst case... */
+ pBStart = pDst = malloc(2 * iBufLen + 3);
+ if(pDst == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ RET_OUT_OF_MEMORY;
+ }
+ pSrc = pRes;
+ *pDst++ = '"'; /* starting quote */
+ while(*pSrc) {
+ if(*pSrc == '"')
+ *pDst++ = '"'; /* need to add double double quote (see RFC4180) */
+ *pDst++ = *pSrc++;
+ }
+ *pDst++ = '"'; /* ending quote */
+ *pDst = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBStart;
+ bufLen = -1;
+ *pbMustBeFreed = 1;
+ } else if(pTpe->data.field.options.bJSON) {
+ jsonEncode(&pRes, pbMustBeFreed, &bufLen, RSTRUE);
+ } else if(pTpe->data.field.options.bJSONf) {
+ jsonField(pTpe, &pRes, pbMustBeFreed, &bufLen, RSTRUE);
+ } else if(pTpe->data.field.options.bJSONr) {
+ jsonEncode(&pRes, pbMustBeFreed, &bufLen, RSFALSE);
+ } else if(pTpe->data.field.options.bJSONfr) {
+ jsonField(pTpe, &pRes, pbMustBeFreed, &bufLen, RSFALSE);
+ }
+
+ *pPropLen = (bufLen == -1) ? (int) ustrlen(pRes) : bufLen;
+
+ return(pRes);
+}
+
+/* Set a single property based on the JSON object provided. The
+ * property name is extracted from the JSON object.
+ */
+static rsRetVal
+msgSetPropViaJSON(smsg_t *__restrict__ const pMsg, const char *name, struct json_object *json, int sharedReference)
+{
+ const char *psz;
+ int val;
+ prop_t *propFromHost = NULL;
+ prop_t *propRcvFromIP = NULL;
+ int bNeedFree = 1;
+ DEFiRet;
+
+ /* note: json_object_get_string() manages the memory of the returned
+ * string. So we MUST NOT free it!
+ */
+ dbgprintf("DDDD: msgSetPropViaJSON key: '%s'\n", name);
+ if(!strcmp(name, "rawmsg")) {
+ psz = json_object_get_string(json);
+ MsgSetRawMsg(pMsg, psz, strlen(psz));
+ } else if(!strcmp(name, "msg")) {
+ psz = json_object_get_string(json);
+ MsgReplaceMSG(pMsg, (const uchar*)psz, strlen(psz));
+ } else if(!strcmp(name, "syslogtag")) {
+ psz = json_object_get_string(json);
+ MsgSetTAG(pMsg, (const uchar*)psz, strlen(psz));
+ } else if(!strcmp(name, "pri")) {
+ val = json_object_get_int(json);
+ msgSetPRI(pMsg, val);
+ } else if(!strcmp(name, "syslogfacility")) {
+ val = json_object_get_int(json);
+ if(val >= 0 && val <= 24)
+ pMsg->iFacility = val;
+ else
+ DBGPRINTF("mmexternal: invalid fac %d requested -- ignored\n", val);
+ } else if(!strcmp(name, "syslogseverity")) {
+ val = json_object_get_int(json);
+ if(val >= 0 && val <= 7)
+ pMsg->iSeverity = val;
+ else
+ DBGPRINTF("mmexternal: invalid fac %d requested -- ignored\n", val);
+ } else if(!strcmp(name, "procid")) {
+ psz = json_object_get_string(json);
+ MsgSetPROCID(pMsg, psz);
+ } else if(!strcmp(name, "msgid")) {
+ psz = json_object_get_string(json);
+ MsgSetMSGID(pMsg, psz);
+ } else if(!strcmp(name, "structured-data")) {
+ psz = json_object_get_string(json);
+ MsgSetStructuredData(pMsg, psz);
+ } else if(!strcmp(name, "hostname") || !strcmp(name, "source")) {
+ psz = json_object_get_string(json);
+ MsgSetHOSTNAME(pMsg, (const uchar*)psz, strlen(psz));
+ } else if(!strcmp(name, "fromhost")) {
+ psz = json_object_get_string(json);
+ MsgSetRcvFromStr(pMsg, (const uchar*) psz, strlen(psz), &propFromHost);
+ prop.Destruct(&propFromHost);
+ } else if(!strcmp(name, "fromhost-ip")) {
+ psz = json_object_get_string(json);
+ MsgSetRcvFromIPStr(pMsg, (const uchar*)psz, strlen(psz), &propRcvFromIP);
+ prop.Destruct(&propRcvFromIP);
+ } else if(!strcmp(name, "$!")) {
+ /* msgAddJSON expects that it can keep the object without incremeting
+ * the json reference count. So we MUST NOT free (_put) the object in
+ * this case. -- rgerhards, 2018-09-14
+ */
+ bNeedFree = 0;
+ msgAddJSON(pMsg, (uchar*)"!", json, 0, sharedReference);
+ } else {
+ /* we ignore unknown properties */
+ DBGPRINTF("msgSetPropViaJSON: unkonwn property ignored: %s\n",
+ name);
+ }
+
+ if(bNeedFree) {
+ json_object_put(json);
+ }
+
+ RETiRet;
+}
+
+
+/* set message properties based on JSON string. This function does it all,
+ * including parsing the JSON string. If an error is detected, the operation
+ * is aborted at the time of error. Any modifications made before the
+ * error ocurs are still PERSISTED.
+ * This function is meant to support the external message modifiction module
+ * interface. As such, replacing properties is expressively permited. Note that
+ * properties which were derived from the message during parsing are NOT
+ * updated if the underlying (raw)msg property is changed.
+ */
+rsRetVal
+MsgSetPropsViaJSON(smsg_t *__restrict__ const pMsg, const uchar *__restrict__ const jsonstr)
+{
+ struct json_tokener *tokener = NULL;
+ struct json_object *json;
+ const char *errMsg;
+ DEFiRet;
+
+ DBGPRINTF("DDDDDD: JSON string for message mod: '%s'\n", jsonstr);
+ if(!strcmp((char*)jsonstr, "{}")) /* shortcut for a common case */
+ FINALIZE;
+
+ tokener = json_tokener_new();
+
+ json = json_tokener_parse_ex(tokener, (char*)jsonstr, ustrlen(jsonstr));
+ if(Debug) {
+ errMsg = NULL;
+ if(json == NULL) {
+ enum json_tokener_error err;
+
+ err = tokener->err;
+ if(err != json_tokener_continue)
+ errMsg = json_tokener_error_desc(err);
+ else
+ errMsg = "Unterminated input";
+ } else if(!json_object_is_type(json, json_type_object))
+ errMsg = "JSON value is not an object";
+ if(errMsg != NULL) {
+ DBGPRINTF("MsgSetPropsViaJSON: Error parsing JSON '%s': %s\n",
+ jsonstr, errMsg);
+ }
+ }
+ if(json == NULL || !json_object_is_type(json, json_type_object)) {
+ ABORT_FINALIZE(RS_RET_JSON_UNUSABLE);
+ }
+ MsgSetPropsViaJSON_Object(pMsg, json);
+
+finalize_it:
+ if(tokener != NULL)
+ json_tokener_free(tokener);
+ RETiRet;
+}
+
+
+/* Used by MsgSetPropsViaJSON to set properties.
+ * The same as MsgSetPropsViaJSON only that a json object is given and not a string
+ */
+rsRetVal
+MsgSetPropsViaJSON_Object(smsg_t *__restrict__ const pMsg, struct json_object *json)
+{
+ DEFiRet;
+ if(json == NULL || !json_object_is_type(json, json_type_object)) {
+ DBGPRINTF("MsgSetPropsViaJSON_Object: json NULL or not object type\n");
+ ABORT_FINALIZE(RS_RET_JSON_UNUSABLE);
+ }
+ struct json_object_iterator it = json_object_iter_begin(json);
+ struct json_object_iterator itEnd = json_object_iter_end(json);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ struct json_object *child = json_object_iter_peek_value(&it);
+ json_object_get(child);
+ msgSetPropViaJSON(pMsg, json_object_iter_peek_name(&it),
+ child, 0);
+ json_object_iter_next(&it);
+ }
+ json_object_put(json);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the severity - this is an entry point that
+ * satisfies the base object class getSeverity semantics.
+ * rgerhards, 2008-01-14
+ */
+rsRetVal
+MsgGetSeverity(smsg_t * const pMsg, int *piSeverity)
+{
+ *piSeverity = pMsg->iSeverity;
+ return RS_RET_OK;
+}
+
+
+static uchar *
+jsonPathGetLeaf(uchar *name, int lenName)
+{
+ int i;
+ for(i = lenName ; i >= 0 ; --i)
+ if(i == 0) {
+ if(name[0] == '!' || name[0] == '.' || name[0] == '/')
+ break;
+ } else {
+ if(name[i] == '!')
+ break;
+ }
+ if(name[i] == '!' || name[i] == '.' || name[i] == '/')
+ ++i;
+ return name + i;
+}
+
+static json_bool jsonVarExtract(struct json_object* root, const char *key, struct json_object **value) {
+ char namebuf[MAX_VARIABLE_NAME_LEN];
+ int key_len = strlen(key);
+ char *array_idx_start = strstr(key, "[");
+ char *array_idx_end = NULL;
+ char *array_idx_num_end_discovered = NULL;
+ struct json_object *arr = NULL;
+ if (array_idx_start != NULL) {
+ array_idx_end = strstr(array_idx_start, "]");
+ }
+ if (array_idx_end != NULL && (array_idx_end - key + 1) == key_len) {
+ errno = 0;
+ int idx = (int) strtol(array_idx_start + 1, &array_idx_num_end_discovered, 10);
+ if (errno == 0 && array_idx_num_end_discovered == array_idx_end) {
+ memcpy(namebuf, key, array_idx_start - key);
+ namebuf[array_idx_start - key] = '\0';
+ json_bool found_obj = json_object_object_get_ex(root, namebuf, &arr);
+ if (found_obj && json_object_is_type(arr, json_type_array)) {
+ int len = json_object_array_length(arr);
+ if (len > idx) {
+ *value = json_object_array_get_idx(arr, idx);
+ if (*value != NULL) return TRUE;
+ }
+ return FALSE;
+ }
+ }
+ }
+ return json_object_object_get_ex(root, key, value);
+}
+
+
+static rsRetVal
+jsonPathFindNext(struct json_object *root, uchar *namestart, uchar **name, uchar *leaf,
+ struct json_object **found, int bCreate)
+{
+ uchar namebuf[MAX_VARIABLE_NAME_LEN];
+ struct json_object *json;
+ size_t i;
+ uchar *p = *name;
+ DEFiRet;
+
+ if(*p == '!' || (*name == namestart && (*p == '.' || *p == '/')))
+ ++p;
+ for(i = 0 ; *p && !(p == namestart && (*p == '.' || *p == '/')) && *p != '!'
+ && p != leaf && i < sizeof(namebuf)-1 ; ++i, ++p)
+ namebuf[i] = *p;
+ if(i > 0) {
+ namebuf[i] = '\0';
+ if(jsonVarExtract(root, (char*)namebuf, &json) == FALSE) {
+ json = NULL;
+ }
+ } else
+ json = root;
+ if(json == NULL) {
+ if(!bCreate) {
+ ABORT_FINALIZE(RS_RET_JNAME_INVALID);
+ } else {
+ if (json_object_get_type(root) != json_type_object) {
+ DBGPRINTF("jsonPathFindNext with bCreate: not a container in json path, "
+ "name is '%s'\n", namestart);
+ ABORT_FINALIZE(RS_RET_INVLD_SETOP);
+ }
+ json = json_object_new_object();
+ json_object_object_add(root, (char*)namebuf, json);
+ }
+ }
+
+ *name = p;
+ *found = json;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent,
+ const int bCreate)
+{
+ uchar *namestart;
+ DEFiRet;
+ namestart = name;
+ *parent = jroot;
+ while(name < leaf-1) {
+ CHKiRet(jsonPathFindNext(*parent, namestart, &name, leaf, parent, bCreate));
+ }
+ if(*parent == NULL)
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+jsonMerge(struct json_object *existing, struct json_object *json)
+{
+ /* TODO: check & handle duplicate names */
+ DEFiRet;
+
+ struct json_object_iterator it = json_object_iter_begin(json);
+ struct json_object_iterator itEnd = json_object_iter_end(json);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ json_object_object_add(existing, json_object_iter_peek_name(&it),
+ json_object_get(json_object_iter_peek_value(&it)));
+ json_object_iter_next(&it);
+ }
+ /* note: json-c does ref counting. We added all descandants refcounts
+ * in the loop above. So when we now free(_put) the root object, only
+ * root gets freed().
+ */
+ json_object_put(json);
+ RETiRet;
+}
+
+/* find a JSON structure element (field or container doesn't matter). */
+rsRetVal
+jsonFind(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **jsonres)
+{
+ uchar *leaf;
+ struct json_object *parent;
+ struct json_object *field;
+ struct json_object **jroot = NULL;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut));
+ pthread_mutex_lock(mut);
+
+ if(*jroot == NULL) {
+ field = NULL;
+ goto finalize_it;
+ }
+
+ if(!strcmp((char*)pProp->name, "!")) {
+ field = *jroot;
+ } else if(!strcmp((char*)pProp->name, ".")) {
+ field = *jroot;
+ } else {
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0));
+ if(jsonVarExtract(parent, (char*)leaf, &field) == FALSE)
+ field = NULL;
+ }
+ *jsonres = field;
+
+finalize_it:
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ RETiRet;
+}
+
+/* check if JSON variable exists (works on terminal var and container) */
+rsRetVal ATTR_NONNULL()
+msgCheckVarExists(smsg_t *const pMsg, msgPropDescr_t *pProp)
+{
+ struct json_object *jsonres = NULL;
+ DEFiRet;
+
+ CHKiRet(jsonFind(pMsg, pProp, &jsonres));
+ if(jsonres == NULL) {
+ iRet = RS_RET_NOT_FOUND;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal
+msgAddJSON(smsg_t * const pM, uchar *name, struct json_object *json, int force_reset, int sharedReference)
+{
+ /* TODO: error checks! This is a quick&dirty PoC! */
+ struct json_object **jroot;
+ struct json_object *parent, *leafnode;
+ struct json_object *given = NULL;
+ uchar *leaf;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ CHKiRet(getJSONRootAndMutexByVarChar(pM, name[0], &jroot, &mut));
+ pthread_mutex_lock(mut);
+
+ if(name[0] == '/') { /* globl var special handling */
+ if (sharedReference) {
+ given = json;
+ json = jsonDeepCopy(json);
+ json_object_put(given);
+ }
+ }
+
+ if(name[1] == '\0') { /* full tree? */
+ if(*jroot == NULL)
+ *jroot = json;
+ else
+ CHKiRet(jsonMerge(*jroot, json));
+ } else {
+ if(*jroot == NULL) {
+ /* now we need a root obj */
+ *jroot = json_object_new_object();
+ }
+ leaf = jsonPathGetLeaf(name, ustrlen(name));
+ iRet = jsonPathFindParent(*jroot, name, leaf, &parent, 1);
+ if (unlikely(iRet != RS_RET_OK)) {
+ json_object_put(json);
+ FINALIZE;
+ }
+ if (json_object_get_type(parent) != json_type_object) {
+ DBGPRINTF("msgAddJSON: not a container in json path,"
+ "name is '%s'\n", name);
+ json_object_put(json);
+ ABORT_FINALIZE(RS_RET_INVLD_SETOP);
+ }
+ if(jsonVarExtract(parent, (char*)leaf, &leafnode) == FALSE)
+ leafnode = NULL;
+ /* json-c code indicates we can simply replace a
+ * json type. Unfortunaltely, this is not documented
+ * as part of the interface spec. We still use it,
+ * because it speeds up processing. If it does not work
+ * at some point, use
+ * json_object_object_del(parent, (char*)leaf);
+ * before adding. rgerhards, 2012-09-17
+ */
+ if (force_reset || (leafnode == NULL)) {
+ json_object_object_add(parent, (char*)leaf, json);
+ } else {
+ if(json_object_get_type(json) == json_type_object) {
+ CHKiRet(jsonMerge(*jroot, json));
+ } else {
+ /* TODO: improve the code below, however, the current
+ * state is not really bad */
+ if(json_object_get_type(leafnode) == json_type_object) {
+ DBGPRINTF("msgAddJSON: trying to update a container "
+ "node with a leaf, name is %s - "
+ "forbidden", name);
+ json_object_put(json);
+ ABORT_FINALIZE(RS_RET_INVLD_SETOP);
+ }
+ json_object_object_add(parent, (char*)leaf, json);
+ }
+ }
+ }
+
+finalize_it:
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ RETiRet;
+}
+
+
+rsRetVal
+msgDelJSON(smsg_t * const pM, uchar *name)
+{
+ struct json_object **jroot;
+ struct json_object *parent, *leafnode;
+ uchar *leaf;
+ pthread_mutex_t *mut = NULL;
+ DEFiRet;
+
+ CHKiRet(getJSONRootAndMutexByVarChar(pM, name[0], &jroot, &mut));
+ pthread_mutex_lock(mut);
+
+ if(*jroot == NULL) {
+ DBGPRINTF("msgDelJSONVar; jroot empty in unset for property %s\n",
+ name);
+ FINALIZE;
+ }
+
+ if(name[1] == '\0') {
+ /* full tree! Strange, but I think we should permit this. After all,
+ * we trust rsyslog.conf to be written by the admin.
+ */
+ DBGPRINTF("unsetting JSON root object\n");
+ json_object_put(*jroot);
+ *jroot = NULL;
+ } else {
+ leaf = jsonPathGetLeaf(name, ustrlen(name));
+ CHKiRet(jsonPathFindParent(*jroot, name, leaf, &parent, 0));
+ if(jsonVarExtract(parent, (char*)leaf, &leafnode) == FALSE)
+ leafnode = NULL;
+ if(leafnode == NULL) {
+ DBGPRINTF("unset JSON: could not find '%s'\n", name);
+ ABORT_FINALIZE(RS_RET_JNAME_NOTFOUND);
+ } else {
+ DBGPRINTF("deleting JSON value path '%s', "
+ "leaf '%s', type %d\n",
+ name, leaf, json_object_get_type(leafnode));
+ json_object_object_del(parent, (char*)leaf);
+ }
+ }
+
+finalize_it:
+ if(mut != NULL)
+ pthread_mutex_unlock(mut);
+ RETiRet;
+}
+
+/* add Metadata to the message. This is stored in a special JSON
+ * container. Note that only string types are currently supported,
+ * what should pose absolutely no problem with the string-ish nature
+ * of rsyslog metadata.
+ * added 2015-01-09 rgerhards
+ */
+rsRetVal
+msgAddMetadata(smsg_t *const __restrict__ pMsg,
+ uchar *const __restrict__ metaname,
+ uchar *const __restrict__ metaval)
+{
+ DEFiRet;
+ struct json_object *const json = json_object_new_object();
+ CHKmalloc(json);
+ struct json_object *const jval = json_object_new_string((char*)metaval);
+ if(jval == NULL) {
+ json_object_put(json);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ json_object_object_add(json, (const char *const)metaname, jval);
+ iRet = msgAddJSON(pMsg, (uchar*)"!metadata", json, 0, 0);
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal
+msgAddMultiMetadata(smsg_t *const __restrict__ pMsg,
+ const uchar ** __restrict__ metaname,
+ const uchar ** __restrict__ metaval,
+ const int count)
+{
+ DEFiRet;
+ int i = 0 ;
+ struct json_object *const json = json_object_new_object();
+ CHKmalloc(json);
+ for ( i = 0 ; i < count ; i++ ) {
+ struct json_object *const jval = json_object_new_string((char*)metaval[i]);
+ if(jval == NULL) {
+ json_object_put(json);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ json_object_object_add(json, (const char *const)metaname[i], jval);
+ }
+ iRet = msgAddJSON(pMsg, (uchar*)"!metadata", json, 0, 0);
+finalize_it:
+ RETiRet;
+}
+
+struct json_object *
+jsonDeepCopy(struct json_object *src)
+{
+ struct json_object *dst = NULL, *json;
+ int arrayLen, i;
+
+ if(src == NULL) goto done;
+
+ switch(json_object_get_type(src)) {
+ case json_type_boolean:
+ dst = json_object_new_boolean(json_object_get_boolean(src));
+ break;
+ case json_type_double:
+ dst = json_object_new_double(json_object_get_double(src));
+ break;
+ case json_type_int:
+ dst = json_object_new_int64(json_object_get_int64(src));
+ break;
+ case json_type_string:
+ dst = json_object_new_string(json_object_get_string(src));
+ break;
+ case json_type_object:
+ dst = json_object_new_object();
+ struct json_object_iterator it = json_object_iter_begin(src);
+ struct json_object_iterator itEnd = json_object_iter_end(src);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ json = jsonDeepCopy(json_object_iter_peek_value(&it));
+ json_object_object_add(dst, json_object_iter_peek_name(&it), json);
+ json_object_iter_next(&it);
+ }
+ break;
+ case json_type_array:
+ arrayLen = json_object_array_length(src);
+ dst = json_object_new_array();
+ for(i = 0 ; i < arrayLen ; ++i) {
+ json = json_object_array_get_idx(src, i);
+ json = jsonDeepCopy(json);
+ json_object_array_add(dst, json);
+ }
+ break;
+ case json_type_null:
+ default:DBGPRINTF("jsonDeepCopy(): error unknown type %d\n",
+ json_object_get_type(src));
+ dst = NULL;
+ break;
+ }
+done: return dst;
+}
+
+
+rsRetVal
+msgSetJSONFromVar(smsg_t * const pMsg, uchar *varname, struct svar *v, int force_reset)
+{
+ struct json_object *json = NULL;
+ char *cstr;
+ DEFiRet;
+ switch(v->datatype) {
+ case 'S':/* string */
+ cstr = es_str2cstr(v->d.estr, NULL);
+ json = json_object_new_string(cstr);
+ free(cstr);
+ break;
+ case 'N':/* number (integer) */
+ json = json_object_new_int64(v->d.n);
+ break;
+ case 'J':/* native JSON */
+ json = jsonDeepCopy(v->d.json);
+ break;
+ default:DBGPRINTF("msgSetJSONFromVar: unsupported datatype %c\n",
+ v->datatype);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ msgAddJSON(pMsg, varname, json, force_reset, 0);
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal
+MsgAddToStructuredData(smsg_t * const pMsg, uchar *toadd, rs_size_t len)
+{
+ uchar *newptr;
+ rs_size_t newlen;
+ int empty;
+ DEFiRet;
+ empty = pMsg->pszStrucData == NULL || pMsg->pszStrucData[0] == '-';
+ newlen = (empty) ? len : pMsg->lenStrucData + len;
+ CHKmalloc(newptr = (uchar*) realloc(pMsg->pszStrucData, newlen+1));
+ if(empty) {
+ memcpy(newptr, toadd, len);
+ } else {
+ memcpy(newptr+pMsg->lenStrucData, toadd, len);
+ }
+ pMsg->pszStrucData = newptr;
+ pMsg->pszStrucData[newlen] = '\0';
+ pMsg->lenStrucData = newlen;
+finalize_it:
+ RETiRet;
+}
+
+
+/* Fill a message propert description. Space must already be alloced
+ * by the caller. This is for efficiency, as we expect this to happen
+ * as part of a larger structure alloc.
+ * Note that CEE/LOCAL_VAR properties can come in either as
+ * "$!xx"/"$.xx" or "!xx"/".xx" - we will unify them here.
+ */
+rsRetVal
+msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen)
+{
+ propid_t id;
+ int offs;
+ DEFiRet;
+ if(propNameToID(name, &id) != RS_RET_OK) {
+ parser_errmsg("invalid property '%s'", name);
+ /* now try to find some common error causes */
+ if(!strcasecmp((char*)name, "myhostname"))
+ parser_errmsg("did you mean '$myhostname' instead of '%s'? "
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "bom"))
+ parser_errmsg("did you mean '$bom' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "now"))
+ parser_errmsg("did you mean '$now' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "year"))
+ parser_errmsg("did you mean '$year' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "month"))
+ parser_errmsg("did you mean '$month' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "day"))
+ parser_errmsg("did you mean '$day' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "hour"))
+ parser_errmsg("did you mean '$hour' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "hhour"))
+ parser_errmsg("did you mean '$hhour' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "qhour"))
+ parser_errmsg("did you mean '$qhour' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "minute"))
+ parser_errmsg("did you mean '$minute' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "now-utc"))
+ parser_errmsg("did you mean '$now-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "year-utc"))
+ parser_errmsg("did you mean '$year-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "month-utc"))
+ parser_errmsg("did you mean '$month-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "day-utc"))
+ parser_errmsg("did you mean '$day-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "hour-utc"))
+ parser_errmsg("did you mean '$hour-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "hhour-utc"))
+ parser_errmsg("did you mean '$hhour-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "qhour-utc"))
+ parser_errmsg("did you mean '$qhour-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ else if(!strcasecmp((char*)name, "minute-utc"))
+ parser_errmsg("did you mean '$minute-utc' instead of '%s'?"
+ "See also: https://www.rsyslog.com/rsyslog-info-1/", name);
+ ABORT_FINALIZE(RS_RET_INVLD_PROP);
+ }
+ if(id == PROP_CEE || id == PROP_LOCAL_VAR || id == PROP_GLOBAL_VAR) {
+ /* in these cases, we need the field name for later processing */
+ /* normalize name: remove $ if present */
+ offs = (name[0] == '$') ? 1 : 0;
+ pProp->name = ustrdup(name + offs);
+ pProp->nameLen = nameLen - offs;
+ /* we patch the root name, so that support functions do not need to
+ * check for different root chars. */
+ pProp->name[0] = '!';
+ }
+ pProp->id = id;
+finalize_it:
+ RETiRet;
+}
+
+void
+msgPropDescrDestruct(msgPropDescr_t *pProp)
+{
+ if(pProp != NULL) {
+ if(pProp->id == PROP_CEE ||
+ pProp->id == PROP_LOCAL_VAR ||
+ pProp->id == PROP_GLOBAL_VAR)
+ free(pProp->name);
+ }
+}
+
+
+/* dummy */
+static rsRetVal msgQueryInterface(interface_t __attribute__((unused)) *i) { return RS_RET_NOT_IMPLEMENTED; }
+
+/* Initialize the message class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-01-04
+ */
+BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE)
+ pthread_mutex_init(&glblVars_lock, NULL);
+
+ /* request objects we use */
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(var, CORE_COMPONENT));
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize);
+ /* some more inits */
+# ifdef HAVE_MALLOC_TRIM
+ INIT_ATOMIC_HELPER_MUT(mutTrimCtr);
+# endif
+ENDObjClassInit(msg)
diff --git a/runtime/msg.h b/runtime/msg.h
new file mode 100644
index 0000000..f665144
--- /dev/null
+++ b/runtime/msg.h
@@ -0,0 +1,281 @@
+/* msg.h
+ * Header file for all msg-related functions.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "template.h" /* this is a quirk, but these two are too interdependant... */
+
+#ifndef MSG_H_INCLUDED
+#define MSG_H_INCLUDED 1
+
+#include <pthread.h>
+#include <libestr.h>
+#include <stdint.h>
+#include <json.h>
+#include "obj.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "atomic.h"
+
+/* rgerhards 2004-11-08: The following structure represents a
+ * syslog message.
+ *
+ * Important Note:
+ * The message object is used for multiple purposes (once it
+ * has been created). Once created, it actully is a read-only
+ * object (though we do not specifically express this). In order
+ * to avoid multiple copies of the same object, we use a
+ * reference counter. This counter is set to 1 by the constructer
+ * and increased by 1 with a call to MsgAddRef(). The destructor
+ * checks the reference count. If it is more than 1, only the counter
+ * will be decremented. If it is 1, however, the object is actually
+ * destroyed. To make this work, it is vital that MsgAddRef() is
+ * called each time a "copy" is stored somewhere.
+ *
+ * WARNING: this structure is not calloc()ed, so be careful when
+ * adding new fields. You need to initialize them in
+ * msgBaseConstruct(). That function header comment also describes
+ * why this is the case.
+ */
+struct msg {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ flowControl_t flowCtlType;
+ /**< type of flow control we can apply, for enqueueing, needs not to be persisted because
+ once data has entered the queue, this property is no longer needed. */
+ pthread_mutex_t mut;
+ int iRefCount; /* reference counter (0 = unused) */
+ sbool bParseSuccess; /* set to reflect state of last executed higher level parser */
+ unsigned short iSeverity;/* the severity */
+ unsigned short iFacility;/* Facility code */
+ int offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */
+ int offMSG; /* offset at which the MSG part starts in pszRawMsg */
+ short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */
+ int msgFlags; /* flags associated with this message */
+ int iLenRawMsg; /* length of raw message */
+ int iLenMSG; /* Length of the MSG part */
+ int iLenTAG; /* Length of the TAG part */
+ int iLenHOSTNAME; /* Length of HOSTNAME */
+ int iLenPROGNAME; /* Length of PROGNAME (-1 = not yet set) */
+ uchar *pszRawMsg; /* message as it was received on the wire. This is important in case we
+ * need to preserve cryptographic verifiers. */
+ uchar *pszHOSTNAME; /* HOSTNAME from syslog message */
+ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 characters) */
+ char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 characters at most) */
+ char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 characters) */
+ char *pszRcvdAt_PgSQL; /* rcvdAt as PgSQL formatted string (always 21 characters) */
+ char *pszTIMESTAMP3164; /* TIMESTAMP as RFC3164 formatted string (always 15 characters) */
+ char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 characters at most) */
+ char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 characters) */
+ char *pszTIMESTAMP_PgSQL;/* TIMESTAMP as PgSQL formatted string (always 21 characters) */
+ uchar *pszStrucData; /* STRUCTURED-DATA */
+ uint16_t lenStrucData; /* (cached) length of STRUCTURED-DATA */
+ cstr_t *pCSAPPNAME; /* APP-NAME */
+ cstr_t *pCSPROCID; /* PROCID */
+ cstr_t *pCSMSGID; /* MSGID */
+ prop_t *pInputName; /* input name property */
+ prop_t *pRcvFromIP; /* IP of system message was received from */
+ union {
+ prop_t *pRcvFrom;/* name of system message was received from */
+ struct sockaddr_storage *pfrominet; /* unresolved name */
+ } rcvFrom;
+
+ ruleset_t *pRuleset; /* ruleset to be used for processing this message */
+ time_t ttGenTime; /* time msg object was generated, same as tRcvdAt, but a Unix timestamp.
+ While this field looks redundant, it is required because a Unix timestamp
+ is used at later processing stages (namely in the output arena). Thanks to
+ the subleties of how time is defined, there is no reliable way to reconstruct
+ the Unix timestamp from the syslogTime fields (in practice, we may be close
+ enough to reliable, but I prefer to leave the subtle things to the OS, where
+ it obviously is solved in way or another...). */
+ struct syslogTime tRcvdAt;/* time the message entered this program */
+ struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */
+ struct json_object *json;
+ struct json_object *localvars;
+ /* some fixed-size buffers to save malloc()/free() for frequently used fields (from the default templates) */
+ uchar szRawMsg[CONF_RAWMSG_BUFSIZE];
+ /* most messages are small, and these are stored here (without malloc/free!) */
+ uchar szHOSTNAME[CONF_HOSTNAME_BUFSIZE];
+ union {
+ uchar *ptr; /* pointer to progname value */
+ uchar szBuf[CONF_PROGNAME_BUFSIZE];
+ } PROGNAME;
+ union {
+ uchar *pszTAG; /* pointer to tag value */
+ uchar szBuf[CONF_TAG_BUFSIZE];
+ } TAG;
+ char pszTimestamp3164[CONST_LEN_TIMESTAMP_3164 + 1];
+ char pszTimestamp3339[CONST_LEN_TIMESTAMP_3339 + 1];
+ char pszTIMESTAMP_SecFrac[7];
+ /* Note: a pointer is 64 bits/8 char, so this is actually fewer than a pointer! */
+ char pszRcvdAt_SecFrac[7];
+ /* same as above. Both are fractional seconds for their respective timestamp */
+ char pszTIMESTAMP_Unix[12]; /* almost as small as a pointer! */
+ char pszRcvdAt_Unix[12];
+ char dfltTZ[8]; /* 7 chars max, less overhead than ptr! */
+ uchar *pszUUID; /* The message's UUID */
+};
+
+
+/* message flags (msgFlags), not an enum for historical reasons */
+#define NOFLAG 0x000
+/* no flag is set (to be used when a flag must be specified and none is required) */
+#define INTERNAL_MSG 0x001
+/* msg generated by logmsgInternal() --> special handling */
+/* 0x002 not used because it was previously a known value - rgerhards, 2008-10-09 */
+#define IGNDATE 0x004
+/* ignore, if given, date in message and use date of reception as msg date */
+#define MARK 0x008
+/* this message is a mark */
+#define NEEDS_PARSING 0x010
+/* raw message, must be parsed before processing can be done */
+#define PARSE_HOSTNAME 0x020
+/* parse the hostname during message parsing */
+#define NEEDS_DNSRESOL 0x040
+/* fromhost address is unresolved and must be locked up via DNS reverse lookup first */
+#define NEEDS_ACLCHK_U 0x080
+/* check UDP ACLs after DNS resolution has been done in main queue consumer */
+#define NO_PRI_IN_RAW 0x100
+/* rawmsg does not include a PRI (Solaris!), but PRI is already set correctly in the msg object */
+#define PRESERVE_CASE 0x200
+/* preserve case in fromhost */
+
+/* (syslog) protocol types */
+#define MSG_LEGACY_PROTOCOL 0
+#define MSG_RFC5424_PROTOCOL 1
+
+#define MAX_VARIABLE_NAME_LEN 1024
+
+/* function prototypes
+ */
+PROTOTYPEObjClassInit(msg);
+rsRetVal msgConstruct(smsg_t **ppThis);
+rsRetVal msgConstructWithTime(smsg_t **ppThis, const struct syslogTime *stTime, const time_t ttGenTime);
+rsRetVal msgConstructForDeserializer(smsg_t **ppThis);
+rsRetVal msgConstructFinalizer(smsg_t *pThis);
+rsRetVal msgDestruct(smsg_t **ppM);
+smsg_t * MsgDup(smsg_t * pOld);
+smsg_t *MsgAddRef(smsg_t *pM);
+void setProtocolVersion(smsg_t *pM, int iNewVersion);
+void MsgSetInputName(smsg_t *pMsg, prop_t*);
+void MsgSetDfltTZ(smsg_t *pThis, char *tz);
+rsRetVal MsgSetAPPNAME(smsg_t *pMsg, const char* pszAPPNAME);
+rsRetVal MsgSetPROCID(smsg_t *pMsg, const char* pszPROCID);
+rsRetVal MsgSetMSGID(smsg_t *pMsg, const char* pszMSGID);
+void MsgSetParseSuccess(smsg_t *pMsg, int bSuccess);
+void MsgSetTAG(smsg_t *pMsg, const uchar* pszBuf, const size_t lenBuf);
+void MsgSetRuleset(smsg_t *pMsg, ruleset_t*);
+rsRetVal MsgSetFlowControlType(smsg_t *pMsg, flowControl_t eFlowCtl);
+rsRetVal MsgSetStructuredData(smsg_t *const pMsg, const char* pszStrucData);
+rsRetVal MsgAddToStructuredData(smsg_t *pMsg, uchar *toadd, rs_size_t len);
+void MsgGetStructuredData(smsg_t *pM, uchar **pBuf, rs_size_t *len);
+rsRetVal msgSetFromSockinfo(smsg_t *pThis, struct sockaddr_storage *sa);
+void MsgSetRcvFrom(smsg_t *pMsg, prop_t*);
+void MsgSetRcvFromStr(smsg_t *const pMsg, const uchar* pszRcvFrom, const int, prop_t **);
+rsRetVal MsgSetRcvFromIP(smsg_t *pMsg, prop_t*);
+rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp);
+void MsgSetHOSTNAME(smsg_t *pMsg, const uchar* pszHOSTNAME, const int lenHOSTNAME);
+rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, int offs);
+void MsgSetMSGoffs(smsg_t *pMsg, int offs);
+void MsgSetRawMsgWOSize(smsg_t *pMsg, char* pszRawMsg);
+void ATTR_NONNULL() MsgSetRawMsg(smsg_t *const pThis, const char*const pszRawMsg, const size_t lenMsg);
+rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar* pszMSG, int lenMSG);
+uchar *MsgGetProp(smsg_t *pMsg, struct templateEntry *pTpe, msgPropDescr_t *pProp,
+ rs_size_t *pPropLen, unsigned short *pbMustBeFreed, struct syslogTime *ttNow);
+uchar *getRcvFrom(smsg_t *pM);
+void getTAG(smsg_t *pM, uchar **ppBuf, int *piLen, sbool);
+const char *getTimeReported(smsg_t *pM, enum tplFormatTypes eFmt);
+const char *getPRI(smsg_t *pMsg);
+int getPRIi(const smsg_t * const pM);
+int ATTR_NONNULL() getRawMsgLen(const smsg_t *const pMsg);
+void getRawMsg(const smsg_t *pM, uchar **pBuf, int *piLen);
+void ATTR_NONNULL() MsgTruncateToMaxSize(smsg_t *const pThis);
+rsRetVal msgAddJSON(smsg_t *pM, uchar *name, struct json_object *json, int force_reset, int sharedReference);
+rsRetVal msgAddMetadata(smsg_t *msg, uchar *metaname, uchar *metaval);
+rsRetVal msgAddMultiMetadata(smsg_t *msg, const uchar **metaname, const uchar **metaval, const int count);
+rsRetVal MsgGetSeverity(smsg_t *pThis, int *piSeverity);
+rsRetVal MsgDeserialize(smsg_t *pMsg, strm_t *pStrm);
+rsRetVal MsgSetPropsViaJSON(smsg_t *__restrict__ const pMsg, const uchar *__restrict__ const json);
+rsRetVal MsgSetPropsViaJSON_Object(smsg_t *__restrict__ const pMsg, struct json_object *json);
+const uchar* msgGetJSONMESG(smsg_t *__restrict__ const pMsg);
+
+uchar *getMSG(smsg_t *pM);
+const char *getHOSTNAME(smsg_t *pM);
+char *getPROCID(smsg_t *pM, sbool bLockMutex);
+char *getAPPNAME(smsg_t *pM, sbool bLockMutex);
+void setMSGLen(smsg_t *pM, int lenMsg);
+int getMSGLen(smsg_t *pM);
+void getInputName(const smsg_t * const pM, uchar **ppsz, int *const plen);
+
+int getHOSTNAMELen(smsg_t *pM);
+uchar *getProgramName(smsg_t *pM, sbool bLockMutex);
+uchar *getRcvFrom(smsg_t *pM);
+rsRetVal propNameToID(const uchar *pName, propid_t *pPropID);
+uchar *propIDToName(propid_t propID);
+rsRetVal ATTR_NONNULL() msgCheckVarExists(smsg_t *const pMsg, msgPropDescr_t *pProp);
+rsRetVal msgGetJSONPropJSON(smsg_t *pMsg, msgPropDescr_t *pProp, struct json_object **pjson);
+rsRetVal msgGetJSONPropJSONorString(smsg_t * const pMsg, msgPropDescr_t *pProp, struct json_object **pjson,
+uchar **pcstr);
+rsRetVal getJSONPropVal(smsg_t *pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen,
+unsigned short *pbMustBeFreed);
+rsRetVal msgSetJSONFromVar(smsg_t *pMsg, uchar *varname, struct svar *var, int force_reset);
+rsRetVal msgDelJSON(smsg_t *pMsg, uchar *varname);
+rsRetVal jsonFind(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **jsonres);
+struct json_object *jsonDeepCopy(struct json_object *src);
+
+rsRetVal msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen);
+void msgPropDescrDestruct(msgPropDescr_t *pProp);
+void msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri);
+
+#define msgGetProtocolVersion(pM) ((pM)->iProtocolVersion)
+
+/* returns non-zero if the message has structured data, 0 otherwise */
+#define MsgHasStructuredData(pM) (((pM)->pszStrucData == NULL) ? 0 : 1)
+
+/* ------------------------------ some inline functions ------------------------------ */
+
+/* add Metadata to the message. This is stored in a special JSON
+ * container. Note that only string types are currently supported,
+ * what should pose absolutely no problem with the string-ish nature
+ * of rsyslog metadata.
+ * added 2015-01-09 rgerhards
+ */
+/* set raw message size. This is needed in some cases where a trunctation is necessary
+ * but the raw message must not be newly set. The most important (and currently only)
+ * use case is if we remove trailing LF or NUL characters. Note that the size can NOT
+ * be extended, only shrunk!
+ * rgerhards, 2009-08-26
+ */
+static inline void __attribute__((unused))
+MsgSetRawMsgSize(smsg_t *const __restrict__ pMsg, const size_t newLen)
+{
+ assert(newLen <= (size_t) pMsg->iLenRawMsg);
+ pMsg->iLenRawMsg = newLen;
+ pMsg->pszRawMsg[newLen] = '\0';
+}
+
+/* get the ruleset that is associated with the ruleset.
+ * May be NULL. -- rgerhards, 2009-10-27
+ */
+#define MsgGetRuleset(pMsg) ((pMsg)->pRuleset)
+
+#endif /* #ifndef MSG_H_INCLUDED */
diff --git a/runtime/net.c b/runtime/net.c
new file mode 100644
index 0000000..ff46cbc
--- /dev/null
+++ b/runtime/net.c
@@ -0,0 +1,1741 @@
+/* net.c
+ * Implementation of network-related stuff.
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" networking code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Starting 2007-12-24, I have begun to shuffle more network-related code
+ * from syslogd.c to over here. I am not sure if it will stay here in the
+ * long term, but it is good to have it out of syslogd.c. Maybe this here is
+ * an interim location ;)
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#else
+#include "compat/ifaddrs.h"
+#endif /* HAVE_GETIFADDRS */
+#include <sys/types.h>
+#include <arpa/inet.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "parse.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "net.h"
+#include "dnscache.h"
+#include "prop.h"
+#include "rsconf.h"
+
+#ifdef OS_SOLARIS
+#include <arpa/nameser_compat.h>
+# define s6_addr32 _S6_un._S6_u32
+ typedef unsigned int u_int32_t;
+#endif
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+
+#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
+extern size_t SALEN(struct sockaddr *sa);
+#endif
+/* support for defining allowed TCP and UDP senders. We use the same
+ * structure to implement this (a linked list), but we define two different
+ * list roots, one for UDP and one for TCP.
+ * rgerhards, 2005-09-26
+ */
+/* All of the five below are read-only after startup */
+struct AllowedSenders *pAllowedSenders_UDP = NULL; /* the roots of the allowed sender */
+struct AllowedSenders *pAllowedSenders_TCP = NULL; /* lists. If NULL, all senders are ok! */
+static struct AllowedSenders *pLastAllowedSenders_UDP = NULL; /* and now the pointers to the last */
+static struct AllowedSenders *pLastAllowedSenders_TCP = NULL; /* element in the respective list */
+#ifdef USE_GSSAPI
+struct AllowedSenders *pAllowedSenders_GSS = NULL;
+static struct AllowedSenders *pLastAllowedSenders_GSS = NULL;
+#endif
+
+/* ------------------------------ begin permitted peers code ------------------------------ */
+
+
+/* sets the correct allow root pointer based on provided type
+ * rgerhards, 2008-12-01
+ */
+static rsRetVal
+setAllowRoot(struct AllowedSenders **ppAllowRoot, uchar *pszType)
+{
+ DEFiRet;
+
+ if(!strcmp((char*)pszType, "UDP"))
+ *ppAllowRoot = pAllowedSenders_UDP;
+ else if(!strcmp((char*)pszType, "TCP"))
+ *ppAllowRoot = pAllowedSenders_TCP;
+#ifdef USE_GSSAPI
+ else if(!strcmp((char*)pszType, "GSS"))
+ *ppAllowRoot = pAllowedSenders_GSS;
+#endif
+ else {
+ dbgprintf("program error: invalid allowed sender ID '%s', denying...\n", pszType);
+ ABORT_FINALIZE(RS_RET_CODE_ERR); /* everything is invalid for an invalid type */
+ }
+
+finalize_it:
+ RETiRet;
+}
+/* re-initializes (sets to NULL) the correct allow root pointer
+ * rgerhards, 2009-01-12
+ */
+static rsRetVal
+reinitAllowRoot(uchar *pszType)
+{
+ DEFiRet;
+
+ if(!strcmp((char*)pszType, "UDP"))
+ pAllowedSenders_UDP = NULL;
+ else if(!strcmp((char*)pszType, "TCP"))
+ pAllowedSenders_TCP = NULL;
+#ifdef USE_GSSAPI
+ else if(!strcmp((char*)pszType, "GSS"))
+ pAllowedSenders_GSS = NULL;
+#endif
+ else {
+ dbgprintf("program error: invalid allowed sender ID '%s', denying...\n", pszType);
+ ABORT_FINALIZE(RS_RET_CODE_ERR); /* everything is invalid for an invalid type */
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* add a wildcard entry to this permitted peer. Entries are always
+ * added at the tail of the list. pszStr and lenStr identify the wildcard
+ * entry to be added. Note that the string is NOT \0 terminated, so
+ * we must rely on lenStr for when it is finished.
+ * rgerhards, 2008-05-27
+ */
+static rsRetVal
+AddPermittedPeerWildcard(permittedPeers_t *pPeer, uchar* pszStr, size_t lenStr)
+{
+ permittedPeerWildcard_t *pNew = NULL;
+ size_t iSrc;
+ size_t iDst;
+ DEFiRet;
+
+ assert(pPeer != NULL);
+ assert(pszStr != NULL);
+
+ CHKmalloc(pNew = calloc(1, sizeof(*pNew)));
+
+ if(lenStr == 0) { /* empty domain components are permitted */
+ pNew->wildcardType = PEER_WILDCARD_EMPTY_COMPONENT;
+ FINALIZE;
+ } else {
+ /* alloc memory for the domain component. We may waste a byte or
+ * two, but that's ok.
+ */
+ CHKmalloc(pNew->pszDomainPart = malloc(lenStr +1 ));
+ }
+
+ if(pszStr[0] == '*') {
+ pNew->wildcardType = PEER_WILDCARD_AT_START;
+ iSrc = 1; /* skip '*' */
+ } else {
+ iSrc = 0;
+ }
+
+ for(iDst = 0 ; iSrc < lenStr && pszStr[iSrc] != '*' ; ++iSrc, ++iDst) {
+ pNew->pszDomainPart[iDst] = pszStr[iSrc];
+ }
+
+ if(iSrc < lenStr) {
+ if(iSrc + 1 == lenStr && pszStr[iSrc] == '*') {
+ if(pNew->wildcardType == PEER_WILDCARD_AT_START) {
+ ABORT_FINALIZE(RS_RET_INVALID_WILDCARD);
+ } else {
+ pNew->wildcardType = PEER_WILDCARD_AT_END;
+ }
+ } else {
+ /* we have an invalid wildcard, something follows the asterisk! */
+ ABORT_FINALIZE(RS_RET_INVALID_WILDCARD);
+ }
+ }
+
+ if(lenStr == 1 && pNew->wildcardType == PEER_WILDCARD_AT_START) {
+ pNew->wildcardType = PEER_WILDCARD_MATCH_ALL;
+ }
+
+ /* if we reach this point, we had a valid wildcard. We now need to
+ * properly terminate the domain component string.
+ */
+ pNew->pszDomainPart[iDst] = '\0';
+ pNew->lenDomainPart = strlen((char*)pNew->pszDomainPart);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL) {
+ if(pNew->pszDomainPart != NULL)
+ free(pNew->pszDomainPart);
+ free(pNew);
+ }
+ } else {
+ /* enqueue the element */
+ if(pPeer->pWildcardRoot == NULL) {
+ pPeer->pWildcardRoot = pNew;
+ pPeer->pWildcardLast = pNew;
+ } else {
+ pPeer->pWildcardLast->pNext = pNew;
+ }
+ pPeer->pWildcardLast = pNew;
+ }
+
+ RETiRet;
+}
+
+
+/* Destruct a permitted peer's wildcard list -- rgerhards, 2008-05-27 */
+static rsRetVal
+DestructPermittedPeerWildcards(permittedPeers_t *pPeer)
+{
+ permittedPeerWildcard_t *pCurr;
+ permittedPeerWildcard_t *pDel;
+ DEFiRet;
+
+ assert(pPeer != NULL);
+
+ for(pCurr = pPeer->pWildcardRoot ; pCurr != NULL ; /*EMPTY*/) {
+ pDel = pCurr;
+ pCurr = pCurr->pNext;
+ free(pDel->pszDomainPart);
+ free(pDel);
+ }
+
+ pPeer->pWildcardRoot = NULL;
+ pPeer->pWildcardLast = NULL;
+
+ RETiRet;
+}
+
+
+/* add a permitted peer. PermittedPeers is an interim solution until we can provide
+ * access control via enhanced RainerScript methods.
+ * Note: the provided string is handed over to this function, caller must
+ * no longer access it. -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+AddPermittedPeer(permittedPeers_t **ppRootPeer, uchar* pszID)
+{
+ permittedPeers_t *pNew = NULL;
+ DEFiRet;
+
+ assert(ppRootPeer != NULL);
+ assert(pszID != NULL);
+
+ CHKmalloc(pNew = calloc(1, sizeof(permittedPeers_t))); /* we use calloc() for consistency with "real" objects */
+ CHKmalloc(pNew->pszID = (uchar*)strdup((char*)pszID));
+
+ if(*ppRootPeer != NULL) {
+ pNew->pNext = *ppRootPeer;
+ }
+ *ppRootPeer = pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ free(pNew);
+ }
+ RETiRet;
+}
+
+
+/* Destruct a permitted peers list -- rgerhards, 2008-05-19 */
+static rsRetVal
+DestructPermittedPeers(permittedPeers_t **ppRootPeer)
+{
+ permittedPeers_t *pCurr;
+ permittedPeers_t *pDel;
+ DEFiRet;
+
+ assert(ppRootPeer != NULL);
+
+ for(pCurr = *ppRootPeer ; pCurr != NULL ; /*EMPTY*/) {
+ pDel = pCurr;
+ pCurr = pCurr->pNext;
+ DestructPermittedPeerWildcards(pDel);
+ free(pDel->pszID);
+ free(pDel);
+ }
+
+ *ppRootPeer = NULL;
+
+ RETiRet;
+}
+
+
+/* Compile a wildcard. The function first checks if there is a wildcard
+ * present and compiles it only if so ;) It sets the etryType status
+ * accordingly.
+ * rgerhards, 2008-05-27
+ */
+static rsRetVal
+PermittedPeerWildcardCompile(permittedPeers_t *pPeer)
+{
+ uchar *pC;
+ uchar *pStart;
+ DEFiRet;
+
+ assert(pPeer != NULL);
+ assert(pPeer->pszID != NULL);
+
+ /* first check if we have a wildcard */
+ for(pC = pPeer->pszID ; *pC != '\0' && *pC != '*' ; ++pC)
+ /*EMPTY, just skip*/;
+
+ if(*pC == '\0') {
+ /* no wildcard found, we are mostly done */
+ pPeer->etryType = PERM_PEER_TYPE_PLAIN;
+ FINALIZE;
+ }
+
+ /* if we reach this point, the string contains wildcards. So let's
+ * compile the structure. To do so, we must parse from dot to dot
+ * and create a wildcard entry for each domain component we find.
+ * We must also flag problems if we have an asterisk in the middle
+ * of the text (it is supported at the start or end only).
+ */
+ pPeer->etryType = PERM_PEER_TYPE_WILDCARD;
+ pC = pPeer->pszID;
+ while(*pC != '\0') {
+ pStart = pC;
+ /* find end of domain component */
+ for( ; *pC != '\0' && *pC != '.' ; ++pC)
+ /*EMPTY, just skip*/;
+ CHKiRet(AddPermittedPeerWildcard(pPeer, pStart, pC - pStart));
+ /* now check if we have an empty component at end of string */
+ if(*pC == '.' && *(pC + 1) == '\0') {
+ /* pStart is a dummy, it is not used if length is 0 */
+ CHKiRet(AddPermittedPeerWildcard(pPeer, pStart, 0));
+ }
+ if(*pC != '\0')
+ ++pC;
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "error compiling wildcard expression '%s'",
+ pPeer->pszID);
+ }
+ RETiRet;
+}
+
+
+/* Do a (potential) wildcard match. The function first checks if the wildcard
+ * has already been compiled and, if not, compiles it. If the peer entry in
+ * question does NOT contain a wildcard, a simple strcmp() is done.
+ * *pbIsMatching is set to 0 if there is no match and something else otherwise.
+ * rgerhards, 2008-05-27 */
+static rsRetVal
+PermittedPeerWildcardMatch(permittedPeers_t *const pPeer,
+ const uchar *pszNameToMatch,
+ int *const pbIsMatching)
+{
+ const permittedPeerWildcard_t *pWildcard;
+ const uchar *pC;
+ size_t iWildcard, iName; /* work indexes for backward comparisons */
+ DEFiRet;
+
+ assert(pPeer != NULL);
+ assert(pszNameToMatch != NULL);
+ assert(pbIsMatching != NULL);
+
+ if(pPeer->etryType == PERM_PEER_TYPE_UNDECIDED) {
+ PermittedPeerWildcardCompile(pPeer);
+ }
+
+ if(pPeer->etryType == PERM_PEER_TYPE_PLAIN) {
+ *pbIsMatching = !strcmp((char*)pPeer->pszID, (char*)pszNameToMatch);
+ FINALIZE;
+ }
+
+ /* we have a wildcard, so we need to extract the domain components and
+ * check then against the provided wildcards.
+ */
+ pWildcard = pPeer->pWildcardRoot;
+ pC = pszNameToMatch;
+ while(*pC != '\0') {
+ if(pWildcard == NULL) {
+ /* we have more domain components than we have wildcards --> no match */
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ const uchar *const pStart = pC; /* start of current domain component */
+ while(*pC != '\0' && *pC != '.') {
+ ++pC;
+ }
+
+ /* got the component, now do the match */
+ switch(pWildcard->wildcardType) {
+ case PEER_WILDCARD_NONE:
+ if( pWildcard->lenDomainPart != (size_t) (pC - pStart)
+ || strncmp((char*)pStart, (char*)pWildcard->pszDomainPart, pC - pStart)) {
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ break;
+ case PEER_WILDCARD_AT_START:
+ /* we need to do the backwards-matching manually */
+ if(pWildcard->lenDomainPart > (size_t) (pC - pStart)) {
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ iName = (size_t) (pC - pStart) - pWildcard->lenDomainPart;
+ iWildcard = 0;
+ while(iWildcard < pWildcard->lenDomainPart) {
+ // I give up, I see now way to remove false positive -- rgerhards, 2017-10-23
+ #ifndef __clang_analyzer__
+ if(pWildcard->pszDomainPart[iWildcard] != pStart[iName]) {
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ #endif
+ ++iName;
+ ++iWildcard;
+ }
+ break;
+ case PEER_WILDCARD_AT_END:
+ if( pWildcard->lenDomainPart > (size_t) (pC - pStart)
+ || strncmp((char*)pStart, (char*)pWildcard->pszDomainPart,
+ pWildcard->lenDomainPart)) {
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ break;
+ case PEER_WILDCARD_MATCH_ALL:
+ /* everything is OK, just continue */
+ break;
+ case PEER_WILDCARD_EMPTY_COMPONENT:
+ if(pC - pStart > 0) {
+ /* if it is not empty, it is no match... */
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+ break;
+ }
+ pWildcard = pWildcard->pNext; /* we processed this entry */
+
+ /* skip '.' if we had it and so prepare for next iteration */
+ if(*pC == '.')
+ ++pC;
+ }
+
+ if(pWildcard != NULL) {
+ /* we have more domain components than in the name to be
+ * checked. So this is no match.
+ */
+ *pbIsMatching = 0;
+ FINALIZE;
+ }
+
+ *pbIsMatching = 1; /* finally... it matches ;) */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ------------------------------ end permitted peers code ------------------------------ */
+
+
+/* Code for handling allowed/disallowed senders
+ */
+static void MaskIP6 (struct in6_addr *addr, uint8_t bits) {
+ register uint8_t i;
+
+ assert (addr != NULL);
+ assert (bits <= 128);
+
+ i = bits/32;
+ if (bits%32)
+ addr->s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
+ for (; i < (sizeof addr->s6_addr32)/4; i++)
+ addr->s6_addr32[i] = 0;
+}
+
+static void MaskIP4 (struct in_addr *addr, uint8_t bits) {
+
+ assert (addr != NULL);
+ assert (bits <=32 );
+
+ addr->s_addr &= htonl(0xffffffff << (32 - bits));
+}
+
+#define SIN(sa) ((struct sockaddr_in *)(void*)(sa))
+#define SIN6(sa) ((struct sockaddr_in6 *)(void*)(sa))
+
+
+/* This is a cancel-safe getnameinfo() version, because we learned
+ * (via drd/valgrind) that getnameinfo() seems to have some issues
+ * when being cancelled, at least if the module was dlloaded.
+ * rgerhards, 2008-09-30
+ */
+static int
+mygetnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ int iCancelStateSave;
+ int i;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ i = getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ pthread_setcancelstate(iCancelStateSave, NULL);
+ return i;
+}
+
+
+/* This function adds an allowed sender entry to the ACL linked list.
+ * In any case, a single entry is added. If an error occurs, the
+ * function does its error reporting itself. All validity checks
+ * must already have been done by the caller.
+ * This is a helper to AddAllowedSender().
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
+ struct NetAddr *iAllow, uint8_t iSignificantBits)
+{
+ struct AllowedSenders *pEntry = NULL;
+
+ assert(ppRoot != NULL);
+ assert(ppLast != NULL);
+ assert(iAllow != NULL);
+
+ if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders))) == NULL) {
+ return RS_RET_OUT_OF_MEMORY; /* no options left :( */
+ }
+
+ memcpy(&(pEntry->allowedSender), iAllow, sizeof (struct NetAddr));
+ pEntry->pNext = NULL;
+ pEntry->SignificantBits = iSignificantBits;
+
+ /* enqueue */
+ if(*ppRoot == NULL) {
+ *ppRoot = pEntry;
+ } else {
+ (*ppLast)->pNext = pEntry;
+ }
+ *ppLast = pEntry;
+
+ return RS_RET_OK;
+}
+
+/* function to clear the allowed sender structure in cases where
+ * it must be freed (occurs most often when HUPed).
+ * rgerhards, 2008-12-02: revamped this code when we fixed the interface
+ * definition. Now an iterative algorithm is used.
+ */
+static void
+clearAllowedSenders(uchar *pszType)
+{
+ struct AllowedSenders *pPrev;
+ struct AllowedSenders *pCurr = NULL;
+
+ if(setAllowRoot(&pCurr, pszType) != RS_RET_OK)
+ return; /* if something went wrong, so let's leave */
+
+ while(pCurr != NULL) {
+ pPrev = pCurr;
+ pCurr = pCurr->pNext;
+ /* now delete the entry we are right now processing */
+ if(F_ISSET(pPrev->allowedSender.flags, ADDR_NAME))
+ free(pPrev->allowedSender.addr.HostWildcard);
+ else
+ free(pPrev->allowedSender.addr.NetAddr);
+ free(pPrev);
+ }
+
+ /* indicate root pointer is de-init (was forgotten previously, resulting in
+ * all kinds of interesting things) -- rgerhards, 2009-01-12
+ */
+ reinitAllowRoot(pszType);
+}
+
+
+/* function to add an allowed sender to the allowed sender list. The
+ * root of the list is caller-provided, so it can be used for all
+ * supported lists. The caller must provide a pointer to the root,
+ * as it eventually needs to be updated. Also, a pointer to the
+ * pointer to the last element must be provided (to speed up adding
+ * list elements).
+ * rgerhards, 2005-09-26
+ * If a hostname is given there are possible multiple entries
+ * added (all addresses from that host).
+ */
+static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
+ struct NetAddr *iAllow, uint8_t iSignificantBits)
+{
+ struct addrinfo *restmp = NULL;
+ DEFiRet;
+
+ assert(ppRoot != NULL);
+ assert(ppLast != NULL);
+ assert(iAllow != NULL);
+
+ if (!F_ISSET(iAllow->flags, ADDR_NAME)) {
+ if(iSignificantBits == 0)
+ /* we handle this seperatly just to provide a better
+ * error message.
+ */
+ LogError(0, NO_ERRCODE, "You can not specify 0 bits of the netmask, this would "
+ "match ALL systems. If you really intend to do that, "
+ "remove all $AllowedSender directives.");
+
+ switch (iAllow->addr.NetAddr->sa_family) {
+ case AF_INET:
+ if((iSignificantBits < 1) || (iSignificantBits > 32)) {
+ LogError(0, NO_ERRCODE, "Invalid number of bits (%d) in IPv4 address - adjusted to 32",
+ (int)iSignificantBits);
+ iSignificantBits = 32;
+ }
+
+ MaskIP4 (&(SIN(iAllow->addr.NetAddr)->sin_addr), iSignificantBits);
+ break;
+ case AF_INET6:
+ if((iSignificantBits < 1) || (iSignificantBits > 128)) {
+ LogError(0, NO_ERRCODE, "Invalid number of bits (%d) in IPv6 address - adjusted to 128",
+ iSignificantBits);
+ iSignificantBits = 128;
+ }
+
+ MaskIP6 (&(SIN6(iAllow->addr.NetAddr)->sin6_addr), iSignificantBits);
+ break;
+ default:
+ /* rgerhards, 2007-07-16: We have an internal program error in this
+ * case. However, there is not much we can do against it right now. Of
+ * course, we could abort, but that would probably cause more harm
+ * than good. So we continue to run. We simply do not add this line - the
+ * worst thing that happens is that one host will not be allowed to
+ * log.
+ */
+ LogError(0, NO_ERRCODE, "Internal error caused AllowedSender to be ignored, AF = %d",
+ iAllow->addr.NetAddr->sa_family);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* OK, entry constructed, now lets add it to the ACL list */
+ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
+ } else {
+ /* we need to process a hostname ACL */
+ if(glbl.GetDisableDNS(loadConf)) {
+ LogError(0, NO_ERRCODE, "Ignoring hostname based ACLs because DNS is disabled.");
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ if (!strchr (iAllow->addr.HostWildcard, '*') &&
+ !strchr (iAllow->addr.HostWildcard, '?') &&
+ loadConf->globals.ACLDontResolve == 0) {
+ /* single host - in this case, we pull its IP addresses from DNS
+ * and add IP-based ACLs.
+ */
+ struct addrinfo hints, *res;
+ struct NetAddr allowIP;
+
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+# ifdef AI_ADDRCONFIG /* seems not to be present on all systems */
+ hints.ai_flags = AI_ADDRCONFIG;
+# endif
+
+ if (getaddrinfo (iAllow->addr.HostWildcard, NULL, &hints, &res) != 0) {
+ LogError(0, NO_ERRCODE, "DNS error: Can't resolve \"%s\"", iAllow->addr.HostWildcard);
+
+ if (loadConf->globals.ACLAddHostnameOnFail) {
+ LogError(0, NO_ERRCODE, "Adding hostname \"%s\" to ACL as a wildcard "
+ "entry.", iAllow->addr.HostWildcard);
+ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
+ FINALIZE;
+ } else {
+ LogError(0, NO_ERRCODE, "Hostname \"%s\" WON\'T be added to ACL.",
+ iAllow->addr.HostWildcard);
+ ABORT_FINALIZE(RS_RET_NOENTRY);
+ }
+ }
+
+ restmp = res;
+ for ( ; res != NULL ; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET: /* add IPv4 */
+ iSignificantBits = 32;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits))
+ != RS_RET_OK) {
+ free(allowIP.addr.NetAddr);
+ FINALIZE;
+ }
+ break;
+ case AF_INET6: /* IPv6 - but need to check if it is a v6-mapped IPv4 */
+ if(IN6_IS_ADDR_V4MAPPED (&SIN6(res->ai_addr)->sin6_addr)) {
+ /* extract & add IPv4 */
+
+ iSignificantBits = 32;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = (struct sockaddr *)
+ malloc(sizeof(struct sockaddr))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ SIN(allowIP.addr.NetAddr)->sin_family = AF_INET;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ SIN(allowIP.addr.NetAddr)->sin_len = sizeof (struct sockaddr_in);
+#endif
+ SIN(allowIP.addr.NetAddr)->sin_port = 0;
+ memcpy(&(SIN(allowIP.addr.NetAddr)->sin_addr.s_addr),
+ &(SIN6(res->ai_addr)->sin6_addr.s6_addr32[3]),
+ sizeof (in_addr_t));
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
+ iSignificantBits))
+ != RS_RET_OK) {
+ free(allowIP.addr.NetAddr);
+ FINALIZE;
+ }
+ } else {
+ /* finally add IPv6 */
+
+ iSignificantBits = 128;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
+ iSignificantBits))
+ != RS_RET_OK) {
+ free(allowIP.addr.NetAddr);
+ FINALIZE;
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ /* wildcards in hostname - we need to add a text-based ACL.
+ * For this, we already have everything ready and just need
+ * to pass it along...
+ */
+ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
+ }
+ }
+
+finalize_it:
+ if(restmp != NULL) {
+ freeaddrinfo (restmp);
+ }
+ RETiRet;
+}
+
+
+static const char *SENDER_TEXT[4] = { "", "UDP", "TCP", "GSS" };
+/* Print an allowed sender list. The caller must tell us which one.
+ * iListToPrint = 1 means UDP, 2 means TCP
+ * rgerhards, 2005-09-27
+ */
+static void
+PrintAllowedSenders(int iListToPrint)
+{
+ struct AllowedSenders *pSender;
+ uchar szIP[64];
+#ifdef USE_GSSAPI
+#define iListToPrint_MAX 3
+#else
+#define iListToPrint_MAX 2
+#endif
+ assert((iListToPrint > 0) && (iListToPrint <= iListToPrint_MAX));
+
+ dbgprintf("Allowed %s Senders:\n", SENDER_TEXT[iListToPrint]);
+
+ pSender = (iListToPrint == 1) ? pAllowedSenders_UDP :
+#ifdef USE_GSSAPI
+ (iListToPrint == 3) ? pAllowedSenders_GSS :
+#endif
+ pAllowedSenders_TCP;
+ if(pSender == NULL) {
+ dbgprintf("\tNo restrictions set.\n");
+ } else {
+ while(pSender != NULL) {
+ if (F_ISSET(pSender->allowedSender.flags, ADDR_NAME))
+ dbgprintf ("\t%s\n", pSender->allowedSender.addr.HostWildcard);
+ else {
+ if(mygetnameinfo (pSender->allowedSender.addr.NetAddr,
+ SALEN(pSender->allowedSender.addr.NetAddr),
+ (char*)szIP, 64, NULL, 0, NI_NUMERICHOST) == 0) {
+ dbgprintf ("\t%s/%u\n", szIP, pSender->SignificantBits);
+ } else {
+ /* getnameinfo() failed - but as this is only a
+ * debug function, we simply spit out an error and do
+ * not care much about it.
+ */
+ dbgprintf("\tERROR in getnameinfo() - something may be wrong "
+ "- ignored for now\n");
+ }
+ }
+ pSender = pSender->pNext;
+ }
+ }
+}
+
+
+/* parse an allowed sender config line and add the allowed senders
+ * (if the line is correct).
+ * rgerhards, 2005-09-27
+ */
+static rsRetVal
+addAllowedSenderLine(char* pName, uchar** ppRestOfConfLine)
+{
+ struct AllowedSenders **ppRoot;
+ struct AllowedSenders **ppLast;
+ rsParsObj *pPars;
+ rsRetVal iRet;
+ struct NetAddr *uIP = NULL;
+ int iBits;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+ assert(*ppRestOfConfLine != NULL);
+
+ if(!strcasecmp(pName, "udp")) {
+ ppRoot = &pAllowedSenders_UDP;
+ ppLast = &pLastAllowedSenders_UDP;
+ } else if(!strcasecmp(pName, "tcp")) {
+ ppRoot = &pAllowedSenders_TCP;
+ ppLast = &pLastAllowedSenders_TCP;
+#ifdef USE_GSSAPI
+ } else if(!strcasecmp(pName, "gss")) {
+ ppRoot = &pAllowedSenders_GSS;
+ ppLast = &pLastAllowedSenders_GSS;
+#endif
+ } else {
+ LogError(0, RS_RET_ERR, "Invalid protocol '%s' in allowed sender "
+ "list, line ignored", pName);
+ return RS_RET_ERR;
+ }
+
+ /* OK, we now know the protocol and have valid list pointers.
+ * So let's process the entries. We are using the parse class
+ * for this.
+ */
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, (uchar*) *ppRestOfConfLine) != RS_RET_OK)) {
+ LogError(0, iRet, "Error %d constructing parser object - ignoring allowed sender list", iRet);
+ return(iRet);
+ }
+
+ while(!parsIsAtEndOfParseString(pPars)) {
+ if(parsPeekAtCharAtParsPtr(pPars) == '#')
+ break; /* a comment-sign stops processing of line */
+ /* now parse a single IP address */
+ if((iRet = parsAddrWithBits(pPars, &uIP, &iBits)) != RS_RET_OK) {
+ LogError(0, iRet, "Error %d parsing address in allowed sender"
+ "list - ignoring.", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+ if((iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits)) != RS_RET_OK) {
+ if(iRet == RS_RET_NOENTRY) {
+ LogError(0, iRet, "Error %d adding allowed sender entry "
+ "- ignoring.", iRet);
+ } else {
+ LogError(0, iRet, "Error %d adding allowed sender entry "
+ "- terminating, nothing more will be added.", iRet);
+ rsParsDestruct(pPars);
+ free(uIP);
+ return(iRet);
+ }
+ }
+ free (uIP); /* copy stored in AllowedSenders list */
+ }
+
+ /* cleanup */
+ *ppRestOfConfLine += parsGetCurrentPosition(pPars);
+ return rsParsDestruct(pPars);
+}
+
+
+
+/* compares a host to an allowed sender list entry. Handles all subleties
+ * including IPv4/v6 as well as domain name wildcards.
+ * This is a helper to isAllowedSender.
+ * Returns 0 if they do not match, 1 if they match and 2 if a DNS name would have been required.
+ * contributed 2007-07-16 by mildew@gmail.com
+ */
+static int
+MaskCmp(struct NetAddr *pAllow, uint8_t bits, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS)
+{
+ assert(pAllow != NULL);
+ assert(pFrom != NULL);
+
+ if(F_ISSET(pAllow->flags, ADDR_NAME)) {
+ if(bChkDNS == 0)
+ return 2;
+ dbgprintf("MaskCmp: host=\"%s\"; pattern=\"%s\"\n", pszFromHost, pAllow->addr.HostWildcard);
+
+# if !defined(FNM_CASEFOLD)
+ /* TODO: I don't know if that then works, seen on HP UX, what I have not in lab... ;) */
+ return(fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE) == 0);
+# else
+ return(fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE|FNM_CASEFOLD) == 0);
+# endif
+ } else {/* We need to compare an IP address */
+ switch (pFrom->sa_family) {
+ case AF_INET:
+ if (AF_INET == pAllow->addr.NetAddr->sa_family)
+ return(( SIN(pFrom)->sin_addr.s_addr & htonl(0xffffffff << (32 - bits)) )
+ == SIN(pAllow->addr.NetAddr)->sin_addr.s_addr);
+ else
+ return 0;
+ break;
+ case AF_INET6:
+ switch (pAllow->addr.NetAddr->sa_family) {
+ case AF_INET6: {
+ struct in6_addr ip, net;
+ register uint8_t i;
+
+ memcpy (&ip, &(SIN6(pFrom))->sin6_addr, sizeof (struct in6_addr));
+ memcpy (&net, &(SIN6(pAllow->addr.NetAddr))->sin6_addr, sizeof (struct in6_addr));
+
+ i = bits/32;
+ if (bits % 32)
+ ip.s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
+ for (; i < (sizeof ip.s6_addr32)/4; i++)
+ ip.s6_addr32[i] = 0;
+
+ return (memcmp (ip.s6_addr, net.s6_addr, sizeof ip.s6_addr) == 0 &&
+ (SIN6(pAllow->addr.NetAddr)->sin6_scope_id != 0 ?
+ SIN6(pFrom)->sin6_scope_id == SIN6(pAllow->addr.NetAddr)->sin6_scope_id : 1));
+ }
+ case AF_INET: {
+ struct in6_addr *ip6 = &(SIN6(pFrom))->sin6_addr;
+ struct in_addr *net = &(SIN(pAllow->addr.NetAddr))->sin_addr;
+
+ if ((ip6->s6_addr32[3] & (u_int32_t)
+ htonl((0xffffffff << (32 - bits)))) == net->s_addr &&
+#if BYTE_ORDER == LITTLE_ENDIAN
+ (ip6->s6_addr32[2] == (u_int32_t)0xffff0000) &&
+#else
+ (ip6->s6_addr32[2] == (u_int32_t)0x0000ffff) &&
+#endif
+ (ip6->s6_addr32[1] == 0) && (ip6->s6_addr32[0] == 0))
+ return 1;
+ else
+ return 0;
+ }
+ default:
+ /* Unsupported AF */
+ return 0;
+ }
+ /* fallthrough */
+ default:
+ /* Unsupported AF */
+ return 0;
+ }
+ }
+}
+
+
+/* check if a sender is allowed. The root of the the allowed sender.
+ * list must be proveded by the caller. As such, this function can be
+ * used to check both UDP and TCP allowed sender lists.
+ * returns 1, if the sender is allowed, 0 if not and 2 if we could not
+ * obtain a result because we would need a dns name, which we don't have
+ * (2 was added rgerhards, 2009-11-16).
+ * rgerhards, 2005-09-26
+ */
+static int isAllowedSender2(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS)
+{
+ struct AllowedSenders *pAllow;
+ struct AllowedSenders *pAllowRoot = NULL;
+ int bNeededDNS = 0; /* partial check because we could not resolve DNS? */
+ int ret;
+
+ assert(pFrom != NULL);
+
+ if(setAllowRoot(&pAllowRoot, pszType) != RS_RET_OK)
+ return 0; /* if something went wrong, we deny access - that's the better choice... */
+
+ if(pAllowRoot == NULL)
+ return 1; /* checking disabled, everything is valid! */
+
+ /* now we loop through the list of allowed senders. As soon as
+ * we find a match, we return back (indicating allowed). We loop
+ * until we are out of allowed senders. If so, we fall through the
+ * loop and the function's terminal return statement will indicate
+ * that the sender is disallowed.
+ */
+ for(pAllow = pAllowRoot ; pAllow != NULL ; pAllow = pAllow->pNext) {
+ ret = MaskCmp (&(pAllow->allowedSender), pAllow->SignificantBits, pFrom, pszFromHost, bChkDNS);
+ if(ret == 1)
+ return 1;
+ else if(ret == 2)
+ bNeededDNS = 2;
+ }
+ return bNeededDNS;
+}
+
+
+/* legacy API, not to be used any longer */
+static int
+isAllowedSender(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost) {
+ return isAllowedSender2(pszType, pFrom, pszFromHost, 1);
+}
+
+
+/* The following #ifdef sequence is a small compatibility
+ * layer. It tries to work around the different availality
+ * levels of SO_BSDCOMPAT on linuxes...
+ * I borrowed this code from
+ * http://www.erlang.org/ml-archive/erlang-questions/200307/msg00037.html
+ * It still needs to be a bit better adapted to rsyslog.
+ * rgerhards 2005-09-19
+ */
+#include <sys/utsname.h>
+static int
+should_use_so_bsdcompat(void)
+{
+#ifndef OS_BSD
+ static int use_so_bsdcompat = -1;
+
+ /* we guard the init code just by an atomic fetch to local variable. This still
+ * is racy, but the worst that can happen is that we do the very same init twice.
+ * This does hurt less than locking a mutex.
+ */
+ const int local_use_so_bsdcompat = PREFER_FETCH_32BIT(use_so_bsdcompat);
+ if(local_use_so_bsdcompat == -1) {
+ struct utsname myutsname;
+ unsigned int version, patchlevel;
+
+ if (uname(&myutsname) < 0) {
+ char errStr[1024];
+ dbgprintf("uname: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ PREFER_STORE_1_TO_INT(&use_so_bsdcompat);
+ FINALIZE;
+ }
+ /* Format is <version>.<patchlevel>.<sublevel><extraversion>
+ * where the first three are unsigned integers and the last
+ * is an arbitrary string. We only care about the first two. */
+ if (sscanf(myutsname.release, "%u.%u", &version, &patchlevel) != 2) {
+ dbgprintf("uname: unexpected release '%s'\r\n",
+ myutsname.release);
+ PREFER_STORE_1_TO_INT(&use_so_bsdcompat);
+ FINALIZE;
+ }
+ /* SO_BSCOMPAT is deprecated and triggers warnings in 2.5
+ * kernels. It is a no-op in 2.4 but not in 2.2 kernels. */
+ if (version > 2 || (version == 2 && patchlevel >= 5)) {
+ PREFER_STORE_0_TO_INT(&use_so_bsdcompat);
+ FINALIZE;
+ }
+ }
+finalize_it:
+ return PREFER_FETCH_32BIT(use_so_bsdcompat);
+#else /* #ifndef OS_BSD */
+ return 1;
+#endif /* #ifndef OS_BSD */
+}
+#ifndef SO_BSDCOMPAT
+/* this shall prevent compiler errors due to undfined name */
+#define SO_BSDCOMPAT 0
+#endif
+
+
+/* print out which socket we are listening on. This is only
+ * a debug aid. rgerhards, 2007-07-02
+ */
+static void
+debugListenInfo(int fd, char *type)
+{
+ const char *szFamily;
+ int port;
+ union {
+ struct sockaddr_storage sa;
+ struct sockaddr_in sa4;
+ struct sockaddr_in6 sa6;
+ } sockaddr;
+ socklen_t saLen = sizeof(sockaddr.sa);
+
+ if(getsockname(fd, (struct sockaddr *) &sockaddr.sa, &saLen) == 0) {
+ switch(sockaddr.sa.ss_family) {
+ case PF_INET:
+ szFamily = "IPv4";
+ port = ntohs(sockaddr.sa4.sin_port);
+ break;
+ case PF_INET6:
+ szFamily = "IPv6";
+ port = ntohs(sockaddr.sa6.sin6_port);
+ break;
+ default:
+ szFamily = "other";
+ port = -1;
+ break;
+ }
+ dbgprintf("Listening on %s syslogd socket %d (%s/port %d).\n",
+ type, fd, szFamily, port);
+ return;
+ }
+
+ /* we can not obtain peer info. We are just providing
+ * debug info, so this is no reason to break the program
+ * or do any serious error reporting.
+ */
+ dbgprintf("Listening on syslogd socket %d - could not obtain peer info.\n", fd);
+}
+
+
+/* Return a printable representation of a host addresses. If
+ * a parameter is NULL, it is not set. rgerhards, 2013-01-22
+ */
+static rsRetVal
+cvthname(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip)
+{
+ DEFiRet;
+ assert(f != NULL);
+ iRet = dnscacheLookup(f, fqdn, NULL, localName, ip);
+ RETiRet;
+}
+
+
+/* get the name of the local host. A pointer to a character pointer is passed
+ * in, which on exit points to the local hostname. This buffer is dynamically
+ * allocated and must be free()ed by the caller. If the functions returns an
+ * error, the pointer is NULL.
+ * This function always tries to return a FQDN, even so be quering DNS. So it
+ * is safe to assume for the caller that when the function does not return
+ * a FQDN, it simply is not available. The domain part of that string is
+ * normalized to lower case. The hostname is kept in mixed case for historic
+ * reasons.
+ */
+#define EMPTY_HOSTNAME_REPLACEMENT "localhost-empty-hostname"
+static rsRetVal
+getLocalHostname(rsconf_t *const pConf, uchar **ppName)
+{
+ DEFiRet;
+ char hnbuf[8192];
+ uchar *fqdn = NULL;
+ int empty_hostname = 1;
+
+ if(gethostname(hnbuf, sizeof(hnbuf)) != 0) {
+ strcpy(hnbuf, EMPTY_HOSTNAME_REPLACEMENT);
+ } else {
+ /* now guard against empty hostname
+ * see https://github.com/rsyslog/rsyslog/issues/1040
+ */
+ if(hnbuf[0] == '\0') {
+ strcpy(hnbuf, EMPTY_HOSTNAME_REPLACEMENT);
+ } else {
+ empty_hostname = 0;
+ hnbuf[sizeof(hnbuf)-1] = '\0'; /* be on the safe side... */
+ }
+ }
+
+ char *dot = strstr(hnbuf, ".");
+ struct addrinfo *res = NULL;
+ if(!empty_hostname && dot == NULL && pConf != NULL && !glbl.GetDisableDNS(pConf)) {
+ /* we need to (try) to find the real name via resolver */
+ struct addrinfo flags;
+ memset(&flags, 0, sizeof(flags));
+ flags.ai_flags = AI_CANONNAME;
+ int error = getaddrinfo((char*)hnbuf, NULL, &flags, &res);
+ if (error != 0 &&
+ error != EAI_NONAME && error != EAI_AGAIN && error != EAI_FAIL) {
+ /* If we get one of errors above, network is probably
+ * not working yet, so we fall back to local hostname below
+ */
+ LogError(0, RS_RET_ERR, "getaddrinfo failed obtaining local "
+ "hostname - using '%s' instead; error: %s",
+ hnbuf, gai_strerror(error));
+ }
+ if (res != NULL) {
+ /* When AI_CANONNAME is set first member of res linked-list */
+ /* should contain what we need */
+ if (res->ai_canonname != NULL && res->ai_canonname[0] != '\0') {
+ CHKmalloc(fqdn = (uchar*)strdup(res->ai_canonname));
+ dot = strstr((char*)fqdn, ".");
+ }
+ }
+ }
+
+ if(fqdn == NULL) {
+ /* already was FQDN or we could not obtain a better one */
+ CHKmalloc(fqdn = (uchar*) strdup(hnbuf));
+ }
+
+ if(dot != NULL)
+ for(char *p = dot+1 ; *p ; ++p)
+ *p = tolower(*p);
+
+ *ppName = fqdn;
+finalize_it:
+ if (res != NULL) {
+ freeaddrinfo(res);
+ }
+ RETiRet;
+}
+
+
+/* closes the UDP listen sockets (if they exist) and frees
+ * all dynamically assigned memory.
+ */
+static void
+closeUDPListenSockets(int *pSockArr)
+{
+ register int i;
+
+ assert(pSockArr != NULL);
+ if(pSockArr != NULL) {
+ for (i = 0; i < *pSockArr; i++)
+ close(pSockArr[i+1]);
+ free(pSockArr);
+ }
+}
+
+
+/* create a single UDP socket and bail out if an error occurs.
+ * This is called from a loop inside create_udp_socket which
+ * iterates through potentially multiple sockets. NOT to be
+ * used elsewhere.
+ */
+static rsRetVal ATTR_NONNULL(1, 2)
+create_single_udp_socket(int *const s, /* socket */
+ struct addrinfo *const r,
+ const uchar *const hostname,
+ const int bIsServer,
+ const int rcvbuf,
+ const int sndbuf,
+ const int ipfreebind,
+ const char *const device
+ )
+{
+ const int on = 1;
+ int sockflags;
+ int actrcvbuf;
+ int actsndbuf;
+ socklen_t optlen;
+ char errStr[1024];
+ DEFiRet;
+
+ assert(r != NULL); // does NOT work with -O2 or higher due to ATTR_NONNULL!
+ assert(s != NULL);
+
+# if defined (_AIX)
+ /* AIXPORT : socktype will be SOCK_DGRAM, as set in hints before */
+ *s = socket(r->ai_family, SOCK_DGRAM, r->ai_protocol);
+# else
+ *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+# endif
+ if (*s < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) {
+ LogError(errno, NO_ERRCODE, "create_udp_socket(), socket");
+ /* it is debateble if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ }
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+# ifdef IPV6_V6ONLY
+ if (r->ai_family == AF_INET6) {
+ int ion = 1;
+ if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&ion, sizeof (ion)) < 0) {
+ LogError(errno, RS_RET_ERR, "error creating UDP socket - setsockopt");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+# endif
+
+ if(device) {
+# if defined(SO_BINDTODEVICE)
+ if(setsockopt(*s, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0)
+# endif
+ {
+ LogError(errno, RS_RET_ERR, "create UDP socket bound to device failed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ if(setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ LogError(errno, RS_RET_ERR, "create UDP socket failed to set REUSEADDR");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+ /* AIXPORT : SO_BSDCOMPAT socket option is deprecated, and its usage
+ * has been discontinued on most unixes, AIX does not support this option,
+ * hence avoid the call.
+ */
+# if !defined(OS_BSD) && !defined(__hpux) && !defined(_AIX)
+ if (should_use_so_bsdcompat()) {
+ if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, (char *) &on, sizeof(on)) < 0) {
+ LogError(errno, RS_RET_ERR, "create UDP socket failed to set BSDCOMPAT");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+# endif
+ if(bIsServer) {
+ DBGPRINTF("net.c: trying to set server socket %d to non-blocking mode\n", *s);
+ if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(*s, F_SETFL, sockflags);
+ }
+ if (sockflags == -1) {
+ LogError(errno, RS_RET_ERR, "net.c: socket %d fcntl(O_NONBLOCK)", *s);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+ if(sndbuf != 0) {
+# if defined(SO_SNDBUFFORCE)
+ if(setsockopt(*s, SOL_SOCKET, SO_SNDBUFFORCE, &sndbuf, sizeof(sndbuf)) < 0)
+# endif
+ {
+ /* if we fail, try to do it the regular way. Experiments show that at
+ * least some platforms do not return an error here, but silently set
+ * it to the max permitted value. So we do our error check a bit
+ * differently by querying the size below.
+ */
+ if(setsockopt(*s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0) {
+ /* keep Coverity happy */
+ DBGPRINTF("setsockopt in %s:%d failed - this is expected and "
+ "handled at later stages\n", __FILE__, __LINE__);
+ }
+ }
+ /* report socket buffer sizes */
+ optlen = sizeof(actsndbuf);
+ if(getsockopt(*s, SOL_SOCKET, SO_SNDBUF, &actsndbuf, &optlen) == 0) {
+ LogMsg(0, NO_ERRCODE, LOG_INFO,
+ "socket %d, actual os socket sndbuf size is %d", *s, actsndbuf);
+ if(sndbuf != 0 && actsndbuf/2 != sndbuf) {
+ LogError(errno, NO_ERRCODE,
+ "could not set os socket sndbuf size %d for socket %d, "
+ "value now is %d", sndbuf, *s, actsndbuf/2);
+ }
+ } else {
+ DBGPRINTF("could not obtain os socket rcvbuf size for socket %d: %s\n",
+ *s, rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+ }
+
+ if(rcvbuf != 0) {
+# if defined(SO_RCVBUFFORCE)
+ if(setsockopt(*s, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)) < 0)
+# endif
+ {
+ /* if we fail, try to do it the regular way. Experiments show that at
+ * least some platforms do not return an error here, but silently set
+ * it to the max permitted value. So we do our error check a bit
+ * differently by querying the size below.
+ */
+ if(setsockopt(*s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0) {
+ /* keep Coverity happy */
+ DBGPRINTF("setsockopt in %s:%d failed - this is expected and "
+ "handled at later stages\n", __FILE__, __LINE__);
+ }
+ }
+ optlen = sizeof(actrcvbuf);
+ if(getsockopt(*s, SOL_SOCKET, SO_RCVBUF, &actrcvbuf, &optlen) == 0) {
+ LogMsg(0, NO_ERRCODE, LOG_INFO,
+ "socket %d, actual os socket rcvbuf size %d\n", *s, actrcvbuf);
+ if(rcvbuf != 0 && actrcvbuf/2 != rcvbuf) {
+ LogError(errno, NO_ERRCODE,
+ "cannot set os socket rcvbuf size %d for socket %d, value now is %d",
+ rcvbuf, *s, actrcvbuf/2);
+ }
+ } else {
+ DBGPRINTF("could not obtain os socket rcvbuf size for socket %d: %s\n",
+ *s, rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+ }
+
+ if(bIsServer) {
+ /* rgerhards, 2007-06-22: if we run on a kernel that does not support
+ * the IPV6_V6ONLY socket option, we need to use a work-around. On such
+ * systems the IPv6 socket does also accept IPv4 sockets. So an IPv4
+ * socket can not listen on the same port as an IPv6 socket. The only
+ * workaround is to ignore the "socket in use" error. This is what we
+ * do if we have to.
+ */
+ if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
+# ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+# endif
+ ) {
+ if (errno == EADDRNOTAVAIL && ipfreebind != IPFREEBIND_DISABLED) {
+ if (setsockopt(*s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)) < 0) {
+ LogError(errno, RS_RET_ERR, "setsockopt(IP_FREEBIND)");
+ } else if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
+ LogError(errno, RS_RET_ERR, "bind with IP_FREEBIND");
+ } else {
+ if (ipfreebind >= IPFREEBIND_ENABLED_WITH_LOG)
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING,
+ "bound address %s IP free", hostname);
+ FINALIZE;
+ }
+ }
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(*s != -1) {
+ close(*s);
+ *s = -1;
+ }
+ }
+ RETiRet;
+}
+
+/* creates the UDP listen sockets
+ * hostname and/or pszPort may be NULL, but not both!
+ * bIsServer indicates if a server socket should be created
+ * 1 - server, 0 - client
+ * Note: server sockets are created in non-blocking mode, client ones
+ * are blocking.
+ * param rcvbuf indicates desired rcvbuf size; 0 means OS default,
+ * similar for sndbuf.
+ */
+static int *
+create_udp_socket(uchar *hostname,
+ uchar *pszPort,
+ const int bIsServer,
+ const int rcvbuf,
+ const int sndbuf,
+ const int ipfreebind,
+ char *device)
+{
+ struct addrinfo hints, *res, *r;
+ int error, maxs, *s, *socks;
+ rsRetVal localRet;
+
+ assert(!((pszPort == NULL) && (hostname == NULL))); /* one of them must be non-NULL */
+ memset(&hints, 0, sizeof(hints));
+ if(bIsServer)
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
+ else
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily(runConf);
+ hints.ai_socktype = SOCK_DGRAM;
+# if defined (_AIX)
+ /* AIXPORT : SOCK_DGRAM has the protocol IPPROTO_UDP
+ * getaddrinfo needs this hint on AIX
+ */
+ hints.ai_protocol = IPPROTO_UDP;
+# endif
+ error = getaddrinfo((char*) hostname, (char*) pszPort, &hints, &res);
+ if(error) {
+ LogError(0, NO_ERRCODE, "%s", gai_strerror(error));
+ LogError(0, NO_ERRCODE, "UDP message reception disabled due to error logged in last message.\n");
+ return NULL;
+ }
+
+ /* Count max number of sockets we may open */
+ for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+ socks = malloc((maxs+1) * sizeof(int));
+ if (socks == NULL) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "couldn't allocate memory for UDP "
+ "sockets, suspending UDP message reception");
+ freeaddrinfo(res);
+ return NULL;
+ }
+
+ *socks = 0; /* num of sockets counter at start of array */
+ s = socks + 1;
+ for (r = res; r != NULL ; r = r->ai_next) {
+ localRet = create_single_udp_socket(s, r, hostname, bIsServer, rcvbuf,
+ sndbuf, ipfreebind, device);
+ if(localRet == RS_RET_OK) {
+ (*socks)++;
+ s++;
+ }
+ }
+
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(Debug && *socks != maxs)
+ dbgprintf("We could initialize %d UDP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", *socks, maxs);
+
+ if(*socks == 0) {
+ LogError(0, NO_ERRCODE, "No UDP socket could successfully be initialized, "
+ "some functionality may be disabled.\n");
+ /* we do NOT need to close any sockets, because there were none... */
+ free(socks);
+ return(NULL);
+ }
+
+ return(socks);
+}
+
+
+/* check if two provided socket addresses point to the same host. Note that the
+ * length of the sockets must be provided as third parameter. This is necessary to
+ * compare non IPv4/v6 hosts, in which case we do a simple memory compare of the
+ * address structure (in that case, the same host may not reliably be detected).
+ * Note that we need to do the comparison not on the full structure, because it contains things
+ * like the port, which we do not need to look at when thinking about hostnames. So we look
+ * at the relevant fields, what means a somewhat more complicated processing.
+ * Also note that we use a non-standard calling interface, as this is much more natural and
+ * it looks extremely unlikely that we get an exception of any kind here. What we
+ * return is mimiced after memcmp(), and as such useful for building binary trees
+ * (the order relation may be a bit arbritrary, but at least it is consistent).
+ * rgerhards, 2009-09-03
+ */
+static int CmpHost(struct sockaddr_storage *s1, struct sockaddr_storage* s2, size_t socklen)
+{
+ int ret;
+
+ if(((struct sockaddr*) s1)->sa_family != ((struct sockaddr*) s2)->sa_family) {
+ ret = memcmp(s1, s2, socklen);
+ goto finalize_it;
+ }
+
+ if(((struct sockaddr*) s1)->sa_family == AF_INET) {
+ if(((struct sockaddr_in *) s1)->sin_addr.s_addr == ((struct sockaddr_in*)s2)->sin_addr.s_addr) {
+ ret = 0;
+ } else if(((struct sockaddr_in *) s1)->sin_addr.s_addr < ((struct sockaddr_in*)s2)->sin_addr.s_addr) {
+ ret = -1;
+ } else {
+ ret = 1;
+ }
+ } else if(((struct sockaddr*) s1)->sa_family == AF_INET6) {
+ /* IPv6 addresses are always 16 octets long */
+ ret = memcmp(((struct sockaddr_in6 *)s1)->sin6_addr.s6_addr,
+ ((struct sockaddr_in6*)s2)->sin6_addr.s6_addr, 16);
+ } else {
+ ret = memcmp(s1, s2, socklen);
+ }
+
+finalize_it:
+ return ret;
+}
+
+
+
+/* check if restrictions (ALCs) exists. The goal of this function is to disable the
+ * somewhat time-consuming ACL checks if no restrictions are defined (the usual case).
+ * This also permits to gain some speedup by using firewall-based ACLs instead of
+ * rsyslog ACLs (the recommended method.
+ * rgerhards, 2009-11-16
+ */
+static rsRetVal
+HasRestrictions(uchar *pszType, int *bHasRestrictions) {
+ struct AllowedSenders *pAllowRoot = NULL;
+ DEFiRet;
+
+ CHKiRet(setAllowRoot(&pAllowRoot, pszType));
+
+ *bHasRestrictions = (pAllowRoot == NULL) ? 0 : 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ *bHasRestrictions = 1; /* in this case it is better to check individually */
+ DBGPRINTF("Error %d trying to obtain ACL restriction state of '%s'\n", iRet, pszType);
+ }
+ RETiRet;
+}
+
+
+/* return the IP address (IPv4/6) for the provided interface. Returns
+ * RS_RET_NOT_FOUND if interface can not be found in interface list.
+ * The family must be correct (AF_INET vs. AF_INET6, AF_UNSPEC means
+ * either of *these two*).
+ * The function re-queries the interface list (at least in theory).
+ * However, it caches entries in order to avoid too-frequent requery.
+ * rgerhards, 2012-03-06
+ */
+static rsRetVal
+getIFIPAddr(uchar *szif, int family, uchar *pszbuf, int lenBuf)
+{
+#ifdef _AIX
+ struct ifaddrs_rsys * ifaddrs = NULL;
+ struct ifaddrs_rsys * ifa;
+#else
+ struct ifaddrs * ifaddrs = NULL;
+ struct ifaddrs * ifa;
+#endif
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
+ } savecast;
+ void * pAddr;
+ DEFiRet;
+
+ if(getifaddrs(&ifaddrs) != 0) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if(strcmp(ifa->ifa_name, (char*)szif))
+ continue;
+ savecast.sa = ifa->ifa_addr;
+ if( (family == AF_INET6 || family == AF_UNSPEC)
+ && ifa->ifa_addr->sa_family == AF_INET6) {
+ pAddr = &(savecast.ipv6->sin6_addr);
+ inet_ntop(AF_INET6, pAddr, (char*)pszbuf, lenBuf);
+ break;
+ } else if(/* (family == AF_INET || family == AF_UNSPEC)
+ &&*/ ifa->ifa_addr->sa_family == AF_INET) {
+ pAddr = &(savecast.ipv4->sin_addr);
+ inet_ntop(AF_INET, pAddr, (char*)pszbuf, lenBuf);
+ break;
+ }
+ }
+
+ if(ifaddrs != NULL)
+ freeifaddrs(ifaddrs);
+
+ if(ifa == NULL)
+ iRet = RS_RET_NOT_FOUND;
+
+finalize_it:
+ RETiRet;
+
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(net)
+CODESTARTobjQueryInterface(net)
+ if(pIf->ifVersion != netCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->cvthname = cvthname;
+ /* things to go away after proper modularization */
+ pIf->addAllowedSenderLine = addAllowedSenderLine;
+ pIf->PrintAllowedSenders = PrintAllowedSenders;
+ pIf->clearAllowedSenders = clearAllowedSenders;
+ pIf->debugListenInfo = debugListenInfo;
+ pIf->create_udp_socket = create_udp_socket;
+ pIf->closeUDPListenSockets = closeUDPListenSockets;
+ pIf->isAllowedSender = isAllowedSender;
+ pIf->isAllowedSender2 = isAllowedSender2;
+ pIf->should_use_so_bsdcompat = should_use_so_bsdcompat;
+ pIf->getLocalHostname = getLocalHostname;
+ pIf->AddPermittedPeer = AddPermittedPeer;
+ pIf->DestructPermittedPeers = DestructPermittedPeers;
+ pIf->PermittedPeerWildcardMatch = PermittedPeerWildcardMatch;
+ pIf->CmpHost = CmpHost;
+ pIf->HasRestrictions = HasRestrictions;
+ pIf->GetIFIPAddr = getIFIPAddr;
+finalize_it:
+ENDobjQueryInterface(net)
+
+
+/* exit our class
+ * rgerhards, 2008-03-10
+ */
+BEGINObjClassExit(net, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(net)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDObjClassExit(net)
+
+
+/* Initialize the net class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(net, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(net)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ netClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(netClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/net.h b/runtime/net.h
new file mode 100644
index 0000000..88d2df5
--- /dev/null
+++ b/runtime/net.h
@@ -0,0 +1,180 @@
+/* Definitions for network-related stuff.
+ *
+ * Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NET_H
+#define INCLUDED_NET_H
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h> /* this is needed on HP UX -- rgerhards, 2008-03-04 */
+
+typedef enum _TCPFRAMINGMODE {
+ TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */
+ TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */
+ } TCPFRAMINGMODE;
+
+#define F_SET(where, flag) ((where)|=(flag))
+#define F_ISSET(where, flag) (((where)&(flag))==(flag))
+#define F_UNSET(where, flag) ((where)&=~(flag))
+
+#define ADDR_NAME 0x01 /* address is hostname wildcard) */
+#define ADDR_PRI6 0x02 /* use IPv6 address prior to IPv4 when resolving */
+
+/* portability: incase IP_FREEBIND is not defined */
+#ifndef IP_FREEBIND
+#define IP_FREEBIND 0
+#endif
+/* defines for IP_FREEBIND, currently being used in imudp */
+#define IPFREEBIND_DISABLED 0x00 /* don't enable IP_FREEBIND in sock option */
+#define IPFREEBIND_ENABLED_NO_LOG 0x01 /* enable IP_FREEBIND but no warn on success */
+#define IPFREEBIND_ENABLED_WITH_LOG 0x02 /* enable IP_FREEBIND and warn on success */
+
+#ifdef OS_BSD
+# ifndef _KERNEL
+# define s6_addr32 __u6_addr.__u6_addr32
+# endif
+#endif
+
+struct NetAddr {
+ uint8_t flags;
+ union {
+ struct sockaddr *NetAddr;
+ char *HostWildcard;
+ } addr;
+};
+
+#ifndef SO_BSDCOMPAT
+ /* this shall prevent compiler errors due to undefined name */
+# define SO_BSDCOMPAT 0
+#endif
+
+
+/* IPv6 compatibility layer for older platforms
+ * We need to handle a few things different if we are running
+ * on an older platform which does not support all the glory
+ * of IPv6. We try to limit toll on features and reliability,
+ * but obviously it is better to run rsyslog on a platform that
+ * supports everything...
+ * rgerhards, 2007-06-22
+ */
+#ifndef AI_NUMERICSERV
+# define AI_NUMERICSERV 0
+#endif
+
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define SALEN(sa) ((sa)->sa_len)
+#else
+static inline size_t __attribute__((unused))
+SALEN(struct sockaddr *sa) {
+ switch (sa->sa_family) {
+ case AF_INET: return (sizeof (struct sockaddr_in));
+ case AF_INET6: return (sizeof (struct sockaddr_in6));
+ default: return 0;
+ }
+}
+#endif
+
+struct AllowedSenders {
+ struct NetAddr allowedSender; /* ip address allowed */
+ uint8_t SignificantBits; /* defines how many bits should be discarded (eqiv to mask) */
+ struct AllowedSenders *pNext;
+};
+
+
+/* this structure is a helper to implement wildcards in permittedPeers_t. It specifies
+ * the domain component and the matching mode.
+ * rgerhards, 2008-05-27
+ */
+struct permittedPeerWildcard_s {
+ uchar *pszDomainPart;
+ size_t lenDomainPart;
+ enum {
+ PEER_WILDCARD_NONE = 0, /**< no wildcard in this entry */
+ PEER_WILDCARD_AT_START = 1, /**< wildcard at start of entry (*name) */
+ PEER_WILDCARD_AT_END = 2, /**< wildcard at end of entry (name*) */
+ PEER_WILDCARD_MATCH_ALL = 3, /**< only * wildcard, matches all values */
+ PEER_WILDCARD_EMPTY_COMPONENT = 4/**< special case: domain component empty (e.g. "..") */
+ } wildcardType;
+ permittedPeerWildcard_t *pNext;
+};
+
+/* for fingerprints and hostnames, we need to have a temporary linked list of
+ * permitted values. Unforutnately, we must also duplicate this in the netstream
+ * drivers. However, this is the best interim solution (with the least effort).
+ * A clean implementation requires that we have more capable variables and the
+ * full-fledged scripting engine available. So we have opted to do the interim
+ * solution so that our users can begin to enjoy authenticated TLS. The next step
+ * (hopefully) is to enhance RainerScript. -- rgerhards, 2008-05-19
+ */
+struct permittedPeers_s {
+ uchar *pszID;
+ enum {
+ PERM_PEER_TYPE_UNDECIDED = 0, /**< we have not yet decided the type (fine in some auth modes) */
+ PERM_PEER_TYPE_PLAIN = 1, /**< just plain text contained */
+ PERM_PEER_TYPE_WILDCARD = 2, /**< wildcards are contained, wildcard struture is filled */
+ } etryType;
+ permittedPeers_t *pNext;
+ permittedPeerWildcard_t *pWildcardRoot; /**< root of the wildcard, NULL if not initialized */
+ permittedPeerWildcard_t *pWildcardLast; /**< end of the wildcard list, NULL if not initialized */
+};
+
+
+/* interfaces */
+BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*cvthname)(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip);
+ /* things to go away after proper modularization */
+ rsRetVal (*addAllowedSenderLine)(char* pName, uchar** ppRestOfConfLine);
+ void (*PrintAllowedSenders)(int iListToPrint);
+ void (*clearAllowedSenders)(uchar*);
+ void (*debugListenInfo)(int fd, char *type);
+ int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer, int rcvbuf, int sndbuf,
+ int ipfreebind, char *device);
+ void (*closeUDPListenSockets)(int *finet);
+ int (*isAllowedSender)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost); /* deprecated! */
+ rsRetVal (*getLocalHostname)(rsconf_t *const, uchar**);
+ int (*should_use_so_bsdcompat)(void);
+ /* permitted peer handling should be replaced by something better (see comments above) */
+ rsRetVal (*AddPermittedPeer)(permittedPeers_t **ppRootPeer, uchar *pszID);
+ rsRetVal (*DestructPermittedPeers)(permittedPeers_t **ppRootPeer);
+ rsRetVal (*PermittedPeerWildcardMatch)(permittedPeers_t *pPeer, const uchar *pszNameToMatch, int *pbIsMatching);
+ /* v5 interface additions */
+ int (*CmpHost)(struct sockaddr_storage *, struct sockaddr_storage*, size_t);
+ /* v6 interface additions - 2009-11-16 */
+ rsRetVal (*HasRestrictions)(uchar *, int *bHasRestrictions);
+ int (*isAllowedSender2)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS);
+ /* v7 interface additions - 2012-03-06 */
+ rsRetVal (*GetIFIPAddr)(uchar *szif, int family, uchar *pszbuf, int lenBuf);
+ /* v8 cvthname() signature change -- rgerhards, 2013-01-18 */
+ /* v9 create_udp_socket() signature change -- dsahern, 2016-11-11 */
+ /* v10 moved data members to rsconf_t -- alakatos, 2021-12-29 */
+ENDinterface(net)
+#define netCURR_IF_VERSION 10 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(net);
+
+/* the name of our library binary */
+#define LM_NET_FILENAME "lmnet"
+
+#endif /* #ifndef INCLUDED_NET_H */
diff --git a/runtime/net_ossl.c b/runtime/net_ossl.c
new file mode 100644
index 0000000..60e3fa2
--- /dev/null
+++ b/runtime/net_ossl.c
@@ -0,0 +1,1217 @@
+/* net.c
+ * Implementation of network-related stuff.
+ *
+ * File begun on 2023-08-29 by Alorbach (extracted from net.c)
+ *
+ * Copyright 2023 Andre Lorbach and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "parse.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "net.h"
+#include "net_ossl.h"
+#include "nsd_ptcp.h"
+#include "rsconf.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(nsd_ptcp)
+
+/*--------------------------------------MT OpenSSL helpers ------------------------------------------*/
+static MUTEX_TYPE *mutex_buf = NULL;
+static sbool openssl_initialized = 0; // Avoid multiple initialization / deinitialization
+
+void locking_function(int mode, int n,
+ __attribute__((unused)) const char * file, __attribute__((unused)) int line)
+{
+ if (mode & CRYPTO_LOCK)
+ MUTEX_LOCK(mutex_buf[n]);
+ else
+ MUTEX_UNLOCK(mutex_buf[n]);
+}
+
+unsigned long id_function(void)
+{
+ return ((unsigned long)THREAD_ID);
+}
+
+
+struct CRYPTO_dynlock_value * dyn_create_function(
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line)
+{
+ struct CRYPTO_dynlock_value *value;
+ value = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
+ if (!value)
+ return NULL;
+
+ MUTEX_SETUP(value->mutex);
+ return value;
+}
+
+void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line)
+{
+ if (mode & CRYPTO_LOCK)
+ MUTEX_LOCK(l->mutex);
+ else
+ MUTEX_UNLOCK(l->mutex);
+}
+
+void dyn_destroy_function(struct CRYPTO_dynlock_value *l,
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line)
+{
+ MUTEX_CLEANUP(l->mutex);
+ free(l);
+}
+
+/* set up support functions for openssl multi-threading. This must
+ * be done at library initialisation. If the function fails,
+ * processing can not continue normally. On failure, 0 is
+ * returned, on success 1.
+ */
+int opensslh_THREAD_setup(void)
+{
+ int i;
+ if (openssl_initialized == 1) {
+ DBGPRINTF("openssl: multithread setup already initialized\n");
+ return 1;
+ }
+
+ mutex_buf = (MUTEX_TYPE *)malloc(CRYPTO_num_locks( ) * sizeof(MUTEX_TYPE));
+ if (mutex_buf == NULL)
+ return 0;
+ for (i = 0; i < CRYPTO_num_locks( ); i++)
+ MUTEX_SETUP(mutex_buf[i]);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ CRYPTO_set_id_callback(id_function);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+ CRYPTO_set_locking_callback(locking_function);
+ /* The following three CRYPTO_... functions are the OpenSSL functions
+ for registering the callbacks we implemented above */
+ CRYPTO_set_dynlock_create_callback(dyn_create_function);
+ CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
+
+ DBGPRINTF("openssl: multithread setup finished\n");
+ openssl_initialized = 1;
+ return 1;
+}
+
+/* shut down openssl - do this only when you are totally done
+ * with openssl.
+ */
+int opensslh_THREAD_cleanup(void)
+{
+ int i;
+ if (openssl_initialized == 0) {
+ DBGPRINTF("openssl: multithread cleanup already done\n");
+ return 1;
+ }
+ if (!mutex_buf)
+ return 0;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ CRYPTO_set_id_callback(NULL);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_dynlock_create_callback(NULL);
+ CRYPTO_set_dynlock_lock_callback(NULL);
+ CRYPTO_set_dynlock_destroy_callback(NULL);
+
+ for (i = 0; i < CRYPTO_num_locks( ); i++)
+ MUTEX_CLEANUP(mutex_buf[i]);
+
+ free(mutex_buf);
+ mutex_buf = NULL;
+
+ DBGPRINTF("openssl: multithread cleanup finished\n");
+ openssl_initialized = 0;
+ return 1;
+}
+/*-------------------------------------- MT OpenSSL helpers -----------------------------------------*/
+
+
+/*--------------------------------------OpenSSL helpers ------------------------------------------*/
+
+/* globally initialize OpenSSL
+ */
+void
+osslGlblInit(void)
+{
+ DBGPRINTF("openssl: entering osslGlblInit\n");
+
+ if((opensslh_THREAD_setup() == 0) ||
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ /* Setup OpenSSL library < 1.1.0 */
+ !SSL_library_init()
+#else
+ /* Setup OpenSSL library >= 1.1.0 with system default settings */
+ OPENSSL_init_ssl(0, NULL) == 0
+#endif
+ ) {
+ LogError(0, RS_RET_NO_ERRCODE, "Error: OpenSSL initialization failed!");
+ }
+
+ /* Load readable error strings */
+ SSL_load_error_strings();
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+ /*
+ * ERR_load_*(), ERR_func_error_string(), ERR_get_error_line(), ERR_get_error_line_data(), ERR_get_state()
+ * OpenSSL now loads error strings automatically so these functions are not needed.
+ * SEE FOR MORE:
+ * https://www.openssl.org/docs/manmaster/man7/migration_guide.html
+ *
+ */
+#else
+ /* Load error strings into mem*/
+ ERR_load_BIO_strings();
+ ERR_load_crypto_strings();
+#endif
+}
+
+/* globally de-initialize OpenSSL */
+void
+osslGlblExit(void)
+{
+ DBGPRINTF("openssl: entering osslGlblExit\n");
+ ENGINE_cleanup();
+ ERR_free_strings();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+
+/* initialize openssl context; called on
+ * - listener creation
+ * - outbound connection creation
+ * Once created, the ctx object is used by-subobjects (accepted inbound connections)
+ */
+static rsRetVal
+net_ossl_osslCtxInit(net_ossl_t *pThis, const SSL_METHOD *method)
+{
+ DEFiRet;
+ int bHaveCA;
+ int bHaveCRL;
+ int bHaveCert;
+ int bHaveKey;
+ int bHaveExtraCAFiles;
+ const char *caFile, *crlFile, *certFile, *keyFile;
+ char *extraCaFiles, *extraCaFile;
+ /* Setup certificates */
+ caFile = (char*) ((pThis->pszCAFile == NULL) ? glbl.GetDfltNetstrmDrvrCAF(runConf) : pThis->pszCAFile);
+ if(caFile == NULL) {
+ LogMsg(0, RS_RET_CA_CERT_MISSING, LOG_WARNING,
+ "Warning: CA certificate is not set");
+ bHaveCA = 0;
+ } else {
+ dbgprintf("osslCtxInit: OSSL CA file: '%s'\n", caFile);
+ bHaveCA = 1;
+ }
+ crlFile = (char*) ((pThis->pszCRLFile == NULL) ? glbl.GetDfltNetstrmDrvrCRLF(runConf) : pThis->pszCRLFile);
+ if(crlFile == NULL) {
+ bHaveCRL = 0;
+ } else {
+ dbgprintf("osslCtxInit: OSSL CRL file: '%s'\n", crlFile);
+ bHaveCRL = 1;
+ }
+ certFile = (char*) ((pThis->pszCertFile == NULL) ?
+ glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile);
+ if(certFile == NULL) {
+ LogMsg(0, RS_RET_CERT_MISSING, LOG_WARNING,
+ "Warning: Certificate file is not set");
+ bHaveCert = 0;
+ } else {
+ dbgprintf("osslCtxInit: OSSL CERT file: '%s'\n", certFile);
+ bHaveCert = 1;
+ }
+ keyFile = (char*) ((pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile);
+ if(keyFile == NULL) {
+ LogMsg(0, RS_RET_CERTKEY_MISSING, LOG_WARNING,
+ "Warning: Key file is not set");
+ bHaveKey = 0;
+ } else {
+ dbgprintf("osslCtxInit: OSSL KEY file: '%s'\n", keyFile);
+ bHaveKey = 1;
+ }
+ extraCaFiles = (char*) ((pThis->pszExtraCAFiles == NULL) ? glbl.GetNetstrmDrvrCAExtraFiles(runConf) :
+ pThis->pszExtraCAFiles);
+ if(extraCaFiles == NULL) {
+ bHaveExtraCAFiles = 0;
+ } else {
+ dbgprintf("osslCtxInit: OSSL EXTRA CA files: '%s'\n", extraCaFiles);
+ bHaveExtraCAFiles = 1;
+ }
+
+ /* Create main CTX Object based on method parameter */
+ pThis->ctx = SSL_CTX_new(method);
+
+ if(bHaveExtraCAFiles == 1) {
+ while((extraCaFile = strsep(&extraCaFiles, ","))) {
+ if(SSL_CTX_load_verify_locations(pThis->ctx, extraCaFile, NULL) != 1) {
+ LogError(0, RS_RET_TLS_CERT_ERR, "Error: Extra Certificate file could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit",
+ "SSL_CTX_load_verify_locations");
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ }
+ }
+ }
+ if(bHaveCA == 1 && SSL_CTX_load_verify_locations(pThis->ctx, caFile, NULL) != 1) {
+ LogError(0, RS_RET_TLS_CERT_ERR, "Error: CA certificate could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_load_verify_locations");
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ }
+ if(bHaveCRL == 1) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+ // Get X509_STORE reference
+ X509_STORE *store = SSL_CTX_get_cert_store(pThis->ctx);
+ if (!X509_STORE_load_file(store, crlFile)) {
+ LogError(0, RS_RET_CRL_INVALID, "Error: CRL could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "X509_STORE_load_file");
+ ABORT_FINALIZE(RS_RET_CRL_INVALID);
+ }
+ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
+#else
+# if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ // Get X509_STORE reference
+ X509_STORE *store = SSL_CTX_get_cert_store(pThis->ctx);
+ // Load the CRL PEM file
+ FILE *fp = fopen(crlFile, "r");
+ if(fp == NULL) {
+ LogError(0, RS_RET_CRL_MISSING, "Error: CRL could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "fopen");
+ ABORT_FINALIZE(RS_RET_CRL_MISSING);
+ }
+ X509_CRL *crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
+ fclose(fp);
+ if(crl == NULL) {
+ LogError(0, RS_RET_CRL_INVALID, "Error: Unable to read CRL."
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "PEM_read_X509_CRL");
+ ABORT_FINALIZE(RS_RET_CRL_INVALID);
+ }
+ // Add the CRL to the X509_STORE
+ if(!X509_STORE_add_crl(store, crl)) {
+ LogError(0, RS_RET_CRL_INVALID, "Error: Unable to add CRL to store."
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "X509_STORE_add_crl");
+ X509_CRL_free(crl);
+ ABORT_FINALIZE(RS_RET_CRL_INVALID);
+ }
+ // Set the X509_STORE to the SSL_CTX
+ // SSL_CTX_set_cert_store(pThis->ctx, store);
+ // Enable CRL checking
+ X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
+ X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
+ SSL_CTX_set1_param(pThis->ctx, param);
+ X509_VERIFY_PARAM_free(param);
+# else
+ LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support X509_STORE_load_file"
+ "(requires OpenSSL 3.x or higher). Cannot use Certificate revocation list (CRL) '%s'.",
+ crlFile);
+# endif
+#endif
+ }
+ if(bHaveCert == 1 && SSL_CTX_use_certificate_chain_file(pThis->ctx, certFile) != 1) {
+ LogError(0, RS_RET_TLS_CERT_ERR, "Error: Certificate file could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit",
+ "SSL_CTX_use_certificate_chain_file");
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ }
+ if(bHaveKey == 1 && SSL_CTX_use_PrivateKey_file(pThis->ctx, keyFile, SSL_FILETYPE_PEM) != 1) {
+ LogError(0, RS_RET_TLS_KEY_ERR , "Error: Key could not be accessed. "
+ "Check at least: 1) file path is correct, 2) file exist, "
+ "3) permissions are correct, 4) file content is correct. "
+ "OpenSSL error info may follow in next messages");
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_use_PrivateKey_file");
+ ABORT_FINALIZE(RS_RET_TLS_KEY_ERR);
+ }
+
+ /* Set CTX Options */
+ SSL_CTX_set_options(pThis->ctx, SSL_OP_NO_SSLv2); /* Disable insecure SSLv2 Protocol */
+ SSL_CTX_set_options(pThis->ctx, SSL_OP_NO_SSLv3); /* Disable insecure SSLv3 Protocol */
+ SSL_CTX_sess_set_cache_size(pThis->ctx,1024); /* TODO: make configurable? */
+
+ /* Set default VERIFY Options for OpenSSL CTX - and CALLBACK */
+ if (pThis->authMode == OSSL_AUTH_CERTANON) {
+ dbgprintf("osslCtxInit: SSL_VERIFY_NONE\n");
+ net_ossl_set_ctx_verify_callback(pThis->ctx, SSL_VERIFY_NONE);
+ } else {
+ dbgprintf("osslCtxInit: SSL_VERIFY_PEER\n");
+ net_ossl_set_ctx_verify_callback(pThis->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ }
+
+ SSL_CTX_set_timeout(pThis->ctx, 30); /* Default Session Timeout, TODO: Make configureable */
+ SSL_CTX_set_mode(pThis->ctx, SSL_MODE_AUTO_RETRY);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+# if OPENSSL_VERSION_NUMBER <= 0x101010FFL
+ /* Enable Support for automatic EC temporary key parameter selection. */
+ SSL_CTX_set_ecdh_auto(pThis->ctx, 1);
+# else
+ /*
+ * SSL_CTX_set_ecdh_auto and SSL_CTX_set_tmp_ecdh are depreceated in higher
+ * OpenSSL Versions, so we no more need them - see for more:
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_ecdh_auto.html
+ */
+# endif
+#else
+ dbgprintf("osslCtxInit: openssl to old, cannot use SSL_CTX_set_ecdh_auto."
+ "Using SSL_CTX_set_tmp_ecdh with NID_X9_62_prime256v1/() instead.\n");
+ SSL_CTX_set_tmp_ecdh(pThis->ctx, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+#endif
+finalize_it:
+ RETiRet;
+}
+
+/* Helper function to print usefull OpenSSL errors
+ */
+void net_ossl_lastOpenSSLErrorMsg
+ (uchar *fromHost, int ret, SSL *ssl, int severity, const char* pszCallSource, const char* pszOsslApi)
+{
+ unsigned long un_error = 0;
+ int iSSLErr = 0;
+ if (ssl == NULL) {
+ /* Output Error Info*/
+ DBGPRINTF("lastOpenSSLErrorMsg: Error in '%s' with ret=%d\n", pszCallSource, ret);
+ } else {
+ /* if object is set, get error code */
+ iSSLErr = SSL_get_error(ssl, ret);
+ /* Output Debug as well */
+ DBGPRINTF("lastOpenSSLErrorMsg: %s Error in '%s': '%s(%d)' with ret=%d, errno=%d(%s), sslapi='%s'\n",
+ (iSSLErr == SSL_ERROR_SSL ? "SSL_ERROR_SSL" :
+ (iSSLErr == SSL_ERROR_SYSCALL ? "SSL_ERROR_SYSCALL" : "SSL_ERROR_UNKNOWN")),
+ pszCallSource, ERR_error_string(iSSLErr, NULL),
+ iSSLErr,
+ ret,
+ errno,
+ strerror(errno),
+ pszOsslApi);
+
+ /* Output error message */
+ LogMsg(0, RS_RET_NO_ERRCODE, severity,
+ "%s Error in '%s': '%s(%d)' with ret=%d, errno=%d(%s), sslapi='%s'\n",
+ (iSSLErr == SSL_ERROR_SSL ? "SSL_ERROR_SSL" :
+ (iSSLErr == SSL_ERROR_SYSCALL ? "SSL_ERROR_SYSCALL" : "SSL_ERROR_UNKNOWN")),
+ pszCallSource, ERR_error_string(iSSLErr, NULL),
+ iSSLErr,
+ ret,
+ errno,
+ strerror(errno),
+ pszOsslApi);
+ }
+
+ /* Loop through ERR_get_error */
+ while ((un_error = ERR_get_error()) > 0){
+ LogMsg(0, RS_RET_NO_ERRCODE, severity,
+ "net_ossl:remote '%s' OpenSSL Error Stack: %s", fromHost, ERR_error_string(un_error, NULL) );
+ }
+}
+
+/* initialize tls config commands in openssl context
+ */
+rsRetVal net_ossl_apply_tlscgfcmd(net_ossl_t *pThis, uchar *tlscfgcmd)
+{
+ DEFiRet;
+ char *pCurrentPos;
+ char *pNextPos;
+ char *pszCmd;
+ char *pszValue;
+ int iConfErr;
+
+ if (tlscfgcmd == NULL) {
+ FINALIZE;
+ }
+
+ dbgprintf("net_ossl_apply_tlscgfcmd: Apply tlscfgcmd: '%s'\n", tlscfgcmd);
+
+ /* Set working pointer */
+ pCurrentPos = (char*) tlscfgcmd;
+ if (pCurrentPos != NULL && strlen(pCurrentPos) > 0) {
+ // Create CTX Config Helper
+ SSL_CONF_CTX *cctx;
+ cctx = SSL_CONF_CTX_new();
+ if (pThis->sslState == osslServer) {
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
+ } else {
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
+ }
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
+ SSL_CONF_CTX_set_ssl_ctx(cctx, pThis->ctx);
+
+ do
+ {
+ pNextPos = index(pCurrentPos, '=');
+ if (pNextPos != NULL) {
+ while ( *pCurrentPos != '\0' &&
+ (*pCurrentPos == ' ' || *pCurrentPos == '\t') )
+ pCurrentPos++;
+ pszCmd = strndup(pCurrentPos, pNextPos-pCurrentPos);
+ pCurrentPos = pNextPos+1;
+ pNextPos = index(pCurrentPos, '\n');
+ pNextPos = (pNextPos == NULL ? index(pCurrentPos, ';') : pNextPos);
+ pszValue = (pNextPos == NULL ?
+ strdup(pCurrentPos) :
+ strndup(pCurrentPos, pNextPos - pCurrentPos));
+ pCurrentPos = (pNextPos == NULL ? NULL : pNextPos+1);
+
+ /* Add SSL Conf Command */
+ iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue);
+ if (iConfErr > 0) {
+ dbgprintf("net_ossl_apply_tlscgfcmd: Successfully added Command "
+ "'%s':'%s'\n",
+ pszCmd, pszValue);
+ }
+ else {
+ LogError(0, RS_RET_SYS_ERR, "Failed to added Command: %s:'%s' "
+ "in net_ossl_apply_tlscgfcmd with error '%d'",
+ pszCmd, pszValue, iConfErr);
+ }
+
+ free(pszCmd);
+ free(pszValue);
+ } else {
+ /* Abort further parsing */
+ pCurrentPos = NULL;
+ }
+ }
+ while (pCurrentPos != NULL);
+
+ /* Finalize SSL Conf */
+ iConfErr = SSL_CONF_CTX_finish(cctx);
+ if (!iConfErr) {
+ LogError(0, RS_RET_SYS_ERR, "Error: setting openssl command parameters: %s"
+ "OpenSSL error info may follow in next messages",
+ tlscfgcmd);
+ net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR,
+ "net_ossl_apply_tlscgfcmd", "SSL_CONF_CTX_finish");
+ }
+ SSL_CONF_CTX_free(cctx);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Convert a fingerprint to printable data. The conversion is carried out
+ * according IETF I-D syslog-transport-tls-12. The fingerprint string is
+ * returned in a new cstr object. It is the caller's responsibility to
+ * destruct that object.
+ * rgerhards, 2008-05-08
+ */
+static rsRetVal
+net_ossl_genfingerprintstr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr, const char* prefix)
+{
+ cstr_t *pStr = NULL;
+ uchar buf[4];
+ size_t i;
+ DEFiRet;
+
+ CHKiRet(rsCStrConstruct(&pStr));
+ CHKiRet(rsCStrAppendStrWithLen(pStr, (uchar*) prefix, strlen(prefix)));
+ for(i = 0 ; i < sizeFingerprint ; ++i) {
+ snprintf((char*)buf, sizeof(buf), ":%2.2X", pFingerprint[i]);
+ CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3));
+ }
+ cstrFinalize(pStr);
+
+ *ppStr = pStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ }
+ RETiRet;
+}
+
+
+
+/* Perform a match on ONE peer name obtained from the certificate. This name
+ * is checked against the set of configured credentials. *pbFoundPositiveMatch is
+ * set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized
+ * to 0 by the caller (this is a performance enhancement as we expect to be
+ * called multiple times).
+ * TODO: implemet wildcards?
+ * rgerhards, 2008-05-26
+ */
+static rsRetVal
+net_ossl_chkonepeername(net_ossl_t *pThis, X509 *certpeer, uchar *pszPeerID, int *pbFoundPositiveMatch)
+{
+ permittedPeers_t *pPeer;
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ int osslRet;
+#endif
+ char *x509name = NULL;
+ DEFiRet;
+
+ if (certpeer == NULL) {
+ ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+ }
+
+ ISOBJ_TYPE_assert(pThis, net_ossl);
+ assert(pszPeerID != NULL);
+ assert(pbFoundPositiveMatch != NULL);
+
+ /* Obtain Namex509 name from subject */
+ x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0);
+
+ if(pThis->pPermPeers) { /* do we have configured peer IDs? */
+ pPeer = pThis->pPermPeers;
+ while(pPeer != NULL) {
+ CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch));
+ if(*pbFoundPositiveMatch)
+ break;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ /* if we did not succeed so far, try ossl X509_check_host
+ * ( Includes check against SubjectAlternativeName )
+ */
+ osslRet = X509_check_host( certpeer, (const char*)pPeer->pszID,
+ strlen((const char*)pPeer->pszID), 0, NULL);
+ if ( osslRet == 1 ) {
+ /* Found Peer cert in allowed Peerslist */
+ dbgprintf("net_ossl_chkonepeername: Client ('%s') is allowed (X509_check_host)\n",
+ x509name);
+ *pbFoundPositiveMatch = 1;
+ break;
+ } else if ( osslRet < 0 ) {
+ net_ossl_lastOpenSSLErrorMsg(NULL, osslRet, NULL, LOG_ERR,
+ "net_ossl_chkonepeername", "X509_check_host");
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+#endif
+ /* Check next peer */
+ pPeer = pPeer->pNext;
+ }
+ } else {
+ LogMsg(0, RS_RET_TLS_NO_CERT, LOG_WARNING,
+ "net_ossl_chkonepeername: Peername check could not be done: "
+ "no peernames configured.");
+ }
+finalize_it:
+ if (x509name != NULL){
+ OPENSSL_free(x509name);
+ }
+
+ RETiRet;
+}
+
+
+/* Check the peer's ID in fingerprint auth mode.
+ * rgerhards, 2008-05-22
+ */
+rsRetVal
+net_ossl_peerfingerprint(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP)
+{
+ DEFiRet;
+ unsigned int n;
+ uchar fingerprint[20 /*EVP_MAX_MD_SIZE**/];
+ uchar fingerprintSha256[32 /*EVP_MAX_MD_SIZE**/];
+ size_t size;
+ size_t sizeSha256;
+ cstr_t *pstrFingerprint = NULL;
+ cstr_t *pstrFingerprintSha256 = NULL;
+ int bFoundPositiveMatch;
+ permittedPeers_t *pPeer;
+ const EVP_MD *fdig = EVP_sha1();
+ const EVP_MD *fdigSha256 = EVP_sha256();
+
+ ISOBJ_TYPE_assert(pThis, net_ossl);
+
+ if (certpeer == NULL) {
+ ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+ }
+
+ /* obtain the SHA1 fingerprint */
+ size = sizeof(fingerprint);
+ if (!X509_digest(certpeer,fdig,fingerprint,&n)) {
+ dbgprintf("net_ossl_peerfingerprint: error X509cert is not valid!\n");
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
+ sizeSha256 = sizeof(fingerprintSha256);
+ if (!X509_digest(certpeer,fdigSha256,fingerprintSha256,&n)) {
+ dbgprintf("net_ossl_peerfingerprint: error X509cert is not valid!\n");
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
+ CHKiRet(net_ossl_genfingerprintstr(fingerprint, size, &pstrFingerprint, "SHA1"));
+ dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA1 fingerprint: %s\n",
+ cstrGetSzStrNoNULL(pstrFingerprint));
+ CHKiRet(net_ossl_genfingerprintstr(fingerprintSha256, sizeSha256, &pstrFingerprintSha256, "SHA256"));
+ dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA256 fingerprint: %s\n",
+ cstrGetSzStrNoNULL(pstrFingerprintSha256));
+
+ /* now search through the permitted peers to see if we can find a permitted one */
+ bFoundPositiveMatch = 0;
+ pPeer = pThis->pPermPeers;
+ while(pPeer != NULL && !bFoundPositiveMatch) {
+ if(!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char*) pPeer->pszID))) {
+ dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA1 MATCH found: %s\n",
+ pPeer->pszID);
+ bFoundPositiveMatch = 1;
+ } else if(!rsCStrSzStrCmp(pstrFingerprintSha256, pPeer->pszID, strlen((char*) pPeer->pszID))) {
+ dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA256 MATCH found: %s\n",
+ pPeer->pszID);
+ bFoundPositiveMatch = 1;
+ } else {
+ dbgprintf("net_ossl_peerfingerprint: NOMATCH peer certificate: %s\n", pPeer->pszID);
+ pPeer = pPeer->pNext;
+ }
+ }
+
+ if(!bFoundPositiveMatch) {
+ dbgprintf("net_ossl_peerfingerprint: invalid peer fingerprint, not permitted to talk to it\n");
+ if(pThis->bReportAuthErr == 1) {
+ errno = 0;
+ LogMsg(0, RS_RET_INVALID_FINGERPRINT, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote syslog server '%s': "
+ "Fingerprint check failed, not permitted to talk to %s",
+ fromHostIP, cstrGetSzStrNoNULL(pstrFingerprint));
+ pThis->bReportAuthErr = 0;
+ }
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
+
+finalize_it:
+ if(pstrFingerprint != NULL)
+ cstrDestruct(&pstrFingerprint);
+ RETiRet;
+}
+
+
+/* Check the peer's ID in name auth mode.
+ */
+rsRetVal
+net_ossl_chkpeername(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP)
+{
+ DEFiRet;
+ uchar lnBuf[256];
+ int bFoundPositiveMatch;
+ cstr_t *pStr = NULL;
+ char *x509name = NULL;
+
+ ISOBJ_TYPE_assert(pThis, net_ossl);
+
+ bFoundPositiveMatch = 0;
+ CHKiRet(rsCStrConstruct(&pStr));
+
+ /* Obtain Namex509 name from subject */
+ x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0);
+
+ dbgprintf("net_ossl_chkpeername: checking - peername '%s' on server '%s'\n", x509name, fromHostIP);
+ snprintf((char*)lnBuf, sizeof(lnBuf), "name: %s; ", x509name);
+ CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(net_ossl_chkonepeername(pThis, certpeer, (uchar*)x509name, &bFoundPositiveMatch));
+
+ if(!bFoundPositiveMatch) {
+ dbgprintf("net_ossl_chkpeername: invalid peername, not permitted to talk to it\n");
+ if(pThis->bReportAuthErr == 1) {
+ cstrFinalize(pStr);
+ errno = 0;
+ LogMsg(0, RS_RET_INVALID_FINGERPRINT, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote syslog server: "
+ "peer name not authorized, not permitted to talk to %s",
+ cstrGetSzStrNoNULL(pStr));
+ pThis->bReportAuthErr = 0;
+ }
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ } else {
+ dbgprintf("net_ossl_chkpeername: permitted to talk!\n");
+ }
+
+finalize_it:
+ if (x509name != NULL){
+ OPENSSL_free(x509name);
+ }
+
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ RETiRet;
+}
+
+
+/* check the ID of the remote peer - used for both fingerprint and
+ * name authentication.
+ */
+X509*
+net_ossl_getpeercert(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP)
+{
+ X509* certpeer;
+
+ ISOBJ_TYPE_assert(pThis, net_ossl);
+
+ /* Get peer certificate from SSL */
+ certpeer = SSL_get_peer_certificate(ssl);
+ if ( certpeer == NULL ) {
+ if(pThis->bReportAuthErr == 1 && 1) {
+ errno = 0;
+ pThis->bReportAuthErr = 0;
+ LogMsg(0, RS_RET_TLS_NO_CERT, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote syslog server '%s': "
+ "Peer check failed, peer did not provide a certificate.", fromHostIP);
+ }
+ }
+ return certpeer;
+}
+
+
+/* Verify the validity of the remote peer's certificate.
+ */
+rsRetVal
+net_ossl_chkpeercertvalidity(net_ossl_t __attribute__((unused)) *pThis, SSL *ssl, uchar *fromHostIP)
+{
+ DEFiRet;
+ int iVerErr = X509_V_OK;
+
+ ISOBJ_TYPE_assert(pThis, net_ossl);
+ PermitExpiredCerts* pPermitExpiredCerts = (PermitExpiredCerts*) SSL_get_ex_data(ssl, 1);
+
+ iVerErr = SSL_get_verify_result(ssl);
+ if (iVerErr != X509_V_OK) {
+ if (iVerErr == X509_V_ERR_CERT_HAS_EXPIRED) {
+ if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_DENY) {
+ LogMsg(0, RS_RET_CERT_EXPIRED, LOG_INFO,
+ "net_ossl:TLS session terminated with remote syslog server '%s': "
+ "not permitted to talk to peer, certificate invalid: "
+ "Certificate expired: %s",
+ fromHostIP, X509_verify_cert_error_string(iVerErr));
+ ABORT_FINALIZE(RS_RET_CERT_EXPIRED);
+ } else if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_WARN) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "net_ossl:CertValidity check - warning talking to peer '%s': "
+ "certificate expired: %s",
+ fromHostIP, X509_verify_cert_error_string(iVerErr));
+ } else {
+ dbgprintf("net_ossl_chkpeercertvalidity: talking to peer '%s': "
+ "certificate expired: %s\n",
+ fromHostIP, X509_verify_cert_error_string(iVerErr));
+ }/* Else do nothing */
+ } else if (iVerErr == X509_V_ERR_CERT_REVOKED) {
+ LogMsg(0, RS_RET_CERT_REVOKED, LOG_INFO,
+ "net_ossl:TLS session terminated with remote syslog server '%s': "
+ "not permitted to talk to peer, certificate invalid: "
+ "certificate revoked '%s'",
+ fromHostIP, X509_verify_cert_error_string(iVerErr));
+ ABORT_FINALIZE(RS_RET_CERT_EXPIRED);
+ } else {
+ LogMsg(0, RS_RET_CERT_INVALID, LOG_INFO,
+ "net_ossl:TLS session terminated with remote syslog server '%s': "
+ "not permitted to talk to peer, certificate validation failed: %s",
+ fromHostIP, X509_verify_cert_error_string(iVerErr));
+ ABORT_FINALIZE(RS_RET_CERT_INVALID);
+ }
+ } else {
+ dbgprintf("net_ossl_chkpeercertvalidity: client certificate validation success: %s\n",
+ X509_verify_cert_error_string(iVerErr));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* Verify Callback for X509 Certificate validation. Force visibility as this function is not called anywhere but
+* only used as callback!
+*/
+int
+net_ossl_verify_callback(int status, X509_STORE_CTX *store)
+{
+ char szdbgdata1[256];
+ char szdbgdata2[256];
+
+ dbgprintf("verify_callback: status %d\n", status);
+
+ if(status == 0) {
+ /* Retrieve all needed pointers */
+ X509 *cert = X509_STORE_CTX_get_current_cert(store);
+ int depth = X509_STORE_CTX_get_error_depth(store);
+ int err = X509_STORE_CTX_get_error(store);
+ SSL* ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
+ int iVerifyMode = SSL_get_verify_mode(ssl);
+ nsd_t *pNsdTcp = (nsd_t*) SSL_get_ex_data(ssl, 0);
+ PermitExpiredCerts* pPermitExpiredCerts = (PermitExpiredCerts*) SSL_get_ex_data(ssl, 1);
+
+ dbgprintf("verify_callback: Certificate validation failed, Mode (%d)!\n", iVerifyMode);
+
+ X509_NAME_oneline(X509_get_issuer_name(cert), szdbgdata1, sizeof(szdbgdata1));
+ X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(cert), szdbgdata2, sizeof(szdbgdata2));
+
+ uchar *fromHost = NULL;
+ if (pNsdTcp != NULL) {
+ nsd_ptcp.GetRemoteHName(pNsdTcp, &fromHost);
+ }
+
+ if (iVerifyMode != SSL_VERIFY_NONE) {
+ /* Handle expired Certificates **/
+ if (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) {
+ if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_PERMIT) {
+ dbgprintf("verify_callback: EXPIRED cert but PERMITTED at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n", depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err));
+
+ /* Set Status to OK*/
+ status = 1;
+ }
+ else if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_WARN) {
+ LogMsg(0, RS_RET_CERT_EXPIRED, LOG_WARNING,
+ "Certificate EXPIRED warning at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s peer '%s'",
+ depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err), fromHost);
+
+ /* Set Status to OK*/
+ status = 1;
+ }
+ else /* also default - if (pPermitExpiredCerts == OSSL_EXPIRED_DENY)*/ {
+ LogMsg(0, RS_RET_CERT_EXPIRED, LOG_ERR,
+ "Certificate EXPIRED at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n\t"
+ "not permitted to talk to peer '%s', certificate invalid: "
+ "certificate expired",
+ depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err), fromHost);
+ }
+ } else if (err == X509_V_ERR_CERT_REVOKED) {
+ LogMsg(0, RS_RET_CERT_REVOKED, LOG_ERR,
+ "Certificate REVOKED at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n\t"
+ "not permitted to talk to peer '%s', certificate invalid: "
+ "certificate revoked",
+ depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err), fromHost);
+ } else {
+ /* all other error codes cause failure */
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_ERR,
+ "Certificate error at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s - peer '%s'",
+ depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err), fromHost);
+ }
+ } else {
+ /* do not verify certs in ANON mode, just log into debug */
+ dbgprintf("verify_callback: Certificate validation DISABLED but Error at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n", depth, szdbgdata1, szdbgdata2,
+ err, X509_verify_cert_error_string(err));
+
+ /* Set Status to OK*/
+ status = 1;
+ }
+ free(fromHost);
+ }
+
+ return status;
+}
+
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+static long
+RSYSLOG_BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl,
+ int ret, size_t __attribute__((unused)) *processed)
+#else
+static long
+RSYSLOG_BIO_debug_callback(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ int argi, long __attribute__((unused)) argl, long ret)
+#endif
+{
+ long ret2 = ret;
+ long r = 1;
+ if (BIO_CB_RETURN & cmd)
+ r = ret;
+ dbgprintf("openssl debugmsg: BIO[%p]: ", (void *)bio);
+ switch (cmd) {
+ case BIO_CB_FREE:
+ dbgprintf("Free - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+/* Disabled due API changes for OpenSSL 1.1.0+ */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ case BIO_CB_READ:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ dbgprintf("read(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_read(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio));
+ else
+ dbgprintf("read(%d,%lu) - %s\n", RSYSLOG_BIO_number_read(bio),
+ (unsigned long)argi, RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ dbgprintf("write(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_written(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio));
+ else
+ dbgprintf("write(%d,%lu) - %s\n",
+ RSYSLOG_BIO_number_written(bio),
+ (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+#else
+ case BIO_CB_READ:
+ dbgprintf("read %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ dbgprintf("write %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+#endif
+ case BIO_CB_PUTS:
+ dbgprintf("puts() - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_GETS:
+ dbgprintf("gets(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_CTRL:
+ dbgprintf("ctrl(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_RETURN | BIO_CB_READ:
+ dbgprintf("read return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_WRITE:
+ dbgprintf("write return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_GETS:
+ dbgprintf("gets return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_PUTS:
+ dbgprintf("puts return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_CTRL:
+ dbgprintf("ctrl return %ld\n", ret2);
+ break;
+ default:
+ dbgprintf("bio callback - unknown type (%d)\n", cmd);
+ break;
+ }
+
+ return (r);
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+// Requires at least OpenSSL v1.1.1
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+static int
+net_ossl_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
+{
+ unsigned char result[EVP_MAX_MD_SIZE];
+ unsigned int resultlength;
+ unsigned char *sslHello;
+ unsigned int length;
+
+ sslHello = (unsigned char *) "rsyslog";
+ length = strlen((char *)sslHello);
+
+ // Generate the cookie using SHA256 hash
+ if (!EVP_Digest(sslHello, length, result, &resultlength, EVP_sha256(), NULL)) {
+ return 0;
+ }
+
+ memcpy(cookie, result, resultlength);
+ *cookie_len = resultlength;
+ dbgprintf("net_ossl_generate_cookie: generate cookie SUCCESS\n");
+
+ return 1;
+}
+#pragma GCC diagnostic pop
+
+static int
+net_ossl_verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len)
+{
+ unsigned char cookie_gen[EVP_MAX_MD_SIZE];
+ unsigned int cookie_gen_len;
+
+ // Generate a cookie using the same method as in net_ossl_generate_cookie
+ if (!net_ossl_generate_cookie(ssl, cookie_gen, &cookie_gen_len)) {
+ dbgprintf("net_ossl_verify_cookie: generate cookie FAILED\n");
+ return 0;
+ }
+
+ // Check if the generated cookie matches the cookie received
+ if (cookie_len == cookie_gen_len && memcmp(cookie, cookie_gen, cookie_len) == 0) {
+ dbgprintf("net_ossl_verify_cookie: compare cookie SUCCESS\n");
+ return 1;
+ }
+
+ dbgprintf("net_ossl_verify_cookie: compare cookie FAILED\n");
+ return 0;
+}
+
+static rsRetVal
+net_ossl_ctx_init_cookie(net_ossl_t *pThis)
+{
+ DEFiRet;
+ // Set our cookie generation and verification callbacks
+ SSL_CTX_set_options(pThis->ctx, SSL_OP_COOKIE_EXCHANGE);
+ SSL_CTX_set_cookie_generate_cb(pThis->ctx, net_ossl_generate_cookie);
+ SSL_CTX_set_cookie_verify_cb(pThis->ctx, net_ossl_verify_cookie);
+ RETiRet;
+}
+#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L
+
+/* ------------------------------ end OpenSSL helpers ------------------------------------------*/
+
+/* ------------------------------ OpenSSL Callback set helpers ---------------------------------*/
+void
+net_ossl_set_ssl_verify_callback(SSL *pSsl, int flags)
+{
+ /* Enable certificate valid checking */
+ SSL_set_verify(pSsl, flags, net_ossl_verify_callback);
+}
+
+void
+net_ossl_set_ctx_verify_callback(SSL_CTX *pCtx, int flags)
+{
+ /* Enable certificate valid checking */
+ SSL_CTX_set_verify(pCtx, flags, net_ossl_verify_callback);
+}
+
+void
+net_ossl_set_bio_callback(BIO *conn)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+ BIO_set_callback_ex(conn, RSYSLOG_BIO_debug_callback_ex);
+#else
+ BIO_set_callback(conn, RSYSLOG_BIO_debug_callback);
+#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L
+}
+/* ------------------------------ End OpenSSL Callback set helpers -----------------------------*/
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(net_ossl) /* be sure to specify the object type also in END macro! */
+ DBGPRINTF("net_ossl_construct: [%p]\n", pThis);
+ pThis->bReportAuthErr = 1;
+ENDobjConstruct(net_ossl)
+
+/* destructor for the net_ossl object */
+BEGINobjDestruct(net_ossl) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(net_ossl)
+ DBGPRINTF("net_ossl_destruct: [%p]\n", pThis);
+ /* Free SSL obj also if we do not have a session - or are NOT in TLS mode! */
+ if (pThis->ssl != NULL) {
+ DBGPRINTF("net_ossl_destruct: [%p] FREE pThis->ssl \n", pThis);
+ SSL_free(pThis->ssl);
+ pThis->ssl = NULL;
+ }
+ if(pThis->ctx != NULL && !pThis->ctx_is_copy) {
+ SSL_CTX_free(pThis->ctx);
+ }
+ free((void*) pThis->pszCAFile);
+ free((void*) pThis->pszCRLFile);
+ free((void*) pThis->pszKeyFile);
+ free((void*) pThis->pszCertFile);
+ free((void*) pThis->pszExtraCAFiles);
+ENDobjDestruct(net_ossl)
+
+/* queryInterface function */
+BEGINobjQueryInterface(net_ossl)
+CODESTARTobjQueryInterface(net_ossl)
+ DBGPRINTF("netosslQueryInterface\n");
+ if(pIf->ifVersion != net_osslCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->Construct = (rsRetVal(*)(net_ossl_t**)) net_osslConstruct;
+ pIf->Destruct = (rsRetVal(*)(net_ossl_t**)) net_osslDestruct;
+ pIf->osslCtxInit = net_ossl_osslCtxInit;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ pIf->osslCtxInitCookie = net_ossl_ctx_init_cookie;
+#endif
+finalize_it:
+ENDobjQueryInterface(net_ossl)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(net_ossl, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(net_ossl)
+ DBGPRINTF("netosslClassExit\n");
+ /* release objects we no longer need */
+ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ /* shut down OpenSSL */
+ osslGlblExit();
+ENDObjClassExit(net_ossl)
+
+
+/* Initialize the net_ossl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ */
+BEGINObjClassInit(net_ossl, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ DBGPRINTF("net_osslClassInit\n");
+ // request objects we use
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME));
+ // Do global TLS init stuff
+ osslGlblInit();
+ENDObjClassInit(net_ossl)
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+/* vi:set ai:
+ */
diff --git a/runtime/net_ossl.h b/runtime/net_ossl.h
new file mode 100644
index 0000000..6e8a61f
--- /dev/null
+++ b/runtime/net_ossl.h
@@ -0,0 +1,173 @@
+/* Definitions for generic OpenSSL include stuff.
+ *
+ * Copyright 2023 Andre Lorbach and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NET_OSSL_H
+#define INCLUDED_NET_OSSL_H
+
+/* Needed OpenSSL Includes */
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+# include <openssl/bioerr.h>
+#endif
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+
+/* Internal OpenSSL defined ENUMS */
+typedef enum {
+ OSSL_AUTH_CERTNAME = 0,
+ OSSL_AUTH_CERTFINGERPRINT = 1,
+ OSSL_AUTH_CERTVALID = 2,
+ OSSL_AUTH_CERTANON = 3
+} AuthMode;
+
+typedef enum {
+ OSSL_EXPIRED_PERMIT = 0,
+ OSSL_EXPIRED_DENY = 1,
+ OSSL_EXPIRED_WARN = 2
+} PermitExpiredCerts;
+
+typedef enum {
+ osslServer = 0, /**< Server SSL Object */
+ osslClient = 1 /**< Client SSL Object */
+} osslSslState_t;
+
+/* the net_ossl object */
+struct net_ossl_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ /* Config Cert vars */
+ const uchar *pszCAFile;
+ const uchar *pszCRLFile;
+ const uchar *pszExtraCAFiles;
+ const uchar *pszKeyFile;
+ const uchar *pszCertFile;
+ AuthMode authMode;
+ permittedPeers_t *pPermPeers; /* permitted peers */
+ int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is
+ * set to 1 and changed to 0 after the first report. It is changed back to 1 after
+ * one successful authentication. */
+ /* Open SSL objects */
+ BIO *bio; /* OpenSSL main BIO obj */
+ int ctx_is_copy;
+ SSL_CTX *ctx; /* credentials, ciphers, ... */
+ SSL *ssl; /* OpenSSL main SSL obj */
+ osslSslState_t sslState;/**< what must we retry? */
+};
+
+/* interface */
+BEGINinterface(net_ossl) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(net_ossl_t **ppThis);
+ rsRetVal (*Destruct)(net_ossl_t **ppThis);
+ rsRetVal (*osslCtxInit)(net_ossl_t *pThis, const SSL_METHOD *method);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ rsRetVal (*osslCtxInitCookie)(net_ossl_t *pThis);
+#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L
+ENDinterface(net_ossl)
+
+#define net_osslCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+// ------------------------------------------------------
+
+/* OpenSSL API differences */
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT)
+ #define RSYSLOG_BIO_method_name(SSLBIO) BIO_method_name(SSLBIO)
+ #define RSYSLOG_BIO_number_read(SSLBIO) BIO_number_read(SSLBIO)
+ #define RSYSLOG_BIO_number_written(SSLBIO) BIO_number_written(SSLBIO)
+#else
+ #define RSYSLOG_X509_NAME_oneline(X509CERT) (X509CERT != NULL ? X509CERT->cert_info->subject : NULL)
+ #define RSYSLOG_BIO_method_name(SSLBIO) SSLBIO->method->name
+ #define RSYSLOG_BIO_number_read(SSLBIO) SSLBIO->num
+ #define RSYSLOG_BIO_number_written(SSLBIO) SSLBIO->num
+#endif
+
+/*-----------------------------------------------------------------------------*/
+/* OpenSSL Global Helper functions prototypes */
+#define MUTEX_TYPE pthread_mutex_t
+#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
+#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
+#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
+#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
+#define THREAD_ID pthread_self()
+
+/* This array will store all of the mutexes available to OpenSSL. */
+struct CRYPTO_dynlock_value
+{
+ MUTEX_TYPE mutex;
+};
+
+void dyn_destroy_function(struct CRYPTO_dynlock_value *l,
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line);
+void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line);
+struct CRYPTO_dynlock_value * dyn_create_function(
+ __attribute__((unused)) const char *file, __attribute__((unused)) int line);
+unsigned long id_function(void);
+void locking_function(int mode, int n,
+ __attribute__((unused)) const char * file, __attribute__((unused)) int line);
+
+int opensslh_THREAD_setup(void);
+int opensslh_THREAD_cleanup(void);
+
+void osslGlblInit(void);
+void osslGlblExit(void);
+
+/*-----------------------------------------------------------------------------*/
+
+/* Prototypes for openssl helper functions */
+__attribute__((visibility("default"))) void net_ossl_lastOpenSSLErrorMsg
+ (uchar *fromHost, const int ret, SSL *ssl, int severity, const char* pszCallSource, const char* pszOsslApi);
+__attribute__((visibility("default"))) void net_ossl_set_ssl_verify_callback(SSL *pSsl, int flags);
+__attribute__((visibility("default"))) void net_ossl_set_ctx_verify_callback(SSL_CTX *pCtx, int flags);
+__attribute__((visibility("default"))) void net_ossl_set_bio_callback(BIO *conn);
+__attribute__((visibility("default"))) int net_ossl_verify_callback(int status, X509_STORE_CTX *store);
+__attribute__((visibility("default"))) rsRetVal net_ossl_apply_tlscgfcmd(net_ossl_t *pThis, uchar *tlscfgcmd);
+__attribute__((visibility("default"))) rsRetVal
+ net_ossl_chkpeercertvalidity(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP);
+__attribute__((visibility("default"))) X509*
+ net_ossl_getpeercert(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP);
+__attribute__((visibility("default"))) rsRetVal
+ net_ossl_peerfingerprint(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP);
+__attribute__((visibility("default"))) rsRetVal
+ net_ossl_chkpeername(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP);
+
+/*
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+long RSYSLOG_BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl,
+ int ret, size_t __attribute__((unused)) *processed);
+#else
+long RSYSLOG_BIO_debug_callback(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ int argi, long __attribute__((unused)) argl, long ret);
+#endif
+*/
+
+/* prototypes */
+PROTOTYPEObj(net_ossl);
+
+/* the name of our library binary */
+// #define LM_NET_OSSL_FILENAME "lmnet_ossl"
+#define LM_NET_OSSL_FILENAME "lmnsd_ossl"
+
+
+#endif /* #ifndef INCLUDED_NET_OSSL_H */
diff --git a/runtime/netstrm.c b/runtime/netstrm.c
new file mode 100644
index 0000000..d20957e
--- /dev/null
+++ b/runtime/netstrm.c
@@ -0,0 +1,508 @@
+/* netstrm.c
+ *
+ * This class implements a generic netstrmwork stream class. It supports
+ * sending and receiving data streams over a netstrmwork. The class abstracts
+ * the transport, though it is a safe assumption that TCP is being used.
+ * The class has a number of properties, among which are also ones to
+ * select privacy settings, eg by enabling TLS and/or GSSAPI. In the
+ * long run, this class shall provide all stream-oriented netstrmwork
+ * functionality inside rsyslog.
+ *
+ * It is a high-level class, which uses a number of helper objects
+ * to carry out its work (including, and most importantly, transport
+ * drivers).
+ *
+ * Note on processing:
+ * - Initiating a listener may be driver-specific, but in regard to TLS/non-TLS
+ * it actually is not. This is because TLS is negotiated after a connection
+ * has been established. So it is the "acceptConnReq" driver entry where TLS
+ * params need to be applied.
+ *
+ * Work on this module begun 2008-04-17 by Rainer Gerhards. This code
+ * borrows from librelp's tcp.c/.h code. librelp is dual licensed and
+ * Rainer Gerhards and Adiscon GmbH have agreed to permit using the code
+ * under the terms of the GNU Lesser General Public License.
+ *
+ * Copyright 2007-2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "net.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "netstrms.h"
+#include "netstrm.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(netstrms)
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(netstrm) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(netstrm)
+
+
+/* destructor for the netstrm object */
+BEGINobjDestruct(netstrm) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(netstrm)
+ if(pThis->pDrvrData != NULL)
+ iRet = pThis->Drvr.Destruct(&pThis->pDrvrData);
+ENDobjDestruct(netstrm)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+netstrmConstructFinalize(netstrm_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ return pThis->Drvr.Construct(&pThis->pDrvrData);
+}
+
+/* abort a connection. This is much like Destruct(), but tries
+ * to discard any unsent data. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+AbortDestruct(netstrm_t **ppThis)
+{
+ DEFiRet;
+ assert(ppThis != NULL);
+ ISOBJ_TYPE_assert((*ppThis), netstrm);
+
+ /* we do NOT exit on error, because that would make things worse */
+ (*ppThis)->Drvr.Abort((*ppThis)->pDrvrData);
+ iRet = netstrmDestruct(ppThis);
+
+ RETiRet;
+}
+
+
+/* accept an incoming connection request
+ * The netstrm instance that had the incoming request must be provided. If
+ * the connection request succeeds, a new netstrm object is created and
+ * passed back to the caller. The caller is responsible for destructing it.
+ * pReq is the nsd_t obj that has the accept request.
+ * rgerhards, 2008-04-21
+ */
+static rsRetVal
+AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew)
+{
+ nsd_t *pNewNsd = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(ppNew != NULL);
+
+ /* accept the new connection */
+ CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd));
+ /* construct our object so that we can use it... */
+ CHKiRet(objUse(netstrms, DONT_LOAD_LIB)); /* use netstrms obj if not already done so */
+ CHKiRet(netstrms.CreateStrm(pThis->pNS, ppNew));
+ (*ppNew)->pDrvrData = pNewNsd;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* the close may be redundant, but that doesn't hurt... */
+ if(pNewNsd != NULL)
+ pThis->Drvr.Destruct(&pNewNsd);
+ }
+
+ RETiRet;
+}
+
+
+/* make the netstrm listen to specified port and IP.
+ * pLstnIP points to the port to listen to (NULL means "all"),
+ * iMaxSess has the maximum number of sessions permitted (this ist just a hint).
+ * pLstnPort must point to a port name or number. NULL is NOT permitted.
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal ATTR_NONNULL(1,3,5)
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pNS, netstrms);
+ assert(fAddLstn != NULL);
+ assert(cnf_params->pszPort != NULL);
+
+ CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read (or -1 in case of error) on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. If *pLenBuf is -1, an error occurred and
+ * oserr holds the exact error cause.
+ * rgerhards, 2008-03-17
+ */
+static rsRetVal
+Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf, int *const oserr)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.Rcv(pThis->pDrvrData, pBuf, pLenBuf, oserr);
+ RETiRet;
+}
+
+/* here follows a number of methods that shuffle authentication settings down
+ * to the drivers. Drivers not supporting these settings may return an error
+ * state.
+ * -------------------------------------------------------------------------- */
+
+/* set the driver mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetDrvrMode(netstrm_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetMode(pThis->pDrvrData, iMode);
+ RETiRet;
+}
+
+
+/* set the driver authentication mode -- rgerhards, 2008-05-16
+ */
+static rsRetVal
+SetDrvrAuthMode(netstrm_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetAuthMode(pThis->pDrvrData, mode);
+ RETiRet;
+}
+
+
+/* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20
+ */
+static rsRetVal
+SetDrvrPermitExpiredCerts(netstrm_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetPermitExpiredCerts(pThis->pDrvrData, mode);
+ RETiRet;
+}
+
+/* set the driver's permitted peers -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetPermPeers(pThis->pDrvrData, pPermPeers);
+ RETiRet;
+}
+
+/* Mandate also verification of Extended key usage / purpose field */
+static rsRetVal
+SetDrvrCheckExtendedKeyUsage(netstrm_t *pThis, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetCheckExtendedKeyUsage(pThis->pDrvrData, ChkExtendedKeyUsage);
+ RETiRet;
+}
+
+/* Mandate stricter name checking per RFC 6125 - ignoce CN if any SAN present */
+static rsRetVal
+SetDrvrPrioritizeSAN(netstrm_t *pThis, int prioritizeSan)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetPrioritizeSAN(pThis->pDrvrData, prioritizeSan);
+ RETiRet;
+}
+
+/* tls verify depth */
+static rsRetVal
+SetDrvrTlsVerifyDepth(netstrm_t *pThis, int verifyDepth)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetTlsVerifyDepth(pThis->pDrvrData, verifyDepth);
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCAFile(netstrm_t *const pThis, const uchar *const file)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetTlsCAFile(pThis->pDrvrData, file);
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCRLFile(netstrm_t *const pThis, const uchar *const file)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetTlsCRLFile(pThis->pDrvrData, file);
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsKeyFile(netstrm_t *const pThis, const uchar *const file)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetTlsKeyFile(pThis->pDrvrData, file);
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCertFile(netstrm_t *const pThis, const uchar *const file)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetTlsCertFile(pThis->pDrvrData, file);
+ RETiRet;
+}
+
+/* End of methods to shuffle autentication settings to the driver.
+ * -------------------------------------------------------------------------- */
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.Send(pThis->pDrvrData, pBuf, pLenBuf);
+ RETiRet;
+}
+
+/* Enable Keep-Alive handling for those drivers that support it.
+ * rgerhards, 2009-06-02
+ */
+static rsRetVal
+EnableKeepAlive(netstrm_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.EnableKeepAlive(pThis->pDrvrData);
+ RETiRet;
+}
+
+/* Keep-Alive options
+ */
+static rsRetVal
+SetKeepAliveProbes(netstrm_t *pThis, int keepAliveProbes)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetKeepAliveProbes(pThis->pDrvrData, keepAliveProbes);
+ RETiRet;
+}
+
+/* Keep-Alive options
+ */
+static rsRetVal
+SetKeepAliveTime(netstrm_t *pThis, int keepAliveTime)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetKeepAliveTime(pThis->pDrvrData, keepAliveTime);
+ RETiRet;
+}
+
+/* Keep-Alive options
+ */
+static rsRetVal
+SetKeepAliveIntvl(netstrm_t *pThis, int keepAliveIntvl)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetKeepAliveIntvl(pThis->pDrvrData, keepAliveIntvl);
+ RETiRet;
+}
+
+/* gnutls priority string */
+static rsRetVal
+SetGnutlsPriorityString(netstrm_t *pThis, uchar *gnutlsPriorityString)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetGnutlsPriorityString(pThis->pDrvrData, gnutlsPriorityString);
+ RETiRet;
+}
+
+/* check connection - slim wrapper for NSD driver function */
+static rsRetVal
+CheckConnection(netstrm_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ return pThis->Drvr.CheckConnection(pThis->pDrvrData);
+}
+
+
+/* get remote hname - slim wrapper for NSD driver function */
+static rsRetVal
+GetRemoteHName(netstrm_t *pThis, uchar **ppsz)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.GetRemoteHName(pThis->pDrvrData, ppsz);
+ RETiRet;
+}
+
+
+/* get remote IP - slim wrapper for NSD driver function */
+static rsRetVal
+GetRemoteIP(netstrm_t *pThis, prop_t **ip)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.GetRemoteIP(pThis->pDrvrData, ip);
+ RETiRet;
+}
+
+
+/* get remote addr - slim wrapper for NSD driver function */
+static rsRetVal
+GetRemAddr(netstrm_t *pThis, struct sockaddr_storage **ppAddr)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.GetRemAddr(pThis->pDrvrData, ppAddr);
+ RETiRet;
+}
+
+
+/* open a connection to a remote host (server).
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Connect(netstrm_t *pThis, int family, uchar *port, uchar *host, char *device)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(port != NULL);
+ assert(host != NULL);
+ iRet = pThis->Drvr.Connect(pThis->pDrvrData, family, port, host, device);
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is dirty
+ * and scheduled to be removed. Does not work with all nsd drivers.
+ * See comment in netstrm interface for details.
+ * rgerhards, 2008-05-05
+ */
+static rsRetVal
+GetSock(netstrm_t *pThis, int *pSock)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(pSock != NULL);
+ iRet = pThis->Drvr.GetSock(pThis->pDrvrData, pSock);
+ RETiRet;
+}
+
+
+/* queryInterface function
+ */
+BEGINobjQueryInterface(netstrm)
+CODESTARTobjQueryInterface(netstrm)
+ if(pIf->ifVersion != netstrmCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = netstrmConstruct;
+ pIf->ConstructFinalize = netstrmConstructFinalize;
+ pIf->Destruct = netstrmDestruct;
+ pIf->AbortDestruct = AbortDestruct;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->Connect = Connect;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+ pIf->GetRemAddr = GetRemAddr;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->SetDrvrAuthMode = SetDrvrAuthMode;
+ pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts;
+ pIf->SetDrvrPermPeers = SetDrvrPermPeers;
+ pIf->CheckConnection = CheckConnection;
+ pIf->GetSock = GetSock;
+ pIf->EnableKeepAlive = EnableKeepAlive;
+ pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ pIf->SetKeepAliveTime = SetKeepAliveTime;
+ pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
+ pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
+ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
+ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
+ pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth;
+ pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile;
+ pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile;
+ pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile;
+ pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile;
+finalize_it:
+ENDobjQueryInterface(netstrm)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(netstrm, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(netstrm)
+ /* release objects we no longer need */
+ objRelease(netstrms, DONT_LOAD_LIB);
+ENDObjClassExit(netstrm)
+
+
+/* Initialize the netstrm class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(netstrm, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* set our own handlers */
+ENDObjClassInit(netstrm)
+/* vi:set ai:
+ */
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
new file mode 100644
index 0000000..4b1d62c
--- /dev/null
+++ b/runtime/netstrm.h
@@ -0,0 +1,114 @@
+/* Definitions for the stream-based netstrmworking class.
+ *
+ * Copyright 2007-2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NETSTRM_H
+#define INCLUDED_NETSTRM_H
+
+#include "tcpsrv.h"
+#include "netstrms.h"
+
+/* the netstrm object */
+struct netstrm_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pDrvrData; /**< the driver's data elements (at most other places, this is called pNsd) */
+ nsd_if_t Drvr; /**< our stream driver */
+ uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */
+ void *pUsr; /**< pointer to user-provided data structure */
+ netstrms_t *pNS; /**< pointer to our netstream subsystem object */
+};
+
+
+/* interface */
+BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(netstrm_t **ppThis);
+ rsRetVal (*ConstructFinalize)(netstrm_t *pThis);
+ rsRetVal (*Destruct)(netstrm_t **ppThis);
+ rsRetVal (*AbortDestruct)(netstrm_t **ppThis);
+ rsRetVal (*AcceptConnReq)(netstrm_t *pThis, netstrm_t **ppNew);
+ rsRetVal (*Rcv)(netstrm_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf, int *oserr);
+ rsRetVal (*Send)(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf);
+ rsRetVal (*Connect)(netstrm_t *pThis, int family, unsigned char *port, unsigned char *host, char *device);
+ rsRetVal (*GetRemoteHName)(netstrm_t *pThis, uchar **pszName);
+ rsRetVal (*GetRemoteIP)(netstrm_t *pThis, prop_t **ip);
+ rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode);
+ rsRetVal (*SetDrvrAuthMode)(netstrm_t *pThis, uchar*);
+ rsRetVal (*SetDrvrPermitExpiredCerts)(netstrm_t *pThis, uchar*);
+ rsRetVal (*SetDrvrPermPeers)(netstrm_t *pThis, permittedPeers_t*);
+ rsRetVal (*CheckConnection)(netstrm_t *pThis); /* This is a trick mostly for plain tcp syslog */
+ /* the GetSock() below is a hack to make imgssapi work. In the long term,
+ * we should migrate imgssapi to a stream driver, which will relieve us of
+ * this problem. Please note that nobody else should use GetSock(). Using it
+ * will also tie the caller to nsd_ptcp, because other drivers may not support
+ * it at all. Once the imgssapi problem is solved, GetSock should be removed from
+ * this interface. -- rgerhards, 2008-05-05
+ */
+ rsRetVal (*GetSock)(netstrm_t *pThis, int *pSock);
+ rsRetVal (*GetRemAddr)(netstrm_t *pThis, struct sockaddr_storage **ppAddr);
+ /* getRemAddr() is an aid needed by the legacy ACL system. It exposes the remote
+ * peer's socket addr structure, so that the legacy matching functions can work on
+ * it. Note that this ties netstream drivers to things that can be implemented over
+ * sockets - not really desirable, but not the end of the world... TODO: should be
+ * reconsidered when a new ACL system is build. -- rgerhards, 2008-12-01
+ */
+ /* v4 */
+ rsRetVal (*EnableKeepAlive)(netstrm_t *pThis);
+ /* v7 */
+ rsRetVal (*SetKeepAliveProbes)(netstrm_t *pThis, int keepAliveProbes);
+ rsRetVal (*SetKeepAliveTime)(netstrm_t *pThis, int keepAliveTime);
+ rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl);
+ rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString);
+ /* v11 -- Parameter pszLstnFileName added to LstnInit*/
+ rsRetVal (ATTR_NONNULL(1,3,5) *LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params);
+ /* v12 -- two new binary flags added to gtls driver enabling stricter operation */
+ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrm_t *pThis, int ChkExtendedKeyUsage);
+ rsRetVal (*SetDrvrPrioritizeSAN)(netstrm_t *pThis, int prioritizeSan);
+
+ /* v14 -- Tls functions */
+ rsRetVal (*SetDrvrTlsVerifyDepth)(netstrm_t *pThis, int verifyDepth);
+
+ /* v15 -- Tls cert functions */
+ rsRetVal (*SetDrvrTlsCAFile)(netstrm_t *pThis, const uchar* file);
+ rsRetVal (*SetDrvrTlsCRLFile)(netstrm_t *pThis, const uchar* file);
+ rsRetVal (*SetDrvrTlsKeyFile)(netstrm_t *pThis, const uchar* file);
+ rsRetVal (*SetDrvrTlsCertFile)(netstrm_t *pThis, const uchar* file);
+ENDinterface(netstrm)
+#define netstrmCURR_IF_VERSION 16 /* increment whenever you change the interface structure! */
+/* interface version 3 added GetRemAddr()
+ * interface version 4 added EnableKeepAlive() -- rgerhards, 2009-06-02
+ * interface version 5 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
+ * interface version 6 changed signature of GetRemoteIP() -- rgerhards, 2013-01-21
+ * interface version 7 added KeepAlive parameter set functions
+ * interface version 8 changed signature of Connect() -- dsa, 2016-11-14
+ * interface version 9 added SetGnutlsPriorityString -- PascalWithopf, 2017-08-08
+ * interface version 10 added oserr parameter to Rcv() -- rgerhards, 2017-09-04
+ * interface version 16 CRL file -- Oracle, 2022-01-16
+ * */
+
+/* prototypes */
+PROTOTYPEObj(netstrm);
+
+/* the name of our library binary */
+#define LM_NETSTRM_FILENAME LM_NETSTRMS_FILENAME
+
+#endif /* #ifndef INCLUDED_NETSTRM_H */
diff --git a/runtime/netstrms.c b/runtime/netstrms.c
new file mode 100644
index 0000000..74795ff
--- /dev/null
+++ b/runtime/netstrms.c
@@ -0,0 +1,553 @@
+/* netstrms.c
+ *
+ * Work on this module begung 2008-04-23 by Rainer Gerhards.
+ *
+ * Copyright 2008-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "nsd.h"
+#include "netstrm.h"
+#include "nssel.h"
+#include "nspoll.h"
+#include "netstrms.h"
+#include "rsconf.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(netstrm)
+
+
+/* load our low-level driver. This must be done before any
+ * driver-specific functions (allmost all...) can be carried
+ * out. Note that the driver's .ifIsLoaded is correctly
+ * initialized by calloc() and we depend on that.
+ * WARNING: this code is mostly identical to similar code in
+ * nssel.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-18
+ */
+static rsRetVal
+loadDrvr(netstrms_t *pThis)
+{
+ DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
+
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr(runConf);
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsd_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
+
+ pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean
+ * enough. -- rgerhards, 2008-04-18
+ */
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, szDrvrName, (void*) &pThis->Drvr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL) {
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
+ }
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(netstrms) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(netstrms)
+
+
+/* destructor for the netstrms object */
+BEGINobjDestruct(netstrms) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(netstrms)
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, pThis->pDrvrName, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
+ if(pThis->pszDrvrAuthMode != NULL) {
+ free(pThis->pszDrvrAuthMode);
+ pThis->pszDrvrAuthMode = NULL;
+ }
+ if(pThis->pszDrvrPermitExpiredCerts != NULL) {
+ free(pThis->pszDrvrPermitExpiredCerts);
+ pThis->pszDrvrPermitExpiredCerts = NULL;
+ }
+ free((void*)pThis->pszDrvrCAFile);
+ pThis->pszDrvrCAFile = NULL;
+ free((void*)pThis->pszDrvrCRLFile);
+ pThis->pszDrvrCRLFile = NULL;
+ free((void*)pThis->pszDrvrKeyFile);
+ pThis->pszDrvrKeyFile = NULL;
+ free((void*)pThis->pszDrvrCertFile);
+ pThis->pszDrvrCertFile = NULL;
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+ if(pThis->gnutlsPriorityString != NULL) {
+ free(pThis->gnutlsPriorityString);
+ pThis->gnutlsPriorityString = NULL;
+ }
+ENDobjDestruct(netstrms)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+netstrmsConstructFinalize(netstrms_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ iRet = loadDrvr(pThis);
+ RETiRet;
+}
+
+
+/* set the base driver name. If the driver name
+ * is set to NULL, the previously set name is deleted but
+ * no name set again (which results in the system default being
+ * used)-- rgerhards, 2008-05-05
+ */
+static rsRetVal
+SetDrvrName(netstrms_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+
+ if(pszName != NULL) {
+ CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the driver's permitted peers -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrPermPeers(netstrms_t *pThis, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->pPermPeers = pPermPeers;
+ RETiRet;
+}
+/* return the driver's permitted peers
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * rgerhards, 2008-05-19
+ */
+static permittedPeers_t*
+GetDrvrPermPeers(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pPermPeers;
+}
+
+
+/* set the driver auth mode -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrAuthMode(netstrms_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ CHKmalloc(pThis->pszDrvrAuthMode = (uchar*)strdup((char*)mode));
+finalize_it:
+ RETiRet;
+}
+
+
+/* return the driver auth mode
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * rgerhards, 2008-05-19
+ */
+static uchar*
+GetDrvrAuthMode(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrAuthMode;
+}
+
+
+/* return the driver permitexpiredcerts mode
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * alorbach, 2018-12-21
+ */
+static uchar*
+GetDrvrPermitExpiredCerts(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrPermitExpiredCerts;
+}
+
+/* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20
+ */
+static rsRetVal
+SetDrvrPermitExpiredCerts(netstrms_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrPermitExpiredCerts = (uchar*) strdup((char*)mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCAFile(netstrms_t *pThis, const uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCAFile = (uchar*) strdup((char*)mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCRLFile(netstrms_t *pThis, const uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCRLFile = (uchar*) strdup((char*)mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsKeyFile(netstrms_t *pThis, const uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrKeyFile = (uchar*) strdup((char*)mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrTlsCertFile(netstrms_t *pThis, const uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCertFile = (uchar*) strdup((char*)mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the priorityString for GnuTLS
+ * PascalWithopf 2017-08-16
+ */
+static rsRetVal
+SetDrvrGnutlsPriorityString(netstrms_t *pThis, uchar *iVal)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ CHKmalloc(pThis->gnutlsPriorityString = (uchar*)strdup((char*)iVal));
+finalize_it:
+ RETiRet;
+}
+
+
+/* return the priorityString for GnuTLS
+ * PascalWithopf, 2017-08-16
+ */
+static uchar*
+GetDrvrGnutlsPriorityString(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->gnutlsPriorityString;
+}
+
+
+/* set the driver mode -- rgerhards, 2008-04-30 */
+static rsRetVal
+SetDrvrMode(netstrms_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->iDrvrMode = iMode;
+ RETiRet;
+}
+
+
+/* return the driver mode
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * rgerhards, 2008-04-30
+ */
+static int
+GetDrvrMode(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->iDrvrMode;
+}
+
+
+/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */
+static rsRetVal
+SetDrvrCheckExtendedKeyUsage(netstrms_t *pThis, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage;
+ RETiRet;
+}
+
+
+/* return the driver cert extended key usage check setting
+ * jvymazal, 2019-08-16
+ */
+static int
+GetDrvrCheckExtendedKeyUsage(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->DrvrChkExtendedKeyUsage;
+}
+
+
+/* set the driver name checking policy -- jvymazal, 2019-08-16 */
+static rsRetVal
+SetDrvrPrioritizeSAN(netstrms_t *pThis, int prioritizeSan)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->DrvrPrioritizeSan = prioritizeSan;
+ RETiRet;
+}
+
+
+/* return the driver name checking policy
+ * jvymazal, 2019-08-16
+ */
+static int
+GetDrvrPrioritizeSAN(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->DrvrPrioritizeSan;
+}
+
+/* set the driver TlsVerifyDepth -- alorbach, 2019-12-20 */
+static rsRetVal
+SetDrvrTlsVerifyDepth(netstrms_t *pThis, int verifyDepth)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->DrvrVerifyDepth = verifyDepth;
+ RETiRet;
+}
+
+/* return the driver TlsVerifyDepth
+ * alorbach, 2019-12-20
+ */
+static int
+GetDrvrTlsVerifyDepth(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->DrvrVerifyDepth;
+}
+
+static const uchar *
+GetDrvrTlsCAFile(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrCAFile;
+}
+static const uchar *
+GetDrvrTlsCRLFile(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrCRLFile;
+}
+static const uchar *
+GetDrvrTlsKeyFile(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrKeyFile;
+}
+static const uchar *
+GetDrvrTlsCertFile(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->pszDrvrCertFile;
+}
+
+/* create an instance of a netstrm object. It is initialized with default
+ * values. The current driver is used. The caller may set netstrm properties
+ * and must call ConstructFinalize().
+ */
+static rsRetVal
+CreateStrm(netstrms_t *pThis, netstrm_t **ppStrm)
+{
+ netstrm_t *pStrm = NULL;
+ DEFiRet;
+
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+ CHKiRet(netstrm.Construct(&pStrm));
+ /* we copy over our driver structure. We could provide a pointer to
+ * ourselves, but that costs some performance on each driver invocation.
+ * As we already have hefty indirection (and thus performance toll), I
+ * prefer to copy over the function pointers here. -- rgerhards, 2008-04-23
+ */
+ memcpy(&pStrm->Drvr, &pThis->Drvr, sizeof(pThis->Drvr));
+ pStrm->pNS = pThis;
+
+ *ppStrm = pStrm;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrm != NULL)
+ netstrm.Destruct(&pStrm);
+ }
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(netstrms)
+CODESTARTobjQueryInterface(netstrms)
+ if(pIf->ifVersion != netstrmsCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = netstrmsConstruct;
+ pIf->ConstructFinalize = netstrmsConstructFinalize;
+ pIf->Destruct = netstrmsDestruct;
+ pIf->CreateStrm = CreateStrm;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->GetDrvrMode = GetDrvrMode;
+ pIf->SetDrvrAuthMode = SetDrvrAuthMode;
+ pIf->GetDrvrAuthMode = GetDrvrAuthMode;
+ pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts;
+ pIf->GetDrvrPermitExpiredCerts = GetDrvrPermitExpiredCerts;
+ pIf->SetDrvrGnutlsPriorityString = SetDrvrGnutlsPriorityString;
+ pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString;
+ pIf->SetDrvrPermPeers = SetDrvrPermPeers;
+ pIf->GetDrvrPermPeers = GetDrvrPermPeers;
+ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
+ pIf->GetDrvrCheckExtendedKeyUsage = GetDrvrCheckExtendedKeyUsage;
+ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
+ pIf->GetDrvrPrioritizeSAN = GetDrvrPrioritizeSAN;
+ pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth;
+ pIf->GetDrvrTlsVerifyDepth = GetDrvrTlsVerifyDepth;
+ pIf->GetDrvrTlsCAFile = GetDrvrTlsCAFile;
+ pIf->GetDrvrTlsCRLFile = GetDrvrTlsCRLFile;
+ pIf->GetDrvrTlsKeyFile = GetDrvrTlsKeyFile;
+ pIf->GetDrvrTlsCertFile = GetDrvrTlsCertFile;
+ pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile;
+ pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile;
+ pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile;
+ pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile;
+finalize_it:
+ENDobjQueryInterface(netstrms)
+
+
+/* exit our class */
+BEGINObjClassExit(netstrms, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(netstrms)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(netstrm, DONT_LOAD_LIB);
+ENDObjClassExit(netstrms)
+
+
+/* Initialize the netstrms class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(netstrms, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(netstrms)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsselClassExit();
+ nspollClassExit();
+ netstrmsClassExit();
+ netstrmClassExit(); /* we use this object, so we must exit it after we are finished */
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(netstrmClassInit(pModInfo));
+ CHKiRet(nsselClassInit(pModInfo));
+ CHKiRet(nspollClassInit(pModInfo));
+ CHKiRet(netstrmsClassInit(pModInfo));
+ENDmodInit
diff --git a/runtime/netstrms.h b/runtime/netstrms.h
new file mode 100644
index 0000000..203ad22
--- /dev/null
+++ b/runtime/netstrms.h
@@ -0,0 +1,94 @@
+/* Definitions for the stream-based netstrmsworking class.
+ *
+ * Copyright 2007-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NETSTRMS_H
+#define INCLUDED_NETSTRMS_H
+
+#include "nsd.h" /* we need our driver interface to be defined */
+
+/* the netstrms object */
+struct netstrms_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ int iDrvrMode; /**< current default driver mode */
+ uchar *pszDrvrAuthMode; /**< current driver authentication mode */
+ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */
+ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */
+ int DrvrVerifyDepth; /**< Verify Depth for certificate chains */
+ uchar *pszDrvrPermitExpiredCerts;
+ const uchar *pszDrvrCAFile;
+ const uchar *pszDrvrCRLFile;
+ const uchar *pszDrvrKeyFile;
+ const uchar *pszDrvrCertFile;
+ uchar *gnutlsPriorityString; /**< priorityString for connection */
+ permittedPeers_t *pPermPeers;/**< current driver's permitted peers */
+ rsRetVal(*fLstnInitDrvr)(netstrm_t*); /**< "late" driver-specific lstn init function NULL if none */
+
+ nsd_if_t Drvr; /**< our stream driver */
+};
+
+
+/* interface */
+BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(netstrms_t **ppThis);
+ rsRetVal (*ConstructFinalize)(netstrms_t *pThis);
+ rsRetVal (*Destruct)(netstrms_t **ppThis);
+ rsRetVal (*CreateStrm)(netstrms_t *pThis, netstrm_t **ppStrm);
+ rsRetVal (*SetDrvrName)(netstrms_t *pThis, uchar *pszName);
+ rsRetVal (*SetDrvrMode)(netstrms_t *pThis, int iMode);
+ rsRetVal (*SetDrvrAuthMode)(netstrms_t *pThis, uchar*);
+ rsRetVal (*SetDrvrPermitExpiredCerts)(netstrms_t *pThis, uchar*);
+ rsRetVal (*SetDrvrPermPeers)(netstrms_t *pThis, permittedPeers_t*);
+ int (*GetDrvrMode)(netstrms_t *pThis);
+ uchar* (*GetDrvrAuthMode)(netstrms_t *pThis);
+ uchar* (*GetDrvrPermitExpiredCerts)(netstrms_t *pThis);
+ permittedPeers_t* (*GetDrvrPermPeers)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrGnutlsPriorityString)(netstrms_t *pThis, uchar*);
+ uchar* (*GetDrvrGnutlsPriorityString)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis, int ChkExtendedKeyUsage);
+ int (*GetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrPrioritizeSAN)(netstrms_t *pThis, int prioritizeSan);
+ int (*GetDrvrPrioritizeSAN)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrTlsVerifyDepth)(netstrms_t *pThis, int verifyDepth);
+ int (*GetDrvrTlsVerifyDepth)(netstrms_t *pThis);
+ /* v2 */
+ rsRetVal (*SetDrvrTlsCAFile)(netstrms_t *pThis, const uchar *);
+ const uchar* (*GetDrvrTlsCAFile)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrTlsKeyFile)(netstrms_t *pThis, const uchar *);
+ const uchar* (*GetDrvrTlsKeyFile)(netstrms_t *pThis);
+ rsRetVal (*SetDrvrTlsCertFile)(netstrms_t *pThis, const uchar *);
+ const uchar* (*GetDrvrTlsCertFile)(netstrms_t *pThis);
+ /* v3 */
+ rsRetVal (*SetDrvrTlsCRLFile)(netstrms_t *pThis, const uchar *);
+ const uchar* (*GetDrvrTlsCRLFile)(netstrms_t *pThis);
+ENDinterface(netstrms)
+#define netstrmsCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(netstrms);
+
+/* the name of our library binary */
+#define LM_NETSTRMS_FILENAME "lmnetstrms"
+
+#endif /* #ifndef INCLUDED_NETSTRMS_H */
diff --git a/runtime/nsd.h b/runtime/nsd.h
new file mode 100644
index 0000000..03df7d2
--- /dev/null
+++ b/runtime/nsd.h
@@ -0,0 +1,134 @@
+/* The interface definition for "NetStream Drivers" (nsd).
+ *
+ * This is just an abstract driver interface, which needs to be
+ * implemented by concrete classes. As such, no nsd data type itself
+ * is defined.
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_NSD_H
+#define INCLUDED_NSD_H
+
+#include <sys/socket.h>
+
+/**
+ * The following structure is a set of descriptors that need to be processed.
+ * This set will be the result of the epoll call and be used
+ * in the actual request processing stage. -- rgerhards, 2011-01-24
+ */
+struct nsd_epworkset_s {
+ int id;
+ void *pUsr;
+};
+
+enum nsdsel_waitOp_e {
+ NSDSEL_RD = 1,
+ NSDSEL_WR = 2,
+ NSDSEL_RDWR = 3
+}; /**< the operation we wait for */
+
+/* nsd_t is actually obj_t (which is somewhat better than void* but in essence
+ * much the same).
+ */
+
+/* interface */
+BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nsd_t **ppThis);
+ rsRetVal (*Destruct)(nsd_t **ppThis);
+ rsRetVal (*Abort)(nsd_t *pThis);
+ rsRetVal (*Rcv)(nsd_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf, int *oserr);
+ rsRetVal (*Send)(nsd_t *pThis, uchar *pBuf, ssize_t *pLenBuf);
+ rsRetVal (*Connect)(nsd_t *pThis, int family, unsigned char *port, unsigned char *host, char *device);
+ rsRetVal (*AcceptConnReq)(nsd_t *pThis, nsd_t **ppThis);
+ rsRetVal (*GetRemoteHName)(nsd_t *pThis, uchar **pszName);
+ rsRetVal (*GetRemoteIP)(nsd_t *pThis, prop_t **ip);
+ rsRetVal (*SetMode)(nsd_t *pThis, int mode); /* sets a driver specific mode - see driver doc for details */
+ rsRetVal (*SetAuthMode)(nsd_t *pThis, uchar*); /* sets a driver specific mode - see driver doc for details */
+ rsRetVal (*SetPermitExpiredCerts)(nsd_t *pThis, uchar*); /* sets a driver specific permitexpiredcerts mode */
+ rsRetVal (*SetPermPeers)(nsd_t *pThis, permittedPeers_t*); /* sets driver permitted peers for auth needs */
+ rsRetVal (*CheckConnection)(nsd_t *pThis); /* This is a trick mostly for plain tcp syslog */
+ rsRetVal (*GetSock)(nsd_t *pThis, int *pSock);
+ rsRetVal (*SetSock)(nsd_t *pThis, int sock);
+ /* GetSock() and SetSock() return an error if the driver does not use plain
+ * OS sockets. This interface is primarily meant as an internal aid for
+ * those drivers that utilize the nsd_ptcp to do some of their work.
+ */
+ rsRetVal (*GetRemAddr)(nsd_t *pThis, struct sockaddr_storage **ppAddr);
+ /* getRemAddr() is an aid needed by the legacy ACL system. It exposes the remote
+ * peer's socket addr structure, so that the legacy matching functions can work on
+ * it. Note that this ties netstream drivers to things that can be implemented over
+ * sockets - not really desirable, but not the end of the world... TODO: should be
+ * reconsidered when a new ACL system is build. -- rgerhards, 2008-12-01
+ */
+ /* v5 */
+ rsRetVal (*EnableKeepAlive)(nsd_t *pThis);
+ /* v8 */
+ rsRetVal (*SetKeepAliveIntvl)(nsd_t *pThis, int keepAliveIntvl);
+ rsRetVal (*SetKeepAliveProbes)(nsd_t *pThis, int keepAliveProbes);
+ rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime);
+ rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString);
+ /* v12 -- parameter pszLstnPortFileName added to LstnInit()*/
+ rsRetVal (ATTR_NONNULL(1,3,5) *LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params);
+ /* v13 -- two new binary flags added to gtls driver enabling stricter operation */
+ rsRetVal (*SetCheckExtendedKeyUsage)(nsd_t *pThis, int ChkExtendedKeyUsage);
+ rsRetVal (*SetPrioritizeSAN)(nsd_t *pThis, int prioritizeSan);
+
+ /* v14 -- Tls functions */
+ rsRetVal (*SetTlsVerifyDepth)(nsd_t *pThis, int verifyDepth);
+
+ /* v15 -- Tls functions */
+ rsRetVal (*SetTlsCAFile)(nsd_t *pThis, const uchar *);
+ rsRetVal (*SetTlsKeyFile)(nsd_t *pThis, const uchar *);
+ rsRetVal (*SetTlsCertFile)(nsd_t *pThis, const uchar *);
+
+ /* v16 - Tls CRL */
+ rsRetVal (*SetTlsCRLFile)(nsd_t *pThis, const uchar *);
+ENDinterface(nsd)
+#define nsdCURR_IF_VERSION 16 /* increment whenever you change the interface structure! */
+/* interface version 4 added GetRemAddr()
+ * interface version 5 added EnableKeepAlive() -- rgerhards, 2009-06-02
+ * interface version 6 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06
+ * interface version 7 changed signature ofGetRempoteIP() -- rgerhards, 2013-01-21
+ * interface version 8 added keep alive parameter set functions
+ * interface version 9 changed signature of Connect() -- dsa, 2016-11-14
+ * interface version 10 added SetGnutlsPriorityString() -- PascalWithopf, 2017-08-08
+ * interface version 11 added oserr to Rcv() signature -- rgerhards, 2017-09-04
+ */
+
+/* interface for the select call */
+BEGINinterface(nsdsel) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nsdsel_t **ppThis);
+ rsRetVal (*Destruct)(nsdsel_t **ppThis);
+ rsRetVal (*Add)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp);
+ rsRetVal (*Select)(nsdsel_t *pNsdsel, int *piNumReady);
+ rsRetVal (*IsReady)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady);
+ENDinterface(nsdsel)
+#define nsdselCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* interface for the epoll call */
+BEGINinterface(nsdpoll) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nsdpoll_t **ppThis);
+ rsRetVal (*Destruct)(nsdpoll_t **ppThis);
+ rsRetVal (*Ctl)(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int mode, int op);
+ rsRetVal (*Wait)(nsdpoll_t *pNsdpoll, int timeout, int *numReady, nsd_epworkset_t workset[]);
+ENDinterface(nsdpoll)
+#define nsdpollCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+#endif /* #ifndef INCLUDED_NSD_H */
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
new file mode 100644
index 0000000..b9c0f8a
--- /dev/null
+++ b/runtime/nsd_gtls.c
@@ -0,0 +1,2451 @@
+/* nsd_gtls.c
+ *
+ * An implementation of the nsd interface for GnuTLS.
+ *
+ * Copyright (C) 2007-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#if GNUTLS_VERSION_NUMBER <= 0x020b00
+# include <gcrypt.h>
+#endif
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "stringbuf.h"
+#include "errmsg.h"
+#include "net.h"
+#include "datetime.h"
+#include "netstrm.h"
+#include "netstrms.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_gtls.h"
+#include "nsd_gtls.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+#if GNUTLS_VERSION_NUMBER <= 0x020b00
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+#endif
+MODULE_TYPE_LIB
+MODULE_TYPE_KEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(nsd_ptcp)
+
+/* Static Helper variables for certless communication */
+static gnutls_anon_client_credentials_t anoncred; /**< client anon credentials */
+static gnutls_anon_server_credentials_t anoncredSrv; /**< server anon credentials */
+static int dhBits = 2048; /**< number of bits for Diffie-Hellman key */
+static int dhMinBits = 512; /**< minimum number of bits for Diffie-Hellman key */
+
+static pthread_mutex_t mutGtlsStrerror;
+/*< a mutex protecting the potentially non-reentrant gtlStrerror() function */
+
+static gnutls_dh_params_t dh_params; /**< server DH parameters for anon mode */
+
+/* a macro to abort if GnuTLS error is not acceptable. We split this off from
+ * CHKgnutls() to avoid some Coverity report in cases where we know GnuTLS
+ * failed. Note: gnuRet must already be set accordingly!
+ */
+#define ABORTgnutls { \
+ uchar *pErr = gtlsStrerror(gnuRet); \
+ LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n", \
+ gnuRet, __FILE__, __LINE__, pErr); \
+ free(pErr); \
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
+}
+/* a macro to check GnuTLS calls against unexpected errors */
+#define CHKgnutls(x) { \
+ gnuRet = (x); \
+ if(gnuRet == GNUTLS_E_FILE_ERROR) { \
+ LogError(0, RS_RET_GNUTLS_ERR, "error reading file - a common cause is that the " \
+ "file does not exist"); \
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
+ } else if(gnuRet != 0) { \
+ ABORTgnutls; \
+ } \
+}
+
+
+/* ------------------------------ GnuTLS specifics ------------------------------ */
+
+/* This defines a log function to be provided to GnuTLS. It hopefully
+ * helps us track down hard to find problems.
+ * rgerhards, 2008-06-20
+ */
+static void logFunction(int level, const char *msg)
+{
+ dbgprintf("GnuTLS log msg, level %d: %s\n", level, msg);
+}
+
+/* read in the whole content of a file. The caller is responsible for
+ * freeing the buffer. To prevent DOS, this function can NOT read
+ * files larger than 1MB (which still is *very* large).
+ * rgerhards, 2008-05-26
+ */
+static rsRetVal
+readFile(const uchar *const pszFile, gnutls_datum_t *const pBuf)
+{
+ int fd;
+ struct stat stat_st;
+ DEFiRet;
+
+ assert(pszFile != NULL);
+ assert(pBuf != NULL);
+
+ pBuf->data = NULL;
+
+ if((fd = open((char*)pszFile, O_RDONLY)) == -1) {
+ LogError(errno, RS_RET_FILE_NOT_FOUND, "can not read file '%s'", pszFile);
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ }
+
+ if(fstat(fd, &stat_st) == -1) {
+ LogError(errno, RS_RET_FILE_NO_STAT, "can not stat file '%s'", pszFile);
+ ABORT_FINALIZE(RS_RET_FILE_NO_STAT);
+ }
+
+ /* 1MB limit */
+ if(stat_st.st_size > 1024 * 1024) {
+ LogError(0, RS_RET_FILE_TOO_LARGE, "file '%s' too large, max 1MB", pszFile);
+ ABORT_FINALIZE(RS_RET_FILE_TOO_LARGE);
+ }
+
+ CHKmalloc(pBuf->data = malloc(stat_st.st_size));
+ pBuf->size = stat_st.st_size;
+ if(read(fd, pBuf->data, stat_st.st_size) != stat_st.st_size) {
+ LogError(0, RS_RET_IO_ERROR, "error or incomplete read of file '%s'", pszFile);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(fd != -1)
+ close(fd);
+ if(iRet != RS_RET_OK) {
+ if(pBuf->data != NULL) {
+ free(pBuf->data);
+ pBuf->data = NULL;
+ pBuf->size = 0;
+ }
+ }
+ RETiRet;
+}
+
+
+/* Load the certificate and the private key into our own store. We need to do
+ * this in the client case, to support fingerprint authentication. In that case,
+ * we may be presented no matching root certificate, but we must provide ours.
+ * The only way to do that is via the cert callback interface, but for it we
+ * need to load certificates into our private store.
+ * rgerhards, 2008-05-26
+ */
+static rsRetVal
+gtlsLoadOurCertKey(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+ int gnuRet;
+ gnutls_datum_t data = { NULL, 0 };
+ const uchar *keyFile;
+ const uchar *certFile;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ certFile = (pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile;
+ keyFile = (pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile;
+
+ if(certFile == NULL || keyFile == NULL) {
+ /* in this case, we can not set our certificate. If we are
+ * a client and the server is running in "anon" auth mode, this
+ * may be well acceptable. In other cases, we will see some
+ * more error messages down the road. -- rgerhards, 2008-07-02
+ */
+ dbgprintf("gtlsLoadOurCertKey our certificate is not set, file name values are cert: '%s', key: '%s'\n",
+ certFile, keyFile);
+ ABORT_FINALIZE(RS_RET_CERTLESS);
+ }
+
+ /* try load certificate */
+ CHKiRet(readFile(certFile, &data));
+ pThis->nOurCerts = sizeof(pThis->pOurCerts) / sizeof(gnutls_x509_crt_t);
+ gnuRet = gnutls_x509_crt_list_import(pThis->pOurCerts, &pThis->nOurCerts,
+ &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
+ if(gnuRet < 0) {
+ ABORTgnutls;
+ }
+ pThis->bOurCertIsInit = 1;
+ free(data.data);
+ data.data = NULL;
+
+ /* try load private key */
+ CHKiRet(readFile(keyFile, &data));
+ CHKgnutls(gnutls_x509_privkey_init(&pThis->ourKey));
+ pThis->bOurKeyIsInit = 1;
+ CHKgnutls(gnutls_x509_privkey_import(pThis->ourKey, &data, GNUTLS_X509_FMT_PEM));
+ free(data.data);
+
+
+finalize_it:
+ if(iRet == RS_RET_CERTLESS) {
+ dbgprintf("gtlsLoadOurCertKey certless exit\n");
+ pThis->bOurCertIsInit = 0;
+ pThis->bOurKeyIsInit = 0;
+ } else if(iRet != RS_RET_OK) {
+ dbgprintf("gtlsLoadOurCertKey error exit\n");
+ if(data.data != NULL)
+ free(data.data);
+ if(pThis->bOurCertIsInit) {
+ for(unsigned i=0; i<pThis->nOurCerts; ++i) {
+ gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
+ }
+ pThis->bOurCertIsInit = 0;
+ }
+ if(pThis->bOurKeyIsInit) {
+ gnutls_x509_privkey_deinit(pThis->ourKey);
+ pThis->bOurKeyIsInit = 0;
+ }
+ } else {
+ dbgprintf("gtlsLoadOurCertKey Successfully Loaded cert '%s' and key: '%s'\n", certFile, keyFile);
+ }
+ RETiRet;
+}
+
+
+/* This callback must be associated with a session by calling
+ * gnutls_certificate_client_set_retrieve_function(session, cert_callback),
+ * before a handshake. We will always return the configured certificate,
+ * even if it does not match the peer's trusted CAs. This is necessary
+ * to use self-signed certs in fingerprint mode. And, yes, this usage
+ * of the callback is quite a hack. But it seems the only way to
+ * obey to the IETF -transport-tls I-D.
+ * Note: GnuTLS requires the function to return 0 on success and
+ * -1 on failure.
+ * rgerhards, 2008-05-27
+ */
+static int
+gtlsClientCertCallback(gnutls_session_t session,
+ __attribute__((unused)) const gnutls_datum_t* req_ca_rdn,
+ int __attribute__((unused)) nreqs,
+ __attribute__((unused)) const gnutls_pk_algorithm_t* sign_algos,
+ int __attribute__((unused)) sign_algos_length,
+#if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
+ gnutls_retr2_st* st
+#else
+ gnutls_retr_st *st
+#endif
+ )
+{
+ nsd_gtls_t *pThis;
+
+ pThis = (nsd_gtls_t*) gnutls_session_get_ptr(session);
+
+#if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
+ st->cert_type = GNUTLS_CRT_X509;
+#else
+ st->type = GNUTLS_CRT_X509;
+#endif
+ st->ncerts = pThis->nOurCerts;
+ st->cert.x509 = pThis->pOurCerts;
+ st->key.x509 = pThis->ourKey;
+ st->deinit_all = 0;
+
+ return 0;
+}
+
+
+/* This function extracts some information about this session's peer
+ * certificate. Works for X.509 certificates only. Adds all
+ * of the info to a cstr_t, which is handed over to the caller.
+ * Caller must destruct it when no longer needed.
+ * rgerhards, 2008-05-21
+ */
+static rsRetVal
+gtlsGetCertInfo(nsd_gtls_t *const pThis, cstr_t **ppStr)
+{
+ uchar szBufA[1024];
+ uchar *szBuf = szBufA;
+ size_t szBufLen = sizeof(szBufA), tmp;
+ unsigned int algo, bits;
+ time_t expiration_time, activation_time;
+ const gnutls_datum_t *cert_list;
+ unsigned cert_list_size = 0;
+ gnutls_x509_crt_t cert;
+ cstr_t *pStr = NULL;
+ int gnuRet;
+ DEFiRet;
+ unsigned iAltName;
+
+ assert(ppStr != NULL);
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ if(gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509)
+ return RS_RET_TLS_CERT_ERR;
+
+ cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size);
+ CHKiRet(rsCStrConstructFromszStrf(&pStr, "peer provided %d certificate(s). ", cert_list_size));
+
+ if(cert_list_size > 0) {
+ /* we only print information about the first certificate */
+ CHKgnutls(gnutls_x509_crt_init(&cert));
+ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
+
+ expiration_time = gnutls_x509_crt_get_expiration_time(cert);
+ activation_time = gnutls_x509_crt_get_activation_time(cert);
+ ctime_r(&activation_time, (char*)szBuf);
+ szBuf[ustrlen(szBuf) - 1] = '\0'; /* strip linefeed */
+ CHKiRet(rsCStrAppendStrf(pStr, "Certificate 1 info: "
+ "certificate valid from %s ", szBuf));
+ ctime_r(&expiration_time, (char*)szBuf);
+ szBuf[ustrlen(szBuf) - 1] = '\0'; /* strip linefeed */
+ CHKiRet(rsCStrAppendStrf(pStr, "to %s; ", szBuf));
+
+ /* Extract some of the public key algorithm's parameters */
+ algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
+ CHKiRet(rsCStrAppendStrf(pStr, "Certificate public key: %s; ",
+ gnutls_pk_algorithm_get_name(algo)));
+
+ /* names */
+ tmp = szBufLen;
+ if(gnutls_x509_crt_get_dn(cert, (char*)szBuf, &tmp)
+ == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = malloc(tmp);
+ gnutls_x509_crt_get_dn(cert, (char*)szBuf, &tmp);
+ }
+ CHKiRet(rsCStrAppendStrf(pStr, "DN: %s; ", szBuf));
+
+ tmp = szBufLen;
+ if(gnutls_x509_crt_get_issuer_dn(cert, (char*)szBuf, &tmp)
+ == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp);
+ gnutls_x509_crt_get_issuer_dn(cert, (char*)szBuf, &tmp);
+ }
+ CHKiRet(rsCStrAppendStrf(pStr, "Issuer DN: %s; ", szBuf));
+
+ /* dNSName alt name */
+ iAltName = 0;
+ while(1) { /* loop broken below */
+ tmp = szBufLen;
+ gnuRet = gnutls_x509_crt_get_subject_alt_name(cert, iAltName,
+ szBuf, &tmp, NULL);
+ if(gnuRet == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp);
+ continue;
+ } else if(gnuRet < 0)
+ break;
+ else if(gnuRet == GNUTLS_SAN_DNSNAME) {
+ /* we found it! */
+ CHKiRet(rsCStrAppendStrf(pStr, "SAN:DNSname: %s; ", szBuf));
+ /* do NOT break, because there may be multiple dNSName's! */
+ }
+ ++iAltName;
+ }
+
+ gnutls_x509_crt_deinit(cert);
+ }
+
+ cstrFinalize(pStr);
+ *ppStr = pStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ }
+ if(szBuf != szBufA)
+ free(szBuf);
+
+ RETiRet;
+}
+
+
+
+#if 0 /* we may need this in the future - code needs to be looked at then! */
+/* This function will print some details of the
+ * given pThis->sess.
+ */
+static rsRetVal
+print_info(nsd_gtls_t *pThis)
+{
+ const char *tmp;
+ gnutls_credentials_type cred;
+ gnutls_kx_algorithm kx;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ /* print the key exchange's algorithm name
+ */
+ kx = gnutls_kx_get(pThis->sess);
+ tmp = gnutls_kx_get_name(kx);
+ dbgprintf("- Key Exchange: %s\n", tmp);
+
+ /* Check the authentication type used and switch
+ * to the appropriate.
+ */
+ cred = gnutls_auth_get_type(pThis->sess);
+ switch (cred) {
+ case GNUTLS_CRD_ANON: /* anonymous authentication */
+ dbgprintf("- Anonymous DH using prime of %d bits\n",
+ gnutls_dh_get_prime_bits(pThis->sess));
+ break;
+ case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */
+ /* Check if we have been using ephemeral Diffie Hellman.
+ */
+ if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) {
+ dbgprintf("\n- Ephemeral DH using prime of %d bits\n",
+ gnutls_dh_get_prime_bits(pThis->sess));
+ }
+
+ /* if the certificate list is available, then
+ * print some information about it.
+ */
+ gtlsPrintCert(pThis);
+ break;
+ case GNUTLS_CRD_SRP: /* certificate authentication */
+ dbgprintf("GNUTLS_CRD_SRP/IA");
+ break;
+ case GNUTLS_CRD_PSK: /* certificate authentication */
+ dbgprintf("GNUTLS_CRD_PSK");
+ break;
+ case GNUTLS_CRD_IA: /* certificate authentication */
+ dbgprintf("GNUTLS_CRD_IA");
+ break;
+ } /* switch */
+
+ /* print the protocol's name (ie TLS 1.0) */
+ tmp = gnutls_protocol_get_name(gnutls_protocol_get_version(pThis->sess));
+ dbgprintf("- Protocol: %s\n", tmp);
+
+ /* print the certificate type of the peer.
+ * ie X.509
+ */
+ tmp = gnutls_certificate_type_get_name(
+ gnutls_certificate_type_get(pThis->sess));
+
+ dbgprintf("- Certificate Type: %s\n", tmp);
+
+ /* print the compression algorithm (if any)
+ */
+ tmp = gnutls_compression_get_name( gnutls_compression_get(pThis->sess));
+ dbgprintf("- Compression: %s\n", tmp);
+
+ /* print the name of the cipher used.
+ * ie 3DES.
+ */
+ tmp = gnutls_cipher_get_name(gnutls_cipher_get(pThis->sess));
+ dbgprintf("- Cipher: %s\n", tmp);
+
+ /* Print the MAC algorithms name.
+ * ie SHA1
+ */
+ tmp = gnutls_mac_get_name(gnutls_mac_get(pThis->sess));
+ dbgprintf("- MAC: %s\n", tmp);
+
+ RETiRet;
+}
+#endif
+
+
+/* Convert a fingerprint to printable data. The conversion is carried out
+ * according IETF I-D syslog-transport-tls-12. The fingerprint string is
+ * returned in a new cstr object. It is the caller's responsibility to
+ * destruct that object.
+ * rgerhards, 2008-05-08
+ */
+static rsRetVal
+GenFingerprintStr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr, const char* prefix)
+{
+ cstr_t *pStr = NULL;
+ uchar buf[4];
+ size_t i;
+ DEFiRet;
+
+ CHKiRet(rsCStrConstruct(&pStr));
+ CHKiRet(rsCStrAppendStrWithLen(pStr, (uchar*) prefix, strlen(prefix)));
+ for(i = 0 ; i < sizeFingerprint ; ++i) {
+ snprintf((char*)buf, sizeof(buf), ":%2.2X", pFingerprint[i]);
+ CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3));
+ }
+ cstrFinalize(pStr);
+
+ *ppStr = pStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ }
+ RETiRet;
+}
+
+
+/* a thread-safe variant of gnutls_strerror
+ * The caller must free the returned string.
+ * rgerhards, 2008-04-30
+ */
+uchar *gtlsStrerror(int error)
+{
+ uchar *pErr;
+
+ pthread_mutex_lock(&mutGtlsStrerror);
+ pErr = (uchar*) strdup(gnutls_strerror(error));
+ pthread_mutex_unlock(&mutGtlsStrerror);
+
+ return pErr;
+}
+
+
+/* try to receive a record from the remote peer. This works with
+ * our own abstraction and handles local buffering and EAGAIN.
+ * See details on local buffering in Rcv(9 header-comment.
+ * This function MUST only be called when the local buffer is
+ * empty. Calling it otherwise will cause losss of current buffer
+ * data.
+ * rgerhards, 2008-06-24
+ */
+rsRetVal
+gtlsRecordRecv(nsd_gtls_t *pThis)
+{
+ ssize_t lenRcvd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ DBGPRINTF("gtlsRecordRecv: start (Pending Data: %zd | Wanted Direction: %s)\n",
+ gnutls_record_check_pending(pThis->sess),
+ (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ ? "READ" : "WRITE") );
+ lenRcvd = gnutls_record_recv(pThis->sess, pThis->pszRcvBuf, NSD_GTLS_MAX_RCVBUF);
+ if(lenRcvd >= 0) {
+ DBGPRINTF("gtlsRecordRecv: gnutls_record_recv received %zd bytes\n", lenRcvd);
+ pThis->lenRcvBuf = lenRcvd;
+ pThis->ptrRcvBuf = 0;
+
+ /* Check for additional data in SSL buffer */
+ size_t stBytesLeft = gnutls_record_check_pending(pThis->sess);
+ if (stBytesLeft > 0 ){
+ DBGPRINTF("gtlsRecordRecv: %zd Bytes pending after gnutls_record_recv, expand buffer.\n",
+ stBytesLeft);
+ /* realloc buffer size and preserve char content */
+ char *const newbuf = realloc(pThis->pszRcvBuf, NSD_GTLS_MAX_RCVBUF+stBytesLeft);
+ CHKmalloc(newbuf);
+ pThis->pszRcvBuf = newbuf;
+
+ /* 2nd read will read missing bytes from the current SSL Packet */
+ lenRcvd = gnutls_record_recv(pThis->sess, pThis->pszRcvBuf+NSD_GTLS_MAX_RCVBUF, stBytesLeft);
+ if(lenRcvd > 0) {
+ DBGPRINTF("gtlsRecordRecv: 2nd SSL_read received %zd bytes\n",
+ (NSD_GTLS_MAX_RCVBUF+lenRcvd));
+ pThis->lenRcvBuf = NSD_GTLS_MAX_RCVBUF+lenRcvd;
+ } else {
+ if (lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) {
+ goto sslerragain; /* Go to ERR AGAIN handling */
+ } else {
+ /* Do all other error handling */
+ int gnuRet = lenRcvd;
+ ABORTgnutls;
+ }
+ }
+ }
+ } else if(lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) {
+sslerragain:
+ /* Check if the underlaying file descriptor needs to read or write data!*/
+ if (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ) {
+ pThis->rtryCall = gtlsRtry_recv;
+ dbgprintf("GnuTLS receive requires a retry, this most probably is OK and no error condition\n");
+ ABORT_FINALIZE(RS_RET_RETRY);
+ } else {
+ uchar *pErr = gtlsStrerror(lenRcvd);
+ LogError(0, RS_RET_GNUTLS_ERR, "GnuTLS receive error %zd has wrong read direction(wants write) "
+ "- this could be caused by a broken connection. GnuTLS reports: %s\n",
+ lenRcvd, pErr);
+ free(pErr);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ } else {
+ int gnuRet = lenRcvd;
+ ABORTgnutls;
+ }
+
+finalize_it:
+ dbgprintf("gtlsRecordRecv return. nsd %p, iRet %d, lenRcvd %d, lenRcvBuf %d, ptrRcvBuf %d\n",
+ pThis, iRet, (int) lenRcvd, pThis->lenRcvBuf, pThis->ptrRcvBuf);
+ RETiRet;
+}
+
+
+/* add our own certificate to the certificate set, so that the peer
+ * can identify us. Please note that we try to use mutual authentication,
+ * so we always add a cert, even if we are in the client role (later,
+ * this may be controlled by a config setting).
+ * rgerhards, 2008-05-15
+ */
+static rsRetVal
+gtlsAddOurCert(nsd_gtls_t *const pThis)
+{
+ int gnuRet = 0;
+ const uchar *keyFile;
+ const uchar *certFile;
+ uchar *pGnuErr; /* for GnuTLS error reporting */
+ DEFiRet;
+
+ certFile = (pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile;
+ keyFile = (pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile;
+ dbgprintf("GTLS certificate file: '%s'\n", certFile);
+ dbgprintf("GTLS key file: '%s'\n", keyFile);
+ if(certFile == NULL) {
+ LogMsg(0, RS_RET_CERT_MISSING, LOG_WARNING, "warning: certificate file is not set");
+ }
+ if(keyFile == NULL) {
+ LogMsg(0, RS_RET_CERTKEY_MISSING, LOG_WARNING, "warning: key file is not set");
+ }
+
+ /* set certificate in gnutls */
+ if(certFile != NULL && keyFile != NULL) {
+ CHKgnutls(gnutls_certificate_set_x509_key_file(pThis->xcred, (char*)certFile, (char*)keyFile,
+ GNUTLS_X509_FMT_PEM));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK && iRet != RS_RET_CERT_MISSING && iRet != RS_RET_CERTKEY_MISSING) {
+ pGnuErr = gtlsStrerror(gnuRet);
+ errno = 0;
+ LogError(0, iRet, "error adding our certificate. GnuTLS error %d, message: '%s', "
+ "key: '%s', cert: '%s'", gnuRet, pGnuErr, keyFile, certFile);
+ free(pGnuErr);
+ }
+ RETiRet;
+}
+
+/*
+* removecomment ifdef out if needed
+*/
+#ifdef false
+
+static void print_cipher_suite_list(const char *priorities)
+{
+ size_t i;
+ int ret;
+ unsigned int idx;
+ const char *name;
+ const char *err;
+ unsigned char id[2];
+ gnutls_protocol_t version;
+ gnutls_priority_t pcache;
+
+ if (priorities != NULL) {
+ printf("print_cipher_suite_list: Cipher suites for %s\n", priorities);
+
+ ret = gnutls_priority_init(&pcache, priorities, &err);
+ if (ret < 0) {
+ fprintf(stderr, "print_cipher_suite_list: Syntax error at: %s\n", err);
+ exit(1);
+ }
+
+ for (i = 0;; i++) {
+ ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ break;
+ if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE)
+ continue;
+
+ name = gnutls_cipher_suite_info(idx, id, NULL, NULL, NULL, &version);
+
+ if (name != NULL)
+ dbgprintf("print_cipher_suite_list: %-50s\t0x%02x, 0x%02x\t%s\n",
+ name, (unsigned char) id[0],
+ (unsigned char) id[1],
+ gnutls_protocol_get_name(version));
+ }
+
+ return;
+ }
+}
+#endif
+
+/* initialize GnuTLS credential structure (certs etc) */
+static rsRetVal
+gtlsInitCred(nsd_gtls_t *const pThis )
+{
+ int gnuRet;
+ const uchar *cafile, *crlfile;
+ DEFiRet;
+
+ /* X509 stuff */
+ if (pThis->xcred == NULL) {
+ /* Allocate only ONCE */
+ CHKgnutls(gnutls_certificate_allocate_credentials(&pThis->xcred));
+ }
+
+ /* sets the trusted cas file */
+ cafile = (pThis->pszCAFile == NULL) ? glbl.GetDfltNetstrmDrvrCAF(runConf) : pThis->pszCAFile;
+ if(cafile == NULL) {
+ LogMsg(0, RS_RET_CA_CERT_MISSING, LOG_WARNING,
+ "Warning: CA certificate is not set");
+ } else {
+ dbgprintf("GTLS CA file: '%s'\n", cafile);
+ gnuRet = gnutls_certificate_set_x509_trust_file(pThis->xcred, (char*)cafile, GNUTLS_X509_FMT_PEM);
+ if(gnuRet == GNUTLS_E_FILE_ERROR) {
+ LogError(0, RS_RET_GNUTLS_ERR,
+ "error reading certificate file '%s' - a common cause is that the "
+ "file does not exist", cafile);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ } else if(gnuRet < 0) {
+ /* TODO; a more generic error-tracking function (this one based on CHKgnutls()) */
+ uchar *pErr = gtlsStrerror(gnuRet);
+ LogError(0, RS_RET_GNUTLS_ERR,
+ "unexpected GnuTLS error reading CA certificate file %d in %s:%d: %s\n",
+ gnuRet, __FILE__, __LINE__, pErr);
+ free(pErr);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ }
+
+ crlfile = (pThis->pszCRLFile == NULL) ? glbl.GetDfltNetstrmDrvrCRLF(runConf) : pThis->pszCRLFile;
+ if(crlfile == NULL) {
+ dbgprintf("Certificate revocation list (CRL) file not set.");
+ } else {
+ dbgprintf("GTLS CRL file: '%s'\n", crlfile);
+ gnuRet = gnutls_certificate_set_x509_crl_file(pThis->xcred, (char*)crlfile, GNUTLS_X509_FMT_PEM);
+ if(gnuRet == GNUTLS_E_FILE_ERROR) {
+ LogError(0, RS_RET_GNUTLS_ERR,
+ "error reading Certificate revocation list (CRL) '%s' - a common cause is that the "
+ "file does not exist", crlfile);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ } else if(gnuRet < 0) {
+ /* TODO; a more generic error-tracking function (this one based on CHKgnutls()) */
+ uchar *pErr = gtlsStrerror(gnuRet);
+ LogError(0, RS_RET_GNUTLS_ERR,
+ "unexpected GnuTLS error reading Certificate revocation list (CRL) %d in %s:%d: %s\n",
+ gnuRet, __FILE__, __LINE__, pErr);
+ free(pErr);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* globally initialize GnuTLS */
+static rsRetVal
+gtlsGlblInit(void)
+{
+ int gnuRet;
+ DEFiRet;
+
+ dbgprintf("gtlsGlblInit: Running Version: '%#010x'\n", GNUTLS_VERSION_NUMBER);
+
+ /* gcry_control must be called first, so that the thread system is correctly set up */
+ #if GNUTLS_VERSION_NUMBER <= 0x020b00
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ #endif
+ CHKgnutls(gnutls_global_init());
+
+ if(GetGnuTLSLoglevel(runConf) > 0){
+ gnutls_global_set_log_function(logFunction);
+ gnutls_global_set_log_level(GetGnuTLSLoglevel(runConf));
+ /* 0 (no) to 9 (most), 10 everything */
+ }
+
+ /* Init Anon cipher helpers */
+ CHKgnutls(gnutls_dh_params_init(&dh_params));
+ CHKgnutls(gnutls_dh_params_generate2(dh_params, dhBits));
+
+ /* Allocate ANON Client Cred */
+ CHKgnutls(gnutls_anon_allocate_client_credentials(&anoncred));
+
+ /* Allocate ANON Server Cred */
+ CHKgnutls(gnutls_anon_allocate_server_credentials(&anoncredSrv));
+ gnutls_anon_set_server_dh_params(anoncredSrv, dh_params);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+gtlsInitSession(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+ int gnuRet = 0;
+ gnutls_session_t session;
+
+ gnutls_init(&session, GNUTLS_SERVER);
+ pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 0;
+ pThis->sess = session;
+
+ /* Moved CertKey Loading to top */
+# if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
+ /* store a pointer to ourselfs (needed by callback) */
+ gnutls_session_set_ptr(pThis->sess, (void*)pThis);
+ iRet = gtlsLoadOurCertKey(pThis); /* first load .pem files */
+ if(iRet == RS_RET_OK) {
+ dbgprintf("gtlsInitSession: enable certificate checking (VerifyDepth=%d)\n", pThis->DrvrVerifyDepth);
+ gnutls_certificate_set_retrieve_function(pThis->xcred, gtlsClientCertCallback);
+ if (pThis->DrvrVerifyDepth != 0){
+ gnutls_certificate_set_verify_limits(pThis->xcred, 8200, pThis->DrvrVerifyDepth);
+ }
+ } else if(iRet == RS_RET_CERTLESS) {
+ dbgprintf("gtlsInitSession: certificates not configured, not loaded.\n");
+ } else {
+ ABORT_FINALIZE(iRet); /* we have an error case! */
+ }
+# endif
+
+ /* avoid calling all the priority functions, since the defaults are adequate. */
+ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_CERTIFICATE, pThis->xcred));
+
+ /* check for anon authmode */
+ if (pThis->authMode == GTLS_AUTH_CERTANON) {
+ dbgprintf("gtlsInitSession: anon authmode, gnutls_credentials_set GNUTLS_CRD_ANON\n");
+ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_ANON, anoncredSrv));
+ gnutls_dh_set_prime_bits(pThis->sess, dhMinBits);
+ }
+
+ /* request client certificate if any. */
+ gnutls_certificate_server_set_request( pThis->sess, GNUTLS_CERT_REQUEST);
+
+
+finalize_it:
+ if(iRet != RS_RET_OK && iRet != RS_RET_CERTLESS) {
+ LogError(0, iRet, "gtlsInitSession failed to INIT Session %d", gnuRet);
+ }
+
+ RETiRet;
+}
+
+
+/* Obtain the CN from the DN field and hand it back to the caller
+ * (which is responsible for destructing it). We try to follow
+ * RFC2253 as far as it makes sense for our use-case. This function
+ * is considered a compromise providing good-enough correctness while
+ * limiting code size and complexity. If a problem occurs, we may enhance
+ * this function. A (pointer to a) certificate must be caller-provided.
+ * If no CN is contained in the cert, no string is returned
+ * (*ppstrCN remains NULL). *ppstrCN MUST be NULL on entry!
+ * rgerhards, 2008-05-22
+ */
+static rsRetVal
+gtlsGetCN(gnutls_x509_crt_t *pCert, cstr_t **ppstrCN)
+{
+ DEFiRet;
+ int gnuRet;
+ int i;
+ int bFound;
+ cstr_t *pstrCN = NULL;
+ size_t size;
+ /* big var the last, so we hope to have all we usually neeed within one mem cache line */
+ uchar szDN[1024]; /* this should really be large enough for any non-malicious case... */
+
+ assert(pCert != NULL);
+ assert(ppstrCN != NULL);
+ assert(*ppstrCN == NULL);
+
+ size = sizeof(szDN);
+ CHKgnutls(gnutls_x509_crt_get_dn(*pCert, (char*)szDN, &size));
+
+ /* now search for the CN part */
+ i = 0;
+ bFound = 0;
+ while(!bFound && szDN[i] != '\0') {
+ /* note that we do not overrun our string due to boolean shortcut
+ * operations. If we have '\0', the if does not match and evaluation
+ * stops. Order of checks is obviously important!
+ */
+ if(szDN[i] == 'C' && szDN[i+1] == 'N' && szDN[i+2] == '=') {
+ bFound = 1;
+ i += 2;
+ }
+ i++;
+
+ }
+
+ if(!bFound) {
+ FINALIZE; /* we are done */
+ }
+
+ /* we found a common name, now extract it */
+ CHKiRet(cstrConstruct(&pstrCN));
+ while(szDN[i] != '\0' && szDN[i] != ',') {
+ if(szDN[i] == '\\') {
+ /* hex escapes are not implemented */
+ ++i; /* escape char processed */
+ if(szDN[i] == '\0')
+ ABORT_FINALIZE(RS_RET_CERT_INVALID_DN);
+ CHKiRet(cstrAppendChar(pstrCN, szDN[i]));
+ } else {
+ CHKiRet(cstrAppendChar(pstrCN, szDN[i]));
+ }
+ ++i; /* char processed */
+ }
+ cstrFinalize(pstrCN);
+
+ /* we got it - we ignore the rest of the DN string (if any). So we may
+ * not detect if it contains more than one CN
+ */
+
+ *ppstrCN = pstrCN;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pstrCN != NULL)
+ cstrDestruct(&pstrCN);
+ }
+
+ RETiRet;
+}
+
+
+/* Check the peer's ID in fingerprint auth mode.
+ * rgerhards, 2008-05-22
+ */
+static rsRetVal
+gtlsChkPeerFingerprint(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert)
+{
+ uchar fingerprint[20];
+ uchar fingerprintSha256[32];
+ size_t size;
+ size_t sizeSha256;
+ cstr_t *pstrFingerprint = NULL;
+ cstr_t *pstrFingerprintSha256 = NULL;
+ int bFoundPositiveMatch;
+ permittedPeers_t *pPeer;
+ int gnuRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ /* obtain the SHA1 fingerprint */
+ size = sizeof(fingerprint);
+ sizeSha256 = sizeof(fingerprintSha256);
+ CHKgnutls(gnutls_x509_crt_get_fingerprint(*pCert, GNUTLS_DIG_SHA1, fingerprint, &size));
+ CHKgnutls(gnutls_x509_crt_get_fingerprint(*pCert, GNUTLS_DIG_SHA256, fingerprintSha256, &sizeSha256));
+ CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint, "SHA1"));
+ CHKiRet(GenFingerprintStr(fingerprintSha256, sizeSha256, &pstrFingerprintSha256, "SHA256"));
+ dbgprintf("peer's certificate SHA1 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprint));
+ dbgprintf("peer's certificate SHA256 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprintSha256));
+
+
+ /* now search through the permitted peers to see if we can find a permitted one */
+ bFoundPositiveMatch = 0;
+ pPeer = pThis->pPermPeers;
+ while(pPeer != NULL && !bFoundPositiveMatch) {
+ if(!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char*) pPeer->pszID))) {
+ dbgprintf("gtlsChkPeerFingerprint: peer's certificate SHA1 MATCH found: %s\n", pPeer->pszID);
+ bFoundPositiveMatch = 1;
+ } else if(!rsCStrSzStrCmp(pstrFingerprintSha256 , pPeer->pszID, strlen((char*) pPeer->pszID))) {
+ dbgprintf("gtlsChkPeerFingerprint: peer's certificate SHA256 MATCH found: %s\n", pPeer->pszID);
+ bFoundPositiveMatch = 1;
+ }
+ else {
+ pPeer = pPeer->pNext;
+ }
+ }
+
+ if(!bFoundPositiveMatch) {
+ dbgprintf("invalid peer fingerprint, not permitted to talk to it\n");
+ if(pThis->bReportAuthErr == 1) {
+ errno = 0;
+ LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer fingerprint '%s' unknown - we are "
+ "not permitted to talk to it", cstrGetSzStrNoNULL(pstrFingerprint));
+ pThis->bReportAuthErr = 0;
+ }
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
+
+finalize_it:
+ if(pstrFingerprint != NULL)
+ cstrDestruct(&pstrFingerprint);
+ RETiRet;
+}
+
+
+/* Perform a match on ONE peer name obtained from the certificate. This name
+ * is checked against the set of configured credentials. *pbFoundPositiveMatch is
+ * set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized
+ * to 0 by the caller (this is a performance enhancement as we expect to be
+ * called multiple times).
+ * TODO: implemet wildcards?
+ * rgerhards, 2008-05-26
+ */
+static rsRetVal
+gtlsChkOnePeerName(nsd_gtls_t *pThis, uchar *pszPeerID, int *pbFoundPositiveMatch)
+{
+ permittedPeers_t *pPeer;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ assert(pszPeerID != NULL);
+ assert(pbFoundPositiveMatch != NULL);
+
+ if(pThis->pPermPeers) { /* do we have configured peer IDs? */
+ pPeer = pThis->pPermPeers;
+ while(pPeer != NULL) {
+ CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch));
+ if(*pbFoundPositiveMatch)
+ break;
+ pPeer = pPeer->pNext;
+ }
+ } else {
+ /* we do not have configured peer IDs, so we use defaults */
+ if( pThis->pszConnectHost
+ && !strcmp((char*)pszPeerID, (char*)pThis->pszConnectHost)) {
+ *pbFoundPositiveMatch = 1;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Check the peer's ID in name auth mode.
+ * rgerhards, 2008-05-22
+ */
+static rsRetVal
+gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert)
+{
+ uchar lnBuf[256];
+ char szAltName[1024]; /* this is sufficient for the DNSNAME... */
+ int iAltName;
+ size_t szAltNameLen;
+ int bFoundPositiveMatch;
+ int bHaveSAN = 0;
+ cstr_t *pStr = NULL;
+ cstr_t *pstrCN = NULL;
+ int gnuRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ bFoundPositiveMatch = 0;
+ CHKiRet(rsCStrConstruct(&pStr));
+
+ /* first search through the dNSName subject alt names */
+ iAltName = 0;
+ while(!bFoundPositiveMatch) { /* loop broken below */
+ szAltNameLen = sizeof(szAltName);
+ gnuRet = gnutls_x509_crt_get_subject_alt_name(*pCert, iAltName,
+ szAltName, &szAltNameLen, NULL);
+ if(gnuRet < 0)
+ break;
+ else if(gnuRet == GNUTLS_SAN_DNSNAME) {
+ bHaveSAN = 1;
+ dbgprintf("subject alt dnsName: '%s'\n", szAltName);
+ snprintf((char*)lnBuf, sizeof(lnBuf), "DNSname: %s; ", szAltName);
+ CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(gtlsChkOnePeerName(pThis, (uchar*)szAltName, &bFoundPositiveMatch));
+ /* do NOT break, because there may be multiple dNSName's! */
+ }
+ ++iAltName;
+ }
+
+ /* Check also CN only if not configured per stricter RFC 6125 or no SAN present*/
+ if(!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) {
+ CHKiRet(gtlsGetCN(pCert, &pstrCN));
+ if(pstrCN != NULL) { /* NULL if there was no CN present */
+ dbgprintf("gtls now checking auth for CN '%s'\n", cstrGetSzStrNoNULL(pstrCN));
+ snprintf((char*)lnBuf, sizeof(lnBuf), "CN: %s; ", cstrGetSzStrNoNULL(pstrCN));
+ CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(gtlsChkOnePeerName(pThis, cstrGetSzStrNoNULL(pstrCN), &bFoundPositiveMatch));
+ }
+ }
+
+ if(!bFoundPositiveMatch) {
+ dbgprintf("invalid peer name, not permitted to talk to it\n");
+ if(pThis->bReportAuthErr == 1) {
+ cstrFinalize(pStr);
+ errno = 0;
+ LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer name not authorized - "
+ "not permitted to talk to it. Names: %s",
+ cstrGetSzStrNoNULL(pStr));
+ pThis->bReportAuthErr = 0;
+ }
+ ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+ }
+
+finalize_it:
+ if(pStr != NULL)
+ rsCStrDestruct(&pStr);
+ if(pstrCN != NULL)
+ rsCStrDestruct(&pstrCN);
+ RETiRet;
+}
+
+
+/* check the ID of the remote peer - used for both fingerprint and
+ * name authentication. This is common code. Will call into specific
+ * drivers once the certificate has been obtained.
+ * rgerhards, 2008-05-08
+ */
+static rsRetVal
+gtlsChkPeerID(nsd_gtls_t *pThis)
+{
+ const gnutls_datum_t *cert_list;
+ unsigned int list_size = 0;
+ gnutls_x509_crt_t cert;
+ int bMustDeinitCert = 0;
+ int gnuRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ /* This function only works for X.509 certificates. */
+ if(gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509)
+ return RS_RET_TLS_CERT_ERR;
+
+ cert_list = gnutls_certificate_get_peers(pThis->sess, &list_size);
+
+ if(list_size < 1) {
+ if(pThis->bReportAuthErr == 1) {
+ uchar *fromHost = NULL;
+ errno = 0;
+ pThis->bReportAuthErr = 0;
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost);
+ LogError(0, RS_RET_TLS_NO_CERT, "error: peer %s did not provide a certificate, "
+ "not permitted to talk to it", fromHost);
+ free(fromHost);
+ }
+ ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+ }
+
+ /* If we reach this point, we have at least one valid certificate.
+ * We always use only the first certificate. As of GnuTLS documentation, the
+ * first certificate always contains the remote peer's own certificate. All other
+ * certificates are issuer's certificates (up the chain). We are only interested
+ * in the first certificate, which is our peer. -- rgerhards, 2008-05-08
+ */
+ CHKgnutls(gnutls_x509_crt_init(&cert));
+ bMustDeinitCert = 1; /* indicate cert is initialized and must be freed on exit */
+ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
+
+ /* Now we see which actual authentication code we must call. */
+ if(pThis->authMode == GTLS_AUTH_CERTFINGERPRINT) {
+ CHKiRet(gtlsChkPeerFingerprint(pThis, &cert));
+ } else {
+ assert(pThis->authMode == GTLS_AUTH_CERTNAME);
+ CHKiRet(gtlsChkPeerName(pThis, &cert));
+ }
+
+finalize_it:
+ if(bMustDeinitCert)
+ gnutls_x509_crt_deinit(cert);
+
+ RETiRet;
+}
+
+
+/* Verify the validity of the remote peer's certificate.
+ * rgerhards, 2008-05-21
+ */
+static rsRetVal
+gtlsChkPeerCertValidity(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+ const char *pszErrCause;
+ int gnuRet;
+ cstr_t *pStr = NULL;
+ unsigned stateCert;
+ const gnutls_datum_t *cert_list;
+ unsigned cert_list_size = 0;
+ gnutls_x509_crt_t cert;
+ unsigned i;
+ time_t ttCert;
+ time_t ttNow;
+ sbool bAbort = RSFALSE;
+ int iAbortCode = RS_RET_OK;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ /* check if we have at least one cert */
+ cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size);
+ if(cert_list_size < 1) {
+ errno = 0;
+ uchar *fromHost = NULL;
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost);
+ LogError(0, RS_RET_TLS_NO_CERT,
+ "peer %s did not provide a certificate, not permitted to talk to it",
+ fromHost);
+ free(fromHost);
+ ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+ }
+#ifdef EXTENDED_CERT_CHECK_AVAILABLE
+ if (pThis->dataTypeCheck == GTLS_NONE) {
+#endif
+ CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert));
+#ifdef EXTENDED_CERT_CHECK_AVAILABLE
+ } else { /* we have configured data to check in addition to cert */
+ gnutls_typed_vdata_st data;
+ data.type = GNUTLS_DT_KEY_PURPOSE_OID;
+ if (pThis->bIsInitiator) { /* client mode */
+ data.data = (uchar *)GNUTLS_KP_TLS_WWW_SERVER;
+ } else { /* server mode */
+ data.data = (uchar *)GNUTLS_KP_TLS_WWW_CLIENT;
+ }
+ data.size = ustrlen(data.data);
+ CHKgnutls(gnutls_certificate_verify_peers(pThis->sess, &data, 1, &stateCert));
+ }
+#endif
+
+ if(stateCert & GNUTLS_CERT_INVALID) {
+ /* Default abort code */
+ iAbortCode = RS_RET_CERT_INVALID;
+
+ /* provide error details if we have them */
+ if (stateCert & GNUTLS_CERT_EXPIRED ) {
+ dbgprintf("GnuTLS returned GNUTLS_CERT_EXPIRED, handling mode %d ...\n",
+ pThis->permitExpiredCerts);
+ /* Handle expired certs */
+ if (pThis->permitExpiredCerts == GTLS_EXPIRED_DENY) {
+ bAbort = RSTRUE;
+ iAbortCode = RS_RET_CERT_EXPIRED;
+ } else if (pThis->permitExpiredCerts == GTLS_EXPIRED_WARN) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "Warning, certificate expired but expired certs are permitted");
+ } else {
+ dbgprintf("GnuTLS returned GNUTLS_CERT_EXPIRED, but expired certs are permitted.\n");
+ }
+ pszErrCause = "certificate expired";
+ } else if(stateCert & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+ pszErrCause = "signer not found";
+ bAbort = RSTRUE;
+ } else if(stateCert & GNUTLS_CERT_SIGNER_NOT_CA) {
+ pszErrCause = "signer is not a CA";
+ bAbort = RSTRUE;
+ } else if(stateCert & GNUTLS_CERT_INSECURE_ALGORITHM) {
+ pszErrCause = "insecure algorithm";
+ bAbort = RSTRUE;
+ } else if(stateCert & GNUTLS_CERT_REVOKED) {
+ pszErrCause = "certificate revoked";
+ bAbort = RSTRUE;
+ iAbortCode = RS_RET_CERT_REVOKED;
+#ifdef EXTENDED_CERT_CHECK_AVAILABLE
+ } else if(stateCert & GNUTLS_CERT_PURPOSE_MISMATCH) {
+ pszErrCause = "key purpose OID does not match";
+ bAbort = RSTRUE;
+#endif
+ } else {
+ pszErrCause = "GnuTLS returned no specific reason";
+ dbgprintf("GnuTLS returned no specific reason for GNUTLS_CERT_INVALID, certificate "
+ "status is %d\n", stateCert);
+ bAbort = RSTRUE;
+ }
+ }
+
+ if (bAbort == RSTRUE) {
+ uchar *fromHost = NULL;
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost);
+ LogError(0, NO_ERRCODE, "not permitted to talk to peer '%s', certificate invalid: %s",
+ fromHost, pszErrCause);
+ free(fromHost);
+ gtlsGetCertInfo(pThis, &pStr);
+ LogError(0, NO_ERRCODE, "invalid cert info: %s", cstrGetSzStrNoNULL(pStr));
+ cstrDestruct(&pStr);
+ ABORT_FINALIZE(iAbortCode);
+ }
+
+ /* get current time for certificate validation */
+ if(datetime.GetTime(&ttNow) == -1)
+ ABORT_FINALIZE(RS_RET_SYS_ERR);
+
+ /* as it looks, we need to validate the expiration dates ourselves...
+ * We need to loop through all certificates as we need to make sure the
+ * interim certificates are also not expired.
+ */
+ for(i = 0 ; i < cert_list_size ; ++i) {
+ CHKgnutls(gnutls_x509_crt_init(&cert));
+ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER));
+ ttCert = gnutls_x509_crt_get_activation_time(cert);
+ if(ttCert == -1)
+ ABORT_FINALIZE(RS_RET_TLS_CERT_ERR);
+ else if(ttCert > ttNow) {
+ uchar *fromHost = NULL;
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost);
+ LogError(0, RS_RET_CERT_NOT_YET_ACTIVE, "not permitted to talk to peer '%s': "
+ "certificate %d not yet active", fromHost, i);
+ free(fromHost);
+ gtlsGetCertInfo(pThis, &pStr);
+ LogError(0, RS_RET_CERT_NOT_YET_ACTIVE,
+ "invalid cert info: %s", cstrGetSzStrNoNULL(pStr));
+ cstrDestruct(&pStr);
+ ABORT_FINALIZE(RS_RET_CERT_NOT_YET_ACTIVE);
+ }
+
+ gnutls_x509_crt_deinit(cert);
+
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check if it is OK to talk to the remote peer
+ * rgerhards, 2008-05-21
+ */
+rsRetVal
+gtlsChkPeerAuth(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ /* call the actual function based on current auth mode */
+ switch(pThis->authMode) {
+ case GTLS_AUTH_CERTNAME:
+ /* if we check the name, we must ensure the cert is valid */
+ CHKiRet(gtlsChkPeerCertValidity(pThis));
+ CHKiRet(gtlsChkPeerID(pThis));
+ break;
+ case GTLS_AUTH_CERTFINGERPRINT:
+ CHKiRet(gtlsChkPeerID(pThis));
+ break;
+ case GTLS_AUTH_CERTVALID:
+ CHKiRet(gtlsChkPeerCertValidity(pThis));
+ break;
+ case GTLS_AUTH_CERTANON:
+ FINALIZE;
+ break;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* globally de-initialize GnuTLS */
+static rsRetVal
+gtlsGlblExit(void)
+{
+ DEFiRet;
+ gnutls_anon_free_server_credentials(anoncredSrv);
+ gnutls_dh_params_deinit(dh_params);
+ gnutls_global_deinit();
+ RETiRet;
+}
+
+
+/* end a GnuTLS session
+ * The function checks if we have a session and ends it only if so. So it can
+ * always be called, even if there currently is no session.
+ */
+static rsRetVal
+gtlsEndSess(nsd_gtls_t *pThis)
+{
+ int gnuRet;
+ DEFiRet;
+
+ if(pThis->bHaveSess) {
+ if(pThis->bIsInitiator) {
+ gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_WR);
+ while(gnuRet == GNUTLS_E_INTERRUPTED || gnuRet == GNUTLS_E_AGAIN) {
+ gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_WR);
+ }
+ }
+ gnutls_deinit(pThis->sess);
+ pThis->bHaveSess = 0;
+ }
+ RETiRet;
+}
+
+
+/* a small wrapper for gnutls_transport_set_ptr(). The main intension for
+ * creating this wrapper is to get the annoying "cast to pointer from different
+ * size" compiler warning just once. There seems to be no way around it, see:
+ * http://lists.gnu.org/archive/html/help-gnutls/2008-05/msg00000.html
+ * rgerhards, 2008.05-07
+ */
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+static inline void
+gtlsSetTransportPtr(nsd_gtls_t *pThis, int sock)
+{
+ /* Note: the compiler warning for the next line is OK - see header comment! */
+ gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr_t) sock);
+}
+#pragma GCC diagnostic warning "-Wint-to-pointer-cast"
+
+/* ---------------------------- end GnuTLS specifics ---------------------------- */
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */
+ iRet = nsd_ptcp.Construct(&pThis->pTcp);
+ pThis->bReportAuthErr = 1;
+ENDobjConstruct(nsd_gtls)
+
+
+/* destructor for the nsd_gtls object */
+PROTOTYPEobjDestruct(nsd_gtls);
+BEGINobjDestruct(nsd_gtls) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsd_gtls)
+ if(pThis->iMode == 1) {
+ gtlsEndSess(pThis);
+ }
+
+ if(pThis->pTcp != NULL) {
+ nsd_ptcp.Destruct(&pThis->pTcp);
+ }
+
+ free(pThis->pszConnectHost);
+ free(pThis->pszRcvBuf);
+ free((void*) pThis->pszCAFile);
+ free((void*) pThis->pszCRLFile);
+
+ if(pThis->bOurCertIsInit)
+ for(unsigned i=0; i<pThis->nOurCerts; ++i) {
+ gnutls_x509_crt_deinit(pThis->pOurCerts[i]);
+ }
+ if(pThis->bOurKeyIsInit)
+ gnutls_x509_privkey_deinit(pThis->ourKey);
+ if(pThis->bHaveSess)
+ gnutls_deinit(pThis->sess);
+ if(pThis->xcred != NULL
+ && (pThis->bIsInitiator || (!pThis->xcred_is_copy && (!pThis->bIsInitiator || pThis->bHaveSess)))
+ ) {
+ gnutls_certificate_free_credentials(pThis->xcred);
+ free((void*) pThis->pszKeyFile);
+ free((void*) pThis->pszCertFile);
+ }
+ENDobjDestruct(nsd_gtls)
+
+
+/* Set the driver mode. For us, this has the following meaning:
+ * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS)
+ * 1 - work in TLS mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t *const pNsd, const int mode)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ dbgprintf("(tls) mode: %d\n", mode);
+ if(mode != 0 && mode != 1) {
+ LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by "
+ "gtls netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE);
+ }
+
+ pThis->iMode = mode;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Set the authentication mode. For us, the following is supported:
+ * anon - no certificate checks whatsoever (discouraged, but supported)
+ * x509/certvalid - (just) check certificate validity
+ * x509/fingerprint - certificate fingerprint
+ * x509/name - cerfificate name check
+ * mode == NULL is valid and defaults to x509/name
+ * rgerhards, 2008-05-16
+ */
+static rsRetVal
+SetAuthMode(nsd_t *pNsd, uchar *mode)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(mode == NULL || !strcasecmp((char*)mode, "x509/name")) {
+ pThis->authMode = GTLS_AUTH_CERTNAME;
+ } else if(!strcasecmp((char*) mode, "x509/fingerprint")) {
+ pThis->authMode = GTLS_AUTH_CERTFINGERPRINT;
+ } else if(!strcasecmp((char*) mode, "x509/certvalid")) {
+ pThis->authMode = GTLS_AUTH_CERTVALID;
+ } else if(!strcasecmp((char*) mode, "anon")) {
+ pThis->authMode = GTLS_AUTH_CERTANON;
+ } else {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by "
+ "gtls netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ dbgprintf("SetAuthMode to %s\n", (mode != NULL ? (char*)mode : "NULL"));
+/* TODO: clear stored IDs! */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the PermitExpiredCerts mode. For us, the following is supported:
+ * on - fail if certificate is expired
+ * off - ignore expired certificates
+ * warn - warn if certificate is expired
+ * alorbach, 2018-12-20
+ */
+static rsRetVal
+SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ /* default is set to off! */
+ if(mode == NULL || !strcasecmp((char*)mode, "off")) {
+ pThis->permitExpiredCerts = GTLS_EXPIRED_DENY;
+ } else if(!strcasecmp((char*) mode, "warn")) {
+ pThis->permitExpiredCerts = GTLS_EXPIRED_WARN;
+ } else if(!strcasecmp((char*) mode, "on")) {
+ pThis->permitExpiredCerts = GTLS_EXPIRED_PERMIT;
+ } else {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by "
+ "gtls netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ dbgprintf("SetPermitExpiredCerts: Set Mode %s/%d\n",
+ (mode != NULL ? (char*)mode : "NULL"), pThis->permitExpiredCerts);
+
+/* TODO: clear stored IDs! */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set permitted peers. It is depending on the auth mode if this are
+ * fingerprints or names. -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(pPermPeers == NULL)
+ FINALIZE;
+
+ if(pThis->authMode != GTLS_AUTH_CERTFINGERPRINT && pThis->authMode != GTLS_AUTH_CERTNAME) {
+ LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by "
+ "gtls netstream driver in the configured authentication mode - ignored");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE);
+ }
+
+ pThis->pPermPeers = pPermPeers;
+
+finalize_it:
+ RETiRet;
+}
+
+/* gnutls priority string
+ * PascalWithopf 2017-08-16
+ */
+static rsRetVal
+SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ pThis->gnutlsPriorityString = gnutlsPriorityString;
+ dbgprintf("gnutlsPriorityString: set to '%s'\n",
+ (gnutlsPriorityString != NULL ? (char*)gnutlsPriorityString : "NULL"));
+ RETiRet;
+}
+
+/* Set the driver cert extended key usage check setting
+ * 0 - ignore contents of extended key usage
+ * 1 - verify that cert contents is compatible with appropriate OID
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetCheckExtendedKeyUsage(nsd_t *pNsd, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(ChkExtendedKeyUsage != 0 && ChkExtendedKeyUsage != 1) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
+ "not supported by gtls netstream driver", ChkExtendedKeyUsage);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ pThis->dataTypeCheck = ChkExtendedKeyUsage;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver name checking strictness
+ * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good
+ * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored)
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(prioritizeSan != 0 && prioritizeSan != 1) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
+ "not supported by gtls netstream driver", prioritizeSan);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ pThis->bSANpriority = prioritizeSan;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver tls verifyDepth
+ * alorbach, 2019-12-20
+ */
+static rsRetVal
+SetTlsVerifyDepth(nsd_t *pNsd, int verifyDepth)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if (verifyDepth == 0) {
+ FINALIZE;
+ }
+ assert(verifyDepth >= 2);
+ pThis->DrvrVerifyDepth = verifyDepth;
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCAFile(nsd_t *pNsd, const uchar *const caFile)
+{
+ DEFiRet;
+ nsd_gtls_t *const pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(caFile == NULL) {
+ pThis->pszCAFile = NULL;
+ } else {
+ CHKmalloc(pThis->pszCAFile = (const uchar*) strdup((const char*) caFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCRLFile(nsd_t *pNsd, const uchar *const crlFile)
+{
+ DEFiRet;
+ nsd_gtls_t *const pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(crlFile == NULL) {
+ pThis->pszCRLFile = NULL;
+ } else {
+ CHKmalloc(pThis->pszCRLFile = (const uchar*) strdup((const char*) crlFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ nsd_gtls_t *const pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(pszFile == NULL) {
+ pThis->pszKeyFile = NULL;
+ } else {
+ CHKmalloc(pThis->pszKeyFile = (const uchar*) strdup((const char*) pszFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCertFile(nsd_t *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ nsd_gtls_t *const pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(pszFile == NULL) {
+ pThis->pszCertFile = NULL;
+ } else {
+ CHKmalloc(pThis->pszCertFile = (const uchar*) strdup((const char*) pszFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality. -- rgerhards, 2008-04-18
+ */
+static rsRetVal
+SetSock(nsd_t *pNsd, int sock)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ assert(sock >= 0);
+
+ nsd_ptcp.SetSock(pThis->pTcp, sock);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ assert(keepAliveIntvl >= 0);
+
+ nsd_ptcp.SetKeepAliveIntvl(pThis->pTcp, keepAliveIntvl);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ assert(keepAliveProbes >= 0);
+
+ nsd_ptcp.SetKeepAliveProbes(pThis->pTcp, keepAliveProbes);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ assert(keepAliveTime >= 0);
+
+ nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime);
+
+ RETiRet;
+}
+
+
+/* abort a connection. This is meant to be called immediately
+ * before the Destruct call. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+Abort(nsd_t *pNsd)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+
+ if(pThis->iMode == 0) {
+ nsd_ptcp.Abort(pThis->pTcp);
+ }
+
+ RETiRet;
+}
+
+
+/* Callback after netstrm obj init in nsd_ptcp - permits us to add some data */
+static rsRetVal
+LstnInitDrvr(netstrm_t *const pThis)
+{
+ DEFiRet;
+ CHKiRet(gtlsInitCred((nsd_gtls_t*) pThis->pDrvrData));
+ CHKiRet(gtlsAddOurCert((nsd_gtls_t*) pThis->pDrvrData));
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* initialize the tcp socket for a listner
+ * Here, we use the ptcp driver - because there is nothing special
+ * at this point with GnuTLS. Things become special once we accept
+ * a session, but not during listener setup.
+ * gerhards, 2008-04-25
+ */
+static rsRetVal ATTR_NONNULL(1,3,5)
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params)
+{
+ DEFiRet;
+ pNS->fLstnInitDrvr = LstnInitDrvr;
+ iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params);
+//finalize_it:
+ RETiRet;
+}
+
+
+/* This function checks if the connection is still alive - well, kind of...
+ * This is a dummy here. For details, check function common in ptcp driver.
+ * rgerhards, 2008-06-09
+ */
+static rsRetVal
+CheckConnection(nsd_t __attribute__((unused)) *pNsd)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ dbgprintf("CheckConnection for %p\n", pNsd);
+ return nsd_ptcp.CheckConnection(pThis->pTcp);
+}
+
+
+/* get the remote hostname. The returned hostname must be freed by the caller.
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+GetRemoteHName(nsd_t *pNsd, uchar **ppszHName)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName);
+ RETiRet;
+}
+
+
+/* Provide access to the sockaddr_storage of the remote peer. This
+ * is needed by the legacy ACL system. --- gerhards, 2008-12-01
+ */
+static rsRetVal
+GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ iRet = nsd_ptcp.GetRemAddr(pThis->pTcp, ppAddr);
+ RETiRet;
+}
+
+
+/* get the remote host's IP address. Caller must Destruct the object. */
+static rsRetVal
+GetRemoteIP(nsd_t *pNsd, prop_t **ip)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ip);
+ RETiRet;
+}
+
+
+/* accept an incoming connection request - here, we do the usual accept
+ * handling. TLS specific handling is done thereafter (and if we run in TLS
+ * mode at this time).
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+{
+ DEFiRet;
+ int gnuRet;
+ nsd_gtls_t *pNew = NULL;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ const char *error_position = NULL;
+
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ CHKiRet(nsd_gtlsConstruct(&pNew)); // TODO: prevent construct/destruct!
+ CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp));
+ CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp));
+
+ if(pThis->iMode == 0) {
+ /* we are in non-TLS mode, so we are done */
+ *ppNew = (nsd_t*) pNew;
+ FINALIZE;
+ }
+ /* copy Properties to pnew first */
+ pNew->authMode = pThis->authMode;
+ pNew->permitExpiredCerts = pThis->permitExpiredCerts;
+ pNew->pPermPeers = pThis->pPermPeers;
+ pNew->gnutlsPriorityString = pThis->gnutlsPriorityString;
+ pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth;
+ pNew->dataTypeCheck = pThis->dataTypeCheck;
+ pNew->bSANpriority = pThis->bSANpriority;
+ pNew->pszCertFile = pThis->pszCertFile;
+ pNew->pszKeyFile = pThis->pszKeyFile;
+ pNew->xcred = pThis->xcred; // TODO: verify once again; xcred is read only at this stage
+ pNew->xcred_is_copy = 1; // do not free on pNew Destruction
+
+ /* if we reach this point, we are in TLS mode */
+ iRet = gtlsInitSession(pNew);
+ if (iRet != RS_RET_OK) {
+ if (iRet == RS_RET_CERTLESS) {
+ dbgprintf("AcceptConnReq certless mode\n");
+ /* Set status to OK */
+ iRet = RS_RET_OK;
+ } else {
+ goto finalize_it;
+ }
+ }
+ gtlsSetTransportPtr(pNew, ((nsd_ptcp_t*) (pNew->pTcp))->sock);
+
+ dbgprintf("AcceptConnReq bOurCertIsInit=%hu bOurKeyIsInit=%hu \n",
+ pNew->bOurCertIsInit, pNew->bOurKeyIsInit);
+
+ /* here is the priorityString set */
+ if(pNew->gnutlsPriorityString != NULL) {
+ dbgprintf("AcceptConnReq setting configured priority string (ciphers)\n");
+ if(gnutls_priority_set_direct(pNew->sess,
+ (const char*) pNew->gnutlsPriorityString,
+ &error_position)==GNUTLS_E_INVALID_REQUEST) {
+ LogError(0, RS_RET_GNUTLS_ERR, "Syntax Error in"
+ " Priority String: \"%s\"\n", error_position);
+ }
+ } else {
+ if(pThis->authMode == GTLS_AUTH_CERTANON) {
+ /* Allow ANON Ciphers */
+ dbgprintf("AcceptConnReq setting anon ciphers Try1: %s\n", GTLS_ANON_PRIO_NOTLSV13);
+ if(gnutls_priority_set_direct(pNew->sess,(const char*) GTLS_ANON_PRIO_NOTLSV13,
+ &error_position)==GNUTLS_E_INVALID_REQUEST) {
+ dbgprintf("AcceptConnReq setting anon ciphers Try2 (TLS1.3 unknown): %s\n",
+ GTLS_ANON_PRIO);
+ CHKgnutls(gnutls_priority_set_direct(pNew->sess, GTLS_ANON_PRIO, &error_position));
+ }
+ /* Uncomment for DEBUG
+ print_cipher_suite_list("NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL"); */
+ } else {
+ /* Use default priorities */
+ dbgprintf("AcceptConnReq setting default ciphers\n");
+ CHKgnutls(gnutls_set_default_priority(pNew->sess));
+ }
+ }
+
+ /* we now do the handshake. This is a bit complicated, because we are
+ * on non-blocking sockets. Usually, the handshake will not complete
+ * immediately, so that we need to retry it some time later.
+ */
+ gnuRet = gnutls_handshake(pNew->sess);
+ if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+ pNew->rtryCall = gtlsRtry_handshake;
+ dbgprintf("GnuTLS handshake does not complete immediately - "
+ "setting to retry (this is OK and normal)\n");
+ } else if(gnuRet == 0) {
+ /* we got a handshake, now check authorization */
+ CHKiRet(gtlsChkPeerAuth(pNew));
+ } else {
+ uchar *pGnuErr = gtlsStrerror(gnuRet);
+ LogError(0, RS_RET_TLS_HANDSHAKE_ERR,
+ "gnutls returned error on handshake: %s\n", pGnuErr);
+ free(pGnuErr);
+ ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
+ }
+
+ pNew->iMode = 1; /* this session is now in TLS mode! */
+
+ *ppNew = (nsd_t*) pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+if (error_position != NULL) {
+ dbgprintf("AcceptConnReq error_position=%s\n", error_position);
+}
+
+ if(pNew != NULL)
+ nsd_gtlsDestruct(&pNew);
+ }
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. -- rgerhards, 2008-03-17
+ * The function now follows the usual iRet calling sequence.
+ * With GnuTLS, we may need to restart a recv() system call. If so, we need
+ * to supply the SAME buffer on the retry. We can not assure this, as the
+ * caller is free to call us with any buffer location (and in current
+ * implementation, it is on the stack and extremely likely to change). To
+ * work-around this problem, we allocate a buffer ourselfs and always receive
+ * into that buffer. We pass data on to the caller only after we have received it.
+ * To save some space, we allocate that internal buffer only when it is actually
+ * needed, which means when we reach this function for the first time. To keep
+ * the algorithm simple, we always supply data only from the internal buffer,
+ * even if it is a single byte. As we have a stream, the caller must be prepared
+ * to accept messages in any order, so we do not need to take care about this.
+ * Please note that the logic also forces us to do some "faking" in select(), as
+ * we must provide a fake "is ready for readign" status if we have data inside our
+ * buffer. -- rgerhards, 2008-06-23
+ */
+static rsRetVal
+Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf, int *const oserr)
+{
+ DEFiRet;
+ ssize_t iBytesCopy; /* how many bytes are to be copied to the client buffer? */
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ if(pThis->bAbortConn)
+ ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf, oserr));
+ FINALIZE;
+ }
+
+ /* --- in TLS mode now --- */
+
+ /* Buffer logic applies only if we are in TLS mode. Here we
+ * assume that we will switch from plain to TLS, but never back. This
+ * assumption may be unsafe, but it is the model for the time being and I
+ * do not see any valid reason why we should switch back to plain TCP after
+ * we were in TLS mode. However, in that case we may lose something that
+ * is already in the receive buffer ... risk accepted. -- rgerhards, 2008-06-23
+ */
+
+ if(pThis->pszRcvBuf == NULL) {
+ /* we have no buffer, so we need to malloc one */
+ CHKmalloc(pThis->pszRcvBuf = malloc(NSD_GTLS_MAX_RCVBUF));
+ pThis->lenRcvBuf = -1;
+ }
+
+ /* now check if we have something in our buffer. If so, we satisfy
+ * the request from buffer contents.
+ */
+ if(pThis->lenRcvBuf == -1) { /* no data present, must read */
+ CHKiRet(gtlsRecordRecv(pThis));
+ }
+
+ if(pThis->lenRcvBuf == 0) { /* EOS */
+ *oserr = errno;
+ ABORT_FINALIZE(RS_RET_CLOSED);
+ }
+
+ /* if we reach this point, data is present in the buffer and must be copied */
+ iBytesCopy = pThis->lenRcvBuf - pThis->ptrRcvBuf;
+ if(iBytesCopy > *pLenBuf) {
+ iBytesCopy = *pLenBuf;
+ } else {
+ pThis->lenRcvBuf = -1; /* buffer will be emptied below */
+ }
+
+ memcpy(pBuf, pThis->pszRcvBuf + pThis->ptrRcvBuf, iBytesCopy);
+ pThis->ptrRcvBuf += iBytesCopy;
+ *pLenBuf = iBytesCopy;
+
+finalize_it:
+ if (iRet != RS_RET_OK &&
+ iRet != RS_RET_RETRY) {
+ /* We need to free the receive buffer in error error case unless a retry is wanted. , if we
+ * allocated one. -- rgerhards, 2008-12-03 -- moved here by alorbach, 2015-12-01
+ */
+ *pLenBuf = 0;
+ free(pThis->pszRcvBuf);
+ pThis->pszRcvBuf = NULL;
+ }
+ dbgprintf("gtlsRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis,
+ iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf);
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ int iSent;
+ int wantsWriteData = 0;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+
+ if(pThis->bAbortConn)
+ ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf));
+ FINALIZE;
+ }
+
+ /* in TLS mode now */
+ while(1) { /* loop broken inside */
+ iSent = gnutls_record_send(pThis->sess, pBuf, *pLenBuf);
+ if(iSent >= 0) {
+ *pLenBuf = iSent;
+ break;
+ }
+ if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN) {
+ /* Check if the underlaying file descriptor needs to read or write data!*/
+ wantsWriteData = gnutls_record_get_direction(pThis->sess);
+ uchar *pErr = gtlsStrerror(iSent);
+ LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d, wantsWriteData=%d - this "
+ "could be caused by a broken connection. GnuTLS reports: %s\n",
+ iSent, wantsWriteData, pErr);
+ free(pErr);
+ gnutls_perror(iSent);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* Enable KEEPALIVE handling on the socket.
+ * rgerhards, 2009-06-02
+ */
+static rsRetVal
+EnableKeepAlive(nsd_t *pNsd)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ return nsd_ptcp.EnableKeepAlive(pThis->pTcp);
+}
+
+
+/*
+ * SNI should not be used if the hostname is a bare IP address
+ */
+static int
+SetServerNameIfPresent(nsd_gtls_t *pThis, uchar *host) {
+ struct sockaddr_in sa;
+ struct sockaddr_in6 sa6;
+
+ int inet_pton_ret = inet_pton(AF_INET, CHAR_CONVERT(host), &(sa.sin_addr));
+
+ if (inet_pton_ret == 0) { // host wasn't a bare IPv4 address: try IPv6
+ inet_pton_ret = inet_pton(AF_INET6, CHAR_CONVERT(host), &(sa6.sin6_addr));
+ }
+
+ switch(inet_pton_ret) {
+ case 1: // host is a valid IP address: don't use SNI
+ return 0;
+ case 0: // host isn't a valid IP address: assume it's a domain name, use SNI
+ return gnutls_server_name_set(pThis->sess, GNUTLS_NAME_DNS, host, ustrlen(host));
+ default: // unexpected error
+ return -1;
+ }
+
+}
+
+/* open a connection to a remote host (server). With GnuTLS, we always
+ * open a plain tcp socket and then, if in TLS mode, do a handshake on it.
+ * rgerhards, 2008-03-19
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations" /* TODO: FIX Warnings! */
+static rsRetVal
+Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device)
+{
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ int sock;
+ int gnuRet;
+ const char *error_position;
+# ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY
+ static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 };
+# endif
+ DEFiRet;
+ dbgprintf("Connect to %s:%s\n", host, port);
+
+ ISOBJ_TYPE_assert(pThis, nsd_gtls);
+ assert(port != NULL);
+ assert(host != NULL);
+
+ CHKiRet(gtlsInitCred(pThis));
+ CHKiRet(gtlsAddOurCert(pThis));
+ CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host, device));
+
+ if(pThis->iMode == 0)
+ FINALIZE;
+
+ /* we reach this point if in TLS mode */
+ CHKgnutls(gnutls_init(&pThis->sess, GNUTLS_CLIENT));
+ pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 1;
+
+ CHKgnutls(SetServerNameIfPresent(pThis, host));
+
+ /* in the client case, we need to set a callback that ensures our certificate
+ * will be presented to the server even if it is not signed by one of the server's
+ * trusted roots. This is necessary to support fingerprint authentication.
+ */
+ /* store a pointer to ourselfs (needed by callback) */
+ gnutls_session_set_ptr(pThis->sess, (void*)pThis);
+ iRet = gtlsLoadOurCertKey(pThis); /* first load .pem files */
+ if(iRet == RS_RET_OK) {
+# if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION
+ gnutls_certificate_set_retrieve_function(pThis->xcred, gtlsClientCertCallback);
+# else
+ gnutls_certificate_client_set_retrieve_function(pThis->xcred, gtlsClientCertCallback);
+# endif
+ dbgprintf("Connect: enable certificate checking (VerifyDepth=%d)\n", pThis->DrvrVerifyDepth);
+ if (pThis->DrvrVerifyDepth != 0) {
+ gnutls_certificate_set_verify_limits(pThis->xcred, 8200, pThis->DrvrVerifyDepth);
+ }
+ } else if(iRet == RS_RET_CERTLESS) {
+ dbgprintf("Connect: certificates not configured, not loaded.\n");
+ } else {
+ LogError(0, iRet, "Connect failed to INIT Session %d", gnuRet);
+ ABORT_FINALIZE(iRet);; /* we have an error case! */
+ }
+
+ /*priority string setzen*/
+ if(pThis->gnutlsPriorityString != NULL) {
+ dbgprintf("Connect: setting configured priority string (ciphers)\n");
+ if(gnutls_priority_set_direct(pThis->sess,
+ (const char*) pThis->gnutlsPriorityString,
+ &error_position)==GNUTLS_E_INVALID_REQUEST) {
+ LogError(0, RS_RET_GNUTLS_ERR, "Syntax Error in"
+ " Priority String: \"%s\"\n", error_position);
+ }
+ } else {
+ if(pThis->authMode == GTLS_AUTH_CERTANON || pThis->bOurCertIsInit == 0) {
+ /* Allow ANON Ciphers */
+ dbgprintf("Connect: setting anon ciphers Try1: %s\n", GTLS_ANON_PRIO_NOTLSV13);
+ if(gnutls_priority_set_direct(pThis->sess,(const char*) GTLS_ANON_PRIO_NOTLSV13,
+ &error_position)==GNUTLS_E_INVALID_REQUEST) {
+ dbgprintf("Connect: setting anon ciphers Try2 (TLS1.3 unknown): %s\n", GTLS_ANON_PRIO);
+ CHKgnutls(gnutls_priority_set_direct(pThis->sess, GTLS_ANON_PRIO, &error_position));
+ }
+ /* Uncomment for DEBUG
+ print_cipher_suite_list("NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL"); */
+ } else {
+ /* Use default priorities */
+ dbgprintf("Connect: setting default ciphers\n");
+ CHKgnutls(gnutls_set_default_priority(pThis->sess));
+ }
+ }
+
+# ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY
+ /* The gnutls_certificate_type_set_priority function is deprecated
+ * and not available in recent GnuTLS versions. However, there is no
+ * doc how to properly replace it with gnutls_priority_set_direct.
+ * A lot of folks have simply removed it, when they also called
+ * gnutls_set_default_priority. This is what we now also do. If
+ * this causes problems or someone has an idea of how to replace
+ * the deprecated function in a better way, please let us know!
+ * In any case, we use it as long as it is available and let
+ * not insult us by the deprecation warnings.
+ * 2015-05-18 rgerhards
+ */
+ CHKgnutls(gnutls_certificate_type_set_priority(pThis->sess, cert_type_priority));
+# endif
+
+ /* put the x509 credentials to the current session */
+ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_CERTIFICATE, pThis->xcred));
+
+ /* check for anon authmode */
+ if (pThis->authMode == GTLS_AUTH_CERTANON) {
+ dbgprintf("Connect: anon authmode, gnutls_credentials_set GNUTLS_CRD_ANON\n");
+ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_ANON, anoncred));
+ gnutls_dh_set_prime_bits(pThis->sess, dhMinBits);
+ }
+
+ /* assign the socket to GnuTls */
+ CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock));
+ gtlsSetTransportPtr(pThis, sock);
+
+ /* we need to store the hostname as an alternate mean of authentication if no
+ * permitted peer names are given. Using the hostname is quite useful. It permits
+ * auto-configuration of security if a commen root cert is present. -- rgerhards, 2008-05-26
+ */
+ CHKmalloc(pThis->pszConnectHost = (uchar*)strdup((char*)host));
+
+ /* and perform the handshake */
+ CHKgnutls(gnutls_handshake(pThis->sess));
+ dbgprintf("GnuTLS handshake succeeded\n");
+
+ /* now check if the remote peer is permitted to talk to us - ideally, we
+ * should do this during the handshake, but GnuTLS does not yet provide
+ * the necessary callbacks -- rgerhards, 2008-05-26
+ */
+ CHKiRet(gtlsChkPeerAuth(pThis));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->bHaveSess) {
+ gnutls_deinit(pThis->sess);
+ pThis->bHaveSess = 0;
+ /* Free memory using gnutls api first*/
+ gnutls_certificate_free_credentials(pThis->xcred);
+ pThis->xcred = NULL;
+ /* Free other memory */
+ free(pThis->pszConnectHost);
+ pThis->pszConnectHost = NULL;
+ }
+ }
+
+ RETiRet;
+}
+#pragma GCC diagnostic pop
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsd_gtls)
+CODESTARTobjQueryInterface(nsd_gtls)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_gtlsConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_gtlsDestruct;
+ pIf->Abort = Abort;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->Connect = Connect;
+ pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
+ pIf->SetAuthMode = SetAuthMode;
+ pIf->SetPermitExpiredCerts = SetPermitExpiredCerts;
+ pIf->SetPermPeers =SetPermPeers;
+ pIf->CheckConnection = CheckConnection;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+ pIf->GetRemAddr = GetRemAddr;
+ pIf->EnableKeepAlive = EnableKeepAlive;
+ pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
+ pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ pIf->SetKeepAliveTime = SetKeepAliveTime;
+ pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
+ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage;
+ pIf->SetPrioritizeSAN = SetPrioritizeSAN;
+ pIf->SetTlsVerifyDepth = SetTlsVerifyDepth;
+ pIf->SetTlsCAFile = SetTlsCAFile;
+ pIf->SetTlsCRLFile = SetTlsCRLFile;
+ pIf->SetTlsKeyFile = SetTlsKeyFile;
+ pIf->SetTlsCertFile = SetTlsCertFile;
+finalize_it:
+ENDobjQueryInterface(nsd_gtls)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsd_gtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsd_gtls)
+ gtlsGlblExit(); /* shut down GnuTLS */
+
+ /* release objects we no longer need */
+ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDObjClassExit(nsd_gtls)
+
+
+/* Initialize the nsd_gtls class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsd_gtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME));
+
+ /* now do global TLS init stuff */
+ CHKiRet(gtlsGlblInit());
+ENDObjClassInit(nsd_gtls)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsdsel_gtlsClassExit();
+ nsd_gtlsClassExit();
+ pthread_mutex_destroy(&mutGtlsStrerror);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(nsd_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+
+ pthread_mutex_init(&mutGtlsStrerror, NULL);
+ENDmodInit
+/* vi:set ai:
+ */
+
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
new file mode 100644
index 0000000..ee0b7f9
--- /dev/null
+++ b/runtime/nsd_gtls.h
@@ -0,0 +1,123 @@
+/* An implementation of the nsd interface for GnuTLS.
+ *
+ * Copyright 2008-2021 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSD_GTLS_H
+#define INCLUDED_NSD_GTLS_H
+
+#include "nsd.h"
+
+#define NSD_GTLS_MAX_RCVBUF 16 * 1024 + 1/* TLS RFC 8449: max size of buffer for message reception */
+#define NSD_GTLS_MAX_CERT 10 /* max number of certs in our chain */
+
+typedef enum {
+ gtlsRtry_None = 0, /**< no call needs to be retried */
+ gtlsRtry_handshake = 1,
+ gtlsRtry_recv = 2
+} gtlsRtryCall_t; /**< IDs of calls that needs to be retried */
+
+typedef enum {
+ gtlsDir_READ = 0, /**< GNUTLS wants READ */
+ gtlsDir_WRITE = 1 /**< GNUTLS wants WRITE */
+} gtlsDirection_t;
+
+typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
+
+/* the nsd_gtls object */
+struct nsd_gtls_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */
+ uchar *pszConnectHost; /**< hostname used for connect - may be used to
+ authenticate peer if no other name given */
+ const uchar *pszCAFile;
+ const uchar *pszCRLFile;
+ const uchar *pszKeyFile;
+ const uchar *pszCertFile;
+ gnutls_certificate_credentials_t xcred;
+ int xcred_is_copy;
+ int iMode; /* 0 - plain tcp, 1 - TLS */
+ int bAbortConn; /* if set, abort conncection (fatal error had happened) */
+ enum {
+ GTLS_AUTH_CERTNAME = 0,
+ GTLS_AUTH_CERTFINGERPRINT = 1,
+ GTLS_AUTH_CERTVALID = 2,
+ GTLS_AUTH_CERTANON = 3
+ } authMode;
+ enum {
+ GTLS_EXPIRED_PERMIT = 0,
+ GTLS_EXPIRED_DENY = 1,
+ GTLS_EXPIRED_WARN = 2
+ } permitExpiredCerts;
+ enum {
+ GTLS_NONE = 0,
+ GTLS_PURPOSE = 1
+ } dataTypeCheck;
+ int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not cehck CN) */
+ gtlsRtryCall_t rtryCall;/**< what must we retry? */
+ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */
+ gnutls_session_t sess;
+ int bHaveSess; /* as we don't know exactly which gnutls_session values
+ are invalid, we use this one to flag whether or
+ not we are in a session (same as -1 for a socket
+ meaning no sess) */
+ int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is
+ * set to 1 and changed to 0 after the first report. It is changed back to 1 after
+ * one successful authentication. */
+ permittedPeers_t *pPermPeers; /* permitted peers */
+ uchar *gnutlsPriorityString; /* gnutls priority string */
+ int DrvrVerifyDepth; /* Verify Depth for certificate chains */
+ gnutls_x509_crt_t pOurCerts[NSD_GTLS_MAX_CERT]; /**< our certificate, if in client mode
+ (unused in server mode) */
+ unsigned int nOurCerts; /* number of certificates in our chain */
+ gnutls_x509_privkey_t ourKey; /**< our private key, if in client mode (unused in server mode) */
+ short bOurCertIsInit; /**< 1 if our certificate is initialized and must be deinit on destruction */
+ short bOurKeyIsInit; /**< 1 if our private key is initialized and must be deinit on destruction */
+ char *pszRcvBuf;
+ int lenRcvBuf;
+ /**< -1: empty, 0: connection closed, 1..NSD_GTLS_MAX_RCVBUF-1: data of that size present */
+ int ptrRcvBuf; /**< offset for next recv operation if 0 < lenRcvBuf < NSD_GTLS_MAX_RCVBUF */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsd_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsd_gtls);
+/* some prototypes for things used by our nsdsel_gtls helper class */
+uchar *gtlsStrerror(int error);
+rsRetVal gtlsChkPeerAuth(nsd_gtls_t *pThis);
+rsRetVal gtlsRecordRecv(nsd_gtls_t *pThis);
+
+/* the name of our library binary */
+#define LM_NSD_GTLS_FILENAME "lmnsd_gtls"
+
+#if GNUTLS_VERSION_NUMBER <= 0x00030000
+#define GTLS_ANON_PRIO_NOTLSV13 "NORMAL:-VERS-TLS1.3:+ANON-DH:+COMP-ALL"
+#define GTLS_ANON_PRIO "NORMAL:+ANON-DH:+COMP-ALL"
+#else
+#define GTLS_ANON_PRIO_NOTLSV13 "NORMAL:-VERS-TLS1.3:+ANON-DH:+ANON-ECDH:+COMP-ALL"
+#define GTLS_ANON_PRIO "NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL"
+#endif
+
+#if GNUTLS_VERSION_MAJOR > 3 || (GNUTLS_VERSION_MAJOR == 3 && GNUTLS_VERSION_MINOR >=4)
+#define EXTENDED_CERT_CHECK_AVAILABLE
+#endif
+
+#endif /* #ifndef INCLUDED_NSD_GTLS_H */
diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
new file mode 100644
index 0000000..2d70fb6
--- /dev/null
+++ b/runtime/nsd_ossl.c
@@ -0,0 +1,1510 @@
+/* nsd_ossl.c
+ *
+ * An implementation of the nsd interface for OpenSSL.
+ *
+ * Copyright 2018-2023 Adiscon GmbH.
+ * Author: Andre Lorbach
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "cfsysline.h"
+#include "obj.h"
+#include "stringbuf.h"
+#include "errmsg.h"
+#include "net.h"
+#include "netstrm.h"
+#include "netstrms.h"
+#include "datetime.h"
+#include "net_ossl.h" // Include OpenSSL Helpers
+#include "nsd_ptcp.h"
+#include "nsdsel_ossl.h"
+#include "nsd_ossl.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_KEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(nsd_ptcp)
+DEFobjCurrIf(net_ossl)
+
+/* Some prototypes for helper functions used inside openssl driver */
+static rsRetVal applyGnutlsPriorityString(nsd_ossl_t *const pNsd);
+
+/*--------------------------------------OpenSSL helpers ------------------------------------------*/
+void nsd_ossl_lastOpenSSLErrorMsg(nsd_ossl_t const *pThis, const int ret, SSL *ssl, int severity,
+ const char* pszCallSource, const char* pszOsslApi)
+{
+ uchar *fromHost = NULL;
+ int errno_store = errno;
+
+ if(pThis != NULL) {
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost);
+ }
+
+ // Call helper in net_ossl
+ net_ossl_lastOpenSSLErrorMsg(fromHost, ret, ssl, severity, pszCallSource, pszOsslApi);
+
+ free(fromHost);
+ errno = errno_store;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+long BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl,
+ int ret, size_t __attribute__((unused)) *processed)
+#else
+long BIO_debug_callback(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ int argi, long __attribute__((unused)) argl, long ret)
+#endif
+{
+ long ret2 = ret; // Helper value to avoid printf compile errors long<>int
+ long r = 1;
+ if (BIO_CB_RETURN & cmd)
+ r = ret;
+ dbgprintf("openssl debugmsg: BIO[%p]: ", (void *)bio);
+ switch (cmd) {
+ case BIO_CB_FREE:
+ dbgprintf("Free - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+/* Disabled due API changes for OpenSSL 1.1.0+ */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ case BIO_CB_READ:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ dbgprintf("read(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_read(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio));
+ else
+ dbgprintf("read(%d,%lu) - %s\n", RSYSLOG_BIO_number_read(bio),
+ (unsigned long)argi, RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ dbgprintf("write(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_written(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio));
+ else
+ dbgprintf("write(%d,%lu) - %s\n",
+ RSYSLOG_BIO_number_written(bio),
+ (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+#else
+ case BIO_CB_READ:
+ dbgprintf("read %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ dbgprintf("write %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+#endif
+ case BIO_CB_PUTS:
+ dbgprintf("puts() - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_GETS:
+ dbgprintf("gets(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_CTRL:
+ dbgprintf("ctrl(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_RETURN | BIO_CB_READ:
+ dbgprintf("read return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_WRITE:
+ dbgprintf("write return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_GETS:
+ dbgprintf("gets return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_PUTS:
+ dbgprintf("puts return %ld\n", ret2);
+ break;
+ case BIO_CB_RETURN | BIO_CB_CTRL:
+ dbgprintf("ctrl return %ld\n", ret2);
+ break;
+ default:
+ dbgprintf("bio callback - unknown type (%d)\n", cmd);
+ break;
+ }
+
+ return (r);
+}
+
+/* try to receive a record from the remote peer. This works with
+ * our own abstraction and handles local buffering and EAGAIN.
+ * See details on local buffering in Rcv(9 header-comment.
+ * This function MUST only be called when the local buffer is
+ * empty. Calling it otherwise will cause losss of current buffer
+ * data.
+ * rgerhards, 2008-06-24
+ */
+rsRetVal
+osslRecordRecv(nsd_ossl_t *pThis)
+{
+ ssize_t lenRcvd;
+ DEFiRet;
+ int err;
+
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ DBGPRINTF("osslRecordRecv: start\n");
+
+ lenRcvd = SSL_read(pThis->pNetOssl->ssl, pThis->pszRcvBuf, NSD_OSSL_MAX_RCVBUF);
+ if(lenRcvd > 0) {
+ DBGPRINTF("osslRecordRecv: SSL_read received %zd bytes\n", lenRcvd);
+ pThis->lenRcvBuf = lenRcvd;
+ pThis->ptrRcvBuf = 0;
+
+ /* Check for additional data in SSL buffer */
+ int iBytesLeft = SSL_pending(pThis->pNetOssl->ssl);
+ if (iBytesLeft > 0 ){
+ DBGPRINTF("osslRecordRecv: %d Bytes pending after SSL_Read, expand buffer.\n", iBytesLeft);
+ /* realloc buffer size and preserve char content */
+ char *const newbuf = realloc(pThis->pszRcvBuf, NSD_OSSL_MAX_RCVBUF+iBytesLeft);
+ CHKmalloc(newbuf);
+ pThis->pszRcvBuf = newbuf;
+
+ /* 2nd read will read missing bytes from the current SSL Packet */
+ lenRcvd = SSL_read(pThis->pNetOssl->ssl, pThis->pszRcvBuf+NSD_OSSL_MAX_RCVBUF, iBytesLeft);
+ if(lenRcvd > 0) {
+ DBGPRINTF("osslRecordRecv: 2nd SSL_read received %zd bytes\n",
+ (NSD_OSSL_MAX_RCVBUF+lenRcvd));
+ pThis->lenRcvBuf = NSD_OSSL_MAX_RCVBUF+lenRcvd;
+ } else {
+ goto sslerr;
+ }
+ }
+ } else {
+sslerr:
+ err = SSL_get_error(pThis->pNetOssl->ssl, lenRcvd);
+ if( err == SSL_ERROR_ZERO_RETURN ) {
+ DBGPRINTF("osslRecordRecv: SSL_ERROR_ZERO_RETURN received, connection may closed already\n");
+ ABORT_FINALIZE(RS_RET_RETRY);
+ }
+ else if(err == SSL_ERROR_SYSCALL) {
+ /* Output error and abort */
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, lenRcvd, pThis->pNetOssl->ssl, LOG_INFO,
+ "osslRecordRecv", "SSL_read 1");
+ iRet = RS_RET_NO_ERRCODE;
+ /* Check for underlaying socket errors **/
+ if ( errno == ECONNRESET) {
+ DBGPRINTF("osslRecordRecv: SSL_ERROR_SYSCALL Errno %d, connection reset by peer\n",
+ errno);
+ /* Connection was dropped from remote site */
+ iRet = RS_RET_CLOSED;
+ } else {
+ DBGPRINTF("osslRecordRecv: SSL_ERROR_SYSCALL Errno %d\n", errno);
+ }
+ ABORT_FINALIZE(iRet);
+ }
+ else if(err != SSL_ERROR_WANT_READ &&
+ err != SSL_ERROR_WANT_WRITE) {
+ DBGPRINTF("osslRecordRecv: SSL_get_error #1 = %d, lenRcvd=%zd\n", err, lenRcvd);
+ /* Output OpenSSL error*/
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, lenRcvd, pThis->pNetOssl->ssl, LOG_ERR,
+ "osslRecordRecv", "SSL_read 2");
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ } else {
+ DBGPRINTF("osslRecordRecv: SSL_get_error #2 = %d, lenRcvd=%zd\n", err, lenRcvd);
+ pThis->rtryCall = osslRtry_recv;
+ pThis->rtryOsslErr = err; /* Store SSL ErrorCode into*/
+ ABORT_FINALIZE(RS_RET_RETRY);
+ }
+ }
+
+// TODO: Check if MORE retry logic needed?
+
+finalize_it:
+ dbgprintf("osslRecordRecv return. nsd %p, iRet %d, lenRcvd %zd, lenRcvBuf %d, ptrRcvBuf %d\n",
+ pThis, iRet, lenRcvd, pThis->lenRcvBuf, pThis->ptrRcvBuf);
+ RETiRet;
+}
+
+static rsRetVal
+osslInitSession(nsd_ossl_t *pThis, osslSslState_t osslType) /* , nsd_ossl_t *pServer) */
+{
+ DEFiRet;
+ BIO *conn;
+ char pristringBuf[4096];
+ nsd_ptcp_t *pPtcp = (nsd_ptcp_t*) pThis->pTcp;
+
+ if(!(pThis->pNetOssl->ssl = SSL_new(pThis->pNetOssl->ctx))) {
+ pThis->pNetOssl->ssl = NULL;
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, 0, pThis->pNetOssl->ssl, LOG_ERR, "osslInitSession", "SSL_new");
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+
+ // Set SSL_MODE_AUTO_RETRY to SSL obj
+ SSL_set_mode(pThis->pNetOssl->ssl, SSL_MODE_AUTO_RETRY);
+
+ if (pThis->pNetOssl->authMode != OSSL_AUTH_CERTANON) {
+ dbgprintf("osslInitSession: enable certificate checking (Mode=%d, VerifyDepth=%d)\n",
+ pThis->pNetOssl->authMode, pThis->DrvrVerifyDepth);
+ /* Enable certificate valid checking */
+ net_ossl_set_ssl_verify_callback(pThis->pNetOssl->ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ if (pThis->DrvrVerifyDepth != 0) {
+ SSL_set_verify_depth(pThis->pNetOssl->ssl, pThis->DrvrVerifyDepth);
+ }
+ } else if (pThis->gnutlsPriorityString == NULL) {
+ /* Allow ANON Ciphers only in ANON Mode and if no custom priority string is defined */
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ /* NOTE: do never use: +eNULL, it DISABLES encryption! */
+ strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0",
+ sizeof(pristringBuf));
+ #else
+ strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL",
+ sizeof(pristringBuf));
+ #endif
+
+ dbgprintf("osslInitSession: setting anon ciphers: %s\n", pristringBuf);
+ if ( SSL_set_cipher_list(pThis->pNetOssl->ssl, pristringBuf) == 0 ){
+ dbgprintf("osslInitSession: Error setting ciphers '%s'\n", pristringBuf);
+ ABORT_FINALIZE(RS_RET_SYS_ERR);
+ }
+ }
+
+ /* Create BIO from ptcp socket! */
+ conn = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*BIO_NOCLOSE*/);
+ dbgprintf("osslInitSession: Init conn BIO[%p] done\n", (void *)conn);
+
+ /* Set debug Callback for conn BIO as well! */
+ net_ossl_set_bio_callback(conn);
+
+ /* TODO: still needed? Set to NON blocking ! */
+ BIO_set_nbio( conn, 1 );
+ SSL_set_bio(pThis->pNetOssl->ssl, conn, conn);
+
+ if (osslType == osslServer) {
+ /* Server Socket */
+ SSL_set_accept_state(pThis->pNetOssl->ssl); /* sets ssl to work in server mode. */
+ pThis->pNetOssl->sslState = osslServer; /*set Server state */
+ } else {
+ /* Client Socket */
+ SSL_set_connect_state(pThis->pNetOssl->ssl); /*sets ssl to work in client mode.*/
+ pThis->pNetOssl->sslState = osslClient; /*set Client state */
+ }
+ pThis->bHaveSess = 1;
+
+ /* we are done */
+ FINALIZE;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* check if it is OK to talk to the remote peer
+ * rgerhards, 2008-05-21
+ */
+rsRetVal
+osslChkPeerAuth(nsd_ossl_t *pThis)
+{
+ DEFiRet;
+ X509 *certpeer;
+
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ uchar *fromHostIP = NULL;
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHostIP);
+
+ /* call the actual function based on current auth mode */
+ switch(pThis->pNetOssl->authMode) {
+ case OSSL_AUTH_CERTNAME:
+ /* if we check the name, we must ensure the cert is valid */
+ certpeer = net_ossl_getpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP);
+ dbgprintf("osslChkPeerAuth: Check peer certname[%p]=%s\n",
+ (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP));
+ CHKiRet(net_ossl_chkpeername(pThis->pNetOssl, certpeer, fromHostIP));
+ break;
+ case OSSL_AUTH_CERTFINGERPRINT:
+ certpeer = net_ossl_getpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP);
+ dbgprintf("osslChkPeerAuth: Check peer fingerprint[%p]=%s\n",
+ (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP));
+ CHKiRet(net_ossl_peerfingerprint(pThis->pNetOssl, certpeer, fromHostIP));
+
+ break;
+ case OSSL_AUTH_CERTVALID:
+ certpeer = net_ossl_getpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP);
+ dbgprintf("osslChkPeerAuth: Check peer valid[%p]=%s\n",
+ (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL"));
+ CHKiRet(net_ossl_chkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP));
+ break;
+ case OSSL_AUTH_CERTANON:
+ FINALIZE;
+ break;
+ }
+finalize_it:
+ if (fromHostIP != NULL) {
+ free(fromHostIP);
+ }
+ RETiRet;
+}
+
+/* end a OpenSSL session
+ * The function checks if we have a session and ends it only if so. So it can
+ * always be called, even if there currently is no session.
+ */
+static rsRetVal
+osslEndSess(nsd_ossl_t *pThis)
+{
+ DEFiRet;
+ uchar *fromHostIP = NULL;
+ int ret;
+ int err;
+
+ /* try closing SSL Connection */
+ if(pThis->bHaveSess) {
+ DBGPRINTF("osslEndSess: closing SSL Session ...\n");
+ ret = SSL_shutdown(pThis->pNetOssl->ssl);
+ nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHostIP);
+ if (ret <= 0) {
+ err = SSL_get_error(pThis->pNetOssl->ssl, ret);
+ DBGPRINTF("osslEndSess: shutdown failed with err = %d\n", err);
+
+ /* ignore those SSL Errors on shutdown */
+ if( err != SSL_ERROR_SYSCALL &&
+ err != SSL_ERROR_ZERO_RETURN &&
+ err != SSL_ERROR_WANT_READ &&
+ err != SSL_ERROR_WANT_WRITE) {
+ /* Output Warning only */
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, ret, pThis->pNetOssl->ssl, LOG_WARNING,
+ "osslEndSess", "SSL_shutdown");
+ }
+ /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more:
+ * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html
+ */
+ char rcvBuf[NSD_OSSL_MAX_RCVBUF];
+ int iBytesRet = SSL_read(pThis->pNetOssl->ssl, rcvBuf, NSD_OSSL_MAX_RCVBUF);
+ DBGPRINTF("osslEndSess: Forcing ssl shutdown SSL_read (%d) to do a bidirectional shutdown\n",
+ iBytesRet);
+ if (ret < 0) {
+ /* Unsuccessful shutdown, log as INFO */
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
+ "TLS session terminated successfully to remote syslog server '%s' with SSL Error '%d':"
+ " End Session", fromHostIP, ret);
+ }
+ dbgprintf( "osslEndSess: TLS session terminated successfully to remote syslog server '%s'"
+ " End Session", fromHostIP);
+ } else {
+ dbgprintf("osslEndSess: TLS session terminated successfully with remote syslog server '%s':"
+ " End Session", fromHostIP);
+ }
+
+ /* Session closed */
+ pThis->bHaveSess = 0;
+ }
+
+ if (fromHostIP != NULL) {
+ free(fromHostIP);
+ }
+ RETiRet;
+}
+/* ---------------------------- end OpenSSL specifics ---------------------------- */
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nsd_ossl) /* be sure to specify the object type also in END macro! */
+ /* construct nsd_ptcp helper */
+ CHKiRet(nsd_ptcp.Construct(&pThis->pTcp));
+ /* construct net_ossl helper */
+ CHKiRet(net_ossl.Construct(&pThis->pNetOssl));
+finalize_it:
+ENDobjConstruct(nsd_ossl)
+
+
+/* destructor for the nsd_ossl object */
+PROTOTYPEobjDestruct(nsd_ossl);
+BEGINobjDestruct(nsd_ossl) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsd_ossl)
+ DBGPRINTF("nsd_ossl_destruct: [%p] Mode %d\n", pThis, pThis->iMode);
+ if(pThis->iMode == 1) {
+ osslEndSess(pThis);
+ }
+ /* TODO MOVE Free SSL obj also if we do not have a session - or are NOT in TLS mode! */
+ if (pThis->pNetOssl->ssl != NULL) {
+ DBGPRINTF("nsd_ossl_destruct: [%p] FREE pThis->pNetOssl->ssl \n", pThis);
+ SSL_free(pThis->pNetOssl->ssl);
+ pThis->pNetOssl->ssl = NULL;
+ }
+ /**/
+ if(pThis->pTcp != NULL) {
+ nsd_ptcp.Destruct(&pThis->pTcp);
+ }
+ if(pThis->pNetOssl != NULL) {
+ net_ossl.Destruct(&pThis->pNetOssl);
+ }
+
+ free(pThis->pszConnectHost);
+ free(pThis->pszRcvBuf);
+ENDobjDestruct(nsd_ossl)
+
+
+/* Set the driver mode. For us, this has the following meaning:
+ * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS)
+ * 1 - work in TLS mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t *pNsd, const int mode)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(mode != 0 && mode != 1) {
+ LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by"
+ " ossl netstream driver", mode);
+ }
+ pThis->iMode = mode;
+
+ RETiRet;
+}
+
+/* Set the authentication mode. For us, the following is supported:
+ * anon - no certificate checks whatsoever (discouraged, but supported)
+ * x509/certvalid - (just) check certificate validity
+ * x509/fingerprint - certificate fingerprint
+ * x509/name - cerfificate name check
+ * mode == NULL is valid and defaults to x509/name
+ * rgerhards, 2008-05-16
+ */
+static rsRetVal
+SetAuthMode(nsd_t *const pNsd, uchar *const mode)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(mode == NULL || !strcasecmp((char*)mode, "x509/name")) {
+ pThis->pNetOssl->authMode = OSSL_AUTH_CERTNAME;
+ } else if(!strcasecmp((char*) mode, "x509/fingerprint")) {
+ pThis->pNetOssl->authMode = OSSL_AUTH_CERTFINGERPRINT;
+ } else if(!strcasecmp((char*) mode, "x509/certvalid")) {
+ pThis->pNetOssl->authMode = OSSL_AUTH_CERTVALID;
+ } else if(!strcasecmp((char*) mode, "anon")) {
+ pThis->pNetOssl->authMode = OSSL_AUTH_CERTANON;
+
+ } else {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by "
+ "ossl netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ dbgprintf("SetAuthMode: Set Mode %s/%d\n", mode, pThis->pNetOssl->authMode);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the PermitExpiredCerts mode. For us, the following is supported:
+ * on - fail if certificate is expired
+ * off - ignore expired certificates
+ * warn - warn if certificate is expired
+ * alorbach, 2018-12-20
+ */
+static rsRetVal
+SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ /* default is set to off! */
+ if(mode == NULL || !strcasecmp((char*)mode, "off")) {
+ pThis->permitExpiredCerts = OSSL_EXPIRED_DENY;
+ } else if(!strcasecmp((char*) mode, "warn")) {
+ pThis->permitExpiredCerts = OSSL_EXPIRED_WARN;
+ } else if(!strcasecmp((char*) mode, "on")) {
+ pThis->permitExpiredCerts = OSSL_EXPIRED_PERMIT;
+ } else {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by "
+ "ossl netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+ dbgprintf("SetPermitExpiredCerts: Set Mode %s/%d\n", mode, pThis->permitExpiredCerts);
+
+/* TODO: clear stored IDs! */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set permitted peers. It is depending on the auth mode if this are
+ * fingerprints or names. -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(pPermPeers == NULL)
+ FINALIZE;
+
+ if(pThis->pNetOssl->authMode != OSSL_AUTH_CERTFINGERPRINT && pThis->pNetOssl->authMode != OSSL_AUTH_CERTNAME) {
+ LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by "
+ "ossl netstream driver in the configured authentication mode - ignored");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE);
+ }
+ pThis->pNetOssl->pPermPeers = pPermPeers;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_ossl) who utilize ourselfs
+ * for some of their functionality. -- rgerhards, 2008-04-18
+ */
+static rsRetVal
+SetSock(nsd_t *pNsd, int sock)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ assert(sock >= 0);
+
+ DBGPRINTF("SetSock for [%p]: Setting sock %d\n", pNsd, sock);
+ nsd_ptcp.SetSock(pThis->pTcp, sock);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ assert(keepAliveIntvl >= 0);
+
+ dbgprintf("SetKeepAliveIntvl: keepAliveIntvl=%d\n", keepAliveIntvl);
+ nsd_ptcp.SetKeepAliveIntvl(pThis->pTcp, keepAliveIntvl);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ assert(keepAliveProbes >= 0);
+
+ dbgprintf("SetKeepAliveProbes: keepAliveProbes=%d\n", keepAliveProbes);
+ nsd_ptcp.SetKeepAliveProbes(pThis->pTcp, keepAliveProbes);
+
+ RETiRet;
+}
+
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ assert(keepAliveTime >= 0);
+
+ dbgprintf("SetKeepAliveTime: keepAliveTime=%d\n", keepAliveTime);
+ nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime);
+
+ RETiRet;
+}
+
+
+/* abort a connection. This is meant to be called immediately
+ * before the Destruct call. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+Abort(nsd_t *pNsd)
+{
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+
+ if(pThis->iMode == 0) {
+ nsd_ptcp.Abort(pThis->pTcp);
+ }
+
+ RETiRet;
+}
+
+
+/* Callback after netstrm obj init in nsd_ptcp - permits us to add some data */
+static rsRetVal
+LstnInitDrvr(netstrm_t *const pThis)
+{
+ DEFiRet;
+ nsd_ossl_t* pNsdOssl = (nsd_ossl_t*) pThis->pDrvrData;
+ /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for all newer versions! */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ CHKiRet(net_ossl.osslCtxInit(pNsdOssl->pNetOssl, SSLv23_method()));
+#else
+ CHKiRet(net_ossl.osslCtxInit(pNsdOssl->pNetOssl, TLS_method()));
+#endif
+ // Apply PriorityString after Ctx Creation
+ applyGnutlsPriorityString(pNsdOssl);
+finalize_it:
+ RETiRet;
+}
+
+
+/* initialize the tcp socket for a listner
+ * Here, we use the ptcp driver - because there is nothing special
+ * at this point with OpenSSL. Things become special once we accept
+ * a session, but not during listener setup.
+ */
+static rsRetVal
+LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params)
+{
+ DEFiRet;
+
+ dbgprintf("LstnInit for openssl: entering LstnInit (%p) for %s:%s SessMax=%d\n",
+ fAddLstn, cnf_params->pszAddr, cnf_params->pszPort, iSessMax);
+
+ pNS->fLstnInitDrvr = LstnInitDrvr;
+ /* Init TCP Listener using base ptcp class */
+ iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params);
+ RETiRet;
+}
+
+
+/* This function checks if the connection is still alive - well, kind of...
+ * This is a dummy here. For details, check function common in ptcp driver.
+ * rgerhards, 2008-06-09
+ */
+static rsRetVal
+CheckConnection(nsd_t __attribute__((unused)) *pNsd)
+{
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+
+ dbgprintf("CheckConnection for %p\n", pNsd);
+ return nsd_ptcp.CheckConnection(pThis->pTcp);
+}
+
+
+/* get the remote hostname. The returned hostname must be freed by the caller.
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+GetRemoteHName(nsd_t *pNsd, uchar **ppszHName)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName);
+ dbgprintf("GetRemoteHName for %p = %s\n", pNsd, *ppszHName);
+ RETiRet;
+}
+
+
+/* Provide access to the sockaddr_storage of the remote peer. This
+ * is needed by the legacy ACL system. --- gerhards, 2008-12-01
+ */
+static rsRetVal
+GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ iRet = nsd_ptcp.GetRemAddr(pThis->pTcp, ppAddr);
+ dbgprintf("GetRemAddr for %p\n", pNsd);
+ RETiRet;
+}
+
+
+/* get the remote host's IP address. Caller must Destruct the object. */
+static rsRetVal
+GetRemoteIP(nsd_t *pNsd, prop_t **ip)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ip);
+ dbgprintf("GetRemoteIP for %p\n", pNsd);
+ RETiRet;
+}
+
+
+/* Perform all necessary checks after Handshake
+ */
+rsRetVal
+osslPostHandshakeCheck(nsd_ossl_t *pNsd)
+{
+ DEFiRet;
+ char szDbg[255];
+ const SSL_CIPHER* sslCipher;
+
+ /* Some extra output for debugging openssl */
+ if (SSL_get_shared_ciphers(pNsd->pNetOssl->ssl,szDbg, sizeof szDbg) != NULL)
+ dbgprintf("osslPostHandshakeCheck: Debug Shared ciphers = %s\n", szDbg);
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if(SSL_get_shared_curve(pNsd->pNetOssl->ssl, -1) == 0) {
+ // This is not a failure
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
+ "Information, no shared curve between syslog client and server");
+ }
+ #endif
+ dbgprintf("osslPostHandshakeCheck: Debug Protocol Version: %s\n",
+ SSL_get_version(pNsd->pNetOssl->ssl));
+
+ sslCipher = (const SSL_CIPHER*) SSL_get_current_cipher(pNsd->pNetOssl->ssl);
+ if (sslCipher != NULL){
+ if(SSL_CIPHER_get_version(sslCipher) == NULL) {
+ LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:"
+ "TLS version mismatch between syslog client and server.");
+ }
+ dbgprintf("osslPostHandshakeCheck: Debug Cipher Version: %s Name: %s\n",
+ SSL_CIPHER_get_version(sslCipher), SSL_CIPHER_get_name(sslCipher));
+ }else {
+ LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:No shared ciphers between syslog client and server.");
+ }
+
+ FINALIZE;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Perform all necessary actions for Handshake
+ */
+rsRetVal
+osslHandshakeCheck(nsd_ossl_t *pNsd)
+{
+ DEFiRet;
+ uchar *fromHostIP = NULL;
+ int res, resErr;
+ dbgprintf("osslHandshakeCheck: Starting TLS Handshake for ssl[%p]\n", (void *)pNsd->pNetOssl->ssl);
+
+ if (pNsd->pNetOssl->sslState == osslServer) {
+ /* Handle Server SSL Object */
+ if((res = SSL_accept(pNsd->pNetOssl->ssl)) <= 0) {
+ /* Obtain SSL Error code */
+ nsd_ptcp.GetRemoteHName((nsd_t*)pNsd->pTcp, &fromHostIP);
+ resErr = SSL_get_error(pNsd->pNetOssl->ssl, res);
+ if( resErr == SSL_ERROR_WANT_READ ||
+ resErr == SSL_ERROR_WANT_WRITE) {
+ pNsd->rtryCall = osslRtry_handshake;
+ pNsd->rtryOsslErr = resErr; /* Store SSL ErrorCode into*/
+ dbgprintf("osslHandshakeCheck: OpenSSL Server handshake does not complete "
+ "immediately - setting to retry (this is OK and normal)\n");
+ FINALIZE;
+ } else if(resErr == SSL_ERROR_SYSCALL) {
+ dbgprintf("osslHandshakeCheck: OpenSSL Server handshake failed with SSL_ERROR_SYSCALL "
+ "- Aborting handshake.\n");
+ nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_WARNING,
+ "osslHandshakeCheck Server", "SSL_accept");
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote client '%s': "
+ "Handshake failed with SSL_ERROR_SYSCALL", fromHostIP);
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ } else {
+ nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_ERR,
+ "osslHandshakeCheck Server", "SSL_accept");
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote client '%s': "
+ "Handshake failed with error code: %d", fromHostIP, resErr);
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+ }
+ } else {
+ /* Handle Client SSL Object */
+ if((res = SSL_do_handshake(pNsd->pNetOssl->ssl)) <= 0) {
+ /* Obtain SSL Error code */
+ nsd_ptcp.GetRemoteHName((nsd_t*)pNsd->pTcp, &fromHostIP);
+ resErr = SSL_get_error(pNsd->pNetOssl->ssl, res);
+ if( resErr == SSL_ERROR_WANT_READ ||
+ resErr == SSL_ERROR_WANT_WRITE) {
+ pNsd->rtryCall = osslRtry_handshake;
+ pNsd->rtryOsslErr = resErr; /* Store SSL ErrorCode into*/
+ dbgprintf("osslHandshakeCheck: OpenSSL Client handshake does not complete "
+ "immediately - setting to retry (this is OK and normal)\n");
+ FINALIZE;
+ } else if(resErr == SSL_ERROR_SYSCALL) {
+ dbgprintf("osslHandshakeCheck: OpenSSL Client handshake failed with SSL_ERROR_SYSCALL "
+ "- Aborting handshake.\n");
+ nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_WARNING,
+ "osslHandshakeCheck Client", "SSL_do_handshake");
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE /*RS_RET_RETRY*/);
+ } else {
+ dbgprintf("osslHandshakeCheck: OpenSSL Client handshake failed with %d "
+ "- Aborting handshake.\n", resErr);
+ nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_ERR,
+ "osslHandshakeCheck Client", "SSL_do_handshake");
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+ "nsd_ossl:TLS session terminated with remote syslog server '%s':"
+ "Handshake failed with error code: %d", fromHostIP, resErr);
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+ }
+ }
+
+ /* Do post handshake stuff */
+ CHKiRet(osslPostHandshakeCheck(pNsd));
+
+ /* Now check authorization */
+ CHKiRet(osslChkPeerAuth(pNsd));
+finalize_it:
+ if (fromHostIP != NULL) {
+ free(fromHostIP);
+ }
+ if(iRet == RS_RET_OK) {
+ /* If no error occurred, set socket to SSL mode */
+ pNsd->iMode = 1;
+ }
+
+ RETiRet;
+}
+
+/* accept an incoming connection request - here, we do the usual accept
+ * handling. TLS specific handling is done thereafter (and if we run in TLS
+ * mode at this time).
+ * rgerhards, 2008-04-25
+ */
+static rsRetVal
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+{
+ DEFiRet;
+ nsd_ossl_t *pNew = NULL;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ CHKiRet(nsd_osslConstruct(&pNew));
+ CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp));
+ dbgprintf("AcceptConnReq for [%p]: Accepting connection ... \n", (void *)pThis);
+ CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp));
+
+ if(pThis->iMode == 0) {
+ /*we are in non-TLS mode, so we are done */
+ DBGPRINTF("AcceptConnReq: NOT in TLS mode!\n");
+ *ppNew = (nsd_t*) pNew;
+ FINALIZE;
+ }
+
+ /* If we reach this point, we are in TLS mode */
+ pNew->pNetOssl->authMode = pThis->pNetOssl->authMode;
+ pNew->permitExpiredCerts = pThis->permitExpiredCerts;
+ pNew->pNetOssl->pPermPeers = pThis->pNetOssl->pPermPeers;
+ pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth;
+ pNew->gnutlsPriorityString = pThis->gnutlsPriorityString;
+ pNew->pNetOssl->ctx = pThis->pNetOssl->ctx;
+ pNew->pNetOssl->ctx_is_copy = 1; // do not free on pNew Destruction
+ CHKiRet(osslInitSession(pNew, osslServer));
+
+ /* Store nsd_ossl_t* reference in SSL obj */
+ SSL_set_ex_data(pNew->pNetOssl->ssl, 0, pThis->pTcp);
+ SSL_set_ex_data(pNew->pNetOssl->ssl, 1, &pThis->permitExpiredCerts);
+
+ /* We now do the handshake */
+ CHKiRet(osslHandshakeCheck(pNew));
+
+ *ppNew = (nsd_t*) pNew;
+finalize_it:
+ /* Accept appears to be done here */
+ if(pNew != NULL) {
+ DBGPRINTF("AcceptConnReq: END iRet = %d, pNew=[%p], pNsd->rtryCall=%d\n",
+ iRet, pNew, pNew->rtryCall);
+ }
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL) {
+ nsd_osslDestruct(&pNew);
+ }
+ }
+ RETiRet;
+}
+
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. -- rgerhards, 2008-03-17
+ * The function now follows the usual iRet calling sequence.
+ * With GnuTLS, we may need to restart a recv() system call. If so, we need
+ * to supply the SAME buffer on the retry. We can not assure this, as the
+ * caller is free to call us with any buffer location (and in current
+ * implementation, it is on the stack and extremely likely to change). To
+ * work-around this problem, we allocate a buffer ourselfs and always receive
+ * into that buffer. We pass data on to the caller only after we have received it.
+ * To save some space, we allocate that internal buffer only when it is actually
+ * needed, which means when we reach this function for the first time. To keep
+ * the algorithm simple, we always supply data only from the internal buffer,
+ * even if it is a single byte. As we have a stream, the caller must be prepared
+ * to accept messages in any order, so we do not need to take care about this.
+ * Please note that the logic also forces us to do some "faking" in select(), as
+ * we must provide a fake "is ready for readign" status if we have data inside our
+ * buffer. -- rgerhards, 2008-06-23
+ */
+static rsRetVal
+Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf, int *const oserr)
+{
+ DEFiRet;
+ ssize_t iBytesCopy; /* how many bytes are to be copied to the client buffer? */
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ DBGPRINTF("Rcv for %p\n", pNsd);
+
+ if(pThis->bAbortConn)
+ ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf, oserr));
+ FINALIZE;
+ }
+
+ /* --- in TLS mode now --- */
+
+ /* Buffer logic applies only if we are in TLS mode. Here we
+ * assume that we will switch from plain to TLS, but never back. This
+ * assumption may be unsafe, but it is the model for the time being and I
+ * do not see any valid reason why we should switch back to plain TCP after
+ * we were in TLS mode. However, in that case we may lose something that
+ * is already in the receive buffer ... risk accepted. -- rgerhards, 2008-06-23
+ */
+
+ if(pThis->pszRcvBuf == NULL) {
+ /* we have no buffer, so we need to malloc one */
+ CHKmalloc(pThis->pszRcvBuf = malloc(NSD_OSSL_MAX_RCVBUF));
+ pThis->lenRcvBuf = -1;
+ }
+
+ /* now check if we have something in our buffer. If so, we satisfy
+ * the request from buffer contents.
+ */
+ if(pThis->lenRcvBuf == -1) { /* no data present, must read */
+ CHKiRet(osslRecordRecv(pThis));
+ }
+
+ if(pThis->lenRcvBuf == 0) { /* EOS */
+ *oserr = errno;
+ ABORT_FINALIZE(RS_RET_CLOSED);
+ }
+
+ /* if we reach this point, data is present in the buffer and must be copied */
+ iBytesCopy = pThis->lenRcvBuf - pThis->ptrRcvBuf;
+ if(iBytesCopy > *pLenBuf) {
+ iBytesCopy = *pLenBuf;
+ } else {
+ pThis->lenRcvBuf = -1; /* buffer will be emptied below */
+ }
+
+ memcpy(pBuf, pThis->pszRcvBuf + pThis->ptrRcvBuf, iBytesCopy);
+ pThis->ptrRcvBuf += iBytesCopy;
+ *pLenBuf = iBytesCopy;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (iRet == RS_RET_CLOSED) {
+ if (pThis->pNetOssl->ssl != NULL) {
+ /* Set SSL Shutdown */
+ SSL_shutdown(pThis->pNetOssl->ssl);
+ dbgprintf("osslRcv SSL_shutdown done\n");
+ }
+ } else if (iRet != RS_RET_RETRY) {
+ /* We need to free the receive buffer in error error case unless a retry is wanted. , if we
+ * allocated one. -- rgerhards, 2008-12-03 -- moved here by alorbach, 2015-12-01
+ */
+ *pLenBuf = 0;
+ free(pThis->pszRcvBuf);
+ pThis->pszRcvBuf = NULL;
+ } else {
+ /* RS_RET_RETRY | Check for SSL Shutdown */
+ if (SSL_get_shutdown(pThis->pNetOssl->ssl) == SSL_RECEIVED_SHUTDOWN) {
+ dbgprintf("osslRcv received SSL_RECEIVED_SHUTDOWN!\n");
+ iRet = RS_RET_CLOSED;
+
+ /* Send Shutdown message back */
+ SSL_shutdown(pThis->pNetOssl->ssl);
+ }
+ }
+ }
+ dbgprintf("osslRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis,
+ iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf);
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ DEFiRet;
+ int iSent;
+ int err;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ DBGPRINTF("Send for %p\n", pNsd);
+
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+
+ if(pThis->bAbortConn)
+ ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ);
+
+ if(pThis->iMode == 0) {
+ CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf));
+ FINALIZE;
+ }
+
+ while(1) {
+ iSent = SSL_write(pThis->pNetOssl->ssl, pBuf, *pLenBuf);
+ if(iSent > 0) {
+ *pLenBuf = iSent;
+ break;
+ } else {
+ err = SSL_get_error(pThis->pNetOssl->ssl, iSent);
+ if( err == SSL_ERROR_ZERO_RETURN ) {
+ DBGPRINTF("Send: SSL_ERROR_ZERO_RETURN received, retry next time\n");
+ ABORT_FINALIZE(RS_RET_RETRY);
+ }
+ else if(err == SSL_ERROR_SYSCALL) {
+ /* Output error and abort */
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, iSent, pThis->pNetOssl->ssl, LOG_INFO,
+ "Send", "SSL_write");
+ iRet = RS_RET_NO_ERRCODE;
+ /* Check for underlaying socket errors **/
+ if ( errno == ECONNRESET) {
+ dbgprintf("Send: SSL_ERROR_SYSCALL Connection was reset by remote\n");
+ /* Connection was dropped from remote site */
+ iRet = RS_RET_CLOSED;
+ } else {
+ DBGPRINTF("Send: SSL_ERROR_SYSCALL Errno %d\n", errno);
+ }
+ ABORT_FINALIZE(iRet);
+ }
+ else if(err != SSL_ERROR_WANT_READ &&
+ err != SSL_ERROR_WANT_WRITE) {
+ /* Output error and abort */
+ nsd_ossl_lastOpenSSLErrorMsg(pThis, iSent, pThis->pNetOssl->ssl, LOG_ERR,
+ "Send", "SSL_write");
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ } else {
+ /* Check for SSL Shutdown */
+ if (SSL_get_shutdown(pThis->pNetOssl->ssl) == SSL_RECEIVED_SHUTDOWN) {
+ dbgprintf("osslRcv received SSL_RECEIVED_SHUTDOWN!\n");
+ ABORT_FINALIZE(RS_RET_CLOSED);
+ }
+ }
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Enable KEEPALIVE handling on the socket.
+ * rgerhards, 2009-06-02
+ */
+static rsRetVal
+EnableKeepAlive(nsd_t *pNsd)
+{
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ return nsd_ptcp.EnableKeepAlive(pThis->pTcp);
+}
+
+
+/* open a connection to a remote host (server). With OpenSSL, we always
+ * open a plain tcp socket and then, if in TLS mode, do a handshake on it.
+ */
+static rsRetVal
+Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device)
+{
+ DEFiRet;
+ DBGPRINTF("openssl: entering Connect family=%d, device=%s\n", family, device);
+ nsd_ossl_t* pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ assert(port != NULL);
+ assert(host != NULL);
+
+ /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for all newer versions! */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ CHKiRet(net_ossl.osslCtxInit(pThis->pNetOssl, SSLv23_method()));
+#else
+ CHKiRet(net_ossl.osslCtxInit(pThis->pNetOssl, TLS_method()));
+#endif
+ // Apply PriorityString after Ctx Creation
+ applyGnutlsPriorityString(pThis);
+
+ // Perform TCP Connect
+ CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host, device));
+
+ if(pThis->iMode == 0) {
+ /*we are in non-TLS mode, so we are done */
+ DBGPRINTF("Connect: NOT in TLS mode!\n");
+ FINALIZE;
+ }
+
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
+ "TLS Connection initiated with remote syslog server.");
+ /*if we reach this point we are in tls mode */
+ DBGPRINTF("Connect: TLS Mode\n");
+
+ /* Do SSL Session init */
+ CHKiRet(osslInitSession(pThis, osslClient));
+
+ /* Store nsd_ossl_t* reference in SSL obj */
+ SSL_set_ex_data(pThis->pNetOssl->ssl, 0, pThis->pTcp);
+ SSL_set_ex_data(pThis->pNetOssl->ssl, 1, &pThis->permitExpiredCerts);
+
+ /* We now do the handshake */
+ iRet = osslHandshakeCheck(pThis);
+finalize_it:
+ /* Connect appears to be done here */
+ dbgprintf("Connect: END iRet = %d, pThis=[%p], pNsd->rtryCall=%d\n",
+ iRet, pThis, pThis->rtryCall);
+ if(iRet != RS_RET_OK) {
+ if(pThis->bHaveSess) {
+ pThis->bHaveSess = 0;
+ SSL_free(pThis->pNetOssl->ssl);
+ pThis->pNetOssl->ssl = NULL;
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+SetGnutlsPriorityString(nsd_t *const pNsd, uchar *const gnutlsPriorityString)
+{
+ DEFiRet;
+ nsd_ossl_t* pThis = (nsd_ossl_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+ sbool ApplySettings = 0;
+ if ( (gnutlsPriorityString != NULL && pThis->gnutlsPriorityString == NULL) ||
+ (gnutlsPriorityString != NULL &&
+ strcmp( (const char*)pThis->gnutlsPriorityString, (const char*)gnutlsPriorityString) != 0)
+ ) {
+ ApplySettings = 1;
+ }
+
+ pThis->gnutlsPriorityString = gnutlsPriorityString;
+ dbgprintf("gnutlsPriorityString: set to '%s' Apply %s\n",
+ (gnutlsPriorityString != NULL ? (char*)gnutlsPriorityString : "NULL"),
+ (ApplySettings == 1? "TRUE" : "FALSE"));
+ if (ApplySettings == 1) {
+ /* Apply Settings if necessary */
+ applyGnutlsPriorityString(pThis);
+ }
+
+#else
+ LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support SSL_CONF_cmd API"
+ "(maybe it is too old?). Cannot use gnutlsPriorityString ('%s'). For more see: "
+ "https://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#gnutlsprioritystring",
+ gnutlsPriorityString);
+#endif
+ RETiRet;
+}
+
+
+static rsRetVal
+applyGnutlsPriorityString(nsd_ossl_t *const pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ossl);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+ /* Note: we disable unkonwn functions. The corresponding error message is
+ * generated during SetGntuTLSPriorityString().
+ */
+ if(pThis->gnutlsPriorityString == NULL || pThis->pNetOssl->ctx == NULL) {
+ FINALIZE;
+ } else {
+ CHKiRet(net_ossl_apply_tlscgfcmd(pThis->pNetOssl, pThis->gnutlsPriorityString));
+ }
+#endif
+
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver cert extended key usage check setting, for now it is empty wrapper.
+ * TODO: implement openSSL version
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ if(ChkExtendedKeyUsage != 0) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
+ "not supported by ossl netstream driver", ChkExtendedKeyUsage);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver name checking strictness, for now it is empty wrapper.
+ * TODO: implement openSSL version
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan)
+{
+ DEFiRet;
+ if(prioritizeSan != 0) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
+ "not supported by ossl netstream driver", prioritizeSan);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver tls verifyDepth
+ * alorbach, 2019-12-20
+ */
+static rsRetVal
+SetTlsVerifyDepth(nsd_t *pNsd, int verifyDepth)
+{
+ DEFiRet;
+ nsd_ossl_t *pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if (verifyDepth == 0) {
+ FINALIZE;
+ }
+ assert(verifyDepth >= 2);
+ pThis->DrvrVerifyDepth = verifyDepth;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+SetTlsCAFile(nsd_t *pNsd, const uchar *const caFile)
+{
+ DEFiRet;
+ nsd_ossl_t *const pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(caFile == NULL) {
+ pThis->pNetOssl->pszCAFile = NULL;
+ } else {
+ CHKmalloc(pThis->pNetOssl->pszCAFile = (const uchar*) strdup((const char*) caFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCRLFile(nsd_t *pNsd, const uchar *const crlFile)
+{
+ DEFiRet;
+ nsd_ossl_t *const pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(crlFile == NULL) {
+ pThis->pNetOssl->pszCRLFile = NULL;
+ } else {
+ CHKmalloc(pThis->pNetOssl->pszCRLFile = (const uchar*) strdup((const char*) crlFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ nsd_ossl_t *const pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(pszFile == NULL) {
+ pThis->pNetOssl->pszKeyFile = NULL;
+ } else {
+ CHKmalloc(pThis->pNetOssl->pszKeyFile = (const uchar*) strdup((const char*) pszFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCertFile(nsd_t *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ nsd_ossl_t *const pThis = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ossl);
+ if(pszFile == NULL) {
+ pThis->pNetOssl->pszCertFile = NULL;
+ } else {
+ CHKmalloc(pThis->pNetOssl->pszCertFile = (const uchar*) strdup((const char*) pszFile));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsd_ossl)
+CODESTARTobjQueryInterface(nsd_ossl)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_osslConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_osslDestruct;
+ pIf->Abort = Abort;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->Connect = Connect;
+ pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
+ pIf->SetAuthMode = SetAuthMode;
+ pIf->SetPermitExpiredCerts = SetPermitExpiredCerts;
+ pIf->SetPermPeers =SetPermPeers;
+ pIf->CheckConnection = CheckConnection;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+ pIf->GetRemAddr = GetRemAddr;
+ pIf->EnableKeepAlive = EnableKeepAlive;
+ pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
+ pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ pIf->SetKeepAliveTime = SetKeepAliveTime;
+ pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; /* we don't NEED this interface! */
+ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; /* we don't NEED this interface! */
+ pIf->SetPrioritizeSAN = SetPrioritizeSAN; /* we don't NEED this interface! */
+ pIf->SetTlsVerifyDepth = SetTlsVerifyDepth;
+ pIf->SetTlsCAFile = SetTlsCAFile;
+ pIf->SetTlsCRLFile = SetTlsCRLFile;
+ pIf->SetTlsKeyFile = SetTlsKeyFile;
+ pIf->SetTlsCertFile = SetTlsCertFile;
+
+finalize_it:
+ENDobjQueryInterface(nsd_ossl)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsd_ossl, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsd_ossl)
+ /* release objects we no longer need */
+ objRelease(net_ossl, CORE_COMPONENT);
+ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDObjClassExit(nsd_ossl)
+
+
+/* Initialize the nsd_ossl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ */
+BEGINObjClassInit(nsd_ossl, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME));
+ CHKiRet(objUse(net_ossl, CORE_COMPONENT));
+ENDObjClassInit(nsd_ossl)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ nsdsel_osslClassExit();
+ nsd_osslClassExit();
+ net_osslClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(net_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsd_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
diff --git a/runtime/nsd_ossl.h b/runtime/nsd_ossl.h
new file mode 100644
index 0000000..000b277
--- /dev/null
+++ b/runtime/nsd_ossl.h
@@ -0,0 +1,85 @@
+/* An implementation of the nsd interface for OpenSSL.
+ *
+ * Copyright 2018-2023 Adiscon GmbH.
+ * Author: Andre Lorbach
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSD_OSSL_H
+#define INCLUDED_NSD_OSSL_H
+
+#include "nsd.h"
+
+#define NSD_OSSL_MAX_RCVBUF 16 * 1024 + 1/* TLS RFC 8449: max size of buffer for message reception */
+
+typedef enum {
+ osslRtry_None = 0, /**< no call needs to be retried */
+ osslRtry_handshake = 1,
+ osslRtry_recv = 2
+} osslRtryCall_t; /**< IDs of calls that needs to be retried */
+
+typedef nsd_if_t nsd_ossl_if_t; /* we just *implement* this interface */
+
+/* the nsd_ossl object */
+struct nsd_ossl_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */
+ uchar *pszConnectHost; /**< hostname used for connect - may be used to
+ authenticate peer if no other name given */
+ int iMode; /* 0 - plain tcp, 1 - TLS */
+ int bAbortConn; /* if set, abort conncection (fatal error had happened) */
+ PermitExpiredCerts permitExpiredCerts;
+ osslRtryCall_t rtryCall;/**< what must we retry? */
+ int rtryOsslErr; /**< store ssl error code into like SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE */
+ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */
+ int bHaveSess; /* as we don't know exactly which gnutls_session values
+ are invalid, we use this one to flag whether or
+ not we are in a session (same as -1 for a socket
+ meaning no sess) */
+ uchar *gnutlsPriorityString; /* gnutls priority string */
+ int DrvrVerifyDepth; /* Verify Depth for certificate chains */
+ short bOurCertIsInit; /**< 1 if our certificate is initialized and must be deinit on destruction */
+ short bOurKeyIsInit; /**< 1 if our private key is initialized and must be deinit on destruction */
+ char *pszRcvBuf;
+ int lenRcvBuf;
+ /**< -1: empty, 0: connection closed, 1..NSD_OSSL_MAX_RCVBUF-1: data of that size present */
+ int ptrRcvBuf; /**< offset for next recv operation if 0 < lenRcvBuf < NSD_OSSL_MAX_RCVBUF */
+
+ /* OpenSSL and Config Cert vars inside net_ossl_t now */
+ net_ossl_t *pNetOssl; /* OSSL shared Config and object vars are here */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsd_osslCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsd_ossl);
+
+/* some prototypes for things used by our nsdsel_ossl helper class */
+uchar *osslStrerror(int error);
+rsRetVal osslChkPeerAuth(nsd_ossl_t *pThis);
+rsRetVal osslRecordRecv(nsd_ossl_t *pThis);
+rsRetVal osslHandshakeCheck(nsd_ossl_t *pNsd);
+void nsd_ossl_lastOpenSSLErrorMsg(nsd_ossl_t const *pThis, const int ret, SSL *ssl, int severity,
+ const char* pszCallSource, const char* pszOsslApi);
+rsRetVal osslPostHandshakeCheck(nsd_ossl_t *pNsd);
+
+/* the name of our library binary */
+#define LM_NSD_OSSL_FILENAME "lmnsd_ossl"
+
+#endif /* #ifndef INCLUDED_NSD_OSSL_H */
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
new file mode 100644
index 0000000..6e2fd67
--- /dev/null
+++ b/runtime/nsd_ptcp.c
@@ -0,0 +1,1153 @@
+/* nsd_ptcp.c
+ *
+ * An implementation of the nsd interface for plain tcp sockets.
+ *
+ * Copyright 2007-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netinet/tcp.h>
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "module-template.h"
+#include "parse.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "net.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "nsdsel_ptcp.h"
+#include "nsdpoll_ptcp.h"
+#include "nsd_ptcp.h"
+#include "prop.h"
+#include "dnscache.h"
+#include "rsconf.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(prop)
+
+
+/* a few deinit helpers */
+
+/* close socket if open (may always be called) */
+static void
+sockClose(int *pSock)
+{
+ if(*pSock >= 0) {
+ close(*pSock);
+ *pSock = -1;
+ }
+}
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsd_ptcp) /* be sure to specify the object type also in END macro! */
+ pThis->sock = -1;
+ENDobjConstruct(nsd_ptcp)
+
+
+/* destructor for the nsd_ptcp object */
+BEGINobjDestruct(nsd_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsd_ptcp)
+ sockClose(&pThis->sock);
+ if(pThis->remoteIP != NULL)
+ prop.Destruct(&pThis->remoteIP);
+ free(pThis->pRemHostName);
+ENDobjDestruct(nsd_ptcp)
+
+
+/* Provide access to the sockaddr_storage of the remote peer. This
+ * is needed by the legacy ACL system. --- gerhards, 2008-12-01
+ */
+static rsRetVal
+GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ assert(ppAddr != NULL);
+
+ *ppAddr = &(pThis->remAddr);
+
+ RETiRet;
+}
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality. -- rgerhards, 2008-04-18
+ */
+static rsRetVal
+GetSock(nsd_t *pNsd, int *pSock)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ assert(pSock != NULL);
+
+ *pSock = pThis->sock;
+
+ RETiRet;
+}
+
+
+/* Set the driver mode. We support no different modes, but allow mode
+ * 0 to be set to be compatible with config file defaults and the other
+ * drivers.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t __attribute__((unused)) *pNsd, int mode)
+{
+ DEFiRet;
+ if(mode != 0) {
+ LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by "
+ "ptcp netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver cert extended key usage check setting, not supported in ptcp.
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) *pNsd, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ if(ChkExtendedKeyUsage != 0) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d "
+ "not supported by ptcp netstream driver", ChkExtendedKeyUsage);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the driver name checking strictness, not supported in ptcp.
+ * jvymazal, 2019-08-16
+ */
+static rsRetVal
+SetPrioritizeSAN(nsd_t __attribute__((unused)) *pNsd, int prioritizeSan)
+{
+ DEFiRet;
+ if(prioritizeSan != 0) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d "
+ "not supported by ptcp netstream driver", prioritizeSan);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the tls verify depth, not supported in ptcp.
+ * alorbach, 2019-12-20
+ */
+static rsRetVal
+SetTlsVerifyDepth(nsd_t __attribute__((unused)) *pNsd, int verifyDepth)
+{
+ nsd_ptcp_t __attribute__((unused)) *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ if (verifyDepth == 0) {
+ FINALIZE;
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Set the authentication mode. For us, the following is supported:
+ * anon - no certificate checks whatsoever (discouraged, but supported)
+ * mode == NULL is valid and defaults to anon
+ * Actually, we do not even record the mode right now, because we can
+ * always work in anon mode, only. So there is no point in recording
+ * something if that's the only choice. What the function does is
+ * return an error if something is requested that we can not support.
+ * rgerhards, 2008-05-17
+ */
+static rsRetVal
+SetAuthMode(nsd_t __attribute__((unused)) *pNsd, uchar *mode)
+{
+ DEFiRet;
+ if(mode != NULL && strcasecmp((char*)mode, "anon")) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by "
+ "ptcp netstream driver", mode);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the PermitExpiredCerts mode. not supported in ptcp
+ * alorbach, 2018-12-20
+ */
+static rsRetVal
+SetPermitExpiredCerts(nsd_t __attribute__((unused)) *pNsd, uchar *mode)
+{
+ DEFiRet;
+ if(mode != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts settingnot supported by "
+ "ptcp netstream driver");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCAFile(nsd_t __attribute__((unused)) *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ if(pszFile != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: CA File setting not supported by "
+ "ptcp netstream driver - value %s", pszFile);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCRLFile(nsd_t __attribute__((unused)) *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ if(pszFile != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: CRL File setting not supported by "
+ "ptcp netstream driver - value %s", pszFile);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsKeyFile(nsd_t __attribute__((unused)) *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ if(pszFile != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS Key File setting not supported by "
+ "ptcp netstream driver");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetTlsCertFile(nsd_t __attribute__((unused)) *pNsd, const uchar *const pszFile)
+{
+ DEFiRet;
+ if(pszFile != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS Cert File setting not supported by "
+ "ptcp netstream driver");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* Set priorityString
+ * PascalWithopf 2017-08-18 */
+static rsRetVal
+SetGnutlsPriorityString(nsd_t __attribute__((unused)) *pNsd, uchar *iVal)
+{
+ DEFiRet;
+ if(iVal != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: "
+ "gnutlsPriorityString '%s' not supported by ptcp netstream "
+ "driver", iVal);
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the permitted peers. This is a dummy, always returning an
+ * error because we do not support fingerprint authentication.
+ * rgerhards, 2008-05-17
+ */
+static rsRetVal
+SetPermPeers(nsd_t __attribute__((unused)) *pNsd, permittedPeers_t __attribute__((unused)) *pPermPeers)
+{
+ DEFiRet;
+
+ if(pPermPeers != NULL) {
+ LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by ptcp netstream driver");
+ ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+
+/* Provide access to the underlying OS socket. This is primarily
+ * useful for other drivers (like nsd_gtls) who utilize ourselfs
+ * for some of their functionality.
+ * This function sets the socket -- rgerhards, 2008-04-25
+ */
+static rsRetVal
+SetSock(nsd_t *pNsd, int sock)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+ assert(sock >= 0);
+
+ pThis->sock = sock;
+
+ RETiRet;
+}
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+
+ pThis->iKeepAliveIntvl = keepAliveIntvl;
+
+ RETiRet;
+}
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+
+ pThis->iKeepAliveProbes = keepAliveProbes;
+
+ RETiRet;
+}
+
+/* Keep Alive Options
+ */
+static rsRetVal
+SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+
+ pThis->iKeepAliveTime = keepAliveTime;
+
+ RETiRet;
+}
+
+/* abort a connection. This is meant to be called immediately
+ * before the Destruct call. -- rgerhards, 2008-03-24
+ */
+static rsRetVal
+Abort(nsd_t *pNsd)
+{
+ struct linger ling;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert((pThis), nsd_ptcp);
+
+ if((pThis)->sock != -1) {
+ ling.l_onoff = 1;
+ ling.l_linger = 0;
+ if(setsockopt((pThis)->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0 ) {
+ dbgprintf("could not set SO_LINGER, errno %d\n", errno);
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* Set pRemHost based on the address provided. This is to be called upon accept()ing
+ * a connection request. It must be provided by the socket we received the
+ * message on as well as a NI_MAXHOST size large character buffer for the FQDN.
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. If we detect a malicious
+ * hostname, we return RS_RET_MALICIOUS_HNAME and let the caller decide
+ * on how to deal with that.
+ * rgerhards, 2008-03-31
+ */
+static rsRetVal
+FillRemHost(nsd_ptcp_t *pThis, struct sockaddr_storage *pAddr)
+{
+ prop_t *fqdn;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(pAddr != NULL);
+
+ CHKiRet(dnscacheLookup(pAddr, &fqdn, NULL, NULL, &pThis->remoteIP));
+
+ /* We now have the names, so now let's allocate memory and store them permanently.
+ * (side note: we may hold on to these values for quite a while, thus we trim their
+ * memory consumption)
+ */
+ if((pThis->pRemHostName = malloc(prop.GetStringLen(fqdn)+1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ memcpy(pThis->pRemHostName, propGetSzStr(fqdn), prop.GetStringLen(fqdn)+1);
+ prop.Destruct(&fqdn);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* accept an incoming connection request
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+{
+ int sockflags;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ nsd_ptcp_t *pNew = NULL;
+ int iNewSock = -1;
+
+ DEFiRet;
+ assert(ppNew != NULL);
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ iNewSock = accept(pThis->sock, (struct sockaddr*) &addr, &addrlen);
+ if(iNewSock < 0) {
+ if(Debug) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ dbgprintf("nds_ptcp: error accepting connection on socket %d, errno %d: %s\n",
+ pThis->sock, errno, errStr);
+ }
+ ABORT_FINALIZE(RS_RET_ACCEPT_ERR);
+ }
+
+ /* construct our object so that we can use it... */
+ CHKiRet(nsd_ptcpConstruct(&pNew));
+
+ /* for the legacy ACL code, we need to preserve addr. While this is far from
+ * begin perfect (from an abstract design perspective), we need this to prevent
+ * breaking everything. TODO: we need to implement a new ACL module to get rid
+ * of this function. -- rgerhards, 2008-12-01
+ */
+ memcpy(&pNew->remAddr, &addr, sizeof(struct sockaddr_storage));
+ CHKiRet(FillRemHost(pNew, &addr));
+
+ /* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */
+ if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(iNewSock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket %d", errno, iNewSock);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ pNew->sock = iNewSock;
+ *ppNew = (nsd_t*) pNew;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pNew != NULL)
+ nsd_ptcpDestruct(&pNew);
+ /* the close may be redundant, but that doesn't hurt... */
+ sockClose(&iNewSock);
+ }
+
+ RETiRet;
+}
+
+
+/* initialize tcp sockets for a listner. The initialized sockets are passed to the
+ * app-level caller via a callback.
+ * pLstnPort must point to a port name or number. NULL is NOT permitted. pLstnIP
+ * points to the port to listen to (NULL means "all"), iMaxSess has the maximum
+ * number of sessions permitted.
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal ATTR_NONNULL(1,3,5)
+LstnInit(netstrms_t *const pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ const int iSessMax, const tcpLstnParams_t *const cnf_params)
+{
+ DEFiRet;
+ netstrm_t *pNewStrm = NULL;
+ nsd_t *pNewNsd = NULL;
+ int error, maxs, on = 1;
+ int isIPv6 = 0;
+ int sock = -1;
+ int numSocks;
+ int sockflags;
+ int port_override = 0; /* if dyn port (0): use this for actually bound port */
+ struct addrinfo hints, *res = NULL, *r;
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
+ } savecast;
+
+ ISOBJ_TYPE_assert(pNS, netstrms);
+ assert(fAddLstn != NULL);
+ assert(cnf_params->pszPort != NULL);
+ assert(iSessMax >= 0);
+
+ dbgprintf("creating tcp listen socket on port %s\n", cnf_params->pszPort);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = glbl.GetDefPFFamily(runConf);
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo((const char*)cnf_params->pszAddr, (const char*) cnf_params->pszPort, &hints, &res);
+ if(error) {
+ LogError(0, RS_RET_INVALID_PORT, "error querying port '%s': %s",
+ (cnf_params->pszAddr == NULL) ? "**UNSPECIFIED**" : (const char*) cnf_params->pszAddr,
+ gai_strerror(error));
+ ABORT_FINALIZE(RS_RET_INVALID_PORT);
+ }
+
+ /* Count max number of sockets we may open */
+ for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+
+ numSocks = 0; /* num of sockets counter at start of array */
+ for(r = res; r != NULL ; r = r->ai_next) {
+ if(port_override != 0) {
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ if(r->ai_family == AF_INET6) {
+ savecast.ipv6->sin6_port = port_override;
+ } else {
+ savecast.ipv4->sin_port = port_override;
+ }
+ }
+ sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(sock < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) {
+ dbgprintf("error %d creating tcp listen socket", errno);
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ }
+ continue;
+ }
+
+ #ifdef IPV6_V6ONLY
+ if(r->ai_family == AF_INET6) {
+ isIPv6 = 1;
+ int iOn = 1;
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&iOn, sizeof (iOn)) < 0) {
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+ #endif
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ dbgprintf("error %d setting tcp socket option\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* We use non-blocking IO! */
+ if((sockflags = fcntl(sock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(sock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+ #if !defined(_AIX) && !defined(BSD)
+ if(net.should_use_so_bsdcompat()) {
+ if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ LogError(errno, NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+ #endif
+
+ if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0)
+ #ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+ #endif
+ ) {
+ /* TODO: check if *we* bound the socket - else we *have* an error! */
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(errno, NO_ERRCODE, "Error while binding tcp socket");
+ dbgprintf("error %d while binding tcp socket: %s\n", errno, errStr);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* if we bind to dynamic port (port 0 given), we will do so consistently. Thus
+ * once we got a dynamic port, we will keep it and use it for other protocols
+ * as well. As of my understanding, this should always work as the OS does not
+ * pick a port that is used by some protocol (well, at least this looks very
+ * unlikely...). If our asusmption is wrong, we should iterate until we find a
+ * combination that works - it is very unusual to have the same service listen
+ * on differnt ports on IPv4 and IPv6.
+ */
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ const int currport = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port;
+ if(currport == 0) {
+ socklen_t socklen_r = r->ai_addrlen;
+ if(getsockname(sock, r->ai_addr, &socklen_r) == -1) {
+ LogError(errno, NO_ERRCODE, "nsd_ptcp: ListenPortFileName: getsockname:"
+ "error while trying to get socket");
+ }
+ r->ai_addrlen = socklen_r;
+ savecast.sa = (struct sockaddr*)r->ai_addr;
+ port_override = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port;
+ if(cnf_params->pszLstnPortFileName != NULL) {
+ FILE *fp;
+ if((fp = fopen((const char*)cnf_params->pszLstnPortFileName, "w+")) == NULL) {
+ LogError(errno, RS_RET_IO_ERROR, "nsd_ptcp: ListenPortFileName: "
+ "error while trying to open file");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ if(isIPv6) {
+ fprintf(fp, "%d", ntohs(savecast.ipv6->sin6_port));
+ } else {
+ fprintf(fp, "%d", ntohs(savecast.ipv4->sin_port));
+ }
+ fclose(fp);
+ }
+ }
+
+ if(listen(sock, iSessMax / 10 + 5) < 0) {
+ /* If the listen fails, it most probably fails because we ask
+ * for a too-large backlog. So in this case we first set back
+ * to a fixed, reasonable, limit that should work. Only if
+ * that fails, too, we give up.
+ */
+ dbgprintf("listen with a backlog of %d failed - retrying with default of 32.\n",
+ iSessMax / 10 + 5);
+ if(listen(sock, 32) < 0) {
+ dbgprintf("tcp listen error %d, suspending\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+
+
+ /* if we reach this point, we were able to obtain a valid socket, so we can
+ * construct a new netstrm obj and hand it over to the upper layers for inclusion
+ * into their socket array. -- rgerhards, 2008-04-23
+ */
+ CHKiRet(pNS->Drvr.Construct(&pNewNsd));
+ CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock));
+ CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS)));
+ CHKiRet(pNS->Drvr.SetCheckExtendedKeyUsage(pNewNsd, netstrms.GetDrvrCheckExtendedKeyUsage(pNS)));
+ CHKiRet(pNS->Drvr.SetPrioritizeSAN(pNewNsd, netstrms.GetDrvrPrioritizeSAN(pNS)));
+ CHKiRet(pNS->Drvr.SetTlsCAFile(pNewNsd, netstrms.GetDrvrTlsCAFile(pNS)));
+ CHKiRet(pNS->Drvr.SetTlsCRLFile(pNewNsd, netstrms.GetDrvrTlsCRLFile(pNS)));
+ CHKiRet(pNS->Drvr.SetTlsKeyFile(pNewNsd, netstrms.GetDrvrTlsKeyFile(pNS)));
+ CHKiRet(pNS->Drvr.SetTlsCertFile(pNewNsd, netstrms.GetDrvrTlsCertFile(pNS)));
+ CHKiRet(pNS->Drvr.SetTlsVerifyDepth(pNewNsd, netstrms.GetDrvrTlsVerifyDepth(pNS)));
+ CHKiRet(pNS->Drvr.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS)));
+ CHKiRet(pNS->Drvr.SetPermitExpiredCerts(pNewNsd, netstrms.GetDrvrPermitExpiredCerts(pNS)));
+ CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS)));
+ CHKiRet(pNS->Drvr.SetGnutlsPriorityString(pNewNsd, netstrms.GetDrvrGnutlsPriorityString(pNS)));
+
+ CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm));
+ pNewStrm->pDrvrData = (nsd_t*) pNewNsd;
+ if(pNS->fLstnInitDrvr != NULL) {
+ CHKiRet(pNS->fLstnInitDrvr(pNewStrm));
+ }
+ CHKiRet(fAddLstn(pUsr, pNewStrm));
+ pNewStrm = NULL;
+ /* sock has been handed over by SetSock() above, so invalidate it here
+ * coverity scan falsely identifies this as ressource leak
+ */
+ sock = -1;
+ ++numSocks;
+ }
+
+ if(numSocks != maxs)
+ dbgprintf("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", numSocks, maxs);
+
+ if(numSocks == 0) {
+ dbgprintf("No TCP listen sockets could successfully be initialized\n");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
+ }
+
+finalize_it:
+ if(sock != -1) {
+ close(sock);
+ }
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(pNewStrm != NULL)
+ netstrm.Destruct(&pNewStrm);
+ else if(pNewNsd != NULL)
+ pNS->Drvr.Destruct(&pNewNsd);
+ }
+
+ RETiRet;
+}
+
+/* receive data from a tcp socket
+ * The lenBuf parameter must contain the max buffer size on entry and contains
+ * the number of octets read (or -1 in case of error) on exit. This function
+ * never blocks, not even when called on a blocking socket. That is important
+ * for client sockets, which are set to block during send, but should not
+ * block when trying to read data. If *pLenBuf is -1, an error occurred and
+ * oserr holds the exact error cause.
+ * rgerhards, 2008-03-17
+ */
+static rsRetVal
+Rcv(nsd_t *pNsd, uchar *pRcvBuf, ssize_t *pLenBuf, int *const oserr)
+{
+ char errStr[1024];
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(oserr != NULL);
+/* AIXPORT : MSG_DONTWAIT not supported */
+#if defined (_AIX)
+#define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
+ *pLenBuf = recv(pThis->sock, pRcvBuf, *pLenBuf, MSG_DONTWAIT);
+ *oserr = errno;
+
+ if(*pLenBuf == 0) {
+ ABORT_FINALIZE(RS_RET_CLOSED);
+ } else if (*pLenBuf < 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ dbgprintf("error during recv on NSD %p: %s\n", pNsd, errStr);
+ ABORT_FINALIZE(RS_RET_RCV_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* send a buffer. On entry, pLenBuf contains the number of octets to
+ * write. On exit, it contains the number of octets actually written.
+ * If this number is lower than on entry, only a partial buffer has
+ * been written.
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ssize_t written;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ written = send(pThis->sock, pBuf, *pLenBuf, 0);
+
+ if(written == -1) {
+ switch(errno) {
+ case EAGAIN:
+ case EINTR:
+ /* this is fine, just retry... */
+ written = 0;
+ break;
+ default:
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ break;
+ }
+ }
+
+ *pLenBuf = written;
+finalize_it:
+ RETiRet;
+}
+
+
+/* Enable KEEPALIVE handling on the socket.
+ * rgerhards, 2009-06-02
+ */
+static rsRetVal
+EnableKeepAlive(nsd_t *pNsd)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ int ret;
+ int optval;
+ socklen_t optlen;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ optval = 1;
+ optlen = sizeof(optval);
+ ret = setsockopt(pThis->sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
+ if(ret < 0) {
+ dbgprintf("EnableKeepAlive socket call returns error %d\n", ret);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+# if defined(IPPROTO_TCP) && defined(TCP_KEEPCNT)
+ if(pThis->iKeepAliveProbes > 0) {
+ optval = pThis->iKeepAliveProbes;
+ optlen = sizeof(optval);
+ ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(ret, NO_ERRCODE, "imptcp cannot set keepalive probes - ignored");
+ }
+
+# if defined(IPPROTO_TCP) && defined(TCP_KEEPIDLE)
+ if(pThis->iKeepAliveTime > 0) {
+ optval = pThis->iKeepAliveTime;
+ optlen = sizeof(optval);
+ ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(ret, NO_ERRCODE, "imptcp cannot set keepalive time - ignored");
+ }
+
+# if defined(IPPROTO_TCP) && defined(TCP_KEEPCNT)
+ if(pThis->iKeepAliveIntvl > 0) {
+ optval = pThis->iKeepAliveIntvl;
+ optlen = sizeof(optval);
+ ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);
+ } else {
+ ret = 0;
+ }
+# else
+ ret = -1;
+# endif
+ if(ret < 0) {
+ LogError(errno, NO_ERRCODE, "imptcp cannot set keepalive intvl - ignored");
+ }
+
+ dbgprintf("KEEPALIVE enabled for socket %d\n", pThis->sock);
+
+finalize_it:
+ RETiRet;
+
+}
+
+
+/* open a connection to a remote host (server).
+ * rgerhards, 2008-03-19
+ */
+static rsRetVal
+Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device)
+{
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(port != NULL);
+ assert(host != NULL);
+ assert(pThis->sock == -1);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo((char*)host, (char*)port, &hints, &res) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "cannot resolve hostname '%s'",
+ host);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* We need to copy Remote Hostname here for error logging purposes */
+ if((pThis->pRemHostName = malloc(strlen((char*)host)+1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ memcpy(pThis->pRemHostName, host, strlen((char*)host)+1);
+
+ if((pThis->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "cannot bind socket for %s:%s",
+ host, port);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if(device) {
+# if defined(SO_BINDTODEVICE)
+ if(setsockopt(pThis->sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0)
+# endif
+ {
+ dbgprintf("setsockopt(SO_BINDTODEVICE) failed\n");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ }
+
+ if(connect(pThis->sock, res->ai_addr, res->ai_addrlen) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "cannot connect to %s:%s",
+ host, port);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ sockClose(&pThis->sock);
+ }
+
+ RETiRet;
+}
+
+
+/* get the remote hostname. The returned hostname must be freed by the
+ * caller.
+ * rgerhards, 2008-04-24
+ */
+static rsRetVal
+GetRemoteHName(nsd_t *pNsd, uchar **ppszHName)
+{
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(ppszHName != NULL);
+
+ // TODO: how can the RemHost be empty?
+ CHKmalloc(*ppszHName = (uchar*)strdup(pThis->pRemHostName == NULL ? "" : (char*) pThis->pRemHostName));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function checks if the connection is still alive - well, kind of... It
+ * is primarily being used for plain TCP syslog and it is quite a hack. However,
+ * as it seems to work, it is worth supporting it. The bottom line is that it
+ * should not be called by anything else but a plain tcp syslog sender.
+ * In order for it to work, it must be called *immediately* *before* the send()
+ * call. For details about what is done, see here:
+ * http://blog.gerhards.net/2008/06/getting-bit-more-reliability-from-plain.html
+ * rgerhards, 2008-06-09
+ */
+static rsRetVal
+CheckConnection(nsd_t *pNsd)
+{
+ DEFiRet;
+ int rc;
+ char msgbuf[1]; /* dummy */
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+
+ rc = recv(pThis->sock, msgbuf, 1, MSG_DONTWAIT | MSG_PEEK);
+ if(rc == 0) {
+ dbgprintf("CheckConnection detected broken connection - closing it (rc %d, errno %d)\n", rc, errno);
+ /* in this case, the remote peer had shut down the connection and we
+ * need to close our side, too.
+ */
+ sockClose(&pThis->sock);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the remote host's IP address. Caller must Destruct the object.
+ */
+static rsRetVal
+GetRemoteIP(nsd_t *pNsd, prop_t **ip)
+{
+ DEFiRet;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ prop.AddRef(pThis->remoteIP);
+ *ip = pThis->remoteIP;
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsd_ptcp)
+CODESTARTobjQueryInterface(nsd_ptcp)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_ptcpConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_ptcpDestruct;
+ pIf->Abort = Abort;
+ pIf->GetRemAddr = GetRemAddr;
+ pIf->GetSock = GetSock;
+ pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
+ pIf->SetAuthMode = SetAuthMode;
+ pIf->SetPermitExpiredCerts = SetPermitExpiredCerts;
+ pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
+ pIf->SetPermPeers = SetPermPeers;
+ pIf->Rcv = Rcv;
+ pIf->Send = Send;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
+ pIf->Connect = Connect;
+ pIf->GetRemoteHName = GetRemoteHName;
+ pIf->GetRemoteIP = GetRemoteIP;
+ pIf->CheckConnection = CheckConnection;
+ pIf->EnableKeepAlive = EnableKeepAlive;
+ pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
+ pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ pIf->SetKeepAliveTime = SetKeepAliveTime;
+ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage;
+ pIf->SetPrioritizeSAN = SetPrioritizeSAN;
+ pIf->SetTlsVerifyDepth = SetTlsVerifyDepth;
+ pIf->SetTlsCAFile = SetTlsCAFile;
+ pIf->SetTlsCRLFile = SetTlsCRLFile;
+ pIf->SetTlsKeyFile = SetTlsKeyFile;
+ pIf->SetTlsCertFile = SetTlsCertFile;
+finalize_it:
+ENDobjQueryInterface(nsd_ptcp)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsd_ptcp, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsd_ptcp)
+ /* release objects we no longer need */
+ objRelease(net, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(netstrm, DONT_LOAD_LIB);
+ objRelease(netstrms, LM_NETSTRMS_FILENAME);
+ENDObjClassExit(nsd_ptcp)
+
+
+/* Initialize the nsd_ptcp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsd_ptcp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, CORE_COMPONENT));
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+
+ /* set our own handlers */
+ENDObjClassInit(nsd_ptcp)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+# ifdef HAVE_EPOLL_CREATE /* module only available if epoll() is supported! */
+ nsdpoll_ptcpClassExit();
+# endif
+ nsdsel_ptcpClassExit();
+ nsd_ptcpClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(nsd_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+# ifdef HAVE_EPOLL_CREATE /* module only available if epoll() is supported! */
+ CHKiRet(nsdpoll_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+# endif
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/nsd_ptcp.h b/runtime/nsd_ptcp.h
new file mode 100644
index 0000000..1c91718
--- /dev/null
+++ b/runtime/nsd_ptcp.h
@@ -0,0 +1,52 @@
+/* An implementation of the nsd interface for plain tcp sockets.
+ *
+ * Copyright 2007-2020 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSD_PTCP_H
+#define INCLUDED_NSD_PTCP_H
+
+#include <sys/socket.h>
+#include "tcpsrv.h"
+
+#include "nsd.h"
+typedef nsd_if_t nsd_ptcp_if_t; /* we just *implement* this interface */
+
+/* the nsd_ptcp object */
+struct nsd_ptcp_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ prop_t *remoteIP; /**< IP address of remote peer (currently used in server mode, only) */
+ uchar *pRemHostName; /**< host name of remote peer (currently used in server mode, only) */
+ struct sockaddr_storage remAddr; /**< remote addr as sockaddr - used for legacy ACL code */
+ int sock; /**< the socket we use for regular, single-socket, operations */
+ int iKeepAliveIntvl; /**< socket layer KEEPALIVE interval */
+ int iKeepAliveProbes; /**< socket layer KEEPALIVE probes */
+ int iKeepAliveTime; /**< socket layer KEEPALIVE timeout */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsd_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsd_ptcp);
+
+/* the name of our library binary */
+#define LM_NSD_PTCP_FILENAME "lmnsd_ptcp"
+
+#endif /* #ifndef INCLUDED_NSD_PTCP_H */
diff --git a/runtime/nsdpoll_ptcp.c b/runtime/nsdpoll_ptcp.c
new file mode 100644
index 0000000..641ae10
--- /dev/null
+++ b/runtime/nsdpoll_ptcp.c
@@ -0,0 +1,320 @@
+/* nsdpoll_ptcp.c
+ *
+ * An implementation of the nsd epoll() interface for plain tcp sockets.
+ *
+ * Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#ifdef HAVE_EPOLL_CREATE /* this module requires epoll! */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_SYS_EPOLL_H
+# include <sys/epoll.h>
+#endif
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "srUtils.h"
+#include "nspoll.h"
+#include "nsd_ptcp.h"
+#include "nsdpoll_ptcp.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+
+/* -START------------------------- helpers for event list ------------------------------------ */
+
+/* add new entry to list. We assume that the fd is not already present and DO NOT check this!
+ * Returns newly created entry in pEvtLst.
+ * Note that we currently need to use level-triggered mode, because the upper layers do not work
+ * in parallel. As such, in edge-triggered mode we may not get notified, because new data comes
+ * in after we have read everything that was present. To use ET mode, we need to change the upper
+ * peers so that they immediately start a new wait before processing the data read. That obviously
+ * requires more elaborate redesign and we postpone this until the current more simplictic mode has
+ * been proven OK in practice.
+ * rgerhards, 2009-11-18
+ */
+static rsRetVal
+addEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr, int mode, nsd_ptcp_t *pSock, nsdpoll_epollevt_lst_t **pEvtLst)
+{
+ nsdpoll_epollevt_lst_t *pNew;
+ DEFiRet;
+
+ CHKmalloc(pNew = (nsdpoll_epollevt_lst_t*) calloc(1, sizeof(nsdpoll_epollevt_lst_t)));
+ pNew->id = id;
+ pNew->pUsr = pUsr;
+ pNew->pSock = pSock;
+ pNew->event.events = 0; /* TODO: at some time we should be able to use EPOLLET */
+ if(mode & NSDPOLL_IN)
+ pNew->event.events |= EPOLLIN;
+ if(mode & NSDPOLL_OUT)
+ pNew->event.events |= EPOLLOUT;
+ pNew->event.data.ptr = pNew;
+ pthread_mutex_lock(&pThis->mutEvtLst);
+ pNew->pNext = pThis->pRoot;
+ pThis->pRoot = pNew;
+ pthread_mutex_unlock(&pThis->mutEvtLst);
+ *pEvtLst = pNew;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* find and unlink the entry identified by id/pUsr from the list.
+ * rgerhards, 2009-11-23
+ */
+static rsRetVal
+unlinkEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr, nsdpoll_epollevt_lst_t **ppEvtLst)
+{
+ nsdpoll_epollevt_lst_t *pEvtLst;
+ nsdpoll_epollevt_lst_t *pPrev = NULL;
+ DEFiRet;
+
+ pthread_mutex_lock(&pThis->mutEvtLst);
+ pEvtLst = pThis->pRoot;
+ while(pEvtLst != NULL && !(pEvtLst->id == id && pEvtLst->pUsr == pUsr)) {
+ pPrev = pEvtLst;
+ pEvtLst = pEvtLst->pNext;
+ }
+ if(pEvtLst == NULL)
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+
+ *ppEvtLst = pEvtLst;
+
+ /* unlink */
+ if(pPrev == NULL)
+ pThis->pRoot = pEvtLst->pNext;
+ else
+ pPrev->pNext = pEvtLst->pNext;
+
+finalize_it:
+ pthread_mutex_unlock(&pThis->mutEvtLst);
+ RETiRet;
+}
+
+
+/* destruct the provided element. It must already be unlinked from the list.
+ * rgerhards, 2009-11-23
+ */
+static rsRetVal
+delEvent(nsdpoll_epollevt_lst_t **ppEvtLst) {
+ DEFiRet;
+ free(*ppEvtLst);
+ *ppEvtLst = NULL;
+ RETiRet;
+}
+
+
+/* -END--------------------------- helpers for event list ------------------------------------ */
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsdpoll_ptcp) /* be sure to specify the object type also in END macro! */
+#if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1)
+ DBGPRINTF("nsdpoll_ptcp uses epoll_create1()\n");
+ pThis->efd = epoll_create1(EPOLL_CLOEXEC);
+ if(pThis->efd < 0 && errno == ENOSYS)
+#endif
+ {
+ DBGPRINTF("nsdpoll_ptcp uses epoll_create()\n");
+ pThis->efd = epoll_create(100); /* size is ignored in newer kernels, but 100 is not bad... */
+ }
+
+ if(pThis->efd < 0) {
+ DBGPRINTF("epoll_create1() could not create fd\n");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ pthread_mutex_init(&pThis->mutEvtLst, NULL);
+finalize_it:
+ENDobjConstruct(nsdpoll_ptcp)
+
+
+/* destructor for the nsdpoll_ptcp object */
+BEGINobjDestruct(nsdpoll_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
+ nsdpoll_epollevt_lst_t *node;
+ nsdpoll_epollevt_lst_t *nextnode;
+CODESTARTobjDestruct(nsdpoll_ptcp)
+ /* we check if the epoll list still holds entries. This may happen, but
+ * is a bit unusual.
+ */
+ if(pThis->pRoot != NULL) {
+ for(node = pThis->pRoot ; node != NULL ; node = nextnode) {
+ nextnode = node->pNext;
+ dbgprintf("nsdpoll_ptcp destruct, need to destruct node %p\n", node);
+ delEvent(&node);
+ }
+ }
+ pthread_mutex_destroy(&pThis->mutEvtLst);
+ENDobjDestruct(nsdpoll_ptcp)
+
+
+/* Modify socket set */
+static rsRetVal
+Ctl(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int mode, int op) {
+ nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll;
+ nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+ nsdpoll_epollevt_lst_t *pEventLst;
+ int errSave;
+ char errStr[512];
+ DEFiRet;
+
+ if(op == NSDPOLL_ADD) {
+ dbgprintf("adding nsdpoll entry %d/%p, sock %d\n", id, pUsr, pSock->sock);
+ CHKiRet(addEvent(pThis, id, pUsr, mode, pSock, &pEventLst));
+ if(epoll_ctl(pThis->efd, EPOLL_CTL_ADD, pSock->sock, &pEventLst->event) < 0) {
+ errSave = errno;
+ rs_strerror_r(errSave, errStr, sizeof(errStr));
+ LogError(errSave, RS_RET_ERR_EPOLL_CTL,
+ "epoll_ctl failed on fd %d, id %d/%p, op %d with %s\n",
+ pSock->sock, id, pUsr, mode, errStr);
+ }
+ } else if(op == NSDPOLL_DEL) {
+ dbgprintf("removing nsdpoll entry %d/%p, sock %d\n", id, pUsr, pSock->sock);
+ CHKiRet(unlinkEvent(pThis, id, pUsr, &pEventLst));
+ if(epoll_ctl(pThis->efd, EPOLL_CTL_DEL, pSock->sock, &pEventLst->event) < 0) {
+ errSave = errno;
+ rs_strerror_r(errSave, errStr, sizeof(errStr));
+ LogError(errSave, RS_RET_ERR_EPOLL_CTL,
+ "epoll_ctl failed on fd %d, id %d/%p, op %d with %s\n",
+ pSock->sock, id, pUsr, mode, errStr);
+ ABORT_FINALIZE(RS_RET_ERR_EPOLL_CTL);
+ }
+ CHKiRet(delEvent(&pEventLst));
+ } else {
+ dbgprintf("program error: invalid NSDPOLL_mode %d - ignoring request\n", op);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Wait for io to become ready. After the successful call, idRdy contains the
+ * id set by the caller for that i/o event, ppUsr is a pointer to a location
+ * where the user pointer shall be stored.
+ * numEntries contains the maximum number of entries on entry and the actual
+ * number of entries actually read on exit.
+ * rgerhards, 2009-11-18
+ */
+static rsRetVal
+Wait(nsdpoll_t *pNsdpoll, int timeout, int *numEntries, nsd_epworkset_t workset[])
+{
+ nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll;
+ nsdpoll_epollevt_lst_t *pOurEvt;
+ struct epoll_event event[128];
+ int nfds;
+ int i;
+ DEFiRet;
+
+ assert(workset != NULL);
+
+ if(*numEntries > 128)
+ *numEntries = 128;
+ DBGPRINTF("doing epoll_wait for max %d events\n", *numEntries);
+ nfds = epoll_wait(pThis->efd, event, *numEntries, timeout);
+ if(nfds == -1) {
+ if(errno == EINTR) {
+ ABORT_FINALIZE(RS_RET_EINTR);
+ } else {
+ DBGPRINTF("epoll() returned with error code %d\n", errno);
+ ABORT_FINALIZE(RS_RET_ERR_EPOLL);
+ }
+ } else if(nfds == 0) {
+ ABORT_FINALIZE(RS_RET_TIMEOUT);
+ }
+
+ /* we got valid events, so tell the caller... */
+ DBGPRINTF("epoll returned %d entries\n", nfds);
+ for(i = 0 ; i < nfds ; ++i) {
+ pOurEvt = (nsdpoll_epollevt_lst_t*) event[i].data.ptr;
+ workset[i].id = pOurEvt->id;
+ workset[i].pUsr = pOurEvt->pUsr;
+ }
+ *numEntries = nfds;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ------------------------------ end support for the epoll() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdpoll_ptcp)
+CODESTARTobjQueryInterface(nsdpoll_ptcp)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdpoll_t**)) nsdpoll_ptcpConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdpoll_t**)) nsdpoll_ptcpDestruct;
+ pIf->Ctl = Ctl;
+ pIf->Wait = Wait;
+finalize_it:
+ENDobjQueryInterface(nsdpoll_ptcp)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdpoll_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdpoll_ptcp)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(nsdpoll_ptcp)
+
+
+/* Initialize the nsdpoll_ptcp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdpoll_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(nsdpoll_ptcp)
+#else
+
+#ifdef __xlc__ /* Xlc require some code, even unused, in source file*/
+static void dummy(void) {}
+#endif
+
+#endif /* #ifdef HAVE_EPOLL_CREATE this module requires epoll! */
+
+/* vi:set ai:
+ */
diff --git a/runtime/nsdpoll_ptcp.h b/runtime/nsdpoll_ptcp.h
new file mode 100644
index 0000000..0c0109b
--- /dev/null
+++ b/runtime/nsdpoll_ptcp.h
@@ -0,0 +1,61 @@
+/* An implementation of the nsd poll interface for plain tcp sockets.
+ *
+ * Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSDPOLL_PTCP_H
+#define INCLUDED_NSDPOLL_PTCP_H
+
+#include "nsd.h"
+#ifdef HAVE_SYS_EPOLL_H
+# include <sys/epoll.h>
+#endif
+typedef nsdpoll_if_t nsdpoll_ptcp_if_t; /* we just *implement* this interface */
+/* a helper object to keep track of the epoll event records
+ * Note that we need to keep track of that list because we need to
+ * free the events when they are no longer needed.
+ */
+typedef struct nsdpoll_epollevt_lst_s nsdpoll_epollevt_lst_t;
+struct nsdpoll_epollevt_lst_s {
+#ifdef HAVE_SYS_EPOLL_H
+ epoll_event_t event;
+#endif
+ int id;
+ void *pUsr;
+ nsd_ptcp_t *pSock; /* our associated netstream driver data */
+ nsdpoll_epollevt_lst_t *pNext;
+};
+
+/* the nsdpoll_ptcp object */
+struct nsdpoll_ptcp_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ int efd; /* file descriptor used by epoll */
+ nsdpoll_epollevt_lst_t *pRoot; /* Root of the epoll event list */
+ pthread_mutex_t mutEvtLst;
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdpoll_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdpoll_ptcp);
+
+#endif /* #ifndef INCLUDED_NSDPOLL_PTCP_H */
diff --git a/runtime/nsdsel_gtls.c b/runtime/nsdsel_gtls.c
new file mode 100644
index 0000000..01cfb05
--- /dev/null
+++ b/runtime/nsdsel_gtls.c
@@ -0,0 +1,317 @@
+/* nsdsel_gtls.c
+ *
+ * An implementation of the nsd select() interface for GnuTLS.
+ *
+ * Copyright (C) 2008-2016 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+#include <gnutls/gnutls.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "nsd.h"
+#include "nsd_gtls.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_ptcp.h"
+#include "nsdsel_gtls.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(nsdsel_ptcp)
+
+static rsRetVal
+gtlsHasRcvInBuffer(nsd_gtls_t *pThis)
+{
+ /* we have a valid receive buffer one such is allocated and
+ * NOT exhausted!
+ */
+ DBGPRINTF("hasRcvInBuffer on nsd %p: pszRcvBuf %p, lenRcvBuf %d\n", pThis,
+ pThis->pszRcvBuf, pThis->lenRcvBuf);
+ return(pThis->pszRcvBuf != NULL && pThis->lenRcvBuf != -1);
+ }
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsdsel_gtls) /* be sure to specify the object type also in END macro! */
+ iRet = nsdsel_ptcp.Construct(&pThis->pTcp);
+ENDobjConstruct(nsdsel_gtls)
+
+
+/* destructor for the nsdsel_gtls object */
+BEGINobjDestruct(nsdsel_gtls) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsdsel_gtls)
+ if(pThis->pTcp != NULL)
+ nsdsel_ptcp.Destruct(&pThis->pTcp);
+ENDobjDestruct(nsdsel_gtls)
+
+
+/* Add a socket to the select set */
+static rsRetVal
+Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+ nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
+ DBGPRINTF("Add on nsd %p:\n", pNsdGTLS);
+ if(pNsdGTLS->iMode == 1) {
+ if(waitOp == NSDSEL_RD && gtlsHasRcvInBuffer(pNsdGTLS)) {
+ ++pThis->iBufferRcvReady;
+ dbgprintf("nsdsel_gtls: data already present in buffer, initiating "
+ "dummy select %p->iBufferRcvReady=%d\n",
+ pThis, pThis->iBufferRcvReady);
+ FINALIZE;
+ }
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ if(gnutls_record_get_direction(pNsdGTLS->sess) == 0) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_RD));
+ } else {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_WR));
+ }
+ FINALIZE;
+ }
+ }
+
+ dbgprintf("nsdsel_gtls: reached end on nsd %p, calling nsdsel_ptcp.Add with waitOp %d... \n", pNsdGTLS, waitOp);
+ /* if we reach this point, we need no special handling */
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* perform the select() piNumReady returns how many descriptors are ready for IO
+ * TODO: add timeout!
+ */
+static rsRetVal
+Select(nsdsel_t *pNsdsel, int *piNumReady)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ if(pThis->iBufferRcvReady > 0) {
+ /* we still have data ready! */
+ *piNumReady = pThis->iBufferRcvReady;
+ dbgprintf("nsdsel_gtls: doing dummy select for %p->iBufferRcvReady=%d, data present\n",
+ pThis, pThis->iBufferRcvReady);
+ } else {
+ iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady);
+ }
+
+ RETiRet;
+}
+
+
+/* retry an interrupted GTLS operation
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+doRetry(nsd_gtls_t *pNsd)
+{
+ DEFiRet;
+ int gnuRet;
+
+ dbgprintf("doRetry: GnuTLS requested retry of %d operation - executing\n", pNsd->rtryCall);
+
+ /* We follow a common scheme here: first, we do the systen call and
+ * then we check the result. So far, the result is checked after the
+ * switch, because the result check is the same for all calls. Note that
+ * this may change once we deal with the read and write calls (but
+ * probably this becomes an issue only when we begin to work on TLS
+ * for relp). -- rgerhards, 2008-04-30
+ */
+ switch(pNsd->rtryCall) {
+ case gtlsRtry_handshake:
+ gnuRet = gnutls_handshake(pNsd->sess);
+ if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+ dbgprintf("doRetry: GnuTLS handshake retry did not finish - "
+ "setting to retry (this is OK and can happen)\n");
+ FINALIZE;
+ } else if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
+ /* we got a handshake, now check authorization */
+ CHKiRet(gtlsChkPeerAuth(pNsd));
+ } else {
+ uchar *pGnuErr = gtlsStrerror(gnuRet);
+ LogError(0, RS_RET_TLS_HANDSHAKE_ERR,
+ "GnuTLS handshake retry returned error: %s\n", pGnuErr);
+ free(pGnuErr);
+ ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
+ }
+ break;
+ case gtlsRtry_recv:
+ dbgprintf("doRetry: retrying gtls recv, nsd: %p\n", pNsd);
+ iRet = gtlsRecordRecv(pNsd);
+ if (iRet == RS_RET_RETRY) {
+ // Check if there is pending data
+ size_t stBytesLeft = gnutls_record_check_pending(pNsd->sess);
+ if (stBytesLeft > 0) {
+ // We are in retry and more data waiting, finalize it
+ goto finalize_it;
+ } else {
+ dbgprintf("doRetry: gtlsRecordRecv returned RETRY, but there is no pending"
+ "data on nsd: %p\n", pNsd);
+ }
+ }
+ pNsd->rtryCall = gtlsRtry_None; /* no more data, we are done */
+ gnuRet = 0;
+ break;
+ case gtlsRtry_None:
+ default:
+ assert(0); /* this shall not happen! */
+ dbgprintf("ERROR: pNsd->rtryCall invalid in nsdsel_gtls.c:%d\n", __LINE__);
+ gnuRet = 0; /* if it happens, we have at least a defined behaviour... ;) */
+ break;
+ }
+
+ if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
+ } else if(gnuRet != GNUTLS_E_AGAIN && gnuRet != GNUTLS_E_INTERRUPTED) {
+ uchar *pErr = gtlsStrerror(gnuRet);
+ LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n",
+ gnuRet, __FILE__, __LINE__, pErr); \
+ free(pErr);
+ pNsd->rtryCall = gtlsRtry_None; /* we are also done... ;) */
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ /* if we are interrupted once again (else case), we do not need to
+ * change our status because we are already setup for retries.
+ */
+
+finalize_it:
+ if(iRet != RS_RET_OK && iRet != RS_RET_CLOSED && iRet != RS_RET_RETRY)
+ pNsd->bAbortConn = 1; /* request abort */
+ RETiRet;
+}
+
+
+/* check if a socket is ready for IO */
+static rsRetVal
+IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
+{
+ DEFiRet;
+ nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel;
+ nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
+ if(pNsdGTLS->iMode == 1) {
+ if(waitOp == NSDSEL_RD && gtlsHasRcvInBuffer(pNsdGTLS)) {
+ *pbIsReady = 1;
+ --pThis->iBufferRcvReady; /* one "pseudo-read" less */
+ dbgprintf("nsdl_gtls: dummy read, decermenting %p->iBufRcvReady, now %d\n",
+ pThis, pThis->iBufferRcvReady);
+ FINALIZE;
+ }
+ if(pNsdGTLS->rtryCall == gtlsRtry_handshake) {
+ CHKiRet(doRetry(pNsdGTLS));
+ /* we used this up for our own internal processing, so the socket
+ * is not ready from the upper layer point of view.
+ */
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ else if(pNsdGTLS->rtryCall == gtlsRtry_recv) {
+ iRet = doRetry(pNsdGTLS);
+ if(iRet == RS_RET_OK) {
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ /* now we must ensure that we do not fall back to PTCP if we have
+ * done a "dummy" select. In that case, we know when the predicate
+ * is not matched here, we do not have data available for this
+ * socket. -- rgerhards, 2010-11-20
+ */
+ if(pThis->iBufferRcvReady) {
+ dbgprintf("nsd_gtls: dummy read, %p->buffer not available for this FD\n", pThis);
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ------------------------------ end support for the select() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdsel_gtls)
+CODESTARTobjQueryInterface(nsdsel_gtls)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdsel_t**)) nsdsel_gtlsConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_gtlsDestruct;
+ pIf->Add = Add;
+ pIf->Select = Select;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nsdsel_gtls)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdsel_gtls, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_gtls)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME);
+ENDObjClassExit(nsdsel_gtls)
+
+
+/* Initialize the nsdsel_gtls class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdsel_gtls, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME));
+
+ /* set our own handlers */
+ENDObjClassInit(nsdsel_gtls)
+/* vi:set ai:
+ */
diff --git a/runtime/nsdsel_gtls.h b/runtime/nsdsel_gtls.h
new file mode 100644
index 0000000..1288097
--- /dev/null
+++ b/runtime/nsdsel_gtls.h
@@ -0,0 +1,41 @@
+/* An implementation of the nsd select interface for GnuTLS.
+ *
+ * Copyright (C) 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSDSEL_GTLS_H
+#define INCLUDED_NSDSEL_GTLS_H
+
+#include "nsd.h"
+typedef nsdsel_if_t nsdsel_gtls_if_t; /* we just *implement* this interface */
+
+/* the nsdsel_gtls object */
+struct nsdsel_gtls_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsdsel_t *pTcp; /* our aggregated ptcp sel handler (which does almost everything) */
+ int iBufferRcvReady; /* number of descriptiors where no RD select is needed because we have data in buf */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdsel_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdsel_gtls);
+
+#endif /* #ifndef INCLUDED_NSDSEL_GTLS_H */
diff --git a/runtime/nsdsel_ossl.c b/runtime/nsdsel_ossl.c
new file mode 100644
index 0000000..cc649cf
--- /dev/null
+++ b/runtime/nsdsel_ossl.c
@@ -0,0 +1,290 @@
+/* nsdsel_ossl.c
+ *
+ * An implementation of the nsd select() interface for OpenSSL.
+ *
+ * Copyright (C) 2018-2018 Adiscon GmbH.
+ * Author: Andre Lorbach
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "net_ossl.h" // Include OpenSSL Helpers
+#include "nsd.h"
+#include "nsd_ossl.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_ptcp.h"
+#include "nsdsel_ossl.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(nsdsel_ptcp)
+
+static rsRetVal
+osslHasRcvInBuffer(nsd_ossl_t *pThis)
+{
+ /* we have a valid receive buffer one such is allocated and
+ * NOT exhausted!
+ */
+ DBGPRINTF("hasRcvInBuffer on nsd %p: pszRcvBuf %p, lenRcvBuf %d\n", pThis,
+ pThis->pszRcvBuf, pThis->lenRcvBuf);
+ return(pThis->pszRcvBuf != NULL && pThis->lenRcvBuf != -1);
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(nsdsel_ossl) /* be sure to specify the object type also in END macro! */
+ iRet = nsdsel_ptcp.Construct(&pThis->pTcp);
+ENDobjConstruct(nsdsel_ossl)
+
+
+/* destructor for the nsdsel_ossl object */
+BEGINobjDestruct(nsdsel_ossl) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsdsel_ossl)
+ if(pThis->pTcp != NULL)
+ nsdsel_ptcp.Destruct(&pThis->pTcp);
+ENDobjDestruct(nsdsel_ossl)
+
+
+/* Add a socket to the select set */
+static rsRetVal
+Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+ nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel;
+ nsd_ossl_t *pNsdOSSL = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ossl);
+ ISOBJ_TYPE_assert(pNsdOSSL, nsd_ossl);
+
+DBGPRINTF("Add on nsd %p:\n", pNsdOSSL);
+
+ if(pNsdOSSL->iMode == 1) {
+ if(waitOp == NSDSEL_RD && osslHasRcvInBuffer(pNsdOSSL)) {
+ ++pThis->iBufferRcvReady;
+ dbgprintf("nsdsel_ossl: data already present in buffer, initiating "
+ "dummy select %p->iBufferRcvReady=%d\n",
+ pThis, pThis->iBufferRcvReady);
+ FINALIZE;
+ }
+ if(pNsdOSSL->rtryCall != osslRtry_None) {
+/* // VERBOSE
+dbgprintf("nsdsel_ossl: rtryOsslErr=%d ... \n", pNsdOSSL->rtryOsslErr);
+*/
+ if (pNsdOSSL->rtryOsslErr == SSL_ERROR_WANT_READ) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, NSDSEL_RD));
+ FINALIZE;
+ } else if (pNsdOSSL->rtryOsslErr == SSL_ERROR_WANT_WRITE) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, NSDSEL_WR));
+ FINALIZE;
+ } else {
+ dbgprintf("nsdsel_ossl: rtryCall=%d, rtryOsslErr=%d, unexpected ... help?! ... \n",
+ pNsdOSSL->rtryCall, pNsdOSSL->rtryOsslErr);
+ ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ }
+
+ } else {
+ dbgprintf("nsdsel_ossl: rtryCall=%d, nothing to do ... \n",
+ pNsdOSSL->rtryCall);
+ }
+ }
+
+ dbgprintf("nsdsel_ossl: reached end, calling nsdsel_ptcp.Add with waitOp %d... \n", waitOp);
+ /* if we reach this point, we need no special handling */
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, waitOp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* perform the select() piNumReady returns how many descriptors are ready for IO
+ * TODO: add timeout!
+ */
+static rsRetVal
+Select(nsdsel_t *pNsdsel, int *piNumReady)
+{
+ DEFiRet;
+ nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ossl);
+ if(pThis->iBufferRcvReady > 0) {
+ /* we still have data ready! */
+ *piNumReady = pThis->iBufferRcvReady;
+ dbgprintf("nsdsel_ossl: doing dummy select, data present\n");
+ } else {
+ iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady);
+ }
+
+ RETiRet;
+}
+
+
+/* retry an interrupted OSSL operation
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+doRetry(nsd_ossl_t *pNsd)
+{
+ DEFiRet;
+ nsd_ossl_t *pNsdOSSL = (nsd_ossl_t*) pNsd;
+
+ dbgprintf("doRetry: requested retry of %d operation - executing\n", pNsd->rtryCall);
+
+ /* We follow a common scheme here: first, we do the systen call and
+ * then we check the result. So far, the result is checked after the
+ * switch, because the result check is the same for all calls. Note that
+ * this may change once we deal with the read and write calls (but
+ * probably this becomes an issue only when we begin to work on TLS
+ * for relp). -- rgerhards, 2008-04-30
+ */
+ switch(pNsd->rtryCall) {
+ case osslRtry_handshake:
+ dbgprintf("doRetry: start osslHandshakeCheck, nsd: %p\n", pNsd);
+ /* Do the handshake again*/
+ CHKiRet(osslHandshakeCheck(pNsdOSSL));
+ pNsd->rtryCall = osslRtry_None; /* we are done */
+ break;
+ case osslRtry_recv:
+ dbgprintf("doRetry: retrying ossl recv, nsd: %p\n", pNsd);
+ CHKiRet(osslRecordRecv(pNsd));
+ pNsd->rtryCall = osslRtry_None; /* we are done */
+ break;
+ case osslRtry_None:
+ default:
+ assert(0); /* this shall not happen! */
+ dbgprintf("doRetry: ERROR, pNsd->rtryCall invalid in nsdsel_ossl.c:%d\n", __LINE__);
+ break;
+ }
+finalize_it:
+ if(iRet != RS_RET_OK && iRet != RS_RET_CLOSED && iRet != RS_RET_RETRY)
+ pNsd->bAbortConn = 1; /* request abort */
+ RETiRet;
+}
+
+
+/* check if a socket is ready for IO */
+static rsRetVal
+IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
+{
+ DEFiRet;
+ nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel;
+ nsd_ossl_t *pNsdOSSL = (nsd_ossl_t*) pNsd;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ossl);
+ ISOBJ_TYPE_assert(pNsdOSSL, nsd_ossl);
+
+DBGPRINTF("nsdsel_ossl IsReady EINTR\n");
+ if(pNsdOSSL->iMode == 1) {
+ if(waitOp == NSDSEL_RD && osslHasRcvInBuffer(pNsdOSSL)) {
+ *pbIsReady = 1;
+ --pThis->iBufferRcvReady; /* one "pseudo-read" less */
+ FINALIZE;
+ }
+ if(pNsdOSSL->rtryCall == osslRtry_handshake) {
+ CHKiRet(doRetry(pNsdOSSL));
+ /* we used this up for our own internal processing, so the socket
+ * is not ready from the upper layer point of view.
+ */
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ else if(pNsdOSSL->rtryCall == osslRtry_recv) {
+ iRet = doRetry(pNsdOSSL);
+ if(iRet == RS_RET_OK) {
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ /* now we must ensure that we do not fall back to PTCP if we have
+ * done a "dummy" select. In that case, we know when the predicate
+ * is not matched here, we do not have data available for this
+ * socket. -- rgerhards, 2010-11-20
+ */
+ if(pThis->iBufferRcvReady) {
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+/* // VERBOSE
+dbgprintf("nsdl_ossl: IsReady before nsdsel_ptcp.IsReady for %p\n", pThis);
+*/
+ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdOSSL->pTcp, waitOp, pbIsReady));
+
+finalize_it:
+ RETiRet;
+}
+/* ------------------------------ end support for the select() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdsel_ossl)
+CODESTARTobjQueryInterface(nsdsel_ossl)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdsel_t**)) nsdsel_osslConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_osslDestruct;
+ pIf->Add = Add;
+ pIf->Select = Select;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nsdsel_ossl)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdsel_ossl, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_ossl)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME);
+ENDObjClassExit(nsdsel_ossl)
+
+
+/* Initialize the nsdsel_ossl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdsel_ossl, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME));
+
+ /* set our own handlers */
+ENDObjClassInit(nsdsel_ossl)
+/* vi:set ai:
+ */
diff --git a/runtime/nsdsel_ossl.h b/runtime/nsdsel_ossl.h
new file mode 100644
index 0000000..bf40c28
--- /dev/null
+++ b/runtime/nsdsel_ossl.h
@@ -0,0 +1,42 @@
+/* An implementation of the nsd select interface for OpenSSL.
+ *
+ * Copyright (C) 2018-2018 Adiscon GmbH.
+ * Author: Andre Lorbach
+*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSDSEL_OSSL_H
+#define INCLUDED_NSDSEL_OSSL_H
+
+#include "nsd.h"
+typedef nsdsel_if_t nsdsel_ossl_if_t; /* we just *implement* this interface */
+
+/* the nsdsel_ossl object */
+struct nsdsel_ossl_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsdsel_t *pTcp; /* our aggregated ptcp sel handler (which does almost everything) */
+ int iBufferRcvReady; /* number of descriptiors where no RD select is needed because we have data in buf */
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdsel_osslCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdsel_ossl);
+
+#endif /* #ifndef INCLUDED_NSDSEL_OSSL_H */
diff --git a/runtime/nsdsel_ptcp.c b/runtime/nsdsel_ptcp.c
new file mode 100644
index 0000000..d77c729
--- /dev/null
+++ b/runtime/nsdsel_ptcp.c
@@ -0,0 +1,221 @@
+/* nsdsel_ptcp.c
+ *
+ * An implementation of the nsd select() interface for plain tcp sockets.
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "nsd_ptcp.h"
+#include "nsdsel_ptcp.h"
+#include "unlimited_select.h"
+
+#define FDSET_INCREMENT 1024 /* increment for struct pollfds array allocation */
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nsdsel_ptcp) /* be sure to specify the object type also in END macro! */
+ pThis->currfds = 0;
+ pThis->maxfds = FDSET_INCREMENT;
+ CHKmalloc(pThis->fds = calloc(FDSET_INCREMENT, sizeof(struct pollfd)));
+finalize_it:
+ENDobjConstruct(nsdsel_ptcp)
+
+
+/* destructor for the nsdsel_ptcp object */
+BEGINobjDestruct(nsdsel_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nsdsel_ptcp)
+ free(pThis->fds);
+ENDobjDestruct(nsdsel_ptcp)
+
+
+/* Add a socket to the select set */
+static rsRetVal ATTR_NONNULL()
+Add(nsdsel_t *const pNsdsel, nsd_t *const pNsd, const nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+ nsdsel_ptcp_t *const pThis = (nsdsel_ptcp_t*) pNsdsel;
+ const nsd_ptcp_t *const pSock = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pSock, nsd_ptcp);
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+
+ if(pThis->currfds == pThis->maxfds) {
+ struct pollfd *newfds;
+ CHKmalloc(newfds = realloc(pThis->fds,
+ sizeof(struct pollfd) * (pThis->maxfds + FDSET_INCREMENT)));
+ pThis->maxfds += FDSET_INCREMENT;
+ pThis->fds = newfds;
+ }
+
+ switch(waitOp) {
+ case NSDSEL_RD:
+ pThis->fds[pThis->currfds].events = POLLIN;
+ break;
+ case NSDSEL_WR:
+ pThis->fds[pThis->currfds].events = POLLOUT;
+ break;
+ case NSDSEL_RDWR:
+ pThis->fds[pThis->currfds].events = POLLIN | POLLOUT;
+ break;
+ }
+ pThis->fds[pThis->currfds].fd = pSock->sock;
+ ++pThis->currfds;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* perform the select() piNumReady returns how many descriptors are ready for IO
+ * TODO: add timeout!
+ */
+static rsRetVal ATTR_NONNULL()
+Select(nsdsel_t *const pNsdsel, int *const piNumReady)
+{
+ DEFiRet;
+ nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
+
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+ assert(piNumReady != NULL);
+
+ /* Output debug first*/
+ if(Debug) {
+ dbgprintf("--------<NSDSEL_PTCP> calling poll, active fds (%d): ", pThis->currfds);
+ for(uint32_t i = 0; i <= pThis->currfds; ++i)
+ dbgprintf("%d ", pThis->fds[i].fd);
+ dbgprintf("\n");
+ }
+ assert(pThis->currfds >= 1);
+
+ /* now do the select */
+ *piNumReady = poll(pThis->fds, pThis->currfds, -1);
+ if(*piNumReady < 0) {
+ if(errno == EINTR) {
+ DBGPRINTF("nsdsel_ptcp received EINTR\n");
+ } else {
+ LogMsg(errno, RS_RET_POLL_ERR, LOG_WARNING,
+ "ndssel_ptcp: poll system call failed, may cause further troubles");
+ }
+ *piNumReady = 0;
+ }
+
+ RETiRet;
+}
+
+
+/* check if a socket is ready for IO */
+static rsRetVal ATTR_NONNULL()
+IsReady(nsdsel_t *const pNsdsel, nsd_t *const pNsd, const nsdsel_waitOp_t waitOp, int *const pbIsReady)
+{
+ DEFiRet;
+ const nsdsel_ptcp_t *const pThis = (nsdsel_ptcp_t*) pNsdsel;
+ const nsd_ptcp_t *const pSock = (nsd_ptcp_t*) pNsd;
+ ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
+ ISOBJ_TYPE_assert(pSock, nsd_ptcp);
+ const int sock = pSock->sock;
+ // TODO: consider doing a binary search
+
+ uint32_t idx;
+ for(idx = 0 ; idx < pThis->currfds ; ++idx) {
+ if(pThis->fds[idx].fd == sock)
+ break;
+ }
+ if(idx >= pThis->currfds) {
+ LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_ERR,
+ "ndssel_ptcp: could not find socket %d which should be present", sock);
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+
+ const short revent = pThis->fds[idx].revents;
+ if (revent & POLLNVAL) {
+ DBGPRINTF("ndssel_ptcp: revent & POLLNVAL is TRUE, we had a race, ignoring, revent = %d", revent);
+ *pbIsReady = 0;
+ }
+ switch(waitOp) {
+ case NSDSEL_RD:
+ *pbIsReady = revent & POLLIN;
+ break;
+ case NSDSEL_WR:
+ *pbIsReady = revent & POLLOUT;
+ break;
+ case NSDSEL_RDWR:
+ *pbIsReady = revent & (POLLIN | POLLOUT);
+ break;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* ------------------------------ end support for the select() interface ------------------------------ */
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nsdsel_ptcp)
+CODESTARTobjQueryInterface(nsdsel_ptcp)
+ if(pIf->ifVersion != nsdCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = (rsRetVal(*)(nsdsel_t**)) nsdsel_ptcpConstruct;
+ pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_ptcpDestruct;
+ pIf->Add = Add;
+ pIf->Select = Select;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nsdsel_ptcp)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nsdsel_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_ptcp)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(nsdsel_ptcp)
+
+
+/* Initialize the nsdsel_ptcp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nsdsel_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDObjClassInit(nsdsel_ptcp)
diff --git a/runtime/nsdsel_ptcp.h b/runtime/nsdsel_ptcp.h
new file mode 100644
index 0000000..87270c9
--- /dev/null
+++ b/runtime/nsdsel_ptcp.h
@@ -0,0 +1,45 @@
+/* An implementation of the nsd select interface for plain tcp sockets.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef INCLUDED_NSDSEL_PTCP_H
+#define INCLUDED_NSDSEL_PTCP_H
+
+#include <poll.h>
+#include "nsd.h"
+typedef nsdsel_if_t nsdsel_ptcp_if_t; /* we just *implement* this interface */
+
+/* the nsdsel_ptcp object */
+struct nsdsel_ptcp_s {
+ BEGINobjInstance;
+ uint32_t maxfds;
+ uint32_t currfds;
+ struct pollfd *fds;
+};
+
+/* interface is defined in nsd.h, we just implement it! */
+#define nsdsel_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION
+
+/* prototypes */
+PROTOTYPEObj(nsdsel_ptcp);
+
+#endif /* #ifndef INCLUDED_NSDSEL_PTCP_H */
diff --git a/runtime/nspoll.c b/runtime/nspoll.c
new file mode 100644
index 0000000..5e17bb1
--- /dev/null
+++ b/runtime/nspoll.c
@@ -0,0 +1,218 @@
+/* nspoll.c
+ *
+ * This is an io waiter interface utilizing the much-more-efficient poll/epoll API.
+ * Note that it may not always be available for a given driver. If so, that is reported
+ * back to the upper peer which then should consult a nssel-based io waiter.
+ *
+ * Work on this module begun 2009-11-18 by Rainer Gerhards.
+ *
+ * Copyright 2009-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "module-template.h"
+#include "netstrm.h"
+#include "nspoll.h"
+#include "rsconf.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+
+/* load our low-level driver. This must be done before any
+ * driver-specific functions (allmost all...) can be carried
+ * out. Note that the driver's .ifIsLoaded is correctly
+ * initialized by calloc() and we depend on that. Please note that
+ * we do some name-mangeling. We know that each nsd driver also needs
+ * a nspoll driver. So we simply append "sel" to the nsd driver name: This,
+ * of course, means that the driver name must match these rules, but that
+ * shouldn't be a real problem.
+ * WARNING: this code is mostly identical to similar code in
+ * netstrms.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+loadDrvr(nspoll_t *pThis)
+{
+ DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
+
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr(runConf);
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsdpoll_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
+
+ pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean
+ * enough. -- rgerhards, 2008-04-18
+ */
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL) {
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
+ }
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nspoll) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(nspoll)
+
+
+/* destructor for the nspoll object */
+BEGINobjDestruct(nspoll) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nspoll)
+ if(pThis->pDrvrData != NULL)
+ pThis->Drvr.Destruct(&pThis->pDrvrData);
+
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ free(pThis->pBaseDrvrName);
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
+ENDobjDestruct(nspoll)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+ConstructFinalize(nspoll_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nspoll);
+ CHKiRet(loadDrvr(pThis));
+ CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData));
+finalize_it:
+ RETiRet;
+}
+
+
+/* Carries out the actual wait (all done in lower layers)
+ */
+static rsRetVal
+Wait(nspoll_t *pThis, int timeout, int *numEntries, nsd_epworkset_t workset[]) {
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nspoll);
+ assert(workset != NULL);
+ iRet = pThis->Drvr.Wait(pThis->pDrvrData, timeout, numEntries, workset);
+ RETiRet;
+}
+
+
+/* set the base driver name. If the driver name
+ * is set to NULL, the previously set name is deleted but
+ * no name set again (which results in the system default being
+ * used)-- rgerhards, 2008-05-05
+ */
+static rsRetVal
+SetDrvrName(nspoll_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nspoll);
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+
+ if(pszName != NULL) {
+ CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* semantics like the epoll_ctl() function, does the same thing.
+ * rgerhards, 2009-11-18
+ */
+static rsRetVal
+Ctl(nspoll_t *pThis, netstrm_t *pStrm, int id, void *pUsr, int mode, int op) {
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nspoll);
+ iRet = pThis->Drvr.Ctl(pThis->pDrvrData, pStrm->pDrvrData, id, pUsr, mode, op);
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nspoll)
+CODESTARTobjQueryInterface(nspoll)
+ if(pIf->ifVersion != nspollCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = nspollConstruct;
+ pIf->ConstructFinalize = ConstructFinalize;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->Destruct = nspollDestruct;
+ pIf->Wait = Wait;
+ pIf->Ctl = Ctl;
+finalize_it:
+ENDobjQueryInterface(nspoll)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nspoll, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nspoll)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(nspoll)
+
+
+/* Initialize the nspoll class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nspoll, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ DBGPRINTF("doing nspollClassInit\n");
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(nspoll)
+/* vi:set ai:
+ */
diff --git a/runtime/nspoll.h b/runtime/nspoll.h
new file mode 100644
index 0000000..08d7da8
--- /dev/null
+++ b/runtime/nspoll.h
@@ -0,0 +1,66 @@
+/* Definitions for the nspoll io activity waiter
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSPOLL_H
+#define INCLUDED_NSPOLL_H
+
+#include "netstrms.h"
+
+/* some operations to be portable when we do not have epoll() available */
+#define NSDPOLL_ADD 1
+#define NSDPOLL_DEL 2
+
+/* and some mode specifiers for waiting on input/output */
+#define NSDPOLL_IN 1 /* EPOLLIN */
+#define NSDPOLL_OUT 2 /* EPOLLOUT */
+/* next is 4, 8, 16, ... - must be bit values, as they are ored! */
+
+/* the nspoll object */
+struct nspoll_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pDrvrData; /**< the driver's data elements */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ nsdpoll_if_t Drvr; /**< our stream driver */
+};
+
+
+/* interface */
+BEGINinterface(nspoll) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nspoll_t **ppThis);
+ rsRetVal (*ConstructFinalize)(nspoll_t *pThis);
+ rsRetVal (*Destruct)(nspoll_t **ppThis);
+ rsRetVal (*Wait)(nspoll_t *pNsdpoll, int timeout, int *numEntries, nsd_epworkset_t workset[]);
+ rsRetVal (*Ctl)(nspoll_t *pNsdpoll, netstrm_t *pStrm, int id, void *pUsr, int mode, int op);
+ rsRetVal (*IsEPollSupported)(void); /* static method */
+ /* v3 - 2013-09-17 by rgerhards */
+ rsRetVal (*SetDrvrName)(nspoll_t *pThis, uchar *name);
+ENDinterface(nspoll)
+#define nspollCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+/* interface change in v2 is that wait supports multiple return objects */
+
+/* prototypes */
+PROTOTYPEObj(nspoll);
+
+/* the name of our library binary */
+#define LM_NSPOLL_FILENAME LM_NETSTRMS_FILENAME
+
+#endif /* #ifndef INCLUDED_NSPOLL_H */
diff --git a/runtime/nssel.c b/runtime/nssel.c
new file mode 100644
index 0000000..bcfbfee
--- /dev/null
+++ b/runtime/nssel.c
@@ -0,0 +1,254 @@
+/* nssel.c
+ *
+ * The io waiter is a helper object enabling us to wait on a set of streams to become
+ * ready for IO - this is modelled after select(). We need this, because
+ * stream drivers may have different concepts. Consequently,
+ * the structure must contain nsd_t's from the same stream driver type
+ * only. This is implemented as a singly-linked list where every
+ * new element is added at the top of the list.
+ *
+ * Work on this module begun 2008-04-22 by Rainer Gerhards.
+ *
+ * Copyright 2008-2014 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "module-template.h"
+#include "netstrm.h"
+#include "nssel.h"
+#include "rsconf.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+
+/* load our low-level driver. This must be done before any
+ * driver-specific functions (allmost all...) can be carried
+ * out. Note that the driver's .ifIsLoaded is correctly
+ * initialized by calloc() and we depend on that. Please note that
+ * we do some name-mangeling. We know that each nsd driver also needs
+ * a nssel driver. So we simply append "sel" to the nsd driver name: This,
+ * of course, means that the driver name must match these rules, but that
+ * shouldn't be a real problem.
+ * WARNING: this code is mostly identical to similar code in
+ * netstrms.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+loadDrvr(nssel_t *pThis)
+{
+ DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
+
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr(runConf);
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsdsel_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
+
+ pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean
+ * enough. -- rgerhards, 2008-04-18
+ */
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL) {
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
+ }
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(nssel) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(nssel)
+
+
+/* destructor for the nssel object */
+BEGINobjDestruct(nssel) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(nssel)
+ if(pThis->pDrvrData != NULL)
+ pThis->Drvr.Destruct(&pThis->pDrvrData);
+
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ free(pThis->pBaseDrvrName);
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
+ENDobjDestruct(nssel)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+ConstructFinalize(nssel_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ CHKiRet(loadDrvr(pThis));
+ CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the base driver name. If the driver name
+ * is set to NULL, the previously set name is deleted but
+ * no name set again (which results in the system default being
+ * used)-- rgerhards, 2008-05-05
+ */
+static rsRetVal
+SetDrvrName(nssel_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+
+ if(pszName != NULL) {
+ CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Add a stream object to the current select() set.
+ * Note that a single stream may have multiple "sockets" if
+ * it is a listener. If so, all of them are begin added.
+ */
+static rsRetVal
+Add(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, nssel);
+ ISOBJ_TYPE_assert(pStrm, netstrm);
+
+ CHKiRet(pThis->Drvr.Add(pThis->pDrvrData, pStrm->pDrvrData, waitOp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* wait for IO to happen on one of our netstreams. iNumReady has
+ * the number of ready "sockets" after the call. This function blocks
+ * until some are ready. EAGAIN is retried.
+ */
+static rsRetVal
+Wait(nssel_t *pThis, int *piNumReady)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ assert(piNumReady != NULL);
+ iRet = pThis->Drvr.Select(pThis->pDrvrData, piNumReady);
+ RETiRet;
+}
+
+
+/* Check if a stream is ready for IO. *piNumReady contains the remaining number
+ * of ready streams. Note that this function may say the stream is not ready
+ * but still decrement *piNumReady. This can happen when (e.g. with TLS) the low
+ * level driver requires some IO which is hidden from the upper layer point of view.
+ * rgerhards, 2008-04-23
+ */
+static rsRetVal
+IsReady(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady,
+int __attribute__((unused)) *piNumReady)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, nssel);
+ ISOBJ_TYPE_assert(pStrm, netstrm);
+ assert(pbIsReady != NULL);
+ assert(piNumReady != NULL);
+ iRet = pThis->Drvr.IsReady(pThis->pDrvrData, pStrm->pDrvrData, waitOp, pbIsReady);
+ RETiRet;
+}
+
+
+/* queryInterface function */
+BEGINobjQueryInterface(nssel)
+CODESTARTobjQueryInterface(nssel)
+ if(pIf->ifVersion != nsselCURR_IF_VERSION) {/* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = nsselConstruct;
+ pIf->ConstructFinalize = ConstructFinalize;
+ pIf->Destruct = nsselDestruct;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->Add = Add;
+ pIf->Wait = Wait;
+ pIf->IsReady = IsReady;
+finalize_it:
+ENDobjQueryInterface(nssel)
+
+
+/* exit our class
+ */
+BEGINObjClassExit(nssel, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nssel)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(nssel)
+
+
+/* Initialize the nssel class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(nssel, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ DBGPRINTF("doing nsselClassInit\n");
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+
+ /* set our own handlers */
+ENDObjClassInit(nssel)
+/* vi:set ai:
+ */
diff --git a/runtime/nssel.h b/runtime/nssel.h
new file mode 100644
index 0000000..f8a67c6
--- /dev/null
+++ b/runtime/nssel.h
@@ -0,0 +1,57 @@
+/* Definitions for the nssel IO waiter.
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_NSSEL_H
+#define INCLUDED_NSSEL_H
+
+#include "netstrms.h"
+
+/* the nssel object */
+struct nssel_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ nsd_t *pDrvrData; /**< the driver's data elements */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ nsdsel_if_t Drvr; /**< our stream driver */
+};
+
+
+/* interface */
+BEGINinterface(nssel) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(nssel_t **ppThis);
+ rsRetVal (*ConstructFinalize)(nssel_t *pThis);
+ rsRetVal (*Destruct)(nssel_t **ppThis);
+ rsRetVal (*Add)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp);
+ rsRetVal (*Wait)(nssel_t *pThis, int *pNumReady);
+ rsRetVal (*IsReady)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady,
+ int *piNumReady);
+ /* v2 - 2013-09-17 by rgerhards */
+ rsRetVal (*SetDrvrName)(nssel_t *pThis, uchar *name);
+ENDinterface(nssel)
+#define nsselCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(nssel);
+
+/* the name of our library binary */
+#define LM_NSSEL_FILENAME LM_NETSTRMS_FILENAME
+
+#endif /* #ifndef INCLUDED_NSSEL_H */
diff --git a/runtime/obj-types.h b/runtime/obj-types.h
new file mode 100644
index 0000000..21fb89b
--- /dev/null
+++ b/runtime/obj-types.h
@@ -0,0 +1,444 @@
+/* Some type definitions and macros for the obj object.
+ * I needed to move them out of the main obj.h, because obj.h's
+ * prototypes use other data types. However, their .h's rely
+ * on some of the obj.h data types and macros. So I needed to break
+ * that loop somehow and I've done that by moving the typedefs
+ * into this file here.
+ *
+ * Copyright 2008-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OBJ_TYPES_H_INCLUDED
+#define OBJ_TYPES_H_INCLUDED
+
+#include "stringbuf.h"
+#include "syslogd-types.h"
+
+/* property types for obj[De]Serialize() */
+typedef enum {
+ PROPTYPE_NONE = 0, /* currently no value set */
+ PROPTYPE_PSZ = 1,
+ PROPTYPE_SHORT = 2,
+ PROPTYPE_INT = 3,
+ PROPTYPE_LONG = 4,
+ PROPTYPE_INT64 = 5,
+ PROPTYPE_CSTR = 6,
+ PROPTYPE_SYSLOGTIME = 7
+} propType_t;
+
+typedef unsigned objID_t;
+
+typedef enum { /* IDs of base methods supported by all objects - used for jump table, so
+ * they must start at zero and be incremented. -- rgerhards, 2008-01-04
+ */
+ objMethod_CONSTRUCT = 0,
+ objMethod_DESTRUCT = 1,
+ objMethod_SERIALIZE = 2,
+ objMethod_DESERIALIZE = 3,
+ objMethod_SETPROPERTY = 4,
+ objMethod_CONSTRUCTION_FINALIZER = 5,
+ objMethod_GETSEVERITY = 6,
+ objMethod_DEBUGPRINT = 7
+} objMethod_t;
+#define OBJ_NUM_METHODS 8 /* must be updated to contain the max number of methods supported */
+
+
+/* the base data type for interfaces
+ * This MUST be in sync with the ifBEGIN macro
+ */
+struct interface_s {
+ int ifVersion; /* must be set to version requested */
+ int ifIsLoaded;
+ /* is the interface loaded? (0-no, 1-yes, 2-load failed; if not 1, functions can NOT be called! */
+};
+
+
+struct objInfo_s {
+ uchar *pszID; /* the object ID as a string */
+ size_t lenID; /* length of the ID string */
+ int iObjVers;
+ uchar *pszName;
+ rsRetVal (*objMethods[OBJ_NUM_METHODS])();
+ rsRetVal (*QueryIF)(interface_t*);
+ struct modInfo_s *pModInfo;
+};
+
+
+struct obj_s { /* the dummy struct that each derived class can be casted to */
+ objInfo_t *pObjInfo;
+#ifndef NDEBUG /* this means if debug... */
+ unsigned int iObjCooCKiE; /* must always be 0xBADEFEE for a valid object */
+#endif
+ uchar *pszName; /* the name of *this* specific object instance */
+};
+
+
+/* macros which must be gloablly-visible (because they are used during definition of
+ * other objects.
+ */
+#ifndef NDEBUG /* this means if debug... */
+#include <string.h>
+# define BEGINobjInstance \
+ obj_t objData
+# define ISOBJ_assert(pObj) \
+ do { \
+ assert((pObj) != NULL); \
+ assert((unsigned) ((obj_t*)(pObj))->iObjCooCKiE == (unsigned) 0xBADEFEE); \
+ } while(0);
+# define ISOBJ_TYPE_assert(pObj, objType) \
+ do { \
+ assert(pObj != NULL); \
+ if(strcmp((char*)(((obj_t*)pObj)->pObjInfo->pszID), #objType)) { \
+ dbgprintf("%s:%d ISOBJ assert failure: invalid object type, expected '%s' " \
+ "actual '%s', cookie: %X\n", __FILE__, __LINE__, #objType, \
+ (((obj_t*)pObj)->pObjInfo->pszID), ((obj_t*)(pObj))->iObjCooCKiE); \
+ fprintf(stderr, "%s:%d ISOBJ assert failure: invalid object type, expected '%s' " \
+ "actual '%s', cookie: %X\n", __FILE__, __LINE__, #objType, \
+ (((obj_t*)pObj)->pObjInfo->pszID), ((obj_t*)(pObj))->iObjCooCKiE); \
+ fflush(stderr); \
+ assert(!strcmp((char*)(((obj_t*)pObj)->pObjInfo->pszID), #objType)); \
+ } \
+ assert((unsigned) ((obj_t*)(pObj))->iObjCooCKiE == (unsigned) 0xBADEFEE); \
+ } while(0)
+ /* now the same for pointers to "regular" objects (like wrkrInstanceData) */
+# define PTR_ASSERT_DEF unsigned int _Assert_type;
+# define PTR_ASSERT_SET_TYPE(_ptr, _type) _ptr->_Assert_type = _type
+# define PTR_ASSERT_CHK(_ptr, _type) do { \
+ assert(_ptr != NULL); \
+ if(_ptr->_Assert_type != _type) {\
+ dbgprintf("%s:%d PTR_ASSERT_CHECK failure: invalid pointer type %x, " \
+ "expected %x\n", __FILE__, __LINE__, _ptr->_Assert_type, _type); \
+ fprintf(stderr, "%s:%d PTR_ASSERT_CHECK failure: invalid pointer type %x, " \
+ "expected %x\n", __FILE__, __LINE__, _ptr->_Assert_type, _type); \
+ assert(_ptr->_Assert_type == _type); \
+ } \
+ } while(0)
+#else /* non-debug mode, no checks but much faster */
+# define BEGINobjInstance obj_t objData
+# define ISOBJ_TYPE_assert(pObj, objType)
+# define ISOBJ_assert(pObj)
+
+# define PTR_ASSERT_DEF
+# define PTR_ASSERT_SET_TYPE(_ptr, _type)
+# define PTR_ASSERT_CHK(_ptr, _type)
+#endif
+
+/* a set method for *very simple* object accesses. Note that this does
+ * NOT conform to the standard calling conventions and should be
+ * used only if actually nothing can go wrong! -- rgerhards, 2008-04-17
+ */
+#define DEFpropGetMeth(obj, prop, dataType)\
+ dataType obj##Get##prop(void)\
+ { \
+ return pThis->prop = pVal; \
+ }
+
+#define DEFpropSetMethPTR(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType *pVal)\
+ { \
+ pThis->prop = pVal; \
+ return RS_RET_OK; \
+ }
+#define PROTOTYPEpropSetMethPTR(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType*)
+#define DEFpropSetMethFP(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType)\
+ { \
+ pThis->prop = pVal; \
+ return RS_RET_OK; \
+ }
+#define PROTOTYPEpropSetMethFP(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType)
+#define DEFpropSetMeth(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType pVal);\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType pVal)\
+ { \
+ pThis->prop = pVal; \
+ return RS_RET_OK; \
+ }
+#define PROTOTYPEpropSetMeth(obj, prop, dataType)\
+ rsRetVal obj##Set##prop(obj##_t *pThis, dataType pVal)
+#define INTERFACEpropSetMeth(obj, prop, dataType)\
+ rsRetVal (*Set##prop)(obj##_t *pThis, dataType)
+/* class initializer */
+#define PROTOTYPEObjClassInit(objName) rsRetVal objName##ClassInit(struct modInfo_s*)
+/* below: objName must be the object name (e.g. vm, strm, ...) and ISCORE must be
+ * 1 if the module is a statically linked core module and 0 if it is a
+ * dynamically loaded one. -- rgerhards, 2008-02-29
+ */
+#define OBJ_IS_CORE_MODULE 1 /* This should better be renamed to something like "OBJ_IS_NOT_LIBHEAD" or so... ;) */
+#define OBJ_IS_LOADABLE_MODULE 0
+#define BEGINObjClassInit(objName, objVers, objType) \
+rsRetVal objName##ClassInit(struct modInfo_s *pModInfo) \
+{ \
+ DEFiRet; \
+ if(objType == OBJ_IS_CORE_MODULE) { /* are we a core module? */ \
+ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ \
+ } \
+ CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, (uchar*) #objName, objVers, \
+ (rsRetVal (*)(void*))objName##Construct,\
+ (rsRetVal (*)(void*))objName##Destruct,\
+ (rsRetVal (*)(interface_t*))objName##QueryInterface, pModInfo)); \
+
+#define ENDObjClassInit(objName) \
+ iRet = obj.RegisterObj((uchar*)#objName, pObjInfoOBJ); \
+finalize_it: \
+ RETiRet; \
+}
+
+/* ... and now the same for abstract classes.
+ * TODO: consolidate the two -- rgerhards, 2008-02-29
+ */
+#define BEGINAbstractObjClassInit(objName, objVers, objType) \
+rsRetVal objName##ClassInit(struct modInfo_s *pModInfo) \
+{ \
+ DEFiRet; \
+ if(objType == OBJ_IS_CORE_MODULE) { /* are we a core module? */ \
+ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ \
+ } \
+ CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, (uchar*) #objName, objVers, \
+ NULL,\
+ NULL,\
+ (rsRetVal (*)(interface_t*))objName##QueryInterface, pModInfo));
+
+#define ENDObjClassInit(objName) \
+ iRet = obj.RegisterObj((uchar*)#objName, pObjInfoOBJ); \
+finalize_it: \
+ RETiRet; \
+}
+
+
+/* now come the class exit. This is to be called immediately before the class is
+ * unloaded (actual unload for plugins, program termination for core modules)
+ * gerhards, 2008-03-10
+ */
+#define PROTOTYPEObjClassExit(objName) rsRetVal objName##ClassExit(void)
+#define BEGINObjClassExit(objName, objType) \
+rsRetVal objName##ClassExit(void) \
+{ \
+ DEFiRet;
+
+#define CODESTARTObjClassExit(objName)
+
+#define ENDObjClassExit(objName) \
+ iRet = obj.UnregisterObj((uchar*)#objName); \
+ RETiRet; \
+}
+
+/* this defines both the constructor and initializer
+ * rgerhards, 2008-01-10
+ */
+#define BEGINobjConstruct(obj) \
+ static rsRetVal obj##Initialize(obj##_t __attribute__((unused)) *pThis) \
+ { \
+ DEFiRet;
+
+#define ENDobjConstruct(obj) \
+ /* use finalize_it: before calling the macro (if you need it)! */ \
+ RETiRet; \
+ } \
+ rsRetVal obj##Construct(obj##_t **ppThis); \
+ rsRetVal obj##Construct(obj##_t **ppThis) \
+ { \
+ DEFiRet; \
+ obj##_t *pThis; \
+ \
+ assert(ppThis != NULL); \
+ \
+ if((pThis = (obj##_t *)calloc(1, sizeof(obj##_t))) == NULL) { \
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); \
+ } \
+ objConstructSetObjInfo(pThis); \
+ \
+ obj##Initialize(pThis); \
+ \
+ finalize_it: \
+ OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \
+ RETiRet; \
+ }
+
+
+/* this defines the destructor. The important point is that the base object
+ * destructor is called. The upper-level class shall destruct all of its
+ * properties, but not the instance itself. This is freed here by the
+ * framework (we need an intact pointer because we need to free the
+ * obj_t structures inside it). A pointer to the object pointer must be
+ * parse, because it is re-set to NULL (this, for example, is important in
+ * cancellation handlers). The object pointer is always named pThis.
+ * The object is always freed, even if there is some error while
+ * Cancellation is blocked during destructors, as this could have fatal
+ * side-effects. However, this also means the upper-level object should
+ * not perform any lengthy processing.
+ * IMPORTANT: if the upper level object requires some situations where the
+ * object shall not be destructed (e.g. via reference counting), then
+ * it shall set pThis to NULL, which prevents destruction of the
+ * object.
+ * processing.
+ * rgerhards, 2008-01-30
+ */
+#define PROTOTYPEobjDestruct(OBJ) \
+ rsRetVal OBJ##Destruct(OBJ##_t __attribute__((unused)) **ppThis)
+/* note: we generate a prototype in any case, as this does not hurt but
+ * many modules otherwise seem to miss one, which generates compiler
+ * warnings.
+ */
+#define BEGINobjDestruct(OBJ) \
+ rsRetVal OBJ##Destruct(OBJ##_t __attribute__((unused)) **ppThis);\
+ rsRetVal OBJ##Destruct(OBJ##_t __attribute__((unused)) **ppThis) \
+ { \
+ DEFiRet; \
+ OBJ##_t *pThis;
+
+#define CODESTARTobjDestruct(OBJ) \
+ assert(ppThis != NULL); \
+ pThis = *ppThis; \
+ ISOBJ_TYPE_assert(pThis, OBJ);
+
+/* note: there was a long-time bug in the macro below that lead to *ppThis = NULL
+ * only when the object was actually destructed. I discovered this issue during
+ * introduction of the pRcvFrom property in smsg_t, but it potentially had other
+ * effects, too. I am not sure if some experienced instability resulted from this
+ * bug OR if its fix will cause harm to so-far "correctly" running code. The later
+ * may very well be. Thus I will change it only for the current branch and also
+ * the beta, but not in all old builds. Let's see how things evolve.
+ * rgerhards, 2009-06-30
+ */
+#define ENDobjDestruct(OBJ) \
+ goto finalize_it; /* prevent compiler warning ;) */ \
+ /* no more code here! */ \
+ finalize_it: \
+ if(pThis != NULL) { \
+ obj.DestructObjSelf((obj_t*) pThis); \
+ free(pThis); \
+ } \
+ *ppThis = NULL; \
+ RETiRet; \
+ }
+
+
+/* this defines the debug print entry point. DebugPrint is optional. If
+ * it is provided, the object should output some meaningful information
+ * via the debug system.
+ * rgerhards, 2008-02-20
+ */
+#define PROTOTYPEObjDebugPrint(obj) rsRetVal obj##DebugPrint(obj##_t *pThis)
+#define INTERFACEObjDebugPrint(obj) rsRetVal (*DebugPrint)(obj##_t *pThis)
+#define BEGINobjDebugPrint(obj) \
+ rsRetVal obj##DebugPrint(obj##_t __attribute__((unused)) *pThis);\
+ rsRetVal obj##DebugPrint(obj##_t __attribute__((unused)) *pThis) \
+ { \
+ DEFiRet; \
+
+#define CODESTARTobjDebugPrint(obj) \
+ assert(pThis != NULL); \
+ ISOBJ_TYPE_assert(pThis, obj); \
+
+#define ENDobjDebugPrint(obj) \
+ RETiRet; \
+ }
+
+/* ------------------------------ object loader system ------------------------------ *
+ * The following code builds a dynamic object loader system. The
+ * root idea is that all objects are dynamically loadable,
+ * which is necessary to get a clean plug-in interface where every plugin can access
+ * rsyslog's rich object model via simple and quite portable methods.
+ *
+ * To do so, each object defines one or more interfaces. They are essentially structures
+ * with function (method) pointers. Anyone interested in calling an object must first
+ * obtain the interface and can then call through it.
+ *
+ * The interface data type must always be called <obj>_if_t, as this is expected
+ * by the macros. Having consitent naming is also easier for the programmer. By default,
+ * macros create a static variable named like the object in each calling objects
+ * static data block.
+ *
+ * rgerhards, 2008-02-21 (initial implementation), 2008-04-17 (update of this note)
+ */
+
+/* this defines the QueryInterface print entry point. Over time, it should be
+ * present in all objects.
+ */
+#define BEGINobjQueryInterface(obj) \
+ rsRetVal obj##QueryInterface(obj##_if_t *pIf);\
+ rsRetVal obj##QueryInterface(obj##_if_t *pIf) \
+ { \
+ DEFiRet; \
+
+#define CODESTARTobjQueryInterface(obj) \
+ assert(pIf != NULL);
+
+#define ENDobjQueryInterface(obj) \
+ RETiRet; \
+ }
+
+#define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pIf)
+
+
+/* the following macros should be used to define interfaces inside the
+ * header files.
+ */
+#define BEGINinterface(obj) \
+ typedef struct obj##_if_s {\
+ ifBEGIN /* This MUST always be the first interface member */
+#define ENDinterface(obj) \
+ } obj##_if_t;
+
+/* the following macro is used to get access to an object (not an instance,
+ * just the class itself!). It must be called before any of the object's
+ * methods can be accessed. The MYLIB part is the name of my library, or NULL if
+ * the caller is a core module. Using the right value here is important to get
+ * the reference counting correct (object accesses from the same library must
+ * not be counted because that would cause a library plugin to never unload, as
+ * its ClassExit() entry points are only called if no object is referenced, which
+ * would never happen as the library references itself.
+ * rgerhards, 2008-03-11
+ */
+#define CORE_COMPONENT NULL /* use this to indicate this is a core component */
+#define DONT_LOAD_LIB NULL /* do not load a library to obtain object interface (currently same as CORE_COMPONENT) */
+#define objUse(objName, FILENAME) \
+ obj.UseObj(__FILE__, (uchar*)#objName, (uchar*)FILENAME, (void*) &objName)
+#define objRelease(objName, FILENAME) \
+ obj.ReleaseObj(__FILE__, (uchar*)#objName, (uchar*) FILENAME, (void*) &objName)
+
+/* defines data that must always be present at the very begin of the interface structure */
+#define ifBEGIN \
+ int ifVersion; /* must be set to version requested */ \
+ int ifIsLoaded; /* is the interface loaded? (0-no, 1-yes; if no, functions can NOT be called! */
+
+
+/* use the following define some place in your static data (suggested right at
+ * the beginning
+ */
+#define DEFobjCurrIf(obj) \
+ static obj##_if_t obj = { .ifVersion = obj##CURR_IF_VERSION, .ifIsLoaded = 0 };
+
+/* define the prototypes for a class - when we use interfaces, we just have few
+ * functions that actually need to be non-static.
+ */
+#define PROTOTYPEObj(obj) \
+ PROTOTYPEObjClassInit(obj); \
+ PROTOTYPEObjClassExit(obj); \
+ PROTOTYPEObjQueryInterface(obj)
+
+/* ------------------------------ end object loader system ------------------------------ */
+
+
+#include "modules.h"
+
+#endif /* #ifndef OBJ_TYPES_H_INCLUDED */
diff --git a/runtime/obj.c b/runtime/obj.c
new file mode 100644
index 0000000..c78b1d2
--- /dev/null
+++ b/runtime/obj.c
@@ -0,0 +1,1409 @@
+/* obj.c
+ *
+ * This file implements a generic object "class". All other classes can
+ * use the service of this base class here to include auto-destruction and
+ * other capabilities in a generic manner.
+ *
+ * As of 2008-02-29, I (rgerhards) am adding support for dynamically loadable
+ * objects. In essence, each object will soon be available via its interface,
+ * only. Before any object's code is accessed (including global static methods),
+ * the caller needs to obtain an object interface. To do so, it needs to provide
+ * the object name and the file where the object is expected to reside in. A
+ * file may not be given, in which case the object is expected to reside in
+ * the rsyslog core. The caller than receives an interface pointer which can
+ * be utilized to access all the object's methods. This method enables rsyslog
+ * to load library modules on demand. In order to keep overhead low, callers
+ * should request object interface only once in the object Init function and
+ * free them when they exit. The only exception is when a caller needs to
+ * access an object only conditional, in which case a pointer to its interface
+ * shall be acquired as need first arises but still be released only on exit
+ * or when there definitely is no further need. The whole idea is to limit
+ * the very performance-intense act of dynamically loading an objects library.
+ * Of course, it is possible to violate this suggestion, but than you should
+ * have very good reasoning to do so.
+ *
+ * Please note that there is one trick we need to do. Each object queries
+ * the object interfaces and it does so via objUse(). objUse, however, is
+ * part of the obj object's interface (implemented via the file you are
+ * just reading). So in order to obtain a pointer to objUse, we need to
+ * call it - obviously not possible. One solution would be that objUse is
+ * hardcoded into all callers. That, however, would bring us into slight
+ * trouble with actually dynamically loaded modules, as we should NOT
+ * rely on the OS loader to resolve symbols back to the caller (this
+ * is a feature not universally available and highly importable). Of course,
+ * we can solve this with a pHostQueryEtryPoint() call. It still sounds
+ * somewhat unnatural to call a regular interface function via a special
+ * method. So what we do instead is define a special function called
+ * objGetObjInterface() which delivers our own interface. That function
+ * than will be defined global and be queriable via pHostQueryEtryPoint().
+ * I agree, technically this is much the same, but from an architecture
+ * point of view it looks cleaner (at least to me).
+ *
+ * Please note that there is another egg-hen problem: we use a linked list,
+ * which is provided by the linkedList object. However, we need to
+ * initialize the linked list before we can provide the UseObj()
+ * functionality. That, in turn, would probably be required by the
+ * linkedList object. So the solution is to use a backdoor just to
+ * init the linked list and from then on use the usual interfaces.
+ *
+ * File begun on 2008-01-04 by RGerhards
+ *
+ * Copyright 2008-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <pthread.h>
+
+#define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */
+
+/* how many objects are supported by rsyslogd? */
+#define OBJ_NUM_IDS 100 /* TODO change to a linked list? info: 16 were currently in use 2008-02-29 */
+
+#include "rsyslog.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "stream.h"
+#include "modules.h"
+#include "errmsg.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "datetime.h"
+
+/* static data */
+DEFobjCurrIf(obj) /* we define our own interface, as this is expected by some macros! */
+DEFobjCurrIf(var)
+DEFobjCurrIf(module)
+DEFobjCurrIf(strm)
+static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information pointers */
+pthread_mutex_t mutObjGlobalOp; /* mutex to guard global operations of the object system */
+
+
+/* cookies for serialized lines */
+#define COOKIE_OBJLINE '<'
+#define COOKIE_PROPLINE '+'
+#define COOKIE_ENDLINE '>'
+#define COOKIE_BLANKLINE '.'
+
+/* forward definitions */
+static rsRetVal FindObjInfo(const char *szObjName, objInfo_t **ppInfo);
+
+/* methods */
+
+/* This is a dummy method to be used when a standard method has not been
+ * implemented by an object. Having it allows us to simply call via the
+ * jump table without any NULL pointer checks - which gains quite
+ * some performance. -- rgerhards, 2008-01-04
+ */
+static rsRetVal objInfoNotImplementedDummy(void __attribute__((unused)) *pThis)
+{
+ return RS_RET_NOT_IMPLEMENTED;
+}
+
+/* and now the macro to check if something is not implemented
+ * must be provided an objInfo_t pointer.
+ */
+#define objInfoIsImplemented(pThis, method) \
+ (pThis->objMethods[method] != objInfoNotImplementedDummy)
+
+/* construct an object Info object. Each class shall do this on init. The
+ * resulting object shall be cached during the lifetime of the class and each
+ * object shall receive a reference. A constructor and destructor MUST be provided for all
+ * objects, thus they are in the parameter list.
+ * pszID is the identifying object name and must point to constant pool memory. It is never freed.
+ */
+static rsRetVal
+InfoConstruct(objInfo_t **ppThis, uchar *pszID, int iObjVers,
+ rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *),
+ rsRetVal (*pQueryIF)(interface_t*), modInfo_t *pModInfo)
+{
+ DEFiRet;
+ int i;
+ objInfo_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = calloc(1, sizeof(objInfo_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pThis->pszID = pszID;
+ pThis->lenID = ustrlen(pszID);
+ pThis->pszName = ustrdup(pszID); /* it's OK if we have NULL ptr, GetName() will deal with that! */
+ pThis->iObjVers = iObjVers;
+ pThis->QueryIF = pQueryIF;
+ pThis->pModInfo = pModInfo;
+
+ pThis->objMethods[0] = pConstruct;
+ pThis->objMethods[1] = pDestruct;
+ for(i = 2 ; i < OBJ_NUM_METHODS ; ++i) {
+ pThis->objMethods[i] = objInfoNotImplementedDummy;
+ }
+
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* destruct the objInfo object - must be done only when no more instances exist.
+ * rgerhards, 2008-03-10
+ */
+static rsRetVal
+InfoDestruct(objInfo_t **ppThis)
+{
+ DEFiRet;
+ objInfo_t *pThis;
+
+ assert(ppThis != NULL);
+ pThis = *ppThis;
+ assert(pThis != NULL);
+
+ free(pThis->pszName);
+ free(pThis);
+ *ppThis = NULL;
+
+ RETiRet;
+}
+
+
+/* set a method handler */
+static rsRetVal
+InfoSetMethod(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void*))
+{
+ pThis->objMethods[objMethod] = pHandler;
+ return RS_RET_OK;
+}
+
+/* destruct the base object properties.
+ * rgerhards, 2008-01-29
+ */
+static rsRetVal
+DestructObjSelf(obj_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_assert(pThis);
+ free(pThis->pszName);
+
+ RETiRet;
+}
+
+
+/* --------------- object serializiation / deserialization support --------------- */
+
+
+/* serialize the header of an object
+ * pszRecType must be either "Obj" (Object) or "OPB" (Object Property Bag)
+ */
+static rsRetVal objSerializeHeader(strm_t *pStrm, obj_t *pObj, uchar *pszRecType)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pStrm, strm);
+ ISOBJ_assert(pObj);
+ assert(!strcmp((char*) pszRecType, "Obj") || !strcmp((char*) pszRecType, "OPB"));
+
+ /* object cookie and serializer version (so far always 1) */
+ CHKiRet(strm.WriteChar(pStrm, COOKIE_OBJLINE));
+ CHKiRet(strm.Write(pStrm, (uchar*) pszRecType, 3)); /* record types are always 3 octets */
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ CHKiRet(strm.WriteChar(pStrm, '1'));
+
+ /* object type, version and string length */
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ CHKiRet(strm.Write(pStrm, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID));
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ CHKiRet(strm.WriteLong(pStrm, objGetVersion(pObj)));
+
+ /* record trailer */
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ CHKiRet(strm.WriteChar(pStrm, '\n'));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* begin serialization of an object
+ * rgerhards, 2008-01-06
+ */
+static rsRetVal
+BeginSerialize(strm_t *pStrm, obj_t *pObj)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pStrm, strm);
+ ISOBJ_assert(pObj);
+
+ CHKiRet(strm.RecordBegin(pStrm));
+ CHKiRet(objSerializeHeader(pStrm, pObj, (uchar*) "Obj"));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* begin serialization of an object's property bag
+ * Note: a property bag is used to serialize some of an objects
+ * properties, but not necessarily all. A good example is the queue
+ * object, which at some stage needs to serialize a number of its
+ * properties, but not the queue data itself. From the object point
+ * of view, a property bag can not be used to re-instantiate an object.
+ * Otherwise, the serialization is exactly the same.
+ * rgerhards, 2008-01-11
+ */
+static rsRetVal
+BeginSerializePropBag(strm_t *pStrm, obj_t *pObj)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pStrm, strm);
+ ISOBJ_assert(pObj);
+
+ CHKiRet(strm.RecordBegin(pStrm));
+ CHKiRet(objSerializeHeader(pStrm, pObj, (uchar*) "OPB"));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* append a property
+ */
+static rsRetVal
+SerializeProp(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr)
+{
+ DEFiRet;
+ uchar *pszBuf = NULL;
+ size_t lenBuf = 0;
+ uchar szBuf[64];
+ varType_t vType = VARTYPE_NONE;
+
+ ISOBJ_TYPE_assert(pStrm, strm);
+ assert(pszPropName != NULL);
+
+ /*dbgprintf("objSerializeProp: strm %p, propName '%s', type %d, pUsr %p\n",
+ pStrm, pszPropName, propType, pUsr);*/
+ /* if we have no user pointer, there is no need to write this property.
+ * TODO: think if that's the righ point of view
+ * rgerhards, 2008-01-06
+ */
+ if(pUsr == NULL) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* TODO: use the stream functions for data conversion here - should be quicker */
+
+ switch(propType) {
+ case PROPTYPE_PSZ:
+ pszBuf = (uchar*) pUsr;
+ lenBuf = ustrlen(pszBuf);
+ vType = VARTYPE_STR;
+ break;
+ case PROPTYPE_SHORT:
+ CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), (long) *((short*) pUsr)));
+ pszBuf = szBuf;
+ lenBuf = ustrlen(szBuf);
+ vType = VARTYPE_NUMBER;
+ break;
+ case PROPTYPE_INT:
+ CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), (long) *((int*) pUsr)));
+ pszBuf = szBuf;
+ lenBuf = ustrlen(szBuf);
+ vType = VARTYPE_NUMBER;
+ break;
+ case PROPTYPE_LONG:
+ CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), *((long*) pUsr)));
+ pszBuf = szBuf;
+ lenBuf = ustrlen(szBuf);
+ vType = VARTYPE_NUMBER;
+ break;
+ case PROPTYPE_INT64:
+ CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), *((int64*) pUsr)));
+ pszBuf = szBuf;
+ lenBuf = ustrlen(szBuf);
+ vType = VARTYPE_NUMBER;
+ break;
+ case PROPTYPE_CSTR:
+ pszBuf = rsCStrGetSzStrNoNULL((cstr_t *) pUsr);
+ lenBuf = rsCStrLen((cstr_t*) pUsr);
+ vType = VARTYPE_STR;
+ break;
+ case PROPTYPE_SYSLOGTIME:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%d:%d:%d:%d:%d:%d:%d:%d:%d:%c:%d:%d",
+ ((syslogTime_t*)pUsr)->timeType,
+ ((syslogTime_t*)pUsr)->year,
+ ((syslogTime_t*)pUsr)->month,
+ ((syslogTime_t*)pUsr)->day,
+ ((syslogTime_t*)pUsr)->hour,
+ ((syslogTime_t*)pUsr)->minute,
+ ((syslogTime_t*)pUsr)->second,
+ ((syslogTime_t*)pUsr)->secfrac,
+ ((syslogTime_t*)pUsr)->secfracPrecision,
+ ((syslogTime_t*)pUsr)->OffsetMode,
+ ((syslogTime_t*)pUsr)->OffsetHour,
+ ((syslogTime_t*)pUsr)->OffsetMinute);
+ if(lenBuf > sizeof(szBuf) - 1)
+ ABORT_FINALIZE(RS_RET_PROVIDED_BUFFER_TOO_SMALL);
+ vType = VARTYPE_SYSLOGTIME;
+ pszBuf = szBuf;
+ break;
+ case PROPTYPE_NONE:
+ default:
+ dbgprintf("invalid PROPTYPE %d\n", propType);
+ break;
+ }
+
+ /* cookie */
+ CHKiRet(strm.WriteChar(pStrm, COOKIE_PROPLINE));
+ /* name */
+ CHKiRet(strm.Write(pStrm, pszPropName, ustrlen(pszPropName)));
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ /* type */
+ CHKiRet(strm.WriteLong(pStrm, (int) vType));
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ /* length */
+ CHKiRet(strm.WriteLong(pStrm, lenBuf));
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+
+ /* data */
+ CHKiRet(strm.Write(pStrm, (uchar*) pszBuf, lenBuf));
+
+ /* trailer */
+ CHKiRet(strm.WriteChar(pStrm, ':'));
+ CHKiRet(strm.WriteChar(pStrm, '\n'));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* end serialization of an object. The caller receives a
+ * standard C string, which he must free when no longer needed.
+ */
+static rsRetVal
+EndSerialize(strm_t *pStrm)
+{
+ DEFiRet;
+
+ assert(pStrm != NULL);
+
+ CHKiRet(strm.WriteChar(pStrm, COOKIE_ENDLINE));
+ CHKiRet(strm.Write(pStrm, (uchar*) "End\n", sizeof("END\n") - 1));
+ CHKiRet(strm.WriteChar(pStrm, COOKIE_BLANKLINE));
+ CHKiRet(strm.WriteChar(pStrm, '\n'));
+
+ CHKiRet(strm.RecordEnd(pStrm));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* define a helper to make code below a bit cleaner (and quicker to write) */
+#define NEXTC CHKiRet(strm.ReadChar(pStrm, &c))/*;dbgprintf("c: %c\n", c)*/
+
+
+/* de-serialize an embedded, non-octect-counted string. This is useful
+ * for deserializing the object name inside the header. The string is
+ * terminated by the first occurrence of the ':' character.
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+objDeserializeEmbedStr(cstr_t **ppStr, strm_t *pStrm)
+{
+ DEFiRet;
+ uchar c;
+ cstr_t *pStr = NULL;
+
+ assert(ppStr != NULL);
+
+ CHKiRet(cstrConstruct(&pStr));
+
+ NEXTC;
+ while(c != ':') {
+ CHKiRet(cstrAppendChar(pStr, c));
+ NEXTC;
+ }
+ cstrFinalize(pStr);
+
+ *ppStr = pStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pStr != NULL)
+ cstrDestruct(&pStr);
+
+ RETiRet;
+}
+
+
+/* de-serialize a number */
+static rsRetVal objDeserializeNumber(number_t *pNum, strm_t *pStrm)
+{
+ DEFiRet;
+ number_t i;
+ int bIsNegative;
+ uchar c;
+
+ assert(pNum != NULL);
+
+ NEXTC;
+ if(c == '-') {
+ bIsNegative = 1;
+ NEXTC;
+ } else {
+ bIsNegative = 0;
+ }
+
+ /* we check this so that we get more meaningful error codes */
+ if(!isdigit(c)) ABORT_FINALIZE(RS_RET_INVALID_NUMBER);
+
+ i = 0;
+ while(isdigit(c)) {
+ i = i * 10 + c - '0';
+ NEXTC;
+ }
+
+ if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER);
+
+ if(bIsNegative)
+ i *= -1;
+
+ *pNum = i;
+finalize_it:
+ RETiRet;
+}
+
+
+/* de-serialize a string, length must be provided but may be 0 */
+static rsRetVal objDeserializeStr(cstr_t **ppCStr, int iLen, strm_t *pStrm)
+{
+ DEFiRet;
+ int i;
+ uchar c;
+ cstr_t *pCStr = NULL;
+
+ assert(ppCStr != NULL);
+ assert(iLen >= 0);
+
+ CHKiRet(cstrConstruct(&pCStr));
+
+ NEXTC;
+ for(i = 0 ; i < iLen ; ++i) {
+ CHKiRet(cstrAppendChar(pCStr, c));
+ NEXTC;
+ }
+ cstrFinalize(pCStr);
+
+ /* check terminator */
+ if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER);
+
+ *ppCStr = pCStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pCStr != NULL)
+ cstrDestruct(&pCStr);
+
+ RETiRet;
+}
+
+
+/* de-serialize a syslogTime -- rgerhards,2008-01-08 */
+#define GETVAL(var) \
+ CHKiRet(objDeserializeNumber(&l, pStrm)); \
+ pTime->var = l;
+static rsRetVal objDeserializeSyslogTime(syslogTime_t *pTime, strm_t *pStrm)
+{
+ DEFiRet;
+ number_t l;
+ uchar c;
+
+ assert(pTime != NULL);
+
+ GETVAL(timeType);
+ GETVAL(year);
+ GETVAL(month);
+ GETVAL(day);
+ GETVAL(hour);
+ GETVAL(minute);
+ GETVAL(second);
+ GETVAL(secfrac);
+ GETVAL(secfracPrecision);
+ /* OffsetMode is a single character! */
+ NEXTC; pTime->OffsetMode = c;
+ NEXTC; if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER);
+ GETVAL(OffsetHour);
+ GETVAL(OffsetMinute);
+
+finalize_it:
+ RETiRet;
+}
+#undef GETVAL
+
+/* de-serialize an object header
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal objDeserializeHeader(uchar *pszRecType, cstr_t **ppstrID, int* poVers, strm_t *pStrm)
+{
+ DEFiRet;
+ number_t oVers;
+ uchar c;
+
+ assert(ppstrID != NULL);
+ assert(poVers != NULL);
+ assert(!strcmp((char*) pszRecType, "Obj") || !strcmp((char*) pszRecType, "OPB"));
+
+ /* check header cookie */
+ NEXTC; if(c != COOKIE_OBJLINE) ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != pszRecType[0]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE);
+ NEXTC; if(c != pszRecType[1]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE);
+ NEXTC; if(c != pszRecType[2]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE);
+ NEXTC; if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != '1') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS);
+ NEXTC; if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS);
+
+ /* object type and version */
+ CHKiRet(objDeserializeEmbedStr(ppstrID, pStrm));
+ CHKiRet(objDeserializeNumber(&oVers, pStrm));
+
+ /* and now we skip over the rest until the delemiting \n */
+ NEXTC;
+ while(c != '\n') {
+ NEXTC;
+ }
+
+ *poVers = oVers;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Deserialize a single property. Pointer must be positioned at begin of line. Whole line
+ * up until the \n is read.
+ */
+rsRetVal objDeserializeProperty(var_t *pProp, strm_t *pStrm)
+{
+ DEFiRet;
+ number_t i;
+ number_t iLen;
+ uchar c;
+ int step = 0; /* which step was successful? */
+ int64 offs;
+
+ assert(pProp != NULL);
+
+ /* check cookie */
+ NEXTC;
+ if(c != COOKIE_PROPLINE) {
+ /* oops, we've read one char that does not belong to use - unget it first */
+ CHKiRet(strm.UnreadChar(pStrm, c));
+ ABORT_FINALIZE(RS_RET_NO_PROPLINE);
+ }
+
+ /* get the property name first */
+ CHKiRet(cstrConstruct(&pProp->pcsName));
+
+ NEXTC;
+ while(c != ':') {
+ CHKiRet(cstrAppendChar(pProp->pcsName, c));
+ NEXTC;
+ }
+ cstrFinalize(pProp->pcsName);
+ step = 1;
+
+ /* property type */
+ CHKiRet(objDeserializeNumber(&i, pStrm));
+ pProp->varType = i;
+ step = 2;
+
+ /* size (needed for strings) */
+ CHKiRet(objDeserializeNumber(&iLen, pStrm));
+ step = 3;
+
+ /* we now need to deserialize the value */
+ switch(pProp->varType) {
+ case VARTYPE_STR:
+ CHKiRet(objDeserializeStr(&pProp->val.pStr, iLen, pStrm));
+ break;
+ case VARTYPE_NUMBER:
+ CHKiRet(objDeserializeNumber(&pProp->val.num, pStrm));
+ break;
+ case VARTYPE_SYSLOGTIME:
+ CHKiRet(objDeserializeSyslogTime(&pProp->val.vSyslogTime, pStrm));
+ break;
+ case VARTYPE_NONE:
+ default:
+ dbgprintf("invalid VARTYPE %d\n", pProp->varType);
+ break;
+ }
+ step = 4;
+
+ /* we should now be at the end of the line. So the next char must be \n */
+ NEXTC;
+ if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_PROPFRAME);
+
+finalize_it:
+ /* ensure the type of var is reset back to VARTYPE_NONE since
+ * the deconstruct method of var might free unallocated memory
+ */
+ if(iRet != RS_RET_OK && iRet != RS_RET_NO_PROPLINE) {
+ if(step <= 2) {
+ pProp->varType = VARTYPE_NONE;
+ }
+ }
+ if(Debug && iRet != RS_RET_OK && iRet != RS_RET_NO_PROPLINE) {
+ strm.GetCurrOffset(pStrm, &offs);
+ dbgprintf("error %d deserializing property name, offset %lld, step %d\n",
+ iRet, offs, step);
+ strmDebugOutBuf(pStrm);
+ if(step >= 1) {
+ dbgprintf("error property name: '%s'\n", rsCStrGetSzStrNoNULL(pProp->pcsName));
+ }
+ if(step >= 2) {
+ dbgprintf("error var type: '%d'\n", pProp->varType);
+ }
+ if(step >= 3) {
+ dbgprintf("error len: '%d'\n", (int) iLen);
+ }
+ if(step >= 4) {
+ switch(pProp->varType) {
+ case VARTYPE_STR:
+ dbgprintf("error data string: '%s'\n",
+ rsCStrGetSzStrNoNULL(pProp->val.pStr));
+ break;
+ case VARTYPE_NUMBER:
+ dbgprintf("error number: %d\n", (int) pProp->val.num);
+ break;
+ case VARTYPE_SYSLOGTIME:
+ dbgprintf("syslog time was successfully parsed (but "
+ "is not displayed\n");
+ break;
+ case VARTYPE_NONE:
+ default:
+ break;
+ }
+ }
+ }
+ RETiRet;
+}
+
+
+/* de-serialize an object trailer. This does not get any data but checks if the
+ * format is ok.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal objDeserializeTrailer(strm_t *pStrm)
+{
+ DEFiRet;
+ uchar c;
+
+ /* check header cookie */
+ NEXTC; if(c != COOKIE_ENDLINE) ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'E') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'd') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != COOKIE_BLANKLINE) ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+
+finalize_it:
+ if(Debug && iRet != RS_RET_OK) {
+ dbgprintf("objDeserializeTrailer fails with %d\n", iRet);
+ }
+
+ RETiRet;
+}
+
+
+
+/* This method tries to recover a serial store if it got out of sync.
+ * To do so, it scans the line beginning cookies and waits for the object
+ * cookie. If that is found, control is returned. If the store is exhausted,
+ * we will receive an RS_RET_EOF error as part of NEXTC, which will also
+ * terminate this function. So we may either return with somehting that
+ * looks like a valid object or end of store.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal objDeserializeTryRecover(strm_t *pStrm)
+{
+ DEFiRet;
+ uchar c;
+ int bWasNL;
+ int bRun;
+
+ assert(pStrm != NULL);
+ bRun = 1;
+ bWasNL = 0;
+
+ while(bRun) {
+ NEXTC;
+ if(c == '\n')
+ bWasNL = 1;
+ else {
+ if(bWasNL == 1 && c == COOKIE_OBJLINE)
+ bRun = 0; /* we found it! */
+ else
+ bWasNL = 0;
+ }
+ }
+
+ CHKiRet(strm.UnreadChar(pStrm, c));
+
+finalize_it:
+ dbgprintf("deserializer has possibly been able to re-sync and recover, state %d\n", iRet);
+ RETiRet;
+}
+
+
+/* De-serialize the properties of an object. This includes processing
+ * of the trailer. Header must already have been processed.
+ * rgerhards, 2008-01-11
+ */
+static rsRetVal objDeserializeProperties(obj_t *pObj, rsRetVal (*objSetProperty)(), strm_t *pStrm)
+{
+ DEFiRet;
+ var_t *pVar = NULL;
+
+ ISOBJ_assert(pObj);
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ CHKiRet(var.Construct(&pVar));
+ CHKiRet(var.ConstructFinalize(pVar));
+
+ iRet = objDeserializeProperty(pVar, pStrm);
+ while(iRet == RS_RET_OK) {
+ CHKiRet(objSetProperty(pObj, pVar));
+ /* re-init var object - TODO: method of var! */
+ rsCStrDestruct(&pVar->pcsName); /* no longer needed */
+ if(pVar->varType == VARTYPE_STR) {
+ if(pVar->val.pStr != NULL)
+ rsCStrDestruct(&pVar->val.pStr);
+ }
+ iRet = objDeserializeProperty(pVar, pStrm);
+ }
+
+ if(iRet != RS_RET_NO_PROPLINE)
+ FINALIZE;
+
+ CHKiRet(objDeserializeTrailer(pStrm)); /* do trailer checks */
+finalize_it:
+ if(pVar != NULL)
+ var.Destruct(&pVar);
+
+ RETiRet;
+}
+
+
+/* De-Serialize an object.
+ * Params: Pointer to object Pointer (pObj) (like a obj_t**, but can not do that due to compiler warning)
+ * expected object ID (to check against), a fixup function that can modify the object before it is finalized
+ * and a user pointer that is to be passed to that function in addition to the object. The fixup function
+ * pointer may be NULL, in which case none is called.
+ * The caller must destruct the created object.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal
+Deserialize(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr)
+{
+ DEFiRet;
+ rsRetVal iRetLocal;
+ obj_t *pObj = NULL;
+ int oVers = 0; /* keep compiler happy, but it is totally useless but takes up some execution time... */
+ cstr_t *pstrID = NULL;
+ objInfo_t *pObjInfo;
+
+ assert(ppObj != NULL);
+ assert(pszTypeExpected != NULL);
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ /* we de-serialize the header. if all goes well, we are happy. However, if
+ * we experience a problem, we try to recover. We do this by skipping to
+ * the next object header. This is defined via the line-start cookies. In
+ * worst case, we exhaust the queue, but then we receive EOF return state,
+ * from objDeserializeTryRecover(), what will cause us to ultimately give up.
+ * rgerhards, 2008-07-08
+ */
+ do {
+ iRetLocal = objDeserializeHeader((uchar*) "Obj", &pstrID, &oVers, pStrm);
+ if(iRetLocal != RS_RET_OK) {
+ dbgprintf("objDeserialize error %d during header processing - trying to recover\n", iRetLocal);
+ CHKiRet(objDeserializeTryRecover(pStrm));
+ }
+ } while(iRetLocal != RS_RET_OK);
+
+ if(rsCStrSzStrCmp(pstrID, pszTypeExpected, ustrlen(pszTypeExpected)))
+ /* TODO: optimize strlen() - caller shall provide */
+ ABORT_FINALIZE(RS_RET_INVALID_OID);
+
+ CHKiRet(FindObjInfo((char*)cstrGetSzStrNoNULL(pstrID), &pObjInfo));
+
+ CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCT](&pObj));
+
+ /* we got the object, now we need to fill the properties */
+ CHKiRet(objDeserializeProperties(pObj, pObjInfo->objMethods[objMethod_SETPROPERTY], pStrm));
+
+ /* check if we need to call a fixup function that modifies the object
+ * before it is finalized. -- rgerhards, 2008-01-13
+ */
+ if(fFixup != NULL)
+ CHKiRet(fFixup(pObj, pUsr));
+
+ /* we have a valid object, let's finalize our work and return */
+ if(objInfoIsImplemented(pObjInfo, objMethod_CONSTRUCTION_FINALIZER))
+ CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCTION_FINALIZER](pObj));
+
+ *((obj_t**) ppObj) = pObj;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pObj != NULL)
+ free(pObj); /* TODO: check if we can call destructor 2008-01-13 rger */
+
+ if(pstrID != NULL)
+ rsCStrDestruct(&pstrID);
+
+ RETiRet;
+}
+
+
+/* De-Serialize an object, with known constructur and destructor. Params like Deserialize().
+ * Note: this is for the queue subsystem, and optimized for its use.
+ * rgerhards, 2012-11-03
+ */
+rsRetVal
+objDeserializeWithMethods(void *ppObj, uchar *pszTypeExpected, int lenTypeExpected, strm_t *pStrm,
+rsRetVal (*fFixup)(obj_t*,void*), void *pUsr, rsRetVal (*objConstruct)(), rsRetVal (*objConstructFinalize)(),
+rsRetVal (*objDeserialize)())
+{
+ DEFiRet;
+ rsRetVal iRetLocal;
+ obj_t *pObj = NULL;
+ int oVers = 0; /* keep compiler happy, but it is totally useless but takes up some execution time... */
+ cstr_t *pstrID = NULL;
+
+ assert(ppObj != NULL);
+ assert(pszTypeExpected != NULL);
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ /* we de-serialize the header. if all goes well, we are happy. However, if
+ * we experience a problem, we try to recover. We do this by skipping to
+ * the next object header. This is defined via the line-start cookies. In
+ * worst case, we exhaust the queue, but then we receive EOF return state,
+ * from objDeserializeTryRecover(), what will cause us to ultimately give up.
+ * rgerhards, 2008-07-08
+ */
+ do {
+ iRetLocal = objDeserializeHeader((uchar*) "Obj", &pstrID, &oVers, pStrm);
+ if(iRetLocal != RS_RET_OK) {
+ dbgprintf("objDeserialize error %d during header processing - "
+ "trying to recover\n", iRetLocal);
+ CHKiRet(objDeserializeTryRecover(pStrm));
+ }
+ } while(iRetLocal != RS_RET_OK);
+
+ if(rsCStrSzStrCmp(pstrID, pszTypeExpected, lenTypeExpected))
+ ABORT_FINALIZE(RS_RET_INVALID_OID);
+
+ CHKiRet(objConstruct(&pObj));
+
+ /* we got the object, now we need to fill the properties */
+ CHKiRet(objDeserialize(pObj, pStrm));
+ CHKiRet(objDeserializeTrailer(pStrm)); /* do trailer checks */
+
+ /* check if we need to call a fixup function that modifies the object
+ * before it is finalized. -- rgerhards, 2008-01-13
+ */
+ if(fFixup != NULL)
+ CHKiRet(fFixup(pObj, pUsr));
+
+ /* we have a valid object, let's finalize our work and return */
+ if(objConstructFinalize != NULL) {
+ CHKiRet(objConstructFinalize(pObj));
+ }
+
+ *((obj_t**) ppObj) = pObj;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pObj != NULL)
+ free(pObj); /* TODO: check if we can call destructor 2008-01-13 rger */
+
+ if(pstrID != NULL)
+ rsCStrDestruct(&pstrID);
+
+ if(Debug && iRet != RS_RET_OK) {
+ dbgprintf("objDeserializeWithMethods fails with %d, stream state:\n", iRet);
+ strmDebugOutBuf(pStrm);
+ }
+
+
+ RETiRet;
+}
+
+
+/* De-Serialize an object property bag. As a property bag contains only partial properties,
+ * it is not instanciable. Thus, the caller must provide a pointer of an already-instanciated
+ * object of the correct type.
+ * Params: Pointer to object (pObj)
+ * Pointer to be passed to the function
+ * The caller must destruct the created object.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal
+DeserializePropBag(obj_t *pObj, strm_t *pStrm)
+{
+ DEFiRet;
+ rsRetVal iRetLocal;
+ cstr_t *pstrID = NULL;
+ int oVers;
+ objInfo_t *pObjInfo;
+
+ ISOBJ_assert(pObj);
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ /* we de-serialize the header. if all goes well, we are happy. However, if
+ * we experience a problem, we try to recover. We do this by skipping to
+ * the next object header. This is defined via the line-start cookies. In
+ * worst case, we exhaust the queue, but then we receive EOF return state
+ * from objDeserializeTryRecover(), what will cause us to ultimately give up.
+ * rgerhards, 2008-07-08
+ */
+ do {
+ iRetLocal = objDeserializeHeader((uchar*) "OPB", &pstrID, &oVers, pStrm);
+ if(iRetLocal != RS_RET_OK) {
+ dbgprintf("objDeserializePropBag error %d during header - trying to recover\n", iRetLocal);
+ CHKiRet(objDeserializeTryRecover(pStrm));
+ }
+ } while(iRetLocal != RS_RET_OK);
+
+ if(rsCStrSzStrCmp(pstrID, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID))
+ ABORT_FINALIZE(RS_RET_INVALID_OID);
+
+ CHKiRet(FindObjInfo((char*)cstrGetSzStrNoNULL(pstrID), &pObjInfo));
+
+ /* we got the object, now we need to fill the properties */
+ CHKiRet(objDeserializeProperties(pObj, pObjInfo->objMethods[objMethod_SETPROPERTY], pStrm));
+
+finalize_it:
+ if(pstrID != NULL)
+ rsCStrDestruct(&pstrID);
+
+ RETiRet;
+}
+
+#undef NEXTC /* undef helper macro */
+
+
+/* --------------- end object serializiation / deserialization support --------------- */
+
+
+/* set the object (instance) name
+ * rgerhards, 2008-01-29
+ * TODO: change the naming to a rsCStr obj! (faster)
+ */
+static rsRetVal
+SetName(obj_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+
+ free(pThis->pszName);
+ CHKmalloc(pThis->pszName = ustrdup(pszName));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get the object (instance) name
+ * Note that we use a non-standard calling convention. Thus function must never
+ * fail, else we run into real big problems. So it must make sure that at least someting
+ * is returned.
+ * rgerhards, 2008-01-30
+ */
+uchar * ATTR_NONNULL()
+objGetName(obj_t *const pThis)
+{
+ uchar *ret;
+ uchar szName[128];
+
+ ISOBJ_assert(pThis);
+
+ if(pThis->pszName == NULL) {
+ snprintf((char*)szName, sizeof(szName), "%s %p", objGetClassName(pThis), pThis);
+ SetName(pThis, szName);
+ /* looks strange, but we NEED to re-check because if there was an
+ * error in objSetName(), the pointer may still be NULL
+ */
+ if(pThis->pszName == NULL) {
+ ret = objGetClassName(pThis);
+ } else {
+ ret = pThis->pszName;
+ }
+ } else {
+ ret = pThis->pszName;
+ }
+
+ return ret;
+}
+
+
+/* Find the objInfo object for the current object
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+FindObjInfo(const char *const __restrict__ strOID, objInfo_t **ppInfo)
+{
+ DEFiRet;
+ int bFound;
+ int i;
+
+ bFound = 0;
+ i = 0;
+ while(!bFound && i < OBJ_NUM_IDS) {
+ if(arrObjInfo[i] != NULL && !strcmp(strOID, (const char*)arrObjInfo[i]->pszID)) {
+ bFound = 1;
+ break;
+ }
+ ++i;
+ }
+
+ if(!bFound)
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+
+ *ppInfo = arrObjInfo[i];
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ dbgprintf("caller requested object '%s', not found (iRet %d)\n", strOID, iRet);
+ }
+
+ RETiRet;
+}
+
+
+/* register a classes' info pointer, so that we can reference it later, if needed to
+ * (e.g. for de-serialization support).
+ * rgerhards, 2008-01-07
+ * In this function, we look for a free space in the object table. While we do so, we
+ * also detect if the same object has already been registered, which is not valid.
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+RegisterObj(uchar *pszObjName, objInfo_t *pInfo)
+{
+ DEFiRet;
+ int bFound;
+ int i;
+
+ assert(pszObjName != NULL);
+ assert(pInfo != NULL);
+
+ bFound = 0;
+ i = 0;
+ while(!bFound && i < OBJ_NUM_IDS && arrObjInfo[i] != NULL) {
+ if( arrObjInfo[i] != NULL
+ && !ustrcmp(arrObjInfo[i]->pszID, pszObjName)) {
+ bFound = 1;
+ break;
+ }
+ ++i;
+ }
+
+ if(bFound) ABORT_FINALIZE(RS_RET_OBJ_ALREADY_REGISTERED);
+ if(i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE);
+
+ arrObjInfo[i] = pInfo;
+ #if DEV_DEBUG == 1
+ dbgprintf("object '%s' successfully registered with "
+ "index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF);
+ #endif
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "registering object '%s' failed with error code %d", pszObjName, iRet);
+ }
+
+ RETiRet;
+}
+
+
+/* deregister a classes' info pointer, usually called because the class is unloaded.
+ * After deregistration, the class can no longer be accessed, except if it is reloaded.
+ * rgerhards, 2008-03-10
+ */
+static rsRetVal
+UnregisterObj(uchar *pszObjName)
+{
+ DEFiRet;
+ int bFound;
+ int i;
+
+ assert(pszObjName != NULL);
+
+ bFound = 0;
+ i = 0;
+ while(!bFound && i < OBJ_NUM_IDS) {
+ if( arrObjInfo[i] != NULL
+ && !ustrcmp(arrObjInfo[i]->pszID, pszObjName)) {
+ bFound = 1;
+ break;
+ }
+ ++i;
+ }
+
+ if(!bFound)
+ ABORT_FINALIZE(RS_RET_OBJ_NOT_REGISTERED);
+
+ InfoDestruct(&arrObjInfo[i]);
+ #if DEV_DEBUG == 1
+ dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i);
+ #endif
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ dbgprintf("unregistering object '%s' failed with error code %d\n", pszObjName, iRet);
+ }
+
+ RETiRet;
+}
+
+
+/* This function shall be called by anyone who would like to use an object. It will
+ * try to locate the object, load it into memory if not already present and return
+ * a pointer to the objects interface.
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+UseObj(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
+{
+ DEFiRet;
+ objInfo_t *pObjInfo;
+
+
+ #if DEV_DEBUG == 1
+ dbgprintf("source file %s requests object '%s', "
+ " ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
+ #endif
+ pthread_mutex_lock(&mutObjGlobalOp);
+
+ if(pIf->ifIsLoaded == 1) {
+ ABORT_FINALIZE(RS_RET_OK); /* we are already set */
+ }
+ if(pIf->ifIsLoaded == 2) {
+ ABORT_FINALIZE(RS_RET_LOAD_ERROR); /* we had a load error and can not continue */
+ }
+
+ /* we must be careful that we do not enter in infinite loop if an error occurs during
+ * loading a module. ModLoad emits an error message in such cases and that potentially
+ * can trigger the same code here. So we initially set the module state to "load error"
+ * and set it to "fully initialized" when the load succeeded. It's a bit hackish, but
+ * looks like a good solution. -- rgerhards, 2008-03-07
+ */
+ pIf->ifIsLoaded = 2;
+
+ iRet = FindObjInfo((const char*)pObjName, &pObjInfo);
+ if(iRet == RS_RET_NOT_FOUND) {
+ /* in this case, we need to see if we can dynamically load the object */
+ if(pObjFile == NULL) {
+ FINALIZE; /* no chance, we have lost... */
+ } else {
+ CHKiRet(module.Load(pObjFile, 0, NULL));
+ /* NOW, we must find it or we have a problem... */
+ CHKiRet(FindObjInfo((const char*)pObjName, &pObjInfo));
+ }
+ } else if(iRet != RS_RET_OK) {
+ FINALIZE; /* give up */
+ }
+
+ /* if we reach this point, we have a valid pObjInfo */
+ if(pObjFile != NULL) { /* NULL means core module */
+ module.Use(srcFile, pObjInfo->pModInfo); /* increase refcount */
+ }
+
+ CHKiRet(pObjInfo->QueryIF(pIf));
+ pIf->ifIsLoaded = 1; /* we are happy */
+
+finalize_it:
+ pthread_mutex_unlock(&mutObjGlobalOp);
+ RETiRet;
+}
+
+
+/* This function shall be called when a caller is done with an object. Its primary
+ * purpose is to keep the reference count correct, which is highly important for
+ * modules residing in loadable modules.
+ * rgerhards, 2008-03-10
+ */
+static rsRetVal
+ReleaseObj(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
+{
+ DEFiRet;
+ objInfo_t *pObjInfo;
+
+ /* dev debug only dbgprintf("source file %s releasing object '%s',
+ ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */
+ pthread_mutex_lock(&mutObjGlobalOp);
+
+ if(pObjFile == NULL)
+ FINALIZE; /* if it is not a lodable module, we do not need to do anything... */
+
+ if(pIf->ifIsLoaded == 0) {
+ FINALIZE; /* we are not loaded - this is perfectly OK... */
+ } else if(pIf->ifIsLoaded == 2) {
+ pIf->ifIsLoaded = 0; /* clean up */
+ FINALIZE; /* we had a load error and can not/must not continue */
+ }
+
+ CHKiRet(FindObjInfo((const char*)pObjName, &pObjInfo));
+
+ /* if we reach this point, we have a valid pObjInfo */
+ module.Release(srcFile, &pObjInfo->pModInfo); /* decrease refcount */
+
+ pIf->ifIsLoaded = 0; /* indicated "no longer valid" */
+
+finalize_it:
+ pthread_mutex_unlock(&mutObjGlobalOp);
+
+ RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+PROTOTYPEObjQueryInterface(obj);
+BEGINobjQueryInterface(obj)
+CODESTARTobjQueryInterface(obj)
+ if(pIf->ifVersion != objCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->UseObj = UseObj;
+ pIf->ReleaseObj = ReleaseObj;
+ pIf->InfoConstruct = InfoConstruct;
+ pIf->DestructObjSelf = DestructObjSelf;
+ pIf->BeginSerializePropBag = BeginSerializePropBag;
+ pIf->InfoSetMethod = InfoSetMethod;
+ pIf->BeginSerialize = BeginSerialize;
+ pIf->SerializeProp = SerializeProp;
+ pIf->EndSerialize = EndSerialize;
+ pIf->RegisterObj = RegisterObj;
+ pIf->UnregisterObj = UnregisterObj;
+ pIf->Deserialize = Deserialize;
+ pIf->DeserializePropBag = DeserializePropBag;
+ pIf->SetName = SetName;
+ pIf->GetName = objGetName;
+finalize_it:
+ENDobjQueryInterface(obj)
+
+
+/* This function returns a pointer to our own interface. It is used as the
+ * hook that every object (including dynamically loaded ones) can use to
+ * obtain a pointer to our interface which than can be used to obtain
+ * pointers to any other interface in the system. This function must be
+ * externally visible because of its special nature.
+ * rgerhards, 2008-02-29 [nice - will have that date the next time in 4 years ;)]
+ */
+rsRetVal
+objGetObjInterface(obj_if_t *pIf)
+{
+ DEFiRet;
+ assert(pIf != NULL);
+ objQueryInterface(pIf);
+ RETiRet;
+}
+
+
+/* exit our class
+ * rgerhards, 2008-03-11
+ */
+rsRetVal
+objClassExit(void)
+{
+ DEFiRet;
+ /* release objects we no longer need */
+ objRelease(strm, CORE_COMPONENT);
+ objRelease(var, CORE_COMPONENT);
+ objRelease(module, CORE_COMPONENT);
+
+ /* TODO: implement the class exits! */
+#if 0
+ cfsyslineExit(pModInfo);
+ varClassExit(pModInfo);
+#endif
+ moduleClassExit();
+ RETiRet;
+}
+
+
+/* initialize our own class
+ * Please note that this also initializes those classes that we rely on.
+ * Though this is a bit dirty, we need to do it - otherwise we can't get
+ * around that bootstrap problem. We need to face the fact the the obj
+ * class is a little different from the rest of the system, as it provides
+ * the core class loader functionality.
+ * rgerhards, 2008-02-29
+ */
+rsRetVal
+objClassInit(modInfo_t *pModInfo)
+{
+ pthread_mutexattr_t mutAttr;
+ int i;
+ DEFiRet;
+
+ /* first, initialize the object system itself. This must be done
+ * before any other object is created.
+ */
+ for(i = 0 ; i < OBJ_NUM_IDS ; ++i) {
+ arrObjInfo[i] = NULL;
+ }
+
+ /* the mutex must be recursive, because objects may call into other
+ * object identifiers recursively.
+ */
+ pthread_mutexattr_init(&mutAttr);
+ pthread_mutexattr_settype(&mutAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mutObjGlobalOp, &mutAttr);
+
+ /* request objects we use */
+ CHKiRet(objGetObjInterface(&obj)); /* get ourselves ;) */
+
+ /* init classes we use (limit to as few as possible!) */
+ CHKiRet(datetimeClassInit(pModInfo));
+ CHKiRet(cfsyslineInit());
+ CHKiRet(varClassInit(pModInfo));
+ CHKiRet(moduleClassInit(pModInfo));
+ CHKiRet(strmClassInit(pModInfo));
+ CHKiRet(objUse(var, CORE_COMPONENT));
+ CHKiRet(objUse(module, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+
+finalize_it:
+ RETiRet;
+}
diff --git a/runtime/obj.h b/runtime/obj.h
new file mode 100644
index 0000000..0efe6e7
--- /dev/null
+++ b/runtime/obj.h
@@ -0,0 +1,132 @@
+/* Definition of the generic obj class module.
+ *
+ * This module relies heavily on preprocessor macros in order to
+ * provide fast execution time AND ease of use.
+ *
+ * Each object that uses this base class MUST provide a constructor with
+ * the following interface:
+ *
+ * Destruct(pThis);
+ *
+ * A constructor is not necessary (except for some features, e.g. de-serialization).
+ * If it is provided, it is a three-part constructor (to handle all cases with a
+ * generic interface):
+ *
+ * Construct(&pThis);
+ * SetProperty(pThis, property_t *);
+ * ConstructFinalize(pThis);
+ *
+ * SetProperty() and ConstructFinalize() may also be called on an object
+ * instance which has been Construct()'ed outside of this module.
+ *
+ * pThis always references to a pointer of the object.
+ *
+ * Copyright 2008-2018 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OBJ_H_INCLUDED
+#define OBJ_H_INCLUDED
+
+#include "obj-types.h"
+#include "var.h"
+#include "stream.h"
+
+/* macros */
+/* the following one is a helper that prevents us from writing the
+ * ever-same code at the end of Construct()
+ */
+#define OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \
+ if(iRet == RS_RET_OK) { \
+ *ppThis = pThis; \
+ } else { \
+ if(pThis != NULL) \
+ free(pThis); \
+ }
+
+#define objSerializeSCALAR_VAR(strm, propName, propType, var) \
+ CHKiRet(obj.SerializeProp(strm, (uchar*) #propName, PROPTYPE_##propType, (void*) &var));
+#define objSerializeSCALAR(strm, propName, propType) \
+ CHKiRet(obj.SerializeProp(strm, (uchar*) #propName, PROPTYPE_##propType, (void*) &pThis->propName));
+#define objSerializePTR(strm, propName, propType) \
+ CHKiRet(obj.SerializeProp(strm, (uchar*) #propName, PROPTYPE_##propType, (void*) pThis->propName));
+#define DEFobjStaticHelpers \
+ static objInfo_t __attribute__((unused)) *pObjInfoOBJ = NULL; \
+ DEFobjCurrIf(obj)
+
+
+#define objGetClassName(pThis) (((obj_t*) (pThis))->pObjInfo->pszID)
+#define objGetVersion(pThis) (((obj_t*) (pThis))->pObjInfo->iObjVers)
+/* the next macro MUST be called in Constructors: */
+#ifndef NDEBUG /* this means if debug... */
+# define objConstructSetObjInfo(pThis) \
+ ((obj_t*) (pThis))->pObjInfo = pObjInfoOBJ; \
+ ((obj_t*) (pThis))->pszName = NULL; \
+ ((obj_t*) (pThis))->iObjCooCKiE = 0xBADEFEE
+#else
+# define objConstructSetObjInfo(pThis) \
+ ((obj_t*) (pThis))->pObjInfo = pObjInfoOBJ; \
+ ((obj_t*) (pThis))->pszName = NULL
+#endif
+#define objSerialize(pThis) (((obj_t*) (pThis))->pObjInfo->objMethods[objMethod_SERIALIZE])
+
+#define OBJSetMethodHandler(methodID, pHdlr) \
+ CHKiRet(obj.InfoSetMethod(pObjInfoOBJ, methodID, (rsRetVal (*)()) pHdlr))
+
+/* interfaces */
+BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*UseObj)(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf);
+ rsRetVal (*ReleaseObj)(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf);
+ rsRetVal (*InfoConstruct)(objInfo_t **ppThis, uchar *pszID, int iObjVers,
+ rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *),
+ rsRetVal (*pQueryIF)(interface_t*), modInfo_t*);
+ rsRetVal (*DestructObjSelf)(obj_t *pThis);
+ rsRetVal (*BeginSerializePropBag)(strm_t *pStrm, obj_t *pObj);
+ rsRetVal (*InfoSetMethod)(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void*));
+ rsRetVal (*BeginSerialize)(strm_t *pStrm, obj_t *pObj);
+ rsRetVal (*SerializeProp)(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr);
+ rsRetVal (*EndSerialize)(strm_t *pStrm);
+ rsRetVal (*RegisterObj)(uchar *pszObjName, objInfo_t *pInfo);
+ rsRetVal (*UnregisterObj)(uchar *pszObjName);
+ rsRetVal (*Deserialize)(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*),
+ void *pUsr);
+ rsRetVal (*DeserializePropBag)(obj_t *pObj, strm_t *pStrm);
+ rsRetVal (*SetName)(obj_t *pThis, uchar *pszName);
+ uchar * (*GetName)(obj_t *pThis);
+ENDinterface(obj)
+#define objCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+/* the following define *is* necessary, because it provides the root way of obtaining
+ * interfaces (at some place we need to start our query...
+ */
+rsRetVal objGetObjInterface(obj_if_t *pIf);
+PROTOTYPEObjClassInit(obj);
+PROTOTYPEObjClassExit(obj);
+rsRetVal objDeserializeWithMethods(void *ppObj, uchar *pszTypeExpected, int lenTypeExpected, strm_t *pStrm,
+rsRetVal (*fFixup)(obj_t*,void*), void *pUsr, rsRetVal (*objConstruct)(), rsRetVal (*objConstructFinalize)(),
+rsRetVal (*objDeserialize)());
+rsRetVal objDeserializeProperty(var_t *pProp, strm_t *pStrm);
+uchar *objGetName(obj_t *pThis);
+
+
+/* the following definition is only for "friends" */
+extern pthread_mutex_t mutObjGlobalOp; /* mutex to guard global operations of the object system */
+
+#endif /* #ifndef OBJ_H_INCLUDED */
diff --git a/runtime/objomsr.c b/runtime/objomsr.c
new file mode 100644
index 0000000..0cf98d0
--- /dev/null
+++ b/runtime/objomsr.c
@@ -0,0 +1,158 @@
+/* objomsr.c
+ * Implementation of the omsr (omodStringRequest) object.
+ *
+ * File begun on 2007-07-27 by RGerhards
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "objomsr.h"
+
+
+/* destructor
+ */
+rsRetVal OMSRdestruct(omodStringRequest_t *pThis)
+{
+ int i;
+
+ assert(pThis != NULL);
+ /* free the strings */
+ if(pThis->ppTplName != NULL) {
+ for(i = 0 ; i < pThis->iNumEntries ; ++i) {
+ free(pThis->ppTplName[i]);
+ }
+ free(pThis->ppTplName);
+ }
+ if(pThis->piTplOpts != NULL)
+ free(pThis->piTplOpts);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor
+ */
+rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries)
+{
+ omodStringRequest_t *pThis = NULL;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ assert(iNumEntries >= 0);
+ if(iNumEntries > CONF_OMOD_NUMSTRINGS_MAXSIZE) {
+ ABORT_FINALIZE(RS_RET_MAX_OMSR_REACHED);
+ }
+ CHKmalloc(pThis = calloc(1, sizeof(omodStringRequest_t)));
+
+ /* got the structure, so fill it */
+ if(iNumEntries > 0) {
+ pThis->iNumEntries = iNumEntries;
+ /* allocate string for template name array. The individual strings will be
+ * allocated as the code progresses (we do not yet know the string sizes)
+ */
+ CHKmalloc(pThis->ppTplName = calloc(iNumEntries, sizeof(uchar*)));
+
+ /* allocate the template options array. */
+ CHKmalloc(pThis->piTplOpts = calloc(iNumEntries, sizeof(int)));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis != NULL) {
+ OMSRdestruct(pThis);
+ pThis = NULL;
+ }
+ }
+ *ppThis = pThis;
+ RETiRet;
+}
+
+/* set a template name and option to the object. Index must be given. The pTplName must be
+ * pointing to memory that can be freed. If in doubt, the caller must strdup() the value.
+ */
+rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts)
+{
+ assert(pThis != NULL);
+ assert(iEntry < pThis->iNumEntries);
+
+ if(pThis->ppTplName[iEntry] != NULL)
+ free(pThis->ppTplName[iEntry]);
+ pThis->ppTplName[iEntry] = pTplName;
+ pThis->piTplOpts[iEntry] = iTplOpts;
+
+ return RS_RET_OK;
+}
+
+
+/* get number of entries for this object
+ */
+int OMSRgetEntryCount(omodStringRequest_t *pThis)
+{
+ assert(pThis != NULL);
+ return pThis->iNumEntries;
+}
+
+
+/* return data for a specific entry. All data returned is
+ * read-only and lasts only as long as the object lives. If the caller
+ * needs it for an extended period of time, the caller must copy the
+ * strings. Please note that the string pointer may be NULL, which is the
+ * case when it was never set.
+ */
+int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts)
+{
+ assert(pThis != NULL);
+ assert(ppTplName != NULL);
+ assert(piTplOpts != NULL);
+ assert(iEntry < pThis->iNumEntries);
+
+ *ppTplName = pThis->ppTplName[iEntry];
+ *piTplOpts = pThis->piTplOpts[iEntry];
+
+ return RS_RET_OK;
+}
+
+
+/* return the full set of template options that are supported by this version of
+ * OMSR. They are returned in an unsigned long value. The caller can mask that
+ * value to check on the option he is interested in.
+ * Note that this interface was added in 4.1.6, so a plugin must obtain a pointer
+ * to this interface via queryHostEtryPt().
+ * rgerhards, 2009-04-03
+ */
+rsRetVal
+OMSRgetSupportedTplOpts(unsigned long *pOpts)
+{
+ DEFiRet;
+ assert(pOpts != NULL);
+ *pOpts = OMSR_RQD_TPL_OPT_SQL | OMSR_TPL_AS_ARRAY | OMSR_TPL_AS_MSG
+ | OMSR_TPL_AS_JSON;
+ RETiRet;
+}
+
+/* vim:set ai:
+ */
diff --git a/runtime/objomsr.h b/runtime/objomsr.h
new file mode 100644
index 0000000..d06db4a
--- /dev/null
+++ b/runtime/objomsr.h
@@ -0,0 +1,51 @@
+/* Definition of the omsr (omodStringRequest) object.
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OBJOMSR_H_INCLUDED
+#define OBJOMSR_H_INCLUDED
+
+/* define flags for required template options */
+#define OMSR_NO_RQD_TPL_OPTS 0
+#define OMSR_RQD_TPL_OPT_SQL 1
+/* only one of OMSR_TPL_AS_ARRAY, _AS_MSG, or _AS_JSON must be specified,
+ * if all are given results are unpredictable.
+ */
+#define OMSR_TPL_AS_ARRAY 2 /* introduced in 4.1.6, 2009-04-03 */
+#define OMSR_TPL_AS_MSG 4 /* introduced in 5.3.4, 2009-11-02 */
+#define OMSR_TPL_AS_JSON 8 /* introduced in 6.5.1, 2012-09-02 */
+/* next option is 16, 32, 64, ... */
+
+struct omodStringRequest_s { /* strings requested by output module for doAction() */
+ int iNumEntries; /* number of array entries for data elements below */
+ uchar **ppTplName; /* pointer to array of template names */
+ int *piTplOpts;/* pointer to array of check-options when pulling template */
+};
+typedef struct omodStringRequest_s omodStringRequest_t;
+
+/* prototypes */
+rsRetVal OMSRdestruct(omodStringRequest_t *pThis);
+rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries);
+rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts);
+rsRetVal OMSRgetSupportedTplOpts(unsigned long *pOpts);
+int OMSRgetEntryCount(omodStringRequest_t *pThis);
+int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts);
+
+#endif /* #ifndef OBJOMSR_H_INCLUDED */
diff --git a/runtime/operatingstate.c b/runtime/operatingstate.c
new file mode 100644
index 0000000..04b4cbd
--- /dev/null
+++ b/runtime/operatingstate.c
@@ -0,0 +1,177 @@
+/* OperatingStateFile Handler.
+ *
+ * Copyright 2018 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "operatingstate.h"
+#include "rsconf.h"
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+#ifndef HAVE_LSEEK64
+# define lseek64(fd, offset, whence) lseek(fd, offset, whence)
+#endif
+
+/* some important standard states */
+#define STATE_INITIALIZING "INITIALIZING"
+#define STATE_CLEAN_CLOSE "CLEAN CLOSE"
+
+static int fd_osf = -1;
+
+/* check if old osf points to a problem and, if so, report */
+static void
+osf_checkOnStartup(void)
+{
+ int do_rename = 1;
+ const char *fn_osf = (const char*) glblGetOperatingStateFile(loadConf);
+ char iobuf[sizeof(STATE_CLEAN_CLOSE)];
+ const int len_clean_close = sizeof(STATE_CLEAN_CLOSE) - 1;
+ assert(fn_osf != NULL);
+
+ const int fd = open(fn_osf, O_RDONLY|O_LARGEFILE|O_CLOEXEC, 0);
+ if(fd == -1) {
+ if(errno != ENOENT) {
+ LogError(errno, RS_RET_ERR, "error opening existing operatingStateFile '%s' - "
+ "this may be an indication of a problem; ignoring", fn_osf);
+ }
+ do_rename = 0;
+ goto done;
+ }
+ assert(fd != -1);
+ int offs = lseek64(fd, -(len_clean_close + 1), SEEK_END);
+ if(offs == -1){
+ LogError(errno, RS_RET_IO_ERROR, "error seeking to end of existing operatingStateFile "
+ "'%s' - this may be an indication of a problem, e.g. empty file", fn_osf);
+ goto done;
+ }
+ int rd = read(fd, iobuf, len_clean_close);
+ if(rd == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "error reading existing operatingStateFile "
+ "'%s' - this probably indicates an improper shutdown", fn_osf);
+ goto done;
+ } else {
+ assert(rd <= len_clean_close);
+ iobuf[rd] = '\0';
+ if(rd != len_clean_close || strcmp(iobuf, STATE_CLEAN_CLOSE) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "existing operatingStateFile '%s' does not end "
+ "with '%s, instead it has '%s' - this probably indicates an "
+ "improper shutdown", fn_osf, STATE_CLEAN_CLOSE, iobuf);
+ goto done;
+ }
+ }
+
+ /* all ok! */
+ do_rename = 0;
+done:
+ if(fd != -1) {
+ close(fd);
+ }
+ if(do_rename) {
+ char newname[MAXFNAME];
+ snprintf(newname, sizeof(newname)-1, "%s.previous", fn_osf);
+ newname[MAXFNAME-1] = '\0';
+ if(rename(fn_osf, newname) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "could not rename existing operatingStateFile "
+ "'%s' to '%s' - ignored, but will probably be overwritten now",
+ fn_osf, newname);
+ } else {
+ LogMsg(errno, RS_RET_OK, LOG_INFO, "existing state file '%s' renamed "
+ "to '%s' - you may want to review it", fn_osf, newname);
+ }
+ }
+ return;
+}
+
+void
+osf_open(void)
+{
+ assert(fd_osf == -1);
+ const char *fn_osf = (const char*) glblGetOperatingStateFile(loadConf);
+ assert(fn_osf != NULL);
+
+ osf_checkOnStartup();
+
+ fd_osf = open(fn_osf, O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE|O_CLOEXEC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
+ if(fd_osf == -1) {
+ LogError(errno, RS_RET_ERR, "error opening operatingStateFile '%s' for write - "
+ "ignoring it", fn_osf);
+ goto done;
+ }
+ assert(fd_osf != -1);
+
+ osf_write(OSF_TAG_STATE, STATE_INITIALIZING " " VERSION);
+done:
+ return;
+}
+
+
+void ATTR_NONNULL()
+osf_write(const char *const tag, const char *const line)
+{
+ char buf[1024]; /* intentionally small */
+ time_t tt;
+ ssize_t wr;
+ size_t len;
+ struct tm tm;
+
+ DBGPRINTF("osf: %s %s: ", tag, line); /* ensure everything is inside the debug log */
+
+ if(fd_osf == -1)
+ return;
+
+ time(&tt);
+ localtime_r(&tt, &tm);
+ len = snprintf(buf, sizeof(buf)-1, "%d%2.2d%2.2d-%2.2d%2.2d%2.2d: %-5.5s %s\n",
+ tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tag, line);
+ if(len > sizeof(buf)-1) {
+ len = sizeof(buf)-1; /* overflow, truncate */
+ }
+ wr = write(fd_osf, buf, len);
+ // TODO: handle EINTR
+ if(wr != (ssize_t) len) {
+ LogError(errno, RS_RET_IO_ERROR, "error writing operating state file - line lost");
+ }
+}
+
+
+void
+osf_close(void)
+{
+ if(fd_osf == -1)
+ return;
+ osf_write(OSF_TAG_STATE, STATE_CLEAN_CLOSE);
+ close(fd_osf);
+}
diff --git a/runtime/operatingstate.h b/runtime/operatingstate.h
new file mode 100644
index 0000000..a832a74
--- /dev/null
+++ b/runtime/operatingstate.h
@@ -0,0 +1,32 @@
+/* OperatingStateFile interface.
+ *
+ * Copyright 2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_OPERATINGSTATEFILE_H
+#define INCLUDED_OPERATINGSTATEFILE_H
+
+/* supported TAGS */
+#define OSF_TAG_STATE "STATE"
+#define OSF_TAG_MSG "MSG"
+
+void osf_open(void);
+void ATTR_NONNULL() osf_write(const char *const tag, const char *const line);
+void osf_close(void);
+
+#endif /* #ifndef INCLUDED_OPERATINGSTATEFILE_H */
diff --git a/runtime/parser.c b/runtime/parser.c
new file mode 100644
index 0000000..a22ad72
--- /dev/null
+++ b/runtime/parser.c
@@ -0,0 +1,742 @@
+/* parser.c
+ * This module contains functions for message parsers. It still needs to be
+ * converted into an object (and much extended).
+ *
+ * Module begun 2008-10-09 by Rainer Gerhards (based on previous code from syslogd.c)
+ *
+ * Copyright 2008-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <zlib.h>
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "msg.h"
+#include "obj.h"
+#include "datetime.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "ruleset.h"
+#include "unicode-helper.h"
+#include "dirty.h"
+#include "cfsysline.h"
+
+/* some defines */
+#define DEFUPRI (LOG_USER|LOG_NOTICE)
+
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(ruleset)
+
+/* static data */
+
+static char hexdigit[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+BEGINobjDestruct(parser) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(parser)
+ DBGPRINTF("destructing parser '%s'\n", pThis->pName);
+ if(pThis->pInst != NULL) {
+ pThis->pModule->mod.pm.freeParserInst(pThis->pInst);
+ }
+ free(pThis->pName);
+ENDobjDestruct(parser)
+
+/* destruct a parser list. The list elements are destroyed, but the parser objects
+ * themselves are not modified. (That is done at a late stage during rsyslogd
+ * shutdown and need not be considered here.)
+ */
+static rsRetVal
+DestructParserList(parserList_t **ppListRoot)
+{
+ parserList_t *pParsLst;
+ parserList_t *pParsLstDel;
+
+ pParsLst = *ppListRoot;
+ while(pParsLst != NULL) {
+ pParsLstDel = pParsLst;
+ pParsLst = pParsLst->pNext;
+ free(pParsLstDel);
+ }
+ *ppListRoot = NULL;
+ return RS_RET_OK;
+}
+
+
+/* Add a parser to the list. We use a VERY simple and ineffcient algorithm,
+ * but it is employed only for a few milliseconds during config processing. So
+ * I prefer to keep it very simple and with simple data structures. Unfortunately,
+ * we need to preserve the order, but I don't like to add a tail pointer as that
+ * would require a container object. So I do the extra work to skip to the tail
+ * when adding elements...
+ * rgerhards, 2009-11-03
+ */
+static rsRetVal
+AddParserToList(parserList_t **ppListRoot, parser_t *pParser)
+{
+ parserList_t *pThis;
+ parserList_t *pTail;
+ DEFiRet;
+
+ CHKmalloc(pThis = malloc(sizeof(parserList_t)));
+ pThis->pParser = pParser;
+ pThis->pNext = NULL;
+
+ if(*ppListRoot == NULL) {
+ pThis->pNext = *ppListRoot;
+ *ppListRoot = pThis;
+ } else {
+ /* find tail first */
+ for(pTail = *ppListRoot ; pTail->pNext != NULL ; pTail = pTail->pNext)
+ /* just search, do nothing else */;
+ /* add at tail */
+ pTail->pNext = pThis;
+ }
+DBGPRINTF("DDDDD: added parser '%s' to list %p\n", pParser->pName, ppListRoot);
+finalize_it:
+ RETiRet;
+}
+
+void
+printParserList(parserList_t *pList)
+{
+ while(pList != NULL) {
+ dbgprintf("parser: %s\n", pList->pParser->pName);
+ pList = pList->pNext;
+ }
+}
+
+/* find a parser based on the provided name */
+static rsRetVal
+FindParser(parserList_t *pParserListRoot, parser_t **ppParser, uchar *pName)
+{
+ parserList_t *pThis;
+ DEFiRet;
+
+ for(pThis = pParserListRoot ; pThis != NULL ; pThis = pThis->pNext) {
+ if(ustrcmp(pThis->pParser->pName, pName) == 0) {
+ *ppParser = pThis->pParser;
+ FINALIZE; /* found it, iRet still eq. OK! */
+ }
+ }
+
+ iRet = RS_RET_PARSER_NOT_FOUND;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* --- END helper functions for parser list handling --- */
+
+/* Add a an already existing parser to the default list. As usual, order
+ * of calls is important (most importantly, that means the legacy parser,
+ * which can process everything, MUST be added last!).
+ * rgerhards, 2009-11-04
+ */
+static rsRetVal
+AddDfltParser(uchar *pName)
+{
+ parser_t *pParser;
+ DEFiRet;
+
+ CHKiRet(FindParser(loadConf->parsers.pParsLstRoot, &pParser, pName));
+ CHKiRet(AddParserToList(&loadConf->parsers.pDfltParsLst, pParser));
+ DBGPRINTF("Parser '%s' added to default parser set.\n", pName);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the parser name - string is copied over, call can continue to use it,
+ * but must free it if desired.
+ */
+static rsRetVal
+SetName(parser_t *pThis, uchar *name)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, parser);
+ assert(name != NULL);
+
+ if(pThis->pName != NULL) {
+ free(pThis->pName);
+ pThis->pName = NULL;
+ }
+
+ CHKmalloc(pThis->pName = ustrdup(name));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set a pointer to "our" module. Note that no module
+ * pointer must already be set.
+ */
+static rsRetVal
+SetModPtr(parser_t *pThis, modInfo_t *pMod)
+{
+ ISOBJ_TYPE_assert(pThis, parser);
+ assert(pMod != NULL);
+ assert(pThis->pModule == NULL);
+ pThis->pModule = pMod;
+ return RS_RET_OK;
+}
+
+
+/* Specify if we should do standard PRI parsing before we pass the data
+ * down to the parser module.
+ */
+static rsRetVal
+SetDoPRIParsing(parser_t *pThis, int bDoIt)
+{
+ ISOBJ_TYPE_assert(pThis, parser);
+ pThis->bDoPRIParsing = bDoIt;
+ return RS_RET_OK;
+}
+
+
+
+
+BEGINobjConstruct(parser) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(parser)
+
+/* ConstructionFinalizer. The most important chore is to add the parser object
+ * to our global list of available parsers.
+ * rgerhards, 2009-11-03
+ */
+static rsRetVal parserConstructFinalize(parser_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, parser);
+ CHKiRet(AddParserToList(&loadConf->parsers.pParsLstRoot, pThis));
+ DBGPRINTF("Parser '%s' added to list of available parsers.\n", pThis->pName);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* construct a parser object via a pointer to the parser module
+ * and the name. This is a separate function because we need it
+ * in multiple spots inside the code.
+ */
+rsRetVal
+parserConstructViaModAndName(modInfo_t *__restrict__ pMod, uchar *const __restrict__ pName, void *pInst)
+{
+ rsRetVal localRet;
+ parser_t *pParser = NULL;
+ DEFiRet;
+
+ if(pInst == NULL && pMod->mod.pm.newParserInst != NULL) {
+ /* this happens for the default instance on ModLoad time */
+ CHKiRet(pMod->mod.pm.newParserInst(NULL, &pInst));
+ }
+ CHKiRet(parserConstruct(&pParser));
+ /* check some features */
+ localRet = pMod->isCompatibleWithFeature(sFEATUREAutomaticSanitazion);
+ if(localRet == RS_RET_OK){
+ pParser->bDoSanitazion = RSTRUE;
+ }
+ localRet = pMod->isCompatibleWithFeature(sFEATUREAutomaticPRIParsing);
+ if(localRet == RS_RET_OK){
+ CHKiRet(SetDoPRIParsing(pParser, RSTRUE));
+ }
+
+ CHKiRet(SetName(pParser, pName));
+ CHKiRet(SetModPtr(pParser, pMod));
+ pParser->pInst = pInst;
+ CHKiRet(parserConstructFinalize(pParser));
+finalize_it:
+ if(iRet != RS_RET_OK)
+ free(pParser);
+ RETiRet;
+}
+
+/* uncompress a received message if it is compressed.
+ * pMsg->pszRawMsg buffer is updated.
+ * rgerhards, 2008-10-09
+ */
+static rsRetVal uncompressMessage(smsg_t *pMsg)
+{
+ DEFiRet;
+ uchar *deflateBuf = NULL;
+ uLongf iLenDefBuf;
+ uchar *pszMsg;
+ size_t lenMsg;
+
+ assert(pMsg != NULL);
+ pszMsg = pMsg->pszRawMsg;
+ lenMsg = pMsg->iLenRawMsg;
+
+ /* we first need to check if we have a compressed record. If so,
+ * we must decompress it.
+ */
+ if(lenMsg > 0 && *pszMsg == 'z' &&
+ runConf->globals.bSupportCompressionExtension) { /* compressed data present? */
+ /* we have compressed data, so let's deflate it. We support a maximum
+ * message size of iMaxLine. If it is larger, an error message is logged
+ * and the message is dropped. We do NOT try to decompress larger messages
+ * as such might be used for denial of service. It might happen to later
+ * builds that such functionality be added as an optional, operator-configurable
+ * feature.
+ */
+ int ret;
+ iLenDefBuf = glbl.GetMaxLine(runConf);
+ CHKmalloc(deflateBuf = malloc(iLenDefBuf + 1));
+ ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) pszMsg+1, lenMsg-1);
+ DBGPRINTF("Compressed message uncompressed with status %d, length: new %ld, old %d.\n",
+ ret, (long) iLenDefBuf, (int) (lenMsg-1));
+ /* Now check if the uncompression worked. If not, there is not much we can do. In
+ * that case, we log an error message but ignore the message itself. Storing the
+ * compressed text is dangerous, as it contains control characters. So we do
+ * not do this. If someone would like to have a copy, this code here could be
+ * modified to do a hex-dump of the buffer in question. We do not include
+ * this functionality right now.
+ * rgerhards, 2006-12-07
+ */
+ if(ret != Z_OK) {
+ LogError(0, NO_ERRCODE, "Uncompression of a message failed with return code %d "
+ "- enable debug logging if you need further information. "
+ "Message ignored.", ret);
+ FINALIZE; /* unconditional exit, nothing left to do... */
+ }
+ MsgSetRawMsg(pMsg, (char*)deflateBuf, iLenDefBuf);
+ }
+finalize_it:
+ if(deflateBuf != NULL)
+ free(deflateBuf);
+
+ RETiRet;
+}
+
+
+/* sanitize a received message
+ * if a message gets to large during sanitization, it is truncated. This is
+ * as specified in the upcoming syslog RFC series.
+ * rgerhards, 2008-10-09
+ * We check if we have a NUL character at the very end of the
+ * message. This seems to be a frequent problem with a number of senders.
+ * So I have now decided to drop these NULs. However, if they are intentional,
+ * that may cause us some problems, e.g. with syslog-sign. On the other hand,
+ * current code always has problems with intentional NULs (as it needs to escape
+ * them to prevent problems with the C string libraries), so that does not
+ * really matter. Just to be on the save side, we'll log destruction of such
+ * NULs in the debug log.
+ * rgerhards, 2007-09-14
+ */
+static rsRetVal
+SanitizeMsg(smsg_t *pMsg)
+{
+ DEFiRet;
+ uchar *pszMsg;
+ uchar *pDst; /* destination for copy job */
+ size_t lenMsg;
+ size_t iSrc;
+ size_t iDst;
+ size_t iMaxLine;
+ size_t maxDest;
+ uchar pc;
+ sbool bUpdatedLen = RSFALSE;
+ uchar szSanBuf[32*1024]; /* buffer used for sanitizing a string */
+
+ assert(pMsg != NULL);
+ assert(pMsg->iLenRawMsg > 0);
+
+ pszMsg = pMsg->pszRawMsg;
+ lenMsg = pMsg->iLenRawMsg;
+
+ /* remove NUL character at end of message (see comment in function header)
+ * Note that we do not need to add a NUL character in this case, because it
+ * is already present ;)
+ */
+ if(pszMsg[lenMsg-1] == '\0') {
+ DBGPRINTF("dropped NUL at very end of message\n");
+ bUpdatedLen = RSTRUE;
+ lenMsg--;
+ }
+
+ /* then we check if we need to drop trailing LFs, which often make
+ * their way into syslog messages unintentionally. In order to remain
+ * compatible to recent IETF developments, we allow the user to
+ * turn on/off this handling. rgerhards, 2007-07-23
+ */
+ if(glbl.GetParserDropTrailingLFOnReception(runConf)
+ && lenMsg > 0 && pszMsg[lenMsg-1] == '\n') {
+ DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n");
+ lenMsg--;
+ pszMsg[lenMsg] = '\0';
+ bUpdatedLen = RSTRUE;
+ }
+
+ /* it is much quicker to sweep over the message and see if it actually
+ * needs sanitation than to do the sanitation in any case. So we first do
+ * this and terminate when it is not needed - which is expectedly the case
+ * for the vast majority of messages. -- rgerhards, 2009-06-15
+ * Note that we do NOT check here if tab characters are to be escaped or
+ * not. I expect this functionality to be seldomly used and thus I do not
+ * like to pay the performance penalty. So the penalty is only with those
+ * that actually use it, because we may call the sanitizer without actual
+ * need below (but it then still will work perfectly well!). -- rgerhards, 2009-11-27
+ */
+ int bNeedSanitize = 0;
+ for(iSrc = 0 ; iSrc < lenMsg ; iSrc++) {
+ if(pszMsg[iSrc] < 32) {
+ if(glbl.GetParserSpaceLFOnReceive(runConf) && pszMsg[iSrc] == '\n') {
+ pszMsg[iSrc] = ' ';
+ } else if(pszMsg[iSrc] == '\0' || glbl.GetParserEscapeControlCharactersOnReceive(runConf)) {
+ bNeedSanitize = 1;
+ if (!glbl.GetParserSpaceLFOnReceive(runConf)) {
+ break;
+ }
+ }
+ } else if(pszMsg[iSrc] > 127 && glbl.GetParserEscape8BitCharactersOnReceive(runConf)) {
+ bNeedSanitize = 1;
+ break;
+ }
+ }
+
+ if(!bNeedSanitize) {
+ if(bUpdatedLen == RSTRUE)
+ MsgSetRawMsgSize(pMsg, lenMsg);
+ FINALIZE;
+ }
+
+ /* now copy over the message and sanitize it. Note that up to iSrc-1 there was
+ * obviously no need to sanitize, so we can go over that quickly...
+ */
+ iMaxLine = glbl.GetMaxLine(runConf);
+ maxDest = lenMsg * 4; /* message can grow at most four-fold */
+
+ if(maxDest > iMaxLine)
+ maxDest = iMaxLine; /* but not more than the max size! */
+ if(maxDest < sizeof(szSanBuf))
+ pDst = szSanBuf;
+ else
+ CHKmalloc(pDst = malloc(maxDest + 1));
+ if(iSrc > 0) {
+ iSrc--; /* go back to where everything is OK */
+ if(iSrc > maxDest) {
+ DBGPRINTF("parser.Sanitize: have oversize index %zd, "
+ "max %zd - corrected, but should not happen\n",
+ iSrc, maxDest);
+ iSrc = maxDest;
+ }
+ memcpy(pDst, pszMsg, iSrc); /* fast copy known good */
+ }
+ iDst = iSrc;
+ while(iSrc < lenMsg && iDst < maxDest - 3) { /* leave some space if last char must be escaped */
+ if((pszMsg[iSrc] < 32) && (pszMsg[iSrc] != '\t' || glbl.GetParserEscapeControlCharacterTab(runConf))) {
+ /* note: \0 must always be escaped, the rest of the code currently
+ * can not handle it! -- rgerhards, 2009-08-26
+ */
+ if(pszMsg[iSrc] == '\0' || glbl.GetParserEscapeControlCharactersOnReceive(runConf)) {
+ /* we are configured to escape control characters. Please note
+ * that this most probably break non-western character sets like
+ * Japanese, Korean or Chinese. rgerhards, 2007-07-17
+ */
+ if (glbl.GetParserEscapeControlCharactersCStyle(runConf)) {
+ pDst[iDst++] = '\\';
+
+ switch (pszMsg[iSrc]) {
+ case '\0':
+ pDst[iDst++] = '0';
+ break;
+ case '\a':
+ pDst[iDst++] = 'a';
+ break;
+ case '\b':
+ pDst[iDst++] = 'b';
+ break;
+ case '\x1b': /* equivalent to '\e' which is not accepted by XLC */
+ pDst[iDst++] = 'e';
+ break;
+ case '\f':
+ pDst[iDst++] = 'f';
+ break;
+ case '\n':
+ pDst[iDst++] = 'n';
+ break;
+ case '\r':
+ pDst[iDst++] = 'r';
+ break;
+ case '\t':
+ pDst[iDst++] = 't';
+ break;
+ case '\v':
+ pDst[iDst++] = 'v';
+ break;
+ default:
+ pDst[iDst++] = 'x';
+
+ pc = pszMsg[iSrc];
+ pDst[iDst++] = hexdigit[(pc & 0xF0) >> 4];
+ pDst[iDst++] = hexdigit[pc & 0xF];
+
+ break;
+ }
+
+ } else {
+ pDst[iDst++] = glbl.GetParserControlCharacterEscapePrefix(runConf);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0300) >> 6);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0070) >> 3);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0007));
+ }
+ }
+
+ } else if(pszMsg[iSrc] > 127 && glbl.GetParserEscape8BitCharactersOnReceive(runConf)) {
+ if (glbl.GetParserEscapeControlCharactersCStyle(runConf)) {
+ pDst[iDst++] = '\\';
+ pDst[iDst++] = 'x';
+
+ pc = pszMsg[iSrc];
+ pDst[iDst++] = hexdigit[(pc & 0xF0) >> 4];
+ pDst[iDst++] = hexdigit[pc & 0xF];
+
+ } else {
+ /* In this case, we also do the conversion. Note that this most
+ * probably breaks European languages. -- rgerhards, 2010-01-27
+ */
+ pDst[iDst++] = glbl.GetParserControlCharacterEscapePrefix(runConf);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0300) >> 6);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0070) >> 3);
+ pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0007));
+ }
+ } else {
+ pDst[iDst++] = pszMsg[iSrc];
+ }
+ ++iSrc;
+ }
+ pDst[iDst] = '\0';
+
+ MsgSetRawMsg(pMsg, (char*)pDst, iDst); /* save sanitized string */
+
+ if(pDst != szSanBuf)
+ free(pDst);
+
+finalize_it:
+ RETiRet;
+}
+
+/* A standard parser to parse out the PRI. This is made available in
+ * this module as it is expected that allmost all parsers will need
+ * that functionality and so they do not need to implement it themsleves.
+ */
+static rsRetVal
+ParsePRI(smsg_t *pMsg)
+{
+ syslog_pri_t pri;
+ uchar *msg;
+ int lenMsg;
+ DEFiRet;
+
+ /* pull PRI */
+ lenMsg = pMsg->iLenRawMsg;
+ msg = pMsg->pszRawMsg;
+ pri = DEFUPRI;
+ if(pMsg->msgFlags & NO_PRI_IN_RAW) {
+ /* In this case, simply do so as if the pri would be right at top */
+ MsgSetAfterPRIOffs(pMsg, 0);
+ } else {
+ if(*msg == '<') {
+ pri = 0;
+ while(--lenMsg > 0 && isdigit((int) *++msg) && pri <= LOG_MAXPRI) {
+ pri = 10 * pri + (*msg - '0');
+ }
+ if(*msg == '>') {
+ ++msg;
+ } else {
+ pri = LOG_PRI_INVLD;
+ }
+ if(pri > LOG_MAXPRI)
+ pri = LOG_PRI_INVLD;
+ }
+ msgSetPRI(pMsg, pri);
+ MsgSetAfterPRIOffs(pMsg, (pri == LOG_PRI_INVLD) ? 0 : msg - pMsg->pszRawMsg);
+ }
+ RETiRet;
+}
+
+
+/* Parse a received message. The object's rawmsg property is taken and
+ * parsed according to the relevant standards. This can later be
+ * extended to support configured parsers.
+ * rgerhards, 2008-10-09
+ */
+static rsRetVal
+ParseMsg(smsg_t *pMsg)
+{
+ rsRetVal localRet = RS_RET_ERR;
+ parserList_t *pParserList;
+ parser_t *pParser;
+ sbool bIsSanitized;
+ sbool bPRIisParsed;
+ static int iErrMsgRateLimiter = 0;
+ DEFiRet;
+
+ if(pMsg->iLenRawMsg == 0)
+ ABORT_FINALIZE(RS_RET_EMPTY_MSG);
+
+ CHKiRet(uncompressMessage(pMsg));
+
+ /* we take the risk to print a non-sanitized string, because this is the best we can get
+ * (and that functionality is too important for debugging to drop it...).
+ */
+ DBGPRINTF("msg parser: flags %x, from '%s', msg '%.60s'\n", pMsg->msgFlags,
+ (pMsg->msgFlags & NEEDS_DNSRESOL) ? UCHAR_CONSTANT("~NOTRESOLVED~") : getRcvFrom(pMsg),
+ pMsg->pszRawMsg);
+
+ /* we now need to go through our list of parsers and see which one is capable of
+ * parsing the message. Note that the first parser that requires message sanitization
+ * will cause it to happen. After that, access to the unsanitized message is no
+ * loger possible.
+ */
+ pParserList = ruleset.GetParserList(runConf, pMsg);
+ if(pParserList == NULL) {
+ pParserList = runConf->parsers.pDfltParsLst;
+ }
+ DBGPRINTF("parse using parser list %p%s.\n", pParserList,
+ (pParserList == runConf->parsers.pDfltParsLst) ? " (the default list)" : "");
+
+ bIsSanitized = RSFALSE;
+ bPRIisParsed = RSFALSE;
+ while(pParserList != NULL) {
+ pParser = pParserList->pParser;
+ if(pParser->bDoSanitazion && bIsSanitized == RSFALSE) {
+ CHKiRet(SanitizeMsg(pMsg));
+ if(pParser->bDoPRIParsing && bPRIisParsed == RSFALSE) {
+ CHKiRet(ParsePRI(pMsg));
+ bPRIisParsed = RSTRUE;
+ }
+ bIsSanitized = RSTRUE;
+ }
+ if(pParser->pModule->mod.pm.parse2 == NULL)
+ localRet = pParser->pModule->mod.pm.parse(pMsg);
+ else
+ localRet = pParser->pModule->mod.pm.parse2(pParser->pInst, pMsg);
+ DBGPRINTF("Parser '%s' returned %d\n", pParser->pName, localRet);
+ if(localRet != RS_RET_COULD_NOT_PARSE)
+ break;
+ pParserList = pParserList->pNext;
+ }
+
+ /* We need to log a warning message and drop the message if we did not find a parser.
+ * Note that we log at most the first 1000 message, as this may very well be a problem
+ * that causes a message generation loop. We do not synchronize that counter, it doesn't
+ * matter if we log a handful messages more than we should...
+ */
+ if(localRet != RS_RET_OK) {
+ if(++iErrMsgRateLimiter < 1000) {
+ LogError(0, localRet, "Error: one message could not be processed by "
+ "any parser, message is being discarded (start of raw msg: '%.60s')",
+ pMsg->pszRawMsg);
+ }
+ DBGPRINTF("No parser could process the message (state %d), we need to discard it.\n", localRet);
+ ABORT_FINALIZE(localRet);
+ }
+
+ /* "finalize" message object */
+ pMsg->msgFlags &= ~NEEDS_PARSING; /* this message is now parsed */
+
+finalize_it:
+ RETiRet;
+}
+
+/* This destroys the master parserlist and all of its parser entries.
+ * Parser modules are NOT unloaded, rsyslog does that at a later stage
+ * for all dynamically loaded modules.
+ */
+static rsRetVal
+destroyMasterParserList(parserList_t *pParserListRoot)
+{
+ DEFiRet;
+ parserList_t *pParsLst;
+ parserList_t *pParsLstDel;
+
+ pParsLst = pParserListRoot;
+ while(pParsLst != NULL) {
+ parserDestruct(&pParsLst->pParser);
+ pParsLstDel = pParsLst;
+ pParsLst = pParsLst->pNext;
+ free(pParsLstDel);
+ }
+ RETiRet;
+}
+
+/* queryInterface function-- rgerhards, 2009-11-03
+ */
+BEGINobjQueryInterface(parser)
+CODESTARTobjQueryInterface(parser)
+ if(pIf->ifVersion != parserCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = parserConstruct;
+ pIf->ConstructFinalize = parserConstructFinalize;
+ pIf->Destruct = parserDestruct;
+ pIf->SetName = SetName;
+ pIf->SetModPtr = SetModPtr;
+ pIf->SetDoPRIParsing = SetDoPRIParsing;
+ pIf->ParseMsg = ParseMsg;
+ pIf->SanitizeMsg = SanitizeMsg;
+ pIf->DestructParserList = DestructParserList;
+ pIf->AddParserToList = AddParserToList;
+ pIf->AddDfltParser = AddDfltParser;
+ pIf->FindParser = FindParser;
+ pIf->destroyMasterParserList = destroyMasterParserList;
+finalize_it:
+ENDobjQueryInterface(parser)
+
+/* Exit our class.
+ * rgerhards, 2009-11-04
+ */
+BEGINObjClassExit(parser, OBJ_IS_CORE_MODULE) /* class, version */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDObjClassExit(parser)
+
+
+/* Initialize the parser class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2009-11-02
+ */
+BEGINObjClassInit(parser, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ENDObjClassInit(parser)
diff --git a/runtime/parser.h b/runtime/parser.h
new file mode 100644
index 0000000..d028b1a
--- /dev/null
+++ b/runtime/parser.h
@@ -0,0 +1,77 @@
+/* header for parser.c
+ *
+ * Copyright 2008-2021 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_PARSER_H
+#define INCLUDED_PARSER_H
+
+/* we create a small helper object, a list of parsers, that we can use to
+ * build a chain of them whereever this is needed (initially thought to be
+ * used in ruleset.c as well as ourselvs).
+ */
+struct parserList_s {
+ parser_t *pParser;
+ parserList_t *pNext;
+};
+
+
+/* the parser object, a dummy because we have only static methods */
+struct parser_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pName; /* name of this parser */
+ modInfo_t *pModule; /* pointer to parser's module */
+ void *pInst; /* instance data for the parser (v2+ module interface) */
+ sbool bDoSanitazion; /* do standard message sanitazion before calling parser? */
+ sbool bDoPRIParsing; /* do standard PRI parsing before calling parser? */
+};
+
+/* interfaces */
+BEGINinterface(parser) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(var);
+ rsRetVal (*Construct)(parser_t **ppThis);
+ rsRetVal (*ConstructFinalize)(parser_t *pThis);
+ rsRetVal (*Destruct)(parser_t **ppThis);
+ rsRetVal (*SetName)(parser_t *pThis, uchar *name);
+ rsRetVal (*SetModPtr)(parser_t *pThis, modInfo_t *pMod);
+ rsRetVal (*SetDoPRIParsing)(parser_t *pThis, int);
+ rsRetVal (*FindParser)(parserList_t *pParserListRoot, parser_t **ppThis, uchar*name);
+ rsRetVal (*DestructParserList)(parserList_t **pListRoot);
+ rsRetVal (*AddParserToList)(parserList_t **pListRoot, parser_t *pParser);
+ rsRetVal (*destroyMasterParserList)(parserList_t *pParserListRoot);
+ /* static functions */
+ rsRetVal (*ParseMsg)(smsg_t *pMsg);
+ rsRetVal (*SanitizeMsg)(smsg_t *pMsg);
+ rsRetVal (*AddDfltParser)(uchar *);
+ENDinterface(parser)
+#define parserCURR_IF_VERSION 3 /* increment whenever you change the interface above! */
+/* version changes
+ 2 SetDoSanitization removed, no longer needed
+ 3 InitParserList removed, no longer needed
+ destroyMasterParserList added
+ findParser extended with new parameter specifying the parser list
+*/
+
+void printParserList(parserList_t *pList);
+
+/* prototypes */
+PROTOTYPEObj(parser);
+rsRetVal parserConstructViaModAndName(modInfo_t *pMod, uchar *const pName, void *parserInst);
+
+
+#endif /* #ifndef INCLUDED_PARSER_H */
diff --git a/runtime/perctile_ringbuf.c b/runtime/perctile_ringbuf.c
new file mode 100644
index 0000000..6eb3b66
--- /dev/null
+++ b/runtime/perctile_ringbuf.c
@@ -0,0 +1,360 @@
+/*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <math.h>
+#include <assert.h>
+#include "perctile_ringbuf.h"
+
+static uint64_t min(uint64_t a, uint64_t b) {
+ return a < b ? a : b;
+}
+
+/*
+ * circ buf macros derived from linux/circ_buf.h
+ */
+
+/* Return count in buffer. */
+#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size)-1))
+
+/* Return space available, 0..size-1. We always leave one free char
+ as a completely full buffer has head == tail, which is the same as
+ empty. */
+#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size))
+
+/* Return count up to the end of the buffer. Carefully avoid
+ accessing head and tail more than once, so they can change
+ underneath us without returning inconsistent results. */
+#define CIRC_CNT_TO_END(head,tail,size) \
+ ({int end = (size) - (tail); \
+ int n = ((head) + end) & ((size)-1); \
+ n < end ? n : end;})
+
+/* Return space available up to the end of the buffer. */
+#define CIRC_SPACE_TO_END(head,tail,size) \
+ ({int end = (size) - 1 - (head); \
+ int n = (end + (tail)) & ((size)-1); \
+ n <= end ? n : end+1;})
+
+/* Move head by size. */
+#define CIRC_ADD(idx, size, offset) (((idx) + (offset)) & ((size) - 1))
+
+// simple use of the linux defined circular buffer.
+
+ringbuf_t* ringbuf_new(size_t count) {
+ // use nearest power of 2
+ double x = ceil(log2(count));
+ size_t bufsize = pow(2, x);
+
+ ringbuf_t *rb = calloc(1, sizeof(ringbuf_t));
+ // Note: count needs to be a power of 2, otherwise our macros won't work.
+ ITEM *pbuf = calloc(bufsize, sizeof(ITEM));
+ rb->cb.buf = pbuf;
+ rb->cb.head = rb->cb.tail = 0;
+ rb->size = bufsize;
+
+ return rb;
+}
+
+void ringbuf_del(ringbuf_t *rb) {
+ if (rb) {
+ if (rb->cb.buf) {
+ free(rb->cb.buf);
+ }
+ free(rb);
+ }
+}
+
+int ringbuf_append(ringbuf_t *rb, ITEM item) {
+ // lock it and add
+ int head = rb->cb.head,
+ tail = rb->cb.tail;
+
+ if (!CIRC_SPACE(head, tail, rb->size)) {
+ return -1;
+ } else {
+ /* insert item into buffer */
+ rb->cb.buf[head] = item;
+ // move head
+ rb->cb.head = CIRC_ADD(head, rb->size, 1);
+ }
+ return 0;
+}
+
+int ringbuf_append_with_overwrite(ringbuf_t *rb, ITEM item) {
+ int head = rb->cb.head,
+ tail = rb->cb.tail;
+ int ret = 0;
+
+ if (!CIRC_SPACE(head, tail, rb->size)) {
+ rb->cb.tail = CIRC_ADD(tail, rb->size, 1);
+ }
+ ret = ringbuf_append(rb, item);
+ assert(ret == 0); // we shouldn't fail due to no space.
+ return ret;
+}
+
+int ringbuf_read(ringbuf_t *rb, ITEM *buf, size_t count) {
+ int head = rb->cb.head,
+ tail = rb->cb.tail;
+ size_t copy_size = 0;
+
+ if (!CIRC_CNT(head, tail, rb->size)) {
+ return 0;
+ }
+
+ // copy to end of buffer
+ copy_size = min((size_t)CIRC_CNT_TO_END(head, tail, rb->size), count);
+ memcpy(buf, rb->cb.buf+tail, copy_size*sizeof(ITEM));
+
+ rb->cb.tail = CIRC_ADD(rb->cb.tail, rb->size, copy_size);
+ return copy_size;
+}
+
+size_t ringbuf_read_to_end(ringbuf_t *rb, ITEM *buf, size_t count) {
+ size_t nread = 0;
+ nread += ringbuf_read(rb, buf, count);
+ if (nread == 0) {
+ return nread;
+ }
+ // read the rest if buf circled around
+ nread += ringbuf_read(rb, buf + nread, count - nread);
+ assert(nread <= count);
+ return nread;
+}
+
+bool ringbuf_peek(ringbuf_t *rb, ITEM *item) {
+ if (CIRC_CNT(rb->cb.head, rb->cb.tail, rb->size) == 0) {
+ return false;
+ }
+
+ *item = rb->cb.buf[rb->cb.tail];
+ return true;
+}
+
+size_t ringbuf_capacity(ringbuf_t *rb) {
+ return rb->size;
+}
+
+/* ---- RINGBUFFER TESTS ---- */
+void ringbuf_init_test(void) {
+ size_t count = 4;
+ ringbuf_t *rb = ringbuf_new(count);
+ // verify ringbuf empty state
+ assert(rb->cb.head == 0);
+ assert(rb->cb.tail == 0);
+ assert(rb->size == 4);
+ ringbuf_del(rb);
+}
+
+void ringbuf_simple_test(void) {
+ size_t count = 3;
+ ITEM item = 0;
+ ringbuf_t *rb = ringbuf_new(count);
+ assert(ringbuf_append(rb, 1) == 0);
+ assert(ringbuf_append(rb, 2) == 0);
+ assert(ringbuf_append(rb, 3) == 0);
+
+ item = 0;
+ assert(ringbuf_peek(rb, &item) == 0);
+ assert(item == 1);
+}
+
+void ringbuf_append_test(void) {
+ size_t count = 4;
+ ringbuf_t *rb = ringbuf_new(count);
+
+ assert(ringbuf_append(rb, 1) == 0);
+ assert(ringbuf_append(rb, 2) == 0);
+ assert(ringbuf_append(rb, 3) == 0);
+
+ // check state of ringbuffer:
+ // {1, 2, 3, X}
+ // T H
+ assert(rb->cb.buf[0] == 1);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.buf[3] == 0);
+ assert(rb->cb.head == 3);
+ assert(rb->cb.tail == 0);
+
+ ringbuf_del(rb);
+}
+
+void ringbuf_append_wrap_test(void) {
+ size_t count = 4;
+ ITEM item = 0;
+
+ ringbuf_t *rb = ringbuf_new(count);
+ assert(ringbuf_append(rb, 1) == 0);
+ assert(ringbuf_append(rb, 2) == 0);
+ assert(ringbuf_append(rb, 3) == 0);
+ assert(ringbuf_append(rb, 4) != 0);
+
+ // check state of ringbuffer:
+ // {1, 2, 3, X}
+ // T H
+ assert(rb->cb.buf[0] == 1);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.head == 3);
+ assert(rb->cb.tail == 0);
+
+ item = 0;
+ assert(ringbuf_read(rb, &item, 1) == 1);
+ assert(item == 1);
+
+ assert(ringbuf_append(rb, 4) == 0);
+
+ // state of ringbuffer:
+ // {1, 2, 3, 4}
+ // H T
+ assert(rb->cb.buf[0] == 1);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.buf[3] == 4);
+ assert(rb->cb.head == 0);
+ assert(rb->cb.tail == 1);
+
+ item = 0;
+ assert(ringbuf_read(rb, &item, 1) == 1);
+ assert(item == 2);
+
+ // test wraparound
+ assert(ringbuf_append(rb, 5) == 0);
+
+ // state of ringbuffer:
+ // {1, 2, 3, 4}
+ // H T
+ assert(rb->cb.buf[0] == 5);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.buf[3] == 4);
+ assert(rb->cb.head == 1);
+ assert(rb->cb.tail == 2);
+
+ ringbuf_del(rb);
+}
+
+void ringbuf_append_overwrite_test(void) {
+ size_t count = 4;
+ ringbuf_t *rb = ringbuf_new(count);
+ assert(ringbuf_append_with_overwrite(rb, 1) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 2) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 3) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 4) == 0);
+
+ // check state of ringbuffer:
+ // {1, 2, 3, 4}
+ // H T
+ assert(rb->cb.buf[0] == 1);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.buf[3] == 4);
+ assert(rb->cb.head == 0);
+ assert(rb->cb.tail == 1);
+
+ assert(ringbuf_append_with_overwrite(rb, 5) == 0);
+ // check state of ringbuffer:
+ // {5, 2, 3, 4}
+ // H T
+ assert(rb->cb.buf[0] == 5);
+ assert(rb->cb.buf[1] == 2);
+ assert(rb->cb.buf[2] == 3);
+ assert(rb->cb.buf[3] == 4);
+ assert(rb->cb.head == 1);
+ assert(rb->cb.tail == 2);
+
+ ringbuf_del(rb);
+}
+
+void ringbuf_read_test(void) {
+ size_t count = 4;
+ ringbuf_t *rb = ringbuf_new(count);
+ ITEM item_array[3];
+ ITEM expects[] = {1, 2, 3};
+ ITEM expects2[] = {4};
+
+ assert(ringbuf_append_with_overwrite(rb, 1) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 2) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 3) == 0);
+
+ assert(ringbuf_read(rb, item_array, count) == 3);
+ assert(memcmp(item_array, expects, 3) == 0);
+
+ // check state of ringbuffer:
+ // {X, X, X, X}
+ // H
+ // T
+ assert(rb->cb.head == 3);
+ assert(rb->cb.tail == 3);
+
+ assert(ringbuf_append_with_overwrite(rb, 4) == 0);
+ assert(ringbuf_read(rb, item_array, count) == 1);
+ assert(memcmp(item_array, expects2, 1) == 0);
+ assert(rb->cb.head == 0);
+ assert(rb->cb.tail == 0);
+
+ ringbuf_del(rb);
+}
+
+void ringbuf_read_to_end_test(void) {
+ size_t count = 4;
+ ringbuf_t *rb = ringbuf_new(count);
+ ITEM item_array[3];
+ ITEM expects[] = {1, 2, 3};
+ ITEM expects2[] = {4};
+
+ assert(ringbuf_append_with_overwrite(rb, 1) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 2) == 0);
+ assert(ringbuf_append_with_overwrite(rb, 3) == 0);
+
+ // state of ringbuffer:
+ // {1, 2, 3, X}
+ // T H
+ assert(ringbuf_read_to_end(rb, item_array, 3) == 3);
+ assert(memcmp(item_array, expects, 3) == 0);
+
+ // check state of ringbuffer:
+ // {1, 2, 3, X}
+ // H
+ // T
+ assert(rb->cb.head == 3);
+ assert(rb->cb.tail == 3);
+
+ assert(ringbuf_append_with_overwrite(rb, 4) == 0);
+ // state of ringbuffer:
+ // {1, 2, 3, 4}
+ // H T
+ assert(ringbuf_read_to_end(rb, item_array, count) == 1);
+
+ // check state of ringbuffer (empty):
+ // {1, 2, 3, 4}
+ // H
+ // T
+ assert(memcmp(item_array, expects2, 1) == 0);
+ assert(rb->cb.head == 0);
+ assert(rb->cb.tail == 0);
+
+ ringbuf_del(rb);
+}
+/* ---- END RINGBUFFER TESTS ---- */
+
diff --git a/runtime/perctile_ringbuf.h b/runtime/perctile_ringbuf.h
new file mode 100644
index 0000000..27bc4a2
--- /dev/null
+++ b/runtime/perctile_ringbuf.h
@@ -0,0 +1,34 @@
+#include <stdlib.h>
+#include <stdbool.h>
+
+typedef int64_t ITEM;
+
+struct circ_buf {
+ ITEM *buf;
+ int head;
+ int tail;
+};
+
+struct ringbuf_s {
+ struct circ_buf cb;
+ size_t size;
+};
+typedef struct ringbuf_s ringbuf_t;
+
+ringbuf_t* ringbuf_new(size_t count);
+void ringbuf_del(ringbuf_t *rb);
+int ringbuf_append(ringbuf_t *rb, ITEM item);
+int ringbuf_append_with_overwrite(ringbuf_t *rb, ITEM item);
+int ringbuf_read(ringbuf_t *rb, ITEM *buf, size_t count);
+size_t ringbuf_read_to_end(ringbuf_t *rb, ITEM *buf, size_t count);
+bool ringbuf_peek(ringbuf_t *rb, ITEM *item);
+size_t ringbuf_capacity(ringbuf_t *rb);
+
+/* ringbuffer tests */
+void ringbuf_init_test(void);
+void ringbuf_simple_test(void);
+void ringbuf_append_test(void);
+void ringbuf_append_wrap_test(void);
+void ringbuf_append_overwrite_test(void);
+void ringbuf_read_test(void);
+void ringbuf_read_to_end_test(void);
diff --git a/runtime/perctile_stats.c b/runtime/perctile_stats.c
new file mode 100644
index 0000000..55a62aa
--- /dev/null
+++ b/runtime/perctile_stats.c
@@ -0,0 +1,695 @@
+/*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include "unicode-helper.h"
+#include "rsyslog.h"
+#include "rsconf.h"
+#include "errmsg.h"
+#include "perctile_stats.h"
+#include "hashtable_itr.h"
+#include "perctile_ringbuf.h"
+#include "datetime.h"
+
+#include <stdio.h>
+#include <pthread.h>
+#include <math.h>
+
+/* Use this macro to enable debug for this module */
+#ifdef PERCTILE_STATS_DEBUG
+#define _DEBUG 1
+#else
+#define _DEBUG 0
+#endif
+#define PERCTILE_STATS_LOG(...) do { if(_DEBUG) fprintf(stderr, __VA_ARGS__); } while(0)
+
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(statsobj)
+DEFobjCurrIf(datetime)
+
+#define PERCTILE_CONF_PARAM_NAME "name"
+#define PERCTILE_CONF_PARAM_PERCENTILES "percentiles"
+#define PERCTILE_CONF_PARAM_WINDOW_SIZE "windowsize"
+#define PERCTILE_CONF_PARAM_DELIM "delimiter"
+
+#define PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH 128
+#define PERCTILE_METRIC_NAME_SEPARATOR '.'
+
+static struct cnfparamdescr modpdescr[] = {
+ { PERCTILE_CONF_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED },
+ { PERCTILE_CONF_PARAM_DELIM, eCmdHdlrString, 0},
+ { PERCTILE_CONF_PARAM_PERCENTILES, eCmdHdlrArray, 0},
+ { PERCTILE_CONF_PARAM_WINDOW_SIZE, eCmdHdlrPositiveInt, 0},
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+rsRetVal
+perctileClassInit(void) {
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+finalize_it:
+ RETiRet;
+}
+
+static uint64_t min(uint64_t a, uint64_t b) {
+ return a < b ? a : b;
+}
+
+static uint64_t max(uint64_t a, uint64_t b) {
+ return a > b ? a : b;
+}
+
+static void perctileStatDestruct(perctile_bucket_t *b, perctile_stat_t *pstat) {
+ if (pstat) {
+ if (pstat->rb_observed_stats) {
+ ringbuf_del(pstat->rb_observed_stats);
+ }
+
+ if (pstat->ctrs) {
+ for (size_t i = 0; i < pstat->perctile_ctrs_count; ++i) {
+ perctile_ctr_t *ctr = &pstat->ctrs[i];
+ if (ctr->ref_ctr_percentile_stat) {
+ statsobj.DestructCounter(b->statsobj, ctr->ref_ctr_percentile_stat);
+ }
+ }
+ free(pstat->ctrs);
+ }
+
+ if (pstat->refCtrWindowCount) {
+ statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowCount);
+ }
+ if (pstat->refCtrWindowMin) {
+ statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowMin);
+ }
+ if (pstat->refCtrWindowMax) {
+ statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowMax);
+ }
+ if (pstat->refCtrWindowSum) {
+ statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowSum);
+ }
+ pthread_rwlock_destroy(&pstat->stats_lock);
+ free(pstat);
+ }
+}
+
+static void perctileBucketDestruct(perctile_bucket_t *bkt) {
+ PERCTILE_STATS_LOG("destructing perctile bucket\n");
+ if (bkt) {
+ pthread_rwlock_wrlock(&bkt->lock);
+ // Delete all items in hashtable
+ size_t count = hashtable_count(bkt->htable);
+ if (count) {
+ int ret = 0;
+ struct hashtable_itr *itr = hashtable_iterator(bkt->htable);
+ dbgprintf("%s() - All container instances, count=%zu...\n", __FUNCTION__, count);
+ do {
+ perctile_stat_t *pstat = hashtable_iterator_value(itr);
+ perctileStatDestruct(bkt, pstat);
+ ret = hashtable_iterator_advance(itr);
+ } while (ret);
+ free (itr);
+ dbgprintf("End of container instances.\n");
+ }
+ hashtable_destroy(bkt->htable, 0);
+ statsobj.Destruct(&bkt->statsobj);
+ pthread_rwlock_unlock(&bkt->lock);
+ pthread_rwlock_destroy(&bkt->lock);
+ free(bkt->perctile_values);
+ free(bkt->delim);
+ free(bkt->name);
+ free(bkt);
+ }
+}
+
+void perctileBucketsDestruct(void) {
+ perctile_buckets_t *bkts = &runConf->perctile_buckets;
+
+ if (bkts->initialized) {
+ perctile_bucket_t *head = bkts->listBuckets;
+ if (head) {
+ pthread_rwlock_wrlock(&bkts->lock);
+ perctile_bucket_t *pnode = head, *pnext = NULL;
+ while (pnode) {
+ pnext = pnode->next;
+ perctileBucketDestruct(pnode);
+ pnode = pnext;
+ }
+ pthread_rwlock_unlock(&bkts->lock);
+ }
+ statsobj.Destruct(&bkts->global_stats);
+ // destroy any global stats we keep specifically for this.
+ pthread_rwlock_destroy(&bkts->lock);
+ }
+}
+
+static perctile_bucket_t*
+findBucket(perctile_bucket_t *head, const uchar *name) {
+ perctile_bucket_t *pbkt_found = NULL;
+ // walk the linked list until the name is found
+ pthread_rwlock_rdlock(&head->lock);
+ for (perctile_bucket_t *pnode = head; pnode != NULL; pnode = pnode->next) {
+ if (ustrcmp(name, pnode->name) == 0) {
+ // found.
+ pbkt_found = pnode;
+ }
+ }
+ pthread_rwlock_unlock(&head->lock);
+ return pbkt_found;
+}
+
+#ifdef PERCTILE_STATS_DEBUG
+static void
+print_perctiles(perctile_bucket_t *bkt) {
+ if (hashtable_count(bkt->htable)) {
+ struct hashtable_itr *itr = hashtable_iterator(bkt->htable);
+ do {
+ uchar* key = hashtable_iterator_key(itr);
+ perctile_stat_t *perc_stat = hashtable_iterator_value(itr);
+ PERCTILE_STATS_LOG("print_perctile() - key: %s, perctile stat name: %s ", key, perc_stat->name);
+ } while (hashtable_iterator_advance(itr));
+ PERCTILE_STATS_LOG("\n");
+ }
+}
+#endif
+
+// Assumes a fully created pstat and bkt, also initiliazes some values in pstat.
+static rsRetVal
+initAndAddPerctileMetrics(perctile_stat_t *pstat, perctile_bucket_t *bkt, uchar* key) {
+ char stat_name[128];
+ int bytes = 0;
+ int stat_name_len = sizeof(stat_name);
+ DEFiRet;
+
+ bytes = snprintf((char*)pstat->name, sizeof(pstat->name), "%s", key);
+ if (bytes < 0 || bytes >= (int) sizeof(pstat->name)) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+
+ int offset = snprintf(stat_name, stat_name_len, "%s%s", (char*)pstat->name, (char*)bkt->delim);
+ if (offset < 0 || offset >= stat_name_len) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+
+ int remaining_size = stat_name_len - offset - 1;
+ // initialize the counters array
+ for (size_t i = 0; i < pstat->perctile_ctrs_count; ++i) {
+ perctile_ctr_t *ctr = &pstat->ctrs[i];
+
+ // bucket contains the supported percentile values.
+ ctr->percentile = bkt->perctile_values[i];
+ bytes = snprintf(stat_name+offset, remaining_size, "p%d", bkt->perctile_values[i]);
+ if (bytes < 0 || bytes >= remaining_size) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n",
+ stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr,
+ CTR_FLAG_NONE, &ctr->ctr_perctile_stat, &ctr->ref_ctr_percentile_stat, 1));
+ }
+
+ bytes = snprintf(stat_name+offset, remaining_size, "window_min");
+ if (bytes < 0 || bytes >= remaining_size) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr,
+ CTR_FLAG_NONE, &pstat->ctrWindowMin, &pstat->refCtrWindowMin, 1));
+
+ bytes = snprintf(stat_name+offset, remaining_size, "window_max");
+ if (bytes < 0 || bytes >= remaining_size) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr,
+ CTR_FLAG_NONE, &pstat->ctrWindowMax, &pstat->refCtrWindowMax, 1));
+
+ bytes = snprintf(stat_name+offset, remaining_size, "window_sum");
+ if (bytes < 0 || bytes >= remaining_size) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr,
+ CTR_FLAG_NONE, &pstat->ctrWindowSum, &pstat->refCtrWindowSum, 1));
+
+ bytes = snprintf(stat_name+offset, remaining_size, "window_count");
+ if (bytes < 0 || bytes >= remaining_size) {
+ LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len);
+ ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD);
+ }
+ CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr,
+ CTR_FLAG_NONE, &pstat->ctrWindowCount, &pstat->refCtrWindowCount, 1));
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(0, iRet, "Could not initialize percentile stats.");
+ }
+ RETiRet;
+}
+
+static rsRetVal
+perctile_observe(perctile_bucket_t *bkt, uchar* key, int64_t value) {
+ uint8_t lock_initialized = 0;
+ uchar* hash_key = NULL;
+ DEFiRet;
+ time_t now;
+ datetime.GetTime(&now);
+
+ pthread_rwlock_wrlock(&bkt->lock);
+ lock_initialized = 1;
+ perctile_stat_t *pstat = (perctile_stat_t*) hashtable_search(bkt->htable, key);
+ if (!pstat) {
+ PERCTILE_STATS_LOG("perctile_observe(): key '%s' not found - creating new pstat", key);
+ // create the pstat if not found
+ CHKmalloc(pstat = calloc(1, sizeof(perctile_stat_t)));
+ pstat->ctrs = calloc(bkt->perctile_values_count, sizeof(perctile_ctr_t));
+ if (!pstat->ctrs) {
+ free(pstat);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pstat->perctile_ctrs_count = bkt->perctile_values_count;
+ pstat->rb_observed_stats = ringbuf_new(bkt->window_size);
+ if (!pstat->rb_observed_stats) {
+ free(pstat->ctrs);
+ free(pstat);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pstat->bReported = 0;
+ pthread_rwlock_init(&pstat->stats_lock, NULL);
+
+ // init all stat counters here
+ pthread_rwlock_wrlock(&pstat->stats_lock);
+ pstat->ctrWindowCount = pstat->ctrWindowMax = pstat->ctrWindowSum = 0;
+ pstat->ctrWindowMin = value;
+ pthread_rwlock_unlock(&pstat->stats_lock);
+
+ iRet = initAndAddPerctileMetrics(pstat, bkt, key);
+ if (iRet != RS_RET_OK) {
+ perctileStatDestruct(bkt, pstat);
+ ABORT_FINALIZE(iRet);
+ }
+
+ CHKmalloc(hash_key = ustrdup(key));
+ if (!hashtable_insert(bkt->htable, hash_key, pstat)) {
+ perctileStatDestruct(bkt, pstat);
+ free(hash_key);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ PERCTILE_STATS_LOG("perctile_observe - new pstat created - name: %s\n", pstat->name);
+ STATSCOUNTER_INC(bkt->ctrNewKeyAdd, bkt->mutCtrNewKeyAdd);
+ }
+
+ // add this value into the ringbuffer
+ assert(pstat->rb_observed_stats);
+ if (ringbuf_append_with_overwrite(pstat->rb_observed_stats, value) != 0) {
+ // ringbuffer is operating in overwrite mode, so should never see this.
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ // update perctile specific stats
+ pthread_rwlock_wrlock(&pstat->stats_lock);
+ {
+ if (pstat->bReported) {
+ // reset window values
+ pstat->ctrWindowCount = pstat->ctrWindowSum = 0;
+ pstat->ctrWindowMin = pstat->ctrWindowMax = value;
+ pstat->bReported = 0;
+ }
+ ++(pstat->ctrWindowCount);
+ pstat->ctrWindowSum += value;
+ pstat->ctrWindowMin = min(pstat->ctrWindowMin, value);
+ pstat->ctrWindowMax = max(pstat->ctrWindowMax, value);
+ }
+ pthread_rwlock_unlock(&pstat->stats_lock);
+
+#ifdef PERCTILE_STATS_DEBUG
+ PERCTILE_STATS_LOG("perctile_observe - appended value: %lld to ringbuffer\n", value);
+ PERCTILE_STATS_LOG("ringbuffer contents... \n");
+ for (size_t i = 0; i < pstat->rb_observed_stats->size; ++i) {
+ PERCTILE_STATS_LOG("%lld ", pstat->rb_observed_stats->cb.buf[i]);
+ }
+ PERCTILE_STATS_LOG("\n");
+ print_perctiles(bkt);
+#endif
+finalize_it:
+ if (lock_initialized) {
+ pthread_rwlock_unlock(&bkt->lock);
+ }
+ if (iRet != RS_RET_OK) {
+ // clean up if there was an error
+ if (iRet == RS_RET_OUT_OF_MEMORY) {
+ STATSCOUNTER_INC(bkt->ctrOpsOverflow, bkt->mutCtrOpsOverflow);
+ }
+ }
+ RETiRet;
+}
+
+static int cmp(const void* p1, const void* p2) {
+ return (*(ITEM*)p1) - (*(ITEM*)p2);
+}
+
+static rsRetVal report_perctile_stats(perctile_bucket_t* pbkt) {
+ ITEM *buf = NULL;
+ struct hashtable_itr *itr = NULL;
+ DEFiRet;
+
+ pthread_rwlock_rdlock(&pbkt->lock);
+ if (hashtable_count(pbkt->htable)) {
+ itr = hashtable_iterator(pbkt->htable);
+ CHKmalloc(buf = malloc(pbkt->window_size*sizeof(ITEM)));
+ do {
+ memset(buf, 0, pbkt->window_size*sizeof(ITEM));
+ perctile_stat_t *perc_stat = hashtable_iterator_value(itr);
+ // ringbuffer read
+ size_t count = ringbuf_read_to_end(perc_stat->rb_observed_stats, buf, pbkt->window_size);
+ if (!count) {
+ continue;
+ }
+ PERCTILE_STATS_LOG("read %zu values\n", count);
+ // calculate the p95 based on the
+#ifdef PERCTILE_STATS_DEBUG
+ PERCTILE_STATS_LOG("ringbuffer contents... \n");
+ for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) {
+ PERCTILE_STATS_LOG("%lld ", perc_stat->rb_observed_stats->cb.buf[i]);
+ }
+ PERCTILE_STATS_LOG("\n");
+
+ PERCTILE_STATS_LOG("buffer contents... \n");
+ for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) {
+ PERCTILE_STATS_LOG("%lld ", buf[i]);
+ }
+ PERCTILE_STATS_LOG("\n");
+#endif
+ qsort(buf, count, sizeof(ITEM), cmp);
+#ifdef PERCTILE_STATS_DEBUG
+ PERCTILE_STATS_LOG("buffer contents after sort... \n");
+ for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) {
+ PERCTILE_STATS_LOG("%lld ", buf[i]);
+ }
+ PERCTILE_STATS_LOG("\n");
+#endif
+ PERCTILE_STATS_LOG("report_perctile_stats() - perctile stat has %zu counters.",
+ perc_stat->perctile_ctrs_count);
+ for (size_t i = 0; i < perc_stat->perctile_ctrs_count; ++i) {
+ perctile_ctr_t *pctr = &perc_stat->ctrs[i];
+ // get percentile - this can be cached.
+ int index = max(0, ((pctr->percentile/100.0) * count)-1);
+ // look into if we need to lock this.
+ pctr->ctr_perctile_stat = buf[index];
+ PERCTILE_STATS_LOG("report_perctile_stats() - index: %d, perctile stat [%s, %d, %llu]",
+ index, perc_stat->name, pctr->percentile, pctr->ctr_perctile_stat);
+ }
+ perc_stat->bReported = 1;
+ } while (hashtable_iterator_advance(itr));
+ }
+
+finalize_it:
+ pthread_rwlock_unlock(&pbkt->lock);
+ free(itr);
+ free(buf);
+ RETiRet;
+}
+
+static void
+perctile_readCallback(statsobj_t __attribute__((unused)) *ignore, void __attribute__((unused)) *b) {
+ perctile_buckets_t *bkts = &runConf->perctile_buckets;
+
+ pthread_rwlock_rdlock(&bkts->lock);
+ for (perctile_bucket_t *pbkt = bkts->listBuckets; pbkt != NULL; pbkt = pbkt->next) {
+ report_perctile_stats(pbkt);
+ }
+ pthread_rwlock_unlock(&bkts->lock);
+}
+
+static rsRetVal
+perctileInitNewBucketStats(perctile_bucket_t *b) {
+ DEFiRet;
+
+ CHKiRet(statsobj.Construct(&b->statsobj));
+ CHKiRet(statsobj.SetOrigin(b->statsobj, UCHAR_CONSTANT("percentile.bucket")));
+ CHKiRet(statsobj.SetName(b->statsobj, b->name));
+ CHKiRet(statsobj.SetReportingNamespace(b->statsobj, UCHAR_CONSTANT("values")));
+ statsobj.SetReadNotifier(b->statsobj, perctile_readCallback, b);
+ CHKiRet(statsobj.ConstructFinalize(b->statsobj));
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+perctileAddBucketMetrics(perctile_buckets_t *bkts, perctile_bucket_t *b, const uchar* name) {
+ uchar *metric_name_buff, *metric_suffix;
+ const uchar *suffix_litteral;
+ int name_len;
+ DEFiRet;
+
+ name_len = ustrlen(name);
+ CHKmalloc(metric_name_buff = malloc((name_len + PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar)));
+
+ strcpy((char*)metric_name_buff, (char*)name);
+ metric_suffix = metric_name_buff + name_len;
+ *metric_suffix = PERCTILE_METRIC_NAME_SEPARATOR;
+ metric_suffix++;
+
+ suffix_litteral = UCHAR_CONSTANT("new_metric_add");
+ ustrncpy(metric_suffix, suffix_litteral, PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrNewKeyAdd, b->mutCtrNewKeyAdd);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrNewKeyAdd),
+ &b->pNewKeyAddCtr, 1));
+
+ suffix_litteral = UCHAR_CONSTANT("ops_overflow");
+ ustrncpy(metric_suffix, suffix_litteral, PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH);
+ STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow);
+ CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr,
+ CTR_FLAG_RESETTABLE,
+ &(b->ctrOpsOverflow),
+ &b->pOpsOverflowCtr, 1));
+
+finalize_it:
+ free(metric_name_buff);
+ if (iRet != RS_RET_OK) {
+ if (b->pOpsOverflowCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr);
+ }
+ if (b->pNewKeyAddCtr != NULL) {
+ statsobj.DestructCounter(bkts->global_stats, b->pNewKeyAddCtr);
+ }
+ }
+ RETiRet;
+}
+
+/* Create new perctile bucket, and add it to our list of perctile buckets.
+*/
+static rsRetVal
+perctile_newBucket(const uchar *name, const uchar *delim,
+ uint8_t *perctiles, uint32_t perctilesCount, uint32_t windowSize) {
+ perctile_buckets_t *bkts;
+ perctile_bucket_t* b = NULL;
+ pthread_rwlockattr_t bucket_lock_attr;
+ DEFiRet;
+
+ bkts = &loadConf->perctile_buckets;
+
+ if (bkts->initialized)
+ {
+ CHKmalloc(b = calloc(1, sizeof(perctile_bucket_t)));
+
+ // initialize
+ pthread_rwlockattr_init(&bucket_lock_attr);
+ pthread_rwlock_init(&b->lock, &bucket_lock_attr);
+ CHKmalloc(b->htable = create_hashtable(7, hash_from_string, key_equals_string, NULL));
+ CHKmalloc(b->name = ustrdup(name));
+ if (delim) {
+ CHKmalloc(b->delim = ustrdup(delim));
+ } else {
+ CHKmalloc(b->delim = ustrdup("."));
+ }
+
+ CHKmalloc(b->perctile_values = calloc(perctilesCount, sizeof(uint8_t)));
+ b->perctile_values_count = perctilesCount;
+ memcpy(b->perctile_values, perctiles, perctilesCount * sizeof(uint8_t));
+ b->window_size = windowSize;
+ b->next = NULL;
+ PERCTILE_STATS_LOG("perctile_newBucket: create new bucket for %s,"
+ "with windowsize: %d, values_count: %zu\n",
+ b->name, b->window_size, b->perctile_values_count);
+
+ // add bucket to list of buckets
+ if (!bkts->listBuckets)
+ {
+ // none yet
+ bkts->listBuckets = b;
+ PERCTILE_STATS_LOG("perctile_newBucket: Adding new bucket to empty list \n");
+ }
+ else
+ {
+ b->next = bkts->listBuckets;
+ bkts->listBuckets = b;
+ PERCTILE_STATS_LOG("perctile_newBucket: prepended new bucket list \n");
+ }
+
+ // create the statsobj for this bucket
+ CHKiRet(perctileInitNewBucketStats(b));
+ CHKiRet(perctileAddBucketMetrics(bkts, b, name));
+ }
+ else
+ {
+ LogError(0, RS_RET_INTERNAL_ERROR, "perctile: bucket creation failed, as "
+ "global-initialization of buckets was unsuccessful");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+finalize_it:
+ if (iRet != RS_RET_OK)
+ {
+ if (b != NULL) {
+ perctileBucketDestruct(b);
+ }
+ }
+ RETiRet;
+}
+
+// Public functions
+rsRetVal
+perctile_processCnf(struct cnfobj *o) {
+ struct cnfparamvals *pvals;
+ uchar *name = NULL;
+ uchar *delim = NULL;
+ uint8_t *perctiles = NULL;
+ uint32_t perctilesCount = 0;
+ uint64_t windowSize = 0;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &modpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ for(short i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_NAME)) {
+ CHKmalloc(name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if(!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_DELIM)) {
+ CHKmalloc(delim = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL));
+ } else if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_PERCENTILES)) {
+ /* Only the first instance of this parameter will be accepted */
+ if (!perctiles) {
+ perctilesCount = pvals[i].val.d.ar->nmemb;
+ if (perctilesCount) {
+ CHKmalloc(perctiles = calloc(perctilesCount, sizeof(uint8_t)));
+ for (int j = 0; j < pvals[i].val.d.ar->nmemb; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ perctiles[j] = atoi(cstr);
+ free(cstr);
+ }
+ }
+ }
+ } else if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_WINDOW_SIZE)) {
+ windowSize = pvals[i].val.d.n;
+ } else {
+ dbgprintf("perctile: program error, non-handled "
+ "param '%s'\n", modpblk.descr[i].name);
+ }
+ }
+
+ if (name != NULL && perctiles != NULL) {
+ CHKiRet(perctile_newBucket(name, delim, perctiles, perctilesCount, windowSize));
+ }
+
+finalize_it:
+ free(name);
+ free(delim);
+ free(perctiles);
+ cnfparamvalsDestruct(pvals, &modpblk);
+ RETiRet;
+}
+
+rsRetVal
+perctile_initCnf(perctile_buckets_t *bkts) {
+ DEFiRet;
+
+ bkts->initialized = 0;
+ bkts->listBuckets = NULL;
+ CHKiRet(statsobj.Construct(&bkts->global_stats));
+ CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("percentile")));
+ CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global")));
+ CHKiRet(statsobj.SetReportingNamespace(bkts->global_stats, UCHAR_CONSTANT("values")));
+ CHKiRet(statsobj.ConstructFinalize(bkts->global_stats));
+ pthread_rwlock_init(&bkts->lock, NULL);
+ bkts->initialized = 1;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ statsobj.Destruct(&bkts->global_stats);
+ }
+ RETiRet;
+}
+
+perctile_bucket_t*
+perctile_findBucket(const uchar* name) {
+ perctile_bucket_t *b = NULL;
+
+ perctile_buckets_t *bkts = &loadConf->perctile_buckets;
+ if (bkts->initialized) {
+ pthread_rwlock_rdlock(&bkts->lock);
+ if (bkts->listBuckets) {
+ b = findBucket(bkts->listBuckets, name);
+ }
+ pthread_rwlock_unlock(&bkts->lock);
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR, "perctile: bucket lookup failed, as global-initialization "
+ "of buckets was unsuccessful");
+ }
+ return b;
+}
+
+rsRetVal
+perctile_obs(perctile_bucket_t *perctile_bkt, uchar* key, int64_t value) {
+ DEFiRet;
+ if (!perctile_bkt) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "perctile() - perctile bkt not available");
+ FINALIZE;
+ }
+ PERCTILE_STATS_LOG("perctile_obs() - bucket name: %s, key: %s, val: %" PRId64 "\n",
+ perctile_bkt->name, key, value);
+
+ CHKiRet(perctile_observe(perctile_bkt, key, value));
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "perctile_obs(): name: %s, key: %s, val: %" PRId64 "\n",
+ perctile_bkt->name, key, value);
+ }
+ RETiRet;
+}
diff --git a/runtime/perctile_stats.h b/runtime/perctile_stats.h
new file mode 100644
index 0000000..6a7ed0d
--- /dev/null
+++ b/runtime/perctile_stats.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDED_PERCTILE_STATS_H
+#define INCLUDED_PERCTILE_STATS_H
+
+#include "hashtable.h"
+#include "statsobj.h"
+
+struct perctile_ctr_s {
+ // percentile [0,100]
+ uint8_t percentile;
+ size_t index;
+ intctr_t ctr_perctile_stat;
+ ctr_t *ref_ctr_percentile_stat;
+};
+
+struct perctile_stat_s {
+ uchar name[128];
+ sbool bReported;
+ struct ringbuf_s *rb_observed_stats;
+ // array of requested perctile to track
+ struct perctile_ctr_s *ctrs;
+ size_t perctile_ctrs_count;
+
+ pthread_rwlock_t stats_lock;
+ intctr_t ctrWindowCount;
+ ctr_t *refCtrWindowCount;
+ intctr_t ctrWindowMin;
+ ctr_t *refCtrWindowMin;
+ intctr_t ctrWindowMax;
+ ctr_t *refCtrWindowMax;
+ intctr_t ctrWindowSum;
+ ctr_t *refCtrWindowSum;
+};
+
+struct perctile_bucket_s {
+ uchar *name;
+ uchar *delim;
+ // lock for entire bucket
+ pthread_rwlock_t lock;
+ struct hashtable *htable;
+ struct perctile_bucket_s *next;
+ statsobj_t *statsobj;
+ STATSCOUNTER_DEF(ctrNewKeyAdd, mutCtrNewKeyAdd);
+ ctr_t *pNewKeyAddCtr;
+ STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow);
+ ctr_t *pOpsOverflowCtr;
+ uint32_t window_size;
+ // These percentile values apply to all perctile stats in this bucket.
+ uint8_t *perctile_values;
+ size_t perctile_values_count;
+};
+
+struct perctile_buckets_s {
+ uint8_t initialized;
+ statsobj_t *global_stats;
+ pthread_rwlock_t lock;
+ struct perctile_bucket_s *listBuckets;
+};
+
+// keep these local for now.
+typedef struct perctile_ctr_s perctile_ctr_t;
+typedef struct perctile_stat_s perctile_stat_t;
+typedef struct perctile_bucket_s perctile_bucket_t;
+
+rsRetVal perctileClassInit(void);
+void perctileBucketsDestruct(void);
+rsRetVal perctile_initCnf(perctile_buckets_t *b);
+perctile_bucket_t* perctile_findBucket(const uchar* name);
+rsRetVal perctile_processCnf(struct cnfobj *cnf);
+rsRetVal perctile_obs(perctile_bucket_t *perctile_bkt, uchar* key, int64_t value);
+
+#endif /* #ifndef INCLUDED_PERCTILE_STATS_H */
diff --git a/runtime/prop.c b/runtime/prop.c
new file mode 100644
index 0000000..c4de5d7
--- /dev/null
+++ b/runtime/prop.c
@@ -0,0 +1,262 @@
+/* prop.c - rsyslog's prop object
+ *
+ * This object is meant to support message properties that are stored
+ * seperately from the message. The main intent is to support properties
+ * that are "constant" during a period of time, so that many messages may
+ * contain a reference to the same property. It is important, though, that
+ * properties are destroyed when they are no longer needed.
+ *
+ * Please note that this is a performance-critical part of the software and
+ * as such we may use some methods in here which do not look elegant, but
+ * which are fast...
+ *
+ * Module begun 2009-06-17 by Rainer Gerhards
+ *
+ * Copyright 2009-2016 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "obj-types.h"
+#include "unicode-helper.h"
+#include "atomic.h"
+#include "prop.h"
+
+/* static data */
+DEFobjStaticHelpers
+
+//extern uchar *propGetSzStr(prop_t *pThis); /* expand inline function here */
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(prop) /* be sure to specify the object type also in END macro! */
+ pThis->iRefCount = 1;
+ INIT_ATOMIC_HELPER_MUT(pThis->mutRefCount);
+ENDobjConstruct(prop)
+
+
+/* destructor for the prop object */
+BEGINobjDestruct(prop) /* be sure to specify the object type also in END and CODESTART macros! */
+ int currRefCount;
+CODESTARTobjDestruct(prop)
+ currRefCount = ATOMIC_DEC_AND_FETCH(&pThis->iRefCount, &pThis->mutRefCount);
+ if(currRefCount == 0) {
+ /* (only) in this case we need to actually destruct the object */
+ if(pThis->len >= CONF_PROP_BUFSIZE)
+ free(pThis->szVal.psz);
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutRefCount);
+ } else {
+ pThis = NULL; /* tell framework NOT to destructing the object! */
+ }
+ENDobjDestruct(prop)
+
+/* set string, we make our own private copy! This MUST only be called BEFORE
+ * ConstructFinalize()!
+ */
+static rsRetVal SetString(prop_t *pThis, const uchar *psz, const int len)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, prop);
+ if(pThis->len >= CONF_PROP_BUFSIZE)
+ free(pThis->szVal.psz);
+ pThis->len = len;
+ if(len < CONF_PROP_BUFSIZE) {
+ memcpy(pThis->szVal.sz, psz, len + 1);
+ } else {
+ if(pThis->szVal.psz != NULL) {
+ free(pThis->szVal.psz);
+ }
+ CHKmalloc(pThis->szVal.psz = malloc(len + 1));
+ memcpy(pThis->szVal.psz, psz, len + 1);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get string length */
+static int GetStringLen(prop_t *pThis)
+{
+ return pThis->len;
+}
+
+
+/* get string */
+static rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen)
+{
+ ISOBJ_TYPE_assert(pThis, prop);
+ if(pThis->len < CONF_PROP_BUFSIZE) {
+ *ppsz = pThis->szVal.sz;
+ } else {
+ *ppsz = pThis->szVal.psz;
+ }
+ *plen = pThis->len;
+ return RS_RET_OK;
+}
+
+
+/* ConstructionFinalizer
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal
+propConstructFinalize(prop_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, prop);
+ RETiRet;
+}
+
+
+/* add a new reference. It is VERY IMPORTANT to call this function whenever
+ * the property is handed over to some entitiy that later call Destruct() on it.
+ */
+static rsRetVal AddRef(prop_t *pThis)
+{
+ if(pThis == NULL) {
+ DBGPRINTF("prop/AddRef is passed a NULL ptr - ignoring it "
+ "- further problems may occur\n");
+ FINALIZE;
+ }
+ ATOMIC_INC(&pThis->iRefCount, &pThis->mutRefCount);
+finalize_it:
+ return RS_RET_OK;
+}
+
+
+/* this is a "do it all in one shot" function that creates a new property,
+ * assigns the provided string to it and finalizes the property. Among the
+ * convenience, it is also (very, very) slightly faster.
+ * rgerhards, 2009-07-01
+ */
+static rsRetVal CreateStringProp(prop_t **ppThis, const uchar* psz, const int len)
+{
+ prop_t *pThis = NULL;
+ DEFiRet;
+
+ CHKiRet(propConstruct(&pThis));
+ CHKiRet(SetString(pThis, psz, len));
+ CHKiRet(propConstructFinalize(pThis));
+ *ppThis = pThis;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis != NULL)
+ propDestruct(&pThis);
+ }
+
+ RETiRet;
+}
+
+/* another one-stop function, quite useful: it takes a property pointer and
+ * a string. If the string is already contained in the property, nothing happens.
+ * If the string is different (or the pointer NULL), the current property
+ * is destructed and a new one created. This can be used to get a specific
+ * name in those cases where there is a good chance that the property
+ * immediatly previously processed already contained the value we need - in
+ * which case we save us all the creation overhead by just reusing the already
+ * existing property).
+ * rgerhards, 2009-07-01
+ */
+static rsRetVal CreateOrReuseStringProp(prop_t **ppThis, const uchar *psz, const int len)
+{
+ uchar *pszPrev;
+ int lenPrev;
+ DEFiRet;
+ assert(ppThis != NULL);
+
+ if(*ppThis == NULL) {
+ /* we need to create a property */
+ CHKiRet(CreateStringProp(ppThis, psz, len));
+ } else {
+ /* already exists, check if we can re-use it */
+ GetString(*ppThis, &pszPrev, &lenPrev);
+ if(len != lenPrev || ustrcmp(psz, pszPrev)) {
+ /* different, need to discard old & create new one */
+ propDestruct(ppThis);
+ CHKiRet(CreateStringProp(ppThis, psz, len));
+ } /* else we can re-use the existing one! */
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* debugprint for the prop object */
+BEGINobjDebugPrint(prop) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(prop)
+ dbgprintf("prop object %p - no further debug info implemented\n", pThis);
+ENDobjDebugPrint(prop)
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(prop)
+CODESTARTobjQueryInterface(prop)
+ if(pIf->ifVersion != propCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = propConstruct;
+ pIf->ConstructFinalize = propConstructFinalize;
+ pIf->Destruct = propDestruct;
+ pIf->DebugPrint = propDebugPrint;
+ pIf->SetString = SetString;
+ pIf->GetString = GetString;
+ pIf->GetStringLen = GetStringLen;
+ pIf->AddRef = AddRef;
+ pIf->CreateStringProp = CreateStringProp;
+ pIf->CreateOrReuseStringProp = CreateOrReuseStringProp;
+
+finalize_it:
+ENDobjQueryInterface(prop)
+
+
+/* Exit the prop class.
+ * rgerhards, 2009-04-06
+ */
+BEGINObjClassExit(prop, OBJ_IS_CORE_MODULE) /* class, version */
+ENDObjClassExit(prop)
+
+
+/* Initialize the prop class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(prop, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, propDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, propConstructFinalize);
+ENDObjClassInit(prop)
+
+/* vi:set ai:
+ */
diff --git a/runtime/prop.h b/runtime/prop.h
new file mode 100644
index 0000000..eed0f56
--- /dev/null
+++ b/runtime/prop.h
@@ -0,0 +1,73 @@
+/* The prop object.
+ *
+ * This implements props within rsyslog.
+ *
+ * Copyright 2009-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_PROP_H
+#define INCLUDED_PROP_H
+#include "atomic.h"
+
+/* the prop object */
+struct prop_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ int iRefCount; /* reference counter */
+ union {
+ uchar *psz; /* stored string */
+ uchar sz[CONF_PROP_BUFSIZE];
+ } szVal;
+ int len; /* we use int intentionally, otherwise we may get some troubles... */
+ DEF_ATOMIC_HELPER_MUT(mutRefCount)
+};
+
+/* interfaces */
+BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(prop);
+ rsRetVal (*Construct)(prop_t **ppThis);
+ rsRetVal (*ConstructFinalize)(prop_t *pThis);
+ rsRetVal (*Destruct)(prop_t **ppThis);
+ rsRetVal (*SetString)(prop_t *pThis, const uchar* psz, const int len);
+ rsRetVal (*GetString)(prop_t *pThis, uchar** ppsz, int *plen);
+ int (*GetStringLen)(prop_t *pThis);
+ rsRetVal (*AddRef)(prop_t *pThis);
+ rsRetVal (*CreateStringProp)(prop_t **ppThis, const uchar* psz, const int len);
+ rsRetVal (*CreateOrReuseStringProp)(prop_t **ppThis, const uchar *psz, const int len);
+ENDinterface(prop)
+#define propCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+
+/* get classic c-style string */
+/* Note: I know that "static inline" is not the right thing from a C99
+ * PoV, but some environments treat, even in C99 mode, compile
+ * non-static inline into the source even if not defined as "extern". This
+ * obviously results in linker errors. Using "static inline" as below together
+ * with "__attribute__((unused))" works in all cases. Note also that we
+ * cannot work around this as we would otherwise need to evaluate
+ * pThis more than once.
+ */
+static inline uchar * __attribute__((unused)) ATTR_NONNULL(1)
+propGetSzStr(prop_t *pThis)
+{
+ return(pThis->len < CONF_PROP_BUFSIZE) ? pThis->szVal.sz : pThis->szVal.psz;
+}
+
+/* prototypes */
+PROTOTYPEObj(prop);
+
+#endif /* #ifndef INCLUDED_PROP_H */
diff --git a/runtime/queue.c b/runtime/queue.c
new file mode 100644
index 0000000..edc9d35
--- /dev/null
+++ b/runtime/queue.c
@@ -0,0 +1,3609 @@
+/* queue.c
+ *
+ * This file implements the queue object and its several queueing methods.
+ *
+ * File begun on 2008-01-03 by RGerhards
+ *
+ * There is some in-depth documentation available in doc/dev_queue.html
+ * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it
+ * if you are getting aquainted to the object.
+ *
+ * NOTE: as of 2009-04-22, I have begin to remove the qqueue* prefix from static
+ * function names - this makes it really hard to read and does not provide much
+ * benefit, at least I (now) think so...
+ *
+ * Copyright 2008-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h> /* required for HP UX */
+#include <time.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "rsyslog.h"
+#include "queue.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "wtp.h"
+#include "wti.h"
+#include "msg.h"
+#include "obj.h"
+#include "atomic.h"
+#include "errmsg.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "statsobj.h"
+#include "parserif.h"
+#include "rsconf.h"
+
+#ifdef OS_SOLARIS
+# include <sched.h>
+#endif
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(strm)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(statsobj)
+
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wcast-function-type" // TODO: investigate further!
+#endif /* if __GNUC__ >= 8 */
+
+#ifdef ENABLE_IMDIAG
+unsigned int iOverallQueueSize = 0;
+#endif
+
+#define OVERSIZE_QUEUE_WATERMARK 500000 /* when is a queue considered to be "overly large"? */
+
+
+/* forward-definitions */
+static rsRetVal doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg);
+static rsRetVal qqueueChkPersist(qqueue_t *pThis, int nUpdates);
+static rsRetVal RateLimiter(qqueue_t *pThis);
+static rsRetVal qqueueChkStopWrkrDA(qqueue_t *pThis);
+static rsRetVal GetDeqBatchSize(qqueue_t *pThis, int *pVal);
+static rsRetVal ConsumerDA(qqueue_t *pThis, wti_t *pWti);
+static rsRetVal batchProcessed(qqueue_t *pThis, wti_t *pWti);
+static rsRetVal qqueueMultiEnqObjNonDirect(qqueue_t *pThis, multi_submit_t *pMultiSub);
+static rsRetVal qqueueMultiEnqObjDirect(qqueue_t *pThis, multi_submit_t *pMultiSub);
+static rsRetVal qAddDirect(qqueue_t *pThis, smsg_t *pMsg);
+static rsRetVal qDestructDirect(qqueue_t __attribute__((unused)) *pThis);
+static rsRetVal qConstructDirect(qqueue_t __attribute__((unused)) *pThis);
+static rsRetVal qDestructDisk(qqueue_t *pThis);
+rsRetVal qqueueSetSpoolDir(qqueue_t *pThis, uchar *pszSpoolDir, int lenSpoolDir);
+
+/* some constants for queuePersist () */
+#define QUEUE_CHECKPOINT 1
+#define QUEUE_NO_CHECKPOINT 0
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfpdescr[] = {
+ { "queue.filename", eCmdHdlrGetWord, 0 },
+ { "queue.spooldirectory", eCmdHdlrGetWord, 0 },
+ { "queue.size", eCmdHdlrSize, 0 },
+ { "queue.dequeuebatchsize", eCmdHdlrInt, 0 },
+ { "queue.mindequeuebatchsize", eCmdHdlrInt, 0 },
+ { "queue.mindequeuebatchsize.timeout", eCmdHdlrInt, 0 },
+ { "queue.maxdiskspace", eCmdHdlrSize, 0 },
+ { "queue.highwatermark", eCmdHdlrInt, 0 },
+ { "queue.lowwatermark", eCmdHdlrInt, 0 },
+ { "queue.fulldelaymark", eCmdHdlrInt, 0 },
+ { "queue.lightdelaymark", eCmdHdlrInt, 0 },
+ { "queue.discardmark", eCmdHdlrInt, 0 },
+ { "queue.discardseverity", eCmdHdlrFacility, 0 },
+ { "queue.checkpointinterval", eCmdHdlrInt, 0 },
+ { "queue.syncqueuefiles", eCmdHdlrBinary, 0 },
+ { "queue.type", eCmdHdlrQueueType, 0 },
+ { "queue.workerthreads", eCmdHdlrInt, 0 },
+ { "queue.timeoutshutdown", eCmdHdlrInt, 0 },
+ { "queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
+ { "queue.timeoutenqueue", eCmdHdlrInt, 0 },
+ { "queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
+ { "queue.workerthreadminimummessages", eCmdHdlrInt, 0 },
+ { "queue.maxfilesize", eCmdHdlrSize, 0 },
+ { "queue.saveonshutdown", eCmdHdlrBinary, 0 },
+ { "queue.dequeueslowdown", eCmdHdlrInt, 0 },
+ { "queue.dequeuetimebegin", eCmdHdlrInt, 0 },
+ { "queue.dequeuetimeend", eCmdHdlrInt, 0 },
+ { "queue.cry.provider", eCmdHdlrGetWord, 0 },
+ { "queue.samplinginterval", eCmdHdlrInt, 0 },
+ { "queue.takeflowctlfrommsg", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfpdescr)/sizeof(struct cnfparamdescr),
+ cnfpdescr
+ };
+
+/* support to detect duplicate queue file names */
+struct queue_filename {
+ struct queue_filename *next;
+ const char *dirname;
+ const char *filename;
+};
+struct queue_filename *queue_filename_root = NULL;
+
+/* debug aid */
+#if 0
+static inline void displayBatchState(batch_t *pBatch)
+{
+ int i;
+ for(i = 0 ; i < pBatch->nElem ; ++i) {
+ DBGPRINTF("displayBatchState %p[%d]: %d\n", pBatch, i, pBatch->eltState[i]);
+ }
+}
+#endif
+static rsRetVal qqueuePersist(qqueue_t *pThis, int bIsCheckpoint);
+
+/* do cleanup when config is loaded */
+void qqueueDoneLoadCnf(void)
+{
+ struct queue_filename *next, *del;
+ next = queue_filename_root;
+ while(next != NULL) {
+ del = next;
+ next = next->next;
+ free((void*) del->filename);
+ free((void*) del->dirname);
+ free((void*) del);
+ }
+}
+
+
+/***********************************************************************
+ * we need a private data structure, the "to-delete" list. As C does
+ * not provide any partly private data structures, we implement this
+ * structure right here inside the module.
+ * Note that this list must always be kept sorted based on a unique
+ * dequeue ID (which is monotonically increasing).
+ * rgerhards, 2009-05-18
+ ***********************************************************************/
+
+/* generate next uniqueue dequeue ID. Note that uniqueness is only required
+ * on a per-queue basis and while this instance runs. So a stricly monotonically
+ * increasing counter is sufficient (if enough bits are used).
+ */
+static inline qDeqID getNextDeqID(qqueue_t *pQueue)
+{
+ ISOBJ_TYPE_assert(pQueue, qqueue);
+ return pQueue->deqIDAdd++;
+}
+
+
+/* return the top element of the to-delete list or NULL, if the
+ * list is empty.
+ */
+static toDeleteLst_t *tdlPeek(qqueue_t *pQueue)
+{
+ ISOBJ_TYPE_assert(pQueue, qqueue);
+ return pQueue->toDeleteLst;
+}
+
+
+/* remove the top element of the to-delete list. Nothing but the
+ * element itself is destroyed. Must not be called when the list
+ * is empty.
+ */
+static rsRetVal tdlPop(qqueue_t *pQueue)
+{
+ toDeleteLst_t *pRemove;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pQueue, qqueue);
+ assert(pQueue->toDeleteLst != NULL);
+
+ pRemove = pQueue->toDeleteLst;
+ pQueue->toDeleteLst = pQueue->toDeleteLst->pNext;
+ free(pRemove);
+
+ RETiRet;
+}
+
+
+/* Add a new to-delete list entry. The function allocates the data
+ * structure, populates it with the values provided and links the new
+ * element into the correct place inside the list.
+ */
+static rsRetVal
+tdlAdd(qqueue_t *pQueue, qDeqID deqID, int nElemDeq)
+{
+ toDeleteLst_t *pNew;
+ toDeleteLst_t *pPrev;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pQueue, qqueue);
+ assert(pQueue->toDeleteLst != NULL);
+
+ CHKmalloc(pNew = malloc(sizeof(toDeleteLst_t)));
+ pNew->deqID = deqID;
+ pNew->nElemDeq = nElemDeq;
+
+ /* now find right spot */
+ for( pPrev = pQueue->toDeleteLst
+ ; pPrev != NULL && deqID > pPrev->deqID
+ ; pPrev = pPrev->pNext) {
+ /*JUST SEARCH*/;
+ }
+
+ if(pPrev == NULL) {
+ pNew->pNext = pQueue->toDeleteLst;
+ pQueue->toDeleteLst = pNew;
+ } else {
+ pNew->pNext = pPrev->pNext;
+ pPrev->pNext = pNew;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* methods */
+
+static const char *
+getQueueTypeName(queueType_t t)
+{
+ const char *r;
+
+ switch(t) {
+ case QUEUETYPE_FIXED_ARRAY:
+ r = "FixedArray";
+ break;
+ case QUEUETYPE_LINKEDLIST:
+ r = "LinkedList";
+ break;
+ case QUEUETYPE_DISK:
+ r = "Disk";
+ break;
+ case QUEUETYPE_DIRECT:
+ r = "Direct";
+ break;
+ default:
+ r = "invalid/unknown queue mode";
+ break;
+ }
+ return r;
+}
+
+void
+qqueueDbgPrint(qqueue_t *pThis)
+{
+ dbgoprint((obj_t*) pThis, "parameter dump:\n");
+ dbgoprint((obj_t*) pThis, "queue.filename '%s'\n",
+ (pThis->pszFilePrefix == NULL) ? "[NONE]" : (char*)pThis->pszFilePrefix);
+ dbgoprint((obj_t*) pThis, "queue.size: %d\n", pThis->iMaxQueueSize);
+ dbgoprint((obj_t*) pThis, "queue.dequeuebatchsize: %d\n", pThis->iDeqBatchSize);
+ dbgoprint((obj_t*) pThis, "queue.mindequeuebatchsize: %d\n", pThis->iMinDeqBatchSize);
+ dbgoprint((obj_t*) pThis, "queue.mindequeuebatchsize.timeout: %d\n", pThis->toMinDeqBatchSize);
+ dbgoprint((obj_t*) pThis, "queue.maxdiskspace: %lld\n", pThis->sizeOnDiskMax);
+ dbgoprint((obj_t*) pThis, "queue.highwatermark: %d\n", pThis->iHighWtrMrk);
+ dbgoprint((obj_t*) pThis, "queue.lowwatermark: %d\n", pThis->iLowWtrMrk);
+ dbgoprint((obj_t*) pThis, "queue.fulldelaymark: %d\n", pThis->iFullDlyMrk);
+ dbgoprint((obj_t*) pThis, "queue.lightdelaymark: %d\n", pThis->iLightDlyMrk);
+ dbgoprint((obj_t*) pThis, "queue.takeflowctlfrommsg: %d\n", pThis->takeFlowCtlFromMsg);
+ dbgoprint((obj_t*) pThis, "queue.discardmark: %d\n", pThis->iDiscardMrk);
+ dbgoprint((obj_t*) pThis, "queue.discardseverity: %d\n", pThis->iDiscardSeverity);
+ dbgoprint((obj_t*) pThis, "queue.checkpointinterval: %d\n", pThis->iPersistUpdCnt);
+ dbgoprint((obj_t*) pThis, "queue.syncqueuefiles: %d\n", pThis->bSyncQueueFiles);
+ dbgoprint((obj_t*) pThis, "queue.type: %d [%s]\n", pThis->qType, getQueueTypeName(pThis->qType));
+ dbgoprint((obj_t*) pThis, "queue.workerthreads: %d\n", pThis->iNumWorkerThreads);
+ dbgoprint((obj_t*) pThis, "queue.timeoutshutdown: %d\n", pThis->toQShutdown);
+ dbgoprint((obj_t*) pThis, "queue.timeoutactioncompletion: %d\n", pThis->toActShutdown);
+ dbgoprint((obj_t*) pThis, "queue.timeoutenqueue: %d\n", pThis->toEnq);
+ dbgoprint((obj_t*) pThis, "queue.timeoutworkerthreadshutdown: %d\n", pThis->toWrkShutdown);
+ dbgoprint((obj_t*) pThis, "queue.workerthreadminimummessages: %d\n", pThis->iMinMsgsPerWrkr);
+ dbgoprint((obj_t*) pThis, "queue.maxfilesize: %lld\n", pThis->iMaxFileSize);
+ dbgoprint((obj_t*) pThis, "queue.saveonshutdown: %d\n", pThis->bSaveOnShutdown);
+ dbgoprint((obj_t*) pThis, "queue.dequeueslowdown: %d\n", pThis->iDeqSlowdown);
+ dbgoprint((obj_t*) pThis, "queue.dequeuetimebegin: %d\n", pThis->iDeqtWinFromHr);
+ dbgoprint((obj_t*) pThis, "queue.dequeuetimeend: %d\n", pThis->iDeqtWinToHr);
+}
+
+
+/* get the physical queue size. Must only be called
+ * while mutex is locked!
+ * rgerhards, 2008-01-29
+ */
+static int
+getPhysicalQueueSize(qqueue_t *pThis)
+{
+ return (int) PREFER_FETCH_32BIT(pThis->iQueueSize);
+}
+
+
+/* get the logical queue size (that is store size minus logically dequeued elements).
+ * Must only be called while mutex is locked!
+ * rgerhards, 2009-05-19
+ */
+static int
+getLogicalQueueSize(qqueue_t *pThis)
+{
+ return pThis->iQueueSize - pThis->nLogDeq;
+}
+
+
+
+/* This function drains the queue in cases where this needs to be done. The most probable
+ * reason is a HUP which needs to discard data (because the queue is configured to be lossy).
+ * During a shutdown, this is typically not needed, as the OS frees up ressources and does
+ * this much quicker than when we clean up ourselvs. -- rgerhards, 2008-10-21
+ * This function returns void, as it makes no sense to communicate an error back, even if
+ * it happens.
+ * This functions works "around" the regular deque mechanism, because it is only used to
+ * clean up (in cases where message loss is acceptable).
+ */
+static void queueDrain(qqueue_t *pThis)
+{
+ smsg_t *pMsg;
+ assert(pThis != NULL);
+
+ DBGOPRINT((obj_t*) pThis, "queue (type %d) will lose %d messages, destroying...\n",
+ pThis->qType, pThis->iQueueSize);
+ /* iQueueSize is not decremented by qDel(), so we need to do it ourselves */
+ while(ATOMIC_DEC_AND_FETCH(&pThis->iQueueSize, &pThis->mutQueueSize) > 0) {
+ pThis->qDeq(pThis, &pMsg);
+ if(pMsg != NULL) {
+ msgDestruct(&pMsg);
+ }
+ pThis->qDel(pThis);
+ }
+}
+
+
+/* --------------- code for disk-assisted (DA) queue modes -------------------- */
+
+
+/* returns the number of workers that should be advised at
+ * this point in time. The mutex must be locked when
+ * ths function is called. -- rgerhards, 2008-01-25
+ */
+static rsRetVal
+qqueueAdviseMaxWorkers(qqueue_t *pThis)
+{
+ DEFiRet;
+ int iMaxWorkers;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ if(!pThis->bEnqOnly) {
+ if(pThis->bIsDA && getLogicalQueueSize(pThis) >= pThis->iHighWtrMrk) {
+ DBGOPRINT((obj_t*) pThis, "(re)activating DA worker\n");
+ wtpAdviseMaxWorkers(pThis->pWtpDA, 1, DENY_WORKER_START_DURING_SHUTDOWN);
+ /* disk queues have always one worker */
+ }
+ if(getLogicalQueueSize(pThis) == 0) {
+ iMaxWorkers = 0;
+ } else if(pThis->iMinMsgsPerWrkr == 0) {
+ iMaxWorkers = 1;
+ } else {
+ iMaxWorkers = getLogicalQueueSize(pThis) / pThis->iMinMsgsPerWrkr + 1;
+ }
+ wtpAdviseMaxWorkers(pThis->pWtpReg, iMaxWorkers, DENY_WORKER_START_DURING_SHUTDOWN);
+ }
+
+ RETiRet;
+}
+
+
+/* check if we run in disk-assisted mode and record that
+ * setting for easy (and quick!) access in the future. This
+ * function must only be called from constructors and only
+ * from those that support disk-assisted modes (aka memory-
+ * based queue drivers).
+ * rgerhards, 2008-01-14
+ */
+static rsRetVal
+qqueueChkIsDA(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ if(pThis->pszFilePrefix != NULL) {
+ pThis->bIsDA = 1;
+ DBGOPRINT((obj_t*) pThis, "is disk-assisted, disk will be used on demand\n");
+ } else {
+ DBGOPRINT((obj_t*) pThis, "is NOT disk-assisted\n");
+ }
+
+ RETiRet;
+}
+
+
+/* Start disk-assisted queue mode.
+ * rgerhards, 2008-01-15
+ */
+static rsRetVal
+StartDA(qqueue_t *pThis)
+{
+ DEFiRet;
+ uchar pszDAQName[128];
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ /* create message queue */
+ CHKiRet(qqueueConstruct(&pThis->pqDA, QUEUETYPE_DISK, pThis->iNumWorkerThreads, 0, pThis->pConsumer));
+
+ /* give it a name */
+ snprintf((char*) pszDAQName, sizeof(pszDAQName), "%s[DA]", obj.GetName((obj_t*) pThis));
+ obj.SetName((obj_t*) pThis->pqDA, pszDAQName);
+
+ /* as the created queue is the same object class, we take the
+ * liberty to access its properties directly.
+ */
+ pThis->pqDA->pqParent = pThis;
+
+ CHKiRet(qqueueSetpAction(pThis->pqDA, pThis->pAction));
+ CHKiRet(qqueueSetsizeOnDiskMax(pThis->pqDA, pThis->sizeOnDiskMax));
+ CHKiRet(qqueueSetiDeqSlowdown(pThis->pqDA, pThis->iDeqSlowdown));
+ CHKiRet(qqueueSetMaxFileSize(pThis->pqDA, pThis->iMaxFileSize));
+ CHKiRet(qqueueSetFilePrefix(pThis->pqDA, pThis->pszFilePrefix, pThis->lenFilePrefix));
+ CHKiRet(qqueueSetSpoolDir(pThis->pqDA, pThis->pszSpoolDir, pThis->lenSpoolDir));
+ CHKiRet(qqueueSetiPersistUpdCnt(pThis->pqDA, pThis->iPersistUpdCnt));
+ CHKiRet(qqueueSetbSyncQueueFiles(pThis->pqDA, pThis->bSyncQueueFiles));
+ CHKiRet(qqueueSettoActShutdown(pThis->pqDA, pThis->toActShutdown));
+ CHKiRet(qqueueSettoEnq(pThis->pqDA, pThis->toEnq));
+ CHKiRet(qqueueSetiDeqtWinFromHr(pThis->pqDA, pThis->iDeqtWinFromHr));
+ CHKiRet(qqueueSetiDeqtWinToHr(pThis->pqDA, pThis->iDeqtWinToHr));
+ CHKiRet(qqueueSettoQShutdown(pThis->pqDA, pThis->toQShutdown));
+ CHKiRet(qqueueSetiHighWtrMrk(pThis->pqDA, 0));
+ CHKiRet(qqueueSetiDiscardMrk(pThis->pqDA, 0));
+ pThis->pqDA->iDeqBatchSize = pThis->iDeqBatchSize;
+ pThis->pqDA->iMinDeqBatchSize = pThis->iMinDeqBatchSize;
+ pThis->pqDA->iMinMsgsPerWrkr = pThis->iMinMsgsPerWrkr;
+ pThis->pqDA->iLowWtrMrk = pThis->iLowWtrMrk;
+ if(pThis->useCryprov) {
+ /* hand over cryprov to DA queue - in-mem queue does no longer need it
+ * and DA queue will be kept active from now on until termination.
+ */
+ pThis->pqDA->useCryprov = pThis->useCryprov;
+ pThis->pqDA->cryprov = pThis->cryprov;
+ pThis->pqDA->cryprovData = pThis->cryprovData;
+ pThis->pqDA->cryprovName = pThis->cryprovName;
+ pThis->pqDA->cryprovNameFull = pThis->cryprovNameFull;
+ /* reset memory queue parameters */
+ pThis->useCryprov = 0;
+ /* pThis->cryprov cannot and need not be reset, is structure */
+ pThis->cryprovData = NULL;
+ pThis->cryprovName = NULL;
+ pThis->cryprovNameFull = NULL;
+ }
+
+ iRet = qqueueStart(runConf, pThis->pqDA);
+ /* file not found is expected, that means it is no previous QIF available */
+ if(iRet != RS_RET_OK && iRet != RS_RET_FILE_NOT_FOUND) {
+ errno = 0; /* else an errno is shown in errmsg! */
+ LogError(errno, iRet, "error starting up disk queue, using pure in-memory mode");
+ pThis->bIsDA = 0; /* disable memory mode */
+ FINALIZE; /* something is wrong */
+ }
+
+ DBGOPRINT((obj_t*) pThis, "DA queue initialized, disk queue 0x%lx\n",
+ qqueueGetID(pThis->pqDA));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pqDA != NULL) {
+ qqueueDestruct(&pThis->pqDA);
+ }
+ LogError(0, iRet, "%s: error creating disk queue - giving up.",
+ obj.GetName((obj_t*)pThis));
+ pThis->bIsDA = 0;
+ }
+
+ RETiRet;
+}
+
+
+/* initiate DA mode
+ * param bEnqOnly tells if the disk queue is to be run in enqueue-only mode. This may
+ * be needed during shutdown of memory queues which need to be persisted to disk.
+ * If this function fails (should not happen), DA mode is not turned on.
+ * rgerhards, 2008-01-16
+ */
+static rsRetVal ATTR_NONNULL()
+InitDA(qqueue_t *const pThis, const int bLockMutex)
+{
+ DEFiRet;
+ uchar pszBuf[64];
+ size_t lenBuf;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ if(bLockMutex == LOCK_MUTEX) {
+ d_pthread_mutex_lock(pThis->mut);
+ }
+
+ /* check if we already have a DA worker pool. If not, initiate one. Please note that the
+ * pool is created on first need but never again destructed (until the queue is). This
+ * is intentional. We assume that when we need it once, we may also need it on another
+ * occasion. Ressources used are quite minimal when no worker is running.
+ * rgerhards, 2008-01-24
+ * NOTE: this is the DA worker *pool*, not the DA queue!
+ */
+ lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%s:DAwpool", obj.GetName((obj_t*) pThis));
+ CHKiRet(wtpConstruct (&pThis->pWtpDA));
+ CHKiRet(wtpSetDbgHdr (pThis->pWtpDA, pszBuf, lenBuf));
+ CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int)) qqueueChkStopWrkrDA));
+ CHKiRet(wtpSetpfGetDeqBatchSize (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, int*)) GetDeqBatchSize));
+ CHKiRet(wtpSetpfDoWork (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, void *pWti)) ConsumerDA));
+ CHKiRet(wtpSetpfObjProcessed (pThis->pWtpDA, (rsRetVal (*)(void *pUsr, wti_t *pWti)) batchProcessed));
+ CHKiRet(wtpSetpmutUsr (pThis->pWtpDA, pThis->mut));
+ CHKiRet(wtpSetiNumWorkerThreads (pThis->pWtpDA, 1));
+ CHKiRet(wtpSettoWrkShutdown (pThis->pWtpDA, pThis->toWrkShutdown));
+ CHKiRet(wtpSetpUsr (pThis->pWtpDA, pThis));
+ CHKiRet(wtpConstructFinalize (pThis->pWtpDA));
+ /* if we reach this point, we have a "good" DA worker pool */
+
+ /* now construct the actual queue (if it does not already exist) */
+ if(pThis->pqDA == NULL) {
+ CHKiRet(StartDA(pThis));
+ }
+
+finalize_it:
+ if(bLockMutex == LOCK_MUTEX) {
+ d_pthread_mutex_unlock(pThis->mut);
+ }
+ RETiRet;
+}
+
+
+/* --------------- end code for disk-assisted queue modes -------------------- */
+
+
+/* Now, we define type-specific handlers. The provide a generic functionality,
+ * but for this specific type of queue. The mapping to these handlers happens during
+ * queue construction. Later on, handlers are called by pointers present in the
+ * queue instance object.
+ */
+
+/* -------------------- fixed array -------------------- */
+static rsRetVal qConstructFixedArray(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ if(pThis->iMaxQueueSize == 0)
+ ABORT_FINALIZE(RS_RET_QSIZE_ZERO);
+
+ if((pThis->tVars.farray.pBuf = malloc(sizeof(void *) * pThis->iMaxQueueSize)) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->tVars.farray.deqhead = 0;
+ pThis->tVars.farray.head = 0;
+ pThis->tVars.farray.tail = 0;
+
+ qqueueChkIsDA(pThis);
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal qDestructFixedArray(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ queueDrain(pThis); /* discard any remaining queue entries */
+ free(pThis->tVars.farray.pBuf);
+
+ RETiRet;
+}
+
+
+static rsRetVal qAddFixedArray(qqueue_t *pThis, smsg_t* in)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ pThis->tVars.farray.pBuf[pThis->tVars.farray.tail] = in;
+ pThis->tVars.farray.tail++;
+ if (pThis->tVars.farray.tail == pThis->iMaxQueueSize)
+ pThis->tVars.farray.tail = 0;
+
+ RETiRet;
+}
+
+
+static rsRetVal qDeqFixedArray(qqueue_t *pThis, smsg_t **out)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ *out = (void*) pThis->tVars.farray.pBuf[pThis->tVars.farray.deqhead];
+
+ pThis->tVars.farray.deqhead++;
+ if (pThis->tVars.farray.deqhead == pThis->iMaxQueueSize)
+ pThis->tVars.farray.deqhead = 0;
+
+ RETiRet;
+}
+
+
+static rsRetVal qDelFixedArray(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ pThis->tVars.farray.head++;
+ if (pThis->tVars.farray.head == pThis->iMaxQueueSize)
+ pThis->tVars.farray.head = 0;
+
+ RETiRet;
+}
+
+
+/* -------------------- linked list -------------------- */
+
+
+static rsRetVal qConstructLinkedList(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ pThis->tVars.linklist.pDeqRoot = NULL;
+ pThis->tVars.linklist.pDelRoot = NULL;
+ pThis->tVars.linklist.pLast = NULL;
+
+ qqueueChkIsDA(pThis);
+
+ RETiRet;
+}
+
+
+static rsRetVal qDestructLinkedList(qqueue_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+
+ queueDrain(pThis); /* discard any remaining queue entries */
+
+ /* with the linked list type, there is nothing left to do here. The
+ * reason is that there are no dynamic elements for the list itself.
+ */
+
+ RETiRet;
+}
+
+static rsRetVal qAddLinkedList(qqueue_t *pThis, smsg_t* pMsg)
+{
+ qLinkedList_t *pEntry;
+ DEFiRet;
+
+ CHKmalloc((pEntry = (qLinkedList_t*) malloc(sizeof(qLinkedList_t))));
+
+ pEntry->pNext = NULL;
+ pEntry->pMsg = pMsg;
+
+ if(pThis->tVars.linklist.pDelRoot == NULL) {
+ pThis->tVars.linklist.pDelRoot = pThis->tVars.linklist.pDeqRoot = pThis->tVars.linklist.pLast
+ = pEntry;
+ } else {
+ pThis->tVars.linklist.pLast->pNext = pEntry;
+ pThis->tVars.linklist.pLast = pEntry;
+ }
+
+ if(pThis->tVars.linklist.pDeqRoot == NULL) {
+ pThis->tVars.linklist.pDeqRoot = pEntry;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal qDeqLinkedList(qqueue_t *pThis, smsg_t **ppMsg)
+{
+ qLinkedList_t *pEntry;
+ DEFiRet;
+
+ pEntry = pThis->tVars.linklist.pDeqRoot;
+ if (pEntry != NULL) {
+ *ppMsg = pEntry->pMsg;
+ pThis->tVars.linklist.pDeqRoot = pEntry->pNext;
+ } else {
+ /* Check and return NULL for linklist.pDeqRoot */
+ dbgprintf("qDeqLinkedList: pDeqRoot is NULL!\n");
+ *ppMsg = NULL;
+ pThis->tVars.linklist.pDeqRoot = NULL;
+ }
+
+ RETiRet;
+}
+
+
+static rsRetVal qDelLinkedList(qqueue_t *pThis)
+{
+ qLinkedList_t *pEntry;
+ DEFiRet;
+
+ pEntry = pThis->tVars.linklist.pDelRoot;
+
+ if(pThis->tVars.linklist.pDelRoot == pThis->tVars.linklist.pLast) {
+ pThis->tVars.linklist.pDelRoot = pThis->tVars.linklist.pDeqRoot = pThis->tVars.linklist.pLast = NULL;
+ } else {
+ pThis->tVars.linklist.pDelRoot = pEntry->pNext;
+ }
+
+ free(pEntry);
+
+ RETiRet;
+}
+
+
+/* -------------------- disk -------------------- */
+
+
+/* The following function is used to "save" ourself from being killed by
+ * a fatally failed disk queue. A fatal failure is, for example, if no
+ * data can be read or written. In that case, the disk support is disabled,
+ * with all on-disk structures kept as-is as much as possible. However,
+ * we do not really stop or destruct the in-memory disk queue object.
+ * Practice has shown that this may cause races during destruction which
+ * themselfs can lead to segfault. So we prefer to was some ressources by
+ * keeping the queue active.
+ * Instead, the queue is switched to direct mode, so that at least
+ * some processing can happen. Of course, this may still have lots of
+ * undesired side-effects, but is probably better than aborting the
+ * syslogd. Note that this function *must* succeed in one way or another, as
+ * we can not recover from failure here. But it may emit different return
+ * states, which can trigger different processing in the higher layers.
+ * rgerhards, 2011-05-03
+ */
+static rsRetVal
+queueSwitchToEmergencyMode(qqueue_t *pThis, rsRetVal initiatingError)
+{
+ pThis->iQueueSize = 0;
+ pThis->nLogDeq = 0;
+
+ pThis->qType = QUEUETYPE_DIRECT;
+ pThis->qConstruct = qConstructDirect;
+ pThis->qDestruct = qDestructDirect;
+ /* these entry points shall not be used in direct mode
+ * To catch program errors, make us abort if that happens!
+ * rgerhards, 2013-11-05
+ */
+ pThis->qAdd = qAddDirect;
+ pThis->MultiEnq = qqueueMultiEnqObjDirect;
+ pThis->qDel = NULL;
+ if(pThis->pqParent != NULL) {
+ DBGOPRINT((obj_t*) pThis, "DA queue is in emergency mode, disabling DA in parent\n");
+ pThis->pqParent->bIsDA = 0;
+ pThis->pqParent->pqDA = NULL;
+ /* This may have undesired side effects, not sure if I really evaluated
+ * all. So you know where to look at if you come to this point during
+ * troubleshooting ;) -- rgerhards, 2011-05-03
+ */
+ }
+
+ LogError(0, initiatingError, "fatal error on disk queue '%s', "
+ "emergency switch to direct mode", obj.GetName((obj_t*) pThis));
+ return RS_RET_ERR_QUEUE_EMERGENCY;
+}
+
+
+static rsRetVal
+qqueueLoadPersStrmInfoFixup(strm_t *pStrm, qqueue_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pStrm, strm);
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ CHKiRet(strm.SetDir(pStrm, pThis->pszSpoolDir, pThis->lenSpoolDir));
+ CHKiRet(strm.SetbSync(pStrm, pThis->bSyncQueueFiles));
+finalize_it:
+ RETiRet;
+}
+
+
+/* The method loads the persistent queue information.
+ * rgerhards, 2008-01-11
+ */
+static rsRetVal
+qqueueTryLoadPersistedInfo(qqueue_t *pThis)
+{
+ DEFiRet;
+ strm_t *psQIF = NULL;
+ struct stat stat_buf;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ /* check if the file exists */
+ if(stat((char*) pThis->pszQIFNam, &stat_buf) == -1) {
+ if(errno == ENOENT) {
+ DBGOPRINT((obj_t*) pThis, "clean startup, no .qi file found\n");
+ ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ } else {
+ LogError(errno, RS_RET_IO_ERROR, "queue: %s: error %d could not access .qi file",
+ obj.GetName((obj_t*) pThis), errno);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ }
+
+ /* If we reach this point, we have a .qi file */
+
+ CHKiRet(strm.Construct(&psQIF));
+ CHKiRet(strm.SettOperationsMode(psQIF, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(psQIF, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(psQIF, pThis->pszQIFNam, pThis->lenQIFNam));
+ CHKiRet(strm.ConstructFinalize(psQIF));
+
+ /* first, we try to read the property bag for ourselfs */
+ CHKiRet(obj.DeserializePropBag((obj_t*) pThis, psQIF));
+
+ /* then the stream objects (same order as when persisted!) */
+ CHKiRet(obj.Deserialize(&pThis->tVars.disk.pWrite, (uchar*) "strm", psQIF,
+ (rsRetVal(*)(obj_t*,void*))qqueueLoadPersStrmInfoFixup, pThis));
+ CHKiRet(obj.Deserialize(&pThis->tVars.disk.pReadDel, (uchar*) "strm", psQIF,
+ (rsRetVal(*)(obj_t*,void*))qqueueLoadPersStrmInfoFixup, pThis));
+ /* create a duplicate for the read "pointer". */
+ CHKiRet(strm.Dup(pThis->tVars.disk.pReadDel, &pThis->tVars.disk.pReadDeq));
+ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDeq, 0)); /* deq must NOT delete the files! */
+ CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDeq));
+ /* if we use a crypto provider, we need to amend the objects with it's info */
+ if(pThis->useCryprov) {
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pWrite, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pWrite, pThis->cryprovData));
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDeq, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDeq, pThis->cryprovData));
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDel, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDel, pThis->cryprovData));
+ }
+
+ CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pWrite));
+ CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pReadDel));
+ CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pReadDeq));
+
+ /* OK, we could successfully read the file, so we now can request that it be
+ * deleted when we are done with the persisted information.
+ */
+ pThis->bNeedDelQIF = 1;
+ LogMsg(0, RS_RET_OK, LOG_INFO, "%s: queue files exist on disk, re-starting with "
+ "%d messages. This will keep the disk queue file open, details: "
+ "https://rainer.gerhards.net/2013/07/rsyslog-why-disk-assisted-queues-keep-a-file-open.html",
+ objGetName((obj_t*) pThis), getLogicalQueueSize(pThis));
+
+finalize_it:
+ if(psQIF != NULL)
+ strm.Destruct(&psQIF);
+
+ if(iRet != RS_RET_OK) {
+ DBGOPRINT((obj_t*) pThis, "state %d reading .qi file - can not read persisted info (if any)\n",
+ iRet);
+ }
+
+ RETiRet;
+}
+
+
+/* disk queue constructor.
+ * Note that we use a file limit of 10,000,000 files. That number should never pose a
+ * problem. If so, I guess the user has a design issue... But of course, the code can
+ * always be changed (though it would probably be more appropriate to increase the
+ * allowed file size at this point - that should be a config setting...
+ * rgerhards, 2008-01-10
+ */
+static rsRetVal qConstructDisk(qqueue_t *pThis)
+{
+ DEFiRet;
+ int bRestarted = 0;
+
+ assert(pThis != NULL);
+
+ /* and now check if there is some persistent information that needs to be read in */
+ iRet = qqueueTryLoadPersistedInfo(pThis);
+ if(iRet == RS_RET_OK)
+ bRestarted = 1;
+ else if(iRet != RS_RET_FILE_NOT_FOUND)
+ FINALIZE;
+
+ if(bRestarted == 1) {
+ ;
+ } else {
+ CHKiRet(strm.Construct(&pThis->tVars.disk.pWrite));
+ CHKiRet(strm.SetbSync(pThis->tVars.disk.pWrite, pThis->bSyncQueueFiles));
+ CHKiRet(strm.SetDir(pThis->tVars.disk.pWrite, pThis->pszSpoolDir, pThis->lenSpoolDir));
+ CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pWrite, 10000000));
+ CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pWrite, STREAMMODE_WRITE));
+ CHKiRet(strm.SetsType(pThis->tVars.disk.pWrite, STREAMTYPE_FILE_CIRCULAR));
+ if(pThis->useCryprov) {
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pWrite, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pWrite, pThis->cryprovData));
+ }
+ CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pWrite));
+
+ CHKiRet(strm.Construct(&pThis->tVars.disk.pReadDeq));
+ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDeq, 0));
+ CHKiRet(strm.SetDir(pThis->tVars.disk.pReadDeq, pThis->pszSpoolDir, pThis->lenSpoolDir));
+ CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pReadDeq, 10000000));
+ CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDeq, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDeq, STREAMTYPE_FILE_CIRCULAR));
+ if(pThis->useCryprov) {
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDeq, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDeq, pThis->cryprovData));
+ }
+ CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDeq));
+
+ CHKiRet(strm.Construct(&pThis->tVars.disk.pReadDel));
+ CHKiRet(strm.SetbSync(pThis->tVars.disk.pReadDel, pThis->bSyncQueueFiles));
+ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 1));
+ CHKiRet(strm.SetDir(pThis->tVars.disk.pReadDel, pThis->pszSpoolDir, pThis->lenSpoolDir));
+ CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pReadDel, 10000000));
+ CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDel, STREAMMODE_READ));
+ CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDel, STREAMTYPE_FILE_CIRCULAR));
+ if(pThis->useCryprov) {
+ CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDel, &pThis->cryprov));
+ CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDel, pThis->cryprovData));
+ }
+ CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDel));
+
+ CHKiRet(strm.SetFName(pThis->tVars.disk.pWrite, pThis->pszFilePrefix, pThis->lenFilePrefix));
+ CHKiRet(strm.SetFName(pThis->tVars.disk.pReadDeq, pThis->pszFilePrefix, pThis->lenFilePrefix));
+ CHKiRet(strm.SetFName(pThis->tVars.disk.pReadDel, pThis->pszFilePrefix, pThis->lenFilePrefix));
+ }
+
+ /* now we set (and overwrite in case of a persisted restart) some parameters which
+ * should always reflect the current configuration variables. Be careful by doing so,
+ * for example file name generation must not be changed as that would break the
+ * ability to read existing queue files. -- rgerhards, 2008-01-12
+ */
+ CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pWrite, pThis->iMaxFileSize));
+ CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pReadDeq, pThis->iMaxFileSize));
+ CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pReadDel, pThis->iMaxFileSize));
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal qDestructDisk(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ free(pThis->pszQIFNam);
+ if(pThis->tVars.disk.pWrite != NULL) {
+ int64 currOffs;
+ strm.GetCurrOffset(pThis->tVars.disk.pWrite, &currOffs);
+ if(currOffs == 0) {
+ /* if no data is present, we can (and must!) delete this
+ * file. Else we can leave garbagge after termination.
+ */
+ strm.SetbDeleteOnClose(pThis->tVars.disk.pWrite, 1);
+ }
+ strm.Destruct(&pThis->tVars.disk.pWrite);
+ }
+ if(pThis->tVars.disk.pReadDeq != NULL)
+ strm.Destruct(&pThis->tVars.disk.pReadDeq);
+ if(pThis->tVars.disk.pReadDel != NULL)
+ strm.Destruct(&pThis->tVars.disk.pReadDel);
+
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL(1,2)
+qAddDisk(qqueue_t *const pThis, smsg_t* pMsg)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ ISOBJ_TYPE_assert(pMsg, msg);
+ number_t nWriteCount;
+ const int oldfile = strmGetCurrFileNum(pThis->tVars.disk.pWrite);
+
+ CHKiRet(strm.SetWCntr(pThis->tVars.disk.pWrite, &nWriteCount));
+ CHKiRet((objSerialize(pMsg))(pMsg, pThis->tVars.disk.pWrite));
+ CHKiRet(strm.Flush(pThis->tVars.disk.pWrite));
+ CHKiRet(strm.SetWCntr(pThis->tVars.disk.pWrite, NULL)); /* no more counting for now... */
+
+ pThis->tVars.disk.sizeOnDisk += nWriteCount;
+
+ /* we have enqueued the user element to disk. So we now need to destruct
+ * the in-memory representation. The instance will be re-created upon
+ * dequeue. -- rgerhards, 2008-07-09
+ */
+ msgDestruct(&pMsg);
+
+ DBGOPRINT((obj_t*) pThis, "write wrote %lld octets to disk, queue disk size now %lld octets, EnqOnly:%d\n",
+ nWriteCount, pThis->tVars.disk.sizeOnDisk, pThis->bEnqOnly);
+
+ /* Did we have a change in the on-disk file? If so, we
+ * should do a "robustness sync" of the .qi file to guard
+ * against the most harsh consequences of kill -9 and power off.
+ */
+ int newfile;
+ newfile = strmGetCurrFileNum(pThis->tVars.disk.pWrite);
+ if(newfile != oldfile) {
+ DBGOPRINT((obj_t*) pThis, "current to-be-written-to file has changed from "
+ "number %d to number %d - requiring a .qi write for robustness\n",
+ oldfile, newfile);
+ pThis->tVars.disk.nForcePersist = 2;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+qDeqDisk(qqueue_t *pThis, smsg_t **ppMsg)
+{
+ DEFiRet;
+ iRet = objDeserializeWithMethods(ppMsg, (uchar*) "msg", 3,
+ pThis->tVars.disk.pReadDeq, NULL,
+ NULL, msgConstructForDeserializer, NULL, MsgDeserialize);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "%s: qDeqDisk error happened at around offset %lld",
+ obj.GetName((obj_t*)pThis),
+ (long long) pThis->tVars.disk.pReadDeq->iCurrOffs);
+ }
+ RETiRet;
+}
+
+
+/* -------------------- direct (no queueing) -------------------- */
+static rsRetVal qConstructDirect(qqueue_t __attribute__((unused)) *pThis)
+{
+ return RS_RET_OK;
+}
+
+
+static rsRetVal qDestructDirect(qqueue_t __attribute__((unused)) *pThis)
+{
+ return RS_RET_OK;
+}
+
+static rsRetVal qAddDirectWithWti(qqueue_t *pThis, smsg_t* pMsg, wti_t *pWti)
+{
+ batch_t singleBatch;
+ batch_obj_t batchObj;
+ batch_state_t batchState = BATCH_STATE_RDY;
+ DEFiRet;
+
+ //TODO: init batchObj (states _OK and new fields -- CHECK)
+ assert(pThis != NULL);
+
+ /* calling the consumer is quite different here than it is from a worker thread */
+ /* we need to provide the consumer's return value back to the caller because in direct
+ * mode the consumer probably has a lot to convey (which get's lost in the other modes
+ * because they are asynchronous. But direct mode is deliberately synchronous.
+ * rgerhards, 2008-02-12
+ * We use our knowledge about the batch_t structure below, but without that, we
+ * pay a too-large performance toll... -- rgerhards, 2009-04-22
+ */
+ memset(&batchObj, 0, sizeof(batch_obj_t));
+ memset(&singleBatch, 0, sizeof(batch_t));
+ batchObj.pMsg = pMsg;
+ singleBatch.nElem = 1; /* there always is only one in direct mode */
+ singleBatch.pElem = &batchObj;
+ singleBatch.eltState = &batchState;
+ iRet = pThis->pConsumer(pThis->pAction, &singleBatch, pWti);
+ msgDestruct(&pMsg);
+
+ RETiRet;
+}
+
+/* this is called if we do not have a pWti. This currently only happens
+ * when we are called from a main queue in direct mode. If so, we need
+ * to obtain a dummy pWti.
+ */
+static rsRetVal
+qAddDirect(qqueue_t *pThis, smsg_t* pMsg)
+{
+ wti_t *pWti;
+ DEFiRet;
+
+ pWti = wtiGetDummy();
+ pWti->pbShutdownImmediate = &pThis->bShutdownImmediate;
+ iRet = qAddDirectWithWti(pThis, pMsg, pWti);
+ RETiRet;
+}
+
+
+/* --------------- end type-specific handlers -------------------- */
+
+
+/* generic code to add a queue entry
+ * We use some specific code to most efficiently support direct mode
+ * queues. This is justified in spite of the gain and the need to do some
+ * things truely different. -- rgerhards, 2008-02-12
+ */
+static rsRetVal
+qqueueAdd(qqueue_t *pThis, smsg_t *pMsg)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ static int msgCnt = 0;
+
+ if(pThis->iSmpInterval > 0)
+ {
+ msgCnt = (msgCnt + 1) % (pThis->iSmpInterval);
+ if(msgCnt != 0)
+ {
+ msgDestruct(&pMsg);
+ goto finalize_it;
+ }
+ }
+
+ CHKiRet(pThis->qAdd(pThis, pMsg));
+
+ if(pThis->qType != QUEUETYPE_DIRECT) {
+ ATOMIC_INC(&pThis->iQueueSize, &pThis->mutQueueSize);
+# ifdef ENABLE_IMDIAG
+# ifdef HAVE_ATOMIC_BUILTINS
+ /* mutex is never used due to conditional compilation */
+ ATOMIC_INC(&iOverallQueueSize, &NULL);
+# else
+ ++iOverallQueueSize; /* racy, but we can't wait for a mutex! */
+# endif
+# endif
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* generic code to dequeue a queue entry
+ */
+static rsRetVal
+qqueueDeq(qqueue_t *pThis, smsg_t **ppMsg)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ /* we do NOT abort if we encounter an error, because otherwise the queue
+ * will not be decremented, what will most probably result in an endless loop.
+ * If we decrement, however, we may lose a message. But that is better than
+ * losing the whole process because it loops... -- rgerhards, 2008-01-03
+ */
+ iRet = pThis->qDeq(pThis, ppMsg);
+ ATOMIC_INC(&pThis->nLogDeq, &pThis->mutLogDeq);
+
+ DBGOPRINT((obj_t*) pThis, "entry deleted, size now log %d, phys %d entries\n",
+ getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+
+ RETiRet;
+}
+
+
+/* Try to shut down regular and DA queue workers, within the queue timeout
+ * period. That means processing continues as usual. This is the expected
+ * usual case, where during shutdown those messages remaining are being
+ * processed. At this point, it is acceptable that the queue can not be
+ * fully depleted, that case is handled in the next step. During this phase,
+ * we first shut down the main queue DA worker to prevent new data to arrive
+ * at the DA queue, and then we ask the regular workers of both the Regular
+ * and DA queue to try complete processing.
+ * rgerhards, 2009-10-14
+ */
+static rsRetVal ATTR_NONNULL(1)
+tryShutdownWorkersWithinQueueTimeout(qqueue_t *const pThis)
+{
+ struct timespec tTimeout;
+ rsRetVal iRetLocal;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pThis->pqParent == NULL); /* detect invalid calling sequence */
+
+ if(pThis->bIsDA) {
+ /* We need to lock the mutex, as otherwise we may have a race that prevents
+ * us from awaking the DA worker. */
+ d_pthread_mutex_lock(pThis->mut);
+
+ /* tell regular queue DA worker to stop shuffling messages to DA queue... */
+ DBGOPRINT((obj_t*) pThis, "setting EnqOnly mode for DA worker\n");
+ pThis->pqDA->bEnqOnly = 1;
+ wtpSetState(pThis->pWtpDA, wtpState_SHUTDOWN_IMMEDIATE);
+ wtpAdviseMaxWorkers(pThis->pWtpDA, 1, DENY_WORKER_START_DURING_SHUTDOWN);
+ DBGOPRINT((obj_t*) pThis, "awoke DA worker, told it to shut down.\n");
+
+ /* also tell the DA queue worker to shut down, so that it already knows... */
+ wtpSetState(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN);
+ wtpAdviseMaxWorkers(pThis->pqDA->pWtpReg, 1, DENY_WORKER_START_DURING_SHUTDOWN);
+ /* awake its lone worker */
+ DBGOPRINT((obj_t*) pThis, "awoke DA queue regular worker, told it to shut down when done.\n");
+
+ d_pthread_mutex_unlock(pThis->mut);
+ }
+
+
+ /* first calculate absolute timeout - we need the absolute value here, because we need to coordinate
+ * shutdown of both the regular and DA queue on *the same* timeout.
+ */
+ timeoutComp(&tTimeout, pThis->toQShutdown);
+ DBGOPRINT((obj_t*) pThis, "trying shutdown of regular workers\n");
+ iRetLocal = wtpShutdownAll(pThis->pWtpReg, wtpState_SHUTDOWN, &tTimeout);
+ if(iRetLocal == RS_RET_TIMED_OUT) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO,
+ "%s: regular queue shutdown timed out on primary queue "
+ "(this is OK, timeout was %d)",
+ objGetName((obj_t*) pThis), pThis->toQShutdown);
+ } else {
+ DBGOPRINT((obj_t*) pThis, "regular queue workers shut down.\n");
+ }
+
+ /* OK, the worker for the regular queue is processed, on the the DA queue regular worker. */
+ if(pThis->pqDA != NULL) {
+ DBGOPRINT((obj_t*) pThis, "we have a DA queue (0x%lx), requesting its shutdown.\n",
+ qqueueGetID(pThis->pqDA));
+ /* we use the same absolute timeout as above, so we do not use more than the configured
+ * timeout interval!
+ */
+ DBGOPRINT((obj_t*) pThis, "trying shutdown of regular worker of DA queue\n");
+ iRetLocal = wtpShutdownAll(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN, &tTimeout);
+ if(iRetLocal == RS_RET_TIMED_OUT) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO,
+ "%s: regular queue shutdown timed out on DA queue (this is OK, "
+ "timeout was %d)", objGetName((obj_t*) pThis), pThis->toQShutdown);
+ } else {
+ DBGOPRINT((obj_t*) pThis, "DA queue worker shut down.\n");
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* Try to shut down regular and DA queue workers, within the action timeout
+ * period. This aborts processing, but at the end of the current action, in
+ * a well-defined manner. During this phase, we terminate all three worker
+ * pools, including the regular queue DA worker if it not yet has terminated.
+ * Not finishing processing all messages is OK (and expected) at this stage
+ * (they may be preserved later, depending * on bSaveOnShutdown setting).
+ * rgerhards, 2009-10-14
+ */
+static rsRetVal
+tryShutdownWorkersWithinActionTimeout(qqueue_t *pThis)
+{
+ struct timespec tTimeout;
+ rsRetVal iRetLocal;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pThis->pqParent == NULL); /* detect invalid calling sequence */
+
+ /* instruct workers to finish ASAP, even if still work exists */
+ DBGOPRINT((obj_t*) pThis, "trying to shutdown workers within Action Timeout");
+ DBGOPRINT((obj_t*) pThis, "setting EnqOnly mode\n");
+ pThis->bEnqOnly = 1;
+ pThis->bShutdownImmediate = 1;
+ /* now DA queue */
+ if(pThis->bIsDA) {
+ pThis->pqDA->bEnqOnly = 1;
+ pThis->pqDA->bShutdownImmediate = 1;
+ }
+
+ /* now give the queue workers a last chance to gracefully shut down (based on action timeout setting) */
+ timeoutComp(&tTimeout, pThis->toActShutdown);
+ DBGOPRINT((obj_t*) pThis, "trying immediate shutdown of regular workers (if any)\n");
+ iRetLocal = wtpShutdownAll(pThis->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout);
+ if(iRetLocal == RS_RET_TIMED_OUT) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO,
+ "%s: immediate shutdown timed out on primary queue (this is acceptable and "
+ "triggers cancellation)", objGetName((obj_t*) pThis));
+ } else if(iRetLocal != RS_RET_OK) {
+ LogMsg(0, iRetLocal, LOG_WARNING,
+ "%s: potential internal error: unexpected return state after trying "
+ "immediate shutdown of the primary queue in disk save mode. "
+ "Continuing, but results are unpredictable", objGetName((obj_t*) pThis));
+ }
+
+ if(pThis->pqDA != NULL) {
+ /* and now the same for the DA queue */
+ DBGOPRINT((obj_t*) pThis, "trying immediate shutdown of DA queue workers\n");
+ iRetLocal = wtpShutdownAll(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout);
+ if(iRetLocal == RS_RET_TIMED_OUT) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO,
+ "%s: immediate shutdown timed out on DA queue (this is acceptable and "
+ "triggers cancellation)", objGetName((obj_t*) pThis));
+ } else if(iRetLocal != RS_RET_OK) {
+ LogMsg(0, iRetLocal, LOG_WARNING,
+ "%s: potential internal error: unexpected return state after trying "
+ "immediate shutdown of the DA queue in disk save mode. "
+ "Continuing, but results are unpredictable", objGetName((obj_t*) pThis));
+ }
+
+ /* and now we need to terminate the DA worker itself. We always grant it a 100ms timeout,
+ * which should be sufficient and usually not be required (it is expected to have finished
+ * long before while we were processing the queue timeout in shutdown phase 1).
+ * rgerhards, 2009-10-14
+ */
+ timeoutComp(&tTimeout, 100);
+ DBGOPRINT((obj_t*) pThis, "trying regular shutdown of main queue DA worker pool\n");
+ iRetLocal = wtpShutdownAll(pThis->pWtpDA, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout);
+ if(iRetLocal == RS_RET_TIMED_OUT) {
+ LogMsg(0, iRetLocal, LOG_WARNING,
+ "%s: shutdown timed out on main queue DA worker pool "
+ "(this is not good, but possibly OK)",
+ objGetName((obj_t*) pThis));
+ } else {
+ DBGOPRINT((obj_t*) pThis, "main queue DA worker pool shut down.\n");
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* This function cancels all remaining regular workers for both the main and the DA
+ * queue.
+ * rgerhards, 2009-05-29
+ */
+static rsRetVal
+cancelWorkers(qqueue_t *pThis)
+{
+ rsRetVal iRetLocal;
+ DEFiRet;
+
+ assert(pThis->qType != QUEUETYPE_DIRECT);
+
+ /* Now queue workers should have terminated. If not, we need to cancel them as we have applied
+ * all timeout setting. If any worker in any queue still executes, its consumer is possibly
+ * long-running and cancelling is the only way to get rid of it.
+ */
+ DBGOPRINT((obj_t*) pThis, "checking to see if we need to cancel any worker threads of the primary queue\n");
+ iRetLocal = wtpCancelAll(pThis->pWtpReg, objGetName((obj_t*) pThis));
+ /* ^-- returns immediately if all threads already have terminated */
+ if(iRetLocal != RS_RET_OK) {
+ DBGOPRINT((obj_t*) pThis, "unexpected iRet state %d trying to cancel primary queue worker "
+ "threads, continuing, but results are unpredictable\n", iRetLocal);
+ }
+
+ /* ... and now the DA queue, if it exists (should always be after the primary one) */
+ if(pThis->pqDA != NULL) {
+ DBGOPRINT((obj_t*) pThis, "checking to see if we need to cancel any worker threads of "
+ "the DA queue\n");
+ iRetLocal = wtpCancelAll(pThis->pqDA->pWtpReg, objGetName((obj_t*) pThis));
+ /* returns immediately if all threads already have terminated */
+ if(iRetLocal != RS_RET_OK) {
+ DBGOPRINT((obj_t*) pThis, "unexpected iRet state %d trying to cancel DA queue worker "
+ "threads, continuing, but results are unpredictable\n", iRetLocal);
+ }
+
+ /* finally, we cancel the main queue's DA worker pool, if it still is running. It may be
+ * restarted later to persist the queue. But we stop it, because otherwise we get into
+ * big trouble when resetting the logical dequeue pointer. This operation can only be
+ * done when *no* worker is running. So time for a shutdown... -- rgerhards, 2009-05-28
+ */
+ DBGOPRINT((obj_t*) pThis, "checking to see if main queue DA worker pool needs to be cancelled\n");
+ wtpCancelAll(pThis->pWtpDA, objGetName((obj_t*) pThis));
+ /* returns immediately if all threads already have terminated */
+ }
+
+ RETiRet;
+}
+
+
+/* This function shuts down all worker threads and waits until they
+ * have terminated. If they timeout, they are cancelled.
+ * rgerhards, 2008-01-24
+ * Please note that this function shuts down BOTH the parent AND the child queue
+ * in DA case. This is necessary because their timeouts are tightly coupled. Most
+ * importantly, the timeouts would be applied twice (or logic be extremely
+ * complex) if each would have its own shutdown. The function does not self check
+ * this condition - the caller must make sure it is not called with a parent.
+ * rgerhards, 2009-05-26: we do NO longer persist the queue here if bSaveOnShutdown
+ * is set. This must be handled by the caller. Not doing that cleans up the queue
+ * shutdown considerably. Also, older engines had a potential hang condition when
+ * the DA queue was already started and the DA worker configured for infinite
+ * retries and the action was during retry processing. This was a design issue,
+ * which is solved as of now. Note that the shutdown now may take a little bit
+ * longer, because we no longer can persist the queue in parallel to waiting
+ * on worker timeouts.
+ */
+rsRetVal ATTR_NONNULL(1)
+qqueueShutdownWorkers(qqueue_t *const pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ if(pThis->qType == QUEUETYPE_DIRECT) {
+ FINALIZE;
+ }
+
+ assert(pThis->pqParent == NULL); /* detect invalid calling sequence */
+
+ DBGOPRINT((obj_t*) pThis, "initiating worker thread shutdown sequence %p\n", pThis);
+
+ CHKiRet(tryShutdownWorkersWithinQueueTimeout(pThis));
+
+ pthread_mutex_lock(pThis->mut);
+ int physQueueSize;
+ physQueueSize = getPhysicalQueueSize(pThis);
+ pthread_mutex_unlock(pThis->mut);
+ if(physQueueSize > 0) {
+ CHKiRet(tryShutdownWorkersWithinActionTimeout(pThis));
+ }
+
+ CHKiRet(cancelWorkers(pThis));
+
+ /* ... finally ... all worker threads have terminated :-)
+ * Well, more precisely, they *are in termination*. Some cancel cleanup handlers
+ * may still be running. Note that the main queue's DA worker may still be running.
+ */
+ DBGOPRINT((obj_t*) pThis, "worker threads terminated, remaining queue size log %d, phys %d.\n",
+ getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+
+finalize_it:
+ RETiRet;
+}
+
+/* Constructor for the queue object
+ * This constructs the data structure, but does not yet start the queue. That
+ * is done by queueStart(). The reason is that we want to give the caller a chance
+ * to modify some parameters before the queue is actually started.
+ */
+rsRetVal qqueueConstruct(qqueue_t **ppThis, queueType_t qType, int iWorkerThreads,
+ int iMaxQueueSize, rsRetVal (*pConsumer)(void*, batch_t*, wti_t*))
+{
+ DEFiRet;
+ qqueue_t *pThis;
+ const uchar *const workDir = glblGetWorkDirRaw(ourConf);
+
+ assert(ppThis != NULL);
+ assert(pConsumer != NULL);
+ assert(iWorkerThreads >= 0);
+
+ CHKmalloc(pThis = (qqueue_t *)calloc(1, sizeof(qqueue_t)));
+
+ /* we have an object, so let's fill the properties */
+ objConstructSetObjInfo(pThis);
+
+ if(workDir != NULL) {
+ if((pThis->pszSpoolDir = ustrdup(workDir)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ pThis->lenSpoolDir = ustrlen(pThis->pszSpoolDir);
+ }
+ /* set some water marks so that we have useful defaults if none are set specifically */
+ pThis->iFullDlyMrk = -1;
+ pThis->iLightDlyMrk = -1;
+ pThis->iMaxFileSize = 1024 * 1024; /* default is 1 MiB */
+ pThis->iQueueSize = 0;
+ pThis->nLogDeq = 0;
+ pThis->useCryprov = 0;
+ pThis->takeFlowCtlFromMsg = 0;
+ pThis->iMaxQueueSize = iMaxQueueSize;
+ pThis->pConsumer = pConsumer;
+ pThis->iNumWorkerThreads = iWorkerThreads;
+ pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */
+ pThis->iDeqBatchSize = 8; /* conservative default, should still provide good performance */
+ pThis->iMinDeqBatchSize = 0; /* conservative default, should still provide good performance */
+ pThis->isRunning = 0;
+
+ pThis->pszFilePrefix = NULL;
+ pThis->qType = qType;
+
+
+ INIT_ATOMIC_HELPER_MUT(pThis->mutQueueSize);
+ INIT_ATOMIC_HELPER_MUT(pThis->mutLogDeq);
+
+finalize_it:
+ OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP
+ RETiRet;
+}
+
+
+/* set default inside queue object suitable for action queues.
+ * This shall be called directly after queue construction. This functions has
+ * been added in support of the new v6 config system. It expect properly pre-initialized
+ * objects, but we need to differentiate between ruleset main and action queues.
+ * In order to avoid unnecessary complexity, we provide the necessary defaults
+ * via specific function calls.
+ */
+void
+qqueueSetDefaultsActionQueue(qqueue_t *pThis)
+{
+ pThis->qType = QUEUETYPE_DIRECT; /* type of the main message queue above */
+ pThis->iMaxQueueSize = 1000; /* size of the main message queue above */
+ pThis->iDeqBatchSize = 128; /* default batch size */
+ pThis->iMinDeqBatchSize = 0;
+ pThis->toMinDeqBatchSize = 1000;
+ pThis->iHighWtrMrk = -1; /* high water mark for disk-assisted queues */
+ pThis->iLowWtrMrk = -1; /* low water mark for disk-assisted queues */
+ pThis->iDiscardMrk = -1; /* begin to discard messages */
+ pThis->iDiscardSeverity = 8; /* turn off */
+ pThis->iNumWorkerThreads = 1; /* number of worker threads for the mm queue above */
+ pThis->iMaxFileSize = 1024*1024;
+ pThis->iPersistUpdCnt = 0; /* persist queue info every n updates */
+ pThis->bSyncQueueFiles = 0;
+ pThis->toQShutdown = loadConf->globals.actq_dflt_toQShutdown; /* queue shutdown */
+ pThis->toActShutdown = loadConf->globals.actq_dflt_toActShutdown; /* action shutdown (in phase 2) */
+ pThis->toEnq = loadConf->globals.actq_dflt_toEnq; /* timeout for queue enque */
+ pThis->toWrkShutdown = loadConf->globals.actq_dflt_toWrkShutdown; /* timeout for worker thread shutdown */
+ pThis->iMinMsgsPerWrkr = -1; /* minimum messages per worker needed to start a new one */
+ pThis->bSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
+ pThis->sizeOnDiskMax = 0; /* unlimited */
+ pThis->iDeqSlowdown = 0;
+ pThis->iDeqtWinFromHr = 0;
+ pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */
+ pThis->iSmpInterval = 0; /* disable sampling */
+}
+
+
+/* set defaults inside queue object suitable for main/ruleset queues.
+ * See queueSetDefaultsActionQueue() for more details and background.
+ */
+void
+qqueueSetDefaultsRulesetQueue(qqueue_t *pThis)
+{
+ pThis->qType = QUEUETYPE_FIXED_ARRAY; /* type of the main message queue above */
+ pThis->iMaxQueueSize = 50000; /* size of the main message queue above */
+ pThis->iDeqBatchSize = 1024; /* default batch size */
+ pThis->iMinDeqBatchSize = 0;
+ pThis->toMinDeqBatchSize = 1000;
+ pThis->iHighWtrMrk = -1; /* high water mark for disk-assisted queues */
+ pThis->iLowWtrMrk = -1; /* low water mark for disk-assisted queues */
+ pThis->iDiscardMrk = -1; /* begin to discard messages */
+ pThis->iDiscardSeverity = 8; /* turn off */
+ pThis->iNumWorkerThreads = 1; /* number of worker threads for the mm queue above */
+ pThis->iMaxFileSize = 16*1024*1024;
+ pThis->iPersistUpdCnt = 0; /* persist queue info every n updates */
+ pThis->bSyncQueueFiles = 0;
+ pThis->toQShutdown = ourConf->globals.ruleset_dflt_toQShutdown;
+ pThis->toActShutdown = ourConf->globals.ruleset_dflt_toActShutdown;
+ pThis->toEnq = ourConf->globals.ruleset_dflt_toEnq;
+ pThis->toWrkShutdown = ourConf->globals.ruleset_dflt_toWrkShutdown;
+ pThis->iMinMsgsPerWrkr = -1; /* minimum messages per worker needed to start a new one */
+ pThis->bSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
+ pThis->sizeOnDiskMax = 0; /* unlimited */
+ pThis->iDeqSlowdown = 0;
+ pThis->iDeqtWinFromHr = 0;
+ pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */
+ pThis->iSmpInterval = 0; /* disable sampling */
+}
+
+
+/* This function checks if the provided message shall be discarded and does so, if needed.
+ * In DA mode, we do not discard any messages as we assume the disk subsystem is fast enough to
+ * provide real-time creation of spool files.
+ * Note: cached copies of iQueueSize is provided so that no mutex locks are required.
+ * The caller must have obtained them while the mutex was locked. Of course, these values may no
+ * longer be current, but that is OK for the discard check. At worst, the message is either processed
+ * or discarded when it should not have been. As discarding is in itself somewhat racy and erratic,
+ * that is no problems for us. This function MUST NOT lock the queue mutex, it could result in
+ * deadlocks!
+ * If the message is discarded, it can no longer be processed by the caller. So be sure to check
+ * the return state!
+ * rgerhards, 2008-01-24
+ */
+static int qqueueChkDiscardMsg(qqueue_t *pThis, int iQueueSize, smsg_t *pMsg)
+{
+ DEFiRet;
+ rsRetVal iRetLocal;
+ int iSeverity;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ if(pThis->iDiscardMrk > 0 && iQueueSize >= pThis->iDiscardMrk) {
+ iRetLocal = MsgGetSeverity(pMsg, &iSeverity);
+ if(iRetLocal == RS_RET_OK && iSeverity >= pThis->iDiscardSeverity) {
+ DBGOPRINT((obj_t*) pThis, "queue nearly full (%d entries), discarded severity %d message\n",
+ iQueueSize, iSeverity);
+ STATSCOUNTER_INC(pThis->ctrNFDscrd, pThis->mutCtrNFDscrd);
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_QUEUE_FULL);
+ } else {
+ DBGOPRINT((obj_t*) pThis, "queue nearly full (%d entries), but could not drop msg "
+ "(iRet: %d, severity %d)\n", iQueueSize, iRetLocal, iSeverity);
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Finally remove n elements from the queue store.
+ */
+static rsRetVal ATTR_NONNULL(1)
+DoDeleteBatchFromQStore(qqueue_t *const pThis, const int nElem)
+{
+ int i;
+ off64_t bytesDel = 0; /* keep CLANG static anaylzer happy */
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ /* now send delete request to storage driver */
+ if(pThis->qType == QUEUETYPE_DISK) {
+ strmMultiFileSeek(pThis->tVars.disk.pReadDel, pThis->tVars.disk.deqFileNumOut,
+ pThis->tVars.disk.deqOffs, &bytesDel);
+ /* We need to correct the on-disk file size. This time it is a bit tricky:
+ * we free disk space only upon file deletion. So we need to keep track of what we
+ * have read until we get an out-offset that is lower than the in-offset (which
+ * indicates file change). Then, we can subtract the whole thing from the on-disk
+ * size. -- rgerhards, 2008-01-30
+ */
+ if(bytesDel != 0) {
+ pThis->tVars.disk.sizeOnDisk -= bytesDel;
+ DBGOPRINT((obj_t*) pThis, "doDeleteBatch: a %lld octet file has been deleted, now %lld "
+ "octets disk space used\n", (long long) bytesDel, pThis->tVars.disk.sizeOnDisk);
+ /* awake possibly waiting enq process */
+ pthread_cond_signal(&pThis->notFull); /* we hold the mutex while we are in here! */
+ }
+ } else { /* memory queue */
+ for(i = 0 ; i < nElem ; ++i) {
+ pThis->qDel(pThis);
+ }
+ }
+
+ /* iQueueSize is not decremented by qDel(), so we need to do it ourselves */
+ ATOMIC_SUB(&pThis->iQueueSize, nElem, &pThis->mutQueueSize);
+# ifdef ENABLE_IMDIAG
+# ifdef HAVE_ATOMIC_BUILTINS
+ /* mutex is never used due to conditional compilation */
+ ATOMIC_SUB(&iOverallQueueSize, nElem, &NULL);
+# else
+ iOverallQueueSize -= nElem; /* racy, but we can't wait for a mutex! */
+# endif
+# endif
+ ATOMIC_SUB(&pThis->nLogDeq, nElem, &pThis->mutLogDeq);
+ DBGPRINTF("doDeleteBatch: delete batch from store, new sizes: log %d, phys %d\n",
+ getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+ ++pThis->deqIDDel; /* one more batch dequeued */
+
+ if((pThis->qType == QUEUETYPE_DISK) && (bytesDel != 0)) {
+ qqueuePersist(pThis, QUEUE_CHECKPOINT); /* robustness persist .qi file */
+ }
+
+ RETiRet;
+}
+
+
+/* remove messages from the physical queue store that are fully processed. This is
+ * controlled via the to-delete list.
+ */
+static rsRetVal
+DeleteBatchFromQStore(qqueue_t *pThis, batch_t *pBatch)
+{
+ toDeleteLst_t *pTdl;
+ qDeqID deqIDDel;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pBatch != NULL);
+
+dbgprintf("rger: deleteBatchFromQStore, nElem %d\n", (int) pBatch->nElem);
+ pTdl = tdlPeek(pThis); /* get current head element */
+ if(pTdl == NULL) { /* to-delete list empty */
+ DoDeleteBatchFromQStore(pThis, pBatch->nElem);
+ } else if(pBatch->deqID == pThis->deqIDDel) {
+ deqIDDel = pThis->deqIDDel;
+ pTdl = tdlPeek(pThis);
+ while(pTdl != NULL && deqIDDel == pTdl->deqID) {
+ DoDeleteBatchFromQStore(pThis, pTdl->nElemDeq);
+ tdlPop(pThis);
+ ++deqIDDel;
+ pTdl = tdlPeek(pThis);
+ }
+ /* old entries deleted, now delete current ones... */
+ DoDeleteBatchFromQStore(pThis, pBatch->nElem);
+ } else {
+ /* can not delete, insert into to-delete list */
+ DBGPRINTF("not at head of to-delete list, enqueue %d\n", (int) pBatch->deqID);
+ CHKiRet(tdlAdd(pThis, pBatch->deqID, pBatch->nElem));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Delete a batch of processed user objects from the queue, which includes
+ * destructing the objects themself. Any entries not marked as finally
+ * processed are enqueued again. The new enqueue is necessary because we have a
+ * rgerhards, 2009-05-13
+ */
+static rsRetVal
+DeleteProcessedBatch(qqueue_t *pThis, batch_t *pBatch)
+{
+ int i;
+ smsg_t *pMsg;
+ int nEnqueued = 0;
+ rsRetVal localRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pBatch != NULL);
+
+ for(i = 0 ; i < pBatch->nElem ; ++i) {
+ pMsg = pBatch->pElem[i].pMsg;
+ DBGPRINTF("DeleteProcessedBatch: etry %d state %d\n", i, pBatch->eltState[i]);
+ if( pBatch->eltState[i] == BATCH_STATE_RDY
+ || pBatch->eltState[i] == BATCH_STATE_SUB) {
+ localRet = doEnqSingleObj(pThis, eFLOWCTL_NO_DELAY, MsgAddRef(pMsg));
+ ++nEnqueued;
+ if(localRet != RS_RET_OK) {
+ DBGPRINTF("DeleteProcessedBatch: error %d re-enqueuing unprocessed "
+ "data element - discarded\n", localRet);
+ }
+ }
+ msgDestruct(&pMsg);
+ }
+
+ DBGPRINTF("DeleteProcessedBatch: we deleted %d objects and enqueued %d objects\n", i-nEnqueued, nEnqueued);
+
+ if(nEnqueued > 0)
+ qqueueChkPersist(pThis, nEnqueued);
+
+ iRet = DeleteBatchFromQStore(pThis, pBatch);
+
+ pBatch->nElem = pBatch->nElemDeq = 0; /* reset batch */ // TODO: more fine init, new fields! 2010-06-14
+
+ RETiRet;
+}
+
+
+/* dequeue as many user pointers as are available, until we hit the configured
+ * upper limit of pointers. Note that this function also deletes all processed
+ * objects from the previous batch. However, it is perfectly valid that the
+ * previous batch contained NO objects at all. For example, this happens
+ * immediately after system startup or when a queue was exhausted and the queue
+ * worker needed to wait for new data.
+ * This must only be called when the queue mutex is LOOKED, otherwise serious
+ * malfunction will happen.
+ */
+static rsRetVal ATTR_NONNULL()
+DequeueConsumableElements(qqueue_t *const pThis, wti_t *const pWti,
+ int *const piRemainingQueueSize, int *const pSkippedMsgs)
+{
+ int nDequeued;
+ int nDiscarded;
+ int nDeleted;
+ int iQueueSize;
+ int keep_running = 1;
+ struct timespec timeout;
+ smsg_t *pMsg;
+ rsRetVal localRet;
+ DEFiRet;
+
+ nDeleted = pWti->batch.nElemDeq;
+ DeleteProcessedBatch(pThis, &pWti->batch);
+
+ nDequeued = nDiscarded = 0;
+ if(pThis->qType == QUEUETYPE_DISK) {
+ pThis->tVars.disk.deqFileNumIn = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq);
+ }
+
+ /* work-around clang static analyzer false positive, we need a const value */
+ const int iMinDeqBatchSize = pThis->iMinDeqBatchSize;
+ if(iMinDeqBatchSize > 0) {
+ timeoutComp(&timeout, pThis->toMinDeqBatchSize);/* get absolute timeout */
+ }
+
+ while((iQueueSize = getLogicalQueueSize(pThis)) > 0 && nDequeued < pThis->iDeqBatchSize) {
+ int rd_fd = -1;
+ int64_t rd_offs = 0;
+ int wr_fd = -1;
+ int64_t wr_offs = 0;
+ if(pThis->tVars.disk.pReadDeq != NULL) {
+ rd_fd = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq);
+ rd_offs = pThis->tVars.disk.pReadDeq->iCurrOffs;
+ }
+ if(pThis->tVars.disk.pWrite != NULL) {
+ wr_fd = strmGetCurrFileNum(pThis->tVars.disk.pWrite);
+ wr_offs = pThis->tVars.disk.pWrite->iCurrOffs;
+ }
+ if(rd_fd != -1 && rd_fd == wr_fd && rd_offs == wr_offs) {
+ DBGPRINTF("problem on disk queue '%s': "
+ //"queue size log %d, phys %d, but rd_fd=wr_rd=%d and offs=%lld\n",
+ "queue size log %d, phys %d, but rd_fd=wr_rd=%d and offs=%" PRId64 "\n",
+ obj.GetName((obj_t*) pThis), iQueueSize, pThis->iQueueSize,
+ rd_fd, rd_offs);
+ *pSkippedMsgs = iQueueSize;
+# ifdef ENABLE_IMDIAG
+ iOverallQueueSize -= iQueueSize;
+# endif
+ pThis->iQueueSize -= iQueueSize;
+ iQueueSize = 0;
+ break;
+ }
+
+ localRet = qqueueDeq(pThis, &pMsg);
+ if(localRet == RS_RET_FILE_NOT_FOUND) {
+ DBGPRINTF("fatal error on disk queue '%s': file '%s' "
+ "not found, queue size said to be %d",
+ obj.GetName((obj_t*) pThis), "...", iQueueSize);
+ }
+ CHKiRet(localRet);
+
+ /* check if we should discard this element */
+ localRet = qqueueChkDiscardMsg(pThis, pThis->iQueueSize, pMsg);
+ if(localRet == RS_RET_QUEUE_FULL) {
+ ++nDiscarded;
+ continue;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ /* all well, use this element */
+ pWti->batch.pElem[nDequeued].pMsg = pMsg;
+ pWti->batch.eltState[nDequeued] = BATCH_STATE_RDY;
+ ++nDequeued;
+ if(nDequeued < iMinDeqBatchSize && getLogicalQueueSize(pThis) == 0) {
+ while(!pThis->bShutdownImmediate
+ && keep_running
+ && nDequeued < iMinDeqBatchSize
+ && getLogicalQueueSize(pThis) == 0) {
+ dbgprintf("%s minDeqBatchSize doing wait, batch is %d messages, "
+ "queue size %d\n", obj.GetName((obj_t*) pThis),
+ nDequeued, getLogicalQueueSize(pThis));
+ if(wtiWaitNonEmpty(pWti, timeout) == 0) { /* timeout? */
+ DBGPRINTF("%s minDeqBatchSize timeout, batch is %d messages\n",
+ obj.GetName((obj_t*) pThis), nDequeued);
+ keep_running = 0;
+ }
+ }
+ }
+ if(keep_running) {
+ keep_running = (getLogicalQueueSize(pThis) > 0)
+ && (nDequeued < pThis->iDeqBatchSize);
+ }
+ }
+
+ if(pThis->qType == QUEUETYPE_DISK) {
+ strm.GetCurrOffset(pThis->tVars.disk.pReadDeq, &pThis->tVars.disk.deqOffs);
+ pThis->tVars.disk.deqFileNumOut = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq);
+ }
+
+ /* it is sufficient to persist only when the bulk of work is done */
+ qqueueChkPersist(pThis, nDequeued+nDiscarded+nDeleted);
+
+ /* If messages where DISCARDED, we need to substract them from the OverallQueueSize */
+# ifdef ENABLE_IMDIAG
+# ifdef HAVE_ATOMIC_BUILTINS
+ ATOMIC_SUB(&iOverallQueueSize, nDiscarded, &NULL);
+# else
+ iOverallQueueSize -= nDiscarded; /* racy, but we can't wait for a mutex! */
+# endif
+ DBGOPRINT((obj_t*) pThis, "dequeued %d discarded %d QueueSize %d consumable elements, szlog %d sz phys %d\n",
+ nDequeued, nDiscarded, iOverallQueueSize, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+# else
+ DBGOPRINT((obj_t*) pThis, "dequeued %d discarded %d consumable elements, szlog %d sz phys %d\n",
+ nDequeued, nDiscarded, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+# endif
+
+ pWti->batch.nElem = nDequeued;
+ pWti->batch.nElemDeq = nDequeued + nDiscarded;
+ pWti->batch.deqID = getNextDeqID(pThis);
+ *piRemainingQueueSize = iQueueSize;
+finalize_it:
+ RETiRet;
+}
+
+
+/* dequeue the queued object for the queue consumers.
+ * rgerhards, 2008-10-21
+ * I made a radical change - we now dequeue multiple elements, and store these objects in
+ * an array of user pointers. We expect that this increases performance.
+ * rgerhards, 2009-04-22
+ */
+static rsRetVal
+DequeueConsumable(qqueue_t *pThis, wti_t *pWti, int *const pSkippedMsgs)
+{
+ DEFiRet;
+ int iQueueSize = 0; /* keep the compiler happy... */
+
+ *pSkippedMsgs = 0;
+ /* dequeue element batch (still protected from mutex) */
+ iRet = DequeueConsumableElements(pThis, pWti, &iQueueSize, pSkippedMsgs);
+ if(*pSkippedMsgs > 0) {
+ LogError(0, RS_RET_ERR, "%s: lost %d messages from diskqueue (invalid .qi file)",
+ obj.GetName((obj_t*)pThis), *pSkippedMsgs);
+ }
+
+ /* awake some flow-controlled sources if we can do this right now */
+ /* TODO: this could be done better from a performance point of view -- do it only if
+ * we have someone waiting for the condition (or only when we hit the watermark right
+ * on the nail [exact value]) -- rgerhards, 2008-03-14
+ * now that we dequeue batches of pointers, this is much less an issue...
+ * rgerhards, 2009-04-22
+ */
+ if(iQueueSize < pThis->iFullDlyMrk / 2 || glbl.GetGlobalInputTermState() == 1) {
+ pthread_cond_broadcast(&pThis->belowFullDlyWtrMrk);
+ }
+
+ if(iQueueSize < pThis->iLightDlyMrk / 2) {
+ pthread_cond_broadcast(&pThis->belowLightDlyWtrMrk);
+ }
+
+ pthread_cond_signal(&pThis->notFull);
+ /* WE ARE NO LONGER PROTECTED BY THE MUTEX */
+
+ if(iRet != RS_RET_OK && iRet != RS_RET_DISCARDMSG) {
+ LogError(0, iRet, "%s: error dequeueing element - ignoring, "
+ "but strange things may happen", obj.GetName((obj_t*)pThis));
+ }
+
+ RETiRet;
+}
+
+
+/* The rate limiter
+ *
+ * IMPORTANT: the rate-limiter MUST unlock and re-lock the queue when
+ * it actually delays processing. Otherwise inputs are stalled.
+ *
+ * Here we may wait if a dequeue time window is defined or if we are
+ * rate-limited. TODO: If we do so, we should also look into the
+ * way new worker threads are spawned. Obviously, it doesn't make much
+ * sense to spawn additional worker threads when none of them can do any
+ * processing. However, it is deemed acceptable to allow this for an initial
+ * implementation of the timeframe/rate limiting feature.
+ * Please also note that these feature could also be implemented at the action
+ * level. However, that would limit them to be used together with actions. We have
+ * taken the broader approach, moving it right into the queue. This is even
+ * necessary if we want to prevent spawning of multiple unnecessary worker
+ * threads as described above. -- rgerhards, 2008-04-02
+ *
+ *
+ * time window: tCurr is current time; tFrom is start time, tTo is end time (in mil 24h format).
+ * We may have tFrom = 4, tTo = 10 --> run from 4 to 10 hrs. nice and happy
+ * we may also have tFrom= 22, tTo = 4 -> run from 10pm to 4am, which is actually two
+ * windows: 0-4; 22-23:59
+ * so when to run? Let's assume we have 3am
+ *
+ * if(tTo < tFrom) {
+ * if(tCurr < tTo [3 < 4] || tCurr > tFrom [3 > 22])
+ * do work
+ * else
+ * sleep for tFrom - tCurr "hours" [22 - 5 --> 17]
+ * } else {
+ * if(tCurr >= tFrom [3 >= 4] && tCurr < tTo [3 < 10])
+ * do work
+ * else
+ * sleep for tTo - tCurr "hours" [4 - 3 --> 1]
+ * }
+ *
+ * Bottom line: we need to check which type of window we have and need to adjust our
+ * logic accordingly. Of course, sleep calculations need to be done up to the minute,
+ * but you get the idea from the code above.
+ */
+static rsRetVal
+RateLimiter(qqueue_t *pThis)
+{
+ DEFiRet;
+ int iDelay;
+ int iHrCurr;
+ time_t tCurr;
+ struct tm m;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ iDelay = 0;
+ if(pThis->iDeqtWinToHr != 25) { /* 25 means disabled */
+ /* time calls are expensive, so only do them when needed */
+ datetime.GetTime(&tCurr);
+ localtime_r(&tCurr, &m);
+ iHrCurr = m.tm_hour;
+
+ if(pThis->iDeqtWinToHr < pThis->iDeqtWinFromHr) {
+ if(iHrCurr < pThis->iDeqtWinToHr || iHrCurr > pThis->iDeqtWinFromHr) {
+ ; /* do not delay */
+ } else {
+ iDelay = (pThis->iDeqtWinFromHr - iHrCurr) * 3600;
+ /* this time, we are already into the next hour, so we need
+ * to subtract our current minute and seconds.
+ */
+ iDelay -= m.tm_min * 60;
+ iDelay -= m.tm_sec;
+ }
+ } else {
+ if(iHrCurr >= pThis->iDeqtWinFromHr && iHrCurr < pThis->iDeqtWinToHr) {
+ ; /* do not delay */
+ } else {
+ if(iHrCurr < pThis->iDeqtWinFromHr) {
+ iDelay = (pThis->iDeqtWinFromHr - iHrCurr - 1) * 3600;
+ /* -1 as we are already in the hour */
+ iDelay += (60 - m.tm_min) * 60;
+ iDelay += 60 - m.tm_sec;
+ } else {
+ iDelay = (24 - iHrCurr + pThis->iDeqtWinFromHr) * 3600;
+ /* this time, we are already into the next hour, so we need
+ * to subtract our current minute and seconds.
+ */
+ iDelay -= m.tm_min * 60;
+ iDelay -= m.tm_sec;
+ }
+ }
+ }
+ }
+
+ if(iDelay > 0) {
+ pthread_mutex_unlock(pThis->mut);
+ DBGOPRINT((obj_t*) pThis, "outside dequeue time window, delaying %d seconds\n", iDelay);
+ srSleep(iDelay, 0);
+ pthread_mutex_lock(pThis->mut);
+ }
+
+ RETiRet;
+}
+
+
+/* This dequeues the next batch. Note that this function must not be
+ * cancelled, else it will leave back an inconsistent state.
+ * rgerhards, 2009-05-20
+ */
+static rsRetVal
+DequeueForConsumer(qqueue_t *pThis, wti_t *pWti, int *const pSkippedMsgs)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ ISOBJ_TYPE_assert(pWti, wti);
+
+ CHKiRet(DequeueConsumable(pThis, pWti, pSkippedMsgs));
+
+ if(pWti->batch.nElem == 0)
+ ABORT_FINALIZE(RS_RET_IDLE);
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This is called when a batch is processed and the worker does not
+ * ask for another batch (e.g. because it is to be terminated)
+ * Note that we must not be terminated while we delete a processed
+ * batch. Otherwise, we may not complete it, and then the cancel
+ * handler also tries to delete the batch. But then it finds some of
+ * the messages already destructed. This was a bug we have seen, especially
+ * with disk mode, where a delete takes rather long. Anyhow, the coneptual
+ * problem exists in all queue modes.
+ * rgerhards, 2009-05-27
+ */
+static rsRetVal
+batchProcessed(qqueue_t *pThis, wti_t *pWti)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ ISOBJ_TYPE_assert(pWti, wti);
+
+ int iCancelStateSave;
+ /* at this spot, we must not be cancelled */
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ DeleteProcessedBatch(pThis, &pWti->batch);
+ qqueueChkPersist(pThis, pWti->batch.nElemDeq);
+ pthread_setcancelstate(iCancelStateSave, NULL);
+
+ RETiRet;
+}
+
+
+/* This is the queue consumer in the regular (non-DA) case. It is
+ * protected by the queue mutex, but MUST release it as soon as possible.
+ * rgerhards, 2008-01-21
+ */
+static rsRetVal
+ConsumerReg(qqueue_t *pThis, wti_t *pWti)
+{
+ int iCancelStateSave;
+ int bNeedReLock = 0; /**< do we need to lock the mutex again? */
+ int skippedMsgs = 0; /**< did the queue loose any messages (can happen with
+ ** disk queue if .qi file is corrupt */
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ ISOBJ_TYPE_assert(pWti, wti);
+
+ iRet = DequeueForConsumer(pThis, pWti, &skippedMsgs);
+ if(iRet == RS_RET_FILE_NOT_FOUND) {
+ /* This is a fatal condition and means the queue is almost unusable */
+ d_pthread_mutex_unlock(pThis->mut);
+ DBGOPRINT((obj_t*) pThis, "got 'file not found' error %d, queue defunct\n", iRet);
+ iRet = queueSwitchToEmergencyMode(pThis, iRet);
+ // TODO: think about what to return as iRet -- keep RS_RET_FILE_NOT_FOUND?
+ d_pthread_mutex_lock(pThis->mut);
+ }
+ if (iRet != RS_RET_OK) {
+ FINALIZE;
+ }
+
+ /* we now have a non-idle batch of work, so we can release the queue mutex and process it */
+ d_pthread_mutex_unlock(pThis->mut);
+ bNeedReLock = 1;
+
+ /* report errors, now that we are outside of queue lock */
+ if(skippedMsgs > 0) {
+ LogError(0, 0, "problem on disk queue '%s': "
+ "queue files contain %d messages fewer than specified "
+ "in .qi file -- we lost those messages. That's all we know.",
+ obj.GetName((obj_t*) pThis), skippedMsgs);
+ }
+
+ /* at this spot, we may be cancelled */
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &iCancelStateSave);
+
+
+ pWti->pbShutdownImmediate = &pThis->bShutdownImmediate;
+ CHKiRet(pThis->pConsumer(pThis->pAction, &pWti->batch, pWti));
+
+ /* we now need to check if we should deliberately delay processing a bit
+ * and, if so, do that. -- rgerhards, 2008-01-30
+ */
+ if(pThis->iDeqSlowdown) {
+ DBGOPRINT((obj_t*) pThis, "sleeping %d microseconds as requested by config params\n",
+ pThis->iDeqSlowdown);
+ srSleep(pThis->iDeqSlowdown / 1000000, pThis->iDeqSlowdown % 1000000);
+ }
+
+ /* but now cancellation is no longer permitted */
+ pthread_setcancelstate(iCancelStateSave, NULL);
+
+finalize_it:
+ DBGPRINTF("regular consumer finished, iret=%d, szlog %d sz phys %d\n", iRet,
+ getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+
+ /* now we are done, but potentially need to re-acquire the mutex */
+ if(bNeedReLock)
+ d_pthread_mutex_lock(pThis->mut);
+
+ RETiRet;
+}
+
+
+/* This is a special consumer to feed the disk-queue in disk-assisted mode.
+ * When active, our own queue more or less acts as a memory buffer to the disk.
+ * So this consumer just needs to drain the memory queue and submit entries
+ * to the disk queue. The disk queue will then call the actual consumer from
+ * the app point of view (we chain two queues here).
+ * When this method is entered, the mutex is always locked and needs to be unlocked
+ * as part of the processing.
+ * rgerhards, 2008-01-14
+ */
+static rsRetVal
+ConsumerDA(qqueue_t *pThis, wti_t *pWti)
+{
+ int i;
+ int iCancelStateSave;
+ int bNeedReLock = 0; /**< do we need to lock the mutex again? */
+ int skippedMsgs = 0;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ ISOBJ_TYPE_assert(pWti, wti);
+
+ CHKiRet(DequeueForConsumer(pThis, pWti, &skippedMsgs));
+
+ /* we now have a non-idle batch of work, so we can release the queue mutex and process it */
+ d_pthread_mutex_unlock(pThis->mut);
+ bNeedReLock = 1;
+
+ /* at this spot, we may be cancelled */
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &iCancelStateSave);
+
+ /* iterate over returned results and enqueue them in DA queue */
+ for(i = 0 ; i < pWti->batch.nElem && !pThis->bShutdownImmediate ; i++) {
+ iRet = qqueueEnqMsg(pThis->pqDA, eFLOWCTL_NO_DELAY, MsgAddRef(pWti->batch.pElem[i].pMsg));
+ if(iRet != RS_RET_OK) {
+ if(iRet == RS_RET_ERR_QUEUE_EMERGENCY) {
+ /* Queue emergency error occurred */
+ DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg caught RS_RET_ERR_QUEUE_EMERGENCY,"
+ "aborting loop.\n");
+ FINALIZE;
+ } else {
+ DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg item (%d) returned "
+ "with error state: '%d'\n", i, iRet);
+ }
+ }
+ pWti->batch.eltState[i] = BATCH_STATE_COMM; /* commited to other queue! */
+ }
+
+ /* but now cancellation is no longer permitted */
+ pthread_setcancelstate(iCancelStateSave, NULL);
+
+finalize_it:
+ /* Check the last return state of qqueueEnqMsg. If an error was returned, we acknowledge it only.
+ * Unless the error code is RS_RET_ERR_QUEUE_EMERGENCY, we reset the return state to RS_RET_OK.
+ * Otherwise the Caller functions would run into an infinite Loop trying to enqueue the
+ * same messages over and over again.
+ *
+ * However we do NOT overwrite positive return states like
+ * RS_RET_TERMINATE_NOW,
+ * RS_RET_NO_RUN,
+ * RS_RET_IDLE,
+ * RS_RET_TERMINATE_WHEN_IDLE
+ * These return states are important for Queue handling of the upper laying functions.
+ * RGer: Note that checking for iRet < 0 is a bit bold. In theory, positive iRet
+ * values are "OK" states, and things that the caller shall deal with. However,
+ * this has not been done so consistently. Andre convinced me that the current
+ * code is an elegant solution. However, if problems with queue workers and/or
+ * shutdown come up, this code here should be looked at suspiciously. In those
+ * cases it may work out to check all status codes explicitely, just to avoid
+ * a pitfall due to unexpected states being passed on to the caller.
+ */
+ if( iRet != RS_RET_OK &&
+ iRet != RS_RET_ERR_QUEUE_EMERGENCY &&
+ iRet < 0) {
+ DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg Resetting iRet from %d back to RS_RET_OK\n", iRet);
+ iRet = RS_RET_OK;
+ } else {
+ DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg returns with iRet %d\n", iRet);
+ }
+
+ /* now we are done, but potentially need to re-acquire the mutex */
+ if(bNeedReLock)
+ d_pthread_mutex_lock(pThis->mut);
+
+ RETiRet;
+}
+
+
+/* must only be called when the queue mutex is locked, else results
+ * are not stable!
+ */
+static rsRetVal
+qqueueChkStopWrkrDA(qqueue_t *pThis)
+{
+ DEFiRet;
+
+ DBGPRINTF("rger: chkStopWrkrDA called, low watermark %d, log Size %d, phys Size %d, bEnqOnly %d\n",
+ pThis->iLowWtrMrk, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->bEnqOnly);
+ if(pThis->bEnqOnly) {
+ iRet = RS_RET_TERMINATE_WHEN_IDLE;
+ }
+ if(getPhysicalQueueSize(pThis) <= pThis->iLowWtrMrk) {
+ iRet = RS_RET_TERMINATE_NOW;
+ }
+
+ RETiRet;
+}
+
+
+/* must only be called when the queue mutex is locked, else results
+ * are not stable!
+ * If we are a child, we have done our duty when the queue is empty. In that case,
+ * we can terminate. Version for the regular worker thread.
+ */
+static rsRetVal
+ChkStopWrkrReg(qqueue_t *pThis)
+{
+ DEFiRet;
+ /*DBGPRINTF("XXXX: chkStopWrkrReg called, low watermark %d, log Size %d, phys Size %d, bEnqOnly %d\n",
+ pThis->iLowWtrMrk, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->bEnqOnly);*/
+ if(pThis->bEnqOnly) {
+ iRet = RS_RET_TERMINATE_NOW;
+ } else if(pThis->pqParent != NULL) {
+ iRet = RS_RET_TERMINATE_WHEN_IDLE;
+ }
+
+ RETiRet;
+}
+
+
+/* return the configured "deq max at once" interval
+ * rgerhards, 2009-04-22
+ */
+static rsRetVal
+GetDeqBatchSize(qqueue_t *pThis, int *pVal)
+{
+ DEFiRet;
+ assert(pVal != NULL);
+ *pVal = pThis->iDeqBatchSize;
+ RETiRet;
+}
+
+
+/* start up the queue - it must have been constructed and parameters defined
+ * before.
+ */
+rsRetVal
+qqueueStart(rsconf_t *cnf, qqueue_t *pThis) /* this is the ConstructionFinalizer */
+{
+ DEFiRet;
+ uchar pszBuf[64];
+ uchar pszQIFNam[MAXFNAME];
+ int wrk;
+ uchar *qName;
+ size_t lenBuf;
+
+ assert(pThis != NULL);
+
+ /* do not modify the queue if it's already running(happens when dynamic config reload is invoked
+ * and the queue is used in the new config as well)
+ */
+ if (pThis->isRunning)
+ FINALIZE;
+
+ dbgoprint((obj_t*) pThis, "starting queue\n");
+
+ if(pThis->pszSpoolDir == NULL) {
+ /* note: we need to pick the path so late as we do not have
+ * the workdir during early config load
+ */
+ if((pThis->pszSpoolDir = (uchar*) strdup((char*)glbl.GetWorkDir(cnf))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ pThis->lenSpoolDir = ustrlen(pThis->pszSpoolDir);
+ }
+ /* set type-specific handlers and other very type-specific things
+ * (we can not totally hide it...)
+ */
+ switch(pThis->qType) {
+ case QUEUETYPE_FIXED_ARRAY:
+ pThis->qConstruct = qConstructFixedArray;
+ pThis->qDestruct = qDestructFixedArray;
+ pThis->qAdd = qAddFixedArray;
+ pThis->qDeq = qDeqFixedArray;
+ pThis->qDel = qDelFixedArray;
+ pThis->MultiEnq = qqueueMultiEnqObjNonDirect;
+ break;
+ case QUEUETYPE_LINKEDLIST:
+ pThis->qConstruct = qConstructLinkedList;
+ pThis->qDestruct = qDestructLinkedList;
+ pThis->qAdd = qAddLinkedList;
+ pThis->qDeq = qDeqLinkedList;
+ pThis->qDel = qDelLinkedList;
+ pThis->MultiEnq = qqueueMultiEnqObjNonDirect;
+ break;
+ case QUEUETYPE_DISK:
+ pThis->qConstruct = qConstructDisk;
+ pThis->qDestruct = qDestructDisk;
+ pThis->qAdd = qAddDisk;
+ pThis->qDeq = qDeqDisk;
+ pThis->qDel = NULL; /* delete for disk handled via special code! */
+ pThis->MultiEnq = qqueueMultiEnqObjNonDirect;
+ /* pre-construct file name for .qi file */
+ pThis->lenQIFNam = snprintf((char*)pszQIFNam, sizeof(pszQIFNam),
+ "%s/%s.qi", (char*) pThis->pszSpoolDir, (char*)pThis->pszFilePrefix);
+ pThis->pszQIFNam = ustrdup(pszQIFNam);
+ DBGOPRINT((obj_t*) pThis, ".qi file name is '%s', len %d\n", pThis->pszQIFNam,
+ (int) pThis->lenQIFNam);
+ break;
+ case QUEUETYPE_DIRECT:
+ pThis->qConstruct = qConstructDirect;
+ pThis->qDestruct = qDestructDirect;
+ /* these entry points shall not be used in direct mode
+ * To catch program errors, make us abort if that happens!
+ * rgerhards, 2013-11-05
+ */
+ pThis->qAdd = qAddDirect;
+ pThis->MultiEnq = qqueueMultiEnqObjDirect;
+ pThis->qDel = NULL;
+ break;
+ }
+
+ /* finalize some initializations that could not yet be done because it is
+ * influenced by properties which might have been set after queueConstruct ()
+ */
+ if(pThis->pqParent == NULL) {
+ CHKmalloc(pThis->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)));
+ pthread_mutex_init(pThis->mut, NULL);
+ } else {
+ /* child queue, we need to use parent's mutex */
+ DBGOPRINT((obj_t*) pThis, "I am a child\n");
+ pThis->mut = pThis->pqParent->mut;
+ }
+
+ pthread_mutex_init(&pThis->mutThrdMgmt, NULL);
+ pthread_cond_init (&pThis->notFull, NULL);
+ pthread_cond_init (&pThis->belowFullDlyWtrMrk, NULL);
+ pthread_cond_init (&pThis->belowLightDlyWtrMrk, NULL);
+
+ /* call type-specific constructor */
+ CHKiRet(pThis->qConstruct(pThis)); /* this also sets bIsDA */
+
+ /* re-adjust some params if required */
+ if(pThis->bIsDA) {
+ /* if we are in DA mode, we must make sure full delayable messages do not
+ * initiate going to disk!
+ */
+ wrk = pThis->iHighWtrMrk - (pThis->iHighWtrMrk / 100) * 50; /* 50% of high water mark */
+ if(wrk < pThis->iFullDlyMrk)
+ pThis->iFullDlyMrk = wrk;
+ }
+
+ DBGOPRINT((obj_t*) pThis, "params: type %d, enq-only %d, disk assisted %d, spoolDir '%s', maxFileSz %lld, "
+ "maxQSize %d, lqsize %d, pqsize %d, child %d, full delay %d, "
+ "light delay %d, deq batch size %d, min deq batch size %d, "
+ "high wtrmrk %d, low wtrmrk %d, "
+ "discardmrk %d, max wrkr %d, min msgs f. wrkr %d "
+ "takeFlowCtlFromMsg %d\n",
+ pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->pszSpoolDir,
+ pThis->iMaxFileSize, pThis->iMaxQueueSize,
+ getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis),
+ pThis->pqParent == NULL ? 0 : 1, pThis->iFullDlyMrk, pThis->iLightDlyMrk,
+ pThis->iDeqBatchSize, pThis->iMinDeqBatchSize, pThis->iHighWtrMrk, pThis->iLowWtrMrk,
+ pThis->iDiscardMrk, (int) pThis->iNumWorkerThreads, (int) pThis->iMinMsgsPerWrkr,
+ pThis->takeFlowCtlFromMsg);
+
+ pThis->bQueueStarted = 1;
+ if(pThis->qType == QUEUETYPE_DIRECT)
+ FINALIZE; /* with direct queues, we are already finished... */
+
+ /* create worker thread pools for regular and DA operation.
+ */
+ lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%.*s:Reg",
+ (int) (sizeof(pszBuf)-16),
+ obj.GetName((obj_t*) pThis)); /* leave some room inside the name for suffixes */
+ if(lenBuf >= sizeof(pszBuf)) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "%s:%d debug header too long: %zd - in "
+ "thory this cannot happen - truncating", __FILE__, __LINE__, lenBuf);
+ lenBuf = sizeof(pszBuf)-1;
+ pszBuf[lenBuf] = '\0';
+ }
+ CHKiRet(wtpConstruct (&pThis->pWtpReg));
+ CHKiRet(wtpSetDbgHdr (pThis->pWtpReg, pszBuf, lenBuf));
+ CHKiRet(wtpSetpfRateLimiter (pThis->pWtpReg, (rsRetVal (*)(void *pUsr)) RateLimiter));
+ CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int)) ChkStopWrkrReg));
+ CHKiRet(wtpSetpfGetDeqBatchSize (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int*)) GetDeqBatchSize));
+ CHKiRet(wtpSetpfDoWork (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, void *pWti)) ConsumerReg));
+ CHKiRet(wtpSetpfObjProcessed (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, wti_t *pWti)) batchProcessed));
+ CHKiRet(wtpSetpmutUsr (pThis->pWtpReg, pThis->mut));
+ CHKiRet(wtpSetiNumWorkerThreads (pThis->pWtpReg, pThis->iNumWorkerThreads));
+ CHKiRet(wtpSettoWrkShutdown (pThis->pWtpReg, pThis->toWrkShutdown));
+ CHKiRet(wtpSetpUsr (pThis->pWtpReg, pThis));
+ CHKiRet(wtpConstructFinalize (pThis->pWtpReg));
+
+ /* set up DA system if we have a disk-assisted queue */
+ if(pThis->bIsDA)
+ InitDA(pThis, LOCK_MUTEX); /* initiate DA mode */
+
+ DBGOPRINT((obj_t*) pThis, "queue finished initialization\n");
+
+ /* if the queue already contains data, we need to start the correct number of worker threads. This can be
+ * the case when a disk queue has been loaded. If we did not start it here, it would never start.
+ */
+ qqueueAdviseMaxWorkers(pThis);
+
+ /* support statistics gathering */
+ qName = obj.GetName((obj_t*)pThis);
+ CHKiRet(statsobj.Construct(&pThis->statsobj));
+ CHKiRet(statsobj.SetName(pThis->statsobj, qName));
+ CHKiRet(statsobj.SetOrigin(pThis->statsobj, (uchar*)"core.queue"));
+ /* we need to save the queue size, as the stats module initializes it to 0! */
+ /* iQueueSize is a dual-use counter: no init, no mutex! */
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("size"),
+ ctrType_Int, CTR_FLAG_NONE, &pThis->iQueueSize));
+
+ STATSCOUNTER_INIT(pThis->ctrEnqueued, pThis->mutCtrEnqueued);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("enqueued"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrEnqueued));
+
+ STATSCOUNTER_INIT(pThis->ctrFull, pThis->mutCtrFull);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("full"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFull));
+
+ STATSCOUNTER_INIT(pThis->ctrFDscrd, pThis->mutCtrFDscrd);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("discarded.full"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFDscrd));
+ STATSCOUNTER_INIT(pThis->ctrNFDscrd, pThis->mutCtrNFDscrd);
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("discarded.nf"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrNFDscrd));
+
+ pThis->ctrMaxqsize = 0; /* no mutex needed, thus no init call */
+ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("maxqsize"),
+ ctrType_Int, CTR_FLAG_NONE, &pThis->ctrMaxqsize));
+
+ CHKiRet(statsobj.ConstructFinalize(pThis->statsobj));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* note: a child uses it's parent mutex, so do not delete it! */
+ if(pThis->pqParent == NULL && pThis->mut != NULL)
+ free(pThis->mut);
+ } else {
+ pThis->isRunning = 1;
+ }
+ RETiRet;
+}
+
+
+/* persist the queue to disk (write the .qi file). If we have something to persist, we first
+ * save the information on the queue properties itself and then we call
+ * the queue-type specific drivers.
+ * Variable bIsCheckpoint is set to 1 if the persist is for a checkpoint,
+ * and 0 otherwise.
+ * rgerhards, 2008-01-10
+ */
+static rsRetVal
+qqueuePersist(qqueue_t *pThis, int bIsCheckpoint)
+{
+ DEFiRet;
+ char *tmpQIFName = NULL;
+ strm_t *psQIF = NULL; /* Queue Info File */
+ char errStr[1024];
+
+ assert(pThis != NULL);
+
+ if(pThis->qType != QUEUETYPE_DISK) {
+ if(getPhysicalQueueSize(pThis) > 0) {
+ /* This error code is OK, but we will probably not implement this any time
+ * The reason is that persistence happens via DA queues. But I would like to
+ * leave the code as is, as we so have a hook in case we need one.
+ * -- rgerhards, 2008-01-28
+ */
+ ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
+ } else
+ FINALIZE; /* if the queue is empty, we are happy and done... */
+ }
+
+ DBGOPRINT((obj_t*) pThis, "persisting queue to disk, %d entries...\n", getPhysicalQueueSize(pThis));
+
+ if((bIsCheckpoint != QUEUE_CHECKPOINT) && (getPhysicalQueueSize(pThis) == 0)) {
+ if(pThis->bNeedDelQIF) {
+ unlink((char*)pThis->pszQIFNam);
+ pThis->bNeedDelQIF = 0;
+ }
+ /* indicate spool file needs to be deleted */
+ if(pThis->tVars.disk.pReadDel != NULL) /* may be NULL if we had a startup failure! */
+ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 1));
+ FINALIZE; /* nothing left to do, so be happy */
+ }
+
+ int lentmpQIFName;
+#ifdef _AIX
+ lentmpQIFName = strlen( pThis->pszQIFNam) + strlen(".tmp") + 1;
+ tmpQIFName = malloc(sizeof(char)*lentmpQIFName);
+ if(tmpQIFName == NULL)
+ tmpQIFName = (char*)pThis->pszQIFNam;
+ snprintf(tmpQIFName, lentmpQIFName, "%s.tmp", pThis->pszQIFNam);
+#else
+ lentmpQIFName = asprintf((char **)&tmpQIFName, "%s.tmp", pThis->pszQIFNam);
+ if(tmpQIFName == NULL)
+ tmpQIFName = (char*)pThis->pszQIFNam;
+#endif
+
+ CHKiRet(strm.Construct(&psQIF));
+ CHKiRet(strm.SettOperationsMode(psQIF, STREAMMODE_WRITE_TRUNC));
+ CHKiRet(strm.SetbSync(psQIF, pThis->bSyncQueueFiles));
+ CHKiRet(strm.SetsType(psQIF, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetFName(psQIF, (uchar*) tmpQIFName, lentmpQIFName));
+ CHKiRet(strm.ConstructFinalize(psQIF));
+
+ /* first, write the property bag for ourselfs
+ * And, surprisingly enough, we currently need to persist only the size of the
+ * queue. All the rest is re-created with then-current config parameters when the
+ * queue is re-created. Well, we'll also save the current queue type, just so that
+ * we know when somebody has changed the queue type... -- rgerhards, 2008-01-11
+ */
+ CHKiRet(obj.BeginSerializePropBag(psQIF, (obj_t*) pThis));
+ objSerializeSCALAR(psQIF, iQueueSize, INT);
+ objSerializeSCALAR(psQIF, tVars.disk.sizeOnDisk, INT64);
+ CHKiRet(obj.EndSerialize(psQIF));
+
+ /* now persist the stream info */
+ if(pThis->tVars.disk.pWrite != NULL)
+ CHKiRet(strm.Serialize(pThis->tVars.disk.pWrite, psQIF));
+ if(pThis->tVars.disk.pReadDel != NULL)
+ CHKiRet(strm.Serialize(pThis->tVars.disk.pReadDel, psQIF));
+
+ strm.Destruct(&psQIF);
+ if(tmpQIFName != (char*)pThis->pszQIFNam) { /* pointer, not string comparison! */
+ if(rename(tmpQIFName, (char*)pThis->pszQIFNam) != 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ DBGOPRINT((obj_t*) pThis,
+ "FATAL error: renaming temporary .qi file failed: %s\n",
+ errStr);
+ ABORT_FINALIZE(RS_RET_RENAME_TMP_QI_ERROR);
+ }
+ }
+
+ /* tell the input file object that it must not delete the file on close if the queue
+ * is non-empty - but only if we are not during a simple checkpoint
+ */
+ if(bIsCheckpoint != QUEUE_CHECKPOINT
+ && pThis->tVars.disk.pReadDel != NULL) {
+ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 0));
+ }
+
+ /* we have persisted the queue object. So whenever it comes to an empty queue,
+ * we need to delete the QIF. Thus, we indicte that need.
+ */
+ pThis->bNeedDelQIF = 1;
+
+finalize_it:
+ if(tmpQIFName != (char*)pThis->pszQIFNam) /* pointer, not string comparison! */
+ free(tmpQIFName);
+ if(psQIF != NULL)
+ strm.Destruct(&psQIF);
+
+ RETiRet;
+}
+
+
+/* check if we need to persist the current queue info. If an
+ * error occurs, this should be ignored by caller (but we still
+ * abide to our regular call interface)...
+ * rgerhards, 2008-01-13
+ * nUpdates is the number of updates since the last call to this function.
+ * It may be > 1 due to batches. -- rgerhards, 2009-05-12
+ */
+static rsRetVal qqueueChkPersist(qqueue_t *const pThis, const int nUpdates)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(nUpdates >= 0);
+
+ if(nUpdates == 0)
+ FINALIZE;
+
+ pThis->iUpdsSincePersist += nUpdates;
+ if(pThis->iPersistUpdCnt && pThis->iUpdsSincePersist >= pThis->iPersistUpdCnt) {
+ qqueuePersist(pThis, QUEUE_CHECKPOINT);
+ pThis->iUpdsSincePersist = 0;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* persist a queue with all data elements to disk - this is used to handle
+ * bSaveOnShutdown. We utilize the DA worker to do this. This must only
+ * be called after all workers have been shut down and if bSaveOnShutdown
+ * is actually set. Note that this function may potentially run long,
+ * depending on the queue configuration (e.g. store on remote machine).
+ * rgerhards, 2009-05-26
+ */
+static rsRetVal
+DoSaveOnShutdown(qqueue_t *pThis)
+{
+ struct timespec tTimeout;
+ rsRetVal iRetLocal;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ /* we reduce the low water mark, otherwise the DA worker would terminate when
+ * it is reached.
+ */
+ DBGOPRINT((obj_t*) pThis, "bSaveOnShutdown set, restarting DA worker...\n");
+ pThis->bShutdownImmediate = 0; /* would termiante the DA worker! */
+ pThis->iLowWtrMrk = 0;
+ wtpSetState(pThis->pWtpDA, wtpState_SHUTDOWN); /* shutdown worker (only) when done (was _IMMEDIATE!) */
+ wtpAdviseMaxWorkers(pThis->pWtpDA, 1, PERMIT_WORKER_START_DURING_SHUTDOWN); /* restart DA worker */
+
+ DBGOPRINT((obj_t*) pThis, "waiting for DA worker to terminate...\n");
+ timeoutComp(&tTimeout, QUEUE_TIMEOUT_ETERNAL);
+ /* and run the primary queue's DA worker to drain the queue */
+ iRetLocal = wtpShutdownAll(pThis->pWtpDA, wtpState_SHUTDOWN, &tTimeout);
+ DBGOPRINT((obj_t*) pThis, "end queue persistence run, iRet %d, queue size log %d, phys %d\n",
+ iRetLocal, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis));
+ if(iRetLocal != RS_RET_OK) {
+ DBGOPRINT((obj_t*) pThis, "unexpected iRet state %d after trying to shut down primary "
+ "queue in disk save mode, continuing, but results are unpredictable\n", iRetLocal);
+ }
+
+ RETiRet;
+}
+
+
+/* destructor for the queue object */
+BEGINobjDestruct(qqueue) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(qqueue)
+ DBGOPRINT((obj_t*) pThis, "shutdown: begin to destruct queue\n");
+ if(ourConf->globals.shutdownQueueDoubleSize) {
+ pThis->iHighWtrMrk *= 2;
+ pThis->iMaxQueueSize *= 2;
+ }
+ if(pThis->bQueueStarted) {
+ /* shut down all workers
+ * We do not need to shutdown workers when we are in enqueue-only mode or we are a
+ * direct queue - because in both cases we have none... ;)
+ * with a child! -- rgerhards, 2008-01-28
+ */
+ if(pThis->qType != QUEUETYPE_DIRECT && !pThis->bEnqOnly && pThis->pqParent == NULL
+ && pThis->pWtpReg != NULL)
+ qqueueShutdownWorkers(pThis);
+
+ if(pThis->bIsDA && getPhysicalQueueSize(pThis) > 0){
+ if(pThis->bSaveOnShutdown) {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO,
+ "%s: queue holds %d messages after shutdown of workers. "
+ "queue.saveonshutdown is set, so data will now be spooled to disk",
+ objGetName((obj_t*) pThis), getPhysicalQueueSize(pThis));
+ CHKiRet(DoSaveOnShutdown(pThis));
+ } else {
+ LogMsg(0, RS_RET_TIMED_OUT, LOG_WARNING,
+ "%s: queue holds %d messages after shutdown of workers. "
+ "queue.saveonshutdown is NOT set, so data will be discarded.",
+ objGetName((obj_t*) pThis), getPhysicalQueueSize(pThis));
+ }
+ }
+
+ /* finally destruct our (regular) worker thread pool
+ * Note: currently pWtpReg is never NULL, but if we optimize our logic, this may happen,
+ * e.g. when they are not created in enqueue-only mode. We already check the condition
+ * as this may otherwise be very hard to find once we optimize (and have long forgotten
+ * about this condition here ;)
+ * rgerhards, 2008-01-25
+ */
+ if(pThis->qType != QUEUETYPE_DIRECT && pThis->pWtpReg != NULL) {
+ wtpDestruct(&pThis->pWtpReg);
+ }
+
+ /* Now check if we actually have a DA queue and, if so, destruct it.
+ * Note that the wtp must be destructed first, it may be in cancel cleanup handler
+ * *right now* and actually *need* to access the queue object to persist some final
+ * data (re-queueing case). So we need to destruct the wtp first, which will make
+ * sure all workers have terminated. Please note that this also generates a situation
+ * where it is possible that the DA queue has a parent pointer but the parent has
+ * no WtpDA associated with it - which is perfectly legal thanks to this code here.
+ */
+ if(pThis->pWtpDA != NULL) {
+ wtpDestruct(&pThis->pWtpDA);
+ }
+ if(pThis->pqDA != NULL) {
+ qqueueDestruct(&pThis->pqDA);
+ }
+
+ /* persist the queue (we always do that - queuePersits() does cleanup if the queue is empty)
+ * This handler is most important for disk queues, it will finally persist the necessary
+ * on-disk structures. In theory, other queueing modes may implement their other (non-DA)
+ * methods of persisting a queue between runs, but in practice all of this is done via
+ * disk queues and DA mode. Anyhow, it doesn't hurt to know that we could extend it here
+ * if need arises (what I doubt...) -- rgerhards, 2008-01-25
+ */
+ CHKiRet_Hdlr(qqueuePersist(pThis, QUEUE_NO_CHECKPOINT)) {
+ DBGOPRINT((obj_t*) pThis, "error %d persisting queue - data lost!\n", iRet);
+ }
+
+ /* finally, clean up some simple things... */
+ if(pThis->pqParent == NULL) {
+ /* if we are not a child, we allocated our own mutex, which we now need to destroy */
+ pthread_mutex_destroy(pThis->mut);
+ free(pThis->mut);
+ }
+ pthread_mutex_destroy(&pThis->mutThrdMgmt);
+ pthread_cond_destroy(&pThis->notFull);
+ pthread_cond_destroy(&pThis->belowFullDlyWtrMrk);
+ pthread_cond_destroy(&pThis->belowLightDlyWtrMrk);
+
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutQueueSize);
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutLogDeq);
+
+ /* type-specific destructor */
+ iRet = pThis->qDestruct(pThis);
+ }
+
+ free(pThis->pszFilePrefix);
+ free(pThis->pszSpoolDir);
+ if(pThis->useCryprov) {
+ pThis->cryprov.Destruct(&pThis->cryprovData);
+ obj.ReleaseObj(__FILE__, pThis->cryprovNameFull+2, pThis->cryprovNameFull,
+ (void*) &pThis->cryprov);
+ free(pThis->cryprovName);
+ free(pThis->cryprovNameFull);
+ }
+
+ /* some queues do not provide stats and thus have no statsobj! */
+ if(pThis->statsobj != NULL)
+ statsobj.Destruct(&pThis->statsobj);
+ENDobjDestruct(qqueue)
+
+
+/* set the queue's spool directory. The directory MUST NOT be NULL.
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it.
+ */
+rsRetVal
+qqueueSetSpoolDir(qqueue_t *pThis, uchar *pszSpoolDir, int lenSpoolDir)
+{
+ DEFiRet;
+
+ free(pThis->pszSpoolDir);
+ CHKmalloc(pThis->pszSpoolDir = ustrdup(pszSpoolDir));
+ pThis->lenSpoolDir = lenSpoolDir;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the queue's file prefix
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it.
+ * rgerhards, 2008-01-09
+ */
+rsRetVal
+qqueueSetFilePrefix(qqueue_t *pThis, uchar *pszPrefix, size_t iLenPrefix)
+{
+ DEFiRet;
+
+ free(pThis->pszFilePrefix);
+ pThis->pszFilePrefix = NULL;
+
+ if(pszPrefix == NULL) /* just unset the prefix! */
+ ABORT_FINALIZE(RS_RET_OK);
+
+ if((pThis->pszFilePrefix = malloc(iLenPrefix + 1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ memcpy(pThis->pszFilePrefix, pszPrefix, iLenPrefix + 1);
+ pThis->lenFilePrefix = iLenPrefix;
+
+finalize_it:
+ RETiRet;
+}
+
+/* set the queue's maximum file size
+ * rgerhards, 2008-01-09
+ */
+rsRetVal
+qqueueSetMaxFileSize(qqueue_t *pThis, size_t iMaxFileSize)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ if(iMaxFileSize < 1024) {
+ ABORT_FINALIZE(RS_RET_VALUE_TOO_LOW);
+ }
+
+ pThis->iMaxFileSize = iMaxFileSize;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* enqueue a single data object.
+ * Note that the queue mutex MUST already be locked when this function is called.
+ * rgerhards, 2009-06-16
+ */
+static rsRetVal
+doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg)
+{
+ DEFiRet;
+ int err;
+ struct timespec t;
+
+ STATSCOUNTER_INC(pThis->ctrEnqueued, pThis->mutCtrEnqueued);
+ /* first check if we need to discard this message (which will cause CHKiRet() to exit)
+ */
+ CHKiRet(qqueueChkDiscardMsg(pThis, pThis->iQueueSize, pMsg));
+
+ /* handle flow control
+ * There are two different flow control mechanisms: basic and advanced flow control.
+ * Basic flow control has always been implemented and protects the queue structures
+ * in that it makes sure no more data is enqueued than the queue is configured to
+ * support. Enhanced flow control is being added today. There are some sources which
+ * can easily be stopped, e.g. a file reader. This is the case because it is unlikely
+ * that blocking those sources will have negative effects (after all, the file is
+ * continued to be written). Other sources can somewhat be blocked (e.g. the kernel
+ * log reader or the local log stream reader): in general, nothing is lost if messages
+ * from these sources are not picked up immediately. HOWEVER, they can not block for
+ * an extended period of time, as this either causes message loss or - even worse - some
+ * other bad effects (e.g. unresponsive system in respect to the main system log socket).
+ * Finally, there are some (few) sources which can not be blocked at all. UDP syslog is
+ * a prime example. If a UDP message is not received, it is simply lost. So we can't
+ * do anything against UDP sockets that come in too fast. The core idea of advanced
+ * flow control is that we take into account the different natures of the sources and
+ * select flow control mechanisms that fit these needs. This also means, in the end
+ * result, that non-blockable sources like UDP syslog receive priority in the system.
+ * It's a side effect, but a good one ;) -- rgerhards, 2008-03-14
+ */
+ if(unlikely(pThis->takeFlowCtlFromMsg)) { /* recommendation is NOT to use this option */
+ flowCtlType = pMsg->flowCtlType;
+ }
+ if(flowCtlType == eFLOWCTL_FULL_DELAY) {
+ while(pThis->iQueueSize >= pThis->iFullDlyMrk&& ! glbl.GetGlobalInputTermState()) {
+ /* We have a problem during shutdown if we block eternally. In that
+ * case, the the input thread cannot be terminated. So we wake up
+ * from time to time to check for termination.
+ * TODO/v6(at earliest): check if we could signal the condition during
+ * shutdown. However, this requires new queue registries and thus is
+ * far to much change for a stable version (and I am still not sure it
+ * is worth the effort, given how seldom this situation occurs and how
+ * few resources the wakeups need). -- rgerhards, 2012-05-03
+ * In any case, this was the old code (if we do the TODO):
+ * pthread_cond_wait(&pThis->belowFullDlyWtrMrk, pThis->mut);
+ */
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: FullDelay mark reached for full "
+ "delayable message - blocking, queue size is %d.\n", pThis->iQueueSize);
+ timeoutComp(&t, 1000);
+ err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t);
+ if(err != 0 && err != ETIMEDOUT) {
+ /* Something is really wrong now. Report to debug log and abort the
+ * wait. That keeps us running, even though we may lose messages.
+ */
+ DBGOPRINT((obj_t*) pThis, "potential program bug: pthread_cond_timedwait()"
+ "/fulldelay returned %d\n", err);
+ break;
+
+ }
+ DBGPRINTF("wti worker in full delay timed out, checking termination...\n");
+ }
+ } else if(flowCtlType == eFLOWCTL_LIGHT_DELAY && !glbl.GetGlobalInputTermState()) {
+ if(pThis->iQueueSize >= pThis->iLightDlyMrk) {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: LightDelay mark reached for light "
+ "delayable message - blocking a bit.\n");
+ timeoutComp(&t, 1000); /* 1000 millisconds = 1 second TODO: make configurable */
+ err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t);
+ if(err != 0 && err != ETIMEDOUT) {
+ /* Something is really wrong now. Report to debug log */
+ DBGOPRINT((obj_t*) pThis, "potential program bug: pthread_cond_timedwait()"
+ "/lightdelay returned %d\n", err);
+
+ }
+ }
+ }
+
+ /* from our regular flow control settings, we are now ready to enqueue the object.
+ * However, we now need to do a check if the queue permits to add more data. If that
+ * is not the case, basic flow control enters the field, which means we wait for
+ * the queue to become ready or drop the new message. -- rgerhards, 2008-03-14
+ */
+ while( (pThis->iMaxQueueSize > 0 && pThis->iQueueSize >= pThis->iMaxQueueSize)
+ || ((pThis->qType == QUEUETYPE_DISK || pThis->bIsDA) && pThis->sizeOnDiskMax != 0
+ && pThis->tVars.disk.sizeOnDisk > pThis->sizeOnDiskMax)) {
+ STATSCOUNTER_INC(pThis->ctrFull, pThis->mutCtrFull);
+ if(pThis->toEnq == 0 || pThis->bEnqOnly) {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL - configured for immediate "
+ "discarding QueueSize=%d MaxQueueSize=%d sizeOnDisk=%lld "
+ "sizeOnDiskMax=%lld\n", pThis->iQueueSize, pThis->iMaxQueueSize,
+ pThis->tVars.disk.sizeOnDisk, pThis->sizeOnDiskMax);
+ STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd);
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_QUEUE_FULL);
+ } else {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL - waiting %dms to drain.\n",
+ pThis->toEnq);
+ if(glbl.GetGlobalInputTermState()) {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL, discard due to "
+ "FORCE_TERM.\n");
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ }
+ timeoutComp(&t, pThis->toEnq);
+ const int r = pthread_cond_timedwait(&pThis->notFull, pThis->mut, &t);
+ if(dbgTimeoutToStderr && r != 0) {
+ fprintf(stderr, "%lld: queue timeout(%dms), error %d%s, "
+ "lost message %s\n", (long long) time(NULL), pThis->toEnq,
+ r, ( r == ETIMEDOUT) ? "[ETIMEDOUT]" : "", pMsg->pszRawMsg);
+ }
+ if(r == ETIMEDOUT) {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: cond timeout, dropping message!\n");
+ STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd);
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_QUEUE_FULL);
+ } else if(r != 0) {
+ DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: cond error %d, dropping message!\n", r);
+ STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd);
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_QUEUE_FULL);
+ }
+ dbgoprint((obj_t*) pThis, "doEnqSingleObject: wait solved queue full condition, enqueing\n");
+ }
+ }
+
+ /* and finally enqueue the message */
+ CHKiRet(qqueueAdd(pThis, pMsg));
+ STATSCOUNTER_SETMAX_NOMUT(pThis->ctrMaxqsize, pThis->iQueueSize);
+
+ /* check if we had a file rollover and need to persist
+ * the .qi file for robustness reasons.
+ * Note: the n=2 write is required for closing the old file and
+ * the n=1 write is required after opening and writing to the new
+ * file.
+ */
+ if(pThis->tVars.disk.nForcePersist > 0) {
+ DBGOPRINT((obj_t*) pThis, ".qi file write required for robustness reasons (n=%d)\n",
+ pThis->tVars.disk.nForcePersist);
+ pThis->tVars.disk.nForcePersist--;
+ qqueuePersist(pThis, QUEUE_CHECKPOINT);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* ------------------------------ multi-enqueue functions ------------------------------ */
+/* enqueue multiple user data elements at once. The aim is to provide a faster interface
+ * for object submission. Uses the multi_submit_t helper object.
+ * Please note that this function is not cancel-safe and consequently
+ * sets the calling thread's cancelibility state to PTHREAD_CANCEL_DISABLE
+ * during its execution. If that is not done, race conditions occur if the
+ * thread is canceled (most important use case is input module termination).
+ * rgerhards, 2009-06-16
+ * Note: there now exists multiple different functions implementing specially
+ * optimized algorithms for different config cases. -- rgerhards, 2010-06-09
+ */
+/* now the function for all modes but direct */
+static rsRetVal
+qqueueMultiEnqObjNonDirect(qqueue_t *pThis, multi_submit_t *pMultiSub)
+{
+ int iCancelStateSave;
+ int i;
+ rsRetVal localRet;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pMultiSub != NULL);
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ d_pthread_mutex_lock(pThis->mut);
+ for(i = 0 ; i < pMultiSub->nElem ; ++i) {
+ localRet = doEnqSingleObj(pThis, pMultiSub->ppMsgs[i]->flowCtlType, (void*)pMultiSub->ppMsgs[i]);
+ if(localRet != RS_RET_OK && localRet != RS_RET_QUEUE_FULL)
+ ABORT_FINALIZE(localRet);
+ }
+ qqueueChkPersist(pThis, pMultiSub->nElem);
+
+finalize_it:
+ /* make sure at least one worker is running. */
+ qqueueAdviseMaxWorkers(pThis);
+ /* and release the mutex */
+ d_pthread_mutex_unlock(pThis->mut);
+ pthread_setcancelstate(iCancelStateSave, NULL);
+ DBGOPRINT((obj_t*) pThis, "MultiEnqObj advised worker start\n");
+
+ RETiRet;
+}
+
+/* now, the same function, but for direct mode */
+static rsRetVal
+qqueueMultiEnqObjDirect(qqueue_t *pThis, multi_submit_t *pMultiSub)
+{
+ int i;
+ wti_t *pWti;
+ DEFiRet;
+
+ pWti = wtiGetDummy();
+ pWti->pbShutdownImmediate = &pThis->bShutdownImmediate;
+
+ for(i = 0 ; i < pMultiSub->nElem ; ++i) {
+ CHKiRet(qAddDirectWithWti(pThis, (void*)pMultiSub->ppMsgs[i], pWti));
+ }
+
+finalize_it:
+ RETiRet;
+}
+/* ------------------------------ END multi-enqueue functions ------------------------------ */
+
+
+/* enqueue a new user data element
+ * Enqueues the new element and awakes worker thread.
+ */
+rsRetVal
+qqueueEnqMsg(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg)
+{
+ DEFiRet;
+ int iCancelStateSave;
+ ISOBJ_TYPE_assert(pThis, qqueue);
+
+ const int isNonDirectQ = pThis->qType != QUEUETYPE_DIRECT;
+
+ if(isNonDirectQ) {
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ d_pthread_mutex_lock(pThis->mut);
+ }
+
+ CHKiRet(doEnqSingleObj(pThis, flowCtlType, pMsg));
+
+ qqueueChkPersist(pThis, 1);
+
+finalize_it:
+ if(isNonDirectQ) {
+ /* make sure at least one worker is running. */
+ qqueueAdviseMaxWorkers(pThis);
+ /* and release the mutex */
+ d_pthread_mutex_unlock(pThis->mut);
+ pthread_setcancelstate(iCancelStateSave, NULL);
+ DBGOPRINT((obj_t*) pThis, "EnqueueMsg advised worker start\n");
+ }
+
+ RETiRet;
+}
+
+
+/* are any queue params set at all? 1 - yes, 0 - no
+ * We need to evaluate the param block for this function, which is somewhat
+ * inefficient. HOWEVER, this is only done during config load, so we really
+ * don't care... -- rgerhards, 2013-05-10
+ */
+int
+queueCnfParamsSet(struct nvlst *lst)
+{
+ int r;
+ struct cnfparamvals *pvals;
+
+ pvals = nvlstGetParams(lst, &pblk, NULL);
+ r = cnfparamvalsIsSet(&pblk, pvals);
+ cnfparamvalsDestruct(pvals, &pblk);
+ return r;
+}
+
+
+static rsRetVal
+initCryprov(qqueue_t *pThis, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+ DEFiRet;
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pThis->cryprovName)
+ == sizeof(szDrvrName)) {
+ LogError(0, RS_RET_ERR, "queue: crypto provider "
+ "name is too long: '%s' - encryption disabled",
+ pThis->cryprovName);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pThis->cryprovNameFull = ustrdup(szDrvrName);
+
+ pThis->cryprov.ifVersion = cryprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pThis->cryprov)
+ != RS_RET_OK) {
+ LogError(0, RS_RET_LOAD_ERROR, "queue: could not load "
+ "crypto provider '%s' - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+
+ if(pThis->cryprov.Construct(&pThis->cryprovData) != RS_RET_OK) {
+ LogError(0, RS_RET_CRYPROV_ERR, "queue: error constructing "
+ "crypto provider %s dataset - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+ CHKiRet(pThis->cryprov.SetCnfParam(pThis->cryprovData, lst, CRYPROV_PARAMTYPE_DISK));
+
+ dbgprintf("loaded crypto provider %s, data instance at %p\n",
+ szDrvrName, pThis->cryprovData);
+ pThis->useCryprov = 1;
+finalize_it:
+ RETiRet;
+}
+
+/* check the the queue file name is unique. */
+static rsRetVal ATTR_NONNULL()
+checkUniqueDiskFile(qqueue_t *const pThis)
+{
+ DEFiRet;
+ struct queue_filename *queue_fn_curr = queue_filename_root;
+ struct queue_filename *newetry = NULL;
+ const char *const curr_dirname = (pThis->pszSpoolDir == NULL) ? "" : (char*)pThis->pszSpoolDir;
+
+ if(pThis->pszFilePrefix == NULL) {
+ FINALIZE; /* no disk queue! */
+ }
+
+ while(queue_fn_curr != NULL) {
+ if(!strcmp((const char*) pThis->pszFilePrefix, queue_fn_curr->filename) &&
+ !strcmp(curr_dirname, queue_fn_curr->dirname)) {
+ parser_errmsg("queue directory '%s' and file name prefix '%s' already used. "
+ "This is not possible. Please make it unique.",
+ curr_dirname, pThis->pszFilePrefix);
+ ABORT_FINALIZE(RS_RET_ERR_QUEUE_FN_DUP);
+ }
+ queue_fn_curr = queue_fn_curr->next;
+ }
+
+ /* name ok, so let's add it to the list */
+ CHKmalloc(newetry = calloc(1, sizeof(struct queue_filename)));
+ CHKmalloc(newetry->filename = strdup((char*) pThis->pszFilePrefix));
+ CHKmalloc(newetry->dirname = strdup(curr_dirname));
+ newetry->next = queue_filename_root;
+ queue_filename_root = newetry;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(newetry != NULL) {
+ free((void*)newetry->filename);
+ free((void*)newetry);
+ }
+ }
+ RETiRet;
+}
+
+void
+qqueueCorrectParams(qqueue_t *pThis)
+{
+ int goodval; /* a "good value" to use for comparisons (different objects) */
+
+ if(pThis->iMaxQueueSize < 100
+ && (pThis->qType == QUEUETYPE_LINKEDLIST || pThis->qType == QUEUETYPE_FIXED_ARRAY)) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "Note: queue.size=\"%d\" is very "
+ "low and can lead to unpredictable results. See also "
+ "https://www.rsyslog.com/lower-bound-for-queue-sizes/",
+ pThis->iMaxQueueSize);
+ }
+
+ /* we need to do a quick check if our water marks are set plausible. If not,
+ * we correct the most important shortcomings.
+ */
+ goodval = (pThis->iMaxQueueSize / 100) * 60;
+ if(pThis->iHighWtrMrk != -1 && pThis->iHighWtrMrk < goodval) {
+ LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": high water mark "
+ "is set quite low at %d. You should only set it below "
+ "60%% (%d) if you have a good reason for this.",
+ obj.GetName((obj_t*) pThis), pThis->iHighWtrMrk, goodval);
+ }
+
+ if(pThis->iNumWorkerThreads > 1) {
+ goodval = (pThis->iMaxQueueSize / 100) * 10;
+ if(pThis->iMinMsgsPerWrkr != -1 && pThis->iMinMsgsPerWrkr < goodval) {
+ LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": "
+ "queue.workerThreadMinimumMessage "
+ "is set quite low at %d. You should only set it below "
+ "10%% (%d) if you have a good reason for this.",
+ obj.GetName((obj_t*) pThis), pThis->iMinMsgsPerWrkr, goodval);
+ }
+ }
+
+ if(pThis->iDiscardMrk > pThis->iMaxQueueSize) {
+ LogError(0, RS_RET_PARAM_ERROR, "error: queue \"%s\": "
+ "queue.discardMark %d is set larger than queue.size",
+ obj.GetName((obj_t*) pThis), pThis->iDiscardMrk);
+ }
+
+ goodval = (pThis->iMaxQueueSize / 100) * 80;
+ if(pThis->iDiscardMrk != -1 && pThis->iDiscardMrk < goodval) {
+ LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING,
+ "queue \"%s\": queue.discardMark "
+ "is set quite low at %d. You should only set it below "
+ "80%% (%d) if you have a good reason for this.",
+ obj.GetName((obj_t*) pThis), pThis->iDiscardMrk, goodval);
+ }
+
+ if(pThis->pszFilePrefix != NULL) { /* This means we have a potential DA queue */
+ if(pThis->iFullDlyMrk != -1 && pThis->iFullDlyMrk < pThis->iHighWtrMrk) {
+ LogMsg(0, RS_RET_CONF_WRN_FULLDLY_BELOW_HIGHWTR, LOG_WARNING,
+ "queue \"%s\": queue.fullDelayMark "
+ "is set below high water mark. This will result in DA mode "
+ " NOT being activated for full delayable messages: In many "
+ "cases this is a configuration error, please check if this "
+ "is really what you want",
+ obj.GetName((obj_t*) pThis));
+ }
+ }
+
+ /* now come parameter corrections and defaults */
+ if(pThis->iHighWtrMrk < 2 || pThis->iHighWtrMrk > pThis->iMaxQueueSize) {
+ pThis->iHighWtrMrk = (pThis->iMaxQueueSize / 100) * 90;
+ if(pThis->iHighWtrMrk == 0) { /* guard against very low max queue sizes! */
+ pThis->iHighWtrMrk = pThis->iMaxQueueSize;
+ }
+ }
+ if( pThis->iLowWtrMrk < 2
+ || pThis->iLowWtrMrk > pThis->iMaxQueueSize
+ || pThis->iLowWtrMrk > pThis->iHighWtrMrk ) {
+ pThis->iLowWtrMrk = (pThis->iMaxQueueSize / 100) * 70;
+ if(pThis->iLowWtrMrk == 0) {
+ pThis->iLowWtrMrk = 1;
+ }
+ }
+
+ if((pThis->iMinMsgsPerWrkr < 1
+ || pThis->iMinMsgsPerWrkr > pThis->iMaxQueueSize) ) {
+ pThis->iMinMsgsPerWrkr = pThis->iMaxQueueSize / pThis->iNumWorkerThreads;
+ }
+
+ if(pThis->iFullDlyMrk == -1 || pThis->iFullDlyMrk > pThis->iMaxQueueSize) {
+ pThis->iFullDlyMrk = (pThis->iMaxQueueSize / 100) * 97;
+ if(pThis->iFullDlyMrk == 0) {
+ pThis->iFullDlyMrk =
+ (pThis->iMaxQueueSize == 1) ? 1 : pThis->iMaxQueueSize - 1;
+ }
+ }
+
+ if(pThis->iLightDlyMrk == 0) {
+ pThis->iLightDlyMrk = pThis->iMaxQueueSize;
+ }
+
+ if(pThis->iLightDlyMrk == -1 || pThis->iLightDlyMrk > pThis->iMaxQueueSize) {
+ pThis->iLightDlyMrk = (pThis->iMaxQueueSize / 100) * 70;
+ if(pThis->iLightDlyMrk == 0) {
+ pThis->iLightDlyMrk =
+ (pThis->iMaxQueueSize == 1) ? 1 : pThis->iMaxQueueSize - 1;
+ }
+ }
+
+ if(pThis->iDiscardMrk < 1 || pThis->iDiscardMrk > pThis->iMaxQueueSize) {
+ pThis->iDiscardMrk = (pThis->iMaxQueueSize / 100) * 98;
+ if(pThis->iDiscardMrk == 0) {
+ /* for very small queues, we disable this by default */
+ pThis->iDiscardMrk = pThis->iMaxQueueSize;
+ }
+ }
+
+ if(pThis->iMaxQueueSize > 0 && pThis->iDeqBatchSize > pThis->iMaxQueueSize) {
+ pThis->iDeqBatchSize = pThis->iMaxQueueSize;
+ }
+}
+
+/* apply all params from param block to queue. Must be called before
+ * finalizing. This supports the v6 config system. Defaults were already
+ * set during queue creation. The pvals object is destructed by this
+ * function.
+ */
+rsRetVal
+qqueueApplyCnfParam(qqueue_t *pThis, struct nvlst *lst)
+{
+ int i;
+ struct cnfparamvals *pvals;
+ int n_params_set = 0;
+ DEFiRet;
+
+ pvals = nvlstGetParams(lst, &pblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing queue config parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ if(Debug) {
+ dbgprintf("queue param blk:\n");
+ cnfparamsPrint(&pblk, pvals);
+ }
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ n_params_set++;
+ if(!strcmp(pblk.descr[i].name, "queue.filename")) {
+ pThis->pszFilePrefix = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ pThis->lenFilePrefix = es_strlen(pvals[i].val.d.estr);
+ } else if(!strcmp(pblk.descr[i].name, "queue.cry.provider")) {
+ pThis->cryprovName = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "queue.spooldirectory")) {
+ free(pThis->pszSpoolDir);
+ pThis->pszSpoolDir = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ pThis->lenSpoolDir = es_strlen(pvals[i].val.d.estr);
+ if(pThis->pszSpoolDir[pThis->lenSpoolDir-1] == '/') {
+ pThis->pszSpoolDir[pThis->lenSpoolDir-1] = '\0';
+ --pThis->lenSpoolDir;
+ parser_errmsg("queue.spooldirectory must not end with '/', "
+ "corrected to '%s'", pThis->pszSpoolDir);
+ }
+ } else if(!strcmp(pblk.descr[i].name, "queue.size")) {
+ if(pvals[i].val.d.n > 0x7fffffff) {
+ parser_warnmsg("queue.size higher than maximum (2147483647) - "
+ "corrected to maximum");
+ pvals[i].val.d.n = 0x7fffffff;
+ } else if(pvals[i].val.d.n > OVERSIZE_QUEUE_WATERMARK) {
+ parser_warnmsg("queue.size=%d is very large - is this "
+ "really intended? More info at "
+ "https://www.rsyslog.com/avoid-overly-large-in-memory-queues/",
+ (int) pvals[i].val.d.n);
+ }
+ pThis->iMaxQueueSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.dequeuebatchsize")) {
+ pThis->iDeqBatchSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.mindequeuebatchsize")) {
+ pThis->iMinDeqBatchSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.mindequeuebatchsize.timeout")) {
+ pThis->toMinDeqBatchSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.maxdiskspace")) {
+ pThis->sizeOnDiskMax = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.highwatermark")) {
+ pThis->iHighWtrMrk = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.lowwatermark")) {
+ pThis->iLowWtrMrk = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.fulldelaymark")) {
+ pThis->iFullDlyMrk = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.lightdelaymark")) {
+ pThis->iLightDlyMrk = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.discardmark")) {
+ pThis->iDiscardMrk = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.discardseverity")) {
+ pThis->iDiscardSeverity = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.checkpointinterval")) {
+ pThis->iPersistUpdCnt = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.syncqueuefiles")) {
+ pThis->bSyncQueueFiles = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.type")) {
+ pThis->qType = (queueType_t) pvals[i].val.d.n;
+ if(pThis->qType == QUEUETYPE_DIRECT) {
+ /* if we have a direct queue, we mimic this param was not set.
+ * Our prime intent is to make sure we detect when "real" params
+ * are set on a direct queue, and the type setting is obviously
+ * not relevant here.
+ */
+ n_params_set--;
+ }
+ } else if(!strcmp(pblk.descr[i].name, "queue.workerthreads")) {
+ pThis->iNumWorkerThreads = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.timeoutshutdown")) {
+ pThis->toQShutdown = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.timeoutactioncompletion")) {
+ pThis->toActShutdown = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.timeoutenqueue")) {
+ pThis->toEnq = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.timeoutworkerthreadshutdown")) {
+ pThis->toWrkShutdown = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.workerthreadminimummessages")) {
+ pThis->iMinMsgsPerWrkr = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.maxfilesize")) {
+ pThis->iMaxFileSize = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.saveonshutdown")) {
+ pThis->bSaveOnShutdown = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.dequeueslowdown")) {
+ pThis->iDeqSlowdown = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.dequeuetimebegin")) {
+ pThis->iDeqtWinFromHr = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.dequeuetimeend")) {
+ pThis->iDeqtWinToHr = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.samplinginterval")) {
+ pThis->iSmpInterval = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "queue.takeflowctlfrommsg")) {
+ pThis->takeFlowCtlFromMsg = pvals[i].val.d.n;
+ } else {
+ DBGPRINTF("queue: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+ }
+
+ checkUniqueDiskFile(pThis);
+
+ if(pThis->qType == QUEUETYPE_DIRECT) {
+ if(n_params_set > 0) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "warning on queue '%s': "
+ "queue is in direct mode, but parameters have been set. "
+ "These PARAMETERS cannot be applied and WILL BE IGNORED.",
+ obj.GetName((obj_t*) pThis));
+ }
+ } else if(pThis->qType == QUEUETYPE_DISK) {
+ if(pThis->pszFilePrefix == NULL) {
+ LogError(0, RS_RET_QUEUE_DISK_NO_FN, "error on queue '%s', disk mode selected, but "
+ "no queue file name given; queue type changed to 'linkedList'",
+ obj.GetName((obj_t*) pThis));
+ pThis->qType = QUEUETYPE_LINKEDLIST;
+ }
+ }
+
+ if(pThis->pszFilePrefix == NULL && pThis->cryprovName != NULL) {
+ LogError(0, RS_RET_QUEUE_CRY_DISK_ONLY, "error on queue '%s', crypto provider can "
+ "only be set for disk or disk assisted queue - ignored",
+ obj.GetName((obj_t*) pThis));
+ free(pThis->cryprovName);
+ pThis->cryprovName = NULL;
+ }
+
+ if(pThis->cryprovName != NULL) {
+ initCryprov(pThis, lst);
+ }
+
+ cnfparamvalsDestruct(pvals, &pblk);
+finalize_it:
+ RETiRet;
+}
+
+/* return 1 if the content of two qqueue_t structs equal */
+int
+queuesEqual(qqueue_t *pOld, qqueue_t *pNew)
+{
+ return (
+ NUM_EQUALS(qType) &&
+ NUM_EQUALS(iMaxQueueSize) &&
+ NUM_EQUALS(iDeqBatchSize) &&
+ NUM_EQUALS(iMinDeqBatchSize) &&
+ NUM_EQUALS(toMinDeqBatchSize) &&
+ NUM_EQUALS(sizeOnDiskMax) &&
+ NUM_EQUALS(iHighWtrMrk) &&
+ NUM_EQUALS(iLowWtrMrk) &&
+ NUM_EQUALS(iFullDlyMrk) &&
+ NUM_EQUALS(iLightDlyMrk) &&
+ NUM_EQUALS(iDiscardMrk) &&
+ NUM_EQUALS(iDiscardSeverity) &&
+ NUM_EQUALS(iPersistUpdCnt) &&
+ NUM_EQUALS(bSyncQueueFiles) &&
+ NUM_EQUALS(iNumWorkerThreads) &&
+ NUM_EQUALS(toQShutdown) &&
+ NUM_EQUALS(toActShutdown) &&
+ NUM_EQUALS(toEnq) &&
+ NUM_EQUALS(toWrkShutdown) &&
+ NUM_EQUALS(iMinMsgsPerWrkr) &&
+ NUM_EQUALS(iMaxFileSize) &&
+ NUM_EQUALS(bSaveOnShutdown) &&
+ NUM_EQUALS(iDeqSlowdown) &&
+ NUM_EQUALS(iDeqtWinFromHr) &&
+ NUM_EQUALS(iDeqtWinToHr) &&
+ NUM_EQUALS(iSmpInterval) &&
+ NUM_EQUALS(takeFlowCtlFromMsg) &&
+ USTR_EQUALS(pszFilePrefix) &&
+ USTR_EQUALS(cryprovName)
+ );
+}
+
+
+/* some simple object access methods */
+DEFpropSetMeth(qqueue, bSyncQueueFiles, int)
+DEFpropSetMeth(qqueue, iPersistUpdCnt, int)
+DEFpropSetMeth(qqueue, iDeqtWinFromHr, int)
+DEFpropSetMeth(qqueue, iDeqtWinToHr, int)
+DEFpropSetMeth(qqueue, toQShutdown, long)
+DEFpropSetMeth(qqueue, toActShutdown, long)
+DEFpropSetMeth(qqueue, toWrkShutdown, long)
+DEFpropSetMeth(qqueue, toEnq, long)
+DEFpropSetMeth(qqueue, iHighWtrMrk, int)
+DEFpropSetMeth(qqueue, iLowWtrMrk, int)
+DEFpropSetMeth(qqueue, iDiscardMrk, int)
+DEFpropSetMeth(qqueue, iDiscardSeverity, int)
+DEFpropSetMeth(qqueue, iLightDlyMrk, int)
+DEFpropSetMeth(qqueue, iNumWorkerThreads, int)
+DEFpropSetMeth(qqueue, iMinMsgsPerWrkr, int)
+DEFpropSetMeth(qqueue, bSaveOnShutdown, int)
+DEFpropSetMeth(qqueue, pAction, action_t*)
+DEFpropSetMeth(qqueue, iDeqSlowdown, int)
+DEFpropSetMeth(qqueue, iDeqBatchSize, int)
+DEFpropSetMeth(qqueue, iMinDeqBatchSize, int)
+DEFpropSetMeth(qqueue, sizeOnDiskMax, int64)
+DEFpropSetMeth(qqueue, iSmpInterval, int)
+
+
+/* This function can be used as a generic way to set properties. Only the subset
+ * of properties required to read persisted property bags is supported. This
+ * functions shall only be called by the property bag reader, thus it is static.
+ * rgerhards, 2008-01-11
+ */
+#define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, (uchar*) name, sizeof(name) - 1)
+static rsRetVal qqueueSetProperty(qqueue_t *pThis, var_t *pProp)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, qqueue);
+ assert(pProp != NULL);
+
+ if(isProp("iQueueSize")) {
+ pThis->iQueueSize = pProp->val.num;
+# ifdef ENABLE_IMDIAG
+ iOverallQueueSize += pThis->iQueueSize;
+# endif
+ } else if(isProp("tVars.disk.sizeOnDisk")) {
+ pThis->tVars.disk.sizeOnDisk = pProp->val.num;
+ } else if(isProp("qType")) {
+ if(pThis->qType != pProp->val.num)
+ ABORT_FINALIZE(RS_RET_QTYPE_MISMATCH);
+ }
+
+finalize_it:
+ RETiRet;
+}
+#undef isProp
+
+/* dummy */
+static rsRetVal qqueueQueryInterface(interface_t __attribute__((unused)) *i) { return RS_RET_NOT_IMPLEMENTED; }
+
+/* Initialize the stream class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-01-09
+ */
+BEGINObjClassInit(qqueue, 1, OBJ_IS_CORE_MODULE)
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ /* now set our own handlers */
+ OBJSetMethodHandler(objMethod_SETPROPERTY, qqueueSetProperty);
+ENDObjClassInit(qqueue)
diff --git a/runtime/queue.h b/runtime/queue.h
new file mode 100644
index 0000000..dd989bd
--- /dev/null
+++ b/runtime/queue.h
@@ -0,0 +1,247 @@
+/* Definition of the queue support module.
+ *
+ * Copyright 2008-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef QUEUE_H_INCLUDED
+#define QUEUE_H_INCLUDED
+
+#include <pthread.h>
+#include "obj.h"
+#include "wtp.h"
+#include "batch.h"
+#include "stream.h"
+#include "statsobj.h"
+#include "cryprov.h"
+
+/* support for the toDelete list */
+typedef struct toDeleteLst_s toDeleteLst_t;
+struct toDeleteLst_s {
+ qDeqID deqID;
+ int nElemDeq; /* numbe of elements that were dequeued and as such must now be discarded */
+ struct toDeleteLst_s *pNext;
+};
+
+
+/* queue types */
+typedef enum {
+ QUEUETYPE_FIXED_ARRAY = 0,/* a simple queue made out of a fixed (initially malloced) array fast but memoryhog */
+ QUEUETYPE_LINKEDLIST = 1, /* linked list used as buffer, lower fixed memory overhead but slower */
+ QUEUETYPE_DISK = 2, /* disk files used as buffer */
+ QUEUETYPE_DIRECT = 3 /* no queuing happens, consumer is directly called */
+} queueType_t;
+
+/* list member definition for linked list types of queues: */
+typedef struct qLinkedList_S {
+ struct qLinkedList_S *pNext;
+ smsg_t *pMsg;
+} qLinkedList_t;
+
+
+/* the queue object */
+struct queue_s {
+ BEGINobjInstance;
+ queueType_t qType;
+ int nLogDeq; /* number of elements currently logically dequeued */
+ int bShutdownImmediate; /* should all workers cease processing messages? */
+ sbool bEnqOnly; /* does queue run in enqueue-only mode (1) or not (0)? */
+ sbool bSaveOnShutdown;/* persists everthing on shutdown (if DA!)? 1-yes, 0-no */
+ sbool bQueueStarted; /* has queueStart() been called on this queue? 1-yes, 0-no */
+ sbool takeFlowCtlFromMsg;/* override enq flow ctl by message property? */
+ int iQueueSize; /* Current number of elements in the queue */
+ int iMaxQueueSize; /* how large can the queue grow? */
+ int iNumWorkerThreads;/* number of worker threads to use */
+ int iCurNumWrkThrd;/* current number of active worker threads */
+ int iMinMsgsPerWrkr;
+ /* minimum nbr of msgs per worker thread, if more, a new worker is started until max wrkrs */
+ wtp_t *pWtpDA;
+ wtp_t *pWtpReg;
+ action_t *pAction; /* for action queues, ptr to action object; for main queues unused */
+ int iUpdsSincePersist;/* nbr of queue updates since the last persist call */
+ int iPersistUpdCnt; /* persits queue info after this nbr of updates - 0 -> persist only on shutdown */
+ sbool bSyncQueueFiles;/* if working with files, sync them after each write? */
+ int iHighWtrMrk; /* high water mark for disk-assisted memory queues */
+ int iLowWtrMrk; /* low water mark for disk-assisted memory queues */
+ int iDiscardMrk; /* if the queue is above this mark, low-severity messages are discarded */
+ int iFullDlyMrk; /* if the queue is above this mark, FULL_DELAYable message are put on hold */
+ int iLightDlyMrk; /* if the queue is above this mark, LIGHT_DELAYable message are put on hold */
+ int iDiscardSeverity;/* messages of this severity above are discarded on too-full queue */
+ sbool bNeedDelQIF; /* does the QIF file need to be deleted when queue becomes empty? */
+ int toQShutdown; /* timeout for regular queue shutdown in ms */
+ int toActShutdown; /* timeout for long-running action shutdown in ms */
+ int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */
+ toDeleteLst_t *toDeleteLst;/* this queue's to-delete list */
+ int toEnq; /* enqueue timeout */
+ int iDeqBatchSize; /* max number of elements that shall be dequeued at once */
+ int iMinDeqBatchSize;/* min number of elements that shall be dequeued at once */
+ int toMinDeqBatchSize;/* timeout for MinDeqBatchSize, in ms */
+ /* rate limiting settings (will be expanded) */
+ int iDeqSlowdown; /* slow down dequeue by specified nbr of microseconds */
+ /* end rate limiting */
+ /* dequeue time window settings (may also be expanded) */
+ int iDeqtWinFromHr; /* begin of dequeue time window (hour only) */
+ int iDeqtWinToHr; /* end of dequeue time window (hour only), set to 25 to disable deq window! */
+ /* note that begin and end have specific semantics. It is a big difference if we have
+ * begin 4, end 22 or begin 22, end 4. In the later case, dequeuing will run from 10p,
+ * throughout the night and stop at 4 in the morning. In the first case, it will start
+ * at 4am, run throughout the day, and stop at 10 in the evening! So far, not logic is
+ * applied to detect user configuration errors (and tell me how should we detect what
+ * the user really wanted...). -- rgerhards, 2008-04-02
+ */
+ /* end dequeue time window */
+ rsRetVal (*pConsumer)(void *,batch_t*, wti_t*); /* user-supplied consumer function for dequeued messages */
+ /* calling interface for pConsumer: arg1 is the global user pointer from this structure, arg2 is the
+ * user pointer array that was dequeued (actual sample: for actions, arg1 is the pAction and arg2
+ * is pointer to an array of message message pointers)
+ */
+ /* type-specific handlers (set during construction) */
+ rsRetVal (*qConstruct)(struct queue_s *pThis);
+ rsRetVal (*qDestruct)(struct queue_s *pThis);
+ rsRetVal (*qAdd)(struct queue_s *pThis, smsg_t *pMsg);
+ rsRetVal (*qDeq)(struct queue_s *pThis, smsg_t **ppMsg);
+ rsRetVal (*qDel)(struct queue_s *pThis);
+ /* end type-specific handler */
+ /* public entry points (set during construction, permit to set best algorithm for params selected) */
+ rsRetVal (*MultiEnq)(qqueue_t *pThis, multi_submit_t *pMultiSub);
+ /* end public entry points */
+ /* synchronization variables */
+ pthread_mutex_t mutThrdMgmt; /* mutex for the queue's thread management */
+ pthread_mutex_t *mut; /* mutex for enqueing and dequeueing messages */
+ pthread_cond_t notFull;
+ pthread_cond_t belowFullDlyWtrMrk; /* below eFLOWCTL_FULL_DELAY watermark */
+ pthread_cond_t belowLightDlyWtrMrk; /* below eFLOWCTL_FULL_DELAY watermark */
+ int bThrdStateChanged; /* at least one thread state has changed if 1 */
+ /* end sync variables */
+ /* the following variables are always present, because they
+ * are not only used for the "disk" queueing mode but also for
+ * any other queueing mode if it is set to "disk assisted".
+ * rgerhards, 2008-01-09
+ */
+ uchar *pszSpoolDir;
+ size_t lenSpoolDir;
+ uchar *pszFilePrefix;
+ size_t lenFilePrefix;
+ uchar *pszQIFNam; /* full .qi file name, based on parts above */
+ size_t lenQIFNam;
+ int iNumberFiles; /* how many files make up the queue? */
+ int64 iMaxFileSize; /* max size for a single queue file */
+ int64 sizeOnDiskMax; /* maximum size on disk allowed */
+ qDeqID deqIDAdd; /* next dequeue ID to use during add to queue store */
+ qDeqID deqIDDel; /* queue store delete position */
+ int bIsDA; /* is this queue disk assisted? */
+ struct queue_s *pqDA; /* queue for disk-assisted modes */
+ struct queue_s *pqParent;/* pointer to the parent (if this is a child queue) */
+ int bDAEnqOnly; /* EnqOnly setting for DA queue */
+ /* now follow queueing mode specific data elements */
+ //union { /* different data elements based on queue type (qType) */
+ struct { /* different data elements based on queue type (qType) */
+ struct {
+ long deqhead, head, tail;
+ void** pBuf; /* the queued user data structure */
+ } farray;
+ struct {
+ qLinkedList_t *pDeqRoot;
+ qLinkedList_t *pDelRoot;
+ qLinkedList_t *pLast;
+ } linklist;
+ struct {
+ int64 sizeOnDisk; /* current amount of disk space used */
+ int64 deqOffs; /* offset after dequeue batch - used for file deleter */
+ int deqFileNumIn; /* same for the circular file numbers, mainly for */
+ int deqFileNumOut;/* deleting finished files */
+ strm_t *pWrite; /* current file to be written */
+ strm_t *pReadDeq; /* current file for dequeueing */
+ strm_t *pReadDel; /* current file for deleting */
+ int nForcePersist;/* force persist of .qi file the next "n" times */
+ } disk;
+ } tVars;
+ sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ uchar *cryprovName; /* crypto provider to use */
+ cryprov_if_t cryprov; /* ptr to crypto provider interface */
+ void *cryprovData; /* opaque data ptr for provider use */
+ uchar *cryprovNameFull;/* full internal crypto provider name */
+ DEF_ATOMIC_HELPER_MUT(mutQueueSize)
+ DEF_ATOMIC_HELPER_MUT(mutLogDeq)
+ /* for statistics subsystem */
+ statsobj_t *statsobj;
+ STATSCOUNTER_DEF(ctrEnqueued, mutCtrEnqueued)
+ STATSCOUNTER_DEF(ctrFull, mutCtrFull)
+ STATSCOUNTER_DEF(ctrFDscrd, mutCtrFDscrd)
+ STATSCOUNTER_DEF(ctrNFDscrd, mutCtrNFDscrd)
+ int ctrMaxqsize; /* NOT guarded by a mutex */
+ int iSmpInterval; /* line interval of sampling logs */
+ int isRunning;
+};
+
+
+/* the define below is an "eternal" timeout for the timeout settings which require a value.
+ * It is one day, which is not really eternal, but comes close to it if we think about
+ * rsyslog (e.g.: do you want to wait on shutdown for more than a day? ;))
+ * rgerhards, 2008-01-17
+ */
+#define QUEUE_TIMEOUT_ETERNAL 24 * 60 * 60 * 1000
+
+/* prototypes */
+rsRetVal qqueueDestruct(qqueue_t **ppThis);
+rsRetVal qqueueEnqMsg(qqueue_t *pThis, flowControl_t flwCtlType, smsg_t *pMsg);
+rsRetVal qqueueStart(rsconf_t *cnf, qqueue_t *pThis);
+rsRetVal qqueueSetMaxFileSize(qqueue_t *pThis, size_t iMaxFileSize);
+rsRetVal qqueueSetFilePrefix(qqueue_t *pThis, uchar *pszPrefix, size_t iLenPrefix);
+rsRetVal qqueueConstruct(qqueue_t **ppThis, queueType_t qType, int iWorkerThreads,
+ int iMaxQueueSize, rsRetVal (*pConsumer)(void*,batch_t*, wti_t *));
+int queueCnfParamsSet(struct nvlst *lst);
+rsRetVal qqueueApplyCnfParam(qqueue_t *pThis, struct nvlst *lst);
+void qqueueSetDefaultsRulesetQueue(qqueue_t *pThis);
+void qqueueSetDefaultsActionQueue(qqueue_t *pThis);
+void qqueueDbgPrint(qqueue_t *pThis);
+rsRetVal qqueueShutdownWorkers(qqueue_t *pThis);
+void qqueueDoneLoadCnf(void);
+int queuesEqual(qqueue_t *pOld, qqueue_t *pNew);
+void qqueueCorrectParams(qqueue_t *pThis);
+
+PROTOTYPEObjClassInit(qqueue);
+PROTOTYPEpropSetMeth(qqueue, iPersistUpdCnt, int);
+PROTOTYPEpropSetMeth(qqueue, bSyncQueueFiles, int);
+PROTOTYPEpropSetMeth(qqueue, iDeqtWinFromHr, int);
+PROTOTYPEpropSetMeth(qqueue, iDeqtWinToHr, int);
+PROTOTYPEpropSetMeth(qqueue, toQShutdown, long);
+PROTOTYPEpropSetMeth(qqueue, toActShutdown, long);
+PROTOTYPEpropSetMeth(qqueue, toWrkShutdown, long);
+PROTOTYPEpropSetMeth(qqueue, toEnq, long);
+PROTOTYPEpropSetMeth(qqueue, iLightDlyMrk, int);
+PROTOTYPEpropSetMeth(qqueue, iHighWtrMrk, int);
+PROTOTYPEpropSetMeth(qqueue, iLowWtrMrk, int);
+PROTOTYPEpropSetMeth(qqueue, iDiscardMrk, int);
+PROTOTYPEpropSetMeth(qqueue, iDiscardSeverity, int);
+PROTOTYPEpropSetMeth(qqueue, iMinMsgsPerWrkr, int);
+PROTOTYPEpropSetMeth(qqueue, iNumWorkerThreads, int);
+PROTOTYPEpropSetMeth(qqueue, bSaveOnShutdown, int);
+PROTOTYPEpropSetMeth(qqueue, pAction, action_t*);
+PROTOTYPEpropSetMeth(qqueue, iDeqSlowdown, int);
+PROTOTYPEpropSetMeth(qqueue, sizeOnDiskMax, int64);
+PROTOTYPEpropSetMeth(qqueue, iDeqBatchSize, int);
+#define qqueueGetID(pThis) ((unsigned long) pThis)
+
+#ifdef ENABLE_IMDIAG
+extern unsigned int iOverallQueueSize;
+#endif
+
+#endif /* #ifndef QUEUE_H_INCLUDED */
diff --git a/runtime/ratelimit.c b/runtime/ratelimit.c
new file mode 100644
index 0000000..1669962
--- /dev/null
+++ b/runtime/ratelimit.c
@@ -0,0 +1,436 @@
+/* ratelimit.c
+ * support for rate-limiting sources, including "last message
+ * repeated n times" processing.
+ *
+ * Copyright 2012-2020 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "ratelimit.h"
+#include "datetime.h"
+#include "parser.h"
+#include "unicode-helper.h"
+#include "msg.h"
+#include "rsconf.h"
+#include "dirty.h"
+
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(parser)
+
+/* static data */
+
+/* generate a "repeated n times" message */
+static smsg_t *
+ratelimitGenRepMsg(ratelimit_t *ratelimit)
+{
+ smsg_t *repMsg;
+ size_t lenRepMsg;
+ uchar szRepMsg[1024];
+
+ if(ratelimit->nsupp == 1) { /* we simply use the original message! */
+ repMsg = MsgAddRef(ratelimit->pMsg);
+ } else {/* we need to duplicate, original message may still be in use in other
+ * parts of the system! */
+ if((repMsg = MsgDup(ratelimit->pMsg)) == NULL) {
+ DBGPRINTF("Message duplication failed, dropping repeat message.\n");
+ goto done;
+ }
+ lenRepMsg = snprintf((char*)szRepMsg, sizeof(szRepMsg),
+ " message repeated %d times: [%.800s]",
+ ratelimit->nsupp, getMSG(ratelimit->pMsg));
+ MsgReplaceMSG(repMsg, szRepMsg, lenRepMsg);
+ }
+
+done: return repMsg;
+}
+
+static rsRetVal
+doLastMessageRepeatedNTimes(ratelimit_t *ratelimit, smsg_t *pMsg, smsg_t **ppRepMsg)
+{
+ int bNeedUnlockMutex = 0;
+ DEFiRet;
+
+ if(ratelimit->bThreadSafe) {
+ pthread_mutex_lock(&ratelimit->mut);
+ bNeedUnlockMutex = 1;
+ }
+
+ if( ratelimit->pMsg != NULL &&
+ getMSGLen(pMsg) == getMSGLen(ratelimit->pMsg) &&
+ !ustrcmp(getMSG(pMsg), getMSG(ratelimit->pMsg)) &&
+ !strcmp(getHOSTNAME(pMsg), getHOSTNAME(ratelimit->pMsg)) &&
+ !strcmp(getPROCID(pMsg, LOCK_MUTEX), getPROCID(ratelimit->pMsg, LOCK_MUTEX)) &&
+ !strcmp(getAPPNAME(pMsg, LOCK_MUTEX), getAPPNAME(ratelimit->pMsg, LOCK_MUTEX))) {
+ ratelimit->nsupp++;
+ DBGPRINTF("msg repeated %d times\n", ratelimit->nsupp);
+ /* use current message, so we have the new timestamp
+ * (means we need to discard previous one) */
+ msgDestruct(&ratelimit->pMsg);
+ ratelimit->pMsg = pMsg;
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ } else {/* new message, do "repeat processing" & save it */
+ if(ratelimit->pMsg != NULL) {
+ if(ratelimit->nsupp > 0) {
+ *ppRepMsg = ratelimitGenRepMsg(ratelimit);
+ ratelimit->nsupp = 0;
+ }
+ msgDestruct(&ratelimit->pMsg);
+ }
+ ratelimit->pMsg = MsgAddRef(pMsg);
+ }
+
+finalize_it:
+ if(bNeedUnlockMutex)
+ pthread_mutex_unlock(&ratelimit->mut);
+ RETiRet;
+}
+
+
+/* helper: tell how many messages we lost due to linux-like ratelimiting */
+static void
+tellLostCnt(ratelimit_t *ratelimit)
+{
+ uchar msgbuf[1024];
+ if(ratelimit->missed) {
+ snprintf((char*)msgbuf, sizeof(msgbuf),
+ "%s: %u messages lost due to rate-limiting (%u allowed within %u seconds)",
+ ratelimit->name, ratelimit->missed, ratelimit->burst, ratelimit->interval);
+ ratelimit->missed = 0;
+ logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG|LOG_INFO, msgbuf, 0);
+ }
+}
+
+/* Linux-like ratelimiting, modelled after the linux kernel
+ * returns 1 if message is within rate limit and shall be
+ * processed, 0 otherwise.
+ * This implementation is NOT THREAD-SAFE and must not
+ * be called concurrently.
+ */
+static int ATTR_NONNULL()
+withinRatelimit(ratelimit_t *__restrict__ const ratelimit,
+ time_t tt,
+ const char*const appname)
+{
+ int ret;
+ uchar msgbuf[1024];
+
+ if(ratelimit->bThreadSafe) {
+ pthread_mutex_lock(&ratelimit->mut);
+ }
+
+ if(ratelimit->interval == 0) {
+ ret = 1;
+ goto finalize_it;
+ }
+
+ /* we primarily need "NoTimeCache" mode for imjournal, as it
+ * sets the message generation time to the journal timestamp.
+ * As such, we do not get a proper indication of the actual
+ * message rate. To prevent this, we need to query local
+ * system time ourselvs.
+ */
+ if(ratelimit->bNoTimeCache)
+ tt = time(NULL);
+
+ assert(ratelimit->burst != 0);
+
+ if(ratelimit->begin == 0)
+ ratelimit->begin = tt;
+
+ /* resume if we go out of time window or if time has gone backwards */
+ if((tt > (time_t)(ratelimit->begin + ratelimit->interval)) || (tt < ratelimit->begin) ) {
+ ratelimit->begin = 0;
+ ratelimit->done = 0;
+ tellLostCnt(ratelimit);
+ }
+
+ /* do actual limit check */
+ if(ratelimit->burst > ratelimit->done) {
+ ratelimit->done++;
+ ret = 1;
+ } else {
+ ratelimit->missed++;
+ if(ratelimit->missed == 1) {
+ snprintf((char*)msgbuf, sizeof(msgbuf),
+ "%s from <%s>: begin to drop messages due to rate-limiting",
+ ratelimit->name, appname);
+ logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG|LOG_INFO, msgbuf, 0);
+ }
+ ret = 0;
+ }
+
+finalize_it:
+ if(ratelimit->bThreadSafe) {
+ pthread_mutex_unlock(&ratelimit->mut);
+ }
+ return ret;
+}
+
+/* ratelimit a message based on message count
+ * - handles only rate-limiting
+ * This function returns RS_RET_OK, if the caller shall process
+ * the message regularly and RS_RET_DISCARD if the caller must
+ * discard the message. The caller should also discard the message
+ * if another return status occurs.
+ */
+rsRetVal
+ratelimitMsgCount(ratelimit_t *__restrict__ const ratelimit,
+ time_t tt,
+ const char* const appname)
+{
+ DEFiRet;
+ if(ratelimit->interval) {
+ if(withinRatelimit(ratelimit, tt, appname) == 0) {
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ }
+ }
+finalize_it:
+ if(Debug) {
+ if(iRet == RS_RET_DISCARDMSG)
+ DBGPRINTF("message discarded by ratelimiting\n");
+ }
+ RETiRet;
+}
+
+/* ratelimit a message, that means:
+ * - handle "last message repeated n times" logic
+ * - handle actual (discarding) rate-limiting
+ * This function returns RS_RET_OK, if the caller shall process
+ * the message regularly and RS_RET_DISCARD if the caller must
+ * discard the message. The caller should also discard the message
+ * if another return status occurs. This places some burden on the
+ * caller logic, but provides best performance. Demanding this
+ * cooperative mode can enable a faulty caller to thrash up part
+ * of the system, but we accept that risk (a faulty caller can
+ * always do all sorts of evil, so...)
+ * If *ppRepMsg != NULL on return, the caller must enqueue that
+ * message before the original message.
+ */
+rsRetVal
+ratelimitMsg(ratelimit_t *__restrict__ const ratelimit, smsg_t *pMsg, smsg_t **ppRepMsg)
+{
+ DEFiRet;
+ rsRetVal localRet;
+ int severity = 0;
+
+ *ppRepMsg = NULL;
+
+ if(runConf->globals.bReduceRepeatMsgs || ratelimit->severity > 0) {
+ /* consider early parsing only if really needed */
+ if((pMsg->msgFlags & NEEDS_PARSING) != 0) {
+ if((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK) {
+ DBGPRINTF("Message discarded, parsing error %d\n", localRet);
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ }
+ }
+ severity = pMsg->iSeverity;
+ }
+
+ /* Only the messages having severity level at or below the
+ * treshold (the value is >=) are subject to ratelimiting. */
+ if(ratelimit->interval && (severity >= ratelimit->severity)) {
+ char namebuf[512]; /* 256 for FGDN adn 256 for APPNAME should be enough */
+ snprintf(namebuf, sizeof namebuf, "%s:%s", getHOSTNAME(pMsg),
+ getAPPNAME(pMsg, 0));
+ if(withinRatelimit(ratelimit, pMsg->ttGenTime, namebuf) == 0) {
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ }
+ }
+ if(runConf->globals.bReduceRepeatMsgs) {
+ CHKiRet(doLastMessageRepeatedNTimes(ratelimit, pMsg, ppRepMsg));
+ }
+finalize_it:
+ if(Debug) {
+ if(iRet == RS_RET_DISCARDMSG)
+ DBGPRINTF("message discarded by ratelimiting\n");
+ }
+ RETiRet;
+}
+
+/* returns 1, if the ratelimiter performs any checks and 0 otherwise */
+int
+ratelimitChecked(ratelimit_t *ratelimit)
+{
+ return ratelimit->interval || runConf->globals.bReduceRepeatMsgs;
+}
+
+
+/* add a message to a ratelimiter/multisubmit structure.
+ * ratelimiting is automatically handled according to the ratelimit
+ * settings.
+ * if pMultiSub == NULL, a single-message enqueue happens (under reconsideration)
+ */
+rsRetVal
+ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, smsg_t *pMsg)
+{
+ rsRetVal localRet;
+ smsg_t *repMsg;
+ DEFiRet;
+
+ localRet = ratelimitMsg(ratelimit, pMsg, &repMsg);
+ if(pMultiSub == NULL) {
+ if(repMsg != NULL)
+ CHKiRet(submitMsg2(repMsg));
+ CHKiRet(localRet);
+ CHKiRet(submitMsg2(pMsg));
+ } else {
+ if(repMsg != NULL) {
+ pMultiSub->ppMsgs[pMultiSub->nElem++] = repMsg;
+ if(pMultiSub->nElem == pMultiSub->maxElem)
+ CHKiRet(multiSubmitMsg2(pMultiSub));
+ }
+ CHKiRet(localRet);
+ if(pMsg->iLenRawMsg > glblGetMaxLine(runConf)) {
+ /* oversize message needs special processing. We keep
+ * at least the previous batch as batch...
+ */
+ if(pMultiSub->nElem > 0) {
+ CHKiRet(multiSubmitMsg2(pMultiSub));
+ }
+ CHKiRet(submitMsg2(pMsg));
+ FINALIZE;
+ }
+ pMultiSub->ppMsgs[pMultiSub->nElem++] = pMsg;
+ if(pMultiSub->nElem == pMultiSub->maxElem)
+ CHKiRet(multiSubmitMsg2(pMultiSub));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* modname must be a static name (usually expected to be the module
+ * name and MUST be present. dynname may be NULL and can be used for
+ * dynamic information, e.g. PID or listener IP, ...
+ * Both values should be kept brief.
+ */
+rsRetVal
+ratelimitNew(ratelimit_t **ppThis, const char *modname, const char *dynname)
+{
+ ratelimit_t *pThis;
+ char namebuf[256];
+ DEFiRet;
+
+ CHKmalloc(pThis = calloc(1, sizeof(ratelimit_t)));
+ if(modname == NULL)
+ modname ="*ERROR:MODULE NAME MISSING*";
+
+ if(dynname == NULL) {
+ pThis->name = strdup(modname);
+ } else {
+ snprintf(namebuf, sizeof(namebuf), "%s[%s]",
+ modname, dynname);
+ namebuf[sizeof(namebuf)-1] = '\0'; /* to be on safe side */
+ pThis->name = strdup(namebuf);
+ }
+ DBGPRINTF("ratelimit:%s:new ratelimiter\n", pThis->name);
+ *ppThis = pThis;
+finalize_it:
+ RETiRet;
+}
+
+
+/* enable linux-like ratelimiting */
+void
+ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned int interval, unsigned int burst)
+{
+ ratelimit->interval = interval;
+ ratelimit->burst = burst;
+ ratelimit->done = 0;
+ ratelimit->missed = 0;
+ ratelimit->begin = 0;
+}
+
+
+/* enable thread-safe operations mode. This make sure that
+ * a single ratelimiter can be called from multiple threads. As
+ * this causes some overhead and is not always required, it needs
+ * to be explicitely enabled. This operation cannot be undone
+ * (think: why should one do that???)
+ */
+void
+ratelimitSetThreadSafe(ratelimit_t *ratelimit)
+{
+ ratelimit->bThreadSafe = 1;
+ pthread_mutex_init(&ratelimit->mut, NULL);
+}
+void
+ratelimitSetNoTimeCache(ratelimit_t *ratelimit)
+{
+ ratelimit->bNoTimeCache = 1;
+ pthread_mutex_init(&ratelimit->mut, NULL);
+}
+
+/* Severity level determines which messages are subject to
+ * ratelimiting. Default (no value set) is all messages.
+ */
+void
+ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity)
+{
+ ratelimit->severity = severity;
+}
+
+void
+ratelimitDestruct(ratelimit_t *ratelimit)
+{
+ smsg_t *pMsg;
+ if(ratelimit->pMsg != NULL) {
+ if(ratelimit->nsupp > 0) {
+ pMsg = ratelimitGenRepMsg(ratelimit);
+ if(pMsg != NULL)
+ submitMsg2(pMsg);
+ }
+ msgDestruct(&ratelimit->pMsg);
+ }
+ tellLostCnt(ratelimit);
+ if(ratelimit->bThreadSafe)
+ pthread_mutex_destroy(&ratelimit->mut);
+ free(ratelimit->name);
+ free(ratelimit);
+}
+
+void
+ratelimitModExit(void)
+{
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+}
+
+rsRetVal
+ratelimitModInit(void)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+finalize_it:
+ RETiRet;
+}
diff --git a/runtime/ratelimit.h b/runtime/ratelimit.h
new file mode 100644
index 0000000..bb45e79
--- /dev/null
+++ b/runtime/ratelimit.h
@@ -0,0 +1,55 @@
+/* header for ratelimit.c
+ *
+ * Copyright 2012-2016 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_RATELIMIT_H
+#define INCLUDED_RATELIMIT_H
+
+struct ratelimit_s {
+ char *name; /**< rate limiter name, e.g. for user messages */
+ /* support for Linux kernel-type ratelimiting */
+ unsigned int interval;
+ unsigned int burst;
+ intTiny severity; /**< ratelimit only equal or lower severity levels (eq or higher values) */
+ unsigned done;
+ unsigned missed;
+ time_t begin;
+ /* support for "last message repeated n times */
+ unsigned nsupp; /**< nbr of msgs suppressed */
+ smsg_t *pMsg;
+ sbool bThreadSafe; /**< do we need to operate in Thread-Safe mode? */
+ sbool bNoTimeCache; /**< if we shall not used cached reception time */
+ pthread_mutex_t mut; /**< mutex if thread-safe operation desired */
+};
+
+/* prototypes */
+rsRetVal ratelimitNew(ratelimit_t **ppThis, const char *modname, const char *dynname);
+void ratelimitSetThreadSafe(ratelimit_t *ratelimit);
+void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned int interval, unsigned int burst);
+void ratelimitSetNoTimeCache(ratelimit_t *ratelimit);
+void ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity);
+rsRetVal ratelimitMsgCount(ratelimit_t *ratelimit, time_t tt, const char* const appname);
+rsRetVal ratelimitMsg(ratelimit_t *ratelimit, smsg_t *pMsg, smsg_t **ppRep);
+rsRetVal ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, smsg_t *pMsg);
+void ratelimitDestruct(ratelimit_t *pThis);
+int ratelimitChecked(ratelimit_t *ratelimit);
+rsRetVal ratelimitModInit(void);
+void ratelimitModExit(void);
+
+#endif /* #ifndef INCLUDED_RATELIMIT_H */
diff --git a/runtime/regexp.c b/runtime/regexp.c
new file mode 100644
index 0000000..433c9c2
--- /dev/null
+++ b/runtime/regexp.c
@@ -0,0 +1,384 @@
+/* The regexp object.
+ *
+ * Module begun 2008-03-05 by Rainer Gerhards, based on some code
+ * from syslogd.c
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <pthread.h>
+#include <regex.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "regexp.h"
+#include "errmsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+
+/* When using glibc, we enable per-thread regex to avoid lock contention.
+ * See:
+ * - https://github.com/rsyslog/rsyslog/issues/2759
+ * - https://github.com/rsyslog/rsyslog/pull/2786
+ * - https://sourceware.org/bugzilla/show_bug.cgi?id=11159
+ *
+ * This should not affect BSD as they don't seem to take a lock in regexec.
+ */
+#ifdef __GLIBC__
+#define USE_PERTHREAD_REGEX 1
+#else
+#define USE_PERTHREAD_REGEX 0
+#endif
+
+static pthread_mutex_t mut_regexp;
+
+// Map a regex_t to its associated uncompiled parameters.
+static struct hashtable *regex_to_uncomp = NULL;
+
+// Map a (regexp_t, pthead_t) to a perthread_regex.
+static struct hashtable *perthread_regexs = NULL;
+
+
+/*
+ * This stores un-compiled regex to allow further
+ * call to regexec to re-compile a new regex dedicated
+ * to the calling thread.
+ */
+typedef struct uncomp_regex {
+ char *regex;
+ int cflags;
+ regex_t *preg;
+} uncomp_regex_t;
+
+/*
+ * This stores a regex dedicated to a single thread.
+ */
+typedef struct perthread_regex {
+ const regex_t *original_preg;
+ regex_t preg;
+ int ret;
+ pthread_mutex_t lock;
+ pthread_t thread;
+} perthread_regex_t;
+
+
+static unsigned __attribute__((nonnull(1))) int hash_from_regex(void *k) {
+ return (uintptr_t)*(regex_t **)k;
+}
+
+static int key_equals_regex(void *key1, void *key2) {
+ return *(regex_t **)key1 == *(regex_t **)key2;
+}
+
+static unsigned __attribute__((nonnull(1))) int hash_from_tregex(void *k) {
+ perthread_regex_t *entry = k;
+ // Cast to (void*) is ok here because already used in other parts of the code.
+ uintptr_t thread_id = (uintptr_t)(void *)entry->thread;
+
+ return thread_id ^ (uintptr_t)entry->original_preg;
+}
+
+static int key_equals_tregex(void *key1, void *key2) {
+ perthread_regex_t *entry1 = key1;
+ perthread_regex_t *entry2 = key2;
+
+ return (pthread_equal(entry1->thread, entry2->thread) &&
+ entry1->original_preg == entry2->original_preg);
+}
+
+
+/* ------------------------------ methods ------------------------------ */
+
+
+// Create a copy of preg to be used by this thread only.
+static perthread_regex_t *create_perthread_regex(const regex_t *preg, uncomp_regex_t *uncomp) {
+ perthread_regex_t *entry = NULL;
+
+ if (Debug) {
+ DBGPRINTF("Creating new regex_t for thread %p original regexp_t %p (pattern: %s, cflags: %x)\n",
+ (void *)pthread_self(), preg,
+ uncomp->regex, uncomp->cflags);
+ }
+ entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ return entry;
+ entry->original_preg = preg;
+ DBGPRINTF("regexp: regcomp %p %p\n", entry, &entry->preg);
+ entry->ret = regcomp(&entry->preg, uncomp->regex, uncomp->cflags);
+ pthread_mutex_init(&entry->lock, NULL);
+ entry->thread = pthread_self();
+ return entry;
+}
+
+// Get (or create) a regex_t to be used by the current thread.
+static perthread_regex_t *get_perthread_regex(const regex_t *preg) {
+ perthread_regex_t *entry = NULL;
+ perthread_regex_t key = { .original_preg = preg, .thread = pthread_self() };
+
+ pthread_mutex_lock(&mut_regexp);
+ entry = hashtable_search(perthread_regexs, (void *)&key);
+ if (!entry) {
+ uncomp_regex_t *uncomp = hashtable_search(regex_to_uncomp, (void *)&preg);
+
+ if (uncomp) {
+ entry = create_perthread_regex(preg, uncomp);
+ if(!hashtable_insert(perthread_regexs, (void *)entry, entry)) {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "error trying to insert thread-regexp into hash-table - things "
+ "will not work 100%% correctly (mostly probably out of memory issue)");
+ }
+ }
+ }
+ if (entry) {
+ pthread_mutex_lock(&entry->lock);
+ }
+ pthread_mutex_unlock(&mut_regexp);
+ return entry;
+}
+
+static void remove_uncomp_regexp(regex_t *preg) {
+ uncomp_regex_t *uncomp = NULL;
+
+ pthread_mutex_lock(&mut_regexp);
+ uncomp = hashtable_remove(regex_to_uncomp, (void *)&preg);
+
+ if (uncomp) {
+ if (Debug) {
+ DBGPRINTF("Removing everything linked to regexp_t %p (pattern: %s, cflags: %x)\n",
+ preg, uncomp->regex, uncomp->cflags);
+ }
+ free(uncomp->regex);
+ free(uncomp);
+ }
+ pthread_mutex_unlock(&mut_regexp);
+}
+
+static void _regfree(regex_t *preg) {
+ int ret = 0;
+ struct hashtable_itr *itr = NULL;
+
+ if (!preg)
+ return;
+
+ regfree(preg);
+ remove_uncomp_regexp(preg);
+
+ pthread_mutex_lock(&mut_regexp);
+ if (!hashtable_count(perthread_regexs)) {
+ pthread_mutex_unlock(&mut_regexp);
+ return;
+ }
+
+ // This can be long to iterate other all regexps, but regfree doesn't get called
+ // a lot during processing.
+ itr = hashtable_iterator(perthread_regexs);
+ do {
+ perthread_regex_t *entry = (perthread_regex_t *)hashtable_iterator_value(itr);
+
+ // Do it before freeing the entry.
+ ret = hashtable_iterator_advance(itr);
+
+ if (entry->original_preg == preg) {
+ // This allows us to avoid freeing this while somebody is still using it.
+ pthread_mutex_lock(&entry->lock);
+ // We can unlock immediately after because mut_regexp is locked.
+ pthread_mutex_unlock(&entry->lock);
+ pthread_mutex_destroy(&entry->lock);
+ regfree(&entry->preg);
+
+ // Do it last because it will free entry.
+ hashtable_remove(perthread_regexs, (void *)entry);
+ }
+ } while (ret);
+ free(itr);
+
+ pthread_mutex_unlock(&mut_regexp);
+}
+
+static int _regcomp(regex_t *preg, const char *regex, int cflags) {
+ int ret = 0;
+ regex_t **ppreg = NULL;
+ uncomp_regex_t *uncomp;
+
+ // Remove previous data if caller forgot to call regfree().
+ remove_uncomp_regexp(preg);
+
+ // Make sure preg itself it correctly initalized.
+ ret = regcomp(preg, regex, cflags);
+ if (ret != 0)
+ return ret;
+
+ uncomp = calloc(1, sizeof(*uncomp));
+ if (!uncomp)
+ return REG_ESPACE;
+
+ uncomp->preg = preg;
+ uncomp->regex = strdup(regex);
+ uncomp->cflags = cflags;
+ pthread_mutex_lock(&mut_regexp);
+
+ // We need to allocate the key because hashtable will free it on remove.
+ ppreg = malloc(sizeof(regex_t *));
+ *ppreg = preg;
+ ret = hashtable_insert(regex_to_uncomp, (void *)ppreg, uncomp);
+ pthread_mutex_unlock(&mut_regexp);
+ if (ret == 0) {
+ free(uncomp->regex);
+ free(uncomp);
+ return REG_ESPACE;
+ }
+
+ perthread_regex_t *entry = get_perthread_regex(preg);
+ if (entry) {
+ ret = entry->ret;
+ pthread_mutex_unlock(&entry->lock);
+ } else {
+ ret = REG_ESPACE;
+ }
+ return ret;
+}
+
+static int _regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) {
+ perthread_regex_t *entry = get_perthread_regex(preg);
+ int ret = REG_NOMATCH;
+ if(entry != NULL) {
+ ret = regexec(&entry->preg, string, nmatch, pmatch, eflags);
+ pthread_mutex_unlock(&entry->lock);
+ }
+ return ret;
+}
+
+static size_t _regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) {
+ perthread_regex_t *entry = get_perthread_regex(preg);
+
+ if (entry)
+ preg = &entry->preg;
+
+ size_t ret = regerror(errcode, preg, errbuf, errbuf_size);
+
+ if (entry)
+ pthread_mutex_unlock(&entry->lock);
+
+ return ret;
+}
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(regexp)
+CODESTARTobjQueryInterface(regexp)
+ if(pIf->ifVersion != regexpCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ if (USE_PERTHREAD_REGEX) {
+ pIf->regcomp = _regcomp;
+ pIf->regexec = _regexec;
+ pIf->regerror = _regerror;
+ pIf->regfree = _regfree;
+ } else {
+ pIf->regcomp = regcomp;
+ pIf->regexec = regexec;
+ pIf->regerror = regerror;
+ pIf->regfree = regfree;
+ }
+
+finalize_it:
+ENDobjQueryInterface(regexp)
+
+
+/* Initialize the regexp class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(regexp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+
+ if (USE_PERTHREAD_REGEX) {
+ pthread_mutex_init(&mut_regexp, NULL);
+
+ regex_to_uncomp = create_hashtable(100, hash_from_regex, key_equals_regex, NULL);
+ perthread_regexs = create_hashtable(100, hash_from_tregex, key_equals_tregex, NULL);
+ if(regex_to_uncomp == NULL || perthread_regexs == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table "
+ "for regexp table. regexp will be disabled.");
+ if (regex_to_uncomp) hashtable_destroy(regex_to_uncomp, 1);
+ if (perthread_regexs) hashtable_destroy(perthread_regexs, 1);
+ regex_to_uncomp = NULL;
+ perthread_regexs = NULL;
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ }
+
+ENDObjClassInit(regexp)
+
+
+/* Exit the class.
+ */
+BEGINObjClassExit(regexp, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ if (USE_PERTHREAD_REGEX) {
+ /* release objects we no longer need */
+ pthread_mutex_destroy(&mut_regexp);
+ if (regex_to_uncomp)
+ hashtable_destroy(regex_to_uncomp, 1);
+ if (perthread_regexs)
+ hashtable_destroy(perthread_regexs, 1);
+ }
+ENDObjClassExit(regexp)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ CHKiRet(regexpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/regexp.h b/runtime/regexp.h
new file mode 100644
index 0000000..ec7c72c
--- /dev/null
+++ b/runtime/regexp.h
@@ -0,0 +1,44 @@
+/* The regexp object. It encapsulates the C regexp functionality. The primary
+ * purpose of this wrapper class is to enable rsyslogd core to be build without
+ * regexp libraries.
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_REGEXP_H
+#define INCLUDED_REGEXP_H
+
+#include <regex.h>
+
+/* interfaces */
+BEGINinterface(regexp) /* name must also be changed in ENDinterface macro! */
+ int (*regcomp)(regex_t *preg, const char *regex, int cflags);
+ int (*regexec)(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+ size_t (*regerror)(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
+ void (*regfree)(regex_t *preg);
+ENDinterface(regexp)
+#define regexpCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(regexp);
+
+/* the name of our library binary */
+#define LM_REGEXP_FILENAME "lmregexp"
+
+#endif /* #ifndef INCLUDED_REGEXP_H */
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
new file mode 100644
index 0000000..27047a5
--- /dev/null
+++ b/runtime/rsconf.c
@@ -0,0 +1,1601 @@
+/* rsconf.c - the rsyslog configuration system.
+ *
+ * Module begun 2011-04-19 by Rainer Gerhards
+ *
+ * Copyright 2011-2023 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdarg.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "srUtils.h"
+#include "ruleset.h"
+#include "modules.h"
+#include "conf.h"
+#include "queue.h"
+#include "rsconf.h"
+#include "cfsysline.h"
+#include "errmsg.h"
+#include "action.h"
+#include "glbl.h"
+#include "unicode-helper.h"
+#include "omshell.h"
+#include "omusrmsg.h"
+#include "omfwd.h"
+#include "omfile.h"
+#include "ompipe.h"
+#include "omdiscard.h"
+#include "pmrfc5424.h"
+#include "pmrfc3164.h"
+#include "smfile.h"
+#include "smtradfile.h"
+#include "smfwd.h"
+#include "smtradfwd.h"
+#include "parser.h"
+#include "outchannel.h"
+#include "threads.h"
+#include "datetime.h"
+#include "parserif.h"
+#include "modules.h"
+#include "dirty.h"
+#include "template.h"
+#include "timezones.h"
+
+extern char* yytext;
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(module)
+DEFobjCurrIf(conf)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+/* exported static data */
+rsconf_t *runConf = NULL;/* the currently running config */
+rsconf_t *loadConf = NULL;/* the config currently being loaded (no concurrent config load supported!) */
+
+/* hardcoded standard templates (used for defaults) */
+static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: "
+"'%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', "
+"APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', "
+"STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% "
+"rawmsg: '%rawmsg%'\n$!:%$!%\n$.:%$.%\n$/:%$/%\n\n\"";
+static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% "
+"%PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
+static uchar template_SyslogRFC5424Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% "
+"%PROCID% %MSGID% %STRUCTURED-DATA% %msg%\"";
+static uchar template_TraditionalFileFormat[] = "=RSYSLOG_TraditionalFileFormat";
+static uchar template_FileFormat[] = "=RSYSLOG_FileFormat";
+static uchar template_ForwardFormat[] = "=RSYSLOG_ForwardFormat";
+static uchar template_TraditionalForwardFormat[] = "=RSYSLOG_TraditionalForwardFormat";
+static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n "
+"%syslogtag%%msg%\n\r\"";
+static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
+static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, "
+"DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, "
+"'%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, "
+"'%syslogtag%')\",SQL";
+static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, "
+"DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, "
+"'%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, "
+"'%syslogtag%')\",STDSQL";
+static uchar template_spoofadr[] = "\"%fromhost-ip%\"";
+static uchar template_SysklogdFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%\n\"";
+static uchar template_StdJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\",\\\"fromhost\\\":\\\""
+"%HOSTNAME:::json%\\\",\\\"facility\\\":\\\"%syslogfacility-text%\\\",\\\"priority\\\":\\\""
+"%syslogpriority-text%\\\",\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\",\\\"timegenerated\\\":\\\""
+"%timegenerated:::date-rfc3339%\\\"}\"";
+static uchar template_FullJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\","
+"\\\"fromhost\\\":\\\"%HOSTNAME:::json%\\\","
+"\\\"programname\\\":\\\"%programname%\\\","
+"\\\"procid\\\":\\\"%PROCID%\\\","
+"\\\"msgid\\\":\\\"%MSGID%\\\","
+"\\\"facility\\\":\\\"%syslogfacility-text%\\\","
+"\\\"priority\\\":\\\"%syslogpriority-text%\\\","
+"\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\","
+"\\\"timegenerated\\\":\\\"%timegenerated:::date-rfc3339%\\\"}\"";
+static uchar template_StdClickHouseFmt[] = "\"INSERT INTO rsyslog.SystemEvents (severity, facility, "
+"timestamp, hostname, tag, message) VALUES (%syslogseverity%, %syslogfacility%, "
+"'%timereported:::date-unixtimestamp%', '%hostname%', '%syslogtag%', '%msg%')\",STDSQL";
+/* end templates */
+
+/* tables for interfacing with the v6 config system (as far as we need to) */
+static struct cnfparamdescr inppdescr[] = {
+ { "type", eCmdHdlrString, CNFPARAM_REQUIRED }
+};
+static struct cnfparamblk inppblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+ };
+
+static struct cnfparamdescr parserpdescr[] = {
+ { "type", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "name", eCmdHdlrString, CNFPARAM_REQUIRED }
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+/* forward-definitions */
+void cnfDoCfsysline(char *ln);
+
+int rsconfNeedDropPriv(rsconf_t *const cnf)
+{
+ return ((cnf->globals.gidDropPriv != 0) || (cnf->globals.uidDropPriv != 0));
+}
+
+static void cnfSetDefaults(rsconf_t *pThis)
+{
+#ifdef ENABLE_LIBCAPNG
+ pThis->globals.bAbortOnFailedLibcapngSetup = 1;
+ pThis->globals.bCapabilityDropEnabled = 1;
+#endif
+ pThis->globals.bAbortOnUncleanConfig = 0;
+ pThis->globals.bAbortOnFailedQueueStartup = 0;
+ pThis->globals.bReduceRepeatMsgs = 0;
+ pThis->globals.bDebugPrintTemplateList = 1;
+ pThis->globals.bDebugPrintModuleList = 0;
+ pThis->globals.bDebugPrintCfSysLineHandlerList = 0;
+ pThis->globals.bLogStatusMsgs = DFLT_bLogStatusMsgs;
+ pThis->globals.bErrMsgToStderr = 1;
+ pThis->globals.maxErrMsgToStderr = -1;
+ pThis->globals.umask = -1;
+ pThis->globals.gidDropPrivKeepSupplemental = 0;
+ pThis->globals.abortOnIDResolutionFail = 1;
+ pThis->templates.root = NULL;
+ pThis->templates.last = NULL;
+ pThis->templates.lastStatic = NULL;
+ pThis->actions.nbrActions = 0;
+ pThis->actions.iActionNbr = 0;
+ pThis->globals.pszWorkDir = NULL;
+ pThis->globals.bDropMalPTRMsgs = 0;
+ pThis->globals.operatingStateFile = NULL;
+ pThis->globals.iGnuTLSLoglevel = 0;
+ pThis->globals.debugOnShutdown = 0;
+ pThis->globals.pszDfltNetstrmDrvrCAF = NULL;
+ pThis->globals.pszDfltNetstrmDrvrCRLF = NULL;
+ pThis->globals.pszDfltNetstrmDrvrCertFile = NULL;
+ pThis->globals.pszDfltNetstrmDrvrKeyFile = NULL;
+ pThis->globals.pszDfltNetstrmDrvr = NULL;
+ pThis->globals.oversizeMsgErrorFile = NULL;
+ pThis->globals.reportOversizeMsg = 1;
+ pThis->globals.oversizeMsgInputMode = 0;
+ pThis->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
+ pThis->globals.bActionReportSuspension = 1;
+ pThis->globals.bActionReportSuspensionCont = 0;
+ pThis->globals.janitorInterval = 10;
+ pThis->globals.reportNewSenders = 0;
+ pThis->globals.reportGoneAwaySenders = 0;
+ pThis->globals.senderStatsTimeout = 12 * 60 * 60; /* 12 hr timeout for senders */
+ pThis->globals.senderKeepTrack = 0;
+ pThis->globals.inputTimeoutShutdown = 1000;
+ pThis->globals.iDefPFFamily = PF_UNSPEC;
+ pThis->globals.ACLAddHostnameOnFail = 0;
+ pThis->globals.ACLDontResolve = 0;
+ pThis->globals.bDisableDNS = 0;
+ pThis->globals.bProcessInternalMessages = 0;
+ const char *const log_dflt = getenv("RSYSLOG_DFLT_LOG_INTERNAL");
+ if(log_dflt != NULL && !strcmp(log_dflt, "1"))
+ pThis->globals.bProcessInternalMessages = 1;
+ pThis->globals.glblDevOptions = 0;
+ pThis->globals.intMsgRateLimitItv = 5;
+ pThis->globals.intMsgRateLimitBurst = 500;
+ pThis->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER;
+ pThis->globals.permitCtlC = glblPermitCtlC;
+
+ pThis->globals.actq_dflt_toQShutdown = 10;
+ pThis->globals.actq_dflt_toActShutdown = 1000;
+ pThis->globals.actq_dflt_toEnq = 2000;
+ pThis->globals.actq_dflt_toWrkShutdown = 60000;
+
+ pThis->globals.ruleset_dflt_toQShutdown = 1500;
+ pThis->globals.ruleset_dflt_toActShutdown = 1000;
+ pThis->globals.ruleset_dflt_toEnq = 2000;
+ pThis->globals.ruleset_dflt_toWrkShutdown = 60000;
+
+ pThis->globals.dnscacheDefaultTTL = 24 * 60 * 60;
+ pThis->globals.dnscacheEnableTTL = 0;
+ pThis->globals.shutdownQueueDoubleSize = 0;
+ pThis->globals.optionDisallowWarning = 1;
+ pThis->globals.bSupportCompressionExtension = 1;
+ #ifdef ENABLE_LIBLOGGING_STDLOG
+ pThis->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG, NULL);
+ pThis->globals.stdlog_chanspec = NULL;
+ #endif
+ pThis->globals.iMaxLine = 8096;
+
+ /* timezone specific*/
+ pThis->timezones.tzinfos = NULL;
+ pThis->timezones.ntzinfos = 0;
+
+ /* queue params */
+ pThis->globals.mainQ.iMainMsgQueueSize = 100000;
+ pThis->globals.mainQ.iMainMsgQHighWtrMark = 80000;
+ pThis->globals.mainQ.iMainMsgQLowWtrMark = 20000;
+ pThis->globals.mainQ.iMainMsgQDiscardMark = 98000;
+ pThis->globals.mainQ.iMainMsgQDiscardSeverity = 8;
+ pThis->globals.mainQ.iMainMsgQueueNumWorkers = 2;
+ pThis->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
+ pThis->globals.mainQ.pszMainMsgQFName = NULL;
+ pThis->globals.mainQ.iMainMsgQueMaxFileSize = 1024*1024;
+ pThis->globals.mainQ.iMainMsgQPersistUpdCnt = 0;
+ pThis->globals.mainQ.bMainMsgQSyncQeueFiles = 0;
+ pThis->globals.mainQ.iMainMsgQtoQShutdown = 1500;
+ pThis->globals.mainQ.iMainMsgQtoActShutdown = 1000;
+ pThis->globals.mainQ.iMainMsgQtoEnq = 2000;
+ pThis->globals.mainQ.iMainMsgQtoWrkShutdown = 60000;
+ pThis->globals.mainQ.iMainMsgQWrkMinMsgs = 40000;
+ pThis->globals.mainQ.iMainMsgQDeqSlowdown = 0;
+ pThis->globals.mainQ.iMainMsgQueMaxDiskSpace = 0;
+ pThis->globals.mainQ.iMainMsgQueDeqBatchSize = 256;
+ pThis->globals.mainQ.bMainMsgQSaveOnShutdown = 1;
+ pThis->globals.mainQ.iMainMsgQueueDeqtWinFromHr = 0;
+ pThis->globals.mainQ.iMainMsgQueueDeqtWinToHr = 25;
+ pThis->pMsgQueue = NULL;
+
+ pThis->globals.parser.cCCEscapeChar = '#';
+ pThis->globals.parser.bDropTrailingLF = 1;
+ pThis->globals.parser.bEscapeCCOnRcv = 1;
+ pThis->globals.parser.bSpaceLFOnRcv = 0;
+ pThis->globals.parser.bEscape8BitChars = 0;
+ pThis->globals.parser.bEscapeTab = 1;
+ pThis->globals.parser.bParserEscapeCCCStyle = 0;
+ pThis->globals.parser.bPermitSlashInProgramname = 0;
+ pThis->globals.parser.bParseHOSTNAMEandTAG = 1;
+
+ pThis->parsers.pDfltParsLst = NULL;
+ pThis->parsers.pParsLstRoot = NULL;
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(rsconf) /* be sure to specify the object type also in END macro! */
+ cnfSetDefaults(pThis);
+ lookupInitCnf(&pThis->lu_tabs);
+ CHKiRet(dynstats_initCnf(&pThis->dynstats_buckets));
+ CHKiRet(perctile_initCnf(&pThis->perctile_buckets));
+ CHKiRet(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList,
+ rulesetKeyDestruct, strcasecmp));
+finalize_it:
+ENDobjConstruct(rsconf)
+
+
+/* ConstructionFinalizer
+ */
+static rsRetVal
+rsconfConstructFinalize(rsconf_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, rsconf);
+ RETiRet;
+}
+
+
+/* call freeCnf() module entry points AND free the module entries themselfes.
+ */
+static void
+freeCnf(rsconf_t *pThis)
+{
+ cfgmodules_etry_t *etry, *del;
+ etry = pThis->modules.root;
+ while(etry != NULL) {
+ if(etry->pMod->beginCnfLoad != NULL) {
+ dbgprintf("calling freeCnf(%p) for module '%s'\n",
+ etry->modCnf, (char*) module.GetName(etry->pMod));
+ etry->pMod->freeCnf(etry->modCnf);
+ }
+ del = etry;
+ etry = etry->next;
+ free(del);
+ }
+}
+
+/* destructor for the rsconf object */
+PROTOTYPEobjDestruct(rsconf);
+BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(rsconf)
+ freeCnf(pThis);
+ tplDeleteAll(pThis);
+ dynstats_destroyAllBuckets();
+ perctileBucketsDestruct();
+ ochDeleteAll();
+ freeTimezones(pThis);
+ parser.DestructParserList(&pThis->parsers.pDfltParsLst);
+ parser.destroyMasterParserList(pThis->parsers.pParsLstRoot);
+ free(pThis->globals.mainQ.pszMainMsgQFName);
+ free(pThis->globals.pszConfDAGFile);
+ free(pThis->globals.pszWorkDir);
+ free(pThis->globals.operatingStateFile);
+ free(pThis->globals.pszDfltNetstrmDrvrCAF);
+ free(pThis->globals.pszDfltNetstrmDrvrCRLF);
+ free(pThis->globals.pszDfltNetstrmDrvrCertFile);
+ free(pThis->globals.pszDfltNetstrmDrvrKeyFile);
+ free(pThis->globals.pszDfltNetstrmDrvr);
+ free(pThis->globals.oversizeMsgErrorFile);
+ #ifdef ENABLE_LIBLOGGING_STDLOG
+ stdlog_close(pThis->globals.stdlog_hdl);
+ free(pThis->globals.stdlog_chanspec);
+ #endif
+ lookupDestroyCnf();
+ llDestroy(&(pThis->rulesets.llRulesets));
+ENDobjDestruct(rsconf)
+
+
+/* DebugPrint support for the rsconf object */
+PROTOTYPEObjDebugPrint(rsconf);
+BEGINobjDebugPrint(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */
+ cfgmodules_etry_t *modNode;
+
+ dbgprintf("configuration object %p\n", pThis);
+ dbgprintf("Global Settings:\n");
+ dbgprintf(" bDebugPrintTemplateList.............: %d\n",
+ pThis->globals.bDebugPrintTemplateList);
+ dbgprintf(" bDebugPrintModuleList : %d\n",
+ pThis->globals.bDebugPrintModuleList);
+ dbgprintf(" bDebugPrintCfSysLineHandlerList.....: %d\n",
+ pThis->globals.bDebugPrintCfSysLineHandlerList);
+ dbgprintf(" bLogStatusMsgs : %d\n",
+ pThis->globals.bLogStatusMsgs);
+ dbgprintf(" bErrMsgToStderr.....................: %d\n",
+ pThis->globals.bErrMsgToStderr);
+ dbgprintf(" drop Msgs with malicious PTR Record : %d\n",
+ glbl.GetDropMalPTRMsgs(pThis));
+ ruleset.DebugPrintAll(pThis);
+ dbgprintf("\n");
+ if(pThis->globals.bDebugPrintTemplateList)
+ tplPrintList(pThis);
+ if(pThis->globals.bDebugPrintModuleList)
+ module.PrintList();
+ if(pThis->globals.bDebugPrintCfSysLineHandlerList)
+ dbgPrintCfSysLineHandlers();
+ // TODO: The following code needs to be "streamlined", so far just moved over...
+ dbgprintf("Main queue size %d messages.\n", pThis->globals.mainQ.iMainMsgQueueSize);
+ dbgprintf("Main queue worker threads: %d, wThread shutdown: %d, Perists every %d updates.\n",
+ pThis->globals.mainQ.iMainMsgQueueNumWorkers,
+ pThis->globals.mainQ.iMainMsgQtoWrkShutdown, pThis->globals.mainQ.iMainMsgQPersistUpdCnt);
+ dbgprintf("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n",
+ pThis->globals.mainQ.iMainMsgQtoQShutdown,
+ pThis->globals.mainQ.iMainMsgQtoActShutdown, pThis->globals.mainQ.iMainMsgQtoEnq);
+ dbgprintf("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d\n",
+ pThis->globals.mainQ.iMainMsgQHighWtrMark, pThis->globals.mainQ.iMainMsgQLowWtrMark,
+ pThis->globals.mainQ.iMainMsgQDiscardMark, pThis->globals.mainQ.iMainMsgQDiscardSeverity);
+ dbgprintf("Main queue save on shutdown %d, max disk space allowed %lld\n",
+ pThis->globals.mainQ.bMainMsgQSaveOnShutdown, pThis->globals.mainQ.iMainMsgQueMaxDiskSpace);
+ /* TODO: add
+ iActionRetryCount = 0;
+ iActionRetryInterval = 30000;
+ static int iMainMsgQtoWrkMinMsgs = 100;
+ static int iMainMsgQbSaveOnShutdown = 1;
+ iMainMsgQueMaxDiskSpace = 0;
+ setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
+ setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
+ */
+ dbgprintf("Work Directory: '%s'.\n", glbl.GetWorkDir(pThis));
+ ochPrintList(pThis);
+ dbgprintf("Modules used in this configuration:\n");
+ for(modNode = pThis->modules.root ; modNode != NULL ; modNode = modNode->next) {
+ dbgprintf(" %s\n", module.GetName(modNode->pMod));
+ }
+CODESTARTobjDebugPrint(rsconf)
+ENDobjDebugPrint(rsconf)
+
+
+static rsRetVal
+parserProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ modInfo_t *pMod;
+ uchar *cnfModName = NULL;
+ uchar *parserName = NULL;
+ int paramIdx;
+ void *parserInst;
+ parser_t *myparser;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &parserpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ DBGPRINTF("input param blk after parserProcessCnf:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ paramIdx = cnfparamGetIdx(&parserpblk, "name");
+ parserName = (uchar*)es_str2cstr(pvals[paramIdx].val.d.estr, NULL);
+ if(parser.FindParser(loadConf->parsers.pParsLstRoot, &myparser, parserName) != RS_RET_PARSER_NOT_FOUND) {
+ LogError(0, RS_RET_PARSER_NAME_EXISTS,
+ "parser module name '%s' already exists", parserName);
+ ABORT_FINALIZE(RS_RET_PARSER_NAME_EXISTS);
+ }
+
+ paramIdx = cnfparamGetIdx(&parserpblk, "type");
+ cnfModName = (uchar*)es_str2cstr(pvals[paramIdx].val.d.estr, NULL);
+ if((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_PARSER)) == NULL) {
+ LogError(0, RS_RET_MOD_UNKNOWN, "parser module name '%s' is unknown", cnfModName);
+ ABORT_FINALIZE(RS_RET_MOD_UNKNOWN);
+ }
+ if(pMod->mod.pm.newParserInst == NULL) {
+ LogError(0, RS_RET_MOD_NO_PARSER_STMT,
+ "parser module '%s' does not support parser() statement", cnfModName);
+ ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT);
+ }
+ CHKiRet(pMod->mod.pm.newParserInst(o->nvlst, &parserInst));
+
+ /* all well, so let's (try) to add parser to config */
+ CHKiRet(parserConstructViaModAndName(pMod, parserName, parserInst));
+finalize_it:
+ free(cnfModName);
+ free(parserName);
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ RETiRet;
+}
+
+
+/* Process input() objects */
+static rsRetVal
+inputProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ modInfo_t *pMod;
+ uchar *cnfModName = NULL;
+ int typeIdx;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &inppblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ DBGPRINTF("input param blk after inputProcessCnf:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ typeIdx = cnfparamGetIdx(&inppblk, "type");
+ cnfModName = (uchar*)es_str2cstr(pvals[typeIdx].val.d.estr, NULL);
+ if((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_IN)) == NULL) {
+ LogError(0, RS_RET_MOD_UNKNOWN, "input module name '%s' is unknown", cnfModName);
+ ABORT_FINALIZE(RS_RET_MOD_UNKNOWN);
+ }
+ if(pMod->mod.im.newInpInst == NULL) {
+ LogError(0, RS_RET_MOD_NO_INPUT_STMT,
+ "input module '%s' does not support input() statement", cnfModName);
+ ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT);
+ }
+ iRet = pMod->mod.im.newInpInst(o->nvlst);
+finalize_it:
+ free(cnfModName);
+ cnfparamvalsDestruct(pvals, &inppblk);
+ RETiRet;
+}
+
+/*------------------------------ interface to flex/bison parser ------------------------------*/
+extern int yylineno;
+
+void
+parser_warnmsg(const char *fmt, ...)
+{
+ va_list ap;
+ char errBuf[1024];
+
+ va_start(ap, fmt);
+ if(vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf))
+ errBuf[sizeof(errBuf)-1] = '\0';
+ LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING,
+ "warning during parsing file %s, on or before line %d: %s",
+ cnfcurrfn, yylineno, errBuf);
+ va_end(ap);
+}
+
+void
+parser_errmsg(const char *fmt, ...)
+{
+ va_list ap;
+ char errBuf[1024];
+
+ va_start(ap, fmt);
+ if(vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf))
+ errBuf[sizeof(errBuf)-1] = '\0';
+ if(cnfcurrfn == NULL) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "error during config processing: %s", errBuf);
+ } else {
+ LogError(0, RS_RET_CONF_PARSE_ERROR,
+ "error during parsing file %s, on or before line %d: %s",
+ cnfcurrfn, yylineno, errBuf);
+ }
+ va_end(ap);
+}
+
+int yyerror(const char *s); /* we need this prototype to make compiler happy */
+int
+yyerror(const char *s)
+{
+ parser_errmsg("%s on token '%s'", s, yytext);
+ return 0;
+}
+void ATTR_NONNULL()
+cnfDoObj(struct cnfobj *const o)
+{
+ int bDestructObj = 1;
+ int bChkUnuse = 1;
+ assert(o != NULL);
+
+ dbgprintf("cnf:global:obj: ");
+ cnfobjPrint(o);
+
+ /* We need to check for object disabling as early as here to cover most
+ * of them at once and avoid needless initializations
+ * - jvymazal 2020-02-12
+ */
+ if (nvlstChkDisabled(o->nvlst)) {
+ dbgprintf("object disabled by configuration\n");
+ return;
+ }
+
+ switch(o->objType) {
+ case CNFOBJ_GLOBAL:
+ glblProcessCnf(o);
+ break;
+ case CNFOBJ_TIMEZONE:
+ glblProcessTimezone(o);
+ break;
+ case CNFOBJ_MAINQ:
+ glblProcessMainQCnf(o);
+ bDestructObj = 0;
+ break;
+ case CNFOBJ_MODULE:
+ modulesProcessCnf(o);
+ break;
+ case CNFOBJ_INPUT:
+ inputProcessCnf(o);
+ break;
+ case CNFOBJ_LOOKUP_TABLE:
+ lookupTableDefProcessCnf(o);
+ break;
+ case CNFOBJ_DYN_STATS:
+ dynstats_processCnf(o);
+ break;
+ case CNFOBJ_PERCTILE_STATS:
+ perctile_processCnf(o);
+ break;
+ case CNFOBJ_PARSER:
+ parserProcessCnf(o);
+ break;
+ case CNFOBJ_TPL:
+ if(tplProcessCnf(o) != RS_RET_OK)
+ parser_errmsg("error processing template object");
+ break;
+ case CNFOBJ_RULESET:
+ rulesetProcessCnf(o);
+ break;
+ case CNFOBJ_PROPERTY:
+ case CNFOBJ_CONSTANT:
+ /* these types are processed at a later stage */
+ bChkUnuse = 0;
+ break;
+ case CNFOBJ_ACTION:
+ default:
+ dbgprintf("cnfDoObj program error: unexpected object type %u\n",
+ o->objType);
+ break;
+ }
+ if(bDestructObj) {
+ if(bChkUnuse)
+ nvlstChkUnused(o->nvlst);
+ cnfobjDestruct(o);
+ }
+}
+
+void cnfDoScript(struct cnfstmt *script)
+{
+ dbgprintf("cnf:global:script\n");
+ ruleset.AddScript(ruleset.GetCurrent(loadConf), script);
+}
+
+void cnfDoCfsysline(char *ln)
+{
+ DBGPRINTF("cnf:global:cfsysline: %s\n", ln);
+ /* the legacy system needs the "$" stripped */
+ conf.cfsysline((uchar*) ln+1);
+ free(ln);
+}
+
+void cnfDoBSDTag(char *ln)
+{
+ DBGPRINTF("cnf:global:BSD tag: %s\n", ln);
+ LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
+ "BSD-style blocks are no longer supported in rsyslog, "
+ "see https://www.rsyslog.com/g/BSD for details and a "
+ "solution (Block '%s')", ln);
+ free(ln);
+}
+
+void cnfDoBSDHost(char *ln)
+{
+ DBGPRINTF("cnf:global:BSD host: %s\n", ln);
+ LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
+ "BSD-style blocks are no longer supported in rsyslog, "
+ "see https://www.rsyslog.com/g/BSD for details and a "
+ "solution (Block '%s')", ln);
+ free(ln);
+}
+/*------------------------------ end interface to flex/bison parser ------------------------------*/
+
+
+
+/* drop to specified group
+ * if something goes wrong, the function never returns
+ */
+static
+rsRetVal doDropPrivGid(rsconf_t *cnf)
+{
+ int res;
+ uchar szBuf[1024];
+ DEFiRet;
+
+ if(!cnf->globals.gidDropPrivKeepSupplemental) {
+ res = setgroups(0, NULL); /* remove all supplemental group IDs */
+ if(res) {
+ LogError(errno, RS_RET_ERR_DROP_PRIV,
+ "could not remove supplemental group IDs");
+ ABORT_FINALIZE(RS_RET_ERR_DROP_PRIV);
+ }
+ DBGPRINTF("setgroups(0, NULL): %d\n", res);
+ }
+ res = setgid(cnf->globals.gidDropPriv);
+ if(res) {
+ LogError(errno, RS_RET_ERR_DROP_PRIV,
+ "could not set requested group id %d via setgid()", cnf->globals.gidDropPriv);
+ ABORT_FINALIZE(RS_RET_ERR_DROP_PRIV);
+ }
+
+ DBGPRINTF("setgid(%d): %d\n", cnf->globals.gidDropPriv, res);
+ snprintf((char*)szBuf, sizeof(szBuf), "rsyslogd's groupid changed to %d",
+ cnf->globals.gidDropPriv);
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
+finalize_it:
+ RETiRet;
+}
+
+
+/* drop to specified user
+ * if something goes wrong, the function never returns
+ * Note that such an abort can cause damage to on-disk structures, so we should
+ * re-design the "interface" in the long term. -- rgerhards, 2008-11-19
+ */
+static void doDropPrivUid(rsconf_t *cnf)
+{
+ int res;
+ uchar szBuf[1024];
+ struct passwd *pw;
+ gid_t gid;
+
+ /* Try to set appropriate supplementary groups for this user.
+ * Failure is not fatal.
+ */
+ pw = getpwuid(cnf->globals.uidDropPriv);
+ if (pw) {
+ gid = getgid();
+ res = initgroups(pw->pw_name, gid);
+ DBGPRINTF("initgroups(%s, %ld): %d\n", pw->pw_name, (long) gid, res);
+ } else {
+ LogError(errno, NO_ERRCODE, "could not get username for userid '%d'",
+ cnf->globals.uidDropPriv);
+ }
+
+ res = setuid(cnf->globals.uidDropPriv);
+ if(res) {
+ /* if we can not set the userid, this is fatal, so let's unconditionally abort */
+ perror("could not set requested userid");
+ exit(1);
+ }
+
+ DBGPRINTF("setuid(%d): %d\n", cnf->globals.uidDropPriv, res);
+ snprintf((char*)szBuf, sizeof(szBuf), "rsyslogd's userid changed to %d", cnf->globals.uidDropPriv);
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
+}
+
+
+
+/* drop privileges. This will drop to the configured privileges, if
+ * set by the user. After this method has been executed, the previous
+ * privileges can no be re-gained.
+ */
+static rsRetVal
+dropPrivileges(rsconf_t *cnf)
+{
+ DEFiRet;
+
+ if(cnf->globals.gidDropPriv != 0) {
+ CHKiRet(doDropPrivGid(cnf));
+ DBGPRINTF("group privileges have been dropped to gid %u\n", (unsigned)
+ cnf->globals.gidDropPriv);
+ }
+
+ if(cnf->globals.uidDropPriv != 0) {
+ doDropPrivUid(cnf);
+ DBGPRINTF("user privileges have been dropped to uid %u\n", (unsigned)
+ cnf->globals.uidDropPriv);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* tell the rsysog core (including ourselfs) that the config load is done and
+ * we need to prepare to move over to activate mode.
+ */
+static inline rsRetVal
+tellCoreConfigLoadDone(void)
+{
+ DBGPRINTF("telling rsyslog core that config load for %p is done\n", loadConf);
+ return glblDoneLoadCnf();
+}
+
+
+/* Tell input modules that the config parsing stage is over. */
+static rsRetVal
+tellModulesConfigLoadDone(void)
+{
+ cfgmodules_etry_t *node;
+
+ DBGPRINTF("telling modules that config load for %p is done\n", loadConf);
+ node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY);
+ while(node != NULL) {
+ DBGPRINTF("beginCnfLoad(%p) for module '%s'\n", node->pMod->beginCnfLoad, node->pMod->pszName);
+ if(node->pMod->beginCnfLoad != NULL) {
+ DBGPRINTF("calling endCnfLoad() for module '%s'\n", node->pMod->pszName);
+ node->pMod->endCnfLoad(node->modCnf);
+ }
+ node = module.GetNxtCnfType(loadConf, node, eMOD_ANY); // loadConf -> runConf
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Tell input modules to verify config object */
+static rsRetVal
+tellModulesCheckConfig(void)
+{
+ cfgmodules_etry_t *node;
+ rsRetVal localRet;
+
+ DBGPRINTF("telling modules to check config %p\n", loadConf);
+ node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY);
+ while(node != NULL) {
+ if(node->pMod->beginCnfLoad != NULL) {
+ localRet = node->pMod->checkCnf(node->modCnf);
+ DBGPRINTF("module %s tells us config can %sbe activated\n",
+ node->pMod->pszName, (localRet == RS_RET_OK) ? "" : "NOT ");
+ if(localRet == RS_RET_OK) {
+ node->canActivate = 1;
+ } else {
+ node->canActivate = 0;
+ }
+ }
+ node = module.GetNxtCnfType(loadConf, node, eMOD_ANY); // runConf -> loadConf
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Tell modules to activate current running config (pre privilege drop) */
+static rsRetVal
+tellModulesActivateConfigPrePrivDrop(void)
+{
+ cfgmodules_etry_t *node;
+ rsRetVal localRet;
+
+ DBGPRINTF("telling modules to activate config (before dropping privs) %p\n", runConf);
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY);
+ while(node != NULL) {
+ if( node->pMod->beginCnfLoad != NULL
+ && node->pMod->activateCnfPrePrivDrop != NULL
+ && node->canActivate) {
+ DBGPRINTF("pre priv drop activating config %p for module %s\n",
+ runConf, node->pMod->pszName);
+ localRet = node->pMod->activateCnfPrePrivDrop(node->modCnf);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "activation of module %s failed",
+ node->pMod->pszName);
+ node->canActivate = 0; /* in a sense, could not activate... */
+ }
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_ANY);
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Tell modules to activate current running config */
+static rsRetVal
+tellModulesActivateConfig(void)
+{
+ cfgmodules_etry_t *node;
+ rsRetVal localRet;
+
+ DBGPRINTF("telling modules to activate config %p\n", runConf);
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY);
+ while(node != NULL) {
+ if(node->pMod->beginCnfLoad != NULL && node->canActivate) {
+ DBGPRINTF("activating config %p for module %s\n",
+ runConf, node->pMod->pszName);
+ localRet = node->pMod->activateCnf(node->modCnf);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "activation of module %s failed",
+ node->pMod->pszName);
+ node->canActivate = 0; /* in a sense, could not activate... */
+ }
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_ANY);
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Actually run the input modules. This happens after privileges are dropped,
+ * if that is requested.
+ */
+static rsRetVal
+runInputModules(void)
+{
+ cfgmodules_etry_t *node;
+ int bNeedsCancel;
+
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ if(node->canRun) {
+ bNeedsCancel = (node->pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination)
+ == RS_RET_OK) ? 0 : 1;
+ DBGPRINTF("running module %s with config %p, term mode: %s\n", node->pMod->pszName, node,
+ bNeedsCancel ? "cancel" : "cooperative/SIGTTIN");
+ thrdCreate(node->pMod->mod.im.runInput, node->pMod->mod.im.afterRun, bNeedsCancel,
+ (node->pMod->cnfName == NULL) ? node->pMod->pszName : node->pMod->cnfName);
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Make the modules check if they are ready to start.
+ */
+static rsRetVal
+startInputModules(void)
+{
+ DEFiRet;
+ cfgmodules_etry_t *node;
+
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ if(node->canActivate) {
+ iRet = node->pMod->mod.im.willRun();
+ node->canRun = (iRet == RS_RET_OK);
+ if(!node->canRun) {
+ DBGPRINTF("module %s will not run, iRet %d\n", node->pMod->pszName, iRet);
+ }
+ } else {
+ node->canRun = 0;
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
+ }
+
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+/* load the main queue */
+static rsRetVal
+loadMainQueue(void)
+{
+ DEFiRet;
+ struct cnfobj *mainqCnfObj;
+
+ mainqCnfObj = glbl.GetmainqCnfObj();
+ DBGPRINTF("loadMainQueue: mainq cnf obj ptr is %p\n", mainqCnfObj);
+ /* create message queue */
+ iRet = createMainQueue(&loadConf->pMsgQueue, UCHAR_CONSTANT("main Q"),
+ (mainqCnfObj == NULL) ? NULL : mainqCnfObj->nvlst);
+ if (iRet == RS_RET_OK) {
+ if (runConf != NULL) { /* dynamic config reload */
+ int areEqual = queuesEqual(loadConf->pMsgQueue, runConf->pMsgQueue);
+ DBGPRINTF("Comparison of old and new main queues: %d\n", areEqual);
+ if (areEqual) { /* content of the new main queue is the same as it was in previous conf */
+ qqueueDestruct(&loadConf->pMsgQueue);
+ loadConf->pMsgQueue = runConf->pMsgQueue;
+ }
+ }
+ }
+
+ if(iRet != RS_RET_OK) {
+ /* no queue is fatal, we need to give up in that case... */
+ fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
+ FINALIZE;
+ }
+finalize_it:
+ glblDestructMainqCnfObj();
+ RETiRet;
+}
+
+/* activate the main queue */
+static rsRetVal
+activateMainQueue(void)
+{
+ DEFiRet;
+
+ DBGPRINTF("activateMainQueue: will try to activate main queue %p\n", runConf->pMsgQueue);
+
+ iRet = startMainQueue(runConf, runConf->pMsgQueue);
+ if(iRet != RS_RET_OK) {
+ /* no queue is fatal, we need to give up in that case... */
+ fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
+ FINALIZE;
+ }
+
+ if(runConf->globals.mainQ.MainMsgQueType == QUEUETYPE_DIRECT) {
+ PREFER_STORE_0_TO_INT(&bHaveMainQueue);
+ } else {
+ PREFER_STORE_1_TO_INT(&bHaveMainQueue);
+ }
+ DBGPRINTF("Main processing queue is initialized and running\n");
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the processes umask (upon configuration request) */
+static inline rsRetVal
+setUmask(int iUmask)
+{
+ if(iUmask != -1) {
+ umask(iUmask);
+ DBGPRINTF("umask set to 0%3.3o.\n", iUmask);
+ }
+
+ return RS_RET_OK;
+}
+
+/* Remove resources from previous config */
+static void
+cleanupOldCnf(rsconf_t *cnf)
+{
+ if (cnf == NULL)
+ FINALIZE;
+
+ if (runConf->pMsgQueue != cnf->pMsgQueue)
+ qqueueDestruct(&cnf->pMsgQueue);
+
+finalize_it:
+ return;
+}
+
+
+/* Activate an already-loaded configuration. The configuration will become
+ * the new running conf (if successful). Note that in theory this method may
+ * be called when there already is a running conf. In practice, the current
+ * version of rsyslog does not support this. Future versions probably will.
+ * Begun 2011-04-20, rgerhards
+ */
+static rsRetVal
+activate(rsconf_t *cnf)
+{
+ DEFiRet;
+ rsconf_t *runCnfOld = runConf;
+
+ /* at this point, we "switch" over to the running conf */
+ runConf = cnf;
+ loadConf = NULL;
+# if 0 /* currently the DAG is not supported -- code missing! */
+ /* TODO: re-enable this functionality some time later! */
+ /* check if we need to generate a config DAG and, if so, do that */
+ if(ourConf->globals.pszConfDAGFile != NULL)
+ generateConfigDAG(ourConf->globals.pszConfDAGFile);
+# endif
+ setUmask(cnf->globals.umask);
+
+ /* the output part and the queue is now ready to run. So it is a good time
+ * to initialize the inputs. Please note that the net code above should be
+ * shuffled to down here once we have everything in input modules.
+ * rgerhards, 2007-12-14
+ * NOTE: as of 2009-06-29, the input modules are initialized, but not yet run.
+ * Keep in mind. though, that the outputs already run if the queue was
+ * persisted to disk. -- rgerhards
+ */
+ tellModulesActivateConfigPrePrivDrop();
+
+ CHKiRet(dropPrivileges(cnf));
+
+ lookupActivateConf();
+ tellModulesActivateConfig();
+ startInputModules();
+ CHKiRet(activateActions());
+ CHKiRet(activateRulesetQueues());
+ CHKiRet(activateMainQueue());
+ /* finally let the inputs run... */
+ runInputModules();
+ qqueueDoneLoadCnf(); /* we no longer need config-load-only data structures */
+
+ dbgprintf("configuration %p activated\n", cnf);
+ cleanupOldCnf(runCnfOld);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* -------------------- some legacy config handlers --------------------
+ * TODO: move to conf.c?
+ */
+
+/* legacy config system: set the action resume interval */
+static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ return actionSetGlobalResumeInterval(iNewVal);
+}
+
+
+/* Switch the default ruleset (that, what servcies bind to if nothing specific
+ * is specified).
+ * rgerhards, 2009-06-12
+ */
+static rsRetVal
+setDefaultRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ DEFiRet;
+
+ CHKiRet(ruleset.SetDefaultRuleset(ourConf, pszName));
+
+finalize_it:
+ free(pszName); /* no longer needed */
+ RETiRet;
+}
+
+
+/* Switch to either an already existing rule set or start a new one. The
+ * named rule set becomes the new "current" rule set (what means that new
+ * actions are added to it).
+ * rgerhards, 2009-06-12
+ */
+static rsRetVal
+setCurrRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ localRet = ruleset.SetCurrRuleset(ourConf, pszName);
+
+ if(localRet == RS_RET_NOT_FOUND) {
+ DBGPRINTF("begin new current rule set '%s'\n", pszName);
+ CHKiRet(ruleset.Construct(&pRuleset));
+ CHKiRet(ruleset.SetName(pRuleset, pszName));
+ CHKiRet(ruleset.ConstructFinalize(ourConf, pRuleset));
+ rulesetSetCurrRulesetPtr(pRuleset);
+ } else {
+ ABORT_FINALIZE(localRet);
+ }
+
+finalize_it:
+ free(pszName); /* no longer needed */
+ RETiRet;
+}
+
+
+/* set the main message queue mode
+ * rgerhards, 2008-01-03
+ */
+static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *pszType)
+{
+ DEFiRet;
+
+ if (!strcasecmp((char *) pszType, "fixedarray")) {
+ loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
+ DBGPRINTF("main message queue type set to FIXED_ARRAY\n");
+ } else if (!strcasecmp((char *) pszType, "linkedlist")) {
+ loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_LINKEDLIST;
+ DBGPRINTF("main message queue type set to LINKEDLIST\n");
+ } else if (!strcasecmp((char *) pszType, "disk")) {
+ loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DISK;
+ DBGPRINTF("main message queue type set to DISK\n");
+ } else if (!strcasecmp((char *) pszType, "direct")) {
+ loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DIRECT;
+ DBGPRINTF("main message queue type set to DIRECT (no queueing at all)\n");
+ } else {
+ LogError(0, RS_RET_INVALID_PARAMS, "unknown mainmessagequeuetype parameter: %s",
+ (char *) pszType);
+ iRet = RS_RET_INVALID_PARAMS;
+ }
+ free(pszType); /* no longer needed */
+
+ RETiRet;
+}
+
+
+/* -------------------- end legacy config handlers -------------------- */
+
+
+/* set the processes max number ob files (upon configuration request)
+ * 2009-04-14 rgerhards
+ */
+static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles)
+{
+// TODO this must use a local var, then carry out action during activate!
+ struct rlimit maxFiles;
+ char errStr[1024];
+ DEFiRet;
+
+ maxFiles.rlim_cur = iFiles;
+ maxFiles.rlim_max = iFiles;
+
+ if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
+ /* NOTE: under valgrind, we seem to be unable to extend the size! */
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ LogError(0, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d: %s "
+ "[kernel max %ld]", iFiles, errStr, (long) maxFiles.rlim_max);
+ ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE);
+ }
+#ifdef USE_UNLIMITED_SELECT
+ glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask));
+#endif
+ DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* legacy config system: reset config variables to default values. */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(loadConf->globals.mainQ.pszMainMsgQFName);
+
+ cnfSetDefaults(loadConf);
+
+ return RS_RET_OK;
+}
+
+
+/* legacy config system: set the action resume interval */
+static rsRetVal
+setModDir(void __attribute__((unused)) *pVal, uchar* pszNewVal)
+{
+ DEFiRet;
+ iRet = module.SetModDir(pszNewVal);
+ free(pszNewVal);
+ RETiRet;
+}
+
+
+/* "load" a build in module and register it for the current load config */
+static rsRetVal
+regBuildInModule(rsRetVal (*modInit)(), uchar *name, void *pModHdlr)
+{
+ cfgmodules_etry_t *pNew;
+ cfgmodules_etry_t *pLast;
+ modInfo_t *pMod;
+ DEFiRet;
+ CHKiRet(module.doModInit(modInit, name, pModHdlr, &pMod));
+ readyModForCnf(pMod, &pNew, &pLast);
+ addModToCnfList(&pNew, pLast);
+finalize_it:
+ RETiRet;
+}
+
+
+/* load build-in modules
+ * very first version begun on 2007-07-23 by rgerhards
+ */
+static rsRetVal
+loadBuildInModules(void)
+{
+ DEFiRet;
+
+ CHKiRet(regBuildInModule(modInitFile, UCHAR_CONSTANT("builtin:omfile"), NULL));
+ CHKiRet(regBuildInModule(modInitPipe, UCHAR_CONSTANT("builtin:ompipe"), NULL));
+ CHKiRet(regBuildInModule(modInitShell, UCHAR_CONSTANT("builtin-shell"), NULL));
+ CHKiRet(regBuildInModule(modInitDiscard, UCHAR_CONSTANT("builtin:omdiscard"), NULL));
+# ifdef SYSLOG_INET
+ CHKiRet(regBuildInModule(modInitFwd, UCHAR_CONSTANT("builtin:omfwd"), NULL));
+# endif
+
+ /* dirty, but this must be for the time being: the usrmsg module must always be
+ * loaded as last module. This is because it processes any type of action selector.
+ * If we load it before other modules, these others will never have a chance of
+ * working with the config file. We may change that implementation so that a user name
+ * must start with an alnum, that would definitely help (but would it break backwards
+ * compatibility?). * rgerhards, 2007-07-23
+ * User names now must begin with:
+ * [a-zA-Z0-9_.]
+ */
+ CHKiRet(regBuildInModule(modInitUsrMsg, (uchar*) "builtin:omusrmsg", NULL));
+
+ /* load build-in parser modules */
+ CHKiRet(regBuildInModule(modInitpmrfc5424, UCHAR_CONSTANT("builtin:pmrfc5424"), NULL));
+ CHKiRet(regBuildInModule(modInitpmrfc3164, UCHAR_CONSTANT("builtin:pmrfc3164"), NULL));
+
+ /* and set default parser modules. Order is *very* important, legacy
+ * (3164) parser needs to go last! */
+ CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc5424")));
+ CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc3164")));
+
+ /* load build-in strgen modules */
+ CHKiRet(regBuildInModule(modInitsmfile, UCHAR_CONSTANT("builtin:smfile"), NULL));
+ CHKiRet(regBuildInModule(modInitsmtradfile, UCHAR_CONSTANT("builtin:smtradfile"), NULL));
+ CHKiRet(regBuildInModule(modInitsmfwd, UCHAR_CONSTANT("builtin:smfwd"), NULL));
+ CHKiRet(regBuildInModule(modInitsmtradfwd, UCHAR_CONSTANT("builtin:smtradfwd"), NULL));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* we need to do fprintf, as we do not yet have an error reporting system
+ * in place.
+ */
+ fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
+ iRet);
+ }
+ RETiRet;
+}
+
+
+/* intialize the legacy config system */
+static rsRetVal
+initLegacyConf(void)
+{
+ DEFiRet;
+ uchar *pTmp;
+ ruleset_t *pRuleset;
+
+ DBGPRINTF("doing legacy config system init\n");
+ /* construct the default ruleset */
+ ruleset.Construct(&pRuleset);
+ ruleset.SetName(pRuleset, UCHAR_CONSTANT("RSYSLOG_DefaultRuleset"));
+ ruleset.ConstructFinalize(loadConf, pRuleset);
+ rulesetSetCurrRulesetPtr(pRuleset);
+
+ /* now register config handlers */
+ CHKiRet(regCfSysLineHdlr((uchar *)"sleep", 0, eCmdHdlrGoneAway,
+ NULL, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.bLogStatusMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"errormessagestostderr", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.bErrMsgToStderr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"abortonuncleanconfig", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.bAbortOnUncleanConfig, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.bReduceRepeatMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary,
+ NULL, &(loadConf->globals.bDebugPrintTemplateList), NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary,
+ NULL, &(loadConf->globals.bDebugPrintModuleList), NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
+ NULL, &(loadConf->globals.bDebugPrintCfSysLineHandlerList), NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouser", 0, eCmdHdlrUID,
+ NULL, &loadConf->globals.uidDropPriv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouserid", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.uidDropPriv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroup", 0, eCmdHdlrGID,
+ NULL, &loadConf->globals.gidDropPriv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroupid", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.gidDropPriv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"generateconfiggraph", 0, eCmdHdlrGetWord,
+ NULL, &loadConf->globals.pszConfDAGFile, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode,
+ NULL, &loadConf->globals.umask, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"maxopenfiles", 0, eCmdHdlrInt,
+ setMaxFiles, NULL, NULL));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt,
+ setActionResumeInterval, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler,
+ conf.doModLoad, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord,
+ setDefaultRuleset, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord,
+ setCurrRuleset, NULL, NULL));
+
+ /* handler for "larger" config statements (tie into legacy conf system) */
+ CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler,
+ conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler,
+ conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler,
+ conf.doNameLine, (void*)DIR_ALLOWEDSENDER, NULL));
+
+ /* the following are parameters for the main message queue. I have the
+ * strong feeling that this needs to go to a different space, but that
+ * feeling may be wrong - we'll see how things evolve.
+ * rgerhards, 2011-04-21
+ */
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord,
+ NULL, &loadConf->globals.mainQ.pszMainMsgQFName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueueSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQHighWtrMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQLowWtrMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQDiscardMark, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity,
+ NULL, &loadConf->globals.mainQ.iMainMsgQDiscardSeverity, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQPersistUpdCnt, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesyncqueuefiles", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.mainQ.bMainMsgQSyncQeueFiles, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord,
+ setMainMsgQueType, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueueNumWorkers, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQtoQShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQtoActShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQtoEnq, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQtoWrkShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQDeqSlowdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQWrkMinMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueMaxFileSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuebatchsize", 0, eCmdHdlrSize,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueDeqBatchSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueMaxDiskSpace, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary,
+ NULL, &loadConf->globals.mainQ.bMainMsgQSaveOnShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt,
+ NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinToHr, NULL));
+ /* moddir is a bit hard problem -- because it actually needs to
+ * modify a setting that is specific to module.c. The important point
+ * is that this action MUST actually be carried out during config load,
+ * because we must load modules in order to get their config extensions
+ * (no way around).
+ * TODO: think about a clean solution
+ */
+ CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord,
+ setModDir, NULL, NULL));
+
+ /* finally, the reset handler */
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, NULL));
+
+ /* initialize the build-in templates */
+ pTmp = template_DebugFormat;
+ tplAddLine(ourConf, "RSYSLOG_DebugFormat", &pTmp);
+ pTmp = template_SyslogProtocol23Format;
+ tplAddLine(ourConf, "RSYSLOG_SyslogProtocol23Format", &pTmp);
+ pTmp = template_SyslogRFC5424Format;
+ tplAddLine(ourConf, "RSYSLOG_SyslogRFC5424Format", &pTmp);
+ pTmp = template_FileFormat; /* new format for files with high-precision stamp */
+ tplAddLine(ourConf, "RSYSLOG_FileFormat", &pTmp);
+ pTmp = template_TraditionalFileFormat;
+ tplAddLine(ourConf, "RSYSLOG_TraditionalFileFormat", &pTmp);
+ pTmp = template_WallFmt;
+ tplAddLine(ourConf, " WallFmt", &pTmp);
+ pTmp = template_ForwardFormat;
+ tplAddLine(ourConf, "RSYSLOG_ForwardFormat", &pTmp);
+ pTmp = template_TraditionalForwardFormat;
+ tplAddLine(ourConf, "RSYSLOG_TraditionalForwardFormat", &pTmp);
+ pTmp = template_StdUsrMsgFmt;
+ tplAddLine(ourConf, " StdUsrMsgFmt", &pTmp);
+ pTmp = template_StdDBFmt;
+ tplAddLine(ourConf, " StdDBFmt", &pTmp);
+ pTmp = template_SysklogdFileFormat;
+ tplAddLine(ourConf, "RSYSLOG_SysklogdFileFormat", &pTmp);
+ pTmp = template_StdPgSQLFmt;
+ tplAddLine(ourConf, " StdPgSQLFmt", &pTmp);
+ pTmp = template_StdJSONFmt;
+ tplAddLine(ourConf, " StdJSONFmt", &pTmp);
+ pTmp = template_FullJSONFmt;
+ tplAddLine(ourConf, " FullJSONFmt", &pTmp);
+ pTmp = template_StdClickHouseFmt;
+ tplAddLine(ourConf, " StdClickHouseFmt", &pTmp);
+ pTmp = template_spoofadr;
+ tplLastStaticInit(ourConf, tplAddLine(ourConf, "RSYSLOG_omudpspoofDfltSourceTpl", &pTmp));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* validate the configuration pointed by conf, generate error messages, do
+ * optimizations, etc, etc,...
+ */
+static rsRetVal
+validateConf(rsconf_t *cnf)
+{
+ DEFiRet;
+
+ /* some checks */
+ if(cnf->globals.mainQ.iMainMsgQueueNumWorkers < 1) {
+ LogError(0, NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n");
+ cnf->globals.mainQ.iMainMsgQueueNumWorkers = 1;
+ }
+
+ if(cnf->globals.mainQ.MainMsgQueType == QUEUETYPE_DISK) {
+ errno = 0; /* for logerror! */
+ if(glbl.GetWorkDir(cnf) == NULL) {
+ LogError(0, NO_ERRCODE, "No $WorkDirectory specified - can not run main "
+ "message queue in 'disk' mode. Using 'FixedArray' instead.\n");
+ cnf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
+ }
+ if(cnf->globals.mainQ.pszMainMsgQFName == NULL) {
+ LogError(0, NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main "
+ "message queue in 'disk' mode. Using 'FixedArray' instead.\n");
+ cnf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
+ }
+ }
+ RETiRet;
+}
+
+
+/* Load a configuration. This will do all necessary steps to create
+ * the in-memory representation of the configuration, including support
+ * for multiple configuration languages.
+ * Note that to support the legacy language we must provide some global
+ * object that holds the currently-being-loaded config ptr.
+ * Begun 2011-04-20, rgerhards
+ */
+static rsRetVal
+load(rsconf_t **cnf, uchar *confFile)
+{
+ int iNbrActions = 0;
+ int r;
+ rsRetVal delayed_iRet = RS_RET_OK;
+ DEFiRet;
+
+ CHKiRet(rsconfConstruct(&loadConf));
+ ourConf = loadConf; // TODO: remove, once ourConf is gone!
+
+ CHKiRet(loadBuildInModules());
+ CHKiRet(initLegacyConf());
+
+ /* open the configuration file */
+ r = cnfSetLexFile((char*)confFile);
+ if(r == 0) {
+ r = yyparse();
+ conf.GetNbrActActions(loadConf, &iNbrActions);
+ }
+
+ /* we run the optimizer even if we have an error, as it may spit out
+ * additional error messages and we want to see these even if we abort.
+ */
+ rulesetOptimizeAll(loadConf);
+
+ if(r == 1) {
+ LogError(0, RS_RET_CONF_PARSE_ERROR, "could not interpret master "
+ "config file '%s'.", confFile);
+ /* we usually keep running with the failure, so we need to continue for now */
+ delayed_iRet = RS_RET_CONF_PARSE_ERROR;
+ } else if(r == 2) { /* file not found? */
+ LogError(errno, RS_RET_CONF_FILE_NOT_FOUND, "could not open config file '%s'",
+ confFile);
+ ABORT_FINALIZE(RS_RET_CONF_FILE_NOT_FOUND);
+ } else if( (iNbrActions == 0)
+ && !(iConfigVerify & CONF_VERIFY_PARTIAL_CONF)) {
+ LogError(0, RS_RET_NO_ACTIONS, "there are no active actions configured. "
+ "Inputs would run, but no output whatsoever were created.");
+ ABORT_FINALIZE(RS_RET_NO_ACTIONS);
+ }
+ tellLexEndParsing();
+ DBGPRINTF("Number of actions in this configuration: %d\n", loadConf->actions.iActionNbr);
+
+ CHKiRet(tellCoreConfigLoadDone());
+ tellModulesConfigLoadDone();
+
+ tellModulesCheckConfig();
+ CHKiRet(validateConf(loadConf));
+ CHKiRet(loadMainQueue());
+
+ /* we are done checking the config - now validate if we should actually run or not.
+ * If not, terminate. -- rgerhards, 2008-07-25
+ * TODO: iConfigVerify -- should it be pulled from the config, or leave as is (option)?
+ */
+ if(iConfigVerify) {
+ if(iRet == RS_RET_OK)
+ iRet = RS_RET_VALIDATION_RUN;
+ FINALIZE;
+ }
+
+ /* all OK, pass loaded conf to caller */
+ *cnf = loadConf;
+ // TODO: enable this once all config code is moved to here! loadConf = NULL;
+
+ dbgprintf("rsyslog finished loading master config %p\n", loadConf);
+ rsconfDebugPrint(loadConf);
+
+finalize_it:
+ if(iRet == RS_RET_OK && delayed_iRet != RS_RET_OK) {
+ iRet = delayed_iRet;
+ }
+ RETiRet;
+}
+
+
+/* queryInterface function
+ */
+BEGINobjQueryInterface(rsconf)
+CODESTARTobjQueryInterface(rsconf)
+ if(pIf->ifVersion != rsconfCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Destruct = rsconfDestruct;
+ pIf->DebugPrint = rsconfDebugPrint;
+ pIf->Load = load;
+ pIf->Activate = activate;
+finalize_it:
+ENDobjQueryInterface(rsconf)
+
+
+/* Initialize the rsconf class. Must be called as the very first method
+ * before anything else is called inside this class.
+ */
+BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(module, CORE_COMPONENT));
+ CHKiRet(objUse(conf, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+
+ /* now set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, rsconfDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, rsconfConstructFinalize);
+ENDObjClassInit(rsconf)
+
+
+/* De-initialize the rsconf class.
+ */
+BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(module, CORE_COMPONENT);
+ objRelease(conf, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ENDObjClassExit(rsconf)
diff --git a/runtime/rsconf.h b/runtime/rsconf.h
new file mode 100644
index 0000000..453861e
--- /dev/null
+++ b/runtime/rsconf.h
@@ -0,0 +1,299 @@
+/* The rsconf object. It models a complete rsyslog configuration.
+ *
+ * Copyright 2011-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef INCLUDED_RSCONF_H
+#define INCLUDED_RSCONF_H
+
+#include "linkedlist.h"
+#include "queue.h"
+#include "lookup.h"
+#include "dynstats.h"
+#include "perctile_stats.h"
+#include "timezones.h"
+
+/* --- configuration objects (the plan is to have ALL upper layers in this file) --- */
+
+#define REPORT_CHILD_PROCESS_EXITS_NONE 0
+#define REPORT_CHILD_PROCESS_EXITS_ERRORS 1
+#define REPORT_CHILD_PROCESS_EXITS_ALL 2
+
+#ifndef DFLT_INT_MSGS_SEV_FILTER
+ #define DFLT_INT_MSGS_SEV_FILTER 6 /* Warning level and more important */
+#endif
+
+/* queue config parameters. TODO: move to queue.c? */
+struct queuecnf_s {
+ int iMainMsgQueueSize; /* size of the main message queue above */
+ int iMainMsgQHighWtrMark; /* high water mark for disk-assisted queues */
+ int iMainMsgQLowWtrMark; /* low water mark for disk-assisted queues */
+ int iMainMsgQDiscardMark; /* begin to discard messages */
+ int iMainMsgQDiscardSeverity; /* by default, discard nothing to prevent unintentional loss */
+ int iMainMsgQueueNumWorkers; /* number of worker threads for the mm queue above */
+ queueType_t MainMsgQueType; /* type of the main message queue above */
+ uchar *pszMainMsgQFName; /* prefix for the main message queue file */
+ int64 iMainMsgQueMaxFileSize;
+ int iMainMsgQPersistUpdCnt; /* persist queue info every n updates */
+ int bMainMsgQSyncQeueFiles; /* sync queue files on every write? */
+ int iMainMsgQtoQShutdown; /* queue shutdown (ms) */
+ int iMainMsgQtoActShutdown; /* action shutdown (in phase 2) */
+ int iMainMsgQtoEnq; /* timeout for queue enque */
+ int iMainMsgQtoWrkShutdown; /* timeout for worker thread shutdown */
+ int iMainMsgQWrkMinMsgs; /* minimum messages per worker needed to start a new one */
+ int iMainMsgQDeqSlowdown; /* dequeue slowdown (simple rate limiting) */
+ int64 iMainMsgQueMaxDiskSpace; /* max disk space allocated 0 ==> unlimited */
+ int64 iMainMsgQueDeqBatchSize; /* dequeue batch size */
+ int bMainMsgQSaveOnShutdown; /* save queue on shutdown (when DA enabled)? */
+ int iMainMsgQueueDeqtWinFromHr; /* hour begin of time frame when queue is to be dequeued */
+ int iMainMsgQueueDeqtWinToHr; /* hour begin of time frame when queue is to be dequeued */
+};
+
+/* parser config parameters */
+struct parsercnf_s {
+ uchar cCCEscapeChar; /* character to be used to start an escape sequence for control chars */
+ int bDropTrailingLF; /* drop trailing LF's on reception? */
+ int bEscapeCCOnRcv; /* escape control characters on reception: 0 - no, 1 - yes */
+ int bSpaceLFOnRcv; /* replace newlines with spaces on reception: 0 - no, 1 - yes */
+ int bEscape8BitChars; /* escape characters > 127 on reception: 0 - no, 1 - yes */
+ int bEscapeTab; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */
+ int bParserEscapeCCCStyle; /* escape control characters in c style: 0 - no, 1 - yes */
+ int bPermitSlashInProgramname;
+ int bParseHOSTNAMEandTAG; /* parser modification (based on startup params!) */
+};
+
+/* globals are data items that are really global, and can be set only
+ * once (at least in theory, because the legacy system permits them to
+ * be re-set as often as the user likes).
+ */
+struct globals_s {
+#ifdef ENABLE_LIBCAPNG
+ int bAbortOnFailedLibcapngSetup;
+ int bCapabilityDropEnabled;
+#endif
+ int bDebugPrintTemplateList;
+ int bDebugPrintModuleList;
+ int bDebugPrintCfSysLineHandlerList;
+ int bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */
+ int bErrMsgToStderr; /* print error messages to stderr
+ (in addition to everything else)? */
+ int maxErrMsgToStderr; /* how many messages to forward at most to stderr? */
+ int bAbortOnUncleanConfig; /* abort run (rather than starting with partial
+ config) if there was any issue in conf */
+ int bAbortOnFailedQueueStartup; /* similar to bAbortOnUncleanConfig, but abort if a queue
+ startup fails. This is not exactly an unclan config. */
+ int uidDropPriv; /* user-id to which priveleges should be dropped to */
+ int gidDropPriv; /* group-id to which priveleges should be dropped to */
+ int gidDropPrivKeepSupplemental; /* keep supplemental groups when dropping? */
+ int abortOnIDResolutionFail;
+ int umask; /* umask to use */
+ uchar *pszConfDAGFile; /* name of config DAG file, non-NULL means generate one */
+ uchar *pszWorkDir;
+ int bDropMalPTRMsgs;/* Drop messages which have malicious PTR records during DNS lookup */
+ uchar *operatingStateFile;
+ int debugOnShutdown; /* start debug log when we are shut down */
+ int iGnuTLSLoglevel;/* Sets GNUTLS Debug Level */
+ uchar *pszDfltNetstrmDrvrCAF; /* default CA file for the netstrm driver */
+ uchar *pszDfltNetstrmDrvrCRLF; /* default CRL file for the netstrm driver */
+ uchar *pszDfltNetstrmDrvrCertFile;/* default cert file for the netstrm driver (server) */
+ uchar *pszDfltNetstrmDrvrKeyFile; /* default key file for the netstrm driver (server) */
+ uchar *pszDfltNetstrmDrvr; /* module name of default netstream driver */
+ uchar *pszNetstrmDrvrCAExtraFiles; /* CA extra file for the netstrm driver */
+ uchar *oversizeMsgErrorFile; /* File where oversize messages are written to */
+ int reportOversizeMsg; /* shall error messages be generated for oversize messages? */
+ int oversizeMsgInputMode; /* Mode which oversize messages will be forwarded */
+ int reportChildProcessExits;
+ int bActionReportSuspension;
+ int bActionReportSuspensionCont;
+ short janitorInterval; /* interval (in minutes) at which the janitor runs */
+ int reportNewSenders;
+ int reportGoneAwaySenders;
+ int senderStatsTimeout;
+ int senderKeepTrack; /* keep track of known senders? */
+ int inputTimeoutShutdown; /* input shutdown timeout in ms */
+ int iDefPFFamily; /* protocol family (IPv4, IPv6 or both) */
+ int ACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */
+ int ACLDontResolve; /* add hostname to acl instead of resolving it to IP(s) */
+ int bDisableDNS; /* don't look up IP addresses of remote messages */
+ int bProcessInternalMessages; /* Should rsyslog itself process internal messages?
+ * 1 - yes
+ * 0 - send them to libstdlog (e.g. to push to journal) or syslog()
+ */
+ uint64_t glblDevOptions; /* to be used by developers only */
+ int intMsgRateLimitItv;
+ int intMsgRateLimitBurst;
+ int intMsgsSeverityFilter;/* filter for logging internal messages by syslog sev. */
+ int permitCtlC;
+
+ int actq_dflt_toQShutdown; /* queue shutdown */
+ int actq_dflt_toActShutdown; /* action shutdown (in phase 2) */
+ int actq_dflt_toEnq; /* timeout for queue enque */
+ int actq_dflt_toWrkShutdown; /* timeout for worker thread shutdown */
+
+ int ruleset_dflt_toQShutdown; /* queue shutdown */
+ int ruleset_dflt_toActShutdown; /* action shutdown (in phase 2) */
+ int ruleset_dflt_toEnq; /* timeout for queue enque */
+ int ruleset_dflt_toWrkShutdown; /* timeout for worker thread shutdown */
+
+ unsigned dnscacheDefaultTTL; /* 24 hrs default TTL */
+ int dnscacheEnableTTL; /* expire entries or not (0) ? */
+ int shutdownQueueDoubleSize;
+ int optionDisallowWarning; /* complain if message from disallowed sender is received */
+ int bSupportCompressionExtension;
+ #ifdef ENABLE_LIBLOGGING_STDLOG
+ stdlog_channel_t stdlog_hdl; /* handle to be used for stdlog */
+ uchar *stdlog_chanspec;
+ #endif
+ int iMaxLine; /* maximum length of a syslog message */
+
+ // TODO are the following ones defaults?
+ int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
+
+ //TODO: other representation for main queue? Or just load it differently?
+ queuecnf_t mainQ; /* main queue parameters */
+ parsercnf_t parser; /* parser parameters */
+};
+
+/* (global) defaults are global in the sense that they are accessible
+ * to all code, but they can change value and other objects (like
+ * actions) actually copy the value a global had at the time the action
+ * was defined. In that sense, a global default is just that, a default,
+ * wich can (and will) be changed in the course of config file
+ * processing. Once the config file has been processed, defaults
+ * can be dropped. The current code does not do this for simplicity.
+ * That is not a problem, because the defaults do not take up much memory.
+ * At a later stage, we may think about dropping them. -- rgerhards, 2011-04-19
+ */
+struct defaults_s {
+ int remove_me_when_first_real_member_is_added;
+};
+
+
+/* list of modules loaded in this configuration (config specific module list) */
+struct cfgmodules_etry_s {
+ cfgmodules_etry_t *next;
+ modInfo_t *pMod;
+ void *modCnf; /* pointer to the input module conf */
+ /* the following data is input module specific */
+ sbool canActivate; /* OK to activate this config? */
+ sbool canRun; /* OK to run this config? */
+};
+
+struct cfgmodules_s {
+ cfgmodules_etry_t *root;
+};
+
+/* outchannel-specific data */
+struct outchannels_s {
+ struct outchannel *ochRoot; /* the root of the outchannel list */
+ struct outchannel *ochLast; /* points to the last element of the outchannel list */
+};
+
+struct templates_s {
+ struct template *root; /* the root of the template list */
+ struct template *last; /* points to the last element of the template list */
+ struct template *lastStatic; /* last static element of the template list */
+};
+
+struct parsers_s {
+ /* This is the list of all parsers known to us.
+ * This is also used to unload all modules on shutdown.
+ */
+ parserList_t *pParsLstRoot;
+
+ /* this is the list of the default parsers, to be used if no others
+ * are specified.
+ */
+ parserList_t *pDfltParsLst;
+};
+
+struct actions_s {
+ /* number of active actions */
+ unsigned nbrActions;
+ /* number of actions created. It is used to obtain unique IDs for the action. They
+ * should not be relied on for any long-term activity (e.g. disk queue names!), but they are nice
+ * to have during one instance of an rsyslogd run. For example, I use them to name actions when there
+ * is no better name available.
+ */
+ int iActionNbr;
+};
+
+
+struct rulesets_s {
+ linkedList_t llRulesets; /* this is NOT a pointer - no typo here ;) */
+
+ /* support for legacy rsyslog.conf format */
+ ruleset_t *pCurr; /* currently "active" ruleset */
+ ruleset_t *pDflt; /* current default ruleset, e.g. for binding to actions which have no other */
+};
+
+
+/* --- end configuration objects --- */
+
+/* the rsconf object */
+struct rsconf_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ cfgmodules_t modules;
+ globals_t globals;
+ defaults_t defaults;
+ templates_t templates;
+ parsers_t parsers;
+ lookup_tables_t lu_tabs;
+ dynstats_buckets_t dynstats_buckets;
+ perctile_buckets_t perctile_buckets;
+ outchannels_t och;
+ actions_t actions;
+ rulesets_t rulesets;
+ /* note: rulesets include the complete output part:
+ * - rules
+ * - filter (as part of the action)
+ * - actions
+ * Of course, we need to debate if we shall change that some time...
+ */
+ timezones_t timezones;
+ qqueue_t *pMsgQueue; /* the main message queue */
+};
+
+
+/* interfaces */
+BEGINinterface(rsconf) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(rsconf);
+ rsRetVal (*Destruct)(rsconf_t **ppThis);
+ rsRetVal (*Load)(rsconf_t **ppThis, uchar *confFile);
+ rsRetVal (*Activate)(rsconf_t *ppThis);
+ENDinterface(rsconf)
+// TODO: switch version to 1 for first "complete" version!!!! 2011-04-20
+#define rsconfCURR_IF_VERSION 0 /* increment whenever you change the interface above! */
+
+
+/* prototypes */
+PROTOTYPEObj(rsconf);
+
+/* globally-visible external data */
+extern rsconf_t *runConf;/* the currently running config */
+extern rsconf_t *loadConf;/* the config currently being loaded (no concurrent config load supported!) */
+
+
+int rsconfNeedDropPriv(rsconf_t *const cnf);
+
+/* some defaults (to be removed?) */
+#define DFLT_bLogStatusMsgs 1
+
+#endif /* #ifndef INCLUDED_RSCONF_H */
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
new file mode 100644
index 0000000..9b4c4c2
--- /dev/null
+++ b/runtime/rsyslog.c
@@ -0,0 +1,298 @@
+/* rsyslog.c - the main entry point into rsyslog's runtime library (RTL)
+ *
+ * This module contains all function which work on a RTL global level. It's
+ * name is abbreviated to "rsrt" (rsyslog runtime).
+ *
+ * Please note that the runtime library tends to be plugin-safe. That is, it must be
+ * initialized by calling a global initialization function. However, that
+ * function checks if the library is already initialized and, if so, does
+ * nothing except incrementing a refeence count. Similarly, the deinit
+ * function does nothing as long as there are still other users (which
+ * is tracked via the refcount). As such, it is safe to call init and
+ * exit multiple times, as long as this are always matching calls. This
+ * capability is needed for a plugin system, where one plugin never
+ * knows what the other did. HOWEVER, as of this writing, not all runtime
+ * library objects may work cleanly without static global data (the
+ * debug system is a very good example of this). So while we aim at the
+ * ability to work well in a plugin environment, things may not really work
+ * out. If you intend to use the rsyslog runtime library inside plugins,
+ * you should investigate the situation in detail. Please note that the
+ * rsyslog project itself does not yet need this functionality - thus you
+ * can safely assume it is totally untested ;).
+ *
+ * rgerhards, 2008-04-17: I have now once again checked on the plugin-safety.
+ * Unfortunately, there is currently no hook at all with which we could
+ * abstract a global data instance class. As such, we can NOT make the
+ * runtime plugin-safe in the above-described sense. As the rsyslog
+ * project itself does not need this functionality (and it is quesationable
+ * if someone else ever will), we do currently do not make an effort to
+ * support it. So if you intend to use rsyslog runtime inside a non-rsyslog
+ * plugin system, be careful!
+ *
+ * The rsyslog runtime library is in general reentrant and thread-safe. There
+ * are some intentional exceptions (e.g. inside the msg object). These are
+ * documented. Any other threading and reentrency issue can be considered a bug.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#ifdef ENABLE_LIBLOGGING_STDLOG
+#include <liblogging/stdlog.h>
+#endif
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "stringbuf.h"
+#include "wti.h"
+#include "wtp.h"
+#include "datetime.h"
+#include "queue.h"
+#include "conf.h"
+#include "rsconf.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "prop.h"
+#include "ruleset.h"
+#include "parser.h"
+#include "lookup.h"
+#include "strgen.h"
+#include "statsobj.h"
+#include "atomic.h"
+#include "srUtils.h"
+
+pthread_attr_t default_thread_attr;
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+struct sched_param default_sched_param;
+int default_thr_sched_policy;
+#endif
+
+/* globally visible static data - see comment in rsyslog.h for details */
+uchar *glblModPath; /* module load path */
+void (*glblErrLogger)(const int, const int, const uchar*) = dfltErrLogger;
+/* the error logger to use by the errmsg module */
+
+/* static data */
+static int iRefCount = 0; /* our refcount - it MUST exist only once inside a process (not thread)
+ thus it is perfectly OK to use a static. MUST be initialized to 0! */
+
+/* This is the default instance of the error logger. It simply writes the message
+ * to stderr. It is expected that this is replaced by the runtime user very early
+ * during startup (at least if the default is unsuitable). However, we provide a
+ * default so that we can log errors during the intial phase, most importantly
+ * during initialization. -- rgerhards. 2008-04-17
+ */
+void
+dfltErrLogger(const int severity, const int iErr, const uchar *errMsg)
+{
+ fprintf(stderr, "rsyslog internal message (%d,%d): %s\n", severity, iErr, errMsg);
+}
+
+
+/* set the error log function
+ * rgerhards, 2008-04-18
+ */
+void
+rsrtSetErrLogger(void (*errLogger)(const int, const int, const uchar*))
+{
+ assert(errLogger != NULL);
+ glblErrLogger = errLogger;
+}
+
+
+/* globally initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * If ppErrObj is provided, it receives a char pointer to the name of the object that
+ * caused the problem (if one occurred). The caller must never free this pointer. If
+ * ppErrObj is NULL, no such information will be provided. pObjIF is the pointer to
+ * the "obj" object interface, which may be used to query any other rsyslog objects.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtInit(const char **ppErrObj, obj_if_t *pObjIF)
+{
+ DEFiRet;
+ int ret;
+ char errstr[1024];
+
+ if(iRefCount == 0) {
+ seedRandomNumber();
+ /* init runtime only if not yet done */
+#ifdef ENABLE_LIBLOGGING_STDLOG
+ stdlog_init(0);
+#endif
+ ret = pthread_attr_init(&default_thread_attr);
+ if(ret != 0) {
+ rs_strerror_r(ret, errstr, sizeof(errstr));
+ fprintf(stderr, "rsyslogd: pthread_attr_init failed during "
+ "startup - can not continue. Error was %s\n", errstr);
+ exit(1);
+ }
+ pthread_attr_setstacksize(&default_thread_attr, 4096*1024);
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ ret = pthread_getschedparam(pthread_self(), &default_thr_sched_policy,
+ &default_sched_param);
+ if(ret != 0) {
+ rs_strerror_r(ret, errstr, sizeof(errstr));
+ fprintf(stderr, "rsyslogd: pthread_getschedparam failed during "
+ "startup - ignoring. Error was %s\n", errstr);
+ default_thr_sched_policy = 0; /* should be default on all platforms */
+ }
+#if defined (_AIX)
+ pthread_attr_setstacksize(&default_thread_attr, 4096*512);
+#endif
+
+
+ ret = pthread_attr_setschedpolicy(&default_thread_attr, default_thr_sched_policy);
+ if(ret != 0) {
+ rs_strerror_r(ret, errstr, sizeof(errstr));
+ fprintf(stderr, "rsyslogd: pthread_attr_setschedpolicy failed during "
+ "startup - tried to set priority %d, now using default "
+ "priority instead. Error was: %s\n",
+ default_thr_sched_policy, errstr);
+ }
+ ret = pthread_attr_setschedparam(&default_thread_attr, &default_sched_param);
+ if(ret != 0) {
+ rs_strerror_r(ret, errstr, sizeof(errstr));
+ fprintf(stderr, "rsyslogd: pthread_attr_setschedparam failed during "
+ "startup - ignored Error was: %s\n", errstr);
+ }
+ ret = pthread_attr_setinheritsched(&default_thread_attr, PTHREAD_EXPLICIT_SCHED);
+ if(ret != 0) {
+ rs_strerror_r(ret, errstr, sizeof(errstr));
+ fprintf(stderr, "rsyslogd: pthread_attr_setinheritsched failed during "
+ "startup - ignoring. Error was: %s\n", errstr);
+ }
+#endif
+ if(ppErrObj != NULL) *ppErrObj = "obj";
+ CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
+ CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */
+
+ /* initialize core classes. We must be very careful with the order of events. Some
+ * classes use others and if we do not initialize them in the right order, we may end
+ * up with an invalid call. The most important thing that can happen is that an error
+ * is detected and needs to be logged, wich in turn requires a broader number of classes
+ * to be available. The solution is that we take care in the order of calls AND use a
+ * class immediately after it is initialized. And, of course, we load those classes
+ * first that we use ourselfs... -- rgerhards, 2008-03-07
+ */
+ if(ppErrObj != NULL) *ppErrObj = "statsobj";
+ CHKiRet(statsobjClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "prop";
+ CHKiRet(propClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "glbl";
+ CHKiRet(glblClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "msg";
+ CHKiRet(msgClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "ruleset";
+ CHKiRet(rulesetClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wti";
+ CHKiRet(wtiClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wtp";
+ CHKiRet(wtpClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "queue";
+ CHKiRet(qqueueClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "conf";
+ CHKiRet(confClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "parser";
+ CHKiRet(parserClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "strgen";
+ CHKiRet(strgenClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "rsconf";
+ CHKiRet(rsconfClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "lookup";
+ CHKiRet(lookupClassInit());
+ if(ppErrObj != NULL) *ppErrObj = "dynstats";
+ CHKiRet(dynstatsClassInit());
+ if(ppErrObj != NULL) *ppErrObj = "perctile_stats";
+ CHKiRet(perctileClassInit());
+
+ /* dummy "classes" */
+ if(ppErrObj != NULL) *ppErrObj = "str";
+ CHKiRet(strInit());
+ }
+
+ ++iRefCount;
+ dbgprintf("rsyslog runtime initialized, version %s, current users %d\n", VERSION, iRefCount);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* globally de-initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * This function must be provided with the caller's obj object pointer. This is
+ * automatically deinitialized by the runtime system.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtExit(void)
+{
+ DEFiRet;
+
+ if(iRefCount == 1) {
+ /* do actual de-init only if we are the last runtime user */
+ confClassExit();
+ glblClassExit();
+ rulesetClassExit();
+ wtiClassExit();
+ wtpClassExit();
+ strgenClassExit();
+ propClassExit();
+ statsobjClassExit();
+
+ objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being
+ called (except debug)! */
+ }
+
+ --iRefCount;
+ /* TODO we must deinit this pointer! pObjIF = NULL; / * no longer exists for this caller */
+
+ dbgprintf("rsyslog runtime de-initialized, current users %d\n", iRefCount);
+
+ RETiRet;
+}
+
+
+/* returns 0 if the rsyslog runtime is not initialized and another value
+ * if it is. This function is primarily meant to be used by runtime functions
+ * itself. However, it is safe to call it before initializing the runtime.
+ * Plugins should NOT rely on this function. The reason is that another caller
+ * may have already initialized it but deinits it before this plugin is done.
+ * So for plugins and like architectures, the right course of action is to
+ * call rsrtInit() and rsrtExit(), which can be called by multiple callers.
+ * rgerhards, 2008-04-16
+ */
+int rsrtIsInit(void)
+{
+ return iRefCount;
+}
+
+
+/* vim:set ai:
+ */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
new file mode 100644
index 0000000..6446b13
--- /dev/null
+++ b/runtime/rsyslog.h
@@ -0,0 +1,814 @@
+/* This is the header file for the rsyslog runtime. It must be included
+ * if someone intends to use the runtime.
+ *
+ * Begun 2005-09-15 RGerhards
+ *
+ * Copyright (C) 2005-2023 by Rainer Gerhards and Adiscon GmbH
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef INCLUDED_RSYSLOG_H
+#define INCLUDED_RSYSLOG_H
+#ifdef __GNUC__
+ #pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
+ #pragma GCC diagnostic ignored "-Wredundant-decls" // TODO: remove!
+ #pragma GCC diagnostic ignored "-Wstrict-prototypes" // TODO: remove!
+ #pragma GCC diagnostic ignored "-Wswitch-default" // TODO: remove!
+ #if __GNUC__ >= 8
+ /* GCC, starting at least with version 8, is now really overdoing with it's
+ * warning messages. We turn those off that either cause an enormous amount
+ * of false positives or flag perfectly legal code as problematic.
+ */
+ /* That one causes warnings when we use variable buffers for error
+ * messages which may be truncated in the very unlikely case of all
+ * vars using max value. If going over the max size, the engine will
+ * most likely truncate due to max message size anyhow. Also, sizing
+ * the buffers for max-max message size is a wast of (stack) memory.
+ */
+ #pragma GCC diagnostic ignored "-Wformat-truncation"
+ /* The next one flags variable initializations within out exception handling
+ * (iRet system) as problematic, even though variables are not used in those
+ * cases. This would be a good diagnostic if gcc would actually check that
+ * a variable is used uninitialized. Unfortunately it does not do that. But
+ * the static analyzers we use as part of CI do, so we are covered in any
+ * case.
+ * Unfortunately ignoring this diagnostic leads to two more info lines
+ * being emitted where nobody knows what the mean and why they appear :-(
+ */
+ #pragma GCC diagnostic ignored "-Wjump-misses-init"
+ #endif /* if __GNUC__ >= 8 */
+
+ /* define a couple of attributes to improve cross-platform builds */
+ #if __GNUC__ > 6
+ #define CASE_FALLTHROUGH __attribute__((fallthrough));
+ #else
+ #define CASE_FALLTHROUGH
+ #endif
+
+ #define ATTR_NORETURN __attribute__ ((noreturn))
+ #define ATTR_UNUSED __attribute__((unused))
+ #define ATTR_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
+
+#else /* ifdef __GNUC__ */
+
+ #define CASE_FALLTHROUGH
+ #define ATTR_NORETURN
+ #define ATTR_UNUSED
+ #define ATTR_NONNULL(...)
+
+#endif /* ifdef __GNUC__ */
+
+#if defined(_AIX)
+#include <sys/select.h>
+/* AIXPORT : start*/
+#define SRC_FD 13
+#define SRCMSG (sizeof(srcpacket))
+#endif
+/* src end */
+
+#include <pthread.h>
+#include "typedefs.h"
+
+#if defined(__GNUC__)
+ #define PRAGMA_INGORE_Wswitch_enum _Pragma("GCC diagnostic ignored \"-Wswitch-enum\"")
+ #define PRAGMA_IGNORE_Wempty_body _Pragma("GCC diagnostic ignored \"-Wempty-body\"")
+ #define PRAGMA_IGNORE_Wstrict_prototypes _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"")
+ #define PRAGMA_IGNORE_Wold_style_definition \
+ _Pragma("GCC diagnostic ignored \"-Wold-style-definition\"")
+ #if defined(__clang_major__) && __clang_major__ >= 14
+ #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast \
+ _Pragma("GCC diagnostic ignored \"-Wvoid-pointer-to-enum-cast\"")
+ #else
+ #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast
+ #endif
+ #define PRAGMA_IGNORE_Wsign_compare _Pragma("GCC diagnostic ignored \"-Wsign-compare\"")
+ #define PRAGMA_IGNORE_Wpragmas _Pragma("GCC diagnostic ignored \"-Wpragmas\"")
+ #define PRAGMA_IGNORE_Wmissing_noreturn _Pragma("GCC diagnostic ignored \"-Wmissing-noreturn\"")
+ #define PRAGMA_IGNORE_Wexpansion_to_defined \
+ _Pragma("GCC diagnostic ignored \"-Wexpansion-to-defined\"")
+ #define PRAGMA_IGNORE_Wunknown_warning_option \
+ _Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"")
+ #define PRAGMA_IGNORE_Wunknown_attribute \
+ _Pragma("GCC diagnostic ignored \"-Wunknown-attribute\"")
+ #define PRAGMA_IGNORE_Wformat_nonliteral \
+ _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
+ #define PRAGMA_IGNORE_Wdeprecated_declarations \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+ #if __GNUC__ >= 5
+ #define PRAGMA_DIAGNOSTIC_PUSH \
+ _Pragma("GCC diagnostic push")
+ #define PRAGMA_DIAGNOSTIC_POP \
+ _Pragma("GCC diagnostic pop")
+ #else
+ #define PRAGMA_DIAGNOSTIC_PUSH
+ #define PRAGMA_DIAGNOSTIC_POP
+ #endif
+#else
+ #define PRAGMA_INGORE_Wswitch_enum
+ #define PRAGMA_IGNORE_Wsign_compare
+ #define PRAGMA_IGNORE_Wformat_nonliteral
+ #define PRAGMA_IGNORE_Wpragmas
+ #define PRAGMA_IGNORE_Wmissing_noreturn
+ #define PRAGMA_IGNORE_Wempty_body
+ #define PRAGMA_IGNORE_Wstrict_prototypes
+ #define PRAGMA_IGNORE_Wold_style_definition
+ #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast
+ #define PRAGMA_IGNORE_Wdeprecated_declarations
+ #define PRAGMA_IGNORE_Wexpansion_to_defined
+ #define PRAGMA_IGNORE_Wunknown_attribute
+ #define PRAGMA_IGNORE_Wunknown_warning_option
+ #define PRAGMA_DIAGNOSTIC_PUSH
+ #define PRAGMA_DIAGNOSTIC_POP
+#endif
+
+/* ############################################################# *
+ * # Some constant values # *
+ * ############################################################# */
+#define CONST_LEN_TIMESTAMP_3164 15 /* number of chars (excluding \0!) in a RFC3164 timestamp */
+#define CONST_LEN_TIMESTAMP_3339 32 /* number of chars (excluding \0!) in a RFC3339 timestamp */
+
+#define CONST_LEN_CEE_COOKIE 5
+#define CONST_CEE_COOKIE "@cee:"
+
+/* ############################################################# *
+ * # Config Settings # *
+ * ############################################################# */
+#define RS_STRINGBUF_ALLOC_INCREMENT 128
+/* MAXSIZE are absolute maxima, while BUFSIZE are just values after which
+ * processing is more time-intense. The BUFSIZE params currently add their
+ * value to the fixed size of the message object.
+ */
+#define CONF_TAG_MAXSIZE 512 /* a value that is deemed far too large for any valid TAG */
+#define CONF_HOSTNAME_MAXSIZE 512 /* a value that is deemed far too large for any valid HOSTNAME */
+#define CONF_RAWMSG_BUFSIZE 101
+#define CONF_TAG_BUFSIZE 32
+#define CONF_PROGNAME_BUFSIZE 16
+#define CONF_HOSTNAME_BUFSIZE 32
+#define CONF_PROP_BUFSIZE 16 /* should be close to sizeof(ptr) or lighly above it */
+#define CONF_IPARAMS_BUFSIZE 16 /* initial size of iparams array in wti (is automatically extended) */
+#define CONF_MIN_SIZE_FOR_COMPRESS 60 /* config param: minimum message size to try compression. The smaller
+ * the message, the less likely is any compression gain. We check for
+ * gain before we submit the message. But to do so we still need to
+ * do the (costly) compress() call. The following setting sets a size
+ * for which no call to compress() is done at all. This may result in
+ * a few more bytes being transmited but better overall performance.
+ * Note: I have not yet checked the minimum UDP packet size. It might be
+ * that we do not save anything by compressing very small messages, because
+ * UDP might need to pad ;)
+ * rgerhards, 2006-11-30
+ */
+
+#define CONF_OMOD_NUMSTRINGS_MAXSIZE 5 /* cache for pointers to output module buffer pointers. All
+ * rsyslog-provided plugins do NOT need more than five buffers. If
+ * more are needed (future developments, third-parties), rsyslog
+ * must be recompiled with a larger parameter. Hardcoding this
+ * saves us some overhead, both in runtime in code complexity. As
+ * it is doubtful if ever more than 3 parameters are needed, the
+ * approach taken here is considered appropriate.
+ * rgerhards, 2010-06-24
+ */
+#define CONF_NUM_MULTISUB 1024 /* default number of messages per multisub structure */
+
+/* ############################################################# *
+ * # End Config Settings # *
+ * ############################################################# */
+
+/* make sure we uses consistent macros, no matter what the
+ * platform gives us.
+ */
+#undef LOG_NFACILITIES /* may be system defined, override */
+#define LOG_NFACILITIES 24+1 /* plus one for our special "invld" facility! */
+#define LOG_MAXPRI 191 /* highest supported valid PRI value --> RFC3164, RFC5424 */
+#undef LOG_MAKEPRI
+#define LOG_PRI_INVLD (LOG_INVLD|LOG_DEBUG)
+/* PRI is invalid --> special "invld.=debug" PRI code (rsyslog-specific) */
+
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but significant condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* security/authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+#if !defined(LOG_CRON)
+#define LOG_CRON (9<<3) /* clock daemon */
+#endif
+#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
+#define LOG_FTP (11<<3) /* ftp daemon */
+#if defined(_AIX) /* AIXPORT : These are necessary for AIX */
+#define LOG_ASO (12<<3) /* Active System Optimizer. Reserved for internal use */
+#define LOG_CAA (15<<3) /* Cluster aware AIX subsystem */
+#endif
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+#define LOG_FAC_INVLD 24
+#define LOG_INVLD (LOG_FAC_INVLD<<3) /* invalid facility/PRI code */
+
+/* we need to evaluate our argument only once, as otherwise we may
+ * have side-effects (this was seen in some version).
+ * Note: I know that "static inline" is not the right thing from a C99
+ * PoV, but some environments treat, even in C99 mode, compile
+ * non-static inline into the source even if not defined as "extern". This
+ * obviously results in linker errors. Using "static inline" as below together
+ * with "__attribute__((unused))" works in all cases. Note also that we
+ * cannot work around this in pri2fac, as we would otherwise need to evaluate
+ * pri more than once.
+ */
+static inline syslog_pri_t __attribute__((unused))
+pri2fac(const syslog_pri_t pri)
+{
+ unsigned fac = pri >> 3;
+ return (fac > 23) ? LOG_FAC_INVLD : fac;
+}
+#define pri2sev(pri) ((pri) & 0x07)
+
+/* the rsyslog core provides information about present feature to plugins
+ * asking it. Below are feature-test macros which must be used to query
+ * features. Note that this must be powers of two, so that multiple queries
+ * can be combined. -- rgerhards, 2009-04-27
+ */
+#define CORE_FEATURE_BATCHING 1
+/*#define CORE_FEATURE_whatever 2 ... and so on ... */
+
+#ifndef _PATH_CONSOLE
+#define _PATH_CONSOLE "/dev/console"
+#endif
+
+
+/* The error codes below are orginally "borrowed" from
+ * liblogging. As such, we reserve values up to -2999
+ * just in case we need to borrow something more ;)
+*/
+enum rsRetVal_ /** return value. All methods return this if not specified otherwise */
+{
+ /* the first two define are for errmsg.logError(), so that we can use the rsRetVal
+ * as an rsyslog error code. -- rgerhards, 20080-06-27
+ */
+ RS_RET_NO_ERRCODE = -1, /**< RESERVED for NO_ERRCODE errmsg.logError status name */
+ RS_RET_INCLUDE_ERRNO = 1073741824, /* 2**30 - do NOT use error codes above this! */
+ /* begin regular error codes */
+ RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */
+ RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */
+ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, /*< the caller provided a buffer, but the called function sees
+ the size of this buffer is too small - operation not carried out */
+ RS_RET_FILE_TRUNCATED = -51, /**< (input) file was truncated, not an error but a status */
+ RS_RET_TRUE = -3, /**< to indicate a true state (can be used as TRUE, legacy) */
+ RS_RET_FALSE = -2, /**< to indicate a false state (can be used as FALSE, legacy) */
+ RS_RET_NO_IRET = -8, /**< This is a trick for the debuging system - it means no iRet is provided */
+ RS_RET_VALIDATION_RUN = -9, /**< indicates a (config) validation run, processing not carried out */
+ RS_RET_ERR = -3000, /**< generic failure */
+ RS_TRUNCAT_TOO_LARGE = -3001, /**< truncation operation where too many chars should be truncated */
+ RS_RET_FOUND_AT_STRING_END = -3002, /**< some value found, but at the last pos of string */
+ RS_RET_NOT_FOUND = -3003, /**< some requested value not found */
+ RS_RET_MISSING_TRAIL_QUOTE = -3004, /**< an expected trailing quote is missing */
+ RS_RET_NO_DIGIT = -3005, /**< an digit was expected, but none found (mostly parsing) */
+ RS_RET_NO_MORE_DATA = -3006, /**< insufficient data, e.g. end of string during parsing */
+ RS_RET_INVALID_IP = -3007, /**< invalid ip found where valid was expected */
+ RS_RET_OBJ_CREATION_FAILED = - 3008, /**< the creation of an object failed (no details available) */
+ RS_RET_INOTIFY_INIT_FAILED = - 3009,
+ /**< the initialization of an inotify instance failed (no details available) */
+ RS_RET_FEN_INIT_FAILED = - 3010, /**< the initialization of a fen instance failed (no details available) */
+ RS_RET_PARAM_ERROR = -1000, /**< invalid parameter in call to function */
+ RS_RET_MISSING_INTERFACE = -1001,/**< interface version mismatch, required missing */
+ RS_RET_INVALID_CORE_INTERFACE = -1002,/**< interface provided by host invalid, can not be used */
+ RS_RET_ENTRY_POINT_NOT_FOUND = -1003,/**< a requested entry point was not found */
+ RS_RET_MODULE_ENTRY_POINT_NOT_FOUND = -1004,/**< a entry point requested from a module was not present in it */
+ RS_RET_OBJ_NOT_AVAILABLE = -1005,
+ /**< something could not be completed because the required object is not available*/
+ RS_RET_LOAD_ERROR = -1006,/**< we had an error loading the object/interface and can not continue */
+ RS_RET_MODULE_STILL_REFERENCED = -1007,
+ /**< module could not be unloaded because it still is referenced by someone */
+ RS_RET_OBJ_UNKNOWN = -1008,/**< object is unknown where required */
+ RS_RET_OBJ_NOT_REGISTERED = -1009,/**< tried to unregister an object that is not registered */
+ /* return states for config file processing */
+ RS_RET_NONE = -2000, /**< some value is not available - not necessarily an error */
+ RS_RET_CONFLINE_UNPROCESSED = -2001,/**< config line was not processed, pass to other module */
+ RS_RET_DISCARDMSG = -2002, /**< discard message (no error state, processing request!) */
+ RS_RET_INCOMPATIBLE = -2003, /**< function not compatible with requested feature */
+ RS_RET_NOENTRY = -2004, /**< do not create an entry for (whatever) - not necessary an error */
+ RS_RET_NO_SQL_STRING = -2005, /**< string is not suitable for use as SQL */
+ RS_RET_DISABLE_ACTION = -2006, /**< action requests that it be disabled */
+ RS_RET_SUSPENDED = -2007, /**< something was suspended, not neccesarily an error */
+ RS_RET_RQD_TPLOPT_MISSING = -2008,/**< a required template option is missing */
+ RS_RET_INVALID_VALUE = -2009,/**< some value is invalid (e.g. user-supplied data) */
+ RS_RET_INVALID_INT = -2010,/**< invalid integer */
+ RS_RET_INVALID_CMD = -2011,/**< invalid command */
+ RS_RET_VAL_OUT_OF_RANGE = -2012, /**< value out of range */
+ RS_RET_FOPEN_FAILURE = -2013, /**< failure during fopen, for example file not found - see errno */
+ RS_RET_END_OF_LINKEDLIST = -2014, /**< end of linked list, not an error, but a status */
+ RS_RET_CHAIN_NOT_PERMITTED = -2015, /**< chaining (e.g. of config command handlers) not permitted */
+ RS_RET_INVALID_PARAMS = -2016,/**< supplied parameters are invalid */
+ RS_RET_EMPTY_LIST = -2017, /**< linked list is empty */
+ RS_RET_FINISHED = -2018, /**< some opertion is finished, not an error state */
+ RS_RET_INVALID_SOURCE = -2019, /**< source (address) invalid for some reason */
+ RS_RET_ADDRESS_UNKNOWN = -2020, /**< an address is unknown - not necessarily an error */
+ RS_RET_MALICIOUS_ENTITY = -2021, /**< there is an malicious entity involved */
+ RS_RET_NO_KERNEL_LOGSRC = -2022, /**< no source for kernel logs can be obtained */
+ RS_RET_TCP_SEND_ERROR = -2023, /**< error during TCP send process */
+ RS_RET_GSS_SEND_ERROR = -2024, /**< error during GSS (via TCP) send process */
+ RS_RET_TCP_SOCKCREATE_ERR = -2025, /**< error during creation of TCP socket */
+ RS_RET_GSS_SENDINIT_ERROR = -2024, /**< error during GSS (via TCP) send initialization process */
+ RS_RET_EOF = -2026, /**< end of file reached, not necessarily an error */
+ RS_RET_IO_ERROR = -2027, /**< some kind of IO error happened */
+ RS_RET_INVALID_OID = -2028, /**< invalid object ID */
+ RS_RET_INVALID_HEADER = -2029, /**< invalid header */
+ RS_RET_INVALID_HEADER_VERS = -2030, /**< invalid header version */
+ RS_RET_INVALID_DELIMITER = -2031, /**< invalid delimiter, e.g. between params */
+ RS_RET_INVALID_PROPFRAME = -2032, /**< invalid framing in serialized property */
+ RS_RET_NO_PROPLINE = -2033, /**< line is not a property line */
+ RS_RET_INVALID_TRAILER = -2034, /**< invalid trailer */
+ RS_RET_VALUE_TOO_LOW = -2035, /**< a provided value is too low */
+ RS_RET_FILE_PREFIX_MISSING = -2036, /**< a required file prefix (parameter?) is missing */
+ RS_RET_INVALID_HEADER_RECTYPE = -2037, /**< invalid record type in header or invalid header */
+ RS_RET_QTYPE_MISMATCH = -2038, /**< different qType when reading back a property type */
+ RS_RET_NO_FILE_ACCESS = -2039, /**< covers EACCES error on file open() */
+ RS_RET_FILE_NOT_FOUND = -2040, /**< file not found */
+ RS_RET_TIMED_OUT = -2041, /**< timeout occurred (not necessarily an error) */
+ RS_RET_QSIZE_ZERO = -2042, /**< queue size is zero where this is not supported */
+ RS_RET_ALREADY_STARTING = -2043, /**< something (a thread?) is already starting - not necessarily an error */
+ RS_RET_NO_MORE_THREADS = -2044, /**< no more threads available, not necessarily an error */
+ RS_RET_NO_FILEPREFIX = -2045, /**< file prefix is not specified where one is needed */
+ RS_RET_CONFIG_ERROR = -2046, /**< there is a problem with the user-provided config settigs */
+ RS_RET_OUT_OF_DESRIPTORS = -2047, /**< a descriptor table's space has been exhausted */
+ RS_RET_NO_DRIVERS = -2048, /**< a required drivers missing */
+ RS_RET_NO_DRIVERNAME = -2049, /**< driver name missing where one was required */
+ RS_RET_EOS = -2050, /**< end of stream (of whatever) */
+ RS_RET_SYNTAX_ERROR = -2051, /**< syntax error, eg. during parsing */
+ RS_RET_INVALID_OCTAL_DIGIT = -2052, /**< invalid octal digit during parsing */
+ RS_RET_INVALID_HEX_DIGIT = -2053, /**< invalid hex digit during parsing */
+ RS_RET_INTERFACE_NOT_SUPPORTED = -2054, /**< interface not supported */
+ RS_RET_OUT_OF_STACKSPACE = -2055, /**< a stack data structure is exhausted and can not be grown */
+ RS_RET_STACK_EMPTY = -2056, /**< a pop was requested on a stack, but the stack was already empty */
+ RS_RET_INVALID_VMOP = -2057, /**< invalid virtual machine instruction */
+ RS_RET_INVALID_VAR = -2058, /**< a var or its content is unsuitable, eg. VARTYPE_NONE */
+ RS_RET_INVALID_NUMBER = -2059, /**< number invalid during parsing */
+ RS_RET_NOT_A_NUMBER = -2060, /**< e.g. conversion impossible because the string is not a number */
+ RS_RET_OBJ_ALREADY_REGISTERED = -2061, /**< object (name) is already registered */
+ RS_RET_OBJ_REGISTRY_OUT_OF_SPACE = -2062, /**< the object registry has run out of space */
+ RS_RET_HOST_NOT_PERMITTED = -2063, /**< a host is not permitted to perform an action it requested */
+ RS_RET_MODULE_LOAD_ERR = -2064, /**< module could not be loaded */
+ RS_RET_MODULE_LOAD_ERR_PATHLEN = -2065, /**< module could not be loaded - path to long */
+ RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */
+ RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */
+ RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */
+ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */
+ RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */
+ RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */
+ RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */
+ RS_RET_INVALID_PRI = -2073, /**< PRI value is invalid */
+ RS_RET_MALICIOUS_HNAME = -2074, /**< remote peer is trying malicious things with its hostname */
+ RS_RET_INVALID_HNAME = -2075, /**< remote peer's hostname invalid or unobtainable */
+ RS_RET_INVALID_PORT = -2076, /**< invalid port value */
+ RS_RET_COULD_NOT_BIND = -2077, /**< could not bind socket, defunct */
+ RS_RET_GNUTLS_ERR = -2078, /**< (unexpected) error in GnuTLS call */
+ RS_RET_MAX_SESS_REACHED = -2079, /**< max nbr of sessions reached, can not create more */
+ RS_RET_MAX_LSTN_REACHED = -2080, /**< max nbr of listeners reached, can not create more */
+ RS_RET_INVALID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */
+ RS_RET_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */
+ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */
+ RS_RET_TLS_CERT_ERR = -2084, /**< generic TLS certificate error */
+ RS_RET_TLS_NO_CERT = -2085, /**< no TLS certificate available where one was expected */
+ RS_RET_VALUE_NOT_SUPPORTED = -2086, /**< a provided value is not supported */
+ RS_RET_VALUE_NOT_IN_THIS_MODE = -2087, /**< a provided value is invalid for the curret mode */
+ RS_RET_INVALID_FINGERPRINT = -2088, /**< a fingerprint is not valid for this use case */
+ RS_RET_CONNECTION_ABORTREQ = -2089, /**< connection was abort requested due to previous error */
+ RS_RET_CERT_INVALID = -2090, /**< a x509 certificate failed validation */
+ RS_RET_CERT_INVALID_DN = -2091, /**< distinguised name in x509 certificate is invalid (e.g. wrong escaping) */
+ RS_RET_CERT_EXPIRED = -2092, /**< we are past a x.509 cert's expiration time */
+ RS_RET_CERT_NOT_YET_ACTIVE = -2094, /**< x.509 cert's activation time not yet reached */
+ RS_RET_SYS_ERR = -2095, /**< system error occurred (e.g. time() returned -1, quite unexpected) */
+ RS_RET_FILE_NO_STAT = -2096, /**< can not stat() a file */
+ RS_RET_FILE_TOO_LARGE = -2097, /**< a file is larger than permitted */
+ RS_RET_INVALID_WILDCARD = -2098, /**< a wildcard entry is invalid */
+ RS_RET_CLOSED = -2099, /**< connection was closed */
+ RS_RET_RETRY = -2100, /**< call should be retried (e.g. EGAIN on recv) */
+ RS_RET_GSS_ERR = -2101, /**< generic error occurred in GSSAPI subsystem */
+ RS_RET_CERTLESS = -2102, /**< state: we run without machine cert (this may be OK) */
+ RS_RET_NO_ACTIONS = -2103, /**< no active actions are configured (no output will be created) */
+ RS_RET_CONF_FILE_NOT_FOUND = -2104, /**< config file or directory not found */
+ RS_RET_QUEUE_FULL = -2105, /**< queue is full, operation could not be completed */
+ RS_RET_ACCEPT_ERR = -2106, /**< error during accept() system call */
+ RS_RET_INVLD_TIME = -2107, /**< invalid timestamp (e.g. could not be parsed) */
+ RS_RET_NO_ZIP = -2108, /**< ZIP functionality is not present */
+ RS_RET_CODE_ERR = -2109, /**< program code (internal) error */
+ RS_RET_FUNC_NO_LPAREN = -2110, /**< left parenthesis missing after function call (rainerscript) */
+ RS_RET_FUNC_MISSING_EXPR = -2111, /**< no expression after comma in function call (rainerscript) */
+ RS_RET_INVLD_NBR_ARGUMENTS = -2112, /**< invalid number of arguments for function call (rainerscript) */
+ RS_RET_INVLD_FUNC = -2113, /**< invalid function name for function call (rainerscript) */
+ RS_RET_DUP_FUNC_NAME = -2114, /**< duplicate function name (rainerscript) */
+ RS_RET_UNKNW_FUNC = -2115, /**< unkown function name (rainerscript) */
+ RS_RET_ERR_RLIM_NOFILE = -2116, /**< error setting max. nbr open files process limit */
+ RS_RET_ERR_CREAT_PIPE = -2117, /**< error during pipe creation */
+ RS_RET_ERR_FORK = -2118, /**< error during fork() */
+ RS_RET_ERR_WRITE_PIPE = -2119, /**< error writing to pipe */
+ RS_RET_RSCORE_TOO_OLD = -2120, /**< rsyslog core is too old for ... (eg this plugin) */
+ RS_RET_DEFER_COMMIT = -2121, /**< output plugin status: not yet committed (an OK state!) */
+ RS_RET_PREVIOUS_COMMITTED = -2122, /**< output plugin status: previous record was committed (an OK state!) */
+ RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended */
+ RS_RET_NON_SIZELIMITCMD = -2125, /**< size limit for file defined, but no size limit command given */
+ RS_RET_SIZELIMITCMD_DIDNT_RESOLVE = -2126, /**< size limit command did not resolve situation */
+ RS_RET_STREAM_DISABLED = -2127, /**< a file has been disabled (e.g. by size limit restriction) */
+ RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */
+ RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */
+ RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */
+ RS_RET_EMPTY_MSG = -2143, /**< provided (raw) MSG is empty */
+ RS_RET_PEER_CLOSED_CONN = -2144, /**< remote peer closed connection (information, no error) */
+ RS_RET_ERR_OPEN_KLOG = -2145, /**< error opening or reading the kernel log socket */
+ RS_RET_ERR_AQ_CONLOG = -2146, /**< error aquiring console log (on solaris) */
+ RS_RET_ERR_DOOR = -2147, /**< some problems with handling the Solaris door functionality */
+ RS_RET_NO_SRCNAME_TPL = -2150, /**< sourcename template was not specified where one was needed
+(omudpspoof spoof addr) */
+ RS_RET_HOST_NOT_SPECIFIED = -2151, /**< (target) host was not specified where it was needed */
+ RS_RET_ERR_LIBNET_INIT = -2152, /**< error initializing libnet, e.g. because not running as root */
+ RS_RET_FORCE_TERM = -2153, /**< thread was forced to terminate by bShallShutdown, a state, not an error */
+ RS_RET_RULES_QUEUE_EXISTS = -2154,/**< we were instructed to create a new
+ ruleset queue, but one already exists */
+ RS_RET_NO_CURR_RULESET = -2155,/**< no current ruleset exists (but one is required) */
+ RS_RET_NO_MSG_PASSING = -2156,
+/*< output module interface parameter passing mode "MSG" is not available but required */
+ RS_RET_RULESET_NOT_FOUND = -2157,/**< a required ruleset could not be found */
+ RS_RET_NO_RULESET= -2158,/**< no ruleset name as specified where one was needed */
+ RS_RET_PARSER_NOT_FOUND = -2159,/**< parser with the specified name was not found */
+ RS_RET_COULD_NOT_PARSE = -2160,/**< (this) parser could not parse the message (no error, means try next one) */
+ RS_RET_EINTR = -2161, /**< EINTR occurred during a system call (not necessarily an error) */
+ RS_RET_ERR_EPOLL = -2162, /**< epoll() returned with an unexpected error code */
+ RS_RET_ERR_EPOLL_CTL = -2163, /**< epol_ctll() returned with an unexpected error code */
+ RS_RET_TIMEOUT = -2164, /**< timeout occurred during operation */
+ RS_RET_RCV_ERR = -2165, /**< error occurred during socket rcv operation */
+ RS_RET_NO_SOCK_CONFIGURED = -2166, /**< no socket (name) was configured where one is required */
+ RS_RET_CONF_NOT_GLBL = -2167, /**< $Begin not in global scope */
+ RS_RET_CONF_IN_GLBL = -2168, /**< $End when in global scope */
+ RS_RET_CONF_INVLD_END = -2169, /**< $End for wrong conf object (probably nesting error) */
+ RS_RET_CONF_INVLD_SCOPE = -2170,
+/*< config statement not valid in current scope (e.g. global stmt in action block) */
+ RS_RET_CONF_END_NO_ACT = -2171, /**< end of action block, but no actual action specified */
+ RS_RET_NO_LSTN_DEFINED = -2172, /**< no listener defined (e.g. inside an input module) */
+ RS_RET_EPOLL_CR_FAILED = -2173, /**< epoll_create() failed */
+ RS_RET_EPOLL_CTL_FAILED = -2174, /**< epoll_ctl() failed */
+ RS_RET_INTERNAL_ERROR = -2175, /**< rsyslogd internal error, unexpected code path reached */
+ RS_RET_ERR_CRE_AFUX = -2176, /**< error creating AF_UNIX socket (and binding it) */
+ RS_RET_RATE_LIMITED = -2177, /**< some messages discarded due to exceeding a rate limit */
+ RS_RET_ERR_HDFS_WRITE = -2178, /**< error writing to HDFS */
+ RS_RET_ERR_HDFS_OPEN = -2179, /**< error during hdfsOpen (e.g. file does not exist) */
+ RS_RET_FILE_NOT_SPECIFIED = -2180, /**< file name not configured where this was required */
+ RS_RET_ERR_WRKDIR = -2181, /**< problems with the rsyslog working directory */
+ RS_RET_WRN_WRKDIR = -2182, /**< correctable problems with the rsyslog working directory */
+ RS_RET_ERR_QUEUE_EMERGENCY = -2183, /**< some fatal error caused queue to switch to emergency mode */
+ RS_RET_OUTDATED_STMT = -2184, /**< some outdated statement/functionality is being used in conf file */
+ RS_RET_MISSING_WHITESPACE = -2185, /**< whitespace is missing in some config construct */
+ RS_RET_OK_WARN = -2186, /**< config part: everything was OK, but a warning message was emitted */
+
+ RS_RET_INVLD_CONF_OBJ= -2200, /**< invalid config object (e.g. $Begin conf statement) */
+ /* UNUSED, WAS; RS_RET_ERR_LIBEE_INIT = -2201, < cannot obtain libee ctx */
+ RS_RET_ERR_LIBLOGNORM_INIT = -2202,/**< cannot obtain liblognorm ctx */
+ RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD = -2203,/**< liblognorm sampledb load failed */
+ RS_RET_CMD_GONE_AWAY = -2204,/**< config directive existed, but no longer supported */
+ RS_RET_ERR_SCHED_PARAMS = -2205,/**< there is a problem with configured thread scheduling params */
+ RS_RET_SOCKNAME_MISSING = -2206,/**< no socket name configured where one is required */
+ RS_RET_CONF_PARSE_ERROR = -2207,/**< (fatal) error parsing config file */
+ RS_RET_CONF_RQRD_PARAM_MISSING = -2208,/**< required parameter in config object is missing */
+ RS_RET_MOD_UNKNOWN = -2209,/**< module (config name) is unknown */
+ RS_RET_CONFOBJ_UNSUPPORTED = -2210,/**< config objects (v6 conf) are not supported here */
+ RS_RET_MISSING_CNFPARAMS = -2211, /**< missing configuration parameters */
+ RS_RET_NO_LISTNERS = -2212, /**< module loaded, but no listeners are defined */
+ RS_RET_INVLD_PROTOCOL = -2213, /**< invalid protocol specified in config file */
+ RS_RET_CNF_INVLD_FRAMING = -2214, /**< invalid framing specified in config file */
+ RS_RET_LEGA_ACT_NOT_SUPPORTED = -2215, /**< the module (no longer) supports legacy action syntax */
+ RS_RET_MAX_OMSR_REACHED = -2216, /**< max nbr of string requests reached, not supported by core */
+ RS_RET_UID_MISSING = -2217, /**< a user id is missing (but e.g. a password provided) */
+ RS_RET_DATAFAIL = -2218, /**< data passed to action caused failure */
+ /* reserved for pre-v6.5 */
+ RS_RET_DUP_PARAM = -2220, /**< config parameter is given more than once */
+ RS_RET_MODULE_ALREADY_IN_CONF = -2221, /**< module already in current configuration */
+ RS_RET_PARAM_NOT_PERMITTED = -2222, /**< legacy parameter no longer permitted (usally already set by v2) */
+ RS_RET_NO_JSON_PASSING = -2223, /**< rsyslog core does not support JSON-passing plugin API */
+ RS_RET_MOD_NO_INPUT_STMT = -2224, /**< (input) module does not support input() statement */
+ RS_RET_NO_CEE_MSG = -2225, /**< the message being processed is NOT CEE-enhanced */
+
+ /**** up to 2290 is reserved for v6 use ****/
+ RS_RET_RELP_ERR = -2291, /**<< error in RELP processing */
+ /**** up to 3000 is reserved for c7 use ****/
+ RS_RET_JNAME_NO_ROOT = -2301, /**< root element is missing in JSON path */
+ RS_RET_JNAME_INVALID = -2302, /**< JSON path is invalid */
+ RS_RET_JSON_PARSE_ERR = -2303, /**< we had a problem parsing JSON (or extra data) */
+ RS_RET_BSD_BLOCKS_UNSUPPORTED = -2304, /**< BSD-style config blocks are no longer supported */
+ RS_RET_JNAME_NOTFOUND = -2305, /**< JSON name not found (does not exist) */
+ RS_RET_INVLD_SETOP = -2305, /**< invalid variable set operation, incompatible type */
+ RS_RET_RULESET_EXISTS = -2306,/**< ruleset already exists */
+ RS_RET_DEPRECATED = -2307,/**< deprecated functionality is used */
+ RS_RET_DS_PROP_SEQ_ERR = -2308,/**< property sequence error deserializing object */
+ RS_RET_INVLD_PROP = -2309,/**< property name error (unknown name) */
+ RS_RET_NO_RULEBASE = -2310,/**< mmnormalize: rulebase can not be found or otherwise invalid */
+ RS_RET_INVLD_MODE = -2311,/**< invalid mode specified in configuration */
+ RS_RET_INVLD_ANON_BITS = -2312,/**< mmanon: invalid number of bits to anonymize specified */
+ RS_RET_REPLCHAR_IGNORED = -2313,/**< mmanon: replacementChar parameter is ignored */
+ RS_RET_SIGPROV_ERR = -2320,/**< error in signature provider */
+ RS_RET_CRYPROV_ERR = -2321,/**< error in cryptography encryption provider */
+ RS_RET_EI_OPN_ERR = -2322,/**< error opening an .encinfo file */
+ RS_RET_EI_NO_EXISTS = -2323,/**< .encinfo file does not exist (status, not necessarily error!)*/
+ RS_RET_EI_WR_ERR = -2324,/**< error writing an .encinfo file */
+ RS_RET_EI_INVLD_FILE = -2325,/**< header indicates the file is no .encinfo file */
+ RS_RET_CRY_INVLD_ALGO = -2326,/**< user specified invalid (unkonwn) crypto algorithm */
+ RS_RET_CRY_INVLD_MODE = -2327,/**< user specified invalid (unkonwn) crypto mode */
+ RS_RET_QUEUE_DISK_NO_FN = -2328,/**< disk queue configured, but filename not set */
+ RS_RET_CA_CERT_MISSING = -2329,/**< a CA cert is missing where one is required (e.g. TLS) */
+ RS_RET_CERT_MISSING = -2330,/**< a cert is missing where one is required (e.g. TLS) */
+ RS_RET_CERTKEY_MISSING = -2331,/**< a cert (private) key is missing where one is required (e.g. TLS) */
+ RS_RET_CRL_MISSING = -2332,/**< a CRL file is missing but not required (e.g. TLS) */
+ RS_RET_CRL_INVALID = -2333, /**< a CRL file PEM file failed validation */
+ RS_RET_CERT_REVOKED = -2334, /**< a certificate has been revoked */
+ RS_RET_STRUC_DATA_INVLD = -2349,/**< structured data is malformed */
+
+ /* up to 2350 reserved for 7.4 */
+ RS_RET_QUEUE_CRY_DISK_ONLY = -2351,/**< crypto provider only supported for disk-associated queues */
+ RS_RET_NO_DATA = -2352,/**< file has no data; more a state than a real error */
+ RS_RET_RELP_AUTH_FAIL = -2353,/**< RELP peer authentication failed */
+ RS_RET_ERR_UDPSEND = -2354,/**< sending msg via UDP failed */
+ RS_RET_LAST_ERRREPORT = -2355,/**< module does not emit more error messages as limit is reached */
+ RS_RET_READ_ERR = -2356,/**< read error occurred (file i/o) */
+ RS_RET_CONF_PARSE_WARNING = -2357,/**< warning parsing config file */
+ RS_RET_CONF_WRN_FULLDLY_BELOW_HIGHWTR = -2358,/**< warning queue full delay mark below high wtr mark */
+ RS_RET_RESUMED = -2359,/**< status: action was resumed (used for reporting) */
+ RS_RET_RELP_NO_TLS = -2360,/**< librel does not support TLS (but TLS requested) */
+ RS_RET_STATEFILE_WRONG_FNAME = -2361,/**< state file is for wrong file */
+ RS_RET_NAME_INVALID = -2362, /**< invalid name (in RainerScript) */
+
+ /* up to 2400 reserved for 7.5 & 7.6 */
+ RS_RET_INVLD_OMOD = -2400, /**< invalid output module, does not provide proper interfaces */
+ RS_RET_INVLD_INTERFACE_INPUT = -2401, /**< invalid value for "interface.input" parameter (ext progs) */
+ RS_RET_PARSER_NAME_EXISTS = -2402, /**< parser name already exists */
+ RS_RET_MOD_NO_PARSER_STMT = -2403, /**< (parser) module does not support parser() statement */
+
+ /* up to 2419 reserved for 8.4.x */
+ RS_RET_IMFILE_WILDCARD = -2420, /**< imfile file name contains wildcard, which may be problematic */
+ RS_RET_RELP_NO_TLS_AUTH = -2421,/**< librel does not support TLS authentication (but was requested) */
+ RS_RET_KAFKA_ERROR = -2422,/**< error reported by Apache Kafka subsystem. See message for details. */
+ RS_RET_KAFKA_NO_VALID_BROKERS = -2423,/**< no valid Kafka brokers configured/available */
+ RS_RET_KAFKA_PRODUCE_ERR = -2424,/**< error during Kafka produce function */
+ RS_RET_CONF_PARAM_INVLD = -2425,/**< config parameter is invalid */
+ RS_RET_KSI_ERR = -2426,/**< error in KSI subsystem */
+ RS_RET_ERR_LIBLOGNORM = -2427,/**< cannot obtain liblognorm ctx */
+ RS_RET_CONC_CTRL_ERR = -2428,/**< error in lock/unlock/condition/concurrent-modification operation */
+ RS_RET_SENDER_GONE_AWAY = -2429,/**< warning: sender not seen for configured amount of time */
+ RS_RET_SENDER_APPEARED = -2430,/**< info: new sender appeared */
+ RS_RET_FILE_ALREADY_IN_TABLE = -2431,/**< in imfile: table already contains to be added file */
+ RS_RET_ERR_DROP_PRIV = -2432,/**< error droping privileges */
+ RS_RET_FILE_OPEN_ERROR = -2433, /**< error other than "not found" occurred during open() */
+ RS_RET_RENAME_TMP_QI_ERROR = -2435, /**< renaming temporary .qi file failed */
+ RS_RET_ERR_SETENV = -2436, /**< error setting an environment variable */
+ RS_RET_DIR_CHOWN_ERROR = -2437, /**< error during chown() */
+ RS_RET_JSON_UNUSABLE = -2438, /**< JSON object is NULL or otherwise unusable */
+ RS_RET_OPERATION_STATUS = -2439, /**< operational status (info) message, no error */
+ RS_RET_UDP_MSGSIZE_TOO_LARGE = -2440, /**< a message is too large to be sent via UDP */
+ RS_RET_NON_JSON_PROP = -2441, /**< a non-json property id is provided where a json one is requried */
+ RS_RET_NO_TZ_SET = -2442, /**< system env var TZ is not set (status msg) */
+ RS_RET_FS_ERR = -2443, /**< file-system error */
+ RS_RET_POLL_ERR = -2444, /**< error in poll() system call */
+ RS_RET_OVERSIZE_MSG = -2445, /**< message is too long (above configured max) */
+ RS_RET_TLS_KEY_ERR = -2446, /**< TLS KEY has problems */
+ RS_RET_RABBITMQ_CONN_ERR = -2447, /**< RabbitMQ Connection error */
+ RS_RET_RABBITMQ_LOGIN_ERR = -2448, /**< RabbitMQ Login error */
+ RS_RET_RABBITMQ_CHANNEL_ERR = -2449, /**< RabbitMQ Connection error */
+ RS_RET_NO_WRKDIR_SET = -2450, /**< working directory not set, but desired by functionality */
+ RS_RET_ERR_QUEUE_FN_DUP = -2451, /**< duplicate queue file name */
+ RS_RET_REDIS_ERROR = -2452, /**< redis-specific error. See message foe details. */
+ RS_RET_REDIS_AUTH_FAILED = -2453, /**< redis authentication failure */
+ RS_RET_FAUP_INIT_OPTIONS_FAILED = -2454, /**< could not initialize faup options */
+ RS_RET_LIBCAPNG_ERR = -2455, /**< error during dropping the capabilities */
+
+ /* RainerScript error messages (range 1000.. 1999) */
+ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
+ RS_RET_FIELD_NOT_FOUND = 1002, /**< field() function did not find requested field */
+
+ /* some generic error/status codes */
+ RS_RET_OK = 0, /**< operation successful */
+ RS_RET_OK_DELETE_LISTENTRY = 1,
+/*< operation successful, but callee requested the deletion of an entry (special state) */
+ RS_RET_TERMINATE_NOW = 2, /**< operation successful, function is requested to terminate
+ (mostly used with threads) */
+ RS_RET_NO_RUN = 3, /**< operation successful, but function does not like to be executed */
+ RS_RET_IDLE = 4, /**< operation successful, but callee is idle (e.g. because queue is empty) */
+ RS_RET_TERMINATE_WHEN_IDLE = 5 /**< operation successful, function is requested to terminate when idle */
+};
+
+/* some helpful macros to work with srRetVals.
+ * Be sure to call the to-be-returned variable always "iRet" and
+ * the function finalizer always "finalize_it".
+ */
+#ifdef HAVE_BUILTIN_EXCEPT
+# define CHKiRet(code) if(__builtin_expect(((iRet = code) != RS_RET_OK), 0)) goto finalize_it
+# define likely(x) __builtin_expect(!!(x), 1)
+# define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+# define CHKiRet(code) if((iRet = code) != RS_RET_OK) goto finalize_it
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
+
+# define CHKiConcCtrl(code) { int tmp_CC; \
+ if ((tmp_CC = code) != 0) { \
+ iRet = RS_RET_CONC_CTRL_ERR; \
+ errno = tmp_CC; \
+ goto finalize_it; \
+ } \
+}
+
+/* macro below is to be used if we need our own handling, eg for cleanup */
+#define CHKiRet_Hdlr(code) if((iRet = code) != RS_RET_OK)
+/* macro below is to handle failing malloc/calloc/strdup... which we almost always handle in the same way... */
+#define CHKmalloc(operation) if((operation) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY)
+/* macro below is used in conjunction with CHKiRet_Hdlr, else use ABORT_FINALIZE */
+#define FINALIZE goto finalize_it;
+#define DEFiRet rsRetVal iRet = RS_RET_OK
+#define RETiRet return iRet
+
+#define ABORT_FINALIZE(errCode) \
+ do { \
+ iRet = errCode; \
+ goto finalize_it; \
+ } while (0)
+
+/** Object ID. These are for internal checking. Each
+ * object is assigned a specific ID. This is contained in
+ * all Object structs (just like C++ RTTI). We can use
+ * this field to see if we have been passed a correct ID.
+ * Other than that, there is currently no other use for
+ * the object id.
+ */
+enum rsObjectID
+{
+ OIDrsFreed = -1, /**< assigned, when an object is freed. If this
+ * is seen during a method call, this is an
+ * invalid object pointer!
+ */
+ OIDrsInvalid = 0, /**< value created by calloc(), so do not use ;) */
+ /* The 0x3412 is a debug aid. It helps us find object IDs in memory
+ * dumps (on X86, this is 1234 in the dump ;)
+ * If you are on an embedded device and you would like to save space
+ * make them 1 byte only.
+ */
+ OIDrsCStr = 0x34120001,
+ OIDrsPars = 0x34120002
+};
+typedef enum rsObjectID rsObjID;
+
+/* support to set object types */
+#ifdef NDEBUG
+#define rsSETOBJTYPE(pObj, type)
+#define rsCHECKVALIDOBJECT(x, type)
+#else
+#define rsSETOBJTYPE(pObj, type) pObj->OID = type;
+#define rsCHECKVALIDOBJECT(x, type) {assert(x != NULL); assert(x->OID == type);}
+#endif
+
+/**
+ * This macro should be used to free objects.
+ * It aids in interpreting dumps during debugging.
+ */
+#ifdef NDEBUG
+#define RSFREEOBJ(x) free(x)
+#else
+#define RSFREEOBJ(x) {(x)->OID = OIDrsFreed; free(x);}
+#endif
+
+extern pthread_attr_t default_thread_attr;
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+extern struct sched_param default_sched_param;
+extern int default_thr_sched_policy;
+#endif
+
+/* The following structure defines immutable parameters which need to
+ * be passed as action parameters.
+ *
+ * Note that output plugins may request multiple templates. Let's say
+ * an output requests n templates. Than the overall table must hold
+ * n*nbrMsgs records, and each messages begins on a n-boundary. There
+ * is a macro defined below to access the proper element.
+ *
+ * WARNING: THIS STRUCTURE IS PART OF THE ***OUTPUT MODULE INTERFACE***
+ * It is passed into the doCommit() function. Do NOT modify it until
+ * absolutely necessary - all output plugins need to be changed!
+ *
+ * If a change is "just" for internal working, consider adding a
+ * separate parameter outside of this structure. Of course, it is
+ * best to avoid this as well ;-)
+ * rgerhards, 2013-12-04
+ */
+struct actWrkrIParams {
+ uchar *param;
+ uint32_t lenBuf; /* length of string buffer (if string ptr) */
+ uint32_t lenStr; /* length of current string (if string ptr) */
+};
+
+/* macro to access actWrkrIParams base object:
+ * param is ptr to base address
+ * nActTpls is the number of templates the action has requested
+ * iMsg is the message index
+ * iTpl is the template index
+ * This macro can be used for read and write access.
+ */
+#define actParam(param, nActTpls, iMsg, iTpl) (param[(iMsg*nActTpls)+iTpl])
+
+/* for the time being, we do our own portability handling here. It
+ * looks like autotools either does not yet support checks for it, or
+ * I wasn't smart enough to find them ;) rgerhards, 2007-07-18
+ */
+#ifndef __GNUC__
+# define __attribute__(x) /*NOTHING*/
+#endif
+
+#if !defined(O_CLOEXEC) && !defined(_AIX)
+/* of course, this limits the functionality... */
+# define O_CLOEXEC 0
+#endif
+
+/* some constants */
+#define MUTEX_ALREADY_LOCKED 0
+#define LOCK_MUTEX 1
+
+
+#include "debug.h"
+#include "obj.h"
+
+/* the variable below is a trick: before we can init the runtime, the caller
+ * may want to set a module load path. We can not do this via the glbl class
+ * because it needs an initialized runtime system (and may at some point in time
+ * even be loaded itself). So this is a no-go. What we do is use a single global
+ * variable which may be provided with a pointer by the caller. This variable
+ * resides in rsyslog.c, the main runtime file. We have not seen any realy valule
+ * in providing object access functions. If you don't like that, feel free to
+ * add them. -- rgerhards, 2008-04-17
+ */
+extern uchar *glblModPath; /* module load path */
+extern void (*glblErrLogger)(const int, const int, const uchar*);
+
+/* some runtime prototypes */
+void processImInternal(void);
+rsRetVal rsrtInit(const char **ppErrObj, obj_if_t *pObjIF);
+rsRetVal rsrtExit(void);
+int rsrtIsInit(void);
+void rsrtSetErrLogger(void (*errLogger)(const int, const int, const uchar*));
+void dfltErrLogger(const int, const int, const uchar *errMsg);
+rsRetVal queryLocalHostname(rsconf_t *const);
+
+
+/* this define below is (later) intended to be used to implement empty
+ * structs. TODO: check if compilers supports this and, if not, define
+ * a dummy variable. This requires review of where in code empty structs
+ * are already defined. -- rgerhards, 2010-07-26
+ */
+#ifdef OS_SOLARIS
+#define EMPTY_STRUCT int remove_me_when_first_real_member_is_added;
+#else
+#define EMPTY_STRUCT
+#endif
+
+/* TODO: remove this -- this is only for transition of the config system */
+extern rsconf_t *ourConf; /* defined by syslogd.c, a hack for functions that do not
+ yet receive a copy, so that we can incrementially
+ compile and change... -- rgerhars, 2011-04-19 */
+
+
+/* here we add some stuff from the compatibility layer. A separate include
+ * would be cleaner, but would potentially require changes all over the
+ * place. So doing it here is better. The respective replacement
+ * functions should usually be found under ./compat -- rgerhards, 2015-05-20
+ */
+#ifndef HAVE_STRNDUP
+char * strndup(const char *s, size_t n);
+#endif
+
+#endif /* multi-include protection */
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
new file mode 100644
index 0000000..c137ee3
--- /dev/null
+++ b/runtime/ruleset.c
@@ -0,0 +1,1194 @@
+/* ruleset.c - rsyslog's ruleset object
+ *
+ * We have a two-way structure of linked lists: one config-specifc linked list
+ * (conf->rulesets.llRulesets) hold alls rule sets that we know. Included in each
+ * list is a list of rules (which contain a list of actions, but that's
+ * a different story).
+ *
+ * Usually, only a single rule set is executed. However, there exist some
+ * situations where all rules must be iterated over, for example on HUP. Thus,
+ * we also provide interfaces to do that.
+ *
+ * Module begun 2009-06-10 by Rainer Gerhards
+ *
+ * Copyright 2009-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "cfsysline.h"
+#include "msg.h"
+#include "ruleset.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "batch.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+#include "action.h"
+#include "rainerscript.h"
+#include "srUtils.h"
+#include "modules.h"
+#include "wti.h"
+#include "dirty.h" /* for main ruleset queue creation */
+
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(parser)
+
+/* tables for interfacing with the v6 config system (as far as we need to) */
+static struct cnfparamdescr rspdescr[] = {
+ { "name", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "parser", eCmdHdlrArray, 0 }
+};
+static struct cnfparamblk rspblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(rspdescr)/sizeof(struct cnfparamdescr),
+ rspdescr
+ };
+
+/* forward definitions */
+static rsRetVal processBatch(batch_t *pBatch, wti_t *pWti);
+static rsRetVal scriptExec(struct cnfstmt *root, smsg_t *pMsg, wti_t *pWti);
+
+
+/* ---------- linked-list key handling functions (ruleset) ---------- */
+
+/* destructor for linked list keys.
+ */
+rsRetVal
+rulesetKeyDestruct(void __attribute__((unused)) *pData)
+{
+ free(pData);
+ return RS_RET_OK;
+}
+/* ---------- END linked-list key handling functions (ruleset) ---------- */
+
+
+/* iterate over all actions in a script (stmt subtree) */
+static void
+scriptIterateAllActions(struct cnfstmt *root, rsRetVal (*pFunc)(void*, void*), void* pParam)
+{
+ struct cnfstmt *stmt;
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ case S_SET:
+ case S_UNSET:
+ case S_CALL_INDIRECT:
+ case S_CALL:/* call does not need to do anything - done in called ruleset! */
+ break;
+ case S_ACT:
+ DBGPRINTF("iterateAllActions calling into action %p\n", stmt->d.act);
+ pFunc(stmt->d.act, pParam);
+ break;
+ case S_IF:
+ if(stmt->d.s_if.t_then != NULL)
+ scriptIterateAllActions(stmt->d.s_if.t_then,
+ pFunc, pParam);
+ if(stmt->d.s_if.t_else != NULL)
+ scriptIterateAllActions(stmt->d.s_if.t_else,
+ pFunc, pParam);
+ break;
+ case S_FOREACH:
+ if(stmt->d.s_foreach.body != NULL)
+ scriptIterateAllActions(stmt->d.s_foreach.body,
+ pFunc, pParam);
+ break;
+ case S_PRIFILT:
+ if(stmt->d.s_prifilt.t_then != NULL)
+ scriptIterateAllActions(stmt->d.s_prifilt.t_then,
+ pFunc, pParam);
+ if(stmt->d.s_prifilt.t_else != NULL)
+ scriptIterateAllActions(stmt->d.s_prifilt.t_else,
+ pFunc, pParam);
+ break;
+ case S_PROPFILT:
+ scriptIterateAllActions(stmt->d.s_propfilt.t_then,
+ pFunc, pParam);
+ break;
+ case S_RELOAD_LOOKUP_TABLE: /* this is a NOP */
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u during iterateAll\n",
+ (unsigned) stmt->nodetype);
+ #ifndef NDEBUG
+ fprintf(stderr, "error: unknown stmt type %u during iterateAll\n",
+ (unsigned) stmt->nodetype);
+ #endif
+ assert(0); /* abort under debugging */
+ break;
+ }
+ }
+}
+
+/* driver to iterate over all of this ruleset actions */
+typedef struct iterateAllActions_s {
+ rsRetVal (*pFunc)(void*, void*);
+ void *pParam;
+} iterateAllActions_t;
+/* driver to iterate over all actions */
+DEFFUNC_llExecFunc(doIterateAllActions)
+{
+ DEFiRet;
+ ruleset_t* pThis = (ruleset_t*) pData;
+ iterateAllActions_t *pMyParam = (iterateAllActions_t*) pParam;
+ scriptIterateAllActions(pThis->root, pMyParam->pFunc, pMyParam->pParam);
+ RETiRet;
+}
+/* iterate over ALL actions present in the WHOLE system.
+ * this is often needed, for example when HUP processing
+ * must be done or a shutdown is pending.
+ */
+static rsRetVal
+iterateAllActions(rsconf_t *conf, rsRetVal (*pFunc)(void*, void*), void* pParam)
+{
+ iterateAllActions_t params;
+ DEFiRet;
+ assert(pFunc != NULL);
+
+ params.pFunc = pFunc;
+ params.pParam = pParam;
+ CHKiRet(llExecFunc(&(conf->rulesets.llRulesets), doIterateAllActions, &params));
+
+finalize_it:
+ RETiRet;
+}
+
+/* driver to iterate over all rulesets */
+DEFFUNC_llExecFunc(doActivateRulesetQueues)
+{
+ DEFiRet;
+ ruleset_t* pThis = (ruleset_t*) pData;
+ dbgprintf("Activating Ruleset Queue[%p] for Ruleset %s\n",
+ pThis->pQueue, pThis->pszName);
+ if(pThis->pQueue != NULL)
+ startMainQueue(runConf, pThis->pQueue);
+ RETiRet;
+}
+/* activate all ruleset queues */
+rsRetVal
+activateRulesetQueues(void)
+{
+ llExecFunc(&(runConf->rulesets.llRulesets), doActivateRulesetQueues, NULL);
+ return RS_RET_OK;
+}
+
+
+static rsRetVal
+execAct(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
+{
+ DEFiRet;
+ if(stmt->d.act->bDisabled) {
+ DBGPRINTF("action %d died, do NOT execute\n", stmt->d.act->iActionNbr);
+ FINALIZE;
+ }
+
+ DBGPRINTF("executing action %d\n", stmt->d.act->iActionNbr);
+ stmt->d.act->submitToActQ(stmt->d.act, pWti, pMsg);
+ if(iRet != RS_RET_DISCARDMSG) {
+ /* note: we ignore the error code here, as we do NEVER want to
+ * stop script execution due to action return code
+ */
+ iRet = RS_RET_OK;
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+execSet(const struct cnfstmt *const stmt,
+ smsg_t *const pMsg,
+ wti_t *const __restrict__ pWti)
+{
+ struct svar result;
+ DEFiRet;
+ cnfexprEval(stmt->d.s_set.expr, &result, pMsg, pWti);
+ msgSetJSONFromVar(pMsg, stmt->d.s_set.varname, &result, stmt->d.s_set.force_reset);
+ varDelete(&result);
+ RETiRet;
+}
+
+static rsRetVal
+execUnset(struct cnfstmt *stmt, smsg_t *pMsg)
+{
+ DEFiRet;
+ msgDelJSON(pMsg, stmt->d.s_unset.varname);
+ RETiRet;
+}
+
+static rsRetVal
+execCallIndirect(struct cnfstmt *const __restrict__ stmt,
+ smsg_t *pMsg,
+ wti_t *const __restrict__ pWti)
+{
+ ruleset_t *pRuleset;
+ struct svar result;
+ int bMustFree; /* dummy parameter */
+ DEFiRet;
+
+ assert(stmt->d.s_call_ind.expr != NULL);
+
+ cnfexprEval(stmt->d.s_call_ind.expr, &result, pMsg, pWti);
+ uchar *const rsName = (uchar*) var2CString(&result, &bMustFree);
+ const rsRetVal localRet = rulesetGetRuleset(runConf, &pRuleset, rsName);
+ if(localRet != RS_RET_OK) {
+ /* in that case, we accept that a NOP will "survive" */
+ LogError(0, RS_RET_RULESET_NOT_FOUND, "error: CALL_INDIRECT: "
+ "ruleset '%s' cannot be found, treating as NOP\n", rsName);
+ FINALIZE;
+ }
+ DBGPRINTF("CALL_INDIRECT obtained ruleset ptr %p for ruleset '%s' [hasQueue:%d]\n",
+ pRuleset, rsName, rulesetHasQueue(pRuleset));
+ if(rulesetHasQueue(pRuleset)) {
+ CHKmalloc(pMsg = MsgDup((smsg_t*) pMsg));
+ DBGPRINTF("CALL_INDIRECT: forwarding message to async ruleset %p\n",
+ pRuleset->pQueue);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ MsgSetRuleset(pMsg, pRuleset);
+ /* Note: we intentionally use submitMsg2() here, as we process messages
+ * that were already run through the rate-limiter.
+ */
+ submitMsg2(pMsg);
+ } else {
+ CHKiRet(scriptExec(pRuleset->root, pMsg, pWti));
+ }
+finalize_it:
+ varDelete(&result);
+ free(rsName);
+ RETiRet;
+}
+
+static rsRetVal
+execCall(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
+{
+ DEFiRet;
+ if(stmt->d.s_call.ruleset == NULL) {
+ CHKiRet(scriptExec(stmt->d.s_call.stmt, pMsg, pWti));
+ } else {
+ CHKmalloc(pMsg = MsgDup((smsg_t*) pMsg));
+ DBGPRINTF("CALL: forwarding message to async ruleset %p\n",
+ stmt->d.s_call.ruleset->pQueue);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ MsgSetRuleset(pMsg, stmt->d.s_call.ruleset);
+ /* Note: we intentionally use submitMsg2() here, as we process messages
+ * that were already run through the rate-limiter.
+ */
+ submitMsg2(pMsg);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+execIf(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti)
+{
+ sbool bRet;
+ DEFiRet;
+ bRet = cnfexprEvalBool(stmt->d.s_if.expr, pMsg, pWti);
+ DBGPRINTF("if condition result is %d\n", bRet);
+ if(bRet) {
+ if(stmt->d.s_if.t_then != NULL)
+ CHKiRet(scriptExec(stmt->d.s_if.t_then, pMsg, pWti));
+ } else {
+ if(stmt->d.s_if.t_else != NULL)
+ CHKiRet(scriptExec(stmt->d.s_if.t_else, pMsg, pWti));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+invokeForeachBodyWith(struct cnfstmt *stmt, json_object *o, smsg_t *pMsg, wti_t *pWti) {
+ struct svar v;
+ v.datatype = 'J';
+ v.d.json = o;
+ DEFiRet;
+ CHKiRet(msgSetJSONFromVar(pMsg, (uchar*)stmt->d.s_foreach.iter->var, &v, 1));
+ CHKiRet(scriptExec(stmt->d.s_foreach.body, pMsg, pWti));
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+callForeachArray(struct cnfstmt *stmt, json_object *arr, smsg_t *pMsg, wti_t *pWti) {
+ DEFiRet;
+ int len = json_object_array_length(arr);
+ json_object *curr;
+ for (int i = 0; i < len; i++) {
+ curr = json_object_array_get_idx(arr, i);
+ CHKiRet(invokeForeachBodyWith(stmt, curr, pMsg, pWti));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+callForeachObject(struct cnfstmt *stmt, json_object *arr, smsg_t *pMsg, wti_t *pWti) {
+ json_object *entry = NULL;
+ json_object *key = NULL;
+ const char **keys = NULL;
+ json_object *curr = NULL;
+ const char **curr_key;
+ struct json_object_iterator it;
+ struct json_object_iterator itEnd;
+ DEFiRet;
+
+ int len = json_object_object_length(arr);
+ CHKmalloc(keys = calloc(len, sizeof(char*)));
+ curr_key = keys;
+ it = json_object_iter_begin(arr);
+ itEnd = json_object_iter_end(arr);
+ while (!json_object_iter_equal(&it, &itEnd)) {
+ *curr_key = json_object_iter_peek_name(&it);
+ curr_key++;
+ json_object_iter_next(&it);
+ }
+ CHKmalloc(entry = json_object_new_object());
+ for (int i = 0; i < len; i++) {
+ if (json_object_object_get_ex(arr, keys[i], &curr)) {
+ CHKmalloc(key = json_object_new_string(keys[i]));
+ json_object_object_add(entry, "key", key);
+ key = NULL;
+ json_object_object_add(entry, "value", json_object_get(curr));
+ CHKiRet(invokeForeachBodyWith(stmt, entry, pMsg, pWti));
+ }
+ }
+finalize_it:
+ if (keys != NULL) free(keys);
+ if (entry != NULL) json_object_put(entry);
+ /* "fix" Coverity scan issue CID 185393: key currently can NOT be NULL
+ * However, instead of just removing the
+ * if (key != NULL) json_object_put(key);
+ * we put an assertion in its place.
+ */
+ assert(key == NULL);
+
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+execForeach(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti)
+{
+ json_object *arr = NULL;
+ DEFiRet;
+
+ /* arr can either be an array or an associative-array (obj) */
+ arr = cnfexprEvalCollection(stmt->d.s_foreach.iter->collection, pMsg, pWti);
+
+ if (arr == NULL) {
+ DBGPRINTF("foreach loop skipped, as object to iterate upon is empty\n");
+ FINALIZE;
+ } else if (json_object_is_type(arr, json_type_array) && json_object_array_length(arr) > 0) {
+ CHKiRet(callForeachArray(stmt, arr, pMsg, pWti));
+ } else if (json_object_is_type(arr, json_type_object) && json_object_object_length(arr) > 0) {
+ CHKiRet(callForeachObject(stmt, arr, pMsg, pWti));
+ } else {
+ DBGPRINTF("foreach loop skipped, as object to iterate upon is empty or is not an array\n");
+ FINALIZE;
+ }
+ CHKiRet(msgDelJSON(pMsg, (uchar*)stmt->d.s_foreach.iter->var));
+
+finalize_it:
+ if (arr != NULL) json_object_put(arr);
+
+ RETiRet;
+}
+
+static rsRetVal
+execPRIFILT(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
+{
+ int bRet;
+ DEFiRet;
+ if( (stmt->d.s_prifilt.pmask[pMsg->iFacility] == TABLE_NOPRI) ||
+ ((stmt->d.s_prifilt.pmask[pMsg->iFacility]
+ & (1<<pMsg->iSeverity)) == 0) )
+ bRet = 0;
+ else
+ bRet = 1;
+
+ DBGPRINTF("PRIFILT condition result is %d\n", bRet);
+ if(bRet) {
+ if(stmt->d.s_prifilt.t_then != NULL)
+ CHKiRet(scriptExec(stmt->d.s_prifilt.t_then, pMsg, pWti));
+ } else {
+ if(stmt->d.s_prifilt.t_else != NULL)
+ CHKiRet(scriptExec(stmt->d.s_prifilt.t_else, pMsg, pWti));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* helper to execPROPFILT(), as the evaluation itself is quite lengthy */
+static int
+evalPROPFILT(struct cnfstmt *stmt, smsg_t *pMsg)
+{
+ unsigned short pbMustBeFreed;
+ uchar *pszPropVal;
+ int bRet = 0;
+ rs_size_t propLen;
+
+ if(stmt->d.s_propfilt.prop.id == PROP_INVALID)
+ goto done;
+
+ pszPropVal = MsgGetProp(pMsg, NULL, &stmt->d.s_propfilt.prop,
+ &propLen, &pbMustBeFreed, NULL);
+
+ /* Now do the compares (short list currently ;)) */
+ switch(stmt->d.s_propfilt.operation ) {
+ case FIOP_CONTAINS:
+ if(rsCStrLocateInSzStr(stmt->d.s_propfilt.pCSCompValue, (uchar*) pszPropVal) != -1)
+ bRet = 1;
+ break;
+ case FIOP_ISEMPTY:
+ if(propLen == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_ISEQUAL:
+ if(rsCStrSzStrCmp(stmt->d.s_propfilt.pCSCompValue,
+ pszPropVal, propLen) == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_STARTSWITH:
+ if(rsCStrSzStrStartsWithCStr(stmt->d.s_propfilt.pCSCompValue,
+ pszPropVal, propLen) == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_REGEX:
+ if(rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue,
+ (unsigned char*) pszPropVal, 0, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK)
+ bRet = 1;
+ break;
+ case FIOP_EREREGEX:
+ if(rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue,
+ (unsigned char*) pszPropVal, 1, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK)
+ bRet = 1;
+ break;
+ case FIOP_NOP:
+ default:
+ /* here, it handles NOP (for performance reasons) */
+ assert(stmt->d.s_propfilt.operation == FIOP_NOP);
+ bRet = 1; /* as good as any other default ;) */
+ break;
+ }
+
+ /* now check if the value must be negated */
+ if(stmt->d.s_propfilt.isNegated)
+ bRet = (bRet == 1) ? 0 : 1;
+
+ if(Debug) {
+ if(stmt->d.s_propfilt.prop.id == PROP_CEE) {
+ DBGPRINTF("Filter: check for CEE property '%s' (value '%s') ",
+ stmt->d.s_propfilt.prop.name, pszPropVal);
+ } else if(stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR) {
+ DBGPRINTF("Filter: check for local var '%s' (value '%s') ",
+ stmt->d.s_propfilt.prop.name, pszPropVal);
+ } else if(stmt->d.s_propfilt.prop.id == PROP_GLOBAL_VAR) {
+ DBGPRINTF("Filter: check for global var '%s' (value '%s') ",
+ stmt->d.s_propfilt.prop.name, pszPropVal);
+ } else {
+ DBGPRINTF("Filter: check for property '%s' (value '%s') ",
+ propIDToName(stmt->d.s_propfilt.prop.id), pszPropVal);
+ }
+ if(stmt->d.s_propfilt.isNegated)
+ DBGPRINTF("NOT ");
+ if(stmt->d.s_propfilt.operation == FIOP_ISEMPTY) {
+ DBGPRINTF("%s : %s\n",
+ getFIOPName(stmt->d.s_propfilt.operation),
+ bRet ? "TRUE" : "FALSE");
+ } else {
+ DBGPRINTF("%s '%s': %s\n",
+ getFIOPName(stmt->d.s_propfilt.operation),
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue),
+ bRet ? "TRUE" : "FALSE");
+ }
+ }
+
+ /* cleanup */
+ if(pbMustBeFreed)
+ free(pszPropVal);
+done:
+ return bRet;
+}
+
+static rsRetVal
+execPROPFILT(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
+{
+ sbool bRet;
+ DEFiRet;
+
+ bRet = evalPROPFILT(stmt, pMsg);
+ DBGPRINTF("PROPFILT condition result is %d\n", bRet);
+ if(bRet)
+ CHKiRet(scriptExec(stmt->d.s_propfilt.t_then, pMsg, pWti));
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+execReloadLookupTable(struct cnfstmt *stmt)
+{
+ assert(stmt != NULL);
+ lookup_ref_t *t;
+ DEFiRet;
+ t = stmt->d.s_reload_lookup_table.table;
+ if (t == NULL) {
+ ABORT_FINALIZE(RS_RET_NONE);
+ }
+
+ iRet = lookupReload(t, stmt->d.s_reload_lookup_table.stub_value);
+ /* Note that reload dispatched above is performed asynchronously,
+ on a different thread. So rsRetVal it returns means it was triggered
+ successfully, and not that it was reloaded successfully. */
+
+finalize_it:
+ RETiRet;
+}
+
+/* The rainerscript execution engine. It is debatable if that would be better
+ * contained in grammer/rainerscript.c, HOWEVER, that file focusses primarily
+ * on the parsing and object creation part. So as an actual executor, it is
+ * better suited here.
+ * rgerhards, 2012-09-04
+ */
+static rsRetVal ATTR_NONNULL(2, 3)
+scriptExec(struct cnfstmt *const root, smsg_t *const pMsg, wti_t *const pWti)
+{
+ struct cnfstmt *stmt;
+ DEFiRet;
+
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ if(*pWti->pbShutdownImmediate) {
+ DBGPRINTF("scriptExec: ShutdownImmediate set, "
+ "force terminating\n");
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ }
+ if(Debug) {
+ cnfstmtPrintOnly(stmt, 2, 0);
+ }
+ switch(stmt->nodetype) {
+ case S_NOP:
+ break;
+ case S_STOP:
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ break;
+ case S_ACT:
+ CHKiRet(execAct(stmt, pMsg, pWti));
+ break;
+ case S_SET:
+ CHKiRet(execSet(stmt, pMsg, pWti));
+ break;
+ case S_UNSET:
+ CHKiRet(execUnset(stmt, pMsg));
+ break;
+ case S_CALL:
+ CHKiRet(execCall(stmt, pMsg, pWti));
+ break;
+ case S_CALL_INDIRECT:
+ CHKiRet(execCallIndirect(stmt, pMsg, pWti));
+ break;
+ case S_IF:
+ CHKiRet(execIf(stmt, pMsg, pWti));
+ break;
+ case S_FOREACH:
+ CHKiRet(execForeach(stmt, pMsg, pWti));
+ break;
+ case S_PRIFILT:
+ CHKiRet(execPRIFILT(stmt, pMsg, pWti));
+ break;
+ case S_PROPFILT:
+ CHKiRet(execPROPFILT(stmt, pMsg, pWti));
+ break;
+ case S_RELOAD_LOOKUP_TABLE:
+ CHKiRet(execReloadLookupTable(stmt));
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u during exec\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Process (consume) a batch of messages. Calls the actions configured.
+ * This is called by MAIN queues.
+ */
+static rsRetVal
+processBatch(batch_t *pBatch, wti_t *pWti)
+{
+ int i;
+ smsg_t *pMsg;
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ DBGPRINTF("processBATCH: batch of %d elements must be processed\n", pBatch->nElem);
+
+ wtiResetExecState(pWti, pBatch);
+
+ /* execution phase */
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pWti->pbShutdownImmediate) ; ++i) {
+ pMsg = pBatch->pElem[i].pMsg;
+ DBGPRINTF("processBATCH: next msg %d: %.128s\n", i, pMsg->pszRawMsg);
+ pRuleset = (pMsg->pRuleset == NULL) ? runConf->rulesets.pDflt : pMsg->pRuleset;
+ localRet = scriptExec(pRuleset->root, pMsg, pWti);
+ /* the most important case here is that processing may be aborted
+ * due to pbShutdownImmediate, in which case we MUST NOT flag this
+ * message as committed. If we would do so, the message would
+ * potentially be lost.
+ */
+ if(localRet == RS_RET_OK)
+ batchSetElemState(pBatch, i, BATCH_STATE_COMM);
+ else if(localRet == RS_RET_SUSPENDED)
+ --i;
+ }
+
+ /* commit phase */
+ DBGPRINTF("END batch execution phase, entering to commit phase "
+ "[processed %d of %d messages]\n", i, batchNumMsgs(pBatch));
+ actionCommitAllDirect(pWti);
+
+ DBGPRINTF("processBATCH: batch of %d elements has been processed\n", pBatch->nElem);
+ RETiRet;
+}
+
+
+/* return the ruleset-assigned parser list. NULL means use the default
+ * parser list.
+ * rgerhards, 2009-11-04
+ */
+static parserList_t*
+GetParserList(rsconf_t *conf, smsg_t *pMsg)
+{
+ return (pMsg->pRuleset == NULL) ? conf->rulesets.pDflt->pParserLst : pMsg->pRuleset->pParserLst;
+}
+
+
+/* Add a script block to the current ruleset */
+static void ATTR_NONNULL(1)
+addScript(ruleset_t *const pThis, struct cnfstmt *const script)
+{
+ if(script == NULL) /* happens for include() */
+ return;
+ if(pThis->last == NULL)
+ pThis->root = pThis->last = script;
+ else {
+ pThis->last->next = script;
+ pThis->last = script;
+ }
+}
+
+
+/* set name for ruleset */
+static rsRetVal rulesetSetName(ruleset_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ free(pThis->pszName);
+ CHKmalloc(pThis->pszName = ustrdup(pszName));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get current ruleset
+ * We use a non-standard calling interface, as nothing can go wrong and it
+ * is really much more natural to return the pointer directly.
+ */
+static ruleset_t*
+GetCurrent(rsconf_t *conf)
+{
+ return conf->rulesets.pCurr;
+}
+
+
+/* get main queue associated with ruleset. If no ruleset-specifc main queue
+ * is set, the primary main message queue is returned.
+ * We use a non-standard calling interface, as nothing can go wrong and it
+ * is really much more natural to return the pointer directly.
+ */
+static qqueue_t*
+GetRulesetQueue(ruleset_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, ruleset);
+ return (pThis->pQueue == NULL) ? runConf->pMsgQueue : pThis->pQueue;
+}
+
+
+/* Find the ruleset with the given name and return a pointer to its object.
+ */
+rsRetVal
+rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName)
+{
+ DEFiRet;
+ assert(ppRuleset != NULL);
+ assert(pszName != NULL);
+
+ CHKiRet(llFind(&(conf->rulesets.llRulesets), pszName, (void*) ppRuleset));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set a new default rule set. If the default can not be found, no change happens.
+ */
+static rsRetVal
+SetDefaultRuleset(rsconf_t *conf, uchar *pszName)
+{
+ ruleset_t *pRuleset;
+ DEFiRet;
+ assert(pszName != NULL);
+
+ CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName));
+ conf->rulesets.pDflt = pRuleset;
+ DBGPRINTF("default rule set changed to %p: '%s'\n", pRuleset, pszName);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set a new current rule set. If the ruleset can not be found, no change happens */
+static rsRetVal
+SetCurrRuleset(rsconf_t *conf, uchar *pszName)
+{
+ ruleset_t *pRuleset;
+ DEFiRet;
+ assert(pszName != NULL);
+
+ CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName));
+ conf->rulesets.pCurr = pRuleset;
+ DBGPRINTF("current rule set changed to %p: '%s'\n", pRuleset, pszName);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(ruleset) /* be sure to specify the object type also in END macro! */
+ pThis->root = NULL;
+ pThis->last = NULL;
+ENDobjConstruct(ruleset)
+
+
+/* ConstructionFinalizer
+ * This also adds the rule set to the list of all known rulesets.
+ */
+static rsRetVal
+rulesetConstructFinalize(rsconf_t *conf, ruleset_t *pThis)
+{
+ uchar *keyName;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, ruleset);
+
+ /* we must duplicate our name, as the key destructer would also
+ * free it, resulting in a double-free. It's also cleaner to have
+ * two separate copies.
+ */
+ CHKmalloc(keyName = ustrdup(pThis->pszName));
+ CHKiRet(llAppend(&(conf->rulesets.llRulesets), keyName, pThis));
+
+ /* and also the default, if so far none has been set */
+ if(conf->rulesets.pDflt == NULL)
+ conf->rulesets.pDflt = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* destructor for the ruleset object */
+BEGINobjDestruct(ruleset) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(ruleset)
+ DBGPRINTF("destructing ruleset %p, name %p\n", pThis, pThis->pszName);
+ if(pThis->pQueue != NULL) {
+ qqueueDestruct(&pThis->pQueue);
+ }
+ if(pThis->pParserLst != NULL) {
+ parser.DestructParserList(&pThis->pParserLst);
+ }
+ free(pThis->pszName);
+ENDobjDestruct(ruleset)
+
+
+/* helper for Destructor, shut down queue workers */
+DEFFUNC_llExecFunc(doShutdownQueueWorkers)
+{
+ DEFiRet;
+ ruleset_t *const pThis = (ruleset_t*) pData;
+ DBGPRINTF("shutting down queue workers for ruleset %p, name %s, queue %p\n",
+ pThis, pThis->pszName, pThis->pQueue);
+ ISOBJ_TYPE_assert(pThis, ruleset);
+ if(pThis->pQueue != NULL) {
+ qqueueShutdownWorkers(pThis->pQueue);
+ }
+ RETiRet;
+}
+/* helper for Destructor, shut down actions (cnfstmt's in general) */
+DEFFUNC_llExecFunc(doDestructCnfStmt)
+{
+ DEFiRet;
+ ruleset_t *const pThis = (ruleset_t*) pData;
+ DBGPRINTF("shutting down actions and conf stmts for ruleset %p, name %s\n",
+ pThis, pThis->pszName);
+ ISOBJ_TYPE_assert(pThis, ruleset);
+ cnfstmtDestructLst(pThis->root);
+ RETiRet;
+}
+/* destruct ALL rule sets that reside in the system. This must
+ * be callable before unloading this module as the module may
+ * not be unloaded before unload of the actions is required. This is
+ * kind of a left-over from previous logic and may be optimized one
+ * everything runs stable again. -- rgerhards, 2009-06-10
+ */
+static rsRetVal
+destructAllActions(rsconf_t *conf)
+{
+ DEFiRet;
+
+ DBGPRINTF("rulesetDestructAllActions\n");
+ /* we first need to stop all queue workers, else we
+ * may run into trouble with "call" statements calling
+ * into then-destroyed rulesets.
+ * see: https://github.com/rsyslog/rsyslog/issues/1122
+ */
+ DBGPRINTF("destructAllActions: queue shutdown\n");
+ llExecFunc(&(conf->rulesets.llRulesets), doShutdownQueueWorkers, NULL);
+ DBGPRINTF("destructAllActions: action and conf stmt shutdown\n");
+ llExecFunc(&(conf->rulesets.llRulesets), doDestructCnfStmt, NULL);
+
+ CHKiRet(llDestroy(&(conf->rulesets.llRulesets)));
+ CHKiRet(llInit(&(conf->rulesets.llRulesets), rulesetDestructForLinkedList,
+ rulesetKeyDestruct, strcasecmp));
+ conf->rulesets.pDflt = NULL;
+
+finalize_it:
+ RETiRet;
+}
+
+/* this is a special destructor for the linkedList class. LinkedList does NOT
+ * provide a pointer to the pointer, but rather the raw pointer itself. So we
+ * must map this, otherwise the destructor will abort.
+ */
+rsRetVal
+rulesetDestructForLinkedList(void *pData)
+{
+ ruleset_t *pThis = (ruleset_t*) pData;
+ return rulesetDestruct(&pThis);
+}
+
+/* debugprint for the ruleset object */
+BEGINobjDebugPrint(ruleset) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(ruleset)
+ dbgoprint((obj_t*) pThis, "rsyslog ruleset %s:\n", pThis->pszName);
+ cnfstmtPrint(pThis->root, 0);
+ dbgoprint((obj_t*) pThis, "ruleset %s assigned parser list:\n", pThis->pszName);
+ printParserList(pThis->pParserLst);
+ENDobjDebugPrint(ruleset)
+
+
+/* helper for debugPrintAll(), prints a single ruleset */
+DEFFUNC_llExecFunc(doDebugPrintAll)
+{
+ return rulesetDebugPrint((ruleset_t*) pData);
+}
+/* debug print all rulesets
+ */
+static rsRetVal
+debugPrintAll(rsconf_t *conf)
+{
+ DEFiRet;
+ dbgprintf("All Rulesets:\n");
+ llExecFunc(&(conf->rulesets.llRulesets), doDebugPrintAll, NULL);
+ dbgprintf("End of Rulesets.\n");
+ RETiRet;
+}
+
+struct cnfstmt * removeNOPs(struct cnfstmt *root);
+static void
+rulesetOptimize(ruleset_t *pRuleset)
+{
+ if(Debug) {
+ dbgprintf("ruleset '%s' before optimization:\n",
+ pRuleset->pszName);
+ rulesetDebugPrint((ruleset_t*) pRuleset);
+ }
+ pRuleset->root = cnfstmtOptimize(pRuleset->root);
+ if(Debug) {
+ dbgprintf("ruleset '%s' after optimization:\n",
+ pRuleset->pszName);
+ rulesetDebugPrint((ruleset_t*) pRuleset);
+ }
+}
+
+/* helper for rulsetOptimizeAll(), optimizes a single ruleset */
+DEFFUNC_llExecFunc(doRulesetOptimizeAll)
+{
+ rulesetOptimize((ruleset_t*) pData);
+ return RS_RET_OK;
+}
+/* optimize all rulesets
+ */
+rsRetVal
+rulesetOptimizeAll(rsconf_t *conf)
+{
+ DEFiRet;
+ dbgprintf("begin ruleset optimization phase\n");
+ llExecFunc(&(conf->rulesets.llRulesets), doRulesetOptimizeAll, NULL);
+ dbgprintf("ruleset optimization phase finished.\n");
+ RETiRet;
+}
+
+
+/* Create a ruleset-specific "main" queue for this ruleset. If one is already
+ * defined, an error message is emitted but nothing else is done.
+ * Note: we use the main message queue parameters for queue creation and access
+ * syslogd.c directly to obtain these. This is far from being perfect, but
+ * considered acceptable for the time being.
+ * rgerhards, 2009-10-27
+ */
+static rsRetVal
+doRulesetCreateQueue(rsconf_t *conf, int *pNewVal)
+{
+ uchar *rsname;
+ DEFiRet;
+
+ if(conf->rulesets.pCurr == NULL) {
+ LogError(0, RS_RET_NO_CURR_RULESET, "error: currently no specific ruleset specified, thus a "
+ "queue can not be added to it");
+ ABORT_FINALIZE(RS_RET_NO_CURR_RULESET);
+ }
+
+ if(conf->rulesets.pCurr->pQueue != NULL) {
+ LogError(0, RS_RET_RULES_QUEUE_EXISTS, "error: ruleset already has a main queue, can not "
+ "add another one");
+ ABORT_FINALIZE(RS_RET_RULES_QUEUE_EXISTS);
+ }
+
+ if(pNewVal == 0)
+ FINALIZE; /* if it is turned off, we do not need to change anything ;) */
+
+ rsname = (conf->rulesets.pCurr->pszName == NULL) ? (uchar*) "[ruleset]" : conf->rulesets.pCurr->pszName;
+ DBGPRINTF("adding a ruleset-specific \"main\" queue for ruleset '%s'\n", rsname);
+ CHKiRet(createMainQueue(&conf->rulesets.pCurr->pQueue, rsname, NULL));
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+rulesetCreateQueue(void __attribute__((unused)) *pVal, int *pNewVal)
+{
+ return doRulesetCreateQueue(ourConf, pNewVal);
+}
+
+/* Add a ruleset specific parser to the ruleset. Note that adding the first
+ * parser automatically disables the default parsers. If they are needed as well,
+ * the must be added via explicit config directives.
+ * Note: this is the only spot in the code that requires the parser object. In order
+ * to solve some class init bootstrap sequence problems, we get the object handle here
+ * instead of during module initialization. Note that objUse() is capable of being
+ * called multiple times.
+ * rgerhards, 2009-11-04
+ */
+static rsRetVal
+doRulesetAddParser(ruleset_t *pRuleset, uchar *pName)
+{
+ parser_t *pParser;
+ DEFiRet;
+
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ iRet = parser.FindParser(loadConf->parsers.pParsLstRoot, &pParser, pName);
+ if(iRet == RS_RET_PARSER_NOT_FOUND) {
+ LogError(0, RS_RET_PARSER_NOT_FOUND, "error: parser '%s' unknown at this time "
+ "(maybe defined too late in rsyslog.conf?)", pName);
+ ABORT_FINALIZE(RS_RET_NO_CURR_RULESET);
+ } else if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "error trying to find parser '%s'\n", pName);
+ FINALIZE;
+ }
+
+ CHKiRet(parser.AddParserToList(&pRuleset->pParserLst, pParser));
+
+ DBGPRINTF("added parser '%s' to ruleset '%s'\n", pName, pRuleset->pszName);
+
+finalize_it:
+ free(pName); /* no longer needed */
+
+ RETiRet;
+}
+
+static rsRetVal
+rulesetAddParser(void __attribute__((unused)) *pVal, uchar *pName)
+{
+ return doRulesetAddParser(loadConf->rulesets.pCurr, pName);
+}
+
+
+/* Process ruleset() objects */
+rsRetVal
+rulesetProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ rsRetVal localRet;
+ uchar *rsName = NULL;
+ uchar *parserName;
+ int nameIdx, parserIdx;
+ ruleset_t *pRuleset;
+ struct cnfarray *ar;
+ int i;
+ int qtype;
+ uchar *rsname;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &rspblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
+ }
+ DBGPRINTF("ruleset param blk after rulesetProcessCnf:\n");
+ cnfparamsPrint(&rspblk, pvals);
+ nameIdx = cnfparamGetIdx(&rspblk, "name");
+ rsName = (uchar*)es_str2cstr(pvals[nameIdx].val.d.estr, NULL);
+
+ localRet = rulesetGetRuleset(loadConf, &pRuleset, rsName);
+ if(localRet == RS_RET_OK) {
+ LogError(0, RS_RET_RULESET_EXISTS,
+ "error: ruleset '%s' specified more than once",
+ rsName);
+ cnfstmtDestructLst(o->script);
+ ABORT_FINALIZE(RS_RET_RULESET_EXISTS);
+ } else if(localRet != RS_RET_NOT_FOUND) {
+ ABORT_FINALIZE(localRet);
+ }
+
+ CHKiRet(rulesetConstruct(&pRuleset));
+ if((localRet = rulesetSetName(pRuleset, rsName)) != RS_RET_OK) {
+ rulesetDestruct(&pRuleset);
+ ABORT_FINALIZE(localRet);
+ }
+ if((localRet = rulesetConstructFinalize(loadConf, pRuleset)) != RS_RET_OK) {
+ rulesetDestruct(&pRuleset);
+ ABORT_FINALIZE(localRet);
+ }
+ addScript(pRuleset, o->script);
+
+ /* we have only two params, so we do NOT do the usual param loop */
+ parserIdx = cnfparamGetIdx(&rspblk, "parser");
+ if(parserIdx != -1 && pvals[parserIdx].bUsed) {
+ ar = pvals[parserIdx].val.d.ar;
+ for(i = 0 ; i < ar->nmemb ; ++i) {
+ parserName = (uchar*)es_str2cstr(ar->arr[i], NULL);
+ doRulesetAddParser(pRuleset, parserName);
+ /* note parserName is freed in doRulesetAddParser()! */
+ }
+ }
+
+ /* pick up ruleset queue parameters */
+ if(queueCnfParamsSet(o->nvlst)) {
+ if(pRuleset->pszName == NULL) {
+ rsname = (uchar*) "[ruleset]";
+ qtype = pRuleset->pQueue->qType;
+ } else {
+ rsname = pRuleset->pszName;
+ qtype = 3;
+ }
+ DBGPRINTF("adding a ruleset-specific \"main\" queue for ruleset '%s', mode %d\n",
+ rsname, qtype);
+ CHKiRet(createMainQueue(&pRuleset->pQueue, rsname, o->nvlst));
+ }
+
+finalize_it:
+ free(rsName);
+ cnfparamvalsDestruct(pvals, &rspblk);
+ RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(ruleset)
+CODESTARTobjQueryInterface(ruleset)
+ if(pIf->ifVersion != rulesetCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = rulesetConstruct;
+ pIf->ConstructFinalize = rulesetConstructFinalize;
+ pIf->Destruct = rulesetDestruct;
+ pIf->DebugPrint = rulesetDebugPrint;
+
+ pIf->IterateAllActions = iterateAllActions;
+ pIf->DestructAllActions = destructAllActions;
+ pIf->AddScript = addScript;
+ pIf->ProcessBatch = processBatch;
+ pIf->SetName = rulesetSetName;
+ pIf->DebugPrintAll = debugPrintAll;
+ pIf->GetCurrent = GetCurrent;
+ pIf->GetRuleset = rulesetGetRuleset;
+ pIf->SetDefaultRuleset = SetDefaultRuleset;
+ pIf->SetCurrRuleset = SetCurrRuleset;
+ pIf->GetRulesetQueue = GetRulesetQueue;
+ pIf->GetParserList = GetParserList;
+finalize_it:
+ENDobjQueryInterface(ruleset)
+
+
+/* Exit the ruleset class.
+ * rgerhards, 2009-04-06
+ */
+BEGINObjClassExit(ruleset, OBJ_IS_CORE_MODULE) /* class, version */
+ objRelease(parser, CORE_COMPONENT);
+ENDObjClassExit(ruleset)
+
+
+/* Initialize the ruleset class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, rulesetDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, rulesetConstructFinalize);
+
+ /* config file handlers */
+ CHKiRet(regCfSysLineHdlr((uchar *)"rulesetparser", 0, eCmdHdlrGetWord, rulesetAddParser, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"rulesetcreatemainqueue", 0, eCmdHdlrBinary, rulesetCreateQueue,
+ NULL, NULL));
+ENDObjClassInit(ruleset)
diff --git a/runtime/ruleset.h b/runtime/ruleset.h
new file mode 100644
index 0000000..2b8caca
--- /dev/null
+++ b/runtime/ruleset.h
@@ -0,0 +1,106 @@
+/* The ruleset object.
+ *
+ * This implements rulesets within rsyslog.
+ *
+ * Copyright 2009-2021 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_RULESET_H
+#define INCLUDED_RULESET_H
+
+#include "queue.h"
+#include "linkedlist.h"
+#include "rsconf.h"
+
+/* the ruleset object */
+struct ruleset_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pszName; /* name of our ruleset */
+ qqueue_t *pQueue; /* "main" message queue, if the ruleset has its own (else NULL) */
+ struct cnfstmt *root;
+ struct cnfstmt *last;
+ parserList_t *pParserLst;/* list of parsers to use for this ruleset */
+};
+
+/* interfaces */
+BEGINinterface(ruleset) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(ruleset);
+ rsRetVal (*DebugPrintAll)(rsconf_t *conf);
+ rsRetVal (*Construct)(ruleset_t **ppThis);
+ rsRetVal (*ConstructFinalize)(rsconf_t *conf, ruleset_t __attribute__((unused)) *pThis);
+ rsRetVal (*Destruct)(ruleset_t **ppThis);
+ rsRetVal (*DestructAllActions)(rsconf_t *conf);
+ rsRetVal (*SetName)(ruleset_t *pThis, uchar *pszName);
+ rsRetVal (*ProcessBatch)(batch_t*, wti_t *);
+ rsRetVal (*GetRuleset)(rsconf_t *conf, ruleset_t **ppThis, uchar*);
+ rsRetVal (*SetDefaultRuleset)(rsconf_t *conf, uchar*);
+ rsRetVal (*SetCurrRuleset)(rsconf_t *conf, uchar*);
+ ruleset_t* (*GetCurrent)(rsconf_t *conf);
+ qqueue_t* (*GetRulesetQueue)(ruleset_t*);
+ /* v3, 2009-11-04 */
+ parserList_t* (*GetParserList)(rsconf_t *conf, smsg_t *);
+ /* v5, 2011-04-19
+ * added support for the rsconf object -- fundamental change
+ * v6, 2011-07-15
+ * removed conf ptr from SetName, AddRule as the flex/bison based
+ * system uses globals in any case.
+ */
+ /* v7, 2012-09-04 */
+ /* AddRule() removed */
+ /*TODO:REMOVE*/rsRetVal (*IterateAllActions)(rsconf_t *conf, rsRetVal (*pFunc)(void*, void*), void* pParam);
+ void (*AddScript)(ruleset_t *pThis, struct cnfstmt *script);
+ /* v8: changed processBatch interface */
+ENDinterface(ruleset)
+#define rulesetCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(ruleset);
+
+/* TODO: remove these -- currently done dirty for config file
+ * redo -- rgerhards, 2011-04-19
+ * rgerhards, 2012-04-19: actually, it may be way cooler not to remove
+ * them and use plain c-style conventions at least inside core objects.
+ */
+rsRetVal rulesetDestructForLinkedList(void *pData);
+rsRetVal rulesetKeyDestruct(void __attribute__((unused)) *pData);
+
+/* Get name associated to ruleset. This function cannot fail (except,
+ * of course, if previously something went really wrong). Returned
+ * pointer is read-only.
+ * rgerhards, 2012-04-18
+ */
+#define rulesetGetName(pRuleset) ((pRuleset)->pszName)
+
+/* returns 1 if the ruleset has a queue associated, 0 if not */
+#define rulesetHasQueue(pRuleset) ( ((pRuleset)->pQueue != NULL) \
+ && ((pRuleset)->pQueue->qType != QUEUETYPE_DIRECT) ? 1 : 0 )
+
+
+/* we will most probably convert this module back to traditional C
+ * calling sequence, so here we go...
+ */
+rsRetVal rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName);
+rsRetVal rulesetOptimizeAll(rsconf_t *conf);
+rsRetVal rulesetProcessCnf(struct cnfobj *o);
+rsRetVal activateRulesetQueues(void);
+
+/* Set a current rule set to already-known pointer */
+#define rulesetSetCurrRulesetPtr(pRuleset) (loadConf->rulesets.pCurr = (pRuleset))
+
+#endif /* #ifndef INCLUDED_RULESET_H */
diff --git a/runtime/sigprov.h b/runtime/sigprov.h
new file mode 100644
index 0000000..a1ff006
--- /dev/null
+++ b/runtime/sigprov.h
@@ -0,0 +1,37 @@
+/* The interface definition for (file) signature providers.
+ *
+ * This is just an abstract driver interface, which needs to be
+ * implemented by concrete classes.
+ *
+ * Copyright 2013 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_SIGPROV_H
+#define INCLUDED_SIGPROV_H
+
+/* interface */
+BEGINinterface(sigprov) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(void *ppThis);
+ rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst);
+ rsRetVal (*Destruct)(void *ppThis);
+ rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData);
+ rsRetVal (*OnRecordWrite)(void *pFileInstData, uchar *rec, rs_size_t lenRec);
+ rsRetVal (*OnFileClose)(void *pFileInstData);
+ENDinterface(sigprov)
+#define sigprovCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+#endif /* #ifndef INCLUDED_SIGPROV_H */
diff --git a/runtime/srUtils.h b/runtime/srUtils.h
new file mode 100644
index 0000000..95fee37
--- /dev/null
+++ b/runtime/srUtils.h
@@ -0,0 +1,106 @@
+/*! \file srUtils.h
+ * \brief General, small utilities that fit nowhere else.
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding begun.
+ *
+ * Copyright 2003-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __SRUTILS_H_INCLUDED__
+#define __SRUTILS_H_INCLUDED__ 1
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/* syslog names */
+#ifndef LOG_MAKEPRI
+# define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+#endif
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+#define TABLE_NOPRI 0 /* Value to indicate no priority in f_pmask */
+#define TABLE_ALLPRI 0xFF /* Value to indicate all priorities in f_pmask */
+#define LOG_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */
+
+typedef struct syslogName_s {
+ const char *c_name;
+ int c_val;
+} syslogName_t;
+
+extern syslogName_t syslogPriNames[];
+extern syslogName_t syslogFacNames[];
+
+/**
+ * A reimplementation of itoa(), as this is not available
+ * on all platforms. We used the chance to make an interface
+ * that fits us well, so it is no longer plain itoa().
+ *
+ * This method works with the US-ASCII alphabet. If you port this
+ * to e.g. EBCDIC, you need to make a small adjustment. Keep in mind,
+ * that on the wire it MUST be US-ASCII, so basically all you need
+ * to do is replace the constant '0' with 0x30 ;).
+ *
+ * \param pBuf Caller-provided buffer that will receive the
+ * generated ASCII string.
+ *
+ * \param iLenBuf Length of the caller-provided buffer.
+ *
+ * \param iToConv The integer to be converted.
+ */
+rsRetVal srUtilItoA(char *pBuf, int iLenBuf, number_t iToConv);
+
+/**
+ * A method to duplicate a string for which the length is known.
+ * Len must be the length in characters WITHOUT the trailing
+ * '\0' byte.
+ * rgerhards, 2007-07-10
+ */
+unsigned char *srUtilStrDup(unsigned char *pOld, size_t len);
+/**
+ * A method to create a directory and all its missing parents for
+ * a given file name. Please not that the rightmost element is
+ * considered to be a file name and thus NO directory is being created
+ * for it.
+ * added 2007-07-17 by rgerhards
+ */
+int makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode,
+ const uid_t uid, const gid_t gid, const int bFailOnChown);
+int execProg(uchar *program, int bWait, uchar *arg);
+void skipWhiteSpace(uchar **pp);
+rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName,
+ size_t lenFName, int64_t lNum, int lNumDigits);
+int getNumberDigits(long lNum);
+rsRetVal timeoutComp(struct timespec *pt, long iTimeout);
+long timeoutVal(struct timespec *pt);
+void mutexCancelCleanup(void *arg);
+void srSleep(int iSeconds, int iuSeconds);
+char *rs_strerror_r(int errnum, char *buf, size_t buflen);
+int decodeSyslogName(uchar *name, syslogName_t *codetab);
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
+rsRetVal getFileSize(uchar *pszName, off_t *pSize);
+int containsGlobWildcard(char *str);
+void seedRandomNumber(void);
+void seedRandomNumberForChild(void);
+#define MAX_RANDOM_NUMBER RAND_MAX
+long int randomNumber(void);
+long long currentTimeMills(void);
+rsRetVal ATTR_NONNULL() split_binary_parameters(uchar **const szBinary,
+ char ***const aParams, int *const iParams, es_str_t *const param_binary);
+
+#endif /* #ifndef __SRUTILS_H_INCLUDED__ */
diff --git a/runtime/srutils.c b/runtime/srutils.c
new file mode 100644
index 0000000..3369975
--- /dev/null
+++ b/runtime/srutils.c
@@ -0,0 +1,868 @@
+/**\file srUtils.c
+ * \brief General utilties that fit nowhere else.
+ *
+ * The namespace for this file is "srUtil".
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding begun.
+ *
+ * Copyright 2003-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <assert.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <fcntl.h>
+
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "rsconf.h"
+
+#if _POSIX_TIMERS <= 0
+#include <sys/time.h>
+#endif
+
+/* here we host some syslog specific names. There currently is no better place
+ * to do it, but over here is also not ideal... -- rgerhards, 2008-02-14
+ * rgerhards, 2008-04-16: note in LGPL move: the code tables below exist in
+ * the same way in BSD, so it is not a problem to move them from GPLv3 to LGPL.
+ * And nobody modified them since it was under LGPL, so we can also move it
+ * to ASL 2.0.
+ */
+syslogName_t syslogPriNames[] = {
+ {"alert", LOG_ALERT},
+ {"crit", LOG_CRIT},
+ {"debug", LOG_DEBUG},
+ {"emerg", LOG_EMERG},
+ {"err", LOG_ERR},
+ {"error", LOG_ERR}, /* DEPRECATED */
+ {"info", LOG_INFO},
+ {"none", INTERNAL_NOPRI}, /* INTERNAL */
+ {"notice", LOG_NOTICE},
+ {"panic", LOG_EMERG}, /* DEPRECATED */
+ {"warn", LOG_WARNING}, /* DEPRECATED */
+ {"warning", LOG_WARNING},
+ {"*", TABLE_ALLPRI},
+ {NULL, -1}
+};
+
+#ifndef LOG_AUTHPRIV
+# define LOG_AUTHPRIV LOG_AUTH
+#endif
+syslogName_t syslogFacNames[] = {
+ {"auth", LOG_AUTH},
+ {"authpriv", LOG_AUTHPRIV},
+ {"cron", LOG_CRON},
+ {"daemon", LOG_DAEMON},
+ {"kern", LOG_KERN},
+ {"lpr", LOG_LPR},
+ {"mail", LOG_MAIL},
+ {"mark", LOG_MARK}, /* INTERNAL */
+ {"news", LOG_NEWS},
+ {"ntp", (12<<3) }, /* NTP, perhaps BSD-specific? */
+ {"security", LOG_AUTH}, /* DEPRECATED */
+ {"bsd_security", (13<<3) }, /* BSD-specific, unfortunatly with duplicate name... */
+ {"syslog", LOG_SYSLOG},
+ {"user", LOG_USER},
+ {"uucp", LOG_UUCP},
+#if defined(_AIX) /* AIXPORT : These are necessary for AIX */
+ { "caa", LOG_CAA },
+ { "aso", LOG_ASO },
+#endif
+#if defined(LOG_FTP)
+ {"ftp", LOG_FTP},
+#endif
+#if defined(LOG_AUDIT)
+ {"audit", LOG_AUDIT},
+#endif
+ {"console", (14 << 3)}, /* BSD-specific priority */
+ {"local0", LOG_LOCAL0},
+ {"local1", LOG_LOCAL1},
+ {"local2", LOG_LOCAL2},
+ {"local3", LOG_LOCAL3},
+ {"local4", LOG_LOCAL4},
+ {"local5", LOG_LOCAL5},
+ {"local6", LOG_LOCAL6},
+ {"local7", LOG_LOCAL7},
+ {"invld", LOG_INVLD},
+ {NULL, -1},
+};
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+/* As this is not a "real" object, there won't be any private
+ * members in this file.
+ */
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+rsRetVal srUtilItoA(char *pBuf, int iLenBuf, number_t iToConv)
+{
+ int i;
+ int bIsNegative;
+ char szBuf[64]; /* sufficiently large for my lifespan and those of my children... ;) */
+
+ assert(pBuf != NULL);
+ assert(iLenBuf > 1); /* This is actually an app error and as thus checked for... */
+
+ if(iToConv < 0)
+ {
+ bIsNegative = RSTRUE;
+ iToConv *= -1;
+ }
+ else
+ bIsNegative = RSFALSE;
+
+ /* first generate a string with the digits in the reverse direction */
+ i = 0;
+ do
+ {
+ szBuf[i++] = iToConv % 10 + '0';
+ iToConv /= 10;
+ } while(iToConv > 0); /* warning: do...while()! */
+ --i; /* undo last increment - we were pointing at NEXT location */
+
+ /* make sure we are within bounds... */
+ if(i + 2 > iLenBuf) /* +2 because: a) i starts at zero! b) the \0 byte */
+ return RS_RET_PROVIDED_BUFFER_TOO_SMALL;
+
+ /* then move it to the right direction... */
+ if(bIsNegative == RSTRUE)
+ *pBuf++ = '-';
+ while(i >= 0)
+ *pBuf++ = szBuf[i--];
+ *pBuf = '\0'; /* terminate it!!! */
+
+ return RS_RET_OK;
+}
+
+uchar *srUtilStrDup(uchar *pOld, size_t len)
+{
+ uchar *pNew;
+
+ assert(pOld != NULL);
+
+ if((pNew = malloc(len + 1)) != NULL)
+ memcpy(pNew, pOld, len + 1);
+
+ return pNew;
+}
+
+
+/* creates a path recursively
+ * Return 0 on success, -1 otherwise. On failure, errno * hold the last OS error.
+ * Param "mode" holds the mode that all non-existing directories are to be
+ * created with.
+ * Note that we have a potential race inside that code, a race that even exists
+ * outside of the rsyslog process (if multiple instances run, or other programs
+ * generate directories): If the directory does not exist, a context switch happens,
+ * at that moment another process creates it, then our creation on the context
+ * switch back fails. This actually happened in practice, and depending on the
+ * configuration it is even likely to happen. We can not solve this situation
+ * with a mutex, as that works only within out process space. So the solution
+ * is that we take the optimistic approach, try the creation, and if it fails
+ * with "already exists" we go back and do one retry of the check/create
+ * sequence. That should then succeed. If the directory is still not found but
+ * the creation fails in the similar way, we return an error on that second
+ * try because otherwise we would potentially run into an endless loop.
+ * loop. -- rgerhards, 2010-03-25
+ * The likeliest scenario for a prolonged contest of creating the parent directiories
+ * is within our process space. This can happen with a high probability when two
+ * threads, that want to start logging to files within same directory tree, are
+ * started close to each other. We should fix what we can. -- nipakoo, 2017-11-25
+ */
+static int real_makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode,
+ const uid_t uid, const gid_t gid, const int bFailOnChownFail)
+{
+ uchar *p;
+ uchar *pszWork;
+ size_t len;
+
+ assert(szFile != NULL);
+ assert(lenFile > 0);
+
+ len = lenFile + 1; /* add one for '\0'-byte */
+ if((pszWork = malloc(len)) == NULL)
+ return -1;
+ memcpy(pszWork, szFile, len);
+ for(p = pszWork+1 ; *p ; p++)
+ if(*p == '/') {
+ /* temporarily terminate string, create dir and go on */
+ *p = '\0';
+ int bErr = 0;
+ if(mkdir((char*)pszWork, mode) == 0) {
+ if(uid != (uid_t) -1 || gid != (gid_t) -1) {
+ /* we need to set owner/group */
+ if(chown((char*)pszWork, uid, gid) != 0) {
+ LogError(errno, RS_RET_DIR_CHOWN_ERROR,
+ "chown for directory '%s' failed", pszWork);
+ if(bFailOnChownFail) {
+ /* ignore if configured to do so */
+ bErr = 1;
+ }
+ }
+ }
+ } else if(errno != EEXIST) {
+ /* EEXIST is ok, means this component exists */
+ bErr = 1;
+ }
+
+ if(bErr) {
+ int eSave = errno;
+ free(pszWork);
+ errno = eSave;
+ return -1;
+ }
+ *p = '/';
+ }
+ free(pszWork);
+ return 0;
+}
+/* note: this small function is the stub for the brain-dead POSIX cancel handling */
+int makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode,
+ const uid_t uid, const gid_t gid, const int bFailOnChownFail)
+{
+ static pthread_mutex_t mutParentDir = PTHREAD_MUTEX_INITIALIZER;
+ int r; /* needs to be declared OUTSIDE of pthread_cleanup... macros! */
+ pthread_mutex_lock(&mutParentDir);
+ pthread_cleanup_push(mutexCancelCleanup, &mutParentDir);
+
+ r = real_makeFileParentDirs(szFile, lenFile, mode, uid, gid, bFailOnChownFail);
+
+ pthread_mutex_unlock(&mutParentDir);
+ pthread_cleanup_pop(0);
+ return r;
+}
+
+
+/* execute a program with a single argument
+ * returns child pid if everything ok, 0 on failure. if
+ * it fails, errno is set. if it fails after the fork(), the caller
+ * can not be notfied for obvious reasons. if bwait is set to 1,
+ * the code waits until the child terminates - that potentially takes
+ * a lot of time.
+ * implemented 2007-07-20 rgerhards
+ */
+int execProg(uchar *program, int bWait, uchar *arg)
+{
+ int pid;
+ int sig;
+ struct sigaction sigAct;
+
+ dbgprintf("exec program '%s' with param '%s'\n", program, arg);
+ pid = fork();
+ if (pid < 0) {
+ return 0;
+ }
+
+ if(pid) { /* Parent */
+ if(bWait) {
+ /* waitpid will fail with errno == ECHILD if the child process has already
+ been reaped by the rsyslogd main loop (see rsyslogd.c) */
+ int status;
+ if(waitpid(pid, &status, 0) == pid) {
+ glblReportChildProcessExit(runConf, program, pid, status);
+ } else if(errno != ECHILD) {
+ /* we do not use logerror(), because
+ * that might bring us into an endless
+ * loop. At some time, we may
+ * reconsider this behaviour.
+ */
+ dbgprintf("could not wait on child after executing '%s'",
+ (char*)program);
+ }
+ }
+ return pid;
+ }
+ /* Child */
+ alarm(0); /* create a clean environment before we exec the real child */
+
+ memset(&sigAct, 0, sizeof(sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = SIG_DFL;
+
+ for(sig = 1 ; sig < NSIG ; ++sig)
+ sigaction(sig, &sigAct, NULL);
+
+ execlp((char*)program, (char*) program, (char*)arg, NULL);
+ /* In the long term, it's a good idea to implement some enhanced error
+ * checking here. However, it can not easily be done. For starters, we
+ * may run into endless loops if we log to syslog. The next problem is
+ * that output is typically not seen by the user. For the time being,
+ * we use no error reporting, which is quite consitent with the old
+ * system() way of doing things. rgerhards, 2007-07-20
+ */
+ perror("exec");
+ fprintf(stderr, "exec program was '%s' with param '%s'\n", program, arg);
+ exit(1); /* not much we can do in this case */
+}
+
+
+/* skip over whitespace in a standard C string. The
+ * provided pointer is advanced to the first non-whitespace
+ * charater or the \0 byte, if there is none. It is never
+ * moved past the \0.
+ */
+void skipWhiteSpace(uchar **pp)
+{
+ register uchar *p;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ p = *pp;
+ while(*p && isspace((int) *p))
+ ++p;
+ *pp = p;
+}
+
+
+/* generate a file name from four parts:
+ * <directory name>/<name>.<number>
+ * If number is negative, it is not used. If any of the strings is
+ * NULL, an empty string is used instead. Length must be provided.
+ * lNumDigits is the minimum number of digits that lNum should have. This
+ * is to pretty-print the file name, e.g. lNum = 3, lNumDigits= 4 will
+ * result in "0003" being used inside the file name. Set lNumDigits to 0
+ * to use as few space as possible.
+ * rgerhards, 2008-01-03
+ */
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wformat_nonliteral
+rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName,
+ size_t lenFName, int64_t lNum, int lNumDigits)
+{
+ DEFiRet;
+ uchar *pName;
+ uchar *pNameWork;
+ size_t lenName;
+ uchar szBuf[128]; /* buffer for number */
+ char szFmtBuf[32]; /* buffer for snprintf format */
+ size_t lenBuf;
+
+ if(lNum < 0) {
+ szBuf[0] = '\0';
+ lenBuf = 0;
+ } else {
+ if(lNumDigits > 0) {
+ snprintf(szFmtBuf, sizeof(szFmtBuf), ".%%0%d" PRId64, lNumDigits);
+ lenBuf = snprintf((char*)szBuf, sizeof(szBuf), szFmtBuf, lNum);
+ } else
+ lenBuf = snprintf((char*)szBuf, sizeof(szBuf), ".%" PRId64, lNum);
+ }
+
+ lenName = lenDirName + 1 + lenFName + lenBuf + 1; /* last +1 for \0 char! */
+ if((pName = malloc(lenName)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ /* got memory, now construct string */
+ memcpy(pName, pDirName, lenDirName);
+ pNameWork = pName + lenDirName;
+ *pNameWork++ = '/';
+ memcpy(pNameWork, pFName, lenFName);
+ pNameWork += lenFName;
+ if(lenBuf > 0) {
+ memcpy(pNameWork, szBuf, lenBuf);
+ pNameWork += lenBuf;
+ }
+ *pNameWork = '\0';
+
+ *ppName = pName;
+
+finalize_it:
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+/* get the number of digits required to represent a given number. We use an
+ * iterative approach as we do not like to draw in the floating point
+ * library just for log(). -- rgerhards, 2008-01-10
+ */
+int getNumberDigits(long lNum)
+{
+ int iDig;
+
+ if(lNum == 0)
+ iDig = 1;
+ else
+ for(iDig = 0 ; lNum != 0 ; ++iDig)
+ lNum /= 10;
+
+ return iDig;
+}
+
+
+/* compute an absolute time timeout suitable for calls to pthread_cond_timedwait()
+ * iTimeout is in milliseconds
+ * rgerhards, 2008-01-14
+ */
+rsRetVal
+timeoutComp(struct timespec *pt, long iTimeout)
+{
+# if _POSIX_TIMERS <= 0
+ struct timeval tv;
+# endif
+
+ assert(pt != NULL);
+ /* compute timeout */
+
+# if _POSIX_TIMERS > 0
+ /* this is the "regular" code */
+ clock_gettime(CLOCK_REALTIME, pt);
+# else
+ gettimeofday(&tv, NULL);
+ pt->tv_sec = tv.tv_sec;
+ pt->tv_nsec = tv.tv_usec * 1000;
+# endif
+ pt->tv_sec += iTimeout / 1000;
+ pt->tv_nsec += (iTimeout % 1000) * 1000000; /* think INTEGER arithmetic! */
+ if(pt->tv_nsec > 999999999) { /* overrun? */
+ pt->tv_nsec -= 1000000000;
+ ++pt->tv_sec;
+ }
+ return RS_RET_OK; /* so far, this is static... */
+}
+
+long long
+currentTimeMills(void)
+{
+ struct timespec tm;
+# if _POSIX_TIMERS <= 0
+ struct timeval tv;
+# endif
+
+# if _POSIX_TIMERS > 0
+ clock_gettime(CLOCK_REALTIME, &tm);
+# else
+ gettimeofday(&tv, NULL);
+ tm.tv_sec = tv.tv_sec;
+ tm.tv_nsec = tv.tv_usec * 1000;
+# endif
+
+ return ((long long) tm.tv_sec) * 1000 + (tm.tv_nsec / 1000000);
+}
+
+
+/* This function is kind of the reverse of timeoutComp() - it takes an absolute
+ * timeout value and computes how far this is in the future. If the value is already
+ * in the past, 0 is returned. The return value is in ms.
+ * rgerhards, 2008-01-25
+ */
+long
+timeoutVal(struct timespec *pt)
+{
+ struct timespec t;
+ long iTimeout;
+# if _POSIX_TIMERS <= 0
+ struct timeval tv;
+# endif
+
+ assert(pt != NULL);
+ /* compute timeout */
+# if _POSIX_TIMERS > 0
+ /* this is the "regular" code */
+ clock_gettime(CLOCK_REALTIME, &t);
+# else
+ gettimeofday(&tv, NULL);
+ t.tv_sec = tv.tv_sec;
+ t.tv_nsec = tv.tv_usec * 1000;
+# endif
+ iTimeout = (pt->tv_nsec - t.tv_nsec) / 1000000;
+ iTimeout += (pt->tv_sec - t.tv_sec) * 1000;
+
+ if(iTimeout < 0)
+ iTimeout = 0;
+
+ return iTimeout;
+}
+
+
+/* cancellation cleanup handler - frees provided mutex
+ * rgerhards, 2008-01-14
+ */
+void
+mutexCancelCleanup(void *arg)
+{
+ assert(arg != NULL);
+ d_pthread_mutex_unlock((pthread_mutex_t*) arg);
+}
+
+
+/* rsSleep() - a fairly portable way to to sleep. It
+ * will wake up when
+ * a) the wake-time is over
+ * rgerhards, 2008-01-28
+ */
+void
+srSleep(int iSeconds, int iuSeconds)
+{
+ struct timeval tvSelectTimeout;
+
+ tvSelectTimeout.tv_sec = iSeconds;
+ tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */
+ select(0, NULL, NULL, NULL, &tvSelectTimeout);
+}
+
+
+/* From varmojfekoj's mail on why he provided rs_strerror_r():
+ * There are two problems with strerror_r():
+ * I see you've rewritten some of the code which calls it to use only
+ * the supplied buffer; unfortunately the GNU implementation sometimes
+ * doesn't use the buffer at all and returns a pointer to some
+ * immutable string instead, as noted in the man page.
+ *
+ * The other problem is that on some systems strerror_r() has a return
+ * type of int.
+ *
+ * So I've written a wrapper function rs_strerror_r(), which should
+ * take care of all this and be used instead.
+ *
+ * Added 2008-01-30
+ */
+char *rs_strerror_r(int errnum, char *buf, size_t buflen) {
+#ifndef HAVE_STRERROR_R
+ char *pszErr;
+ pszErr = strerror(errnum);
+ snprintf(buf, buflen, "%s", pszErr);
+#else
+# ifdef STRERROR_R_CHAR_P
+ char *p = strerror_r(errnum, buf, buflen);
+ if (p != buf) {
+ strncpy(buf, p, buflen);
+ buf[buflen - 1] = '\0';
+ }
+# else
+ strerror_r(errnum, buf, buflen);
+# endif
+#endif /* #ifdef __hpux */
+ return buf;
+}
+
+
+/* Decode a symbolic name to a numeric value */
+int decodeSyslogName(uchar *name, syslogName_t *codetab)
+{
+ register syslogName_t *c;
+ register uchar *p;
+ uchar buf[80];
+
+ assert(name != NULL);
+ assert(codetab != NULL);
+
+ DBGPRINTF("symbolic name: %s", name);
+ if(isdigit((int) *name)) {
+ DBGPRINTF("\n");
+ return (atoi((char*) name));
+ }
+ strncpy((char*) buf, (char*) name, 79);
+ for(p = buf; *p; p++) {
+ if (isupper((int) *p))
+ *p = tolower((int) *p);
+ }
+ for(c = codetab; c->c_name; c++) {
+ if(!strcmp((char*) buf, (char*) c->c_name)) {
+ DBGPRINTF(" ==> %d\n", c->c_val);
+ return (c->c_val);
+ }
+ }
+ DBGPRINTF("\n");
+ return (-1);
+}
+
+
+/**
+ * getSubString
+ *
+ * Copy a string byte by byte until the occurrence
+ * of a given separator.
+ *
+ * \param ppSrc Pointer to a pointer of the source array of characters. If a
+ separator detected the Pointer points to the next char after the
+ separator. Except if the end of the string is dedected ('\n').
+ Then it points to the terminator char.
+ * \param pDst Pointer to the destination array of characters. Here the substing
+ will be stored.
+ * \param DstSize Maximum numbers of characters to store.
+ * \param cSep Separator char.
+ * \ret int Returns 0 if no error occurred.
+ *
+ * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time
+ * so that it treats ' ' as a request for whitespace. But in general, the function and its callers
+ * should be changed over time, this is not really very good code...
+ */
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
+{
+ uchar *pSrc = *ppSrc;
+ int iErr = 0; /* 0 = no error, >0 = error */
+ while((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
+ *pDst++ = *(pSrc)++;
+ DstSize--;
+ }
+ /* check if the Dst buffer was to small */
+ if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') {
+ dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
+ iErr = 1;
+ }
+ if (*pSrc == '\0' || *pSrc == '\n')
+ /* this line was missing, causing ppSrc to be invalid when it
+ * was returned in case of end-of-string. rgerhards 2005-07-29
+ */
+ *ppSrc = pSrc;
+ else
+ *ppSrc = pSrc+1;
+ *pDst = '\0';
+ return iErr;
+}
+
+
+/* get the size of a file or return appropriate error code. If an error is returned,
+ * *pSize content is undefined.
+ * rgerhards, 2009-06-12
+ */
+rsRetVal
+getFileSize(uchar *pszName, off_t *pSize)
+{
+ int ret;
+ struct stat statBuf;
+ DEFiRet;
+
+ ret = stat((char*) pszName, &statBuf);
+ if(ret == -1) {
+ switch(errno) {
+ case EACCES: ABORT_FINALIZE(RS_RET_NO_FILE_ACCESS);
+ case ENOTDIR:
+ case ENOENT: ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ default: ABORT_FINALIZE(RS_RET_FILE_NO_STAT);
+ }
+ }
+
+ *pSize = statBuf.st_size;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Returns 1 if the given string contains a non-escaped glob(3)
+ * wildcard character and 0 otherwise (or if the string is empty).
+ */
+int
+containsGlobWildcard(char *str)
+{
+ char *p;
+ if(!str) {
+ return 0;
+ }
+ /* From Linux Programmer's Guide:
+ * "A string is a wildcard pattern if it contains one of the characters '?', '*', '{' or '['"
+ * "One can remove the special meaning of '?', '*', '{' and '[' by preceding them by a backslash"
+ */
+ for(p = str; *p != '\0'; p++) {
+ if((*p == '?' || *p == '*' || *p == '[' || *p == '{') &&
+ (p == str || *(p-1) != '\\')) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void seedRandomInsecureNumber(void)
+{
+ struct timespec t;
+ timeoutComp(&t, 0);
+ long long x = t.tv_sec * 3 + t.tv_nsec * 2;
+ srandom((unsigned int) x);
+}
+
+static long int randomInsecureNumber(void)
+{
+ return random();
+}
+
+#ifdef OS_LINUX
+static int fdURandom = -1;
+void seedRandomNumber(void)
+{
+ if(fdURandom >= 0) {
+ /* Already opened. */
+ return;
+ }
+ fdURandom = open("/dev/urandom", O_RDONLY);
+ if(fdURandom == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "failed to seed random number generation,"
+ " will use fallback (open urandom failed)");
+ seedRandomInsecureNumber();
+ }
+}
+
+void seedRandomNumberForChild(void)
+{
+ /* The file descriptor inherited from our parent will have been closed after
+ * the fork. Discard this and call seedRandomNumber() to open /dev/urandom
+ * again.
+ */
+ fdURandom = -1;
+ seedRandomNumber();
+}
+
+long int randomNumber(void)
+{
+ long int ret;
+ if(fdURandom >= 0) {
+ if(read(fdURandom, &ret, sizeof(long int)) == -1) {
+ LogError(errno, RS_RET_IO_ERROR, "failed to generate random number, will"
+ " use fallback (read urandom failed)");
+ ret = randomInsecureNumber();
+ }
+ } else {
+ ret = randomInsecureNumber();
+ }
+ return ret;
+}
+#else
+void seedRandomNumber(void)
+{
+ seedRandomInsecureNumber();
+}
+
+void seedRandomNumberForChild(void)
+{
+ seedRandomNumber();
+}
+
+long int randomNumber(void)
+{
+ return randomInsecureNumber();
+}
+#endif
+
+
+/* process "binary" parameters where this is needed to execute
+ * programs (namely mmexternal and omprog).
+ * Most importantly, split them into argv[] and get the binary name
+ */
+rsRetVal ATTR_NONNULL()
+split_binary_parameters(uchar **const szBinary, char ***const __restrict__ aParams,
+ int *const iParams, es_str_t *const param_binary)
+{
+ es_size_t iCnt;
+ es_size_t iStr;
+ int iPrm;
+ es_str_t *estrParams = NULL;
+ es_str_t *estrBinary = param_binary;
+ es_str_t *estrTmp = NULL;
+ uchar *c;
+ int bInQuotes;
+ DEFiRet;
+ assert(iParams != NULL);
+ assert(param_binary != NULL);
+
+ /* Search for end of binary name */
+ c = es_getBufAddr(param_binary);
+ iCnt = 0;
+ while(iCnt < es_strlen(param_binary) ) {
+ if (c[iCnt] == ' ') {
+ /* Split binary name from parameters */
+ estrBinary = es_newStrFromSubStr( param_binary, 0, iCnt);
+ estrParams = es_newStrFromSubStr( param_binary, iCnt+1,
+ es_strlen(param_binary));
+ break;
+ }
+ iCnt++;
+ }
+ *szBinary = (uchar*)es_str2cstr(estrBinary, NULL);
+ DBGPRINTF("szBinary = '%s'\n", *szBinary);
+
+ *iParams = 1; /* we always have argv[0] */
+ /* count size of argv[] */
+ if (estrParams != NULL) {
+ (*iParams)++; /* last parameter is not counted in loop below! */
+ if(Debug) {
+ char *params = es_str2cstr(estrParams, NULL);
+ dbgprintf("szParams = '%s'\n", params);
+ free(params);
+ }
+ c = es_getBufAddr(estrParams);
+ for(iCnt = 0 ; iCnt < es_strlen(estrParams) ; ++iCnt) {
+ if (c[iCnt] == ' ' && c[iCnt-1] != '\\')
+ (*iParams)++;
+ }
+ }
+ DBGPRINTF("iParams %d (+1 for NULL terminator)\n", *iParams);
+
+ /* create argv[] */
+ CHKmalloc(*aParams = malloc((*iParams + 1) * sizeof(char*)));
+ iPrm = 0;
+ bInQuotes = FALSE;
+ /* Set first parameter to binary */
+ (*aParams)[iPrm] = strdup((char*)*szBinary);
+ iPrm++;
+ if (estrParams != NULL) {
+ iCnt = iStr = 0;
+ c = es_getBufAddr(estrParams); /* Reset to beginning */
+ while(iCnt < es_strlen(estrParams) ) {
+ if ( c[iCnt] == ' ' && !bInQuotes ) {
+ estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
+ } else if ( iCnt+1 >= es_strlen(estrParams) ) {
+ estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
+ } else if (c[iCnt] == '"') {
+ bInQuotes = !bInQuotes;
+ }
+
+ if ( estrTmp != NULL ) {
+ (*aParams)[iPrm] = es_str2cstr(estrTmp, NULL);
+ iStr = iCnt+1; /* Set new start */
+ DBGPRINTF("Param (%d): '%s'\n", iPrm, (*aParams)[iPrm]);
+ es_deleteStr( estrTmp );
+ estrTmp = NULL;
+ iPrm++;
+ }
+ iCnt++;
+ }
+ }
+ (*aParams)[iPrm] = NULL; /* NULL per argv[] convention */
+
+finalize_it:
+ if(estrBinary != param_binary) {
+ es_deleteStr(estrBinary);
+ }
+ if(estrParams != NULL) {
+ es_deleteStr(estrParams);
+ }
+ RETiRet;
+}
diff --git a/runtime/statsobj.c b/runtime/statsobj.c
new file mode 100644
index 0000000..ad959f5
--- /dev/null
+++ b/runtime/statsobj.c
@@ -0,0 +1,761 @@
+/* The statsobj object.
+ *
+ * This object provides a statistics-gathering facility inside rsyslog. This
+ * functionality will be pragmatically implemented and extended.
+ *
+ * Copyright 2010-2021 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h>
+#include <assert.h>
+#include <json.h>
+
+#include "rsyslog.h"
+#include "unicode-helper.h"
+#include "obj.h"
+#include "statsobj.h"
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "errmsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "rsconf.h"
+
+
+/* externally-visiable data (see statsobj.h for explanation) */
+int GatherStats = 0;
+
+/* static data */
+DEFobjStaticHelpers
+
+/* doubly linked list of stats objects. Object is automatically linked to it
+ * upon construction. Enqueue always happens at the front (simplifies logic).
+ */
+static statsobj_t *objRoot = NULL;
+static statsobj_t *objLast = NULL;
+
+static pthread_mutex_t mutStats;
+static pthread_mutex_t mutSenders;
+
+static struct hashtable *stats_senders = NULL;
+
+/* ------------------------------ statsobj linked list maintenance ------------------------------ */
+
+static void
+addToObjList(statsobj_t *pThis)
+{
+ pthread_mutex_lock(&mutStats);
+ if (pThis->flags && STATSOBJ_FLAG_DO_PREPEND) {
+ pThis->next = objRoot;
+ if (objRoot != NULL) {
+ objRoot->prev = pThis;
+ }
+ objRoot = pThis;
+ if (objLast == NULL)
+ objLast = pThis;
+ } else {
+ pThis->prev = objLast;
+ if(objLast != NULL)
+ objLast->next = pThis;
+ objLast = pThis;
+ if(objRoot == NULL)
+ objRoot = pThis;
+ }
+ pthread_mutex_unlock(&mutStats);
+}
+
+
+static void
+removeFromObjList(statsobj_t *pThis)
+{
+ pthread_mutex_lock(&mutStats);
+ if(pThis->prev != NULL)
+ pThis->prev->next = pThis->next;
+ if(pThis->next != NULL)
+ pThis->next->prev = pThis->prev;
+ if(objLast == pThis)
+ objLast = pThis->prev;
+ if(objRoot == pThis)
+ objRoot = pThis->next;
+ pthread_mutex_unlock(&mutStats);
+}
+
+
+static void
+addCtrToList(statsobj_t *pThis, ctr_t *pCtr)
+{
+ pthread_mutex_lock(&pThis->mutCtr);
+ pCtr->prev = pThis->ctrLast;
+ if(pThis->ctrLast != NULL)
+ pThis->ctrLast->next = pCtr;
+ pThis->ctrLast = pCtr;
+ if(pThis->ctrRoot == NULL)
+ pThis->ctrRoot = pCtr;
+ pthread_mutex_unlock(&pThis->mutCtr);
+}
+
+/* ------------------------------ methods ------------------------------ */
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(statsobj) /* be sure to specify the object type also in END macro! */
+ pthread_mutex_init(&pThis->mutCtr, NULL);
+ pThis->ctrLast = NULL;
+ pThis->ctrRoot = NULL;
+ pThis->read_notifier = NULL;
+ pThis->flags = 0;
+ENDobjConstruct(statsobj)
+
+
+/* ConstructionFinalizer
+ */
+static rsRetVal
+statsobjConstructFinalize(statsobj_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, statsobj);
+ addToObjList(pThis);
+ RETiRet;
+}
+
+/* set read_notifier (a function which is invoked after stats are read).
+ */
+static rsRetVal
+setReadNotifier(statsobj_t *pThis, statsobj_read_notifier_t notifier, void* ctx)
+{
+ DEFiRet;
+ pThis->read_notifier = notifier;
+ pThis->read_notifier_ctx = ctx;
+ RETiRet;
+}
+
+
+/* set origin (module name, etc).
+ * Note that we make our own copy of the memory, caller is
+ * responsible to free up name it passes in (if required).
+ */
+static rsRetVal
+setOrigin(statsobj_t *pThis, uchar *origin)
+{
+ DEFiRet;
+ CHKmalloc(pThis->origin = ustrdup(origin));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set name. Note that we make our own copy of the memory, caller is
+ * responsible to free up name it passes in (if required).
+ */
+static rsRetVal
+setName(statsobj_t *pThis, uchar *name)
+{
+ DEFiRet;
+ CHKmalloc(pThis->name = ustrdup(name));
+finalize_it:
+ RETiRet;
+}
+
+static void
+setStatsObjFlags(statsobj_t *pThis, int flags) {
+ pThis->flags = flags;
+}
+
+static rsRetVal
+setReportingNamespace(statsobj_t *pThis, uchar *ns)
+{
+ DEFiRet;
+ CHKmalloc(pThis->reporting_ns = ustrdup(ns));
+finalize_it:
+ RETiRet;
+}
+
+/* add a counter to an object
+ * ctrName is duplicated, caller must free it if requried
+ * NOTE: The counter is READ-ONLY and MUST NOT be modified (most
+ * importantly, it must not be initialized, so the caller must
+ * ensure the counter is properly initialized before AddCounter()
+ * is called.
+ */
+static rsRetVal
+addManagedCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr,
+ctr_t **entryRef, int8_t linked)
+{
+ ctr_t *ctr;
+ DEFiRet;
+
+ *entryRef = NULL;
+
+ CHKmalloc(ctr = calloc(1, sizeof(ctr_t)));
+ ctr->next = NULL;
+ ctr->prev = NULL;
+ if((ctr->name = ustrdup(ctrName)) == NULL) {
+ DBGPRINTF("addCounter: OOM in strdup()\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ ctr->flags = flags;
+ ctr->ctrType = ctrType;
+ switch(ctrType) {
+ case ctrType_IntCtr:
+ ctr->val.pIntCtr = (intctr_t*) pCtr;
+ break;
+ case ctrType_Int:
+ ctr->val.pInt = (int*) pCtr;
+ break;
+ }
+ if (linked) {
+ addCtrToList(pThis, ctr);
+ }
+ *entryRef = ctr;
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ if (ctr != NULL) {
+ free(ctr->name);
+ free(ctr);
+ }
+ }
+ RETiRet;
+}
+
+static void
+addPreCreatedCounter(statsobj_t *pThis, ctr_t *pCtr)
+{
+ pCtr->next = NULL;
+ pCtr->prev = NULL;
+ addCtrToList(pThis, pCtr);
+}
+
+static rsRetVal
+addCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr)
+{
+ ctr_t *ctr;
+ DEFiRet;
+ iRet = addManagedCounter(pThis, ctrName, ctrType, flags, pCtr, &ctr, 1);
+ RETiRet;
+}
+
+static void
+destructUnlinkedCounter(ctr_t *ctr) {
+ free(ctr->name);
+ free(ctr);
+}
+
+static void
+destructCounter(statsobj_t *pThis, ctr_t *pCtr)
+{
+ pthread_mutex_lock(&pThis->mutCtr);
+ if (pCtr->prev != NULL) {
+ pCtr->prev->next = pCtr->next;
+ }
+ if (pCtr->next != NULL) {
+ pCtr->next->prev = pCtr->prev;
+ }
+ if (pThis->ctrLast == pCtr) {
+ pThis->ctrLast = pCtr->prev;
+ }
+ if (pThis->ctrRoot == pCtr) {
+ pThis->ctrRoot = pCtr->next;
+ }
+ pthread_mutex_unlock(&pThis->mutCtr);
+ destructUnlinkedCounter(pCtr);
+}
+
+static void
+resetResettableCtr(ctr_t *pCtr, int8_t bResetCtrs)
+{
+ if ((bResetCtrs && (pCtr->flags & CTR_FLAG_RESETTABLE)) ||
+ (pCtr->flags & CTR_FLAG_MUST_RESET)) {
+ switch(pCtr->ctrType) {
+ case ctrType_IntCtr:
+ *(pCtr->val.pIntCtr) = 0;
+ break;
+ case ctrType_Int:
+ *(pCtr->val.pInt) = 0;
+ break;
+ }
+ }
+}
+
+static rsRetVal
+addCtrForReporting(json_object *to, const uchar* field_name, intctr_t value) {
+ json_object *v;
+ DEFiRet;
+
+ /*We should migrate libfastjson to support uint64_t in addition to int64_t.
+ Although no counter is likely to grow to int64 max-value, this is theoritically
+ incorrect (as intctr_t is uint64)*/
+ CHKmalloc(v = json_object_new_int64((int64_t) value));
+
+ json_object_object_add(to, (const char*) field_name, v);
+finalize_it:
+ /* v cannot be NULL in error case, as this would only happen during malloc fail,
+ * which itself sets it to NULL -- so not doing cleanup here.
+ */
+ RETiRet;
+}
+
+static rsRetVal
+addContextForReporting(json_object *to, const uchar* field_name, const uchar* value) {
+ json_object *v;
+ DEFiRet;
+
+ CHKmalloc(v = json_object_new_string((const char*) value));
+
+ json_object_object_add(to, (const char*) field_name, v);
+finalize_it:
+ RETiRet;
+}
+
+static intctr_t
+accumulatedValue(ctr_t *pCtr) {
+ switch(pCtr->ctrType) {
+ case ctrType_IntCtr:
+ return *(pCtr->val.pIntCtr);
+ case ctrType_Int:
+ return *(pCtr->val.pInt);
+ }
+ return -1;
+}
+
+
+/* get all the object's countes together as CEE. */
+static rsRetVal
+getStatsLineCEE(statsobj_t *pThis, cstr_t **ppcstr, const statsFmtType_t fmt, const int8_t bResetCtrs)
+{
+ cstr_t *pcstr = NULL;
+ ctr_t *pCtr;
+ json_object *root, *values;
+ int locked = 0;
+ DEFiRet;
+
+ root = values = NULL;
+
+ CHKiRet(cstrConstruct(&pcstr));
+
+ if (fmt == statsFmt_CEE)
+ CHKiRet(rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT(CONST_CEE_COOKIE" "), CONST_LEN_CEE_COOKIE + 1));
+
+ CHKmalloc(root = json_object_new_object());
+
+ CHKiRet(addContextForReporting(root, UCHAR_CONSTANT("name"), pThis->name));
+
+ if(pThis->origin != NULL) {
+ CHKiRet(addContextForReporting(root, UCHAR_CONSTANT("origin"), pThis->origin));
+ }
+
+ if (pThis->reporting_ns == NULL) {
+ values = json_object_get(root);
+ } else {
+ CHKmalloc(values = json_object_new_object());
+ json_object_object_add(root, (const char*) pThis->reporting_ns, json_object_get(values));
+ }
+
+ /* now add all counters to this line */
+ pthread_mutex_lock(&pThis->mutCtr);
+ locked = 1;
+ for(pCtr = pThis->ctrRoot ; pCtr != NULL ; pCtr = pCtr->next) {
+ if (fmt == statsFmt_JSON_ES) {
+ /* work-around for broken Elasticsearch JSON implementation:
+ * we need to replace dots by a different char, we use bang.
+ * Note: ES 2.0 does not longer accept dot in name
+ */
+ uchar esbuf[256];
+ strncpy((char*)esbuf, (char*)pCtr->name, sizeof(esbuf)-1);
+ esbuf[sizeof(esbuf)-1] = '\0';
+ for(uchar *c = esbuf ; *c ; ++c) {
+ if(*c == '.')
+ *c = '!';
+ }
+ CHKiRet(addCtrForReporting(values, esbuf, accumulatedValue(pCtr)));
+ } else {
+ CHKiRet(addCtrForReporting(values, pCtr->name, accumulatedValue(pCtr)));
+ }
+ resetResettableCtr(pCtr, bResetCtrs);
+ }
+ pthread_mutex_unlock(&pThis->mutCtr);
+ locked = 0;
+ CHKiRet(rsCStrAppendStr(pcstr, (const uchar*) json_object_to_json_string(root)));
+
+ cstrFinalize(pcstr);
+ *ppcstr = pcstr;
+ pcstr = NULL;
+
+finalize_it:
+ if(locked) {
+ pthread_mutex_unlock(&pThis->mutCtr);
+ }
+
+ if (pcstr != NULL) {
+ cstrDestruct(&pcstr);
+ }
+ if (root != NULL) {
+ json_object_put(root);
+ }
+ if (values != NULL) {
+ json_object_put(values);
+ }
+
+ RETiRet;
+}
+
+/* get all the object's countes together with object name as one line.
+ */
+static rsRetVal
+getStatsLine(statsobj_t *pThis, cstr_t **ppcstr, int8_t bResetCtrs)
+{
+ cstr_t *pcstr;
+ ctr_t *pCtr;
+ DEFiRet;
+
+ CHKiRet(cstrConstruct(&pcstr));
+ rsCStrAppendStr(pcstr, pThis->name);
+ rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT(": "), 2);
+
+ if(pThis->origin != NULL) {
+ rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT("origin="), 7);
+ rsCStrAppendStr(pcstr, pThis->origin);
+ cstrAppendChar(pcstr, ' ');
+ }
+
+ /* now add all counters to this line */
+ pthread_mutex_lock(&pThis->mutCtr);
+ for(pCtr = pThis->ctrRoot ; pCtr != NULL ; pCtr = pCtr->next) {
+ rsCStrAppendStr(pcstr, pCtr->name);
+ cstrAppendChar(pcstr, '=');
+ switch(pCtr->ctrType) {
+ case ctrType_IntCtr:
+ rsCStrAppendInt(pcstr, *(pCtr->val.pIntCtr)); // TODO: OK?????
+ break;
+ case ctrType_Int:
+ rsCStrAppendInt(pcstr, *(pCtr->val.pInt));
+ break;
+ }
+ cstrAppendChar(pcstr, ' ');
+ resetResettableCtr(pCtr, bResetCtrs);
+ }
+ pthread_mutex_unlock(&pThis->mutCtr);
+
+ cstrFinalize(pcstr);
+ *ppcstr = pcstr;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* this function obtains all sender stats. hlper to getAllStatsLines()
+ * We need to keep this looked to avoid resizing of the hash table
+ * (what could otherwise cause a segfault).
+ */
+static void
+getSenderStats(rsRetVal(*cb)(void*, const char*),
+ void *usrptr,
+ statsFmtType_t fmt,
+ const int8_t bResetCtrs)
+{
+ struct hashtable_itr *itr = NULL;
+ struct sender_stats *stat;
+ char fmtbuf[2048];
+
+ pthread_mutex_lock(&mutSenders);
+
+ /* Iterator constructor only returns a valid iterator if
+ * the hashtable is not empty
+ */
+ if(hashtable_count(stats_senders) > 0) {
+ itr = hashtable_iterator(stats_senders);
+ do {
+ stat = (struct sender_stats*)hashtable_iterator_value(itr);
+ if(fmt == statsFmt_Legacy) {
+ snprintf(fmtbuf, sizeof(fmtbuf),
+ "_sender_stat: sender=%s messages=%"
+ PRIu64,
+ stat->sender, stat->nMsgs);
+ } else {
+ snprintf(fmtbuf, sizeof(fmtbuf),
+ "{ \"name\":\"_sender_stat\", "
+ "\"origin\":\"impstats\", "
+ "\"sender\":\"%s\", \"messages\":%"
+ PRIu64 "}",
+ stat->sender, stat->nMsgs);
+ }
+ fmtbuf[sizeof(fmtbuf)-1] = '\0';
+ cb(usrptr, fmtbuf);
+ if(bResetCtrs)
+ stat->nMsgs = 0;
+ } while (hashtable_iterator_advance(itr));
+ }
+
+ free(itr);
+ pthread_mutex_unlock(&mutSenders);
+}
+
+
+/* this function can be used to obtain all stats lines. In this case,
+ * a callback must be provided. This module than iterates over all objects and
+ * submits each stats line to the callback. The callback has two parameters:
+ * the first one is a caller-provided void*, the second one the cstr_t with the
+ * line. If the callback reports an error, processing is stopped.
+ */
+static rsRetVal
+getAllStatsLines(rsRetVal(*cb)(void*, const char*), void *const usrptr, statsFmtType_t fmt, const int8_t bResetCtrs)
+{
+ statsobj_t *o;
+ cstr_t *cstr = NULL;
+ DEFiRet;
+
+ for(o = objRoot ; o != NULL ; o = o->next) {
+ switch(fmt) {
+ case statsFmt_Legacy:
+ CHKiRet(getStatsLine(o, &cstr, bResetCtrs));
+ break;
+ case statsFmt_CEE:
+ case statsFmt_JSON:
+ case statsFmt_JSON_ES:
+ CHKiRet(getStatsLineCEE(o, &cstr, fmt, bResetCtrs));
+ break;
+ }
+ CHKiRet(cb(usrptr, (const char*)cstrGetSzStrNoNULL(cstr)));
+ rsCStrDestruct(&cstr);
+ if (o->read_notifier != NULL) {
+ o->read_notifier(o, o->read_notifier_ctx);
+ }
+ }
+
+ getSenderStats(cb, usrptr, fmt, bResetCtrs);
+
+finalize_it:
+ if(cstr != NULL) {
+ rsCStrDestruct(&cstr);
+ }
+ RETiRet;
+}
+
+/* Enable statistics gathering. currently there is no function to disable it
+ * again, as this is right now not needed.
+ */
+static rsRetVal
+enableStats(void)
+{
+ GatherStats = 1;
+ return RS_RET_OK;
+}
+
+
+rsRetVal
+statsRecordSender(const uchar *sender, unsigned nMsgs, time_t lastSeen)
+{
+ struct sender_stats *stat;
+ int mustUnlock = 0;
+ DEFiRet;
+
+ if(stats_senders == NULL)
+ FINALIZE; /* unlikely: we could not init our hash table */
+
+ pthread_mutex_lock(&mutSenders);
+ mustUnlock = 1;
+ stat = hashtable_search(stats_senders, (void*)sender);
+ if(stat == NULL) {
+ DBGPRINTF("statsRecordSender: sender '%s' not found, adding\n",
+ sender);
+ CHKmalloc(stat = calloc(1, sizeof(struct sender_stats)));
+ stat->sender = (const uchar*)strdup((const char*)sender);
+ stat->nMsgs = 0;
+ if(runConf->globals.reportNewSenders) {
+ LogMsg(0, RS_RET_SENDER_APPEARED,
+ LOG_INFO, "new sender '%s'", stat->sender);
+ }
+ if(hashtable_insert(stats_senders, (void*)stat->sender,
+ (void*)stat) == 0) {
+ LogError(errno, RS_RET_INTERNAL_ERROR,
+ "error inserting sender '%s' into sender "
+ "hash table", sender);
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ }
+
+ stat->nMsgs += nMsgs;
+ stat->lastSeen = lastSeen;
+ DBGPRINTF("DDDDD: statsRecordSender: '%s', nmsgs %u [%llu], lastSeen %llu\n", sender, nMsgs,
+ (long long unsigned) stat->nMsgs, (long long unsigned) lastSeen);
+
+finalize_it:
+ if(mustUnlock)
+ pthread_mutex_unlock(&mutSenders);
+ RETiRet;
+}
+
+static ctr_t*
+unlinkAllCounters(statsobj_t *pThis) {
+ ctr_t *ctr;
+ pthread_mutex_lock(&pThis->mutCtr);
+ ctr = pThis->ctrRoot;
+ pThis->ctrLast = NULL;
+ pThis->ctrRoot = NULL;
+ pthread_mutex_unlock(&pThis->mutCtr);
+ return ctr;
+}
+
+static void
+destructUnlinkedCounters(ctr_t *ctr) {
+ ctr_t *ctrToDel;
+
+ while(ctr != NULL) {
+ ctrToDel = ctr;
+ ctr = ctr->next;
+ destructUnlinkedCounter(ctrToDel);
+ }
+}
+
+/* check if a sender has not sent info to us for an extended period
+ * of time.
+ */
+void
+checkGoneAwaySenders(const time_t tCurr)
+{
+ struct hashtable_itr *itr = NULL;
+ struct sender_stats *stat;
+ const time_t rqdLast = tCurr - runConf->globals.senderStatsTimeout;
+ struct tm tm;
+
+ pthread_mutex_lock(&mutSenders);
+
+ /* Iterator constructor only returns a valid iterator if
+ * the hashtable is not empty
+ */
+ if(hashtable_count(stats_senders) > 0) {
+ itr = hashtable_iterator(stats_senders);
+ do {
+ stat = (struct sender_stats*)hashtable_iterator_value(itr);
+ if(stat->lastSeen < rqdLast) {
+ if(runConf->globals.reportGoneAwaySenders) {
+ localtime_r(&stat->lastSeen, &tm);
+ LogMsg(0, RS_RET_SENDER_GONE_AWAY,
+ LOG_WARNING,
+ "removing sender '%s' from connection "
+ "table, last seen at "
+ "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
+ stat->sender,
+ tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+ hashtable_remove(stats_senders, (void*)stat->sender);
+ }
+ } while (hashtable_iterator_advance(itr));
+ }
+
+ pthread_mutex_unlock(&mutSenders);
+ free(itr);
+}
+
+/* destructor for the statsobj object */
+BEGINobjDestruct(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(statsobj)
+ removeFromObjList(pThis);
+
+ /* destruct counters */
+ destructUnlinkedCounters(unlinkAllCounters(pThis));
+
+ pthread_mutex_destroy(&pThis->mutCtr);
+ free(pThis->name);
+ free(pThis->origin);
+ free(pThis->reporting_ns);
+ENDobjDestruct(statsobj)
+
+
+/* debugprint for the statsobj object */
+BEGINobjDebugPrint(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(statsobj)
+ dbgoprint((obj_t*) pThis, "statsobj object, currently no state info available\n");
+ENDobjDebugPrint(statsobj)
+
+
+/* queryInterface function
+ */
+BEGINobjQueryInterface(statsobj)
+CODESTARTobjQueryInterface(statsobj)
+ if(pIf->ifVersion != statsobjCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = statsobjConstruct;
+ pIf->ConstructFinalize = statsobjConstructFinalize;
+ pIf->Destruct = statsobjDestruct;
+ pIf->DebugPrint = statsobjDebugPrint;
+ pIf->SetName = setName;
+ pIf->SetOrigin = setOrigin;
+ pIf->SetReadNotifier = setReadNotifier;
+ pIf->SetReportingNamespace = setReportingNamespace;
+ pIf->SetStatsObjFlags = setStatsObjFlags;
+ pIf->GetAllStatsLines = getAllStatsLines;
+ pIf->AddCounter = addCounter;
+ pIf->AddManagedCounter = addManagedCounter;
+ pIf->AddPreCreatedCtr = addPreCreatedCounter;
+ pIf->DestructCounter = destructCounter;
+ pIf->DestructUnlinkedCounter = destructUnlinkedCounter;
+ pIf->UnlinkAllCounters = unlinkAllCounters;
+ pIf->EnableStats = enableStats;
+finalize_it:
+ENDobjQueryInterface(statsobj)
+
+
+/* Initialize the statsobj class. Must be called as the very first method
+ * before anything else is called inside this class.
+ */
+BEGINAbstractObjClassInit(statsobj, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, statsobjDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, statsobjConstructFinalize);
+
+ /* init other data items */
+ pthread_mutex_init(&mutStats, NULL);
+ pthread_mutex_init(&mutSenders, NULL);
+
+ if((stats_senders = create_hashtable(100, hash_from_string, key_equals_string, NULL)) == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table "
+ "for sender table. Sender statistics and warnings are disabled.");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+ENDObjClassInit(statsobj)
+
+/* Exit the class.
+ */
+BEGINObjClassExit(statsobj, OBJ_IS_CORE_MODULE) /* class, version */
+ /* release objects we no longer need */
+ pthread_mutex_destroy(&mutStats);
+ pthread_mutex_destroy(&mutSenders);
+ hashtable_destroy(stats_senders, 1);
+ENDObjClassExit(statsobj)
diff --git a/runtime/statsobj.h b/runtime/statsobj.h
new file mode 100644
index 0000000..d57cd0e
--- /dev/null
+++ b/runtime/statsobj.h
@@ -0,0 +1,203 @@
+/* The statsobj object.
+ *
+ * Copyright 2010-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_STATSOBJ_H
+#define INCLUDED_STATSOBJ_H
+
+#include "atomic.h"
+
+/* The following data item is somewhat dirty, in that it does not follow
+ * our usual object calling conventions. However, much like with "Debug", we
+ * do this to gain speed. If we finally come to a platform that does not
+ * provide resolution of names for dynamically loaded modules, we need to find
+ * a work-around, but until then, we use the direct access.
+ * If set to 0, statistics are not gathered, otherwise they are.
+ */
+extern int GatherStats;
+
+/* our basic counter type -- need 32 bit on 32 bit platform.
+ * IMPORTANT: this type *MUST* be supported by atomic instructions!
+ */
+typedef uint64 intctr_t;
+
+/* counter types */
+typedef enum statsCtrType_e {
+ ctrType_IntCtr,
+ ctrType_Int
+} statsCtrType_t;
+
+/* stats line format types */
+typedef enum statsFmtType_e {
+ statsFmt_Legacy,
+ statsFmt_JSON,
+ statsFmt_JSON_ES,
+ statsFmt_CEE
+} statsFmtType_t;
+
+/* counter flags */
+#define CTR_FLAG_NONE 0
+#define CTR_FLAG_RESETTABLE 1
+#define CTR_FLAG_MUST_RESET 2
+
+/* statsobj flags */
+#define STATSOBJ_FLAG_NONE 0
+#define STATSOBJ_FLAG_DO_PREPEND 1
+
+/* helper entity, the counter */
+typedef struct ctr_s {
+ uchar *name;
+ statsCtrType_t ctrType;
+ union {
+ intctr_t *pIntCtr;
+ int *pInt;
+ } val;
+ int8_t flags;
+ struct ctr_s *next, *prev;
+} ctr_t;
+
+/* the statsobj object */
+struct statsobj_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *name;
+ uchar *origin;
+ uchar *reporting_ns;
+ statsobj_read_notifier_t read_notifier;
+ void *read_notifier_ctx;
+ pthread_mutex_t mutCtr; /* to guard counter linked-list ops */
+ ctr_t *ctrRoot; /* doubly-linked list of statsobj counters */
+ ctr_t *ctrLast;
+ int flags;
+ /* used to link ourselves together */
+ statsobj_t *prev;
+ statsobj_t *next;
+};
+
+struct sender_stats {
+ const uchar *sender;
+ uint64_t nMsgs;
+ time_t lastSeen;
+};
+
+
+/* interfaces */
+BEGINinterface(statsobj) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(statsobj);
+ rsRetVal (*Construct)(statsobj_t **ppThis);
+ rsRetVal (*ConstructFinalize)(statsobj_t *pThis);
+ rsRetVal (*Destruct)(statsobj_t **ppThis);
+ rsRetVal (*SetName)(statsobj_t *pThis, uchar *name);
+ rsRetVal (*SetOrigin)(statsobj_t *pThis, uchar *name); /* added v12, 2014-09-08 */
+ rsRetVal (*SetReadNotifier)(statsobj_t *pThis, statsobj_read_notifier_t notifier, void* ctx);
+ rsRetVal (*SetReportingNamespace)(statsobj_t *pThis, uchar *ns);
+ void (*SetStatsObjFlags)(statsobj_t *pThis, int flags);
+ rsRetVal (*GetAllStatsLines)(rsRetVal(*cb)(void*, const char*), void *usrptr, statsFmtType_t fmt,
+ int8_t bResetCtr);
+ rsRetVal (*AddCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags,
+ void *pCtr);
+ rsRetVal (*AddManagedCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags,
+ void *pCtr, ctr_t **ref, int8_t linked);
+ void (*AddPreCreatedCtr)(statsobj_t *pThis, ctr_t *ctr);
+ void (*DestructCounter)(statsobj_t *pThis, ctr_t *ref);
+ void (*DestructUnlinkedCounter)(ctr_t *ctr);
+ ctr_t* (*UnlinkAllCounters)(statsobj_t *pThis);
+ rsRetVal (*EnableStats)(void);
+ENDinterface(statsobj)
+#define statsobjCURR_IF_VERSION 13 /* increment whenever you change the interface structure! */
+/* Changes
+ * v2-v9 rserved for future use in "older" version branches
+ * v10, 2012-04-01: GetAllStatsLines got fmt parameter
+ * v11, 2013-09-07: - add "flags" to AddCounter API
+ * - GetAllStatsLines got parameter telling if ctrs shall be reset
+ * v13, 2016-05-19: GetAllStatsLines cb data type changed (char* instead of cstr)
+ */
+
+
+/* prototypes */
+PROTOTYPEObj(statsobj);
+
+rsRetVal statsRecordSender(const uchar *sender, unsigned nMsgs, time_t lastSeen);
+/* checkGoneAwaySenders() is part of this module because all it needs is
+ * done by this module, so even though it's own processing is not directly
+ * related to stats, it makes sense to do it here... -- rgerhards, 2016-02-01
+ */
+void checkGoneAwaySenders(time_t);
+
+/* macros to handle stats counters
+ * These are to be used by "counter providers". Note that we MUST
+ * specify the mutex name, even though at first it looks like it
+ * could be automatically be generated via e.g. "mut##ctr".
+ * Unfortunately, this does not work if counter is e.g. "pThis->ctr".
+ * So we decided, for clarity, to always insist on specifying the mutex
+ * name (after all, it's just a few more keystrokes...).
+ * --------------------------------------------------------------------
+ * NOTE WELL
+ * --------------------------------------------------------------------
+ * There are actually two types of stats counters: "regular" counters,
+ * which are only used for stats purposes and "dual" counters, which
+ * are primarily used for other purposes but can be included in stats
+ * as well. ALL regular counters MUST be initialized with
+ * STATSCOUNTER_INIT and only be modified by STATSCOUNTER_* functions.
+ * They MUST NOT be used for any other purpose (if this seems to make
+ * sense, consider changing it to a dual counter).
+ * Dual counters are somewhat dangerous in that a single variable is
+ * used for two purposes: the actual application need and stats
+ * counting. However, this is supported for performance reasons, as it
+ * provides insight into the inner engine workings without need for
+ * additional counters (and their maintenance code). Dual counters
+ * MUST NOT be modified by STATSCOUNTER_* functions. Most importantly,
+ * it is expected that the actua application code provides proper
+ * (enough) synchronized access to these counters. Most importantly,
+ * this means they have NO stats-system mutex associated to them.
+ *
+ * The interface function AddCounter() is a read-only function. It
+ * only provides the stats subsystem with a reference to a counter.
+ * It is irrelevant if the counter is a regular or dual one. For that
+ * reason, AddCounter() must not modify the counter contents, as in
+ * the case of a dual counter application code may be broken.
+ */
+#define STATSCOUNTER_DEF(ctr, mut) \
+ intctr_t ctr; \
+ DEF_ATOMIC_HELPER_MUT64(mut)
+
+#define STATSCOUNTER_INIT(ctr, mut) \
+ INIT_ATOMIC_HELPER_MUT64(mut); \
+ ctr = 0;
+
+#define STATSCOUNTER_INC(ctr, mut) \
+ if(GatherStats) \
+ ATOMIC_INC_uint64(&ctr, &mut);
+
+#define STATSCOUNTER_ADD(ctr, mut, delta) \
+ if(GatherStats) \
+ ATOMIC_ADD_uint64(&ctr, &mut, delta);
+
+#define STATSCOUNTER_DEC(ctr, mut) \
+ if(GatherStats) \
+ ATOMIC_DEC_uint64(&ctr, &mut);
+
+/* the next macro works only if the variable is already guarded
+ * by mutex (or the users risks a wrong result). It is assumed
+ * that there are not concurrent operations that modify the counter.
+ */
+#define STATSCOUNTER_SETMAX_NOMUT(ctr, newmax) \
+ if(GatherStats && ((newmax) > (ctr))) \
+ ctr = newmax;
+
+#endif /* #ifndef INCLUDED_STATSOBJ_H */
diff --git a/runtime/stream.c b/runtime/stream.c
new file mode 100644
index 0000000..73d63e4
--- /dev/null
+++ b/runtime/stream.c
@@ -0,0 +1,2533 @@
+/* The serial stream class.
+ *
+ * A serial stream provides serial data access. In theory, serial streams
+ * can be implemented via a number of methods (e.g. files or in-memory
+ * streams). In practice, there currently only exist the file type (aka
+ * "driver").
+ *
+ * File begun on 2008-01-09 by RGerhards
+ * Large modifications in 2009-06 to support using it with omfile, including zip writer.
+ * Note that this file obtains the zlib wrapper object is needed, but it never frees it
+ * again. While this sounds like a leak (and one may argue it actually is), there is no
+ * harm associated with that. The reason is that strm is a core object, so it is terminated
+ * only when rsyslogd exists. As we could only release on termination (or else bear more
+ * overhead for keeping track of how many users we have), not releasing zlibw is OK, because
+ * it will be released when rsyslogd terminates. We may want to revisit this decision if
+ * it turns out to be problematic. Then, we need to quasi-refcount the number of accesses
+ * to the object.
+ *
+ * Copyright 2008-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h> /* required for HP UX */
+#include <errno.h>
+#include <pthread.h>
+#include <poll.h>
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
+
+#include "rsyslog.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "obj.h"
+#include "stream.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "zstdw.h"
+#include "cryprov.h"
+#include "datetime.h"
+#include "rsconf.h"
+
+/* some platforms do not have large file support :( */
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+#ifndef HAVE_LSEEK64
+# define lseek64(fd, offset, whence) lseek(fd, offset, whence)
+#endif
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(zlibw)
+DEFobjCurrIf(zstdw)
+
+/* forward definitions */
+static rsRetVal strmFlushInternal(strm_t *pThis, int bFlushZip);
+static rsRetVal strmWrite(strm_t *__restrict__ const pThis, const uchar *__restrict__ const pBuf,
+ const size_t lenBuf);
+static rsRetVal strmOpenFile(strm_t *pThis);
+static rsRetVal strmCloseFile(strm_t *pThis);
+static void *asyncWriterThread(void *pPtr);
+static rsRetVal doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, int bFlush);
+static rsRetVal doZipFinish(strm_t *pThis);
+static rsRetVal strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf);
+static rsRetVal strmSeekCurrOffs(strm_t *pThis);
+
+
+/* methods */
+
+
+/* note: this may return NULL if not line segment is currently set */
+// TODO: due to the cstrFinalize() this is not totally clean, albeit for our
+// current use case it does not hurt -- refactor! rgerhards, 2018-03-27
+const uchar * ATTR_NONNULL()
+strmGetPrevLineSegment(strm_t *const pThis)
+{
+ const uchar *ret = NULL;
+ if(pThis->prevLineSegment != NULL) {
+ cstrFinalize(pThis->prevLineSegment);
+ ret = rsCStrGetSzStrNoNULL(pThis->prevLineSegment);
+ }
+ return ret;
+}
+/* note: this may return NULL if not line segment is currently set */
+// TODO: due to the cstrFinalize() this is not totally clean, albeit for our
+// current use case it does not hurt -- refactor! rgerhards, 2018-03-27
+const uchar * ATTR_NONNULL()
+strmGetPrevMsgSegment(strm_t *const pThis)
+{
+ const uchar *ret = NULL;
+ if(pThis->prevMsgSegment != NULL) {
+ cstrFinalize(pThis->prevMsgSegment);
+ ret = rsCStrGetSzStrNoNULL(pThis->prevMsgSegment);
+ }
+ return ret;
+}
+
+
+int ATTR_NONNULL()
+strmGetPrevWasNL(const strm_t *const pThis)
+{
+ return pThis->bPrevWasNL;
+}
+
+
+/* output (current) file name for debug log purposes. Falls back to various
+ * levels of impreciseness if more precise name is not known.
+ */
+static const char *
+getFileDebugName(const strm_t *const pThis)
+{
+ return (pThis->pszCurrFName == NULL) ?
+ ((pThis->pszFName == NULL) ? "N/A" : (char*)pThis->pszFName)
+ : (const char*) pThis->pszCurrFName;
+}
+
+/* Try to resolve a size limit situation. This is used to support custom-file size handlers
+ * for omfile. It first runs the command, and then checks if we are still above the size
+ * treshold. Note that this works only with single file names, NOT with circular names.
+ * Note that pszCurrFName can NOT be taken from pThis, because the stream is closed when
+ * we are called (and that destroys pszCurrFName, as there is NO CURRENT file name!). So
+ * we need to receive the name as a parameter.
+ * initially wirtten 2005-06-21, moved to this class & updates 2009-06-01, both rgerhards
+ */
+static rsRetVal
+resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName)
+{
+ uchar *pParams;
+ uchar *pCmd;
+ uchar *p;
+ off_t actualFileSize;
+ rsRetVal localRet;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(pszCurrFName != NULL);
+
+ if(pThis->pszSizeLimitCmd == NULL) {
+ ABORT_FINALIZE(RS_RET_NON_SIZELIMITCMD); /* nothing we can do in this case... */
+ }
+
+ /* we first check if we have command line parameters. We assume this,
+ * when we have a space in the program name. If we find it, everything after
+ * the space is treated as a single argument.
+ */
+ CHKmalloc(pCmd = ustrdup(pThis->pszSizeLimitCmd));
+
+ for(p = pCmd ; *p && *p != ' ' ; ++p) {
+ /* JUST SKIP */
+ }
+
+ if(*p == ' ') {
+ *p = '\0'; /* pretend string-end */
+ pParams = p+1;
+ } else
+ pParams = NULL;
+
+ /* the execProg() below is probably not great, but at least is is
+ * fairly secure now. Once we change the way file size limits are
+ * handled, we should also revisit how this command is run (and
+ * with which parameters). rgerhards, 2007-07-20
+ */
+ execProg(pCmd, 1, pParams);
+
+ free(pCmd);
+
+ localRet = getFileSize(pszCurrFName, &actualFileSize);
+
+ if(localRet == RS_RET_OK && actualFileSize >= pThis->iSizeLimit) {
+ ABORT_FINALIZE(RS_RET_SIZELIMITCMD_DIDNT_RESOLVE); /* OK, it didn't work out... */
+ } else if(localRet != RS_RET_FILE_NOT_FOUND) {
+ /* file not found is OK, the command may have moved away the file */
+ ABORT_FINALIZE(localRet);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(iRet == RS_RET_SIZELIMITCMD_DIDNT_RESOLVE) {
+ LogError(0, RS_RET_ERR, "file size limit cmd for file '%s' "
+ "did no resolve situation\n", pszCurrFName);
+ } else {
+ LogError(0, RS_RET_ERR, "file size limit cmd for file '%s' "
+ "failed with code %d.\n", pszCurrFName, iRet);
+ }
+ pThis->bDisabled = 1;
+ }
+
+ RETiRet;
+}
+
+
+/* Check if the file has grown beyond the configured omfile iSizeLimit
+ * and, if so, initiate processing.
+ */
+static rsRetVal
+doSizeLimitProcessing(strm_t *pThis)
+{
+ uchar *pszCurrFName = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(pThis->iSizeLimit != 0);
+ assert(pThis->fd != -1);
+
+ if(pThis->iCurrOffs >= pThis->iSizeLimit) {
+ /* strmCloseFile() destroys the current file name, so we
+ * need to preserve it.
+ */
+ CHKmalloc(pszCurrFName = ustrdup(pThis->pszCurrFName));
+ CHKiRet(strmCloseFile(pThis));
+ CHKiRet(resolveFileSizeLimit(pThis, pszCurrFName));
+ }
+
+finalize_it:
+ free(pszCurrFName);
+ RETiRet;
+}
+
+
+/* now, we define type-specific handlers. The provide a generic functionality,
+ * but for this specific type of strm. The mapping to these handlers happens during
+ * strm construction. Later on, handlers are called by pointers present in the
+ * strm instance object.
+ */
+
+/* do the physical open() call on a file.
+ */
+static rsRetVal
+doPhysOpen(strm_t *pThis)
+{
+ int iFlags = 0;
+ struct stat statOpen;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ /* compute which flags we need to provide to open */
+ switch(pThis->tOperationsMode) {
+ case STREAMMODE_READ:
+ iFlags = O_CLOEXEC | O_NOCTTY | O_RDONLY;
+ break;
+ case STREAMMODE_WRITE: /* legacy mode used inside queue engine */
+ iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT;
+ break;
+ case STREAMMODE_WRITE_TRUNC:
+ iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_TRUNC;
+ break;
+ case STREAMMODE_WRITE_APPEND:
+ iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_APPEND;
+ break;
+ case STREAMMMODE_INVALID:
+ default:assert(0);
+ break;
+ }
+ if(pThis->sType == STREAMTYPE_NAMED_PIPE) {
+ DBGPRINTF("Note: stream '%s' is a named pipe, open with O_NONBLOCK\n", pThis->pszCurrFName);
+ iFlags |= O_NONBLOCK;
+ }
+
+ if(pThis->bAsyncWrite)d_pthread_mutex_lock(&pThis->mut);
+ pThis->fd = open((char*)pThis->pszCurrFName, iFlags | O_LARGEFILE, pThis->tOpenMode);
+ if(pThis->bAsyncWrite) d_pthread_mutex_unlock(&pThis->mut);
+
+ const int errno_save = errno; /* dbgprintf can mangle it! */
+ DBGPRINTF("file '%s' opened as #%d with mode %d\n", pThis->pszCurrFName,
+ pThis->fd, (int) pThis->tOpenMode);
+ if(pThis->fd == -1) {
+ const rsRetVal errcode = (errno_save == ENOENT) ? RS_RET_FILE_NOT_FOUND
+ : RS_RET_FILE_OPEN_ERROR;
+ if(pThis->fileNotFoundError) {
+ if(pThis->noRepeatedErrorOutput == 0) {
+ LogError(errno_save, errcode, "file '%s': open error", pThis->pszCurrFName);
+ pThis->noRepeatedErrorOutput = 1;
+ }
+ } else {
+ DBGPRINTF("file '%s': open error", pThis->pszCurrFName);
+ }
+ ABORT_FINALIZE(errcode);
+ } else {
+ pThis->noRepeatedErrorOutput = 0;
+ }
+
+ if(pThis->tOperationsMode == STREAMMODE_READ) {
+ if(fstat(pThis->fd, &statOpen) == -1) {
+ DBGPRINTF("Error: cannot obtain inode# for file %s\n", pThis->pszCurrFName);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ pThis->inode = statOpen.st_ino;
+ }
+
+ if(!ustrcmp(pThis->pszCurrFName, UCHAR_CONSTANT(_PATH_CONSOLE)) || isatty(pThis->fd)) {
+ DBGPRINTF("file %d is a tty-type file\n", pThis->fd);
+ pThis->bIsTTY = 1;
+ } else {
+ pThis->bIsTTY = 0;
+ }
+
+ if(pThis->cryprov != NULL) {
+ CHKiRet(pThis->cryprov->OnFileOpen(pThis->cryprovData,
+ pThis->pszCurrFName, &pThis->cryprovFileData,
+ (pThis->tOperationsMode == STREAMMODE_READ) ? 'r' : 'w'));
+ pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+strmSetCurrFName(strm_t *pThis)
+{
+ DEFiRet;
+
+ if(pThis->sType == STREAMTYPE_FILE_CIRCULAR) {
+ CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir,
+ pThis->pszFName, pThis->lenFName, pThis->iCurrFNum, pThis->iFileNumDigits));
+ } else {
+ if(pThis->pszDir == NULL) {
+ if((pThis->pszCurrFName = ustrdup(pThis->pszFName)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ } else {
+ CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir,
+ pThis->pszFName, pThis->lenFName, -1, 0));
+ }
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* This function checks if the actual file has changed and, if so, resets the
+ * offset. This is support for monitoring files. It should be called after
+ * deserializing the strm object and before doing any other operation on it
+ * (most importantly not an open or seek!).
+ */
+static rsRetVal
+CheckFileChange(strm_t *pThis)
+{
+ struct stat statName;
+ DEFiRet;
+
+ CHKiRet(strmSetCurrFName(pThis));
+ if(stat((char*) pThis->pszCurrFName, &statName) == -1)
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ DBGPRINTF("CheckFileChange: stream/after deserialize checking for file change "
+ "on '%s', inode %u/%u, size/currOffs %llu/%llu\n",
+ pThis->pszCurrFName, (unsigned) pThis->inode,
+ (unsigned) statName.st_ino,
+ (long long unsigned) statName.st_size,
+ (long long unsigned) pThis->iCurrOffs);
+ if(pThis->inode != statName.st_ino || statName.st_size < pThis->iCurrOffs) {
+ DBGPRINTF("stream: file %s has changed\n", pThis->pszCurrFName);
+ pThis->iCurrOffs = 0;
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* open a strm file
+ * It is OK to call this function when the stream is already open. In that
+ * case, it returns immediately with RS_RET_OK
+ */
+static rsRetVal strmOpenFile(strm_t *pThis)
+{
+ DEFiRet;
+ off_t offset;
+
+ assert(pThis != NULL);
+
+ if(pThis->fd != -1)
+ ABORT_FINALIZE(RS_RET_OK);
+
+ free(pThis->pszCurrFName);
+ pThis->pszCurrFName = NULL; /* used to prevent mem leak in case of error */
+
+ if(pThis->pszFName == NULL)
+ ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING);
+
+ CHKiRet(strmSetCurrFName(pThis));
+
+ CHKiRet(doPhysOpen(pThis));
+
+ pThis->iCurrOffs = 0;
+ pThis->iBufPtrMax = 0;
+ CHKiRet(getFileSize(pThis->pszCurrFName, &offset));
+ if(pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) {
+ pThis->iCurrOffs = offset;
+ } else if(pThis->tOperationsMode == STREAMMODE_WRITE_TRUNC) {
+ if(offset != 0) {
+ LogError(0, 0, "file '%s' opened for truncate write, but "
+ "already contains %zd bytes\n",
+ pThis->pszCurrFName, (ssize_t) offset);
+ }
+ }
+
+ DBGOPRINT((obj_t*) pThis, "opened file '%s' for %s as %d\n", pThis->pszCurrFName,
+ (pThis->tOperationsMode == STREAMMODE_READ) ? "READ" : "WRITE", pThis->fd);
+
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ assert(pThis->fd != -1);
+ } else {
+ if(pThis->pszCurrFName != NULL) {
+ free(pThis->pszCurrFName);
+ pThis->pszCurrFName = NULL; /* just to prevent mis-adressing down the road... */
+ }
+ if(pThis->fd != -1) {
+ close(pThis->fd);
+ pThis->fd = -1;
+ }
+ }
+ RETiRet;
+}
+
+
+/* wait for the output writer thread to be done. This must be called before actions
+ * that require data to be persisted. May be called in non-async mode and is a null
+ * operation than. Must be called with the mutex locked.
+ */
+static void
+strmWaitAsyncWriterDone(strm_t *pThis)
+{
+ if(pThis->bAsyncWrite) {
+ /* awake writer thread and make it write out everything */
+ while(pThis->iCnt > 0) {
+ pthread_cond_signal(&pThis->notEmpty);
+ d_pthread_cond_wait(&pThis->isEmpty, &pThis->mut);
+ }
+ }
+}
+
+/* stop the writer thread (we MUST be runnnig asynchronously when this method
+ * is called!). Note that the mutex must be locked! -- rgerhards, 2009-07-06
+ */
+static void
+stopWriter(strm_t *const pThis)
+{
+ pThis->bStopWriter = 1;
+ pthread_cond_signal(&pThis->notEmpty);
+ d_pthread_mutex_unlock(&pThis->mut);
+ pthread_join(pThis->writerThreadID, NULL);
+}
+
+
+
+/* close a strm file
+ * Note that the bDeleteOnClose flag is honored. If it is set, the file will be
+ * deleted after close. This is in support for the qRead thread.
+ * Note: it is valid to call this function when the physical file is closed. If so,
+ * strmCloseFile() will still check if there is any unwritten data inside buffers
+ * (this may be the case) and, if so, will open the file, write the data, and then
+ * close it again (this is done via strmFlushInternal and friends).
+ */
+static rsRetVal strmCloseFile(strm_t *pThis)
+{
+ off64_t currOffs;
+ DEFiRet;
+
+ assert(pThis != NULL);
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) closing, bDeleteOnClose %d\n", pThis->fd,
+ getFileDebugName(pThis), pThis->bDeleteOnClose);
+
+ if(pThis->tOperationsMode != STREAMMODE_READ) {
+ if(pThis->bAsyncWrite) {
+ strmWaitAsyncWriterDone(pThis);
+ }
+ strmFlushInternal(pThis, 0);
+ if(pThis->iZipLevel) {
+ doZipFinish(pThis);
+ }
+ if(pThis->bAsyncWrite) {
+ stopWriter(pThis);
+ }
+ }
+
+ /* if we have a signature provider, we must make sure that the crypto
+ * state files are opened and proper close processing happens. */
+ if(pThis->cryprov != NULL && pThis->fd == -1) {
+ const rsRetVal localRet = strmOpenFile(pThis);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "could not open file %s, this "
+ "may result in problems with encryption - "
+ "unfortunately, we cannot do anything against "
+ "this.", pThis->pszCurrFName);
+ }
+ }
+
+ /* the file may already be closed (or never have opened), so guard
+ * against this. -- rgerhards, 2010-03-19
+ */
+ if(pThis->fd != -1) {
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) closing\n",
+ pThis->fd, getFileDebugName(pThis));
+ currOffs = lseek64(pThis->fd, 0, SEEK_CUR);
+ close(pThis->fd);
+ pThis->fd = -1;
+ pThis->inode = 0;
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->OnFileClose(pThis->cryprovFileData, currOffs);
+ pThis->cryprovFileData = NULL;
+ }
+ }
+
+ if(pThis->fdDir != -1) {
+ /* close associated directory handle, if it is open */
+ close(pThis->fdDir);
+ pThis->fdDir = -1;
+ }
+
+ if(pThis->bDeleteOnClose) {
+ if(pThis->pszCurrFName == NULL) {
+ CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir,
+ pThis->pszFName, pThis->lenFName, pThis->iCurrFNum,
+ pThis->iFileNumDigits));
+ }
+ DBGPRINTF("strmCloseFile: deleting '%s'\n", pThis->pszCurrFName);
+ if(unlink((char*) pThis->pszCurrFName) == -1) {
+ char errStr[1024];
+ int err = errno;
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("error %d unlinking '%s' - ignored: %s\n",
+ errno, pThis->pszCurrFName, errStr);
+ }
+ }
+
+ pThis->iCurrOffs = 0; /* we are back at begin of file */
+
+finalize_it:
+ free(pThis->pszCurrFName);
+ pThis->pszCurrFName = NULL;
+ RETiRet;
+}
+
+
+/* switch to next strm file
+ * This method must only be called if we are in a multi-file mode!
+ */
+static rsRetVal
+strmNextFile(strm_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pThis->sType == STREAMTYPE_FILE_CIRCULAR);
+ assert(pThis->iMaxFiles != 0);
+ assert(pThis->fd != -1);
+
+ CHKiRet(strmCloseFile(pThis));
+
+ /* we do modulo operation to ensure we obey the iMaxFile property. This will always
+ * result in a file number lower than iMaxFile, so it if wraps, the name is back to
+ * 0, which results in the first file being overwritten. Not desired for queues, so
+ * make sure their iMaxFiles is large enough. But it is well-desired for other
+ * use cases, e.g. a circular output log file. -- rgerhards, 2008-01-10
+ */
+ pThis->iCurrFNum = (pThis->iCurrFNum + 1) % pThis->iMaxFiles;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* handle the EOF case of a stream
+ * The EOF case is somewhat complicated, as the proper action depends on the
+ * mode the stream is in. If there are multiple files (circular logs, most
+ * important use case is queue files!), we need to close the current file and
+ * try to open the next one.
+ * rgerhards, 2008-02-13
+ */
+static rsRetVal ATTR_NONNULL()
+strmHandleEOF(strm_t *const pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ switch(pThis->sType) {
+ case STREAMTYPE_FILE_SINGLE:
+ case STREAMTYPE_NAMED_PIPE:
+ ABORT_FINALIZE(RS_RET_EOF);
+ break;
+ case STREAMTYPE_FILE_CIRCULAR:
+ /* we have multiple files and need to switch to the next one */
+ /* TODO: think about emulating EOF in this case (not yet needed) */
+ DBGOPRINT((obj_t*) pThis, "file %d EOF\n", pThis->fd);
+ CHKiRet(strmNextFile(pThis));
+ break;
+ case STREAMTYPE_FILE_MONITOR:
+ DBGOPRINT((obj_t*) pThis, "file '%s' (%d) EOF, rotationCheck %d\n",
+ pThis->pszCurrFName, pThis->fd, pThis->rotationCheck);
+DBGPRINTF("RGER: EOF!\n");
+ ABORT_FINALIZE(RS_RET_EOF);
+ break;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* helper to checkTruncation */
+static rsRetVal ATTR_NONNULL()
+rereadTruncated(strm_t *const pThis, const int err_no, const char *const reason, const long long data)
+{
+ DEFiRet;
+
+ LogMsg(err_no, RS_RET_FILE_TRUNCATED, LOG_WARNING, "file '%s': truncation detected, "
+ "(%s) - re-start reading from beginning (data %lld)",
+ pThis->pszCurrFName, reason, data);
+ DBGPRINTF("checkTruncation, file %s last buffer CHANGED\n", pThis->pszCurrFName);
+ CHKiRet(strmCloseFile(pThis));
+ CHKiRet(strmOpenFile(pThis));
+ iRet = RS_RET_FILE_TRUNCATED;
+
+finalize_it:
+ RETiRet;
+}
+/* helper to read:
+ * Check if file has been truncated since last read and, if so, re-set reading
+ * to begin of file. To detect truncation, we try to re-read the last block.
+ * If that does not succeed or different data than from the original read is
+ * returned, truncation is assumed.
+ * NOTE: this function must be called only if truncation is enabled AND
+ * when the previous read buffer still is valid (aka "before the next read").
+ * It is ok to call with a 0-size buffer, which we than assume as begin of
+ * reading. In that case, no truncation will be detected.
+ * rgerhards, 2018-09-20
+ */
+static rsRetVal ATTR_NONNULL()
+checkTruncation(strm_t *const pThis)
+{
+ DEFiRet;
+ off64_t ret;
+ assert(pThis->bReopenOnTruncate);
+ assert(pThis->fd != -1);
+
+ DBGPRINTF("checkTruncation, file %s, iBufPtrMax %zd\n", pThis->pszCurrFName, pThis->iBufPtrMax);
+ if(pThis->iBufPtrMax == 0) {
+ FINALIZE;
+ }
+
+ const off64_t backseek = -1 * (off64_t) pThis->iBufPtrMax;
+ ret = lseek64(pThis->fd, backseek, SEEK_CUR);
+ if(ret < 0) {
+ iRet = rereadTruncated(pThis, errno,
+ "cannot seek backward to begin of last block", backseek);
+ FINALIZE;
+ }
+
+ const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax);
+ if(lenRead != (ssize_t) pThis->iBufPtrMax) {
+ iRet = rereadTruncated(pThis, errno,
+ "last block could not be re-read", lenRead);
+ FINALIZE;
+ }
+
+ if(!memcmp(pThis->pIOBuf_truncation, pThis->pIOBuf, pThis->iBufPtrMax)) {
+ DBGPRINTF("checkTruncation, file %s last buffer unchanged\n", pThis->pszCurrFName);
+ } else {
+ iRet = rereadTruncated(pThis, errno, "last block data different", 0);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read the next buffer from disk
+ * rgerhards, 2008-02-13
+ */
+static rsRetVal
+strmReadBuf(strm_t *pThis, int *padBytes)
+{
+ DEFiRet;
+ int bRun;
+ long iLenRead;
+ size_t actualDataLen;
+ size_t toRead;
+ ssize_t bytesLeft;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ /* We need to try read at least twice because we may run into EOF and need to switch files. */
+ bRun = 1;
+ while(bRun) {
+ /* first check if we need to (re)open the file. We may have switched to a new one in
+ * circular mode or it may have been rewritten (rotated) if we monitor a file
+ * rgerhards, 2008-02-13
+ */
+ CHKiRet(strmOpenFile(pThis));
+ if(pThis->cryprov == NULL) {
+ toRead = pThis->sIOBufSize;
+ } else {
+ CHKiRet(pThis->cryprov->GetBytesLeftInBlock(pThis->cryprovFileData, &bytesLeft));
+ if(bytesLeft == -1 || bytesLeft > (ssize_t) pThis->sIOBufSize) {
+ toRead = pThis->sIOBufSize;
+ } else {
+ toRead = (size_t) bytesLeft;
+ }
+ }
+ if(pThis->bReopenOnTruncate) {
+ rsRetVal localRet = checkTruncation(pThis);
+ if(localRet == RS_RET_FILE_TRUNCATED) {
+ continue;
+ }
+ CHKiRet(localRet);
+ }
+ iLenRead = read(pThis->fd, pThis->pIOBuf, toRead);
+ DBGOPRINT((obj_t*) pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead);
+ DBGOPRINT((obj_t*) pThis, "file %d read %*s\n", pThis->fd, (unsigned) iLenRead, (char*) pThis->pIOBuf);
+ /* end crypto */
+ if(iLenRead == 0) {
+ CHKiRet(strmHandleEOF(pThis));
+ } else if(iLenRead < 0)
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ else { /* good read */
+ /* here we place our crypto interface */
+ if(pThis->cryprov != NULL) {
+ actualDataLen = iLenRead;
+ pThis->cryprov->Decrypt(pThis->cryprovFileData, pThis->pIOBuf, &actualDataLen);
+ *padBytes = iLenRead - actualDataLen;
+ iLenRead = actualDataLen;
+ DBGOPRINT((obj_t*) pThis, "encrypted file %d pad bytes %d, actual "
+ "data %ld\n", pThis->fd, *padBytes, iLenRead);
+ } else {
+ *padBytes = 0;
+ }
+ pThis->iBufPtrMax = iLenRead;
+ bRun = 0; /* exit loop */
+ }
+ }
+ /* if we reach this point, we had a good read */
+ pThis->iBufPtr = 0;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* debug output of current buffer */
+void
+strmDebugOutBuf(const strm_t *const pThis)
+{
+ int strtIdx = pThis->iBufPtr - 50;
+ if(strtIdx < 0)
+ strtIdx = 0;
+ DBGOPRINT((obj_t*) pThis, "strmRead ungetc %d, index %zd, max %zd, buf '%.*s', CURR: '%.*s'\n",
+ pThis->iUngetC, pThis->iBufPtr, pThis->iBufPtrMax, (int) pThis->iBufPtrMax - strtIdx,
+ pThis->pIOBuf+strtIdx, (int) (pThis->iBufPtrMax - pThis->iBufPtr), pThis->pIOBuf+pThis->iBufPtr);
+}
+
+/* logically "read" a character from a file. What actually happens is that
+ * data is taken from the buffer. Only if the buffer is full, data is read
+ * directly from file. In that case, a read is performed blockwise.
+ * rgerhards, 2008-01-07
+ * NOTE: needs to be enhanced to support sticking with a strm entry (if not
+ * deleted).
+ */
+static rsRetVal strmReadChar(strm_t *pThis, uchar *pC)
+{
+ int padBytes = 0; /* in crypto mode, we may have some padding (non-data) bytes */
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pC != NULL);
+
+ /* DEV debug only: DBGOPRINT((obj_t*) pThis, "strmRead index %zd, max %zd\n", pThis->iBufPtr,
+ pThis->iBufPtrMax); */
+ if(pThis->iUngetC != -1) { /* do we have an "unread" char that we need to provide? */
+ *pC = pThis->iUngetC;
+ ++pThis->iCurrOffs; /* one more octet read */
+ pThis->iUngetC = -1;
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* do we need to obtain a new buffer? */
+ if(pThis->iBufPtr >= pThis->iBufPtrMax) {
+ CHKiRet(strmReadBuf(pThis, &padBytes));
+ }
+ pThis->iCurrOffs += padBytes;
+
+ /* if we reach this point, we have data available in the buffer */
+
+ *pC = pThis->pIOBuf[pThis->iBufPtr++];
+ ++pThis->iCurrOffs; /* one more octet read */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* unget a single character just like ungetc(). As with that call, there is only a single
+ * character buffering capability.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal strmUnreadChar(strm_t *pThis, uchar c)
+{
+ assert(pThis != NULL);
+ assert(pThis->iUngetC == -1);
+ pThis->iUngetC = c;
+ --pThis->iCurrOffs; /* one less octet read - NOTE: this can cause problems if we got a file change
+ and immediately do an unread and the file is on a buffer boundary and the stream is then persisted.
+ With the queue, this can not happen as an Unread is only done on record begin, which is never split
+ accross files. For other cases we accept the very remote risk. -- rgerhards, 2008-01-12 */
+
+ return RS_RET_OK;
+}
+
+/* read a 'paragraph' from a strm file.
+ * A paragraph may be terminated by a LF, by a LFLF, or by LF<not whitespace> depending on the option set.
+ * The termination LF characters are read, but are
+ * not returned in the buffer (it is discared). The caller is responsible for
+ * destruction of the returned CStr object! -- dlang 2010-12-13
+ *
+ * Parameter mode controls legacy multi-line processing:
+ * mode = 0 single line mode (equivalent to ReadLine)
+ * mode = 1 LFLF mode (paragraph, blank line between entries)
+ * mode = 2 LF <not whitespace> mode, a log line starts at the beginning of
+ * a line, but following lines that are indented are part of the same log entry
+ */
+static rsRetVal ATTR_NONNULL(1, 2)
+strmReadLine(strm_t *const pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF,
+ const uchar *const escapeLFString, uint32_t trimLineOverBytes, int64 *const strtOffs)
+{
+ uchar c;
+ uchar finished;
+ const int escapeLFString_len = (escapeLFString == NULL) ? 4 : strlen((char*) escapeLFString);
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(ppCStr != NULL);
+
+ CHKiRet(cstrConstruct(ppCStr));
+ CHKiRet(strmReadChar(pThis, &c));
+
+ /* append previous message to current message if necessary */
+ if(pThis->prevLineSegment != NULL) {
+ cstrFinalize(pThis->prevLineSegment);
+ dbgprintf("readLine: have previous line segment: '%s'\n",
+ rsCStrGetSzStrNoNULL(pThis->prevLineSegment));
+ CHKiRet(cstrAppendCStr(*ppCStr, pThis->prevLineSegment));
+ cstrDestruct(&pThis->prevLineSegment);
+ }
+ if(mode == 0) {
+ while(c != '\n') {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ CHKiRet(strmReadChar(pThis, &c));
+ }
+ if (trimLineOverBytes > 0 && (uint32_t) cstrLen(*ppCStr) > trimLineOverBytes) {
+ /* Truncate long line at trimLineOverBytes position */
+ dbgprintf("Truncate long line at %u, mode %d\n", trimLineOverBytes, mode);
+ rsCStrTruncate(*ppCStr, cstrLen(*ppCStr) - trimLineOverBytes);
+ cstrAppendChar(*ppCStr, '\n');
+ }
+ cstrFinalize(*ppCStr);
+ } else if(mode == 1) {
+ finished=0;
+ while(finished == 0){
+ if(c != '\n') {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ CHKiRet(strmReadChar(pThis, &c));
+ pThis->bPrevWasNL = 0;
+ } else {
+ if ((((*ppCStr)->iStrLen) > 0) ){
+ if(pThis->bPrevWasNL && escapeLFString_len > 0) {
+ rsCStrTruncate(*ppCStr, (bEscapeLF) ? escapeLFString_len : 1);
+ /* remove the prior newline */
+ finished=1;
+ } else {
+ if(bEscapeLF) {
+ if(escapeLFString == NULL) {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr,
+ (uchar*)"#012", sizeof("#012")-1));
+ } else {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr,
+ escapeLFString, escapeLFString_len));
+ }
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
+ CHKiRet(strmReadChar(pThis, &c));
+ pThis->bPrevWasNL = 1;
+ }
+ } else {
+ finished=1; /* this is a blank line, a \n with nothing since
+ the last complete record */
+ }
+ }
+ }
+ cstrFinalize(*ppCStr);
+ pThis->bPrevWasNL = 0;
+ } else if(mode == 2) {
+ /* indented follow-up lines */
+ finished=0;
+ while(finished == 0){
+ if ((*ppCStr)->iStrLen == 0){
+ if(c != '\n') {
+ /* nothing in the buffer, and it's not a newline, add it to the buffer */
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ CHKiRet(strmReadChar(pThis, &c));
+ } else {
+ finished=1; /* this is a blank line, a \n with nothing since the
+ last complete record */
+ }
+ } else {
+ if(pThis->bPrevWasNL) {
+ if ((c == ' ') || (c == '\t')){
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ CHKiRet(strmReadChar(pThis, &c));
+ pThis->bPrevWasNL = 0;
+ } else {
+ /* clean things up by putting the character we just read back into
+ * the input buffer and removing the LF character that is
+ * currently at the
+ * end of the output string */
+ CHKiRet(strmUnreadChar(pThis, c));
+ if(bEscapeLF && escapeLFString_len > 0) {
+ rsCStrTruncate(*ppCStr, (bEscapeLF) ? escapeLFString_len : 1);
+ }
+ finished=1;
+ }
+ } else { /* not the first character after a newline, add it to the buffer */
+ if(c == '\n') {
+ pThis->bPrevWasNL = 1;
+ if(bEscapeLF && escapeLFString_len > 0) {
+ if(escapeLFString == NULL) {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr,
+ (uchar*)"#012", sizeof("#012")-1));
+ } else {
+ CHKiRet(rsCStrAppendStrWithLen(*ppCStr,
+ escapeLFString, escapeLFString_len));
+ }
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
+ } else {
+ CHKiRet(cstrAppendChar(*ppCStr, c));
+ }
+ CHKiRet(strmReadChar(pThis, &c));
+ }
+ }
+ }
+ if (trimLineOverBytes > 0 && (uint32_t) cstrLen(*ppCStr) > trimLineOverBytes) {
+ /* Truncate long line at trimLineOverBytes position */
+ dbgprintf("Truncate long line at %u, mode %d\n", trimLineOverBytes, mode);
+ rsCStrTruncate(*ppCStr, cstrLen(*ppCStr) - trimLineOverBytes);
+ cstrAppendChar(*ppCStr, '\n');
+ }
+ cstrFinalize(*ppCStr);
+ pThis->bPrevWasNL = 0;
+ }
+
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ if(strtOffs != NULL) {
+ *strtOffs = pThis->strtOffs;
+ }
+ pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */
+ } else {
+DBGPRINTF("RGER: strmReadLine iRet %d\n", iRet);
+ if(*ppCStr != NULL) {
+ if(cstrLen(*ppCStr) > 0) {
+ /* we may have an empty string in an unsuccesfull poll or after restart! */
+ if(rsCStrConstructFromCStr(&pThis->prevLineSegment, *ppCStr) != RS_RET_OK) {
+ /* we cannot do anything against this, but we can at least
+ * ensure we do not have any follow-on errors.
+ */
+ pThis->prevLineSegment = NULL;
+ }
+ }
+ cstrDestruct(ppCStr);
+ }
+ }
+
+ RETiRet;
+}
+
+/* check if the current multi line read is timed out
+ * @return 0 - no timeout, something else - timeout
+ */
+int
+strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis)
+{
+ /* note: order of evaluation is choosen so that the most inexpensive
+ * processing flow is used.
+ */
+ DBGPRINTF("strmReadMultiline_isTimedOut: prevMsgSeg %p, readTimeout %d, "
+ "lastRead %lld\n", pThis->prevMsgSegment, pThis->readTimeout,
+ (long long) pThis->lastRead);
+ return( (pThis->readTimeout)
+ && (pThis->prevMsgSegment != NULL)
+ && (getTime(NULL) > pThis->lastRead + pThis->readTimeout) );
+}
+
+/* read a multi-line message from a strm file.
+ * The multi-line message is terminated based on the user-provided
+ * startRegex or endRegex (Posix ERE). For performance reasons, the regex
+ * must already have been compiled by the user.
+ * added 2015-05-12 rgerhards
+ */
+rsRetVal ATTR_NONNULL(1,2)
+strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, const sbool bEscapeLF,
+ const uchar *const escapeLFString, const sbool discardTruncatedMsg, const sbool msgDiscardingError,
+ int64 *const strtOffs)
+{
+ uchar c;
+ uchar finished = 0;
+ cstr_t *thisLine = NULL;
+ rsRetVal readCharRet;
+ const time_t tCurr = pThis->readTimeout ? getTime(NULL) : 0;
+ size_t maxMsgSize = glblGetMaxLine(runConf);
+ DEFiRet;
+
+ do {
+ CHKiRet(strmReadChar(pThis, &c)); /* immediately exit on EOF */
+ pThis->lastRead = tCurr;
+ CHKiRet(cstrConstruct(&thisLine));
+ /* append previous message to current message if necessary */
+ if(pThis->prevLineSegment != NULL) {
+ CHKiRet(cstrAppendCStr(thisLine, pThis->prevLineSegment));
+ cstrDestruct(&pThis->prevLineSegment);
+ }
+
+ while(c != '\n') {
+ CHKiRet(cstrAppendChar(thisLine, c));
+ readCharRet = strmReadChar(pThis, &c);
+ if(readCharRet == RS_RET_EOF) {/* end of file reached without \n? */
+ CHKiRet(rsCStrConstructFromCStr(&pThis->prevLineSegment, thisLine));
+ }
+ CHKiRet(readCharRet);
+ }
+ cstrFinalize(thisLine);
+
+ /* we have a line, now let's assemble the message */
+ const int isStartMatch = start_preg ?
+ !regexec(start_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) :
+ 0;
+ const int isEndMatch = end_preg ?
+ !regexec(end_preg, (char*)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) :
+ 0;
+
+ if(isStartMatch) {
+ /* in this case, the *previous* message is complete and we are
+ * at the start of a new one.
+ */
+ if(pThis->ignoringMsg == 0) {
+ if(pThis->prevMsgSegment != NULL) {
+ /* may be NULL in initial poll! */
+ finished = 1;
+ *ppCStr = pThis->prevMsgSegment;
+ }
+ }
+ CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, thisLine));
+ pThis->ignoringMsg = 0;
+ } else {
+ if(pThis->ignoringMsg == 0) {
+ if(pThis->prevMsgSegment == NULL) {
+ /* may be NULL in initial poll or after timeout! */
+ CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, thisLine));
+ } else {
+ if(bEscapeLF) {
+ if(escapeLFString == NULL) {
+ rsCStrAppendStrWithLen(pThis->prevMsgSegment, (uchar*)"\\n", 2);
+ } else {
+ rsCStrAppendStr(pThis->prevMsgSegment, escapeLFString);
+ }
+ } else {
+ cstrAppendChar(pThis->prevMsgSegment, '\n');
+ }
+
+
+ size_t currLineLen = cstrLen(thisLine);
+ if(currLineLen > 0) {
+ size_t len;
+ if((len = cstrLen(pThis->prevMsgSegment) + currLineLen) <
+ maxMsgSize) {
+ CHKiRet(cstrAppendCStr(pThis->prevMsgSegment, thisLine));
+ /* we could do this faster, but for now keep it simple */
+ } else {
+ if (cstrLen(pThis->prevMsgSegment) > maxMsgSize) {
+ len = 0;
+ } else {
+ len = currLineLen-(len-maxMsgSize);
+ for(size_t z=0; z<len; z++) {
+ cstrAppendChar(pThis->prevMsgSegment,
+ thisLine->pBuf[z]);
+ }
+ }
+ finished = 1;
+ *ppCStr = pThis->prevMsgSegment;
+ CHKiRet(rsCStrConstructFromszStr(&pThis->prevMsgSegment,
+ thisLine->pBuf+len));
+ if(discardTruncatedMsg == 1) {
+ pThis->ignoringMsg = 1;
+ }
+ if(msgDiscardingError == 1) {
+ if(discardTruncatedMsg == 1) {
+ LogError(0, RS_RET_ERR,
+ "imfile error: message received is "
+ "larger than max msg size; "
+ "rest of message will not be "
+ "processed");
+ } else {
+ LogError(0, RS_RET_ERR,
+ "imfile error: message received is "
+ "larger than max msg size; message "
+ "will be split and processed as "
+ "another message");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if(isEndMatch) {
+ /* in this case, the *current* message is complete and we are
+ * at the end of it.
+ */
+ if(pThis->ignoringMsg == 0) {
+ if(pThis->prevMsgSegment != NULL) {
+ finished = 1;
+ *ppCStr = pThis->prevMsgSegment;
+ pThis->prevMsgSegment= NULL;
+ }
+ }
+ pThis->ignoringMsg = 0;
+ }
+ cstrDestruct(&thisLine);
+ } while(finished == 0);
+
+finalize_it:
+ *strtOffs = pThis->strtOffs;
+ if(thisLine != NULL) {
+ cstrDestruct(&thisLine);
+ }
+ if(iRet == RS_RET_OK) {
+ pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */
+ cstrFinalize(*ppCStr);
+ } else {
+ if( pThis->readTimeout
+ && (pThis->prevMsgSegment != NULL)
+ && (tCurr > pThis->lastRead + pThis->readTimeout)) {
+ if(rsCStrConstructFromCStr(ppCStr, pThis->prevMsgSegment) == RS_RET_OK) {
+ cstrFinalize(*ppCStr);
+ cstrDestruct(&pThis->prevMsgSegment);
+ pThis->lastRead = tCurr;
+ pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */
+ dbgprintf("stream: generated msg based on timeout: %s\n",
+ cstrGetSzStrNoNULL(*ppCStr));
+ iRet = RS_RET_OK;
+ }
+ }
+ }
+ RETiRet;
+}
+
+/* Standard-Constructor for the strm object
+ */
+BEGINobjConstruct(strm) /* be sure to specify the object type also in END macro! */
+ pThis->iCurrFNum = 1;
+ pThis->fd = -1;
+ pThis->fdDir = -1;
+ pThis->iUngetC = -1;
+ pThis->bVeryReliableZip = 0;
+ pThis->sType = STREAMTYPE_FILE_SINGLE;
+ pThis->sIOBufSize = glblGetIOBufSize();
+ pThis->tOpenMode = 0600;
+ pThis->compressionDriver = STRM_COMPRESS_ZIP;
+ pThis->pszSizeLimitCmd = NULL;
+ pThis->prevLineSegment = NULL;
+ pThis->prevMsgSegment = NULL;
+ pThis->strtOffs = 0;
+ pThis->ignoringMsg = 0;
+ pThis->bPrevWasNL = 0;
+ pThis->fileNotFoundError = 1;
+ pThis->noRepeatedErrorOutput = 0;
+ pThis->lastRead = getTime(NULL);
+ENDobjConstruct(strm)
+
+
+/* ConstructionFinalizer
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal strmConstructFinalize(strm_t *pThis)
+{
+ pthread_mutexattr_t mutAttr;
+ rsRetVal localRet;
+ int i;
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ pThis->iBufPtrMax = 0; /* results in immediate read request */
+ if(pThis->iZipLevel) { /* do we need a zip buf? */
+ if(pThis->compressionDriver == STRM_COMPRESS_ZSTD) {
+ localRet = objUse(zstdw, LM_ZSTDW_FILENAME);
+ if(localRet != RS_RET_OK) {
+ pThis->iZipLevel = 0;
+ LogError(0, localRet, "stream was requested with zstd compression mode, "
+ "but zstdw module unavailable - using without compression\n");
+ }
+ } else {
+ assert(pThis->compressionDriver == STRM_COMPRESS_ZIP);
+ localRet = objUse(zlibw, LM_ZLIBW_FILENAME);
+ if(localRet != RS_RET_OK) {
+ pThis->iZipLevel = 0;
+ LogError(0, localRet, "stream was requested with zip mode, but zlibw "
+ "module unavailable - using without zip\n");
+ }
+ }
+ /* we use the same size as the original buf, as we would like
+ * to make sure we can write out everything with a SINGLE api call!
+ * We add another 128 bytes to take care of the gzip header and "all eventualities".
+ */
+ CHKmalloc(pThis->pZipBuf = (Bytef*) malloc(pThis->sIOBufSize + 128));
+ }
+
+ /* if we are set to sync, we must obtain a file handle to the directory for fsync() purposes */
+ if(pThis->bSync && !pThis->bIsTTY && pThis->pszDir != NULL) {
+ pThis->fdDir = open((char*)pThis->pszDir, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ if(pThis->fdDir == -1) {
+ char errStr[1024];
+ int err = errno;
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("error %d opening directory file for fsync() use - fsync for directory "
+ "disabled: %s\n", errno, errStr);
+ }
+ }
+
+ /* if we have a flush interval, we need to do async writes in any case */
+ if(pThis->iFlushInterval != 0) {
+ pThis->bAsyncWrite = 1;
+ }
+
+ DBGPRINTF("file stream %s params: flush interval %d, async write %d\n",
+ getFileDebugName(pThis),
+ pThis->iFlushInterval, pThis->bAsyncWrite);
+
+ /* if we work asynchronously, we need a couple of synchronization objects */
+ if(pThis->bAsyncWrite) {
+ /* the mutex must be recursive, because objects may call into other
+ * object identifiers recursively.
+ */
+ pthread_mutexattr_init(&mutAttr);
+ pthread_mutexattr_settype(&mutAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&pThis->mut, &mutAttr);
+ pthread_cond_init(&pThis->notFull, 0);
+ pthread_cond_init(&pThis->notEmpty, 0);
+ pthread_cond_init(&pThis->isEmpty, 0);
+ pThis->iCnt = pThis->iEnq = pThis->iDeq = 0;
+ for(i = 0 ; i < STREAM_ASYNC_NUMBUFS ; ++i) {
+ CHKmalloc(pThis->asyncBuf[i].pBuf = (uchar*) malloc(pThis->sIOBufSize));
+ }
+ pThis->pIOBuf = pThis->asyncBuf[0].pBuf;
+ pThis->bStopWriter = 0;
+ if(pthread_create(&pThis->writerThreadID,
+ &default_thread_attr,
+ asyncWriterThread, pThis) != 0)
+ DBGPRINTF("ERROR: stream %p cold not create writer thread\n", pThis);
+ } else {
+ /* we work synchronously, so we need to alloc a fixed pIOBuf */
+ CHKmalloc(pThis->pIOBuf = (uchar*) malloc(pThis->sIOBufSize));
+ CHKmalloc(pThis->pIOBuf_truncation = (char*) malloc(pThis->sIOBufSize));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* destructor for the strm object */
+BEGINobjDestruct(strm) /* be sure to specify the object type also in END and CODESTART macros! */
+ int i;
+CODESTARTobjDestruct(strm)
+ /* we need to stop the ZIP writer */
+ if(pThis->bAsyncWrite)
+ /* Note: mutex will be unlocked in strmCloseFile/stopWriter! */
+ d_pthread_mutex_lock(&pThis->mut);
+
+ /* strmClose() will handle read-only files as well as need to open
+ * files that have unwritten buffers. -- rgerhards, 2010-03-09
+ */
+ strmCloseFile(pThis);
+
+ if(pThis->bAsyncWrite) {
+ pthread_mutex_destroy(&pThis->mut);
+ pthread_cond_destroy(&pThis->notFull);
+ pthread_cond_destroy(&pThis->notEmpty);
+ pthread_cond_destroy(&pThis->isEmpty);
+ for(i = 0 ; i < STREAM_ASYNC_NUMBUFS ; ++i) {
+ free(pThis->asyncBuf[i].pBuf);
+ }
+ } else {
+ free(pThis->pIOBuf);
+ free(pThis->pIOBuf_truncation);
+ }
+
+ /* Finally, we can free the resources.
+ * IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else
+ * we get random errors...
+ */
+ if(pThis->compressionDriver == STRM_COMPRESS_ZSTD) {
+ zstdw.Destruct(pThis);
+ }
+ if(pThis->prevLineSegment)
+ cstrDestruct(&pThis->prevLineSegment);
+ if(pThis->prevMsgSegment)
+ cstrDestruct(&pThis->prevMsgSegment);
+ free(pThis->pszDir);
+ free(pThis->pZipBuf);
+ free(pThis->pszCurrFName);
+ free(pThis->pszFName);
+ free(pThis->pszSizeLimitCmd);
+ pThis->bStopWriter = 2; /* RG: use as flag for destruction */
+ENDobjDestruct(strm)
+
+
+/* check if we need to open a new file (in output mode only).
+ * The decision is based on file size AND record delimition state.
+ * This method may also be called on a closed file, in which case
+ * it immediately returns.
+ */
+static rsRetVal strmCheckNextOutputFile(strm_t *pThis)
+{
+ DEFiRet;
+
+ if(pThis->fd == -1 || pThis->sType != STREAMTYPE_FILE_CIRCULAR)
+ FINALIZE;
+
+ /* wait for output to be empty, so that our counts are correct */
+ strmWaitAsyncWriterDone(pThis);
+
+ if(pThis->iCurrOffs >= pThis->iMaxFileSize) {
+ DBGOPRINT((obj_t*) pThis, "max file size %ld reached for %d, now %ld - starting new file\n",
+ (long) pThis->iMaxFileSize, pThis->fd, (long) pThis->iCurrOffs);
+ CHKiRet(strmNextFile(pThis));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* try to recover a tty after a write error. This may have happend
+ * due to vhangup(), and, if so, we can simply re-open it.
+ */
+#ifdef linux
+# define ERR_TTYHUP EIO
+#else
+# define ERR_TTYHUP EBADF
+#endif
+static rsRetVal
+tryTTYRecover(strm_t *pThis, int err)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+#ifndef __FreeBSD__
+ if(err == ERR_TTYHUP) {
+#else
+ /* Try to reopen our file descriptor even on errno 6, FreeBSD bug 200429
+ * Also try on errno 5, FreeBSD bug 211033
+ */
+ if(err == ERR_TTYHUP || err == ENXIO || err == EIO) {
+#endif /* __FreeBSD__ */
+ close(pThis->fd);
+ pThis->fd = -1;
+ CHKiRet(doPhysOpen(pThis));
+ }
+
+finalize_it:
+ RETiRet;
+}
+#undef ER_TTYHUP
+
+
+/* issue write() api calls until either the buffer is completely
+ * written or an error occurred (it may happen that multiple writes
+ * are required, what is perfectly legal. On exit, *pLenBuf contains
+ * the number of bytes actually written.
+ * rgerhards, 2009-06-08
+ */
+static rsRetVal ATTR_NONNULL(1,2,3)
+doWriteCall(strm_t *pThis, uchar *pBuf, size_t *pLenBuf)
+{
+ ssize_t lenBuf;
+ ssize_t iTotalWritten;
+ ssize_t iWritten;
+ char *pWriteBuf;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+#ifdef __FreeBSD__
+ sbool crnlNow = 0;
+#endif /* __FreeBSD__ */
+
+ lenBuf = *pLenBuf;
+ pWriteBuf = (char*) pBuf;
+ iTotalWritten = 0;
+ do {
+ #ifdef __FreeBSD__
+ if (pThis->bIsTTY && !pThis->iZipLevel && !pThis->cryprov) {
+ char *pNl = NULL;
+ if (crnlNow == 0) pNl = strchr(pWriteBuf, '\n');
+ else crnlNow = 0;
+ if (pNl == pWriteBuf) {
+ iWritten = write(pThis->fd, "\r", 1);
+ if (iWritten > 0) {
+ crnlNow = 1;
+ iWritten = 0;
+ }
+ } else iWritten = write(pThis->fd, pWriteBuf, pNl ? pNl - pWriteBuf : lenBuf);
+ } else
+ #endif /* __FreeBSD__ */
+ iWritten = write(pThis->fd, pWriteBuf, lenBuf);
+ if(iWritten < 0) {
+ const int err = errno;
+ iWritten = 0; /* we have written NO bytes! */
+ if(err == EBADF) {
+ DBGPRINTF("file %s: errno %d, fd %d no longer valid, recovery by "
+ "reopen; if you see this, consider reporting at "
+ "https://github.com/rsyslog/rsyslog/issues/3404 "
+ "so that we know when it happens. Include output of uname -a. "
+ "OS error reason", pThis->pszCurrFName, err, pThis->fd);
+ pThis->fd = -1;
+ CHKiRet(doPhysOpen(pThis));
+ } else {
+ if(err != EINTR) {
+ LogError(err, RS_RET_IO_ERROR, "file '%s'[%d] write error - see "
+ "https://www.rsyslog.com/solving-rsyslog-write-errors/ for help "
+ "OS error", pThis->pszCurrFName, pThis->fd);
+ }
+ if(err == EINTR) {
+ /*NO ERROR, just continue */;
+ } else if( !pThis->bIsTTY && ( err == ENOTCONN || err == EIO )) {
+ /* Failure for network file system, thus file needs to be closed
+ * and reopened. */
+ close(pThis->fd);
+ pThis->fd = -1;
+ CHKiRet(doPhysOpen(pThis));
+ } else {
+ if(pThis->bIsTTY) {
+ CHKiRet(tryTTYRecover(pThis, err));
+ } else {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ /* Would it make sense to cover more error cases? So far, I
+ * do not see good reason to do so.
+ */
+ }
+ }
+ }
+ }
+ /* advance buffer to next write position */
+ iTotalWritten += iWritten;
+ lenBuf -= iWritten;
+ pWriteBuf += iWritten;
+ } while(lenBuf > 0); /* Warning: do..while()! */
+
+ DBGOPRINT((obj_t*) pThis, "file %d write wrote %d bytes\n", pThis->fd, (int) iWritten);
+
+finalize_it:
+ *pLenBuf = iTotalWritten;
+ RETiRet;
+}
+
+
+
+/* write memory buffer to a stream object.
+ */
+static rsRetVal
+doWriteInternal(strm_t *pThis, uchar *pBuf, const size_t lenBuf, const int bFlush)
+{
+ DEFiRet;
+
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) doWriteInternal: bFlush %d\n",
+ pThis->fd, getFileDebugName(pThis), bFlush);
+
+ if(pThis->iZipLevel) {
+ CHKiRet(doZipWrite(pThis, pBuf, lenBuf, bFlush));
+ } else {
+ /* write without zipping */
+ CHKiRet(strmPhysWrite(pThis, pBuf, lenBuf));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called to "do" an async write call, what primarily means that
+ * the data is handed over to the writer thread (which will then do the actual write
+ * in parallel). Note that the stream mutex has already been locked by the
+ * strmWrite...() calls. Also note that we always have only a single producer,
+ * so we can simply serially assign the next free buffer to it and be sure that
+ * the very some producer comes back in sequence to submit the then-filled buffers.
+ * This also enables us to timout on partially written buffers. -- rgerhards, 2009-07-06
+ */
+static rsRetVal
+doAsyncWriteInternal(strm_t *pThis, size_t lenBuf, const int bFlushZip)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) doAsyncWriteInternal at begin: "
+ "iCnt %d, iEnq %d, bFlushZip %d\n",
+ pThis->fd, getFileDebugName(pThis),
+ pThis->iCnt, pThis->iEnq, bFlushZip);
+ /* the -1 below is important, because we need one buffer for the main thread! */
+ while(pThis->iCnt >= STREAM_ASYNC_NUMBUFS - 1)
+ d_pthread_cond_wait(&pThis->notFull, &pThis->mut);
+
+ pThis->asyncBuf[pThis->iEnq % STREAM_ASYNC_NUMBUFS].lenBuf = lenBuf;
+ pThis->pIOBuf = pThis->asyncBuf[++pThis->iEnq % STREAM_ASYNC_NUMBUFS].pBuf;
+ if(!pThis->bFlushNow) /* if we already need to flush, do not overwrite */
+ pThis->bFlushNow = bFlushZip;
+
+ pThis->bDoTimedWait = 0; /* everything written, no need to timeout partial buffer writes */
+ if(++pThis->iCnt == 1) {
+ pthread_cond_signal(&pThis->notEmpty);
+ DBGOPRINT((obj_t*) pThis, "doAsyncWriteInternal signaled notEmpty\n");
+ }
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) doAsyncWriteInternal at exit: "
+ "iCnt %d, iEnq %d, bFlushZip %d\n",
+ pThis->fd, getFileDebugName(pThis),
+ pThis->iCnt, pThis->iEnq, bFlushZip);
+
+ RETiRet;
+}
+
+
+/* schedule writing to the stream. Depending on our concurrency settings,
+ * this either directly writes to the stream or schedules writing via
+ * the background thread. -- rgerhards, 2009-07-07
+ */
+static rsRetVal
+strmSchedWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlushZip)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ /* we need to reset the buffer pointer BEFORE calling the actual write
+ * function. Otherwise, in circular mode, the write function will
+ * potentially close the file, then close will flush and as the
+ * buffer pointer is nonzero, will re-call into this code here. In
+ * the end result, we than have a problem (and things are screwed
+ * up). So we reset the buffer pointer first, and all this can
+ * not happen. It is safe to do so, because that pointer is NOT
+ * used inside the write functions. -- rgerhads, 2010-03-10
+ */
+ pThis->iBufPtr = 0; /* we are at the begin of a new buffer */
+ if(pThis->bAsyncWrite) {
+ CHKiRet(doAsyncWriteInternal(pThis, lenBuf, bFlushZip));
+ } else {
+ CHKiRet(doWriteInternal(pThis, pBuf, lenBuf, bFlushZip));
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* This is the writer thread for asynchronous mode.
+ * -- rgerhards, 2009-07-06
+ */
+static void*
+asyncWriterThread(void *pPtr)
+{
+ int iDeq;
+ struct timespec t;
+ sbool bTimedOut = 0;
+ strm_t *pThis = (strm_t*) pPtr;
+ int err;
+ uchar thrdName[256] = "rs:";
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ ustrncpy(thrdName+3, pThis->pszFName, sizeof(thrdName)-4);
+ dbgOutputTID((char*)thrdName);
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ if(prctl(PR_SET_NAME, (char*)thrdName, 0, 0, 0) != 0) {
+ DBGPRINTF("prctl failed, not setting thread name for '%s'\n", "stream writer");
+ }
+# endif
+
+ d_pthread_mutex_lock(&pThis->mut);
+ while(1) { /* loop broken inside */
+ while(pThis->iCnt == 0) {
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) asyncWriterThread new iteration, "
+ "iCnt %d, bTimedOut %d, iFlushInterval %d\n", pThis->fd,
+ getFileDebugName(pThis),
+ pThis->iCnt, bTimedOut, pThis->iFlushInterval);
+ if(pThis->bStopWriter) {
+ pthread_cond_broadcast(&pThis->isEmpty);
+ d_pthread_mutex_unlock(&pThis->mut);
+ goto finalize_it; /* break main loop */
+ }
+ if(bTimedOut && pThis->iBufPtr > 0) {
+ /* if we timed out, we need to flush pending data */
+ strmFlushInternal(pThis, 1);
+ bTimedOut = 0;
+ continue;
+ }
+ bTimedOut = 0;
+ if(pThis->bDoTimedWait) {
+ timeoutComp(&t, pThis->iFlushInterval * 1000); /* 1000 *millisconds* */
+ if((err = pthread_cond_timedwait(&pThis->notEmpty, &pThis->mut, &t)) != 0) {
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) asyncWriterThread timed out\n",
+ pThis->fd, getFileDebugName(pThis));
+ bTimedOut = 1; /* simulate in any case */
+ if(err != ETIMEDOUT) {
+ char errStr[1024];
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("stream async writer timeout with error (%d): %s - "
+ "ignoring\n", err, errStr);
+ }
+ }
+ } else {
+ d_pthread_cond_wait(&pThis->notEmpty, &pThis->mut);
+ }
+ }
+
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) asyncWriterThread awoken, "
+ "iCnt %d, bTimedOut %d\n", pThis->fd, getFileDebugName(pThis),
+ pThis->iCnt, bTimedOut);
+ bTimedOut = 0; /* we may have timed out, but there *is* work to do... */
+
+ iDeq = pThis->iDeq++ % STREAM_ASYNC_NUMBUFS;
+ const int bFlush = (pThis->bFlushNow || bTimedOut) ? 1 : 0;
+ pThis->bFlushNow = 0;
+
+ /* now we can do the actual write in parallel */
+ d_pthread_mutex_unlock(&pThis->mut);
+ doWriteInternal(pThis, pThis->asyncBuf[iDeq].pBuf, pThis->asyncBuf[iDeq].lenBuf, bFlush);
+ // TODO: error check????? 2009-07-06
+ d_pthread_mutex_lock(&pThis->mut);
+
+ --pThis->iCnt;
+ if(pThis->iCnt < STREAM_ASYNC_NUMBUFS) {
+ pthread_cond_signal(&pThis->notFull);
+ if(pThis->iCnt == 0)
+ pthread_cond_broadcast(&pThis->isEmpty);
+ }
+ }
+ /* Not reached */
+
+finalize_it:
+ DBGOPRINT((obj_t*) pThis, "file %d(%s) asyncWriterThread terminated\n",
+ pThis->fd, getFileDebugName(pThis));
+ return NULL; /* to keep pthreads happy */
+}
+
+
+/* sync the file to disk, so that any unwritten data is persisted. This
+ * also syncs the directory and thus makes sure that the file survives
+ * fatal failure. Note that we do NOT return an error status if the
+ * sync fails. Doing so would probably cause more trouble than it
+ * is worth (read: data loss may occur where we otherwise might not
+ * have it). -- rgerhards, 2009-06-08
+ */
+#undef SYNCCALL
+#if defined(HAVE_FDATASYNC) && !defined(__APPLE__)
+# define SYNCCALL(x) fdatasync(x)
+#else
+# define SYNCCALL(x) fsync(x)
+#endif
+static rsRetVal
+syncFile(strm_t *pThis)
+{
+ int ret;
+ DEFiRet;
+
+ if(pThis->bIsTTY)
+ FINALIZE; /* TTYs can not be synced */
+
+ DBGPRINTF("syncing file %d\n", pThis->fd);
+ ret = SYNCCALL(pThis->fd);
+ if(ret != 0) {
+ char errStr[1024];
+ int err = errno;
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("sync failed for file %d with error (%d): %s - ignoring\n",
+ pThis->fd, err, errStr);
+ }
+
+ if(pThis->fdDir != -1) {
+ if(fsync(pThis->fdDir) != 0)
+ DBGPRINTF("stream/syncFile: fsync returned error, ignoring\n");
+ }
+
+finalize_it:
+ RETiRet;
+}
+#undef SYNCCALL
+
+/* physically write to the output file. the provided data is ready for
+ * writing (e.g. zipped if we are requested to do that).
+ * Note that if the write() API fails, we do not reset any pointers, but return
+ * an error code. That means we may redo work in the next iteration.
+ * rgerhards, 2009-06-04
+ */
+static rsRetVal
+strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf)
+{
+ size_t iWritten;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ DBGPRINTF("strmPhysWrite, stream %p, len %u\n", pThis, (unsigned)lenBuf);
+ if(pThis->fd == -1)
+ CHKiRet(strmOpenFile(pThis));
+
+ /* here we place our crypto interface */
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->Encrypt(pThis->cryprovFileData, pBuf, &lenBuf);
+ }
+ /* end crypto */
+
+ iWritten = lenBuf;
+ CHKiRet(doWriteCall(pThis, pBuf, &iWritten));
+
+ pThis->iCurrOffs += iWritten;
+ /* update user counter, if provided */
+ if(pThis->pUsrWCntr != NULL)
+ *pThis->pUsrWCntr += iWritten;
+
+ if(pThis->bSync) {
+ CHKiRet(syncFile(pThis));
+ }
+
+ if(pThis->sType == STREAMTYPE_FILE_CIRCULAR) {
+ CHKiRet(strmCheckNextOutputFile(pThis));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* write the output buffer in zip mode
+ * This means we compress it first and then do a physical write.
+ * Note that we always do a full deflateInit ... deflate ... deflateEnd
+ * sequence. While this is not optimal, we need to do it because we need
+ * to ensure that the file is readable even when we are aborted. Doing the
+ * full sequence brings us as far towards this goal as possible (and not
+ * doing it would be a total failure). It may be worth considering to
+ * add a config switch so that the user can decide the risk he is ready
+ * to take, but so far this is not yet implemented (not even requested ;)).
+ * rgerhards, 2009-06-04
+ */
+static rsRetVal
+doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlush)
+{
+ if(pThis->compressionDriver == STRM_COMPRESS_ZSTD) {
+ return zstdw.doStrmWrite(pThis, pBuf, lenBuf, bFlush, strmPhysWrite);
+ } else {
+ return zlibw.doStrmWrite(pThis, pBuf, lenBuf, bFlush, strmPhysWrite);
+ }
+}
+
+
+
+/* finish zlib buffer, to be called before closing the ZIP file (if
+ * running in stream mode).
+ */
+static rsRetVal
+doZipFinish(strm_t *pThis)
+{
+ if(pThis->compressionDriver == STRM_COMPRESS_ZSTD) {
+ return zstdw.doCompressFinish(pThis, strmPhysWrite);
+ } else {
+ return zlibw.doCompressFinish(pThis, strmPhysWrite);
+ }
+}
+
+/* flush stream output buffer to persistent storage. This can be called at any time
+ * and is automatically called when the output buffer is full.
+ * rgerhards, 2008-01-10
+ */
+static rsRetVal
+strmFlushInternal(strm_t *pThis, int bFlushZip)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ DBGOPRINT((obj_t*) pThis, "strmFlushinternal: file %d(%s) flush, buflen %ld%s\n", pThis->fd,
+ getFileDebugName(pThis),
+ (long) pThis->iBufPtr, (pThis->iBufPtr == 0) ? " (no need to flush)" : "");
+
+ if(pThis->tOperationsMode != STREAMMODE_READ && pThis->iBufPtr > 0) {
+ iRet = strmSchedWrite(pThis, pThis->pIOBuf, pThis->iBufPtr, bFlushZip);
+ }
+
+ RETiRet;
+}
+
+
+/* flush stream output buffer to persistent storage. This can be called at any time
+ * and is automatically called when the output buffer is full. This function is for
+ * use by EXTERNAL callers. Do NOT use it internally. It locks the async writer
+ * mutex if ther is need to do so.
+ * rgerhards, 2010-03-18
+ */
+static rsRetVal
+strmFlush(strm_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ DBGOPRINT((obj_t*) pThis, "file %d strmFlush\n", pThis->fd);
+
+ if(pThis->bAsyncWrite)
+ d_pthread_mutex_lock(&pThis->mut);
+ CHKiRet(strmFlushInternal(pThis, 1));
+
+finalize_it:
+ if(pThis->bAsyncWrite)
+ d_pthread_mutex_unlock(&pThis->mut);
+
+ RETiRet;
+}
+
+
+/* seek a stream to a specific location. Pending writes are flushed, read data
+ * is invalidated.
+ * rgerhards, 2008-01-12
+ */
+static rsRetVal ATTR_NONNULL()
+strmSeek(strm_t *pThis, const off64_t offs)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ if(pThis->fd == -1) {
+ CHKiRet(strmOpenFile(pThis));
+ } else {
+ CHKiRet(strmFlushInternal(pThis, 0));
+ }
+ DBGOPRINT((obj_t*) pThis, "file %d seek, pos %llu\n", pThis->fd, (long long unsigned) offs);
+ const off64_t i = lseek64(pThis->fd, offs, SEEK_SET);
+ if(i != offs) {
+ LogError(errno, RS_RET_IO_ERROR, "file %s: unexpected error seeking to "
+ "offset %lld (ret %lld) - further malfunctions may happen",
+ pThis->pszCurrFName, (long long) i, (long long) offs);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ pThis->strtOffs = pThis->iCurrOffs = offs; /* we are now at *this* offset */
+ pThis->iBufPtr = 0; /* buffer invalidated */
+
+finalize_it:
+ RETiRet;
+}
+
+/* multi-file seek, seeks to file number & offset within file. This
+ * is a support function for the queue, in circular mode. DO NOT USE
+ * IT FOR OTHER NEEDS - it may not work as expected. It will
+ * seek to the new position and delete interim files, as it skips them.
+ * Note: this code can be removed when the queue gets a new disk store
+ * handler (if and when it does ;)).
+ * The output parameter bytesDel receives the number of bytes that have
+ * been deleted (if a file is deleted) or 0 if nothing was deleted.
+ * rgerhards, 2012-11-07
+ */
+rsRetVal
+strmMultiFileSeek(strm_t *pThis, unsigned int FNum, off64_t offs, off64_t *bytesDel)
+{
+ struct stat statBuf;
+ int skipped_files;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ if(FNum == 0 && offs == 0) { /* happens during queue init */
+ *bytesDel = 0;
+ FINALIZE;
+ }
+
+ skipped_files = FNum - pThis->iCurrFNum;
+ *bytesDel = 0;
+
+ while(skipped_files > 0) {
+ CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir,
+ pThis->pszFName, pThis->lenFName, pThis->iCurrFNum,
+ pThis->iFileNumDigits));
+ dbgprintf("rger: processing file %s\n", pThis->pszCurrFName);
+ if(stat((char*)pThis->pszCurrFName, &statBuf) != 0) {
+ LogError(errno, RS_RET_IO_ERROR, "unexpected error doing a stat() "
+ "on file %s - further malfunctions may happen",
+ pThis->pszCurrFName);
+ /* we do NOT error-terminate here as this could worsen the
+ * situation. As such, we just keep running and try to delete
+ * as many files as possible.
+ */
+ }
+ *bytesDel += statBuf.st_size;
+ DBGPRINTF("strmMultiFileSeek: detected new filenum, was %u, new %u, "
+ "deleting '%s' (%lld bytes)\n", pThis->iCurrFNum, FNum,
+ pThis->pszCurrFName, (long long) statBuf.st_size);
+ unlink((char*)pThis->pszCurrFName);
+ if(pThis->cryprov != NULL)
+ pThis->cryprov->DeleteStateFiles(pThis->pszCurrFName);
+ free(pThis->pszCurrFName);
+ pThis->pszCurrFName = NULL;
+ pThis->iCurrFNum++;
+ --skipped_files;
+ }
+ DBGOPRINT((obj_t*) pThis, "strmMultiFileSeek: deleted %lld bytes in this run\n",
+ (long long) *bytesDel);
+ pThis->strtOffs = pThis->iCurrOffs = offs;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* seek to current offset. This is primarily a helper to readjust the OS file
+ * pointer after a strm object has been deserialized.
+ */
+static rsRetVal strmSeekCurrOffs(strm_t *pThis)
+{
+ off64_t targetOffs;
+ uchar c;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ if(pThis->cryprov == NULL || pThis->tOperationsMode != STREAMMODE_READ) {
+ iRet = strmSeek(pThis, pThis->iCurrOffs);
+ FINALIZE;
+ }
+
+ /* As the cryprov may use CBC or similiar things, we need to read skip data */
+ targetOffs = pThis->iCurrOffs;
+ pThis->strtOffs = pThis->iCurrOffs = 0;
+ DBGOPRINT((obj_t*) pThis, "encrypted, doing skip read of %lld bytes\n",
+ (long long) targetOffs);
+ while(targetOffs != pThis->iCurrOffs) {
+ CHKiRet(strmReadChar(pThis, &c));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* write a *single* character to a stream object -- rgerhards, 2008-01-10
+ */
+static rsRetVal strmWriteChar(strm_t *__restrict__ const pThis, const uchar c)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ if(pThis->bAsyncWrite)
+ d_pthread_mutex_lock(&pThis->mut);
+
+ if(pThis->bDisabled)
+ ABORT_FINALIZE(RS_RET_STREAM_DISABLED);
+
+ /* if the buffer is full, we need to flush before we can write */
+ if(pThis->iBufPtr == pThis->sIOBufSize) {
+ CHKiRet(strmFlushInternal(pThis, 0));
+ }
+
+ /* we now always have space for one character, so we simply copy it */
+ *(pThis->pIOBuf + pThis->iBufPtr) = c;
+ pThis->iBufPtr++;
+
+finalize_it:
+ if(pThis->bAsyncWrite)
+ d_pthread_mutex_unlock(&pThis->mut);
+
+ RETiRet;
+}
+
+
+/* write an integer value (actually a long) to a stream object
+ * Note that we do not need to lock the mutex here, because we call
+ * strmWrite(), which does the lock (aka: we must not lock it, else we
+ * would run into a recursive lock, resulting in a deadlock!)
+ */
+static rsRetVal strmWriteLong(strm_t *__restrict__ const pThis, const long i)
+{
+ DEFiRet;
+ uchar szBuf[32];
+
+ assert(pThis != NULL);
+
+ CHKiRet(srUtilItoA((char*)szBuf, sizeof(szBuf), i));
+ CHKiRet(strmWrite(pThis, szBuf, strlen((char*)szBuf)));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* write memory buffer to a stream object.
+ * process the data in chunks and copy it over to our buffer. The caller-provided data
+ * may theoritically be larger than our buffer. In that case, we do multiple copies. One
+ * may argue if it were more efficient to write out the caller-provided buffer in that case
+ * and earlier versions of rsyslog did this. However, this introduces a lot of complexity
+ * inside the buffered writer and potential performance bottlenecks when trying to solve
+ * it. Now keep in mind that we actually do (almost?) never have a case where the
+ * caller-provided buffer is larger than our one. So instead of optimizing a case
+ * which normally does not exist, we expect some degradation in its case but make us
+ * perform better in the regular cases. -- rgerhards, 2009-07-07
+ * Note: the pThis->iBufPtr == pThis->sIOBufSize logic below looks a bit like an
+ * on-off error. In fact, it is not, because iBufPtr always points to the next
+ * *free* byte in the buffer. So if it is sIOBufSize - 1, there actually is one
+ * free byte left. This came up during a code walkthrough and was considered
+ * worth nothing. -- rgerhards, 2010-03-10
+ */
+static rsRetVal ATTR_NONNULL(1,2)
+strmWrite(strm_t *__restrict__ const pThis, const uchar *__restrict__ const pBuf, size_t lenBuf)
+{
+ DEFiRet;
+ size_t iWrite;
+ size_t iOffset;
+
+ assert(pThis != NULL);
+ assert(pBuf != NULL);
+
+ if(pThis->bDisabled)
+ ABORT_FINALIZE(RS_RET_STREAM_DISABLED);
+
+ if(pThis->bAsyncWrite)
+ d_pthread_mutex_lock(&pThis->mut);
+
+ iOffset = 0;
+ do {
+ if(pThis->iBufPtr == pThis->sIOBufSize) {
+ CHKiRet(strmFlushInternal(pThis, 0)); /* get a new buffer for rest of data */
+ }
+ iWrite = pThis->sIOBufSize - pThis->iBufPtr; /* this fits in current buf */
+ if(iWrite > lenBuf)
+ iWrite = lenBuf;
+ memcpy(pThis->pIOBuf + pThis->iBufPtr, pBuf + iOffset, iWrite);
+ pThis->iBufPtr += iWrite;
+ iOffset += iWrite;
+ lenBuf -= iWrite;
+ } while(lenBuf > 0);
+
+ /* now check if the buffer right at the end of the write is full and, if so,
+ * write it. This seems more natural than waiting (hours?) for the next message...
+ */
+ if(pThis->iBufPtr == pThis->sIOBufSize) {
+ CHKiRet(strmFlushInternal(pThis, 0)); /* get a new buffer for rest of data */
+ }
+ if(pThis->fd != -1 && pThis->iSizeLimit != 0) { /* Only check if fd already set */
+ CHKiRet(doSizeLimitProcessing(pThis));
+ }
+
+
+finalize_it:
+ if(pThis->bAsyncWrite) {
+ if(pThis->bDoTimedWait == 0) {
+ /* we potentially have a partial buffer, so re-activate the
+ * writer thread that it can set and pick up timeouts.
+ */
+ pThis->bDoTimedWait = 1;
+ pthread_cond_signal(&pThis->notEmpty);
+ }
+ d_pthread_mutex_unlock(&pThis->mut);
+ }
+
+ RETiRet;
+}
+
+
+/* property set methods */
+/* simple ones first */
+DEFpropSetMeth(strm, iMaxFileSize, int64)
+DEFpropSetMeth(strm, iFileNumDigits, int)
+DEFpropSetMeth(strm, tOperationsMode, int)
+DEFpropSetMeth(strm, tOpenMode, mode_t)
+DEFpropSetMeth(strm, compressionDriver, strm_compressionDriver_t)
+DEFpropSetMeth(strm, sType, strmType_t)
+DEFpropSetMeth(strm, iZipLevel, int)
+DEFpropSetMeth(strm, bVeryReliableZip, int)
+DEFpropSetMeth(strm, bSync, int)
+DEFpropSetMeth(strm, bReopenOnTruncate, int)
+DEFpropSetMeth(strm, sIOBufSize, size_t)
+DEFpropSetMeth(strm, iSizeLimit, off_t)
+DEFpropSetMeth(strm, iFlushInterval, int)
+DEFpropSetMeth(strm, pszSizeLimitCmd, uchar*)
+DEFpropSetMeth(strm, cryprov, cryprov_if_t*)
+DEFpropSetMeth(strm, cryprovData, void*)
+
+/* sets timeout in seconds */
+void ATTR_NONNULL()
+strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val)
+{
+ ISOBJ_TYPE_assert(pThis, strm);
+ pThis->readTimeout = val;
+}
+
+static rsRetVal ATTR_NONNULL()
+strmSetbDeleteOnClose(strm_t *const pThis, const int val)
+{
+ ISOBJ_TYPE_assert(pThis, strm);
+ pThis->bDeleteOnClose = val;
+ if(pThis->cryprov != NULL) {
+ pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
+ }
+ return RS_RET_OK;
+}
+
+static rsRetVal ATTR_NONNULL()
+strmSetiMaxFiles(strm_t *const pThis, const int iNewVal)
+{
+ ISOBJ_TYPE_assert(pThis, strm);
+ pThis->iMaxFiles = iNewVal;
+ pThis->iFileNumDigits = getNumberDigits(iNewVal);
+ return RS_RET_OK;
+}
+
+static rsRetVal ATTR_NONNULL()
+strmSetFileNotFoundError(strm_t *const pThis, const int pFileNotFoundError)
+{
+ ISOBJ_TYPE_assert(pThis, strm);
+ pThis->fileNotFoundError = pFileNotFoundError;
+ return RS_RET_OK;
+}
+
+
+/* set the stream's file prefix
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it.
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal
+strmSetFName(strm_t *pThis, uchar *pszName, size_t iLenName)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pszName != NULL);
+
+ if(iLenName < 1)
+ ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING);
+
+ if(pThis->pszFName != NULL)
+ free(pThis->pszFName);
+
+ if((pThis->pszFName = malloc(iLenName + 1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ memcpy(pThis->pszFName, pszName, iLenName + 1); /* always think about the \0! */
+ pThis->lenFName = iLenName;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the stream's directory
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it.
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal
+strmSetDir(strm_t *pThis, uchar *pszDir, size_t iLenDir)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pszDir != NULL);
+
+ if(iLenDir < 1)
+ ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING);
+
+ CHKmalloc(pThis->pszDir = malloc(iLenDir + 1));
+
+ memcpy(pThis->pszDir, pszDir, iLenDir + 1); /* always think about the \0! */
+ pThis->lenDir = iLenDir;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* support for data records
+ * The stream class is able to write to multiple files. However, there are
+ * situation (actually quite common), where a single data record should not
+ * be split across files. This may be problematic if multiple stream write
+ * calls are used to create the record. To support that, we provide the
+ * bInRecord status variable. If it is set, no file spliting occurs. Once
+ * it is set to 0, a check is done if a split is necessary and it then
+ * happens. For a record-oriented caller, the proper sequence is:
+ *
+ * strmRecordBegin()
+ * strmWrite...()
+ * strmRecordEnd()
+ *
+ * Please note that records do not affect the writing of output buffers. They
+ * are always written when full. The only thing affected is circular files
+ * creation. So it is safe to write large records.
+ *
+ * IMPORTANT: RecordBegin() can not be nested! It is a programming error
+ * if RecordBegin() is called while already in a record!
+ *
+ * rgerhards, 2008-01-10
+ */
+static rsRetVal strmRecordBegin(strm_t *pThis)
+{
+ assert(pThis != NULL);
+ assert(pThis->bInRecord == 0);
+ pThis->bInRecord = 1;
+ return RS_RET_OK;
+}
+
+static rsRetVal strmRecordEnd(strm_t *pThis)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+ assert(pThis->bInRecord == 1);
+
+ pThis->bInRecord = 0;
+ iRet = strmCheckNextOutputFile(pThis); /* check if we need to switch files */
+
+ RETiRet;
+}
+/* end stream record support functions */
+
+
+/* This method serializes a stream object. That means the whole
+ * object is modified into text form. That text form is suitable for
+ * later reconstruction of the object.
+ * The most common use case for this method is the creation of an
+ * on-disk representation of the message object.
+ * We do not serialize the dynamic properties.
+ * rgerhards, 2008-01-10
+ */
+static rsRetVal strmSerialize(strm_t *pThis, strm_t *pStrm)
+{
+ DEFiRet;
+ int i;
+ int64 l;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ ISOBJ_TYPE_assert(pStrm, strm);
+
+ strmFlushInternal(pThis, 0);
+ CHKiRet(obj.BeginSerialize(pStrm, (obj_t*) pThis));
+
+ objSerializeSCALAR(pStrm, iCurrFNum, INT); /* implicit cast is OK for persistance */
+ objSerializePTR(pStrm, pszFName, PSZ);
+ objSerializeSCALAR(pStrm, iMaxFiles, INT);
+ objSerializeSCALAR(pStrm, bDeleteOnClose, INT);
+
+ i = pThis->sType;
+ objSerializeSCALAR_VAR(pStrm, sType, INT, i);
+
+ i = pThis->tOperationsMode;
+ objSerializeSCALAR_VAR(pStrm, tOperationsMode, INT, i);
+
+ i = pThis->tOpenMode;
+ objSerializeSCALAR_VAR(pStrm, tOpenMode, INT, i);
+
+ l = pThis->iCurrOffs;
+ objSerializeSCALAR_VAR(pStrm, iCurrOffs, INT64, l);
+
+ l = pThis->inode;
+ objSerializeSCALAR_VAR(pStrm, inode, INT64, l);
+
+ l = pThis->strtOffs;
+ objSerializeSCALAR_VAR(pStrm, strtOffs, INT64, l);
+
+ dbgprintf("strmSerialize: pThis->prevLineSegment %p\n", pThis->prevLineSegment);
+ if(pThis->prevLineSegment != NULL) {
+ cstrFinalize(pThis->prevLineSegment);
+ objSerializePTR(pStrm, prevLineSegment, CSTR);
+ }
+
+ if(pThis->prevMsgSegment != NULL) {
+ cstrFinalize(pThis->prevMsgSegment);
+ objSerializePTR(pStrm, prevMsgSegment, CSTR);
+ }
+
+ i = pThis->bPrevWasNL;
+ objSerializeSCALAR_VAR(pStrm, bPrevWasNL, INT, i);
+
+ CHKiRet(obj.EndSerialize(pStrm));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* duplicate a stream object excluding dynamic properties. This function is
+ * primarily meant to provide a duplicate that later on can be used to access
+ * the data. This is needed, for example, for a restart of the disk queue.
+ * Note that ConstructFinalize() is NOT called. So our caller may change some
+ * properties before finalizing things.
+ * rgerhards, 2009-05-26
+ */
+static rsRetVal
+strmDup(strm_t *const pThis, strm_t **ppNew)
+{
+ strm_t *pNew = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(ppNew != NULL);
+
+ CHKiRet(strmConstruct(&pNew));
+ pNew->sType = pThis->sType;
+ pNew->iCurrFNum = pThis->iCurrFNum;
+ CHKmalloc(pNew->pszFName = ustrdup(pThis->pszFName));
+ pNew->lenFName = pThis->lenFName;
+ CHKmalloc(pNew->pszDir = ustrdup(pThis->pszDir));
+ pNew->lenDir = pThis->lenDir;
+ pNew->tOperationsMode = pThis->tOperationsMode;
+ pNew->tOpenMode = pThis->tOpenMode;
+ pNew->compressionDriver = pThis->compressionDriver;
+ pNew->iMaxFileSize = pThis->iMaxFileSize;
+ pNew->iMaxFiles = pThis->iMaxFiles;
+ pNew->iFileNumDigits = pThis->iFileNumDigits;
+ pNew->bDeleteOnClose = pThis->bDeleteOnClose;
+ pNew->iCurrOffs = pThis->iCurrOffs;
+
+ *ppNew = pNew;
+ pNew = NULL;
+
+finalize_it:
+ if(pNew != NULL)
+ strmDestruct(&pNew);
+
+ RETiRet;
+}
+
+
+static rsRetVal
+SetCompressionWorkers(strm_t *const pThis, int num_wrkrs)
+{
+ ISOBJ_TYPE_assert(pThis, strm);
+ if(num_wrkrs < 0)
+ num_wrkrs = 1;
+ pThis->zstd.num_wrkrs = num_wrkrs;
+ return RS_RET_OK;
+}
+
+
+/* set a user write-counter. This counter is initialized to zero and
+ * receives the number of bytes written. It is accurate only after a
+ * flush(). This hook is provided as a means to control disk size usage.
+ * The pointer must be valid at all times (so if it is on the stack, be sure
+ * to remove it when you exit the function). Pointers are removed by
+ * calling strmSetWCntr() with a NULL param. Only one pointer is settable,
+ * any new set overwrites the previous one.
+ * rgerhards, 2008-02-27
+ */
+static rsRetVal
+strmSetWCntr(strm_t *pThis, number_t *pWCnt)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+
+ if(pWCnt != NULL)
+ *pWCnt = 0;
+ pThis->pUsrWCntr = pWCnt;
+
+ RETiRet;
+}
+
+
+#include "stringbuf.h"
+
+/* This function can be used as a generic way to set properties.
+ * rgerhards, 2008-01-11
+ */
+#define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, UCHAR_CONSTANT(name), sizeof(name) - 1)
+static rsRetVal strmSetProperty(strm_t *pThis, var_t *pProp)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(pProp != NULL);
+
+ if(isProp("sType")) {
+ CHKiRet(strmSetsType(pThis, (strmType_t) pProp->val.num));
+ } else if(isProp("iCurrFNum")) {
+ pThis->iCurrFNum = (unsigned) pProp->val.num;
+ } else if(isProp("pszFName")) {
+ CHKiRet(strmSetFName(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)));
+ } else if(isProp("tOperationsMode")) {
+ CHKiRet(strmSettOperationsMode(pThis, pProp->val.num));
+ } else if(isProp("tOpenMode")) {
+ CHKiRet(strmSettOpenMode(pThis, pProp->val.num));
+ } else if(isProp("iCurrOffs")) {
+ pThis->iCurrOffs = pProp->val.num;
+ } else if(isProp("inode")) {
+ pThis->inode = (ino_t) pProp->val.num;
+ } else if(isProp("strtOffs")) {
+ pThis->strtOffs = pProp->val.num;
+ } else if(isProp("iMaxFileSize")) {
+ CHKiRet(strmSetiMaxFileSize(pThis, pProp->val.num));
+ } else if(isProp("fileNotFoundError")) {
+ CHKiRet(strmSetFileNotFoundError(pThis, pProp->val.num));
+ } else if(isProp("iMaxFiles")) {
+ CHKiRet(strmSetiMaxFiles(pThis, pProp->val.num));
+ } else if(isProp("iFileNumDigits")) {
+ CHKiRet(strmSetiFileNumDigits(pThis, pProp->val.num));
+ } else if(isProp("bDeleteOnClose")) {
+ CHKiRet(strmSetbDeleteOnClose(pThis, pProp->val.num));
+ } else if(isProp("prevLineSegment")) {
+ CHKiRet(rsCStrConstructFromCStr(&pThis->prevLineSegment, pProp->val.pStr));
+ } else if(isProp("prevMsgSegment")) {
+ CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, pProp->val.pStr));
+ } else if(isProp("bPrevWasNL")) {
+ pThis->bPrevWasNL = (sbool) pProp->val.num;
+ }
+
+finalize_it:
+ RETiRet;
+}
+#undef isProp
+
+
+/* return the current offset inside the stream. Note that on two consequtive calls, the offset
+ * reported on the second call may actually be lower than on the first call. This is due to
+ * file circulation. A caller must deal with that. -- rgerhards, 2008-01-30
+ */
+static rsRetVal
+strmGetCurrOffset(strm_t *pThis, int64 *pOffs)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(pOffs != NULL);
+
+ *pOffs = pThis->iCurrOffs;
+
+ RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(strm)
+CODESTARTobjQueryInterface(strm)
+ if(pIf->ifVersion != strmCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = strmConstruct;
+ pIf->ConstructFinalize = strmConstructFinalize;
+ pIf->Destruct = strmDestruct;
+ pIf->ReadChar = strmReadChar;
+ pIf->UnreadChar = strmUnreadChar;
+ pIf->ReadLine = strmReadLine;
+ pIf->SeekCurrOffs = strmSeekCurrOffs;
+ pIf->Write = strmWrite;
+ pIf->WriteChar = strmWriteChar;
+ pIf->WriteLong = strmWriteLong;
+ pIf->SetFName = strmSetFName;
+ pIf->SetFileNotFoundError = strmSetFileNotFoundError;
+ pIf->SetDir = strmSetDir;
+ pIf->Flush = strmFlush;
+ pIf->RecordBegin = strmRecordBegin;
+ pIf->RecordEnd = strmRecordEnd;
+ pIf->Serialize = strmSerialize;
+ pIf->GetCurrOffset = strmGetCurrOffset;
+ pIf->Dup = strmDup;
+ pIf->SetCompressionWorkers = SetCompressionWorkers;
+ pIf->SetWCntr = strmSetWCntr;
+ pIf->CheckFileChange = CheckFileChange;
+ /* set methods */
+ pIf->SetbDeleteOnClose = strmSetbDeleteOnClose;
+ pIf->SetiMaxFileSize = strmSetiMaxFileSize;
+ pIf->SetiMaxFiles = strmSetiMaxFiles;
+ pIf->SetiFileNumDigits = strmSetiFileNumDigits;
+ pIf->SettOperationsMode = strmSettOperationsMode;
+ pIf->SettOpenMode = strmSettOpenMode;
+ pIf->SetcompressionDriver = strmSetcompressionDriver;
+ pIf->SetsType = strmSetsType;
+ pIf->SetiZipLevel = strmSetiZipLevel;
+ pIf->SetbVeryReliableZip = strmSetbVeryReliableZip;
+ pIf->SetbSync = strmSetbSync;
+ pIf->SetbReopenOnTruncate = strmSetbReopenOnTruncate;
+ pIf->SetsIOBufSize = strmSetsIOBufSize;
+ pIf->SetiSizeLimit = strmSetiSizeLimit;
+ pIf->SetiFlushInterval = strmSetiFlushInterval;
+ pIf->SetpszSizeLimitCmd = strmSetpszSizeLimitCmd;
+ pIf->Setcryprov = strmSetcryprov;
+ pIf->SetcryprovData = strmSetcryprovData;
+finalize_it:
+ENDobjQueryInterface(strm)
+
+
+/* Initialize the stream class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-01-09
+ */
+BEGINObjClassInit(strm, 1, OBJ_IS_CORE_MODULE)
+ /* request objects we use */
+
+ OBJSetMethodHandler(objMethod_SERIALIZE, strmSerialize);
+ OBJSetMethodHandler(objMethod_SETPROPERTY, strmSetProperty);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, strmConstructFinalize);
+ENDObjClassInit(strm)
diff --git a/runtime/stream.h b/runtime/stream.h
new file mode 100644
index 0000000..38db1ab
--- /dev/null
+++ b/runtime/stream.h
@@ -0,0 +1,254 @@
+/* Definition of serial stream class (strm).
+ *
+ * A serial stream provides serial data access. In theory, serial streams
+ * can be implemented via a number of methods (e.g. files or in-memory
+ * streams). In practice, there currently only exist the file type (aka
+ * "driver").
+ *
+ * In practice, many stream features are bound to files. I have not yet made
+ * any serious effort, except for the naming of this class, to try to make
+ * the interfaces very generic. However, I assume that we could work much
+ * like in the strm class, where some properties are simply ignored when
+ * the wrong strm mode is selected (which would translate here to the wrong
+ * stream mode).
+ *
+ * Most importantly, this class provides generic input and output functions
+ * which can directly be used to work with the strms and file output. It
+ * provides such useful things like a circular file buffer and, hopefully
+ * at a later stage, a lazy writer. The object is also seriazable and thus
+ * can easily be persistet. The bottom line is that it makes much sense to
+ * use this class whereever possible as its features may grow in the future.
+ *
+ * An important note on writing gzip format via zlib (kept anonymous
+ * by request):
+ *
+ * --------------------------------------------------------------------------
+ * We'd like to make sure the output file is in full gzip format
+ * (compatible with gzip -d/zcat etc). There is a flag in how the output
+ * is initialized within zlib to properly add the gzip wrappers to the
+ * output. (gzip is effectively a small metadata wrapper around raw
+ * zstream output.)
+ *
+ * I had written an old bit of code to do this - the documentation on
+ * deflatInit2() was pretty tricky to nail down on this specific feature:
+ *
+ * int deflateInit2 (z_streamp strm, int level, int method, int windowBits,
+ * int memLevel, int strategy);
+ *
+ * I believe "31" would be the value for the "windowBits" field that you'd
+ * want to try:
+ *
+ * deflateInit2(zstrmptr, 6, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY);
+ * --------------------------------------------------------------------------
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#ifndef STREAM_H_INCLUDED
+#define STREAM_H_INCLUDED
+
+typedef struct strm_s strm_t; /* forward reference because of zlib... */
+
+#include <regex.h> // TODO: fix via own module
+#include <pthread.h>
+#include <stdint.h>
+#include <time.h>
+#include "obj-types.h"
+#include "glbl.h"
+#include "stream.h"
+#include "zlibw.h"
+#include "cryprov.h"
+
+/* stream types */
+typedef enum {
+ STREAMTYPE_FILE_SINGLE = 0, /**< read a single file */
+ STREAMTYPE_FILE_CIRCULAR = 1, /**< circular files */
+ STREAMTYPE_FILE_MONITOR = 2, /**< monitor a (third-party) file */
+ STREAMTYPE_NAMED_PIPE = 3 /**< file is a named pipe (so far, tested for output only) */
+} strmType_t;
+
+typedef enum { /* when extending, do NOT change existing modes! */
+ STREAMMMODE_INVALID = 0,
+ STREAMMODE_READ = 1,
+ STREAMMODE_WRITE = 2,
+ STREAMMODE_WRITE_TRUNC = 3,
+ STREAMMODE_WRITE_APPEND = 4
+} strmMode_t;
+typedef enum {
+ STRM_COMPRESS_ZIP = 0,
+ STRM_COMPRESS_ZSTD = 1
+ } strm_compressionDriver_t;
+
+#define STREAM_ASYNC_NUMBUFS 2 /* must be a power of 2 -- TODO: make configurable */
+/* The strm_t data structure */
+struct strm_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ strmType_t sType;
+ /* descriptive properties */
+ unsigned int iCurrFNum;/* current file number (NOT descriptor, but the number in the file name!) */
+ uchar *pszFName; /* prefix for generated filenames */
+ int lenFName;
+ strmMode_t tOperationsMode;
+ mode_t tOpenMode;
+ int64 iMaxFileSize;/* maximum size a file may grow to */
+ unsigned int iMaxFiles; /* maximum number of files if a circular mode is in use */
+ int iFileNumDigits;/* min number of digits to use in file number (only in circular mode) */
+ sbool bDeleteOnClose; /* set to 1 to auto-delete on close -- be careful with that setting! */
+ int64 iCurrOffs;/* current offset */
+ int64 *pUsrWCntr; /* NULL or a user-provided counter that receives the nbr of bytes written since
+ the last CntrSet() */
+ sbool bPrevWasNL; /* used for readLine() when reading multi-line messages */
+ /* dynamic properties, valid only during file open, not to be persistet */
+ sbool bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */
+ sbool bSync; /* sync this file after every write? */
+ sbool bReopenOnTruncate;
+ int rotationCheck; /* rotation check mode */
+ size_t sIOBufSize;/* size of IO buffer */
+ uchar *pszDir; /* Directory */
+ int lenDir;
+ int fd; /* the file descriptor, -1 if closed */
+ int fdDir; /* the directory's descriptor, in case bSync is requested (-1 if closed) */
+ int readTimeout;/* 0: do not timeout */
+ time_t lastRead;/* for timeout processing */
+ ino_t inode; /* current inode for files being monitored (undefined else) */
+ uchar *pszCurrFName; /* name of current file (if open) */
+ uchar *pIOBuf; /* the iobuffer currently in use to gather data */
+ char *pIOBuf_truncation; /* iobuffer used during trucation detection block re-reads */
+ size_t iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */
+ size_t iBufPtr; /* pointer into current buffer */
+ int iUngetC; /* char set via UngetChar() call or -1 if none set */
+ sbool bInRecord; /* if 1, indicates that we are currently writing a not-yet complete record */
+ int iZipLevel; /* zip level (0..9). If 0, zip is completely disabled */
+ Bytef *pZipBuf;
+ /* support for async flush procesing */
+ sbool bAsyncWrite; /* do asynchronous writes (always if a flush interval is given) */
+ sbool bStopWriter; /* shall writer thread terminate? */
+ sbool bDoTimedWait; /* instruct writer thread to do a times wait to support flush timeouts */
+ sbool bzInitDone; /* did we do an init of zstrm already? */
+ sbool bFlushNow; /* shall we flush with the next async write? */
+ sbool bVeryReliableZip; /* shall we write interim headers to create a very reliable ZIP file? */
+ int iFlushInterval; /* flush in which interval - 0, no flushing */
+ pthread_mutex_t mut;/* mutex for flush in async mode */
+ pthread_cond_t notFull;
+ pthread_cond_t notEmpty;
+ pthread_cond_t isEmpty;
+ unsigned short iEnq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
+ unsigned short iDeq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
+ cryprov_if_t *cryprov; /* ptr to crypto provider; NULL = do not encrypt */
+ void *cryprovData; /* opaque data ptr for provider use */
+ void *cryprovFileData;/* opaque data ptr for file instance */
+ short iCnt; /* current nbr of elements in buffer */
+ z_stream zstrm; /* zip stream to use */
+ struct {
+ uchar *pBuf;
+ size_t lenBuf;
+ } asyncBuf[STREAM_ASYNC_NUMBUFS];
+ struct {
+ int num_wrkrs; /* nbr of worker threads */
+ void *cctx;
+ } zstd; /* supporting per-instance data if zstd is used */
+ pthread_t writerThreadID;
+ /* support for omfile size-limiting commands, special counters, NOT persisted! */
+ off_t iSizeLimit; /* file size limit, 0 = no limit */
+ uchar *pszSizeLimitCmd; /* command to carry out when size limit is reached */
+ sbool bIsTTY; /* is this a tty file? */
+ cstr_t *prevLineSegment; /* for ReadLine, previous, unprocessed part of file */
+ cstr_t *prevMsgSegment; /* for ReadMultiLine, previous, yet unprocessed part of msg */
+ int64 strtOffs; /* start offset in file for current line/msg */
+ int fileNotFoundError; /* boolean; if set, report file not found errors, else silently ignore */
+ int noRepeatedErrorOutput; /* if a file is missing the Error is only given once */
+ int ignoringMsg;
+ strm_compressionDriver_t compressionDriver;
+};
+
+
+/* interfaces */
+BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(strm_t **ppThis);
+ rsRetVal (*ConstructFinalize)(strm_t *pThis);
+ rsRetVal (*Destruct)(strm_t **ppThis);
+ rsRetVal (*SetFileName)(strm_t *pThis, uchar *pszName, size_t iLenName);
+ rsRetVal (*ReadChar)(strm_t *pThis, uchar *pC);
+ rsRetVal (*UnreadChar)(strm_t *pThis, uchar c);
+ rsRetVal (*SeekCurrOffs)(strm_t *pThis);
+ rsRetVal (*Write)(strm_t *const pThis, const uchar *const pBuf, size_t lenBuf);
+ rsRetVal (*WriteChar)(strm_t *pThis, uchar c);
+ rsRetVal (*WriteLong)(strm_t *pThis, long i);
+ rsRetVal (*SetFileNotFoundError)(strm_t *pThis, int pFileNotFoundError);
+ rsRetVal (*SetFName)(strm_t *pThis, uchar *pszPrefix, size_t iLenPrefix);
+ rsRetVal (*SetDir)(strm_t *pThis, uchar *pszDir, size_t iLenDir);
+ rsRetVal (*Flush)(strm_t *pThis);
+ rsRetVal (*RecordBegin)(strm_t *pThis);
+ rsRetVal (*RecordEnd)(strm_t *pThis);
+ rsRetVal (*Serialize)(strm_t *pThis, strm_t *pStrm);
+ rsRetVal (*GetCurrOffset)(strm_t *pThis, int64 *pOffs);
+ rsRetVal (*SetWCntr)(strm_t *pThis, number_t *pWCnt);
+ rsRetVal (*Dup)(strm_t *pThis, strm_t **ppNew);
+ rsRetVal (*SetCompressionWorkers)(strm_t *const pThis, int num_wrkrs);
+ INTERFACEpropSetMeth(strm, bDeleteOnClose, int);
+ INTERFACEpropSetMeth(strm, iMaxFileSize, int64);
+ INTERFACEpropSetMeth(strm, iMaxFiles, int);
+ INTERFACEpropSetMeth(strm, iFileNumDigits, int);
+ INTERFACEpropSetMeth(strm, tOperationsMode, int);
+ INTERFACEpropSetMeth(strm, tOpenMode, mode_t);
+ INTERFACEpropSetMeth(strm, compressionDriver, strm_compressionDriver_t);
+ INTERFACEpropSetMeth(strm, sType, strmType_t);
+ INTERFACEpropSetMeth(strm, iZipLevel, int);
+ INTERFACEpropSetMeth(strm, bSync, int);
+ INTERFACEpropSetMeth(strm, bReopenOnTruncate, int);
+ INTERFACEpropSetMeth(strm, sIOBufSize, size_t);
+ INTERFACEpropSetMeth(strm, iSizeLimit, off_t);
+ INTERFACEpropSetMeth(strm, iFlushInterval, int);
+ INTERFACEpropSetMeth(strm, pszSizeLimitCmd, uchar*);
+ /* v6 added */
+ rsRetVal (*ReadLine)(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF, const uchar *,
+ uint32_t trimLineOverBytes, int64 *const strtOffs);
+ /* v7 added 2012-09-14 */
+ INTERFACEpropSetMeth(strm, bVeryReliableZip, int);
+ /* v8 added 2013-03-21 */
+ rsRetVal (*CheckFileChange)(strm_t *pThis);
+ /* v9 added 2013-04-04 */
+ INTERFACEpropSetMeth(strm, cryprov, cryprov_if_t*);
+ INTERFACEpropSetMeth(strm, cryprovData, void*);
+ENDinterface(strm)
+#define strmCURR_IF_VERSION 14 /* increment whenever you change the interface structure! */
+/* V10, 2013-09-10: added new parameter bEscapeLF, changed mode to uint8_t (rgerhards) */
+/* V11, 2015-12-03: added new parameter bReopenOnTruncate */
+/* V12, 2015-12-11: added new parameter trimLineOverBytes, changed mode to uint32_t */
+/* V13, 2017-09-06: added new parameter strtoffs to ReadLine() */
+/* V14, 2019-11-13: added new parameter bEscapeLFString (rgerhards) */
+
+#define strmGetCurrFileNum(pStrm) ((pStrm)->iCurrFNum)
+
+/* prototypes */
+PROTOTYPEObjClassInit(strm);
+rsRetVal strmMultiFileSeek(strm_t *pThis, unsigned int fileNum, off64_t offs, off64_t *bytesDel);
+rsRetVal ATTR_NONNULL(1,2) strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg,
+ regex_t *end_preg, const sbool bEscapeLF, const uchar *const escapeLFString,
+ const sbool discardTruncatedMsg, const sbool msgDiscardingError, int64 *const strtOffs);
+int strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis);
+void strmDebugOutBuf(const strm_t *const pThis);
+void strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val);
+const uchar * ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis);
+const uchar * ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis);
+int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis);
+
+#endif /* #ifndef STREAM_H_INCLUDED */
diff --git a/runtime/strgen.c b/runtime/strgen.c
new file mode 100644
index 0000000..89381cb
--- /dev/null
+++ b/runtime/strgen.c
@@ -0,0 +1,278 @@
+/* strgen.c
+ * Module to handle string generators. These are C modules that receive
+ * the message object and return a custom-built string. The primary purpose
+ * for their existence is performance -- they do the same as template strings, but
+ * potentially faster (if well implmented).
+ *
+ * Module begun 2010-06-01 by Rainer Gerhards
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "msg.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "strgen.h"
+#include "ruleset.h"
+#include "unicode-helper.h"
+#include "cfsysline.h"
+
+/* definitions for objects we access */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(ruleset)
+
+/* static data */
+
+/* config data */
+
+/* This is the list of all strgens known to us.
+ * This is also used to unload all modules on shutdown.
+ */
+strgenList_t *pStrgenLstRoot = NULL;
+
+
+/* intialize (but NOT allocate) a strgen list. Primarily meant as a hook
+ * which can be used to extend the list in the future. So far, just sets
+ * it to NULL.
+ */
+static rsRetVal
+InitStrgenList(strgenList_t **pListRoot)
+{
+ *pListRoot = NULL;
+ return RS_RET_OK;
+}
+
+
+/* destruct a strgen list. The list elements are destroyed, but the strgen objects
+ * themselves are not modified. (That is done at a late stage during rsyslogd
+ * shutdown and need not be considered here.)
+ */
+static rsRetVal
+DestructStrgenList(strgenList_t **ppListRoot)
+{
+ strgenList_t *pStrgenLst;
+ strgenList_t *pStrgenLstDel;
+
+ pStrgenLst = *ppListRoot;
+ while(pStrgenLst != NULL) {
+ pStrgenLstDel = pStrgenLst;
+ pStrgenLst = pStrgenLst->pNext;
+ free(pStrgenLstDel);
+ }
+ *ppListRoot = NULL;
+ return RS_RET_OK;
+}
+
+
+/* Add a strgen to the list. We use a VERY simple and ineffcient algorithm,
+ * but it is employed only for a few milliseconds during config processing. So
+ * I prefer to keep it very simple and with simple data structures. Unfortunately,
+ * we need to preserve the order, but I don't like to add a tail pointer as that
+ * would require a container object. So I do the extra work to skip to the tail
+ * when adding elements...
+ */
+static rsRetVal
+AddStrgenToList(strgenList_t **ppListRoot, strgen_t *pStrgen)
+{
+ strgenList_t *pThis;
+ strgenList_t *pTail;
+ DEFiRet;
+
+ CHKmalloc(pThis = malloc(sizeof(strgenList_t)));
+ pThis->pStrgen = pStrgen;
+ pThis->pNext = NULL;
+
+ if(*ppListRoot == NULL) {
+ pThis->pNext = *ppListRoot;
+ *ppListRoot = pThis;
+ } else {
+ /* find tail first */
+ for(pTail = *ppListRoot ; pTail->pNext != NULL ; pTail = pTail->pNext)
+ /* just search, do nothing else */;
+ /* add at tail */
+ pTail->pNext = pThis;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* find a strgen based on the provided name */
+static rsRetVal
+FindStrgen(strgen_t **ppStrgen, uchar *pName)
+{
+ strgenList_t *pThis;
+ DEFiRet;
+
+ for(pThis = pStrgenLstRoot ; pThis != NULL ; pThis = pThis->pNext) {
+ if(ustrcmp(pThis->pStrgen->pName, pName) == 0) {
+ *ppStrgen = pThis->pStrgen;
+ FINALIZE; /* found it, iRet still eq. OK! */
+ }
+ }
+
+ iRet = RS_RET_PARSER_NOT_FOUND;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* --- END helper functions for strgen list handling --- */
+
+
+BEGINobjConstruct(strgen) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(strgen)
+
+/* ConstructionFinalizer. The most important chore is to add the strgen object
+ * to our global list of available strgens.
+ * rgerhards, 2009-11-03
+ */
+static rsRetVal
+strgenConstructFinalize(strgen_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strgen);
+ CHKiRet(AddStrgenToList(&pStrgenLstRoot, pThis));
+ DBGPRINTF("Strgen '%s' added to list of available strgens.\n", pThis->pName);
+
+finalize_it:
+ RETiRet;
+}
+
+PROTOTYPEobjDestruct(strgen);
+BEGINobjDestruct(strgen) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(strgen)
+ dbgprintf("destructing strgen '%s'\n", pThis->pName);
+ free(pThis->pName);
+ENDobjDestruct(strgen)
+
+/* set the strgen name - string is copied over, call can continue to use it,
+ * but must free it if desired.
+ */
+static rsRetVal
+SetName(strgen_t *pThis, uchar *name)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strgen);
+ assert(name != NULL);
+
+ if(pThis->pName != NULL) {
+ free(pThis->pName);
+ pThis->pName = NULL;
+ }
+
+ CHKmalloc(pThis->pName = ustrdup(name));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set a pointer to "our" module. Note that no module
+ * pointer must already be set.
+ */
+static rsRetVal
+SetModPtr(strgen_t *pThis, modInfo_t *pMod)
+{
+ ISOBJ_TYPE_assert(pThis, strgen);
+ assert(pMod != NULL);
+ assert(pThis->pModule == NULL);
+ pThis->pModule = pMod;
+ return RS_RET_OK;
+}
+
+
+/* queryInterface function-- rgerhards, 2009-11-03
+ */
+BEGINobjQueryInterface(strgen)
+CODESTARTobjQueryInterface(strgen)
+ if(pIf->ifVersion != strgenCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = strgenConstruct;
+ pIf->ConstructFinalize = strgenConstructFinalize;
+ pIf->Destruct = strgenDestruct;
+ pIf->SetName = SetName;
+ pIf->SetModPtr = SetModPtr;
+ pIf->InitStrgenList = InitStrgenList;
+ pIf->DestructStrgenList = DestructStrgenList;
+ pIf->AddStrgenToList = AddStrgenToList;
+ pIf->FindStrgen = FindStrgen;
+finalize_it:
+ENDobjQueryInterface(strgen)
+
+
+/* This destroys the master strgenlist and all of its strgen entries. MUST only be
+ * done when the module is shut down. Strgen modules are NOT unloaded, rsyslog
+ * does that at a later stage for all dynamically loaded modules.
+ */
+static void
+destroyMasterStrgenList(void)
+{
+ strgenList_t *pStrgenLst;
+ strgenList_t *pStrgenLstDel;
+
+ pStrgenLst = pStrgenLstRoot;
+ while(pStrgenLst != NULL) {
+ strgenDestruct(&pStrgenLst->pStrgen);
+ pStrgenLstDel = pStrgenLst;
+ pStrgenLst = pStrgenLst->pNext;
+ free(pStrgenLstDel);
+ }
+}
+
+/* Exit our class.
+ * rgerhards, 2009-11-04
+ */
+BEGINObjClassExit(strgen, OBJ_IS_CORE_MODULE) /* class, version */
+ destroyMasterStrgenList();
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDObjClassExit(strgen)
+
+
+/* Initialize the strgen class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2009-11-02
+ */
+BEGINObjClassInit(strgen, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ InitStrgenList(&pStrgenLstRoot);
+ENDObjClassInit(strgen)
+
diff --git a/runtime/strgen.h b/runtime/strgen.h
new file mode 100644
index 0000000..3819dcc
--- /dev/null
+++ b/runtime/strgen.h
@@ -0,0 +1,60 @@
+/* header for strgen.c
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef INCLUDED_STRGEN_H
+#define INCLUDED_STRGEN_H
+
+
+/* we create a small helper object, a list of strgens, that we can use to
+ * build a chain of them whereever this is needed.
+ */
+struct strgenList_s {
+ strgen_t *pStrgen;
+ strgenList_t *pNext;
+};
+
+
+/* the strgen object, a dummy because we have only static methods */
+struct strgen_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ uchar *pName; /* name of this strgen */
+ modInfo_t *pModule; /* pointer to strgen's module */
+};
+
+/* interfaces */
+BEGINinterface(strgen) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(strgen_t **ppThis);
+ rsRetVal (*ConstructFinalize)(strgen_t *pThis);
+ rsRetVal (*Destruct)(strgen_t **ppThis);
+ rsRetVal (*SetName)(strgen_t *pThis, uchar *name);
+ rsRetVal (*SetModPtr)(strgen_t *pThis, modInfo_t *pMod);
+ rsRetVal (*FindStrgen)(strgen_t **ppThis, uchar*name);
+ rsRetVal (*InitStrgenList)(strgenList_t **pListRoot);
+ rsRetVal (*DestructStrgenList)(strgenList_t **pListRoot);
+ rsRetVal (*AddStrgenToList)(strgenList_t **pListRoot, strgen_t *pStrgen);
+ENDinterface(strgen)
+#define strgenCURR_IF_VERSION 1 /* increment whenever you change the interface above! */
+
+
+/* prototypes */
+PROTOTYPEObj(strgen);
+
+#endif /* #ifndef INCLUDED_STRGEN_H */
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
new file mode 100644
index 0000000..ea39b7c
--- /dev/null
+++ b/runtime/stringbuf.c
@@ -0,0 +1,777 @@
+/* This is the byte-counted string class for rsyslog.
+ * This object has a lot of legacy. Among others, it was started to
+ * support embedded \0 bytes, which looked like they were needed to
+ * be supported by RFC developments at that time. Later, this was
+ * no longer a requirement, and we refactored the class in 2016
+ * to some simpler internals which make use of the fact that no
+ * NUL can ever occur in rsyslog strings (they are escaped at the
+ * input side of rsyslog).
+ * It now serves primarily to a) dynamic string creation, b) keep
+ * old interfaces supported, and c) some special functionality,
+ * e.g. search. Further refactoring and simplificytin may make
+ * sense.
+ *
+ * Copyright (C) 2005-2019 Adiscon GmbH
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <libestr.h>
+#include "rsyslog.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "regexp.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+
+#define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */
+
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+/* static data */
+DEFobjCurrIf(obj)
+DEFobjCurrIf(regexp)
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+
+rsRetVal
+cstrConstruct(cstr_t **const ppThis)
+{
+ DEFiRet;
+ cstr_t *pThis;
+
+ CHKmalloc(pThis = (cstr_t*) malloc(sizeof(cstr_t)));
+ rsSETOBJTYPE(pThis, OIDrsCStr);
+ #ifndef NDEBUG
+ pThis->isFinalized = 0;
+ #endif
+ pThis->pBuf = NULL;
+ pThis->iBufSize = 0;
+ pThis->iStrLen = 0;
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* construct from sz string
+ * rgerhards 2005-09-15
+ */
+rsRetVal
+rsCStrConstructFromszStr(cstr_t **const ppThis, const uchar *const sz)
+{
+ DEFiRet;
+ cstr_t *pThis;
+
+ CHKiRet(rsCStrConstruct(&pThis));
+
+ pThis->iStrLen = strlen((char *) sz);
+ pThis->iBufSize = strlen((char *) sz) + 1;
+ if((pThis->pBuf = (uchar*) malloc(pThis->iBufSize)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* we do NOT need to copy the \0! */
+ memcpy(pThis->pBuf, sz, pThis->iStrLen);
+
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* a helper function for rsCStr*Strf()
+ */
+static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, const char *fmt,
+va_list ap) __attribute__((format(printf,2, 0)));
+static rsRetVal
+rsCStrConstructFromszStrv(cstr_t **const ppThis, const char *const fmt, va_list ap)
+{
+ DEFiRet;
+ cstr_t *pThis;
+ va_list ap2;
+ int len;
+
+ va_copy(ap2, ap);
+ len = vsnprintf(NULL, 0, (char*)fmt, ap2);
+ va_end(ap2);
+
+ if(len < 0)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ CHKiRet(rsCStrConstruct(&pThis));
+
+ pThis->iStrLen = len;
+ pThis->iBufSize = len + 1;
+ len++; /* account for the \0 written by vsnprintf */
+ if((pThis->pBuf = (uchar*) malloc(pThis->iBufSize)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ vsnprintf((char*)pThis->pBuf, len, (char*)fmt, ap);
+ *ppThis = pThis;
+finalize_it:
+ RETiRet;
+}
+
+
+/* construct from a printf-style formated string
+ */
+rsRetVal
+rsCStrConstructFromszStrf(cstr_t **ppThis, const char *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+
+ va_start(ap, fmt);
+ iRet = rsCStrConstructFromszStrv(ppThis, fmt, ap);
+ va_end(ap);
+
+ RETiRet;
+}
+
+
+/* construct from es_str_t string
+ * rgerhards 2010-12-03
+ */
+rsRetVal
+cstrConstructFromESStr(cstr_t **const ppThis, es_str_t *const str)
+{
+ DEFiRet;
+ cstr_t *pThis;
+
+ CHKiRet(rsCStrConstruct(&pThis));
+
+ pThis->iStrLen = es_strlen(str);
+ pThis->iBufSize = pThis->iStrLen + 1;
+ if((pThis->pBuf = (uchar*) malloc(pThis->iBufSize)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* we do NOT need to copy the \0! */
+ memcpy(pThis->pBuf, es_getBufAddr(str), pThis->iStrLen);
+
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+/* construct from CStr object.
+ * rgerhards 2005-10-18
+ */
+rsRetVal ATTR_NONNULL()
+rsCStrConstructFromCStr(cstr_t **const ppThis, const cstr_t *const pFrom)
+{
+ DEFiRet;
+ cstr_t *pThis;
+
+ rsCHECKVALIDOBJECT(pFrom, OIDrsCStr);
+
+ CHKiRet(rsCStrConstruct(&pThis));
+ if(pFrom->iStrLen > 0) {
+ pThis->iStrLen = pFrom->iStrLen;
+ pThis->iBufSize = pFrom->iStrLen + 1;
+ if((pThis->pBuf = (uchar*) malloc(pThis->iBufSize)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen);
+ }
+
+ *ppThis = pThis;
+finalize_it:
+ RETiRet;
+}
+
+
+void rsCStrDestruct(cstr_t **const ppThis)
+{
+ free((*ppThis)->pBuf);
+ RSFREEOBJ(*ppThis);
+ *ppThis = NULL;
+}
+
+
+/* extend the string buffer if its size is insufficient.
+ * Param iMinNeeded is the minumum free space needed. If it is larger
+ * than the default alloc increment, space for at least this amount is
+ * allocated. In practice, a bit more is allocated because we envision that
+ * some more characters may be added after these.
+ * rgerhards, 2008-01-07
+ * changed to utilized realloc() -- rgerhards, 2009-06-16
+ */
+static rsRetVal
+rsCStrExtendBuf(cstr_t *const __restrict__ pThis, const size_t iMinNeeded)
+{
+ uchar *pNewBuf;
+ size_t iNewSize;
+ DEFiRet;
+
+ /* first compute the new size needed */
+ if(iMinNeeded > RS_STRINGBUF_ALLOC_INCREMENT) {
+ /* we allocate "n" ALLOC_INCREMENTs. Usually, that should
+ * leave some room after the absolutely needed one. It also
+ * reduces memory fragmentation. Note that all of this are
+ * integer operations (very important to understand what is
+ * going on)! Parenthesis are for better readibility.
+ */
+ iNewSize = (iMinNeeded / RS_STRINGBUF_ALLOC_INCREMENT + 1) * RS_STRINGBUF_ALLOC_INCREMENT;
+ } else {
+ iNewSize = pThis->iBufSize + RS_STRINGBUF_ALLOC_INCREMENT;
+ }
+ iNewSize += pThis->iBufSize; /* add current size */
+
+ #if DEV_DEBUG == 1
+ dbgprintf("extending string buffer, old %d, new %d\n", pThis->iBufSize, iNewSize);
+ #endif
+ CHKmalloc(pNewBuf = (uchar*) realloc(pThis->pBuf, iNewSize));
+ pThis->iBufSize = iNewSize;
+ pThis->pBuf = pNewBuf;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Append a character to the current string object. This may only be done until
+ * cstrFinalize() is called.
+ * rgerhards, 2009-06-16
+ */
+rsRetVal cstrAppendChar(cstr_t *const __restrict__ pThis, const uchar c)
+{
+ rsRetVal iRet = RS_RET_OK;
+
+ if(pThis->iStrLen+1 >= pThis->iBufSize) {
+ CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */
+ }
+
+ /* ok, when we reach this, we have sufficient memory */
+ *(pThis->pBuf + pThis->iStrLen++) = c;
+
+finalize_it:
+ return iRet;
+}
+
+/* append a string of known length. In this case, we make sure we do at most
+ * one additional memory allocation.
+ */
+rsRetVal rsCStrAppendStrWithLen(cstr_t *const pThis, const uchar*const psz, const size_t iStrLen)
+{
+ DEFiRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(psz != NULL);
+
+ /* does the string fit? */
+ if(pThis->iStrLen + iStrLen >= pThis->iBufSize) {
+ CHKiRet(rsCStrExtendBuf(pThis, iStrLen)); /* need more memory! */
+ }
+
+ /* ok, now we always have sufficient continues memory to do a memcpy() */
+ memcpy(pThis->pBuf + pThis->iStrLen, psz, iStrLen);
+ pThis->iStrLen += iStrLen;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* changed to be a wrapper to rsCStrAppendStrWithLen() so that
+ * we can save some time when we have the length but do not
+ * need to change existing code.
+ * rgerhards, 2007-07-03
+ */
+rsRetVal rsCStrAppendStr(cstr_t *const pThis, const uchar*const psz)
+{
+ return rsCStrAppendStrWithLen(pThis, psz, strlen((char*) psz));
+}
+
+
+/* append the contents of one cstr_t object to another
+ * rgerhards, 2008-02-25
+ */
+rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend)
+{
+ return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen);
+}
+
+
+/* append a printf-style formated string
+ */
+rsRetVal rsCStrAppendStrf(cstr_t *pThis, const char *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+ cstr_t *pStr = NULL;
+
+ va_start(ap, fmt);
+ iRet = rsCStrConstructFromszStrv(&pStr, (char*)fmt, ap);
+ va_end(ap);
+
+ if(iRet != RS_RET_OK)
+ goto finalize_it;
+
+ iRet = cstrAppendCStr(pThis, pStr);
+ rsCStrDestruct(&pStr);
+finalize_it:
+ RETiRet;
+}
+
+
+rsRetVal rsCStrAppendInt(cstr_t *pThis, long i)
+{
+ DEFiRet;
+ uchar szBuf[32];
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), i));
+
+ iRet = rsCStrAppendStr(pThis, szBuf);
+finalize_it:
+ RETiRet;
+}
+
+
+/* Sets the string object to the classigal sz-string provided.
+ * Any previously stored vlaue is discarded. If a NULL pointer
+ * the the new value (pszNew) is provided, an empty string is
+ * created (this is NOT an error!).
+ * rgerhards, 2005-10-18
+ */
+rsRetVal rsCStrSetSzStr(cstr_t *const __restrict__ pThis,
+ uchar *const __restrict__ pszNew)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pszNew == NULL) {
+ free(pThis->pBuf);
+ pThis->pBuf = NULL;
+ pThis->iStrLen = 0;
+ pThis->iBufSize = 0;
+ } else {
+ const size_t newlen = strlen((char*)pszNew);
+ if(newlen > pThis->iBufSize) {
+ uchar *const newbuf = (uchar*) realloc(pThis->pBuf, newlen + 1);
+ if(newbuf == NULL) {
+ /* we keep the old value, best we can do */
+ return RS_RET_OUT_OF_MEMORY;
+ }
+ pThis->pBuf = newbuf;
+ pThis->iBufSize = newlen + 1;
+ }
+ pThis->iStrLen = newlen;
+ memcpy(pThis->pBuf, pszNew, pThis->iStrLen);
+ }
+
+ return RS_RET_OK;
+}
+
+/* Converts the CStr object to a classical zero-terminated C string
+ * and returns that string. The caller must not free it and must not
+ * destroy the CStr object as long as the ascii string is used.
+ */
+uchar*
+cstrGetSzStrNoNULL(cstr_t *const __restrict__ pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(pThis->isFinalized);
+ return (pThis->pBuf == NULL) ? (uchar*) "" : pThis->pBuf;
+}
+
+
+/* Converts the CStr object to a classical zero-terminated C string,
+ * returns that string and destroys the CStr object. The returned string
+ * MUST be freed by the caller. The function might return NULL if
+ * no memory can be allocated.
+ *
+ * This is the NEW replacement for rsCStrConvSzStrAndDestruct which does
+ * no longer utilize a special buffer but soley works on pBuf (and also
+ * assumes that cstrFinalize had been called).
+ *
+ * Parameters are as follows:
+ * pointer to the object, pointer to string-pointer to receive string and
+ * bRetNULL: 0 - must not return NULL on empty string, return "" in that
+ * case, 1 - return NULL instead of an empty string.
+ * PLEASE NOTE: the caller must free the memory returned in ppSz in any case
+ * (except, of course, if it is NULL).
+ */
+rsRetVal cstrConvSzStrAndDestruct(cstr_t **ppThis, uchar **ppSz, int bRetNULL)
+{
+ DEFiRet;
+ uchar* pRetBuf;
+ cstr_t *pThis;
+
+ assert(ppThis != NULL);
+ pThis = *ppThis;
+ assert(pThis->isFinalized);
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(ppSz != NULL);
+ assert(bRetNULL == 0 || bRetNULL == 1);
+
+ if(pThis->pBuf == NULL) {
+ if(bRetNULL == 0) {
+ CHKmalloc(pRetBuf = malloc(1));
+ *pRetBuf = '\0';
+ } else {
+ pRetBuf = NULL;
+ }
+ } else {
+ pThis->pBuf[pThis->iStrLen] = '\0'; /* space for this is reserved */
+ pRetBuf = pThis->pBuf;
+ }
+
+ *ppSz = pRetBuf;
+
+finalize_it:
+ /* We got it, now free the object ourselfs. Please note
+ * that we can NOT use the rsCStrDestruct function as it would
+ * also free the sz String buffer, which we pass on to the user.
+ */
+ RSFREEOBJ(pThis);
+ *ppThis = NULL;
+
+ RETiRet;
+}
+
+
+/* return the length of the current string
+ * 2005-09-09 rgerhards
+ * Please note: this is only a function in a debug build.
+ * For release builds, it is a macro defined in stringbuf.h.
+ * This is due to performance reasons.
+ */
+#ifndef NDEBUG
+size_t cstrLen(cstr_t *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ return(pThis->iStrLen);
+}
+#endif
+
+/* Truncate characters from the end of the string.
+ * rgerhards 2005-09-15
+ */
+rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->iStrLen < nTrunc)
+ return RS_TRUNCAT_TOO_LARGE;
+
+ pThis->iStrLen -= nTrunc;
+
+ return RS_RET_OK;
+}
+
+/* Trim trailing whitespace from a given string
+ */
+void
+cstrTrimTrailingWhiteSpace(cstr_t *const __restrict__ pThis)
+{
+ register int i;
+ register uchar *pC;
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->iStrLen == 0)
+ goto done; /* empty string -> nothing to trim ;) */
+ i = pThis->iStrLen;
+ pC = pThis->pBuf + i - 1;
+ while(i > 0 && isspace((int)*pC)) {
+ --pC;
+ --i;
+ }
+ /* i now is the new string length! */
+ if(i != (int) pThis->iStrLen) {
+ pThis->iStrLen = i;
+ pThis->pBuf[pThis->iStrLen] = '\0'; /* we always have this space */ //TODO: can we remove this?
+ }
+
+done: return;
+}
+
+/* compare two string objects - works like strcmp(), but operates
+ * on CStr objects. Please note that this version here is
+ * faster in the majority of cases, simply because it can
+ * rely on StrLen.
+ * rgerhards 2005-09-19
+ * fixed bug, in which only the last byte was actually compared
+ * in equal-size strings.
+ * rgerhards, 2005-09-26
+ */
+int
+rsCStrCStrCmp(cstr_t *const __restrict__ pCS1, cstr_t *const __restrict__ pCS2)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ rsCHECKVALIDOBJECT(pCS2, OIDrsCStr);
+ if(pCS1->iStrLen == pCS2->iStrLen)
+ if(pCS1->iStrLen == 0)
+ return 0; /* zero-sized string are equal ;) */
+ else
+ return memcmp(pCS1->pBuf, pCS2->pBuf, pCS1->iStrLen);
+ else
+ return pCS1->iStrLen - pCS2->iStrLen;
+}
+
+
+/* check if a sz-type string starts with a CStr object. This function
+ * is initially written to support the "startswith" property-filter
+ * comparison operation. Maybe it also has other needs.
+ * This functions is modelled after the strcmp() series, thus a
+ * return value of 0 indicates that the string starts with the
+ * sequence while -1 indicates it does not!
+ * rgerhards 2005-10-19
+ */
+int
+rsCStrSzStrStartsWithCStr(cstr_t *const __restrict__ pCS1,
+ uchar *const __restrict__ psz,
+ const size_t iLenSz)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if(iLenSz >= pCS1->iStrLen) {
+ if(pCS1->iStrLen == 0)
+ return 0; /* yes, it starts with a zero-sized string ;) */
+ else
+ return memcmp(psz, pCS1->pBuf, pCS1->iStrLen);
+ } else {
+ return -1; /* pCS1 is less then psz */
+ }
+}
+
+
+/* check if a CStr object matches a regex.
+ * msamia@redhat.com 2007-07-12
+ * @return returns 0 if matched
+ * bug: doesn't work for CStr containing \0
+ * rgerhards, 2007-07-16: bug is no real bug, because rsyslogd ensures there
+ * never is a \0 *inside* a property string.
+ * Note that the function returns -1 if regexp functionality is not available.
+ * rgerhards: 2009-03-04: ERE support added, via parameter iType: 0 - BRE, 1 - ERE
+ * Arnaud Cornet/rgerhards: 2009-04-02: performance improvement by caching compiled regex
+ * If a caller does not need the cached version, it must still provide memory for it
+ * and must call rsCStrRegexDestruct() afterwards.
+ */
+rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *rc)
+{
+ regex_t **cache = (regex_t**) rc;
+ int ret;
+ DEFiRet;
+
+ assert(pCS1 != NULL);
+ assert(psz != NULL);
+ assert(cache != NULL);
+
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ if (*cache == NULL) {
+ *cache = calloc(sizeof(regex_t), 1);
+ int errcode;
+ if((errcode = regexp.regcomp(*cache, (char*) rsCStrGetSzStrNoNULL(pCS1),
+ (iType == 1 ? REG_EXTENDED : 0) | REG_NOSUB))) {
+ char errbuff[512];
+ regexp.regerror(errcode, *cache, errbuff, sizeof(errbuff));
+ LogError(0, NO_ERRCODE, "Error in regular expression: %s\n", errbuff);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ }
+ ret = regexp.regexec(*cache, (char*) psz, 0, NULL, 0);
+ if(ret != 0)
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ } else {
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* free a cached compiled regex
+ * Caller must provide a pointer to a buffer that was created by
+ * rsCStrSzStrMatchRegexCache()
+ */
+void rsCStrRegexDestruct(void *rc)
+{
+ regex_t **cache = rc;
+
+ assert(cache != NULL);
+ assert(*cache != NULL);
+
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ regexp.regfree(*cache);
+ free(*cache);
+ *cache = NULL;
+ }
+}
+
+
+/* compare a rsCStr object with a classical sz string. This function
+ * is almost identical to rsCStrZsStrCmp(), but it also takes an offset
+ * to the CStr object from where the comparison is to start.
+ * I have thought quite a while if it really makes sense to more or
+ * less duplicate the code. After all, if you call it with an offset of
+ * zero, the functionality is exactly the same. So it looks natural to
+ * just have a single function. However, supporting the offset requires
+ * some (few) additional integer operations. While they are few, they
+ * happen at places in the code that is run very frequently. All in all,
+ * I have opted for performance and thus duplicated the code. I hope
+ * this is a good, or at least acceptable, compromise.
+ * rgerhards, 2005-09-26
+ * This function also has an offset-pointer which allows one to
+ * specify *where* the compare operation should begin in
+ * the CStr. If everything is to be compared, it must be set
+ * to 0. If some leading bytes are to be skipped, it must be set
+ * to the first index that is to be compared. It must not be
+ * set higher than the string length (this is considered a
+ * program bug and will lead to unpredictable results and program aborts).
+ * rgerhards 2005-09-26
+ */
+int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(iOffset < pCS1->iStrLen);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if((pCS1->iStrLen - iOffset) == iLenSz) {
+ /* we are using iLenSz below, because the lengths
+ * are equal and iLenSz is faster to access
+ */
+ if(iLenSz == 0) {
+ return 0; /* zero-sized strings are equal ;) */
+ } else { /* we now have two non-empty strings of equal
+ * length, so we need to actually check if they
+ * are equal.
+ */
+ return memcmp(pCS1->pBuf+iOffset, psz, iLenSz);
+ }
+ }
+ else {
+ return pCS1->iStrLen - iOffset - iLenSz;
+ }
+}
+
+
+/* compare a rsCStr object with a classical sz string.
+ * Just like rsCStrCStrCmp, just for a different data type.
+ * There must not only the sz string but also its length be
+ * provided. If the caller does not know the length he can
+ * call with
+ * rsCstrSzStrCmp(pCS, psz, strlen((char*)psz));
+ * we are not doing the strlen((char*)) ourselfs as the caller might
+ * already know the length and in such cases we can save the
+ * overhead of doing it one more time (strelen() is costly!).
+ * The bottom line is that the provided length MUST be correct!
+ * The to sz string pointer must not be NULL!
+ * rgerhards 2005-09-26
+ */
+int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if(pCS1->iStrLen == iLenSz)
+ if(iLenSz == 0)
+ return 0; /* zero-sized strings are equal ;) */
+ else
+ return strncmp((char*)pCS1->pBuf, (char*)psz, iLenSz);
+ else
+ return (ssize_t) pCS1->iStrLen - (ssize_t) iLenSz;
+}
+
+
+/* Locate the first occurrence of this rsCStr object inside a standard sz string.
+ * Returns the offset (0-bound) of this first occurrence. If not found, -1 is
+ * returned. Both parameters MUST be given (NULL is not allowed).
+ * rgerhards 2005-09-19
+ */
+int ATTR_NONNULL(1, 2)
+rsCStrLocateInSzStr(cstr_t *const pThis, uchar *const sz)
+{
+ size_t i;
+ size_t iMax;
+ size_t len_sz = ustrlen(sz);
+ int bFound;
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(sz != NULL);
+
+ if(pThis->iStrLen == 0)
+ return 0;
+
+ /* compute the largest index where a match could occur - after all,
+ * the to-be-located string must be able to be present in the
+ * searched string (it needs its size ;)).
+ */
+ iMax = (pThis->iStrLen >= len_sz) ? 0 : len_sz - pThis->iStrLen;
+
+ bFound = 0;
+ i = 0;
+ while(i <= iMax && !bFound) {
+ size_t iCheck;
+ uchar *pComp = sz + i;
+ for(iCheck = 0 ; iCheck < pThis->iStrLen ; ++iCheck)
+ if(*(pComp + iCheck) != *(pThis->pBuf + iCheck))
+ break;
+ if(iCheck == pThis->iStrLen)
+ bFound = 1; /* found! - else it wouldn't be equal */
+ else
+ ++i; /* on to the next try */
+ }
+
+ return(bFound ? (int) i : -1);
+}
+
+
+/* our exit function. TODO: remove once converted to a class
+ * rgerhards, 2008-03-11
+ */
+rsRetVal strExit(void)
+{
+ DEFiRet;
+ objRelease(regexp, LM_REGEXP_FILENAME);
+ RETiRet;
+}
+
+
+/* our init function. TODO: remove once converted to a class
+ */
+rsRetVal
+strInit(void)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+
+finalize_it:
+ RETiRet;
+}
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
new file mode 100644
index 0000000..8fa3bb5
--- /dev/null
+++ b/runtime/stringbuf.h
@@ -0,0 +1,157 @@
+/* stringbuf.h
+ * The counted string object
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2005-09-07
+ * Initial version begun.
+ *
+ * Copyright 2005-2016 Adiscon GmbH. All Rights Reserved.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _STRINGBUF_H_INCLUDED__
+#define _STRINGBUF_H_INCLUDED__ 1
+
+#include <assert.h>
+#include <libestr.h>
+
+/**
+ * The dynamic string buffer object.
+ */
+typedef struct cstr_s
+{
+#ifndef NDEBUG
+ rsObjID OID; /**< object ID */
+ sbool isFinalized;
+#endif
+ uchar *pBuf; /**< pointer to the string buffer, may be NULL if string is empty */
+ size_t iBufSize; /**< current maximum size of the string buffer */
+ size_t iStrLen; /**< length of the string in characters. */
+} cstr_t;
+
+
+/**
+ * Construct a rsCStr object.
+ */
+rsRetVal cstrConstruct(cstr_t **ppThis);
+#define rsCStrConstruct(x) cstrConstruct((x))
+rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str);
+rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, const uchar *sz);
+rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, const cstr_t *pFrom);
+rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, const char *fmt, ...) __attribute__((format(printf,2, 3)));
+
+/**
+ * Destruct the string buffer object.
+ */
+void rsCStrDestruct(cstr_t **ppThis);
+#define cstrDestruct(x) rsCStrDestruct((x))
+
+
+/* Append a character to the current string object. This may only be done until
+ * cstrFinalize() is called.
+ * rgerhards, 2009-06-16
+ */
+rsRetVal cstrAppendChar(cstr_t *pThis, const uchar c);
+
+/* Finalize the string object. This must be called after all data is added to it
+ * but before that data is used.
+ * rgerhards, 2009-06-16
+ */
+#ifdef NDEBUG
+#define cstrFinalize(pThis) { \
+ if((pThis)->iStrLen > 0) \
+ (pThis)->pBuf[(pThis)->iStrLen] = '\0'; /* space is always reserved for this */ \
+}
+#else
+#define cstrFinalize(pThis) { \
+ if((pThis)->iStrLen > 0) \
+ (pThis)->pBuf[(pThis)->iStrLen] = '\0'; /* space is always reserved for this */ \
+ (pThis)->isFinalized = 1; \
+}
+#endif
+
+
+/**
+ * Truncate "n" number of characters from the end of the
+ * string. The buffer remains unchanged, just the
+ * string length is manipulated. This is for performance
+ * reasons.
+ */
+rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc);
+
+void cstrTrimTrailingWhiteSpace(cstr_t *pThis);
+
+/**
+ * Append a string to the buffer. For performance reasons,
+ * use rsCStrAppenStrWithLen() if you know the length.
+ *
+ * \param psz pointer to string to be appended. Must not be NULL.
+ */
+rsRetVal rsCStrAppendStr(cstr_t *pThis, const uchar* psz);
+
+/**
+ * Append a string to the buffer.
+ *
+ * \param psz pointer to string to be appended. Must not be NULL.
+ * \param iStrLen the length of the string pointed to by psz
+ */
+rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, const uchar* psz, size_t iStrLen);
+
+/**
+ * Append a printf-style formated string to the buffer.
+ *
+ * \param fmt pointer to the format string (see man 3 printf for details). Must not be NULL.
+ */
+rsRetVal rsCStrAppendStrf(cstr_t *pThis, const char *fmt, ...) __attribute__((format(printf,2, 3)));
+
+/**
+ * Append an integer to the string. No special formatting is
+ * done.
+ */
+rsRetVal rsCStrAppendInt(cstr_t *pThis, long i);
+
+
+rsRetVal strExit(void);
+uchar* cstrGetSzStrNoNULL(cstr_t *pThis);
+#define rsCStrGetSzStrNoNULL(x) cstrGetSzStrNoNULL(x)
+rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew);
+int rsCStrCStrCmp(cstr_t *pCS1, cstr_t *pCS2);
+int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz);
+int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz);
+int rsCStrLocateSzStr(cstr_t *pCStr, uchar *sz);
+int rsCStrLocateInSzStr(cstr_t *pThis, uchar *sz);
+int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz);
+rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *cache);
+void rsCStrRegexDestruct(void *rc);
+
+/* new calling interface */
+rsRetVal cstrConvSzStrAndDestruct(cstr_t **pThis, uchar **ppSz, int bRetNULL);
+rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend);
+
+/* now come inline-like functions */
+#ifdef NDEBUG
+# define cstrLen(x) ((size_t)((x)->iStrLen))
+#else
+ size_t cstrLen(cstr_t *pThis);
+#endif
+#define rsCStrLen(s) cstrLen((s))
+
+#define rsCStrGetBufBeg(x) ((x)->pBuf)
+
+rsRetVal strInit(void);
+
+#endif /* single include */
diff --git a/runtime/syslogd-types.h b/runtime/syslogd-types.h
new file mode 100644
index 0000000..0924a3c
--- /dev/null
+++ b/runtime/syslogd-types.h
@@ -0,0 +1,114 @@
+/* syslogd-type.h
+ * This file contains type defintions used by syslogd and its modules.
+ * It is a required input for any module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2018 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SYSLOGD_TYPES_INCLUDED
+#define SYSLOGD_TYPES_INCLUDED 1
+
+#include "stringbuf.h"
+#include <sys/param.h>
+
+/* we use RSTRUE/FALSE to prevent name claches with other packages */
+#define RSFALSE 0
+#define RSTRUE 1
+
+#define MAXFNAME 4096 /* max file pathname length */
+
+#define _DB_MAXCONNINFOLEN 2048 /* maximum length connection string */
+#define _DB_MAXDBLEN 128 /* maximum number of db */
+#define _DB_MAXUNAMELEN 128 /* maximum number of user name */
+#define _DB_MAXPWDLEN 128 /* maximum number of user's pass */
+#define _DB_DELAYTIMEONERROR 20 /* If an error occur we stop logging until a delayed time is over */
+
+/* we define features of the syslog code. This features can be used
+ * to check if modules are compatible with them - and possible other
+ * applications I do not yet envision. -- rgerhards, 2007-07-24
+ */
+typedef enum _syslogFeature {
+ sFEATURERepeatedMsgReduction = 1, /* for output modules */
+ sFEATURENonCancelInputTermination = 2, /* for input modules */
+ sFEATUREAutomaticSanitazion = 3, /* for parser modules */
+ sFEATUREAutomaticPRIParsing = 4 /* for parser modules */
+} syslogFeature;
+
+/* we define our own facility and severities */
+/* facility and severity codes */
+typedef struct _syslogCode {
+ char *c_name;
+ int c_val;
+} syslogCODE;
+
+/* values for host comparisons specified with host selector blocks
+ * (+host, -host). rgerhards 2005-10-18.
+ */
+enum _EHostnameCmpMode {
+ HN_NO_COMP = 0, /* do not compare hostname */
+ HN_COMP_MATCH = 1, /* hostname must match */
+ HN_COMP_NOMATCH = 2 /* hostname must NOT match */
+};
+typedef enum _EHostnameCmpMode EHostnameCmpMode;
+
+/* time type numerical values for structure below */
+#define TIME_TYPE_UNINIT 0
+#define TIME_TYPE_RFC3164 1
+#define TIME_TYPE_RFC5424 2
+/* rgerhards 2004-11-11: the following structure represents
+ * a time as it is used in syslog.
+ * rgerhards, 2009-06-23: packed structure for better cache performance
+ * (but left ultimate decision about packing to compiler)
+ */
+struct syslogTime {
+ intTiny timeType; /* 0 - unitinialized , 1 - RFC 3164, 2 - syslog-protocol */
+ intTiny month;
+ intTiny day;
+ intTiny wday;
+ intTiny hour; /* 24 hour clock */
+ intTiny minute;
+ intTiny second;
+ intTiny secfracPrecision;
+ intTiny OffsetMinute; /* UTC offset in minutes */
+ intTiny OffsetHour; /* UTC offset in hours
+ * full UTC offset minutes = OffsetHours*60 + OffsetMinute. Then use
+ * OffsetMode to know the direction.
+ */
+ char OffsetMode; /* UTC offset + or - */
+ short year;
+ int secfrac; /* fractional seconds (must be 32 bit!) */
+ intTiny inUTC; /* forced UTC? */
+};
+typedef struct syslogTime syslogTime_t;
+
+struct tzinfo {
+ char *id;
+ char offsMode;
+ int8_t offsHour;
+ int8_t offsMin;
+};
+typedef struct tzinfo tzinfo_t;
+
+typedef enum { ACT_STRING_PASSING = 0, ACT_ARRAY_PASSING = 1, ACT_MSG_PASSING = 2,
+ ACT_JSON_PASSING = 3} paramPassing_t;
+
+#endif /* #ifndef SYSLOGD_TYPES_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/runtime/tcpclt.c b/runtime/tcpclt.c
new file mode 100644
index 0000000..47064dd
--- /dev/null
+++ b/runtime/tcpclt.c
@@ -0,0 +1,525 @@
+/* tcpclt.c
+ *
+ * This is the implementation of TCP-based syslog clients (the counterpart
+ * of the tcpsrv class).
+ *
+ * Copyright 2007-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "syslogd-types.h"
+#include "net.h"
+#include "tcpclt.h"
+#include "module-template.h"
+#include "srUtils.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+
+/* Initialize TCP sockets (for sender)
+ */
+static int
+CreateSocket(struct addrinfo *addrDest)
+{
+ int fd;
+ struct addrinfo *r;
+
+ r = addrDest;
+
+ while(r != NULL) {
+ fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if (fd != -1) {
+ /* We can not allow the TCP sender to block syslogd, at least
+ * not in a single-threaded design. That would cause rsyslogd to
+ * loose input messages - which obviously also would affect
+ * other selector lines, too. So we do set it to non-blocking and
+ * handle the situation ourselfs (by discarding messages). IF we run
+ * dual-threaded, however, the situation is different: in this case,
+ * the receivers and the selector line processing are only loosely
+ * coupled via a memory buffer. Now, I think, we can afford the extra
+ * wait time. Thus, we enable blocking mode for TCP if we compile with
+ * pthreads. -- rgerhards, 2005-10-25
+ * And now, we always run on multiple threads... -- rgerhards, 2007-12-20
+ */
+ if (connect (fd, r->ai_addr, r->ai_addrlen) != 0) {
+ if(errno == EINPROGRESS) {
+ /* this is normal - will complete later select */
+ return fd;
+ } else {
+ char errStr[1024];
+ dbgprintf("create tcp connection failed, reason %s",
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ }
+
+ }
+ else {
+ return fd;
+ }
+ close(fd);
+ }
+ else {
+ char errStr[1024];
+ dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr,
+ sizeof(errStr)));
+ }
+ r = r->ai_next;
+ }
+
+ dbgprintf("no working socket could be obtained");
+
+ return -1;
+}
+
+
+
+/* Build frame based on selected framing
+ * This function was created by pulling code from TCPSend()
+ * on 2007-12-27 by rgerhards. Older comments are still relevant.
+ *
+ * In order to support compressed messages via TCP, we must support an
+ * octet-counting based framing (LF may be part of the compressed message).
+ * We are now supporting the same mode that is available in IETF I-D
+ * syslog-transport-tls-05 (current at the time of this writing). This also
+ * eases things when we go ahead and implement that framing. I have now made
+ * available two cases where this framing is used: either by explitely
+ * specifying it in the config file or implicitely when sending a compressed
+ * message. In the later case, compressed and uncompressed messages within
+ * the same session have different framings. If it is explicitely set to
+ * octet-counting, only this framing mode is used within the session.
+ * rgerhards, 2006-12-07
+ */
+static rsRetVal
+TCPSendBldFrame(tcpclt_t *pThis, char **pmsg, size_t *plen, int *pbMustBeFreed)
+{
+ DEFiRet;
+ TCPFRAMINGMODE framingToUse;
+ int bIsCompressed;
+ size_t len;
+ char *msg;
+ char *buf = NULL; /* if this is non-NULL, it MUST be freed before return! */
+
+ assert(plen != NULL);
+ assert(pbMustBeFreed != NULL);
+ assert(pmsg != NULL);
+
+ msg = *pmsg;
+ len = *plen;
+ bIsCompressed = *msg == 'z'; /* cache this, so that we can modify the message buffer */
+ /* select framing for this record. If we have a compressed record, we always need to
+ * use octet counting because the data potentially contains all control characters
+ * including LF.
+ */
+ framingToUse = bIsCompressed ? TCP_FRAMING_OCTET_COUNTING : pThis->tcp_framing;
+
+ /* now check if we need to add a line terminator. We need to
+ * copy the string in memory in this case, this is probably
+ * quicker than using writev and definitely quicker than doing
+ * two socket calls.
+ * rgerhards 2005-07-22
+ *
+ * Some messages already contain a \n character at the end
+ * of the message. We append one only if we there is not
+ * already one. This seems the best fit, though this also
+ * means the message does not arrive unaltered at the final
+ * destination. But in the spirit of legacy syslog, this is
+ * probably the best to do...
+ * rgerhards 2005-07-20
+ */
+
+ /* Build frame based on selected framing */
+ if(framingToUse == TCP_FRAMING_OCTET_STUFFING) {
+ if((*(msg+len-1) != pThis->tcp_framingDelimiter)) {
+ /* in the malloc below, we need to add 2 to the length. The
+ * reason is that we a) add one character and b) len does
+ * not take care of the '\0' byte. Up until today, it was just
+ * +1 , which caused rsyslogd to sometimes dump core.
+ * I have added this comment so that the logic is not accidently
+ * changed again. rgerhards, 2005-10-25
+ */
+ if((buf = malloc(len + 2)) == NULL) {
+ /* extreme mem shortage, try to solve
+ * as good as we can. No point in calling
+ * any alarms, they might as well run out
+ * of memory (the risk is very high, so we
+ * do NOT risk that). If we have a message of
+ * more than 1 byte (what I guess), we simply
+ * overwrite the last character.
+ * rgerhards 2005-07-22
+ */
+ if(len > 1) {
+ *(msg+len-1) = pThis->tcp_framingDelimiter;
+ } else {
+ /* we simply can not do anything in
+ * this case (its an error anyhow...).
+ */
+ }
+ } else {
+ /* we got memory, so we can copy the message */
+ memcpy(buf, msg, len); /* do not copy '\0' */
+ *(buf+len) = pThis->tcp_framingDelimiter;
+ *(buf+len+1) = '\0';
+ msg = buf; /* use new one */
+ ++len; /* care for the \n */
+ }
+ }
+ } else {
+ /* Octect-Counting
+ * In this case, we need to always allocate a buffer. This is because
+ * we need to put a header in front of the message text
+ */
+ char szLenBuf[16];
+ int iLenBuf;
+
+ /* important: the printf-mask is "%d<sp>" because there must be a
+ * space after the len!
+ *//* The chairs of the IETF syslog-sec WG have announced that it is
+ * consensus to do the octet count on the SYSLOG-MSG part only. I am
+ * now changing the code to reflect this. Hopefully, it will not change
+ * once again (there can no compatibility layer programmed for this).
+ * To be on the save side, I just comment the code out. I mark these
+ * comments with "IETF20061218".
+ * rgerhards, 2006-12-19
+ */
+ iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf), "%d ", (int) len);
+ /* IETF20061218 iLenBuf =
+ snprintf(szLenBuf, sizeof(szLenBuf), "%d ", len + iLenBuf);*/
+
+ if((buf = malloc(len + iLenBuf)) == NULL) {
+ /* we are out of memory. This is an extreme situation. We do not
+ * call any alarm handlers because they most likely run out of mem,
+ * too. We are brave enough to call debug output, though. Other than
+ * that, there is nothing left to do. We can not sent the message (as
+ * in case of the other framing, because the message is incomplete.
+ * We could, however, send two chunks (header and text separate), but
+ * that would cause a lot of complexity in the code. So we think it
+ * is appropriate enough to just make sure we do not crash in this
+ * very unlikely case. For this, it is justified just to loose
+ * the message. Rgerhards, 2006-12-07
+ */
+ dbgprintf("Error: out of memory when building TCP octet-counted "
+ "frame. Message is lost, trying to continue.\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ memcpy(buf, szLenBuf, iLenBuf); /* header */
+ memcpy(buf + iLenBuf, msg, len); /* message */
+ len += iLenBuf; /* new message size */
+ msg = buf; /* set message buffer */
+ }
+
+ /* frame building complete, on to actual sending */
+
+ *plen = len;
+ if(buf == NULL) {
+ /* msg not modified */
+ *pbMustBeFreed = 0;
+ } else {
+ *pmsg = msg;
+ *pbMustBeFreed = 1;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Sends a TCP message. It is first checked if the
+ * session is open and, if not, it is opened. Then the send
+ * is tried. If it fails, one silent re-try is made. If the send
+ * fails again, an error status (-1) is returned. If all goes well,
+ * 0 is returned. The TCP session is NOT torn down.
+ * For now, EAGAIN is ignored (causing message loss) - but it is
+ * hard to do something intelligent in this case. With this
+ * implementation here, we can not block and/or defer. Things are
+ * probably a bit better when we move to liblogging. The alternative
+ * would be to enhance the current select server with buffering and
+ * write descriptors. This seems not justified, given the expected
+ * short life span of this code (and the unlikeliness of this event).
+ * rgerhards 2005-07-06
+ * This function is now expected to stay. Libloging won't be used for
+ * that purpose. I have added the param "len", because it is known by the
+ * caller and so saves us some time. Also, it MUST be given because there
+ * may be NULs inside msg so that we can not rely on strlen(). Please note
+ * that the restrictions outlined above do not existin in multi-threaded
+ * mode, which we assume will now be most often used. So there is no
+ * real issue with the potential message loss in single-threaded builds.
+ * rgerhards, 2006-11-30
+ * I greatly restructured the function to be more generic and work
+ * with function pointers. So it now can be used with any type of transport,
+ * as long as it follows stream semantics. This was initially done to
+ * support plain TCP and GSS via common code.
+ */
+static int
+Send(tcpclt_t *pThis, void *pData, char *msg, size_t len)
+{
+ DEFiRet;
+ int bDone = 0;
+ int retry = 0;
+ int bMsgMustBeFreed = 0;/* must msg be freed at end of function? 0 - no, 1 - yes */
+
+ ISOBJ_TYPE_assert(pThis, tcpclt);
+ assert(pData != NULL);
+ assert(msg != NULL);
+ assert(len > 0);
+
+ CHKiRet(TCPSendBldFrame(pThis, &msg, &len, &bMsgMustBeFreed));
+
+ if(pThis->iRebindInterval > 0 && ++pThis->iNumMsgs == pThis->iRebindInterval) {
+ /* we need to rebind, and use the retry logic for this*/
+ CHKiRet(pThis->prepRetryFunc(pData)); /* try to recover */
+ pThis->iNumMsgs = 0;
+ }
+
+ while(!bDone) { /* loop is broken when send succeeds or error occurs */
+ CHKiRet(pThis->initFunc(pData));
+ iRet = pThis->sendFunc(pData, msg, len);
+
+ if(iRet == RS_RET_OK || iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) {
+ /* we are done, we also use this as indication that the previous
+ * message was succesfully received (it's not always the case, but its at
+ * least our best shot at it -- rgerhards, 2008-03-12
+ * As of 2008-06-09, we have implemented an algorithm which detects connection
+ * loss quite good in some (common) scenarios. Thus, the probability of
+ * message duplication due to the code below has increased. We so now have
+ * a config setting, default off, that enables the user to request retransmits.
+ * However, if not requested, we do NOT need to do all the stuff needed for it.
+ */
+ if(pThis->bResendLastOnRecon == 1) {
+ if(pThis->prevMsg != NULL)
+ free(pThis->prevMsg);
+ /* if we can not alloc a new buffer, we silently ignore it. The worst that
+ * happens is that we lose our message recovery buffer - anything else would
+ * be worse, so don't try anything ;) -- rgerhards, 2008-03-12
+ */
+ if((pThis->prevMsg = malloc(len)) != NULL) {
+ memcpy(pThis->prevMsg, msg, len);
+ pThis->lenPrevMsg = len;
+ }
+ }
+
+ /* we are done with this record */
+ bDone = 1;
+ } else {
+ if(retry == 0) { /* OK, one retry */
+ ++retry;
+ CHKiRet(pThis->prepRetryFunc(pData)); /* try to recover */
+ /* now try to send our stored previous message (which most probably
+ * didn't make it. Note that if bResendLastOnRecon is 0, prevMsg will
+ * never become non-NULL, so the check below covers all cases.
+ */
+ if(pThis->prevMsg != NULL) {
+ CHKiRet(pThis->initFunc(pData));
+ CHKiRet(pThis->sendFunc(pData, pThis->prevMsg, pThis->lenPrevMsg));
+ }
+ } else {
+ /* OK, max number of retries reached, nothing we can do */
+ bDone = 1;
+ }
+ }
+ }
+
+finalize_it:
+ if(bMsgMustBeFreed)
+ free(msg);
+ RETiRet;
+}
+
+
+/* set functions */
+static rsRetVal
+SetResendLastOnRecon(tcpclt_t *pThis, int bResendLastOnRecon)
+{
+ DEFiRet;
+ pThis->bResendLastOnRecon = (short) bResendLastOnRecon;
+ RETiRet;
+}
+static rsRetVal
+SetSendInit(tcpclt_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->initFunc = pCB;
+ RETiRet;
+}
+static rsRetVal
+SetSendPrepRetry(tcpclt_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->prepRetryFunc = pCB;
+ RETiRet;
+}
+static rsRetVal
+SetSendFrame(tcpclt_t *pThis, rsRetVal (*pCB)(void*, char*, size_t))
+{
+ DEFiRet;
+ pThis->sendFunc = pCB;
+ RETiRet;
+}
+static rsRetVal
+SetFraming(tcpclt_t *pThis, TCPFRAMINGMODE framing)
+{
+ DEFiRet;
+ pThis->tcp_framing = framing;
+ RETiRet;
+}
+static rsRetVal
+SetFramingDelimiter(tcpclt_t *pThis, uchar tcp_framingDelimiter)
+{
+ DEFiRet;
+ pThis->tcp_framingDelimiter = tcp_framingDelimiter;
+ RETiRet;
+}
+static rsRetVal
+SetRebindInterval(tcpclt_t *pThis, int iRebindInterval)
+{
+ DEFiRet;
+ pThis->iRebindInterval = iRebindInterval;
+ RETiRet;
+}
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(tcpclt) /* be sure to specify the object type also in END macro! */
+ pThis->tcp_framingDelimiter = '\n';
+ENDobjConstruct(tcpclt)
+
+
+/* ConstructionFinalizer
+ */
+static rsRetVal
+tcpcltConstructFinalize(tcpclt_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpclt);
+
+ RETiRet;
+}
+
+
+/* destructor for the tcpclt object */
+BEGINobjDestruct(tcpclt) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(tcpclt)
+ if(pThis->prevMsg != NULL)
+ free(pThis->prevMsg);
+ENDobjDestruct(tcpclt)
+
+
+/* ------------------------------ handling the interface plumbing ------------------------------ */
+
+/* queryInterface function
+ * rgerhards, 2008-03-12
+ */
+BEGINobjQueryInterface(tcpclt)
+CODESTARTobjQueryInterface(tcpclt)
+ if(pIf->ifVersion != tcpcltCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = tcpcltConstruct;
+ pIf->ConstructFinalize = tcpcltConstructFinalize;
+ pIf->Destruct = tcpcltDestruct;
+
+ pIf->CreateSocket = CreateSocket;
+ pIf->Send = Send;
+
+ /* set functions */
+ pIf->SetResendLastOnRecon = SetResendLastOnRecon;
+ pIf->SetSendInit = SetSendInit;
+ pIf->SetSendFrame = SetSendFrame;
+ pIf->SetSendPrepRetry = SetSendPrepRetry;
+ pIf->SetFraming = SetFraming;
+ pIf->SetFramingDelimiter = SetFramingDelimiter;
+ pIf->SetRebindInterval = SetRebindInterval;
+
+finalize_it:
+ENDobjQueryInterface(tcpclt)
+
+
+/* exit our class
+ * rgerhards, 2008-03-10
+ */
+BEGINObjClassExit(tcpclt, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(tcpclt)
+ /* release objects we no longer need */
+ENDObjClassExit(tcpclt)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-29
+ */
+BEGINObjClassInit(tcpclt, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ /* request objects we use */
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcpcltConstructFinalize);
+ENDObjClassInit(tcpclt)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* de-init in reverse order! */
+ tcpcltClassExit();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(tcpcltClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/runtime/tcpclt.h b/runtime/tcpclt.h
new file mode 100644
index 0000000..5e04b29
--- /dev/null
+++ b/runtime/tcpclt.h
@@ -0,0 +1,76 @@
+/* tcpclt.h
+ *
+ * This are the definitions for the TCP based clients class.
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef TCPCLT_H_INCLUDED
+#define TCPCLT_H_INCLUDED 1
+
+#include "obj.h"
+
+/* the tcpclt object */
+typedef struct tcpclt_s {
+ BEGINobjInstance; /**< Data to implement generic object - MUST be the first data element! */
+ TCPFRAMINGMODE tcp_framing;
+ uchar tcp_framingDelimiter;
+ char *prevMsg;
+ short bResendLastOnRecon; /* should the last message be resent on a successful reconnect? */
+ size_t lenPrevMsg;
+ /* session specific callbacks */
+ int iRebindInterval; /* how often should the send socket be rebound? */
+ int iNumMsgs; /* number of messages during current "rebind session" */
+ rsRetVal (*initFunc)(void*);
+ rsRetVal (*sendFunc)(void*, char*, size_t);
+ rsRetVal (*prepRetryFunc)(void*);
+} tcpclt_t;
+
+
+/* interfaces */
+BEGINinterface(tcpclt) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*Construct)(tcpclt_t **ppThis);
+ rsRetVal (*ConstructFinalize)(tcpclt_t __attribute__((unused)) *pThis);
+ rsRetVal (*Destruct)(tcpclt_t **ppThis);
+ int (*Send)(tcpclt_t *pThis, void*pData, char*msg, size_t len);
+ int (*CreateSocket)(struct addrinfo *addrDest);
+ /* set methods */
+ rsRetVal (*SetResendLastOnRecon)(tcpclt_t*, int);
+ rsRetVal (*SetSendInit)(tcpclt_t*, rsRetVal (*)(void*));
+ rsRetVal (*SetSendFrame)(tcpclt_t*, rsRetVal (*)(void*, char*, size_t));
+ rsRetVal (*SetSendPrepRetry)(tcpclt_t*, rsRetVal (*)(void*));
+ rsRetVal (*SetFraming)(tcpclt_t*, TCPFRAMINGMODE framing);
+ /* v3, 2009-07-14*/
+ rsRetVal (*SetRebindInterval)(tcpclt_t*, int iRebindInterval);
+ /* v4, 2017-06-10*/
+ rsRetVal (*SetFramingDelimiter)(tcpclt_t*, uchar tcp_framingDelimiter);
+ENDinterface(tcpclt)
+#define tcpcltCURR_IF_VERSION 4 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(tcpclt);
+
+/* the name of our library binary */
+#define LM_TCPCLT_FILENAME "lmtcpclt"
+
+#endif /* #ifndef TCPCLT_H_INCLUDED */
+/* vim:set ai:
+ */
diff --git a/runtime/tcps_sess.c b/runtime/tcps_sess.c
new file mode 100644
index 0000000..b0832b1
--- /dev/null
+++ b/runtime/tcps_sess.c
@@ -0,0 +1,625 @@
+/* tcps_sess.c
+ *
+ * This implements a session of the tcpsrv object. For general
+ * comments, see header of tcpsrv.c.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2008-03-01 by RGerhards (extracted from tcpsrv.c, which
+ * based on the BSD-licensed syslogd.c)
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "net.h"
+#include "tcpsrv.h"
+#include "tcps_sess.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "netstrm.h"
+#include "msg.h"
+#include "datetime.h"
+#include "prop.h"
+#include "ratelimit.h"
+#include "debug.h"
+#include "rsconf.h"
+
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(datetime)
+
+
+/* forward definitions */
+static rsRetVal Close(tcps_sess_t *pThis);
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(tcps_sess) /* be sure to specify the object type also in END macro! */
+ pThis->iMsg = 0; /* just make sure... */
+ pThis->iMaxLine = glbl.GetMaxLine(runConf);
+ pThis->inputState = eAtStrtFram; /* indicate frame header expected */
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */
+ /* now allocate the message reception buffer */
+ CHKmalloc(pThis->pMsg = (uchar*) malloc(pThis->iMaxLine + 1));
+finalize_it:
+ENDobjConstruct(tcps_sess)
+
+
+/* ConstructionFinalizer
+ */
+static rsRetVal
+tcps_sessConstructFinalize(tcps_sess_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ if(pThis->pSrv->OnSessConstructFinalize != NULL) {
+ CHKiRet(pThis->pSrv->OnSessConstructFinalize(&pThis->pUsr));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* destructor for the tcps_sess object */
+BEGINobjDestruct(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(tcps_sess)
+ if(pThis->pStrm != NULL)
+ netstrm.Destruct(&pThis->pStrm);
+
+ if(pThis->pSrv->pOnSessDestruct != NULL) {
+ pThis->pSrv->pOnSessDestruct(&pThis->pUsr);
+ }
+ /* now destruct our own properties */
+ if(pThis->fromHost != NULL)
+ CHKiRet(prop.Destruct(&pThis->fromHost));
+ if(pThis->fromHostIP != NULL)
+ CHKiRet(prop.Destruct(&pThis->fromHostIP));
+ free(pThis->pMsg);
+ENDobjDestruct(tcps_sess)
+
+
+/* debugprint for the tcps_sess object */
+BEGINobjDebugPrint(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(tcps_sess)
+ENDobjDebugPrint(tcps_sess)
+
+
+/* set property functions */
+/* set the hostname. Note that the caller *hands over* the string. That is,
+ * the caller no longer controls it once SetHost() has received it. Most importantly,
+ * the caller must not free it. -- rgerhards, 2008-04-24
+ */
+static rsRetVal
+SetHost(tcps_sess_t *pThis, uchar *pszHost)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+
+ if(pThis->fromHost == NULL)
+ CHKiRet(prop.Construct(&pThis->fromHost));
+
+ CHKiRet(prop.SetString(pThis->fromHost, pszHost, ustrlen(pszHost)));
+
+finalize_it:
+ free(pszHost); /* we must free according to our (old) calling conventions */
+ RETiRet;
+}
+
+/* set the remote host's IP. Note that the caller *hands over* the property. That is,
+ * the caller no longer controls it once SetHostIP() has received it. Most importantly,
+ * the caller must not destruct it. -- rgerhards, 2008-05-16
+ */
+static rsRetVal
+SetHostIP(tcps_sess_t *pThis, prop_t *ip)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+
+ if(pThis->fromHostIP != NULL) {
+ prop.Destruct(&pThis->fromHostIP);
+ }
+ pThis->fromHostIP = ip;
+ RETiRet;
+}
+
+static rsRetVal
+SetStrm(tcps_sess_t *pThis, netstrm_t *pStrm)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ pThis->pStrm = pStrm;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetMsgIdx(tcps_sess_t *pThis, int idx)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ pThis->iMsg = idx;
+ RETiRet;
+}
+
+
+/* set our parent, the tcpsrv object */
+static rsRetVal
+SetTcpsrv(tcps_sess_t *pThis, tcpsrv_t *pSrv)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ ISOBJ_TYPE_assert(pSrv, tcpsrv);
+ pThis->pSrv = pSrv;
+ RETiRet;
+}
+
+
+/* set our parent listener info*/
+static rsRetVal
+SetLstnInfo(tcps_sess_t *pThis, tcpLstnPortList_t *pLstnInfo)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ assert(pLstnInfo != NULL);
+ pThis->pLstnInfo = pLstnInfo;
+ /* set cached elements */
+ pThis->bSuppOctetFram = pLstnInfo->cnf_params->bSuppOctetFram;
+ pThis->bSPFramingFix = pLstnInfo->cnf_params->bSPFramingFix;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetUsrP(tcps_sess_t *pThis, void *pUsr)
+{
+ DEFiRet;
+ pThis->pUsr = pUsr;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetOnMsgReceive(tcps_sess_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int))
+{
+ DEFiRet;
+ pThis->DoSubmitMessage = OnMsgReceive;
+ RETiRet;
+}
+
+
+/* This is a helper for submitting the message to the rsyslog core.
+ * It does some common processing, including resetting the various
+ * state variables to a "processed" state.
+ * Note that this function is also called if we had a buffer overflow
+ * due to a too-long message. So far, there is no indication this
+ * happened and it may be worth thinking about different handling
+ * of this case (what obviously would require a change to this
+ * function or some related code).
+ * rgerhards, 2009-04-23
+ */
+static rsRetVal
+defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub)
+{
+ smsg_t *pMsg;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params;
+
+ if(pThis->iMsg == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+
+ if(pThis->DoSubmitMessage != NULL) {
+ pThis->DoSubmitMessage(pThis, pThis->pMsg, pThis->iMsg);
+ FINALIZE;
+ }
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg);
+ MsgSetInputName(pMsg, cnf_params->pInputName);
+ if(cnf_params->dfltTZ[0] != '\0')
+ MsgSetDfltTZ(pMsg, (char*) cnf_params->dfltTZ);
+ MsgSetFlowControlType(pMsg, pThis->pSrv->bUseFlowControl
+ ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ MsgSetRcvFrom(pMsg, pThis->fromHost);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP));
+ MsgSetRuleset(pMsg, cnf_params->pRuleset);
+
+ STATSCOUNTER_INC(pThis->pLstnInfo->ctrSubmit, pThis->pLstnInfo->mutCtrSubmit);
+ ratelimitAddMsg(pThis->pLstnInfo->ratelimiter, pMultiSub, pMsg);
+
+finalize_it:
+ /* reset status variables */
+ pThis->iMsg = 0;
+
+ RETiRet;
+}
+
+
+
+/* This should be called before a normal (non forced) close
+ * of a TCP session. This function checks if there is any unprocessed
+ * message left in the TCP stream. Such a message is probably a
+ * fragement. If evrything goes well, we must be right at the
+ * beginnig of a new frame without any data received from it. If
+ * not, there is some kind of a framing error. I think I remember that
+ * some legacy syslog/TCP implementations have non-LF terminated
+ * messages at the end of the stream. For now, we allow this behaviour.
+ * Later, it should probably become a configuration option.
+ * rgerhards, 2006-12-07
+ */
+static rsRetVal
+PrepareClose(tcps_sess_t *pThis)
+{
+ struct syslogTime stTime;
+ time_t ttGenTime;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+
+ if(pThis->inputState == eAtStrtFram) {
+ /* this is how it should be. There is no unprocessed
+ * data left and such we have nothing to do. For simplicity
+ * reasons, we immediately return in that case.
+ */
+ FINALIZE;
+ }
+
+ /* we have some data left! */
+ if(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ /* In this case, we have an invalid frame count and thus
+ * generate an error message and discard the frame.
+ */
+ LogError(0, NO_ERRCODE, "Incomplete frame at end of stream in session %p - "
+ "ignoring extra data (a message may be lost).", pThis->pStrm);
+ /* nothing more to do */
+ } else { /* here, we have traditional framing. Missing LF at the end
+ * of message may occur. As such, we process the message in
+ * this case.
+ */
+ DBGPRINTF("Extra data at end of stream in legacy syslog/tcp message - processing\n");
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ defaultDoSubmitMessage(pThis, &stTime, ttGenTime, NULL);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Closes a TCP session
+ * No attention is paid to the return code
+ * of close, so potential-double closes are not detected.
+ */
+static rsRetVal
+Close(tcps_sess_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ netstrm.Destruct(&pThis->pStrm);
+ if(pThis->fromHost != NULL) {
+ prop.Destruct(&pThis->fromHost);
+ }
+ if(pThis->fromHostIP != NULL)
+ prop.Destruct(&pThis->fromHostIP);
+
+ RETiRet;
+}
+
+
+/* process the data received. As TCP is stream based, we need to process the
+ * data inside a state machine. The actual data received is passed in byte-by-byte
+ * from DataRcvd, and this function here compiles messages from them and submits
+ * the end result to the queue. Introducing this function fixes a long-term bug ;)
+ * rgerhards, 2008-03-14
+ */
+static rsRetVal ATTR_NONNULL(1)
+processDataRcvd(tcps_sess_t *pThis,
+ const char c,
+ struct syslogTime *stTime,
+ const time_t ttGenTime,
+ multi_submit_t *pMultiSub,
+ unsigned *const __restrict__ pnMsgs)
+{
+ DEFiRet;
+ const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params;
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+
+ if(pThis->inputState == eAtStrtFram) {
+ if(c >= '0' && c <= '9' && pThis->bSuppOctetFram) {
+ pThis->inputState = eInOctetCnt;
+ pThis->iOctetsRemain = 0;
+ pThis->eFraming = TCP_FRAMING_OCTET_COUNTING;
+ } else if(c == ' ' && pThis->bSPFramingFix) {
+ /* Cisco ASA very occasionally sends a SP after a LF, which
+ * thrashes framing if not taken special care of. Here,
+ * we permit space *in front of the next frame* and
+ * ignore it.
+ */
+ FINALIZE;
+ } else {
+ pThis->inputState = eInMsg;
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ }
+ }
+
+ if(pThis->inputState == eInMsg) {
+ #if 0 // set to 1 for ultra-verbose
+ DBGPRINTF("DEBUG: processDataRcvd c=%c remain=%d\n",
+ c, pThis->iOctetsRemain);
+ #endif
+
+ if(( ((c == '\n') && !pThis->pSrv->bDisableLFDelim)
+ || ((pThis->pSrv->addtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
+ && (c == pThis->pSrv->addtlFrameDelim))
+ ) && pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delimiter? */
+ defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+ pThis->inputState = eAtStrtFram;
+ } else {
+ /* IMPORTANT: here we copy the actual frame content to the message - for BOTH framing modes!
+ * If we have a message that is larger than the max msg size, we truncate it. This is the best
+ * we can do in light of what the engine supports. -- rgerhards, 2008-03-14
+ */
+ if(pThis->iMsg < pThis->iMaxLine) {
+ *(pThis->pMsg + pThis->iMsg++) = c;
+ } else {
+ /* emergency, we now need to flush, no matter if we are at end of message or not... */
+ DBGPRINTF("error: message received is larger than max msg size, we %s it - c=%x\n",
+ pThis->pSrv->discardTruncatedMsg == 1 ? "truncate" : "split", c);
+ defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+ if(pThis->pSrv->discardTruncatedMsg == 1) {
+ if (pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ pThis->iOctetsRemain--;
+ if (pThis->iOctetsRemain == 0) {
+ pThis->inputState = eAtStrtFram;
+ FINALIZE;
+ }
+ }
+ pThis->inputState = eInMsgTruncating;
+ FINALIZE;
+ }
+ }
+ }
+
+ if(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ /* do we need to find end-of-frame via octet counting? */
+ pThis->iOctetsRemain--;
+ if(pThis->iOctetsRemain < 1) {
+ /* we have end of frame! */
+ defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub);
+ ++(*pnMsgs);
+ pThis->inputState = eAtStrtFram;
+ }
+ }
+ } else if(pThis->inputState == eInMsgTruncating) {
+ if(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ DBGPRINTF("DEBUG: TCP_FRAMING_OCTET_COUNTING eInMsgTruncating c=%c remain=%d\n",
+ c, pThis->iOctetsRemain);
+
+ pThis->iOctetsRemain--;
+ if(pThis->iOctetsRemain < 1) {
+ pThis->inputState = eAtStrtFram;
+ }
+ } else {
+ if( ((c == '\n') && !pThis->pSrv->bDisableLFDelim)
+ || ((pThis->pSrv->addtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER)
+ && (c == pThis->pSrv->addtlFrameDelim))
+ ) {
+ pThis->inputState = eAtStrtFram;
+ }
+ }
+ } else {
+ assert(pThis->inputState == eInOctetCnt);
+ if(c >= '0' && c <= '9') { /* isdigit() the faster way */
+ if(pThis->iOctetsRemain <= 200000000) {
+ pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0';
+ }
+ if(pThis->iMsg < pThis->iMaxLine) {
+ *(pThis->pMsg + pThis->iMsg++) = c;
+ }
+ } else { /* done with the octet count, so this must be the SP terminator */
+ uchar *propPeerName = NULL;
+ uchar *propPeerIP = NULL;
+ int lenPeerName = 0;
+ int lenPeerIP = 0;
+ DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain);
+ prop.GetString(pThis->fromHost, &propPeerName, &lenPeerName);
+ prop.GetString(pThis->fromHost, &propPeerIP, &lenPeerIP);
+ if(c != ' ') {
+ LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from "
+ "peer: (hostname) %s, (ip) %s: delimiter is not SP but has "
+ "ASCII value %d.", cnf_params->pszInputName, propPeerName, propPeerIP, c);
+ }
+ if(pThis->iOctetsRemain < 1) {
+ /* TODO: handle the case where the octet count is 0! */
+ LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from "
+ "peer: (hostname) %s, (ip) %s: invalid octet count %d.",
+ cnf_params->pszInputName, propPeerName, propPeerIP, pThis->iOctetsRemain);
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ } else if(pThis->iOctetsRemain > pThis->iMaxLine) {
+ /* while we can not do anything against it, we can at least log an indication
+ * that something went wrong) -- rgerhards, 2008-03-14
+ */
+ LogError(0, NO_ERRCODE, "imtcp %s: received oversize message from peer: "
+ "(hostname) %s, (ip) %s: size is %d bytes, max msg size "
+ "is %d, truncating...", cnf_params->pszInputName, propPeerName,
+ propPeerIP, pThis->iOctetsRemain, pThis->iMaxLine);
+ }
+ if(pThis->iOctetsRemain > pThis->pSrv->maxFrameSize) {
+ LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from "
+ "peer: (hostname) %s, (ip) %s: frame too large: %d, change "
+ "to octet stuffing", cnf_params->pszInputName, propPeerName, propPeerIP,
+ pThis->iOctetsRemain);
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ } else {
+ pThis->iMsg = 0;
+ }
+ pThis->inputState = eInMsg;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Processes the data received via a TCP session. If there
+ * is no other way to handle it, data is discarded.
+ * Input parameter data is the data received, iLen is its
+ * len as returned from recv(). iLen must be 1 or more (that
+ * is errors must be handled by caller!). iTCPSess must be
+ * the index of the TCP session that received the data.
+ * rgerhards 2005-07-04
+ * And another change while generalizing. We now return either
+ * RS_RET_OK, which means the session should be kept open
+ * or anything else, which means it must be closed.
+ * rgerhards, 2008-03-01
+ * As a performance optimization, we pick up the timestamp here. Acutally,
+ * this *is* the *correct* reception step for all the data we received, because
+ * we have just received a bunch of data! -- rgerhards, 2009-06-16
+ */
+#define NUM_MULTISUB 1024
+static rsRetVal
+DataRcvd(tcps_sess_t *pThis, char *pData, const size_t iLen)
+{
+ multi_submit_t multiSub;
+ smsg_t *pMsgs[NUM_MULTISUB];
+ struct syslogTime stTime;
+ time_t ttGenTime;
+ char *pEnd;
+ unsigned nMsgs = 0;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcps_sess);
+ assert(pData != NULL);
+ assert(iLen > 0);
+
+ datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME);
+ multiSub.ppMsgs = pMsgs;
+ multiSub.maxElem = NUM_MULTISUB;
+ multiSub.nElem = 0;
+
+ /* We now copy the message to the session buffer. */
+ pEnd = pData + iLen; /* this is one off, which is intensional */
+
+ while(pData < pEnd) {
+ CHKiRet(processDataRcvd(pThis, *pData++, &stTime, ttGenTime, &multiSub, &nMsgs));
+ }
+ iRet = multiSubmitFlush(&multiSub);
+
+ if(runConf->globals.senderKeepTrack)
+ statsRecordSender(propGetSzStr(pThis->fromHost), nMsgs, ttGenTime);
+
+finalize_it:
+ RETiRet;
+}
+#undef NUM_MULTISUB
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(tcps_sess)
+CODESTARTobjQueryInterface(tcps_sess)
+ if(pIf->ifVersion != tcps_sessCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->DebugPrint = tcps_sessDebugPrint;
+ pIf->Construct = tcps_sessConstruct;
+ pIf->ConstructFinalize = tcps_sessConstructFinalize;
+ pIf->Destruct = tcps_sessDestruct;
+
+ pIf->PrepareClose = PrepareClose;
+ pIf->Close = Close;
+ pIf->DataRcvd = DataRcvd;
+
+ pIf->SetUsrP = SetUsrP;
+ pIf->SetTcpsrv = SetTcpsrv;
+ pIf->SetLstnInfo = SetLstnInfo;
+ pIf->SetHost = SetHost;
+ pIf->SetHostIP = SetHostIP;
+ pIf->SetStrm = SetStrm;
+ pIf->SetMsgIdx = SetMsgIdx;
+ pIf->SetOnMsgReceive = SetOnMsgReceive;
+finalize_it:
+ENDobjQueryInterface(tcps_sess)
+
+
+/* exit our class
+ * rgerhards, 2008-03-10
+ */
+BEGINObjClassExit(tcps_sess, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(tcps_sess)
+ /* release objects we no longer need */
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDObjClassExit(tcps_sess)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-29
+ */
+BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ /* request objects we use */
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ objRelease(glbl, CORE_COMPONENT);
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcps_sessDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcps_sessConstructFinalize);
+ENDObjClassInit(tcps_sess)
+
+/* vim:set ai:
+ */
diff --git a/runtime/tcps_sess.h b/runtime/tcps_sess.h
new file mode 100644
index 0000000..578b559
--- /dev/null
+++ b/runtime/tcps_sess.h
@@ -0,0 +1,90 @@
+/* Definitions for tcps_sess class. This implements a session of the
+ * plain TCP server.
+ *
+ * Copyright 2008-2022 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_TCPS_SESS_H
+#define INCLUDED_TCPS_SESS_H
+
+#include "obj.h"
+#include "prop.h"
+
+/* a forward-definition, we are somewhat cyclic */
+struct tcpsrv_s;
+
+/* the tcps_sess object */
+struct tcps_sess_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ tcpsrv_t *pSrv; /* pointer back to my server (e.g. for callbacks) */
+ tcpLstnPortList_t *pLstnInfo; /* pointer back to listener info */
+ netstrm_t *pStrm;
+ int iMsg; /* index of next char to store in msg */
+ sbool bSuppOctetFram; /**< copy from listener, to speed up access */
+ sbool bSPFramingFix;
+ enum {
+ eAtStrtFram,
+ eInOctetCnt,
+ eInMsg,
+ eInMsgTruncating
+ } inputState; /* our current state */
+ int iOctetsRemain; /* Number of Octets remaining in message */
+ TCPFRAMINGMODE eFraming;
+ uchar *pMsg; /* message (fragment) received */
+ prop_t *fromHost; /* host name we received messages from */
+ prop_t *fromHostIP;
+ void *pUsr; /* a user-pointer */
+ rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit message callback */
+ int iMaxLine; /* fast lookup buffer for config property */
+};
+
+
+/* interfaces */
+BEGINinterface(tcps_sess) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(tcps_sess);
+ rsRetVal (*Construct)(tcps_sess_t **ppThis);
+ rsRetVal (*ConstructFinalize)(tcps_sess_t __attribute__((unused)) *pThis);
+ rsRetVal (*Destruct)(tcps_sess_t **ppThis);
+ rsRetVal (*PrepareClose)(tcps_sess_t *pThis);
+ rsRetVal (*Close)(tcps_sess_t *pThis);
+ rsRetVal (*DataRcvd)(tcps_sess_t *pThis, char *pData, size_t iLen);
+ /* set methods */
+ rsRetVal (*SetTcpsrv)(tcps_sess_t *pThis, struct tcpsrv_s *pSrv);
+ rsRetVal (*SetLstnInfo)(tcps_sess_t *pThis, tcpLstnPortList_t *pLstnInfo);
+ rsRetVal (*SetUsrP)(tcps_sess_t*, void*);
+ rsRetVal (*SetHost)(tcps_sess_t *pThis, uchar*);
+ rsRetVal (*SetHostIP)(tcps_sess_t *pThis, prop_t*);
+ rsRetVal (*SetStrm)(tcps_sess_t *pThis, netstrm_t*);
+ rsRetVal (*SetMsgIdx)(tcps_sess_t *pThis, int);
+ rsRetVal (*SetOnMsgReceive)(tcps_sess_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int));
+ENDinterface(tcps_sess)
+#define tcps_sessCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+/* interface changes
+ * to version v2, rgerhards, 2009-05-22
+ * - Data structures changed
+ * - SetLstnInfo entry point added
+ * version 3, rgerhards, 2013-01-21:
+ * - signature of SetHostIP() changed
+ */
+
+
+/* prototypes */
+PROTOTYPEObj(tcps_sess);
+
+
+#endif /* #ifndef INCLUDED_TCPS_SESS_H */
diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c
new file mode 100644
index 0000000..df9bcec
--- /dev/null
+++ b/runtime/tcpsrv.c
@@ -0,0 +1,1799 @@
+/* tcpsrv.c
+ *
+ * Common code for plain TCP syslog based servers. This is currently being
+ * utilized by imtcp and imgssapi.
+ *
+ * NOTE: this is *not* a generic TCP server, but one for syslog servers. For
+ * generic stream servers, please use ./runtime/strmsrv.c!
+ *
+ * There are actually two classes within the tcpserver code: one is
+ * the tcpsrv itself, the other one is its sessions. This is a helper
+ * class to tcpsrv.
+ *
+ * The common code here calls upon specific functionality by using
+ * callbacks. The specialised input modules need to set the proper
+ * callbacks before the code is run. The tcpsrv then calls back
+ * into the specific input modules at the appropriate time.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-12-21 by RGerhards (extracted from syslogd.c[which was
+ * licensed under BSD at the time of the rsyslog fork])
+ *
+ * Copyright 2007-2022 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "net.h"
+#include "srUtils.h"
+#include "conf.h"
+#include "tcpsrv.h"
+#include "obj.h"
+#include "glbl.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "nssel.h"
+#include "nspoll.h"
+#include "errmsg.h"
+#include "ruleset.h"
+#include "ratelimit.h"
+#include "unicode-helper.h"
+
+PRAGMA_INGORE_Wswitch_enum
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* defines */
+#define TCPSESS_MAX_DEFAULT 200 /* default for nbr of tcp sessions if no number is given */
+#define TCPLSTN_MAX_DEFAULT 20 /* default for nbr of listeners */
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(conf)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(tcps_sess)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(nssel)
+DEFobjCurrIf(nspoll)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(statsobj)
+
+static void startWorkerPool(void);
+
+/* The following structure controls the worker threads. Global data is
+ * needed for their access.
+ */
+static struct wrkrInfo_s {
+ pthread_t tid; /* the worker's thread ID */
+ pthread_cond_t run;
+ int idx;
+ tcpsrv_t *pSrv; /* pSrv == NULL -> idle */
+ nspoll_t *pPoll;
+ void *pUsr;
+ sbool enabled;
+ long long unsigned numCalled; /* how often was this called */
+} wrkrInfo[4];
+static sbool bWrkrRunning; /* are the worker threads running? */
+static pthread_mutex_t wrkrMut;
+static pthread_cond_t wrkrIdle;
+static int wrkrMax = 4;
+static int wrkrRunning;
+
+/* add new listener port to listener port list
+ * rgerhards, 2009-05-21
+ */
+static rsRetVal ATTR_NONNULL(1, 2)
+addNewLstnPort(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params)
+{
+ tcpLstnPortList_t *pEntry;
+ uchar statname[64];
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ /* create entry */
+ CHKmalloc(pEntry = (tcpLstnPortList_t*)calloc(1, sizeof(tcpLstnPortList_t)));
+ pEntry->cnf_params = cnf_params;
+
+ strcpy((char*)pEntry->cnf_params->dfltTZ, (char*)pThis->dfltTZ);
+ pEntry->cnf_params->bSPFramingFix = pThis->bSPFramingFix;
+ pEntry->cnf_params->bPreserveCase = pThis->bPreserveCase;
+ pEntry->pSrv = pThis;
+
+
+ /* support statistics gathering */
+ CHKiRet(ratelimitNew(&pEntry->ratelimiter, "tcperver", NULL));
+ ratelimitSetLinuxLike(pEntry->ratelimiter, pThis->ratelimitInterval, pThis->ratelimitBurst);
+ ratelimitSetThreadSafe(pEntry->ratelimiter);
+
+ CHKiRet(statsobj.Construct(&(pEntry->stats)));
+ snprintf((char*)statname, sizeof(statname), "%s(%s)", cnf_params->pszInputName, cnf_params->pszPort);
+ statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ CHKiRet(statsobj.SetName(pEntry->stats, statname));
+ CHKiRet(statsobj.SetOrigin(pEntry->stats, pThis->pszOrigin));
+ STATSCOUNTER_INIT(pEntry->ctrSubmit, pEntry->mutCtrSubmit);
+ CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrSubmit)));
+ CHKiRet(statsobj.ConstructFinalize(pEntry->stats));
+
+ /* all OK - add to list */
+ pEntry->pNext = pThis->pLstnPorts;
+ pThis->pLstnPorts = pEntry;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pEntry != NULL) {
+ if(pEntry->cnf_params->pInputName != NULL) {
+ prop.Destruct(&pEntry->cnf_params->pInputName);
+ }
+ if(pEntry->ratelimiter != NULL) {
+ ratelimitDestruct(pEntry->ratelimiter);
+ }
+ if(pEntry->stats != NULL) {
+ statsobj.Destruct(&pEntry->stats);
+ }
+ free(pEntry);
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* configure TCP listener settings.
+ * Note: pszPort is handed over to us - the caller MUST NOT free it!
+ * rgerhards, 2008-03-20
+ */
+static rsRetVal ATTR_NONNULL(1,2)
+configureTCPListen(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params)
+{
+ assert(cnf_params->pszPort != NULL);
+ int i;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ /* extract port */
+ const uchar *pPort = cnf_params->pszPort;
+ i = 0;
+ while(isdigit((int) *pPort)) {
+ i = i * 10 + *pPort++ - '0';
+ }
+
+ if(i >= 0 && i <= 65535) {
+ CHKiRet(addNewLstnPort(pThis, cnf_params));
+ } else {
+ LogError(0, NO_ERRCODE, "Invalid TCP listen port %s - ignored.\n", cnf_params->pszPort);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Initialize the session table
+ * returns 0 if OK, somewhat else otherwise
+ */
+static rsRetVal
+TCPSessTblInit(tcpsrv_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ assert(pThis->pSessions == NULL);
+
+ DBGPRINTF("Allocating buffer for %d TCP sessions.\n", pThis->iSessMax);
+ if((pThis->pSessions = (tcps_sess_t **) calloc(pThis->iSessMax, sizeof(tcps_sess_t *))) == NULL) {
+ DBGPRINTF("Error: TCPSessInit() could not alloc memory for TCP session table.\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* find a free spot in the session table. If the table
+ * is full, -1 is returned, else the index of the free
+ * entry (0 or higher).
+ */
+static int
+TCPSessTblFindFreeSpot(tcpsrv_t *pThis)
+{
+ register int i;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ for(i = 0 ; i < pThis->iSessMax ; ++i) {
+ if(pThis->pSessions[i] == NULL)
+ break;
+ }
+
+ return((i < pThis->iSessMax) ? i : -1);
+}
+
+
+/* Get the next session index. Free session tables entries are
+ * skipped. This function is provided the index of the last
+ * session entry, or -1 if no previous entry was obtained. It
+ * returns the index of the next session or -1, if there is no
+ * further entry in the table. Please note that the initial call
+ * might as well return -1, if there is no session at all in the
+ * session table.
+ */
+static int
+TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr)
+{
+ register int i;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ assert(pThis->pSessions != NULL);
+ for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) {
+ if(pThis->pSessions[i] != NULL)
+ break;
+ }
+
+ return((i < pThis->iSessMax) ? i : -1);
+}
+
+
+/* De-Initialize TCP listner sockets.
+ * This function deinitializes everything, including freeing the
+ * session table. No TCP listen receive operations are permitted
+ * unless the subsystem is reinitialized.
+ * rgerhards, 2007-06-21
+ */
+static void ATTR_NONNULL()
+deinit_tcp_listener(tcpsrv_t *const pThis)
+{
+ int i;
+ tcpLstnPortList_t *pEntry;
+ tcpLstnPortList_t *pDel;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ if(pThis->pSessions != NULL) {
+ /* close all TCP connections! */
+ if(!pThis->bUsingEPoll) {
+ i = TCPSessGetNxtSess(pThis, -1);
+ while(i != -1) {
+ tcps_sess.Destruct(&pThis->pSessions[i]);
+ /* now get next... */
+ i = TCPSessGetNxtSess(pThis, i);
+ }
+ }
+
+ /* we are done with the session table - so get rid of it... */
+ free(pThis->pSessions);
+ pThis->pSessions = NULL; /* just to make sure... */
+ }
+
+ /* free list of tcp listen ports */
+ pEntry = pThis->pLstnPorts;
+ while(pEntry != NULL) {
+ prop.Destruct(&pEntry->cnf_params->pInputName);
+ free((void*)pEntry->cnf_params->pszInputName);
+ free((void*)pEntry->cnf_params->pszPort);
+ free((void*)pEntry->cnf_params->pszAddr);
+ free((void*)pEntry->cnf_params->pszLstnPortFileName);
+ free((void*)pEntry->cnf_params);
+ ratelimitDestruct(pEntry->ratelimiter);
+ statsobj.Destruct(&(pEntry->stats));
+ pDel = pEntry;
+ pEntry = pEntry->pNext;
+ free(pDel);
+ }
+
+ /* finally close our listen streams */
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
+ netstrm.Destruct(pThis->ppLstn + i);
+ }
+}
+
+
+/* add a listen socket to our listen socket array. This is a callback
+ * invoked from the netstrm class. -- rgerhards, 2008-04-23
+ */
+static rsRetVal
+addTcpLstn(void *pUsr, netstrm_t *pLstn)
+{
+ tcpLstnPortList_t *pPortList = (tcpLstnPortList_t *) pUsr;
+ tcpsrv_t *pThis = pPortList->pSrv;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ ISOBJ_TYPE_assert(pLstn, netstrm);
+
+ if(pThis->iLstnCurr >= pThis->iLstnMax)
+ ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED);
+
+ pThis->ppLstn[pThis->iLstnCurr] = pLstn;
+ pThis->ppLstnPort[pThis->iLstnCurr] = pPortList;
+ ++pThis->iLstnCurr;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Initialize TCP listener socket for a single port
+ * Note: at this point, TLS vs. non-TLS does not matter; TLS params are
+ * set on connect!
+ * rgerhards, 2009-05-21
+ */
+static rsRetVal
+initTCPListener(tcpsrv_t *pThis, tcpLstnPortList_t *pPortEntry)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ assert(pPortEntry != NULL);
+
+ // pPortEntry->pszAddr = NULL ==> bind to all interfaces
+ CHKiRet(netstrm.LstnInit(pThis->pNS, (void*)pPortEntry, addTcpLstn,
+ pThis->iSessMax, pPortEntry->cnf_params));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Initialize TCP sockets (for listener) and listens on them */
+static rsRetVal
+create_tcp_socket(tcpsrv_t *pThis)
+{
+ DEFiRet;
+ rsRetVal localRet;
+ tcpLstnPortList_t *pEntry;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ /* init all configured ports */
+ pEntry = pThis->pLstnPorts;
+ while(pEntry != NULL) {
+ localRet = initTCPListener(pThis, pEntry);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "Could not create tcp listener, ignoring port "
+ "%s bind-address %s.",
+ (pEntry->cnf_params->pszPort == NULL) ? "**UNSPECIFIED**"
+ : (const char*) pEntry->cnf_params->pszPort,
+ (pEntry->cnf_params->pszAddr == NULL) ? "**UNSPECIFIED**"
+ : (const char*)pEntry->cnf_params->pszAddr);
+ }
+ pEntry = pEntry->pNext;
+ }
+
+ /* OK, we had success. Now it is also time to
+ * initialize our connections
+ */
+ if(TCPSessTblInit(pThis) != 0) {
+ /* OK, we are in some trouble - we could not initialize the
+ * session table, so we can not continue. We need to free all
+ * we have assigned so far, because we can not really use it...
+ */
+ LogError(0, RS_RET_ERR, "Could not initialize TCP session table, suspending TCP "
+ "message reception.");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Accept new TCP connection; make entry in session table. If there
+ * is no more space left in the connection table, the new TCP
+ * connection is immediately dropped.
+ * ppSess has a pointer to the newly created session, if it succeeds.
+ * If it does not succeed, no session is created and ppSess is
+ * undefined. If the user has provided an OnSessAccept Callback,
+ * this one is executed immediately after creation of the
+ * session object, so that it can do its own initialization.
+ * rgerhards, 2008-03-02
+ */
+static rsRetVal
+SessAccept(tcpsrv_t *pThis, tcpLstnPortList_t *pLstnInfo, tcps_sess_t **ppSess, netstrm_t *pStrm)
+{
+ DEFiRet;
+ tcps_sess_t *pSess = NULL;
+ netstrm_t *pNewStrm = NULL;
+ const tcpLstnParams_t *const cnf_params = pLstnInfo->cnf_params;
+ int iSess = -1;
+ struct sockaddr_storage *addr;
+ uchar *fromHostFQDN = NULL;
+ prop_t *fromHostIP = NULL;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ assert(pLstnInfo != NULL);
+
+ CHKiRet(netstrm.AcceptConnReq(pStrm, &pNewStrm));
+
+ /* Add to session list */
+ iSess = TCPSessTblFindFreeSpot(pThis);
+ if(iSess == -1) {
+ errno = 0;
+ LogError(0, RS_RET_MAX_SESS_REACHED, "too many tcp sessions - dropping incoming request");
+ ABORT_FINALIZE(RS_RET_MAX_SESS_REACHED);
+ }
+
+ if(pThis->bUseKeepAlive) {
+ CHKiRet(netstrm.SetKeepAliveProbes(pNewStrm, pThis->iKeepAliveProbes));
+ CHKiRet(netstrm.SetKeepAliveTime(pNewStrm, pThis->iKeepAliveTime));
+ CHKiRet(netstrm.SetKeepAliveIntvl(pNewStrm, pThis->iKeepAliveIntvl));
+ CHKiRet(netstrm.EnableKeepAlive(pNewStrm));
+ }
+
+ /* we found a free spot and can construct our session object */
+ if(pThis->gnutlsPriorityString != NULL) {
+ CHKiRet(netstrm.SetGnutlsPriorityString(pNewStrm, pThis->gnutlsPriorityString));
+ }
+ CHKiRet(tcps_sess.Construct(&pSess));
+ CHKiRet(tcps_sess.SetTcpsrv(pSess, pThis));
+ CHKiRet(tcps_sess.SetLstnInfo(pSess, pLstnInfo));
+ if(pThis->OnMsgReceive != NULL)
+ CHKiRet(tcps_sess.SetOnMsgReceive(pSess, pThis->OnMsgReceive));
+
+ /* get the host name */
+ CHKiRet(netstrm.GetRemoteHName(pNewStrm, &fromHostFQDN));
+ if (!cnf_params->bPreserveCase) {
+ /* preserve_case = off */
+ uchar *p;
+ for(p = fromHostFQDN; *p; p++) {
+ if (isupper((int) *p)) {
+ *p = tolower((int) *p);
+ }
+ }
+ }
+ CHKiRet(netstrm.GetRemoteIP(pNewStrm, &fromHostIP));
+ CHKiRet(netstrm.GetRemAddr(pNewStrm, &addr));
+ /* TODO: check if we need to strip the domain name here -- rgerhards, 2008-04-24 */
+
+ /* Here we check if a host is permitted to send us messages. If it isn't, we do not further
+ * process the message but log a warning (if we are configured to do this).
+ * rgerhards, 2005-09-26
+ */
+ if(!pThis->pIsPermittedHost((struct sockaddr*) addr, (char*) fromHostFQDN, pThis->pUsr, pSess->pUsr)) {
+ DBGPRINTF("%s is not an allowed sender\n", fromHostFQDN);
+ if(glbl.GetOptionDisallowWarning(runConf)) {
+ errno = 0;
+ LogError(0, RS_RET_HOST_NOT_PERMITTED, "connection request from disallowed "
+ "sender %s discarded", fromHostFQDN);
+ }
+ ABORT_FINALIZE(RS_RET_HOST_NOT_PERMITTED);
+ }
+
+ /* OK, we have an allowed sender, so let's continue, what
+ * means we can finally fill in the session object.
+ */
+ CHKiRet(tcps_sess.SetHost(pSess, fromHostFQDN));
+ fromHostFQDN = NULL; /* we handed this string over */
+ CHKiRet(tcps_sess.SetHostIP(pSess, fromHostIP));
+ CHKiRet(tcps_sess.SetStrm(pSess, pNewStrm));
+ pNewStrm = NULL; /* prevent it from being freed in error handler, now done in tcps_sess! */
+ CHKiRet(tcps_sess.SetMsgIdx(pSess, 0));
+ CHKiRet(tcps_sess.ConstructFinalize(pSess));
+
+ /* check if we need to call our callback */
+ if(pThis->pOnSessAccept != NULL) {
+ CHKiRet(pThis->pOnSessAccept(pThis, pSess));
+ }
+
+ *ppSess = pSess;
+ if(!pThis->bUsingEPoll)
+ pThis->pSessions[iSess] = pSess;
+ pSess = NULL; /* this is now also handed over */
+
+ if(pThis->bEmitMsgOnOpen) {
+ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
+ "imtcp: connection established with host: %s",
+ propGetSzStr(fromHostIP));
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(iRet != RS_RET_HOST_NOT_PERMITTED && pThis->bEmitMsgOnOpen) {
+ LogError(0, NO_ERRCODE, "imtcp: connection could not be "
+ "established with host: %s",
+ fromHostIP == NULL ? "(IP unknown)"
+ : (const char*)propGetSzStr(fromHostIP));
+ }
+ if(pSess != NULL)
+ tcps_sess.Destruct(&pSess);
+ if(pNewStrm != NULL)
+ netstrm.Destruct(&pNewStrm);
+ free(fromHostFQDN);
+ }
+
+ RETiRet;
+}
+
+
+static void
+RunCancelCleanup(void *arg)
+{
+ nspoll_t **ppPoll = (nspoll_t**) arg;
+
+ if (*ppPoll != NULL)
+ nspoll.Destruct(ppPoll);
+
+ /* Wait for any running workers to finish */
+ pthread_mutex_lock(&wrkrMut);
+ DBGPRINTF("tcpsrv terminating, waiting for %d workers\n", wrkrRunning);
+ while(wrkrRunning > 0) {
+ pthread_cond_wait(&wrkrIdle, &wrkrMut);
+ }
+ pthread_mutex_unlock(&wrkrMut);
+}
+
+static void
+RunSelectCancelCleanup(void *arg)
+{
+ nssel_t **ppSel = (nssel_t**) arg;
+
+ if(*ppSel != NULL)
+ nssel.Destruct(ppSel);
+}
+
+
+/* helper to close a session. Takes status of poll vs. select into consideration.
+ * rgerhards, 2009-11-25
+ */
+static rsRetVal
+closeSess(tcpsrv_t *pThis, tcps_sess_t **ppSess, nspoll_t *pPoll) {
+ DEFiRet;
+ if(pPoll != NULL) {
+ CHKiRet(nspoll.Ctl(pPoll, (*ppSess)->pStrm, 0, *ppSess, NSDPOLL_IN, NSDPOLL_DEL));
+ }
+ pThis->pOnRegularClose(*ppSess);
+ tcps_sess.Destruct(ppSess);
+finalize_it:
+ RETiRet;
+}
+
+
+/* process a receive request on one of the streams
+ * If pPoll is non-NULL, we have a netstream in epoll mode, which means we need
+ * to remove any descriptor we close from the epoll set.
+ * rgerhards, 2009-07-020
+ */
+static rsRetVal
+doReceive(tcpsrv_t *pThis, tcps_sess_t **ppSess, nspoll_t *pPoll)
+{
+ char buf[128*1024]; /* reception buffer - may hold a partial or multiple messages */
+ ssize_t iRcvd;
+ rsRetVal localRet;
+ DEFiRet;
+ uchar *pszPeer;
+ int lenPeer;
+ int oserr = 0;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
+ DBGPRINTF("netstream %p with new data from remote peer %s\n", (*ppSess)->pStrm, pszPeer);
+ /* Receive message */
+ iRet = pThis->pRcvData(*ppSess, buf, sizeof(buf), &iRcvd, &oserr);
+ switch(iRet) {
+ case RS_RET_CLOSED:
+ if(pThis->bEmitMsgOnClose) {
+ errno = 0;
+ LogError(0, RS_RET_PEER_CLOSED_CONN, "Netstream session %p closed by remote "
+ "peer %s.\n", (*ppSess)->pStrm, pszPeer);
+ }
+ CHKiRet(closeSess(pThis, ppSess, pPoll));
+ break;
+ case RS_RET_RETRY:
+ /* we simply ignore retry - this is not an error, but we also have not received anything */
+ break;
+ case RS_RET_OK:
+ /* valid data received, process it! */
+ localRet = tcps_sess.DataRcvd(*ppSess, buf, iRcvd);
+ if(localRet != RS_RET_OK && localRet != RS_RET_QUEUE_FULL) {
+ /* in this case, something went awfully wrong.
+ * We are instructed to terminate the session.
+ */
+ LogError(oserr, localRet, "Tearing down TCP Session from %s", pszPeer);
+ CHKiRet(closeSess(pThis, ppSess, pPoll));
+ }
+ break;
+ default:
+ LogError(oserr, iRet, "netstream session %p from %s will be closed due to error",
+ (*ppSess)->pStrm, pszPeer);
+ CHKiRet(closeSess(pThis, ppSess, pPoll));
+ break;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+/* process a single workset item
+ */
+static rsRetVal ATTR_NONNULL(1)
+processWorksetItem(tcpsrv_t *const pThis, nspoll_t *pPoll, const int idx, void *pUsr)
+{
+ tcps_sess_t *pNewSess = NULL;
+ tcpLstnParams_t *cnf_params;
+
+ DEFiRet;
+
+ DBGPRINTF("tcpsrv: processing item %d, pUsr %p, bAbortConn\n", idx, pUsr);
+ if(pUsr == pThis->ppLstn) {
+ DBGPRINTF("New connect on NSD %p.\n", pThis->ppLstn[idx]);
+ iRet = SessAccept(pThis, pThis->ppLstnPort[idx], &pNewSess, pThis->ppLstn[idx]);
+ cnf_params = pThis->ppLstnPort[idx]->cnf_params;
+ if(iRet == RS_RET_OK) {
+ if(pPoll != NULL) {
+ CHKiRet(nspoll.Ctl(pPoll, pNewSess->pStrm, 0, pNewSess, NSDPOLL_IN, NSDPOLL_ADD));
+ }
+ DBGPRINTF("New session created with NSD %p.\n", pNewSess);
+ } else {
+ DBGPRINTF("tcpsrv: error %d during accept\n", iRet);
+ }
+ } else {
+ pNewSess = (tcps_sess_t*) pUsr;
+ cnf_params = pNewSess->pLstnInfo->cnf_params;
+ doReceive(pThis, &pNewSess, pPoll);
+ if(pPoll == NULL && pNewSess == NULL) {
+ pThis->pSessions[idx] = NULL;
+ }
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "tcpsrv listener (inputname: '%s') failed "
+ "to process incoming connection with error %d",
+ (cnf_params->pszInputName == NULL) ? (uchar*)"*UNSET*" : cnf_params->pszInputName, iRet);
+ srSleep(0,20000); /* Sleep 20ms */
+ }
+ RETiRet;
+}
+
+
+/* worker to process incoming requests
+ */
+static void * ATTR_NONNULL(1)
+wrkr(void *const myself)
+{
+ struct wrkrInfo_s *const me = (struct wrkrInfo_s*) myself;
+
+
+ pthread_mutex_lock(&wrkrMut);
+ while(1) {
+ // wait for work, in which case pSrv will be populated
+ while(me->pSrv == NULL && glbl.GetGlobalInputTermState() == 0) {
+ pthread_cond_wait(&me->run, &wrkrMut);
+ }
+ if(me->pSrv == NULL) {
+ // only possible if glbl.GetGlobalInputTermState() == 1
+ // we need to query me->opSrv to avoid clang static
+ // analyzer false positive! -- rgerhards, 2017-10-23
+ assert(glbl.GetGlobalInputTermState() == 1);
+ break;
+ }
+ pthread_mutex_unlock(&wrkrMut);
+
+ ++me->numCalled;
+ processWorksetItem(me->pSrv, me->pPoll, me->idx, me->pUsr);
+
+ pthread_mutex_lock(&wrkrMut);
+ me->pSrv = NULL; /* indicate we are free again */
+ --wrkrRunning;
+ pthread_cond_broadcast(&wrkrIdle);
+ }
+ me->enabled = 0; /* indicate we are no longer available */
+ pthread_mutex_unlock(&wrkrMut);
+
+ return NULL;
+}
+
+/* This has been factored out from processWorkset() because
+ * pthread_cleanup_push() invokes setjmp() and this triggers the -Wclobbered
+ * warning for the iRet variable.
+ */
+static void
+waitForWorkers(void)
+{
+ pthread_mutex_lock(&wrkrMut);
+ pthread_cleanup_push(mutexCancelCleanup, &wrkrMut);
+ while(wrkrRunning > 0) {
+ pthread_cond_wait(&wrkrIdle, &wrkrMut);
+ }
+ pthread_cleanup_pop(1);
+}
+
+/* Process a workset, that is handle io. We become activated
+ * from either select or epoll handler. We split the workload
+ * out to a pool of threads, but try to avoid context switches
+ * as much as possible.
+ */
+static rsRetVal
+processWorkset(tcpsrv_t *pThis, nspoll_t *pPoll, int numEntries, nsd_epworkset_t workset[])
+{
+ int i;
+ int origEntries = numEntries;
+ DEFiRet;
+
+ DBGPRINTF("tcpsrv: ready to process %d event entries\n", numEntries);
+
+ while(numEntries > 0) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ if(numEntries == 1) {
+ /* process self, save context switch */
+ iRet = processWorksetItem(pThis, pPoll, workset[numEntries-1].id, workset[numEntries-1].pUsr);
+ } else {
+ /* No cancel handler needed here, since no cancellation
+ * points are executed while wrkrMut is locked.
+ *
+ * Re-evaluate this if you add a DBGPRINTF or something!
+ */
+ pthread_mutex_lock(&wrkrMut);
+ /* check if there is a free worker */
+ for(i = 0 ; (i < wrkrMax) && ((wrkrInfo[i].pSrv != NULL) || (wrkrInfo[i].enabled == 0)) ; ++i)
+ /*do search*/;
+ if(i < wrkrMax) {
+ /* worker free -> use it! */
+ wrkrInfo[i].pSrv = pThis;
+ wrkrInfo[i].pPoll = pPoll;
+ wrkrInfo[i].idx = workset[numEntries -1].id;
+ wrkrInfo[i].pUsr = workset[numEntries -1].pUsr;
+ /* Note: we must increment wrkrRunning HERE and not inside the worker's
+ * code. This is because a worker may actually never start, and thus
+ * increment wrkrRunning, before we finish and check the running worker
+ * count. We can only avoid this by incrementing it here.
+ */
+ ++wrkrRunning;
+ pthread_cond_signal(&wrkrInfo[i].run);
+ pthread_mutex_unlock(&wrkrMut);
+ } else {
+ pthread_mutex_unlock(&wrkrMut);
+ /* no free worker, so we process this one ourselfs */
+ iRet = processWorksetItem(pThis, pPoll, workset[numEntries-1].id,
+ workset[numEntries-1].pUsr);
+ }
+ }
+ --numEntries;
+ }
+
+ if(origEntries > 1) {
+ /* we now need to wait until all workers finish. This is because the
+ * rest of this module can not handle the concurrency introduced
+ * by workers running during the epoll call.
+ */
+ waitForWorkers();
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called to gather input.
+ * This variant here is only used if we need to work with a netstream driver
+ * that does not support epoll().
+ */
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wempty_body
+static rsRetVal
+RunSelect(tcpsrv_t *pThis, nsd_epworkset_t workset[], size_t sizeWorkset)
+{
+ DEFiRet;
+ int nfds;
+ int i;
+ int iWorkset;
+ int iTCPSess;
+ int bIsReady;
+ nssel_t *pSel = NULL;
+ rsRetVal localRet;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ pthread_cleanup_push(RunSelectCancelCleanup, (void*) &pSel);
+ while(1) {
+ CHKiRet(nssel.Construct(&pSel));
+ if(pThis->pszDrvrName != NULL)
+ CHKiRet(nssel.SetDrvrName(pSel, pThis->pszDrvrName));
+ CHKiRet(nssel.ConstructFinalize(pSel));
+
+ /* Add the TCP listen sockets to the list of read descriptors. */
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
+ CHKiRet(nssel.Add(pSel, pThis->ppLstn[i], NSDSEL_RD));
+ }
+
+ /* do the sessions */
+ iTCPSess = TCPSessGetNxtSess(pThis, -1);
+ while(iTCPSess != -1) {
+ /* TODO: access to pNsd is NOT really CLEAN, use method... */
+ CHKiRet(nssel.Add(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD));
+ DBGPRINTF("tcpsrv process session %d:\n", iTCPSess);
+
+ /* now get next... */
+ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
+ }
+
+ /* wait for io to become ready */
+ CHKiRet(nssel.Wait(pSel, &nfds));
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ iWorkset = 0;
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ CHKiRet(nssel.IsReady(pSel, pThis->ppLstn[i], NSDSEL_RD, &bIsReady, &nfds));
+ if(bIsReady) {
+ workset[iWorkset].id = i;
+ workset[iWorkset].pUsr = (void*) pThis->ppLstn;
+ /* this is a flag to indicate listen sock */
+ ++iWorkset;
+ if(iWorkset >= (int) sizeWorkset) {
+ processWorkset(pThis, NULL, iWorkset, workset);
+ iWorkset = 0;
+ }
+ --nfds; /* indicate we have processed one */
+ }
+ }
+
+ /* now check the sessions */
+ iTCPSess = TCPSessGetNxtSess(pThis, -1);
+ while(nfds && iTCPSess != -1) {
+ if(glbl.GetGlobalInputTermState() == 1)
+ ABORT_FINALIZE(RS_RET_FORCE_TERM);
+ localRet = nssel.IsReady(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD,
+ &bIsReady, &nfds);
+ if(bIsReady || localRet != RS_RET_OK) {
+ workset[iWorkset].id = iTCPSess;
+ workset[iWorkset].pUsr = (void*) pThis->pSessions[iTCPSess];
+ ++iWorkset;
+ if(iWorkset >= (int) sizeWorkset) {
+ processWorkset(pThis, NULL, iWorkset, workset);
+ iWorkset = 0;
+ }
+ if(bIsReady)
+ --nfds; /* indicate we have processed one */
+ }
+ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
+ }
+
+ if(iWorkset > 0)
+ processWorkset(pThis, NULL, iWorkset, workset);
+
+ /* we need to copy back close descriptors */
+ nssel.Destruct(&pSel); /* no iRet check as it is overriden at start of loop! */
+finalize_it: /* this is a very special case - this time only we do not exit the function,
+ * because that would not help us either. So we simply retry it. Let's see
+ * if that actually is a better idea. Exiting the loop wasn't we always
+ * crashed, which made sense (the rest of the engine was not prepared for
+ * that) -- rgerhards, 2008-05-19
+ */
+ if(pSel != NULL) { /* cleanup missing? happens during err exit! */
+ nssel.Destruct(&pSel);
+ }
+ }
+
+ pthread_cleanup_pop(1); /* execute and remove cleanup handler */
+
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+static rsRetVal
+DoRun(tcpsrv_t *pThis, nspoll_t **ppPoll)
+{
+ DEFiRet;
+ int i;
+ nsd_epworkset_t workset[128]; /* 128 is currently fixed num of concurrent requests */
+ int numEntries;
+ nspoll_t *pPoll = NULL;
+ rsRetVal localRet;
+
+ if((localRet = nspoll.Construct(ppPoll)) == RS_RET_OK) {
+ pPoll = *ppPoll;
+ if(pThis->pszDrvrName != NULL)
+ CHKiRet(nspoll.SetDrvrName(pPoll, pThis->pszDrvrName));
+ localRet = nspoll.ConstructFinalize(pPoll);
+ }
+ if(localRet != RS_RET_OK) {
+ /* fall back to select */
+ DBGPRINTF("tcpsrv could not use epoll() interface, iRet=%d, using select()\n", localRet);
+ iRet = RunSelect(pThis, workset, sizeof(workset)/sizeof(nsd_epworkset_t));
+ FINALIZE;
+ }
+
+ DBGPRINTF("tcpsrv uses epoll() interface, nsdpoll driver found\n");
+
+ /* flag that we are in epoll mode */
+ pThis->bUsingEPoll = RSTRUE;
+
+ /* Add the TCP listen sockets to the list of sockets to monitor */
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
+ DBGPRINTF("Trying to add listener %d, pUsr=%p\n", i, pThis->ppLstn);
+ CHKiRet(nspoll.Ctl(pPoll, pThis->ppLstn[i], i, pThis->ppLstn, NSDPOLL_IN, NSDPOLL_ADD));
+ DBGPRINTF("Added listener %d\n", i);
+ }
+
+ while(glbl.GetGlobalInputTermState() == 0) {
+ numEntries = sizeof(workset)/sizeof(nsd_epworkset_t);
+ localRet = nspoll.Wait(pPoll, -1, &numEntries, workset);
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ /* check if we need to ignore the i/o ready state. We do this if we got an invalid
+ * return state. Validly, this can happen for RS_RET_EINTR, for other cases it may
+ * not be the right thing, but what is the right thing is really hard at this point...
+ */
+ if(localRet != RS_RET_OK)
+ continue;
+
+ processWorkset(pThis, pPoll, numEntries, workset);
+ }
+
+ /* remove the tcp listen sockets from the epoll set */
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
+ CHKiRet(nspoll.Ctl(pPoll, pThis->ppLstn[i], i, pThis->ppLstn, NSDPOLL_IN, NSDPOLL_DEL));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called to gather input. It tries doing that via the epoll()
+ * interface. If the driver does not support that, it falls back to calling its
+ * select() equivalent.
+ * rgerhards, 2009-11-18
+ */
+static rsRetVal
+Run(tcpsrv_t *pThis)
+{
+ DEFiRet;
+ nspoll_t *pPoll = NULL;
+
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ if(pThis->iLstnCurr == 0) {
+ dbgprintf("tcpsrv: no listeneres at all (probably init error), terminating\n");
+ RETiRet; /* somewhat "dirty" exit to avoid issue with cancel handler */
+ }
+
+ /* check if we need to start the worker pool. Once it is running, all is
+ * well. Shutdown is done on modExit.
+ */
+ d_pthread_mutex_lock(&wrkrMut);
+ if(!bWrkrRunning) {
+ bWrkrRunning = 1;
+ startWorkerPool();
+ }
+ d_pthread_mutex_unlock(&wrkrMut);
+
+ /* We try to terminate cleanly, but install a cancellation clean-up
+ * handler in case we are cancelled.
+ */
+ pthread_cleanup_push(RunCancelCleanup, (void*) &pPoll);
+ iRet = DoRun(pThis, &pPoll);
+ pthread_cleanup_pop(1);
+
+ RETiRet;
+}
+
+
+/* Standard-Constructor */
+BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macro! */
+ pThis->iSessMax = TCPSESS_MAX_DEFAULT;
+ pThis->iLstnMax = TCPLSTN_MAX_DEFAULT;
+ pThis->addtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ pThis->maxFrameSize = 200000;
+ pThis->bDisableLFDelim = 0;
+ pThis->discardTruncatedMsg = 0;
+ pThis->OnMsgReceive = NULL;
+ pThis->dfltTZ[0] = '\0';
+ pThis->bSPFramingFix = 0;
+ pThis->ratelimitInterval = 0;
+ pThis->ratelimitBurst = 10000;
+ pThis->bUseFlowControl = 1;
+ pThis->pszDrvrName = NULL;
+ pThis->bPreserveCase = 1; /* preserve case in fromhost; default to true. */
+ pThis->DrvrTlsVerifyDepth = 0;
+ENDobjConstruct(tcpsrv)
+
+
+/* ConstructionFinalizer */
+static rsRetVal
+tcpsrvConstructFinalize(tcpsrv_t *pThis)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+
+ /* prepare network stream subsystem */
+ CHKiRet(netstrms.Construct(&pThis->pNS));
+ if(pThis->pszDrvrName != NULL)
+ CHKiRet(netstrms.SetDrvrName(pThis->pNS, pThis->pszDrvrName));
+ CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode));
+ CHKiRet(netstrms.SetDrvrCheckExtendedKeyUsage(pThis->pNS, pThis->DrvrChkExtendedKeyUsage));
+ CHKiRet(netstrms.SetDrvrPrioritizeSAN(pThis->pNS, pThis->DrvrPrioritizeSan));
+ CHKiRet(netstrms.SetDrvrTlsVerifyDepth(pThis->pNS, pThis->DrvrTlsVerifyDepth));
+ if(pThis->pszDrvrAuthMode != NULL)
+ CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode));
+ /* Call SetDrvrPermitExpiredCerts required
+ * when param is NULL default handling for ExpiredCerts is set! */
+ CHKiRet(netstrms.SetDrvrPermitExpiredCerts(pThis->pNS, pThis->pszDrvrPermitExpiredCerts));
+ CHKiRet(netstrms.SetDrvrTlsCAFile(pThis->pNS, pThis->pszDrvrCAFile));
+ CHKiRet(netstrms.SetDrvrTlsCRLFile(pThis->pNS, pThis->pszDrvrCRLFile));
+ CHKiRet(netstrms.SetDrvrTlsKeyFile(pThis->pNS, pThis->pszDrvrKeyFile));
+ CHKiRet(netstrms.SetDrvrTlsCertFile(pThis->pNS, pThis->pszDrvrCertFile));
+ if(pThis->pPermPeers != NULL)
+ CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers));
+ if(pThis->gnutlsPriorityString != NULL)
+ CHKiRet(netstrms.SetDrvrGnutlsPriorityString(pThis->pNS, pThis->gnutlsPriorityString));
+ CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
+
+ /* set up listeners */
+ CHKmalloc(pThis->ppLstn = calloc(pThis->iLstnMax, sizeof(netstrm_t*)));
+ CHKmalloc(pThis->ppLstnPort = calloc(pThis->iLstnMax, sizeof(tcpLstnPortList_t*)));
+ iRet = pThis->OpenLstnSocks(pThis);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pNS != NULL)
+ netstrms.Destruct(&pThis->pNS);
+ LogError(0, iRet, "tcpsrv could not create listener (inputname: '%s')",
+ (pThis->pszInputName == NULL) ? (uchar*)"*UNSET*" : pThis->pszInputName);
+ }
+ RETiRet;
+}
+
+
+/* destructor for the tcpsrv object */
+BEGINobjDestruct(tcpsrv) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(tcpsrv)
+ if(pThis->OnDestruct != NULL)
+ pThis->OnDestruct(pThis->pUsr);
+
+ deinit_tcp_listener(pThis);
+
+ if(pThis->pNS != NULL)
+ netstrms.Destruct(&pThis->pNS);
+ free(pThis->pszDrvrName);
+ free(pThis->pszDrvrAuthMode);
+ free(pThis->pszDrvrPermitExpiredCerts);
+ free(pThis->pszDrvrCAFile);
+ free(pThis->pszDrvrCRLFile);
+ free(pThis->pszDrvrKeyFile);
+ free(pThis->pszDrvrCertFile);
+ free(pThis->ppLstn);
+ free(pThis->ppLstnPort);
+ free(pThis->pszInputName);
+ free(pThis->pszOrigin);
+ENDobjDestruct(tcpsrv)
+
+
+/* debugprint for the tcpsrv object */
+BEGINobjDebugPrint(tcpsrv) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(tcpsrv)
+ENDobjDebugPrint(tcpsrv)
+
+/* set functions */
+static rsRetVal
+SetCBIsPermittedHost(tcpsrv_t *pThis, int (*pCB)(struct sockaddr *addr, char *fromHostFQDN, void*, void*))
+{
+ DEFiRet;
+ pThis->pIsPermittedHost = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBRcvData(tcpsrv_t *pThis, rsRetVal (*pRcvData)(tcps_sess_t*, char*, size_t, ssize_t*, int*))
+{
+ DEFiRet;
+ pThis->pRcvData = pRcvData;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnListenDeinit(tcpsrv_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->pOnListenDeinit = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*, tcps_sess_t*))
+{
+ DEFiRet;
+ pThis->pOnSessAccept = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->OnDestruct = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnSessConstructFinalize(tcpsrv_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->OnSessConstructFinalize = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnSessDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*))
+{
+ DEFiRet;
+ pThis->pOnSessDestruct = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnRegularClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*))
+{
+ DEFiRet;
+ pThis->pOnRegularClose = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOnErrClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*))
+{
+ DEFiRet;
+ pThis->pOnErrClose = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetCBOpenLstnSocks(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*))
+{
+ DEFiRet;
+ pThis->OpenLstnSocks = pCB;
+ RETiRet;
+}
+
+static rsRetVal
+SetUsrP(tcpsrv_t *pThis, void *pUsr)
+{
+ DEFiRet;
+ pThis->pUsr = pUsr;
+ RETiRet;
+}
+
+static rsRetVal
+SetKeepAlive(tcpsrv_t *pThis, int iVal)
+{
+ DEFiRet;
+ DBGPRINTF("tcpsrv: keep-alive set to %d\n", iVal);
+ pThis->bUseKeepAlive = iVal;
+ RETiRet;
+}
+
+static rsRetVal
+SetKeepAliveIntvl(tcpsrv_t *pThis, int iVal)
+{
+ DEFiRet;
+ DBGPRINTF("tcpsrv: keep-alive interval set to %d\n", iVal);
+ pThis->iKeepAliveIntvl = iVal;
+ RETiRet;
+}
+
+static rsRetVal
+SetKeepAliveProbes(tcpsrv_t *pThis, int iVal)
+{
+ DEFiRet;
+ DBGPRINTF("tcpsrv: keep-alive probes set to %d\n", iVal);
+ pThis->iKeepAliveProbes = iVal;
+ RETiRet;
+}
+
+static rsRetVal
+SetKeepAliveTime(tcpsrv_t *pThis, int iVal)
+{
+ DEFiRet;
+ DBGPRINTF("tcpsrv: keep-alive timeout set to %d\n", iVal);
+ pThis->iKeepAliveTime = iVal;
+ RETiRet;
+}
+
+static rsRetVal
+SetGnutlsPriorityString(tcpsrv_t *pThis, uchar *iVal)
+{
+ DEFiRet;
+ DBGPRINTF("tcpsrv: gnutlsPriorityString set to %s\n",
+ (iVal == NULL) ? "(null)" : (const char*) iVal);
+ pThis->gnutlsPriorityString = iVal;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetOnMsgReceive(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int))
+{
+ DEFiRet;
+ assert(OnMsgReceive != NULL);
+ pThis->OnMsgReceive = OnMsgReceive;
+ RETiRet;
+}
+
+
+/* set enable/disable standard LF frame delimiter (use with care!)
+ * -- rgerhards, 2010-01-03
+ */
+static rsRetVal
+SetbDisableLFDelim(tcpsrv_t *pThis, int bVal)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->bDisableLFDelim = bVal;
+ RETiRet;
+}
+
+
+/* discard the truncated msg part
+ * -- PascalWithopf, 2017-04-20
+ */
+static rsRetVal
+SetDiscardTruncatedMsg(tcpsrv_t *pThis, int discard)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->discardTruncatedMsg = discard;
+ RETiRet;
+}
+
+
+/* Set additional framing to use (if any) -- rgerhards, 2008-12-10 */
+static rsRetVal
+SetAddtlFrameDelim(tcpsrv_t *pThis, int iDelim)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->addtlFrameDelim = iDelim;
+ RETiRet;
+}
+
+
+/* Set max frame size for octet counted -- PascalWithopf, 2017-04-20*/
+static rsRetVal
+SetMaxFrameSize(tcpsrv_t *pThis, int maxFrameSize)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->maxFrameSize = maxFrameSize;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetDfltTZ(tcpsrv_t *const pThis, uchar *const tz)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ strncpy((char*)pThis->dfltTZ, (char*)tz, sizeof(pThis->dfltTZ));
+ pThis->dfltTZ[sizeof(pThis->dfltTZ)-1] = '\0';
+ RETiRet;
+}
+
+
+static rsRetVal
+SetbSPFramingFix(tcpsrv_t *pThis, const sbool val)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->bSPFramingFix = val;
+ RETiRet;
+}
+
+static rsRetVal
+SetOrigin(tcpsrv_t *pThis, uchar *origin)
+{
+ DEFiRet;
+ free(pThis->pszOrigin);
+ pThis->pszOrigin = (origin == NULL) ? NULL : ustrdup(origin);
+ RETiRet;
+}
+
+/* Set the input name to use -- rgerhards, 2008-12-10 */
+static rsRetVal
+SetInputName(tcpsrv_t *const pThis,tcpLstnParams_t *const cnf_params, const uchar *const name)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if(name == NULL)
+ cnf_params->pszInputName = NULL;
+ else
+ CHKmalloc(cnf_params->pszInputName = ustrdup(name));
+ free(pThis->pszInputName); // TODO: REMOVE ME
+ pThis->pszInputName = ustrdup("imtcp"); // TODO: REMOVE ME
+
+ /* we need to create a property */
+ CHKiRet(prop.Construct(&cnf_params->pInputName));
+ CHKiRet(prop.SetString(cnf_params->pInputName, cnf_params->pszInputName, ustrlen(cnf_params->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(cnf_params->pInputName));
+finalize_it:
+ RETiRet;
+}
+
+
+/* Set the linux-like ratelimiter settings */
+static rsRetVal
+SetLinuxLikeRatelimiters(tcpsrv_t *pThis, unsigned int ratelimitInterval, unsigned int ratelimitBurst)
+{
+ DEFiRet;
+ pThis->ratelimitInterval = ratelimitInterval;
+ pThis->ratelimitBurst = ratelimitBurst;
+ RETiRet;
+}
+
+
+/* Set connection open notification */
+static rsRetVal
+SetNotificationOnRemoteOpen(tcpsrv_t *pThis, const int bNewVal)
+{
+ pThis->bEmitMsgOnOpen = bNewVal;
+ return RS_RET_OK;
+}
+/* Set connection close notification */
+static rsRetVal
+SetNotificationOnRemoteClose(tcpsrv_t *pThis, const int bNewVal)
+{
+ DEFiRet;
+ pThis->bEmitMsgOnClose = bNewVal;
+ RETiRet;
+}
+
+
+/* here follows a number of methods that shuffle authentication settings down
+ * to the drivers. Drivers not supporting these settings may return an error
+ * state.
+ * -------------------------------------------------------------------------- */
+
+/* set the driver mode -- rgerhards, 2008-04-30 */
+static rsRetVal
+SetDrvrMode(tcpsrv_t *pThis, const int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->iDrvrMode = iMode;
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrName(tcpsrv_t *pThis, uchar *const name)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ free(pThis->pszDrvrName);
+ CHKmalloc(pThis->pszDrvrName = ustrdup(name));
+finalize_it:
+ RETiRet;
+}
+
+/* set the driver authentication mode -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrAuthMode(tcpsrv_t *pThis, uchar *const mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ CHKmalloc(pThis->pszDrvrAuthMode = ustrdup(mode));
+finalize_it:
+ RETiRet;
+}
+
+/* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20
+ */
+static rsRetVal
+SetDrvrPermitExpiredCerts(tcpsrv_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrPermitExpiredCerts = ustrdup(mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrCAFile(tcpsrv_t *const pThis, uchar *const mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCAFile = ustrdup(mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrCRLFile(tcpsrv_t *const pThis, uchar *const mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCRLFile = ustrdup(mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrKeyFile(tcpsrv_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrKeyFile = ustrdup(mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+SetDrvrCertFile(tcpsrv_t *pThis, uchar *mode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ if (mode != NULL) {
+ CHKmalloc(pThis->pszDrvrCertFile = ustrdup(mode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the driver's permitted peers -- rgerhards, 2008-05-19 */
+static rsRetVal
+SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->pPermPeers = pPermPeers;
+ RETiRet;
+}
+
+/* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */
+static rsRetVal
+SetDrvrCheckExtendedKeyUsage(tcpsrv_t *pThis, int ChkExtendedKeyUsage)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage;
+ RETiRet;
+}
+
+/* set the driver name checking policy -- jvymazal, 2019-08-16 */
+static rsRetVal
+SetDrvrPrioritizeSAN(tcpsrv_t *pThis, int prioritizeSan)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->DrvrPrioritizeSan = prioritizeSan;
+ RETiRet;
+}
+
+/* set the driver Set the driver tls verifyDepth -- alorbach, 2019-12-20 */
+static rsRetVal
+SetDrvrTlsVerifyDepth(tcpsrv_t *pThis, int verifyDepth)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->DrvrTlsVerifyDepth = verifyDepth;
+ RETiRet;
+}
+
+/* End of methods to shuffle autentication settings to the driver.;
+
+ * -------------------------------------------------------------------------- */
+
+
+/* set max number of listeners
+ * this must be called before ConstructFinalize, or it will have no effect!
+ * rgerhards, 2009-08-17
+ */
+static rsRetVal
+SetLstnMax(tcpsrv_t *pThis, int iMax)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->iLstnMax = iMax;
+ RETiRet;
+}
+
+
+/* set if flow control shall be supported
+ */
+static rsRetVal
+SetUseFlowControl(tcpsrv_t *pThis, int bUseFlowControl)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->bUseFlowControl = bUseFlowControl;
+ RETiRet;
+}
+
+
+/* set max number of sessions
+ * this must be called before ConstructFinalize, or it will have no effect!
+ * rgerhards, 2009-04-09
+ */
+static rsRetVal
+SetSessMax(tcpsrv_t *pThis, int iMax)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->iSessMax = iMax;
+ RETiRet;
+}
+
+
+static rsRetVal
+SetPreserveCase(tcpsrv_t *pThis, int bPreserveCase)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis-> bPreserveCase = bPreserveCase;
+ RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(tcpsrv)
+CODESTARTobjQueryInterface(tcpsrv)
+ if(pIf->ifVersion != tcpsrvCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->DebugPrint = tcpsrvDebugPrint;
+ pIf->Construct = tcpsrvConstruct;
+ pIf->ConstructFinalize = tcpsrvConstructFinalize;
+ pIf->Destruct = tcpsrvDestruct;
+
+ pIf->configureTCPListen = configureTCPListen;
+ pIf->create_tcp_socket = create_tcp_socket;
+ pIf->Run = Run;
+
+ pIf->SetKeepAlive = SetKeepAlive;
+ pIf->SetKeepAliveIntvl = SetKeepAliveIntvl;
+ pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ pIf->SetKeepAliveTime = SetKeepAliveTime;
+ pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
+ pIf->SetUsrP = SetUsrP;
+ pIf->SetInputName = SetInputName;
+ pIf->SetOrigin = SetOrigin;
+ pIf->SetDfltTZ = SetDfltTZ;
+ pIf->SetbSPFramingFix = SetbSPFramingFix;
+ pIf->SetAddtlFrameDelim = SetAddtlFrameDelim;
+ pIf->SetMaxFrameSize = SetMaxFrameSize;
+ pIf->SetbDisableLFDelim = SetbDisableLFDelim;
+ pIf->SetDiscardTruncatedMsg = SetDiscardTruncatedMsg;
+ pIf->SetSessMax = SetSessMax;
+ pIf->SetUseFlowControl = SetUseFlowControl;
+ pIf->SetLstnMax = SetLstnMax;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->SetDrvrAuthMode = SetDrvrAuthMode;
+ pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts;
+ pIf->SetDrvrCAFile = SetDrvrCAFile;
+ pIf->SetDrvrCRLFile = SetDrvrCRLFile;
+ pIf->SetDrvrKeyFile = SetDrvrKeyFile;
+ pIf->SetDrvrCertFile = SetDrvrCertFile;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->SetDrvrPermPeers = SetDrvrPermPeers;
+ pIf->SetCBIsPermittedHost = SetCBIsPermittedHost;
+ pIf->SetCBOpenLstnSocks = SetCBOpenLstnSocks;
+ pIf->SetCBRcvData = SetCBRcvData;
+ pIf->SetCBOnListenDeinit = SetCBOnListenDeinit;
+ pIf->SetCBOnSessAccept = SetCBOnSessAccept;
+ pIf->SetCBOnSessConstructFinalize = SetCBOnSessConstructFinalize;
+ pIf->SetCBOnSessDestruct = SetCBOnSessDestruct;
+ pIf->SetCBOnDestruct = SetCBOnDestruct;
+ pIf->SetCBOnRegularClose = SetCBOnRegularClose;
+ pIf->SetCBOnErrClose = SetCBOnErrClose;
+ pIf->SetOnMsgReceive = SetOnMsgReceive;
+ pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters;
+ pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose;
+ pIf->SetNotificationOnRemoteOpen = SetNotificationOnRemoteOpen;
+ pIf->SetPreserveCase = SetPreserveCase;
+ pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
+ pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
+ pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth;
+
+finalize_it:
+ENDobjQueryInterface(tcpsrv)
+
+
+/* exit our class
+ * rgerhards, 2008-03-10
+ */
+BEGINObjClassExit(tcpsrv, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(tcpsrv)
+ /* release objects we no longer need */
+ objRelease(tcps_sess, DONT_LOAD_LIB);
+ objRelease(conf, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(netstrms, DONT_LOAD_LIB);
+ objRelease(nssel, DONT_LOAD_LIB);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(net, LM_NET_FILENAME);
+ENDObjClassExit(tcpsrv)
+
+
+/* Initialize our class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-29
+ */
+BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */
+ /* request objects we use */
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
+ CHKiRet(objUse(nssel, DONT_LOAD_LIB));
+ CHKiRet(objUse(nspoll, DONT_LOAD_LIB));
+ CHKiRet(objUse(tcps_sess, DONT_LOAD_LIB));
+ CHKiRet(objUse(conf, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ /* set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcpsrvConstructFinalize);
+ENDObjClassInit(tcpsrv)
+
+
+/* start worker threads
+ * Important: if we fork, this MUST be done AFTER forking
+ */
+static void
+startWorkerPool(void)
+{
+ int i;
+ int r;
+ pthread_attr_t sessThrdAttr;
+
+ /* We need to temporarily block all signals because the new thread
+ * inherits our signal mask. There is a race if we do not block them
+ * now, and we have seen in practice that this race causes grief.
+ * So we 1. save the current set, 2. block evertyhing, 3. start
+ * threads, and 4 reset the current set to saved state.
+ * rgerhards, 2019-08-16
+ */
+ sigset_t sigSet, sigSetSave;
+ sigfillset(&sigSet);
+ pthread_sigmask(SIG_SETMASK, &sigSet, &sigSetSave);
+
+ wrkrRunning = 0;
+ pthread_cond_init(&wrkrIdle, NULL);
+ pthread_attr_init(&sessThrdAttr);
+ pthread_attr_setstacksize(&sessThrdAttr, 4096*1024);
+ for(i = 0 ; i < wrkrMax ; ++i) {
+ /* init worker info structure! */
+ pthread_cond_init(&wrkrInfo[i].run, NULL);
+ wrkrInfo[i].pSrv = NULL;
+ wrkrInfo[i].numCalled = 0;
+ r = pthread_create(&wrkrInfo[i].tid, &sessThrdAttr, wrkr, &(wrkrInfo[i]));
+ if(r == 0) {
+ wrkrInfo[i].enabled = 1;
+ } else {
+ LogError(r, NO_ERRCODE, "tcpsrv error creating thread");
+ }
+ }
+ pthread_attr_destroy(&sessThrdAttr);
+ pthread_sigmask(SIG_SETMASK, &sigSetSave, NULL);
+}
+
+/* destroy worker pool structures and wait for workers to terminate
+ */
+static void
+stopWorkerPool(void)
+{
+ int i;
+ for(i = 0 ; i < wrkrMax ; ++i) {
+ pthread_mutex_lock(&wrkrMut);
+ pthread_cond_signal(&wrkrInfo[i].run); /* awake wrkr if not running */
+ pthread_mutex_unlock(&wrkrMut);
+ pthread_join(wrkrInfo[i].tid, NULL);
+ DBGPRINTF("tcpsrv: info: worker %d was called %llu times\n", i, wrkrInfo[i].numCalled);
+ pthread_cond_destroy(&wrkrInfo[i].run);
+ }
+ pthread_cond_destroy(&wrkrIdle);
+}
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+BEGINmodExit
+CODESTARTmodExit
+ if(bWrkrRunning) {
+ stopWorkerPool();
+ bWrkrRunning = 0;
+ }
+ /* de-init in reverse order! */
+ tcpsrvClassExit();
+ tcps_sessClassExit();
+ pthread_mutex_destroy(&wrkrMut);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+ /* we just init the worker mutex, but do not start the workers themselves. This is deferred
+ * to the first call of Run(). Reasons for this:
+ * 1. depending on load order, tcpsrv gets loaded during rsyslog startup BEFORE
+ * it forks, in which case the workers would be running in the then-killed parent,
+ * leading to a defuncnt child (we actually had this bug).
+ * 2. depending on circumstances, Run() would possibly never be called, in which case
+ * the worker threads would be totally useless.
+ * Note that in order to guarantee a non-racy worker start, we need to guard the
+ * startup sequence by a mutex, which is why we init it here (no problem with fork()
+ * in this case as the mutex is a pure-memory structure).
+ * rgerhards, 2012-05-18
+ */
+ pthread_mutex_init(&wrkrMut, NULL);
+ bWrkrRunning = 0;
+
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ CHKiRet(tcps_sessClassInit(pModInfo));
+ CHKiRet(tcpsrvClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ENDmodInit
diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h
new file mode 100644
index 0000000..d1ffdc3
--- /dev/null
+++ b/runtime/tcpsrv.h
@@ -0,0 +1,233 @@
+/* Definitions for tcpsrv class.
+ *
+ * Copyright 2008-2022 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_TCPSRV_H
+#define INCLUDED_TCPSRV_H
+
+#include "obj.h"
+#include "prop.h"
+#include "net.h"
+#include "tcps_sess.h"
+#include "statsobj.h"
+
+/* support for framing anomalies */
+typedef enum ETCPsyslogFramingAnomaly {
+ frame_normal = 0,
+ frame_NetScreen = 1,
+ frame_CiscoIOS = 2
+} eTCPsyslogFramingAnomaly;
+
+
+/* config parameters for TCP listeners */
+struct tcpLstnParams_s {
+ const uchar *pszPort; /**< the ports the listener shall listen on */
+ const uchar *pszAddr; /**< the addrs the listener shall listen on */
+ sbool bSuppOctetFram; /**< do we support octect-counted framing? (if no->legay only!)*/
+ sbool bSPFramingFix; /**< support work-around for broken Cisco ASA framing? */
+ sbool bPreserveCase; /**< preserve case in fromhost */
+ const uchar *pszLstnPortFileName; /**< File in which the dynamic port is written */
+ uchar *pszStrmDrvrName; /**< stream driver to use */
+ uchar *pszInputName; /**< value to be used as input name */
+ prop_t *pInputName;
+ ruleset_t *pRuleset; /**< associated ruleset */
+ uchar dfltTZ[8]; /**< default TZ if none in timestamp; '\0' =No Default */
+};
+
+/* list of tcp listen ports */
+struct tcpLstnPortList_s {
+ tcpLstnParams_t *cnf_params; /**< listener config parameters */
+ tcpsrv_t *pSrv; /**< pointer to higher-level server instance */
+ statsobj_t *stats; /**< associated stats object */
+ ratelimit_t *ratelimiter;
+ STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ tcpLstnPortList_t *pNext; /**< next port or NULL */
+};
+
+#define TCPSRV_NO_ADDTL_DELIMITER -1 /* specifies that no additional delimiter is to be used in TCP framing */
+
+/* the tcpsrv object */
+struct tcpsrv_s {
+ BEGINobjInstance; /**< Data to implement generic object - MUST be the first data element! */
+ int bUseKeepAlive; /**< use socket layer KEEPALIVE handling? */
+ int iKeepAliveIntvl; /**< socket layer KEEPALIVE interval */
+ int iKeepAliveProbes; /**< socket layer KEEPALIVE probes */
+ int iKeepAliveTime; /**< socket layer KEEPALIVE timeout */
+ netstrms_t *pNS; /**< pointer to network stream subsystem */
+ int iDrvrMode; /**< mode of the stream driver to use */
+ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */
+ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */
+ int DrvrTlsVerifyDepth; /**< Verify Depth for certificate chains */
+ uchar *gnutlsPriorityString; /**< priority string for gnutls */
+ uchar *pszLstnPortFileName; /**< File in which the dynamic port is written */
+ uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */
+ uchar *pszDrvrPermitExpiredCerts;/**< current driver setting for handlign expired certs */
+ uchar *pszDrvrCAFile;
+ uchar *pszDrvrCRLFile;
+ uchar *pszDrvrKeyFile;
+ uchar *pszDrvrCertFile;
+ uchar *pszDrvrName; /**< name of stream driver to use */
+ uchar *pszInputName; /**< value to be used as input name */ // TODO: REMOVE ME!!!!
+ uchar *pszOrigin; /**< module to be used as "origin" (e.g. for pstats) */
+ ruleset_t *pRuleset; /**< ruleset to bind to */
+ permittedPeers_t *pPermPeers;/**< driver's permitted peers */
+ sbool bEmitMsgOnClose; /**< emit an informational message when the remote peer closes connection */
+ sbool bEmitMsgOnOpen;
+ sbool bUsingEPoll; /**< are we in epoll mode (means we do not need to keep track of sessions!) */
+ sbool bUseFlowControl; /**< use flow control (make light delayable) */
+ sbool bSPFramingFix; /**< support work-around for broken Cisco ASA framing? */
+ int iLstnCurr; /**< max nbr of listeners currently supported */
+ netstrm_t **ppLstn; /**< our netstream listeners */
+ tcpLstnPortList_t **ppLstnPort; /**< pointer to relevant listen port description */
+ int iLstnMax; /**< max number of listeners supported */
+ int iSessMax; /**< max number of sessions supported */
+ uchar dfltTZ[8]; /**< default TZ if none in timestamp; '\0' =No Default */
+ tcpLstnPortList_t *pLstnPorts; /**< head pointer for listen ports */
+
+ int addtlFrameDelim; /**< additional frame delimiter for plain TCP syslog
+ framing (e.g. to handle NetScreen) */
+ int maxFrameSize; /**< max frame size for octet counted*/
+ int bDisableLFDelim; /**< if 1, standard LF frame delimiter is disabled (*very dangerous*) */
+ int discardTruncatedMsg;/**< discard msg part that has been truncated*/
+ sbool bPreserveCase; /**< preserve case in fromhost */
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ tcps_sess_t **pSessions;/**< array of all of our sessions */
+ void *pUsr; /**< a user-settable pointer (provides extensibility for "derived classes")*/
+ /* callbacks */
+ int (*pIsPermittedHost)(struct sockaddr *addr, char *fromHostFQDN, void*pUsrSrv, void*pUsrSess);
+ rsRetVal (*pRcvData)(tcps_sess_t*, char*, size_t, ssize_t *, int*);
+ rsRetVal (*OpenLstnSocks)(struct tcpsrv_s*);
+ rsRetVal (*pOnListenDeinit)(void*);
+ rsRetVal (*OnDestruct)(void*);
+ rsRetVal (*pOnRegularClose)(tcps_sess_t *pSess);
+ rsRetVal (*pOnErrClose)(tcps_sess_t *pSess);
+ /* session specific callbacks */
+ rsRetVal (*pOnSessAccept)(tcpsrv_t *, tcps_sess_t*);
+ rsRetVal (*OnSessConstructFinalize)(void*);
+ rsRetVal (*pOnSessDestruct)(void*);
+ rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *pszMsg, int iLenMsg); /* submit message callback */
+};
+
+
+/**
+ * The following structure is a set of descriptors that need to be processed.
+ * This set will be the result of the epoll or select call and be used
+ * in the actual request processing stage. It serves as a basis
+ * to run multiple request by concurrent threads. -- rgerhards, 2011-01-24
+ */
+struct tcpsrv_workset_s {
+ int idx; /**< index into session table (or -1 if listener) */
+ void *pUsr;
+};
+
+
+/* interfaces */
+BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(tcpsrv);
+ rsRetVal (*Construct)(tcpsrv_t **ppThis);
+ rsRetVal (*ConstructFinalize)(tcpsrv_t __attribute__((unused)) *pThis);
+ rsRetVal (*Destruct)(tcpsrv_t **ppThis);
+ rsRetVal (*ATTR_NONNULL(1,2) configureTCPListen)(tcpsrv_t*, tcpLstnParams_t *const cnf_params);
+ rsRetVal (*create_tcp_socket)(tcpsrv_t *pThis);
+ rsRetVal (*Run)(tcpsrv_t *pThis);
+ /* set methods */
+ rsRetVal (*SetAddtlFrameDelim)(tcpsrv_t*, int);
+ rsRetVal (*SetMaxFrameSize)(tcpsrv_t*, int);
+ rsRetVal (*SetInputName)(tcpsrv_t *const pThis,tcpLstnParams_t *const cnf_params, const uchar *const name);
+ rsRetVal (*SetUsrP)(tcpsrv_t*, void*);
+ rsRetVal (*SetCBIsPermittedHost)(tcpsrv_t*, int (*) (struct sockaddr *addr, char*, void*, void*));
+ rsRetVal (*SetCBOpenLstnSocks)(tcpsrv_t *, rsRetVal (*)(tcpsrv_t*));
+ rsRetVal (*SetCBRcvData)(tcpsrv_t *pThis, rsRetVal (*pRcvData)(tcps_sess_t*, char*, size_t, ssize_t*, int*));
+ rsRetVal (*SetCBOnListenDeinit)(tcpsrv_t*, rsRetVal (*)(void*));
+ rsRetVal (*SetCBOnDestruct)(tcpsrv_t*, rsRetVal (*) (void*));
+ rsRetVal (*SetCBOnRegularClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
+ rsRetVal (*SetCBOnErrClose)(tcpsrv_t*, rsRetVal (*) (tcps_sess_t*));
+ rsRetVal (*SetDrvrMode)(tcpsrv_t *pThis, int iMode);
+ rsRetVal (*SetDrvrAuthMode)(tcpsrv_t *pThis, uchar *pszMode);
+ rsRetVal (*SetDrvrPermitExpiredCerts)(tcpsrv_t *pThis, uchar *pszMode);
+ rsRetVal (*SetDrvrPermPeers)(tcpsrv_t *pThis, permittedPeers_t*);
+ /* session specifics */
+ rsRetVal (*SetCBOnSessAccept)(tcpsrv_t*, rsRetVal (*) (tcpsrv_t*, tcps_sess_t*));
+ rsRetVal (*SetCBOnSessDestruct)(tcpsrv_t*, rsRetVal (*) (void*));
+ rsRetVal (*SetCBOnSessConstructFinalize)(tcpsrv_t*, rsRetVal (*) (void*));
+ /* added v5 */
+ rsRetVal (*SetSessMax)(tcpsrv_t *pThis, int iMaxSess); /* 2009-04-09 */
+ /* added v6 */
+ rsRetVal (*SetOnMsgReceive)(tcpsrv_t *pThis,
+ rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int)); /* 2009-05-24 */
+ rsRetVal (*SetRuleset)(tcpsrv_t *pThis, ruleset_t*); /* 2009-06-12 */
+ /* added v7 (accidently named v8!) */
+ rsRetVal (*SetLstnMax)(tcpsrv_t *pThis, int iMaxLstn); /* 2009-08-17 */
+ rsRetVal (*SetNotificationOnRemoteClose)(tcpsrv_t *pThis, int bNewVal); /* 2009-10-01 */
+ rsRetVal (*SetNotificationOnRemoteOpen)(tcpsrv_t *pThis, int bNewVal); /* 2022-08-23 */
+ /* added v9 -- rgerhards, 2010-03-01 */
+ rsRetVal (*SetbDisableLFDelim)(tcpsrv_t*, int);
+ /* added v10 -- rgerhards, 2011-04-01 */
+ rsRetVal (*SetDiscardTruncatedMsg)(tcpsrv_t*, int);
+ rsRetVal (*SetUseFlowControl)(tcpsrv_t*, int);
+ /* added v11 -- rgerhards, 2011-05-09 */
+ rsRetVal (*SetKeepAlive)(tcpsrv_t*, int);
+ /* added v13 -- rgerhards, 2012-10-15 */
+ rsRetVal (*SetLinuxLikeRatelimiters)(tcpsrv_t *pThis, unsigned int interval, unsigned int burst);
+ /* added v14 -- rgerhards, 2013-07-28 */
+ rsRetVal (*SetDfltTZ)(tcpsrv_t *pThis, uchar *dfltTZ);
+ /* added v15 -- rgerhards, 2013-09-17 */
+ rsRetVal (*SetDrvrName)(tcpsrv_t *pThis, uchar *pszName);
+ /* added v16 -- rgerhards, 2014-09-08 */
+ rsRetVal (*SetOrigin)(tcpsrv_t*, uchar*);
+ /* added v17 */
+ rsRetVal (*SetKeepAliveIntvl)(tcpsrv_t*, int);
+ rsRetVal (*SetKeepAliveProbes)(tcpsrv_t*, int);
+ rsRetVal (*SetKeepAliveTime)(tcpsrv_t*, int);
+ /* added v18 */
+ rsRetVal (*SetbSPFramingFix)(tcpsrv_t*, sbool);
+ /* added v19 -- PascalWithopf, 2017-08-08 */
+ rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*);
+ /* added v21 -- Preserve case in fromhost, 2018-08-16 */
+ rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase);
+ /* added v23 -- Options for stricter driver behavior, 2019-08-16 */
+ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(tcpsrv_t *pThis, int ChkExtendedKeyUsage);
+ rsRetVal (*SetDrvrPrioritizeSAN)(tcpsrv_t *pThis, int prioritizeSan);
+ /* added v24 -- Options for TLS verify depth driver behavior, 2019-12-20 */
+ rsRetVal (*SetDrvrTlsVerifyDepth)(tcpsrv_t *pThis, int verifyDepth);
+ /* added v25 -- Options for TLS certificates, 2021-07-19 */
+ rsRetVal (*SetDrvrCAFile)(tcpsrv_t *pThis, uchar *pszMode);
+ rsRetVal (*SetDrvrKeyFile)(tcpsrv_t *pThis, uchar *pszMode);
+ rsRetVal (*SetDrvrCertFile)(tcpsrv_t *pThis, uchar *pszMode);
+ /* added v26 -- Options for TLS CRL file */
+ rsRetVal (*SetDrvrCRLFile)(tcpsrv_t *pThis, uchar *pszMode);
+ENDinterface(tcpsrv)
+#define tcpsrvCURR_IF_VERSION 26 /* increment whenever you change the interface structure! */
+/* change for v4:
+ * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10
+ * - SetInputName() added -- rgerhards, 2008-12-10
+ * change for v5 and up: see above
+ * for v12: param bSuppOctetFram added to configureTCPListen
+ * for v20: add oserr to setCBRcvData signature -- rgerhards, 2017-09-04
+ */
+
+
+/* prototypes */
+PROTOTYPEObj(tcpsrv);
+
+/* the name of our library binary */
+#define LM_TCPSRV_FILENAME "lmtcpsrv"
+
+#endif /* #ifndef INCLUDED_TCPSRV_H */
diff --git a/runtime/timezones.c b/runtime/timezones.c
new file mode 100644
index 0000000..e1e0394
--- /dev/null
+++ b/runtime/timezones.c
@@ -0,0 +1,205 @@
+/* timezones.c
+ * Support for timezones in RainerScript.
+ *
+ * Copyright 2022 Attila Lakatos and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "unicode-helper.h"
+#include "errmsg.h"
+#include "parserif.h"
+#include "rainerscript.h"
+#include "srUtils.h"
+#include "rsconf.h"
+
+
+static struct cnfparamdescr timezonecnfparamdescr[] = {
+ { "id", eCmdHdlrString, CNFPARAM_REQUIRED},
+ { "offset", eCmdHdlrGetWord, CNFPARAM_REQUIRED }
+};
+static struct cnfparamblk timezonepblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(timezonecnfparamdescr)/sizeof(struct cnfparamdescr),
+ timezonecnfparamdescr
+};
+
+/* Note: this function is NOT thread-safe!
+ * This is currently not needed as used only during
+ * initialization.
+ */
+static rsRetVal
+addTimezoneInfo(rsconf_t *cnf, uchar *tzid, char offsMode, int8_t offsHour, int8_t offsMin)
+{
+ DEFiRet;
+ tzinfo_t *newti;
+ CHKmalloc(newti = realloc(cnf->timezones.tzinfos, (cnf->timezones.ntzinfos+1)*sizeof(tzinfo_t)));
+ if((newti[cnf->timezones.ntzinfos].id = strdup((char*)tzid)) == NULL) {
+ free(newti);
+ DBGPRINTF("addTimezoneInfo: strdup failed with OOM\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ newti[cnf->timezones.ntzinfos].offsMode = offsMode;
+ newti[cnf->timezones.ntzinfos].offsHour = offsHour;
+ newti[cnf->timezones.ntzinfos].offsMin = offsMin;
+ ++cnf->timezones.ntzinfos, cnf->timezones.tzinfos = newti;
+finalize_it:
+ RETiRet;
+}
+
+void
+glblProcessTimezone(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ uchar *id = NULL;
+ uchar *offset = NULL;
+ char offsMode;
+ int8_t offsHour;
+ int8_t offsMin;
+ int i;
+
+ pvals = nvlstGetParams(o->nvlst, &timezonepblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing timezone "
+ "config parameters");
+ goto done;
+ }
+ if(Debug) {
+ dbgprintf("timezone param blk after glblProcessTimezone:\n");
+ cnfparamsPrint(&timezonepblk, pvals);
+ }
+
+ for(i = 0 ; i < timezonepblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(timezonepblk.descr[i].name, "id")) {
+ id = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(timezonepblk.descr[i].name, "offset")) {
+ offset = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("glblProcessTimezone: program error, non-handled "
+ "param '%s'\n", timezonepblk.descr[i].name);
+ }
+ }
+
+ /* note: the following two checks for NULL are not strictly necessary
+ * as these are required parameters for the config block. But we keep
+ * them to make the clang static analyzer happy, which also helps
+ * guard against logic errors.
+ */
+ if(offset == NULL) {
+ parser_errmsg("offset parameter missing (logic error?), timezone config ignored");
+ goto done;
+ }
+ if(id == NULL) {
+ parser_errmsg("id parameter missing (logic error?), timezone config ignored");
+ goto done;
+ }
+
+ if( strlen((char*)offset) != 6
+ || !(offset[0] == '-' || offset[0] == '+')
+ || !(isdigit(offset[1]) && isdigit(offset[2]))
+ || offset[3] != ':'
+ || !(isdigit(offset[4]) && isdigit(offset[5]))
+ ) {
+ parser_errmsg("timezone offset has invalid format. Must be +/-hh:mm, e.g. \"-07:00\".");
+ goto done;
+ }
+
+ offsHour = (offset[1] - '0') * 10 + offset[2] - '0';
+ offsMin = (offset[4] - '0') * 10 + offset[5] - '0';
+ offsMode = offset[0];
+
+ if(offsHour > 12 || offsMin > 59) {
+ parser_errmsg("timezone offset outside of supported range (hours 0..12, minutes 0..59)");
+ goto done;
+ }
+
+ addTimezoneInfo(loadConf, id, offsMode, offsHour, offsMin);
+
+done:
+ cnfparamvalsDestruct(pvals, &timezonepblk);
+ free(id);
+ free(offset);
+}
+
+/* comparison function for qsort() and string array compare
+ * this is for the string lookup table type
+ */
+static int
+qs_arrcmp_tzinfo(const void *s1, const void *s2)
+{
+ return strcmp(((tzinfo_t*)s1)->id, ((tzinfo_t*)s2)->id);
+}
+
+void sortTimezones(rsconf_t *cnf)
+{
+ if (cnf->timezones.ntzinfos > 0) {
+ qsort(cnf->timezones.tzinfos, cnf->timezones.ntzinfos,
+ sizeof(tzinfo_t), qs_arrcmp_tzinfo);
+ }
+}
+
+void
+displayTimezones(rsconf_t *cnf)
+{
+ if(!Debug)
+ return;
+ for(int i = 0 ; i < cnf->timezones.ntzinfos ; ++i)
+ dbgprintf("tzinfo: '%s':%c%2.2d:%2.2d\n",
+ cnf->timezones.tzinfos[i].id, cnf->timezones.tzinfos[i].offsMode,
+ cnf->timezones.tzinfos[i].offsHour, cnf->timezones.tzinfos[i].offsMin);
+}
+
+static int
+bs_arrcmp_tzinfo(const void *s1, const void *s2)
+{
+ return strcmp((char*)s1, (char*)((tzinfo_t*)s2)->id);
+}
+
+/* returns matching timezone info or NULL if no entry exists */
+tzinfo_t*
+glblFindTimezone(rsconf_t *cnf, char *id)
+{
+ return (tzinfo_t*) bsearch(
+ id, cnf->timezones.tzinfos, cnf->timezones.ntzinfos, sizeof(tzinfo_t), bs_arrcmp_tzinfo);
+}
+
+static void
+freeTimezone(tzinfo_t *tzinfo)
+{
+ free(tzinfo->id);
+}
+
+void
+freeTimezones(rsconf_t *cnf)
+{
+ for(int i = 0; i < cnf->timezones.ntzinfos ; ++i)
+ freeTimezone(&cnf->timezones.tzinfos[i]);
+ if (cnf->timezones.ntzinfos > 0)
+ free(cnf->timezones.tzinfos);
+ cnf->timezones.tzinfos = NULL;
+}
diff --git a/runtime/timezones.h b/runtime/timezones.h
new file mode 100644
index 0000000..d2bcdb4
--- /dev/null
+++ b/runtime/timezones.h
@@ -0,0 +1,38 @@
+/* header for timezones.c
+ *
+ * Copyright 2022 Attila Lakatos and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_TIMEZONES_H
+#define INCLUDED_TIMEZONES_H
+
+#include "rsconf.h"
+
+/* timezone specific parameters*/
+struct timezones_s {
+ tzinfo_t *tzinfos;
+ int ntzinfos;
+};
+
+void displayTimezones(rsconf_t *cnf);
+void sortTimezones(rsconf_t *cnf);
+void glblProcessTimezone(struct cnfobj *o);
+tzinfo_t* glblFindTimezone(rsconf_t *cnf, char *id);
+void freeTimezones(rsconf_t *cnf);
+
+#endif
diff --git a/runtime/typedefs.h b/runtime/typedefs.h
new file mode 100644
index 0000000..0ce6da0
--- /dev/null
+++ b/runtime/typedefs.h
@@ -0,0 +1,314 @@
+/* This defines some types commonly used. Do NOT include any other
+ * rsyslog runtime file.
+ *
+ * Begun 2010-11-25 RGerhards
+ *
+ * Copyright (C) 2005-2020 by Rainer Gerhards and Adiscon GmbH
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#ifndef INCLUDED_TYPEDEFS_H
+#define INCLUDED_TYPEDEFS_H
+
+#include <stdint.h>
+#if defined(__FreeBSD__) || !defined(HAVE_LSEEK64)
+#include <sys/types.h>
+#endif
+
+/* some universal fixed size integer defines ... */
+#ifndef _AIX
+typedef long long int64;
+#endif
+typedef long long unsigned uint64;
+typedef int64 number_t; /* type to use for numbers - TODO: maybe an autoconf option? */
+typedef char intTiny; /* 0..127! */
+typedef unsigned char uintTiny; /* 0..255! */
+
+/* define some base data types */
+
+typedef uint16_t syslog_pri_t; /* to be used for syslog PRI values */
+typedef unsigned char uchar;/* get rid of the unhandy "unsigned char" */
+typedef struct aUsrp_s aUsrp_t;
+typedef struct thrdInfo thrdInfo_t;
+typedef struct obj_s obj_t;
+typedef struct ruleset_s ruleset_t;
+typedef struct rule_s rule_t;
+typedef struct NetAddr netAddr_t;
+typedef struct netstrms_s netstrms_t;
+typedef struct netstrm_s netstrm_t;
+typedef struct nssel_s nssel_t;
+typedef struct nspoll_s nspoll_t;
+typedef enum nsdsel_waitOp_e nsdsel_waitOp_t;
+typedef struct net_ossl_s net_ossl_t;
+typedef struct nsd_ptcp_s nsd_ptcp_t;
+typedef struct nsd_gtls_s nsd_gtls_t;
+typedef struct nsd_ossl_s nsd_ossl_t;
+typedef struct nsd_gsspi_s nsd_gsspi_t;
+typedef struct nsd_nss_s nsd_nss_t;
+typedef struct nsdsel_ptcp_s nsdsel_ptcp_t;
+typedef struct nsdsel_gtls_s nsdsel_gtls_t;
+typedef struct nsdsel_ossl_s nsdsel_ossl_t;
+typedef struct nsdpoll_ptcp_s nsdpoll_ptcp_t;
+typedef struct wti_s wti_t;
+typedef struct msgPropDescr_s msgPropDescr_t;
+typedef struct msg smsg_t;
+typedef struct queue_s qqueue_t;
+typedef struct prop_s prop_t;
+typedef struct interface_s interface_t;
+typedef struct objInfo_s objInfo_t;
+typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
+typedef rsRetVal (*errLogFunc_t)(uchar*);
+/* this is a trick to store a function ptr to a function returning a function ptr... */
+typedef struct permittedPeers_s permittedPeers_t;
+/* this should go away in the long term -- rgerhards, 2008-05-19 */
+typedef struct permittedPeerWildcard_s permittedPeerWildcard_t;
+/* this should go away in the long term -- rgerhards, 2008-05-19 */
+typedef struct tcpsrv_s tcpsrv_t;
+typedef struct tcps_sess_s tcps_sess_t;
+typedef struct strmsrv_s strmsrv_t;
+typedef struct strms_sess_s strms_sess_t;
+typedef struct vmstk_s vmstk_t;
+typedef struct batch_obj_s batch_obj_t;
+typedef struct batch_s batch_t;
+typedef struct wtp_s wtp_t;
+typedef struct modInfo_s modInfo_t;
+typedef struct parser_s parser_t;
+typedef struct parserList_s parserList_t;
+typedef struct strgen_s strgen_t;
+typedef struct strgenList_s strgenList_t;
+typedef struct statsobj_s statsobj_t;
+typedef void (*statsobj_read_notifier_t)(statsobj_t *, void *);
+typedef struct nsd_epworkset_s nsd_epworkset_t;
+typedef struct templates_s templates_t;
+typedef struct parsers_s parsers_t;
+typedef struct queuecnf_s queuecnf_t;
+typedef struct parsercnf_s parsercnf_t;
+typedef struct rulesets_s rulesets_t;
+typedef struct globals_s globals_t;
+typedef struct defaults_s defaults_t;
+typedef struct actions_s actions_t;
+typedef struct timezones_s timezones_t;
+typedef struct rsconf_s rsconf_t;
+typedef struct cfgmodules_s cfgmodules_t;
+typedef struct cfgmodules_etry_s cfgmodules_etry_t;
+typedef struct outchannels_s outchannels_t;
+typedef struct modConfData_s modConfData_t;
+typedef struct instanceConf_s instanceConf_t;
+typedef struct ratelimit_s ratelimit_t;
+typedef struct lookup_string_tab_entry_s lookup_string_tab_entry_t;
+typedef struct lookup_string_tab_s lookup_string_tab_t;
+typedef struct lookup_array_tab_s lookup_array_tab_t;
+typedef struct lookup_sparseArray_tab_s lookup_sparseArray_tab_t;
+typedef struct lookup_sparseArray_tab_entry_s lookup_sparseArray_tab_entry_t;
+typedef struct lookup_tables_s lookup_tables_t;
+typedef union lookup_key_u lookup_key_t;
+
+typedef struct lookup_s lookup_t;
+typedef struct lookup_ref_s lookup_ref_t;
+typedef struct action_s action_t;
+typedef int rs_size_t; /* we do never need more than 2Gig strings, signed permits to
+ * use -1 as a special flag. */
+typedef rsRetVal (*prsf_t)(struct vmstk_s*, int); /* pointer to a RainerScript function */
+typedef uint64 qDeqID; /* queue Dequeue order ID. 32 bits is considered dangerously few */
+
+typedef struct tcpLstnParams_s tcpLstnParams_t;
+typedef struct tcpLstnPortList_s tcpLstnPortList_t; // TODO: rename?
+typedef struct strmLstnPortList_s strmLstnPortList_t; // TODO: rename?
+typedef struct actWrkrIParams actWrkrIParams_t;
+typedef struct dynstats_bucket_s dynstats_bucket_t;
+typedef struct dynstats_buckets_s dynstats_buckets_t;
+typedef struct perctile_buckets_s perctile_buckets_t;
+typedef struct dynstats_ctr_s dynstats_ctr_t;
+
+/* under Solaris (actually only SPARC), we need to redefine some types
+ * to be void, so that we get void* pointers. Otherwise, we will see
+ * alignment errors.
+ */
+#ifdef OS_SOLARIS
+ typedef void * obj_t_ptr;
+ typedef void nsd_t;
+ typedef void nsdsel_t;
+ typedef void nsdpoll_t;
+#else
+ typedef obj_t *obj_t_ptr;
+ typedef obj_t nsd_t;
+ typedef obj_t nsdsel_t;
+ typedef obj_t nsdpoll_t;
+#endif
+
+
+#ifdef __hpux
+typedef unsigned int u_int32_t; /* TODO: is this correct? */
+typedef int socklen_t;
+#endif
+
+typedef struct epoll_event epoll_event_t;
+
+typedef signed char sbool; /* (small bool) I intentionally use char, to keep it slim so that
+ many fit into the CPU cache! */
+
+/* settings for flow control
+ * TODO: is there a better place for them? -- rgerhards, 2008-03-14
+ */
+typedef enum {
+ eFLOWCTL_NO_DELAY = 0, /**< UDP and other non-delayable sources */
+ eFLOWCTL_LIGHT_DELAY = 1, /**< some light delay possible, but no extended period of time */
+ eFLOWCTL_FULL_DELAY = 2 /**< delay possible for extended period of time */
+} flowControl_t;
+
+/* filter operations */
+typedef enum {
+ FIOP_NOP = 0, /* do not use - No Operation */
+ FIOP_CONTAINS = 1, /* contains string? */
+ FIOP_ISEQUAL = 2, /* is (exactly) equal? */
+ FIOP_STARTSWITH = 3, /* starts with a string? */
+ FIOP_REGEX = 4, /* matches a (BRE) regular expression? */
+ FIOP_EREREGEX = 5, /* matches a ERE regular expression? */
+ FIOP_ISEMPTY = 6 /* string empty <=> strlen(s) == 0 ?*/
+} fiop_t;
+
+#ifndef HAVE_LSEEK64
+# ifndef HAVE_OFF64_T
+ typedef off_t off64_t;
+# endif
+#endif
+
+
+/* properties are now encoded as (tiny) integers. I do not use an enum as I would like
+ * to keep the memory footprint small (and thus cache hits high).
+ * rgerhards, 2009-06-26
+ */
+typedef uintTiny propid_t;
+#define PROP_INVALID 0
+#define PROP_MSG 1
+#define PROP_TIMESTAMP 2
+#define PROP_HOSTNAME 3
+#define PROP_SYSLOGTAG 4
+#define PROP_RAWMSG 5
+#define PROP_INPUTNAME 6
+#define PROP_FROMHOST 7
+#define PROP_FROMHOST_IP 8
+#define PROP_PRI 9
+#define PROP_PRI_TEXT 10
+#define PROP_IUT 11
+#define PROP_SYSLOGFACILITY 12
+#define PROP_SYSLOGFACILITY_TEXT 13
+#define PROP_SYSLOGSEVERITY 14
+#define PROP_SYSLOGSEVERITY_TEXT 15
+#define PROP_TIMEGENERATED 16
+#define PROP_PROGRAMNAME 17
+#define PROP_PROTOCOL_VERSION 18
+#define PROP_STRUCTURED_DATA 19
+#define PROP_APP_NAME 20
+#define PROP_PROCID 21
+#define PROP_MSGID 22
+#define PROP_PARSESUCCESS 23
+#define PROP_JSONMESG 24
+#define PROP_RAWMSG_AFTER_PRI 25
+#define PROP_SYS_NOW 150
+#define PROP_SYS_YEAR 151
+#define PROP_SYS_MONTH 152
+#define PROP_SYS_DAY 153
+#define PROP_SYS_HOUR 154
+#define PROP_SYS_HHOUR 155
+#define PROP_SYS_QHOUR 156
+#define PROP_SYS_MINUTE 157
+#define PROP_SYS_MYHOSTNAME 158
+#define PROP_SYS_BOM 159
+#define PROP_SYS_UPTIME 160
+#define PROP_UUID 161
+#define PROP_SYS_NOW_UTC 162
+#define PROP_SYS_YEAR_UTC 163
+#define PROP_SYS_MONTH_UTC 164
+#define PROP_SYS_DAY_UTC 165
+#define PROP_SYS_HOUR_UTC 166
+#define PROP_SYS_HHOUR_UTC 167
+#define PROP_SYS_QHOUR_UTC 168
+#define PROP_SYS_MINUTE_UTC 169
+#define PROP_SYS_WDAY 170
+#define PROP_SYS_WDAY_UTC 171
+#define PROP_SYS_NOW_UXTIMESTAMP 173
+#define PROP_CEE 200
+#define PROP_CEE_ALL_JSON 201
+#define PROP_LOCAL_VAR 202
+#define PROP_GLOBAL_VAR 203
+#define PROP_CEE_ALL_JSON_PLAIN 204
+
+/* types of configuration handlers
+ */
+typedef enum cslCmdHdlrType {
+ eCmdHdlrInvalid = 0, /* invalid handler type - indicates a coding error */
+ eCmdHdlrCustomHandler, /* custom handler, just call handler function */
+ eCmdHdlrUID,
+ eCmdHdlrGID,
+ eCmdHdlrBinary,
+ eCmdHdlrFileCreateMode,
+ eCmdHdlrInt,
+ eCmdHdlrNonNegInt,
+ eCmdHdlrPositiveInt,
+ eCmdHdlrSize,
+ eCmdHdlrGetChar,
+ eCmdHdlrFacility,
+ eCmdHdlrSeverity,
+ eCmdHdlrGetWord,
+ eCmdHdlrString,
+ eCmdHdlrArray,
+ eCmdHdlrQueueType,
+ eCmdHdlrGoneAway /* statment existed, but is no longer supported */
+} ecslCmdHdrlType;
+
+
+/* the next type describes $Begin .. $End block object types
+ */
+typedef enum cslConfObjType {
+ eConfObjGlobal = 0, /* global directives */
+ eConfObjAction, /* action-specific directives */
+ /* now come states that indicate that we wait for a block-end. These are
+ * states that permit us to do some safety checks and they hopefully ease
+ * migration to a "real" parser/grammar.
+ */
+ eConfObjActionWaitEnd,
+ eConfObjAlways /* always valid, very special case (guess $End only!) */
+} ecslConfObjType;
+
+
+/* multi-submit support.
+ * This is done via a simple data structure, which holds the number of elements
+ * as well as an array of to-be-submitted messages.
+ * rgerhards, 2009-06-16
+ */
+typedef struct multi_submit_s multi_submit_t;
+struct multi_submit_s {
+ short maxElem; /* maximum number of Elements */
+ short nElem; /* current number of Elements, points to the next one FREE */
+ smsg_t **ppMsgs;
+};
+
+/* the following structure is a helper to describe a message property */
+struct msgPropDescr_s {
+ propid_t id;
+ uchar *name; /* name and lenName are only set for dynamic */
+ int nameLen; /* properties (JSON) */
+};
+
+/* some forward-definitions from the grammar */
+struct nvlst;
+struct cnfobj;
+
+#endif /* multi-include protection */
diff --git a/runtime/unicode-helper.h b/runtime/unicode-helper.h
new file mode 100644
index 0000000..61dc2e0
--- /dev/null
+++ b/runtime/unicode-helper.h
@@ -0,0 +1,44 @@
+/* This is the header file for unicode support.
+ *
+ * Currently, this is a dummy module.
+ * The following functions are wrappers which hopefully enable us to move
+ * from 8-bit chars to unicode with relative ease when we finally attack this
+ *
+ * Begun 2009-05-21 RGerhards
+ *
+ * Copyright (C) 2009-2016 by Rainer Gerhards and Adiscon GmbH
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_UNICODE_HELPER_H
+#define INCLUDED_UNICODE_HELPER_H
+
+#include <string.h>
+
+#define ustrncpy(psz1, psz2, len) strncpy((char*)(psz1), (char*)(psz2), (len))
+#define ustrdup(psz) (uchar*)strdup((char*)(psz))
+#define ustrcmp(psz1, psz2) (strcmp((const char*) (psz1), (const char*) (psz2)))
+#define ustrlen(psz) (strlen((const char*) (psz)))
+#define UCHAR_CONSTANT(x) ((uchar*) (x))
+#define CHAR_CONVERT(x) ((char*) (x))
+
+/* Compare values of two instances/configs/queues especially during dynamic config reload */
+#define USTR_EQUALS(var) \
+ ((pOld->var == NULL) ? (pNew->var == NULL) : (pNew->var != NULL && !ustrcmp(pOld->var, pNew->var)))
+#define NUM_EQUALS(var) (pOld->var == pNew->var)
+
+#endif /* multi-include protection */
diff --git a/runtime/unlimited_select.h b/runtime/unlimited_select.h
new file mode 100644
index 0000000..fcc0107
--- /dev/null
+++ b/runtime/unlimited_select.h
@@ -0,0 +1,45 @@
+/* unlimited_select.h
+ * Tweak the macros for accessing fd_set so that the select() syscall
+ * won't be limited to a particular number of file descriptors.
+ *
+ * Copyright 2009-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNLIMITED_SELECT_H_INCLUDED
+#define UNLIMITED_SELECT_H_INCLUDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include "glbl.h"
+
+#ifdef USE_UNLIMITED_SELECT
+# undef FD_ZERO
+# define FD_ZERO(set) memset((set), 0, glbl.GetFdSetSize());
+#endif
+
+#ifdef USE_UNLIMITED_SELECT
+static inline void freeFdSet(fd_set *p) {
+ free(p);
+}
+#else
+# define freeFdSet(x)
+#endif
+
+#endif /* #ifndef UNLIMITED_SELECT_H_INCLUDED */
diff --git a/runtime/var.c b/runtime/var.c
new file mode 100644
index 0000000..c636fbb
--- /dev/null
+++ b/runtime/var.c
@@ -0,0 +1,131 @@
+/* var.c - a typeless variable class
+ *
+ * This class is used to represent variable values, which may have any type.
+ * Among others, it will be used inside rsyslog's expression system, but
+ * also internally at any place where a typeless variable is needed.
+ *
+ * Module begun 2008-02-20 by Rainer Gerhards, with some code taken
+ * from the obj.c/.h files.
+ *
+ * Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "srUtils.h"
+#include "var.h"
+
+/* static data */
+DEFobjStaticHelpers
+
+
+/* Standard-Constructor
+ */
+BEGINobjConstruct(var) /* be sure to specify the object type also in END macro! */
+ENDobjConstruct(var)
+
+
+/* ConstructionFinalizer
+ * rgerhards, 2008-01-09
+ */
+static rsRetVal
+varConstructFinalize(var_t __attribute__((unused)) *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, var);
+
+ RETiRet;
+}
+
+
+/* destructor for the var object */
+BEGINobjDestruct(var) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(var)
+ if(pThis->pcsName != NULL)
+ rsCStrDestruct(&pThis->pcsName);
+ if(pThis->varType == VARTYPE_STR) {
+ if(pThis->val.pStr != NULL)
+ rsCStrDestruct(&pThis->val.pStr);
+ }
+ENDobjDestruct(var)
+
+
+/* DebugPrint support for the var object */
+BEGINobjDebugPrint(var) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDebugPrint(var)
+ switch(pThis->varType) {
+ case VARTYPE_STR:
+ dbgoprint((obj_t*) pThis, "type: cstr, val '%s'\n", rsCStrGetSzStrNoNULL(pThis->val.pStr));
+ break;
+ case VARTYPE_NUMBER:
+ dbgoprint((obj_t*) pThis, "type: number, val %lld\n", pThis->val.num);
+ break;
+ case VARTYPE_SYSLOGTIME:
+ case VARTYPE_NONE:
+ default:
+ dbgoprint((obj_t*) pThis, "type %d currently not supported in debug output\n", pThis->varType);
+ break;
+ }
+ENDobjDebugPrint(var)
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(var)
+CODESTARTobjQueryInterface(var)
+ if(pIf->ifVersion != varCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->Construct = varConstruct;
+ pIf->ConstructFinalize = varConstructFinalize;
+ pIf->Destruct = varDestruct;
+ pIf->DebugPrint = varDebugPrint;
+finalize_it:
+ENDobjQueryInterface(var)
+
+
+/* Initialize the var class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINObjClassInit(var, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* now set our own handlers */
+ OBJSetMethodHandler(objMethod_DEBUGPRINT, varDebugPrint);
+ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, varConstructFinalize);
+ENDObjClassInit(var)
+
+/* vi:set ai:
+ */
diff --git a/runtime/var.h b/runtime/var.h
new file mode 100644
index 0000000..ab1c005
--- /dev/null
+++ b/runtime/var.h
@@ -0,0 +1,62 @@
+/* The var object.
+ *
+ * Copyright 2008-2012 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_VAR_H
+#define INCLUDED_VAR_H
+
+#include "stringbuf.h"
+
+/* data types */
+typedef enum {
+ VARTYPE_NONE = 0, /* currently no value set */
+ VARTYPE_STR = 1,
+ VARTYPE_NUMBER = 2,
+ VARTYPE_SYSLOGTIME = 3
+} varType_t;
+
+/* the var object */
+typedef struct var_s {
+ BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ cstr_t *pcsName;
+ varType_t varType;
+ union {
+ number_t num;
+ es_str_t *str;
+ cstr_t *pStr;
+ syslogTime_t vSyslogTime;
+ } val;
+} var_t;
+
+
+/* interfaces */
+BEGINinterface(var) /* name must also be changed in ENDinterface macro! */
+ INTERFACEObjDebugPrint(var);
+ rsRetVal (*Construct)(var_t **ppThis);
+ rsRetVal (*ConstructFinalize)(var_t __attribute__((unused)) *pThis);
+ rsRetVal (*Destruct)(var_t **ppThis);
+ENDinterface(var)
+#define varCURR_IF_VERSION 2 /* increment whenever you change the interface above! */
+/* v2 - 2011-07-15/rger: on the way to remove var */
+
+
+/* prototypes */
+PROTOTYPEObj(var);
+
+#endif /* #ifndef INCLUDED_VAR_H */
diff --git a/runtime/wti.c b/runtime/wti.c
new file mode 100644
index 0000000..96bae4d
--- /dev/null
+++ b/runtime/wti.c
@@ -0,0 +1,573 @@
+/* wti.c
+ *
+ * This file implements the worker thread instance (wti) class.
+ *
+ * File begun on 2008-01-20 by RGerhards based on functions from the
+ * previous queue object class (the wti functions have been extracted)
+ *
+ * There is some in-depth documentation available in doc/dev_queue.html
+ * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it
+ * if you are getting aquainted to the object.
+ *
+ * Copyright 2008-2019 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "wtp.h"
+#include "wti.h"
+#include "obj.h"
+#include "glbl.h"
+#include "action.h"
+#include "atomic.h"
+#include "rsconf.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+pthread_key_t thrd_wti_key;
+
+
+/* forward-definitions */
+
+/* methods */
+
+/* get the header for debug messages
+ * The caller must NOT free or otherwise modify the returned string!
+ */
+uchar * ATTR_NONNULL()
+wtiGetDbgHdr(const wti_t *const pThis)
+{
+ ISOBJ_TYPE_assert(pThis, wti);
+
+ if(pThis->pszDbgHdr == NULL)
+ return (uchar*) "wti"; /* should not normally happen */
+ else
+ return pThis->pszDbgHdr;
+}
+
+
+/* return the current worker processing state. For the sake of
+ * simplicity, we do not use the iRet interface. -- rgerhards, 2009-07-17
+ */
+int ATTR_NONNULL()
+wtiGetState(wti_t *pThis)
+{
+ return ATOMIC_FETCH_32BIT(&pThis->bIsRunning, &pThis->mutIsRunning);
+}
+
+/* join terminated worker thread
+ * This may be called in any thread state, it will be a NOP if the
+ * thread is not to join.
+ */
+void ATTR_NONNULL()
+wtiJoinThrd(wti_t *const pThis)
+{
+ int r;
+ ISOBJ_TYPE_assert(pThis, wti);
+ if(wtiGetState(pThis) == WRKTHRD_WAIT_JOIN) {
+ DBGPRINTF("%s: joining terminated worker\n", wtiGetDbgHdr(pThis));
+ if((r = pthread_join(pThis->thrdID, NULL)) != 0) {
+ LogMsg(r, RS_RET_INTERNAL_ERROR, LOG_WARNING,
+ "rsyslog bug? wti cannot join terminated wrkr");
+ }
+ DBGPRINTF("%s: worker fully terminated\n", wtiGetDbgHdr(pThis));
+ wtiSetState(pThis, WRKTHRD_STOPPED);
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: thread joined\n",
+ wtiGetDbgHdr(pThis));
+ }
+ }
+}
+
+/* Set this thread to "always running" state (can not be unset)
+ * rgerhards, 2009-07-20
+ */
+rsRetVal ATTR_NONNULL()
+wtiSetAlwaysRunning(wti_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, wti);
+ pThis->bAlwaysRunning = RSTRUE;
+ return RS_RET_OK;
+}
+
+/* Set status (thread is running or not), actually an property of
+ * use for wtp, but we need to have it per thread instance (thus it
+ * is inside wti). -- rgerhards, 2009-07-17
+ */
+rsRetVal ATTR_NONNULL()
+wtiSetState(wti_t *pThis, const int newVal)
+{
+ ISOBJ_TYPE_assert(pThis, wti);
+ if(newVal == WRKTHRD_STOPPED) {
+ ATOMIC_STORE_0_TO_INT(&pThis->bIsRunning, &pThis->mutIsRunning);
+ } else {
+ ATOMIC_OR_INT_TO_INT(&pThis->bIsRunning, &pThis->mutIsRunning, newVal);
+ }
+ return RS_RET_OK;
+}
+
+
+/* advise all workers to start by interrupting them. That should unblock all srSleep()
+ * calls.
+ */
+rsRetVal
+wtiWakeupThrd(wti_t *pThis)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, wti);
+
+ if(wtiGetState(pThis)) {
+ /* we first try the cooperative "cancel" interface */
+ pthread_kill(pThis->thrdID, SIGTTIN);
+ DBGPRINTF("sent SIGTTIN to worker thread %p\n", (void*) pThis->thrdID);
+ }
+
+ RETiRet;
+}
+
+
+/* Cancel the thread. If the thread is not running. But it is save and legal to
+ * call wtiCancelThrd() in such situations. This function only returns when the
+ * thread has terminated. Else we may get race conditions all over the code...
+ * Note that when waiting for the thread to terminate, we do a busy wait, checking
+ * progress every 10ms. It is very unlikely that we will ever cancel a thread
+ * and, if so, it will only happen at the end of the rsyslog run. So doing this
+ * kind of non-optimal wait is considered preferable over using condition variables.
+ * rgerhards, 2008-02-26
+ */
+rsRetVal ATTR_NONNULL()
+wtiCancelThrd(wti_t *pThis, const uchar *const cancelobj)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, wti);
+
+ wtiJoinThrd(pThis);
+ if(wtiGetState(pThis) != WRKTHRD_STOPPED) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING, "%s: need to do cooperative cancellation "
+ "- some data may be lost, increase timeout?", cancelobj);
+ /* we first try the cooperative "cancel" interface */
+ pthread_kill(pThis->thrdID, SIGTTIN);
+ DBGPRINTF("sent SIGTTIN to worker thread %p, giving it a chance to terminate\n",
+ (void *) pThis->thrdID);
+ srSleep(0, 50000);
+ wtiJoinThrd(pThis);
+ }
+
+ if(wtiGetState(pThis) != WRKTHRD_STOPPED) {
+ LogMsg(0, RS_RET_ERR, LOG_WARNING, "%s: need to do hard cancellation", cancelobj);
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: need to do hard cancellation\n",
+ cancelobj);
+ }
+ pthread_cancel(pThis->thrdID);
+ pthread_kill(pThis->thrdID, SIGTTIN);
+ DBGPRINTF("cooperative worker termination failed, using cancellation...\n");
+ DBGOPRINT((obj_t*) pThis, "canceling worker thread\n");
+ pthread_cancel(pThis->thrdID);
+ /* now wait until the thread terminates... */
+ while(wtiGetState(pThis) != WRKTHRD_STOPPED && wtiGetState(pThis) != WRKTHRD_WAIT_JOIN) {
+ DBGOPRINT((obj_t*) pThis, "waiting on termination, state %d\n", wtiGetState(pThis));
+ srSleep(0, 10000);
+ }
+ }
+
+ wtiJoinThrd(pThis);
+ RETiRet;
+}
+
+/* note: this function is only called once in action.c */
+rsRetVal
+wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams)
+{
+ actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]);
+ actWrkrIParams_t *iparams;
+ int newMax;
+ DEFiRet;
+
+ if(wrkrInfo->p.tx.currIParam == wrkrInfo->p.tx.maxIParams) {
+ /* we need to extend */
+ newMax = (wrkrInfo->p.tx.maxIParams == 0) ? CONF_IPARAMS_BUFSIZE
+ : 2 * wrkrInfo->p.tx.maxIParams;
+ CHKmalloc(iparams = realloc(wrkrInfo->p.tx.iparams,
+ sizeof(actWrkrIParams_t) * pAction->iNumTpls * newMax));
+ memset(iparams + (wrkrInfo->p.tx.currIParam * pAction->iNumTpls), 0,
+ sizeof(actWrkrIParams_t) * pAction->iNumTpls * (newMax - wrkrInfo->p.tx.maxIParams));
+ wrkrInfo->p.tx.iparams = iparams;
+ wrkrInfo->p.tx.maxIParams = newMax;
+ }
+ *piparams = wrkrInfo->p.tx.iparams + wrkrInfo->p.tx.currIParam * pAction->iNumTpls;
+ ++wrkrInfo->p.tx.currIParam;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* Destructor */
+BEGINobjDestruct(wti) /* be sure to specify the object type also in END and CODESTART macros! */
+CODESTARTobjDestruct(wti)
+ if(wtiGetState(pThis) != WRKTHRD_STOPPED) {
+ DBGPRINTF("%s: rsyslog bug: worker not stopped during shutdown\n",
+ wtiGetDbgHdr(pThis));
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "RSYSLOG BUG: %s: worker not stopped during shutdown\n",
+ wtiGetDbgHdr(pThis));
+ } else {
+ assert(wtiGetState(pThis) == WRKTHRD_STOPPED);
+ }
+ }
+ /* actual destruction */
+ batchFree(&pThis->batch);
+ free(pThis->actWrkrInfo);
+ pthread_cond_destroy(&pThis->pcondBusy);
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutIsRunning);
+ free(pThis->pszDbgHdr);
+ENDobjDestruct(wti)
+
+
+/* Standard-Constructor for the wti object
+ */
+BEGINobjConstruct(wti) /* be sure to specify the object type also in END macro! */
+ INIT_ATOMIC_HELPER_MUT(pThis->mutIsRunning);
+ pthread_cond_init(&pThis->pcondBusy, NULL);
+ENDobjConstruct(wti)
+
+
+/* Construction finalizer
+ * rgerhards, 2008-01-17
+ */
+rsRetVal
+wtiConstructFinalize(wti_t *pThis)
+{
+ DEFiRet;
+ int iDeqBatchSize;
+
+ ISOBJ_TYPE_assert(pThis, wti);
+
+ DBGPRINTF("%s: finalizing construction of worker instance data (for %d actions)\n",
+ wtiGetDbgHdr(pThis), runConf->actions.iActionNbr);
+
+ /* initialize our thread instance descriptor (no concurrency here) */
+ pThis->bIsRunning = WRKTHRD_STOPPED;
+
+ /* must use calloc as we need zero-init */
+ CHKmalloc(pThis->actWrkrInfo = calloc(runConf->actions.iActionNbr, sizeof(actWrkrInfo_t)));
+
+ if(pThis->pWtp == NULL) {
+ dbgprintf("wtiConstructFinalize: pWtp not set, this may be intentional\n");
+ FINALIZE;
+ }
+
+ /* we now alloc the array for user pointers. We obtain the max from the queue itself. */
+ CHKiRet(pThis->pWtp->pfGetDeqBatchSize(pThis->pWtp->pUsr, &iDeqBatchSize));
+ CHKiRet(batchInit(&pThis->batch, iDeqBatchSize));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* cancellation cleanup handler for queueWorker ()
+ * Most importantly, it must bring back the batch into a consistent state.
+ * Keep in mind that cancellation is disabled if we run into
+ * the cancel cleanup handler (and have been cancelled).
+ * rgerhards, 2008-01-16
+ */
+static void
+wtiWorkerCancelCleanup(void *arg)
+{
+ wti_t *pThis = (wti_t*) arg;
+ wtp_t *pWtp;
+
+ ISOBJ_TYPE_assert(pThis, wti);
+ pWtp = pThis->pWtp;
+ ISOBJ_TYPE_assert(pWtp, wtp);
+
+ DBGPRINTF("%s: cancellation cleanup handler called.\n", wtiGetDbgHdr(pThis));
+ pWtp->pfObjProcessed(pWtp->pUsr, pThis);
+ DBGPRINTF("%s: done cancellation cleanup handler.\n", wtiGetDbgHdr(pThis));
+
+}
+
+
+/* wait for queue to become non-empty or timeout
+ * this is introduced as helper to support queue minimum batch sizes, but may
+ * also be used for other cases. This function waits until the queue is non-empty
+ * or a timeout occurs. The timeout must be passed in as absolute value.
+ * @returns 0 if timeout occurs (queue still empty), something else otherwise
+ */
+int ATTR_NONNULL()
+wtiWaitNonEmpty(wti_t *const pThis, const struct timespec timeout)
+{
+ wtp_t *__restrict__ const pWtp = pThis->pWtp;
+ int r;
+
+ DBGOPRINT((obj_t*) pThis, "waiting on queue to become non-empty\n");
+ if(d_pthread_cond_timedwait(&pThis->pcondBusy, pWtp->pmutUsr, &timeout) != 0) {
+ r = 0;
+ } else {
+ r = 1;
+ }
+ DBGOPRINT((obj_t*) pThis, "waited on queue to become non-empty, result %d\n", r);
+ return r;
+}
+
+
+/* wait for queue to become non-empty or timeout
+ * helper to wtiWorker. Note the the predicate is
+ * re-tested by the caller, so it is OK to NOT do it here.
+ * rgerhards, 2009-05-20
+ */
+static void ATTR_NONNULL()
+doIdleProcessing(wti_t *const pThis, wtp_t *const pWtp, int *const pbInactivityTOOccurred)
+{
+ struct timespec t;
+
+ DBGPRINTF("%s: worker IDLE, waiting for work.\n", wtiGetDbgHdr(pThis));
+
+ if(pThis->bAlwaysRunning) {
+ /* never shut down any started worker */
+ d_pthread_cond_wait(&pThis->pcondBusy, pWtp->pmutUsr);
+ } else {
+ timeoutComp(&t, pWtp->toWrkShutdown);/* get absolute timeout */
+ if(d_pthread_cond_timedwait(&pThis->pcondBusy, pWtp->pmutUsr, &t) != 0) {
+ DBGPRINTF("%s: inactivity timeout, worker terminating...\n", wtiGetDbgHdr(pThis));
+ *pbInactivityTOOccurred = 1; /* indicate we had a timeout */
+ }
+ }
+ DBGOPRINT((obj_t*) pThis, "worker awoke from idle processing\n");
+}
+
+
+/* generic worker thread framework. Note that we prohibit cancellation
+ * during almost all times, because it can have very undesired side effects.
+ * However, we may need to cancel a thread if the consumer blocks for too
+ * long (during shutdown). So what we do is block cancellation, and every
+ * consumer must enable it during the periods where it is safe.
+ */
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wempty_body
+rsRetVal
+wtiWorker(wti_t *__restrict__ const pThis)
+{
+ wtp_t *__restrict__ const pWtp = pThis->pWtp; /* our worker thread pool -- shortcut */
+ action_t *__restrict__ pAction;
+ rsRetVal localRet;
+ rsRetVal terminateRet;
+ actWrkrInfo_t *__restrict__ wrkrInfo;
+ int iCancelStateSave;
+ int i, j, k;
+ DEFiRet;
+
+ dbgSetThrdName(pThis->pszDbgHdr);
+ pthread_cleanup_push(wtiWorkerCancelCleanup, pThis);
+ int bInactivityTOOccurred = 0;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+ DBGPRINTF("wti %p: worker starting\n", pThis);
+ /* now we have our identity, on to real processing */
+
+ /* note: in this loop, the mutex is "never" unlocked. Of course,
+ * this is not true: it actually is unlocked when the actual processing
+ * is done, as part of pWtp->pfDoWork() processing. Note that this
+ * function is required to re-lock it when done. We cannot do the
+ * lock/unlock here ourselfs, as pfDoWork() needs to access queue
+ * structures itself.
+ * The same goes for pfRateLimiter(). While we could unlock/lock when
+ * we call it, in practice the function is often called without any
+ * ratelimiting actually done. Only the rate limiter itself knows
+ * that. As such, it needs to bear the burden of doing the locking
+ * when required. -- rgerhards, 2013-11-20
+ */
+ d_pthread_mutex_lock(pWtp->pmutUsr);
+ while(1) { /* loop will be broken below */
+ if(pWtp->pfRateLimiter != NULL) { /* call rate-limiter, if defined */
+ pWtp->pfRateLimiter(pWtp->pUsr);
+ }
+
+ /* first check if we are in shutdown process (but evaluate a bit later) */
+ terminateRet = wtpChkStopWrkr(pWtp, MUTEX_ALREADY_LOCKED);
+ if(terminateRet == RS_RET_TERMINATE_NOW) {
+ /* we now need to free the old batch */
+ localRet = pWtp->pfObjProcessed(pWtp->pUsr, pThis);
+ DBGOPRINT((obj_t*) pThis, "terminating worker because of "
+ "TERMINATE_NOW mode, del iRet %d\n", localRet);
+ break;
+ }
+
+ /* try to execute and process whatever we have */
+ localRet = pWtp->pfDoWork(pWtp->pUsr, pThis);
+
+ if(localRet == RS_RET_ERR_QUEUE_EMERGENCY) {
+ break; /* end of loop */
+ } else if(localRet == RS_RET_IDLE) {
+ if(terminateRet == RS_RET_TERMINATE_WHEN_IDLE || bInactivityTOOccurred) {
+ DBGOPRINT((obj_t*) pThis, "terminating worker terminateRet=%d, "
+ "bInactivityTOOccurred=%d\n", terminateRet, bInactivityTOOccurred);
+ break; /* end of loop */
+ }
+ doIdleProcessing(pThis, pWtp, &bInactivityTOOccurred);
+ continue; /* request next iteration */
+ }
+
+ bInactivityTOOccurred = 0; /* reset for next run */
+ }
+
+ d_pthread_mutex_unlock(pWtp->pmutUsr);
+
+ DBGPRINTF("DDDD: wti %p: worker cleanup action instances\n", pThis);
+ for(i = 0 ; i < runConf->actions.iActionNbr ; ++i) {
+ wrkrInfo = &(pThis->actWrkrInfo[i]);
+ dbgprintf("wti %p, action %d, ptr %p\n", pThis, i, wrkrInfo->actWrkrData);
+ if(wrkrInfo->actWrkrData != NULL) {
+ pAction = wrkrInfo->pAction;
+ actionRemoveWorker(pAction, wrkrInfo->actWrkrData);
+ pAction->pMod->mod.om.freeWrkrInstance(wrkrInfo->actWrkrData);
+ if(pAction->isTransactional) {
+ /* free iparam "cache" - we need to go through to max! */
+ for(j = 0 ; j < wrkrInfo->p.tx.maxIParams ; ++j) {
+ for(k = 0 ; k < pAction->iNumTpls ; ++k) {
+ free(actParam(wrkrInfo->p.tx.iparams,
+ pAction->iNumTpls, j, k).param);
+ }
+ }
+ free(wrkrInfo->p.tx.iparams);
+ wrkrInfo->p.tx.iparams = NULL;
+ wrkrInfo->p.tx.currIParam = 0;
+ wrkrInfo->p.tx.maxIParams = 0;
+ } else {
+ releaseDoActionParams(pAction, pThis, 1);
+ }
+ wrkrInfo->actWrkrData = NULL; /* re-init for next activation */
+ }
+ }
+
+ /* indicate termination */
+ pthread_cleanup_pop(0); /* remove cleanup handler */
+ pthread_setcancelstate(iCancelStateSave, NULL);
+ dbgprintf("wti %p: exiting\n", pThis);
+
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+
+/* some simple object access methods */
+DEFpropSetMeth(wti, pWtp, wtp_t*)
+
+/* set the debug header message
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it. Must be called only before object is finalized.
+ * rgerhards, 2008-01-09
+ */
+rsRetVal
+wtiSetDbgHdr(wti_t *pThis, uchar *pszMsg, const size_t lenMsg)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, wti);
+ assert(pszMsg != NULL);
+
+ if(lenMsg < 1)
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+
+ if(pThis->pszDbgHdr != NULL) {
+ free(pThis->pszDbgHdr);
+ }
+
+ if((pThis->pszDbgHdr = malloc(lenMsg + 1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ memcpy(pThis->pszDbgHdr, pszMsg, lenMsg + 1); /* always think about the \0! */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function returns (and creates if necessary) a dummy wti suitable
+ * for use by the rule engine. It is intended to be used for direct-mode
+ * main queues (folks, don't do that!). Once created, data is stored in
+ * thread-specific storage.
+ * Note: we do NOT do error checking -- if this functions fails, all the
+ * rest will fail as well... (also, it will only fail under OOM, so...).
+ * Memleak: we leak pWti's when run in direct mode. However, this is only
+ * a cosmetic leak, as we need them until all inputs are terminated,
+ * what means essentially until rsyslog itself is terminated. So we
+ * don't care -- it's just not nice in valgrind, but that's it.
+ */
+wti_t *
+wtiGetDummy(void)
+{
+ wti_t *pWti;
+
+ pWti = (wti_t*) pthread_getspecific(thrd_wti_key);
+ if(pWti == NULL) {
+ wtiConstruct(&pWti);
+ if(pWti != NULL)
+ wtiConstructFinalize(pWti);
+ if(pthread_setspecific(thrd_wti_key, pWti) != 0) {
+ DBGPRINTF("wtiGetDummy: error setspecific thrd_wti_key\n");
+ }
+ }
+ return pWti;
+}
+
+/* dummy */
+static rsRetVal wtiQueryInterface(interface_t __attribute__((unused)) *i) { return RS_RET_NOT_IMPLEMENTED; }
+
+/* exit our class
+ */
+BEGINObjClassExit(wti, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_gtls)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ pthread_key_delete(thrd_wti_key);
+ENDObjClassExit(wti)
+
+
+/* Initialize the wti class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-01-09
+ */
+BEGINObjClassInit(wti, 1, OBJ_IS_CORE_MODULE) /* one is the object version (most important for persisting) */
+ int r;
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ r = pthread_key_create(&thrd_wti_key, NULL);
+ if(r != 0) {
+ dbgprintf("wti.c: pthread_key_create failed\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ENDObjClassInit(wti)
diff --git a/runtime/wti.h b/runtime/wti.h
new file mode 100644
index 0000000..71eed56
--- /dev/null
+++ b/runtime/wti.h
@@ -0,0 +1,144 @@
+/* Definition of the worker thread instance (wti) class.
+ *
+ * Copyright 2008-2017 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WTI_H_INCLUDED
+#define WTI_H_INCLUDED
+
+#include <pthread.h>
+#include <stdlib.h>
+#include "wtp.h"
+#include "obj.h"
+#include "batch.h"
+#include "action.h"
+
+
+#define ACT_STATE_RDY 0 /* action ready, waiting for new transaction */
+#define ACT_STATE_ITX 1 /* transaction active, waiting for new data or commit */
+/* 2 currently not being used */
+#define ACT_STATE_RTRY 3 /* failure occurred, trying to restablish ready state */
+#define ACT_STATE_SUSP 4 /* suspended due to failure (return fail until timeout expired) */
+#define ACT_STATE_DATAFAIL 5 /* suspended due to failure in data, which means the message in
+ questions needs to be dropped as it will always fail. The
+ action must still do a "normal" retry in order to bring
+ it back to regular state. */
+/* note: 3 bit bit field --> highest value is 7! */
+
+typedef struct actWrkrInfo {
+ action_t *pAction;
+ void *actWrkrData;
+ uint16_t uResumeOKinRow;/* number of times in a row that resume said OK with an
+ immediate failure following */
+ int iNbrResRtry; /* number of retries since last suspend */
+ sbool bHadAutoCommit; /* did an auto-commit happen during doAction()? */
+ struct {
+ unsigned actState : 3;
+ } flags;
+ union {
+ struct {
+ actWrkrIParams_t *iparams;/* dynamically sized array for transactional outputs */
+ int currIParam;
+ int maxIParams; /* current max */
+ } tx;
+ struct {
+ actWrkrIParams_t actParams[CONF_OMOD_NUMSTRINGS_MAXSIZE];
+ } nontx;
+ } p; /* short name for "parameters" */
+} actWrkrInfo_t;
+
+/* the worker thread instance class */
+struct wti_s {
+ BEGINobjInstance;
+ pthread_t thrdID; /* thread ID */
+ int bIsRunning; /* is this thread currently running? (must be int for atomic op!) */
+ sbool bAlwaysRunning; /* should this thread always run? */
+ int *pbShutdownImmediate;/* end processing of this batch immediately if set to 1 */
+ wtp_t *pWtp; /* my worker thread pool (important if only the work thread instance is passed! */
+ batch_t batch; /* pointer to an object array meaningful for current user
+ pointer (e.g. queue pUsr data elemt) */
+ uchar *pszDbgHdr; /* header string for debug messages */
+ actWrkrInfo_t *actWrkrInfo; /* *array* of action wrkr infos for all actions
+ (sized for max nbr of actions in config!) */
+ pthread_cond_t pcondBusy; /* condition to wake up the worker, protected by pmutUsr in wtp */
+ DEF_ATOMIC_HELPER_MUT(mutIsRunning)
+ struct {
+ uint8_t script_errno; /* errno-type interface for RainerScript functions */
+ uint8_t bPrevWasSuspended;
+ uint8_t bDoAutoCommit; /* do a commit after each message
+ * this is usually set for batches with 0 element, but may
+ * also be added as a user-selectable option (not implemented yet)
+ */
+ } execState; /* state for the execution engine */
+};
+
+
+/* prototypes */
+rsRetVal wtiConstruct(wti_t **ppThis);
+rsRetVal wtiConstructFinalize(wti_t * const pThis);
+rsRetVal wtiDestruct(wti_t **ppThis);
+rsRetVal wtiWorker(wti_t * const pThis);
+rsRetVal wtiSetDbgHdr(wti_t * const pThis, uchar *pszMsg, size_t lenMsg);
+uchar * ATTR_NONNULL() wtiGetDbgHdr(const wti_t *const pThis);
+rsRetVal wtiCancelThrd(wti_t * const pThis, const uchar *const cancelobj);
+void ATTR_NONNULL() wtiJoinThrd(wti_t *const pThis);
+rsRetVal wtiSetAlwaysRunning(wti_t * const pThis);
+rsRetVal wtiSetState(wti_t * const pThis, int bNew);
+rsRetVal wtiWakeupThrd(wti_t * const pThis);
+int wtiGetState(wti_t * const pThis);
+wti_t *wtiGetDummy(void);
+int ATTR_NONNULL() wtiWaitNonEmpty(wti_t *const pThis, const struct timespec timeout);
+PROTOTYPEObjClassInit(wti);
+PROTOTYPEObjClassExit(wti);
+PROTOTYPEpropSetMeth(wti, pszDbgHdr, uchar*);
+PROTOTYPEpropSetMeth(wti, pWtp, wtp_t*);
+
+#define getActionStateByNbr(pWti, iActNbr) ((uint8_t) ((pWti)->actWrkrInfo[(iActNbr)].flags.actState))
+#define getActionState(pWti, pAction) (((uint8_t) (pWti)->actWrkrInfo[(pAction)->iActionNbr].flags.actState))
+#define setActionState(pWti, pAction, newState) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].flags.actState = \
+(newState))
+#define getActionResumeInRow(pWti, pAction) (((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow))
+#define setActionResumeInRow(pWti, pAction, val) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow = (val))
+#define incActionResumeInRow(pWti, pAction) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow++)
+#define getActionNbrResRtry(pWti, pAction) (((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry))
+#define setActionNbrResRtry(pWti, pAction, val) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry = (val))
+#define incActionNbrResRtry(pWti, pAction) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry++)
+#define wtiInitIParam(piparams) (memset((piparams), 0, sizeof(actWrkrIParams_t)))
+
+#define wtiGetScriptErrno(pWti) ((pWti)->execState.script_errno)
+#define wtiSetScriptErrno(pWti, newval) (pWti)->execState.script_errno = (newval)
+
+static inline uint8_t ATTR_UNUSED ATTR_NONNULL(1)
+wtiGetPrevWasSuspended(const wti_t * const pWti)
+{
+ assert(pWti != NULL);
+ return pWti->execState.bPrevWasSuspended;
+}
+
+static inline void __attribute__((unused))
+wtiResetExecState(wti_t * const pWti, batch_t * const pBatch)
+{
+ wtiSetScriptErrno(pWti, 0);
+ pWti->execState.bPrevWasSuspended = 0;
+ pWti->execState.bDoAutoCommit = (batchNumMsgs(pBatch) == 1);
+}
+
+
+rsRetVal wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams);
+#endif /* #ifndef WTI_H_INCLUDED */
diff --git a/runtime/wtp.c b/runtime/wtp.c
new file mode 100644
index 0000000..3bce02a
--- /dev/null
+++ b/runtime/wtp.c
@@ -0,0 +1,650 @@
+/* wtp.c
+ *
+ * This file implements the worker thread pool (wtp) class.
+ *
+ * File begun on 2008-01-20 by RGerhards
+ *
+ * There is some in-depth documentation available in doc/dev_queue.html
+ * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it
+ * if you are getting aquainted to the object.
+ *
+ * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime 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 the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <atomic.h>
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
+
+/// TODO: check on solaris if this is any longer needed - I don't think so - rgerhards, 2009-09-20
+//#ifdef OS_SOLARIS
+//# include <sched.h>
+//#endif
+
+#include "rsyslog.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+#include "wtp.h"
+#include "wti.h"
+#include "obj.h"
+#include "unicode-helper.h"
+#include "glbl.h"
+#include "errmsg.h"
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
+
+/* forward-definitions */
+
+/* methods */
+
+/* get the header for debug messages
+ * The caller must NOT free or otherwise modify the returned string!
+ */
+static uchar *
+wtpGetDbgHdr(wtp_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ if(pThis->pszDbgHdr == NULL)
+ return (uchar*) "wtp"; /* should not normally happen */
+ else
+ return pThis->pszDbgHdr;
+}
+
+
+
+/* Not implemented dummy function for constructor */
+static rsRetVal NotImplementedDummy_voidp_int(__attribute__((unused)) void* p1, __attribute__((unused)) int p2) {
+ return RS_RET_NOT_IMPLEMENTED; }
+static rsRetVal NotImplementedDummy_voidp_intp(__attribute__((unused)) void* p1, __attribute__((unused)) int* p2) {
+ return RS_RET_NOT_IMPLEMENTED; }
+static rsRetVal NotImplementedDummy_voidp_voidp(__attribute__((unused)) void* p1, __attribute__((unused)) void* p2) {
+ return RS_RET_NOT_IMPLEMENTED; }
+static rsRetVal NotImplementedDummy_voidp_wti_tp(__attribute__((unused)) void* p1, __attribute__((unused)) wti_t* p2) {
+ return RS_RET_NOT_IMPLEMENTED; }
+/* Standard-Constructor for the wtp object
+ */
+BEGINobjConstruct(wtp) /* be sure to specify the object type also in END macro! */
+ pthread_mutex_init(&pThis->mutWtp, NULL);
+ pthread_cond_init(&pThis->condThrdInitDone, NULL);
+ pthread_cond_init(&pThis->condThrdTrm, NULL);
+ pthread_attr_init(&pThis->attrThrd);
+ /* Set thread scheduling policy to default */
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ pthread_attr_setschedpolicy(&pThis->attrThrd, default_thr_sched_policy);
+ pthread_attr_setschedparam(&pThis->attrThrd, &default_sched_param);
+ pthread_attr_setinheritsched(&pThis->attrThrd, PTHREAD_EXPLICIT_SCHED);
+#endif
+ /* set all function pointers to "not implemented" dummy so that we can safely call them */
+ pThis->pfChkStopWrkr = (rsRetVal (*)(void*,int))NotImplementedDummy_voidp_int;
+ pThis->pfGetDeqBatchSize = (rsRetVal (*)(void*,int*))NotImplementedDummy_voidp_intp;
+ pThis->pfDoWork = (rsRetVal (*)(void*,void*))NotImplementedDummy_voidp_voidp;
+ pThis->pfObjProcessed = (rsRetVal (*)(void*,wti_t*))NotImplementedDummy_voidp_wti_tp;
+ INIT_ATOMIC_HELPER_MUT(pThis->mutCurNumWrkThrd);
+ INIT_ATOMIC_HELPER_MUT(pThis->mutWtpState);
+ENDobjConstruct(wtp)
+
+
+/* Construction finalizer
+ * rgerhards, 2008-01-17
+ */
+rsRetVal
+wtpConstructFinalize(wtp_t *pThis)
+{
+ DEFiRet;
+ int i;
+ uchar pszBuf[64];
+ size_t lenBuf;
+ wti_t *pWti;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ DBGPRINTF("%s: finalizing construction of worker thread pool (numworkerThreads %d)\n",
+ wtpGetDbgHdr(pThis), pThis->iNumWorkerThreads);
+ /* alloc and construct workers - this can only be done in finalizer as we previously do
+ * not know the max number of workers
+ */
+ CHKmalloc(pThis->pWrkr = malloc(sizeof(wti_t*) * pThis->iNumWorkerThreads));
+
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ CHKiRet(wtiConstruct(&pThis->pWrkr[i]));
+ pWti = pThis->pWrkr[i];
+ lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%.*s/w%d",
+ (int) (sizeof(pszBuf)-6), /* leave 6 chars for \0, "/w" and number: */
+ wtpGetDbgHdr(pThis), i);
+ if(lenBuf >= sizeof(pszBuf)) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "%s:%d debug header too long: %zd - in "
+ "thory this cannot happen - truncating", __FILE__, __LINE__, lenBuf);
+ lenBuf = sizeof(pszBuf)-1;
+ pszBuf[lenBuf] = '\0';
+ }
+ CHKiRet(wtiSetDbgHdr(pWti, pszBuf, lenBuf));
+ CHKiRet(wtiSetpWtp(pWti, pThis));
+ CHKiRet(wtiConstructFinalize(pWti));
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Destructor */
+BEGINobjDestruct(wtp) /* be sure to specify the object type also in END and CODESTART macros! */
+ int i;
+CODESTARTobjDestruct(wtp)
+ d_pthread_mutex_lock(&pThis->mutWtp); /* make sure nobody is still using the mutex */
+ assert(pThis->iCurNumWrkThrd == 0);
+
+ /* destruct workers */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i)
+ wtiDestruct(&pThis->pWrkr[i]);
+
+ free(pThis->pWrkr);
+ pThis->pWrkr = NULL;
+
+ /* actual destruction */
+ d_pthread_mutex_unlock(&pThis->mutWtp);
+ pthread_cond_destroy(&pThis->condThrdTrm);
+ pthread_cond_destroy(&pThis->condThrdInitDone);
+ pthread_mutex_destroy(&pThis->mutWtp);
+ pthread_attr_destroy(&pThis->attrThrd);
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutCurNumWrkThrd);
+ DESTROY_ATOMIC_HELPER_MUT(pThis->mutWtpState);
+
+ free(pThis->pszDbgHdr);
+ENDobjDestruct(wtp)
+
+
+/* Sent a specific state for the worker thread pool. -- rgerhards, 2008-01-21
+ * We do not need to do atomic instructions as set operations are only
+ * called when terminating the pool, and then in strict sequence. So we
+ * can never overwrite each other. On the other hand, it also doesn't
+ * matter if the read operation obtains an older value, as we then simply
+ * do one more iteration, what is perfectly legal (during shutdown
+ * they are awoken in any case). -- rgerhards, 2009-07-20
+ */
+rsRetVal
+wtpSetState(wtp_t *pThis, wtpState_t iNewState)
+{
+ ISOBJ_TYPE_assert(pThis, wtp);
+ pThis->wtpState = iNewState; // TODO: do we need a mutex here? 2010-04-26
+ return RS_RET_OK;
+}
+
+/* join terminated worker threads */
+static void ATTR_NONNULL()
+wtpJoinTerminatedWrkr(wtp_t *const pThis)
+{
+ int i;
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ wtiJoinThrd(pThis->pWrkr[i]);
+ }
+}
+
+
+/* check if the worker shall shutdown (1 = yes, 0 = no)
+ * Note: there may be two mutexes locked, the bLockUsrMutex is the one in our "user"
+ * (e.g. the queue clas)
+ * rgerhards, 2008-01-21
+ */
+rsRetVal
+wtpChkStopWrkr(wtp_t *pThis, int bLockUsrMutex)
+{
+ DEFiRet;
+ wtpState_t wtpState;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+ /* we need a consistent value, but it doesn't really matter if it is changed
+ * right after the fetch - then we simply do one more iteration in the worker
+ */
+ wtpState = (wtpState_t) ATOMIC_FETCH_32BIT((int*)&pThis->wtpState, &pThis->mutWtpState);
+
+ if(wtpState == wtpState_SHUTDOWN_IMMEDIATE) {
+ ABORT_FINALIZE(RS_RET_TERMINATE_NOW);
+ } else if(wtpState == wtpState_SHUTDOWN) {
+ ABORT_FINALIZE(RS_RET_TERMINATE_WHEN_IDLE);
+ }
+
+ /* try customer handler if one was set and we do not yet have a definite result */
+ if(pThis->pfChkStopWrkr != NULL) {
+ iRet = pThis->pfChkStopWrkr(pThis->pUsr, bLockUsrMutex);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wempty_body
+/* Send a shutdown command to all workers and see if they terminate.
+ * A timeout may be specified. This function may also be called with
+ * the current number of workers being 0, in which case it does not
+ * shut down any worker.
+ * rgerhards, 2008-01-14
+ */
+rsRetVal ATTR_NONNULL()
+wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *ptTimeout)
+{
+ DEFiRet;
+ int bTimedOut;
+ int i;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ /* lock mutex to prevent races (may otherwise happen during idle processing and such...) */
+ d_pthread_mutex_lock(pThis->pmutUsr);
+ wtpSetState(pThis, tShutdownCmd);
+ /* awake workers in retry loop */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ wtpJoinTerminatedWrkr(pThis);
+ pthread_cond_signal(&pThis->pWrkr[i]->pcondBusy);
+ wtiWakeupThrd(pThis->pWrkr[i]);
+ }
+ d_pthread_mutex_unlock(pThis->pmutUsr);
+
+ /* wait for worker thread termination */
+ d_pthread_mutex_lock(&pThis->mutWtp);
+ pthread_cleanup_push(mutexCancelCleanup, &pThis->mutWtp);
+ bTimedOut = 0;
+ while(pThis->iCurNumWrkThrd > 0 && !bTimedOut) {
+ wtpJoinTerminatedWrkr(pThis);
+ DBGPRINTF("%s: waiting %ldms on worker thread termination, %d still running\n",
+ wtpGetDbgHdr(pThis), timeoutVal(ptTimeout),
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+
+ if(d_pthread_cond_timedwait(&pThis->condThrdTrm, &pThis->mutWtp, ptTimeout) != 0) {
+ DBGPRINTF("%s: timeout waiting on worker thread termination\n",
+ wtpGetDbgHdr(pThis));
+ bTimedOut = 1; /* we exit the loop on timeout */
+ }
+
+ /* awake workers in retry loop */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ wtiWakeupThrd(pThis->pWrkr[i]);
+ }
+
+ }
+ pthread_cleanup_pop(1);
+
+ if(bTimedOut)
+ iRet = RS_RET_TIMED_OUT;
+
+ RETiRet;
+}
+PRAGMA_DIAGNOSTIC_POP
+
+
+/* Unconditionally cancel all running worker threads.
+ * rgerhards, 2008-01-14
+ */
+rsRetVal ATTR_NONNULL()
+wtpCancelAll(wtp_t *pThis, const uchar *const cancelobj)
+{
+ DEFiRet;
+ int i;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ /* go through all workers and cancel those that are active */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ wtiCancelThrd(pThis->pWrkr[i], cancelobj);
+ }
+
+ RETiRet;
+}
+
+
+/* this function contains shared code for both regular worker shutdown as
+ * well as shutdown via cancellation. We can not simply use pthread_cleanup_pop(1)
+ * as this introduces a race in the debug system (RETiRet system).
+ * rgerhards, 2009-10-26
+ */
+static void
+wtpWrkrExecCleanup(wti_t *pWti)
+{
+ wtp_t *pThis;
+
+ ISOBJ_TYPE_assert(pWti, wti);
+ pThis = pWti->pWtp;
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+// TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards
+if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: enter WrkrExecCleanup\n", wtiGetDbgHdr(pWti));
+}
+ /* the order of the next two statements is important! */
+ wtiSetState(pWti, WRKTHRD_WAIT_JOIN);
+ ATOMIC_DEC(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd);
+
+ /* note: numWorkersNow is only for message generation, so we do not try
+ * hard to get it 100% accurate (as curently done, it is not).
+ */
+ const int numWorkersNow = ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd);
+ DBGPRINTF("%s: Worker thread %lx, terminated, num workers now %d\n",
+ wtpGetDbgHdr(pThis), (unsigned long) pWti, numWorkersNow);
+ if(numWorkersNow > 0) {
+ LogMsg(0, RS_RET_OPERATION_STATUS, LOG_INFO,
+ "%s: worker thread %lx terminated, now %d active worker threads",
+ wtpGetDbgHdr(pThis), (unsigned long) pWti, numWorkersNow);
+ }
+}
+
+
+/* cancellation cleanup handler for executing worker decrements the worker counter.
+ * rgerhards, 2009-07-20
+ */
+static void
+wtpWrkrExecCancelCleanup(void *arg)
+{
+ wti_t *pWti = (wti_t*) arg;
+ wtp_t *pThis;
+
+ ISOBJ_TYPE_assert(pWti, wti);
+ pThis = pWti->pWtp;
+ ISOBJ_TYPE_assert(pThis, wtp);
+ DBGPRINTF("%s: Worker thread %lx requested to be cancelled.\n",
+ wtpGetDbgHdr(pThis), (unsigned long) pWti);
+
+ wtpWrkrExecCleanup(pWti);
+
+ pthread_cond_broadcast(&pThis->condThrdTrm); /* activate anyone waiting on thread shutdown */
+}
+
+
+/* wtp worker shell. This is started and calls into the actual
+ * wti worker.
+ * rgerhards, 2008-01-21
+ */
+PRAGMA_DIAGNOSTIC_PUSH
+PRAGMA_IGNORE_Wempty_body
+static void *
+wtpWorker(void *arg) /* the arg is actually a wti object, even though we are in wtp! */
+{
+ wti_t *pWti = (wti_t*) arg;
+ wtp_t *pThis;
+ sigset_t sigSet;
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ uchar *pszDbgHdr;
+ uchar thrdName[32] = "rs:";
+# endif
+
+ ISOBJ_TYPE_assert(pWti, wti);
+ pThis = pWti->pWtp;
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ /* block all signals except SIGTTIN and SIGSEGV */
+ sigfillset(&sigSet);
+ sigdelset(&sigSet, SIGTTIN);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
+
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ /* set thread name - we ignore if the call fails, has no harsh consequences... */
+ pszDbgHdr = wtpGetDbgHdr(pThis);
+ ustrncpy(thrdName+3, pszDbgHdr, 20);
+ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) {
+ DBGPRINTF("prctl failed, not setting thread name for '%s'\n", wtpGetDbgHdr(pThis));
+ }
+ dbgOutputTID((char*)thrdName);
+# endif
+
+// TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards
+if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: worker %p started\n", wtpGetDbgHdr(pThis), pThis);
+}
+ /* let the parent know we're done with initialization */
+ d_pthread_mutex_lock(&pThis->mutWtp);
+ wtiSetState(pWti, WRKTHRD_RUNNING);
+ pthread_cond_broadcast(&pThis->condThrdInitDone);
+ d_pthread_mutex_unlock(&pThis->mutWtp);
+
+ pthread_cleanup_push(wtpWrkrExecCancelCleanup, pWti);
+
+ wtiWorker(pWti);
+ pthread_cleanup_pop(0);
+ d_pthread_mutex_lock(&pThis->mutWtp);
+ pthread_cleanup_push(mutexCancelCleanup, &pThis->mutWtp);
+ wtpWrkrExecCleanup(pWti);
+
+ pthread_cond_broadcast(&pThis->condThrdTrm); /* activate anyone waiting on thread shutdown */
+ pthread_cleanup_pop(1); /* unlock mutex */
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %p: worker exiting\n", pWti);
+ }
+ pthread_exit(0);
+ return NULL; /* To suppress warning */
+}
+PRAGMA_DIAGNOSTIC_POP
+
+/* start a new worker */
+static rsRetVal ATTR_NONNULL()
+wtpStartWrkr(wtp_t *const pThis, const int permit_during_shutdown)
+{
+ wti_t *pWti;
+ int i;
+ int iState;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+// TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards
+if(dbgTimeoutToStderr) {
+ fprintf(stderr, "%s: worker start requested, num workers currently %d\n",
+ wtpGetDbgHdr(pThis),
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+}
+ const wtpState_t wtpState = (wtpState_t) ATOMIC_FETCH_32BIT((int*)&pThis->wtpState, &pThis->mutWtpState);
+ if(wtpState != wtpState_RUNNING && !permit_during_shutdown) {
+ DBGPRINTF("%s: worker start requested during shutdown - ignored\n", wtpGetDbgHdr(pThis));
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: worker start requested during shutdown - ignored\n",
+ wtpGetDbgHdr(pThis));
+ }
+ return RS_RET_ERR; /* exceptional case, but really makes sense here! */
+ }
+
+ d_pthread_mutex_lock(&pThis->mutWtp);
+
+ wtpJoinTerminatedWrkr(pThis);
+ /* find free spot in thread table. */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ if(wtiGetState(pThis->pWrkr[i]) == WRKTHRD_STOPPED) {
+ break;
+ }
+ }
+
+ if(i == pThis->iNumWorkerThreads)
+ ABORT_FINALIZE(RS_RET_NO_MORE_THREADS);
+
+ if(i == 0 || pThis->toWrkShutdown == -1) {
+ wtiSetAlwaysRunning(pThis->pWrkr[i]);
+ }
+
+ pWti = pThis->pWrkr[i];
+ wtiSetState(pWti, WRKTHRD_INITIALIZING);
+ iState = pthread_create(&(pWti->thrdID), &pThis->attrThrd, wtpWorker, (void*) pWti);
+ ATOMIC_INC(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); /* we got one more! */
+
+// TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards
+if(dbgTimeoutToStderr) {
+ fprintf(stderr, "%s: wrkr start initiated with state %d, num workers now %d\n",
+ wtpGetDbgHdr(pThis), iState,
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+}
+ DBGPRINTF("%s: started with state %d, num workers now %d\n",
+ wtpGetDbgHdr(pThis), iState,
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+
+ /* wait for the new thread to initialize its signal mask and
+ * cancellation cleanup handler before proceeding
+ */
+ do {
+ d_pthread_cond_wait(&pThis->condThrdInitDone, &pThis->mutWtp);
+ } while((iState = wtiGetState(pWti)) == WRKTHRD_INITIALIZING);
+ DBGPRINTF("%s: new worker finished initialization with state %d, num workers now %d\n",
+ wtpGetDbgHdr(pThis), iState,
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+// TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards
+if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslog debug: %s: started with state %d, num workers now %d\n",
+ wtpGetDbgHdr(pThis), iState,
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd));
+}
+
+finalize_it:
+ d_pthread_mutex_unlock(&pThis->mutWtp);
+ RETiRet;
+}
+
+
+/* set the number of worker threads that should be running. If less than currently running,
+ * a new worker may be started. Please note that there is no guarantee the number of workers
+ * said will be running after we exit this function. It is just a hint. If the number is
+ * higher than one, and no worker is started, the "busy" condition is signaled to awake a worker.
+ * So the caller can assume that there is at least one worker re-checking if there is "work to do"
+ * after this function call.
+ * Parameter "permit_during_shutdown" if true, permits worker starts while the system is
+ * in shutdown state. The prime use case for this is persisting disk queues in enqueue only
+ * mode, which is activated during shutdown.
+ */
+rsRetVal ATTR_NONNULL()
+wtpAdviseMaxWorkers(wtp_t *const pThis, int nMaxWrkr, const int permit_during_shutdown)
+{
+ DEFiRet;
+ int nMissing; /* number workers missing to run */
+ int i, nRunning;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+
+ if(nMaxWrkr == 0)
+ FINALIZE;
+
+ if(nMaxWrkr > pThis->iNumWorkerThreads) /* limit to configured maximum */
+ nMaxWrkr = pThis->iNumWorkerThreads;
+
+ nMissing = nMaxWrkr - ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd);
+
+ if(nMissing > 0) {
+ if(ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd) > 0) {
+ LogMsg(0, RS_RET_OPERATION_STATUS, LOG_INFO,
+ "%s: high activity - starting %d additional worker thread(s), "
+ "currently %d active worker threads.",
+ wtpGetDbgHdr(pThis), nMissing,
+ ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd,
+ &pThis->mutCurNumWrkThrd) );
+ }
+ /* start the rqtd nbr of workers */
+ for(i = 0 ; i < nMissing ; ++i) {
+ CHKiRet(wtpStartWrkr(pThis, permit_during_shutdown));
+ }
+ } else {
+ /* we have needed number of workers, but they may be sleeping */
+ for(i = 0, nRunning = 0; i < pThis->iNumWorkerThreads && nRunning < nMaxWrkr; ++i) {
+ if (wtiGetState(pThis->pWrkr[i]) != WRKTHRD_STOPPED) {
+ pthread_cond_signal(&pThis->pWrkr[i]->pcondBusy);
+ nRunning++;
+ }
+ }
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* some simple object access methods */
+DEFpropSetMeth(wtp, toWrkShutdown, long)
+DEFpropSetMeth(wtp, wtpState, wtpState_t)
+DEFpropSetMeth(wtp, iNumWorkerThreads, int)
+DEFpropSetMeth(wtp, pUsr, void*)
+DEFpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t)
+DEFpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int))
+DEFpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*))
+DEFpropSetMethFP(wtp, pfGetDeqBatchSize, rsRetVal(*pVal)(void*, int*))
+DEFpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*))
+DEFpropSetMethFP(wtp, pfObjProcessed, rsRetVal(*pVal)(void*, wti_t*))
+
+
+/* set the debug header message
+ * The passed-in string is duplicated. So if the caller does not need
+ * it any longer, it must free it. Must be called only before object is finalized.
+ * rgerhards, 2008-01-09
+ */
+rsRetVal
+wtpSetDbgHdr(wtp_t *pThis, uchar *pszMsg, size_t lenMsg)
+{
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, wtp);
+ assert(pszMsg != NULL);
+
+ if(lenMsg < 1)
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+
+ if(pThis->pszDbgHdr != NULL) {
+ free(pThis->pszDbgHdr);
+ pThis->pszDbgHdr = NULL;
+ }
+
+ if((pThis->pszDbgHdr = malloc(lenMsg + 1)) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ memcpy(pThis->pszDbgHdr, pszMsg, lenMsg + 1); /* always think about the \0! */
+
+finalize_it:
+ RETiRet;
+}
+
+/* dummy */
+static rsRetVal wtpQueryInterface(interface_t __attribute__((unused)) *i) { return RS_RET_NOT_IMPLEMENTED; }
+
+/* exit our class
+ */
+BEGINObjClassExit(wtp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
+CODESTARTObjClassExit(nsdsel_gtls)
+ /* release objects we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ENDObjClassExit(wtp)
+
+
+/* Initialize the stream class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-01-09
+ */
+BEGINObjClassInit(wtp, 1, OBJ_IS_CORE_MODULE)
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ENDObjClassInit(wtp)
diff --git a/runtime/wtp.h b/runtime/wtp.h
new file mode 100644
index 0000000..6fff374
--- /dev/null
+++ b/runtime/wtp.h
@@ -0,0 +1,108 @@
+/* Definition of the worker thread pool (wtp) object.
+ *
+ * Copyright 2008-2018 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WTP_H_INCLUDED
+#define WTP_H_INCLUDED
+
+#include <pthread.h>
+#include "obj.h"
+#include "atomic.h"
+
+/* states for worker threads.
+ * important: they need to be increasing with all previous state bits
+ * set. That is because we can only atomically or a value!
+ */
+#define WRKTHRD_STOPPED 0
+#define WRKTHRD_INITIALIZING 1
+#define WRKTHRD_RUNNING 3
+#define WRKTHRD_WAIT_JOIN 7
+
+
+/* possible states of a worker thread pool */
+typedef enum {
+ wtpState_RUNNING = 0, /* runs in regular mode */
+ wtpState_SHUTDOWN = 1, /* worker threads shall shutdown when idle */
+ wtpState_SHUTDOWN_IMMEDIATE = 2 /* worker threads shall shutdown ASAP, even if not idle */
+} wtpState_t;
+
+
+/* the worker thread pool (wtp) object */
+struct wtp_s {
+ BEGINobjInstance;
+ wtpState_t wtpState;
+ int iNumWorkerThreads;/* number of worker threads to use */
+ int iCurNumWrkThrd;/* current number of active worker threads */
+ struct wti_s **pWrkr;/* array with control structure for the worker thread(s) associated with this wtp */
+ int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */
+ rsRetVal (*pConsumer)(void *); /* user-supplied consumer function for dewtpd messages */
+ /* synchronization variables */
+ pthread_mutex_t mutWtp; /* mutex for the wtp's thread management */
+ pthread_cond_t condThrdInitDone; /* signalled when a new thread is ready for work */
+ pthread_cond_t condThrdTrm;/* signalled when threads terminate */
+ /* end sync variables */
+ /* user objects */
+ void *pUsr; /* pointer to user object (in this case, the queue the wtp belongs to) */
+ pthread_attr_t attrThrd;/* attribute for new threads (created just once and cached here) */
+ pthread_mutex_t *pmutUsr;
+ rsRetVal (*pfChkStopWrkr)(void *pUsr, int);
+ rsRetVal (*pfGetDeqBatchSize)(void *pUsr, int*); /* obtains max dequeue count from queue config */
+ rsRetVal (*pfObjProcessed)(void *pUsr, wti_t *pWti); /* indicate user object is processed */
+ rsRetVal (*pfRateLimiter)(void *pUsr);
+ rsRetVal (*pfDoWork)(void *pUsr, void *pWti);
+ /* end user objects */
+ uchar *pszDbgHdr; /* header string for debug messages */
+ DEF_ATOMIC_HELPER_MUT(mutCurNumWrkThrd)
+ DEF_ATOMIC_HELPER_MUT(mutWtpState)
+};
+
+/* some symbolic constants for easier reference */
+
+
+#define DENY_WORKER_START_DURING_SHUTDOWN 0
+#define PERMIT_WORKER_START_DURING_SHUTDOWN 1
+
+/* prototypes */
+rsRetVal wtpConstruct(wtp_t **ppThis);
+rsRetVal wtpConstructFinalize(wtp_t *pThis);
+rsRetVal wtpDestruct(wtp_t **ppThis);
+rsRetVal wtpAdviseMaxWorkers(wtp_t *pThis, int nMaxWrkr, const int permit_during_shutdown);
+rsRetVal wtpProcessThrdChanges(wtp_t *pThis);
+rsRetVal wtpChkStopWrkr(wtp_t *pThis, int bLockUsrMutex);
+rsRetVal wtpSetState(wtp_t *pThis, wtpState_t iNewState);
+rsRetVal wtpWakeupAllWrkr(wtp_t *pThis);
+rsRetVal wtpCancelAll(wtp_t *pThis, const uchar *const cancelobj);
+rsRetVal wtpSetDbgHdr(wtp_t *pThis, uchar *pszMsg, size_t lenMsg);
+rsRetVal wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *ptTimeout);
+PROTOTYPEObjClassInit(wtp);
+PROTOTYPEObjClassExit(wtp);
+PROTOTYPEpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int));
+PROTOTYPEpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*));
+PROTOTYPEpropSetMethFP(wtp, pfGetDeqBatchSize, rsRetVal(*pVal)(void*, int*));
+PROTOTYPEpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*));
+PROTOTYPEpropSetMethFP(wtp, pfObjProcessed, rsRetVal(*pVal)(void*, wti_t*));
+PROTOTYPEpropSetMeth(wtp, toWrkShutdown, long);
+PROTOTYPEpropSetMeth(wtp, wtpState, wtpState_t);
+PROTOTYPEpropSetMeth(wtp, iMaxWorkerThreads, int);
+PROTOTYPEpropSetMeth(wtp, pUsr, void*);
+PROTOTYPEpropSetMeth(wtp, iNumWorkerThreads, int);
+PROTOTYPEpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t);
+
+#endif /* #ifndef WTP_H_INCLUDED */
diff --git a/runtime/zlibw.c b/runtime/zlibw.c
new file mode 100644
index 0000000..77fd2e7
--- /dev/null
+++ b/runtime/zlibw.c
@@ -0,0 +1,239 @@
+/* The zlibwrap object.
+ *
+ * This is an rsyslog object wrapper around zlib.
+ *
+ * Copyright 2009-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <assert.h>
+#include <zlib.h>
+
+#include "rsyslog.h"
+#include "module-template.h"
+#include "obj.h"
+#include "stream.h"
+#include "zlibw.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+
+
+/* ------------------------------ methods ------------------------------ */
+
+/* zlib make strong use of macros for its interface functions, so we can not simply
+ * pass function pointers to them. Instead, we create very small wrappers which call
+ * the relevant entry points.
+ */
+
+static int myDeflateInit(z_streamp strm, int level)
+{
+ return deflateInit(strm, level);
+}
+
+static int myDeflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)
+{
+ return deflateInit2(strm, level, method, windowBits, memLevel, strategy);
+}
+
+static int myDeflateEnd(z_streamp strm)
+{
+ return deflateEnd(strm);
+}
+
+static int myDeflate(z_streamp strm, int flush)
+{
+ return deflate(strm, flush);
+}
+
+/* finish zlib buffer */
+static rsRetVal
+doCompressFinish(strm_t *pThis,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) )
+{
+ int zRet; /* zlib return state */
+ DEFiRet;
+ unsigned outavail;
+ assert(pThis != NULL);
+
+ assert(pThis->compressionDriver == STRM_COMPRESS_ZIP);
+
+ if(!pThis->bzInitDone)
+ goto done;
+
+ pThis->zstrm.avail_in = 0;
+ /* run deflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld\n", pThis->zstrm.avail_in,
+ pThis->zstrm.total_in);
+ pThis->zstrm.avail_out = pThis->sIOBufSize;
+ pThis->zstrm.next_out = pThis->pZipBuf;
+ zRet = deflate(&pThis->zstrm, Z_FINISH); /* no bad return value */
+ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pThis->zstrm.avail_out);
+ outavail = pThis->sIOBufSize - pThis->zstrm.avail_out;
+ if(outavail != 0) {
+ CHKiRet(strmPhysWrite(pThis, (uchar*)pThis->pZipBuf, outavail));
+ }
+ } while (pThis->zstrm.avail_out == 0);
+
+finalize_it:
+ zRet = deflateEnd(&pThis->zstrm);
+ if(zRet != Z_OK) {
+ LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/deflateEnd()", zRet);
+ }
+
+ pThis->bzInitDone = 0;
+done: RETiRet;
+}
+
+/* write the output buffer in zip mode
+ * This means we compress it first and then do a physical write.
+ * Note that we always do a full deflateInit ... deflate ... deflateEnd
+ * sequence. While this is not optimal, we need to do it because we need
+ * to ensure that the file is readable even when we are aborted. Doing the
+ * full sequence brings us as far towards this goal as possible (and not
+ * doing it would be a total failure). It may be worth considering to
+ * add a config switch so that the user can decide the risk he is ready
+ * to take, but so far this is not yet implemented (not even requested ;)).
+ * rgerhards, 2009-06-04
+ */
+static rsRetVal
+doStrmWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlush,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) )
+{
+ int zRet; /* zlib return state */
+ DEFiRet;
+ unsigned outavail = 0;
+ assert(pThis != NULL);
+ assert(pBuf != NULL);
+
+ assert(pThis->compressionDriver == STRM_COMPRESS_ZIP);
+
+ if(!pThis->bzInitDone) {
+ /* allocate deflate state */
+ pThis->zstrm.zalloc = Z_NULL;
+ pThis->zstrm.zfree = Z_NULL;
+ pThis->zstrm.opaque = Z_NULL;
+ /* see note in file header for the params we use with deflateInit2() */
+ zRet = deflateInit2(&pThis->zstrm, pThis->iZipLevel, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY);
+ if(zRet != Z_OK) {
+ LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/deflateInit2()", zRet);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ pThis->bzInitDone = RSTRUE;
+ }
+
+ /* now doing the compression */
+ pThis->zstrm.next_in = (Bytef*) pBuf;
+ pThis->zstrm.avail_in = lenBuf;
+ /* run deflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld, bFlush %d\n",
+ pThis->zstrm.avail_in, pThis->zstrm.total_in, bFlush);
+ pThis->zstrm.avail_out = pThis->sIOBufSize;
+ pThis->zstrm.next_out = pThis->pZipBuf;
+ zRet = deflate(&pThis->zstrm, bFlush ? Z_SYNC_FLUSH : Z_NO_FLUSH); /* no bad return value */
+ DBGPRINTF("after deflate, ret %d, avail_out %d, to write %d\n",
+ zRet, pThis->zstrm.avail_out, outavail);
+ if(zRet != Z_OK) {
+ LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/Deflate()", zRet);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ outavail = pThis->sIOBufSize - pThis->zstrm.avail_out;
+ if(outavail != 0) {
+ CHKiRet(strmPhysWrite(pThis, (uchar*)pThis->pZipBuf, outavail));
+ }
+ } while (pThis->zstrm.avail_out == 0);
+
+finalize_it:
+ if(pThis->bzInitDone && pThis->bVeryReliableZip) {
+ doCompressFinish(pThis, strmPhysWrite);
+ }
+ RETiRet;
+}
+/* destruction of caller's zlib ressources - a dummy for us */
+static rsRetVal
+zlib_Destruct(ATTR_UNUSED strm_t *pThis)
+{
+ return RS_RET_OK;
+}
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(zlibw)
+CODESTARTobjQueryInterface(zlibw)
+ if(pIf->ifVersion != zlibwCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->DeflateInit = myDeflateInit;
+ pIf->DeflateInit2 = myDeflateInit2;
+ pIf->Deflate = myDeflate;
+ pIf->DeflateEnd = myDeflateEnd;
+ pIf->doStrmWrite = doStrmWrite;
+ pIf->doCompressFinish = doCompressFinish;
+ pIf->Destruct = zlib_Destruct;
+finalize_it:
+ENDobjQueryInterface(zlibw)
+
+
+/* Initialize the zlibw class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(zlibw, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ /* request objects we use */
+
+ /* set our own handlers */
+ENDObjClassInit(zlibw)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+
+ CHKiRet(zlibwClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ /* Initialize all classes that are in our module - this includes ourselfs */
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/runtime/zlibw.h b/runtime/zlibw.h
new file mode 100644
index 0000000..fdbd520
--- /dev/null
+++ b/runtime/zlibw.h
@@ -0,0 +1,51 @@
+/* The zlibw object. It encapsulates the zlib functionality. The primary
+ * purpose of this wrapper class is to enable rsyslogd core to be build without
+ * zlib libraries.
+ *
+ * Copyright 2009-2022 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_ZLIBW_H
+#define INCLUDED_ZLIBW_H
+
+#include <zlib.h>
+
+#include "errmsg.h"
+
+/* interfaces */
+BEGINinterface(zlibw) /* name must also be changed in ENDinterface macro! */
+ int (*DeflateInit)(z_streamp strm, int);
+ int (*DeflateInit2)(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy);
+ int (*Deflate)(z_streamp strm, int);
+ int (*DeflateEnd)(z_streamp strm);
+ rsRetVal (*doStrmWrite)(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) );
+ rsRetVal (*doCompressFinish)(strm_t *pThis,
+ rsRetVal (*Destruct)(strm_t *pThis, uchar *pBuf, size_t lenBuf) );
+ rsRetVal (*Destruct)(strm_t *pThis);
+ENDinterface(zlibw)
+#define zlibwCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(zlibw);
+
+/* the name of our library binary */
+#define LM_ZLIBW_FILENAME "lmzlibw"
+
+#endif /* #ifndef INCLUDED_ZLIBW_H */
diff --git a/runtime/zstdw.c b/runtime/zstdw.c
new file mode 100644
index 0000000..7f80dae
--- /dev/null
+++ b/runtime/zstdw.c
@@ -0,0 +1,191 @@
+/* The zstdw object.
+ *
+ * This is an rsyslog object wrapper around zstd.
+ *
+ * Copyright 2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <assert.h>
+#include <zstd.h>
+
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "stream.h"
+#include "module-template.h"
+#include "obj.h"
+#include "zstdw.h"
+
+MODULE_TYPE_LIB
+MODULE_TYPE_NOKEEP
+
+/* static data */
+DEFobjStaticHelpers
+
+
+/* finish buffer, to be called before closing the zstd file. */
+static rsRetVal
+zstd_doCompressFinish(strm_t *pThis,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) )
+{
+ size_t remaining = 0;
+ DEFiRet;
+ assert(pThis != NULL);
+
+ if(!pThis->bzInitDone)
+ goto done;
+
+ char dummybuf; /* not sure if we can pass in NULL as buffer address in this special case */
+ ZSTD_inBuffer input = { &dummybuf, 0, 0 };
+
+ do {
+ ZSTD_outBuffer output = { pThis->pZipBuf, pThis->sIOBufSize, 0 };
+ remaining = ZSTD_compressStream2(pThis->zstd.cctx, &output , &input, ZSTD_e_end);
+ if(ZSTD_isError(remaining)) {
+ LogError(0, RS_RET_ZLIB_ERR,
+ "error returned from ZSTD_compressStream2(): %s\n",
+ ZSTD_getErrorName(remaining));
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+
+ CHKiRet(strmPhysWrite(pThis, (uchar*)pThis->pZipBuf, output.pos));
+
+ } while (remaining != 0);
+
+finalize_it:
+done: RETiRet;
+}
+
+
+static rsRetVal
+zstd_doStrmWrite(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) )
+{
+ DEFiRet;
+ assert(pThis != NULL);
+ assert(pBuf != NULL);
+ if(!pThis->bzInitDone) {
+ pThis->zstd.cctx = (void*) ZSTD_createCCtx();
+ if(pThis->zstd.cctx == NULL) {
+ LogError(0, RS_RET_ZLIB_ERR, "error creating zstd context (ZSTD_createCCtx failed, "
+ "that's all we know");
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+
+ ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_compressionLevel, pThis->iZipLevel);
+ ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_checksumFlag, 1);
+ if(pThis->zstd.num_wrkrs > 0) {
+ ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_nbWorkers,
+ pThis->zstd.num_wrkrs);
+ }
+ pThis->bzInitDone = RSTRUE;
+ }
+
+ /* now doing the compression */
+ ZSTD_inBuffer input = { pBuf, lenBuf, 0 };
+
+ // This following needs to be configurable? It's possibly sufficient to use e_flush
+ // only, as this can also be controlled by veryRobustZip. However, testbench will than
+ // not be able to check when all file lines are complete.
+ ZSTD_EndDirective const mode = bFlush ? ZSTD_e_flush : ZSTD_e_continue;
+ size_t remaining;
+ do {
+ ZSTD_outBuffer output = { pThis->pZipBuf, 128, 0 };
+ remaining = ZSTD_compressStream2(pThis->zstd.cctx, &output , &input, mode);
+ if(ZSTD_isError(remaining)) {
+ LogError(0, RS_RET_ZLIB_ERR, "error returned from ZSTD_compressStream2(): %s",
+ ZSTD_getErrorName(remaining));
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+
+ CHKiRet(strmPhysWrite(pThis, (uchar*)pThis->pZipBuf, output.pos));
+
+ } while ( mode == ZSTD_e_end ? (remaining != 0) : (input.pos != input.size));
+
+finalize_it:
+ if(pThis->bzInitDone && pThis->bVeryReliableZip) {
+ zstd_doCompressFinish(pThis, strmPhysWrite);
+ }
+ RETiRet;
+}
+
+/* destruction of caller's zstd ressources */
+static rsRetVal
+zstd_Destruct(strm_t *const pThis)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+
+ if(!pThis->bzInitDone)
+ goto done;
+
+ const int result = ZSTD_freeCCtx(pThis->zstd.cctx);
+ if(ZSTD_isError(result)) {
+ LogError(0, RS_RET_ZLIB_ERR, "error from ZSTD_freeCCtx(): %s",
+ ZSTD_getErrorName(result));
+ }
+
+ pThis->bzInitDone = 0;
+done: RETiRet;
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-03-05
+ */
+BEGINobjQueryInterface(zstdw)
+CODESTARTobjQueryInterface(zstdw)
+ if(pIf->ifVersion != zstdwCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+ pIf->doStrmWrite = zstd_doStrmWrite;
+ pIf->doCompressFinish = zstd_doCompressFinish;
+ pIf->Destruct = zstd_Destruct;
+finalize_it:
+ENDobjQueryInterface(zstdw)
+
+
+/* Initialize the zstdw class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(zstdw, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+ENDObjClassInit(zstdw)
+
+
+/* --------------- here now comes the plumbing that makes as a library module --------------- */
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_LIB_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+ CHKiRet(zstdwClassInit(pModInfo));
+ENDmodInit
diff --git a/runtime/zstdw.h b/runtime/zstdw.h
new file mode 100644
index 0000000..0dbc468
--- /dev/null
+++ b/runtime/zstdw.h
@@ -0,0 +1,43 @@
+/* The zstdw object. It encapsulates the zstd functionality. The primary
+ * purpose of this wrapper class is to enable rsyslogd core to be build without
+ * zstd libraries.
+ *
+ * Copyright 2022 Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDED_ZSTDW_H
+#define INCLUDED_ZSTDW_H
+
+/* interfaces */
+BEGINinterface(zstdw) /* name must also be changed in ENDinterface macro! */
+ rsRetVal (*doStrmWrite)(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush,
+ rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf) );
+ rsRetVal (*doCompressFinish)(strm_t *pThis,
+ rsRetVal (*Destruct)(strm_t *pThis, uchar *pBuf, size_t lenBuf) );
+ rsRetVal (*Destruct)(strm_t *pThis);
+ENDinterface(zstdw)
+#define zstdwCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+
+/* prototypes */
+PROTOTYPEObj(zstdw);
+
+/* the name of our library binary */
+#define LM_ZSTDW_FILENAME "lmzstdw"
+
+#endif /* #ifndef INCLUDED_ZSTDW_H */
diff --git a/template.c b/template.c
new file mode 100644
index 0000000..5f5a098
--- /dev/null
+++ b/template.c
@@ -0,0 +1,2449 @@
+/* This is the template processing code of rsyslog.
+ * begun 2004-11-17 rgerhards
+ *
+ * Copyright 2004-2019 Rainer Gerhards and Adiscon
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Note: there is a tiny bit of code left where I could not get any response
+ * from the author if this code can be placed under ASL2.0. I have guarded this
+ * with #ifdef STRICT_GPLV3. Only if that macro is defined, the code will be
+ * compiled. Otherwise this feature is not present. The plan is to do a
+ * different implementation in the future to get rid of this problem.
+ * rgerhards, 2012-08-25
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <json.h>
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "dirty.h"
+#include "obj.h"
+#include "errmsg.h"
+#include "strgen.h"
+#include "rsconf.h"
+#include "msg.h"
+#include "parserif.h"
+#include "unicode-helper.h"
+
+PRAGMA_INGORE_Wswitch_enum
+/* static data */
+DEFobjCurrIf(obj)
+DEFobjCurrIf(strgen)
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfparamdescr[] = {
+ { "name", eCmdHdlrString, 1 },
+ { "type", eCmdHdlrString, 1 },
+ { "string", eCmdHdlrString, 0 },
+ { "plugin", eCmdHdlrString, 0 },
+ { "subtree", eCmdHdlrString, 0 },
+ { "option.stdsql", eCmdHdlrBinary, 0 },
+ { "option.sql", eCmdHdlrBinary, 0 },
+ { "option.json", eCmdHdlrBinary, 0 },
+ { "option.jsonf", eCmdHdlrBinary, 0 },
+ { "option.casesensitive", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescr)/sizeof(struct cnfparamdescr),
+ cnfparamdescr
+ };
+
+static struct cnfparamdescr cnfparamdescrProperty[] = {
+ { "name", eCmdHdlrString, 1 },
+ { "outname", eCmdHdlrString, 0 },
+ { "dateformat", eCmdHdlrString, 0 },
+ { "date.inutc", eCmdHdlrBinary, 0 },
+ { "compressspace", eCmdHdlrBinary, 0 },
+ { "caseconversion", eCmdHdlrString, 0 },
+ { "controlcharacters", eCmdHdlrString, 0 },
+ { "securepath", eCmdHdlrString, 0 },
+ { "format", eCmdHdlrString, 0 },
+ { "position.from", eCmdHdlrInt, 0 },
+ { "position.to", eCmdHdlrInt, 0 },
+ { "position.relativetoend", eCmdHdlrBinary, 0 },
+ { "field.number", eCmdHdlrInt, 0 },
+ { "field.delimiter", eCmdHdlrInt, 0 },
+ { "regex.expression", eCmdHdlrString, 0 },
+ { "regex.type", eCmdHdlrString, 0 },
+ { "regex.nomatchmode", eCmdHdlrString, 0 },
+ { "regex.match", eCmdHdlrInt, 0 },
+ { "regex.submatch", eCmdHdlrInt, 0 },
+ { "droplastlf", eCmdHdlrBinary, 0 },
+ { "fixedwidth", eCmdHdlrBinary, 0 },
+ { "datatype", eCmdHdlrString, 0 },
+ { "onempty", eCmdHdlrString, 0 },
+ { "mandatory", eCmdHdlrBinary, 0 },
+ { "spifno1stsp", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk pblkProperty =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescrProperty)/sizeof(struct cnfparamdescr),
+ cnfparamdescrProperty
+ };
+
+static struct cnfparamdescr cnfparamdescrConstant[] = {
+ { "value", eCmdHdlrString, 1 },
+ { "format", eCmdHdlrString, 0 },
+ { "outname", eCmdHdlrString, 0 }
+};
+static struct cnfparamblk pblkConstant =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescrConstant)/sizeof(struct cnfparamdescr),
+ cnfparamdescrConstant
+ };
+
+
+#ifdef FEATURE_REGEXP
+DEFobjCurrIf(regexp)
+static int bFirstRegexpErrmsg = 1; /**< did we already do a "can't load regexp" error message? */
+#endif
+
+/* helper to tplToString and strgen's, extends buffer */
+#define ALLOC_INC 128
+rsRetVal
+ExtendBuf(actWrkrIParams_t *__restrict__ const iparam, const size_t iMinSize)
+{
+ uchar *pNewBuf;
+ size_t iNewSize;
+ DEFiRet;
+
+ iNewSize = (iMinSize / ALLOC_INC + 1) * ALLOC_INC;
+ CHKmalloc(pNewBuf = (uchar*) realloc(iparam->param, iNewSize));
+ iparam->param = pNewBuf;
+ iparam->lenBuf = iNewSize;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This functions converts a template into a string.
+ *
+ * The function takes a pointer to a template and a pointer to a msg object
+ * as well as a pointer to an output buffer and its size. Note that the output
+ * buffer pointer may be NULL, size 0, in which case a new one is allocated.
+ * The output buffer is grown as required. It is the caller's duty to free the
+ * buffer when it is done. Note that it is advisable to reuse memory, as this
+ * offers big performance improvements.
+ * rewritten 2009-06-19 rgerhards
+ */
+rsRetVal
+tplToString(struct template *__restrict__ const pTpl,
+ smsg_t *__restrict__ const pMsg,
+ actWrkrIParams_t *__restrict__ const iparam,
+ struct syslogTime *const ttNow)
+{
+ DEFiRet;
+ struct templateEntry *__restrict__ pTpe;
+ size_t iBuf;
+ unsigned short bMustBeFreed = 0;
+ uchar *pVal;
+ rs_size_t iLenVal = 0;
+ int need_comma = 0;
+
+ if(pTpl->pStrgen != NULL) {
+ CHKiRet(pTpl->pStrgen(pMsg, iparam));
+ FINALIZE;
+ }
+
+ if(pTpl->bHaveSubtree) {
+ /* only a single CEE subtree must be provided */
+ /* note: we could optimize the code below, however, this is
+ * not worth the effort, as this passing mode is not expected
+ * in subtree mode and so most probably only used for debug & test.
+ */
+ getJSONPropVal(pMsg, &pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed);
+ if(iLenVal >= (rs_size_t)iparam->lenBuf) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(iparam, iLenVal + 1));
+ memcpy(iparam->param, pVal, iLenVal+1);
+ FINALIZE;
+ }
+
+ /* we have a "regular" template with template entries */
+
+ /* loop through the template. We obtain one value
+ * and copy it over to our dynamic string buffer. Then, we
+ * free the obtained value (if requested). We continue this
+ * loop until we got hold of all values.
+ */
+ pTpe = pTpl->pEntryRoot;
+ iBuf = 0;
+ const int extra_space = (pTpl->optFormatEscape == JSONF) ? 1 : 3;
+ if(pTpl->optFormatEscape == JSONF) {
+ if(iparam->lenBuf < 2) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(iparam, 2));
+ iBuf = 1;
+ *iparam->param = '{';
+ }
+ while(pTpe != NULL) {
+ if(pTpe->eEntryType == CONSTANT) {
+ pVal = (uchar*) pTpe->data.constant.pConstant;
+ iLenVal = pTpe->data.constant.iLenConstant;
+ bMustBeFreed = 0;
+ } else if(pTpe->eEntryType == FIELD) {
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &iLenVal, &bMustBeFreed, ttNow);
+ /* we now need to check if we should use SQL option. In this case,
+ * we must go over the generated string and escape '\'' characters.
+ * rgerhards, 2005-09-22: the option values below look somewhat misplaced,
+ * but they are handled in this way because of legacy (don't break any
+ * existing thing).
+ */
+ if(pTpl->optFormatEscape == SQL_ESCAPE)
+ doEscape(&pVal, &iLenVal, &bMustBeFreed, SQL_ESCAPE);
+ else if(pTpl->optFormatEscape == JSON_ESCAPE)
+ doEscape(&pVal, &iLenVal, &bMustBeFreed, JSON_ESCAPE);
+ else if(pTpl->optFormatEscape == STDSQL_ESCAPE)
+ doEscape(&pVal, &iLenVal, &bMustBeFreed, STDSQL_ESCAPE);
+ } else {
+ DBGPRINTF("TplToString: invalid entry type %d\n", pTpe->eEntryType);
+ pVal = (uchar*) "*LOGIC ERROR*";
+ iLenVal = sizeof("*LOGIC ERROR*") - 1;
+ bMustBeFreed = 0;
+ }
+ /* got source, now copy over */
+ if(iLenVal > 0) { /* may be zero depending on property */
+ /* first, make sure buffer fits */
+ if(iBuf + iLenVal + extra_space >= iparam->lenBuf) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(iparam, iBuf + iLenVal + 1));
+
+ if(need_comma) {
+ memcpy(iparam->param + iBuf, ", ", 2);
+ iBuf += 2;
+ }
+ memcpy(iparam->param + iBuf, pVal, iLenVal);
+ iBuf += iLenVal;
+ if(pTpl->optFormatEscape == JSONF) {
+ need_comma = 1;
+ }
+ }
+
+ if((pTpl->optFormatEscape == JSONF) && (pTpe->pNext == NULL)) {
+ /* space was reserved while processing field above
+ (via extra_space in ExtendBuf() new size formula. */
+ memcpy(iparam->param + iBuf, "}\n", 2);
+ iBuf += 2;
+ }
+
+ if(bMustBeFreed) {
+ free(pVal);
+ bMustBeFreed = 0;
+ }
+
+ pTpe = pTpe->pNext;
+ }
+
+ if(iBuf == iparam->lenBuf) {
+ /* in the weired case of an *empty* template, this can happen.
+ * it is debatable if we should really fix it here or simply
+ * forbid that case. However, performance toll is minimal, so
+ * I tend to permit it. -- 2010-11-05 rgerhards
+ */
+ CHKiRet(ExtendBuf(iparam, iBuf + 1));
+ }
+ iparam->param[iBuf] = '\0';
+ iparam->lenStr = iBuf;
+
+finalize_it:
+ if(bMustBeFreed) {
+ free(pVal);
+ bMustBeFreed = 0;
+ }
+
+ RETiRet;
+}
+
+
+/* This functions converts a template into a json object.
+ * For further general details, see the very similar funtion
+ * tpltoString().
+ * rgerhards, 2012-08-29
+ */
+rsRetVal
+tplToJSON(struct template *pTpl, smsg_t *pMsg, struct json_object **pjson, struct syslogTime *ttNow)
+{
+ struct templateEntry *pTpe;
+ rs_size_t propLen;
+ unsigned short bMustBeFreed;
+ uchar *pVal;
+ struct json_object *json, *jsonf;
+ rsRetVal localRet;
+ DEFiRet;
+
+ if(pTpl->bHaveSubtree){
+ if(jsonFind(pMsg, &pTpl->subtree, pjson) != RS_RET_OK)
+ *pjson = NULL;
+ if(*pjson == NULL) {
+ /* we need to have a root object! */
+ *pjson = json_object_new_object();
+ } else {
+ json_object_get(*pjson); /* inc refcount */
+ }
+ FINALIZE;
+ }
+
+ json = json_object_new_object();
+ for(pTpe = pTpl->pEntryRoot ; pTpe != NULL ; pTpe = pTpe->pNext) {
+ if(pTpe->eEntryType == CONSTANT) {
+ if(pTpe->fieldName == NULL)
+ continue;
+ jsonf = json_object_new_string((char*) pTpe->data.constant.pConstant);
+ json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
+ } else if(pTpe->eEntryType == FIELD) {
+ if(pTpe->data.field.msgProp.id == PROP_CEE ||
+ pTpe->data.field.msgProp.id == PROP_LOCAL_VAR ||
+ pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR ) {
+ localRet = msgGetJSONPropJSON(pMsg, &pTpe->data.field.msgProp, &jsonf);
+ if(localRet == RS_RET_OK) {
+ json_object_object_add(json, (char*)pTpe->fieldName, json_object_get(jsonf));
+ } else {
+ DBGPRINTF("tplToJSON: error %d looking up property %s\n",
+ localRet, pTpe->fieldName);
+ if(pTpe->data.field.options.bMandatory) {
+ json_object_object_add(json, (char*)pTpe->fieldName, NULL);
+ }
+ }
+ } else {
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &propLen, &bMustBeFreed, ttNow);
+ if(pTpe->data.field.options.bMandatory || propLen > 0) {
+ jsonf = json_object_new_string_len((char*)pVal, propLen+1);
+ json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
+ }
+ if(bMustBeFreed) { /* json-c makes its own private copy! */
+ free(pVal);
+ }
+ }
+ }
+ }
+ assert(iRet == RS_RET_OK);
+ *pjson = json;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Helper to doEscape. This is called if doEscape
+ * runs out of memory allocating the escaped string.
+ * Then we are in trouble. We can
+ * NOT simply return the unmodified string because this
+ * may cause SQL injection. But we also can not simply
+ * abort the run, this would be a DoS. I think an appropriate
+ * measure is to remove the dangerous \' characters (SQL). We
+ * replace them by \", which will break the message and
+ * signatures eventually present - but this is the
+ * best thing we can do now (or does anybody
+ * have a better idea?). rgerhards 2004-11-23
+ * added support for escape mode (see doEscape for details).
+ * if mode = SQL_ESCAPE, then backslashes are changed to slashes.
+ * rgerhards 2005-09-22
+ */
+static void doEmergencyEscape(register uchar *p, int mode)
+{
+ while(*p) {
+ if((mode == SQL_ESCAPE||mode == STDSQL_ESCAPE) && *p == '\'') {
+ *p = '"';
+ } else if(mode == JSON_ESCAPE) {
+ if(*p == '"') {
+ *p = '\'';
+ } else if(*p == '\\' ) {
+ *p = '/';
+ }
+ } else if((mode == SQL_ESCAPE) && *p == '\\') {
+ *p = '/';
+ }
+ ++p;
+ }
+}
+
+
+/* SQL-Escape a string. Single quotes are found and
+ * replaced by two of them. A new buffer is allocated
+ * for the provided string and the provided buffer is
+ * freed. The length is updated. Parameter pbMustBeFreed
+ * is set to 1 if a new buffer is allocated. Otherwise,
+ * it is left untouched.
+ * --
+ * We just discovered a security issue. MySQL is so
+ * "smart" to not only support the standard SQL mechanism
+ * for escaping quotes, but to also provide its own (using
+ * c-type syntax with backslashes). As such, it is actually
+ * possible to do sql injection via rsyslogd. The cure is now
+ * to escape backslashes, too. As we have found on the web, some
+ * other databases seem to be similar "smart" (why do we have standards
+ * at all if they are violated without any need???). Even better, MySQL's
+ * smartness depends on config settings. So we add a new option to this
+ * function that allows the caller to select if they want to standard or
+ * "smart" encoding ;)
+ * --
+ * Parameter "mode" is STDSQL_ESCAPE, SQL_ESCAPE "smart" SQL engines, or
+ * JSON_ESCAPE for everyone requiring escaped JSON (e.g. ElasticSearch).
+ * 2005-09-22 rgerhards
+ */
+rsRetVal
+doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int mode)
+{
+ DEFiRet;
+ uchar *p = NULL;
+ int iLen;
+ cstr_t *pStrB = NULL;
+ uchar *pszGenerated;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pLen != NULL);
+ assert(pbMustBeFreed != NULL);
+
+ /* first check if we need to do anything at all... */
+ if(mode == STDSQL_ESCAPE)
+ for(p = *pp ; *p && *p != '\'' ; ++p)
+ ;
+ else if(mode == SQL_ESCAPE)
+ for(p = *pp ; *p && *p != '\'' && *p != '\\' ; ++p)
+ ;
+ else if(mode == JSON_ESCAPE)
+ for(p = *pp ; *p && (*p == '"' || *p == '\\' ) ; ++p)
+ ;
+ /* when we get out of the loop, we are either at the
+ * string terminator or the first character to escape */
+ if(p && *p == '\0')
+ FINALIZE; /* nothing to do in this case! */
+
+ p = *pp;
+ iLen = *pLen;
+ CHKiRet(cstrConstruct(&pStrB));
+
+ while(*p) {
+ if((mode == SQL_ESCAPE || mode == STDSQL_ESCAPE) && *p == '\'') {
+ CHKiRet(cstrAppendChar(pStrB, (mode == STDSQL_ESCAPE) ? '\'' : '\\'));
+ iLen++; /* reflect the extra character */
+ } else if((mode == SQL_ESCAPE) && *p == '\\') {
+ CHKiRet(cstrAppendChar(pStrB, '\\'));
+ iLen++; /* reflect the extra character */
+ } else if((mode == JSON_ESCAPE) && (*p == '"' || *p == '\\' )) {
+ CHKiRet(cstrAppendChar(pStrB, '\\'));
+ iLen++; /* reflect the extra character */
+ }
+ CHKiRet(cstrAppendChar(pStrB, *p));
+ ++p;
+ }
+ cstrFinalize(pStrB);
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pszGenerated, 0));
+
+ if(*pbMustBeFreed)
+ free(*pp); /* discard previous value */
+
+ *pp = pszGenerated;
+ *pLen = iLen;
+ *pbMustBeFreed = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ doEmergencyEscape(*pp, mode);
+ if(pStrB != NULL)
+ cstrDestruct(&pStrB);
+ }
+
+ RETiRet;
+}
+
+
+/* Constructs a template entry object. Returns pointer to it
+ * or NULL (if it fails). Pointer to associated template list entry
+ * must be provided.
+ */
+static struct templateEntry* tpeConstruct(struct template *pTpl)
+{
+ struct templateEntry *pTpe;
+
+ assert(pTpl != NULL);
+
+ if((pTpe = calloc(1, sizeof(struct templateEntry))) == NULL)
+ return NULL;
+
+ /* basic initialization is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(pTpl->pEntryLast == NULL){
+ /* we are the first element! */
+ pTpl->pEntryRoot = pTpl->pEntryLast = pTpe;
+ } else {
+ pTpl->pEntryLast->pNext = pTpe;
+ pTpl->pEntryLast = pTpe;
+ }
+ pTpl->tpenElements++;
+
+ return(pTpe);
+}
+
+
+/* Helper function to apply case-sensitivity to templates.
+ */
+static void
+apply_case_sensitivity(struct template *pTpl)
+{
+ if(pTpl->optCaseSensitive) return;
+
+ struct templateEntry *pTpe;
+
+ for(pTpe = pTpl->pEntryRoot ; pTpe != NULL ; pTpe = pTpe->pNext) {
+ if(pTpe->eEntryType == FIELD) {
+ if(pTpe->data.field.msgProp.id == PROP_CEE ||
+ pTpe->data.field.msgProp.id == PROP_LOCAL_VAR ||
+ pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR ) {
+ uchar* p;
+ p = pTpe->fieldName;
+ for ( ; *p; ++p) *p = tolower(*p);
+ p = pTpe->data.field.msgProp.name;
+ for ( ; *p; ++p) *p = tolower(*p);
+ }
+ }
+ }
+}
+
+
+/* Constructs a template list object. Returns pointer to it
+ * or NULL (if it fails).
+ */
+static struct template*
+tplConstruct(rsconf_t *conf)
+{
+ struct template *pTpl;
+ if((pTpl = calloc(1, sizeof(struct template))) == NULL)
+ return NULL;
+
+ /* basic initialisation is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(conf->templates.last == NULL) {
+ /* we are the first element! */
+ conf->templates.root = conf->templates.last = pTpl;
+ } else {
+ conf->templates.last->pNext = pTpl;
+ conf->templates.last = pTpl;
+ }
+
+ return(pTpl);
+}
+
+
+/* helper to tplAddLine. Parses a constant and generates
+ * the necessary structure.
+ * Parameter "bDoEscapes" is to support legacy vs. v6+ config system. In
+ * legacy, we must do escapes ourselves, whereas v6+ passes in already
+ * escaped strings (which we are NOT permitted to further escape, this would
+ * cause invalid result strings!). Note: if escapes are not permitted,
+ * quotes (") are just a regular character and do NOT terminate the constant!
+ */
+static rsRetVal
+do_Constant(unsigned char **pp, struct template *pTpl, int bDoEscapes)
+{
+ register unsigned char *p;
+ cstr_t *pStrB;
+ struct templateEntry *pTpe;
+ int i;
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpl != NULL);
+
+ p = *pp;
+
+ CHKiRet(cstrConstruct(&pStrB));
+ /* process the message and expand escapes
+ * (additional escapes can be added here if needed)
+ */
+ while(*p && *p != '%' && !(bDoEscapes && *p == '\"')) {
+ if(bDoEscapes && *p == '\\') {
+ switch(*++p) {
+ case '\0':
+ /* the best we can do - it's invalid anyhow... */
+ cstrAppendChar(pStrB, *p);
+ break;
+ case 'n':
+ cstrAppendChar(pStrB, '\n');
+ ++p;
+ break;
+ case 'r':
+ cstrAppendChar(pStrB, '\r');
+ ++p;
+ break;
+ case '\\':
+ cstrAppendChar(pStrB, '\\');
+ ++p;
+ break;
+ case '%':
+ cstrAppendChar(pStrB, '%');
+ ++p;
+ break;
+ case '0': /* numerical escape sequence */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i = 0;
+ while(*p && isdigit((int)*p)) {
+ i = i * 10 + *p++ - '0';
+ }
+ cstrAppendChar(pStrB, i);
+ break;
+ default:
+ cstrAppendChar(pStrB, *p++);
+ break;
+ }
+ }
+ else
+ cstrAppendChar(pStrB, *p++);
+ }
+
+ if((pTpe = tpeConstruct(pTpl)) == NULL) {
+ rsCStrDestruct(&pStrB);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pTpe->eEntryType = CONSTANT;
+ cstrFinalize(pStrB);
+ /* We obtain the length from the counted string object
+ * (before we delete it). Later we might take additional
+ * benefit from the counted string object.
+ * 2005-09-09 rgerhards
+ */
+ pTpe->data.constant.iLenConstant = rsCStrLen(pStrB);
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pTpe->data.constant.pConstant, 0));
+
+ *pp = p;
+
+finalize_it:
+ RETiRet;
+}
+
+/* Helper that checks to see if a property already has a format
+ * type defined
+ */
+static int hasFormat(struct templateEntry *pTpe) {
+ return (
+ pTpe->data.field.options.bCSV ||
+ pTpe->data.field.options.bJSON ||
+ pTpe->data.field.options.bJSONf ||
+ pTpe->data.field.options.bJSONr
+ );
+}
+
+/* Helper to do_Parameter(). This parses the formatting options
+ * specified in a template variable. It returns the passed-in pointer
+ * updated to the next processed character.
+ */
+static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
+{
+ register unsigned char *p;
+ unsigned char Buf[64];
+ size_t i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpe != NULL);
+
+ p = *pp;
+
+ while(*p && *p != '%' && *p != ':') {
+ /* outer loop - until end of options */
+ memset(Buf, 0, sizeof(Buf)); /* silence valgrind warnings */
+ i = 0;
+ while((i < sizeof(Buf)-1) &&
+ *p && *p != '%' && *p != ':' && *p != ',') {
+ /* inner loop - until end of ONE option */
+ Buf[i++] = tolower((int)*p);
+ ++p;
+ }
+ Buf[i] = '\0'; /* terminate */
+ /* check if we need to skip oversize option */
+ while(*p && *p != '%' && *p != ':' && *p != ',')
+ ++p; /* just skip */
+ if(*p == ',')
+ ++p; /* eat ',' */
+ /* OK, we got the option, so now lets look what
+ * it tells us...
+ */
+ if(!strcmp((char*)Buf, "date-mysql")) {
+ pTpe->data.field.eDateFormat = tplFmtMySQLDate;
+ } else if(!strcmp((char*)Buf, "date-pgsql")) {
+ pTpe->data.field.eDateFormat = tplFmtPgSQLDate;
+ } else if(!strcmp((char*)Buf, "date-rfc3164")) {
+ pTpe->data.field.eDateFormat = tplFmtRFC3164Date;
+ } else if(!strcmp((char*)Buf, "date-rfc3164-buggyday")) {
+ pTpe->data.field.eDateFormat = tplFmtRFC3164BuggyDate;
+ } else if(!strcmp((char*)Buf, "date-rfc3339")) {
+ pTpe->data.field.eDateFormat = tplFmtRFC3339Date;
+ } else if(!strcmp((char*)Buf, "date-unixtimestamp")) {
+ pTpe->data.field.eDateFormat = tplFmtUnixDate;
+ } else if(!strcmp((char*)Buf, "date-subseconds")) {
+ pTpe->data.field.eDateFormat = tplFmtSecFrac;
+ } else if(!strcmp((char*)Buf, "date-wdayname")) {
+ pTpe->data.field.eDateFormat = tplFmtWDayName;
+ } else if(!strcmp((char*)Buf, "date-wday")) {
+ pTpe->data.field.eDateFormat = tplFmtWDay;
+ } else if(!strcmp((char*)Buf, "date-year")) {
+ pTpe->data.field.eDateFormat = tplFmtYear;
+ } else if(!strcmp((char*)Buf, "date-month")) {
+ pTpe->data.field.eDateFormat = tplFmtMonth;
+ } else if(!strcmp((char*)Buf, "date-day")) {
+ pTpe->data.field.eDateFormat = tplFmtDay;
+ } else if(!strcmp((char*)Buf, "date-hour")) {
+ pTpe->data.field.eDateFormat = tplFmtHour;
+ } else if(!strcmp((char*)Buf, "date-minute")) {
+ pTpe->data.field.eDateFormat = tplFmtMinute;
+ } else if(!strcmp((char*)Buf, "date-second")) {
+ pTpe->data.field.eDateFormat = tplFmtSecond;
+ } else if(!strcmp((char*)Buf, "date-tzoffshour")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsHour;
+ } else if(!strcmp((char*)Buf, "date-tzoffsmin")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsMin;
+ } else if(!strcmp((char*)Buf, "date-tzoffsdirection")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsDirection;
+ } else if (!strcmp((char*)Buf, "date-ordinal")) {
+ pTpe->data.field.eDateFormat = tplFmtOrdinal;
+ } else if (!strcmp((char*)Buf, "date-week")) {
+ pTpe->data.field.eDateFormat = tplFmtWeek;
+ } else if (!strcmp((char*)Buf, "date-iso-week")) {
+ pTpe->data.field.eDateFormat = tplFmtISOWeek;
+ } else if (!strcmp((char*)Buf, "date-iso-week-year")) {
+ pTpe->data.field.eDateFormat = tplFmtISOWeekYear;
+ } else if(!strcmp((char*)Buf, "date-utc")) {
+ pTpe->data.field.options.bDateInUTC = 1;
+ } else if(!strcmp((char*)Buf, "lowercase")) {
+ pTpe->data.field.eCaseConv = tplCaseConvLower;
+ } else if(!strcmp((char*)Buf, "uppercase")) {
+ pTpe->data.field.eCaseConv = tplCaseConvUpper;
+ } else if(!strcmp((char*)Buf, "sp-if-no-1st-sp")) {
+ pTpe->data.field.options.bSPIffNo1stSP = 1;
+ } else if(!strcmp((char*)Buf, "compressspace")) {
+ pTpe->data.field.options.bCompressSP = 1;
+ } else if(!strcmp((char*)Buf, "escape-cc")) {
+ pTpe->data.field.options.bEscapeCC = 1;
+ } else if(!strcmp((char*)Buf, "drop-cc")) {
+ pTpe->data.field.options.bDropCC = 1;
+ } else if(!strcmp((char*)Buf, "space-cc")) {
+ pTpe->data.field.options.bSpaceCC = 1;
+ } else if(!strcmp((char*)Buf, "drop-last-lf")) {
+ pTpe->data.field.options.bDropLastLF = 1;
+ } else if(!strcmp((char*)Buf, "secpath-drop")) {
+ pTpe->data.field.options.bSecPathDrop = 1;
+ } else if(!strcmp((char*)Buf, "secpath-replace")) {
+ pTpe->data.field.options.bSecPathReplace = 1;
+ } else if(!strcmp((char*)Buf, "pos-end-relative")) {
+ pTpe->data.field.options.bFromPosEndRelative = 1;
+ } else if(!strcmp((char*)Buf, "fixed-width")) {
+ pTpe->data.field.options.bFixedWidth = 1;
+ } else if(!strcmp((char*)Buf, "csv")) {
+ if(hasFormat(pTpe)) {
+ LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - csv ignored");
+ } else {
+ pTpe->data.field.options.bCSV = 1;
+ }
+ } else if(!strcmp((char*)Buf, "json")) {
+ if(hasFormat(pTpe)) {
+ LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - json ignored");
+ } else {
+ pTpe->data.field.options.bJSON = 1;
+ }
+ } else if(!strcmp((char*)Buf, "jsonf")) {
+ if(hasFormat(pTpe)) {
+ LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonf ignored");
+ } else {
+ pTpe->data.field.options.bJSONf = 1;
+ }
+ } else if(!strcmp((char*)Buf, "jsonr")) {
+ if(hasFormat(pTpe)) {
+ LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonr ignored");
+ } else {
+ pTpe->data.field.options.bJSONr = 1;
+ }
+ } else if(!strcmp((char*)Buf, "jsonfr")) {
+ if(hasFormat(pTpe)) {
+ LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonfr ignored");
+ } else {
+ pTpe->data.field.options.bJSONfr = 1;
+ }
+ } else if(!strcmp((char*)Buf, "mandatory-field")) {
+ pTpe->data.field.options.bMandatory = 1;
+ } else {
+ LogError(0, NO_ERRCODE, "template error: invalid field option '%s' "
+ "specified - ignored", Buf);
+ }
+ }
+
+ *pp = p;
+}
+
+/* helper to tplAddLine. Parses a parameter and generates
+ * the necessary structure.
+ */
+static rsRetVal
+do_Parameter(uchar **pp, struct template *pTpl)
+{
+ uchar *p;
+ cstr_t *pStrProp = NULL;
+ cstr_t *pStrField = NULL;
+ struct templateEntry *pTpe;
+ int iNum; /* to compute numbers */
+#ifdef FEATURE_REGEXP
+ /* APR: variables for regex */
+ rsRetVal iRetLocal;
+ int longitud;
+ unsigned char *regex_char;
+ unsigned char *regex_end;
+#endif
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpl != NULL);
+
+ p = (uchar*) *pp;
+ CHKiRet(cstrConstruct(&pStrProp));
+ CHKmalloc(pTpe = tpeConstruct(pTpl));
+ pTpe->eEntryType = FIELD;
+
+ while(*p && *p != '%' && *p != ':') {
+ cstrAppendChar(pStrProp, *p);
+ ++p;
+ }
+
+ /* got the name */
+ cstrFinalize(pStrProp);
+
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(pStrProp),
+ cstrLen(pStrProp)));
+
+ /* Check frompos, if it has an R, then topos should be a regex */
+ if(*p == ':') {
+ pTpe->bComplexProcessing = 1;
+ ++p; /* eat ':' */
+#ifdef FEATURE_REGEXP
+ if(*p == 'R') {
+ /* APR: R found! regex alarm ! :) */
+ ++p; /* eat ':' */
+
+ /* first come the regex type */
+ if(*p == ',') {
+ ++p; /* eat ',' */
+ if(p[0] == 'B' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) {
+ pTpe->data.field.typeRegex = TPL_REGEX_BRE;
+ p += 3; /* eat indicator sequence */
+ } else if(p[0] == 'E' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) {
+ pTpe->data.field.typeRegex = TPL_REGEX_ERE;
+ p += 3; /* eat indicator sequence */
+ } else {
+ LogError(0, NO_ERRCODE, "error: invalid regular expression "
+ "type, rest of line %s", (char*) p);
+ }
+ }
+
+ /* now check for submatch ID */
+ pTpe->data.field.iSubMatchToUse = 0;
+ if(*p == ',') {
+ /* in this case a number follows, which indicates which match
+ * shall be used. This must be a single digit.
+ */
+ ++p; /* eat ',' */
+ if(isdigit((int) *p)) {
+ pTpe->data.field.iSubMatchToUse = *p - '0';
+ ++p; /* eat digit */
+ }
+ }
+
+ /* now pull what to do if we do not find a match */
+ if(*p == ',') {
+ ++p; /* eat ',' */
+ if(p[0] == 'D' && p[1] == 'F' && p[2] == 'L' && p[3] == 'T'
+ && (p[4] == ',' || p[4] == ':')) {
+ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_DFLTSTR;
+ p += 4; /* eat indicator sequence */
+ } else if(p[0] == 'B' && p[1] == 'L' && p[2] == 'A' && p[3] == 'N' && p[4] == 'K'
+ && (p[5] == ',' || p[5] == ':')) {
+ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_BLANK;
+ p += 5; /* eat indicator sequence */
+ } else if(p[0] == 'F' && p[1] == 'I' && p[2] == 'E' && p[3] == 'L' && p[4] == 'D'
+ && (p[5] == ',' || p[5] == ':')) {
+ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_WHOLE_FIELD;
+ p += 5; /* eat indicator sequence */
+ } else if(p[0] == 'Z' && p[1] == 'E' && p[2] == 'R' && p[3] == 'O'
+ && (p[4] == ',' || p[4] == ':')) {
+ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_ZERO;
+ p += 4; /* eat indicator sequence */
+ } else if(p[0] == ',') { /* empty, use default */
+ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_DFLTSTR;
+ /* do NOT eat indicator sequence, as this was already eaten - the
+ * comma itself is already part of the next field.
+ */
+ } else {
+ LogError(0, NO_ERRCODE, "template %s error: invalid regular "
+ "expression type, rest of line %s",
+ pTpl->pszName, (char*) p);
+ }
+ }
+
+ /* now check for match ID */
+ pTpe->data.field.iMatchToUse = 0;
+ if(*p == ',') {
+ /* in this case a number follows, which indicates which match
+ * shall be used. This must be a single digit.
+ */
+ ++p; /* eat ',' */
+ if(isdigit((int) *p)) {
+ pTpe->data.field.iMatchToUse = *p - '0';
+ ++p; /* eat digit */
+ }
+ }
+
+ if(*p != ':') {
+ /* There is something more than an R , this is invalid ! */
+ /* Complain on extra characters */
+ LogError(0, NO_ERRCODE, "error: invalid character in frompos "
+ "after \"R\", property: '%%%s'", (char*) *pp);
+ } else {
+ pTpe->data.field.has_regex = 1;
+ dbgprintf("we have a regexp and use match #%d, submatch #%d\n",
+ pTpe->data.field.iMatchToUse, pTpe->data.field.iSubMatchToUse);
+ }
+ } else {
+ /* now we fall through the "regular" FromPos code */
+#endif /* #ifdef FEATURE_REGEXP */
+ if(*p == 'F') {
+#ifdef STRICT_GPLV3
+ pTpe->data.field.field_expand = 0;
+#endif
+ /* we have a field counter, so indicate it in the template */
+ ++p; /* eat 'F' */
+ if (*p == ':') {
+ /* no delimiter specified, so use the default (HT) */
+ pTpe->data.field.has_fields = 1;
+ pTpe->data.field.field_delim = 9;
+ } else if (*p == ',') {
+ ++p; /* eat ',' */
+ /* configured delimiter follows, so we need to obtain
+ * it. Important: the following number must be the
+ * **DECIMAL** ASCII value of the delimiter character.
+ */
+ pTpe->data.field.has_fields = 1;
+ if(!isdigit((int)*p)) {
+ /* complain and use default */
+ LogError(0, NO_ERRCODE, "error: invalid character in "
+"frompos after \"F,\", property: '%%%s' - using 9 (HT) as field delimiter",
+ (char*) *pp);
+ pTpe->data.field.field_delim = 9;
+ } else {
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ if(iNum < 0 || iNum > 255) {
+ LogError(0, NO_ERRCODE, "error: non-USASCII delimiter "
+"character value %d in template - using 9 (HT) as substitute", iNum);
+ pTpe->data.field.field_delim = 9;
+ } else {
+ pTpe->data.field.field_delim = iNum;
+# ifdef STRICT_GPLV3
+ if (*p == '+') {
+ pTpe->data.field.field_expand = 1;
+ p ++;
+ }
+# endif
+ if(*p == ',') { /* real fromPos? */
+ ++p;
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iFromPos = iNum;
+ } else if(*p != ':') {
+ parser_errmsg("error: invalid character "
+ "'%c' in frompos after \"F,\", property: '%s' "
+ "be sure to use DECIMAL character "
+ "codes!", *p, (char*) *pp);
+ ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
+ }
+ }
+ }
+ } else {
+ /* invalid character after F, so we need to reject
+ * this.
+ */
+ LogError(0, NO_ERRCODE, "error: invalid character in frompos "
+ "after \"F\", property: '%%%s'", (char*) *pp);
+ }
+ } else {
+ /* we now have a simple offset in frompos (the previously "normal" case) */
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iFromPos = iNum;
+ /* skip to next known good */
+ while(*p && *p != '%' && *p != ':') {
+ /* TODO: complain on extra characters */
+ dbgprintf("error: extra character in frompos: '%s'\n", p);
+ ++p;
+ }
+ }
+#ifdef FEATURE_REGEXP
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+ /* check topos (holds an regex if FromPos is "R"*/
+ if(*p == ':') {
+ ++p; /* eat ':' */
+
+#ifdef FEATURE_REGEXP
+ if (pTpe->data.field.has_regex) {
+ dbgprintf("debug: has regex \n");
+ /* APR 2005-09 I need the string that represent the regex */
+ /* The regex end is: "--end" */
+ /* TODO : this is hardcoded and cant be escaped, please change */
+ regex_end = (unsigned char*) strstr((char*)p, "--end");
+ if (regex_end == NULL) {
+ dbgprintf("error: can not find regex end in: '%s'\n", p);
+ pTpe->data.field.has_regex = 0;
+ } else {
+ /* We get here ONLY if the regex end was found */
+ longitud = regex_end - p;
+ /* Malloc for the regex string */
+ regex_char = (unsigned char *) malloc(longitud + 1);
+ if(regex_char == NULL) {
+ dbgprintf("Could not allocate memory for template parameter!\n");
+ pTpe->data.field.has_regex = 0;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* Get the regex string for compiling later */
+ memcpy(regex_char, p, longitud);
+ regex_char[longitud] = '\0';
+ dbgprintf("debug: regex detected: '%s'\n", regex_char);
+ /* Now i compile the regex */
+ /* Remember that the re is an attribute of the Template entry */
+ if((iRetLocal = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) {
+ int iOptions;
+ iOptions = (pTpe->data.field.typeRegex == TPL_REGEX_ERE) ? REG_EXTENDED : 0;
+ int errcode;
+ if((errcode = regexp.regcomp(&(pTpe->data.field.re),
+ (char*) regex_char, iOptions) != 0)) {
+ char errbuff[512];
+ regexp.regerror(errcode, &(pTpe->data.field.re),
+ errbuff, sizeof(errbuff));
+ DBGPRINTF("Template.c: Error in regular expression: %s\n", errbuff);
+ pTpe->data.field.has_regex = 2;
+ }
+ } else {
+ /* regexp object could not be loaded */
+ dbgprintf("error %d trying to load regexp library - this may be desired "
+ "and thus OK", iRetLocal);
+ if(bFirstRegexpErrmsg) {
+ /* prevent flood of messages, maybe even an endless loop! */
+ bFirstRegexpErrmsg = 0;
+ LogError(0, NO_ERRCODE, "regexp library could not be loaded "
+ "(error %d), regexp ignored", iRetLocal);
+ }
+ pTpe->data.field.has_regex = 2;
+ }
+
+ /* Finally we move the pointer to the end of the regex
+ * so it aint parsed twice or something weird */
+ p = regex_end + 5/*strlen("--end")*/;
+ free(regex_char);
+ }
+ } else if(*p == '$') {
+ /* shortcut for "end of message */
+ p++; /* eat '$' */
+ /* in this case, we do a quick, somewhat dirty but totally
+ * legitimate trick: we simply use a topos that is higher than
+ * potentially ever can happen. The code below checks that no copy
+ * will occur after the end of string, so this is perfectly legal.
+ * rgerhards, 2006-10-17
+ */
+ pTpe->data.field.iToPos = 9999999;
+ } else {
+ /* fallthrough to "regular" ToPos code */
+#endif /* #ifdef FEATURE_REGEXP */
+
+ if(pTpe->data.field.has_fields == 1) {
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iFieldNr = iNum;
+ if(*p == ',') { /* get real toPos? */
+ ++p;
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iToPos = iNum;
+ }
+ } else {
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iToPos = iNum;
+ }
+ /* skip to next known good */
+ while(*p && *p != '%' && *p != ':') {
+ /* TODO: complain on extra characters */
+ dbgprintf("error: extra character in frompos: '%s'\n", p);
+ ++p;
+ }
+#ifdef FEATURE_REGEXP
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+
+ /* check options */
+ if(*p == ':') {
+ ++p; /* eat ':' */
+ doOptions(&p, pTpe);
+ }
+
+ if(pTpe->data.field.options.bFromPosEndRelative) {
+ if(pTpe->data.field.iToPos > pTpe->data.field.iFromPos) {
+ iNum = pTpe->data.field.iToPos;
+ pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
+ pTpe->data.field.iFromPos = iNum;
+ }
+ } else {
+ if(pTpe->data.field.iToPos < pTpe->data.field.iFromPos) {
+ iNum = pTpe->data.field.iToPos;
+ pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
+ pTpe->data.field.iFromPos = iNum;
+ }
+ }
+
+
+ /* check field name */
+ if(*p == ':') {
+ ++p; /* eat ':' */
+ CHKiRet(cstrConstruct(&pStrField));
+ while(*p != ':' && *p != '%' && *p != '\0') {
+ cstrAppendChar(pStrField, *p);
+ ++p;
+ }
+ cstrFinalize(pStrField);
+ }
+
+ /* save field name - if none was given, use the property name instead */
+ if(pStrField == NULL) {
+ if(pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
+ /* in CEE case, we remove "$!"/"$." from the fieldname - it's just our indicator */
+ pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp)+2);
+ pTpe->lenFieldName = cstrLen(pStrProp)-2;
+ } else {
+ pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp));
+ pTpe->lenFieldName = cstrLen(pStrProp);
+ }
+ } else {
+ pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrField));
+ pTpe->lenFieldName = ustrlen(pTpe->fieldName);
+ cstrDestruct(&pStrField);
+ }
+ if(pTpe->fieldName == NULL) {
+ DBGPRINTF("template/do_Parameter: fieldName is NULL!\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ if(*p) ++p; /* eat '%' */
+ *pp = p;
+finalize_it:
+ if(pStrProp != NULL)
+ cstrDestruct(&pStrProp);
+ RETiRet;
+}
+
+
+/* Add a new entry for a template module.
+ * returns pointer to new object if it succeeds, NULL otherwise.
+ * rgerhards, 2010-05-31
+ */
+static rsRetVal
+tplAddTplMod(struct template *pTpl, uchar** ppRestOfConfLine)
+{
+ uchar *pSrc;
+ uchar szMod[2048];
+ unsigned lenMod;
+ strgen_t *pStrgen;
+ DEFiRet;
+
+ pSrc = *ppRestOfConfLine;
+ lenMod = 0;
+ while(*pSrc && !isspace(*pSrc) && lenMod < sizeof(szMod) - 1) {
+ szMod[lenMod] = *pSrc++;
+ lenMod++;
+
+ }
+ szMod[lenMod] = '\0';
+ *ppRestOfConfLine = pSrc;
+ CHKiRet(strgen.FindStrgen(&pStrgen, szMod));
+ pTpl->pStrgen = pStrgen->pModule->mod.sm.strgen;
+ DBGPRINTF("template bound to strgen '%s'\n", szMod);
+ /* check if the name potentially contains some well-known options
+ * Note: we have opted to let the name contain all options. This sounds
+ * useful, because the strgen MUST actually implement a specific set
+ * of options. Doing this via the name looks to the enduser as if the
+ * regular syntax were used, and it make sure the strgen postively
+ * acknowledged implementing the option. -- rgerhards, 2011-03-21
+ */
+ if(lenMod > 6 && !strcasecmp((char*) szMod + lenMod - 7, ",stdsql")) {
+ pTpl->optFormatEscape = STDSQL_ESCAPE;
+ DBGPRINTF("strgen supports the stdsql option\n");
+ } else if(lenMod > 3 && !strcasecmp((char*) szMod+ lenMod - 4, ",sql")) {
+ pTpl->optFormatEscape = SQL_ESCAPE;
+ DBGPRINTF("strgen supports the sql option\n");
+ } else if(lenMod > 4 && !strcasecmp((char*) szMod+ lenMod - 4, ",json")) {
+ pTpl->optFormatEscape = JSON_ESCAPE;
+ DBGPRINTF("strgen supports the json option\n");
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Add a new template line
+ * returns pointer to new object if it succeeds, NULL otherwise.
+ */
+struct template *tplAddLine(rsconf_t *conf, const char* pName, uchar** ppRestOfConfLine)
+{
+ struct template *pTpl;
+ unsigned char *p;
+ int bDone;
+ size_t i;
+ rsRetVal localRet;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+ if((pTpl = tplConstruct(conf)) == NULL)
+ return NULL;
+
+ DBGPRINTF("tplAddLine processing template '%s'\n", pName);
+ pTpl->iLenName = strlen(pName);
+ pTpl->pszName = (char*) malloc(pTpl->iLenName + 1);
+ if(pTpl->pszName == NULL) {
+ dbgprintf("tplAddLine could not alloc memory for template name!");
+ pTpl->iLenName = 0;
+ return NULL;
+ /* I know - we create a memory leak here - but I deem
+ * it acceptable as it is a) a very small leak b) very
+ * unlikely to happen. rgerhards 2004-11-17
+ */
+ }
+ memcpy(pTpl->pszName, pName, pTpl->iLenName + 1);
+
+ /* now actually parse the line */
+ p = *ppRestOfConfLine;
+ assert(p != NULL);
+
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ switch(*p) {
+ case '"': /* just continue */
+ break;
+ case '=':
+ *ppRestOfConfLine = p + 1;
+ localRet = tplAddTplMod(pTpl, ppRestOfConfLine);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "Template '%s': error %d defining template via strgen module",
+ pTpl->pszName, localRet);
+ /* we simply make the template defunct in this case by setting
+ * its name to a zero-string. We do not free it, as this would
+ * require additional code and causes only a very small memory
+ * consumption. Memory is freed, however, in normal operation
+ * and most importantly by HUPing syslogd.
+ */
+ *pTpl->pszName = '\0';
+ }
+ return NULL;
+ default:
+ dbgprintf("Template '%s' invalid, does not start with '\"'!\n", pTpl->pszName);
+ /* we simply make the template defunct in this case by setting
+ * its name to a zero-string. We do not free it, as this would
+ * require additional code and causes only a very small memory
+ * consumption.
+ */
+ *pTpl->pszName = '\0';
+ return NULL;
+ }
+ ++p;
+
+ /* we finally go to the actual template string - so let's have some fun... */
+ bDone = *p ? 0 : 1;
+ while(!bDone) {
+ switch(*p) {
+ case '\0':
+ bDone = 1;
+ break;
+ case '%': /* parameter */
+ ++p; /* eat '%' */
+ if(do_Parameter(&p, pTpl) != RS_RET_OK) {
+ dbgprintf("tplAddLine error: parameter invalid");
+ return NULL;
+ };
+ break;
+ default: /* constant */
+ do_Constant(&p, pTpl, 1);
+ break;
+ }
+ if(*p == '"') {/* end of template string? */
+ ++p; /* eat it! */
+ bDone = 1;
+ }
+ }
+
+ /* we now have the template - let's look at the options (if any)
+ * we process options until we reach the end of the string or
+ * an error occurs - whichever is first.
+ */
+ while(*p) {
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ if(*p != ',')
+ break;
+ ++p; /* eat ',' */
+
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ /* read option word */
+ char optBuf[128] = { '\0' }; /* buffer for options - should be more than enough... */
+ i = 0;
+ while((i < (sizeof(optBuf) - 1))
+ && *p && *p != '=' && *p !=',' && *p != '\n') {
+ optBuf[i++] = tolower((int)*p);
+ ++p;
+ }
+ optBuf[i] = '\0';
+
+ if(*p == '\n')
+ ++p;
+
+ /* as of now, the no form is nonsense... but I do include
+ * it anyhow... ;) rgerhards 2004-11-22
+ */
+ if(!strcmp(optBuf, "stdsql")) {
+ pTpl->optFormatEscape = STDSQL_ESCAPE;
+ } else if(!strcmp(optBuf, "json")) {
+ pTpl->optFormatEscape = JSON_ESCAPE;
+ } else if(!strcmp(optBuf, "sql")) {
+ pTpl->optFormatEscape = SQL_ESCAPE;
+ } else if(!strcmp(optBuf, "nosql")) {
+ pTpl->optFormatEscape = NO_ESCAPE;
+ } else if(!strcmp(optBuf, "casesensitive")) {
+ pTpl->optCaseSensitive = 1;
+ } else {
+ dbgprintf("Invalid option '%s' ignored.\n", optBuf);
+ }
+ }
+
+ *ppRestOfConfLine = p;
+ apply_case_sensitivity(pTpl);
+
+ return(pTpl);
+}
+
+static rsRetVal
+createConstantTpe(struct template *pTpl, struct cnfobj *o)
+{
+ struct templateEntry *pTpe;
+ es_str_t *value = NULL; /* init just to keep compiler happy - mandatory parameter */
+ int i;
+ int is_jsonf = 0;
+ struct cnfparamvals *pvals = NULL;
+ struct json_object *json = NULL;
+ struct json_object *jval = NULL;
+ uchar *outname = NULL;
+ DEFiRet;
+
+ /* pull params */
+ pvals = nvlstGetParams(o->nvlst, &pblkConstant, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing template parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ cnfparamsPrint(&pblkConstant, pvals);
+
+ for(i = 0 ; i < pblkConstant.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblkConstant.descr[i].name, "value")) {
+ value = pvals[i].val.d.estr;
+ } else if(!strcmp(pblkConstant.descr[i].name, "outname")) {
+ outname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblkConstant.descr[i].name, "format")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonf", sizeof("jsonf")-1)) {
+ is_jsonf = 1;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid format type '%s' for constant",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "template:constantTpe: program error, non-handled "
+ "param '%s'\n", pblkConstant.descr[i].name);
+ }
+ }
+
+ if(is_jsonf && outname == NULL) {
+ parser_errmsg("constant set to format jsonf, but outname not specified - aborting");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* just double-check */
+ assert(value != NULL);
+
+ /* apply */
+ CHKmalloc(pTpe = tpeConstruct(pTpl));
+ es_unescapeStr(value);
+ pTpe->eEntryType = CONSTANT;
+ pTpe->fieldName = outname;
+ if(outname != NULL)
+ pTpe->lenFieldName = ustrlen(outname);
+ if(is_jsonf) {
+ CHKmalloc(json = json_object_new_object());
+ const char *sz = es_str2cstr(value, NULL);
+ CHKmalloc(sz);
+ CHKmalloc(jval = json_object_new_string(sz));
+ free((void*)sz);
+ json_object_object_add(json, (char*)outname, jval);
+ CHKmalloc(sz = json_object_get_string(json));
+ const size_t len_json = strlen(sz) - 4;
+ CHKmalloc(pTpe->data.constant.pConstant = (uchar*) strndup(sz+2, len_json));
+ pTpe->data.constant.iLenConstant = ustrlen(pTpe->data.constant.pConstant);
+ json_object_put(json);
+ } else {
+ pTpe->data.constant.iLenConstant = es_strlen(value);
+ pTpe->data.constant.pConstant = (uchar*)es_str2cstr(value, NULL);
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &pblkConstant);
+ RETiRet;
+}
+
+static rsRetVal
+createPropertyTpe(struct template *pTpl, struct cnfobj *o)
+{
+ struct templateEntry *pTpe;
+ uchar *name = NULL;
+ uchar *outname = NULL;
+ int i;
+ int droplastlf = 0;
+ int spifno1stsp = 0;
+ int mandatory = 0;
+ int frompos = -1;
+ int topos = 0;
+ int topos_set = 0;
+ int fieldnum = -1;
+ int fielddelim = 9; /* default is HT (USACSII 9) */
+ int fixedwidth = 0;
+ int re_matchToUse = 0;
+ int re_submatchToUse = 0;
+ int bComplexProcessing = 0;
+ int bPosRelativeToEnd = 0;
+ int bDateInUTC = 0;
+ int bCompressSP = 0;
+ unsigned dataType = TPE_DATATYPE_STRING;
+ unsigned onEmpty = TPE_DATAEMPTY_KEEP;
+ char *re_expr = NULL;
+ struct cnfparamvals *pvals = NULL;
+ enum {F_NONE, F_CSV, F_JSON, F_JSONF, F_JSONR, F_JSONFR} formatType = F_NONE;
+ enum {CC_NONE, CC_ESCAPE, CC_SPACE, CC_DROP} controlchr = CC_NONE;
+ enum {SP_NONE, SP_DROP, SP_REPLACE} secpath = SP_NONE;
+ enum tplFormatCaseConvTypes caseconv = tplCaseConvNo;
+ enum tplFormatTypes datefmt = tplFmtDefault;
+ enum tplRegexType re_type = TPL_REGEX_BRE;
+ enum tlpRegexNoMatchType re_nomatchType = TPL_REGEX_NOMATCH_USE_DFLTSTR;
+ DEFiRet;
+
+ /* pull params */
+ pvals = nvlstGetParams(o->nvlst, &pblkProperty, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing template entry config parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ cnfparamsPrint(&pblkProperty, pvals);
+
+ for(i = 0 ; i < pblkProperty.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblkProperty.descr[i].name, "name")) {
+ name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblkProperty.descr[i].name, "datatype")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"string", sizeof("string")-1)) {
+ dataType = TPE_DATATYPE_STRING;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"number", sizeof("number")-1)) {
+ dataType = TPE_DATATYPE_NUMBER;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"bool", sizeof("bool")-1)) {
+ dataType = TPE_DATATYPE_BOOL;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"auto", sizeof("auto")-1)) {
+ dataType = TPE_DATATYPE_AUTO;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid dataType '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "onempty")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"keep", sizeof("keep")-1)) {
+ onEmpty = TPE_DATAEMPTY_KEEP;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"skip", sizeof("skip")-1)) {
+ onEmpty = TPE_DATAEMPTY_SKIP;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"null", sizeof("null")-1)) {
+ onEmpty = TPE_DATAEMPTY_NULL;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid onEmpty value '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "droplastlf")) {
+ droplastlf = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "fixedwidth")) {
+ fixedwidth = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "mandatory")) {
+ mandatory = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "spifno1stsp")) {
+ spifno1stsp = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "outname")) {
+ outname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblkProperty.descr[i].name, "position.from")) {
+ frompos = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "position.to")) {
+ topos = pvals[i].val.d.n;
+ topos_set = 1;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "position.relativetoend")) {
+ bPosRelativeToEnd = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "field.number")) {
+ fieldnum = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "field.delimiter")) {
+ fielddelim = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "regex.expression")) {
+ re_expr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "regex.type")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"BRE", sizeof("BRE")-1)) {
+ re_type = TPL_REGEX_BRE;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"ERE", sizeof("ERE")-1)) {
+ re_type = TPL_REGEX_ERE;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid regex.type '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "regex.nomatchmode")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"DFLT", sizeof("DFLT")-1)) {
+ re_nomatchType = TPL_REGEX_NOMATCH_USE_DFLTSTR;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"BLANK", sizeof("BLANK")-1)) {
+ re_nomatchType = TPL_REGEX_NOMATCH_USE_BLANK;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"FIELD", sizeof("FIELD")-1)) {
+ re_nomatchType = TPL_REGEX_NOMATCH_USE_WHOLE_FIELD;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"ZERO", sizeof("ZERO")-1)) {
+ re_nomatchType = TPL_REGEX_NOMATCH_USE_ZERO;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid format type '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "regex.match")) {
+ bComplexProcessing = 1;
+ re_matchToUse = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "regex.submatch")) {
+ bComplexProcessing = 1;
+ re_submatchToUse = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "format")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"csv", sizeof("csv")-1)) {
+ formatType = F_CSV;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"json", sizeof("json")-1)) {
+ formatType = F_JSON;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonf", sizeof("jsonf")-1)) {
+ formatType = F_JSONF;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonr", sizeof("jsonr")-1)) {
+ formatType = F_JSONR;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonfr", sizeof("jsonfr")-1)) {
+ formatType = F_JSONFR;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid format type '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "controlcharacters")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"escape", sizeof("escape")-1)) {
+ controlchr = CC_ESCAPE;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"space", sizeof("space")-1)) {
+ controlchr = CC_SPACE;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"drop", sizeof("drop")-1)) {
+ controlchr = CC_DROP;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid controlcharacter mode '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "securepath")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"drop", sizeof("drop")-1)) {
+ secpath = SP_DROP;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"replace", sizeof("replace")-1)) {
+ secpath = SP_REPLACE;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid securepath mode '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "caseconversion")) {
+ bComplexProcessing = 1;
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"lower", sizeof("lower")-1)) {
+ caseconv = tplCaseConvLower;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"upper", sizeof("upper")-1)) {
+ caseconv = tplCaseConvUpper;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid caseconversion type '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblkProperty.descr[i].name, "compressspace")) {
+ bComplexProcessing = 1;
+ bCompressSP = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "date.inutc")) {
+ bDateInUTC = pvals[i].val.d.n;
+ } else if(!strcmp(pblkProperty.descr[i].name, "dateformat")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"mysql", sizeof("mysql")-1)) {
+ datefmt = tplFmtMySQLDate;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"pgsql", sizeof("pgsql")-1)) {
+ datefmt = tplFmtPgSQLDate;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"rfc3164", sizeof("rfc3164")-1)) {
+ datefmt = tplFmtRFC3164Date;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"rfc3164-buggyday",
+ sizeof("rfc3164-buggyday")-1)) {
+ datefmt = tplFmtRFC3164BuggyDate;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"rfc3339", sizeof("rfc3339")-1)) {
+ datefmt = tplFmtRFC3339Date;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"unixtimestamp",
+ sizeof("unixtimestamp")-1)) {
+ datefmt = tplFmtUnixDate;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"subseconds", sizeof("subseconds")-1)) {
+ datefmt = tplFmtSecFrac;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"wdayname", sizeof("wdayname")-1)) {
+ datefmt = tplFmtWDayName;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"wday", sizeof("wday")-1)) {
+ datefmt = tplFmtWDay;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"year", sizeof("year")-1)) {
+ datefmt = tplFmtYear;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"month", sizeof("month")-1)) {
+ datefmt = tplFmtMonth;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"day", sizeof("day")-1)) {
+ datefmt = tplFmtDay;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"hour", sizeof("hour")-1)) {
+ datefmt = tplFmtHour;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"minute", sizeof("minute")-1)) {
+ datefmt = tplFmtMinute;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"second", sizeof("second")-1)) {
+ datefmt = tplFmtSecond;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffshour", sizeof("tzoffshour")-1)) {
+ datefmt = tplFmtTZOffsHour;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffsmin", sizeof("tzoffsmin")-1)) {
+ datefmt = tplFmtTZOffsMin;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffsdirection",
+ sizeof("tzoffsdirection")-1)) {
+ datefmt = tplFmtTZOffsDirection;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"ordinal", sizeof("ordinal")-1)) {
+ datefmt = tplFmtOrdinal;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"week", sizeof("week")-1)) {
+ datefmt = tplFmtWeek;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid date format '%s' for property",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ dbgprintf("template:propertyTpe: program error, non-handled "
+ "param '%s'\n", pblkProperty.descr[i].name);
+ }
+ }
+ if (name == NULL) {
+ CHKmalloc(name = (uchar*)strdup(""));
+ }
+ if(outname == NULL) {
+ /* we need to drop "$!" prefix, if present */
+ if(ustrlen(name) >= 2 && !strncmp((char*)name, "$!", 2))
+ outname = ustrdup(name + 2);
+ else
+ outname = ustrdup(name);
+ }
+
+ /* sanity check */
+ if(topos_set == 0 && frompos != -1)
+ topos = 2000000000; /* large enough ;) */
+ if(frompos == -1 && topos_set != 0)
+ frompos = 0;
+ if(bPosRelativeToEnd) {
+ if(topos > frompos) {
+ LogError(0, RS_RET_ERR, "position.to=%d is higher than postion.from=%d "
+ "in 'relativeToEnd' mode\n", topos, frompos);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if((topos >= 0) && (topos < frompos)) {
+ LogError(0, RS_RET_ERR, "position.to=%d is lower than postion.from=%d\n",
+ topos, frompos);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ if(fieldnum != -1 && re_expr != NULL) {
+ LogError(0, RS_RET_ERR, "both field extraction and regex extraction "
+ "specified - this is not possible, remove one");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* apply */
+ CHKmalloc(pTpe = tpeConstruct(pTpl));
+ pTpe->eEntryType = FIELD;
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, name, strlen((char*)name)));
+ pTpe->data.field.options.bDropLastLF = droplastlf;
+ pTpe->data.field.options.bSPIffNo1stSP = spifno1stsp;
+ pTpe->data.field.options.bMandatory = mandatory;
+ pTpe->data.field.options.bFixedWidth = fixedwidth;
+ pTpe->data.field.options.dataType = dataType;
+ pTpe->data.field.options.onEmpty = onEmpty;
+ pTpe->data.field.eCaseConv = caseconv;
+ switch(formatType) {
+ case F_NONE:
+ /* all set ;) */
+ break;
+ case F_CSV:
+ pTpe->data.field.options.bCSV = 1;
+ break;
+ case F_JSON:
+ pTpe->data.field.options.bJSON = 1;
+ break;
+ case F_JSONF:
+ pTpe->data.field.options.bJSONf = 1;
+ break;
+ case F_JSONR:
+ pTpe->data.field.options.bJSONr = 1;
+ break;
+ case F_JSONFR:
+ pTpe->data.field.options.bJSONfr = 1;
+ break;
+ }
+ switch(controlchr) {
+ case CC_NONE:
+ /* all set ;) */
+ break;
+ case CC_ESCAPE:
+ pTpe->data.field.options.bEscapeCC = 1;
+ break;
+ case CC_SPACE:
+ pTpe->data.field.options.bSpaceCC = 1;
+ break;
+ case CC_DROP:
+ pTpe->data.field.options.bDropCC = 1;
+ break;
+ }
+ switch(secpath) {
+ case SP_NONE:
+ /* all set ;) */
+ break;
+ case SP_DROP:
+ pTpe->data.field.options.bSecPathDrop = 1;
+ break;
+ case SP_REPLACE:
+ pTpe->data.field.options.bSecPathReplace = 1;
+ break;
+ }
+ pTpe->fieldName = outname;
+ if(outname != NULL)
+ pTpe->lenFieldName = ustrlen(outname);
+ outname = NULL;
+ pTpe->bComplexProcessing = bComplexProcessing;
+ pTpe->data.field.eDateFormat = datefmt;
+ pTpe->data.field.options.bDateInUTC = bDateInUTC;
+ pTpe->data.field.options.bCompressSP = bCompressSP;
+ if(fieldnum != -1) {
+ pTpe->data.field.has_fields = 1;
+ pTpe->data.field.iFieldNr = fieldnum;
+ pTpe->data.field.field_delim = fielddelim;
+ }
+ if(frompos != -1) {
+ pTpe->data.field.iFromPos = frompos;
+ pTpe->data.field.iToPos = topos;
+ pTpe->data.field.options.bFromPosEndRelative = bPosRelativeToEnd;
+ }
+ if(re_expr != NULL) {
+ rsRetVal iRetLocal;
+ pTpe->data.field.typeRegex = re_type;
+ pTpe->data.field.nomatchAction = re_nomatchType;
+ pTpe->data.field.iMatchToUse = re_matchToUse;
+ pTpe->data.field.iSubMatchToUse = re_submatchToUse;
+ pTpe->data.field.has_regex = 1;
+ if((iRetLocal = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) {
+ int iOptions;
+ iOptions = (pTpe->data.field.typeRegex == TPL_REGEX_ERE) ? REG_EXTENDED : 0;
+ if(regexp.regcomp(&(pTpe->data.field.re), (char*) re_expr, iOptions) != 0) {
+ LogError(0, NO_ERRCODE, "error compiling regex '%s'", re_expr);
+ pTpe->data.field.has_regex = 2;
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ /* regexp object could not be loaded */
+ if(bFirstRegexpErrmsg) { /* prevent flood of messages, maybe even an endless loop! */
+ bFirstRegexpErrmsg = 0;
+ LogError(0, NO_ERRCODE, "regexp library could not be loaded (error %d), "
+ "regexp ignored", iRetLocal);
+ }
+ pTpe->data.field.has_regex = 2;
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &pblkProperty);
+ free(name);
+ free(outname);
+ RETiRet;
+}
+
+/* create a template in list mode, is build from sub-objects */
+static rsRetVal
+createListTpl(struct template *pTpl, struct cnfobj *o)
+{
+ struct objlst *lst;
+ DEFiRet;
+
+ dbgprintf("create template from subobjs\n");
+ objlstPrint(o->subobjs);
+
+ for(lst = o->subobjs ; lst != NULL ; lst = lst->next) {
+ switch(lst->obj->objType) {
+ case CNFOBJ_PROPERTY:
+ CHKiRet(createPropertyTpe(pTpl, lst->obj));
+ break;
+ case CNFOBJ_CONSTANT:
+ CHKiRet(createConstantTpe(pTpl, lst->obj));
+ break;
+ default:dbgprintf("program error: invalid object type %d "
+ "in createLstTpl\n", lst->obj->objType);
+ break;
+ }
+ nvlstChkUnused(lst->obj->nvlst);
+ }
+finalize_it:
+ RETiRet;
+}
+
+/* Add a new template via the v6 config system. */
+rsRetVal ATTR_NONNULL()
+tplProcessCnf(struct cnfobj *o)
+{
+ struct template *pTpl = NULL;
+ struct cnfparamvals *pvals = NULL;
+ int lenName = 0; /* init just to keep compiler happy: mandatory parameter */
+ char *name = NULL;
+ uchar *tplStr = NULL;
+ uchar *plugin = NULL;
+ uchar *p;
+ msgPropDescr_t subtree;
+ sbool bHaveSubtree = 0;
+ enum { T_STRING, T_PLUGIN, T_LIST, T_SUBTREE }
+ tplType = T_STRING; /* init just to keep compiler happy: mandatory parameter */
+ int i;
+ int o_sql=0, o_stdsql=0, o_jsonf=0, o_json=0, o_casesensitive=0; /* options */
+ int numopts;
+ rsRetVal localRet;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &pblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing template config parameters");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+ cnfparamsPrint(&pblk, pvals);
+
+ for(i = 0 ; i < pblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(pblk.descr[i].name, "name")) {
+ lenName = es_strlen(pvals[i].val.d.estr);
+ name = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "type")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"string", sizeof("string")-1)) {
+ tplType = T_STRING;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"plugin", sizeof("plugin")-1)) {
+ tplType = T_PLUGIN;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"list", sizeof("list")-1)) {
+ tplType = T_LIST;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"subtree", sizeof("subtree")-1)) {
+ tplType = T_SUBTREE;
+ } else {
+ uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid template type '%s'",
+ typeStr);
+ free(typeStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else if(!strcmp(pblk.descr[i].name, "string")) {
+ tplStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "subtree")) {
+ uchar *st_str = es_getBufAddr(pvals[i].val.d.estr);
+ if(st_str[0] != '$' || st_str[1] != '!') {
+ char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_ERR, "invalid subtree "
+ "parameter, variable must start with '$!' but "
+ "var name is '%s'", cstr);
+ free(cstr);
+ free(name); /* overall assigned */
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ uchar *cstr;
+ cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CHKiRet(msgPropDescrFill(&subtree, cstr, ustrlen(cstr)));
+ free(cstr);
+ bHaveSubtree = 1;
+ }
+ } else if(!strcmp(pblk.descr[i].name, "plugin")) {
+ plugin = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "option.stdsql")) {
+ o_stdsql = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "option.sql")) {
+ o_sql = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "option.json")) {
+ o_json = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "option.jsonf")) {
+ o_jsonf = pvals[i].val.d.n;
+ } else if(!strcmp(pblk.descr[i].name, "option.casesensitive")) {
+ o_casesensitive = pvals[i].val.d.n;
+ } else {
+ dbgprintf("template: program error, non-handled "
+ "param '%s'\n", pblk.descr[i].name);
+ }
+ }
+
+ /* the following check is just for clang static anaylzer: this condition
+ * cannot occur if all is setup well, because "name" is a required parameter
+ * inside the param block and so the code should err out above.
+ */
+ if(name == NULL) {
+ DBGPRINTF("template/tplProcessConf: logic error name == NULL - pblk wrong?\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* do config sanity checks */
+ if(tplStr == NULL) {
+ if(tplType == T_STRING) {
+ LogError(0, RS_RET_ERR, "template '%s' of type string needs "
+ "string parameter", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(tplType != T_STRING) {
+ LogError(0, RS_RET_ERR, "template '%s' is not a string "
+ "template but has a string specified - ignored", name);
+ }
+ }
+
+ if(plugin == NULL) {
+ if(tplType == T_PLUGIN) {
+ LogError(0, RS_RET_ERR, "template '%s' of type plugin needs "
+ "plugin parameter", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(tplType != T_PLUGIN) {
+ LogError(0, RS_RET_ERR, "template '%s' is not a plugin "
+ "template but has a plugin specified - ignored", name);
+ }
+ }
+
+ if(!bHaveSubtree) {
+ if(tplType == T_SUBTREE) {
+ LogError(0, RS_RET_ERR, "template '%s' of type subtree needs "
+ "subtree parameter", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(tplType != T_SUBTREE) {
+ LogError(0, RS_RET_ERR, "template '%s' is not a subtree "
+ "template but has a subtree specified - ignored", name);
+ }
+ }
+
+ if(o->subobjs == NULL) {
+ if(tplType == T_LIST) {
+ LogError(0, RS_RET_ERR, "template '%s' of type list has "
+ "no parameters specified", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(tplType != T_LIST) {
+ LogError(0, RS_RET_ERR, "template '%s' is not a list "
+ "template but has parameters specified - ignored", name);
+ }
+ }
+
+ numopts = 0;
+ if(o_sql) ++numopts;
+ if(o_stdsql) ++numopts;
+ if(o_json) ++numopts;
+ if(o_jsonf) ++numopts;
+ if(numopts > 1) {
+ LogError(0, RS_RET_ERR, "template '%s' has multiple incompatible "
+ "options of sql, stdsql or json specified", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* config ok */
+ if((pTpl = tplConstruct(loadConf)) == NULL) {
+ DBGPRINTF("template.c: tplConstruct failed!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pTpl->pszName = name;
+ pTpl->iLenName = lenName;
+
+ switch(tplType) {
+ case T_STRING: p = tplStr;
+ while(*p) {
+ switch(*p) {
+ case '%': /* parameter */
+ ++p; /* eat '%' */
+ CHKiRet(do_Parameter(&p, pTpl));
+ break;
+ default: /* constant */
+ do_Constant(&p, pTpl, 0);
+ break;
+ }
+ }
+ break;
+ case T_PLUGIN: p = plugin;
+ /* TODO: the use of tplAddTplMod() can be improved! */
+ localRet = tplAddTplMod(pTpl, &p);
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "template '%s': error %d "
+ "defining template via plugin (strgen) module",
+ pTpl->pszName, localRet);
+ ABORT_FINALIZE(localRet);
+ }
+ break;
+ case T_LIST: createListTpl(pTpl, o);
+ break;
+ case T_SUBTREE: memcpy(&pTpl->subtree, &subtree, sizeof(msgPropDescr_t));
+ pTpl->bHaveSubtree = 1;
+ break;
+ }
+
+ pTpl->optFormatEscape = NO_ESCAPE;
+ if(o_stdsql)
+ pTpl->optFormatEscape = STDSQL_ESCAPE;
+ else if(o_sql)
+ pTpl->optFormatEscape = SQL_ESCAPE;
+ else if(o_json)
+ pTpl->optFormatEscape = JSON_ESCAPE;
+ else if(o_jsonf)
+ pTpl->optFormatEscape = JSONF;
+
+ if(o_casesensitive)
+ pTpl->optCaseSensitive = 1;
+ apply_case_sensitivity(pTpl);
+finalize_it:
+ free(tplStr);
+ free(plugin);
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &pblk);
+ if(iRet != RS_RET_OK) {
+ if(pTpl != NULL) {
+ /* we simply make the template defunct in this case by setting
+ * its name to a zero-string. We do not free it, as this would
+ * require additional code and causes only a very small memory
+ * consumption. TODO: maybe in next iteration...
+ */
+ *pTpl->pszName = '\0';
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* Find a template object based on name. Search
+ * currently is case-sensitive (should we change?).
+ * returns pointer to template object if found and
+ * NULL otherwise.
+ * rgerhards 2004-11-17
+ */
+struct template *tplFind(rsconf_t *conf, char *pName, int iLenName)
+{
+ struct template *pTpl;
+
+ assert(pName != NULL);
+
+ pTpl = conf->templates.root;
+ while(pTpl != NULL &&
+ !(pTpl->iLenName == iLenName &&
+ !strcmp(pTpl->pszName, pName)
+ ))
+ {
+ pTpl = pTpl->pNext;
+ }
+ return(pTpl);
+}
+
+/* Destroy the template structure. This is for de-initialization
+ * at program end. Everything is deleted.
+ * rgerhards 2005-02-22
+ * I have commented out dbgprintfs, because they are not needed for
+ * "normal" debugging. Uncomment them, if they are needed.
+ * rgerhards, 2007-07-05
+ */
+void tplDeleteAll(rsconf_t *conf)
+{
+ struct template *pTpl, *pTplDel;
+ struct templateEntry *pTpe, *pTpeDel;
+
+ pTpl = conf->templates.root;
+ while(pTpl != NULL) {
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ pTpeDel = pTpe;
+ pTpe = pTpe->pNext;
+ switch(pTpeDel->eEntryType) {
+ case UNDEFINED:
+ break;
+ case CONSTANT:
+ free(pTpeDel->data.constant.pConstant);
+ break;
+ case FIELD:
+ /* check if we have a regexp and, if so, delete it */
+#ifdef FEATURE_REGEXP
+ if(pTpeDel->data.field.has_regex != 0) {
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ regexp.regfree(&(pTpeDel->data.field.re));
+ }
+ }
+#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
+ break;
+ }
+ free(pTpeDel->fieldName);
+ free(pTpeDel);
+ }
+ pTplDel = pTpl;
+ pTpl = pTpl->pNext;
+ free(pTplDel->pszName);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
+ free(pTplDel);
+ }
+}
+
+
+/* Destroy all templates obtained from conf file
+ * preserving hardcoded ones. This is called from init().
+ */
+void tplDeleteNew(rsconf_t *conf)
+{
+ struct template *pTpl, *pTplDel;
+ struct templateEntry *pTpe, *pTpeDel;
+
+
+ if(conf->templates.root == NULL || conf->templates.lastStatic == NULL)
+ return;
+
+ pTpl = conf->templates.lastStatic->pNext;
+ conf->templates.lastStatic->pNext = NULL;
+ conf->templates.last = conf->templates.lastStatic;
+ while(pTpl != NULL) {
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ pTpeDel = pTpe;
+ pTpe = pTpe->pNext;
+ switch(pTpeDel->eEntryType) {
+ case UNDEFINED:
+ break;
+ case CONSTANT:
+ free(pTpeDel->data.constant.pConstant);
+ break;
+ case FIELD:
+#ifdef FEATURE_REGEXP
+ /* check if we have a regexp and, if so, delete it */
+ if(pTpeDel->data.field.has_regex != 0) {
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ regexp.regfree(&(pTpeDel->data.field.re));
+ }
+ }
+#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
+ break;
+ }
+ free(pTpeDel);
+ }
+ pTplDel = pTpl;
+ pTpl = pTpl->pNext;
+ free(pTplDel->pszName);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
+ free(pTplDel);
+ }
+}
+
+/* Store the pointer to the last hardcoded template */
+void tplLastStaticInit(rsconf_t *conf, struct template *tpl)
+{
+ conf->templates.lastStatic = tpl;
+}
+
+/* Print the template structure. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ */
+void tplPrintList(rsconf_t *conf)
+{
+ struct template *pTpl;
+ struct templateEntry *pTpe;
+
+ pTpl = conf->templates.root;
+ while(pTpl != NULL) {
+ dbgprintf("Template: Name='%s' ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);
+ if(pTpl->optFormatEscape == SQL_ESCAPE)
+ dbgprintf("[SQL-Format (MySQL)] ");
+ else if(pTpl->optFormatEscape == JSON_ESCAPE)
+ dbgprintf("[JSON-Escaped Format] ");
+ else if(pTpl->optFormatEscape == STDSQL_ESCAPE)
+ dbgprintf("[SQL-Format (standard SQL)] ");
+ else if(pTpl->optFormatEscape == JSONF)
+ dbgprintf("[JSON fields] ");
+ if(pTpl->optCaseSensitive)
+ dbgprintf("[Case Sensitive Vars] ");
+ dbgprintf("\n");
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ dbgprintf("\tEntry(%lx): type %d, ", (unsigned long) pTpe, pTpe->eEntryType);
+ switch(pTpe->eEntryType) {
+ case UNDEFINED:
+ dbgprintf("(UNDEFINED)");
+ break;
+ case CONSTANT:
+ dbgprintf("(CONSTANT), value: '%s'",
+ pTpe->data.constant.pConstant);
+ break;
+ case FIELD:
+ dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.msgProp.id);
+ if(pTpe->data.field.msgProp.id == PROP_CEE) {
+ dbgprintf("[EE-Property: '%s'] ", pTpe->data.field.msgProp.name);
+ } else if(pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
+ dbgprintf("[Local Var: '%s'] ", pTpe->data.field.msgProp.name);
+ }
+ switch(pTpe->data.field.eDateFormat) {
+ case tplFmtDefault:
+ break;
+ case tplFmtMySQLDate:
+ dbgprintf("[Format as MySQL-Date] ");
+ break;
+ case tplFmtPgSQLDate:
+ dbgprintf("[Format as PgSQL-Date] ");
+ break;
+ case tplFmtRFC3164Date:
+ dbgprintf("[Format as RFC3164-Date] ");
+ break;
+ case tplFmtRFC3339Date:
+ dbgprintf("[Format as RFC3339-Date] ");
+ break;
+ case tplFmtUnixDate:
+ dbgprintf("[Format as Unix timestamp] ");
+ break;
+ case tplFmtSecFrac:
+ dbgprintf("[fractional seconds, only] ");
+ break;
+ case tplFmtRFC3164BuggyDate:
+ dbgprintf("[Format as buggy RFC3164-Date] ");
+ break;
+ case tplFmtWDayName:
+ dbgprintf("[Format as weekday name] ");
+ break;
+ case tplFmtYear:
+ dbgprintf("[Format as year] ");
+ break;
+ case tplFmtMonth:
+ dbgprintf("[Format as month] ");
+ break;
+ case tplFmtDay:
+ dbgprintf("[Format as day] ");
+ break;
+ case tplFmtHour:
+ dbgprintf("[Format as hour] ");
+ break;
+ case tplFmtMinute:
+ dbgprintf("[Format as minute] ");
+ break;
+ case tplFmtSecond:
+ dbgprintf("[Format as second] ");
+ break;
+ case tplFmtTZOffsHour:
+ dbgprintf("[Format as offset hour] ");
+ break;
+ case tplFmtTZOffsMin:
+ dbgprintf("[Format as offset minute] ");
+ break;
+ case tplFmtTZOffsDirection:
+ dbgprintf("[Format as offset direction] ");
+ break;
+ case tplFmtWDay:
+ dbgprintf("[Format as weekday] ");
+ break;
+ case tplFmtOrdinal:
+ dbgprintf("[Format as ordinal] ");
+ break;
+ case tplFmtWeek:
+ dbgprintf("[Format as week] ");
+ break;
+ default:
+ dbgprintf("[UNKNOWN eDateFormat %d] ", pTpe->data.field.eDateFormat);
+ }
+ switch(pTpe->data.field.eCaseConv) {
+ case tplCaseConvNo:
+ break;
+ case tplCaseConvLower:
+ dbgprintf("[Converted to Lower Case] ");
+ break;
+ case tplCaseConvUpper:
+ dbgprintf("[Converted to Upper Case] ");
+ break;
+ }
+ if(pTpe->data.field.options.bEscapeCC) {
+ dbgprintf("[escape control-characters] ");
+ }
+ if(pTpe->data.field.options.bDropCC) {
+ dbgprintf("[drop control-characters] ");
+ }
+ if(pTpe->data.field.options.bSpaceCC) {
+ dbgprintf("[replace control-characters with space] ");
+ }
+ if(pTpe->data.field.options.bSecPathDrop) {
+ dbgprintf("[slashes are dropped] ");
+ }
+ if(pTpe->data.field.options.bSecPathReplace) {
+ dbgprintf("[slashes are replaced by '_'] ");
+ }
+ if(pTpe->data.field.options.bSPIffNo1stSP) {
+ dbgprintf("[SP iff no first SP] ");
+ }
+ if(pTpe->data.field.options.bCSV) {
+ dbgprintf("[format as CSV (RFC4180)]");
+ }
+ if(pTpe->data.field.options.bJSON) {
+ dbgprintf("[format as JSON] ");
+ }
+ if(pTpe->data.field.options.bJSONf) {
+ dbgprintf("[format as JSON field] ");
+ }
+ if(pTpe->data.field.options.bJSONr) {
+ dbgprintf("[format as JSON without re-escaping] ");
+ }
+ if(pTpe->data.field.options.bJSONfr) {
+ dbgprintf("[format as JSON field without re-escaping] ");
+ }
+ if(pTpe->data.field.options.bMandatory) {
+ dbgprintf("[mandatory field] ");
+ }
+ if(pTpe->data.field.options.bDropLastLF) {
+ dbgprintf("[drop last LF in msg] ");
+ }
+ if(pTpe->data.field.has_fields == 1) {
+ dbgprintf("[substring, field #%d only (delimiter %d)] ",
+ pTpe->data.field.iFieldNr, pTpe->data.field.field_delim);
+ }
+ if(pTpe->data.field.iFromPos != 0 || pTpe->data.field.iToPos != 0) {
+ dbgprintf("[substring, from character %d to %d] ",
+ pTpe->data.field.iFromPos,
+ pTpe->data.field.iToPos);
+ }
+ break;
+ }
+ if(pTpe->bComplexProcessing)
+ dbgprintf("[COMPLEX]");
+ dbgprintf("\n");
+ pTpe = pTpe->pNext;
+ }
+ pTpl = pTpl->pNext; /* done, go next */
+ }
+}
+
+int tplGetEntryCount(struct template *pTpl)
+{
+ assert(pTpl != NULL);
+ return(pTpl->tpenElements);
+}
+
+rsRetVal templateInit(void)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+ CHKiRet(objUse(strgen, CORE_COMPONENT));
+
+finalize_it:
+ RETiRet;
+}
diff --git a/template.h b/template.h
new file mode 100644
index 0000000..8c30adc
--- /dev/null
+++ b/template.h
@@ -0,0 +1,188 @@
+/* This is the header for template processing code of rsyslog.
+ * begun 2004-11-17 rgerhards
+ *
+ * Copyright (C) 2004-2013 by Rainer Gerhards and Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Note: there is a tiny bit of code left where I could not get any response
+ * from the author if this code can be placed under ASL2.0. I have guarded this
+ * with #ifdef STRICT_GPLV3. Only if that macro is defined, the code will be
+ * compiled. Otherwise this feature is not present. The plan is to do a
+ * different implementation in the future to get rid of this problem.
+ * rgerhards, 2012-08-25
+ */
+
+#ifndef TEMPLATE_H_INCLUDED
+#define TEMPLATE_H_INCLUDED 1
+
+#include <json.h>
+#include <libestr.h>
+#include "regexp.h"
+#include "stringbuf.h"
+
+struct template {
+ struct template *pNext;
+ char *pszName;
+ int iLenName;
+ rsRetVal (*pStrgen)(const smsg_t*const, actWrkrIParams_t *const iparam);
+ sbool bHaveSubtree;
+ msgPropDescr_t subtree; /* subtree property name for subtree-type templates */
+ int tpenElements; /* number of elements in templateEntry list */
+ struct templateEntry *pEntryRoot;
+ struct templateEntry *pEntryLast;
+ char optFormatEscape; /* in text fields, */
+# define NO_ESCAPE 0 /* 0 - do not escape, */
+# define SQL_ESCAPE 1 /* 1 - escape "the MySQL way" */
+# define STDSQL_ESCAPE 2 /* 2 - escape quotes by double quotes, */
+# define JSON_ESCAPE 3 /* 3 - escape double quotes for JSON. */
+# define JSONF 4 /* 4 - not a real escape - template contains json fields only */
+ /* following are options. All are 0/1 defined (either on or off).
+ * we use chars because they are faster than bit fields and smaller
+ * than short...
+ */
+ char optCaseSensitive; /* case-sensitive variable property references, default False, 0 */
+};
+
+enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 };
+enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1,
+ tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3, tplFmtPgSQLDate = 4,
+ tplFmtSecFrac = 5, tplFmtRFC3164BuggyDate = 6, tplFmtUnixDate = 7,
+ tplFmtWDayName = 8, tplFmtYear = 9, tplFmtMonth = 10, tplFmtDay = 11,
+ tplFmtHour = 12, tplFmtMinute = 13, tplFmtSecond = 14,
+ tplFmtTZOffsHour = 15, tplFmtTZOffsMin = 16, tplFmtTZOffsDirection = 17,
+ tplFmtWDay = 18, tplFmtOrdinal = 19, tplFmtWeek = 20,
+ tplFmtISOWeek = 21, tplFmtISOWeekYear = 22};
+enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 };
+enum tplRegexType { TPL_REGEX_BRE = 0, /* posix BRE */
+ TPL_REGEX_ERE = 1 /* posix ERE */
+ };
+
+#include "msg.h"
+
+/* a specific parse entry */
+struct templateEntry {
+ struct templateEntry *pNext;
+ enum EntryTypes eEntryType;
+ uchar *fieldName; /**< field name to be used for structured output */
+ int lenFieldName;
+ sbool bComplexProcessing; /**< set if complex processing (options, etc) is required */
+ union {
+ struct {
+ uchar *pConstant; /* pointer to constant value */
+ int iLenConstant; /* its length */
+ } constant;
+ struct {
+ msgPropDescr_t msgProp; /* property to be used */
+ unsigned iFromPos; /* for partial strings only chars from this position ... */
+ unsigned iToPos; /* up to that one... */
+ unsigned iFieldNr; /* for field extraction: field to extract */
+#ifdef FEATURE_REGEXP
+ regex_t re; /* APR: this is the regular expression */
+ short has_regex;
+ short iMatchToUse;/* which match should be obtained (10 max) */
+ short iSubMatchToUse;/* which submatch should be obtained (10 max) */
+ enum tplRegexType typeRegex;
+ enum tlpRegexNoMatchType {
+ TPL_REGEX_NOMATCH_USE_DFLTSTR = 0,
+ /* use the (old style) default "**NO MATCH**" string */
+ TPL_REGEX_NOMATCH_USE_BLANK = 1, /* use a blank string */
+ TPL_REGEX_NOMATCH_USE_WHOLE_FIELD = 2, /* use the full field contents
+ that we were searching in*/
+ TPL_REGEX_NOMATCH_USE_ZERO = 3 /* use 0 (useful for numerical values) */
+ } nomatchAction; /**< what to do if we do not have a match? */
+
+#endif
+ unsigned has_fields; /* support for field-counting: field to extract */
+ unsigned char field_delim; /* support for field-counting: field delimiter char */
+#ifdef STRICT_GPLV3
+ int field_expand; /* use multiple instances of the field delimiter as a single one? */
+#endif
+
+
+ enum tplFormatTypes eDateFormat;
+ enum tplFormatCaseConvTypes eCaseConv;
+ struct { /* bit fields! */
+ unsigned bDropCC: 1; /* drop control characters? */
+ unsigned bSpaceCC: 1; /* change control characters to spaceescape? */
+ unsigned bEscapeCC: 1; /* escape control characters? */
+ unsigned bCompressSP: 1; /* compress multiple spaces to a single one? */
+ unsigned bDropLastLF: 1; /* drop last LF char in msg (PIX!) */
+ unsigned bSecPathDrop: 1; /* drop slashes, replace dots, empty string */
+ unsigned bSecPathReplace: 1; /* replace slashes, replace dots, empty string */
+ unsigned bSPIffNo1stSP: 1; /* be a space if 1st pos if field is no space*/
+ unsigned bCSV: 1; /* format field in CSV (RFC 4180) format */
+ unsigned bJSON: 1; /* format field JSON escaped */
+ unsigned bJSONf: 1; /* format field JSON *field* (n/v pair) */
+ unsigned bJSONr: 1; /* format field JSON non escaped */
+ unsigned bJSONfr: 1; /* format field JSON *field* non escaped (n/v pair) */
+ unsigned bMandatory: 1; /* mandatory field - emit even if empty */
+ unsigned bFromPosEndRelative: 1;/* is From/To-Pos relative to end of string? */
+ unsigned bFixedWidth: 1; /* space pad to toChar if string is shorter */
+ unsigned bDateInUTC: 1; /* should date be expressed in UTC? */
+ #define TPE_DATATYPE_STRING 0
+ #define TPE_DATATYPE_NUMBER 1
+ #define TPE_DATATYPE_BOOL 2
+ #define TPE_DATATYPE_AUTO 3 /* NOTE: bit field values exhausted! */
+ unsigned dataType: 2;
+ #define TPE_DATAEMPTY_KEEP 0
+ #define TPE_DATAEMPTY_SKIP 1
+ #define TPE_DATAEMPTY_NULL 2
+ unsigned onEmpty: 2;
+ } options; /* options as bit fields */
+ } field;
+ } data;
+};
+
+
+/* interfaces */
+BEGINinterface(tpl) /* name must also be changed in ENDinterface macro! */
+ENDinterface(tpl)
+#define tplCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+/* prototypes */
+PROTOTYPEObj(tpl);
+
+
+struct template *tplAddLine(rsconf_t *conf, const char* pName, unsigned char** pRestOfConfLine);
+struct template *tplFind(rsconf_t *conf, char *pName, int iLenName);
+int tplGetEntryCount(struct template *pTpl);
+void tplDeleteAll(rsconf_t *conf);
+void tplDeleteNew(rsconf_t *conf);
+void tplPrintList(rsconf_t *conf);
+void tplLastStaticInit(rsconf_t *conf, struct template *tpl);
+rsRetVal ExtendBuf(actWrkrIParams_t *const iparam, const size_t iMinSize);
+int tplRequiresDateCall(struct template *pTpl);
+/* note: if a compiler warning for undefined type tells you to look at this
+ * code line below, the actual cause is that you currently MUST include template.h
+ * BEFORE msg.h, even if your code file does not actually need it.
+ * rgerhards, 2007-08-06
+ */
+rsRetVal tplToJSON(struct template *pTpl, smsg_t *pMsg, struct json_object **, struct syslogTime *ttNow);
+rsRetVal doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);
+rsRetVal
+tplToString(struct template *__restrict__ const pTpl,
+ smsg_t *__restrict__ const pMsg,
+ actWrkrIParams_t *__restrict__ const iparam,
+ struct syslogTime *const ttNow);
+
+rsRetVal templateInit(void);
+rsRetVal tplProcessCnf(struct cnfobj *o);
+
+#endif /* #ifndef TEMPLATE_H_INCLUDED */
+/* vim:set ai:
+ */
diff --git a/test-driver b/test-driver
new file mode 100755
index 0000000..b8521a4
--- /dev/null
+++ b/test-driver
@@ -0,0 +1,148 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 2011-2018 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 <https://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='' # Red.
+ grn='' # Green.
+ lgn='' # Light green.
+ blu='' # Blue.
+ mgn='' # Magenta.
+ std='' # 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
+ tweaked_estatus=1
+else
+ tweaked_estatus=$estatus
+fi
+
+case $tweaked_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 the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# 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 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/tests/1.rstest b/tests/1.rstest
new file mode 100644
index 0000000..4716e8b
--- /dev/null
+++ b/tests/1.rstest
@@ -0,0 +1,26 @@
+# a simple RainerScript test
+result: 0
+in:
+'test 1' <> $var or /* some comment */($SEVERITY == -4 +5 -(3 * - 2) and $fromhost == '127.0.0.1') then
+$$$
+out:
+00000000: push_const test 1[cstr]
+00000001: push_msgvar var[cstr]
+00000002: cmp_!=
+00000003: push_msgvar severity[cstr]
+00000004: push_const 4[nbr]
+00000005: unary_minus
+00000006: push_const 5[nbr]
+00000007: add
+00000008: push_const 3[nbr]
+00000009: push_const 2[nbr]
+00000010: unary_minus
+00000011: mul
+00000012: sub
+00000013: cmp_==
+00000014: push_msgvar fromhost[cstr]
+00000015: push_const 127.0.0.1[cstr]
+00000016: cmp_==
+00000017: and
+00000018: or
+$$$
diff --git a/tests/2.rstest b/tests/2.rstest
new file mode 100644
index 0000000..f0e8205
--- /dev/null
+++ b/tests/2.rstest
@@ -0,0 +1,10 @@
+# a simple RainerScript test
+result: 0
+in:
+$msg contains 'test' then
+$$$
+out:
+00000000: push_msgvar msg[cstr]
+00000001: push_const test[cstr]
+00000002: contains
+$$$
diff --git a/tests/3.rstest b/tests/3.rstest
new file mode 100644
index 0000000..e75d975
--- /dev/null
+++ b/tests/3.rstest
@@ -0,0 +1,21 @@
+# a simple RainerScript test
+result: 0
+in:
+strlen($msg & strlen('abc')) > 20 +30 + -40 then
+$$$
+out:
+00000000: push_msgvar msg[cstr]
+00000001: push_const abc[cstr]
+00000002: push_const 1[nbr]
+00000003: func_call strlen
+00000004: strconcat
+00000005: push_const 1[nbr]
+00000006: func_call strlen
+00000007: push_const 20[nbr]
+00000008: push_const 30[nbr]
+00000009: add
+00000010: push_const 40[nbr]
+00000011: unary_minus
+00000012: add
+00000013: cmp_>
+$$$
diff --git a/tests/CI/centos6-9.supp b/tests/CI/centos6-9.supp
new file mode 100644
index 0000000..e77e3e1
--- /dev/null
+++ b/tests/CI/centos6-9.supp
@@ -0,0 +1,32 @@
+{
+ CentOS 6.9 problem in either helgrind or system lib
+ Helgrind:Misc
+ fun:pthread_cond_destroy_WRK
+ fun:pthread_cond_destroy@*
+ fun:qqueueDestruct
+ fun:actionDestruct
+ fun:cnfstmtDestruct
+ fun:cnfstmtDestructLst
+ fun:cnfstmtDestruct
+ fun:cnfstmtDestructLst
+ fun:doDestructCnfStmt
+ fun:llExecFunc
+ fun:destructAllActions
+ fun:main
+}
+{
+ libcrypto issue - only seen on Centos 6 so pretty sure false positive
+ Memcheck:Leak
+ fun:malloc
+ fun:CRYPTO_malloc
+ fun:EC_KEY_new
+ fun:EC_KEY_new_by_curve_name
+ fun:osslAnonInit
+ fun:SetAuthMode
+ fun:LstnInit
+ fun:LstnInit
+ fun:LstnInit
+ fun:initTCPListener
+ fun:create_tcp_socket
+ fun:doOpenLstnSocks
+}
diff --git a/tests/CI/centos7.supp b/tests/CI/centos7.supp
new file mode 100644
index 0000000..424dd72
--- /dev/null
+++ b/tests/CI/centos7.supp
@@ -0,0 +1,9 @@
+{
+ CentOS 7 system lib memleak
+ Memcheck:Free
+ fun:free
+ fun:__libc_freeres
+ fun:_vgnU_freeres
+ fun:__run_exit_handlers
+ ...
+}
diff --git a/tests/CI/gcov.supp b/tests/CI/gcov.supp
new file mode 100644
index 0000000..61269dd
--- /dev/null
+++ b/tests/CI/gcov.supp
@@ -0,0 +1,6 @@
+{
+ gcc -coverage exceptions
+ Helgrind:Race
+ fun:__gcov_merge_add
+ ...
+}
diff --git a/tests/CI/ubuntu20.04.supp b/tests/CI/ubuntu20.04.supp
new file mode 100644
index 0000000..2638a7f
--- /dev/null
+++ b/tests/CI/ubuntu20.04.supp
@@ -0,0 +1,42 @@
+{
+ librdkafka issue
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ fun:checkInstance
+ fun:activateCnf
+ fun:tellModulesActivateConfig
+ fun:activate
+ fun:initAll
+}
+
+{
+ librdkafka issue
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ ...
+ obj:*
+ fun:checkInstance
+ fun:activateCnf
+ fun:tellModulesActivateConfig
+ fun:activate
+ fun:initAll
+ fun:main
+}
+
+{
+ invalid atexit call - seems to stem back to libcurl
+ Helgrind:Misc
+ ...
+ fun:_dl_fini
+ fun:__run_exit_handlers
+ fun:exit
+ fun:(below main)
+}
diff --git a/tests/DevNull.cfgtest b/tests/DevNull.cfgtest
new file mode 100644
index 0000000..bc43693
--- /dev/null
+++ b/tests/DevNull.cfgtest
@@ -0,0 +1,2 @@
+rsyslogd: CONFIG ERROR: there are no active actions configured. Inputs will run, but no output whatsoever is created. [try https://www.rsyslog.com/e/2103 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..70b0a60
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,3148 @@
+TEST_EXTENSIONS=.sh
+
+if ENABLE_TESTBENCH
+
+CLEANFILES=\
+ *_*.conf \
+ rsyslog*.started work-*.conf rsyslog.random.data \
+ rsyslog*.pid.save xlate*.lkp_tbl \
+ log log* *.log \
+ work \
+ test-spool test-logdir stat-file1 \
+ rsyslog.pipe rsyslog.input.* \
+ rsyslog.input rsyslog.input.* imfile-state:* omkafka-failed.data \
+ rsyslog.input-symlink.log rsyslog-link.*.log targets \
+ HOSTNAME \
+ rstb_* \
+ zookeeper.pid \
+ tmp.qi nocert
+
+CLEANFILES+= \
+ IN_AUTO_DEBUG
+# IN_AUTO_DEBUG should be deleted each time make check is run, but
+# there exists no such hook. Se we at least delete it on make clean.
+
+
+pkglib_LTLIBRARIES =
+
+pkglib_LTLIBRARIES += liboverride_gethostname.la
+liboverride_gethostname_la_SOURCES = override_gethostname.c
+liboverride_gethostname_la_CFLAGS =
+liboverride_gethostname_la_LDFLAGS = -avoid-version -shared
+
+pkglib_LTLIBRARIES += liboverride_gethostname_nonfqdn.la
+liboverride_gethostname_nonfqdn_la_SOURCES = override_gethostname_nonfqdn.c
+liboverride_gethostname_nonfqdn_la_CFLAGS =
+liboverride_gethostname_nonfqdn_la_LDFLAGS = -avoid-version -shared
+
+pkglib_LTLIBRARIES += liboverride_getaddrinfo.la
+liboverride_getaddrinfo_la_SOURCES = override_getaddrinfo.c
+liboverride_getaddrinfo_la_CFLAGS =
+liboverride_getaddrinfo_la_LDFLAGS = -avoid-version -shared
+
+# TODO: reenable TESTRUNS = rt_init rscript
+check_PROGRAMS = $(TESTRUNS) ourtail tcpflood chkseq msleep randomgen \
+ diagtalker uxsockrcvr syslog_caller inputfilegen minitcpsrv \
+ omrelp_dflt_port \
+ mangle_qi \
+ have_relpSrvSetOversizeMode \
+ have_relpEngineSetTLSLibByName \
+ have_relpSrvSetTlsConfigCmd \
+ check_relpEngineVersion \
+ test_id
+if ENABLE_JOURNAL_TESTS
+if ENABLE_IMJOURNAL
+check_PROGRAMS += journal_print
+endif
+endif # if ENABLE_JOURNAL_TESTS
+TESTS = $(TESTRUNS)
+
+if ENABLE_ELASTICSEARCH_TESTS_MINIMAL
+TESTS += \
+ es-duplicated-ruleset.sh
+# the following test need to be serialized:
+TESTS += \
+ es-basic-es6.0.sh \
+ es-basic-es7.14.sh \
+ es-basic.sh \
+ es-basic-bulk.sh
+es-basic-es7.14.log: es-basic-es6.0.log
+es-basic.log: es-basic-es7.14.log
+es-basic-bulk.log: es-basic.log
+es-basic-server.log: es-basic-bulk.log
+
+# special "test" for stopping ES once all ES tests are done
+TESTS += elasticsearch-stop.sh
+elasticsearch-stop.log: es-basic-bulk.log
+
+
+if HAVE_VALGRIND
+TESTS += \
+ es-duplicated-ruleset-vg.sh \
+ es-basic-vg.sh
+es-basic-vg.log: es-basic-bulk.log
+# for next if block:
+es-basic-server.log: es-basic-vg.log
+elasticsearch-stop.log: es-basic-vg.log
+if ENABLE_HELGRIND
+TESTS += \
+ es-basic-vgthread.sh
+es-basic-vgthread.log: es-basic-vg.log
+# for next if block:
+es-basic-server.log: es-basic-vgthread.log
+elasticsearch-stop.log: es-basic-vgthread.log
+endif # ENABLE_HELGRIND
+endif # HAVE_VALGRIND
+endif # ENABLE_ELASTICSEARCH_TESTS_MINIMAL
+
+if ENABLE_ELASTICSEARCH_TESTS
+TESTS += \
+ es-basic-server.sh \
+ es-execOnlyWhenPreviousSuspended.sh \
+ es-maxbytes-bulk.sh \
+ es-basic-errfile-empty.sh \
+ es-basic-errfile-popul.sh \
+ es-bulk-errfile-empty.sh \
+ es-bulk-errfile-popul.sh \
+ es-searchType-empty.sh \
+ diskqueue-multithread-es.sh \
+ es-writeoperation.sh
+
+es-basic-server.log: es-basic-bulk.log
+es-execOnlyWhenPreviousSuspended.log: es-basic-server.log
+es-maxbytes-bulk.log: es-execOnlyWhenPreviousSuspended.log
+es-basic-errfile-empty.log: es-maxbytes-bulk.log
+es-basic-errfile-popul.log: es-basic-errfile-empty.log
+es-bulk-errfile-empty.log: es-basic-errfile-popul.log
+es-bulk-errfile-popul.log: es-bulk-errfile-empty.log
+es-searchType-empty.log: es-bulk-errfile-popul.log
+diskqueue-multithread-es.log: es-searchType-empty.log
+es-writeoperation.log: diskqueue-multithread-es.log
+elasticsearch-stop.log: es-writeoperation.log
+
+if ENABLE_IMPSTATS
+TESTS += \
+ es-basic-ha.sh \
+ es-bulk-retry.sh
+
+es-basic-ha.log: es-writeoperation.log
+es-bulk-retry.log: es-basic-ha.log
+elasticsearch-stop.log: es-bulk-retry.log
+endif
+if ENABLE_IMFILE
+TESTS += \
+ es-bulk-errfile-popul-def-format.sh \
+ es-bulk-errfile-popul-erronly.sh \
+ es-bulk-errfile-popul-erronly-interleaved.sh \
+ es-bulk-errfile-popul-def-interleaved.sh
+
+es-bulk-errfile-popul-def-format.log: es-bulk-retry.log
+es-bulk-errfile-popul-erronly.log: es-bulk-errfile-popul-def-format.log
+es-bulk-errfile-popul-erronly-interleaved.log: es-bulk-errfile-popul-erronly.log
+es-bulk-errfile-popul-def-interleaved.log: es-bulk-errfile-popul-erronly-interleaved.log
+elasticsearch-stop.log: es-bulk-errfile-popul-def-interleaved.log
+endif
+if HAVE_VALGRIND
+TESTS += \
+ es-basic-bulk-vg.sh \
+ es-basic-ha-vg.sh
+
+es-basic-bulk-vg.log: es-writeoperation.log
+es-basic-bulk-vg.log: es-bulk-retry.log
+es-basic-bulk-vg.log: es-bulk-errfile-popul-def-interleaved.log
+es-basic-ha-vg.log: es-basic-bulk-vg.log
+elasticsearch-stop.log: es-basic-ha-vg.log
+endif
+endif # if ENABLE_ELASTICSEARCH_TESTS
+
+
+
+if ENABLE_DEFAULT_TESTS
+TESTS += \
+ immark.sh \
+ immark-inputname.sh \
+ immark-ruleset.sh \
+ immark-ruleset-custom-msg.sh \
+ operatingstate-basic.sh \
+ operatingstate-empty.sh \
+ operatingstate-unclean.sh \
+ smtradfile.sh \
+ loadbalance.sh \
+ empty-hostname.sh \
+ timestamp-3164.sh \
+ timestamp-3339.sh \
+ timestamp-isoweek.sh \
+ timestamp-mysql.sh \
+ timestamp-pgsql.sh \
+ timestamp-subseconds.sh \
+ msleep_usage_output.sh \
+ mangle_qi_usage_output.sh \
+ minitcpsrv_usage_output.sh \
+ test_id_usage_output.sh \
+ prop-programname.sh \
+ prop-programname-with-slashes.sh \
+ hostname-with-slash-pmrfc5424.sh \
+ hostname-with-slash-pmrfc3164.sh \
+ hostname-with-slash-dflt-invld.sh \
+ func-substring-invld-startpos.sh \
+ func-substring-large-endpos.sh \
+ func-substring-large-neg-endpos.sh \
+ func-substring-relative-endpos.sh \
+ hostname-with-slash-dflt-slash-valid.sh \
+ empty-app-name.sh \
+ stop-localvar.sh \
+ stop-msgvar.sh \
+ glbl-ruleset-queue-defaults.sh \
+ glbl-internalmsg_severity-info-shown.sh \
+ glbl-internalmsg_severity-debug-shown.sh \
+ glbl-internalmsg_severity-debug-not_shown.sh \
+ glbl-umask.sh \
+ glbl-unloadmodules.sh \
+ glbl-invld-param.sh \
+ glbl_setenv_2_vars.sh \
+ glbl_setenv_err.sh \
+ glbl_setenv_err_too_long.sh \
+ glbl_setenv.sh \
+ mmexternal-SegFault.sh \
+ nested-call-shutdown.sh \
+ dnscache-TTL-0.sh \
+ invalid_nested_include.sh \
+ omfwd-tls-invalid-permitExpiredCerts.sh \
+ omfwd-keepalive.sh \
+ omusrmsg-errmsg-no-params.sh \
+ omusrmsg-noabort.sh \
+ omfile-module-params.sh \
+ omfile-read-only-errmsg.sh \
+ omfile-null-filename.sh \
+ omfile-whitespace-filename.sh \
+ omfile-read-only.sh \
+ omfile-outchannel.sh \
+ omfile_both_files_set.sh \
+ omfile_hup.sh \
+ msgvar-concurrency.sh \
+ localvar-concurrency.sh \
+ exec_tpl-concurrency.sh \
+ rscript_privdropuser.sh \
+ rscript_privdropuserid.sh \
+ rscript_privdropgroup.sh \
+ rscript_privdropgroupid.sh \
+ privdropuser.sh \
+ privdropuserid.sh \
+ privdropgroup.sh \
+ privdropgroupid.sh \
+ privdropabortonidfail.sh \
+ privdropabortonidfaillegacy.sh \
+ json-nonstring.sh \
+ json-onempty-at-end.sh \
+ template-json.sh \
+ template-pure-json.sh \
+ template-pos-from-to.sh \
+ template-pos-from-to-lowercase.sh \
+ template-pos-from-to-oversize.sh \
+ template-pos-from-to-oversize-lowercase.sh \
+ template-pos-from-to-missing-jsonvar.sh \
+ template-const-jsonf.sh \
+ template-topos-neg.sh \
+ fac_authpriv.sh \
+ fac_local0.sh \
+ fac_local7.sh \
+ fac_mail.sh \
+ fac_news.sh \
+ fac_ftp.sh \
+ fac_ntp.sh \
+ fac_uucp.sh \
+ fac_invld1.sh \
+ fac_invld2.sh \
+ fac_invld3.sh \
+ fac_invld4_rfc5424.sh \
+ rfc5424parser-sp_at_msg_start.sh \
+ compresssp.sh \
+ compresssp-stringtpl.sh \
+ rawmsg-after-pri.sh \
+ rfc5424parser.sh \
+ pmrfc3164-msgFirstSpace.sh \
+ pmrfc3164-AtSignsInHostname.sh \
+ pmrfc3164-AtSignsInHostname_off.sh \
+ pmrfc3164-tagEndingByColon.sh \
+ pmrfc3164-defaultTag.sh \
+ pmrfc3164-json.sh \
+ tcp_forwarding_tpl.sh \
+ tcp_forwarding_dflt_tpl.sh \
+ tcp_forwarding_retries.sh \
+ mainq_actq_DA.sh \
+ queue_warnmsg-oversize.sh \
+ queue-minbatch.sh \
+ queue-minbatch-queuefull.sh \
+ queue-direct-with-no-params.sh \
+ queue-direct-with-params-given.sh \
+ arrayqueue.sh \
+ global_vars.sh \
+ no-parser-errmsg.sh \
+ da-mainmsg-q.sh \
+ validation-run.sh \
+ msgdup.sh \
+ msgdup_props.sh \
+ empty-ruleset.sh \
+ ruleset-direct-queue.sh \
+ imtcp-listen-port-file-2.sh \
+ allowed-sender-tcp-ok.sh \
+ allowed-sender-tcp-fail.sh \
+ allowed-sender-tcp-hostname-ok.sh \
+ allowed-sender-tcp-hostname-fail.sh \
+ imtcp-discard-truncated-msg.sh \
+ imtcp-basic.sh \
+ imtcp-basic-hup.sh \
+ imtcp-maxFrameSize.sh \
+ imtcp-msg-truncation-on-number.sh \
+ imtcp-msg-truncation-on-number2.sh \
+ imtcp-NUL.sh \
+ imtcp-NUL-rawmsg.sh \
+ imtcp_incomplete_frame_at_end.sh \
+ imtcp-multiport.sh \
+ imtcp-bigmessage-octetcounting.sh \
+ imtcp-bigmessage-octetstuffing.sh \
+ da-queue-persist.sh \
+ daqueue-persist.sh \
+ daqueue-invld-qi.sh \
+ daqueue-dirty-shutdown.sh \
+ diskq-rfc5424.sh \
+ diskqueue.sh \
+ diskqueue-fsync.sh \
+ diskqueue-full.sh \
+ diskqueue-fail.sh \
+ diskqueue-non-unique-prefix.sh \
+ rulesetmultiqueue.sh \
+ rulesetmultiqueue-v6.sh \
+ manytcp.sh \
+ rsf_getenv.sh \
+ msg-deadlock-headerless-noappname.sh \
+ imtcp_conndrop.sh \
+ imtcp_addtlframedelim.sh \
+ imtcp_no_octet_counted.sh \
+ imtcp_addtlframedelim_on_input.sh \
+ imtcp_spframingfix.sh \
+ imtcp-connection-msg-recieved.sh \
+ sndrcv.sh \
+ sndrcv_failover.sh \
+ sndrcv_gzip.sh \
+ sndrcv_udp_nonstdpt.sh \
+ sndrcv_udp_nonstdpt_v6.sh \
+ imudp_thread_hang.sh \
+ sndrcv_udp_nonstdpt_v6.sh \
+ asynwr_simple.sh \
+ asynwr_simple_2.sh \
+ asynwr_timeout.sh \
+ asynwr_timeout_2.sh \
+ asynwr_small.sh \
+ asynwr_tinybuf.sh \
+ wr_large_async.sh \
+ wr_large_sync.sh \
+ asynwr_deadlock.sh \
+ asynwr_deadlock_2.sh \
+ asynwr_deadlock2.sh \
+ asynwr_deadlock4.sh \
+ asynwr_dynfile_flushtxend-off.sh \
+ abort-uncleancfg-goodcfg.sh \
+ abort-uncleancfg-goodcfg-check.sh \
+ abort-uncleancfg-badcfg-check.sh \
+ abort-uncleancfg-badcfg-check_1.sh \
+ variable_leading_underscore.sh \
+ gzipwr_hup_multi_file.sh \
+ gzipwr_hup_single_file.sh \
+ gzipwr_rscript.sh \
+ gzipwr_flushInterval.sh \
+ gzipwr_flushOnTXEnd.sh \
+ gzipwr_large.sh \
+ gzipwr_large_dynfile.sh \
+ gzipwr_hup.sh \
+ dynfile_invld_async.sh \
+ dynfile_invld_sync.sh \
+ dynfile_invalid2.sh \
+ complex1.sh \
+ queue-persist.sh \
+ pipeaction.sh \
+ execonlyonce.sh \
+ execonlywhenprevsuspended.sh \
+ execonlywhenprevsuspended2.sh \
+ execonlywhenprevsuspended3.sh \
+ execonlywhenprevsuspended4.sh \
+ execonlywhenprevsuspended_multiwrkr.sh \
+ execonlywhenprevsuspended-queue.sh \
+ execonlywhenprevsuspended-nonsusp.sh \
+ execonlywhenprevsuspended-nonsusp-queue.sh \
+ pipe_noreader.sh \
+ dircreate_dflt.sh \
+ dircreate_off.sh \
+ imuxsock_legacy.sh \
+ imuxsock_logger.sh \
+ imuxsock_logger_ratelimit.sh \
+ imuxsock_logger_ruleset.sh \
+ imuxsock_logger_ruleset_ratelimit.sh \
+ imuxsock_logger_err.sh \
+ imuxsock_logger_parserchain.sh \
+ imuxsock_traillf.sh \
+ imuxsock_ccmiddle.sh \
+ imuxsock_logger_syssock.sh \
+ imuxsock_traillf_syssock.sh \
+ imuxsock_ccmiddle_syssock.sh \
+ discard-rptdmsg.sh \
+ discard-allmark.sh \
+ discard.sh \
+ stop.sh \
+ failover-async.sh \
+ failover-double.sh \
+ failover-basic.sh \
+ failover-rptd.sh \
+ failover-no-rptd.sh \
+ failover-no-basic.sh \
+ suspend-via-file.sh \
+ suspend-omfwd-via-file.sh \
+ externalstate-failed-rcvr.sh \
+ rcvr_fail_restore.sh \
+ rscript_contains.sh \
+ rscript_bare_var_root.sh \
+ rscript_bare_var_root-empty.sh \
+ rscript_ipv42num.sh \
+ rscript_field.sh \
+ rscript_stop.sh \
+ rscript_stop2.sh \
+ rscript_prifilt.sh \
+ rscript_optimizer1.sh \
+ rscript_ruleset_call.sh \
+ rscript_ruleset_call_indirect-basic.sh \
+ rscript_ruleset_call_indirect-var.sh \
+ rscript_ruleset_call_indirect-invld.sh \
+ rscript_set_unset_invalid_var.sh \
+ rscript_set_modify.sh \
+ rscript_unaffected_reset.sh \
+ rscript_replace_complex.sh \
+ rscript_wrap2.sh \
+ rscript_wrap3.sh \
+ rscript_re_extract_i.sh \
+ rscript_re_extract.sh \
+ rscript_re_match_i.sh \
+ rscript_re_match.sh \
+ rscript_re_match-dbl_quotes.sh \
+ rscript_eq.sh \
+ rscript_eq_var.sh \
+ rscript_ge.sh \
+ rscript_ge_var.sh \
+ rscript_gt.sh \
+ rscript_gt_var.sh \
+ rscript_le.sh \
+ rscript_le_var.sh \
+ rscript_lt.sh \
+ rscript_lt_var.sh \
+ rscript_ne.sh \
+ rscript_ne_var.sh \
+ rscript_number_comparison_LE.sh \
+ rscript_number_comparison_LT.sh \
+ rscript_compare_str-numstr.sh \
+ rscript_compare_str-num.sh \
+ rscript_compare_numstr-str.sh \
+ rscript_compare_num-str.sh \
+ rscript_compare_numstr-numstr.sh \
+ rscript_compare_numstr-num.sh \
+ rscript_compare_num-numstr.sh \
+ rscript_compare_num-num.sh \
+ rscript_compare_str-str.sh \
+ rscript_num2ipv4.sh \
+ rscript_int2Hex.sh \
+ rscript_trim.sh \
+ rscript_substring.sh \
+ rscript_format_time.sh \
+ rscript_parse_time.sh \
+ rscript_is_time.sh \
+ rscript_script_error.sh \
+ rscript_parse_json.sh \
+ rscript_previous_action_suspended.sh \
+ rscript_str2num_negative.sh \
+ rscript_exists-yes.sh \
+ rscript_exists-yes2.sh \
+ rscript_exists-not1.sh \
+ rscript_exists-not2.sh \
+ rscript_exists-not3.sh \
+ rscript_exists-not4.sh \
+ rscript-config_enable-on.sh \
+ rscript_get_property.sh \
+ config_output-o-option.sh \
+ rs-cnum.sh \
+ rs-substring.sh \
+ rs-int2hex.sh \
+ empty-prop-comparison.sh \
+ rs_optimizer_pri.sh \
+ cee_simple.sh \
+ cee_diskqueue.sh \
+ incltest.sh \
+ incltest_dir.sh \
+ incltest_dir_wildcard.sh \
+ incltest_dir_empty_wildcard.sh \
+ linkedlistqueue.sh \
+ lookup_table.sh \
+ lookup_table-hup-backgrounded.sh \
+ lookup_table_no_hup_reload.sh \
+ key_dereference_on_uninitialized_variable_space.sh \
+ array_lookup_table.sh \
+ sparse_array_lookup_table.sh \
+ lookup_table_bad_configs.sh \
+ lookup_table_rscript_reload.sh \
+ lookup_table_rscript_reload_without_stub.sh \
+ config_multiple_include.sh \
+ include-obj-text-from-file.sh \
+ include-obj-text-from-file-noexist.sh \
+ multiple_lookup_tables.sh \
+ parsertest-parse1.sh \
+ parsertest-parse1-udp.sh \
+ parsertest-parse2.sh \
+ parsertest-parse2-udp.sh \
+ parsertest-parse_8bit_escape.sh \
+ parsertest-parse_8bit_escape-udp.sh \
+ parsertest-parse3.sh \
+ parsertest-parse3-udp.sh \
+ parsertest-parse_invld_regex.sh \
+ parsertest-parse_invld_regex-udp.sh \
+ parsertest-parse-3164-buggyday.sh \
+ parsertest-parse-3164-buggyday-udp.sh \
+ parsertest-parse-nodate.sh \
+ parsertest-parse-nodate-udp.sh \
+ parsertest-snare_ccoff_udp.sh \
+ parsertest-snare_ccoff_udp2.sh
+
+if ENABLE_LIBZSTD
+TESTS += \
+ zstd.sh
+if HAVE_VALGRIND
+TESTS += \
+ zstd-vg.sh
+endif # if HAVE_VALGRIND
+endif
+
+if ENABLE_LIBGCRYPT
+TESTS += \
+ queue-encryption-disk.sh \
+ queue-encryption-disk_keyfile.sh \
+ queue-encryption-disk_keyprog.sh \
+ queue-encryption-da.sh
+endif # ENABLE_LIBGCRYPT
+if HAVE_VALGRIND
+TESTS += \
+ omusrmsg-noabort-vg.sh \
+ omfile_hup-vg.sh \
+ gzipwr_hup-vg.sh \
+ tcpflood_wrong_option_output.sh \
+ imtcp-octet-framing-too-long-vg.sh \
+ smtradfile-vg.sh \
+ dnscache-TTL-0-vg.sh \
+ include-obj-outside-control-flow-vg.sh \
+ include-obj-in-if-vg.sh \
+ include-obj-text-vg.sh \
+ rscript_parse_json-vg.sh \
+ rscript_backticks-vg.sh \
+ rscript_backticks_empty_envvar-vg.sh \
+ rscript-config_enable-off-vg.sh \
+ rscript_get_property-vg.sh \
+ prop-jsonmesg-vg.sh \
+ mmexternal-InvldProg-vg.sh \
+ internal-errmsg-memleak-vg.sh \
+ glbl-oversizeMsg-log-vg.sh \
+ rscript_set_memleak-vg.sh \
+ no-parser-vg.sh \
+ discard-rptdmsg-vg.sh \
+ discard-allmark-vg.sh \
+ failover-basic-vg.sh \
+ failover-rptd-vg.sh \
+ failover-no-basic-vg.sh \
+ failover-no-rptd-vg.sh \
+ timereported-utc-vg.sh \
+ udp-msgreduc-vg.sh \
+ udp-msgreduc-orgmsg-vg.sh \
+ tcp-msgreduc-vg.sh \
+ rscript_field-vg.sh \
+ rscript_number_comparison_LE-vg.sh \
+ rscript_compare_str-str-vg.sh \
+ rscript_compare_str-num-vg.sh \
+ rscript_compare_str-numstr-vg.sh \
+ rscript_compare_num-str-vg.sh \
+ rscript_compare_numstr-str-vg.sh \
+ rscript_compare_numstr-num-vg.sh \
+ rscript_compare_numstr-numstr-vg.sh \
+ rscript_compare_num-num-vg.sh \
+ rscript_compare_num-numstr-vg.sh \
+ unused_lookup_table-vg.sh \
+ lookup_table-vg.sh \
+ lookup_table_no_hup_reload-vg.sh \
+ array_lookup_table-vg.sh \
+ array_lookup_table_misuse-vg.sh \
+ sparse_array_lookup_table-vg.sh \
+ lookup_table_bad_configs-vg.sh \
+ lookup_table_rscript_reload-vg.sh \
+ lookup_table_rscript_reload_without_stub-vg.sh \
+ multiple_lookup_tables-vg.sh \
+ fac_local0-vg.sh \
+ badqi.sh \
+ threadingmq.sh \
+ threadingmqaq.sh \
+ func-substring-invld-startpos-vg.sh \
+ rscript_trim-vg.sh
+if ENABLE_LIBGCRYPT
+TESTS += \
+ queue-encryption-disk_keyfile-vg.sh
+endif # ENABLE_LIBGCRYPT
+endif # HAVE_VALGRIND
+endif # ENABLE_DEFAULT_TESTS
+
+if ENABLE_SNMP
+TESTS += \
+ omsnmp_errmsg_no_params.sh
+if ENABLE_SNMP_TESTS
+TESTS += \
+ sndrcv_omsnmpv1_udp.sh \
+ sndrcv_omsnmpv1_udp_dynsource.sh \
+ sndrcv_omsnmpv1_udp_invalidoid.sh
+endif # if ENABLE_SNMP_TESTS
+endif # if ENABLE_SNMP
+
+if ENABLE_MMUTF8FIX
+TESTS += \
+ mmutf8fix_no_error.sh
+endif # if ENABLE_MAIL
+
+if ENABLE_MAIL
+TESTS += \
+ ommail_errmsg_no_params.sh
+endif # if ENABLE_MAIL
+
+if ENABLE_MMANON
+TESTS += \
+ mmanon_with_debug.sh \
+ mmanon_random_32_ipv4.sh \
+ mmanon_random_cons_32_ipv4.sh \
+ mmanon_recognize_ipv4.sh \
+ mmanon_zero_12_ipv4.sh \
+ mmanon_zero_33_ipv4.sh \
+ mmanon_zero_8_ipv4.sh \
+ mmanon_simple_12_ipv4.sh \
+ mmanon_simple_33_ipv4.sh \
+ mmanon_simple_8_ipv4.sh \
+ mmanon_simple_mallformed_ipv4.sh \
+ mmanon_random_128_ipv6.sh \
+ mmanon_zero_128_ipv6.sh \
+ mmanon_zero_96_ipv6.sh \
+ mmanon_random_cons_128_ipv6.sh \
+ mmanon_zero_50_ipv6.sh \
+ mmanon_recognize_ipv6.sh \
+ mmanon_zero_64_ipv6.sh \
+ mmanon_both_modes_compatible.sh \
+ mmanon_recognize_ipembedded.sh \
+ mmanon_ipv6_port.sh \
+ mmanon_random_cons_128_ipembedded.sh
+endif # if ENABLE_MMANON
+
+if ENABLE_CLICKHOUSE_TESTS
+TESTS += \
+ clickhouse-start.sh \
+ clickhouse-basic.sh \
+ clickhouse-dflt-tpl.sh \
+ clickhouse-retry-error.sh \
+ clickhouse-load.sh \
+ clickhouse-bulk.sh \
+ clickhouse-bulk-load.sh \
+ clickhouse-limited-batch.sh \
+ clickhouse-select.sh \
+ clickhouse-errorfile.sh \
+ clickhouse-wrong-quotation-marks.sh \
+ clickhouse-wrong-template-option.sh \
+ clickhouse-wrong-insert-syntax.sh
+
+clickhouse-basic.log: clickhouse-start.log
+clickhouse-dflt-tpl.log: clickhouse-basic.log
+clickhouse-retry-error.log: clickhouse-dflt-tpl.log
+clickhouse-load.log: clickhouse-retry-error.log
+clickhouse-bulk.log: clickhouse-load.log
+clickhouse-bulk-load.log: clickhouse-bulk.log
+clickhouse-limited-batch.log: clickhouse-bulk-load.log
+clickhouse-select.log: clickhouse-limited-batch.log
+clickhouse-errorfile.log: clickhouse-select.log
+clickhouse-wrong-quotation-marks.log: clickhouse-errorfile.log
+clickhouse-wrong-template-option.log: clickhouse-wrong-quotation-marks.log
+clickhouse-wrong-insert-syntax.log: clickhouse-wrong-template-option.log
+clickhouse-stop.log: clickhouse-wrong-insert-syntax.log
+
+if HAVE_VALGRIND
+TESTS += \
+ clickhouse-basic-vg.sh \
+ clickhouse-load-vg.sh \
+ clickhouse-bulk-vg.sh \
+ clickhouse-bulk-load-vg.sh
+
+clickhouse-basic-vg.log: clickhouse-wrong-insert-syntax.log
+clickhouse-load-vg.log: clickhouse-basic-vg.log
+clickhouse-bulk-vg.log: clickhouse-load-vg.log
+clickhouse-bulk-load-vg.log: clickhouse-bulk-vg.log
+clickhouse-stop.log: clickhouse-bulk-load-vg.log
+endif # VALGRIND
+
+TESTS += clickhouse-stop.sh
+endif # CLICKHOUSE_TESTS
+
+
+if ENABLE_LIBFAKETIME
+TESTS += \
+ now_family_utc.sh \
+ now-utc.sh \
+ now-utc-ymd.sh \
+ now-utc-casecmp.sh \
+ now-unixtimestamp.sh \
+ timegenerated-ymd.sh \
+ timegenerated-uxtimestamp.sh \
+ timegenerated-uxtimestamp-invld.sh \
+ timegenerated-dateordinal.sh \
+ timegenerated-dateordinal-invld.sh \
+ timegenerated-utc.sh \
+ timegenerated-utc-legacy.sh \
+ timereported-utc.sh \
+ timereported-utc-legacy.sh
+# now come faketime tests that utilize mmnormalize - aka "no endif here"
+if ENABLE_MMNORMALIZE
+TESTS += \
+ mmnormalize_processing_test1.sh \
+ mmnormalize_processing_test2.sh \
+ mmnormalize_processing_test3.sh \
+ mmnormalize_processing_test4.sh
+endif
+endif
+
+if ENABLE_PGSQL
+if ENABLE_PGSQL_TESTS
+TESTS += \
+ pgsql-basic.sh \
+ pgsql-basic-cnf6.sh \
+ pgsql-basic-threads-cnf6.sh \
+ pgsql-template.sh \
+ pgsql-template-cnf6.sh \
+ pgsql-actq-mt-withpause.sh \
+ pgsql-template-threads-cnf6.sh
+
+pgsql-basic-cnf6.log: pgsql-basic.log
+pgsql-basic-threads-cnf6.log: pgsql-basic-cnf6.log
+pgsql-template.log: pgsql-basic-threads-cnf6.log
+pgsql-template-cnf6.log: pgsql-template.log
+pgsql-actq-mt-withpause.log: pgsql-template-cnf6.log
+pgsql-template-threads-cnf6.log: pgsql-actq-mt-withpause.log
+if HAVE_VALGRIND
+TESTS += \
+ pgsql-basic-vg.sh \
+ pgsql-template-vg.sh \
+ pgsql-basic-cnf6-vg.sh \
+ pgsql-template-cnf6-vg.sh \
+ pgsql-actq-mt-withpause-vg.sh
+
+pgsql-basic-vg.log: pgsql-template-threads-cnf6.log
+pgsql-template-vg.log: pgsql-basic-vg.log
+pgsql-basic-cnf6-vg.log: pgsql-template-vg.log
+pgsql-template-cnf6-vg.log: pgsql-basic-cnf6-vg.log
+pgsql-actq-mt-withpause-vg.log: pgsql-template-cnf6-vg.log
+endif
+endif
+endif
+
+if ENABLE_MYSQL_TESTS
+TESTS += \
+ mysqld-start.sh \
+ mysql-basic.sh \
+ mysql-basic-cnf6.sh \
+ mysql-asyn.sh \
+ mysql-actq-mt.sh \
+ mysql-actq-mt-withpause.sh \
+ action-tx-single-processing.sh \
+ action-tx-errfile-maxsize.sh \
+ action-tx-errfile.sh
+
+mysql-basic.log: mysqld-start.log
+mysql-basic-cnf6.log: mysqld-start.log
+mysql-asyn.log: mysqld-start.log
+mysql-actq-mt.log: mysqld-start.log
+mysql-actq-mt-withpause.log: mysqld-start.log
+action-tx-single-processing.log: mysqld-start.log
+action-tx-errfile.log: mysqld-start.log
+
+mysqld-stop.log: mysql-basic.log \
+ mysql-basic-cnf6.log \
+ mysql-asyn.log \
+ mysql-actq-mt.log \
+ mysql-actq-mt-withpause.log \
+ action-tx-single-processing.log \
+ action-tx-errfile.log
+
+if HAVE_VALGRIND
+TESTS += \
+ mysql-basic-vg.sh \
+ mysql-asyn-vg.sh \
+ mysql-actq-mt-withpause-vg.sh
+mysql-basic-vg.log: mysqld-start.log
+mysql-asyn-vg.log: mysqld-start.log
+mysql-actq-mt-withpause-vg.log: mysqld-start.log
+
+mysqld-stop.log: mysql-basic-vg.log \
+ mysql-asyn-vg.log \
+ mysql-actq-mt-withpause-vg.log
+endif
+
+if ENABLE_OMLIBDBI # we piggy-back on MYSQL_TESTS as we need the same environment
+TESTS += \
+ libdbi-basic.sh \
+ libdbi-asyn.sh
+libdbi-basic.log: mysqld-start.log
+libdbi-asyn.log: mysqld-start.log
+mysqld-stop.log: libdbi-basic.log \
+ libdbi-asyn.log
+if HAVE_VALGRIND
+TESTS += \
+ libdbi-basic-vg.sh
+libdbi-basic-vg.log: mysqld-start.log
+mysqld-stop.log: libdbi-basic-vg.log
+endif
+endif
+TESTS += mysqld-stop.sh
+endif # MYSQL_TESTS
+
+if ENABLE_FMHTTP
+TESTS += \
+ rscript_http_request.sh
+if HAVE_VALGRIND
+TESTS += \
+ rscript_http_request-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_FMHTTP
+
+
+if ENABLE_ROOT_TESTS
+TESTS += \
+ sndrcv_udp.sh \
+ imuxsock_logger_root.sh \
+ imuxsock_traillf_root.sh \
+ imuxsock_ccmiddle_root.sh \
+ imklog_permitnonkernelfacility_root.sh
+if ENABLE_IP
+TESTS += tcp_forwarding_ns_tpl.sh
+endif
+if HAVE_VALGRIND
+TESTS += \
+ mmexternal-SegFault-empty-jroot-vg.sh
+endif
+endif
+
+if ENABLE_JOURNAL_TESTS
+if ENABLE_IMJOURNAL
+TESTS += \
+ imjournal-basic.sh \
+ imjournal-statefile.sh
+if HAVE_VALGRIND
+TESTS += \
+ imjournal-basic-vg.sh \
+ imjournal-statefile-vg.sh
+endif
+endif
+
+if ENABLE_OMJOURNAL
+TESTS += \
+ omjournal-abort-template.sh \
+ omjournal-abort-no-template.sh \
+ omjournal-basic-template.sh \
+ omjournal-basic-no-template.sh
+endif
+endif #if ENABLE_JOURNAL_TESTS
+
+if ENABLE_IMPROG
+TESTS += \
+ improg_errmsg_no_params.sh \
+ improg_prog_simple.sh \
+ improg_prog_confirm.sh \
+ improg_prog_confirm_killonclose.sh \
+ improg_prog_killonclose.sh \
+ improg_simple_multi.sh
+if HAVE_VALGRIND
+TESTS += \
+ improg_errmsg_no_params-vg.sh \
+ improg_prog_simple-vg.sh
+endif # ENABLE_IMPROG
+endif
+
+if ENABLE_MMDARWIN
+TESTS += \
+ mmdarwin_errmsg_no_params.sh \
+ mmdarwin_errmsg_no_sock.sh
+if HAVE_VALGRIND
+TESTS += \
+ mmdarwin_errmsg_no_sock-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_IMPROG
+
+if ENABLE_OMPROG
+TESTS += \
+ omprog-defaults.sh \
+ omprog-output-capture.sh \
+ omprog-output-capture-mt.sh \
+ omprog-feedback.sh \
+ omprog-feedback-mt.sh \
+ omprog-feedback-timeout.sh \
+ omprog-close-unresponsive.sh \
+ omprog-close-unresponsive-noterm.sh \
+ omprog-restart-terminated.sh \
+ omprog-restart-terminated-outfile.sh \
+ omprog-single-instance.sh \
+ omprog-single-instance-outfile.sh \
+ omprog-transactions.sh \
+ omprog-if-error.sh \
+ omprog-transactions-failed-messages.sh \
+ omprog-transactions-failed-commits.sh
+if HAVE_VALGRIND
+TESTS += \
+ omprog-defaults-vg.sh \
+ omprog-output-capture-vg.sh \
+ omprog-feedback-vg.sh \
+ omprog-close-unresponsive-vg.sh \
+ omprog-restart-terminated-vg.sh \
+ omprog-single-instance-vg.sh \
+ omprog-transactions-vg.sh
+endif
+endif
+
+if ENABLE_OMHTTP
+TESTS += \
+ omhttp-auth.sh \
+ omhttp-basic.sh \
+ omhttp-batch-fail-with-400.sh \
+ omhttp-batch-jsonarray-compress.sh \
+ omhttp-batch-jsonarray-retry.sh \
+ omhttp-batch-jsonarray.sh \
+ omhttp-batch-kafkarest-retry.sh \
+ omhttp-batch-kafkarest.sh \
+ omhttp-batch-lokirest-retry.sh \
+ omhttp-batch-lokirest.sh \
+ omhttp-batch-newline.sh \
+ omhttp-retry.sh \
+ omhttp-httpheaderkey.sh \
+ omhttp-multiplehttpheaders.sh \
+ omhttp-dynrestpath.sh \
+ omhttp-batch-dynrestpath.sh
+if HAVE_VALGRIND
+TESTS += \
+ omhttp-auth-vg.sh \
+ omhttp-basic-vg.sh \
+ omhttp-batch-jsonarray-compress-vg.sh \
+ omhttp-batch-jsonarray-retry-vg.sh \
+ omhttp-batch-jsonarray-vg.sh \
+ omhttp-batch-kafkarest-retry-vg.sh \
+ omhttp-batch-lokirest-retry-vg.sh \
+ omhttp-retry-vg.sh \
+ omhttp-batch-lokirest-vg.sh
+endif
+endif
+
+if ENABLE_OMKAFKA
+if ENABLE_IMKAFKA
+if ENABLE_KAFKA_TESTS
+TESTS += \
+ kafka-selftest.sh \
+ omkafka.sh \
+ omkafkadynakey.sh \
+ imkafka.sh \
+ imkafka-backgrounded.sh \
+ imkafka-config-err-ruleset.sh \
+ imkafka-config-err-param.sh \
+ imkafka-hang-on-no-kafka.sh \
+ imkafka-hang-other-action-on-no-kafka.sh \
+ imkafka_multi_single.sh \
+ imkafka_multi_group.sh \
+ sndrcv_kafka.sh \
+ sndrcv_kafka_multi_topics.sh
+# Tests below need to be stable first!
+# sndrcv_kafka_fail.sh \
+# sndrcv_kafka_failresume.sh \
+# needs properly to much mempory on arm devices!
+# sndrcv_kafka_multi.sh
+omkafka.log: kafka-selftest.log
+imkafka.log: omkafka.log
+imkafka-backgrounded.log: imkafka.log
+imkafka-config-err-ruleset.log: imkafka-backgrounded.log
+imkafka-config-err-param.log: imkafka-config-err-ruleset.log
+imkafka-hang-on-no-kafka.log: imkafka-config-err-param.log
+imkafka-hang-other-action-on-no-kafka.log: imkafka-hang-on-no-kafka.log
+imkafka_multi_single.log: imkafka-hang-other-action-on-no-kafka.log
+sndrcv_kafka.log: imkafka_multi_single.log
+imkafka_multi_group.log: sndrcv_kafka.log
+sndrcv_kafka_multi_topics.log: imkafka_multi_group.log
+omkafkadynakey.log: sndrcv_kafka_multi_topics.log
+
+if HAVE_VALGRIND
+TESTS += \
+ omkafka-vg.sh \
+ imkafka-vg.sh
+
+omkafka-vg.log: sndrcv_kafka_multi_topics.log
+imkafka-vg.log: omkafka-vg.log
+endif
+endif
+endif
+endif
+
+if ENABLE_OMAZUREEVENTHUBS
+if ENABLE_OMAZUREEVENTHUBS_TESTS
+TESTS += \
+ omazureeventhubs-basic.sh \
+ omazureeventhubs-list.sh \
+ omazureeventhubs-stress.sh \
+ omazureeventhubs-interrupt.sh
+if HAVE_VALGRIND
+TESTS += \
+ omazureeventhubs-basic-vg.sh \
+ omazureeventhubs-interrupt-vg.sh
+endif
+endif
+endif
+
+if ENABLE_IMDOCKER
+if ENABLE_IMDOCKER_TESTS
+TESTS += \
+ imdocker-basic.sh \
+ imdocker-long-logline.sh \
+ imdocker-new-logs-from-start.sh \
+ imdocker-multi-line.sh
+if HAVE_VALGRIND
+TESTS += \
+ imdocker-basic-vg.sh \
+ imdocker-long-logline-vg.sh \
+ imdocker-new-logs-from-start-vg.sh \
+ imdocker-multi-line-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_IMDOCKER_TESTS
+endif # ENABLE_IMDOCKER
+
+if ENABLE_IMHTTP
+TESTS += \
+ imhttp-post-payload.sh \
+ imhttp-post-payload-basic-auth.sh \
+ imhttp-post-payload-query-params.sh \
+ imhttp-post-payload-large.sh \
+ imhttp-post-payload-multi.sh \
+ imhttp-post-payload-multi-lf.sh \
+ imhttp-post-payload-compress.sh \
+ imhttp-getrequest-file.sh
+if HAVE_VALGRIND
+TESTS += \
+ imhttp-post-payload-vg.sh \
+ imhttp-post-payload-basic-auth-vg.sh \
+ imhttp-post-payload-query-params-vg.sh \
+ imhttp-post-payload-large-vg.sh \
+ imhttp-post-payload-multi-vg.sh \
+ imhttp-post-payload-multi-lf-vg.sh \
+ imhttp-post-payload-compress-vg.sh \
+ imhttp-getrequest-file-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_IMHTTP
+
+if ENABLE_OMRABBITMQ
+check_PROGRAMS += miniamqpsrvr
+miniamqpsrvr_SOURCES = miniamqpsrvr.c
+miniamqpsrvr_CPPFLAGS = $(PTHREADS_CFLAGS) $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS)
+miniamqpsrvr_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS)
+
+TESTS += \
+ omrabbitmq_no_params.sh \
+ omrabbitmq_params_missing0.sh \
+ omrabbitmq_params_missing1.sh \
+ omrabbitmq_params_missing2.sh \
+ omrabbitmq_params_invalid0.sh \
+ omrabbitmq_params_invalid1.sh \
+ omrabbitmq_params_invalid2.sh \
+ omrabbitmq_params_invalid3.sh \
+ omrabbitmq_data_1server.sh \
+ omrabbitmq_data_2servers.sh \
+ omrabbitmq_error_server0.sh \
+ omrabbitmq_error_server1.sh \
+ omrabbitmq_error_server2.sh \
+ omrabbitmq_error_server3.sh \
+ omrabbitmq_json.sh \
+ omrabbitmq_raw.sh
+if HAVE_VALGRIND
+TESTS += \
+ omrabbitmq_data_1server-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_OMRABBITMQ
+
+if ENABLE_REDIS_TESTS
+if ENABLE_IMHIREDIS
+TESTS += \
+ imhiredis-queue.sh \
+ imhiredis-queue-lpop.sh \
+ imhiredis-redis-restart.sh \
+ imhiredis-redis-start-after.sh \
+ imhiredis-subscribe.sh \
+ imhiredis-stream.sh \
+ imhiredis-stream-from-beginning.sh \
+ imhiredis-stream-consumerGroup-ack.sh \
+ imhiredis-stream-consumerGroup-noack.sh \
+ imhiredis-stream-consumerGroup-reclaim.sh
+if HAVE_VALGRIND
+TESTS += \
+ imhiredis-queue-vg.sh \
+ imhiredis-queue-lpop-vg.sh \
+ imhiredis-redis-restart-vg.sh \
+ imhiredis-redis-start-after-vg.sh \
+ imhiredis-subscribe-vg.sh \
+ imhiredis-stream-vg.sh \
+ imhiredis-stream-from-beginning-vg.sh \
+ imhiredis-stream-consumerGroup-ack-vg.sh \
+ imhiredis-stream-consumerGroup-noack-vg.sh \
+ imhiredis-stream-consumerGroup-reclaim-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_IMHIREDIS
+
+if ENABLE_OMHIREDIS
+TESTS += \
+ mmdb-reload.sh \
+ omhiredis-dynakey.sh \
+ omhiredis-publish.sh \
+ omhiredis-queue-rpush.sh \
+ omhiredis-queue.sh \
+ omhiredis-set.sh \
+ omhiredis-setex.sh \
+ omhiredis-template.sh \
+ omhiredis-withpass.sh \
+ omhiredis-wrongpass.sh \
+ omhiredis-stream-ack.sh \
+ omhiredis-stream-capped.sh \
+ omhiredis-stream-del.sh \
+ omhiredis-stream-dynack.sh \
+ omhiredis-stream-outfield.sh \
+ omhiredis-stream.sh
+if HAVE_VALGRIND
+TESTS += \
+ mmdb-reload-vg.sh \
+ omhiredis-dynakey-vg.sh \
+ omhiredis-publish-vg.sh \
+ omhiredis-queue-rpush-vg.sh \
+ omhiredis-queue-vg.sh \
+ omhiredis-set-vg.sh \
+ omhiredis-setex-vg.sh \
+ omhiredis-template-vg.sh \
+ omhiredis-withpass-vg.sh \
+ omhiredis-wrongpass-vg.sh \
+ omhiredis-stream-ack-vg.sh \
+ omhiredis-stream-capped-vg.sh \
+ omhiredis-stream-del-vg.sh \
+ omhiredis-stream-dynack-vg.sh \
+ omhiredis-stream-outfield-vg.sh \
+ omhiredis-stream-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_OMHIREDIS
+endif # ENABLE_REDIS_TESTS
+
+if ENABLE_IMPSTATS
+TESTS += \
+ impstats-hup.sh \
+ perctile-simple.sh \
+ dynstats.sh \
+ dynstats_overflow.sh \
+ dynstats_reset.sh \
+ dynstats_ctr_reset.sh \
+ dynstats_nometric.sh \
+ no-dynstats-json.sh \
+ no-dynstats.sh \
+ stats-json.sh \
+ dynstats-json.sh \
+ stats-cee.sh \
+ stats-json-es.sh \
+ dynstats_reset_without_pstats_reset.sh \
+ dynstats_prevent_premature_eviction.sh \
+ omfwd_fast_imuxsock.sh \
+ omfwd_impstats-udp.sh \
+ omfwd_impstats-tcp.sh
+if HAVE_VALGRIND
+TESTS += \
+ perctile-simple-vg.sh \
+ dynstats-vg.sh \
+ dynstats_reset-vg.sh \
+ dynstats_overflow-vg.sh \
+ dynstats-json-vg.sh \
+ stats-json-vg.sh \
+ stats-cee-vg.sh \
+ dynstats_prevent_premature_eviction-vg.sh
+endif
+endif
+
+if ENABLE_IMPTCP
+# note that some tests simply USE imptcp, but they also
+# need to be disabled if we do not have this module
+TESTS += \
+ manyptcp.sh \
+ imptcp_framing_regex.sh \
+ imptcp_framing_regex-oversize.sh \
+ imptcp_large.sh \
+ imptcp-connection-msg-disabled.sh \
+ imptcp-connection-msg-received.sh \
+ imptcp-discard-truncated-msg.sh \
+ imptcp_addtlframedelim.sh \
+ imptcp_conndrop.sh \
+ imptcp_no_octet_counted.sh \
+ imptcp_multi_line.sh \
+ imptcp_spframingfix.sh \
+ imptcp_maxsessions.sh \
+ imptcp_nonProcessingPoller.sh \
+ imptcp_veryLargeOctateCountedMessages.sh \
+ imptcp-basic-hup.sh \
+ imptcp-NUL.sh \
+ imptcp-NUL-rawmsg.sh \
+ rscript_random.sh \
+ rscript_hash32.sh \
+ rscript_hash64.sh \
+ rscript_replace.sh \
+ omfile-sizelimitcmd-many.sh \
+ omfile-outchannel-many.sh
+if HAVE_VALGRIND
+TESTS += \
+ imptcp-octet-framing-too-long-vg.sh \
+ imptcp_conndrop-vg.sh
+if ENABLE_FMHASH
+TESTS += \
+ rscript_hash32-vg.sh \
+ rscript_hash64-vg.sh
+endif # ENABLE_FMHASH
+endif # HAVE_VALGRIND
+if ENABLE_FMUNFLATTEN
+TESTS += \
+ rscript_unflatten_arg1_unsuitable.sh \
+ rscript_unflatten_arg2_invalid.sh \
+ rscript_unflatten_conflict1.sh \
+ rscript_unflatten_conflict2.sh \
+ rscript_unflatten_conflict3.sh \
+ rscript_unflatten_key_truncated.sh \
+ rscript_unflatten_non_object.sh \
+ rscript_unflatten_object.sh \
+ rscript_unflatten_object_exclamation.sh
+if HAVE_VALGRIND
+TESTS += \
+ rscript_unflatten_arg1_unsuitable-vg.sh \
+ rscript_unflatten_arg2_invalid-vg.sh \
+ rscript_unflatten_conflict1-vg.sh \
+ rscript_unflatten_conflict2-vg.sh \
+ rscript_unflatten_conflict3-vg.sh \
+ rscript_unflatten_key_truncated-vg.sh \
+ rscript_unflatten_non_object-vg.sh \
+ rscript_unflatten_object-vg.sh \
+ rscript_unflatten_object_exclamation-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_FMUNFLATTEN
+if ENABLE_FFAUP
+TESTS += \
+ rscript_faup_all.sh \
+ rscript_faup_all_2.sh \
+ rscript_faup_all_empty.sh \
+ rscript_faup_scheme.sh \
+ rscript_faup_credential.sh \
+ rscript_faup_subdomain.sh \
+ rscript_faup_domain.sh \
+ rscript_faup_domain_without_tld.sh \
+ rscript_faup_host.sh \
+ rscript_faup_tld.sh \
+ rscript_faup_port.sh \
+ rscript_faup_resource_path.sh \
+ rscript_faup_query_string.sh \
+ rscript_faup_fragment.sh \
+ rscript_faup_mozilla_tld.sh
+if HAVE_VALGRIND
+TESTS += \
+ rscript_faup_all_vg.sh \
+ rscript_faup_all_2_vg.sh \
+ rscript_faup_all_empty_vg.sh \
+ rscript_faup_scheme_vg.sh \
+ rscript_faup_credential_vg.sh \
+ rscript_faup_subdomain_vg.sh \
+ rscript_faup_domain_vg.sh \
+ rscript_faup_domain_without_tld_vg.sh \
+ rscript_faup_host_vg.sh \
+ rscript_faup_tld_vg.sh \
+ rscript_faup_port_vg.sh \
+ rscript_faup_resource_path_vg.sh \
+ rscript_faup_query_string_vg.sh \
+ rscript_faup_fragment_vg.sh \
+ rscript_faup_mozilla_tld_vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_FFAUP
+endif
+
+if ENABLE_MMPSTRUCDATA
+TESTS += \
+ mmpstrucdata.sh \
+ mmpstrucdata-escaping.sh \
+ mmpstrucdata-case.sh
+if HAVE_VALGRIND
+TESTS += \
+ mmpstrucdata-vg.sh \
+ mmpstrucdata-invalid-vg.sh
+endif
+endif
+
+if ENABLE_MMRM1STSPACE
+TESTS += \
+ mmrm1stspace-basic.sh
+endif
+
+if ENABLE_PMNULL
+TESTS += \
+ pmnull-basic.sh \
+ pmnull-withparams.sh
+endif
+
+if ENABLE_OMSTDOUT
+TESTS += \
+ omstdout-basic.sh
+endif
+
+if ENABLE_PMNORMALIZE
+TESTS += \
+ pmnormalize-basic.sh \
+ pmnormalize-invld-rulebase.sh \
+ pmnormalize-rule.sh \
+ pmnormalize-rule_and_rulebase.sh \
+ pmnormalize-neither_rule_rulebase.sh \
+ pmnormalize-rule_invld-data.sh
+if HAVE_VALGRIND
+TESTS += \
+ pmnormalize-basic-vg.sh \
+ pmnormalize-invld-rulebase-vg.sh \
+ pmnormalize-rule-vg.sh \
+ pmnormalize-rule_and_rulebase-vg.sh \
+ pmnormalize-neither_rule_rulebase-vg.sh \
+ pmnormalize-rule_invld-data-vg.sh
+endif
+endif
+
+if ENABLE_MMNORMALIZE
+TESTS += msgvar-concurrency-array.sh \
+ msgvar-concurrency-array-event.tags.sh \
+ mmnormalize_rule_from_string.sh \
+ mmnormalize_rule_from_array.sh \
+ mmnormalize_parsesuccess.sh
+
+if HAVE_VALGRIND
+TESTS += \
+ mmnormalize_parsesuccess-vg.sh
+endif
+
+if ENABLE_IMPTCP
+TESTS += \
+ mmnormalize_regex_defaulted.sh \
+ mmnormalize_regex_disabled.sh \
+ mmnormalize_variable.sh \
+ mmnormalize_tokenized.sh
+endif
+
+if LOGNORM_REGEX_SUPPORTED
+TESTS += \
+ mmnormalize_regex.sh
+endif
+endif # ENABLE_MMNORMALIZE
+
+if ENABLE_MMJSONPARSE
+TESTS += \
+ mmjsonparse-w-o-cookie.sh \
+ mmjsonparse-w-o-cookie-multi-spaces.sh
+if ENABLE_IMPSTATS
+TESTS += \
+ mmjsonparse-invalid-containerName.sh \
+ wtpShutdownAll-assertionFailure.sh
+endif
+if ENABLE_IMPTCP
+TESTS += \
+ mmjsonparse_simple.sh \
+ imptcp-oversize-message-display.sh \
+ imptcp-msg-truncation-on-number.sh \
+ imptcp-msg-truncation-on-number2.sh \
+ imptcp-maxFrameSize-parameter.sh \
+ mmjsonparse_cim.sh \
+ mmjsonparse_cim2.sh \
+ mmjsonparse_localvar.sh \
+ json_array_subscripting.sh \
+ json_array_looping.sh \
+ json_object_looping.sh \
+ json_nonarray_looping.sh
+endif
+if HAVE_VALGRIND
+TESTS += \
+ mmjsonparse_extra_data-vg.sh \
+ json_null_array-vg.sh \
+ json_object_looping-vg.sh \
+ json_array_looping-vg.sh \
+ json_object_suicide_in_loop-vg.sh \
+ json_null-vg.sh
+endif
+TESTS += \
+ stop_when_array_has_element.sh \
+ json_null_array.sh \
+ json_null.sh \
+ json_var_cmpr.sh \
+ json_var_case.sh
+endif
+
+if ENABLE_MMDBLOOKUP
+TESTS += \
+ mmdb.sh \
+ mmdb-space.sh \
+ mmdb-container.sh \
+ mmdb-container-empty.sh
+if HAVE_VALGRIND
+TESTS += \
+ mmdb-vg.sh \
+ mmdb-multilevel-vg.sh
+endif
+endif
+
+if ENABLE_GNUTLS_TESTS
+TESTS += \
+ imtcp-tls-basic.sh \
+ imtcp-tls-input-basic.sh \
+ imtcp-tls-input-2certs.sh \
+ imtcp-tls-basic-verifydepth.sh \
+ imtcp_conndrop_tls.sh \
+ sndrcv_tls_anon_rebind.sh \
+ sndrcv_tls_anon_hostname.sh \
+ sndrcv_tls_anon_ipv4.sh \
+ sndrcv_tls_anon_ipv6.sh \
+ sndrcv_tls_certless_clientonly.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh \
+ sndrcv_tls_gtls_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_priorityString.sh \
+ sndrcv_tls_certvalid.sh \
+ sndrcv_tls_certvalid_action_level.sh \
+ sndrcv_tls_certvalid_expired.sh \
+ sndrcv_tls_certvalid_expired_defaultmode.sh \
+ sndrcv_tls_certvalid_revoked.sh \
+ sndrcv_tls_client_missing_cert.sh \
+ imtcp-tls-no-lstn-startup.sh \
+ imtcp-tls-gtls-x509fingerprint-invld.sh \
+ imtcp-tls-gtls-x509fingerprint.sh \
+ imtcp-tls-gtls-x509name-invld.sh \
+ imtcp-tls-gtls-x509name.sh \
+ imtcp-tls-gtls-x509name-legacy.sh \
+ imtcp-drvr-in-input-basic.sh \
+ imtcp-multi-drvr-basic.sh \
+ imtcp-multi-drvr-basic-parallel.sh
+if HAVE_VALGRIND
+TESTS += \
+ imtcp-tls-basic-vg.sh \
+ imtcp_conndrop_tls-vg.sh \
+ manytcp-too-few-tls-vg.sh
+endif
+if ENABLE_OPENSSL
+TESTS += \
+ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh
+endif
+endif
+
+if ENABLE_OPENSSL
+TESTS += \
+ imtcp-tls-ossl-basic.sh \
+ imtcp-tls-ossl-input-basic.sh \
+ imtcp-tls-ossl-input-2certs.sh \
+ imtcp-tls-ossl-basic-tlscommands.sh \
+ imtcp-tls-ossl-basic-verifydepth.sh \
+ imtcp-tls-ossl-invalid-verifydepth.sh \
+ sndrcv_tls_ossl_anon_ipv4.sh \
+ sndrcv_tls_ossl_anon_ipv6.sh \
+ sndrcv_tls_ossl_anon_rebind.sh \
+ sndrcv_tls_ossl_anon_ciphers.sh \
+ sndrcv_tls_ossl_serveranon_ossl_clientanon.sh \
+ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \
+ sndrcv_tls_ossl_certvalid.sh \
+ sndrcv_tls_ossl_certvalid_action_level.sh \
+ sndrcv_tls_ossl_certvalid_expired.sh \
+ sndrcv_tls_ossl_certvalid_tlscommand.sh \
+ sndrcv_tls_ossl_certvalid_ciphers.sh \
+ sndrcv_tls_ossl_certvalid_revoked.sh \
+ imtcp-tls-ossl-x509valid.sh \
+ imtcp-tls-ossl-x509name.sh \
+ imtcp-tls-ossl-x509fingerprint.sh \
+ imtcp-tls-ossl-error-ca.sh \
+ imtcp-tls-ossl-error-cert.sh \
+ imtcp-tls-ossl-error-key.sh \
+ imtcp-tls-ossl-error-key2.sh
+if HAVE_VALGRIND
+TESTS += \
+ imtcp-tls-ossl-basic-vg.sh \
+ imtcp-tls-ossl-basic-brokenhandshake-vg.sh
+endif
+endif
+
+if ENABLE_GNUTLS_TESTS
+if ENABLE_OPENSSL
+TESTS += \
+ sndrcv_tls_ossl_servercert_gtls_clientanon.sh \
+ sndrcv_tls_ossl_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_ossl_clientanon.sh \
+ sndrcv_tls_gtls_serveranon_ossl_clientanon.sh
+endif
+endif
+
+if ENABLE_OMUXSOCK
+TESTS += uxsock_simple.sh
+endif
+
+if ENABLE_RELP
+TESTS += sndrcv_relp.sh \
+ sndrcv_relp_rebind.sh \
+ omrelp_errmsg_no_connect.sh \
+ imrelp-basic.sh \
+ imrelp-basic-oldstyle.sh \
+ imrelp-basic-hup.sh \
+ imrelp-manyconn.sh \
+ imrelp-maxDataSize-error.sh \
+ imrelp-long-msg.sh \
+ imrelp-oversizeMode-truncate.sh \
+ imrelp-oversizeMode-accept.sh \
+ imrelp-invld-tlslib.sh \
+ imrelp-bigmessage.sh \
+ omrelp-invld-tlslib.sh \
+ sndrcv_relp_dflt_pt.sh \
+ glbl-oversizeMsg-log.sh \
+ glbl-oversizeMsg-truncate.sh \
+ glbl-oversizeMsg-split.sh
+if ENABLE_GNUTLS
+TESTS += \
+ sndrcv_relp_tls.sh \
+ sndrcv_relp_tls_certvalid.sh \
+ sndrcv_tls_certvalid_action_level.sh \
+ sndrcv_relp_tls_prio.sh \
+ sndrcv_relp_tls_chainedcert.sh \
+ relp_tls_certificate_not_found.sh \
+ omrelp_wrong_authmode.sh \
+ imrelp-tls.sh \
+ imrelp-tls-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert2.sh
+if USE_RELPENGINESETTLSCFGCMD
+TESTS += \
+ imrelp-tls-cfgcmd.sh \
+ sndrcv_relp_tls-cfgcmd.sh
+endif # USE_RELPENGINESETTLSCFGCMD
+endif # ENABLE_GNUTLS
+if HAVE_VALGRIND
+TESTS += \
+ imrelp-basic-vg.sh \
+ imrelp-sessionbreak-vg.sh \
+ imrelp-manyconn-vg.sh \
+ sndrcv_relp-vg-rcvr.sh \
+ sndrcv_relp-vg-sender.sh
+endif # HAVE_VALGRIND
+endif
+
+if ENABLE_IMDTLS
+TESTS += \
+ imdtls-basic.sh \
+ imdtls-basic-tlscommands.sh \
+ imdtls-basic-timeout.sh \
+ imdtls-error-cert.sh \
+ imdtls-sessionbreak.sh
+if HAVE_VALGRIND
+TESTS += \
+ imdtls-basic-vg.sh \
+ imdtls-sessionbreak-vg.sh
+endif # HAVE_VALGRIND
+if ENABLE_OMDTLS
+TESTS += \
+ sndrcv_dtls_certvalid.sh \
+ sndrcv_dtls_anon_ciphers.sh \
+ sndrcv_dtls_certvalid_ciphers.sh \
+ sndrcv_dtls_certvalid_permitted.sh \
+ sndrcv_dtls_certvalid_missing.sh \
+ sndrcv_dtls_anon_ciphers.sh
+if HAVE_VALGRIND
+TESTS += \
+ sndrcv_dtls_certvalid-vg.sh
+endif # HAVE_VALGRIND
+endif # ENABLE_OMDTLS
+endif # ENABLE_IMDTLS
+
+if ENABLE_OMUDPSPOOF
+TESTS += \
+ omudpspoof_errmsg_no_params.sh \
+ sndrcv_omudpspoof.sh \
+ sndrcv_omudpspoof-bigmsg.sh \
+ sndrcv_omudpspoof_nonstdpt.sh
+endif
+
+#disabled as array-passing mode is no longer supported: omod-if-array.sh
+# omod-if-array.sh
+# omod-if-array-udp.sh
+if ENABLE_IMPTCP
+TESTS += \
+ tabescape_dflt.sh \
+ tabescape_dflt-udp.sh \
+ tabescape_off.sh \
+ tabescape_off-udp.sh \
+ tabescape_on.sh \
+ inputname-imtcp.sh \
+ fieldtest.sh \
+ fieldtest-udp.sh \
+ proprepltest-nolimittag-udp.sh \
+ proprepltest-nolimittag.sh \
+ proprepltest-rfctag-udp.sh \
+ proprepltest-rfctag.sh
+
+endif
+
+if ENABLE_OMRULESET
+TESTS += \
+ omruleset.sh \
+ omruleset-queue.sh
+endif
+
+if ENABLE_PMDB2DIAG
+TESTS += \
+ pmdb2diag_parse.sh
+endif
+
+if ENABLE_PMSNARE
+TESTS += \
+ pmsnare-default.sh \
+ pmsnare-default-udp.sh \
+ pmsnare-ccoff.sh \
+ pmsnare-ccoff-udp.sh \
+ pmsnare-ccdefault.sh \
+ pmsnare-ccdefault-udp.sh \
+ pmsnare-cccstyle.sh \
+ pmsnare-cccstyle-udp.sh \
+ pmsnare-ccbackslash.sh \
+ pmsnare-ccbackslash-udp.sh \
+ pmsnare-modoverride.sh \
+ pmsnare-modoverride-udp.sh
+endif
+
+if ENABLE_PMLASTMSG
+TESTS += \
+ pmlastmsg.sh \
+ pmlastmsg-udp.sh
+endif
+
+if ENABLE_EXTENDED_TESTS
+# random.sh is temporarily disabled as it needs some work
+# to rsyslog core to complete in reasonable time
+#TESTS += random.sh
+if ENABLE_IMFILE_TESTS
+TESTS += \
+ imfile-basic-2GB-file.sh \
+ imfile-truncate-2GB-file.sh
+endif # ENABLE_IMFILE_TESTS
+endif
+
+if ENABLE_IMFILE_TESTS
+TESTS += \
+ imfile-basic.sh \
+ imfile-basic-legacy.sh \
+ imfile-discard-truncated-line.sh \
+ imfile-truncate-line.sh \
+ imfile-file-not-found-error.sh \
+ imfile-fileNotFoundError-parameter.sh \
+ imfile-error-not-repeated.sh \
+ imfile-truncate.sh \
+ imfile-truncate-multiple.sh \
+ imfile-readmode2.sh \
+ imfile-readmode2-polling.sh \
+ imfile-readmode2-with-persists-data-during-stop.sh \
+ imfile-readmode2-with-persists.sh \
+ imfile-endregex.sh \
+ imfile-endregex-save-lf.sh \
+ imfile-endregex-save-lf-persist.sh \
+ imfile-endregex-timeout-none-polling.sh \
+ imfile-endregex-timeout-polling.sh \
+ imfile-endregex-timeout.sh \
+ imfile-endregex-timeout-none.sh \
+ imfile-endregex-timeout-with-shutdown.sh \
+ imfile-endregex-timeout-with-shutdown-polling.sh \
+ imfile-endmsg.regex.sh \
+ imfile-escapelf.replacement.sh \
+ imfile-escapelf.replacement-empty.sh \
+ imfile-statefile-no-file_id.sh \
+ imfile-statefile-no-file_id-TO-file_id.sh \
+ imfile-statefile-directory.sh \
+ imfile-statefile-delete.sh \
+ imfile-statefile-no-delete.sh \
+ imfile-persist-state-1.sh \
+ imfile-freshStartTail1.sh \
+ imfile-freshStartTail2.sh \
+ imfile-freshStartTail3.sh \
+ imfile-wildcards.sh \
+ imfile-wildcards-dirs.sh \
+ imfile-wildcards-dirs2.sh \
+ imfile-wildcards-dirs-multi.sh \
+ imfile-wildcards-dirs-multi2.sh \
+ imfile-wildcards-dirs-multi3.sh \
+ imfile-wildcards-dirs-multi4.sh \
+ imfile-wildcards-dirs-multi5.sh \
+ imfile-wildcards-dirs-multi5-polling.sh \
+ imfile-old-state-file.sh \
+ imfile-rename-while-stopped.sh \
+ imfile-rename.sh \
+ imfile-symlink.sh \
+ imfile-symlink-multi.sh \
+ imfile-symlink-ext-tmp-dir-tree.sh \
+ imfile-logrotate.sh \
+ imfile-logrotate-async.sh \
+ imfile-logrotate-multiple.sh \
+ imfile-logrotate-copytruncate.sh \
+ imfile-logrotate-nocopytruncate.sh \
+ imfile-growing-file-id.sh \
+ imfile-ignore-old-file-1.sh \
+ imfile-ignore-old-file-2.sh \
+ imfile-ignore-old-file-3.sh \
+ imfile-ignore-old-file-4.sh \
+ imfile-ignore-old-file-5.sh \
+ imfile-ignore-old-file-6.sh \
+ imfile-ignore-old-file-7.sh \
+ glbl-oversizeMsg-truncate-imfile.sh \
+ config_enabled-on.sh \
+ config_enabled-off.sh
+
+if ENABLE_MMNORMALIZE
+TESTS += \
+ imfile-endmsg.regex-with-example.sh
+endif
+
+if HAVE_VALGRIND
+TESTS += \
+ imfile-basic-vg.sh \
+ imfile-endregex-vg.sh \
+ imfile-endmsg.regex-vg.sh \
+ imfile-readmode0-vg.sh \
+ imfile-readmode2-vg.sh
+
+if ENABLE_HELGRIND
+TESTS += \
+ imfile-basic-vgthread.sh
+endif # ENABLE_HELGRIND
+
+if ENABLE_MMNORMALIZE
+TESTS += \
+ imfile-endmsg.regex-with-example-vg.sh
+endif # ENABLE_MMNORMALIZE
+
+endif # HAVE_VALGRIND
+
+endif # ENABLE_IMFILE_TESTS
+
+if ENABLE_IMBATCHREPORT
+TESTS += \
+ imbatchreport_errmsg_no_params.sh \
+ imbatchreport_errmsg_glob_not_regular.sh \
+ imbatchreport_errmsg_glob_dir_fake.sh \
+ imbatchreport_errmsg_glob_dir_not_dir.sh \
+ imbatchreport_errmsg_regex.match.reject.sh \
+ imbatchreport_errmsg_regex.match.rename.sh \
+ imbatchreport_errmsg_regex.nomatch.sh \
+ imbatchreport_errmsg_not_supported1.sh \
+ imbatchreport_errmsg_not_supported2.sh \
+ imbatchreport_errmsg_not_supported3.sh \
+ imbatchreport_errmsg_delete_params.sh \
+ imbatchreport_errmsg_rename_params.sh \
+ imbatchreport_delete_success.sh \
+ imbatchreport_delete_structdata.sh \
+ imbatchreport_rename_success.sh \
+ imbatchreport_delete_toolarge.sh \
+ imbatchreport_rename_toolarge.sh
+if HAVE_VALGRIND
+TESTS += \
+ imbatchreport_errmsg_no_params-vg.sh
+endif # ENABLE_IMBATCHREPORT
+endif
+
+if ENABLE_OMTCL
+TESTS += \
+ omtcl.sh
+endif
+
+if ENABLE_MMTAGHOSTNAME
+TESTS += \
+ mmtaghostname_tag.sh \
+ mmtaghostname_server.sh
+endif
+
+if ENABLE_MMKUBERNETES
+if ENABLE_MMJSONPARSE
+if ENABLE_IMFILE
+if ENABLE_IMPSTATS
+TESTS += \
+ mmkubernetes-basic.sh \
+ mmkubernetes-cache-expire.sh
+if HAVE_VALGRIND
+TESTS += \
+ mmkubernetes-basic-vg.sh \
+ mmkubernetes-cache-expire-vg.sh
+endif
+endif
+endif
+endif
+endif
+
+if ENABLE_IMTUXEDOULOG
+TESTS += \
+ imtuxedoulog_errmsg_no_params.sh \
+ imtuxedoulog_data.sh
+if HAVE_VALGRIND
+TESTS += \
+ imtuxedoulog_errmsg_no_params-vg.sh
+endif # ENABLE_IMTUXEDOULOG
+endif
+
+if ENABLE_OMAMQP1
+TESTS += \
+ omamqp1-basic.sh
+if HAVE_VALGRIND
+TESTS += \
+ omamqp1-basic-vg.sh
+endif
+endif # ENABLE_OMAMQP1
+
+endif # if ENABLE_TESTBENCH
+
+TESTS_ENVIRONMENT = RSYSLOG_MODDIR='$(abs_top_builddir)'/runtime/.libs/
+TESTS_ENVIRONMENT+= TOP_BUILDDIR='$(top_builddir)'
+TESTS_ENVIRONMENT+= TESTTOOL_DIR='$(abs_top_builddir)/tests'
+test_files = testbench.h runtime-dummy.c
+DISTCLEANFILES=rsyslog.pid
+
+distclean-local:
+ rm -rf .dep_cache .dep_wrk
+
+EXTRA_DIST= \
+ set-envvars.in \
+ urlencode.py \
+ dnscache-TTL-0.sh \
+ dnscache-TTL-0-vg.sh \
+ loadbalance.sh \
+ smtradfile.sh \
+ smtradfile-vg.sh \
+ immark.sh \
+ immark-inputname.sh \
+ immark-ruleset.sh \
+ immark-ruleset-custom-msg.sh \
+ operatingstate-basic.sh \
+ operatingstate-empty.sh \
+ operatingstate-unclean.sh \
+ internal-errmsg-memleak-vg.sh \
+ glbl-ruleset-queue-defaults.sh \
+ glbl-internalmsg_severity-info-shown.sh \
+ glbl-internalmsg_severity-debug-shown.sh \
+ glbl-internalmsg_severity-debug-not_shown.sh \
+ glbl-oversizeMsg-log-vg.sh \
+ config_enabled-on.sh \
+ config_enabled-off.sh \
+ empty-app-name.sh \
+ empty-hostname.sh \
+ func-substring-invld-startpos.sh \
+ func-substring-invld-startpos-vg.sh \
+ func-substring-large-endpos.sh \
+ func-substring-large-neg-endpos.sh \
+ func-substring-relative-endpos.sh \
+ hostname-with-slash-pmrfc5424.sh \
+ hostname-with-slash-pmrfc3164.sh \
+ pmrfc3164-msgFirstSpace.sh \
+ pmrfc3164-AtSignsInHostname.sh \
+ pmrfc3164-AtSignsInHostname_off.sh \
+ pmrfc3164-tagEndingByColon.sh \
+ pmrfc3164-defaultTag.sh \
+ pmrfc3164-json.sh \
+ hostname-with-slash-dflt-invld.sh \
+ hostname-with-slash-dflt-slash-valid.sh \
+ glbl-umask.sh \
+ glbl-unloadmodules.sh \
+ glbl-invld-param.sh \
+ glbl_setenv_2_vars.sh \
+ glbl_setenv_err.sh \
+ glbl_setenv_err_too_long.sh \
+ glbl_setenv.sh \
+ imtuxedoulog_errmsg_no_params.sh \
+ imtuxedoulog_data.sh \
+ imtuxedoulog_errmsg_no_params-vg.sh \
+ pmdb2diag_parse.sh \
+ mmtaghostname_tag.sh \
+ mmtaghostname_server.sh \
+ imbatchreport_errmsg_no_params.sh \
+ imbatchreport_errmsg_glob_not_regular.sh \
+ imbatchreport_errmsg_glob_dir_fake.sh \
+ imbatchreport_errmsg_glob_dir_not_dir.sh \
+ imbatchreport_errmsg_regex.match.reject.sh \
+ imbatchreport_errmsg_regex.match.rename.sh \
+ imbatchreport_errmsg_regex.nomatch.sh \
+ imbatchreport_errmsg_not_supported1.sh \
+ imbatchreport_errmsg_not_supported2.sh \
+ imbatchreport_errmsg_not_supported3.sh \
+ imbatchreport_errmsg_delete_params.sh \
+ imbatchreport_errmsg_rename_params.sh \
+ imbatchreport_delete_success.sh \
+ imbatchreport_delete_structdata.sh \
+ imbatchreport_rename_success.sh \
+ imbatchreport_delete_toolarge.sh \
+ imbatchreport_rename_toolarge.sh \
+ imbatchreport_errmsg_no_params-vg.sh \
+ mmexternal-SegFault.sh \
+ mmexternal-SegFault-empty-jroot-vg.sh \
+ testsuites/mmexternal-SegFault-mm-python.py \
+ mmexternal-InvldProg-vg.sh \
+ nested-call-shutdown.sh \
+ 1.rstest 2.rstest 3.rstest err1.rstest \
+ config_multiple_include.sh \
+ testsuites/include-std1-omfile-action.conf \
+ testsuites/include-std2-omfile-action.conf \
+ invalid_nested_include.sh \
+ validation-run.sh \
+ tls-certs/ca-key.pem \
+ tls-certs/ca.pem \
+ tls-certs/cert.pem \
+ tls-certs/certchained.pem \
+ tls-certs/key.pem \
+ tls-certs/ca-fail.pem \
+ tls-certs/cert-fail.pem \
+ tls-certs/key-fail.pem \
+ testsuites/x.509/ca.srl \
+ testsuites/x.509/client-cert-new.pem \
+ testsuites/x.509/client-new.csr \
+ testsuites/x.509/client-revoked-key.pem \
+ testsuites/x.509/client-revoked-valid.pem \
+ testsuites/x.509/client-revoked.csr \
+ testsuites/x.509/client-revoked.pem \
+ testsuites/x.509/crl.pem \
+ testsuites/x.509/index.txt \
+ testsuites/x.509/index.txt.attr \
+ testsuites/x.509/newcerts/01.pem \
+ testsuites/x.509/newcerts/02.pem \
+ testsuites/x.509/newcerts/03.pem \
+ testsuites/x.509/newcerts/04.pem \
+ testsuites/x.509/openssl-cmds.sh \
+ testsuites/x.509/openssl.cnf \
+ testsuites/x.509/serial \
+ testsuites/x.509/ca.pem \
+ testsuites/x.509/ca-key.pem \
+ testsuites/x.509/client-cert.pem \
+ testsuites/x.509/client-key.pem \
+ testsuites/x.509/machine-cert.pem \
+ testsuites/x.509/machine-key.pem \
+ testsuites/x.509/client-expired-cert.pem \
+ testsuites/x.509/client-expired-key.pem \
+ cfg.sh \
+ cfg1.cfgtest \
+ cfg1.testin \
+ cfg2.cfgtest \
+ cfg2.testin \
+ cfg3.cfgtest \
+ cfg3.testin \
+ cfg4.cfgtest \
+ cfg4.testin \
+ DevNull.cfgtest \
+ err1.rstest \
+ NoExistFile.cfgtest \
+ tcp_forwarding_tpl.sh \
+ tcp_forwarding_ns_tpl.sh \
+ tcp_forwarding_dflt_tpl.sh \
+ tcp_forwarding_retries.sh \
+ mainq_actq_DA.sh \
+ queue_warnmsg-oversize.sh \
+ queue-minbatch.sh \
+ queue-minbatch-queuefull.sh \
+ queue-direct-with-no-params.sh \
+ queue-direct-with-params-given.sh \
+ killrsyslog.sh \
+ parsertest-parse1.sh \
+ parsertest-parse1-udp.sh \
+ parsertest-parse2.sh \
+ parsertest-parse2-udp.sh \
+ parsertest-parse_8bit_escape.sh \
+ parsertest-parse_8bit_escape-udp.sh \
+ parsertest-parse3.sh \
+ parsertest-parse3-udp.sh \
+ parsertest-parse_invld_regex.sh \
+ parsertest-parse_invld_regex-udp.sh \
+ parsertest-parse-3164-buggyday.sh \
+ parsertest-parse-3164-buggyday-udp.sh \
+ parsertest-parse-nodate.sh \
+ parsertest-parse-nodate-udp.sh \
+ parsertest-snare_ccoff_udp.sh \
+ parsertest-snare_ccoff_udp2.sh \
+ fieldtest.sh \
+ fieldtest-udp.sh \
+ proprepltest-nolimittag-udp.sh \
+ proprepltest-nolimittag.sh \
+ proprepltest-rfctag-udp.sh \
+ proprepltest-rfctag.sh \
+ timestamp-3164.sh \
+ timestamp-3339.sh \
+ timestamp-isoweek.sh \
+ timestamp-mysql.sh \
+ timestamp-pgsql.sh \
+ timestamp-subseconds.sh \
+ rsf_getenv.sh \
+ diskq-rfc5424.sh \
+ rfc5424parser-sp_at_msg_start.sh \
+ diskqueue-full.sh \
+ diskqueue-fail.sh \
+ diskqueue.sh \
+ diskqueue-non-unique-prefix.sh \
+ arrayqueue.sh \
+ include-obj-text-from-file.sh \
+ include-obj-text-from-file-noexist.sh \
+ include-obj-outside-control-flow-vg.sh \
+ include-obj-in-if-vg.sh \
+ include-obj-text-vg.sh \
+ config_output-o-option.sh \
+ rscript-config_enable-off-vg.sh \
+ rscript-config_enable-on.sh \
+ rscript_http_request.sh \
+ rscript_http_request-vg.sh \
+ rscript_bare_var_root.sh \
+ rscript_bare_var_root-empty.sh \
+ rscript_contains.sh \
+ rscript_ipv42num.sh \
+ rscript_field.sh \
+ rscript_field-vg.sh \
+ rscript_stop.sh \
+ rscript_stop2.sh \
+ stop.sh \
+ rscript_le.sh \
+ rscript_le_var.sh \
+ rscript_ge.sh \
+ rscript_ge_var.sh \
+ rscript_lt.sh \
+ rscript_lt_var.sh \
+ rscript_gt.sh \
+ rscript_gt_var.sh \
+ rscript_ne.sh \
+ rscript_ne_var.sh \
+ rscript_number_comparison_LE.sh \
+ rscript_number_comparison_LE-vg.sh \
+ rscript_number_comparison_LT.sh \
+ rscript_compare_str-numstr.sh \
+ rscript_compare_str-num.sh \
+ rscript_compare_numstr-str.sh \
+ rscript_compare_num-str.sh \
+ rscript_compare_numstr-numstr.sh \
+ rscript_compare_numstr-num.sh \
+ rscript_compare_num-numstr.sh \
+ rscript_compare_num-num.sh \
+ rscript_compare_str-str.sh \
+ rscript_compare_str-str-vg.sh \
+ rscript_compare_str-num-vg.sh \
+ rscript_compare_str-numstr-vg.sh \
+ rscript_compare_num-str-vg.sh \
+ rscript_compare_numstr-str-vg.sh \
+ rscript_compare_numstr-num-vg.sh \
+ rscript_compare_numstr-numstr-vg.sh \
+ rscript_compare_num-num-vg.sh \
+ rscript_compare_num-numstr-vg.sh \
+ rscript_compare-common.sh \
+ rscript_num2ipv4.sh \
+ rscript_int2Hex.sh \
+ rscript_trim.sh \
+ rscript_substring.sh \
+ rscript_format_time.sh \
+ rscript_parse_time.sh \
+ rscript_parse_time_get-ts.py \
+ rscript_is_time.sh \
+ rscript_script_error.sh \
+ rscript_parse_json.sh \
+ rscript_parse_json-vg.sh \
+ rscript_backticks-vg.sh \
+ rscript_backticks_empty_envvar-vg.sh \
+ rscript_previous_action_suspended.sh \
+ rscript_str2num_negative.sh \
+ rscript_exists-yes.sh \
+ rscript_exists-yes2.sh \
+ rscript_exists-not1.sh \
+ rscript_exists-not2.sh \
+ rscript_exists-not3.sh \
+ rscript_exists-not4.sh \
+ rscript_unflatten_arg1_unsuitable.sh \
+ rscript_unflatten_arg2_invalid.sh \
+ rscript_unflatten_conflict1.sh \
+ rscript_unflatten_conflict2.sh \
+ rscript_unflatten_conflict3.sh \
+ rscript_unflatten_key_truncated.sh \
+ rscript_unflatten_non_object.sh \
+ rscript_unflatten_object_exclamation.sh \
+ rscript_unflatten_object.sh \
+ rscript_unflatten_arg1_unsuitable-vg.sh \
+ rscript_unflatten_arg2_invalid-vg.sh \
+ rscript_unflatten_conflict1-vg.sh \
+ rscript_unflatten_conflict2-vg.sh \
+ rscript_unflatten_conflict3-vg.sh \
+ rscript_unflatten_key_truncated-vg.sh \
+ rscript_unflatten_non_object-vg.sh \
+ rscript_unflatten_object_exclamation-vg.sh \
+ rscript_unflatten_object-vg.sh \
+ rscript_get_property.sh \
+ rscript_get_property-vg.sh \
+ rs-cnum.sh \
+ rs-int2hex.sh \
+ rs-substring.sh \
+ omsnmp_errmsg_no_params.sh \
+ sndrcv_omsnmpv1_udp.sh \
+ sndrcv_omsnmpv1_udp_dynsource.sh \
+ sndrcv_omsnmpv1_udp_invalidoid.sh \
+ snmptrapreceiver.py \
+ ommail_errmsg_no_params.sh \
+ mmdarwin_errmsg_no_params.sh \
+ mmdarwin_errmsg_no_sock.sh \
+ mmdarwin_errmsg_no_sock-vg.sh \
+ mmutf8fix_no_error.sh \
+ tcpflood_wrong_option_output.sh \
+ msleep_usage_output.sh \
+ mangle_qi_usage_output.sh \
+ minitcpsrv_usage_output.sh \
+ test_id_usage_output.sh \
+ mmanon_with_debug.sh \
+ mmanon_random_32_ipv4.sh \
+ mmanon_random_cons_32_ipv4.sh \
+ mmanon_recognize_ipv4.sh \
+ mmanon_zero_12_ipv4.sh \
+ mmanon_zero_33_ipv4.sh \
+ mmanon_zero_8_ipv4.sh \
+ mmanon_simple_12_ipv4.sh \
+ mmanon_simple_33_ipv4.sh \
+ mmanon_simple_8_ipv4.sh \
+ mmanon_simple_mallformed_ipv4.sh \
+ mmanon_random_128_ipv6.sh \
+ mmanon_zero_128_ipv6.sh \
+ mmanon_zero_96_ipv6.sh \
+ mmanon_random_cons_128_ipv6.sh \
+ mmanon_zero_50_ipv6.sh \
+ mmanon_recognize_ipv6.sh \
+ mmanon_zero_64_ipv6.sh \
+ mmanon_both_modes_compatible.sh \
+ mmanon_recognize_ipembedded.sh \
+ mmanon_ipv6_port.sh \
+ mmanon_random_cons_128_ipembedded.sh \
+ rscript_eq.sh \
+ rscript_eq_var.sh \
+ rscript_set_memleak-vg.sh \
+ rscript_set_unset_invalid_var.sh \
+ rscript_set_modify.sh \
+ stop-localvar.sh \
+ stop-msgvar.sh \
+ omfwd-tls-invalid-permitExpiredCerts.sh \
+ omfwd-keepalive.sh \
+ omfwd_fast_imuxsock.sh \
+ omfile_hup-vg.sh \
+ zstd.sh \
+ zstd-vg.sh \
+ gzipwr_hup-vg.sh \
+ omusrmsg-errmsg-no-params.sh \
+ omusrmsg-noabort.sh \
+ omusrmsg-noabort-vg.sh \
+ omfile-module-params.sh \
+ omfile-read-only-errmsg.sh \
+ omfile-null-filename.sh \
+ omfile-whitespace-filename.sh \
+ omfile-read-only.sh \
+ omfile-outchannel.sh \
+ omfile-outchannel-many.sh \
+ omfile-sizelimitcmd-many.sh \
+ omfile_both_files_set.sh \
+ omfile_hup.sh \
+ omrabbitmq_no_params.sh \
+ omrabbitmq_params_missing0.sh \
+ omrabbitmq_params_missing1.sh \
+ omrabbitmq_params_missing2.sh \
+ omrabbitmq_params_invalid0.sh \
+ omrabbitmq_params_invalid1.sh \
+ omrabbitmq_params_invalid2.sh \
+ omrabbitmq_params_invalid3.sh \
+ omrabbitmq_data_1server.sh \
+ omrabbitmq_data_1server-vg.sh \
+ omrabbitmq_data_2servers.sh \
+ omrabbitmq_error_server0.sh \
+ omrabbitmq_error_server1.sh \
+ omrabbitmq_error_server2.sh \
+ omrabbitmq_error_server3.sh \
+ omrabbitmq_json.sh \
+ omrabbitmq_raw.sh \
+ imhiredis-queue.sh \
+ imhiredis-queue-vg.sh \
+ imhiredis-queue-lpop.sh \
+ imhiredis-queue-lpop-vg.sh \
+ imhiredis-redis-restart.sh \
+ imhiredis-redis-restart-vg.sh \
+ imhiredis-redis-start-after.sh \
+ imhiredis-redis-start-after-vg.sh \
+ imhiredis-subscribe.sh \
+ imhiredis-subscribe-vg.sh \
+ imhiredis-stream.sh \
+ imhiredis-stream-vg.sh \
+ imhiredis-stream-from-beginning.sh \
+ imhiredis-stream-from-beginning-vg.sh \
+ imhiredis-stream-consumerGroup-ack.sh \
+ imhiredis-stream-consumerGroup-ack-vg.sh \
+ imhiredis-stream-consumerGroup-noack.sh \
+ imhiredis-stream-consumerGroup-noack-vg.sh \
+ imhiredis-stream-consumerGroup-reclaim.sh \
+ imhiredis-stream-consumerGroup-reclaim-vg.sh \
+ msgvar-concurrency.sh \
+ msgvar-concurrency-array.sh \
+ testsuites/msgvar-concurrency-array.rulebase \
+ msgvar-concurrency-array-event.tags.sh \
+ testsuites/msgvar-concurrency-array-event.tags.rulebase \
+ localvar-concurrency.sh \
+ exec_tpl-concurrency.sh \
+ prop-jsonmesg-vg.sh \
+ prop-all-json-concurrency.sh \
+ no-parser-errmsg.sh \
+ global_vars.sh \
+ no-parser-errmsg.sh \
+ no-parser-vg.sh \
+ prop-programname.sh \
+ prop-programname-with-slashes.sh \
+ rfc5424parser.sh \
+ rscript_privdropuser.sh \
+ rscript_privdropuserid.sh \
+ rscript_privdropgroup.sh \
+ rscript_privdropgroupid.sh \
+ privdrop_common.sh \
+ privdropuser.sh \
+ privdropuserid.sh \
+ privdropgroup.sh \
+ privdropgroupid.sh \
+ privdropabortonidfail.sh \
+ privdropabortonidfaillegacy.sh \
+ json-nonstring.sh \
+ json-onempty-at-end.sh \
+ template-json.sh \
+ template-pure-json.sh \
+ template-pos-from-to.sh \
+ template-pos-from-to-lowercase.sh \
+ template-pos-from-to-oversize.sh \
+ template-pos-from-to-oversize-lowercase.sh \
+ template-pos-from-to-missing-jsonvar.sh \
+ template-const-jsonf.sh \
+ template-topos-neg.sh \
+ fac_authpriv.sh \
+ fac_local0.sh \
+ fac_local0-vg.sh \
+ fac_local7.sh \
+ fac_mail.sh \
+ fac_news.sh \
+ fac_ftp.sh \
+ fac_ntp.sh \
+ fac_uucp.sh \
+ fac_invld1.sh \
+ fac_invld2.sh \
+ fac_invld3.sh \
+ fac_invld4_rfc5424.sh \
+ compresssp.sh \
+ compresssp-stringtpl.sh \
+ now_family_utc.sh \
+ now-utc-ymd.sh \
+ now-utc-casecmp.sh \
+ now-utc.sh \
+ now-unixtimestamp.sh \
+ faketime_common.sh \
+ imjournal-basic.sh \
+ imjournal-statefile.sh \
+ imjournal-statefile-vg.sh \
+ imjournal-basic-vg.sh \
+ omjournal-abort-template.sh \
+ omjournal-abort-no-template.sh \
+ omjournal-basic-template.sh \
+ omjournal-basic-no-template.sh \
+ timegenerated-ymd.sh \
+ timegenerated-uxtimestamp.sh \
+ timegenerated-uxtimestamp-invld.sh \
+ timegenerated-dateordinal.sh \
+ timegenerated-dateordinal-invld.sh \
+ timegenerated-utc.sh \
+ timegenerated-utc-legacy.sh \
+ timereported-utc.sh \
+ timereported-utc-legacy.sh \
+ timereported-utc-vg.sh \
+ mmrm1stspace-basic.sh \
+ mmnormalize_parsesuccess.sh \
+ mmnormalize_parsesuccess-vg.sh \
+ mmnormalize_rule_from_string.sh \
+ mmnormalize_rule_from_array.sh \
+ pmnull-basic.sh \
+ pmnull-withparams.sh \
+ omstdout-basic.sh \
+ testsuites/mmnormalize_processing_tests.rulebase \
+ mmnormalize_processing_test1.sh \
+ mmnormalize_processing_test2.sh \
+ mmnormalize_processing_test3.sh \
+ mmnormalize_processing_test4.sh \
+ pmnormalize-basic.sh \
+ pmnormalize-rule.sh \
+ pmnormalize-rule_and_rulebase.sh \
+ pmnormalize-neither_rule_rulebase.sh \
+ pmnormalize-invld-rulebase.sh \
+ pmnormalize-rule_invld-data.sh \
+ testsuites/pmnormalize_basic.rulebase \
+ pmnormalize-basic-vg.sh \
+ pmnormalize-rule-vg.sh\
+ pmnormalize-rule_and_rulebase-vg.sh \
+ pmnormalize-neither_rule_rulebase-vg.sh \
+ pmnormalize-invld-rulebase-vg.sh \
+ pmnormalize-rule_invld-data-vg.sh \
+ rawmsg-after-pri.sh \
+ rs_optimizer_pri.sh \
+ rscript_prifilt.sh \
+ rscript_optimizer1.sh \
+ rscript_ruleset_call.sh \
+ rscript_ruleset_call_indirect-basic.sh \
+ rscript_ruleset_call_indirect-var.sh \
+ rscript_ruleset_call_indirect-invld.sh \
+ cee_simple.sh \
+ cee_diskqueue.sh \
+ mmjsonparse-w-o-cookie.sh \
+ mmjsonparse-w-o-cookie-multi-spaces.sh \
+ mmjsonparse_simple.sh \
+ mmjsonparse-invalid-containerName.sh \
+ wtpShutdownAll-assertionFailure.sh \
+ imptcp-octet-framing-too-long-vg.sh \
+ imptcp-oversize-message-display.sh \
+ imptcp-msg-truncation-on-number.sh \
+ imptcp-msg-truncation-on-number2.sh \
+ imptcp-maxFrameSize-parameter.sh \
+ mmjsonparse_cim.sh \
+ mmjsonparse_cim2.sh \
+ mmjsonparse_localvar.sh \
+ mmdb.sh \
+ mmdb-space.sh \
+ mmdb.rb \
+ test.mmdb \
+ with_space.mmdb \
+ mmdb-vg.sh \
+ mmdb-container.sh \
+ mmdb-container-empty.sh \
+ mmdb-multilevel-vg.sh \
+ incltest.sh \
+ incltest_dir.sh \
+ incltest_dir_empty_wildcard.sh \
+ incltest_dir_wildcard.sh \
+ testsuites/es.yml \
+ clickhouse-dflt-tpl.sh \
+ clickhouse-retry-error.sh \
+ clickhouse-start.sh \
+ clickhouse-stop.sh \
+ clickhouse-basic.sh \
+ clickhouse-load.sh \
+ clickhouse-bulk.sh \
+ clickhouse-bulk-load.sh \
+ clickhouse-limited-batch.sh \
+ clickhouse-select.sh \
+ clickhouse-wrong-quotation-marks.sh \
+ clickhouse-wrong-template-option.sh \
+ clickhouse-errorfile.sh \
+ clickhouse-wrong-insert-syntax.sh \
+ clickhouse-basic-vg.sh \
+ clickhouse-load-vg.sh \
+ clickhouse-bulk-vg.sh \
+ clickhouse-bulk-load-vg.sh \
+ es_response_get_msgnum.py \
+ elasticsearch-error-format-check.py \
+ es-duplicated-ruleset.sh \
+ es-duplicated-ruleset-vg.sh \
+ es-basic-es6.0.sh \
+ es-basic-es7.14.sh \
+ es-basic.sh \
+ es-basic-vgthread.sh \
+ es-basic-server.sh \
+ es-execOnlyWhenPreviousSuspended.sh \
+ es-basic-ha.sh \
+ es-basic-bulk.sh \
+ es-basic-errfile-empty.sh \
+ es-basic-errfile-popul.sh \
+ es-bulk-errfile-empty.sh \
+ es-bulk-errfile-popul.sh \
+ es-bulk-errfile-popul-def-format.sh \
+ es-bulk-errfile-popul-erronly.sh \
+ es-bulk-errfile-popul-erronly-interleaved.sh \
+ es-bulk-errfile-popul-def-interleaved.sh \
+ es-searchType-empty.sh \
+ diskqueue-multithread-es.sh \
+ es-basic-vg.sh \
+ es-basic-bulk-vg.sh \
+ es-basic-ha-vg.sh \
+ es-maxbytes-bulk.sh \
+ es-bulk-retry.sh \
+ elasticsearch-stop.sh \
+ linkedlistqueue.sh \
+ da-mainmsg-q.sh \
+ diskqueue-fsync.sh \
+ msgdup.sh \
+ msgdup_props.sh \
+ empty-ruleset.sh \
+ ruleset-direct-queue.sh \
+ imtcp-listen-port-file-2.sh \
+ allowed-sender-tcp-ok.sh \
+ allowed-sender-tcp-fail.sh \
+ allowed-sender-tcp-hostname-ok.sh \
+ allowed-sender-tcp-hostname-fail.sh \
+ imtcp-octet-framing-too-long-vg.sh \
+ imtcp-discard-truncated-msg.sh \
+ imtcp-basic.sh \
+ imtcp-basic-hup.sh \
+ imtcp-maxFrameSize.sh \
+ imtcp-msg-truncation-on-number.sh \
+ imtcp-msg-truncation-on-number2.sh \
+ imtcp-NUL.sh \
+ imtcp-NUL-rawmsg.sh \
+ imtcp-tls-gtls-x509fingerprint-invld.sh \
+ imtcp-tls-gtls-x509fingerprint.sh \
+ imtcp-tls-gtls-x509name-invld.sh \
+ imtcp-tls-gtls-x509name.sh \
+ imtcp-tls-gtls-x509name-legacy.sh \
+ imtcp-drvr-in-input-basic.sh \
+ imtcp-multi-drvr-basic.sh \
+ imtcp-multi-drvr-basic-parallel.sh \
+ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh \
+ imtcp-tls-basic.sh \
+ imtcp-tls-input-basic.sh \
+ imtcp-tls-input-2certs.sh \
+ imtcp-tls-basic-verifydepth.sh \
+ imtcp-tls-basic-vg.sh \
+ imtcp-tls-no-lstn-startup.sh \
+ imtcp_incomplete_frame_at_end.sh \
+ imtcp-multiport.sh \
+ imtcp-bigmessage-octetcounting.sh \
+ imtcp-bigmessage-octetstuffing.sh \
+ udp-msgreduc-orgmsg-vg.sh \
+ udp-msgreduc-vg.sh \
+ manytcp-too-few-tls-vg.sh \
+ imtcp-tls-ossl-basic.sh \
+ imtcp-tls-ossl-input-basic.sh \
+ imtcp-tls-ossl-input-2certs.sh \
+ imtcp-tls-ossl-basic-tlscommands.sh \
+ imtcp-tls-ossl-basic-verifydepth.sh \
+ imtcp-tls-ossl-invalid-verifydepth.sh \
+ sndrcv_tls_ossl_anon_ipv4.sh \
+ sndrcv_tls_ossl_anon_ipv6.sh \
+ sndrcv_tls_ossl_anon_rebind.sh \
+ sndrcv_tls_ossl_anon_ciphers.sh \
+ sndrcv_tls_ossl_certvalid.sh \
+ sndrcv_tls_ossl_certvalid_action_level.sh \
+ sndrcv_tls_ossl_certvalid_expired.sh \
+ sndrcv_tls_ossl_certvalid_tlscommand.sh \
+ sndrcv_tls_ossl_certvalid_ciphers.sh \
+ sndrcv_tls_ossl_certvalid_revoked.sh \
+ imtcp-tls-ossl-x509valid.sh \
+ imtcp-tls-ossl-x509name.sh \
+ imtcp-tls-ossl-x509fingerprint.sh \
+ imtcp-tls-ossl-basic-vg.sh \
+ imtcp-tls-ossl-basic-brokenhandshake-vg.sh \
+ imtcp-tls-ossl-error-ca.sh \
+ imtcp-tls-ossl-error-cert.sh \
+ imtcp-tls-ossl-error-key.sh \
+ imtcp-tls-ossl-error-key2.sh \
+ manytcp.sh \
+ manyptcp.sh \
+ imptcp-basic-hup.sh \
+ imptcp-NUL.sh \
+ imptcp-NUL-rawmsg.sh \
+ imptcp_framing_regex.sh \
+ testsuites/imptcp_framing_regex.testdata \
+ imptcp_framing_regex-oversize.sh \
+ testsuites/imptcp_framing_regex-oversize.testdata \
+ imptcp_large.sh \
+ imptcp-connection-msg-disabled.sh \
+ imptcp-connection-msg-received.sh \
+ imptcp-discard-truncated-msg.sh \
+ imptcp_addtlframedelim.sh \
+ imptcp_conndrop-vg.sh \
+ imptcp_conndrop.sh \
+ imptcp_multi_line.sh \
+ testsuites/imptcp_multi_line.testdata \
+ imptcp_no_octet_counted.sh \
+ imtcp_addtlframedelim_on_input.sh \
+ testsuites/no_octet_counted.testdata \
+ imtcp_no_octet_counted.sh \
+ testsuites/spframingfix.testdata \
+ imtcp_spframingfix.sh \
+ imtcp-connection-msg-recieved.sh \
+ imptcp_spframingfix.sh \
+ msg-deadlock-headerless-noappname.sh \
+ imtcp_conndrop.sh \
+ imtcp_conndrop_tls.sh \
+ imtcp_conndrop_tls-vg.sh \
+ imtcp_addtlframedelim.sh \
+ tcp-msgreduc-vg.sh \
+ inputname-imtcp.sh \
+ omod-if-array.sh \
+ omod-if-array-udp.sh \
+ discard.sh \
+ failover-no-rptd.sh \
+ failover-no-rptd-vg.sh \
+ failover-no-basic.sh \
+ failover-no-basic-vg.sh \
+ failover-rptd.sh \
+ failover-rptd-vg.sh \
+ failover-basic.sh \
+ failover-basic-vg.sh \
+ failover-async.sh \
+ failover-double.sh \
+ suspend-via-file.sh \
+ suspend-omfwd-via-file.sh \
+ externalstate-failed-rcvr.sh \
+ discard-rptdmsg.sh \
+ discard-rptdmsg-vg.sh \
+ discard-allmark.sh \
+ discard-allmark-vg.sh \
+ diag.sh \
+ rcvr_fail_restore.sh \
+ queue-encryption-disk.sh \
+ queue-encryption-disk_keyfile.sh \
+ queue-encryption-disk_keyfile-vg.sh \
+ queue-encryption-disk_keyprog.sh \
+ queue-encryption-da.sh \
+ da-queue-persist.sh \
+ daqueue-dirty-shutdown.sh \
+ daqueue-invld-qi.sh \
+ daqueue-persist.sh \
+ daqueue-persist-drvr.sh \
+ queue-persist.sh \
+ queue-persist-drvr.sh \
+ threadingmq.sh \
+ threadingmqaq.sh \
+ sndrcv_drvr.sh \
+ sndrcv_drvr_noexit.sh \
+ sndrcv_failover.sh \
+ sndrcv.sh \
+ omrelp_errmsg_no_connect.sh \
+ imrelp-basic.sh \
+ imrelp-basic-hup.sh \
+ imrelp-basic-vg.sh \
+ imrelp-basic-oldstyle.sh \
+ imrelp-manyconn.sh \
+ imrelp-manyconn-vg.sh \
+ imrelp-maxDataSize-error.sh \
+ imrelp-long-msg.sh \
+ imrelp-oversizeMode-truncate.sh \
+ imrelp-oversizeMode-accept.sh \
+ imrelp-invld-tlslib.sh \
+ imrelp-bigmessage.sh \
+ imrelp-sessionbreak-vg.sh \
+ omrelp-invld-tlslib.sh \
+ glbl-oversizeMsg-log.sh \
+ glbl-oversizeMsg-truncate.sh \
+ glbl-oversizeMsg-split.sh \
+ sndrcv_relp.sh \
+ sndrcv_relp_rebind.sh \
+ sndrcv_relp_tls_prio.sh \
+ sndrcv_relp_tls_chainedcert.sh \
+ sndrcv_relp_tls.sh \
+ sndrcv_relp_tls_certvalid.sh \
+ sndrcv_relp-vg-rcvr.sh \
+ sndrcv_relp-vg-sender.sh \
+ relp_tls_certificate_not_found.sh \
+ omrelp_wrong_authmode.sh \
+ imrelp-tls.sh \
+ imrelp-tls-cfgcmd.sh \
+ imrelp-tls-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert2.sh \
+ sndrcv_relp_tls-cfgcmd.sh \
+ sndrcv_relp_dflt_pt.sh \
+ sndrcv_udp.sh \
+ imudp_thread_hang.sh \
+ sndrcv_udp_nonstdpt.sh \
+ sndrcv_udp_nonstdpt_v6.sh \
+ omudpspoof_errmsg_no_params.sh \
+ sndrcv_omudpspoof.sh \
+ sndrcv_omudpspoof-bigmsg.sh \
+ sndrcv_omudpspoof_nonstdpt.sh \
+ sndrcv_gzip.sh \
+ imdtls-basic.sh \
+ imdtls-basic-tlscommands.sh \
+ imdtls-basic-timeout \
+ imdtls-error-cert.sh \
+ imdtls-sessionbreak.sh \
+ imdtls-basic-vg.sh \
+ imdtls-sessionbreak-vg.sh \
+ sndrcv_dtls_certvalid.sh \
+ sndrcv_dtls_anon_ciphers.sh \
+ sndrcv_dtls_certvalid_ciphers.sh \
+ sndrcv_dtls_certvalid_permitted.sh \
+ sndrcv_dtls_certvalid_missing.sh \
+ sndrcv_dtls_anon_ciphers.sh \
+ sndrcv_dtls_certvalid-vg.sh \
+ action-tx-single-processing.sh \
+ omfwd-errfile-maxsize.sh \
+ omfwd-errfile-maxsize-filled.sh \
+ action-tx-errfile-maxsize.sh \
+ action-tx-errfile.sh \
+ testsuites/action-tx-errfile.result \
+ pipeaction.sh \
+ improg-simul.sh \
+ improg-multiline-test.py \
+ improg_errmsg_no_params.sh \
+ improg_errmsg_no_params-vg.sh \
+ improg_prog_simple.sh \
+ improg_prog_confirm.sh \
+ improg_prog_confirm_killonclose.sh \
+ improg_prog_killonclose.sh \
+ improg_prog_simple-vg.sh \
+ improg_simple_multi.sh \
+ imhttp-post-payload.sh \
+ imhttp-post-payload-vg.sh \
+ imhttp-post-payload-basic-auth.sh \
+ imhttp-post-payload-basic-auth-vg.sh \
+ imhttp-post-payload-query-params.sh \
+ imhttp-post-payload-query-params-vg.sh \
+ imhttp-post-payload-large.sh \
+ imhttp-post-payload-large-vg.sh \
+ testsuites/imhttp-large-data.txt \
+ imhttp-post-payload-multi.sh \
+ imhttp-post-payload-multi-vg.sh \
+ imhttp-getrequest-file.sh \
+ imhttp-getrequest-file-vg.sh \
+ imhttp-post-payload-multi-lf.sh \
+ imhttp-post-payload-multi-lf-vg.sh \
+ imhttp-post-payload-compress.sh \
+ imhttp-post-payload-compress-vg.sh \
+ testsuites/docroot/file.txt \
+ testsuites/htpasswd \
+ omhttp-auth.sh \
+ omhttp-basic.sh \
+ omhttp-batch-fail-with-400.sh \
+ omhttp-batch-jsonarray-compress.sh \
+ omhttp-batch-jsonarray-retry.sh \
+ omhttp-batch-jsonarray.sh \
+ omhttp-batch-kafkarest-retry.sh \
+ omhttp-batch-kafkarest.sh \
+ omhttp-batch-lokirest-retry.sh \
+ omhttp-batch-lokirest.sh \
+ omhttp-batch-lokirest-vg.sh \
+ omhttp-batch-newline.sh \
+ omhttp-retry.sh \
+ omhttp-httpheaderkey.sh \
+ omhttp-multiplehttpheaders.sh \
+ omhttp-dynrestpath.sh \
+ omhttp-batch-dynrestpath.sh \
+ omhttp-auth-vg.sh \
+ omhttp-basic-vg.sh \
+ omhttp-batch-jsonarray-compress-vg.sh \
+ omhttp-batch-jsonarray-retry-vg.sh \
+ omhttp-batch-jsonarray-vg.sh \
+ omhttp-batch-kafkarest-retry-vg.sh \
+ omhttp-batch-lokirest-retry-vg.sh \
+ omhttp-retry-vg.sh \
+ omhttp_server.py \
+ omprog-defaults.sh \
+ omprog-defaults-vg.sh \
+ omprog-output-capture.sh \
+ omprog-output-capture-mt.sh \
+ omprog-output-capture-vg.sh \
+ omprog-feedback.sh \
+ omprog-feedback-mt.sh \
+ omprog-feedback-vg.sh \
+ omprog-feedback-timeout.sh \
+ omprog-close-unresponsive.sh \
+ omprog-close-unresponsive-vg.sh \
+ omprog-close-unresponsive-noterm.sh \
+ omprog-restart-terminated.sh \
+ omprog-restart-terminated-vg.sh \
+ omprog-restart-terminated-outfile.sh \
+ omprog-single-instance.sh \
+ omprog-single-instance-vg.sh \
+ omprog-single-instance-outfile.sh \
+ omprog-if-error.sh \
+ omprog-transactions.sh \
+ omprog-transactions-vg.sh \
+ omprog-transactions-failed-messages.sh \
+ omprog-transactions-failed-commits.sh \
+ testsuites/omprog-defaults-bin.sh \
+ testsuites/omprog-output-capture-bin.sh \
+ testsuites/omprog-output-capture-mt-bin.py \
+ testsuites/omprog-feedback-bin.sh \
+ testsuites/omprog-feedback-mt-bin.sh \
+ testsuites/omprog-feedback-timeout-bin.sh \
+ testsuites/omprog-close-unresponsive-bin.sh \
+ testsuites/omprog-restart-terminated-bin.sh \
+ testsuites/omprog-single-instance-bin.sh \
+ testsuites/omprog-transactions-bin.sh \
+ pipe_noreader.sh \
+ uxsock_simple.sh \
+ asynwr_simple.sh \
+ asynwr_simple_2.sh \
+ asynwr_timeout.sh \
+ asynwr_timeout_2.sh \
+ asynwr_small.sh \
+ asynwr_tinybuf.sh \
+ wr_large_async.sh \
+ wr_large_sync.sh \
+ asynwr_deadlock.sh \
+ asynwr_deadlock_2.sh \
+ asynwr_deadlock2.sh \
+ asynwr_deadlock4.sh \
+ asynwr_dynfile_flushtxend-off.sh \
+ abort-uncleancfg-goodcfg.sh \
+ abort-uncleancfg-goodcfg-check.sh \
+ abort-uncleancfg-badcfg-check.sh \
+ abort-uncleancfg-badcfg-check_1.sh \
+ variable_leading_underscore.sh \
+ gzipwr_hup_multi_file.sh \
+ gzipwr_hup_single_file.sh \
+ gzipwr_rscript.sh \
+ gzipwr_flushInterval.sh \
+ gzipwr_flushOnTXEnd.sh \
+ gzipwr_large.sh \
+ gzipwr_large_dynfile.sh \
+ gzipwr_hup.sh \
+ complex1.sh \
+ random.sh \
+ testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input \
+ imfile-readmode0-vg.sh \
+ imfile-readmode2.sh \
+ imfile-readmode2-polling.sh \
+ imfile-readmode2-vg.sh \
+ imfile-readmode2-with-persists-data-during-stop.sh \
+ imfile-readmode2-with-persists.sh \
+ imfile-endregex-save-lf.sh \
+ imfile-endregex-save-lf-persist.sh \
+ imfile-endregex.sh \
+ imfile-endregex-vg.sh \
+ imfile-basic.sh \
+ imfile-basic-legacy.sh \
+ imfile-basic-2GB-file.sh \
+ imfile-truncate-2GB-file.sh \
+ imfile-discard-truncated-line.sh \
+ imfile-truncate-line.sh \
+ imfile-file-not-found-error.sh \
+ imfile-fileNotFoundError-parameter.sh \
+ imfile-error-not-repeated.sh \
+ imfile-basic-vg.sh \
+ imfile-basic-vgthread.sh \
+ imfile-endregex-timeout-none-polling.sh \
+ imfile-endregex-timeout-polling.sh \
+ imfile-endregex-timeout.sh \
+ imfile-endregex-timeout-none.sh \
+ imfile-endregex-timeout-with-shutdown.sh \
+ imfile-endregex-timeout-with-shutdown-polling.sh \
+ imfile-escapelf.replacement.sh \
+ imfile-escapelf.replacement-empty.sh \
+ imfile-endmsg.regex.sh \
+ imfile-endmsg.regex-vg.sh \
+ imfile-endmsg.regex-with-example.sh \
+ imfile-endmsg.regex-with-example-vg.sh \
+ imfile-endmsg.regex.crio.rulebase \
+ imfile-endmsg.regex.json.rulebase \
+ imfile-statefile-no-file_id.sh \
+ imfile-statefile-no-file_id-TO-file_id.sh \
+ imfile-statefile-directory.sh \
+ imfile-statefile-delete.sh \
+ imfile-statefile-no-delete.sh \
+ imfile-persist-state-1.sh \
+ imfile-freshStartTail1.sh \
+ imfile-freshStartTail2.sh \
+ imfile-freshStartTail3.sh \
+ imfile-truncate.sh \
+ imfile-truncate-multiple.sh \
+ imfile-wildcards.sh \
+ imfile-wildcards-dirs.sh \
+ imfile-wildcards-dirs2.sh \
+ imfile-wildcards-dirs-multi.sh \
+ imfile-wildcards-dirs-multi2.sh \
+ imfile-wildcards-dirs-multi3.sh \
+ imfile-wildcards-dirs-multi4.sh \
+ imfile-wildcards-dirs-multi5.sh \
+ imfile-wildcards-dirs-multi5-polling.sh \
+ imfile-old-state-file.sh \
+ imfile-rename-while-stopped.sh \
+ imfile-rename.sh \
+ imfile-symlink.sh \
+ imfile-symlink-multi.sh \
+ imfile-symlink-ext-tmp-dir-tree.sh \
+ imfile-logrotate.sh \
+ imfile-logrotate-async.sh \
+ imfile-logrotate-copytruncate.sh \
+ imfile-logrotate-nocopytruncate.sh \
+ imfile-logrotate-multiple.sh \
+ imfile-growing-file-id.sh \
+ imfile-ignore-old-file-1.sh \
+ imfile-ignore-old-file-2.sh \
+ imfile-ignore-old-file-3.sh \
+ imfile-ignore-old-file-4.sh \
+ imfile-ignore-old-file-5.sh \
+ imfile-ignore-old-file-6.sh \
+ imfile-ignore-old-file-7.sh \
+ glbl-oversizeMsg-truncate-imfile.sh \
+ dynfile_invld_async.sh \
+ dynfile_invld_sync.sh \
+ dynfile_invalid2.sh \
+ rulesetmultiqueue.sh \
+ rulesetmultiqueue-v6.sh \
+ omruleset.sh \
+ omruleset-queue.sh \
+ badqi.sh \
+ bad_qi/dbq.qi \
+ execonlyonce.sh \
+ execonlywhenprevsuspended.sh \
+ execonlywhenprevsuspended2.sh \
+ execonlywhenprevsuspended3.sh \
+ execonlywhenprevsuspended4.sh \
+ execonlywhenprevsuspended_multiwrkr.sh \
+ execonlywhenprevsuspended-queue.sh \
+ execonlywhenprevsuspended-nonsusp.sh \
+ execonlywhenprevsuspended-nonsusp-queue.sh \
+ tabescape_dflt.sh \
+ tabescape_dflt-udp.sh \
+ tabescape_off.sh \
+ tabescape_off-udp.sh \
+ tabescape_on.sh \
+ dircreate_dflt.sh \
+ dircreate_off.sh \
+ imuxsock_legacy.sh \
+ imuxsock_logger_parserchain.sh \
+ imuxsock_logger.sh \
+ imuxsock_logger_ratelimit.sh \
+ imuxsock_logger_ruleset.sh \
+ imuxsock_logger_ruleset_ratelimit.sh \
+ imuxsock_logger_err.sh \
+ imuxsock_logger_root.sh \
+ imuxsock_logger_syssock.sh \
+ imuxsock_traillf.sh \
+ imuxsock_traillf_root.sh \
+ imuxsock_traillf_syssock.sh \
+ imuxsock_ccmiddle.sh \
+ imuxsock_ccmiddle_root.sh \
+ imklog_permitnonkernelfacility_root.sh \
+ imuxsock_ccmiddle_syssock.sh \
+ imuxsock_hostname.sh \
+ testsuites/mysql-truncate.sql \
+ testsuites/mysql-select-msg.sql \
+ libdbi-basic.sh \
+ libdbi-asyn.sh \
+ mysqld-start.sh \
+ mysqld-stop.sh \
+ mysql-basic.sh \
+ mysql-basic-cnf6.sh \
+ mysql-basic-vg.sh \
+ mysql-asyn.sh \
+ mysql-asyn-vg.sh \
+ mysql-actq-mt.sh \
+ mysql-actq-mt-withpause.sh \
+ mysql-actq-mt-withpause-vg.sh \
+ kafka-selftest.sh \
+ omkafka.sh \
+ omkafkadynakey.sh \
+ omkafka-vg.sh \
+ imkafka-hang-on-no-kafka.sh \
+ imkafka-hang-other-action-on-no-kafka.sh \
+ imkafka-backgrounded.sh \
+ imkafka-config-err-ruleset.sh \
+ imkafka-config-err-param.sh \
+ imkafka.sh \
+ imkafka-vg.sh \
+ imkafka_multi_single.sh \
+ imkafka_multi_group.sh \
+ sndrcv_kafka.sh \
+ sndrcv_kafka_multi_topics.sh \
+ testsuites/kafka-server.properties \
+ testsuites/kafka-server.dep_wrk1.properties \
+ testsuites/kafka-server.dep_wrk2.properties \
+ testsuites/kafka-server.dep_wrk3.properties \
+ testsuites/zoo.cfg \
+ testsuites/zoo.dep_wrk1.cfg \
+ testsuites/zoo.dep_wrk2.cfg \
+ testsuites/zoo.dep_wrk3.cfg \
+ omazureeventhubs-basic.sh \
+ omazureeventhubs-list.sh \
+ omazureeventhubs-stress.sh \
+ omazureeventhubs-interrupt.sh \
+ omazureeventhubs-basic-vg.sh \
+ omazureeventhubs-interrupt-vg.sh \
+ mmpstrucdata.sh \
+ mmpstrucdata-escaping.sh \
+ mmpstrucdata-case.sh \
+ mmpstrucdata-vg.sh \
+ mmpstrucdata-invalid-vg.sh \
+ libdbi-basic-vg.sh \
+ dynstats_ctr_reset.sh \
+ dynstats_reset_without_pstats_reset.sh \
+ dynstats_nometric.sh \
+ dynstats_overflow.sh \
+ dynstats_overflow-vg.sh \
+ dynstats_reset.sh \
+ dynstats_reset-vg.sh \
+ impstats-hup.sh \
+ dynstats.sh \
+ dynstats-vg.sh \
+ dynstats_prevent_premature_eviction.sh \
+ dynstats_prevent_premature_eviction-vg.sh \
+ testsuites/dynstats_empty_input \
+ testsuites/dynstats_input \
+ testsuites/dynstats_input_1 \
+ testsuites/dynstats_input_2 \
+ testsuites/dynstats_input_3 \
+ testsuites/dynstats_input_more_0 \
+ testsuites/dynstats_input_more_1 \
+ testsuites/dynstats_input_more_2 \
+ no-dynstats-json.sh \
+ no-dynstats.sh \
+ omfwd_impstats-udp.sh \
+ omfwd_impstats-tcp.sh \
+ perctile-simple.sh \
+ perctile-simple-vg.sh \
+ stats-json.sh \
+ stats-json-vg.sh \
+ stats-cee.sh \
+ stats-cee-vg.sh \
+ stats-json-es.sh \
+ dynstats-json.sh \
+ dynstats-json-vg.sh \
+ mmnormalize_variable.sh \
+ mmnormalize_tokenized.sh \
+ testsuites/mmnormalize_variable.rulebase \
+ testsuites/date_time_msg \
+ testsuites/mmnormalize_tokenized.rulebase \
+ testsuites/tokenized_input \
+ rscript_random.sh \
+ rscript_hash32.sh \
+ rscript_hash32-vg.sh \
+ rscript_hash64.sh \
+ rscript_hash64-vg.sh \
+ rscript_replace.sh \
+ rscript_replace_complex.sh \
+ testsuites/complex_replace_input \
+ rscript_unaffected_reset.sh \
+ rscript_wrap2.sh \
+ rscript_wrap3.sh \
+ testsuites/wrap3_input\
+ json_array_subscripting.sh \
+ testsuites/json_array_input \
+ testsuites/json_object_input \
+ testsuites/json_nonarray_input \
+ json_array_looping.sh \
+ json_object_looping.sh \
+ json_object_looping-vg.sh \
+ json_array_looping-vg.sh \
+ json_object_suicide_in_loop-vg.sh \
+ json_nonarray_looping.sh \
+ json_null.sh \
+ json_null-vg.sh \
+ json_null_array.sh \
+ json_null_array-vg.sh \
+ mmjsonparse_extra_data-vg.sh \
+ mmnormalize_regex.sh \
+ testsuites/mmnormalize_regex.rulebase \
+ testsuites/regex_input \
+ mmnormalize_regex_disabled.sh \
+ mmnormalize_regex_defaulted.sh \
+ stop_when_array_has_element.sh \
+ testsuites/stop_when_array_has_elem_input \
+ key_dereference_on_uninitialized_variable_space.sh \
+ rscript_re_extract_i.sh \
+ rscript_re_extract.sh \
+ rscript_re_match_i.sh \
+ rscript_re_match.sh \
+ rscript_re_match-dbl_quotes.sh \
+ lookup_table.sh \
+ lookup_table-hup-backgrounded.sh \
+ lookup_table_no_hup_reload.sh \
+ lookup_table_no_hup_reload-vg.sh \
+ lookup_table_rscript_reload.sh \
+ lookup_table_rscript_reload_without_stub.sh \
+ lookup_table_rscript_reload-vg.sh \
+ lookup_table_rscript_reload_without_stub-vg.sh \
+ rscript_trim-vg.sh \
+ testsuites/xlate.lkp_tbl \
+ testsuites/xlate_more.lkp_tbl \
+ unused_lookup_table-vg.sh \
+ lookup_table-vg.sh \
+ array_lookup_table.sh \
+ array_lookup_table-vg.sh \
+ array_lookup_table_misuse-vg.sh \
+ multiple_lookup_tables.sh \
+ multiple_lookup_tables-vg.sh \
+ testsuites/xlate_array.lkp_tbl \
+ testsuites/xlate_array_more.lkp_tbl \
+ testsuites/xlate_array_misuse.lkp_tbl \
+ testsuites/xlate_array_more_misuse.lkp_tbl \
+ sparse_array_lookup_table.sh \
+ sparse_array_lookup_table-vg.sh \
+ testsuites/xlate_sparse_array.lkp_tbl \
+ testsuites/xlate_sparse_array_more.lkp_tbl \
+ lookup_table_bad_configs.sh \
+ lookup_table_bad_configs-vg.sh \
+ testsuites/xlate_array_empty_table.lkp_tbl \
+ testsuites/xlate_array_no_index.lkp_tbl \
+ testsuites/xlate_array_no_table.lkp_tbl \
+ testsuites/xlate_array_no_value.lkp_tbl \
+ testsuites/xlate_empty_file.lkp_tbl \
+ testsuites/xlate_incorrect_type.lkp_tbl \
+ testsuites/xlate_incorrect_version.lkp_tbl \
+ testsuites/xlate_sparseArray_empty_table.lkp_tbl \
+ testsuites/xlate_sparseArray_no_index.lkp_tbl \
+ testsuites/xlate_sparseArray_no_table.lkp_tbl \
+ testsuites/xlate_sparseArray_no_value.lkp_tbl \
+ testsuites/xlate_string_empty_table.lkp_tbl \
+ testsuites/xlate_string_no_index.lkp_tbl \
+ testsuites/xlate_string_no_table.lkp_tbl \
+ testsuites/xlate_string_no_value.lkp_tbl \
+ testsuites/xlate_invalid_json.lkp_tbl \
+ testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl \
+ testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl \
+ testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl \
+ json_var_cmpr.sh \
+ imptcp_maxsessions.sh \
+ imptcp_nonProcessingPoller.sh \
+ imptcp_veryLargeOctateCountedMessages.sh \
+ known_issues.supp \
+ libmaxmindb.supp \
+ travis/trusty.supp \
+ linux_localtime_r.supp \
+ CI/centos6-9.supp \
+ CI/centos7.supp \
+ CI/gcov.supp \
+ CI/ubuntu20.04.supp \
+ json_var_case.sh \
+ cfg.sh \
+ empty-prop-comparison.sh \
+ sndrcv_tls_anon_rebind.sh \
+ sndrcv_tls_anon_hostname.sh \
+ sndrcv_tls_anon_ipv4.sh \
+ sndrcv_tls_anon_ipv6.sh \
+ sndrcv_tls_priorityString.sh \
+ sndrcv_tls_certvalid.sh \
+ sndrcv_tls_certvalid_action_level.sh \
+ sndrcv_tls_certvalid_expired.sh \
+ sndrcv_tls_certvalid_expired_defaultmode.sh \
+ sndrcv_tls_certvalid_revoked.sh \
+ sndrcv_tls_certless_clientonly.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh \
+ sndrcv_tls_gtls_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_ossl_serveranon_ossl_clientanon.sh \
+ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \
+ sndrcv_tls_ossl_servercert_gtls_clientanon.sh \
+ sndrcv_tls_ossl_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_ossl_clientanon.sh \
+ sndrcv_tls_gtls_serveranon_ossl_clientanon.sh \
+ sndrcv_tls_client_missing_cert.sh \
+ sndrcv_ossl_cert_chain.sh \
+ omtcl.sh \
+ omtcl.tcl \
+ pmsnare-default.sh \
+ pmsnare-default-udp.sh \
+ pmsnare-ccoff.sh \
+ pmsnare-ccoff-udp.sh \
+ pmsnare-ccdefault.sh \
+ pmsnare-ccdefault-udp.sh \
+ pmsnare-cccstyle.sh \
+ pmsnare-cccstyle-udp.sh \
+ pmsnare-ccbackslash.sh \
+ pmsnare-ccbackslash-udp.sh \
+ pmsnare-modoverride.sh \
+ pmsnare-modoverride-udp.sh \
+ pmlastmsg.sh \
+ pmlastmsg-udp.sh \
+ pgsql-basic.sh \
+ testsuites/pgsql-basic.sql \
+ testsuites/pgsql-select-msg.sql \
+ testsuites/pgsql-select-syslogtag.sql \
+ pgsql-basic-cnf6.sh \
+ pgsql-basic-threads-cnf6.sh \
+ pgsql-template.sh \
+ pgsql-template-cnf6.sh \
+ pgsql-actq-mt-withpause.sh \
+ pgsql-template-threads-cnf6.sh \
+ pgsql-basic-vg.sh \
+ pgsql-template-vg.sh \
+ pgsql-basic-cnf6-vg.sh \
+ pgsql-template-cnf6-vg.sh \
+ pgsql-actq-mt-withpause-vg.sh \
+ ../devtools/prep-mysql-db.sh \
+ ../devtools/prepare_clickhouse.sh \
+ mmkubernetes-basic.sh \
+ mmkubernetes-basic-vg.sh \
+ mmkubernetes_test_server.py \
+ mmkubernetes-basic.out.json \
+ mmkubernetes-cache-expire.sh \
+ mmkubernetes-cache-expire-vg.sh \
+ mmkubernetes-cache-expire.out.expected \
+ mmkubernetes.supp \
+ es-writeoperation.sh \
+ imdocker-basic.sh \
+ imdocker-basic-vg.sh \
+ imdocker-long-logline.sh \
+ imdocker-long-logline-vg.sh \
+ imdocker-new-logs-from-start.sh \
+ imdocker-new-logs-from-start-vg.sh \
+ imdocker-multi-line.sh \
+ imdocker-multi-line-vg.sh \
+ testsuites/incltest.d/include.conf \
+ testsuites/abort-uncleancfg-goodcfg.conf \
+ testsuites/include-std-omfile-action.conf \
+ testsuites/invalid.conf \
+ testsuites/valid.conf \
+ testsuites/variable_leading_underscore.conf \
+ omamqp1-common.sh \
+ omamqp1-basic.sh \
+ omamqp1-basic-vg.sh
+
+ourtail_SOURCES = ourtail.c
+msleep_SOURCES = msleep.c
+omrelp_dflt_port_SOURCES = omrelp_dflt_port.c
+mangle_qi_SOURCES = mangle_qi.c
+chkseq_SOURCES = chkseq.c
+check_relpEngineVersion = check_relpEngineVersion.c
+have_relpSrvSetOversizeMode = have_relpSrvSetOversizeMode.c
+have_relpEngineSetTLSLibByName = have_relpEngineSetTLSLibByName.c
+have_relpSrvSetTlsConfigCmd = have_relpSrvSetTlsConfigCmd.c
+test_id_SOURCES = test_id.c
+
+uxsockrcvr_SOURCES = uxsockrcvr.c
+uxsockrcvr_LDADD = $(SOL_LIBS)
+
+tcpflood_SOURCES = tcpflood.c
+tcpflood_CFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS)
+tcpflood_CPPFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS)
+tcpflood_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) $(RELP_LIBS)
+if ENABLE_GNUTLS
+tcpflood_CFLAGS += $(GNUTLS_CFLAGS)
+tcpflood_CPPFLAGS += $(GNUTLS_CFLAGS)
+tcpflood_LDADD += $(GNUTLS_LIBS)
+endif
+if ENABLE_OPENSSL
+tcpflood_CFLAGS += $(OPENSSL_CFLAGS)
+tcpflood_CPPFLAGS += $(OPENSSL_CFLAGS)
+tcpflood_LDADD += $(OPENSSL_LIBS)
+endif
+
+minitcpsrv_SOURCES = minitcpsrvr.c
+minitcpsrv_LDADD = $(SOL_LIBS)
+
+syslog_caller_SOURCES = syslog_caller.c
+syslog_caller_CPPFLAGS = $(LIBLOGGING_STDLOG_CFLAGS)
+syslog_caller_LDADD = $(SOL_LIBS) $(LIBLOGGING_STDLOG_LIBS)
+
+journal_print_SOURCES = journal_print.c
+journal_print_CPPFLAGS = $(LIBSYSTEMD_JOURNAL_CFLAGS)
+journal_print_LDADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+
+diagtalker_SOURCES = diagtalker.c
+diagtalker_LDADD = $(SOL_LIBS)
+
+randomgen_SOURCES = randomgen.c
+randomgen_LDADD = $(SOL_LIBS)
+
+inputfilegen_SOURCES = inputfilegen.c
+inputfilegen_LDADD = $(SOL_LIBS)
+
+# rtinit tests disabled for the moment - also questionable if they
+# really provide value (after all, everything fails if rtinit fails...)
+#rt_init_SOURCES = rt-init.c $(test_files)
+#rt_init_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+#rt_init_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS)
+#rt_init_LDFLAGS = -export-dynamic
+
+# same for basic rscript tests
+#rscript_SOURCES = rscript.c getline.c $(test_files)
+#rscript_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+#rscript_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS)
+#rscript_LDFLAGS = -export-dynamic
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644
index 0000000..485b8c5
--- /dev/null
+++ b/tests/Makefile.in
@@ -0,0 +1,4452 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+@ENABLE_TESTBENCH_TRUE@check_PROGRAMS = ourtail$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ tcpflood$(EXEEXT) chkseq$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ msleep$(EXEEXT) randomgen$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ diagtalker$(EXEEXT) uxsockrcvr$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ syslog_caller$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ inputfilegen$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ minitcpsrv$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ omrelp_dflt_port$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ mangle_qi$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ have_relpSrvSetOversizeMode$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ have_relpEngineSetTLSLibByName$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ have_relpSrvSetTlsConfigCmd$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ check_relpEngineVersion$(EXEEXT) \
+@ENABLE_TESTBENCH_TRUE@ test_id$(EXEEXT) $(am__EXEEXT_1) \
+@ENABLE_TESTBENCH_TRUE@ $(am__EXEEXT_2)
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_1 = journal_print
+@ENABLE_TESTBENCH_TRUE@TESTS = $(am__append_2) $(am__append_3) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_4) $(am__append_5) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_6) $(am__append_7) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_8) $(am__append_9) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_10) $(am__append_11) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_12) $(am__append_13) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_14) $(am__append_15) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_16) $(am__append_17) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_18) $(am__append_19) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_20) $(am__append_21) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_22) $(am__append_23) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_24) $(am__append_25) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_26) $(am__append_27) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_28) $(am__append_29) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_30) $(am__append_31) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_32) $(am__append_33) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_34) $(am__append_35) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_36) $(am__append_37) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_38) $(am__append_39) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_40) $(am__append_41) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_42) $(am__append_43) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_44) $(am__append_45) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_46) $(am__append_47) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_48) $(am__append_49) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_50) $(am__append_51) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_52) $(am__append_53) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_54) $(am__append_55) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_57) $(am__append_58) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_59) $(am__append_60) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_61) $(am__append_62) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_63) $(am__append_64) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_65) $(am__append_66) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_67) $(am__append_68) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_69) $(am__append_70) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_71) $(am__append_72) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_73) $(am__append_74) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_75) $(am__append_76) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_77) $(am__append_78) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_79) $(am__append_80) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_81) $(am__append_82) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_83) $(am__append_84) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_85) $(am__append_86) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_87) $(am__append_88) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_89) $(am__append_90) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_91) $(am__append_92) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_93) $(am__append_94) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_95) $(am__append_96) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_97) $(am__append_98) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_99) $(am__append_100) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_101) $(am__append_102) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_103) $(am__append_104) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_105) $(am__append_106) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_107) $(am__append_108) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_109) $(am__append_110) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_111) $(am__append_112) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_113) $(am__append_114) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_115) $(am__append_116) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_117) $(am__append_118) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_119) $(am__append_120) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_121) $(am__append_122) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_123) $(am__append_124) \
+@ENABLE_TESTBENCH_TRUE@ $(am__append_125) $(am__append_126)
+# the following test need to be serialized:
+
+# special "test" for stopping ES once all ES tests are done
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_2 = es-duplicated-ruleset.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-es6.0.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-es7.14.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-bulk.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@ elasticsearch-stop.sh
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_3 = \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ es-duplicated-ruleset-vg.sh \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ es-basic-vg.sh
+
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_HELGRIND_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_4 = \
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_HELGRIND_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ es-basic-vgthread.sh
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_5 = \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-server.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-execOnlyWhenPreviousSuspended.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-maxbytes-bulk.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-errfile-empty.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-errfile-popul.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-empty.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-popul.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-searchType-empty.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue-multithread-es.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-writeoperation.sh
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_6 = \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-basic-ha.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-retry.sh
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_7 = \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-popul-def-format.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-popul-erronly.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-popul-erronly-interleaved.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@ es-bulk-errfile-popul-def-interleaved.sh
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_8 = \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ es-basic-bulk-vg.sh \
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ es-basic-ha-vg.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_9 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ immark.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ immark-inputname.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ immark-ruleset.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ immark-ruleset-custom-msg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ operatingstate-basic.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ operatingstate-empty.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ operatingstate-unclean.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ smtradfile.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ loadbalance.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ empty-hostname.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-3164.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-3339.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-isoweek.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-mysql.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-pgsql.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ timestamp-subseconds.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ msleep_usage_output.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mangle_qi_usage_output.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ minitcpsrv_usage_output.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ test_id_usage_output.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ prop-programname.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ prop-programname-with-slashes.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ hostname-with-slash-pmrfc5424.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ hostname-with-slash-pmrfc3164.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ hostname-with-slash-dflt-invld.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ func-substring-invld-startpos.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ func-substring-large-endpos.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ func-substring-large-neg-endpos.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ func-substring-relative-endpos.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ hostname-with-slash-dflt-slash-valid.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ empty-app-name.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ stop-localvar.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ stop-msgvar.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-ruleset-queue-defaults.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-internalmsg_severity-info-shown.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-internalmsg_severity-debug-shown.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-internalmsg_severity-debug-not_shown.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-umask.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-unloadmodules.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-invld-param.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl_setenv_2_vars.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl_setenv_err.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl_setenv_err_too_long.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl_setenv.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mmexternal-SegFault.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ nested-call-shutdown.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dnscache-TTL-0.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ invalid_nested_include.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfwd-tls-invalid-permitExpiredCerts.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfwd-keepalive.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omusrmsg-errmsg-no-params.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omusrmsg-noabort.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-module-params.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-read-only-errmsg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-null-filename.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-whitespace-filename.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-read-only.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-outchannel.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile_both_files_set.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile_hup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ msgvar-concurrency.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ localvar-concurrency.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ exec_tpl-concurrency.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_privdropuser.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_privdropuserid.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_privdropgroup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_privdropgroupid.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropuser.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropuserid.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropgroup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropgroupid.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropabortonidfail.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ privdropabortonidfaillegacy.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ json-nonstring.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ json-onempty-at-end.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-json.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pure-json.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pos-from-to.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pos-from-to-lowercase.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pos-from-to-oversize.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pos-from-to-oversize-lowercase.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-pos-from-to-missing-jsonvar.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-const-jsonf.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ template-topos-neg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_authpriv.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_local0.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_local7.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_mail.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_news.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_ftp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_ntp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_uucp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_invld1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_invld2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_invld3.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ fac_invld4_rfc5424.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rfc5424parser-sp_at_msg_start.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ compresssp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ compresssp-stringtpl.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rawmsg-after-pri.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rfc5424parser.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-msgFirstSpace.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-AtSignsInHostname.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-AtSignsInHostname_off.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-tagEndingByColon.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-defaultTag.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pmrfc3164-json.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ tcp_forwarding_tpl.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ tcp_forwarding_dflt_tpl.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ tcp_forwarding_retries.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mainq_actq_DA.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue_warnmsg-oversize.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-minbatch.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-minbatch-queuefull.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-direct-with-no-params.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-direct-with-params-given.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ arrayqueue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ global_vars.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ no-parser-errmsg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ da-mainmsg-q.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ validation-run.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ msgdup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ msgdup_props.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ empty-ruleset.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ ruleset-direct-queue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-listen-port-file-2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ allowed-sender-tcp-ok.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ allowed-sender-tcp-fail.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ allowed-sender-tcp-hostname-ok.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ allowed-sender-tcp-hostname-fail.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-discard-truncated-msg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-basic.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-basic-hup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-maxFrameSize.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-msg-truncation-on-number.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-msg-truncation-on-number2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-NUL.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-NUL-rawmsg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_incomplete_frame_at_end.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-multiport.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-bigmessage-octetcounting.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-bigmessage-octetstuffing.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ da-queue-persist.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ daqueue-persist.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ daqueue-invld-qi.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ daqueue-dirty-shutdown.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskq-rfc5424.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue-fsync.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue-full.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue-fail.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ diskqueue-non-unique-prefix.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rulesetmultiqueue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rulesetmultiqueue-v6.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ manytcp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rsf_getenv.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ msg-deadlock-headerless-noappname.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_conndrop.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_addtlframedelim.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_no_octet_counted.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_addtlframedelim_on_input.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_spframingfix.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-connection-msg-recieved.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_failover.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_gzip.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_udp_nonstdpt.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_udp_nonstdpt_v6.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imudp_thread_hang.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_udp_nonstdpt_v6.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_simple.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_simple_2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_timeout.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_timeout_2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_small.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_tinybuf.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ wr_large_async.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ wr_large_sync.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_deadlock.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_deadlock_2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_deadlock2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_deadlock4.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ asynwr_dynfile_flushtxend-off.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ abort-uncleancfg-goodcfg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ abort-uncleancfg-goodcfg-check.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ abort-uncleancfg-badcfg-check.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ abort-uncleancfg-badcfg-check_1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ variable_leading_underscore.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_hup_multi_file.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_hup_single_file.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_rscript.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_flushInterval.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_flushOnTXEnd.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_large.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_large_dynfile.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ gzipwr_hup.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynfile_invld_async.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynfile_invld_sync.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynfile_invalid2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ complex1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-persist.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pipeaction.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlyonce.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended3.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended4.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended_multiwrkr.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended-queue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended-nonsusp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ execonlywhenprevsuspended-nonsusp-queue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ pipe_noreader.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dircreate_dflt.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ dircreate_off.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_legacy.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_ratelimit.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_ruleset.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_ruleset_ratelimit.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_err.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_parserchain.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_traillf.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_ccmiddle.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_syssock.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_traillf_syssock.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_ccmiddle_syssock.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ discard-rptdmsg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ discard-allmark.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ discard.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ stop.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-async.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-double.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-basic.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-rptd.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-no-rptd.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ failover-no-basic.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ suspend-via-file.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ suspend-omfwd-via-file.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ externalstate-failed-rcvr.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rcvr_fail_restore.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_contains.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_bare_var_root.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_bare_var_root-empty.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ipv42num.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_field.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_stop.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_stop2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_prifilt.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_optimizer1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ruleset_call.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ruleset_call_indirect-basic.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ruleset_call_indirect-var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ruleset_call_indirect-invld.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_set_unset_invalid_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_set_modify.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unaffected_reset.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_replace_complex.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_wrap2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_wrap3.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_re_extract_i.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_re_extract.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_re_match_i.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_re_match.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_re_match-dbl_quotes.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_eq.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_eq_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ge.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ge_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_gt.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_gt_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_le.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_le_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_lt.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_lt_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ne.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_ne_var.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_number_comparison_LE.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_number_comparison_LT.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_str-numstr.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_str-num.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_numstr-str.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_num-str.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_numstr-numstr.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_numstr-num.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_num-numstr.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_num-num.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_compare_str-str.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_num2ipv4.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_int2Hex.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_trim.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_substring.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_format_time.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_parse_time.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_is_time.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_script_error.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_parse_json.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_previous_action_suspended.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_str2num_negative.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-yes.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-yes2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-not1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-not2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-not3.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_exists-not4.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript-config_enable-on.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_get_property.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ config_output-o-option.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rs-cnum.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rs-substring.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rs-int2hex.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ empty-prop-comparison.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ rs_optimizer_pri.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ cee_simple.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ cee_diskqueue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ incltest.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ incltest_dir.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ incltest_dir_wildcard.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ incltest_dir_empty_wildcard.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ linkedlistqueue.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table-hup-backgrounded.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table_no_hup_reload.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ key_dereference_on_uninitialized_variable_space.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ array_lookup_table.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sparse_array_lookup_table.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table_bad_configs.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table_rscript_reload.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ lookup_table_rscript_reload_without_stub.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ config_multiple_include.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ include-obj-text-from-file.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ include-obj-text-from-file-noexist.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ multiple_lookup_tables.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse1.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse1-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse2.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse2-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse_8bit_escape.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse_8bit_escape-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse3.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse3-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse_invld_regex.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse_invld_regex-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse-3164-buggyday.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse-3164-buggyday-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse-nodate.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-parse-nodate-udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-snare_ccoff_udp.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ parsertest-snare_ccoff_udp2.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBZSTD_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_10 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBZSTD_TRUE@@ENABLE_TESTBENCH_TRUE@ zstd.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBZSTD_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_11 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBZSTD_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ zstd-vg.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_12 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-encryption-disk.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-encryption-disk_keyfile.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-encryption-disk_keyprog.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@ queue-encryption-da.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_13 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omusrmsg-noabort-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omfile_hup-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ gzipwr_hup-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ tcpflood_wrong_option_output.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtcp-octet-framing-too-long-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ smtradfile-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dnscache-TTL-0-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ include-obj-outside-control-flow-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ include-obj-in-if-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ include-obj-text-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_parse_json-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_backticks-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_backticks_empty_envvar-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript-config_enable-off-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_get_property-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ prop-jsonmesg-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmexternal-InvldProg-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ internal-errmsg-memleak-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ glbl-oversizeMsg-log-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_set_memleak-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ no-parser-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ discard-rptdmsg-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ discard-allmark-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ failover-basic-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ failover-rptd-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ failover-no-basic-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ failover-no-rptd-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ timereported-utc-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ udp-msgreduc-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ udp-msgreduc-orgmsg-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ tcp-msgreduc-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_field-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_number_comparison_LE-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_str-str-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_str-num-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_str-numstr-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_num-str-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_numstr-str-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_numstr-num-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_numstr-numstr-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_num-num-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_compare_num-numstr-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ unused_lookup_table-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ lookup_table-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ lookup_table_no_hup_reload-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ array_lookup_table-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ array_lookup_table_misuse-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ sparse_array_lookup_table-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ lookup_table_bad_configs-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ lookup_table_rscript_reload-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ lookup_table_rscript_reload_without_stub-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ multiple_lookup_tables-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ fac_local0-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ badqi.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ threadingmq.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ threadingmqaq.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ func-substring-invld-startpos-vg.sh \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_trim-vg.sh
+
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_14 = \
+@ENABLE_DEFAULT_TESTS_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ queue-encryption-disk_keyfile-vg.sh
+
+@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_15 = \
+@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@ omsnmp_errmsg_no_params.sh
+
+@ENABLE_SNMP_TESTS_TRUE@@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_16 = \
+@ENABLE_SNMP_TESTS_TRUE@@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omsnmpv1_udp.sh \
+@ENABLE_SNMP_TESTS_TRUE@@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omsnmpv1_udp_dynsource.sh \
+@ENABLE_SNMP_TESTS_TRUE@@ENABLE_SNMP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omsnmpv1_udp_invalidoid.sh
+
+@ENABLE_MMUTF8FIX_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_17 = \
+@ENABLE_MMUTF8FIX_TRUE@@ENABLE_TESTBENCH_TRUE@ mmutf8fix_no_error.sh
+
+@ENABLE_MAIL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_18 = \
+@ENABLE_MAIL_TRUE@@ENABLE_TESTBENCH_TRUE@ ommail_errmsg_no_params.sh
+
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_19 = \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_with_debug.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_random_32_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_random_cons_32_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_recognize_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_12_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_33_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_8_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_simple_12_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_simple_33_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_simple_8_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_simple_mallformed_ipv4.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_random_128_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_128_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_96_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_random_cons_128_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_50_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_recognize_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_zero_64_ipv6.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_both_modes_compatible.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_recognize_ipembedded.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_ipv6_port.sh \
+@ENABLE_MMANON_TRUE@@ENABLE_TESTBENCH_TRUE@ mmanon_random_cons_128_ipembedded.sh
+
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_20 = \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-start.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-basic.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-dflt-tpl.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-retry-error.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-load.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-bulk.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-bulk-load.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-limited-batch.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-select.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-errorfile.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-wrong-quotation-marks.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-wrong-template-option.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ clickhouse-wrong-insert-syntax.sh
+
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_21 = \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ clickhouse-basic-vg.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ clickhouse-load-vg.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ clickhouse-bulk-vg.sh \
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ clickhouse-bulk-load-vg.sh
+
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_22 = clickhouse-stop.sh
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_23 = \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ now_family_utc.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ now-utc.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ now-utc-ymd.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ now-utc-casecmp.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ now-unixtimestamp.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-ymd.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-uxtimestamp.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-uxtimestamp-invld.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-dateordinal.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-dateordinal-invld.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-utc.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timegenerated-utc-legacy.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timereported-utc.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_TESTBENCH_TRUE@ timereported-utc-legacy.sh
+
+# now come faketime tests that utilize mmnormalize - aka "no endif here"
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_24 = \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_processing_test1.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_processing_test2.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_processing_test3.sh \
+@ENABLE_LIBFAKETIME_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_processing_test4.sh
+
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_25 = \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-basic.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-basic-cnf6.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-basic-threads-cnf6.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-template.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-template-cnf6.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-actq-mt-withpause.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@ pgsql-template-threads-cnf6.sh
+
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_26 = \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pgsql-basic-vg.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pgsql-template-vg.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pgsql-basic-cnf6-vg.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pgsql-template-cnf6-vg.sh \
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pgsql-actq-mt-withpause-vg.sh
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_27 = \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysqld-start.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-basic.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-basic-cnf6.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-asyn.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-actq-mt.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-actq-mt-withpause.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ action-tx-single-processing.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ action-tx-errfile-maxsize.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ action-tx-errfile.sh
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_28 = \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mysql-basic-vg.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mysql-asyn-vg.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mysql-actq-mt-withpause-vg.sh
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_29 = \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@ libdbi-basic.sh \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@ libdbi-asyn.sh
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_30 = \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ libdbi-basic-vg.sh
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_31 = mysqld-stop.sh
+@ENABLE_FMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_32 = \
+@ENABLE_FMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_http_request.sh
+
+@ENABLE_FMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_33 = \
+@ENABLE_FMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_http_request-vg.sh
+
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_34 = \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_udp.sh \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_logger_root.sh \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_traillf_root.sh \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imuxsock_ccmiddle_root.sh \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imklog_permitnonkernelfacility_root.sh
+
+@ENABLE_IP_TRUE@@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_35 = tcp_forwarding_ns_tpl.sh
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_36 = \
+@ENABLE_ROOT_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmexternal-SegFault-empty-jroot-vg.sh
+
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_37 = \
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imjournal-basic.sh \
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imjournal-statefile.sh
+
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_38 = \
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imjournal-basic-vg.sh \
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imjournal-statefile-vg.sh
+
+@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_OMJOURNAL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_39 = \
+@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_OMJOURNAL_TRUE@@ENABLE_TESTBENCH_TRUE@ omjournal-abort-template.sh \
+@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_OMJOURNAL_TRUE@@ENABLE_TESTBENCH_TRUE@ omjournal-abort-no-template.sh \
+@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_OMJOURNAL_TRUE@@ENABLE_TESTBENCH_TRUE@ omjournal-basic-template.sh \
+@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_OMJOURNAL_TRUE@@ENABLE_TESTBENCH_TRUE@ omjournal-basic-no-template.sh
+
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_40 = \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_errmsg_no_params.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_prog_simple.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_prog_confirm.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_prog_confirm_killonclose.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_prog_killonclose.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ improg_simple_multi.sh
+
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_41 = \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ improg_errmsg_no_params-vg.sh \
+@ENABLE_IMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ improg_prog_simple-vg.sh
+
+@ENABLE_MMDARWIN_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_42 = \
+@ENABLE_MMDARWIN_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdarwin_errmsg_no_params.sh \
+@ENABLE_MMDARWIN_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdarwin_errmsg_no_sock.sh
+
+@ENABLE_MMDARWIN_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_43 = \
+@ENABLE_MMDARWIN_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmdarwin_errmsg_no_sock-vg.sh
+
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_44 = \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-defaults.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-output-capture.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-output-capture-mt.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-feedback.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-feedback-mt.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-feedback-timeout.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-close-unresponsive.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-close-unresponsive-noterm.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-restart-terminated.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-restart-terminated-outfile.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-single-instance.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-single-instance-outfile.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-transactions.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-if-error.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-transactions-failed-messages.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@ omprog-transactions-failed-commits.sh
+
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_45 = \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-defaults-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-output-capture-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-feedback-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-close-unresponsive-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-restart-terminated-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-single-instance-vg.sh \
+@ENABLE_OMPROG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omprog-transactions-vg.sh
+
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_46 = \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-auth.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-basic.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-fail-with-400.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-jsonarray-compress.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-jsonarray-retry.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-jsonarray.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-kafkarest-retry.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-kafkarest.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-lokirest-retry.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-lokirest.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-newline.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-retry.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-httpheaderkey.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-multiplehttpheaders.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-dynrestpath.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ omhttp-batch-dynrestpath.sh
+
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_47 = \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-auth-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-basic-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-jsonarray-compress-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-jsonarray-retry-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-jsonarray-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-kafkarest-retry-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-lokirest-retry-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-retry-vg.sh \
+@ENABLE_OMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhttp-batch-lokirest-vg.sh
+
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_48 = \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ kafka-selftest.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ omkafka.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ omkafkadynakey.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka-backgrounded.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka-config-err-ruleset.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka-config-err-param.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka-hang-on-no-kafka.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka-hang-other-action-on-no-kafka.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka_multi_single.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ imkafka_multi_group.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_kafka.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_kafka_multi_topics.sh
+
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_49 = \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omkafka-vg.sh \
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imkafka-vg.sh
+
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_50 = \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@ omazureeventhubs-basic.sh \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@ omazureeventhubs-list.sh \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@ omazureeventhubs-stress.sh \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@ omazureeventhubs-interrupt.sh
+
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_51 = \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omazureeventhubs-basic-vg.sh \
+@ENABLE_OMAZUREEVENTHUBS_TESTS_TRUE@@ENABLE_OMAZUREEVENTHUBS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omazureeventhubs-interrupt-vg.sh
+
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_52 = \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@ imdocker-basic.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@ imdocker-long-logline.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@ imdocker-new-logs-from-start.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@ imdocker-multi-line.sh
+
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_53 = \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdocker-basic-vg.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdocker-long-logline-vg.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdocker-new-logs-from-start-vg.sh \
+@ENABLE_IMDOCKER_TESTS_TRUE@@ENABLE_IMDOCKER_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdocker-multi-line-vg.sh
+
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_54 = \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-basic-auth.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-query-params.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-large.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-multi.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-multi-lf.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-post-payload-compress.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@ imhttp-getrequest-file.sh
+
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_55 = \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-basic-auth-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-query-params-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-large-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-multi-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-multi-lf-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-post-payload-compress-vg.sh \
+@ENABLE_IMHTTP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhttp-getrequest-file-vg.sh
+
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_56 = miniamqpsrvr
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_57 = \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_no_params.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_missing0.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_missing1.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_missing2.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_invalid0.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_invalid1.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_invalid2.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_params_invalid3.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_data_1server.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_data_2servers.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_error_server0.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_error_server1.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_error_server2.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_error_server3.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_json.sh \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ omrabbitmq_raw.sh
+
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_58 = \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omrabbitmq_data_1server-vg.sh
+
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_59 = \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-queue.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-queue-lpop.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-redis-restart.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-redis-start-after.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-subscribe.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-stream.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-stream-from-beginning.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-stream-consumerGroup-ack.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-stream-consumerGroup-noack.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imhiredis-stream-consumerGroup-reclaim.sh
+
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_60 = \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-queue-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-queue-lpop-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-redis-restart-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-redis-start-after-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-subscribe-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-stream-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-stream-from-beginning-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-stream-consumerGroup-ack-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-stream-consumerGroup-noack-vg.sh \
+@ENABLE_IMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imhiredis-stream-consumerGroup-reclaim-vg.sh
+
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_61 = \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdb-reload.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-dynakey.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-publish.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-queue-rpush.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-queue.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-set.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-setex.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-template.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-withpass.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-wrongpass.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream-ack.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream-capped.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream-del.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream-dynack.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream-outfield.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ omhiredis-stream.sh
+
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_62 = \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmdb-reload-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-dynakey-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-publish-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-queue-rpush-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-queue-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-set-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-setex-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-template-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-withpass-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-wrongpass-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-ack-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-capped-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-del-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-dynack-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-outfield-vg.sh \
+@ENABLE_OMHIREDIS_TRUE@@ENABLE_REDIS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omhiredis-stream-vg.sh
+
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_63 = \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ impstats-hup.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ perctile-simple.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_overflow.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_reset.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_ctr_reset.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_nometric.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ no-dynstats-json.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ no-dynstats.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ stats-json.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats-json.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ stats-cee.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ stats-json-es.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_reset_without_pstats_reset.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ dynstats_prevent_premature_eviction.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfwd_fast_imuxsock.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfwd_impstats-udp.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@ omfwd_impstats-tcp.sh
+
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_64 = \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ perctile-simple-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dynstats-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dynstats_reset-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dynstats_overflow-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dynstats-json-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ stats-json-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ stats-cee-vg.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ dynstats_prevent_premature_eviction-vg.sh
+
+
+# note that some tests simply USE imptcp, but they also
+# need to be disabled if we do not have this module
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_65 = \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ manyptcp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_framing_regex.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_framing_regex-oversize.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_large.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-connection-msg-disabled.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-connection-msg-received.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-discard-truncated-msg.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_addtlframedelim.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_conndrop.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_no_octet_counted.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_multi_line.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_spframingfix.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_maxsessions.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_nonProcessingPoller.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp_veryLargeOctateCountedMessages.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-basic-hup.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-NUL.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-NUL-rawmsg.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_random.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_hash32.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_hash64.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_replace.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-sizelimitcmd-many.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ omfile-outchannel-many.sh
+
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_66 = \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imptcp-octet-framing-too-long-vg.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imptcp_conndrop-vg.sh
+
+@ENABLE_FMHASH_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_67 = \
+@ENABLE_FMHASH_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_hash32-vg.sh \
+@ENABLE_FMHASH_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_hash64-vg.sh
+
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_68 = \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_arg1_unsuitable.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_arg2_invalid.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_conflict1.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_conflict2.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_conflict3.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_key_truncated.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_non_object.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_object.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_unflatten_object_exclamation.sh
+
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_69 = \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_arg1_unsuitable-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_arg2_invalid-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_conflict1-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_conflict2-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_conflict3-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_key_truncated-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_non_object-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_object-vg.sh \
+@ENABLE_FMUNFLATTEN_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_unflatten_object_exclamation-vg.sh
+
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_70 = \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_all.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_all_2.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_all_empty.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_scheme.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_credential.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_subdomain.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_domain.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_domain_without_tld.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_host.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_tld.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_port.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_resource_path.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_query_string.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_fragment.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ rscript_faup_mozilla_tld.sh
+
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_71 = \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_all_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_all_2_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_all_empty_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_scheme_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_credential_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_subdomain_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_domain_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_domain_without_tld_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_host_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_tld_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_port_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_resource_path_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_query_string_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_fragment_vg.sh \
+@ENABLE_FFAUP_TRUE@@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ rscript_faup_mozilla_tld_vg.sh
+
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_72 = \
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@ mmpstrucdata.sh \
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@ mmpstrucdata-escaping.sh \
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@ mmpstrucdata-case.sh
+
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_73 = \
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmpstrucdata-vg.sh \
+@ENABLE_MMPSTRUCDATA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmpstrucdata-invalid-vg.sh
+
+@ENABLE_MMRM1STSPACE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_74 = \
+@ENABLE_MMRM1STSPACE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmrm1stspace-basic.sh
+
+@ENABLE_PMNULL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_75 = \
+@ENABLE_PMNULL_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnull-basic.sh \
+@ENABLE_PMNULL_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnull-withparams.sh
+
+@ENABLE_OMSTDOUT_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_76 = \
+@ENABLE_OMSTDOUT_TRUE@@ENABLE_TESTBENCH_TRUE@ omstdout-basic.sh
+
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_77 = \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-basic.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-invld-rulebase.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-rule.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-rule_and_rulebase.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-neither_rule_rulebase.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmnormalize-rule_invld-data.sh
+
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_78 = \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-basic-vg.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-invld-rulebase-vg.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-rule-vg.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-rule_and_rulebase-vg.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-neither_rule_rulebase-vg.sh \
+@ENABLE_PMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ pmnormalize-rule_invld-data-vg.sh
+
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_79 = msgvar-concurrency-array.sh \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ msgvar-concurrency-array-event.tags.sh \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_rule_from_string.sh \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_rule_from_array.sh \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_parsesuccess.sh
+
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_80 = \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmnormalize_parsesuccess-vg.sh
+
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_81 = \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_regex_defaulted.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_regex_disabled.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_variable.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmnormalize_tokenized.sh
+
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@LOGNORM_REGEX_SUPPORTED_TRUE@am__append_82 = \
+@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@LOGNORM_REGEX_SUPPORTED_TRUE@ mmnormalize_regex.sh
+
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_83 = \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse-w-o-cookie.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse-w-o-cookie-multi-spaces.sh
+
+@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_84 = \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse-invalid-containerName.sh \
+@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ wtpShutdownAll-assertionFailure.sh
+
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_85 = \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse_simple.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-oversize-message-display.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-msg-truncation-on-number.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-msg-truncation-on-number2.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ imptcp-maxFrameSize-parameter.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse_cim.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse_cim2.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ mmjsonparse_localvar.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_array_subscripting.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_array_looping.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_object_looping.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_nonarray_looping.sh
+
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_86 = \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmjsonparse_extra_data-vg.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ json_null_array-vg.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ json_object_looping-vg.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ json_array_looping-vg.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ json_object_suicide_in_loop-vg.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ json_null-vg.sh
+
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_87 = \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ stop_when_array_has_element.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_null_array.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_null.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_var_cmpr.sh \
+@ENABLE_MMJSONPARSE_TRUE@@ENABLE_TESTBENCH_TRUE@ json_var_case.sh
+
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_88 = \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdb.sh \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdb-space.sh \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdb-container.sh \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@ mmdb-container-empty.sh
+
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_89 = \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmdb-vg.sh \
+@ENABLE_MMDBLOOKUP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmdb-multilevel-vg.sh
+
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_90 = \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-basic.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-input-basic.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-input-2certs.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-basic-verifydepth.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp_conndrop_tls.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_anon_rebind.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_anon_hostname.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_anon_ipv4.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_anon_ipv6.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certless_clientonly.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_gtls_servercert_gtls_clientanon.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_gtls_serveranon_gtls_clientanon.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_priorityString.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid_action_level.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid_expired.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid_expired_defaultmode.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid_revoked.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_client_missing_cert.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-no-lstn-startup.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-gtls-x509fingerprint-invld.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-gtls-x509fingerprint.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-gtls-x509name-invld.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-gtls-x509name.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-gtls-x509name-legacy.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-drvr-in-input-basic.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-multi-drvr-basic.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-multi-drvr-basic-parallel.sh
+
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_91 = \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtcp-tls-basic-vg.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtcp_conndrop_tls-vg.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ manytcp-too-few-tls-vg.sh
+
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_92 = \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh
+
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_93 = \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-basic.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-input-basic.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-input-2certs.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-basic-tlscommands.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-basic-verifydepth.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-invalid-verifydepth.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_anon_ipv4.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_anon_ipv6.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_anon_rebind.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_anon_ciphers.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_serveranon_ossl_clientanon.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid_action_level.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid_expired.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid_tlscommand.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid_ciphers.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_certvalid_revoked.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-x509valid.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-x509name.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-x509fingerprint.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-error-ca.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-error-cert.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-error-key.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ imtcp-tls-ossl-error-key2.sh
+
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_94 = \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtcp-tls-ossl-basic-vg.sh \
+@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtcp-tls-ossl-basic-brokenhandshake-vg.sh
+
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_95 = \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_servercert_gtls_clientanon.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_ossl_serveranon_gtls_clientanon.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_gtls_servercert_ossl_clientanon.sh \
+@ENABLE_GNUTLS_TESTS_TRUE@@ENABLE_OPENSSL_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_gtls_serveranon_ossl_clientanon.sh
+
+@ENABLE_OMUXSOCK_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_96 = uxsock_simple.sh
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_97 = sndrcv_relp.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_rebind.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ omrelp_errmsg_no_connect.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-basic.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-basic-oldstyle.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-basic-hup.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-manyconn.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-maxDataSize-error.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-long-msg.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-oversizeMode-truncate.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-oversizeMode-accept.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-invld-tlslib.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-bigmessage.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ omrelp-invld-tlslib.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_dflt_pt.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-oversizeMsg-log.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-oversizeMsg-truncate.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-oversizeMsg-split.sh
+
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_98 = \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_tls.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_tls_certvalid.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_tls_certvalid_action_level.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_tls_prio.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_relp_tls_chainedcert.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ relp_tls_certificate_not_found.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ omrelp_wrong_authmode.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-tls.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-tls-chainedcert.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-tls-mixed-chainedcert.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@ imrelp-tls-mixed-chainedcert2.sh
+
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@USE_RELPENGINESETTLSCFGCMD_TRUE@am__append_99 = \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@USE_RELPENGINESETTLSCFGCMD_TRUE@ imrelp-tls-cfgcmd.sh \
+@ENABLE_GNUTLS_TRUE@@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@USE_RELPENGINESETTLSCFGCMD_TRUE@ sndrcv_relp_tls-cfgcmd.sh
+
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_100 = \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imrelp-basic-vg.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imrelp-sessionbreak-vg.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imrelp-manyconn-vg.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ sndrcv_relp-vg-rcvr.sh \
+@ENABLE_RELP_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ sndrcv_relp-vg-sender.sh
+
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_101 = \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ imdtls-basic.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ imdtls-basic-tlscommands.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ imdtls-basic-timeout.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ imdtls-error-cert.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ imdtls-sessionbreak.sh
+
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_102 = \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdtls-basic-vg.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imdtls-sessionbreak-vg.sh
+
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_103 = \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_certvalid.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_anon_ciphers.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_certvalid_ciphers.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_certvalid_permitted.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_certvalid_missing.sh \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_dtls_anon_ciphers.sh
+
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_104 = \
+@ENABLE_IMDTLS_TRUE@@ENABLE_OMDTLS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ sndrcv_dtls_certvalid-vg.sh
+
+@ENABLE_OMUDPSPOOF_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_105 = \
+@ENABLE_OMUDPSPOOF_TRUE@@ENABLE_TESTBENCH_TRUE@ omudpspoof_errmsg_no_params.sh \
+@ENABLE_OMUDPSPOOF_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omudpspoof.sh \
+@ENABLE_OMUDPSPOOF_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omudpspoof-bigmsg.sh \
+@ENABLE_OMUDPSPOOF_TRUE@@ENABLE_TESTBENCH_TRUE@ sndrcv_omudpspoof_nonstdpt.sh
+
+
+#disabled as array-passing mode is no longer supported: omod-if-array.sh
+# omod-if-array.sh
+# omod-if-array-udp.sh
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_106 = \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ tabescape_dflt.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ tabescape_dflt-udp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ tabescape_off.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ tabescape_off-udp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ tabescape_on.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ inputname-imtcp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ fieldtest.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ fieldtest-udp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ proprepltest-nolimittag-udp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ proprepltest-nolimittag.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ proprepltest-rfctag-udp.sh \
+@ENABLE_IMPTCP_TRUE@@ENABLE_TESTBENCH_TRUE@ proprepltest-rfctag.sh
+
+@ENABLE_OMRULESET_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_107 = \
+@ENABLE_OMRULESET_TRUE@@ENABLE_TESTBENCH_TRUE@ omruleset.sh \
+@ENABLE_OMRULESET_TRUE@@ENABLE_TESTBENCH_TRUE@ omruleset-queue.sh
+
+@ENABLE_PMDB2DIAG_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_108 = \
+@ENABLE_PMDB2DIAG_TRUE@@ENABLE_TESTBENCH_TRUE@ pmdb2diag_parse.sh
+
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_109 = \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-default.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-default-udp.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccoff.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccoff-udp.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccdefault.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccdefault-udp.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-cccstyle.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-cccstyle-udp.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccbackslash.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-ccbackslash-udp.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-modoverride.sh \
+@ENABLE_PMSNARE_TRUE@@ENABLE_TESTBENCH_TRUE@ pmsnare-modoverride-udp.sh
+
+@ENABLE_PMLASTMSG_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_110 = \
+@ENABLE_PMLASTMSG_TRUE@@ENABLE_TESTBENCH_TRUE@ pmlastmsg.sh \
+@ENABLE_PMLASTMSG_TRUE@@ENABLE_TESTBENCH_TRUE@ pmlastmsg-udp.sh
+
+
+# random.sh is temporarily disabled as it needs some work
+# to rsyslog core to complete in reasonable time
+#TESTS += random.sh
+@ENABLE_EXTENDED_TESTS_TRUE@@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_111 = \
+@ENABLE_EXTENDED_TESTS_TRUE@@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-basic-2GB-file.sh \
+@ENABLE_EXTENDED_TESTS_TRUE@@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-truncate-2GB-file.sh
+
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_112 = \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-basic.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-basic-legacy.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-discard-truncated-line.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-truncate-line.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-file-not-found-error.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-fileNotFoundError-parameter.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-error-not-repeated.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-truncate.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-truncate-multiple.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-readmode2.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-readmode2-polling.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-readmode2-with-persists-data-during-stop.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-readmode2-with-persists.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-save-lf.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-save-lf-persist.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout-none-polling.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout-polling.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout-none.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout-with-shutdown.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endregex-timeout-with-shutdown-polling.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endmsg.regex.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-escapelf.replacement.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-escapelf.replacement-empty.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-statefile-no-file_id.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-statefile-no-file_id-TO-file_id.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-statefile-directory.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-statefile-delete.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-statefile-no-delete.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-persist-state-1.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-freshStartTail1.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-freshStartTail2.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-freshStartTail3.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs2.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi2.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi3.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi4.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi5.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-wildcards-dirs-multi5-polling.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-old-state-file.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-rename-while-stopped.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-rename.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-symlink.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-symlink-multi.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-symlink-ext-tmp-dir-tree.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-logrotate.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-logrotate-async.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-logrotate-multiple.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-logrotate-copytruncate.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-logrotate-nocopytruncate.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-growing-file-id.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-1.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-2.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-3.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-4.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-5.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-6.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-ignore-old-file-7.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ glbl-oversizeMsg-truncate-imfile.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ config_enabled-on.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ config_enabled-off.sh
+
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_113 = \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@ imfile-endmsg.regex-with-example.sh
+
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_114 = \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-basic-vg.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-endregex-vg.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-endmsg.regex-vg.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-readmode0-vg.sh \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-readmode2-vg.sh
+
+@ENABLE_HELGRIND_TRUE@@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_115 = \
+@ENABLE_HELGRIND_TRUE@@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-basic-vgthread.sh
+
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_116 = \
+@ENABLE_IMFILE_TESTS_TRUE@@ENABLE_MMNORMALIZE_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imfile-endmsg.regex-with-example-vg.sh
+
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_117 = \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_no_params.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_glob_not_regular.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_glob_dir_fake.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_glob_dir_not_dir.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_regex.match.reject.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_regex.match.rename.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_regex.nomatch.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_not_supported1.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_not_supported2.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_not_supported3.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_delete_params.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_errmsg_rename_params.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_delete_success.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_delete_structdata.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_rename_success.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_delete_toolarge.sh \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@ imbatchreport_rename_toolarge.sh
+
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_118 = \
+@ENABLE_IMBATCHREPORT_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imbatchreport_errmsg_no_params-vg.sh
+
+@ENABLE_OMTCL_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_119 = \
+@ENABLE_OMTCL_TRUE@@ENABLE_TESTBENCH_TRUE@ omtcl.sh
+
+@ENABLE_MMTAGHOSTNAME_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_120 = \
+@ENABLE_MMTAGHOSTNAME_TRUE@@ENABLE_TESTBENCH_TRUE@ mmtaghostname_tag.sh \
+@ENABLE_MMTAGHOSTNAME_TRUE@@ENABLE_TESTBENCH_TRUE@ mmtaghostname_server.sh
+
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_121 = \
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@ mmkubernetes-basic.sh \
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@ mmkubernetes-cache-expire.sh
+
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_122 = \
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmkubernetes-basic-vg.sh \
+@ENABLE_IMFILE_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_MMJSONPARSE_TRUE@@ENABLE_MMKUBERNETES_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mmkubernetes-cache-expire-vg.sh
+
+@ENABLE_IMTUXEDOULOG_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_123 = \
+@ENABLE_IMTUXEDOULOG_TRUE@@ENABLE_TESTBENCH_TRUE@ imtuxedoulog_errmsg_no_params.sh \
+@ENABLE_IMTUXEDOULOG_TRUE@@ENABLE_TESTBENCH_TRUE@ imtuxedoulog_data.sh
+
+@ENABLE_IMTUXEDOULOG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_124 = \
+@ENABLE_IMTUXEDOULOG_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ imtuxedoulog_errmsg_no_params-vg.sh
+
+@ENABLE_OMAMQP1_TRUE@@ENABLE_TESTBENCH_TRUE@am__append_125 = \
+@ENABLE_OMAMQP1_TRUE@@ENABLE_TESTBENCH_TRUE@ omamqp1-basic.sh
+
+@ENABLE_OMAMQP1_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@am__append_126 = \
+@ENABLE_OMAMQP1_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ omamqp1-basic-vg.sh
+
+@ENABLE_GNUTLS_TRUE@am__append_127 = $(GNUTLS_CFLAGS)
+@ENABLE_GNUTLS_TRUE@am__append_128 = $(GNUTLS_CFLAGS)
+@ENABLE_GNUTLS_TRUE@am__append_129 = $(GNUTLS_LIBS)
+@ENABLE_OPENSSL_TRUE@am__append_130 = $(OPENSSL_CFLAGS)
+@ENABLE_OPENSSL_TRUE@am__append_131 = $(OPENSSL_CFLAGS)
+@ENABLE_OPENSSL_TRUE@am__append_132 = $(OPENSSL_LIBS)
+subdir = tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = set-envvars
+CONFIG_CLEAN_VPATH_FILES =
+@ENABLE_IMJOURNAL_TRUE@@ENABLE_JOURNAL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@am__EXEEXT_1 = journal_print$(EXEEXT)
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@am__EXEEXT_2 = miniamqpsrvr$(EXEEXT)
+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)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+liboverride_getaddrinfo_la_LIBADD =
+am__liboverride_getaddrinfo_la_SOURCES_DIST = override_getaddrinfo.c
+@ENABLE_TESTBENCH_TRUE@am_liboverride_getaddrinfo_la_OBJECTS = liboverride_getaddrinfo_la-override_getaddrinfo.lo
+liboverride_getaddrinfo_la_OBJECTS = \
+ $(am_liboverride_getaddrinfo_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 =
+liboverride_getaddrinfo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(liboverride_getaddrinfo_la_CFLAGS) $(CFLAGS) \
+ $(liboverride_getaddrinfo_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_TESTBENCH_TRUE@am_liboverride_getaddrinfo_la_rpath = -rpath \
+@ENABLE_TESTBENCH_TRUE@ $(pkglibdir)
+liboverride_gethostname_la_LIBADD =
+am__liboverride_gethostname_la_SOURCES_DIST = override_gethostname.c
+@ENABLE_TESTBENCH_TRUE@am_liboverride_gethostname_la_OBJECTS = liboverride_gethostname_la-override_gethostname.lo
+liboverride_gethostname_la_OBJECTS = \
+ $(am_liboverride_gethostname_la_OBJECTS)
+liboverride_gethostname_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(liboverride_gethostname_la_CFLAGS) $(CFLAGS) \
+ $(liboverride_gethostname_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_TESTBENCH_TRUE@am_liboverride_gethostname_la_rpath = -rpath \
+@ENABLE_TESTBENCH_TRUE@ $(pkglibdir)
+liboverride_gethostname_nonfqdn_la_LIBADD =
+am__liboverride_gethostname_nonfqdn_la_SOURCES_DIST = \
+ override_gethostname_nonfqdn.c
+@ENABLE_TESTBENCH_TRUE@am_liboverride_gethostname_nonfqdn_la_OBJECTS = liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.lo
+liboverride_gethostname_nonfqdn_la_OBJECTS = \
+ $(am_liboverride_gethostname_nonfqdn_la_OBJECTS)
+liboverride_gethostname_nonfqdn_la_LINK = $(LIBTOOL) $(AM_V_lt) \
+ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(liboverride_gethostname_nonfqdn_la_CFLAGS) $(CFLAGS) \
+ $(liboverride_gethostname_nonfqdn_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_TESTBENCH_TRUE@am_liboverride_gethostname_nonfqdn_la_rpath = \
+@ENABLE_TESTBENCH_TRUE@ -rpath $(pkglibdir)
+check_relpEngineVersion_SOURCES = check_relpEngineVersion.c
+check_relpEngineVersion_OBJECTS = check_relpEngineVersion.$(OBJEXT)
+check_relpEngineVersion_LDADD = $(LDADD)
+am_chkseq_OBJECTS = chkseq.$(OBJEXT)
+chkseq_OBJECTS = $(am_chkseq_OBJECTS)
+chkseq_LDADD = $(LDADD)
+am_diagtalker_OBJECTS = diagtalker.$(OBJEXT)
+diagtalker_OBJECTS = $(am_diagtalker_OBJECTS)
+am__DEPENDENCIES_1 =
+diagtalker_DEPENDENCIES = $(am__DEPENDENCIES_1)
+have_relpEngineSetTLSLibByName_SOURCES = \
+ have_relpEngineSetTLSLibByName.c
+have_relpEngineSetTLSLibByName_OBJECTS = \
+ have_relpEngineSetTLSLibByName.$(OBJEXT)
+have_relpEngineSetTLSLibByName_LDADD = $(LDADD)
+have_relpSrvSetOversizeMode_SOURCES = have_relpSrvSetOversizeMode.c
+have_relpSrvSetOversizeMode_OBJECTS = \
+ have_relpSrvSetOversizeMode.$(OBJEXT)
+have_relpSrvSetOversizeMode_LDADD = $(LDADD)
+have_relpSrvSetTlsConfigCmd_SOURCES = have_relpSrvSetTlsConfigCmd.c
+have_relpSrvSetTlsConfigCmd_OBJECTS = \
+ have_relpSrvSetTlsConfigCmd.$(OBJEXT)
+have_relpSrvSetTlsConfigCmd_LDADD = $(LDADD)
+am_inputfilegen_OBJECTS = inputfilegen.$(OBJEXT)
+inputfilegen_OBJECTS = $(am_inputfilegen_OBJECTS)
+inputfilegen_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_journal_print_OBJECTS = journal_print-journal_print.$(OBJEXT)
+journal_print_OBJECTS = $(am_journal_print_OBJECTS)
+journal_print_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_mangle_qi_OBJECTS = mangle_qi.$(OBJEXT)
+mangle_qi_OBJECTS = $(am_mangle_qi_OBJECTS)
+mangle_qi_LDADD = $(LDADD)
+am__miniamqpsrvr_SOURCES_DIST = miniamqpsrvr.c
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@am_miniamqpsrvr_OBJECTS = miniamqpsrvr-miniamqpsrvr.$(OBJEXT)
+miniamqpsrvr_OBJECTS = $(am_miniamqpsrvr_OBJECTS)
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@miniamqpsrvr_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@ $(am__DEPENDENCIES_1)
+am_minitcpsrv_OBJECTS = minitcpsrvr.$(OBJEXT)
+minitcpsrv_OBJECTS = $(am_minitcpsrv_OBJECTS)
+minitcpsrv_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_msleep_OBJECTS = msleep.$(OBJEXT)
+msleep_OBJECTS = $(am_msleep_OBJECTS)
+msleep_LDADD = $(LDADD)
+am_omrelp_dflt_port_OBJECTS = omrelp_dflt_port.$(OBJEXT)
+omrelp_dflt_port_OBJECTS = $(am_omrelp_dflt_port_OBJECTS)
+omrelp_dflt_port_LDADD = $(LDADD)
+am_ourtail_OBJECTS = ourtail.$(OBJEXT)
+ourtail_OBJECTS = $(am_ourtail_OBJECTS)
+ourtail_LDADD = $(LDADD)
+am_randomgen_OBJECTS = randomgen.$(OBJEXT)
+randomgen_OBJECTS = $(am_randomgen_OBJECTS)
+randomgen_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_syslog_caller_OBJECTS = syslog_caller-syslog_caller.$(OBJEXT)
+syslog_caller_OBJECTS = $(am_syslog_caller_OBJECTS)
+syslog_caller_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_tcpflood_OBJECTS = tcpflood-tcpflood.$(OBJEXT)
+tcpflood_OBJECTS = $(am_tcpflood_OBJECTS)
+@ENABLE_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@ENABLE_OPENSSL_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+tcpflood_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_3)
+tcpflood_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(tcpflood_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_test_id_OBJECTS = test_id.$(OBJEXT)
+test_id_OBJECTS = $(am_test_id_OBJECTS)
+test_id_LDADD = $(LDADD)
+am_uxsockrcvr_OBJECTS = uxsockrcvr.$(OBJEXT)
+uxsockrcvr_OBJECTS = $(am_uxsockrcvr_OBJECTS)
+uxsockrcvr_DEPENDENCIES = $(am__DEPENDENCIES_1)
+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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/check_relpEngineVersion.Po \
+ ./$(DEPDIR)/chkseq.Po ./$(DEPDIR)/diagtalker.Po \
+ ./$(DEPDIR)/have_relpEngineSetTLSLibByName.Po \
+ ./$(DEPDIR)/have_relpSrvSetOversizeMode.Po \
+ ./$(DEPDIR)/have_relpSrvSetTlsConfigCmd.Po \
+ ./$(DEPDIR)/inputfilegen.Po \
+ ./$(DEPDIR)/journal_print-journal_print.Po \
+ ./$(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Plo \
+ ./$(DEPDIR)/liboverride_gethostname_la-override_gethostname.Plo \
+ ./$(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Plo \
+ ./$(DEPDIR)/mangle_qi.Po \
+ ./$(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po \
+ ./$(DEPDIR)/minitcpsrvr.Po ./$(DEPDIR)/msleep.Po \
+ ./$(DEPDIR)/omrelp_dflt_port.Po ./$(DEPDIR)/ourtail.Po \
+ ./$(DEPDIR)/randomgen.Po \
+ ./$(DEPDIR)/syslog_caller-syslog_caller.Po \
+ ./$(DEPDIR)/tcpflood-tcpflood.Po ./$(DEPDIR)/test_id.Po \
+ ./$(DEPDIR)/uxsockrcvr.Po
+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 = $(liboverride_getaddrinfo_la_SOURCES) \
+ $(liboverride_gethostname_la_SOURCES) \
+ $(liboverride_gethostname_nonfqdn_la_SOURCES) \
+ check_relpEngineVersion.c $(chkseq_SOURCES) \
+ $(diagtalker_SOURCES) have_relpEngineSetTLSLibByName.c \
+ have_relpSrvSetOversizeMode.c have_relpSrvSetTlsConfigCmd.c \
+ $(inputfilegen_SOURCES) $(journal_print_SOURCES) \
+ $(mangle_qi_SOURCES) $(miniamqpsrvr_SOURCES) \
+ $(minitcpsrv_SOURCES) $(msleep_SOURCES) \
+ $(omrelp_dflt_port_SOURCES) $(ourtail_SOURCES) \
+ $(randomgen_SOURCES) $(syslog_caller_SOURCES) \
+ $(tcpflood_SOURCES) $(test_id_SOURCES) $(uxsockrcvr_SOURCES)
+DIST_SOURCES = $(am__liboverride_getaddrinfo_la_SOURCES_DIST) \
+ $(am__liboverride_gethostname_la_SOURCES_DIST) \
+ $(am__liboverride_gethostname_nonfqdn_la_SOURCES_DIST) \
+ check_relpEngineVersion.c $(chkseq_SOURCES) \
+ $(diagtalker_SOURCES) have_relpEngineSetTLSLibByName.c \
+ have_relpSrvSetOversizeMode.c have_relpSrvSetTlsConfigCmd.c \
+ $(inputfilegen_SOURCES) $(journal_print_SOURCES) \
+ $(mangle_qi_SOURCES) $(am__miniamqpsrvr_SOURCES_DIST) \
+ $(minitcpsrv_SOURCES) $(msleep_SOURCES) \
+ $(omrelp_dflt_port_SOURCES) $(ourtail_SOURCES) \
+ $(randomgen_SOURCES) $(syslog_caller_SOURCES) \
+ $(tcpflood_SOURCES) $(test_id_SOURCES) $(uxsockrcvr_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=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ 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)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.sh.log=.log)
+SH_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+SH_LOG_COMPILE = $(SH_LOG_COMPILER) $(AM_SH_LOG_FLAGS) $(SH_LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/set-envvars.in \
+ $(top_srcdir)/depcomp $(top_srcdir)/test-driver README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+TEST_EXTENSIONS = .sh
+@ENABLE_TESTBENCH_TRUE@CLEANFILES = *_*.conf rsyslog*.started \
+@ENABLE_TESTBENCH_TRUE@ work-*.conf rsyslog.random.data \
+@ENABLE_TESTBENCH_TRUE@ rsyslog*.pid.save xlate*.lkp_tbl log \
+@ENABLE_TESTBENCH_TRUE@ log* *.log work test-spool test-logdir \
+@ENABLE_TESTBENCH_TRUE@ stat-file1 rsyslog.pipe rsyslog.input.* \
+@ENABLE_TESTBENCH_TRUE@ rsyslog.input rsyslog.input.* \
+@ENABLE_TESTBENCH_TRUE@ imfile-state:* omkafka-failed.data \
+@ENABLE_TESTBENCH_TRUE@ rsyslog.input-symlink.log \
+@ENABLE_TESTBENCH_TRUE@ rsyslog-link.*.log targets HOSTNAME \
+@ENABLE_TESTBENCH_TRUE@ rstb_* zookeeper.pid tmp.qi nocert \
+@ENABLE_TESTBENCH_TRUE@ IN_AUTO_DEBUG
+# IN_AUTO_DEBUG should be deleted each time make check is run, but
+# there exists no such hook. Se we at least delete it on make clean.
+@ENABLE_TESTBENCH_TRUE@pkglib_LTLIBRARIES = \
+@ENABLE_TESTBENCH_TRUE@ liboverride_gethostname.la \
+@ENABLE_TESTBENCH_TRUE@ liboverride_gethostname_nonfqdn.la \
+@ENABLE_TESTBENCH_TRUE@ liboverride_getaddrinfo.la
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_la_SOURCES = override_gethostname.c
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_la_CFLAGS =
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_la_LDFLAGS = -avoid-version -shared
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_nonfqdn_la_SOURCES = override_gethostname_nonfqdn.c
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_nonfqdn_la_CFLAGS =
+@ENABLE_TESTBENCH_TRUE@liboverride_gethostname_nonfqdn_la_LDFLAGS = -avoid-version -shared
+@ENABLE_TESTBENCH_TRUE@liboverride_getaddrinfo_la_SOURCES = override_getaddrinfo.c
+@ENABLE_TESTBENCH_TRUE@liboverride_getaddrinfo_la_CFLAGS =
+@ENABLE_TESTBENCH_TRUE@liboverride_getaddrinfo_la_LDFLAGS = -avoid-version -shared
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@miniamqpsrvr_SOURCES = miniamqpsrvr.c
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@miniamqpsrvr_CPPFLAGS = $(PTHREADS_CFLAGS) $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS)
+@ENABLE_OMRABBITMQ_TRUE@@ENABLE_TESTBENCH_TRUE@miniamqpsrvr_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS)
+TESTS_ENVIRONMENT = \
+ RSYSLOG_MODDIR='$(abs_top_builddir)'/runtime/.libs/ \
+ TOP_BUILDDIR='$(top_builddir)' \
+ TESTTOOL_DIR='$(abs_top_builddir)/tests'
+test_files = testbench.h runtime-dummy.c
+DISTCLEANFILES = rsyslog.pid
+EXTRA_DIST = \
+ set-envvars.in \
+ urlencode.py \
+ dnscache-TTL-0.sh \
+ dnscache-TTL-0-vg.sh \
+ loadbalance.sh \
+ smtradfile.sh \
+ smtradfile-vg.sh \
+ immark.sh \
+ immark-inputname.sh \
+ immark-ruleset.sh \
+ immark-ruleset-custom-msg.sh \
+ operatingstate-basic.sh \
+ operatingstate-empty.sh \
+ operatingstate-unclean.sh \
+ internal-errmsg-memleak-vg.sh \
+ glbl-ruleset-queue-defaults.sh \
+ glbl-internalmsg_severity-info-shown.sh \
+ glbl-internalmsg_severity-debug-shown.sh \
+ glbl-internalmsg_severity-debug-not_shown.sh \
+ glbl-oversizeMsg-log-vg.sh \
+ config_enabled-on.sh \
+ config_enabled-off.sh \
+ empty-app-name.sh \
+ empty-hostname.sh \
+ func-substring-invld-startpos.sh \
+ func-substring-invld-startpos-vg.sh \
+ func-substring-large-endpos.sh \
+ func-substring-large-neg-endpos.sh \
+ func-substring-relative-endpos.sh \
+ hostname-with-slash-pmrfc5424.sh \
+ hostname-with-slash-pmrfc3164.sh \
+ pmrfc3164-msgFirstSpace.sh \
+ pmrfc3164-AtSignsInHostname.sh \
+ pmrfc3164-AtSignsInHostname_off.sh \
+ pmrfc3164-tagEndingByColon.sh \
+ pmrfc3164-defaultTag.sh \
+ pmrfc3164-json.sh \
+ hostname-with-slash-dflt-invld.sh \
+ hostname-with-slash-dflt-slash-valid.sh \
+ glbl-umask.sh \
+ glbl-unloadmodules.sh \
+ glbl-invld-param.sh \
+ glbl_setenv_2_vars.sh \
+ glbl_setenv_err.sh \
+ glbl_setenv_err_too_long.sh \
+ glbl_setenv.sh \
+ imtuxedoulog_errmsg_no_params.sh \
+ imtuxedoulog_data.sh \
+ imtuxedoulog_errmsg_no_params-vg.sh \
+ pmdb2diag_parse.sh \
+ mmtaghostname_tag.sh \
+ mmtaghostname_server.sh \
+ imbatchreport_errmsg_no_params.sh \
+ imbatchreport_errmsg_glob_not_regular.sh \
+ imbatchreport_errmsg_glob_dir_fake.sh \
+ imbatchreport_errmsg_glob_dir_not_dir.sh \
+ imbatchreport_errmsg_regex.match.reject.sh \
+ imbatchreport_errmsg_regex.match.rename.sh \
+ imbatchreport_errmsg_regex.nomatch.sh \
+ imbatchreport_errmsg_not_supported1.sh \
+ imbatchreport_errmsg_not_supported2.sh \
+ imbatchreport_errmsg_not_supported3.sh \
+ imbatchreport_errmsg_delete_params.sh \
+ imbatchreport_errmsg_rename_params.sh \
+ imbatchreport_delete_success.sh \
+ imbatchreport_delete_structdata.sh \
+ imbatchreport_rename_success.sh \
+ imbatchreport_delete_toolarge.sh \
+ imbatchreport_rename_toolarge.sh \
+ imbatchreport_errmsg_no_params-vg.sh \
+ mmexternal-SegFault.sh \
+ mmexternal-SegFault-empty-jroot-vg.sh \
+ testsuites/mmexternal-SegFault-mm-python.py \
+ mmexternal-InvldProg-vg.sh \
+ nested-call-shutdown.sh \
+ 1.rstest 2.rstest 3.rstest err1.rstest \
+ config_multiple_include.sh \
+ testsuites/include-std1-omfile-action.conf \
+ testsuites/include-std2-omfile-action.conf \
+ invalid_nested_include.sh \
+ validation-run.sh \
+ tls-certs/ca-key.pem \
+ tls-certs/ca.pem \
+ tls-certs/cert.pem \
+ tls-certs/certchained.pem \
+ tls-certs/key.pem \
+ tls-certs/ca-fail.pem \
+ tls-certs/cert-fail.pem \
+ tls-certs/key-fail.pem \
+ testsuites/x.509/ca.srl \
+ testsuites/x.509/client-cert-new.pem \
+ testsuites/x.509/client-new.csr \
+ testsuites/x.509/client-revoked-key.pem \
+ testsuites/x.509/client-revoked-valid.pem \
+ testsuites/x.509/client-revoked.csr \
+ testsuites/x.509/client-revoked.pem \
+ testsuites/x.509/crl.pem \
+ testsuites/x.509/index.txt \
+ testsuites/x.509/index.txt.attr \
+ testsuites/x.509/newcerts/01.pem \
+ testsuites/x.509/newcerts/02.pem \
+ testsuites/x.509/newcerts/03.pem \
+ testsuites/x.509/newcerts/04.pem \
+ testsuites/x.509/openssl-cmds.sh \
+ testsuites/x.509/openssl.cnf \
+ testsuites/x.509/serial \
+ testsuites/x.509/ca.pem \
+ testsuites/x.509/ca-key.pem \
+ testsuites/x.509/client-cert.pem \
+ testsuites/x.509/client-key.pem \
+ testsuites/x.509/machine-cert.pem \
+ testsuites/x.509/machine-key.pem \
+ testsuites/x.509/client-expired-cert.pem \
+ testsuites/x.509/client-expired-key.pem \
+ cfg.sh \
+ cfg1.cfgtest \
+ cfg1.testin \
+ cfg2.cfgtest \
+ cfg2.testin \
+ cfg3.cfgtest \
+ cfg3.testin \
+ cfg4.cfgtest \
+ cfg4.testin \
+ DevNull.cfgtest \
+ err1.rstest \
+ NoExistFile.cfgtest \
+ tcp_forwarding_tpl.sh \
+ tcp_forwarding_ns_tpl.sh \
+ tcp_forwarding_dflt_tpl.sh \
+ tcp_forwarding_retries.sh \
+ mainq_actq_DA.sh \
+ queue_warnmsg-oversize.sh \
+ queue-minbatch.sh \
+ queue-minbatch-queuefull.sh \
+ queue-direct-with-no-params.sh \
+ queue-direct-with-params-given.sh \
+ killrsyslog.sh \
+ parsertest-parse1.sh \
+ parsertest-parse1-udp.sh \
+ parsertest-parse2.sh \
+ parsertest-parse2-udp.sh \
+ parsertest-parse_8bit_escape.sh \
+ parsertest-parse_8bit_escape-udp.sh \
+ parsertest-parse3.sh \
+ parsertest-parse3-udp.sh \
+ parsertest-parse_invld_regex.sh \
+ parsertest-parse_invld_regex-udp.sh \
+ parsertest-parse-3164-buggyday.sh \
+ parsertest-parse-3164-buggyday-udp.sh \
+ parsertest-parse-nodate.sh \
+ parsertest-parse-nodate-udp.sh \
+ parsertest-snare_ccoff_udp.sh \
+ parsertest-snare_ccoff_udp2.sh \
+ fieldtest.sh \
+ fieldtest-udp.sh \
+ proprepltest-nolimittag-udp.sh \
+ proprepltest-nolimittag.sh \
+ proprepltest-rfctag-udp.sh \
+ proprepltest-rfctag.sh \
+ timestamp-3164.sh \
+ timestamp-3339.sh \
+ timestamp-isoweek.sh \
+ timestamp-mysql.sh \
+ timestamp-pgsql.sh \
+ timestamp-subseconds.sh \
+ rsf_getenv.sh \
+ diskq-rfc5424.sh \
+ rfc5424parser-sp_at_msg_start.sh \
+ diskqueue-full.sh \
+ diskqueue-fail.sh \
+ diskqueue.sh \
+ diskqueue-non-unique-prefix.sh \
+ arrayqueue.sh \
+ include-obj-text-from-file.sh \
+ include-obj-text-from-file-noexist.sh \
+ include-obj-outside-control-flow-vg.sh \
+ include-obj-in-if-vg.sh \
+ include-obj-text-vg.sh \
+ config_output-o-option.sh \
+ rscript-config_enable-off-vg.sh \
+ rscript-config_enable-on.sh \
+ rscript_http_request.sh \
+ rscript_http_request-vg.sh \
+ rscript_bare_var_root.sh \
+ rscript_bare_var_root-empty.sh \
+ rscript_contains.sh \
+ rscript_ipv42num.sh \
+ rscript_field.sh \
+ rscript_field-vg.sh \
+ rscript_stop.sh \
+ rscript_stop2.sh \
+ stop.sh \
+ rscript_le.sh \
+ rscript_le_var.sh \
+ rscript_ge.sh \
+ rscript_ge_var.sh \
+ rscript_lt.sh \
+ rscript_lt_var.sh \
+ rscript_gt.sh \
+ rscript_gt_var.sh \
+ rscript_ne.sh \
+ rscript_ne_var.sh \
+ rscript_number_comparison_LE.sh \
+ rscript_number_comparison_LE-vg.sh \
+ rscript_number_comparison_LT.sh \
+ rscript_compare_str-numstr.sh \
+ rscript_compare_str-num.sh \
+ rscript_compare_numstr-str.sh \
+ rscript_compare_num-str.sh \
+ rscript_compare_numstr-numstr.sh \
+ rscript_compare_numstr-num.sh \
+ rscript_compare_num-numstr.sh \
+ rscript_compare_num-num.sh \
+ rscript_compare_str-str.sh \
+ rscript_compare_str-str-vg.sh \
+ rscript_compare_str-num-vg.sh \
+ rscript_compare_str-numstr-vg.sh \
+ rscript_compare_num-str-vg.sh \
+ rscript_compare_numstr-str-vg.sh \
+ rscript_compare_numstr-num-vg.sh \
+ rscript_compare_numstr-numstr-vg.sh \
+ rscript_compare_num-num-vg.sh \
+ rscript_compare_num-numstr-vg.sh \
+ rscript_compare-common.sh \
+ rscript_num2ipv4.sh \
+ rscript_int2Hex.sh \
+ rscript_trim.sh \
+ rscript_substring.sh \
+ rscript_format_time.sh \
+ rscript_parse_time.sh \
+ rscript_parse_time_get-ts.py \
+ rscript_is_time.sh \
+ rscript_script_error.sh \
+ rscript_parse_json.sh \
+ rscript_parse_json-vg.sh \
+ rscript_backticks-vg.sh \
+ rscript_backticks_empty_envvar-vg.sh \
+ rscript_previous_action_suspended.sh \
+ rscript_str2num_negative.sh \
+ rscript_exists-yes.sh \
+ rscript_exists-yes2.sh \
+ rscript_exists-not1.sh \
+ rscript_exists-not2.sh \
+ rscript_exists-not3.sh \
+ rscript_exists-not4.sh \
+ rscript_unflatten_arg1_unsuitable.sh \
+ rscript_unflatten_arg2_invalid.sh \
+ rscript_unflatten_conflict1.sh \
+ rscript_unflatten_conflict2.sh \
+ rscript_unflatten_conflict3.sh \
+ rscript_unflatten_key_truncated.sh \
+ rscript_unflatten_non_object.sh \
+ rscript_unflatten_object_exclamation.sh \
+ rscript_unflatten_object.sh \
+ rscript_unflatten_arg1_unsuitable-vg.sh \
+ rscript_unflatten_arg2_invalid-vg.sh \
+ rscript_unflatten_conflict1-vg.sh \
+ rscript_unflatten_conflict2-vg.sh \
+ rscript_unflatten_conflict3-vg.sh \
+ rscript_unflatten_key_truncated-vg.sh \
+ rscript_unflatten_non_object-vg.sh \
+ rscript_unflatten_object_exclamation-vg.sh \
+ rscript_unflatten_object-vg.sh \
+ rscript_get_property.sh \
+ rscript_get_property-vg.sh \
+ rs-cnum.sh \
+ rs-int2hex.sh \
+ rs-substring.sh \
+ omsnmp_errmsg_no_params.sh \
+ sndrcv_omsnmpv1_udp.sh \
+ sndrcv_omsnmpv1_udp_dynsource.sh \
+ sndrcv_omsnmpv1_udp_invalidoid.sh \
+ snmptrapreceiver.py \
+ ommail_errmsg_no_params.sh \
+ mmdarwin_errmsg_no_params.sh \
+ mmdarwin_errmsg_no_sock.sh \
+ mmdarwin_errmsg_no_sock-vg.sh \
+ mmutf8fix_no_error.sh \
+ tcpflood_wrong_option_output.sh \
+ msleep_usage_output.sh \
+ mangle_qi_usage_output.sh \
+ minitcpsrv_usage_output.sh \
+ test_id_usage_output.sh \
+ mmanon_with_debug.sh \
+ mmanon_random_32_ipv4.sh \
+ mmanon_random_cons_32_ipv4.sh \
+ mmanon_recognize_ipv4.sh \
+ mmanon_zero_12_ipv4.sh \
+ mmanon_zero_33_ipv4.sh \
+ mmanon_zero_8_ipv4.sh \
+ mmanon_simple_12_ipv4.sh \
+ mmanon_simple_33_ipv4.sh \
+ mmanon_simple_8_ipv4.sh \
+ mmanon_simple_mallformed_ipv4.sh \
+ mmanon_random_128_ipv6.sh \
+ mmanon_zero_128_ipv6.sh \
+ mmanon_zero_96_ipv6.sh \
+ mmanon_random_cons_128_ipv6.sh \
+ mmanon_zero_50_ipv6.sh \
+ mmanon_recognize_ipv6.sh \
+ mmanon_zero_64_ipv6.sh \
+ mmanon_both_modes_compatible.sh \
+ mmanon_recognize_ipembedded.sh \
+ mmanon_ipv6_port.sh \
+ mmanon_random_cons_128_ipembedded.sh \
+ rscript_eq.sh \
+ rscript_eq_var.sh \
+ rscript_set_memleak-vg.sh \
+ rscript_set_unset_invalid_var.sh \
+ rscript_set_modify.sh \
+ stop-localvar.sh \
+ stop-msgvar.sh \
+ omfwd-tls-invalid-permitExpiredCerts.sh \
+ omfwd-keepalive.sh \
+ omfwd_fast_imuxsock.sh \
+ omfile_hup-vg.sh \
+ zstd.sh \
+ zstd-vg.sh \
+ gzipwr_hup-vg.sh \
+ omusrmsg-errmsg-no-params.sh \
+ omusrmsg-noabort.sh \
+ omusrmsg-noabort-vg.sh \
+ omfile-module-params.sh \
+ omfile-read-only-errmsg.sh \
+ omfile-null-filename.sh \
+ omfile-whitespace-filename.sh \
+ omfile-read-only.sh \
+ omfile-outchannel.sh \
+ omfile-outchannel-many.sh \
+ omfile-sizelimitcmd-many.sh \
+ omfile_both_files_set.sh \
+ omfile_hup.sh \
+ omrabbitmq_no_params.sh \
+ omrabbitmq_params_missing0.sh \
+ omrabbitmq_params_missing1.sh \
+ omrabbitmq_params_missing2.sh \
+ omrabbitmq_params_invalid0.sh \
+ omrabbitmq_params_invalid1.sh \
+ omrabbitmq_params_invalid2.sh \
+ omrabbitmq_params_invalid3.sh \
+ omrabbitmq_data_1server.sh \
+ omrabbitmq_data_1server-vg.sh \
+ omrabbitmq_data_2servers.sh \
+ omrabbitmq_error_server0.sh \
+ omrabbitmq_error_server1.sh \
+ omrabbitmq_error_server2.sh \
+ omrabbitmq_error_server3.sh \
+ omrabbitmq_json.sh \
+ omrabbitmq_raw.sh \
+ imhiredis-queue.sh \
+ imhiredis-queue-vg.sh \
+ imhiredis-queue-lpop.sh \
+ imhiredis-queue-lpop-vg.sh \
+ imhiredis-redis-restart.sh \
+ imhiredis-redis-restart-vg.sh \
+ imhiredis-redis-start-after.sh \
+ imhiredis-redis-start-after-vg.sh \
+ imhiredis-subscribe.sh \
+ imhiredis-subscribe-vg.sh \
+ imhiredis-stream.sh \
+ imhiredis-stream-vg.sh \
+ imhiredis-stream-from-beginning.sh \
+ imhiredis-stream-from-beginning-vg.sh \
+ imhiredis-stream-consumerGroup-ack.sh \
+ imhiredis-stream-consumerGroup-ack-vg.sh \
+ imhiredis-stream-consumerGroup-noack.sh \
+ imhiredis-stream-consumerGroup-noack-vg.sh \
+ imhiredis-stream-consumerGroup-reclaim.sh \
+ imhiredis-stream-consumerGroup-reclaim-vg.sh \
+ msgvar-concurrency.sh \
+ msgvar-concurrency-array.sh \
+ testsuites/msgvar-concurrency-array.rulebase \
+ msgvar-concurrency-array-event.tags.sh \
+ testsuites/msgvar-concurrency-array-event.tags.rulebase \
+ localvar-concurrency.sh \
+ exec_tpl-concurrency.sh \
+ prop-jsonmesg-vg.sh \
+ prop-all-json-concurrency.sh \
+ no-parser-errmsg.sh \
+ global_vars.sh \
+ no-parser-errmsg.sh \
+ no-parser-vg.sh \
+ prop-programname.sh \
+ prop-programname-with-slashes.sh \
+ rfc5424parser.sh \
+ rscript_privdropuser.sh \
+ rscript_privdropuserid.sh \
+ rscript_privdropgroup.sh \
+ rscript_privdropgroupid.sh \
+ privdrop_common.sh \
+ privdropuser.sh \
+ privdropuserid.sh \
+ privdropgroup.sh \
+ privdropgroupid.sh \
+ privdropabortonidfail.sh \
+ privdropabortonidfaillegacy.sh \
+ json-nonstring.sh \
+ json-onempty-at-end.sh \
+ template-json.sh \
+ template-pure-json.sh \
+ template-pos-from-to.sh \
+ template-pos-from-to-lowercase.sh \
+ template-pos-from-to-oversize.sh \
+ template-pos-from-to-oversize-lowercase.sh \
+ template-pos-from-to-missing-jsonvar.sh \
+ template-const-jsonf.sh \
+ template-topos-neg.sh \
+ fac_authpriv.sh \
+ fac_local0.sh \
+ fac_local0-vg.sh \
+ fac_local7.sh \
+ fac_mail.sh \
+ fac_news.sh \
+ fac_ftp.sh \
+ fac_ntp.sh \
+ fac_uucp.sh \
+ fac_invld1.sh \
+ fac_invld2.sh \
+ fac_invld3.sh \
+ fac_invld4_rfc5424.sh \
+ compresssp.sh \
+ compresssp-stringtpl.sh \
+ now_family_utc.sh \
+ now-utc-ymd.sh \
+ now-utc-casecmp.sh \
+ now-utc.sh \
+ now-unixtimestamp.sh \
+ faketime_common.sh \
+ imjournal-basic.sh \
+ imjournal-statefile.sh \
+ imjournal-statefile-vg.sh \
+ imjournal-basic-vg.sh \
+ omjournal-abort-template.sh \
+ omjournal-abort-no-template.sh \
+ omjournal-basic-template.sh \
+ omjournal-basic-no-template.sh \
+ timegenerated-ymd.sh \
+ timegenerated-uxtimestamp.sh \
+ timegenerated-uxtimestamp-invld.sh \
+ timegenerated-dateordinal.sh \
+ timegenerated-dateordinal-invld.sh \
+ timegenerated-utc.sh \
+ timegenerated-utc-legacy.sh \
+ timereported-utc.sh \
+ timereported-utc-legacy.sh \
+ timereported-utc-vg.sh \
+ mmrm1stspace-basic.sh \
+ mmnormalize_parsesuccess.sh \
+ mmnormalize_parsesuccess-vg.sh \
+ mmnormalize_rule_from_string.sh \
+ mmnormalize_rule_from_array.sh \
+ pmnull-basic.sh \
+ pmnull-withparams.sh \
+ omstdout-basic.sh \
+ testsuites/mmnormalize_processing_tests.rulebase \
+ mmnormalize_processing_test1.sh \
+ mmnormalize_processing_test2.sh \
+ mmnormalize_processing_test3.sh \
+ mmnormalize_processing_test4.sh \
+ pmnormalize-basic.sh \
+ pmnormalize-rule.sh \
+ pmnormalize-rule_and_rulebase.sh \
+ pmnormalize-neither_rule_rulebase.sh \
+ pmnormalize-invld-rulebase.sh \
+ pmnormalize-rule_invld-data.sh \
+ testsuites/pmnormalize_basic.rulebase \
+ pmnormalize-basic-vg.sh \
+ pmnormalize-rule-vg.sh\
+ pmnormalize-rule_and_rulebase-vg.sh \
+ pmnormalize-neither_rule_rulebase-vg.sh \
+ pmnormalize-invld-rulebase-vg.sh \
+ pmnormalize-rule_invld-data-vg.sh \
+ rawmsg-after-pri.sh \
+ rs_optimizer_pri.sh \
+ rscript_prifilt.sh \
+ rscript_optimizer1.sh \
+ rscript_ruleset_call.sh \
+ rscript_ruleset_call_indirect-basic.sh \
+ rscript_ruleset_call_indirect-var.sh \
+ rscript_ruleset_call_indirect-invld.sh \
+ cee_simple.sh \
+ cee_diskqueue.sh \
+ mmjsonparse-w-o-cookie.sh \
+ mmjsonparse-w-o-cookie-multi-spaces.sh \
+ mmjsonparse_simple.sh \
+ mmjsonparse-invalid-containerName.sh \
+ wtpShutdownAll-assertionFailure.sh \
+ imptcp-octet-framing-too-long-vg.sh \
+ imptcp-oversize-message-display.sh \
+ imptcp-msg-truncation-on-number.sh \
+ imptcp-msg-truncation-on-number2.sh \
+ imptcp-maxFrameSize-parameter.sh \
+ mmjsonparse_cim.sh \
+ mmjsonparse_cim2.sh \
+ mmjsonparse_localvar.sh \
+ mmdb.sh \
+ mmdb-space.sh \
+ mmdb.rb \
+ test.mmdb \
+ with_space.mmdb \
+ mmdb-vg.sh \
+ mmdb-container.sh \
+ mmdb-container-empty.sh \
+ mmdb-multilevel-vg.sh \
+ incltest.sh \
+ incltest_dir.sh \
+ incltest_dir_empty_wildcard.sh \
+ incltest_dir_wildcard.sh \
+ testsuites/es.yml \
+ clickhouse-dflt-tpl.sh \
+ clickhouse-retry-error.sh \
+ clickhouse-start.sh \
+ clickhouse-stop.sh \
+ clickhouse-basic.sh \
+ clickhouse-load.sh \
+ clickhouse-bulk.sh \
+ clickhouse-bulk-load.sh \
+ clickhouse-limited-batch.sh \
+ clickhouse-select.sh \
+ clickhouse-wrong-quotation-marks.sh \
+ clickhouse-wrong-template-option.sh \
+ clickhouse-errorfile.sh \
+ clickhouse-wrong-insert-syntax.sh \
+ clickhouse-basic-vg.sh \
+ clickhouse-load-vg.sh \
+ clickhouse-bulk-vg.sh \
+ clickhouse-bulk-load-vg.sh \
+ es_response_get_msgnum.py \
+ elasticsearch-error-format-check.py \
+ es-duplicated-ruleset.sh \
+ es-duplicated-ruleset-vg.sh \
+ es-basic-es6.0.sh \
+ es-basic-es7.14.sh \
+ es-basic.sh \
+ es-basic-vgthread.sh \
+ es-basic-server.sh \
+ es-execOnlyWhenPreviousSuspended.sh \
+ es-basic-ha.sh \
+ es-basic-bulk.sh \
+ es-basic-errfile-empty.sh \
+ es-basic-errfile-popul.sh \
+ es-bulk-errfile-empty.sh \
+ es-bulk-errfile-popul.sh \
+ es-bulk-errfile-popul-def-format.sh \
+ es-bulk-errfile-popul-erronly.sh \
+ es-bulk-errfile-popul-erronly-interleaved.sh \
+ es-bulk-errfile-popul-def-interleaved.sh \
+ es-searchType-empty.sh \
+ diskqueue-multithread-es.sh \
+ es-basic-vg.sh \
+ es-basic-bulk-vg.sh \
+ es-basic-ha-vg.sh \
+ es-maxbytes-bulk.sh \
+ es-bulk-retry.sh \
+ elasticsearch-stop.sh \
+ linkedlistqueue.sh \
+ da-mainmsg-q.sh \
+ diskqueue-fsync.sh \
+ msgdup.sh \
+ msgdup_props.sh \
+ empty-ruleset.sh \
+ ruleset-direct-queue.sh \
+ imtcp-listen-port-file-2.sh \
+ allowed-sender-tcp-ok.sh \
+ allowed-sender-tcp-fail.sh \
+ allowed-sender-tcp-hostname-ok.sh \
+ allowed-sender-tcp-hostname-fail.sh \
+ imtcp-octet-framing-too-long-vg.sh \
+ imtcp-discard-truncated-msg.sh \
+ imtcp-basic.sh \
+ imtcp-basic-hup.sh \
+ imtcp-maxFrameSize.sh \
+ imtcp-msg-truncation-on-number.sh \
+ imtcp-msg-truncation-on-number2.sh \
+ imtcp-NUL.sh \
+ imtcp-NUL-rawmsg.sh \
+ imtcp-tls-gtls-x509fingerprint-invld.sh \
+ imtcp-tls-gtls-x509fingerprint.sh \
+ imtcp-tls-gtls-x509name-invld.sh \
+ imtcp-tls-gtls-x509name.sh \
+ imtcp-tls-gtls-x509name-legacy.sh \
+ imtcp-drvr-in-input-basic.sh \
+ imtcp-multi-drvr-basic.sh \
+ imtcp-multi-drvr-basic-parallel.sh \
+ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh \
+ imtcp-tls-basic.sh \
+ imtcp-tls-input-basic.sh \
+ imtcp-tls-input-2certs.sh \
+ imtcp-tls-basic-verifydepth.sh \
+ imtcp-tls-basic-vg.sh \
+ imtcp-tls-no-lstn-startup.sh \
+ imtcp_incomplete_frame_at_end.sh \
+ imtcp-multiport.sh \
+ imtcp-bigmessage-octetcounting.sh \
+ imtcp-bigmessage-octetstuffing.sh \
+ udp-msgreduc-orgmsg-vg.sh \
+ udp-msgreduc-vg.sh \
+ manytcp-too-few-tls-vg.sh \
+ imtcp-tls-ossl-basic.sh \
+ imtcp-tls-ossl-input-basic.sh \
+ imtcp-tls-ossl-input-2certs.sh \
+ imtcp-tls-ossl-basic-tlscommands.sh \
+ imtcp-tls-ossl-basic-verifydepth.sh \
+ imtcp-tls-ossl-invalid-verifydepth.sh \
+ sndrcv_tls_ossl_anon_ipv4.sh \
+ sndrcv_tls_ossl_anon_ipv6.sh \
+ sndrcv_tls_ossl_anon_rebind.sh \
+ sndrcv_tls_ossl_anon_ciphers.sh \
+ sndrcv_tls_ossl_certvalid.sh \
+ sndrcv_tls_ossl_certvalid_action_level.sh \
+ sndrcv_tls_ossl_certvalid_expired.sh \
+ sndrcv_tls_ossl_certvalid_tlscommand.sh \
+ sndrcv_tls_ossl_certvalid_ciphers.sh \
+ sndrcv_tls_ossl_certvalid_revoked.sh \
+ imtcp-tls-ossl-x509valid.sh \
+ imtcp-tls-ossl-x509name.sh \
+ imtcp-tls-ossl-x509fingerprint.sh \
+ imtcp-tls-ossl-basic-vg.sh \
+ imtcp-tls-ossl-basic-brokenhandshake-vg.sh \
+ imtcp-tls-ossl-error-ca.sh \
+ imtcp-tls-ossl-error-cert.sh \
+ imtcp-tls-ossl-error-key.sh \
+ imtcp-tls-ossl-error-key2.sh \
+ manytcp.sh \
+ manyptcp.sh \
+ imptcp-basic-hup.sh \
+ imptcp-NUL.sh \
+ imptcp-NUL-rawmsg.sh \
+ imptcp_framing_regex.sh \
+ testsuites/imptcp_framing_regex.testdata \
+ imptcp_framing_regex-oversize.sh \
+ testsuites/imptcp_framing_regex-oversize.testdata \
+ imptcp_large.sh \
+ imptcp-connection-msg-disabled.sh \
+ imptcp-connection-msg-received.sh \
+ imptcp-discard-truncated-msg.sh \
+ imptcp_addtlframedelim.sh \
+ imptcp_conndrop-vg.sh \
+ imptcp_conndrop.sh \
+ imptcp_multi_line.sh \
+ testsuites/imptcp_multi_line.testdata \
+ imptcp_no_octet_counted.sh \
+ imtcp_addtlframedelim_on_input.sh \
+ testsuites/no_octet_counted.testdata \
+ imtcp_no_octet_counted.sh \
+ testsuites/spframingfix.testdata \
+ imtcp_spframingfix.sh \
+ imtcp-connection-msg-recieved.sh \
+ imptcp_spframingfix.sh \
+ msg-deadlock-headerless-noappname.sh \
+ imtcp_conndrop.sh \
+ imtcp_conndrop_tls.sh \
+ imtcp_conndrop_tls-vg.sh \
+ imtcp_addtlframedelim.sh \
+ tcp-msgreduc-vg.sh \
+ inputname-imtcp.sh \
+ omod-if-array.sh \
+ omod-if-array-udp.sh \
+ discard.sh \
+ failover-no-rptd.sh \
+ failover-no-rptd-vg.sh \
+ failover-no-basic.sh \
+ failover-no-basic-vg.sh \
+ failover-rptd.sh \
+ failover-rptd-vg.sh \
+ failover-basic.sh \
+ failover-basic-vg.sh \
+ failover-async.sh \
+ failover-double.sh \
+ suspend-via-file.sh \
+ suspend-omfwd-via-file.sh \
+ externalstate-failed-rcvr.sh \
+ discard-rptdmsg.sh \
+ discard-rptdmsg-vg.sh \
+ discard-allmark.sh \
+ discard-allmark-vg.sh \
+ diag.sh \
+ rcvr_fail_restore.sh \
+ queue-encryption-disk.sh \
+ queue-encryption-disk_keyfile.sh \
+ queue-encryption-disk_keyfile-vg.sh \
+ queue-encryption-disk_keyprog.sh \
+ queue-encryption-da.sh \
+ da-queue-persist.sh \
+ daqueue-dirty-shutdown.sh \
+ daqueue-invld-qi.sh \
+ daqueue-persist.sh \
+ daqueue-persist-drvr.sh \
+ queue-persist.sh \
+ queue-persist-drvr.sh \
+ threadingmq.sh \
+ threadingmqaq.sh \
+ sndrcv_drvr.sh \
+ sndrcv_drvr_noexit.sh \
+ sndrcv_failover.sh \
+ sndrcv.sh \
+ omrelp_errmsg_no_connect.sh \
+ imrelp-basic.sh \
+ imrelp-basic-hup.sh \
+ imrelp-basic-vg.sh \
+ imrelp-basic-oldstyle.sh \
+ imrelp-manyconn.sh \
+ imrelp-manyconn-vg.sh \
+ imrelp-maxDataSize-error.sh \
+ imrelp-long-msg.sh \
+ imrelp-oversizeMode-truncate.sh \
+ imrelp-oversizeMode-accept.sh \
+ imrelp-invld-tlslib.sh \
+ imrelp-bigmessage.sh \
+ imrelp-sessionbreak-vg.sh \
+ omrelp-invld-tlslib.sh \
+ glbl-oversizeMsg-log.sh \
+ glbl-oversizeMsg-truncate.sh \
+ glbl-oversizeMsg-split.sh \
+ sndrcv_relp.sh \
+ sndrcv_relp_rebind.sh \
+ sndrcv_relp_tls_prio.sh \
+ sndrcv_relp_tls_chainedcert.sh \
+ sndrcv_relp_tls.sh \
+ sndrcv_relp_tls_certvalid.sh \
+ sndrcv_relp-vg-rcvr.sh \
+ sndrcv_relp-vg-sender.sh \
+ relp_tls_certificate_not_found.sh \
+ omrelp_wrong_authmode.sh \
+ imrelp-tls.sh \
+ imrelp-tls-cfgcmd.sh \
+ imrelp-tls-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert.sh \
+ imrelp-tls-mixed-chainedcert2.sh \
+ sndrcv_relp_tls-cfgcmd.sh \
+ sndrcv_relp_dflt_pt.sh \
+ sndrcv_udp.sh \
+ imudp_thread_hang.sh \
+ sndrcv_udp_nonstdpt.sh \
+ sndrcv_udp_nonstdpt_v6.sh \
+ omudpspoof_errmsg_no_params.sh \
+ sndrcv_omudpspoof.sh \
+ sndrcv_omudpspoof-bigmsg.sh \
+ sndrcv_omudpspoof_nonstdpt.sh \
+ sndrcv_gzip.sh \
+ imdtls-basic.sh \
+ imdtls-basic-tlscommands.sh \
+ imdtls-basic-timeout \
+ imdtls-error-cert.sh \
+ imdtls-sessionbreak.sh \
+ imdtls-basic-vg.sh \
+ imdtls-sessionbreak-vg.sh \
+ sndrcv_dtls_certvalid.sh \
+ sndrcv_dtls_anon_ciphers.sh \
+ sndrcv_dtls_certvalid_ciphers.sh \
+ sndrcv_dtls_certvalid_permitted.sh \
+ sndrcv_dtls_certvalid_missing.sh \
+ sndrcv_dtls_anon_ciphers.sh \
+ sndrcv_dtls_certvalid-vg.sh \
+ action-tx-single-processing.sh \
+ omfwd-errfile-maxsize.sh \
+ omfwd-errfile-maxsize-filled.sh \
+ action-tx-errfile-maxsize.sh \
+ action-tx-errfile.sh \
+ testsuites/action-tx-errfile.result \
+ pipeaction.sh \
+ improg-simul.sh \
+ improg-multiline-test.py \
+ improg_errmsg_no_params.sh \
+ improg_errmsg_no_params-vg.sh \
+ improg_prog_simple.sh \
+ improg_prog_confirm.sh \
+ improg_prog_confirm_killonclose.sh \
+ improg_prog_killonclose.sh \
+ improg_prog_simple-vg.sh \
+ improg_simple_multi.sh \
+ imhttp-post-payload.sh \
+ imhttp-post-payload-vg.sh \
+ imhttp-post-payload-basic-auth.sh \
+ imhttp-post-payload-basic-auth-vg.sh \
+ imhttp-post-payload-query-params.sh \
+ imhttp-post-payload-query-params-vg.sh \
+ imhttp-post-payload-large.sh \
+ imhttp-post-payload-large-vg.sh \
+ testsuites/imhttp-large-data.txt \
+ imhttp-post-payload-multi.sh \
+ imhttp-post-payload-multi-vg.sh \
+ imhttp-getrequest-file.sh \
+ imhttp-getrequest-file-vg.sh \
+ imhttp-post-payload-multi-lf.sh \
+ imhttp-post-payload-multi-lf-vg.sh \
+ imhttp-post-payload-compress.sh \
+ imhttp-post-payload-compress-vg.sh \
+ testsuites/docroot/file.txt \
+ testsuites/htpasswd \
+ omhttp-auth.sh \
+ omhttp-basic.sh \
+ omhttp-batch-fail-with-400.sh \
+ omhttp-batch-jsonarray-compress.sh \
+ omhttp-batch-jsonarray-retry.sh \
+ omhttp-batch-jsonarray.sh \
+ omhttp-batch-kafkarest-retry.sh \
+ omhttp-batch-kafkarest.sh \
+ omhttp-batch-lokirest-retry.sh \
+ omhttp-batch-lokirest.sh \
+ omhttp-batch-lokirest-vg.sh \
+ omhttp-batch-newline.sh \
+ omhttp-retry.sh \
+ omhttp-httpheaderkey.sh \
+ omhttp-multiplehttpheaders.sh \
+ omhttp-dynrestpath.sh \
+ omhttp-batch-dynrestpath.sh \
+ omhttp-auth-vg.sh \
+ omhttp-basic-vg.sh \
+ omhttp-batch-jsonarray-compress-vg.sh \
+ omhttp-batch-jsonarray-retry-vg.sh \
+ omhttp-batch-jsonarray-vg.sh \
+ omhttp-batch-kafkarest-retry-vg.sh \
+ omhttp-batch-lokirest-retry-vg.sh \
+ omhttp-retry-vg.sh \
+ omhttp_server.py \
+ omprog-defaults.sh \
+ omprog-defaults-vg.sh \
+ omprog-output-capture.sh \
+ omprog-output-capture-mt.sh \
+ omprog-output-capture-vg.sh \
+ omprog-feedback.sh \
+ omprog-feedback-mt.sh \
+ omprog-feedback-vg.sh \
+ omprog-feedback-timeout.sh \
+ omprog-close-unresponsive.sh \
+ omprog-close-unresponsive-vg.sh \
+ omprog-close-unresponsive-noterm.sh \
+ omprog-restart-terminated.sh \
+ omprog-restart-terminated-vg.sh \
+ omprog-restart-terminated-outfile.sh \
+ omprog-single-instance.sh \
+ omprog-single-instance-vg.sh \
+ omprog-single-instance-outfile.sh \
+ omprog-if-error.sh \
+ omprog-transactions.sh \
+ omprog-transactions-vg.sh \
+ omprog-transactions-failed-messages.sh \
+ omprog-transactions-failed-commits.sh \
+ testsuites/omprog-defaults-bin.sh \
+ testsuites/omprog-output-capture-bin.sh \
+ testsuites/omprog-output-capture-mt-bin.py \
+ testsuites/omprog-feedback-bin.sh \
+ testsuites/omprog-feedback-mt-bin.sh \
+ testsuites/omprog-feedback-timeout-bin.sh \
+ testsuites/omprog-close-unresponsive-bin.sh \
+ testsuites/omprog-restart-terminated-bin.sh \
+ testsuites/omprog-single-instance-bin.sh \
+ testsuites/omprog-transactions-bin.sh \
+ pipe_noreader.sh \
+ uxsock_simple.sh \
+ asynwr_simple.sh \
+ asynwr_simple_2.sh \
+ asynwr_timeout.sh \
+ asynwr_timeout_2.sh \
+ asynwr_small.sh \
+ asynwr_tinybuf.sh \
+ wr_large_async.sh \
+ wr_large_sync.sh \
+ asynwr_deadlock.sh \
+ asynwr_deadlock_2.sh \
+ asynwr_deadlock2.sh \
+ asynwr_deadlock4.sh \
+ asynwr_dynfile_flushtxend-off.sh \
+ abort-uncleancfg-goodcfg.sh \
+ abort-uncleancfg-goodcfg-check.sh \
+ abort-uncleancfg-badcfg-check.sh \
+ abort-uncleancfg-badcfg-check_1.sh \
+ variable_leading_underscore.sh \
+ gzipwr_hup_multi_file.sh \
+ gzipwr_hup_single_file.sh \
+ gzipwr_rscript.sh \
+ gzipwr_flushInterval.sh \
+ gzipwr_flushOnTXEnd.sh \
+ gzipwr_large.sh \
+ gzipwr_large_dynfile.sh \
+ gzipwr_hup.sh \
+ complex1.sh \
+ random.sh \
+ testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input \
+ imfile-readmode0-vg.sh \
+ imfile-readmode2.sh \
+ imfile-readmode2-polling.sh \
+ imfile-readmode2-vg.sh \
+ imfile-readmode2-with-persists-data-during-stop.sh \
+ imfile-readmode2-with-persists.sh \
+ imfile-endregex-save-lf.sh \
+ imfile-endregex-save-lf-persist.sh \
+ imfile-endregex.sh \
+ imfile-endregex-vg.sh \
+ imfile-basic.sh \
+ imfile-basic-legacy.sh \
+ imfile-basic-2GB-file.sh \
+ imfile-truncate-2GB-file.sh \
+ imfile-discard-truncated-line.sh \
+ imfile-truncate-line.sh \
+ imfile-file-not-found-error.sh \
+ imfile-fileNotFoundError-parameter.sh \
+ imfile-error-not-repeated.sh \
+ imfile-basic-vg.sh \
+ imfile-basic-vgthread.sh \
+ imfile-endregex-timeout-none-polling.sh \
+ imfile-endregex-timeout-polling.sh \
+ imfile-endregex-timeout.sh \
+ imfile-endregex-timeout-none.sh \
+ imfile-endregex-timeout-with-shutdown.sh \
+ imfile-endregex-timeout-with-shutdown-polling.sh \
+ imfile-escapelf.replacement.sh \
+ imfile-escapelf.replacement-empty.sh \
+ imfile-endmsg.regex.sh \
+ imfile-endmsg.regex-vg.sh \
+ imfile-endmsg.regex-with-example.sh \
+ imfile-endmsg.regex-with-example-vg.sh \
+ imfile-endmsg.regex.crio.rulebase \
+ imfile-endmsg.regex.json.rulebase \
+ imfile-statefile-no-file_id.sh \
+ imfile-statefile-no-file_id-TO-file_id.sh \
+ imfile-statefile-directory.sh \
+ imfile-statefile-delete.sh \
+ imfile-statefile-no-delete.sh \
+ imfile-persist-state-1.sh \
+ imfile-freshStartTail1.sh \
+ imfile-freshStartTail2.sh \
+ imfile-freshStartTail3.sh \
+ imfile-truncate.sh \
+ imfile-truncate-multiple.sh \
+ imfile-wildcards.sh \
+ imfile-wildcards-dirs.sh \
+ imfile-wildcards-dirs2.sh \
+ imfile-wildcards-dirs-multi.sh \
+ imfile-wildcards-dirs-multi2.sh \
+ imfile-wildcards-dirs-multi3.sh \
+ imfile-wildcards-dirs-multi4.sh \
+ imfile-wildcards-dirs-multi5.sh \
+ imfile-wildcards-dirs-multi5-polling.sh \
+ imfile-old-state-file.sh \
+ imfile-rename-while-stopped.sh \
+ imfile-rename.sh \
+ imfile-symlink.sh \
+ imfile-symlink-multi.sh \
+ imfile-symlink-ext-tmp-dir-tree.sh \
+ imfile-logrotate.sh \
+ imfile-logrotate-async.sh \
+ imfile-logrotate-copytruncate.sh \
+ imfile-logrotate-nocopytruncate.sh \
+ imfile-logrotate-multiple.sh \
+ imfile-growing-file-id.sh \
+ imfile-ignore-old-file-1.sh \
+ imfile-ignore-old-file-2.sh \
+ imfile-ignore-old-file-3.sh \
+ imfile-ignore-old-file-4.sh \
+ imfile-ignore-old-file-5.sh \
+ imfile-ignore-old-file-6.sh \
+ imfile-ignore-old-file-7.sh \
+ glbl-oversizeMsg-truncate-imfile.sh \
+ dynfile_invld_async.sh \
+ dynfile_invld_sync.sh \
+ dynfile_invalid2.sh \
+ rulesetmultiqueue.sh \
+ rulesetmultiqueue-v6.sh \
+ omruleset.sh \
+ omruleset-queue.sh \
+ badqi.sh \
+ bad_qi/dbq.qi \
+ execonlyonce.sh \
+ execonlywhenprevsuspended.sh \
+ execonlywhenprevsuspended2.sh \
+ execonlywhenprevsuspended3.sh \
+ execonlywhenprevsuspended4.sh \
+ execonlywhenprevsuspended_multiwrkr.sh \
+ execonlywhenprevsuspended-queue.sh \
+ execonlywhenprevsuspended-nonsusp.sh \
+ execonlywhenprevsuspended-nonsusp-queue.sh \
+ tabescape_dflt.sh \
+ tabescape_dflt-udp.sh \
+ tabescape_off.sh \
+ tabescape_off-udp.sh \
+ tabescape_on.sh \
+ dircreate_dflt.sh \
+ dircreate_off.sh \
+ imuxsock_legacy.sh \
+ imuxsock_logger_parserchain.sh \
+ imuxsock_logger.sh \
+ imuxsock_logger_ratelimit.sh \
+ imuxsock_logger_ruleset.sh \
+ imuxsock_logger_ruleset_ratelimit.sh \
+ imuxsock_logger_err.sh \
+ imuxsock_logger_root.sh \
+ imuxsock_logger_syssock.sh \
+ imuxsock_traillf.sh \
+ imuxsock_traillf_root.sh \
+ imuxsock_traillf_syssock.sh \
+ imuxsock_ccmiddle.sh \
+ imuxsock_ccmiddle_root.sh \
+ imklog_permitnonkernelfacility_root.sh \
+ imuxsock_ccmiddle_syssock.sh \
+ imuxsock_hostname.sh \
+ testsuites/mysql-truncate.sql \
+ testsuites/mysql-select-msg.sql \
+ libdbi-basic.sh \
+ libdbi-asyn.sh \
+ mysqld-start.sh \
+ mysqld-stop.sh \
+ mysql-basic.sh \
+ mysql-basic-cnf6.sh \
+ mysql-basic-vg.sh \
+ mysql-asyn.sh \
+ mysql-asyn-vg.sh \
+ mysql-actq-mt.sh \
+ mysql-actq-mt-withpause.sh \
+ mysql-actq-mt-withpause-vg.sh \
+ kafka-selftest.sh \
+ omkafka.sh \
+ omkafkadynakey.sh \
+ omkafka-vg.sh \
+ imkafka-hang-on-no-kafka.sh \
+ imkafka-hang-other-action-on-no-kafka.sh \
+ imkafka-backgrounded.sh \
+ imkafka-config-err-ruleset.sh \
+ imkafka-config-err-param.sh \
+ imkafka.sh \
+ imkafka-vg.sh \
+ imkafka_multi_single.sh \
+ imkafka_multi_group.sh \
+ sndrcv_kafka.sh \
+ sndrcv_kafka_multi_topics.sh \
+ testsuites/kafka-server.properties \
+ testsuites/kafka-server.dep_wrk1.properties \
+ testsuites/kafka-server.dep_wrk2.properties \
+ testsuites/kafka-server.dep_wrk3.properties \
+ testsuites/zoo.cfg \
+ testsuites/zoo.dep_wrk1.cfg \
+ testsuites/zoo.dep_wrk2.cfg \
+ testsuites/zoo.dep_wrk3.cfg \
+ omazureeventhubs-basic.sh \
+ omazureeventhubs-list.sh \
+ omazureeventhubs-stress.sh \
+ omazureeventhubs-interrupt.sh \
+ omazureeventhubs-basic-vg.sh \
+ omazureeventhubs-interrupt-vg.sh \
+ mmpstrucdata.sh \
+ mmpstrucdata-escaping.sh \
+ mmpstrucdata-case.sh \
+ mmpstrucdata-vg.sh \
+ mmpstrucdata-invalid-vg.sh \
+ libdbi-basic-vg.sh \
+ dynstats_ctr_reset.sh \
+ dynstats_reset_without_pstats_reset.sh \
+ dynstats_nometric.sh \
+ dynstats_overflow.sh \
+ dynstats_overflow-vg.sh \
+ dynstats_reset.sh \
+ dynstats_reset-vg.sh \
+ impstats-hup.sh \
+ dynstats.sh \
+ dynstats-vg.sh \
+ dynstats_prevent_premature_eviction.sh \
+ dynstats_prevent_premature_eviction-vg.sh \
+ testsuites/dynstats_empty_input \
+ testsuites/dynstats_input \
+ testsuites/dynstats_input_1 \
+ testsuites/dynstats_input_2 \
+ testsuites/dynstats_input_3 \
+ testsuites/dynstats_input_more_0 \
+ testsuites/dynstats_input_more_1 \
+ testsuites/dynstats_input_more_2 \
+ no-dynstats-json.sh \
+ no-dynstats.sh \
+ omfwd_impstats-udp.sh \
+ omfwd_impstats-tcp.sh \
+ perctile-simple.sh \
+ perctile-simple-vg.sh \
+ stats-json.sh \
+ stats-json-vg.sh \
+ stats-cee.sh \
+ stats-cee-vg.sh \
+ stats-json-es.sh \
+ dynstats-json.sh \
+ dynstats-json-vg.sh \
+ mmnormalize_variable.sh \
+ mmnormalize_tokenized.sh \
+ testsuites/mmnormalize_variable.rulebase \
+ testsuites/date_time_msg \
+ testsuites/mmnormalize_tokenized.rulebase \
+ testsuites/tokenized_input \
+ rscript_random.sh \
+ rscript_hash32.sh \
+ rscript_hash32-vg.sh \
+ rscript_hash64.sh \
+ rscript_hash64-vg.sh \
+ rscript_replace.sh \
+ rscript_replace_complex.sh \
+ testsuites/complex_replace_input \
+ rscript_unaffected_reset.sh \
+ rscript_wrap2.sh \
+ rscript_wrap3.sh \
+ testsuites/wrap3_input\
+ json_array_subscripting.sh \
+ testsuites/json_array_input \
+ testsuites/json_object_input \
+ testsuites/json_nonarray_input \
+ json_array_looping.sh \
+ json_object_looping.sh \
+ json_object_looping-vg.sh \
+ json_array_looping-vg.sh \
+ json_object_suicide_in_loop-vg.sh \
+ json_nonarray_looping.sh \
+ json_null.sh \
+ json_null-vg.sh \
+ json_null_array.sh \
+ json_null_array-vg.sh \
+ mmjsonparse_extra_data-vg.sh \
+ mmnormalize_regex.sh \
+ testsuites/mmnormalize_regex.rulebase \
+ testsuites/regex_input \
+ mmnormalize_regex_disabled.sh \
+ mmnormalize_regex_defaulted.sh \
+ stop_when_array_has_element.sh \
+ testsuites/stop_when_array_has_elem_input \
+ key_dereference_on_uninitialized_variable_space.sh \
+ rscript_re_extract_i.sh \
+ rscript_re_extract.sh \
+ rscript_re_match_i.sh \
+ rscript_re_match.sh \
+ rscript_re_match-dbl_quotes.sh \
+ lookup_table.sh \
+ lookup_table-hup-backgrounded.sh \
+ lookup_table_no_hup_reload.sh \
+ lookup_table_no_hup_reload-vg.sh \
+ lookup_table_rscript_reload.sh \
+ lookup_table_rscript_reload_without_stub.sh \
+ lookup_table_rscript_reload-vg.sh \
+ lookup_table_rscript_reload_without_stub-vg.sh \
+ rscript_trim-vg.sh \
+ testsuites/xlate.lkp_tbl \
+ testsuites/xlate_more.lkp_tbl \
+ unused_lookup_table-vg.sh \
+ lookup_table-vg.sh \
+ array_lookup_table.sh \
+ array_lookup_table-vg.sh \
+ array_lookup_table_misuse-vg.sh \
+ multiple_lookup_tables.sh \
+ multiple_lookup_tables-vg.sh \
+ testsuites/xlate_array.lkp_tbl \
+ testsuites/xlate_array_more.lkp_tbl \
+ testsuites/xlate_array_misuse.lkp_tbl \
+ testsuites/xlate_array_more_misuse.lkp_tbl \
+ sparse_array_lookup_table.sh \
+ sparse_array_lookup_table-vg.sh \
+ testsuites/xlate_sparse_array.lkp_tbl \
+ testsuites/xlate_sparse_array_more.lkp_tbl \
+ lookup_table_bad_configs.sh \
+ lookup_table_bad_configs-vg.sh \
+ testsuites/xlate_array_empty_table.lkp_tbl \
+ testsuites/xlate_array_no_index.lkp_tbl \
+ testsuites/xlate_array_no_table.lkp_tbl \
+ testsuites/xlate_array_no_value.lkp_tbl \
+ testsuites/xlate_empty_file.lkp_tbl \
+ testsuites/xlate_incorrect_type.lkp_tbl \
+ testsuites/xlate_incorrect_version.lkp_tbl \
+ testsuites/xlate_sparseArray_empty_table.lkp_tbl \
+ testsuites/xlate_sparseArray_no_index.lkp_tbl \
+ testsuites/xlate_sparseArray_no_table.lkp_tbl \
+ testsuites/xlate_sparseArray_no_value.lkp_tbl \
+ testsuites/xlate_string_empty_table.lkp_tbl \
+ testsuites/xlate_string_no_index.lkp_tbl \
+ testsuites/xlate_string_no_table.lkp_tbl \
+ testsuites/xlate_string_no_value.lkp_tbl \
+ testsuites/xlate_invalid_json.lkp_tbl \
+ testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl \
+ testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl \
+ testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl \
+ json_var_cmpr.sh \
+ imptcp_maxsessions.sh \
+ imptcp_nonProcessingPoller.sh \
+ imptcp_veryLargeOctateCountedMessages.sh \
+ known_issues.supp \
+ libmaxmindb.supp \
+ travis/trusty.supp \
+ linux_localtime_r.supp \
+ CI/centos6-9.supp \
+ CI/centos7.supp \
+ CI/gcov.supp \
+ CI/ubuntu20.04.supp \
+ json_var_case.sh \
+ cfg.sh \
+ empty-prop-comparison.sh \
+ sndrcv_tls_anon_rebind.sh \
+ sndrcv_tls_anon_hostname.sh \
+ sndrcv_tls_anon_ipv4.sh \
+ sndrcv_tls_anon_ipv6.sh \
+ sndrcv_tls_priorityString.sh \
+ sndrcv_tls_certvalid.sh \
+ sndrcv_tls_certvalid_action_level.sh \
+ sndrcv_tls_certvalid_expired.sh \
+ sndrcv_tls_certvalid_expired_defaultmode.sh \
+ sndrcv_tls_certvalid_revoked.sh \
+ sndrcv_tls_certless_clientonly.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh \
+ sndrcv_tls_gtls_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_ossl_serveranon_ossl_clientanon.sh \
+ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \
+ sndrcv_tls_ossl_servercert_gtls_clientanon.sh \
+ sndrcv_tls_ossl_serveranon_gtls_clientanon.sh \
+ sndrcv_tls_gtls_servercert_ossl_clientanon.sh \
+ sndrcv_tls_gtls_serveranon_ossl_clientanon.sh \
+ sndrcv_tls_client_missing_cert.sh \
+ sndrcv_ossl_cert_chain.sh \
+ omtcl.sh \
+ omtcl.tcl \
+ pmsnare-default.sh \
+ pmsnare-default-udp.sh \
+ pmsnare-ccoff.sh \
+ pmsnare-ccoff-udp.sh \
+ pmsnare-ccdefault.sh \
+ pmsnare-ccdefault-udp.sh \
+ pmsnare-cccstyle.sh \
+ pmsnare-cccstyle-udp.sh \
+ pmsnare-ccbackslash.sh \
+ pmsnare-ccbackslash-udp.sh \
+ pmsnare-modoverride.sh \
+ pmsnare-modoverride-udp.sh \
+ pmlastmsg.sh \
+ pmlastmsg-udp.sh \
+ pgsql-basic.sh \
+ testsuites/pgsql-basic.sql \
+ testsuites/pgsql-select-msg.sql \
+ testsuites/pgsql-select-syslogtag.sql \
+ pgsql-basic-cnf6.sh \
+ pgsql-basic-threads-cnf6.sh \
+ pgsql-template.sh \
+ pgsql-template-cnf6.sh \
+ pgsql-actq-mt-withpause.sh \
+ pgsql-template-threads-cnf6.sh \
+ pgsql-basic-vg.sh \
+ pgsql-template-vg.sh \
+ pgsql-basic-cnf6-vg.sh \
+ pgsql-template-cnf6-vg.sh \
+ pgsql-actq-mt-withpause-vg.sh \
+ ../devtools/prep-mysql-db.sh \
+ ../devtools/prepare_clickhouse.sh \
+ mmkubernetes-basic.sh \
+ mmkubernetes-basic-vg.sh \
+ mmkubernetes_test_server.py \
+ mmkubernetes-basic.out.json \
+ mmkubernetes-cache-expire.sh \
+ mmkubernetes-cache-expire-vg.sh \
+ mmkubernetes-cache-expire.out.expected \
+ mmkubernetes.supp \
+ es-writeoperation.sh \
+ imdocker-basic.sh \
+ imdocker-basic-vg.sh \
+ imdocker-long-logline.sh \
+ imdocker-long-logline-vg.sh \
+ imdocker-new-logs-from-start.sh \
+ imdocker-new-logs-from-start-vg.sh \
+ imdocker-multi-line.sh \
+ imdocker-multi-line-vg.sh \
+ testsuites/incltest.d/include.conf \
+ testsuites/abort-uncleancfg-goodcfg.conf \
+ testsuites/include-std-omfile-action.conf \
+ testsuites/invalid.conf \
+ testsuites/valid.conf \
+ testsuites/variable_leading_underscore.conf \
+ omamqp1-common.sh \
+ omamqp1-basic.sh \
+ omamqp1-basic-vg.sh
+
+ourtail_SOURCES = ourtail.c
+msleep_SOURCES = msleep.c
+omrelp_dflt_port_SOURCES = omrelp_dflt_port.c
+mangle_qi_SOURCES = mangle_qi.c
+chkseq_SOURCES = chkseq.c
+check_relpEngineVersion = check_relpEngineVersion.c
+have_relpSrvSetOversizeMode = have_relpSrvSetOversizeMode.c
+have_relpEngineSetTLSLibByName = have_relpEngineSetTLSLibByName.c
+have_relpSrvSetTlsConfigCmd = have_relpSrvSetTlsConfigCmd.c
+test_id_SOURCES = test_id.c
+uxsockrcvr_SOURCES = uxsockrcvr.c
+uxsockrcvr_LDADD = $(SOL_LIBS)
+tcpflood_SOURCES = tcpflood.c
+tcpflood_CFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS) $(am__append_127) \
+ $(am__append_130)
+tcpflood_CPPFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS) \
+ $(am__append_128) $(am__append_131)
+tcpflood_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) $(RELP_LIBS) \
+ $(am__append_129) $(am__append_132)
+minitcpsrv_SOURCES = minitcpsrvr.c
+minitcpsrv_LDADD = $(SOL_LIBS)
+syslog_caller_SOURCES = syslog_caller.c
+syslog_caller_CPPFLAGS = $(LIBLOGGING_STDLOG_CFLAGS)
+syslog_caller_LDADD = $(SOL_LIBS) $(LIBLOGGING_STDLOG_LIBS)
+journal_print_SOURCES = journal_print.c
+journal_print_CPPFLAGS = $(LIBSYSTEMD_JOURNAL_CFLAGS)
+journal_print_LDADD = $(LIBSYSTEMD_JOURNAL_LIBS)
+diagtalker_SOURCES = diagtalker.c
+diagtalker_LDADD = $(SOL_LIBS)
+randomgen_SOURCES = randomgen.c
+randomgen_LDADD = $(SOL_LIBS)
+inputfilegen_SOURCES = inputfilegen.c
+inputfilegen_LDADD = $(SOL_LIBS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .sh .sh$(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) --gnu tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+set-envvars: $(top_builddir)/config.status $(srcdir)/set-envvars.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+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-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}; \
+ }
+
+liboverride_getaddrinfo.la: $(liboverride_getaddrinfo_la_OBJECTS) $(liboverride_getaddrinfo_la_DEPENDENCIES) $(EXTRA_liboverride_getaddrinfo_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(liboverride_getaddrinfo_la_LINK) $(am_liboverride_getaddrinfo_la_rpath) $(liboverride_getaddrinfo_la_OBJECTS) $(liboverride_getaddrinfo_la_LIBADD) $(LIBS)
+
+liboverride_gethostname.la: $(liboverride_gethostname_la_OBJECTS) $(liboverride_gethostname_la_DEPENDENCIES) $(EXTRA_liboverride_gethostname_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(liboverride_gethostname_la_LINK) $(am_liboverride_gethostname_la_rpath) $(liboverride_gethostname_la_OBJECTS) $(liboverride_gethostname_la_LIBADD) $(LIBS)
+
+liboverride_gethostname_nonfqdn.la: $(liboverride_gethostname_nonfqdn_la_OBJECTS) $(liboverride_gethostname_nonfqdn_la_DEPENDENCIES) $(EXTRA_liboverride_gethostname_nonfqdn_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(liboverride_gethostname_nonfqdn_la_LINK) $(am_liboverride_gethostname_nonfqdn_la_rpath) $(liboverride_gethostname_nonfqdn_la_OBJECTS) $(liboverride_gethostname_nonfqdn_la_LIBADD) $(LIBS)
+
+check_relpEngineVersion$(EXEEXT): $(check_relpEngineVersion_OBJECTS) $(check_relpEngineVersion_DEPENDENCIES) $(EXTRA_check_relpEngineVersion_DEPENDENCIES)
+ @rm -f check_relpEngineVersion$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(check_relpEngineVersion_OBJECTS) $(check_relpEngineVersion_LDADD) $(LIBS)
+
+chkseq$(EXEEXT): $(chkseq_OBJECTS) $(chkseq_DEPENDENCIES) $(EXTRA_chkseq_DEPENDENCIES)
+ @rm -f chkseq$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(chkseq_OBJECTS) $(chkseq_LDADD) $(LIBS)
+
+diagtalker$(EXEEXT): $(diagtalker_OBJECTS) $(diagtalker_DEPENDENCIES) $(EXTRA_diagtalker_DEPENDENCIES)
+ @rm -f diagtalker$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(diagtalker_OBJECTS) $(diagtalker_LDADD) $(LIBS)
+
+have_relpEngineSetTLSLibByName$(EXEEXT): $(have_relpEngineSetTLSLibByName_OBJECTS) $(have_relpEngineSetTLSLibByName_DEPENDENCIES) $(EXTRA_have_relpEngineSetTLSLibByName_DEPENDENCIES)
+ @rm -f have_relpEngineSetTLSLibByName$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(have_relpEngineSetTLSLibByName_OBJECTS) $(have_relpEngineSetTLSLibByName_LDADD) $(LIBS)
+
+have_relpSrvSetOversizeMode$(EXEEXT): $(have_relpSrvSetOversizeMode_OBJECTS) $(have_relpSrvSetOversizeMode_DEPENDENCIES) $(EXTRA_have_relpSrvSetOversizeMode_DEPENDENCIES)
+ @rm -f have_relpSrvSetOversizeMode$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(have_relpSrvSetOversizeMode_OBJECTS) $(have_relpSrvSetOversizeMode_LDADD) $(LIBS)
+
+have_relpSrvSetTlsConfigCmd$(EXEEXT): $(have_relpSrvSetTlsConfigCmd_OBJECTS) $(have_relpSrvSetTlsConfigCmd_DEPENDENCIES) $(EXTRA_have_relpSrvSetTlsConfigCmd_DEPENDENCIES)
+ @rm -f have_relpSrvSetTlsConfigCmd$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(have_relpSrvSetTlsConfigCmd_OBJECTS) $(have_relpSrvSetTlsConfigCmd_LDADD) $(LIBS)
+
+inputfilegen$(EXEEXT): $(inputfilegen_OBJECTS) $(inputfilegen_DEPENDENCIES) $(EXTRA_inputfilegen_DEPENDENCIES)
+ @rm -f inputfilegen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(inputfilegen_OBJECTS) $(inputfilegen_LDADD) $(LIBS)
+
+journal_print$(EXEEXT): $(journal_print_OBJECTS) $(journal_print_DEPENDENCIES) $(EXTRA_journal_print_DEPENDENCIES)
+ @rm -f journal_print$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(journal_print_OBJECTS) $(journal_print_LDADD) $(LIBS)
+
+mangle_qi$(EXEEXT): $(mangle_qi_OBJECTS) $(mangle_qi_DEPENDENCIES) $(EXTRA_mangle_qi_DEPENDENCIES)
+ @rm -f mangle_qi$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(mangle_qi_OBJECTS) $(mangle_qi_LDADD) $(LIBS)
+
+miniamqpsrvr$(EXEEXT): $(miniamqpsrvr_OBJECTS) $(miniamqpsrvr_DEPENDENCIES) $(EXTRA_miniamqpsrvr_DEPENDENCIES)
+ @rm -f miniamqpsrvr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(miniamqpsrvr_OBJECTS) $(miniamqpsrvr_LDADD) $(LIBS)
+
+minitcpsrv$(EXEEXT): $(minitcpsrv_OBJECTS) $(minitcpsrv_DEPENDENCIES) $(EXTRA_minitcpsrv_DEPENDENCIES)
+ @rm -f minitcpsrv$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(minitcpsrv_OBJECTS) $(minitcpsrv_LDADD) $(LIBS)
+
+msleep$(EXEEXT): $(msleep_OBJECTS) $(msleep_DEPENDENCIES) $(EXTRA_msleep_DEPENDENCIES)
+ @rm -f msleep$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(msleep_OBJECTS) $(msleep_LDADD) $(LIBS)
+
+omrelp_dflt_port$(EXEEXT): $(omrelp_dflt_port_OBJECTS) $(omrelp_dflt_port_DEPENDENCIES) $(EXTRA_omrelp_dflt_port_DEPENDENCIES)
+ @rm -f omrelp_dflt_port$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(omrelp_dflt_port_OBJECTS) $(omrelp_dflt_port_LDADD) $(LIBS)
+
+ourtail$(EXEEXT): $(ourtail_OBJECTS) $(ourtail_DEPENDENCIES) $(EXTRA_ourtail_DEPENDENCIES)
+ @rm -f ourtail$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ourtail_OBJECTS) $(ourtail_LDADD) $(LIBS)
+
+randomgen$(EXEEXT): $(randomgen_OBJECTS) $(randomgen_DEPENDENCIES) $(EXTRA_randomgen_DEPENDENCIES)
+ @rm -f randomgen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(randomgen_OBJECTS) $(randomgen_LDADD) $(LIBS)
+
+syslog_caller$(EXEEXT): $(syslog_caller_OBJECTS) $(syslog_caller_DEPENDENCIES) $(EXTRA_syslog_caller_DEPENDENCIES)
+ @rm -f syslog_caller$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(syslog_caller_OBJECTS) $(syslog_caller_LDADD) $(LIBS)
+
+tcpflood$(EXEEXT): $(tcpflood_OBJECTS) $(tcpflood_DEPENDENCIES) $(EXTRA_tcpflood_DEPENDENCIES)
+ @rm -f tcpflood$(EXEEXT)
+ $(AM_V_CCLD)$(tcpflood_LINK) $(tcpflood_OBJECTS) $(tcpflood_LDADD) $(LIBS)
+
+test_id$(EXEEXT): $(test_id_OBJECTS) $(test_id_DEPENDENCIES) $(EXTRA_test_id_DEPENDENCIES)
+ @rm -f test_id$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_id_OBJECTS) $(test_id_LDADD) $(LIBS)
+
+uxsockrcvr$(EXEEXT): $(uxsockrcvr_OBJECTS) $(uxsockrcvr_DEPENDENCIES) $(EXTRA_uxsockrcvr_DEPENDENCIES)
+ @rm -f uxsockrcvr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(uxsockrcvr_OBJECTS) $(uxsockrcvr_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_relpEngineVersion.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chkseq.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diagtalker.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/have_relpEngineSetTLSLibByName.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/have_relpSrvSetOversizeMode.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/have_relpSrvSetTlsConfigCmd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inputfilegen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/journal_print-journal_print.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboverride_gethostname_la-override_gethostname.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangle_qi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minitcpsrvr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msleep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omrelp_dflt_port.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ourtail.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/randomgen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog_caller-syslog_caller.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcpflood-tcpflood.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_id.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uxsockrcvr.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+liboverride_getaddrinfo_la-override_getaddrinfo.lo: override_getaddrinfo.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) $(liboverride_getaddrinfo_la_CFLAGS) $(CFLAGS) -MT liboverride_getaddrinfo_la-override_getaddrinfo.lo -MD -MP -MF $(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Tpo -c -o liboverride_getaddrinfo_la-override_getaddrinfo.lo `test -f 'override_getaddrinfo.c' || echo '$(srcdir)/'`override_getaddrinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Tpo $(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='override_getaddrinfo.c' object='liboverride_getaddrinfo_la-override_getaddrinfo.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) $(liboverride_getaddrinfo_la_CFLAGS) $(CFLAGS) -c -o liboverride_getaddrinfo_la-override_getaddrinfo.lo `test -f 'override_getaddrinfo.c' || echo '$(srcdir)/'`override_getaddrinfo.c
+
+liboverride_gethostname_la-override_gethostname.lo: override_gethostname.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) $(liboverride_gethostname_la_CFLAGS) $(CFLAGS) -MT liboverride_gethostname_la-override_gethostname.lo -MD -MP -MF $(DEPDIR)/liboverride_gethostname_la-override_gethostname.Tpo -c -o liboverride_gethostname_la-override_gethostname.lo `test -f 'override_gethostname.c' || echo '$(srcdir)/'`override_gethostname.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboverride_gethostname_la-override_gethostname.Tpo $(DEPDIR)/liboverride_gethostname_la-override_gethostname.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='override_gethostname.c' object='liboverride_gethostname_la-override_gethostname.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) $(liboverride_gethostname_la_CFLAGS) $(CFLAGS) -c -o liboverride_gethostname_la-override_gethostname.lo `test -f 'override_gethostname.c' || echo '$(srcdir)/'`override_gethostname.c
+
+liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.lo: override_gethostname_nonfqdn.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) $(liboverride_gethostname_nonfqdn_la_CFLAGS) $(CFLAGS) -MT liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.lo -MD -MP -MF $(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Tpo -c -o liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.lo `test -f 'override_gethostname_nonfqdn.c' || echo '$(srcdir)/'`override_gethostname_nonfqdn.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Tpo $(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='override_gethostname_nonfqdn.c' object='liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.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) $(liboverride_gethostname_nonfqdn_la_CFLAGS) $(CFLAGS) -c -o liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.lo `test -f 'override_gethostname_nonfqdn.c' || echo '$(srcdir)/'`override_gethostname_nonfqdn.c
+
+journal_print-journal_print.o: journal_print.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(journal_print_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT journal_print-journal_print.o -MD -MP -MF $(DEPDIR)/journal_print-journal_print.Tpo -c -o journal_print-journal_print.o `test -f 'journal_print.c' || echo '$(srcdir)/'`journal_print.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/journal_print-journal_print.Tpo $(DEPDIR)/journal_print-journal_print.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='journal_print.c' object='journal_print-journal_print.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) $(journal_print_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o journal_print-journal_print.o `test -f 'journal_print.c' || echo '$(srcdir)/'`journal_print.c
+
+journal_print-journal_print.obj: journal_print.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(journal_print_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT journal_print-journal_print.obj -MD -MP -MF $(DEPDIR)/journal_print-journal_print.Tpo -c -o journal_print-journal_print.obj `if test -f 'journal_print.c'; then $(CYGPATH_W) 'journal_print.c'; else $(CYGPATH_W) '$(srcdir)/journal_print.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/journal_print-journal_print.Tpo $(DEPDIR)/journal_print-journal_print.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='journal_print.c' object='journal_print-journal_print.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) $(journal_print_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o journal_print-journal_print.obj `if test -f 'journal_print.c'; then $(CYGPATH_W) 'journal_print.c'; else $(CYGPATH_W) '$(srcdir)/journal_print.c'; fi`
+
+miniamqpsrvr-miniamqpsrvr.o: miniamqpsrvr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(miniamqpsrvr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT miniamqpsrvr-miniamqpsrvr.o -MD -MP -MF $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Tpo -c -o miniamqpsrvr-miniamqpsrvr.o `test -f 'miniamqpsrvr.c' || echo '$(srcdir)/'`miniamqpsrvr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Tpo $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='miniamqpsrvr.c' object='miniamqpsrvr-miniamqpsrvr.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) $(miniamqpsrvr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o miniamqpsrvr-miniamqpsrvr.o `test -f 'miniamqpsrvr.c' || echo '$(srcdir)/'`miniamqpsrvr.c
+
+miniamqpsrvr-miniamqpsrvr.obj: miniamqpsrvr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(miniamqpsrvr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT miniamqpsrvr-miniamqpsrvr.obj -MD -MP -MF $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Tpo -c -o miniamqpsrvr-miniamqpsrvr.obj `if test -f 'miniamqpsrvr.c'; then $(CYGPATH_W) 'miniamqpsrvr.c'; else $(CYGPATH_W) '$(srcdir)/miniamqpsrvr.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Tpo $(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='miniamqpsrvr.c' object='miniamqpsrvr-miniamqpsrvr.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) $(miniamqpsrvr_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o miniamqpsrvr-miniamqpsrvr.obj `if test -f 'miniamqpsrvr.c'; then $(CYGPATH_W) 'miniamqpsrvr.c'; else $(CYGPATH_W) '$(srcdir)/miniamqpsrvr.c'; fi`
+
+syslog_caller-syslog_caller.o: syslog_caller.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syslog_caller_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog_caller-syslog_caller.o -MD -MP -MF $(DEPDIR)/syslog_caller-syslog_caller.Tpo -c -o syslog_caller-syslog_caller.o `test -f 'syslog_caller.c' || echo '$(srcdir)/'`syslog_caller.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog_caller-syslog_caller.Tpo $(DEPDIR)/syslog_caller-syslog_caller.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslog_caller.c' object='syslog_caller-syslog_caller.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) $(syslog_caller_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog_caller-syslog_caller.o `test -f 'syslog_caller.c' || echo '$(srcdir)/'`syslog_caller.c
+
+syslog_caller-syslog_caller.obj: syslog_caller.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syslog_caller_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog_caller-syslog_caller.obj -MD -MP -MF $(DEPDIR)/syslog_caller-syslog_caller.Tpo -c -o syslog_caller-syslog_caller.obj `if test -f 'syslog_caller.c'; then $(CYGPATH_W) 'syslog_caller.c'; else $(CYGPATH_W) '$(srcdir)/syslog_caller.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog_caller-syslog_caller.Tpo $(DEPDIR)/syslog_caller-syslog_caller.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslog_caller.c' object='syslog_caller-syslog_caller.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) $(syslog_caller_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog_caller-syslog_caller.obj `if test -f 'syslog_caller.c'; then $(CYGPATH_W) 'syslog_caller.c'; else $(CYGPATH_W) '$(srcdir)/syslog_caller.c'; fi`
+
+tcpflood-tcpflood.o: tcpflood.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tcpflood_CPPFLAGS) $(CPPFLAGS) $(tcpflood_CFLAGS) $(CFLAGS) -MT tcpflood-tcpflood.o -MD -MP -MF $(DEPDIR)/tcpflood-tcpflood.Tpo -c -o tcpflood-tcpflood.o `test -f 'tcpflood.c' || echo '$(srcdir)/'`tcpflood.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tcpflood-tcpflood.Tpo $(DEPDIR)/tcpflood-tcpflood.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpflood.c' object='tcpflood-tcpflood.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) $(tcpflood_CPPFLAGS) $(CPPFLAGS) $(tcpflood_CFLAGS) $(CFLAGS) -c -o tcpflood-tcpflood.o `test -f 'tcpflood.c' || echo '$(srcdir)/'`tcpflood.c
+
+tcpflood-tcpflood.obj: tcpflood.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tcpflood_CPPFLAGS) $(CPPFLAGS) $(tcpflood_CFLAGS) $(CFLAGS) -MT tcpflood-tcpflood.obj -MD -MP -MF $(DEPDIR)/tcpflood-tcpflood.Tpo -c -o tcpflood-tcpflood.obj `if test -f 'tcpflood.c'; then $(CYGPATH_W) 'tcpflood.c'; else $(CYGPATH_W) '$(srcdir)/tcpflood.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tcpflood-tcpflood.Tpo $(DEPDIR)/tcpflood-tcpflood.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpflood.c' object='tcpflood-tcpflood.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) $(tcpflood_CPPFLAGS) $(CPPFLAGS) $(tcpflood_CFLAGS) $(CFLAGS) -c -o tcpflood-tcpflood.obj `if test -f 'tcpflood.c'; then $(CYGPATH_W) 'tcpflood.c'; else $(CYGPATH_W) '$(srcdir)/tcpflood.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; \
+ elif test -n "$$redo_logs"; then \
+ 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: $(check_PROGRAMS)
+ @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 $$?
+.sh.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(SH_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_SH_LOG_DRIVER_FLAGS) $(SH_LOG_DRIVER_FLAGS) -- $(SH_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.sh$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(SH_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_SH_LOG_DRIVER_FLAGS) $(SH_LOG_DRIVER_FLAGS) -- $(SH_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; 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:
+ -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-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-pkglibLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/check_relpEngineVersion.Po
+ -rm -f ./$(DEPDIR)/chkseq.Po
+ -rm -f ./$(DEPDIR)/diagtalker.Po
+ -rm -f ./$(DEPDIR)/have_relpEngineSetTLSLibByName.Po
+ -rm -f ./$(DEPDIR)/have_relpSrvSetOversizeMode.Po
+ -rm -f ./$(DEPDIR)/have_relpSrvSetTlsConfigCmd.Po
+ -rm -f ./$(DEPDIR)/inputfilegen.Po
+ -rm -f ./$(DEPDIR)/journal_print-journal_print.Po
+ -rm -f ./$(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Plo
+ -rm -f ./$(DEPDIR)/liboverride_gethostname_la-override_gethostname.Plo
+ -rm -f ./$(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Plo
+ -rm -f ./$(DEPDIR)/mangle_qi.Po
+ -rm -f ./$(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po
+ -rm -f ./$(DEPDIR)/minitcpsrvr.Po
+ -rm -f ./$(DEPDIR)/msleep.Po
+ -rm -f ./$(DEPDIR)/omrelp_dflt_port.Po
+ -rm -f ./$(DEPDIR)/ourtail.Po
+ -rm -f ./$(DEPDIR)/randomgen.Po
+ -rm -f ./$(DEPDIR)/syslog_caller-syslog_caller.Po
+ -rm -f ./$(DEPDIR)/tcpflood-tcpflood.Po
+ -rm -f ./$(DEPDIR)/test_id.Po
+ -rm -f ./$(DEPDIR)/uxsockrcvr.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-local 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-pkglibLTLIBRARIES
+
+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 ./$(DEPDIR)/check_relpEngineVersion.Po
+ -rm -f ./$(DEPDIR)/chkseq.Po
+ -rm -f ./$(DEPDIR)/diagtalker.Po
+ -rm -f ./$(DEPDIR)/have_relpEngineSetTLSLibByName.Po
+ -rm -f ./$(DEPDIR)/have_relpSrvSetOversizeMode.Po
+ -rm -f ./$(DEPDIR)/have_relpSrvSetTlsConfigCmd.Po
+ -rm -f ./$(DEPDIR)/inputfilegen.Po
+ -rm -f ./$(DEPDIR)/journal_print-journal_print.Po
+ -rm -f ./$(DEPDIR)/liboverride_getaddrinfo_la-override_getaddrinfo.Plo
+ -rm -f ./$(DEPDIR)/liboverride_gethostname_la-override_gethostname.Plo
+ -rm -f ./$(DEPDIR)/liboverride_gethostname_nonfqdn_la-override_gethostname_nonfqdn.Plo
+ -rm -f ./$(DEPDIR)/mangle_qi.Po
+ -rm -f ./$(DEPDIR)/miniamqpsrvr-miniamqpsrvr.Po
+ -rm -f ./$(DEPDIR)/minitcpsrvr.Po
+ -rm -f ./$(DEPDIR)/msleep.Po
+ -rm -f ./$(DEPDIR)/omrelp_dflt_port.Po
+ -rm -f ./$(DEPDIR)/ourtail.Po
+ -rm -f ./$(DEPDIR)/randomgen.Po
+ -rm -f ./$(DEPDIR)/syslog_caller-syslog_caller.Po
+ -rm -f ./$(DEPDIR)/tcpflood-tcpflood.Po
+ -rm -f ./$(DEPDIR)/test_id.Po
+ -rm -f ./$(DEPDIR)/uxsockrcvr.Po
+ -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-pkglibLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-pkglibLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-local 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-pkglibLTLIBRARIES 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 recheck tags tags-am uninstall \
+ uninstall-am uninstall-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-es7.14.log: es-basic-es6.0.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic.log: es-basic-es7.14.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-bulk.log: es-basic.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-server.log: es-basic-bulk.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@elasticsearch-stop.log: es-basic-bulk.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-vg.log: es-basic-bulk.log
+# for next if block:
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-server.log: es-basic-vg.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@elasticsearch-stop.log: es-basic-vg.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_HELGRIND_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-vgthread.log: es-basic-vg.log
+# for next if block:
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_HELGRIND_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-server.log: es-basic-vgthread.log
+@ENABLE_ELASTICSEARCH_TESTS_MINIMAL_TRUE@@ENABLE_HELGRIND_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@elasticsearch-stop.log: es-basic-vgthread.log
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-server.log: es-basic-bulk.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-execOnlyWhenPreviousSuspended.log: es-basic-server.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-maxbytes-bulk.log: es-execOnlyWhenPreviousSuspended.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-errfile-empty.log: es-maxbytes-bulk.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-errfile-popul.log: es-basic-errfile-empty.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-empty.log: es-basic-errfile-popul.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-popul.log: es-bulk-errfile-empty.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-searchType-empty.log: es-bulk-errfile-popul.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@diskqueue-multithread-es.log: es-searchType-empty.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@es-writeoperation.log: diskqueue-multithread-es.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@elasticsearch-stop.log: es-writeoperation.log
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@es-basic-ha.log: es-writeoperation.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-retry.log: es-basic-ha.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMPSTATS_TRUE@@ENABLE_TESTBENCH_TRUE@elasticsearch-stop.log: es-bulk-retry.log
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-popul-def-format.log: es-bulk-retry.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-popul-erronly.log: es-bulk-errfile-popul-def-format.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-popul-erronly-interleaved.log: es-bulk-errfile-popul-erronly.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@es-bulk-errfile-popul-def-interleaved.log: es-bulk-errfile-popul-erronly-interleaved.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_IMFILE_TRUE@@ENABLE_TESTBENCH_TRUE@elasticsearch-stop.log: es-bulk-errfile-popul-def-interleaved.log
+
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-bulk-vg.log: es-writeoperation.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-bulk-vg.log: es-bulk-retry.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-bulk-vg.log: es-bulk-errfile-popul-def-interleaved.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@es-basic-ha-vg.log: es-basic-bulk-vg.log
+@ENABLE_ELASTICSEARCH_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@elasticsearch-stop.log: es-basic-ha-vg.log
+
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-basic.log: clickhouse-start.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-dflt-tpl.log: clickhouse-basic.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-retry-error.log: clickhouse-dflt-tpl.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-load.log: clickhouse-retry-error.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-bulk.log: clickhouse-load.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-bulk-load.log: clickhouse-bulk.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-limited-batch.log: clickhouse-bulk-load.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-select.log: clickhouse-limited-batch.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-errorfile.log: clickhouse-select.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-wrong-quotation-marks.log: clickhouse-errorfile.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-wrong-template-option.log: clickhouse-wrong-quotation-marks.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-wrong-insert-syntax.log: clickhouse-wrong-template-option.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@clickhouse-stop.log: clickhouse-wrong-insert-syntax.log
+
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@clickhouse-basic-vg.log: clickhouse-wrong-insert-syntax.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@clickhouse-load-vg.log: clickhouse-basic-vg.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@clickhouse-bulk-vg.log: clickhouse-load-vg.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@clickhouse-bulk-load-vg.log: clickhouse-bulk-vg.log
+@ENABLE_CLICKHOUSE_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@clickhouse-stop.log: clickhouse-bulk-load-vg.log
+
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-basic-cnf6.log: pgsql-basic.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-basic-threads-cnf6.log: pgsql-basic-cnf6.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-template.log: pgsql-basic-threads-cnf6.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-template-cnf6.log: pgsql-template.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-actq-mt-withpause.log: pgsql-template-cnf6.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@pgsql-template-threads-cnf6.log: pgsql-actq-mt-withpause.log
+
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@pgsql-basic-vg.log: pgsql-template-threads-cnf6.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@pgsql-template-vg.log: pgsql-basic-vg.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@pgsql-basic-cnf6-vg.log: pgsql-template-vg.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@pgsql-template-cnf6-vg.log: pgsql-basic-cnf6-vg.log
+@ENABLE_PGSQL_TESTS_TRUE@@ENABLE_PGSQL_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@pgsql-actq-mt-withpause-vg.log: pgsql-template-cnf6-vg.log
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysql-basic.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysql-basic-cnf6.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysql-asyn.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysql-actq-mt.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysql-actq-mt-withpause.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@action-tx-single-processing.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@action-tx-errfile.log: mysqld-start.log
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@mysqld-stop.log: mysql-basic.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-basic-cnf6.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-asyn.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-actq-mt.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ mysql-actq-mt-withpause.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ action-tx-single-processing.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@ action-tx-errfile.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@mysql-basic-vg.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@mysql-asyn-vg.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@mysql-actq-mt-withpause-vg.log: mysqld-start.log
+
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@mysqld-stop.log: mysql-basic-vg.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mysql-asyn-vg.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@ mysql-actq-mt-withpause-vg.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@libdbi-basic.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@libdbi-asyn.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@mysqld-stop.log: libdbi-basic.log \
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@ libdbi-asyn.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@libdbi-basic-vg.log: mysqld-start.log
+@ENABLE_MYSQL_TESTS_TRUE@@ENABLE_OMLIBDBI_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@mysqld-stop.log: libdbi-basic-vg.log
+# Tests below need to be stable first!
+# sndrcv_kafka_fail.sh \
+# sndrcv_kafka_failresume.sh \
+# needs properly to much mempory on arm devices!
+# sndrcv_kafka_multi.sh
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@omkafka.log: kafka-selftest.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka.log: omkafka.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka-backgrounded.log: imkafka.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka-config-err-ruleset.log: imkafka-backgrounded.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka-config-err-param.log: imkafka-config-err-ruleset.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka-hang-on-no-kafka.log: imkafka-config-err-param.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka-hang-other-action-on-no-kafka.log: imkafka-hang-on-no-kafka.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka_multi_single.log: imkafka-hang-other-action-on-no-kafka.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@sndrcv_kafka.log: imkafka_multi_single.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@imkafka_multi_group.log: sndrcv_kafka.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@sndrcv_kafka_multi_topics.log: imkafka_multi_group.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@omkafkadynakey.log: sndrcv_kafka_multi_topics.log
+
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@omkafka-vg.log: sndrcv_kafka_multi_topics.log
+@ENABLE_IMKAFKA_TRUE@@ENABLE_KAFKA_TESTS_TRUE@@ENABLE_OMKAFKA_TRUE@@ENABLE_TESTBENCH_TRUE@@HAVE_VALGRIND_TRUE@imkafka-vg.log: omkafka-vg.log
+
+distclean-local:
+ rm -rf .dep_cache .dep_wrk
+
+# rtinit tests disabled for the moment - also questionable if they
+# really provide value (after all, everything fails if rtinit fails...)
+#rt_init_SOURCES = rt-init.c $(test_files)
+#rt_init_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+#rt_init_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS)
+#rt_init_LDFLAGS = -export-dynamic
+
+# same for basic rscript tests
+#rscript_SOURCES = rscript.c getline.c $(test_files)
+#rscript_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+#rscript_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS)
+#rscript_LDFLAGS = -export-dynamic
+
+# 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/tests/NoExistFile.cfgtest b/tests/NoExistFile.cfgtest
new file mode 100644
index 0000000..39d008f
--- /dev/null
+++ b/tests/NoExistFile.cfgtest
@@ -0,0 +1,2 @@
+rsyslogd: CONFIG ERROR: could not interpret master config file '/This/does/not/exist'. [try https://www.rsyslog.com/e/2013 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..63a15d4
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,102 @@
+This directory contains the rsyslog testbench. It is slowly
+evolving. New tests are always welcome. So far, most tests check
+out the functionality of a single module. More complex tests are
+welcome.
+
+For a simple sample, see rtinit.c, which does a simple
+init/deinit check of the runtime system.
+
+Test Naming
+===========
+
+Test that use valgrind shall end in "-vg.sh".
+Test that use valgrind's helgrind thread debugger shall end in "-vgthread.sh".
+
+Setting up Test Environments
+============================
+
+Setting up MariaDB/MySQL
+------------------------
+to create the necessary user:
+
+echo "create user 'rsyslog'@'localhost' identified by 'testbench';" | mysql -u root
+mysql -u root < ../plugins/ommysql/createDB.sql
+echo "grant all on Syslog.* to 'rsyslog'@'localhost';" | mysql -u root
+
+openSUSE
+--------
+To configure system properties like hostname and firewall, use the
+graphical "yast2" administration tool. Note the ssh-access by default
+is disable in the firewall!
+
+Before running tests
+====================
+make check - this will compile all of the C code used in the tests, as well as
+do any other preparations, and will start running all of the tests. Ctrl-C to
+stop running all of the tests.
+
+Running all tests
+=================
+make check
+
+Running named tests
+===================
+make testname.log
+
+For example, to run the imfile-basic.sh test, use
+
+ make imfile-basic.log
+
+Test output is in imfile-basic.log
+
+To re-run the test, first remove imfile-basic.log then make again
+
+Or an alternative option is to run
+
+ make check TESTS='imfile-basic.sh'
+
+* Using gdb to debug rsyslog during a test run
+
+Edit your test like this:
+
+ . $srcdir/diag.sh startup
+ if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+ fi
+
+Run your test in the background:
+
+ USE_GDB=1 make mytest.sh.log &
+
+Tail mytest.sh.log until you see 'attach gdb here'. The log should also
+tell you what is the rsyslogd pid.
+
+ gdb ../tools/rsyslogd $rsyslogd_pid
+
+Set breakpoints, whatever, then 'continue'
+
+In another window, do ps -ef|grep 54321, then kill that pid
+
+Core Dump Analysis
+==================
+The testbench contains some limited (yet useful) support for automatically
+analyzing core dumps. In order for this to work, obviously core files need
+to be generated. This often doesn't work as intended. If you hit this problem,
+check
+
+1. ulimit -c unlimited (or a reasonable limit)
+ Note that root may need to increase a system-wide limit, which is
+ usually recorded in /etc/security/limits.conf
+ You need:
+ * soft core unlimited
+
+2. cat /proc/sys/kernel/core_pattern"
+ On systemd systems (and some others), the pattern is changed to save
+ core files so that systemd can import them -- with the result that the
+ testbench doesn't see them any longer. We require classic format, which
+ can be set via
+ $ sudo bash -c "echo \"core\" > /proc/sys/kernel/core_pattern"
+
+Note that you probably want to do neither of these changes to a production
+system.
diff --git a/tests/abort-uncleancfg-badcfg-check.sh b/tests/abort-uncleancfg-badcfg-check.sh
new file mode 100755
index 0000000..aa09eef
--- /dev/null
+++ b/tests/abort-uncleancfg-badcfg-check.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 2015-01-29 by Tim Eifler
+# This file is part of the rsyslog project, released under ASL 2.0
+# The configuration test should fail because of the invalid config file.
+. ${srcdir:=.}/diag.sh init
+../tools/rsyslogd -C -N1 -f$srcdir/testsuites/abort-uncleancfg-badcfg.conf -M../runtime/.libs:../.libs
+if [ $? == 0 ]; then
+ echo "Error: config check should fail"
+ error_exit 1
+fi
+printf 'unclean config lead to exit, as expected - OK\n'
+exit_test
+
diff --git a/tests/abort-uncleancfg-badcfg-check_1.sh b/tests/abort-uncleancfg-badcfg-check_1.sh
new file mode 100755
index 0000000..986688b
--- /dev/null
+++ b/tests/abort-uncleancfg-badcfg-check_1.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 2015-01-29 by Tim Eifler
+# This file is part of the rsyslog project, released under ASL 2.0
+# The configuration test should fail because of the invalid config file.
+echo ===============================================================================
+echo \[abort-uncleancfg-badcfg_1.sh\]: testing abort on unclean configuration
+echo "testing a bad Configuration verification run"
+. ${srcdir:=.}/diag.sh init
+../tools/rsyslogd -C -N1 -f$srcdir/testsuites/abort-uncleancfg-badcfg_1.conf -M../runtime/.libs:../.libs
+if [ $? == 0 ]; then
+ echo "Error: config check should fail"
+ exit 1
+fi
+exit_test
+
diff --git a/tests/abort-uncleancfg-goodcfg-check.sh b/tests/abort-uncleancfg-goodcfg-check.sh
new file mode 100755
index 0000000..cc576a8
--- /dev/null
+++ b/tests/abort-uncleancfg-goodcfg-check.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 2015-01-29 by Tim Eifler
+# This file is part of the rsyslog project, released under ASL 2.0
+# The configuration test should pass because of the good config file.
+. ${srcdir:=.}/diag.sh init
+echo "testing a good Configuration verification run"
+../tools/rsyslogd -C -N1 -f$srcdir/testsuites/abort-uncleancfg-goodcfg.conf -M../runtime/.libs:../.libs
+if [ $? -ne 0 ]; then
+ echo "Error: config check fail"
+ exit 1
+fi
+exit_test
+
diff --git a/tests/abort-uncleancfg-goodcfg.sh b/tests/abort-uncleancfg-goodcfg.sh
new file mode 100755
index 0000000..7dcc92b
--- /dev/null
+++ b/tests/abort-uncleancfg-goodcfg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 2015-01-29 by Tim Eifler
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[abort-uncleancfg-goodcfg.sh\]: testing abort on unclean configuration
+echo "testing a good Configuration verification run"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$AbortOnUncleanConfig on
+$MainMsgQueueTimeoutShutdown 10000
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg 1 10
+shutdown_when_empty
+wait_shutdown
+
+if [ ! -e $RSYSLOG_OUT_LOG ]
+then
+ echo "error: expected file does not exist"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/action-tx-errfile-maxsize.sh b/tests/action-tx-errfile-maxsize.sh
new file mode 100755
index 0000000..eaff6d7
--- /dev/null
+++ b/tests/action-tx-errfile-maxsize.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# part of the rsyslog project, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50 # enough to generate big file
+export MAX_ERROR_SIZE=100
+
+generate_conf
+add_conf '
+$ModLoad ../plugins/ommysql/.libs/ommysql
+global(errormessagestostderr.maxnumber="5")
+
+template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on")
+
+if((not($msg contains "error")) and ($msg contains "msgnum:")) then {
+ set $.num = field($msg, 58, 2);
+ if $.num % 2 == 0 then {
+ set $!facility = $syslogfacility;
+ } else {
+ set $/cntr = 0;
+ }
+ action(type="ommysql" name="mysql_action_errfile_maxsize" server="127.0.0.1" template="tpl"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
+}
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+check_file_exists ${RSYSLOG2_OUT_LOG}
+file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
+exit_test
diff --git a/tests/action-tx-errfile.sh b/tests/action-tx-errfile.sh
new file mode 100755
index 0000000..fd492d3
--- /dev/null
+++ b/tests/action-tx-errfile.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# added by Rainer Gerhards 2018-01-05
+# part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50 # sufficient for our needs!
+export SEQ_CHECK_OPTIONS=-i2
+check_sql_data_ready() {
+ mysql_get_data
+ seq_check --check-only 0 $((NUMMESSAGES - 2))
+}
+export QUEUE_EMPTY_CHECK_FUNC=check_sql_data_ready
+
+generate_conf
+add_conf '
+$ModLoad ../plugins/ommysql/.libs/ommysql
+global(errormessagestostderr.maxnumber="5")
+
+template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on")
+
+if((not($msg contains "error")) and ($msg contains "msgnum:")) then {
+ set $.num = field($msg, 58, 2);
+ if $.num % 2 == 0 then {
+ set $!facility = $syslogfacility;
+ } else {
+ set $/cntr = 0;
+ }
+ action(type="ommysql" name="mysql_action" server="127.0.0.1" template="tpl"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'")
+}
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="$(cat ${srcdir}/testsuites/action-tx-errfile.result)"
+cmp_exact ${RSYSLOG2_OUT_LOG}
+mysql_get_data
+seq_check 0 $((NUMMESSAGES - 2)) -i2
+exit_test
diff --git a/tests/action-tx-single-processing.sh b/tests/action-tx-single-processing.sh
new file mode 100755
index 0000000..43c9f2e
--- /dev/null
+++ b/tests/action-tx-single-processing.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=2000
+export SEQ_CHECK_OPTIONS=-i2
+check_sql_data_ready() {
+ mysql_get_data
+ seq_check --check-only 0 $((NUMMESSAGES - 2))
+}
+export QUEUE_EMPTY_CHECK_FUNC=check_sql_data_ready
+generate_conf
+add_conf '
+module(load="../plugins/ommysql/.libs/ommysql")
+global(errormessagestostderr.maxnumber="50")
+
+template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on")
+template(type="string" name="tpl2" string="%$.num%|%$!facility%|insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)\n" option.sql="on")
+
+if($msg contains "msgnum:") then {
+ set $.num = field($msg, 58, 2);
+ if $.num % 2 == 0 then {
+ set $!facility = $syslogfacility;
+ } else {
+ set $/cntr = 0;
+ }
+ action(type="ommysql" name="mysql_action" server="127.0.0.1" template="tpl"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench")
+}
+action(type="omfile" file="'$RSYSLOG2_OUT_LOG'")
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check 0 $((NUMMESSAGES - 2))
+exit_test
diff --git a/tests/allowed-sender-tcp-fail.sh b/tests/allowed-sender-tcp-fail.sh
new file mode 100755
index 0000000..81b053e
--- /dev/null
+++ b/tests/allowed-sender-tcp-fail.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# check that we are able to receive messages from allowed sender
+# added 2019-08-15 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5 # it's just important that we get any messages at all
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+
+$AllowedSender TCP,128.66.0.0/16 # this IP range is reserved by RFC5737
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="rs") {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_DYNNAME.must-not-be-created'")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+content_check --regex "connection request from disallowed sender .* discarded"
+check_file_not_exists "$RSYSLOG_DYNNAME.must-not-be-created"
+exit_test
diff --git a/tests/allowed-sender-tcp-hostname-fail.sh b/tests/allowed-sender-tcp-hostname-fail.sh
new file mode 100755
index 0000000..01ec9d7
--- /dev/null
+++ b/tests/allowed-sender-tcp-hostname-fail.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# check that we are able to receive messages from allowed sender
+# added 2019-08-19 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# Note: we need to know if CI supports DNS resolution. For this, we try to access
+# our rsyslog echo service. If that works, DNS obviously works. On the contrary
+# if we cannot access it, DNS might still work. But we prefer to skip the test in
+# that case (on rsyslog CI it will always work).
+rsyslog_testbench_test_url_access http://testbench.rsyslog.com/testbench/echo-get.php
+export NUMMESSAGES=5 # it's just important that we get any messages at all
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+
+$AllowedSender TCP,www.rsyslog.com
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="rs") {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_DYNNAME.must-not-be-created'")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+content_check --regex "connection request from disallowed sender .* discarded"
+check_file_not_exists "$RSYSLOG_DYNNAME.must-not-be-created"
+exit_test
diff --git a/tests/allowed-sender-tcp-hostname-ok.sh b/tests/allowed-sender-tcp-hostname-ok.sh
new file mode 100755
index 0000000..282800e
--- /dev/null
+++ b/tests/allowed-sender-tcp-hostname-ok.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# check that we are able to receive messages from allowed sender
+# added 2019-08-15 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+export NUMMESSAGES=5 # it's just important that we get any messages at all
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$AllowedSender TCP,*'$RS_HOSTNAME'*
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/allowed-sender-tcp-ok.sh b/tests/allowed-sender-tcp-ok.sh
new file mode 100755
index 0000000..75322ee
--- /dev/null
+++ b/tests/allowed-sender-tcp-ok.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# check that we are able to receive messages from allowed sender
+# added 2019-08-15 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5 # it's just important that we get any messages at all
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$AllowedSender TCP,127.0.0.1/16,[::1]
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/array_lookup_table-vg.sh b/tests/array_lookup_table-vg.sh
new file mode 100755
index 0000000..1f3ccf5
--- /dev/null
+++ b/tests/array_lookup_table-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-10-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/array_lookup_table.sh
diff --git a/tests/array_lookup_table.sh b/tests/array_lookup_table.sh
new file mode 100755
index 0000000..b141c0d
--- /dev/null
+++ b/tests/array_lookup_table.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# test for array lookup-table and HUP based reloading of it
+# added 2015-10-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate_array.lkp_tbl")
+
+template(name="outfmt" type="string" string="%msg% %$.lkp%\n")
+
+set $.num = field($msg, 58, 2);
+
+set $.lkp = lookup("xlate", $.num);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate_array.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+startup
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_array_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+cp -f $srcdir/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 12
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: quux"
+content_check "msgnum:00000001: quux"
+content_check "msgnum:00000002: foo_latest"
+content_check "msgnum:00000003: baz_latest"
+content_check "msgnum:00000004: foo_latest"
+content_check "msgnum:00000005: foo_latest"
+content_check "msgnum:00000006: baz_latest"
+content_check "msgnum:00000007: foo_latest"
+content_check "msgnum:00000008: baz_latest"
+content_check "msgnum:00000009: baz_latest"
+content_check "msgnum:00000010: quux"
+content_check "msgnum:00000011: quux"
+exit_test
diff --git a/tests/array_lookup_table_misuse-vg.sh b/tests/array_lookup_table_misuse-vg.sh
new file mode 100755
index 0000000..26ca1c2
--- /dev/null
+++ b/tests/array_lookup_table_misuse-vg.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# test cleanup for array lookup-table and HUP based reloading of it
+# added 2015-10-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate_array.lkp_tbl")
+
+template(name="outfmt" type="string" string="%msg% %$.lkp%\n")
+
+set $.num = field($msg, 58, 2);
+
+set $.lkp = lookup("xlate", $.num);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate_array_misuse.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+startup_vg
+injectmsg 0 3
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_array_more_misuse.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_array_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+exit_test
diff --git a/tests/arrayqueue.sh b/tests/arrayqueue.sh
new file mode 100755
index 0000000..16008cc
--- /dev/null
+++ b/tests/arrayqueue.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Test for fixedArray queue mode
+# added 2009-05-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=40000
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$MainMsgQueueType FixedArray
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/asynwr_deadlock.sh b/tests/asynwr_deadlock.sh
new file mode 100755
index 0000000..34e28c9
--- /dev/null
+++ b/tests/asynwr_deadlock.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This is test case from practice, with the version we introduced it, it
+# caused a deadlock on shutdown. I have added it to the test suite to automatically
+# detect such things in the future.
+#
+# added 2010-03-17 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ================================================================================
+echo TEST: \[asynwr_deadlock.sh\]: a case known to have caused a deadlock in the past
+. ${srcdir:=.}/diag.sh init
+export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=20 # this test is notoriously slow...
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+$template outfmt,"%msg:F,58:2%\n"
+
+$OMFileFlushOnTXEnd on
+$OMFileFlushInterval 10
+$OMFileIOBufferSize 10k
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+startup
+# just send one message
+tcpflood -m1
+# sleep is important! need to make sure the instance is inactive
+sleep 1
+# now try shutdown. The actual test is if the process does hang here!
+echo "processing must continue soon"
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 0
+exit_test
diff --git a/tests/asynwr_deadlock2.sh b/tests/asynwr_deadlock2.sh
new file mode 100755
index 0000000..f656721
--- /dev/null
+++ b/tests/asynwr_deadlock2.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# This is test case from practice, with the version we introduced it, it
+# caused a deadlock during processing (when the a stream was purged from the
+# dynafile cache).
+# We added this as a standard test in the hopes that iw will help
+# detect such things in the future.
+#
+# The problem that originally caused this test to fail was:
+# We write to files asynchronously (with the async writer thread). There is
+# no signaling done when the file stream is closed. That can lead to the writer
+# process hanging in memory, that in turn leads to the main thread waiting on a
+# condition that never occurs (because it would need to be signalled by the
+# async writer). Even worse, in that case, the async writer was signalled invalid
+# in such a way that when it received a wakeup, it thought it shall not terminate,
+# but received a spurios wakeup due to timeout and no data to write. In that case
+# it (correctly) concluded that it would not need to timeout until a new buffer write
+# was done (in which case it would receive a wakeup). As such, it went into an eternal
+# wait. However, the invalid signaling did not take into account that it did not
+# signal the async writer to shut down. So the main thread went into a condition
+# wait - and thus we had a deadlock. That situation occurred only under very specific
+# circumstances. As far as the analysis goes, the following need to happen:
+# 1. buffers on that file are being flushed
+# 2. no new data arrives
+# 3. the inactivity timeout has not yet expired
+# 4. *then* (and only then) the stream is closed or destructed
+# In that, 1 to 4 are prerequisites for the deadlock which will happen in 4. However,
+# for it to happen, we also need the right "timing". There is a race between the
+# main thread and the async writer thread. The deadlock will only happen under
+# the "right" circumstances, which basically means it will not happen always.
+# In order to create this case as reliable as possible, I have used
+# the "$OMFileFlushOnTXEnd on" directive
+# inside my test case. It makes sure that #1 above happens. The test uses a dynafile
+# cache size of 4, and the load generator generates data for 5 different dynafiles.
+# So over time, we will hit a spot where 4 dynafiles are open and the 5th file name
+# is generated. As such, one file needs to be discarded. Thanks to FlushOnTXEnd, we
+# now likely have #2 in place and thanks to the load pattern generated, we most
+# probably have #3 in place. During the dynafile cache displacement of the oldest
+# entry, #4 is generated. At this point, we have the deadlock we are testing for.
+# Note that this deadlock does not necessarily lead to a total lockup of rsyslogd.
+# Parts of it continue to operate. But in our test setup, this means data is
+# received and placed into the main queue. Once it's high water mark is hit, data
+# is still being enqueued, but at a slow rate. So if one is patient enough, the load
+# generator will be able to finish. However, rsyslogd will never process the data
+# it received because it is locked in the deadlock caused by #4 above.
+# Note that "$OMFileFlushOnTXEnd on" is not causing this behavior. We just use it
+# to (quite) reliably cause the failure condition. The failure described above
+# (in version 4.6.1) was also present when the setting was set to "off", but its
+# occurrence was very much less probable - because the perquisites are then much
+# harder to hit. without it, the test may need to run for several hours before
+# we hit all failure conditions.
+#
+# added 2010-03-17 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=20 # this test is notoriously slow...
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+$template outfmt,"%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n"
+$template dynfile,"'$RSYSLOG_DYNNAME'.%msg:F,58:2%.log" # use multiple dynafiles
+
+$OMFileFlushOnTXEnd on
+$OMFileFlushInterval 10
+$OMFileIOBufferSize 10k
+$OMFileAsyncWriting on
+$DynaFileCacheSize 4
+local0.* ?dynfile;outfmt
+'
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+startup
+# send 20000 messages, each close to 2K (non-randomized!), so that we can fill
+# the buffers and hopefully run into the "deadlock".
+tcpflood -m20000 -d1800 -P129 -i1 -f5
+shutdown_when_empty
+wait_shutdown
+cat $RSYSLOG_DYNNAME.*.log > $RSYSLOG_OUT_LOG
+seq_check 1 20000 -E
+rm -f $RSYSLOG_DYNNAME.*.log
+exit_test
diff --git a/tests/asynwr_deadlock4.sh b/tests/asynwr_deadlock4.sh
new file mode 100755
index 0000000..41dece3
--- /dev/null
+++ b/tests/asynwr_deadlock4.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This is test case from practice, with the version we introduced it, it
+# caused a deadlock during processing.
+# We added this as a standard test in the hopes that iw will help
+# detect such things in the future.
+#
+# This is a test that is constructed similar to asynwr_deadlock2.sh, but
+# can produce problems in a simpler way.
+#
+# added 2010-03-18 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+$template outfmt,"%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+
+$OMFileFlushOnTXEnd on
+$OMFileFlushInterval 10
+$OMFileIOBufferSize 10k
+$OMFileAsyncWriting on
+$DynaFileCacheSize 4
+local0.* ?dynfile;outfmt
+'
+startup
+# send 20000 messages, each close to 2K (non-randomized!), so that we can fill
+# the buffers and hopefully run into the "deadlock".
+tcpflood -m20000 -d18 -P129 -f5
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/asynwr_deadlock_2.sh b/tests/asynwr_deadlock_2.sh
new file mode 100755
index 0000000..6447706
--- /dev/null
+++ b/tests/asynwr_deadlock_2.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This is test case from practice, with the version we introduced it, it
+# caused a deadlock on shutdown. I have added it to the test suite to automatically
+# detect such things in the future.
+# a case known to have caused a deadlock in the past
+#
+# added 2010-03-17 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+
+$OMFileFlushOnTXEnd on
+$OMFileFlushInterval 10
+$OMFileIOBufferSize 4k
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood
+wait_file_lines # wait to become inactive - important bug trigger contidion
+# now try shutdown. The actual test is if the process does hang here!
+echo "processing must continue soon"
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/asynwr_dynfile_flushtxend-off.sh b/tests/asynwr_dynfile_flushtxend-off.sh
new file mode 100755
index 0000000..b734932
--- /dev/null
+++ b/tests/asynwr_dynfile_flushtxend-off.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This tests async writing functionality under a set of additional
+# conditions (see config for details). This covers non-async cases as
+# well. This test was created while actually hunting a bug that was
+# very hard to reproduce but severe. While it had different trigger
+# conditions, the set of config parameters in this test helped to find
+# it quickly. As such the hope is the test will be useful in future again.
+#
+# NOTE WELL: The rsyslog shutdown condition is hard to get 100% right
+# as due to not flushing at transaction end we cannot rely on the output
+# file count as we usually do. However, we cannot avoid this as otherwise
+# we loose an important trigger condition.
+# added 2019-10-23 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=30 # this test is notoriously slow...
+export NUMMESSAGES=20000
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n")
+template(name="dynfile" type="string" string="'$RSYSLOG_DYNNAME'.%msg:F,58:2%.log") # use multiple dynafiles
+
+local0.* action(type="omfile" dynafile="dynfile" template="outfmt"
+ flushOnTXEnd="off" flushInterval="10" ioBufferSize="10k"
+ asyncWriting="on" dynaFileCacheSize="4")
+'
+# uncomment for debugging support:
+startup
+tcpflood -m$NUMMESSAGES -d1800 -P129 -f5
+shutdown_when_empty
+wait_shutdown
+cat $RSYSLOG_DYNNAME.*.log > $RSYSLOG_OUT_LOG
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/asynwr_simple.sh b/tests/asynwr_simple.sh
new file mode 100755
index 0000000..9fdbc67
--- /dev/null
+++ b/tests/asynwr_simple.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# This is test driver for testing asynchronous file output.
+# This test intentionally uses legacy format.
+# added 2010-03-09 by Rgerhards, re-written 2019-08-15
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# send 35555 messages, make sure file size is not a multiple of
+# 10K, the buffer size!
+export NUMMESSAGES=355555
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 10k
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/asynwr_simple_2.sh b/tests/asynwr_simple_2.sh
new file mode 100755
index 0000000..7a7f9dd
--- /dev/null
+++ b/tests/asynwr_simple_2.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# This is test driver for testing asynchronous file output.
+# added 2010-03-09 by Rgerhards, re-written 2019-08-15
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# send 35555 messages, make sure file size is not a multiple of
+# 4K, the buffer size!
+export NUMMESSAGES=355555
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:"
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ asyncWriting="on" flushOnTXEnd="off" flushInterval="2" ioBufferSize="4k")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/asynwr_small.sh b/tests/asynwr_small.sh
new file mode 100755
index 0000000..5d45238
--- /dev/null
+++ b/tests/asynwr_small.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This tests async writing with only a small set of data. That
+# shall result in data staying in buffers until shutdown, what
+# then will trigger some somewhat complex logic in the stream
+# writer (open, write, close all during the stream close
+# operation). It is vital that only few messages be sent.
+#
+# The main effort of this test is not (only) to see if we
+# receive the data, but rather to see if we get into an abort
+# condition.
+#
+# added 2010-03-09 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=2
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+startup
+tcpflood
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/asynwr_timeout.sh b/tests/asynwr_timeout.sh
new file mode 100755
index 0000000..5c990a2
--- /dev/null
+++ b/tests/asynwr_timeout.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This test writes to the output buffers, let's the output
+# write timeout (and write data) and then continue. The conf file
+# has a 2 second timeout, so we wait 4 seconds to be on the save side.
+#
+# added 2010-03-09 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# send 35555 messages, make sure file size is not a multiple of
+# 10K, the buffer size!
+export NUMMESSAGES=15555
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 10k
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+tcpflood -m $NUMMESSAGES
+printf 'waiting for timeout to occur\n'
+sleep 15 # GOOD SLEEP - we wait for the timeout! long to take care of slow test machines...
+printf 'timeout should now have occurred - check file state\n'
+seq_check
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/asynwr_timeout_2.sh b/tests/asynwr_timeout_2.sh
new file mode 100755
index 0000000..0cbbd4d
--- /dev/null
+++ b/tests/asynwr_timeout_2.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This test writes to the output buffers, let's the output
+# write timeout (and write data) and then continue. The conf file
+# has a 2 second timeout, so we wait 4 seconds to be on the save side.
+#
+# added 2010-03-09 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo TEST: \[asynwr_timeout.sh\]: test async file writing timeout writes
+. ${srcdir:=.}/diag.sh init
+export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=20 # this test is notoriously slow...
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 4k
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+startup
+# send 35555 messages, make sure file size is not a multiple of
+# 4K, the buffer size!
+tcpflood -m 35555
+sleep 4 # wait for output writer to write and empty buffer
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 35554
+exit_test
diff --git a/tests/asynwr_tinybuf.sh b/tests/asynwr_tinybuf.sh
new file mode 100755
index 0000000..60da2fc
--- /dev/null
+++ b/tests/asynwr_tinybuf.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# This tests async writing with a very small output buffer (1 byte!),
+# so it stresses output buffer handling. This also means operations will
+# be somewhat slow, so we send only a small amounts of data.
+#
+# added 2010-03-09 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo TEST: \[asynwr_tinybuf.sh\]: test async file writing with 1-byte buffer
+. ${srcdir:=.}/diag.sh init
+export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=20 # this test is notoriously slow...
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 1
+$OMFileAsyncWriting on
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+startup
+# send 1000 messages, fairly enough to trigger problems
+tcpflood -m1000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # shut down rsyslogd when done processing messages
+seq_check 0 999
+exit_test
diff --git a/tests/bad_qi/dbq.qi b/tests/bad_qi/dbq.qi
new file mode 100644
index 0000000..5f56e41
--- /dev/null
+++ b/tests/bad_qi/dbq.qi
@@ -0,0 +1,29 @@
+!OPB:1:queue:1:
++iQueueSize:2:2:84:
++iUngottenObjs:2:1:1:
++tVars.disk.sizeOnDisk:2:5:57906:
++tVars.disk.bytesRead:2:4:1010:
+>End
+.
+<Obj:1:strm:1:
++iCurrFNum:2:1:1:
++pszFName:1:3:dbq:
++iMaxFiles:2:8:10000000:
++bDeleteOnClose:2:1:0:
++sType:2:1:1:
++tOperationsMode:2:1:2:
++tOpenMode:2:3:384:
++iCurrOffs:2:5:57906:
+>End
+.
+<Obj:1:strm:1:
++iCurrFNum:2:1:1:
++pszFName:1:3:dbq:
++iMaxFiles:2:8:10000000:
++bDeleteOnClose:2:1:1:
++sType:2:1:1:
++tOperationsMode:2:1:1:
++tOpenMode:2:3:384:
++iCurrOffs:2:4:1010:
+>End
+.
diff --git a/tests/badqi.sh b/tests/badqi.sh
new file mode 100755
index 0000000..733c896
--- /dev/null
+++ b/tests/badqi.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Test for a startup with a bad qi file. This tests simply tests
+# if the rsyslog engine survives (we had segfaults in this situation
+# in the past).
+# added 2009-10-21 by RGerhards
+# This file is part of the rsyslog project, released under GPLv3
+# uncomment for debugging support:
+echo ===============================================================================
+echo \[badqi.sh\]: test startup with invalid .qi file
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+# instruct to use bad .qi file
+$WorkDirectory bad_qi
+$ActionQueueType LinkedList
+$ActionQueueFileName dbq
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+# we just inject a handful of messages so that we have something to wait for...
+tcpflood -m20
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # wait for process to terminate
+seq_check 0 19
+exit_test
diff --git a/tests/cee_diskqueue.sh b/tests/cee_diskqueue.sh
new file mode 100755
index 0000000..172c429
--- /dev/null
+++ b/tests/cee_diskqueue.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# check if CEE properties are properly saved & restored to/from disk queue
+# added 2012-09-19 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test probably does not work on all flavors of Solaris"
+export NUMMESSAGES=5000
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+template(name="outfmt" type="string" string="%$!usr!msg:F,58:2%\n")
+
+set $!usr!msg = $msg;
+if $msg contains "msgnum" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ queue.type="disk" queue.filename="rsyslog-act1")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/cee_simple.sh b/tests/cee_simple.sh
new file mode 100755
index 0000000..b81e6d1
--- /dev/null
+++ b/tests/cee_simple.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2012-09-19 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[cee_simple.sh\]: basic CEE property test
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!usr!msg:F,58:2%\n")
+set $!usr!msg = $msg;
+if $msg contains '
+add_conf "'msgnum' "
+add_conf 'then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/cfg.sh b/tests/cfg.sh
new file mode 100755
index 0000000..5e2f81b
--- /dev/null
+++ b/tests/cfg.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+# This is a simple shell script that carries out some checks against
+# configurations we expect from some provided config files. We use
+# rsyslogd's verification function. Note that modifications to the
+# config elements, or even simple text changes, cause these checks to
+# fail. However, it should be fairly easy to adapt them to the changed
+# environment. And while nothing changed, they permit is to make sure
+# that everything works well and is not broken by interim changes.
+# Note that we always compare starting with the second output line.
+# This is because the first line contains the rsyslog version ;)
+# rgerhards, 2008-07-29
+#
+# Part of the testbench for rsyslog.
+#
+# Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+#
+# This file is part of rsyslog.
+#
+# Rsyslog 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.
+#
+# Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+#
+# A copy of the GPL can be found in the file "COPYING" in this distribution.
+#set -x
+echo \[cfg.sh\]:
+rm -f tmp
+echo "local directory"
+#
+# check empty config file
+#
+../tools/rsyslogd -c4 -N1 -f/dev/null -M../runtime/.libs:../.libs 2>&1 |./ourtail |head -2 > tmp
+cmp tmp $srcdir/DevNull.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "DevNull.cfgtest failed"
+echo "Expected:"
+cat $srcdir/DevNull.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "DevNull.cfgtest succeeded"
+fi;
+#
+# check missing config file
+#
+../tools/rsyslogd -c4 -N1 -M../runtime/.libs:../.libs -f/This/does/not/exist 2>&1 |./ourtail |head -2 > tmp
+cmp tmp $srcdir/NoExistFile.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "NoExistFile.cfgtest failed"
+echo "Expected:"
+cat $srcdir/NoExistFile.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "NoExistFile.cfgtest succeeded"
+fi;
+
+
+# TODO: re-enable the following checks. They need to have support in
+# rsyslogd so that the log file name is NOT contained in the error
+# messages - this prevents proper comparison in make distcheck
+rm -f tmp
+exit 0
+
+#
+# check config with invalid directive
+#
+../tools/rsyslogd -c4 -u2 -N1 -f$srcdir/cfg1.testin 2>&1 |./ourtail > tmp
+cmp tmp $srcdir/cfg1.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg1.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg1.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg1.cfgtest succeeded"
+fi;
+#
+# now check for included config file. We use a sample similar to
+# the one with the invalid config directive, so that we may see
+# an effect of the included config ;)
+#
+../tools/rsyslogd -c4 -u2 -N1 -f$srcdir/cfg2.testin 2>&1 |./ourtail > tmp
+cmp tmp $srcdir/cfg2.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg2.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg2.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg2.cfgtest succeeded"
+fi;
+#
+# check included config file, where included file does not exist
+#
+../tools/rsyslogd -c4 -u2 -N1 -f$srcdir/cfg3.testin 2>&1 |./ourtail > tmp
+cmp tmp $srcdir/cfg3.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg3.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg3.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg3.cfgtest succeeded"
+fi;
+#
+# check a reasonable complex, but correct, log file
+#
+../tools/rsyslogd -c4 -u2 -N1 -f$srcdir/cfg4.testin 2>&1 |./ourtail > tmp
+cmp tmp $srcdir/cfg4.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg4.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg4.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg4.cfgtest succeeded"
+fi;
+#
+# done, some cleanup
+#
+rm -f tmp
diff --git a/tests/cfg1.cfgtest b/tests/cfg1.cfgtest
new file mode 100644
index 0000000..d49d207
--- /dev/null
+++ b/tests/cfg1.cfgtest
@@ -0,0 +1,3 @@
+rsyslogd: invalid or yet-unknown config file command - have you forgotten to load a module? [try https://www.rsyslog.com/e/3003 ]
+rsyslogd: the last error occurred in ./cfg1.testin, line 2
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg1.testin b/tests/cfg1.testin
new file mode 100644
index 0000000..7d7b594
--- /dev/null
+++ b/tests/cfg1.testin
@@ -0,0 +1,2 @@
+*.* *
+$invaliddirective test
diff --git a/tests/cfg2.cfgtest b/tests/cfg2.cfgtest
new file mode 100644
index 0000000..8a98eb5
--- /dev/null
+++ b/tests/cfg2.cfgtest
@@ -0,0 +1,3 @@
+rsyslogd: invalid or yet-unknown config file command - have you forgotten to load a module? [try https://www.rsyslog.com/e/3003 ]
+rsyslogd: the last error occurred in cfg1.testin, line 2
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg2.testin b/tests/cfg2.testin
new file mode 100644
index 0000000..b6d98c8
--- /dev/null
+++ b/tests/cfg2.testin
@@ -0,0 +1 @@
+$includeconfig cfg1.testin
diff --git a/tests/cfg3.cfgtest b/tests/cfg3.cfgtest
new file mode 100644
index 0000000..5edd4ef
--- /dev/null
+++ b/tests/cfg3.cfgtest
@@ -0,0 +1,5 @@
+rsyslogd: error accessing config file or directory 'file-does-not-exist': No such file or directory [try https://www.rsyslog.com/e/2040 ]
+rsyslogd: the last error occurred in ./cfg3.testin, line 1
+rsyslogd: CONFIG ERROR: there are no active actions configured. Inputs will run, but no output whatsoever is created. [try https://www.rsyslog.com/e/2103 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg3.testin b/tests/cfg3.testin
new file mode 100644
index 0000000..9789d93
--- /dev/null
+++ b/tests/cfg3.testin
@@ -0,0 +1 @@
+$includeconfig file-does-not-exist
diff --git a/tests/cfg4.cfgtest b/tests/cfg4.cfgtest
new file mode 100644
index 0000000..04acf84
--- /dev/null
+++ b/tests/cfg4.cfgtest
@@ -0,0 +1 @@
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg4.testin b/tests/cfg4.testin
new file mode 100644
index 0000000..b8694ad
--- /dev/null
+++ b/tests/cfg4.testin
@@ -0,0 +1,31 @@
+# This is more or less the sample config, but without imklog being
+# active. imklog must not always be present and as such may spoil
+# our testing result. The core point at this test is that a valid
+# config file should not lead to any error messages.
+# It may be a good idea to update this file from time to time, so that
+# it contains a reasonable complex config sample.
+
+# if you experience problems, check
+# https://www.rsyslog.com/troubleshoot for assistance
+
+# rsyslog v3: load input modules
+# If you do not load inputs, nothing happens!
+# You may need to set the module load path if modules are not found.
+
+
+
+# ######### Receiving Messages from Remote Hosts ##########
+# TCP Syslog Server:
+# provides TCP syslog reception and GSS-API (if compiled to support it)
+#$ModLoad imtcp.so # load module
+#$InputTCPServerRun 514 # start up TCP listener at port 514
+
+# UDP Syslog Server:
+$ModLoad imudp.so # provides UDP syslog reception
+$ModLoad omoracle.so
+$UDPServerRun 514 # start a UDP syslog server at standard port 514
+
+$IncludeConfig /home/munoz/logging/rsyslog/20*conf
+$IncludeConfig /home/munoz/logging/rsyslog/30*conf
+
+#*.* ~
diff --git a/tests/check_relpEngineVersion.c b/tests/check_relpEngineVersion.c
new file mode 100644
index 0000000..69b6700
--- /dev/null
+++ b/tests/check_relpEngineVersion.c
@@ -0,0 +1,66 @@
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/* only care about first two digits */
+void parseVersionNumberFromStr(char *pszIn, long* piMajor, long* piMinor, long* piSubMinor) {
+ char *p = pszIn;
+ while (*p) { // While there are more characters to process...
+ if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
+ if (*piMajor == 0) {
+ *piMajor = strtol(p, &p, 10); // Read number
+ } else if (*piMinor == 0) {
+ *piMinor = strtol(p, &p, 10); // Read number
+ } else {
+ *piSubMinor = strtol(p, &p, 10); // Read number
+ return;
+ }
+ } else {
+ p++;
+ }
+ }
+}
+
+int main(int argc __attribute__((unused)), char *argv[]__attribute__((unused)))
+{
+ long iRelpVerMajor = 0;
+ long iRelpVerMinor = 0;
+ long iRelpVerSubMinor = 0;
+ long iRelpCmpMajor = 0;
+ long iRelpCmpMinor = 0;
+ long iRelpCmpSubMinor = 0;
+
+#if defined(RELP_VERSION)
+ parseVersionNumberFromStr(RELP_VERSION, &iRelpVerMajor, &iRelpVerMinor, &iRelpVerSubMinor);
+ if (argc > 1) {
+ parseVersionNumberFromStr(argv[1], &iRelpCmpMajor, &iRelpCmpMinor, &iRelpCmpSubMinor);
+
+ // Compare Version numbers
+ if ( iRelpVerMajor > iRelpCmpMajor ||
+ ( iRelpVerMajor == iRelpCmpMajor &&
+ iRelpVerMinor > iRelpCmpMinor ) ||
+ ( iRelpVerMajor == iRelpCmpMajor &&
+ iRelpVerMinor == iRelpCmpMinor &&
+ iRelpVerSubMinor >= iRelpCmpSubMinor)
+ ) {
+ printf("RELP Version %ld.%ld.%ld OK (Requested Version %ld.%ld.%ld)\n",
+ iRelpVerMajor, iRelpVerMinor, iRelpVerSubMinor,
+ iRelpCmpMajor, iRelpCmpMinor, iRelpCmpSubMinor);
+ return 0;
+ } else {
+ printf("RELP Version %ld.%ld.%ld NOT OK (Requested Version %ld.%ld.%ld)\n",
+ iRelpVerMajor, iRelpVerMinor, iRelpVerSubMinor,
+ iRelpCmpMajor, iRelpCmpMinor, iRelpCmpSubMinor);
+ return 1;
+ }
+
+ } else {
+ printf("RELP Version %s\n", RELP_VERSION);
+ }
+ return 0;
+#else
+ printf("RELP Version unknown\n");
+ return 1;
+#endif
+}
diff --git a/tests/chkseq.c b/tests/chkseq.c
new file mode 100644
index 0000000..00674e9
--- /dev/null
+++ b/tests/chkseq.c
@@ -0,0 +1,249 @@
+/* Checks if a file consists of line of strictly monotonically
+ * increasing numbers. An expected start and end number may
+ * be set.
+ *
+ * Params
+ * -f<filename> file to process, if not given stdin is processed.
+ * -s<starting number> -e<ending number>
+ * default for s is 0. -e should be given (else it is also 0)
+ * -d may be specified, in which case duplicate messages are permitted.
+ * -m number of messages permitted to be missing without triggering a
+ * failure. This is necessary for some failover tests, where it is
+ * impossible to totally guard against messagt loss. By default, NO
+ * message is permitted to be lost.
+ * -T anticipate truncation (which means specified payload length may be
+ * more than actual payload (which may have been truncated)
+ * -i increment between messages (default: 1). Can be used for tests which
+ * intentionally leave consistent gaps in the message numbering.
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(_AIX)
+ #include <unistd.h>
+#else
+ #include <getopt.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+ FILE *fp;
+ int val;
+ int i;
+ int ret = 0;
+ int scanfOK;
+ int verbose = 0;
+ int bHaveExtraData = 0;
+ int bAnticipateTruncation = 0;
+ int dupsPermitted = 0;
+ int start = 0, end = 0;
+ int opt;
+ int lostok = 0; /* how many messages are OK to be lost? */
+ int nDups = 0;
+ int increment = 1;
+ int reachedEOF;
+ int edLen; /* length of extra data */
+ static char edBuf[500*1024]; /* buffer for extra data (pretty large to be on the save side...) */
+ static char ioBuf[sizeof(edBuf)+1024];
+ char *file = NULL;
+
+ while((opt = getopt(argc, argv, "i:e:f:ds:vm:ET")) != EOF) {
+ switch((char)opt) {
+ case 'f':
+ file = optarg;
+ break;
+ case 'd':
+ dupsPermitted = 1;
+ break;
+ case 'i':
+ increment = atoi(optarg);
+ break;
+ case 'e':
+ end = atoi(optarg);
+ break;
+ case 's':
+ start = atoi(optarg);
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ case 'm':
+ lostok = atoi(optarg);
+ break;
+ case 'E':
+ bHaveExtraData = 1;
+ break;
+ case 'T':
+ bAnticipateTruncation = 1;
+ break;
+ default:printf("Invalid call of chkseq, optchar='%c'\n", opt);
+ printf("Usage: chkseq file -sstart -eend -d -E\n");
+ exit(1);
+ }
+ }
+
+ if(start > end) {
+ printf("start must be less than or equal end!\n");
+ exit(1);
+ }
+
+ if(verbose) {
+ printf("chkseq: start %d, end %d\n", start, end);
+ }
+
+ /* read file */
+ if(file == NULL) {
+ fp = stdin;
+ } else {
+ fp = fopen(file, "r");
+ }
+ if(fp == NULL) {
+ printf("error opening file '%s'\n", file);
+ perror(file);
+ exit(1);
+ }
+
+ for(i = start ; i <= end ; i += increment) {
+ if(bHaveExtraData) {
+ if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) {
+ scanfOK = 0;
+ } else {
+ scanfOK = sscanf(ioBuf, "%d,%d,%s\n", &val, &edLen, edBuf) == 3 ? 1 : 0;
+ }
+ if(edLen != (int) strlen(edBuf)) {
+ if (bAnticipateTruncation == 1) {
+ if (edLen < (int) strlen(edBuf)) {
+ printf("extra data length specified %d, but actually is %ld in"
+ " record %d (truncation was anticipated, but payload should"
+ " have been smaller than data-length, not larger)\n",
+ edLen, (long) strlen(edBuf), i);
+ exit(1);
+ }
+ } else {
+ printf("extra data length specified %d, but actually is %ld in record %d\n",
+ edLen, (long) strlen(edBuf), i);
+ exit(1);
+ }
+ }
+ } else {
+ if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) {
+ scanfOK = 0;
+ } else {
+ scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0;
+ }
+ }
+ if(!scanfOK) {
+ printf("scanf error in index i=%d\n", i);
+ exit(1);
+ }
+ while(val > i && lostok > 0) {
+ --lostok;
+ printf("message %d missing (ok due to -m [now %d])\n", i, lostok);
+ ++i;
+ }
+ if(val != i) {
+ if(val == i - increment && dupsPermitted) {
+ --i;
+ ++nDups;
+ } else {
+ printf("read value %d, but expected value %d\n", val, i);
+ exit(1);
+ }
+ }
+ }
+
+ if(i - increment != end) {
+ printf("lastrecord does not match. file: %d, expected %d\n", i - increment, end);
+ exit(1);
+ }
+
+ int c = getc(fp);
+ if(c == EOF) {
+ reachedEOF = 1;
+ } else {
+ ungetc(c, fp);
+ /* if duplicates are permitted, we need to do a final check if we have duplicates at the
+ * end of file.
+ */
+ if(dupsPermitted) {
+ i = end;
+ while(!feof(fp)) {
+ if(bHaveExtraData) {
+ if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) {
+ scanfOK = 0;
+ } else {
+ scanfOK = sscanf(ioBuf, "%d,%d,%s\n", &val,
+ &edLen, edBuf) == 3 ? 1 : 0;
+ }
+ if(edLen != (int) strlen(edBuf)) {
+ if (bAnticipateTruncation == 1) {
+ if (edLen < (int) strlen(edBuf)) {
+ printf("extra data length specified %d, but "
+ "actually is %ld in record %d (truncation was"
+ " anticipated, but payload should have been "
+ "smaller than data-length, not larger)\n",
+ edLen, (long) strlen(edBuf), i);
+ exit(1);
+ }
+ } else {
+ printf("extra data length specified %d, but actually "
+ "is %ld in record %d\n",
+ edLen, (long) strlen(edBuf), i);
+ exit(1);
+ }
+ }
+ } else {
+ if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) {
+ scanfOK = 0;
+ } else {
+ scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0;
+ }
+ }
+
+ if(val != i) {
+ reachedEOF = 0;
+ goto breakIF;
+ }
+ }
+ reachedEOF = feof(fp) ? 1 : 0;
+ } else {
+ reachedEOF = 0;
+ }
+ }
+
+breakIF:
+ if(nDups != 0)
+ printf("info: had %d duplicates (this is no error)\n", nDups);
+
+ if(!reachedEOF) {
+ printf("end of processing, but NOT end of file! First line of extra data is:\n");
+ for(c = fgetc(fp) ; c != '\n' && c != EOF ; c = fgetc(fp))
+ putchar(c);
+ putchar('\n');
+ exit(1);
+ }
+
+ exit(ret);
+}
diff --git a/tests/clickhouse-basic-vg.sh b/tests/clickhouse-basic-vg.sh
new file mode 100755
index 0000000..f51450b
--- /dev/null
+++ b/tests/clickhouse-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/clickhouse-basic.sh
diff --git a/tests/clickhouse-basic.sh b/tests/clickhouse-basic.sh
new file mode 100755
index 0000000..0c3306d
--- /dev/null
+++ b/tests/clickhouse-basic.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.basic (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, '
+add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" bulkmode="off"
+ user="default" pwd="" template="outfmt")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.basic ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT id, severity, facility, ipaddress, tag, message FROM rsyslog.basic" > $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.basic"
+export EXPECTED='0 7 20 127.0.0.1 tag msgnum:00000000:'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/clickhouse-bulk-load-vg.sh b/tests/clickhouse-bulk-load-vg.sh
new file mode 100755
index 0000000..75ad35c
--- /dev/null
+++ b/tests/clickhouse-bulk-load-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/clickhouse-bulk-load.sh
diff --git a/tests/clickhouse-bulk-load.sh b/tests/clickhouse-bulk-load.sh
new file mode 100755
index 0000000..3f4099e
--- /dev/null
+++ b/tests/clickhouse-bulk-load.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100000
+
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.bulkLoad (id, ipaddress, message) VALUES (%msg:F,58:2%, '
+add_conf "'%fromhost-ip%', '%msg:F,58:2%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ user="default" pwd="" template="outfmt")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.bulkLoad ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT message FROM rsyslog.bulkLoad ORDER BY id" > $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.bulkLoad"
+seq_check 0 $(( NUMMESSAGES - 1 ))
+
+exit_test
diff --git a/tests/clickhouse-bulk-vg.sh b/tests/clickhouse-bulk-vg.sh
new file mode 100755
index 0000000..fbc77ba
--- /dev/null
+++ b/tests/clickhouse-bulk-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/clickhouse-bulk.sh
diff --git a/tests/clickhouse-bulk.sh b/tests/clickhouse-bulk.sh
new file mode 100755
index 0000000..297df36
--- /dev/null
+++ b/tests/clickhouse-bulk.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.bulk (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, '
+add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ user="default" pwd="" template="outfmt")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.bulk ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT id, severity, facility, ipaddress, tag, message FROM rsyslog.bulk ORDER BY id" > $RSYSLOG_OUT_LOG
+
+export EXPECTED='0 7 20 127.0.0.1 tag msgnum:00000000:
+1 7 20 127.0.0.1 tag msgnum:00000001:
+2 7 20 127.0.0.1 tag msgnum:00000002:
+3 7 20 127.0.0.1 tag msgnum:00000003:
+4 7 20 127.0.0.1 tag msgnum:00000004:
+5 7 20 127.0.0.1 tag msgnum:00000005:
+6 7 20 127.0.0.1 tag msgnum:00000006:
+7 7 20 127.0.0.1 tag msgnum:00000007:
+8 7 20 127.0.0.1 tag msgnum:00000008:
+9 7 20 127.0.0.1 tag msgnum:00000009:'
+cmp_exact $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.bulk"
+exit_test
diff --git a/tests/clickhouse-dflt-tpl.sh b/tests/clickhouse-dflt-tpl.sh
new file mode 100755
index 0000000..3224b86
--- /dev/null
+++ b/tests/clickhouse-dflt-tpl.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" bulkmode="off"
+ user="default" pwd="")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.SystemEvents ( severity Int8, facility Int8, timestamp DateTime, hostname String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity order by tuple()"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT * FROM rsyslog.SystemEvents FORMAT CSV" > $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.SystemEvents"
+content_check --regex '7,20,"20..-03-01 01:00:00","172.20.245.8","tag"," msgnum:00000000:"'
+
+exit_test
diff --git a/tests/clickhouse-errorfile.sh b/tests/clickhouse-errorfile.sh
new file mode 100755
index 0000000..6004861
--- /dev/null
+++ b/tests/clickhouse-errorfile.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+echo looks like clickhouse does no longer generate exceptions on error - skip until investigated
+exit 77
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.errorfile (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, '
+add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ user="default" pwd="" template="outfmt"
+ bulkmode="off" errorfile="'$RSYSLOG_OUT_LOG'")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.errorfile ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:NoInteger\""
+shutdown_when_empty
+wait_shutdown
+
+content_check --regex "msgnum:NoInteger.*DB::Exception:"
+
+clickhouse-client --query="DROP TABLE rsyslog.errorfile"
+exit_test
diff --git a/tests/clickhouse-limited-batch.sh b/tests/clickhouse-limited-batch.sh
new file mode 100755
index 0000000..7f1fcd1
--- /dev/null
+++ b/tests/clickhouse-limited-batch.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-12-20 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100000
+
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.limited (id, ipaddress, message) VALUES (%msg:F,58:2%, '
+add_conf "'%fromhost-ip%', '%msg:F,58:2%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ user="default" pwd="" template="outfmt"
+ maxbytes="1k")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.limited ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT message FROM rsyslog.limited ORDER BY id" > $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.limited"
+seq_check 0 $(( NUMMESSAGES - 1 ))
+
+exit_test
diff --git a/tests/clickhouse-load-vg.sh b/tests/clickhouse-load-vg.sh
new file mode 100755
index 0000000..e0e33eb
--- /dev/null
+++ b/tests/clickhouse-load-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/clickhouse-load.sh
diff --git a/tests/clickhouse-load.sh b/tests/clickhouse-load.sh
new file mode 100755
index 0000000..40e00b9
--- /dev/null
+++ b/tests/clickhouse-load.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.load (id, ipaddress, message) VALUES (%msg:F,58:2%, '
+add_conf "'%fromhost-ip%', '%msg:F,58:2%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" usehttps="off"
+ user="default" pwd="" template="outfmt"
+ bulkmode="off")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.load ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT message FROM rsyslog.load ORDER BY id" > $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.load"
+seq_check 0 $(( NUMMESSAGES - 1 ))
+
+exit_test
diff --git a/tests/clickhouse-retry-error.sh b/tests/clickhouse-retry-error.sh
new file mode 100755
index 0000000..d5dccff
--- /dev/null
+++ b/tests/clickhouse-retry-error.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2018-12-31 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.retryerror (id, severity, message) VALUES (%msg:F,58:2%, %syslogseverity%, '
+add_conf "'%msg%')"
+add_conf '")
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost"
+ bulkmode="off" user="default" pwd=""
+ template="outfmt")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+content_check "omclickhouse: checkConn failed."
+
+exit_test
diff --git a/tests/clickhouse-select.sh b/tests/clickhouse-select.sh
new file mode 100755
index 0000000..0f5ccc3
--- /dev/null
+++ b/tests/clickhouse-select.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="SELECT * FROM rsyslog.select")
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ bulkmode="off" user="default" pwd=""
+ template="outfmt")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.select ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+clickhouse-client --query="DROP TABLE rsyslog.select"
+content_check "omclickhouse: Message is no Insert query: Message suspended: SELECT * FROM rsyslog.select"
+
+exit_test
diff --git a/tests/clickhouse-start.sh b/tests/clickhouse-start.sh
new file mode 100755
index 0000000..200200c
--- /dev/null
+++ b/tests/clickhouse-start.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This is not a real test, but a script to start clickhouse. It is
+# implemented as test so that we can start clickhouse at the time we need
+# it (do so via Makefile.am).
+# Copyright (C) 2018 Pascal Withopf and Adiscon GmbH
+# Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+set -x
+if [ "$CLICKHOUSE_START_CMD" == "" ]; then
+ exit_test # no start needed
+fi
+
+test_error_exit_handler() {
+ printf 'clickhouse startup failed, log is:\n'
+ $SUDO cat /var/log/clickhouse-server/clickhouse-server.err.log
+}
+
+printf 'starting clickhouse...\n'
+$CLICKHOUSE_START_CMD &
+sleep 10
+#wait_startup_pid /var/run/clickhouse-server/clickhouse-server.pid
+printf 'preparing clickhouse for testbench use...\n'
+$SUDO ${srcdir}/../devtools/prepare_clickhouse.sh
+clickhouse-client --query="select 1"
+rc=$?
+if [ $rc -ne 0 ]; then
+ printf 'clickhouse failed to start, exit code %d\n' $rc
+ error_exit 100
+fi
+printf 'done, clickhouse ready for testbench\n'
+exit_test
diff --git a/tests/clickhouse-stop.sh b/tests/clickhouse-stop.sh
new file mode 100755
index 0000000..7f132d8
--- /dev/null
+++ b/tests/clickhouse-stop.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This is not a real test, but a script to stop clickhouse. It is
+# implemented as test so that we can stop clickhouse at the time we need
+# it (do so via Makefile.am).
+# Copyright (C) 2018 Pascal Withopf and Adiscon GmbH
+# Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ "$CLICKHOUSE_STOP_CMD" == "" ]; then
+ exit_test
+fi
+
+clickhouse-client --query="DROP DATABASE rsyslog"
+sleep 1
+printf 'stopping clickhouse...\n'
+#$SUDO sed -n -r 's/PID: ([0-9]+\.*)/\1/p' /var/lib/clickhouse/status > /tmp/clickhouse-server.pid
+#$SUDO kill $($SUDO sed -n -r 's/PID: ([0-9]+\.*)/\1/p' /var/lib/clickhouse/status)
+eval $CLICKHOUSE_STOP_CMD
+sleep 1 # cosmetic: give clickhouse a chance to emit shutdown message
+exit_test
diff --git a/tests/clickhouse-wrong-insert-syntax.sh b/tests/clickhouse-wrong-insert-syntax.sh
new file mode 100755
index 0000000..7c3ae9e
--- /dev/null
+++ b/tests/clickhouse-wrong-insert-syntax.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2018-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+echo looks like clickhouse does no longer generate exceptions on error - skip until investigated
+exit 77
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.wrongInsertSyntax (id, severity, facility, timestamp, ipaddress, tag, message) VLUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, '
+add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443"
+ user="default" pwd="" template="outfmt"
+ bulkmode="off" errorfile="'$RSYSLOG_OUT_LOG'")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.wrongInsertSyntax ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+clickhouse-client --query="DROP TABLE rsyslog.wrongInsertSyntax"
+content_check "DB::Exception: Syntax error"
+exit_test
diff --git a/tests/clickhouse-wrong-quotation-marks.sh b/tests/clickhouse-wrong-quotation-marks.sh
new file mode 100755
index 0000000..618aafe
--- /dev/null
+++ b/tests/clickhouse-wrong-quotation-marks.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2018-12-19 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+
+template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.quotation (id, severity, message) VALUES ( 1, '
+add_conf "%syslogseverity%, '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost"
+ port="8443" bulkmode="off"
+ user="default" pwd="" template="outfmt")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.quotation ( id Int32, severity Int8, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+tcpflood -m1 -M "\"<130>Mar 10 01:00:00 172.20.245.8 tag:it's a test\""
+shutdown_when_empty
+wait_shutdown
+clickhouse-client --query="SELECT id, severity, message FROM rsyslog.quotation" > $RSYSLOG_OUT_LOG
+
+export EXPECTED="1 2 it\\'s a test"
+cmp_exact $RSYSLOG_OUT_LOG
+
+clickhouse-client --query="DROP TABLE rsyslog.quotation"
+exit_test
diff --git a/tests/clickhouse-wrong-template-option.sh b/tests/clickhouse-wrong-template-option.sh
new file mode 100755
index 0000000..3c9083f
--- /dev/null
+++ b/tests/clickhouse-wrong-template-option.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-12-19 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+module(load="../plugins/omclickhouse/.libs/omclickhouse")
+
+template(name="outfmt" type="string" string="INSERT INTO rsyslog.template (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, '
+add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')"
+add_conf '")
+
+
+:syslogtag, contains, "tag" action(type="omclickhouse" server="localhost"
+ usehttps="off" bulkmode="off"
+ user="default" pwd="" template="outfmt")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.template ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id"
+
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+clickhouse-client --query="DROP TABLE rsyslog.template"
+content_check "you have to specify the SQL or stdSQL option in your template!"
+
+exit_test
diff --git a/tests/complex1.sh b/tests/complex1.sh
new file mode 100755
index 0000000..a51d332
--- /dev/null
+++ b/tests/complex1.sh
@@ -0,0 +1,132 @@
+#!/bin/bash
+# This is a rather complex test that runs a number of features together.
+#
+# added 2010-03-16 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on all flavors of Solaris."
+export NUMMESSAGES=40000
+export RSYSLOG_PORT2="$(get_free_port)"
+export RSYSLOG_PORT3="$(get_free_port)"
+generate_conf
+echo ports: $TCPFLOOD_PORT $RSYSLOG_PORT2 $RSYSLOG_PORT3
+add_conf '
+$MaxMessageSize 10k
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+
+$template outfmt,"%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n"
+$template dynfile,"'$RSYSLOG_DYNNAME'.out.%inputname%.%msg:F,58:2%.log.Z"
+
+## RULESET with listener
+$Ruleset R13514
+# queue params:
+$ActionQueueTimeoutShutdown 60000
+$ActionQueueTimeoutEnqueue 20000
+$ActionQueueSize 5000
+$ActionQueueSaveOnShutdown on
+$ActionQueueHighWaterMark 4900
+$ActionQueueLowWaterMark 3500
+$ActionQueueType FixedArray
+$ActionQueueWorkerThreads 1
+# action params:
+$OMFileFlushOnTXEnd off
+$OMFileZipLevel 6
+$DynaFileCacheSize 4
+$omfileFlushInterval 1
+*.* ?dynfile;outfmt
+action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile")
+# listener
+$InputTCPServerInputName '$TCPFLOOD_PORT'
+$InputTCPServerBindRuleset R13514
+$InputTCPServerRun '$TCPFLOOD_PORT'
+
+
+## RULESET with listener
+$Ruleset R_PORT2
+# queue params:
+$ActionQueueTimeoutShutdown 60000
+$ActionQueueTimeoutEnqueue 20000
+$ActionQueueSize 5000
+$ActionQueueSaveOnShutdown on
+$ActionQueueHighWaterMark 4900
+$ActionQueueLowWaterMark 3500
+$ActionQueueType FixedArray
+$ActionQueueWorkerThreads 1
+# action params:
+$OMFileFlushOnTXEnd off
+$OMFileZipLevel 6
+$OMFileIOBufferSize 256k
+$DynaFileCacheSize 4
+$omfileFlushInterval 1
+*.* ?dynfile;outfmt
+action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile")
+# listener
+$InputTCPServerInputName '$RSYSLOG_PORT2'
+$InputTCPServerBindRuleset R_PORT2
+$InputTCPServerRun '$RSYSLOG_PORT2'
+
+
+
+## RULESET with listener
+$Ruleset R_PORT3
+# queue params:
+$ActionQueueTimeoutShutdown 60000
+$ActionQueueTimeoutEnqueue 20000
+$ActionQueueSize 5000
+$ActionQueueSaveOnShutdown on
+$ActionQueueHighWaterMark 4900
+$ActionQueueLowWaterMark 3500
+$ActionQueueType FixedArray
+$ActionQueueWorkerThreads 1
+# action params:
+$OMFileFlushOnTXEnd off
+$OMFileZipLevel 6
+$OMFileIOBufferSize 256k
+$DynaFileCacheSize 4
+$omfileFlushInterval 1
+*.* ?dynfile;outfmt
+action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile")
+# listener
+$InputTCPServerInputName '$RSYSLOG_PORT3'
+$InputTCPServerBindRuleset R_PORT3
+$InputTCPServerRun '$RSYSLOG_PORT3'
+'
+
+count_function() {
+ # TODO: try to make this work on the compressed files, only
+ # idea does not work as we miss end-of-zip record
+ # leaving it commented out if we see we should really switch to that
+ # method; if we do not need for an extended period of time, this shall
+ # be removed -- rgerhards, 2018-12-19
+ #mkdir "$RSYSLOG_DYNNAME.countwrk"
+ #cp $RSYSLOG_DYNNAME.out.*.log.Z "$RSYSLOG_DYNNAME.countwrk"
+ #cd "$RSYSLOG_DYNNAME.countwrk"
+ #gunzip $RSYSLOG_DYNNAME.out.*.log.Z
+ #printf '%d' $(cat $RSYSLOG_DYNNAME.out.*.log | wc -l)
+ #cd ..
+ #rm -rf "$RSYSLOG_DYNNAME.countwrk"
+
+ # now the real - simple - code:
+ printf '%d' $(wc -l < $RSYSLOG_DYNNAME.countfile)
+}
+
+startup
+# send 40,000 messages of 400 bytes plus header max, via three dest ports
+export TCPFLOOD_PORT="$TCPFLOOD_PORT:$RSYSLOG_PORT2:$RSYSLOG_PORT3"
+tcpflood -m$NUMMESSAGES -rd400 -P129 -f5 -n3 -c15 -i1
+
+# note: we have FlushOnTX=off, so we will not see the last block inside the file;
+# as such we wait until a "sufficiently large" number of messages has arrived and
+# hope that shutdown_when_empty gets us toward the rest. It's still a bit racy,
+# but should be better than without the wait_file_lines.
+wait_file_lines --delay 1000 --count-function count_function DUMMY-filename $((NUMMESSAGES - 1500))
+shutdown_when_empty
+wait_shutdown
+ls $RSYSLOG_DYNNAME.out.*.log.Z
+gunzip $RSYSLOG_DYNNAME.out.*.log.Z
+cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG
+seq_check 1 $NUMMESSAGES -E
+exit_test
diff --git a/tests/compresssp-stringtpl.sh b/tests/compresssp-stringtpl.sh
new file mode 100755
index 0000000..957cede
--- /dev/null
+++ b/tests/compresssp-stringtpl.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:::compressSPACE%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+# we need to generate a file, because otherwise our multiple spaces
+# do not survive the execution paths through the shell
+echo "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test" >$RSYSLOG_DYNNAME.tmp
+tcpflood -I $RSYSLOG_DYNNAME.tmp
+rm $RSYSLOG_DYNNAME.tmp
+#tcpflood -m1 -M"\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="msgnum:0000000 test test test"
+cmp_exact
+exit_test
diff --git a/tests/compresssp.sh b/tests/compresssp.sh
new file mode 100755
index 0000000..3261568
--- /dev/null
+++ b/tests/compresssp.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+# we need to generate a file, because otherwise our multiple spaces
+# do not survive the execution paths through the shell
+echo "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test" >$RSYSLOG_DYNNAME.tmp
+tcpflood -I $RSYSLOG_DYNNAME.tmp
+rm $RSYSLOG_DYNNAME.tmp
+#tcpflood -m1 -M"\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="msgnum:0000000 test test test"
+cmp_exact
+exit_test
diff --git a/tests/config_enabled-off.sh b/tests/config_enabled-off.sh
new file mode 100755
index 0000000..8cc2777
--- /dev/null
+++ b/tests/config_enabled-off.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# check disabling a config construct via config.enable. Most
+# importantly ensure that it does not emit any error messages
+# for object parameters.
+# addd 2019-05-09 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" file="/tmp/notyet.txt" tag="testing-tag" config.enabled="off")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check 'imfile: no files configured'
+check_not_present 'parameter .* not known'
+exit_test
diff --git a/tests/config_enabled-on.sh b/tests/config_enabled-on.sh
new file mode 100755
index 0000000..11e5f8f
--- /dev/null
+++ b/tests/config_enabled-on.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# check disabling a config construct via config.enable. Most
+# importantly ensure that it does not emit any error messages
+# for object parameters.
+# addd 2019-12-09 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" file="/tmp/notyet.txt" tag="testing-tag" config.enabled="on" invalid.param="error")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check 'imfile: on startup file'
+content_check --regex 'parameter.*invalid.param.*not known'
+check_not_present 'parameter.*config.enabled.*not known'
+exit_test
diff --git a/tests/config_multiple_include.sh b/tests/config_multiple_include.sh
new file mode 100755
index 0000000..534640c
--- /dev/null
+++ b/tests/config_multiple_include.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# check nested include processing works correctly (and keeps proper order)
+# added 2021-03-29 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+# Note: we need to pre-build the second level include file name because
+# under "make distchek" we have a different environment and with the
+# current rsyslog implemenation, we can only have a single environment
+# variable in an `echo $VAR` block. This we cannot combine the include
+# file name inside the config include without this trick.
+export INCLUDE2="${srcdir}/testsuites/include-std2-omfile-action.conf"
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ include(file="'${srcdir}'/testsuites/include-std1-omfile-actio*.conf")
+ continue
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+ls -l "$RSYSLOG2_OUT_LOG"
+if [ -f "$RSYSLOG2_OUT_LOG" ]; then
+ printf '\nERROR: file %s exists, but should have stopped by inner include\n' "$RSYSLOG2_OUT_LOG"
+ printf 'This looks like a problem with order of include file processing.\n\n'
+ error_exit 1
+fi
+exit_test
diff --git a/tests/config_output-o-option.sh b/tests/config_output-o-option.sh
new file mode 100755
index 0000000..65c30ea
--- /dev/null
+++ b/tests/config_output-o-option.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# check that the -o command line option works
+# added 2019-04-26 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ include(file="'${srcdir}'/testsuites/include-std-omfile-actio*.conf")
+ continue
+}
+'
+../tools/rsyslogd -N1 -f${TESTCONF_NM}.conf -o$RSYSLOG_DYNNAME.fullconf -M../runtime/.libs:../.libs
+content_check 'if $msg contains "msgnum:" then' $RSYSLOG_DYNNAME.fullconf
+content_check 'action(type="omfile"' $RSYSLOG_DYNNAME.fullconf
+content_check --regex "BEGIN CONFIG: .*include-std-omfile-action.conf" $RSYSLOG_DYNNAME.fullconf
+exit_test
diff --git a/tests/da-mainmsg-q.sh b/tests/da-mainmsg-q.sh
new file mode 100755
index 0000000..386fa08
--- /dev/null
+++ b/tests/da-mainmsg-q.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# Test for DA mode on the main message queue
+# This test checks if DA mode operates correctly. To do so,
+# it uses a small in-memory queue size, so that DA mode is initiated
+# rather soon, and disk spooling used. There is some uncertainty (based
+# on machine speeds), but in general the test should work rather well.
+# We add a few messages after the initial run, just so that we can
+# check everything recovers from DA mode correctly.
+# added 2009-04-22 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# set spool locations and switch queue to disk assisted mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueSize 200 # this *should* trigger moving on to DA mode...
+# note: we must set QueueSize sufficiently high, so that 70% (light delay mark)
+# is high enough above HighWatermark!
+$MainMsgQueueHighWatermark 80
+$MainMsgQueueLowWatermark 40
+$MainMsgQueueFilename mainq
+$MainMsgQueueType linkedlist
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+
+# part1: send first 50 messages (in memory, only)
+injectmsg 0 50
+wait_file_lines $RSYSLOG_OUT_LOG 50 # let queue drain for this test case
+
+# part 2: send bunch of messages. This should trigger DA mode
+injectmsg 50 2000
+ls -l ${RSYSLOG_DYNNAME}.spool # for manual review
+wait_file_lines $RSYSLOG_OUT_LOG 2050 # wait to ensure DA queue is "empty"
+
+# send another handful
+injectmsg 2050 50
+
+shutdown_when_empty
+wait_shutdown
+seq_check 0 2099
+exit_test
diff --git a/tests/da-queue-persist.sh b/tests/da-queue-persist.sh
new file mode 100755
index 0000000..e5d9ced
--- /dev/null
+++ b/tests/da-queue-persist.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Test for DA queue data persisting at shutdown. The
+# plan is to start an instance, emit some data, do a relatively
+# fast shutdown and then re-start the engine to process the
+# remaining data.
+# added 2019-05-08 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.type="linkedList" queue.filename="mainq"
+ queue.timeoutShutdown="1" queue.saveonshutdown="on")
+
+module(load="../plugins/omtesting/.libs/omtesting")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+else
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsg")
+
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf
+'
+
+# prepare config
+echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf
+
+startup
+injectmsg 0 $NUMMESSAGES
+shutdown_immediate
+wait_shutdown
+check_mainq_spool
+
+echo "Enter phase 2, rsyslogd restart"
+# note: we may have some few duplicates!
+echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf
+wait_seq_check_with_dupes() {
+ wait_seq_check 0 $((NUMMESSAGES - 1)) -d
+}
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check_with_dupes
+startup
+shutdown_when_empty
+seq_check 0 $((NUMMESSAGES - 1)) -d
+content_check "queue files exist on disk, re-starting with" $RSYSLOG_DYNNAME.othermsg
+exit_test
diff --git a/tests/daqueue-dirty-shutdown.sh b/tests/daqueue-dirty-shutdown.sh
new file mode 100755
index 0000000..c8de84b
--- /dev/null
+++ b/tests/daqueue-dirty-shutdown.sh
@@ -0,0 +1,116 @@
+#!/bin/bash
+# This test simulates the case where the OS force-terminates rsyslog
+# before it completely finishes persisting the queue to disk. Obviously,
+# there is some data loss involved, but rsyslog should try to limit it.
+# Most importantly, a .qi file needs to be written at "save" places, so that
+# at least the queue is kind of readable.
+# To simulate the error condition, we create a DA queue with a large memory
+# part and fill it via injectmsg (do NOT use tcpflood, as this would add
+# complexity of TCP window etc to the reception of messages - injectmsg is
+# synchronous, so we do not have anything in flight after it terminates).
+# We have a blocking action which prevents actual processing of any of the
+# injected messages. We then inject a large number of messages, but only
+# few above the number the memory part of the disk can hold. So the disk queue
+# begins to get used. Once injection is done, we terminate rsyslog in the
+# regular way, which will cause the memory part of the queue to be written
+# out. After a relatively short period, we kill -9 rsyslogd, so that it
+# does not have any chance to fully persists its state (this actually is
+# what happens when force-terminated by the OS).
+# Then, we check that at a minimum the .qi file exists.
+# Copyright (C) 2016 by Rainer Gerhards
+# Released under ASL 2.0
+
+#uncomment the following if you want a log for step 1 of this test
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+
+# set spool locations and switch queue to disk-only mode
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq" queue.saveonshutdown="on"
+ queue.timeoutshutdown="1" queue.maxfilesize="1m"
+ queue.timeoutworkerthreadshutdown="500" queue.size="200000"
+ )
+
+:msg, contains, "msgnum:" :omtesting:sleep 10 0
+'
+startup
+injectmsg 0 210000
+echo spool files immediately before shutdown:
+ls ${RSYSLOG_DYNNAME}.spool
+shutdown_immediate # shut down without the ability to fully persist state
+./msleep 750 # simulate an os timeout (let it run a *very short* bit, else it's done ;))
+echo spool files immediately after shutdown \(but before kill\):
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+
+. $srcdir/diag.sh kill-immediate # do not give it sufficient time to shutdown
+wait_shutdown
+rm -f $RSYSLOG_PIDBASE.pid # as we kill, rsyslog does not itself cleanup the pid file
+
+echo spool files after kill:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+if [ ! -f ${RSYSLOG_DYNNAME}.spool/mainq.qi ]; then
+ echo "FAIL: .qi file does not exist!"
+ error_exit 1
+fi
+
+echo .qi file contents:
+cat ${RSYSLOG_DYNNAME}.spool/mainq.qi
+
+
+# We now restart rsyslog and make sure it'll clean up the disk queue.
+# So far, we cannot reliably detect if the data is properly shuffled
+# over, but that's a moot point anyhow because we expect to loss
+# (large) amounts of the data. In later stages, we however may verify
+
+#uncomment the following if you want a log for step 2 of this test
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="log2"
+
+printf 'RSYSLOG RESTART\n\n'
+# special case: we need to preserve our dynamic settings, as generate_conf
+# overwrites them. TODO: handle this in diag.sh
+RSYSLOG_DYNNAME_SAVE="$RSYSLOG_DYNNAME"
+RSYSLOG_OUT_LOG_SAVE="$RSYSLOG_OUT_LOG"
+generate_conf
+RSYSLOG_OUT_LOG="$RSYSLOG_OUT_LOG_SAVE"
+RSYSLOG_DYNNAME="$RSYSLOG_DYNNAME_SAVE"
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq" queue.saveonshutdown="on"
+ queue.maxfilesize="1m" # note: now regular shutdown timeout!
+ queue.timeoutworkerthreadshutdown="500" queue.size="200000"
+ )
+
+$template outfmt,"%msg:F,58:2%\n"
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+#wait_queueempty
+#echo existing queue empty, injecting new data
+#injectmsg 1000000 1000
+shutdown_when_empty
+wait_shutdown
+
+# now the spool directory must be empty
+spoolFiles=$(ls ${RSYSLOG_DYNNAME}.spool/)
+
+if [[ ! -z $spoolFiles ]]; then
+ echo "FAIL: spool directory is not empty!"
+ ls -l ${RSYSLOG_DYNNAME}.spool
+ error_exit 1
+fi
+
+# check if we got at least some data
+if [ ! -f $RSYSLOG_OUT_LOG ]; then
+ echo "FAIL: no output data gathered (no ${RSYSLOG_OUT_LOG})!"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/daqueue-invld-qi.sh b/tests/daqueue-invld-qi.sh
new file mode 100755
index 0000000..94d6e72
--- /dev/null
+++ b/tests/daqueue-invld-qi.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on all flavors of Solaris."
+
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 1
+$MainMsgQueueSaveOnShutdown on
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-queuemode.conf
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf
+'
+#export RSYSLOG_DEBUG="debug nologfuncflow nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+
+# prepare config
+echo \$MainMsgQueueType LinkedList > ${RSYSLOG_DYNNAME}work-queuemode.conf
+echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf
+
+# inject 10000 msgs, so that DO hit the high watermark
+startup
+injectmsg 0 10000
+shutdown_immediate
+wait_shutdown
+check_mainq_spool
+./mangle_qi -d -q ${RSYSLOG_DYNNAME}.spool/mainq.qi > tmp.qi
+mv tmp.qi ${RSYSLOG_DYNNAME}.spool/mainq.qi
+
+echo "Enter phase 2, rsyslogd restart"
+
+# restart engine and have rest processed
+#remove delay
+echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 9999 -d
+exit_test
diff --git a/tests/daqueue-persist-drvr.sh b/tests/daqueue-persist-drvr.sh
new file mode 100755
index 0000000..ec5c1af
--- /dev/null
+++ b/tests/daqueue-persist-drvr.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# Test for queue data persisting at shutdown. The
+# plan is to start an instance, emit some data, do a relatively
+# fast shutdown and then re-start the engine to process the
+# remaining data.
+# added 2009-05-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 1
+$MainMsgQueueSaveOnShutdown on
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-queuemode.conf
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf
+'
+
+#export RSYSLOG_DEBUG="debug nologfuncflow nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+
+# prepare config
+echo \$MainMsgQueueType $1 > ${RSYSLOG_DYNNAME}work-queuemode.conf
+echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf
+
+# inject 10000 msgs, so that DO hit the high watermark
+startup
+injectmsg 0 10000
+shutdown_immediate
+wait_shutdown
+check_mainq_spool
+
+echo "Enter phase 2, rsyslogd restart"
+
+# restart engine and have rest processed
+#remove delay
+echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 9999
+exit_test
diff --git a/tests/daqueue-persist.sh b/tests/daqueue-persist.sh
new file mode 100755
index 0000000..9499a06
--- /dev/null
+++ b/tests/daqueue-persist.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# Test for queue data persisting at shutdown. We use the actual driver
+# to carry out multiple tests with different queue modes
+# added 2009-05-27 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[daqueue-persist.sh\]: test data persisting at shutdown
+echo TEST is currently DISABLE because it is unstable
+exit 77
+echo mode linkedList
+$srcdir/daqueue-persist-drvr.sh LinkedList
+echo mode fixedArray
+$srcdir/daqueue-persist-drvr.sh FixedArray
+# the disk test should not fail, however, the config is extreme and using
+# it more or less is a config error
+echo Disk
+$srcdir/daqueue-persist-drvr.sh Disk
+# we do not test Direct mode because this absolute can not work in direct mode
+# (maybe we should do a fail-type of test?)
diff --git a/tests/diag.sh b/tests/diag.sh
new file mode 100755
index 0000000..c35edb0
--- /dev/null
+++ b/tests/diag.sh
@@ -0,0 +1,2946 @@
+#!/bin/bash
+#
+# this shell script provides commands to the common diag system. It enables
+# test scripts to wait for certain conditions and initiate certain actions.
+# needs support in config file.
+# NOTE: this file should be included with ". diag.sh", as it otherwise is
+# not always able to convey back states to the upper-level test driver
+# begun 2009-05-27 by rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+#
+# This file can be customized to environment specifics via environment
+# variables:
+# SUDO either blank, or the command to use for sudo (usually "sudo").
+# This env var is sometimes used to increase the chance that we
+# get extra information, e.g. when trying to analyze running
+# processes. Bottom line: if sudo is possible and you are OK with
+# the testbench utilizing this, use
+# export SUDO=sudo
+# to activate the extra functionality.
+# RS_SORTCMD Sort command to use (must support $RS_SORT_NUMERIC_OPT option). If unset,
+# "sort" is used. E.g. Solaris needs "gsort"
+# RS_SORT_NUMERIC_OPT option to use for numerical sort, If unset "-g" is used.
+# RS_CMPCMD cmp command to use. If unset, "cmd" is used.
+# E.g. Solaris needs "gcmp"
+# RS_HEADCMD head command to use. If unset, "head" is used.
+# E.g. Solaris needs "ghead"
+# RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT
+# global input timeout shutdown, default 60000 (60) sec. This should
+# only be set specifically if there is good need to do so, e.g. if
+# a test needs to timeout.
+# USE_VALGRIND if set to "YES", the test will be run under valgrind control, with
+# "default" settings (memcheck including leak check, termination on error).
+# This permits to have valgrind and non-valgrind versions of the same test
+# without the need to write it twice: just have a 2-liner -vg.sh which
+# does:
+# export USE_VALGRIND="YES"
+# source original-test.sh
+# sample can be seen in imjournal-basic[.vg].sh
+# You may also use USE_VALGRIND="YES-NOLEAK" to request valgrind without
+# leakcheck (this sometimes is needed).
+# ABORT_ALL_ON_TEST_FAIL
+# if set to "YES" and one test fails, all others are not executed but skipped.
+# This is useful in long-running CI jobs where we are happy with seeing the
+# first failure (to save time).
+#
+#
+# EXIT STATES
+# 0 - ok
+# 1 - FAIL
+# 77 - SKIP
+# 100 - Testbench failure
+export TB_ERR_TIMEOUT=101
+# 177 - internal state: test failed, but in a way that makes us strongly believe
+# this is caused by environment. This will lead to exit 77 (SKIP), but report
+# the failure if failure reporting is active
+
+# environment variables:
+# USE_AUTO_DEBUG "on" --> enables automatic debugging, anything else
+# turns it off
+
+# diag system internal environment variables
+# these variables are for use by test scripts - they CANNOT be
+# overridden by the user
+# TCPFLOOD_EXTRA_OPTS enables to set extra options for tcpflood, usually
+# used in tests that have a common driver where it
+# is too hard to set these options otherwise
+# CONFIG
+export ZOOPIDFILE="$(pwd)/zookeeper.pid"
+
+#valgrind="valgrind --malloc-fill=ff --free-fill=fe --log-fd=1"
+#valgrind="valgrind --tool=callgrind" # for kcachegrind profiling
+
+# **** use the line below for very hard to find leaks! *****
+#valgrind="valgrind --leak-check=full --show-leak-kinds=all --malloc-fill=ff --free-fill=fe --log-fd=1"
+
+#valgrind="valgrind --tool=drd --log-fd=1"
+#valgrind="valgrind --tool=helgrind --log-fd=1 --suppressions=$srcdir/linux_localtime_r.supp --gen-suppressions=all"
+#valgrind="valgrind --tool=exp-ptrcheck --log-fd=1"
+#set -o xtrace
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+TB_TIMEOUT_STARTSTOP=400 # timeout for start/stop rsyslogd in tenths (!) of a second 400 => 40 sec
+# note that 40sec for the startup should be sufficient even on very slow machines. we changed this from 2min on 2017-12-12
+TB_TEST_TIMEOUT=90 # number of seconds after which test checks timeout (eg. waits)
+TB_TEST_MAX_RUNTIME=${TEST_MAX_RUNTIME:-580} # maximum runtime in seconds for a test;
+ # default TEST_MAX_RUNTIME e.g. for long-running tests or special
+ # testbench use. Testbench will abort test
+ # after that time (iff it has a chance to, not strictly enforced)
+ # Note: 580 is slightly below the rsyslog-ci required max non-stdout writing timeout
+ # This is usually at 600 (10 minutes) and processes will be force-terminated if they
+ # go over it. This is especially bad because we do not receive notifications in this
+ # case.
+export RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR="on" # we want to know when we loose messages due to timeouts
+if [ "$TESTTOOL_DIR" == "" ]; then
+ export TESTTOOL_DIR="${srcdir:-.}"
+fi
+
+# newer functionality is preferably introduced via bash functions
+# rgerhards, 2018-07-03
+rsyslog_testbench_test_url_access() {
+ local missing_requirements=
+ if ! hash curl 2>/dev/null ; then
+ missing_requirements="'curl' is missing in PATH; Make sure you have cURL installed! Skipping test ..."
+ fi
+
+ if [ -n "${missing_requirements}" ]; then
+ printf '%s\n' "${missing_requirements}"
+ exit 77
+ fi
+
+ local http_endpoint="$1"
+ if ! curl --fail --max-time 30 "${http_endpoint}" 1>/dev/null 2>&1; then
+ echo "HTTP endpoint '${http_endpoint}' is not reachable. Skipping test ..."
+ exit 77
+ else
+ echo "HTTP endpoint '${http_endpoint}' is reachable! Starting test ..."
+ fi
+}
+
+# function to skip a test on a specific platform
+# $1 is what we check in uname, $2 (optional) is a reason message
+skip_platform() {
+ if [ "$(uname)" == "$1" ]; then
+ printf 'platform is "%s" - test does not work under "%s"\n' "$(uname)" "$1"
+ if [ "$2" != "" ]; then
+ printf 'reason: %s\n' "$2"
+ fi
+ exit 77
+ fi
+
+}
+
+# function to skip a test if TSAN is enabled
+# This is necessary as TSAN does not properly handle thread creation
+# after fork() - which happens regularly in rsyslog if backgrounding
+# is activated.
+# $1 is the reason why TSAN is not supported
+# note: we depend on CFLAGS to properly reflect build options (what
+# usually is the case when the testbench is run)
+skip_TSAN() {
+ if [[ "$CFLAGS" == *"sanitize=thread"* ]]; then
+ printf 'test incompatible with TSAN because of %s\n' "$1"
+ exit 77
+ fi
+}
+
+
+# a consistent format to output testbench timestamps
+tb_timestamp() {
+ printf '%s[%s] ' "$(date +%H:%M:%S)" "$(( $(date +%s) - TB_STARTTEST ))"
+}
+
+# override the test timeout, but only if the new value is higher
+# than the previous one. This is necessary for slow test systems
+# $1 is timeout in seconds
+override_test_timeout() {
+ if [ "${1:=0}" == "" ]; then
+ printf 'FAIL: invalid testbench call, override_test_timeout needs value\n'
+ error_exit 100
+ fi
+ if [ "$1" -gt "$TB_TEST_TIMEOUT" ]; then
+ TB_TEST_TIMEOUT=$1
+ printf 'info: TB_TEST_TIMEOUT increased to %s\n' "$TB_TEST_TIMEOUT"
+ fi
+}
+
+# set special tests status. States ($1) are:
+# unreliable -- as the name says, test does not work reliably; $2 must be github issue URL
+# depending on CI configuration, "unreliable" tests are skipped and not failed
+# or not executed at all. Test reports may also be amended to github issue.
+test_status() {
+ if [ "$1" == "unreliable" ]; then
+ if [ "$2" == "" ]; then
+ printf 'TESTBENCH_ERROR: github issue URL must be given\n'
+ error_exit 100
+ fi
+ export TEST_STATUS="$1"
+ export TEST_GITHUB_ISSUE="$2"
+ else
+ printf 'TESTBENCH_ERROR: test_status "%s" unknown\n' "$1"
+ error_exit 100
+ fi
+}
+
+
+setvar_RS_HOSTNAME() {
+ printf '### Obtaining HOSTNAME (prerequisite, not actual test) ###\n'
+ generate_conf ""
+ add_conf 'module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template hostname,"%hostname%"
+local0.* ./'${RSYSLOG_DYNNAME}'.HOSTNAME;hostname
+'
+ rm -f "${RSYSLOG_DYNNAME}.HOSTNAME"
+ startup ""
+ tcpflood -m1 -M "\"<128>\""
+ shutdown_when_empty
+ wait_shutdown ""
+ export RS_HOSTNAME="$(cat ${RSYSLOG_DYNNAME}.HOSTNAME)"
+ rm -f "${RSYSLOG_DYNNAME}.HOSTNAME"
+ echo HOSTNAME is: $RS_HOSTNAME
+}
+
+
+# begin a new testconfig
+# 2018-09-07: Incremented inputs.timeout.shutdown to 60000 because kafka tests may not be
+# finished under stress otherwise
+# $1 is the instance id, if given
+generate_conf() {
+ if [ "$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT" == "" ]; then
+ RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT="10000"
+ fi
+ if [ "$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT" == "" ]; then
+ RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT="60000"
+ fi
+ if [ "$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN" == "" ]; then
+ RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN="20000"
+ fi
+ if [ "$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE" == "" ]; then
+ RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE="20000"
+ fi
+ export TCPFLOOD_PORT="$(get_free_port)"
+ if [ "$1" == "" ]; then
+ export TESTCONF_NM="${RSYSLOG_DYNNAME}_" # this basename is also used by instance 2!
+ export RSYSLOG_OUT_LOG="${RSYSLOG_DYNNAME}.out.log"
+ export RSYSLOG2_OUT_LOG="${RSYSLOG_DYNNAME}_2.out.log"
+ export RSYSLOG_PIDBASE="${RSYSLOG_DYNNAME}:" # also used by instance 2!
+ mkdir $RSYSLOG_DYNNAME.spool
+ fi
+ echo 'module(load="../plugins/imdiag/.libs/imdiag")
+global(inputs.timeout.shutdown="'$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT'"
+ default.action.queue.timeoutshutdown="'$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN'"
+ default.action.queue.timeoutEnqueue="'$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE'")
+# use legacy-style for the following settings so that we can override if needed
+$MainmsgQueueTimeoutEnqueue 20000
+$MainmsgQueueTimeoutShutdown '$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT'
+$IMDiagListenPortFileName '$RSYSLOG_DYNNAME.imdiag$1.port'
+$IMDiagServerRun 0
+$IMDiagAbortTimeout '$TB_TEST_MAX_RUNTIME'
+
+:syslogtag, contains, "rsyslogd" ./'${RSYSLOG_DYNNAME}$1'.started
+###### end of testbench instrumentation part, test conf follows:' > ${TESTCONF_NM}$1.conf
+}
+
+# add more data to config file. Note: generate_conf must have been called
+# $1 is config fragment, $2 the instance id, if given
+add_conf() {
+ printf '%s' "$1" >> ${TESTCONF_NM}$2.conf
+}
+
+
+rst_msleep() {
+ $TESTTOOL_DIR/msleep $1
+}
+
+
+# compare file to expected exact content
+# $1 is file to compare, default $RSYSLOG_OUT_LOG
+cmp_exact() {
+ filename=${1:-"$RSYSLOG_OUT_LOG"}
+ if [ "$filename" == "" ]; then
+ printf 'Testbench ERROR, cmp_exact() does not have a filename at ALL!\n'
+ error_exit 100
+ fi
+ if [ "$EXPECTED" == "" ]; then
+ printf 'Testbench ERROR, cmp_exact() needs to have env var EXPECTED set!\n'
+ error_exit 100
+ fi
+ printf '%s\n' "$EXPECTED" | cmp - "$filename"
+ if [ $? -ne 0 ]; then
+ printf 'invalid response generated\n'
+ printf '################# %s is:\n' "$filename"
+ cat -n $filename
+ printf '################# EXPECTED was:\n'
+ cat -n <<< "$EXPECTED"
+ printf '\n#################### diff is:\n'
+ diff - "$filename" <<< "$EXPECTED"
+ error_exit 1
+ fi;
+}
+
+# code common to all startup...() functions
+startup_common() {
+ instance=
+ if [ "$1" == "2" ]; then
+ CONF_FILE="${TESTCONF_NM}2.conf"
+ instance=2
+ elif [ "$1" == "" ] || [ "$1" == "1" ]; then
+ CONF_FILE="${TESTCONF_NM}.conf"
+ else
+ CONF_FILE="$srcdir/testsuites/$1"
+ instance=$2
+ fi
+ # we need to remove the imdiag port file as there are some
+ # tests that start multiple times. These may get the old port
+ # number if the file still exists AND timing is bad so that
+ # imdiag does not generate the port file quickly enough on
+ # startup.
+ rm -f $RSYSLOG_DYNNAME.imdiag$instance.port
+ if [ ! -f $CONF_FILE ]; then
+ echo "ERROR: config file '$CONF_FILE' not found!"
+ error_exit 1
+ fi
+ echo config $CONF_FILE is:
+ cat -n $CONF_FILE
+}
+
+# wait for appearance of a specific pid file, given as $1
+wait_startup_pid() {
+ if [ "$1" == "" ]; then
+ echo "FAIL: testbench bug: wait_startup_called without \$1"
+ error_exit 100
+ fi
+ while test ! -f $1; do
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting on startup (pid file %s)\n' "$(tb_timestamp)" "$1"
+ ls -l "$1"
+ ps -fp $($SUDO cat "$1")
+ error_exit 1
+ fi
+ done
+ printf '%s %s found, pid %s\n' "$(tb_timestamp)" "$1" "$(cat $1)"
+}
+
+# special version of wait_startup_pid() for rsyslog startup
+wait_rsyslog_startup_pid() {
+ wait_startup_pid $RSYSLOG_PIDBASE$1.pid
+}
+
+# wait for startup of an arbitrary process
+# $1 - pid file name
+# $2 - startup file name (optional, only checked if given)
+wait_process_startup() {
+ wait_startup_pid $1.pid
+ i=0
+ if [ "$2" != "" ]; then
+ while test ! -f "$2"; do
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ ps -p $(cat $1.pid) &> /dev/null
+ if [ $? -ne 0 ]
+ then
+ echo "ABORT! pid in $1 no longer active during startup!"
+ error_exit 1
+ fi
+ (( i++ ))
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting on file %s\n' "$(tb_timestamp)" "$2"
+ error_exit 1
+ fi
+ done
+ printf '%s %s seen, associated pid %s\n' "$(tb_timestamp)" "$2" "$(cat $1)"
+ fi
+}
+
+
+# wait for the pid in $1 to terminate, abort on timeout
+wait_pid_termination() {
+ out_pid="$1"
+ if [[ "$out_pid" == "" ]]; then
+ printf 'TESTBENCH error: pidfile name not specified in wait_pid_termination\n'
+ error_exit 100
+ fi
+ terminated=0
+ while [[ $terminated -eq 0 ]]; do
+ ps -p $out_pid &> /dev/null
+ if [[ $? != 0 ]]; then
+ terminated=1
+ fi
+ $TESTTOOL_DIR/msleep 100
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting on shutdown (pid %s)\n' "$(tb_timestamp)" $out_pid
+ ps -fp $out_pid
+ printf 'Instance is possibly still running and may need manual cleanup.\n'
+ error_exit 1
+ fi
+ done
+ unset terminated
+ unset out_pid
+}
+
+# wait for file $1 to exist AND be non-empty
+# $1 : file to wait for
+# $2 (optional): error message to show if timeout occurs
+wait_file_exists() {
+ echo waiting for file $1
+ i=0
+ while true; do
+ if [ -f $1 ] && [ "$(cat $1 2> /dev/null)" != "" ]; then
+ break
+ fi
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ ((i++))
+ if test $i -gt $TB_TIMEOUT_STARTSTOP; then
+ echo "ABORT! Timeout waiting for file $1"
+ ls -l $1
+ if [ "$2" != "" ]; then
+ echo "$2"
+ fi
+ error_exit 1
+ fi
+ done
+}
+
+# kafka special wait function: we wait for the output file in order
+# to ensure Kafka/Zookeeper is actually ready to go. This is NOT
+# a generic check function and must only used with those kafka tests
+# that actually need it.
+kafka_wait_group_coordinator() {
+echo We are waiting for kafka/zookeeper being ready to deliver messages
+wait_file_exists $RSYSLOG_OUT_LOG "
+
+Non-existence of $RSYSLOG_OUT_LOG can be caused
+by a problem inside zookeeper. If debug output in the receiver is enabled, one
+may see this message:
+
+\"GroupCoordinator response error: Broker: Group coordinator not available\"
+
+In this case you may want to do a web search and/or have a look at
+ https://github.com/edenhill/librdkafka/issues/799
+
+The question, of course, is if there is nevertheless a problem in imkafka.
+Usually, the wait we do inside the testbench is sufficient to handle all
+Zookeeper/Kafka startup. So if the issue reoccurs, it is suggested to enable
+debug output in the receiver and check for actual problems.
+"
+}
+
+# check if kafka itself failed. $1 is the message file name.
+kafka_check_broken_broker() {
+ failed=0
+ if grep "Broker transport failure" < "$1" ; then
+ failed=1
+ fi
+ if grep "broker connections are down" < "$1" ; then
+ failed=1
+ fi
+ if [ $failed -eq 1 ]; then
+ printf '\n\nenvironment-induced test error - kafka broker failed - skipping test\n'
+ printf 'content of %s:\n' "$1"
+ cat -n "$1"
+ error_exit 177
+ fi
+}
+
+# inject messages via kafkacat tool (for imkafka tests)
+# $1 == "--wait" means wait for rsyslog to receive TESTMESSAGES lines in RSYSLOG_OUT_LOG
+# $TESTMESSAGES contains number of messages to inject
+# $RANDTOPIC contains topic to produce to
+injectmsg_kafkacat() {
+ if [ "$1" == "--wait" ]; then
+ wait="YES"
+ shift
+ fi
+ if [ "$TESTMESSAGES" == "" ]; then
+ printf 'TESTBENCH ERROR: TESTMESSAGES env var not set!\n'
+ error_exit 1
+ fi
+ MAXATONCE=25000 # how many msgs should kafkacat send? - hint: current version errs out above ~70000
+ i=1
+ while (( i<=TESTMESSAGES )); do
+ currmsgs=0
+ while ((i <= $TESTMESSAGES && currmsgs != MAXATONCE)); do
+ printf ' msgnum:%8.8d\n' $i;
+ i=$((i + 1))
+ currmsgs=$((currmsgs+1))
+ done > "$RSYSLOG_DYNNAME.kafkacat.in"
+ set -e
+ kafkacat -P -b localhost:29092 -t $RANDTOPIC <"$RSYSLOG_DYNNAME.kafkacat.in" 2>&1 | tee >$RSYSLOG_DYNNAME.kafkacat.log
+ set +e
+ printf 'kafkacat injected %d msgs so far\n' $((i - 1))
+ kafka_check_broken_broker $RSYSLOG_DYNNAME.kafkacat.log
+ check_not_present "ERROR" $RSYSLOG_DYNNAME.kafkacat.log
+ cat $RSYSLOG_DYNNAME.kafkacat.log
+ done
+
+ if [ "$wait" == "YES" ]; then
+ wait_seq_check "$@"
+ fi
+}
+
+
+# wait for rsyslogd startup ($1 is the instance)
+wait_startup() {
+ wait_rsyslog_startup_pid $1
+ while test ! -f ${RSYSLOG_DYNNAME}$1.started; do
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ ps -p $(cat $RSYSLOG_PIDBASE$1.pid) &> /dev/null
+ if [ $? -ne 0 ]
+ then
+ echo "ABORT! rsyslog pid no longer active during startup!"
+ error_exit 1 stacktrace
+ fi
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting startup file %s\n' "$(tb_timestamp)" "${RSYSLOG_DYNNAME}.started"
+ error_exit 1
+ fi
+ done
+ echo "$(tb_timestamp) rsyslogd$1 startup msg seen, pid " $(cat $RSYSLOG_PIDBASE$1.pid)
+ wait_file_exists $RSYSLOG_DYNNAME.imdiag$1.port
+ eval export IMDIAG_PORT$1=$(cat $RSYSLOG_DYNNAME.imdiag$1.port)
+ eval PORT='$IMDIAG_PORT'$1
+ echo "imdiag$1 port: $PORT"
+ if [ "$PORT" == "" ]; then
+ echo "TESTBENCH ERROR: imdiag port not found!"
+ ls -l $RSYSLOG_DYNNAME*
+ exit 100
+ fi
+}
+
+# reassign ports after rsyslog startup; must be called from all
+# functions that startup rsyslog
+reassign_ports() {
+ if grep -q 'listenPortFileName="'$RSYSLOG_DYNNAME'\.tcpflood_port"' $CONF_FILE; then
+ assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+ fi
+ if grep -q '$InputTCPServerListenPortFile.*\.tcpflood_port' $CONF_FILE; then
+ assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+ fi
+}
+
+# start rsyslogd with default params. $1 is the config file name to use
+# returns only after successful startup, $2 is the instance (blank or 2!)
+# RS_REDIR maybe set to redirect rsyslog output
+# env var RSTB_DAEMONIZE" == "YES" means rsyslogd shall daemonize itself;
+# any other value or unset means it does not do that.
+startup() {
+ if [ "$USE_VALGRIND" == "YES" ]; then
+ startup_vg "$1" "$2"
+ return
+ elif [ "$USE_VALGRIND" == "YES-NOLEAK" ]; then
+ startup_vg_noleak "$1" "$2"
+ return
+ fi
+ startup_common "$1" "$2"
+ if [ "$RSTB_DAEMONIZE" == "YES" ]; then
+ n_option=""
+ else
+ n_option="-n"
+ fi
+ eval LD_PRELOAD=$RSYSLOG_PRELOAD $valgrind ../tools/rsyslogd -C $n_option -i$RSYSLOG_PIDBASE$instance.pid -M../runtime/.libs:../.libs -f$CONF_FILE $RS_REDIR &
+ wait_startup $instance
+ reassign_ports
+}
+
+
+# assign TCPFLOOD_PORT from port file
+# $1 - port file
+assign_tcpflood_port() {
+ wait_file_exists "$1"
+ export TCPFLOOD_PORT=$(cat "$1")
+ echo "TCPFLOOD_PORT now: $TCPFLOOD_PORT"
+ if [ "$TCPFLOOD_PORT" == "" ]; then
+ echo "TESTBENCH ERROR: TCPFLOOD_PORT not found!"
+ ls -l $RSYSLOG_DYNNAME*
+ exit 100
+ fi
+}
+
+
+# assign TCPFLOOD_PORT2 from port file
+# $1 - port file
+assign_tcpflood_port2() {
+ wait_file_exists "$1"
+ export TCPFLOOD_PORT2=$(cat "$1")
+ echo "TCPFLOOD_PORT2 now: $TCPFLOOD_PORT2"
+ if [ "$TCPFLOOD_PORT2" == "" ]; then
+ echo "TESTBENCH ERROR: TCPFLOOD_PORT2 not found!"
+ ls -l $RSYSLOG_DYNNAME*
+ exit 100
+ fi
+}
+# assign RS_PORT from port file - this is meant as generic way to
+# obtain additional port variables
+# $1 - port file
+assign_rs_port() {
+ wait_file_exists "$1"
+ export RS_PORT=$(cat "$1")
+ echo "RS_PORT now: $RS_PORT"
+ if [ "$RS_PORT" == "" ]; then
+ echo "TESTBENCH ERROR: RS_PORT not found!"
+ ls -l $RSYSLOG_DYNNAME*
+ exit 100
+ fi
+}
+
+# wait for a file to exist, then export it's content to env var
+# intended to be used for very small files, e.g. listenPort files
+# $1 - env var name
+# $2 - port file
+assign_file_content() {
+ wait_file_exists "$2"
+ content=$(cat "$2")
+ if [ "$content" == "" ]; then
+ echo "TESTBENCH ERROR: get_file content had empty file $2"
+ ls -l $RSYSLOG_DYNNAME*
+ exit 100
+ fi
+ eval export $1="$content"
+ printf 'exported: %s=%s\n' $1 "$content"
+}
+
+# same as startup_vg, BUT we do NOT wait on the startup message!
+startup_vg_waitpid_only() {
+ startup_common "$1" "$2"
+ if [ "$RS_TESTBENCH_LEAK_CHECK" == "" ]; then
+ RS_TESTBENCH_LEAK_CHECK=full
+ fi
+ # add --keep-debuginfo=yes for hard to find cases; this cannot be used generally,
+ # because it is only supported by newer versions of valgrind (else CI will fail
+ # on older platforms).
+ LD_PRELOAD=$RSYSLOG_PRELOAD valgrind $RS_TEST_VALGRIND_EXTRA_OPTS $RS_TESTBENCH_VALGRIND_EXTRA_OPTS --suppressions=$srcdir/known_issues.supp ${EXTRA_VALGRIND_SUPPRESSIONS:-} --gen-suppressions=all --log-fd=1 --error-exitcode=10 --malloc-fill=ff --free-fill=fe --leak-check=$RS_TESTBENCH_LEAK_CHECK ../tools/rsyslogd -C -n -i$RSYSLOG_PIDBASE$instance.pid -M../runtime/.libs:../.libs -f$CONF_FILE &
+ wait_rsyslog_startup_pid $1
+}
+
+# start rsyslogd with default params under valgrind control. $1 is the config file name to use
+# returns only after successful startup, $2 is the instance (blank or 2!)
+startup_vg() {
+ startup_vg_waitpid_only $1 $2
+ wait_startup $instance
+ reassign_ports
+}
+
+# same as startup-vg, except that --leak-check is set to "none". This
+# is meant to be used in cases where we have to deal with libraries (and such
+# that) we don't can influence and where we cannot provide suppressions as
+# they are platform-dependent. In that case, we can't test for leak checks
+# (obviously), but we can check for access violations, what still is useful.
+startup_vg_noleak() {
+ RS_TESTBENCH_LEAK_CHECK=no
+ startup_vg "$@"
+}
+
+# same as startup-vgthread, BUT we do NOT wait on the startup message!
+startup_vgthread_waitpid_only() {
+ startup_common "$1" "$2"
+ valgrind --tool=helgrind $RS_TEST_VALGRIND_EXTRA_OPTS $RS_TESTBENCH_VALGRIND_EXTRA_OPTS --log-fd=1 --error-exitcode=10 --suppressions=$srcdir/linux_localtime_r.supp --suppressions=$srcdir/known_issues.supp ${EXTRA_VALGRIND_SUPPRESSIONS:-} --suppressions=$srcdir/CI/gcov.supp --gen-suppressions=all ../tools/rsyslogd -C -n -i$RSYSLOG_PIDBASE$2.pid -M../runtime/.libs:../.libs -f$CONF_FILE &
+ wait_rsyslog_startup_pid $2
+}
+
+# start rsyslogd with default params under valgrind thread debugger control.
+# $1 is the config file name to use, $2 is the instance (blank or 2!)
+# returns only after successful startup
+startup_vgthread() {
+ startup_vgthread_waitpid_only $1 $2
+ wait_startup $2
+ reassign_ports
+}
+
+
+# inject messages via our inject interface (imdiag)
+# $1 is start message number, env var NUMMESSAGES is number of messages to inject
+injectmsg() {
+ if [ "$3" != "" ] ; then
+ printf 'error: injectmsg only has two arguments, extra arg is %s\n' "$3"
+ fi
+ msgs=${2:-$NUMMESSAGES}
+ echo injecting $msgs messages
+ echo injectmsg "${1:-0}" "$msgs" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+}
+
+# inject messages in INSTANCE 2 via our inject interface (imdiag)
+injectmsg2() {
+ msgs=${2:-$NUMMESSAGES}
+ echo injecting $msgs messages into instance 2
+ echo injectmsg "${1:-0}" "$msgs" $3 $4 | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT2 || error_exit $?
+ # TODO: some return state checking? (does it really make sense here?)
+}
+
+# inject literal payload via our inject interface (imdiag)
+injectmsg_literal() {
+ printf 'injecting msg payload: %s\n' "$1"
+ sed -e 's/^/injectmsg literal /g' <<< "$1" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+}
+
+# inject literal payload via our inject interface (imdiag)
+injectmsg_file() {
+ printf 'injecting msg payload: %s\n' "$1"
+ sed -e 's/^/injectmsg literal /g' < "$1" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+}
+
+
+# show the current main queue size. $1 is the instance.
+get_mainqueuesize() {
+ if [ "$1" == "2" ]; then
+ echo getmainmsgqueuesize | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT2 || error_exit $?
+ else
+ echo getmainmsgqueuesize | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ fi
+}
+
+# get pid of rsyslog instance $1
+getpid() {
+ printf '%s' "$(cat $RSYSLOG_PIDBASE$1.pid)"
+}
+
+# grep for (partial) content. $1 is the content to check for, $2 the file to check
+# option --check-only just returns success/fail but does not terminate on fail
+# this is meant for checking during queue shutdown processing.
+# option --regex is understood, in which case $1 is a regex
+content_check() {
+ if [ "$1" == "--check-only" ]; then
+ check_only="yes"
+ shift
+ else
+ check_only="no"
+ fi
+ if [ "$1" == "--regex" ]; then
+ grep_opt=
+ shift
+ else
+ grep_opt=-F
+ fi
+ if [ "$1" == "--output-results" ]; then
+ output_results="yes"
+ shift
+ else
+ output_results="no"
+ fi
+ file=${2:-$RSYSLOG_OUT_LOG}
+ if ! grep -q $grep_opt -- "$1" < "${file}"; then
+ if [ "$check_only" == "yes" ]; then
+ printf 'content_check did not yet succeed\n'
+ return 1
+ fi
+ printf '\n============================================================\n'
+ printf 'FILE "%s" content:\n' "$file"
+ cat -n ${file}
+ printf 'FAIL: content_check failed to find "%s"\n' "$1"
+ error_exit 1
+ else
+ if [ "$output_results" == "yes" ]; then
+ # Output GREP results
+ echo "SUCCESS: content_check found results for '$1'\n"
+ grep "$1" "${file}"
+ fi
+ fi
+ if [ "$check_only" == "yes" ]; then
+ return 0
+ fi
+}
+
+
+# grep for (partial) content. this checks the count of the content
+# $1 is the content to check for
+# $2 required count
+# $3 the file to check (if default not used)
+# option --regex is understood, in which case $1 is a regex
+content_count_check() {
+ if [ "$1" == "--regex" ]; then
+ grep_opt=
+ shift
+ else
+ grep_opt=-F
+ fi
+ file=${3:-$RSYSLOG_OUT_LOG}
+ count=$(grep -c $grep_opt -- "$1" <${RSYSLOG_OUT_LOG})
+ if [ ${count:=0} -ne "$2" ]; then
+ grep -c -F -- "$1" <${RSYSLOG_OUT_LOG}
+ printf '\n============================================================\n'
+ printf 'FILE "%s" content:\n' "$file"
+ cat -n ${file}
+ printf 'FAIL: content count required %d but was %d\n' "$2" $count
+ printf 'FAIL: content_check failed to find "%s"\n' "$1"
+ error_exit 1
+ fi
+}
+
+
+
+# $1 - content to check for
+# $2 - number of times content must appear
+# $3 - timeout (default: 1)
+content_check_with_count() {
+ timeoutend=${3:-1}
+ timecounter=0
+ while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter=timecounter+1 ))
+ count=0
+ if [ -f "${RSYSLOG_OUT_LOG}" ]; then
+ count=$(grep -c -F -- "$1" <${RSYSLOG_OUT_LOG})
+ fi
+ if [ ${count:=0} -eq $2 ]; then
+ echo content_check_with_count SUCCESS, \"$1\" occurred $2 times
+ break
+ else
+ if [ "$timecounter" == "$timeoutend" ]; then
+ shutdown_when_empty ""
+ wait_shutdown ""
+
+ echo "$(tb_timestamp)" content_check_with_count failed, expected \"$1\" to occur $2 times, but found it "$count" times
+ echo file $RSYSLOG_OUT_LOG content is:
+ if [ $(wc -l < "$RSYSLOG_OUT_LOG") -gt 10000 ]; then
+ printf 'truncation, we have %d lines, which is way too much\n' \
+ $(wc -l < "$RSYSLOG_OUT_LOG")
+ printf 'showing first and last 5000 lines\n'
+ head -n 5000 < "$RSYSLOG_OUT_LOG"
+ print '\n ... CUT ..................................................\n\n'
+ tail -n 5000 < "$RSYSLOG_OUT_LOG"
+ else
+ cat -n "$RSYSLOG_OUT_LOG"
+ fi
+ error_exit 1
+ else
+ printf '%s content_check_with_count, try %d have %d, wait for %d, search for: "%s"\n' \
+ "$(tb_timestamp)" "$timecounter" "$count" "$2" "$1"
+ $TESTTOOL_DIR/msleep 1000
+ fi
+ fi
+ printf '%s **** content_check_with_count DEBUG (timeout %s, need %s lines):\n' "$(tb_timestamp)" "$3" "$2" # rger: REMOVE ME when problems are fixed
+ if [ -f "${RSYSLOG_OUT_LOG}" ]; then cat -n "$RSYSLOG_OUT_LOG"; fi
+ done
+}
+
+
+custom_content_check() {
+ grep -qF -- "$1" < $2
+ if [ "$?" -ne "0" ]; then
+ echo FAIL: custom_content_check failed to find "'$1'" inside "'$2'"
+ echo "file contents:"
+ cat -n $2
+ error_exit 1
+ fi
+}
+
+# check that given content $1 is not present in file $2 (default: RSYSLOG_OUT_LOG)
+# regular expressions may be used
+check_not_present() {
+ if [ "$2" == "" ]; then
+ file=$RSYSLOG_OUT_LOG
+ else
+ file="$2"
+ fi
+ grep -q -- "$1" < "$file"
+ if [ "$?" -eq "0" ]; then
+ echo FAIL: check_not present found
+ echo $1
+ echo inside file $file of $(wc -l < $file) lines
+ echo samples:
+ cat -n "$file" | grep -- "$1" | head -10
+ error_exit 1
+ fi
+}
+
+
+# check if mainqueue spool files exist, if not abort (we just check .qi).
+check_mainq_spool() {
+ printf 'There must exist some files now:\n'
+ ls -l $RSYSLOG_DYNNAME.spool
+ printf '.qi file:\n'
+ cat $RSYSLOG_DYNNAME.spool/mainq.qi
+ if [ ! -f $RSYSLOG_DYNNAME.spool/mainq.qi ]; then
+ printf 'error: mainq.qi does not exist where expected to do so!\n'
+ error_exit 1
+ fi
+}
+# check that no spool file exists. Abort if they do.
+# This situation must exist after a successful termination of rsyslog
+# where the disk queue has properly been drained and shut down.
+check_spool_empty() {
+ if [ "$(ls $RSYSLOG_DYNNAME.spool/* 2> /dev/null)" != "" ]; then
+ printf 'error: spool files exists where they are not permitted to do so:\n'
+ ls -l $RSYSLOG_DYNNAME.spool/*
+ error_exit 1
+ fi
+}
+
+# general helper for imjournal tests: check that we got hold of the
+# injected test message. This is pretty lengthy as the journal has played
+# "a bit" with us and also seems to sometimes have a heavy latency in
+# forwarding messages. So let's centralize the check code.
+#
+# $TESTMSG must contain the test message
+check_journal_testmsg_received() {
+ printf 'checking that journal indeed contains test message - may take a short while...\n'
+ # search reverse, gets us to our message (much) faster .... if it is there...
+ journalctl -a -r | grep -qF "$TESTMSG"
+ if [ $? -ne 0 ]; then
+ print 'SKIP: cannot read journal - our testmessage not found via journalctl\n'
+ exit 77
+ fi
+ printf 'journal contains test message\n'
+
+ echo "INFO: $(wc -l < $RSYSLOG_OUT_LOG) lines in $RSYSLOG_OUT_LOG"
+
+ grep -qF "$TESTMSG" < $RSYSLOG_OUT_LOG
+ if [ $? -ne 0 ]; then
+ echo "FAIL: $RSYSLOG_OUT_LOG content (tail -n200):"
+ tail -n200 $RSYSLOG_OUT_LOG
+ echo "======="
+ echo "searching journal for testbench messages:"
+ journalctl -a | grep -qF "TestBenCH-RSYSLog imjournal"
+ echo "======="
+ echo "NOTE: showing only last 200 lines, may be insufficient on busy systems!"
+ echo "last entries from journal:"
+ journalctl -an 200
+ echo "======="
+ echo "NOTE: showing only last 200 lines, may be insufficient on busy systems!"
+ echo "However, the test check all of the journal, we are just limiting the output"
+ echo "to 200 lines to not spam CI systems too much."
+ echo "======="
+ echo "FAIL: imjournal test message could not be found!"
+ echo "Expected message content was:"
+ echo "$TESTMSG"
+ error_exit 1
+ fi;
+}
+
+# checks that among the open files found in /proc/<PID>/fd/*
+# there is or is not, depending on the calling mode,
+# a link with the specified suffix in the target name
+check_fd_for_pid() {
+ local pid="$1" mode="$2" suffix="$3" target seen
+ seen="false"
+ for fd in $(echo /proc/$pid/fd/*); do
+ target="$(readlink -m "$fd")"
+ if [[ "$target" != *$RSYSLOG_DYNNAME* ]]; then
+ continue
+ fi
+ if ((i % 10 == 0)); then
+ echo "INFO: check target='$target'"
+ fi
+ if [[ "$target" == *$suffix ]]; then
+ seen="true"
+ if [[ "$mode" == "exists" ]]; then
+ echo "PASS: check fd for pid=$pid mode='$mode' suffix='$suffix'"
+ return 0
+ fi
+ fi
+ done
+ if [[ "$seen" == "false" ]] && [[ "$mode" == "absent" ]]; then
+ echo "PASS: check fd for pid=$pid mode='$mode' suffix='$suffix'"
+ return 0
+ fi
+ echo "FAIL: check fd for pid=$pid mode='$mode' suffix='$suffix'"
+ if [[ "$mode" != "ignore" ]]; then
+ return 1
+ fi
+ return 0
+}
+
+# wait for main message queue to be empty. $1 is the instance.
+# we run in a loop to ensure rsyslog is *really* finished when a
+# function for the "finished predicate" is defined. This is done
+# by setting env var QUEUE_EMPTY_CHECK_FUNC to the bash
+# function name.
+wait_queueempty() {
+ while [ $(date +%s) -le $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; do
+ if [ "$1" == "2" ]; then
+ echo WaitMainQueueEmpty | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT2 || error_exit $?
+ else
+ echo WaitMainQueueEmpty | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ fi
+ if [ "$QUEUE_EMPTY_CHECK_FUNC" == "" ]; then
+ return
+ else
+ if $QUEUE_EMPTY_CHECK_FUNC ; then
+ return
+ fi
+ fi
+ done
+ error_exit $TB_ERR_TIMEOUT
+}
+
+
+# shut rsyslogd down when main queue is empty. $1 is the instance.
+shutdown_when_empty() {
+ echo Shutting down instance ${1:-1}
+ wait_queueempty $1
+ if [ "$RSYSLOG_PIDBASE" == "" ]; then
+ echo "RSYSLOG_PIDBASE is EMPTY! - bug in test? (instance $1)"
+ error_exit 1
+ fi
+ cp $RSYSLOG_PIDBASE$1.pid $RSYSLOG_PIDBASE$1.pid.save
+ $TESTTOOL_DIR/msleep 500 # wait a bit (think about slow testbench machines!)
+ kill $(cat $RSYSLOG_PIDBASE$1.pid) # note: we do not wait for the actual termination!
+}
+
+# shut rsyslogd down without emptying the queue. $2 is the instance.
+shutdown_immediate() {
+ pidfile=$RSYSLOG_PIDBASE${1:-}.pid
+ cp $pidfile $pidfile.save
+ kill $(cat $pidfile)
+}
+
+
+# actually, we wait for rsyslog.pid to be deleted.
+# $1 is the instance
+wait_shutdown() {
+ if [ "$USE_VALGRIND" == "YES" ] || [ "$USE_VALGRIND" == "YES-NOLEAK" ]; then
+ wait_shutdown_vg "$1"
+ return
+ fi
+ out_pid=$(cat $RSYSLOG_PIDBASE$1.pid.save)
+ printf '%s wait on shutdown of %s\n' "$(tb_timestamp)" "$out_pid"
+ if [[ "$out_pid" == "" ]]
+ then
+ terminated=1
+ else
+ terminated=0
+ fi
+ while [[ $terminated -eq 0 ]]; do
+ ps -p $out_pid &> /dev/null
+ if [[ $? != 0 ]]; then
+ terminated=1
+ fi
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s wait_shutdown ABORT! Timeout waiting on shutdown (pid %s)\n' "$(tb_timestamp)" $out_pid
+ ps -fp $out_pid
+ echo "Instance is possibly still running and may need"
+ echo "manual cleanup."
+ echo "TRYING TO capture status via gdb from hanging process"
+ $SUDO gdb ../tools/rsyslogd <<< "attach $out_pid
+set pagination off
+inf thr
+thread apply all bt
+quit"
+ echo "trying to kill -9 process"
+ kill -9 $out_pid
+ error_exit 1
+ fi
+ done
+ unset terminated
+ unset out_pid
+ if [ "$(ls core.* 2>/dev/null)" != "" ]; then
+ printf 'ABORT! core file exists (maybe from a parallel run!)\n'
+ pwd
+ ls -l core.*
+ error_exit 1
+ fi
+}
+
+
+# wait for HUP to complete. $1 is the instance
+# note: there is a slight chance HUP was not completed. This can happen if it takes
+# the system very long (> 500ms) to receive the HUP and set the internal flag
+# variable. aka "very very low probability".
+await_HUP_processed() {
+ if [ "$1" == "2" ]; then
+ echo AwaitHUPComplete | $TESTTOOL_DIR/diagtalker -pIMDIAG_PORT2 || error_exit $?
+ else
+ echo AwaitHUPComplete | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ fi
+}
+
+
+# wait for all pending lookup table reloads to complete $1 is the instance.
+await_lookup_table_reload() {
+ if [ "$1" == "2" ]; then
+ echo AwaitLookupTableReload | $TESTTOOL_DIR/diagtalker -pIMDIAG_PORT2 || error_exit $?
+ else
+ echo AwaitLookupTableReload | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ fi
+}
+
+# $1 filename, default $RSYSLOG_OUT_LOG
+# $2 expected nbr of lines, default $NUMMESSAGES
+# $3 timeout in seconds
+# options (need to be specified in THIS ORDER if multiple given):
+# --delay ms -- if given, delay to use between retries
+# --abort-on-oversize -- error_exit if more lines than expected are present
+# --count-function func -- function to call to obtain current count
+# this permits to override the default predicate and makes
+# the wait really universally usable.
+wait_file_lines() {
+ delay=200
+ if [ "$1" == "--delay" ]; then
+ delay="$2"
+ shift 2
+ fi
+ abort_oversize=NO
+ if [ "$1" == "--abort-on-oversize" ]; then
+ abort_oversize="YES"
+ shift
+ fi
+ count_function=
+ if [ "$1" == "--count-function" ]; then
+ count_function="$2"
+ shift 2
+ fi
+ interrupt_connection=NO
+ if [ "$1" == "--interrupt-connection" ]; then
+ interrupt_connection="YES"
+ interrupt_host="$2"
+ interrupt_port="$3"
+ interrupt_tick="$4"
+ shift 4
+ lastcurrent_time=0
+ fi
+
+ timeout=${3:-$TB_TEST_TIMEOUT}
+ timeoutbegin=$(date +%s)
+ timeoutend=$(( timeoutbegin + timeout ))
+ # TODO: change this to support odl mode, if needed: timeoutend=${3:-200}
+ file=${1:-$RSYSLOG_OUT_LOG}
+ waitlines=${2:-$NUMMESSAGES}
+
+ while true ; do
+ count=0
+ if [ "$count_function" == "" ]; then
+ if [ -f "$file" ]; then
+ if [ "$COUNT_FILE_IS_ZIPPED" == "yes" ]; then
+ issue_HUP ""
+ count=$(gunzip < "$file" | wc -l)
+ else
+ count=$(wc -l < "$file")
+ fi
+ fi
+ else
+ count=$($count_function)
+ fi
+ if [ ${count} -gt $waitlines ]; then
+ if [ $abort_oversize == "YES" ] && [ ${count} -gt $waitlines ]; then
+ printf 'FAIL: wait_file_lines, too many lines, expected %d, current %s, took %s seconds\n' \
+ $waitlines $count "$(( $(date +%s) - timeoutbegin ))"
+ error_exit 1
+ else
+ printf 'wait_file_lines success, target %d or more lines, have %d, took %d seconds\n' \
+ "$waitlines" $count "$(( $(date +%s) - timeoutbegin ))"
+ return
+ fi
+ fi
+ if [ ${count} -eq $waitlines ]; then
+ echo wait_file_lines success, have $waitlines lines, took $(( $(date +%s) - timeoutbegin )) seconds, file "$file"
+ break
+ else
+ if [ $(date +%s) -ge $timeoutend ]; then
+ echo wait_file_lines failed, expected $waitlines got $count after $timeoutend retries, took $(( $(date +%s) - timeoutbegin )) seconds
+ error_exit 1
+ else
+ echo $(date +%H:%M:%S) wait_file_lines waiting, expected $waitlines, current $count lines
+
+ current_time=$(date +%s)
+ if [ $interrupt_connection == "YES" ] && [ $current_time -gt $lastcurrent_time ] && [ $((current_time % $interrupt_tick)) -eq 0 ] && [ ${count} -gt 1 ]; then
+ # Interrupt Connection - requires root and linux kernel >= 4.9 in order to work!
+ echo wait_file_lines Interrupt Connection on ${interrupt_host}:${interrupt_port}
+ sudo ss -K dst ${interrupt_host} dport = ${interrupt_port}
+ fi
+ lastcurrent_time=$current_time
+
+ $TESTTOOL_DIR/msleep $delay
+ fi
+ fi
+ done
+}
+
+
+
+
+# wait until seq_check succeeds. This is used to synchronize various
+# testbench timing-related issues, most importantly rsyslog shutdown
+# all parameters are passed to seq_check
+wait_seq_check() {
+ timeoutend=$(( $(date +%s) + TB_TEST_TIMEOUT ))
+ if [ "$SEQ_CHECK_FILE" == "" ]; then
+ filename="$RSYSLOG_OUT_LOG"
+ else
+ filename="$SEQ_CHECK_FILE"
+ fi
+
+ while true ; do
+ if [ "$PRE_SEQ_CHECK_FUNC" != "" ]; then
+ $PRE_SEQ_CHECK_FUNC
+ fi
+ if [ "${filename##.*}" != "gz" ]; then
+ if [ -f "$filename" ]; then
+ count=$(wc -l < "$filename")
+ fi
+ fi
+ seq_check --check-only "$@" #&>/dev/null
+ ret=$?
+ if [ $ret == 0 ]; then
+ printf 'wait_seq_check success (%d lines)\n' "$count"
+ break
+ else
+ if [ $(date +%s) -ge $timeoutend ]; then
+ printf 'wait_seq_check failed, no success before timeout\n'
+ error_exit 1
+ else
+ printf 'wait_seq_check waiting (%d lines)\n' $count
+ $TESTTOOL_DIR/msleep 500
+ fi
+ fi
+ done
+ unset count
+}
+
+
+# wait until some content appears in the specified file.
+# This is used to synchronize various
+# testbench timing-related issues, most importantly rsyslog shutdown
+# all parameters are passed to seq_check
+# $1 - content to search for
+# $2 - file to check
+wait_content() {
+ file=${2:-$RSYSLOG_OUT_LOG}
+ timeoutend=$(( $(date +%s) + TB_TEST_TIMEOUT ))
+ count=0
+
+ while true ; do
+ if [ -f "$file" ]; then
+ count=$(wc -l < "$file")
+ if grep -q "$1" < "$file"; then
+ printf 'expected content found, continue test (%d lines)\n' "$count"
+ break
+ fi
+ fi
+ if [ $(date +%s) -ge $timeoutend ]; then
+ printf 'wait_content failed, no success before timeout (%d lines)\n' "$count"
+ printf 'searched content was:\n%s\n' "$1"
+ error_exit 1
+ else
+ printf 'wait_content still waiting... (%d lines)\n' "$count"
+ tail "$file"
+ $TESTTOOL_DIR/msleep 500
+ fi
+ done
+ unset count
+}
+
+
+assert_content_missing() {
+ grep -qF -- "$1" < ${RSYSLOG_OUT_LOG}
+ if [ "$?" -eq "0" ]; then
+ echo content-missing assertion failed, some line matched pattern "'$1'"
+ error_exit 1
+ fi
+}
+
+
+custom_assert_content_missing() {
+ grep -qF -- "$1" < $2
+ if [ "$?" -eq "0" ]; then
+ echo content-missing assertion failed, some line in "'$2'" matched pattern "'$1'"
+ cat -n "$2"
+ error_exit 1
+ fi
+}
+
+
+# shut rsyslogd down when main queue is empty. $1 is the instance.
+issue_HUP() {
+ if [ "$1" == "--sleep" ]; then
+ sleeptime="$2"
+ shift 2
+ else
+ sleeptime=1000
+ fi
+ kill -HUP $(cat $RSYSLOG_PIDBASE$1.pid)
+ printf 'HUP issued to pid %d - waiting for it to become processed\n' \
+ $(cat $RSYSLOG_PIDBASE$1.pid)
+ await_HUP_processed
+ #$TESTTOOL_DIR/msleep $sleeptime
+}
+
+
+# actually, we wait for rsyslog.pid to be deleted. $1 is the instance
+wait_shutdown_vg() {
+ wait $(cat $RSYSLOG_PIDBASE$1.pid)
+ export RSYSLOGD_EXIT=$?
+ echo rsyslogd run exited with $RSYSLOGD_EXIT
+
+ if [ "$(ls vgcore.* 2>/dev/null)" != "" ]; then
+ printf 'ABORT! core file exists:\n'
+ ls -l vgcore.*
+ error_exit 1
+ fi
+ if [ "$USE_VALGRIND" == "YES" ] || [ "$USE_VALGRIND" == "YES-NOLEAK" ]; then
+ check_exit_vg
+ fi
+}
+
+check_file_exists() {
+ if [ ! -f "$1" ]; then
+ printf 'FAIL: file "%s" must exist, but does not\n' "$1"
+ error_exit 1
+ fi
+}
+
+check_file_not_exists() {
+ if [ -f "$1" ]; then
+ printf 'FILE %s CONTENT:\n' "$1"
+ cat -n -- "$1"
+ printf 'FAIL: file "%s" must NOT exist, but does\n' "$1"
+ error_exit 1
+ fi
+}
+
+# check exit code for valgrind error
+check_exit_vg(){
+ if [ "$RSYSLOGD_EXIT" -eq "10" ]; then
+ printf 'valgrind run FAILED with exceptions - terminating\n'
+ error_exit 1
+ fi
+}
+
+
+# do cleanup during exit processing
+do_cleanup() {
+ if [ "$(type -t test_error_exit_handler)" == "function" ]; then
+ test_error_exit_handler
+ fi
+
+ if [ -f $RSYSLOG_PIDBASE.pid ]; then
+ printf 'rsyslog pid file still exists, trying to shutdown...\n'
+ shutdown_immediate ""
+ fi
+ if [ -f ${RSYSLOG_PIDBASE}1.pid ]; then
+ printf 'rsyslog pid file still exists, trying to shutdown...\n'
+ shutdown_immediate 1
+ fi
+ if [ -f ${RSYSLOG_PIDBASE}2.pid ]; then
+ printf 'rsyslog pid file still exists, trying to shutdown...\n'
+ shutdown_immediate 2
+ fi
+}
+
+
+# this is called if we had an error and need to abort. Here, we
+# try to gather as much information as possible. That's most important
+# for systems like Travis-CI where we cannot debug on the machine itself.
+# our $1 is the to-be-used exit code. if $2 is "stacktrace", call gdb.
+#
+# NOTE: if a function test_error_exit_handler is defined, error_exit will
+# call it immediately before termination. This may be used to cleanup
+# some things or emit additional diagnostic information.
+error_exit() {
+ if [ $1 -eq $TB_ERR_TIMEOUT ]; then
+ printf '%s Test %s exceeded max runtime of %d seconds\n' "$(tb_timestamp)" "$0" $TB_TEST_MAX_RUNTIME
+ fi
+ if [ "$(ls core* 2>/dev/null)" != "" ]; then
+ echo trying to obtain crash location info
+ echo note: this may not be the correct file, check it
+ CORE=$(ls core*)
+ echo "bt" >> gdb.in
+ echo "q" >> gdb.in
+ gdb ../tools/rsyslogd $CORE -batch -x gdb.in
+ CORE=
+ rm gdb.in
+ fi
+ if [[ "$2" == 'stacktrace' || ( ! -e IN_AUTO_DEBUG && "$USE_AUTO_DEBUG" == 'on' ) ]]; then
+ if [ "$(ls core* 2>/dev/null)" != "" ]; then
+ CORE=$(ls core*)
+ printf 'trying to analyze core "%s" for main rsyslogd binary\n' "$CORE"
+ printf 'note: this may not be the correct file, check it\n'
+ $SUDO gdb ../tools/rsyslogd "$CORE" -batch <<- EOF
+ bt
+ echo === THREAD INFO ===
+ info thread
+ echo === thread apply all bt full ===
+ thread apply all bt full
+ q
+ EOF
+ $SUDO gdb ./tcpflood "$CORE" -batch <<- EOF
+ bt
+ echo === THREAD INFO ===
+ info thread
+ echo === thread apply all bt full ===
+ thread apply all bt full
+ q
+ EOF
+ fi
+ fi
+ if [[ ! -e IN_AUTO_DEBUG && "$USE_AUTO_DEBUG" == 'on' ]]; then
+ touch IN_AUTO_DEBUG
+ # OK, we have the testname and can re-run under valgrind
+ echo re-running under valgrind control
+ current_test="./$(basename $0)" # this path is probably wrong -- theinric
+ $current_test
+ # wait a little bit so that valgrind can finish
+ $TESTTOOL_DIR/msleep 4000
+ # next let's try us to get a debug log
+ RSYSLOG_DEBUG_SAVE=$RSYSLOG_DEBUG
+ export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction"
+ $current_test
+ $TESTTOOL_DIR/msleep 4000
+ RSYSLOG_DEBUG=$RSYSLOG_DEBUG_SAVE
+ rm IN_AUTO_DEBUG
+ fi
+ # output listening ports as a temporary debug measure (2018-09-08 rgerhards), now disables, but not yet removed (2018-10-22)
+ #if [ $(uname) == "Linux" ]; then
+ # netstat -tlp
+ #else
+ # netstat
+ #fi
+
+ # Extended debug output for dependencies started by testbench
+ if [ "$EXTRA_EXITCHECK" == 'dumpkafkalogs' ] && [ "$TEST_OUTPUT" == "VERBOSE" ]; then
+ # Dump Zookeeper log
+ dump_zookeeper_serverlog
+ # Dump Kafka log
+ dump_kafka_serverlog
+ fi
+
+ # Extended Exit handling for kafka / zookeeper instances
+ kafka_exit_handling "false"
+
+ # Ensure redis instance is stopped
+ if [ -n "$REDIS_DYN_DIR" ]; then
+ stop_redis
+ fi
+
+ error_stats $1 # Report error to rsyslog testbench stats
+ do_cleanup
+
+ exitval=$1
+ if [ "$TEST_STATUS" == "unreliable" ] && [ "$1" -ne 100 ]; then
+ # TODO: log github issue
+ printf 'Test flagged as unreliable, exiting with SKIP. Original exit code was %d\n' "$1"
+ printf 'GitHub ISSUE: %s\n' "$TEST_GITHUB_ISSUE"
+ exitval=77
+ else
+ if [ "$1" -eq 177 ]; then
+ exitval=77
+ fi
+ fi
+ printf '%s FAIL: Test %s (took %s seconds)\n' "$(tb_timestamp)" "$0" "$(( $(date +%s) - TB_STARTTEST ))"
+ if [ $exitval -ne 77 ]; then
+ echo $0 > testbench_test_failed_rsyslog
+ fi
+ exit $exitval
+}
+
+
+# skip a test; do cleanup when we detect it is necessary
+skip_test(){
+ do_cleanup
+ exit 77
+}
+
+
+# Helper function to call rsyslog project test error script
+# $1 is the exit code
+error_stats() {
+ if [ "$RSYSLOG_STATSURL" == "" ]; then
+ printf 'not reporting failure as RSYSLOG_STATSURL is not set\n'
+ else
+ echo reporting failure to $RSYSLOG_STATSURL
+ testname=$($PYTHON $srcdir/urlencode.py "$RSYSLOG_TESTNAME")
+ testenv=$($PYTHON $srcdir/urlencode.py "${VCS_SLUG:-$PWD}")
+ testmachine=$($PYTHON $srcdir/urlencode.py "$HOSTNAME")
+ logurl=$($PYTHON $srcdir/urlencode.py "${CI_BUILD_URL:-}")
+ wget -nv -O/dev/null $RSYSLOG_STATSURL\?Testname=$testname\&Testenv=$testenv\&Testmachine=$testmachine\&exitcode=${1:-1}\&logurl=$logurl\&rndstr=jnxv8i34u78fg23
+ fi
+}
+
+# do the usual sequence check to see if everything was properly received.
+# $4... are just to have the ability to pass in more options...
+# add -v to chkseq if you need more verbose output
+# argument --check-only can be used to simply do a check without abort in fail case
+# env var SEQ_CHECK_FILE permits to override file name to check
+# env var SEQ_CHECK_OPTIONS provide the ability to add extra options for check program
+seq_check() {
+ if [ "$SEQ_CHECK_FILE" == "" ]; then
+ SEQ_CHECK_FILE="$RSYSLOG_OUT_LOG"
+ fi
+ if [ "$1" == "--check-only" ]; then
+ check_only="YES"
+ shift
+ else
+ check_only="NO"
+ fi
+ if [ "$1" == "" ]; then
+ if [ "$NUMMESSAGES" == "" ]; then
+ printf 'FAIL: seq_check called without parameters but NUMMESSAGES is unset!\n'
+ error_exit 100
+ fi
+ # use default parameters
+ startnum=0
+ endnum=$(( NUMMESSAGES - 1 ))
+ else
+ startnum=$1
+ endnum=$2
+ fi
+ if [ ! -f "$SEQ_CHECK_FILE" ]; then
+ if [ "$check_only" == "YES" ]; then
+ return 1
+ fi
+ printf 'FAIL: %s does not exist in seq_check!\n' "$SEQ_CHECK_FILE"
+ error_exit 1
+ fi
+ if [ "${SEQ_CHECK_FILE##*.}" == "gz" ]; then
+ gunzip -c "${SEQ_CHECK_FILE}" | $RS_SORTCMD $RS_SORT_NUMERIC_OPT | ./chkseq -s$startnum -e$endnum $3 $4 $5 $6 $7 $SEQ_CHECK_OPTIONS
+ elif [ "${SEQ_CHECK_FILE##*.}" == "zst" ]; then
+ ls -l "${SEQ_CHECK_FILE}"
+ unzstd < "${SEQ_CHECK_FILE}" | $RS_SORTCMD $RS_SORT_NUMERIC_OPT | ./chkseq -s$startnum -e$endnum $3 $4 $5 $6 $7 $SEQ_CHECK_OPTIONS
+ else
+ $RS_SORTCMD $RS_SORT_NUMERIC_OPT < "${SEQ_CHECK_FILE}" | ./chkseq -s$startnum -e$endnum $3 $4 $5 $6 $7 $SEQ_CHECK_OPTIONS
+ fi
+ ret=$?
+ if [ "$check_only" == "YES" ]; then
+ return $ret
+ fi
+ if [ $ret -ne 0 ]; then
+ if [ "${SEQ_CHECK_FILE##*.}" == "gz" ]; then
+ gunzip -c "${SEQ_CHECK_FILE}" | $RS_SORTCMD $RS_SORT_NUMERIC_OPT \
+ | ./chkseq -s$startnum -e$endnum $3 $4 $5 $6 $7 $SEQ_CHECK_OPTIONS \
+ > $RSYSLOG_DYNNAME.error.log
+ elif [ "${SEQ_CHECK_FILE##*.}" == "zst" ]; then
+ unzstd < "${SEQ_CHECK_FILE}" | $RS_SORTCMD $RS_SORT_NUMERIC_OPT \
+ | ./chkseq -s$startnum -e$endnum $3 $4 $5 $6 $7 $SEQ_CHECK_OPTIONS \
+ > $RSYSLOG_DYNNAME.error.log
+ else
+ $RS_SORTCMD $RS_SORT_NUMERIC_OPT < ${SEQ_CHECK_FILE} \
+ > $RSYSLOG_DYNNAME.error.log
+ fi
+ echo "sequence error detected in $SEQ_CHECK_FILE"
+ echo "number of lines in file: $(wc -l $SEQ_CHECK_FILE)"
+ echo "sorted data has been placed in error.log, first 10 lines are:"
+ cat -n "$RSYSLOG_DYNNAME.error.log" | head -10
+ echo "---last 10 lines are:"
+ cat -n "$RSYSLOG_DYNNAME.error.log" | tail -10
+ echo "UNSORTED data, first 10 lines are:"
+ cat -n "$RSYSLOG_DYNNAME.error.log" | head -10
+ echo "---last 10 lines are:"
+ cat -n "$RSYSLOG_DYNNAME.error.log" | tail -10
+ # for interactive testing, create a static filename. We know this may get
+ # mangled during a parallel test run
+ mv -f $RSYSLOG_DYNNAME.error.log error.log
+ error_exit 1
+ fi
+ return 0
+}
+
+
+# do the usual sequence check to see if everything was properly received. This is
+# a duplicateof seq-check, but we could not change its calling conventions without
+# breaking a lot of exitings test cases, so we preferred to duplicate the code here.
+# $4... are just to have the ability to pass in more options...
+# add -v to chkseq if you need more verbose output
+seq_check2() {
+ $RS_SORTCMD $RS_SORT_NUMERIC_OPT < ${RSYSLOG2_OUT_LOG} | ./chkseq -s$1 -e$2 $3 $4 $5 $6 $7
+ if [ "$?" -ne "0" ]; then
+ echo "sequence error detected"
+ error_exit 1
+ fi
+}
+
+
+# do the usual sequence check, but for gzip files
+# $4... are just to have the ability to pass in more options...
+gzip_seq_check() {
+ if [ "$1" == "" ]; then
+ if [ "$NUMMESSAGES" == "" ]; then
+ printf 'FAIL: gzip_seq_check called without parameters but NUMMESSAGES is unset!\n'
+ error_exit 100
+ fi
+ # use default parameters
+ startnum=0
+ endnum=$(( NUMMESSAGES - 1 ))
+ else
+ startnum=$1
+ endnum=$2
+ fi
+ ls -l ${RSYSLOG_OUT_LOG}
+ gunzip < ${RSYSLOG_OUT_LOG} | $RS_SORTCMD $RS_SORT_NUMERIC_OPT | ./chkseq -v -s$startnum -e$endnum $3 $4 $5 $6 $7
+ if [ "$?" -ne "0" ]; then
+ echo "sequence error detected"
+ error_exit 1
+ fi
+}
+
+
+# do a tcpflood run and check if it worked params are passed to tcpflood
+tcpflood() {
+ if [ "$1" == "--check-only" ]; then
+ check_only="yes"
+ shift
+ else
+ check_only="no"
+ fi
+ eval ./tcpflood -p$TCPFLOOD_PORT "$@" $TCPFLOOD_EXTRA_OPTS
+ res=$?
+ if [ "$check_only" == "yes" ]; then
+ if [ "$res" -ne "0" ]; then
+ echo "error during tcpflood on port ${TCPFLOOD_PORT}! But test continues..."
+ fi
+ return 0
+ else
+ if [ "$res" -ne "0" ]; then
+ echo "error during tcpflood on port ${TCPFLOOD_PORT}! see ${RSYSLOG_OUT_LOG}.save for what was written"
+ cp ${RSYSLOG_OUT_LOG} ${RSYSLOG_OUT_LOG}.save
+ error_exit 1 stacktrace
+ fi
+ fi
+}
+
+
+# cleanup
+# detect any left-over hanging instance
+exit_test() {
+ nhanging=0
+ #for pid in $(ps -eo pid,args|grep '/tools/[r]syslogd ' |sed -e 's/\( *\)\([0-9]*\).*/\2/');
+ #do
+ #echo "ERROR: left-over instance $pid, killing it"
+ # ps -fp $pid
+ # pwd
+ # printf "we do NOT kill the instance as this does not work with multiple\n"
+ # printf "builds per machine - this message is now informational to show prob exists!\n"
+ # #kill -9 $pid
+ # let "nhanging++"
+ #done
+ if test $nhanging -ne 0
+ then
+ echo "ABORT! hanging instances left at exit"
+ #error_exit 1
+ #exit 77 # for now, just skip - TODO: reconsider when supporting -j
+ fi
+ # now real cleanup
+ rm -f rsyslog.action.*.include
+ rm -f work rsyslog.out.* xlate*.lkp_tbl
+ rm -rf test-logdir stat-file1
+ rm -f rsyslog.conf.tlscert stat-file1 rsyslog.empty imfile-state:*
+ rm -f ${TESTCONF_NM}.conf
+ rm -f tmp.qi nocert
+ rm -fr $RSYSLOG_DYNNAME* # delete all of our dynamic files
+ unset TCPFLOOD_EXTRA_OPTS
+
+ # Extended Exit handling for kafka / zookeeper instances
+ kafka_exit_handling "true"
+
+ # Ensure redis is stopped
+ stop_redis
+
+ printf '%s Test %s SUCCESSFUL (took %s seconds)\n' "$(tb_timestamp)" "$0" "$(( $(date +%s) - TB_STARTTEST ))"
+ echo -------------------------------------------------------------------------------
+ exit 0
+}
+
+# finds a free port that we can bind a listener to
+# Obviously, any solution is race as another process could start
+# just after us and grab the same port. However, in practice it seems
+# to work pretty well. In any case, we should probably call this as
+# late as possible before the usage of the port.
+get_free_port() {
+$PYTHON -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
+}
+
+
+# return the inode number of file $1; file MUST exist
+get_inode() {
+ if [ ! -f "$1" ]; then
+ printf 'FAIL: file "%s" does not exist in get_inode\n' "$1"
+ error_exit 100
+ fi
+ $PYTHON -c 'import os; import stat; print(os.lstat("'$1'")[stat.ST_INO])'
+}
+
+
+# check that logger supports -d option, if not skip test
+# right now this is a bit dirty, we check distros which do not support it
+check_logger_has_option_d() {
+ skip_platform "FreeBSD" "We need logger -d option, which we do not have on FreeBSD"
+ skip_platform "SunOS" "We need logger -d option, which we do not have on (all flavors of) Solaris"
+
+ # check also the case for busybox
+ logger --help 2>&1 | head -n1 | grep -q BusyBox
+ if [ $? -eq 0 ]; then
+ echo "We need logger -d option, which we do not have have on Busybox"
+ exit 77
+ fi
+}
+
+
+require_relpEngineSetTLSLibByName() {
+ ./have_relpEngineSetTLSLibByName
+ if [ $? -eq 1 ]; then
+ echo "relpEngineSetTLSLibByName API not available. Test stopped"
+ exit 77
+ fi;
+}
+
+require_relpEngineVersion() {
+ if [ "$1" == "" ]; then
+ echo "require_relpEngineVersion missing required parameter (minimum version required)"
+ exit 1
+ else
+ ./check_relpEngineVersion $1
+ if [ $? -eq 1 ]; then
+ echo "relpEngineVersion too OLD. Test stopped"
+ exit 77
+ fi;
+ fi
+}
+
+
+# check if command $1 is available - will exit 77 when not OK
+check_command_available() {
+ have_cmd=0
+ if [ "$1" == "timeout" ]; then
+ if timeout --version &>/dev/null ; then
+ have_cmd=1
+ fi
+ else
+ command -v $1
+ if [ $? -eq 0 ]; then
+ have_cmd=1
+ fi
+ fi
+ if [ $have_cmd -eq 0 ] ; then
+ printf 'Testbench requires unavailable command: %s\n' "$1"
+ exit 77 # do NOT error_exit here!
+ fi
+}
+
+
+# sort the output file just like we normally do it, but do not call
+# seqchk. This is needed for some operations where we need the sort
+# result for some preprocessing. Note that a later seqchk will sort
+# again, but that's not an issue.
+presort() {
+ rm -f $RSYSLOG_DYNNAME.presort
+ $RS_SORTCMD $RS_SORT_NUMERIC_OPT < ${RSYSLOG_OUT_LOG} > $RSYSLOG_DYNNAME.presort
+}
+
+
+#START: ext kafka config
+#dep_cache_dir=$(readlink -f .dep_cache)
+export RS_ZK_DOWNLOAD=apache-zookeeper-3.9.1-bin.tar.gz
+dep_cache_dir=$(pwd)/.dep_cache
+dep_zk_url=https://downloads.apache.org/zookeeper/zookeeper-3.9.1/$RS_ZK_DOWNLOAD
+dep_zk_cached_file=$dep_cache_dir/$RS_ZK_DOWNLOAD
+
+export RS_KAFKA_DOWNLOAD=kafka_2.13-2.8.0.tgz
+dep_kafka_url="https://www.rsyslog.com/files/download/rsyslog/$RS_KAFKA_DOWNLOAD"
+dep_kafka_cached_file=$dep_cache_dir/$RS_KAFKA_DOWNLOAD
+
+if [ -z "$ES_DOWNLOAD" ]; then
+ export ES_DOWNLOAD=elasticsearch-7.14.1-linux-x86_64.tar.gz
+fi
+if [ -z "$ES_PORT" ]; then
+ export ES_PORT=19200
+fi
+dep_es_cached_file="$dep_cache_dir/$ES_DOWNLOAD"
+
+# kafka (including Zookeeper)
+dep_kafka_dir_xform_pattern='s#^[^/]\+#kafka#g'
+dep_zk_dir_xform_pattern='s#^[^/]\+#zk#g'
+dep_es_dir_xform_pattern='s#^[^/]\+#es#g'
+#dep_kafka_log_dump=$(readlink -f rsyslog.out.kafka.log)
+
+# TODO Make dynamic work dir for multiple instances
+#dep_work_dir=$(readlink -f .dep_wrk)
+dep_work_dir=$(pwd)/.dep_wrk
+#dep_kafka_work_dir=$dep_work_dir/kafka
+#dep_zk_work_dir=$dep_work_dir/zk
+
+#END: ext kafka config
+
+kafka_exit_handling() {
+
+ # Extended Exit handling for kafka / zookeeper instances
+ if [[ "$EXTRA_EXIT" == 'kafka' ]]; then
+
+ echo "stop kafka instance"
+ stop_kafka '.dep_wrk' $1
+
+ echo "stop zookeeper instance"
+ stop_zookeeper '.dep_wrk' $1
+ fi
+
+ # Extended Exit handling for kafka / zookeeper instances
+ if [[ "$EXTRA_EXIT" == 'kafkamulti' ]]; then
+ echo "stop kafka instances"
+ stop_kafka '.dep_wrk1' $1
+ stop_kafka '.dep_wrk2' $1
+ stop_kafka '.dep_wrk3' $1
+
+ echo "stop zookeeper instances"
+ stop_zookeeper '.dep_wrk1' $1
+ stop_zookeeper '.dep_wrk2' $1
+ stop_zookeeper '.dep_wrk3' $1
+ fi
+}
+
+download_kafka() {
+ if [ ! -d $dep_cache_dir ]; then
+ echo "Creating dependency cache dir $dep_cache_dir"
+ mkdir $dep_cache_dir
+ fi
+ if [ ! -f $dep_zk_cached_file ]; then
+ if [ -f /local_dep_cache/$RS_ZK_DOWNLOAD ]; then
+ printf 'Zookeeper: satisfying dependency %s from system cache.\n' "$RS_ZK_DOWNLOAD"
+ cp /local_dep_cache/$RS_ZK_DOWNLOAD $dep_zk_cached_file
+ else
+ echo "Downloading zookeeper"
+ echo wget -q $dep_zk_url -O $dep_zk_cached_file
+ wget -q $dep_zk_url -O $dep_zk_cached_file
+ if [ $? -ne 0 ]
+ then
+ echo error during wget, retry:
+ wget $dep_zk_url -O $dep_zk_cached_file
+ if [ $? -ne 0 ]
+ then
+ error_exit 1
+ fi
+ fi
+ fi
+ fi
+ if [ ! -f $dep_kafka_cached_file ]; then
+ if [ -f /local_dep_cache/$RS_KAFKA_DOWNLOAD ]; then
+ printf 'Kafka: satisfying dependency %s from system cache.\n' "$RS_KAFKA_DOWNLOAD"
+ cp /local_dep_cache/$RS_KAFKA_DOWNLOAD $dep_kafka_cached_file
+ else
+ echo "Downloading kafka"
+ wget -q $dep_kafka_url -O $dep_kafka_cached_file
+ if [ $? -ne 0 ]
+ then
+ echo error during wget, retry:
+ wget $dep_kafka_url -O $dep_kafka_cached_file
+ if [ $? -ne 0 ]
+ then
+ rm $dep_kafka_cached_file # a 0-size file may be left over
+ error_exit 1
+ fi
+ fi
+ fi
+ fi
+}
+
+stop_kafka() {
+ if [ "$KEEP_KAFKA_RUNNING" == "YES" ]; then
+ return
+ fi
+ i=0
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_kafka_config="kafka-server.properties"
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ if [[ ".dep_wrk" != "$1" ]]; then
+ dep_work_kafka_config="kafka-server$1.properties"
+ else
+ dep_work_kafka_config="kafka-server.properties"
+ fi
+ fi
+ if [ ! -d $dep_work_dir/kafka ]; then
+ echo "Kafka work-dir $dep_work_dir/kafka does not exist, no action needed"
+ else
+ # shellcheck disable=SC2009 - we do not grep on the process name!
+ kafkapid=$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')
+
+ echo "Stopping Kafka instance $1 ($dep_work_kafka_config/$kafkapid)"
+ kill $kafkapid
+
+ # Check if kafka instance went down!
+ while true; do
+ # shellcheck disable=SC2009 - we do not grep on the process name!
+ kafkapid=$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')
+ if [[ "" != "$kafkapid" ]]; then
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if test $i -gt $TB_TIMEOUT_STARTSTOP; then
+ echo "Kafka instance $dep_work_kafka_config (PID $kafkapid) still running - Performing hard shutdown (-9)"
+ kill -9 $kafkapid
+ break
+ fi
+ (( i++ ))
+ else
+ # Break the loop
+ break
+ fi
+ done
+
+ if [[ "$2" == 'true' ]]; then
+ # Process shutdown, do cleanup now
+ cleanup_kafka $1
+ fi
+ fi
+}
+
+cleanup_kafka() {
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ fi
+ if [ ! -d $dep_work_dir/kafka ]; then
+ echo "Kafka work-dir $dep_work_dir/kafka does not exist, no action needed"
+ else
+ echo "Cleanup Kafka instance $1"
+ rm -rf $dep_work_dir/kafka
+ fi
+}
+
+stop_zookeeper() {
+ if [ "$KEEP_KAFKA_RUNNING" == "YES" ]; then
+ return
+ fi
+ i=0
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_tk_config="zoo.cfg"
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ if [[ ".dep_wrk" != "$1" ]]; then
+ dep_work_tk_config="zoo$1.cfg"
+ else
+ dep_work_tk_config="zoo.cfg"
+ fi
+ fi
+
+ if [ ! -d $dep_work_dir/zk ]; then
+ echo "Zookeeper work-dir $dep_work_dir/zk does not exist, no action needed"
+ else
+ # Get Zookeeper pid instance
+ zkpid=$(ps aux | grep -i $dep_work_tk_config | grep java | grep -v grep | awk '{print $2}')
+ echo "Stopping Zookeeper instance $1 ($dep_work_tk_config/$zkpid)"
+ kill $zkpid
+
+ # Check if Zookeeper instance went down!
+ zkpid=$(ps aux | grep -i $dep_work_tk_config | grep java | grep -v grep | awk '{print $2}')
+ if [[ "" != "$zkpid" ]]; then
+ while true; do
+ zkpid=$(ps aux | grep -i $dep_work_tk_config | grep java | grep -v grep | awk '{print $2}')
+ if [[ "" != "$zkpid" ]]; then
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if test $i -gt $TB_TIMEOUT_STARTSTOP; then
+ echo "Zookeeper instance $dep_work_tk_config (PID $zkpid) still running - Performing hard shutdown (-9)"
+ kill -9 $zkpid
+ break
+ fi
+ (( i++ ))
+ else
+ break
+ fi
+ done
+ fi
+
+ if [[ "$2" == 'true' ]]; then
+ # Process shutdown, do cleanup now
+ cleanup_zookeeper $1
+ fi
+ rm "$ZOOPIDFILE"
+ fi
+}
+
+cleanup_zookeeper() {
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ fi
+ rm -rf $dep_work_dir/zk
+}
+
+start_zookeeper() {
+ if [ "$KEEP_KAFKA_RUNNING" == "YES" ] && [ -f "$ZOOPIDFILE" ]; then
+ if kill -0 "$(cat "$ZOOPIDFILE")"; then
+ printf 'zookeeper already running, no need to start\n'
+ return
+ else
+ printf 'INFO: zookeeper pidfile %s exists, but zookeeper not running\n' "$ZOOPIDFILE"
+ printf 'deleting pid file\n'
+ rm -f "$ZOOPIDFILE"
+ fi
+ fi
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_tk_config="zoo.cfg"
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ dep_work_tk_config="zoo$1.cfg"
+ fi
+
+ if [ ! -f $dep_zk_cached_file ]; then
+ echo "Dependency-cache does not have zookeeper package, did you download dependencies?"
+ error_exit 77
+ fi
+ if [ ! -d $dep_work_dir ]; then
+ echo "Creating dependency working directory"
+ mkdir -p $dep_work_dir
+ fi
+ if [ -d $dep_work_dir/zk ]; then
+ (cd $dep_work_dir/zk && ./bin/zkServer.sh stop)
+ $TESTTOOL_DIR/msleep 2000
+ fi
+ rm -rf $dep_work_dir/zk
+ (cd $dep_work_dir && tar -zxvf $dep_zk_cached_file --xform $dep_zk_dir_xform_pattern --show-transformed-names) > /dev/null
+ cp -f $srcdir/testsuites/$dep_work_tk_config $dep_work_dir/zk/conf/zoo.cfg
+ echo "Starting Zookeeper instance $1"
+ (cd $dep_work_dir/zk && ./bin/zkServer.sh start)
+ wait_startup_pid "$ZOOPIDFILE"
+}
+
+start_kafka() {
+ printf '%s starting kafka\n' "$(tb_timestamp)"
+
+ # Force IPv4 usage of Kafka!
+ export KAFKA_HEAP_OPTS="-Xms256m -Xmx256m" # we need to take care for smaller CI systems!
+ export KAFKA_OPTS="-Djava.net.preferIPv4Stack=True"
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_kafka_config="kafka-server.properties"
+ else
+ dep_work_dir=$(readlink -f $1)
+ dep_work_kafka_config="kafka-server$1.properties"
+ fi
+
+ # shellcheck disable=SC2009 - we do not grep on the process name!
+ kafkapid=$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')
+ if [ "$KEEP_KAFKA_RUNNING" == "YES" ] && [ "$kafkapid" != "" ]; then
+ printf 'kafka already running, no need to start\n'
+ return
+ fi
+
+ if [ ! -f $dep_kafka_cached_file ]; then
+ echo "Dependency-cache does not have kafka package, did you download dependencies?"
+ error_exit 77
+ fi
+ if [ ! -d $dep_work_dir ]; then
+ echo "Creating dependency working directory"
+ mkdir -p $dep_work_dir
+ fi
+ rm -rf $dep_work_dir/kafka
+ ( cd $dep_work_dir &&
+ tar -zxvf $dep_kafka_cached_file --xform $dep_kafka_dir_xform_pattern --show-transformed-names) > /dev/null
+ cp -f $srcdir/testsuites/$dep_work_kafka_config $dep_work_dir/kafka/config/
+ #if [ "$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')" != "" ]; then
+ echo "Starting Kafka instance $dep_work_kafka_config"
+ (cd $dep_work_dir/kafka && ./bin/kafka-server-start.sh -daemon ./config/$dep_work_kafka_config)
+ $TESTTOOL_DIR/msleep 4000
+
+ # Check if kafka instance came up!
+ # shellcheck disable=SC2009 - we do not grep on the process name!
+ kafkapid=$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')
+ if [[ "" != "$kafkapid" ]];
+ then
+ echo "Kafka instance $dep_work_kafka_config (PID $kafkapid) started ... "
+ else
+ echo "Starting Kafka instance $dep_work_kafka_config, SECOND ATTEMPT!"
+ (cd $dep_work_dir/kafka && ./bin/kafka-server-start.sh -daemon ./config/$dep_work_kafka_config)
+ $TESTTOOL_DIR/msleep 4000
+
+ # shellcheck disable=SC2009 - we do not grep on the process name!
+ kafkapid=$(ps aux | grep -i $dep_work_kafka_config | grep java | grep -v grep | awk '{print $2}')
+ if [[ "" != "$kafkapid" ]];
+ then
+ echo "Kafka instance $dep_work_kafka_config (PID $kafkapid) started ... "
+ else
+ echo "Failed to start Kafka instance for $dep_work_kafka_config"
+ echo "displaying all kafka logs now:"
+ for logfile in $dep_work_dir/logs/*; do
+ echo "FILE: $logfile"
+ cat $logfile
+ done
+ error_exit 77
+ fi
+ fi
+}
+
+create_kafka_topic() {
+ if [ "x$2" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $2)
+ fi
+ if [ "x$3" == "x" ]; then
+ dep_work_port='2181'
+ else
+ dep_work_port=$3
+ fi
+ if [ ! -d $dep_work_dir/kafka ]; then
+ echo "Kafka work-dir $dep_work_dir/kafka does not exist, did you start kafka?"
+ exit 1
+ fi
+ if [ "x$1" == "x" ]; then
+ echo "Topic-name not provided."
+ exit 1
+ fi
+
+ # we need to make sure replication has is working. So let's loop until no more
+ # errors (or timeout) - see also: https://github.com/rsyslog/rsyslog/issues/3045
+ timeout_ready=100 # roughly 10 sec
+ is_retry=0
+ i=0
+ while true; do
+ text=$(cd $dep_work_dir/kafka && ./bin/kafka-topics.sh --zookeeper localhost:$dep_work_port/kafka --create --topic $1 --replication-factor 1 --partitions 2 )
+ grep "Error.* larger than available brokers: 0" <<<"$text"
+ res=$?
+ if [ $res -ne 0 ]; then
+ echo looks like brokers are available - continue...
+ break
+ fi
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ (( i++ ))
+ if test $i -gt $timeout_ready; then
+ echo "ENV ERROR: kafka brokers did not come up:"
+ cat -n <<< $text
+ if [ $is_retry == 1 ]; then
+ echo "SKIPing test as the env is not ready for it"
+ exit 177
+ fi
+ echo "RETRYING kafka startup, doing shutdown and startup"
+ stop_zookeeper ""; stop_kafka ""
+ start_zookeeper ""; start_kafka ""
+ echo "READY for RETRY"
+ is_retry=1
+ i=0
+ fi
+ done
+
+ # we *assume* now all goes well
+ (cd $dep_work_dir/kafka && ./bin/kafka-topics.sh --zookeeper localhost:$dep_work_port/kafka --alter --topic $1 --delete-config retention.ms)
+ (cd $dep_work_dir/kafka && ./bin/kafka-topics.sh --zookeeper localhost:$dep_work_port/kafka --alter --topic $1 --delete-config retention.bytes)
+}
+
+delete_kafka_topic() {
+ if [ "x$2" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$2)
+ fi
+ if [ "x$3" == "x" ]; then
+ dep_work_port='2181'
+ else
+ dep_work_port=$3
+ fi
+
+ echo "deleting kafka-topic $1"
+ (cd $dep_work_dir/kafka && ./bin/kafka-topics.sh --delete --zookeeper localhost:$dep_work_port/kafka --topic $1)
+}
+
+dump_kafka_topic() {
+ if [ "x$2" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_kafka_log_dump=$(readlink -f rsyslog.out.kafka.log)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$2)
+ dep_kafka_log_dump=$(readlink -f rsyslog.out.kafka$2.log)
+ fi
+ if [ "x$3" == "x" ]; then
+ dep_work_port='2181'
+ else
+ dep_work_port=$3
+ fi
+
+ echo "dumping kafka-topic $1"
+ if [ ! -d $dep_work_dir/kafka ]; then
+ echo "Kafka work-dir does not exist, did you start kafka?"
+ exit 1
+ fi
+ if [ "x$1" == "x" ]; then
+ echo "Topic-name not provided."
+ exit 1
+ fi
+
+ (cd $dep_work_dir/kafka && ./bin/kafka-console-consumer.sh --timeout-ms 2000 --from-beginning --zookeeper localhost:$dep_work_port/kafka --topic $1 > $dep_kafka_log_dump)
+}
+
+dump_kafka_serverlog() {
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ fi
+ if [ ! -d $dep_work_dir/kafka ]; then
+ echo "Kafka work-dir $dep_work_dir/kafka does not exist, no kafka debuglog"
+ else
+ echo "Dumping server.log from Kafka instance $1"
+ echo "========================================="
+ cat $dep_work_dir/kafka/logs/server.log
+ echo "========================================="
+ printf 'non-info is:\n'
+ grep --invert-match '^\[.* INFO ' $dep_work_dir/kafka/logs/server.log | grep '^\['
+ fi
+}
+
+dump_zookeeper_serverlog() {
+ if [ "x$1" == "x" ]; then
+ dep_work_dir=$(readlink -f .dep_wrk)
+ else
+ dep_work_dir=$(readlink -f $srcdir/$1)
+ fi
+ echo "Dumping zookeeper.out from Zookeeper instance $1"
+ echo "========================================="
+ cat $dep_work_dir/zk/zookeeper.out
+ echo "========================================="
+ printf 'non-info is:\n'
+ grep --invert-match '^\[.* INFO ' $dep_work_dir/zk/zookeeper.out | grep '^\['
+}
+
+
+# download elasticsearch files, if necessary
+download_elasticsearch() {
+ if [ ! -d $dep_cache_dir ]; then
+ echo "Creating dependency cache dir $dep_cache_dir"
+ mkdir $dep_cache_dir
+ fi
+ if [ ! -f $dep_es_cached_file ]; then
+ if [ -f /local_dep_cache/$ES_DOWNLOAD ]; then
+ printf 'ElasticSearch: satisfying dependency %s from system cache.\n' "$ES_DOWNLOAD"
+ cp /local_dep_cache/$ES_DOWNLOAD $dep_es_cached_file
+ else
+ dep_es_url="https://www.rsyslog.com/files/download/rsyslog/$ES_DOWNLOAD"
+ printf 'ElasticSearch: satisfying dependency %s from %s\n' "$ES_DOWNLOAD" "$dep_es_url"
+ wget -q $dep_es_url -O $dep_es_cached_file
+ fi
+ fi
+}
+
+
+# prepare elasticsearch execution environment
+# this also stops any previous elasticsearch instance, if found
+prepare_elasticsearch() {
+ stop_elasticsearch # stop if it is still running
+ # Heap Size (limit to 128MB for testbench! default is way to HIGH)
+ export ES_JAVA_OPTS="-Xms128m -Xmx128m"
+
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_es_config="es.yml"
+ dep_work_es_pidfile="es.pid"
+
+ if [ ! -f $dep_es_cached_file ]; then
+ echo "Dependency-cache does not have elasticsearch package, did "
+ echo "you download dependencies?"
+ error_exit 100
+ fi
+ if [ ! -d $dep_work_dir ]; then
+ echo "Creating dependency working directory"
+ mkdir -p $dep_work_dir
+ fi
+ if [ -d $dep_work_dir/es ]; then
+ if [ -e $dep_work_es_pidfile ]; then
+ es_pid=$(cat $dep_work_es_pidfile)
+ kill -SIGTERM $es_pid
+ wait_pid_termination $es_pid
+ fi
+ fi
+ rm -rf $dep_work_dir/es
+ echo TEST USES ELASTICSEARCH BINARY $dep_es_cached_file
+ (cd $dep_work_dir && tar -zxf $dep_es_cached_file --xform $dep_es_dir_xform_pattern --show-transformed-names) > /dev/null
+ if [ -n "${ES_PORT:-}" ] ; then
+ rm -f $dep_work_dir/es/config/elasticsearch.yml
+ sed "s/^http.port:.*\$/http.port: ${ES_PORT}/" $srcdir/testsuites/$dep_work_es_config > $dep_work_dir/es/config/elasticsearch.yml
+ if [ "$ES_DOWNLOAD" != "elasticsearch-6.0.0.tar.gz" ]; then
+ printf 'xpack.security.enabled: false\n' >> $dep_work_dir/es/config/elasticsearch.yml
+ fi
+ else
+ cp -f $srcdir/testsuites/$dep_work_es_config $dep_work_dir/es/config/elasticsearch.yml
+ fi
+
+ # Avoid deprecated parameter, new option introduced with 6.7
+ echo "Setting transport tcp option to ${ES_PORT_OPTION:-transport.tcp.port}"
+ sed -i "s/transport.tcp.port/${ES_PORT_OPTION:-transport.tcp.port}/g" "$dep_work_dir/es/config/elasticsearch.yml"
+
+ if [ ! -d $dep_work_dir/es/data ]; then
+ echo "Creating elastic search directories"
+ mkdir -p $dep_work_dir/es/data
+ mkdir -p $dep_work_dir/es/logs
+ mkdir -p $dep_work_dir/es/tmp
+ fi
+ echo ElasticSearch prepared for use in test.
+}
+
+
+# ensure that a basic, suitable instance of elasticsearch is running. This is part
+# of an effort to avoid restarting elasticsearch more often than necessary.
+ensure_elasticsearch_ready() {
+ if printf '%s:%s:%s\n' "$ES_DOWNLOAD" "$ES_PORT" "$(cat es.pid)" \
+ | cmp -b - elasticsearch.running
+ then
+ printf 'Elasticsearch already running, NOT restarting it\n'
+ else
+ cat elasticsearch.running
+ cleanup_elasticsearch
+ dep_es_cached_file="$dep_cache_dir/$ES_DOWNLOAD"
+ download_elasticsearch
+ prepare_elasticsearch
+ if [ "$1" != "--no-start" ]; then
+ start_elasticsearch
+ printf '%s:%s:%s\n' "$ES_DOWNLOAD" "$ES_PORT" "$(cat es.pid)" > elasticsearch.running
+ fi
+ fi
+ if [ "$1" != "--no-start" ]; then
+ printf 'running elasticsearch instance: %s\n' "$(cat elasticsearch.running)"
+ init_elasticsearch
+ fi
+}
+
+
+# $2, if set, is the number of additional ES instances
+start_elasticsearch() {
+ # Heap Size (limit to 256MB for testbench! defaults is way to HIGH)
+ export ES_JAVA_OPTS="-Xms256m -Xmx256m"
+
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_es_config="es.yml"
+ dep_work_es_pidfile="$(pwd)/es.pid"
+ echo "Starting ElasticSearch"
+
+ # THIS IS THE ACTUAL START of ES
+ $dep_work_dir/es/bin/elasticsearch -p $dep_work_es_pidfile -d
+ $TESTTOOL_DIR/msleep 2000
+ wait_startup_pid $dep_work_es_pidfile
+ printf 'elasticsearch pid is %s\n' "$(cat $dep_work_es_pidfile)"
+
+ # Wait for startup with hardcoded timeout
+ timeoutend=120
+ timeseconds=0
+ # Loop until elasticsearch port is reachable or until
+ # timeout is reached!
+ until [ "$(curl --silent --show-error --connect-timeout 1 http://localhost:${ES_PORT:-19200} | grep 'rsyslog-testbench')" != "" ]; do
+ echo "--- waiting for ES startup: $timeseconds seconds"
+ $TESTTOOL_DIR/msleep 1000
+ (( timeseconds=timeseconds + 1 ))
+
+ if [ "$timeseconds" -gt "$timeoutend" ]; then
+ echo "--- TIMEOUT ( $timeseconds ) reached!!!"
+ if [ ! -d $dep_work_dir/es ]; then
+ echo "ElasticSearch $dep_work_dir/es does not exist, no ElasticSearch debuglog"
+ else
+ echo "Dumping rsyslog-testbench.log from ElasticSearch instance $1"
+ echo "========================================="
+ cat $dep_work_dir/es/logs/rsyslog-testbench.log
+ echo "========================================="
+# printf 'non-info is:\n'
+# grep --invert-match '^\[.* INFO ' $dep_work_dir/kafka/logs/server.log | grep '^\['
+ fi
+ error_exit 1
+ fi
+ done
+ $TESTTOOL_DIR/msleep 2000
+ echo ES startup succeeded
+}
+
+# read data from ES to a local file so that we can process
+# $1 - number of records (ES does not return all records unless you tell it explicitly).
+# $2 - ES port
+es_getdata() {
+ curl --silent -XPUT --show-error -H 'Content-Type: application/json' "http://localhost:${2:-$ES_PORT}/rsyslog_testbench/_settings" -d '{ "index" : { "max_result_window" : '${1:-$NUMMESSAGES}' } }'
+ # refresh to ensure we get the latest data
+ curl --silent localhost:${2:-$ES_PORT}/rsyslog_testbench/_refresh
+ curl --silent localhost:${2:-$ES_PORT}/rsyslog_testbench/_search?size=${1:-$NUMMESSAGES} > $RSYSLOG_DYNNAME.work
+ $PYTHON $srcdir/es_response_get_msgnum.py > ${RSYSLOG_OUT_LOG}
+}
+
+# a standard method to support shutdown & queue empty check for a wide range
+# of elasticsearch tests. This works if we assume that ES has delivered messages
+# to the default location.
+es_shutdown_empty_check() {
+ es_getdata $NUMMESSAGES $ES_PORT
+ lines=$(wc -l < "$RSYSLOG_OUT_LOG")
+ if [ "$lines" -eq $NUMMESSAGES ]; then
+ printf '%s es_shutdown_empty_check: success, have %d lines\n' "$(tb_timestamp)" $lines
+ return 0
+ fi
+ printf '%s es_shutdown_empty_check: have %d lines, expecting %d\n' "$(tb_timestamp)" $lines $NUMMESSAGES
+ return 1
+}
+
+
+stop_elasticsearch() {
+ dep_work_dir=$(readlink -f $srcdir)
+ dep_work_es_pidfile="es.pid"
+ rm elasticsearch.running
+ if [ -e $dep_work_es_pidfile ]; then
+ es_pid=$(cat $dep_work_es_pidfile)
+ printf 'stopping ES with pid %d\n' $es_pid
+ kill -SIGTERM $es_pid
+ wait_pid_termination $es_pid
+ fi
+}
+
+# cleanup es leftovers when it is being stopped
+cleanup_elasticsearch() {
+ dep_work_dir=$(readlink -f .dep_wrk)
+ dep_work_es_pidfile="es.pid"
+ stop_elasticsearch
+ rm -f $dep_work_es_pidfile
+ rm -rf $dep_work_dir/es
+}
+
+# initialize local Elasticsearch *testbench* instance for the next
+# test. NOTE: do NOT put anything useful on that instance!
+init_elasticsearch() {
+ curl --silent -XDELETE localhost:${ES_PORT:-9200}/rsyslog_testbench
+}
+
+omhttp_start_server() {
+ # Args: 1=port 2=server args
+ # Args 2 and up are passed along as is to omhttp_server.py
+ omhttp_server_py=$srcdir/omhttp_server.py
+ if [ ! -f $omhttp_server_py ]; then
+ echo "Cannot find ${omhttp_server_py} for omhttp test"
+ error_exit 1
+ fi
+
+ if [ "x$1" == "x" ]; then
+ omhttp_server_port="8080"
+ else
+ omhttp_server_port="$1"
+ fi
+
+ # Create work directory for parallel tests
+ omhttp_work_dir=$RSYSLOG_DYNNAME/omhttp
+
+ omhttp_server_pidfile="${omhttp_work_dir}/omhttp_server.pid"
+ omhttp_server_logfile="${omhttp_work_dir}/omhttp_server.log"
+ mkdir -p ${omhttp_work_dir}
+
+ server_args="-p $omhttp_server_port ${*:2} --port-file $RSYSLOG_DYNNAME.omhttp_server_lstnport.file"
+
+ timeout 30m $PYTHON ${omhttp_server_py} ${server_args} >> ${omhttp_server_logfile} 2>&1 &
+ if [ ! $? -eq 0 ]; then
+ echo "Failed to start omhttp test server."
+ rm -rf $omhttp_work_dir
+ error_exit 1
+ fi
+ omhttp_server_pid=$!
+
+ wait_file_exists "$RSYSLOG_DYNNAME.omhttp_server_lstnport.file"
+ omhttp_server_lstnport="$(cat $RSYSLOG_DYNNAME.omhttp_server_lstnport.file)"
+ echo ${omhttp_server_pid} > ${omhttp_server_pidfile}
+ echo "Started omhttp test server with args ${server_args} with pid ${omhttp_server_pid}, port {$omhttp_server_lstnport}"
+}
+
+omhttp_stop_server() {
+ # Args: None
+ omhttp_work_dir=$RSYSLOG_DYNNAME/omhttp
+ if [ ! -d $omhttp_work_dir ]; then
+ echo "omhttp server $omhttp_work_dir does not exist, no action needed"
+ else
+ echo "Stopping omhttp server"
+ kill -9 $(cat ${omhttp_work_dir}/omhttp_server.pid) > /dev/null 2>&1
+ rm -rf $omhttp_work_dir
+ fi
+}
+
+omhttp_get_data() {
+ # Args: 1=port 2=endpoint 3=batchformat(optional)
+ if [ "x$1" == "x" ]; then
+ omhttp_server_port=8080
+ else
+ omhttp_server_port=$1
+ fi
+
+ if [ "x$2" == "x" ]; then
+ omhttp_path=""
+ else
+ omhttp_path=$2
+ fi
+
+ # The test server returns a json encoded array of strings containing whatever omhttp sent to it in each request
+ python_init="import json, sys; dat = json.load(sys.stdin)"
+ python_print="print('\n'.join(out))"
+ if [ "x$3" == "x" ]; then
+ # dat = ['{"msgnum":"1"}, '{"msgnum":"2"}', '{"msgnum":"3"}', '{"msgnum":"4"}']
+ python_parse="$python_init; out = [json.loads(l)['msgnum'] for l in dat]; $python_print"
+ else
+ if [ "x$3" == "xjsonarray" ]; then
+ # dat = ['[{"msgnum":"1"},{"msgnum":"2"}]', '[{"msgnum":"3"},{"msgnum":"4"}]']
+ python_parse="$python_init; out = [l['msgnum'] for a in dat for l in json.loads(a)]; $python_print"
+ elif [ "x$3" == "xnewline" ]; then
+ # dat = ['{"msgnum":"1"}\n{"msgnum":"2"}', '{"msgnum":"3"}\n{"msgnum":"4"}']
+ python_parse="$python_init; out = [json.loads(l)['msgnum'] for a in dat for l in a.split('\n')]; $python_print"
+ elif [ "x$3" == "xkafkarest" ]; then
+ # dat = ['{"records":[{"value":{"msgnum":"1"}},{"value":{"msgnum":"2"}}]}',
+ # '{"records":[{"value":{"msgnum":"3"}},{"value":{"msgnum":"4"}}]}']
+ python_parse="$python_init; out = [l['value']['msgnum'] for a in dat for l in json.loads(a)['records']]; $python_print"
+ elif [ "x$3" == "xlokirest" ]; then
+ # dat = ['{"streams":[{"msgnum":"1"},{"msgnum":"2"}]}',
+ # '{"streams":[{"msgnum":"3"},{"msgnum":"4"}]}']
+ python_parse="$python_init; out = [l['msgnum'] for a in dat for l in json.loads(a)['streams']]; $python_print"
+ else
+ # use newline parsing as default
+ python_parse="$python_init; out = [json.loads(l)['msgnum'] for a in dat for l in a.split('\n')]; $python_print"
+ fi
+
+ fi
+
+ omhttp_url="localhost:${omhttp_server_port}/${omhttp_path}"
+ curl -s ${omhttp_url} \
+ | $PYTHON -c "${python_parse}" | sort -n \
+ > ${RSYSLOG_OUT_LOG}
+}
+
+
+# prepare MySQL for next test
+# each test receives its own database so that we also can run in parallel
+mysql_prep_for_test() {
+ mysql -u rsyslog --password=testbench -e "CREATE DATABASE $RSYSLOG_DYNNAME; "
+ mysql -u rsyslog --password=testbench --database $RSYSLOG_DYNNAME \
+ -e "CREATE TABLE SystemEvents (ID int unsigned not null auto_increment primary key, CustomerID bigint,ReceivedAt datetime NULL,DeviceReportedTime datetime NULL,Facility smallint NULL,Priority smallint NULL,FromHost varchar(60) NULL,Message text,NTSeverity int NULL,Importance int NULL,EventSource varchar(60),EventUser varchar(60) NULL,EventCategory int NULL,EventID int NULL,EventBinaryData text NULL,MaxAvailable int NULL,CurrUsage int NULL,MinUsage int NULL,MaxUsage int NULL,InfoUnitID int NULL,SysLogTag varchar(60),EventLogType varchar(60),GenericFileName VarChar(60),SystemID int NULL); CREATE TABLE SystemEventsProperties (ID int unsigned not null auto_increment primary key,SystemEventID int NULL,ParamName varchar(255) NULL,ParamValue text NULL);"
+ mysql --user=rsyslog --password=testbench --database $RSYSLOG_DYNNAME \
+ -e "truncate table SystemEvents;"
+ # TEST ONLY:
+ #mysql -s --user=rsyslog --password=testbench --database $RSYSLOG_DYNNAME \
+ #-e "select substring(Message,9,8) from SystemEvents;"
+ # END TEST
+ printf 'mysql ready for test, database: %s\n' $RSYSLOG_DYNNAME
+}
+
+# get data from mysql DB so that we can do seq_check on it.
+mysql_get_data() {
+ # note "-s" is required to suppress the select "field header"
+ mysql -s --user=rsyslog --password=testbench --database $RSYSLOG_DYNNAME \
+ -e "select substring(Message,9,8) from SystemEvents;" \
+ > $RSYSLOG_OUT_LOG 2> "$RSYSLOG_DYNNAME.mysqlerr"
+ grep -iv "Using a password on the command line interface can be insecure." < "$RSYSLOG_DYNNAME.mysqlerr"
+}
+
+# cleanup any temp data from mysql test
+# if we do not do this, we may run out of disk space
+# especially in container environment.
+mysql_cleanup_test() {
+ mysql --user=rsyslog --password=testbench -e "drop database $RSYSLOG_DYNNAME;" \
+ 2>&1 | grep -iv "Using a password on the command line interface can be insecure."
+}
+
+
+start_redis() {
+ check_command_available redis-server
+
+ export REDIS_DYN_CONF="${RSYSLOG_DYNNAME}.redis.conf"
+ export REDIS_DYN_DIR="$(pwd)/${RSYSLOG_DYNNAME}-redis"
+
+ # Only set a random port if not set (useful when Redis must be restarted during a test)
+ if [ -z "$REDIS_RANDOM_PORT" ]; then
+ export REDIS_RANDOM_PORT="$(get_free_port)"
+ fi
+
+ cp $srcdir/testsuites/redis.conf $REDIS_DYN_CONF
+ mkdir -p $REDIS_DYN_DIR
+
+ sed -itemp "s+<tmpdir>+${REDIS_DYN_DIR}+g" $REDIS_DYN_CONF
+ sed -itemp "s+<rndport>+${REDIS_RANDOM_PORT}+g" $REDIS_DYN_CONF
+
+ # Start the server
+ echo "Starting redis with conf file $REDIS_DYN_CONF"
+ redis-server $REDIS_DYN_CONF &
+ $TESTTOOL_DIR/msleep 2000
+
+ # Wait for Redis to be fully up
+ timeoutend=10
+ until nc -w1 -z 127.0.0.1 $REDIS_RANDOM_PORT; do
+ echo "Waiting for Redis to start..."
+ $TESTTOOL_DIR/msleep 1000
+ (( timeseconds=timeseconds + 2 ))
+
+ if [ "$timeseconds" -gt "$timeoutend" ]; then
+ echo "--- TIMEOUT ( $timeseconds ) reached!!!"
+ if [ ! -d ${REDIS_DYN_DIR}/redis.log ]; then
+ echo "no Redis logs"
+ else
+ echo "Dumping ${REDIS_DYN_DIR}/redis.log"
+ echo "========================================="
+ cat ${REDIS_DYN_DIR}/redis.log
+ echo "========================================="
+ fi
+ error_exit 1
+ fi
+ done
+}
+
+cleanup_redis() {
+ if [ -d ${REDIS_DYN_DIR} ]; then
+ rm -rf ${REDIS_DYN_DIR}
+ fi
+ if [ -f ${REDIS_DYN_CONF} ]; then
+ rm -f ${REDIS_DYN_CONF}
+ fi
+}
+
+stop_redis() {
+ if [ -f "$REDIS_DYN_DIR/redis.pid" ]; then
+ redispid=$(cat $REDIS_DYN_DIR/redis.pid)
+ echo "Stopping Redis instance"
+ kill $redispid
+
+ i=0
+
+ # Check if redis instance went down!
+ while [ -f $REDIS_DYN_DIR/redis.pid ]; do
+ redispid=$(cat $REDIS_DYN_DIR/redis.pid)
+ if [[ "" != "$redispid" ]]; then
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if test $i -gt $TB_TIMEOUT_STARTSTOP; then
+ echo "redis server (PID $redispid) still running - Performing hard shutdown (-9)"
+ kill -9 $redispid
+ break
+ fi
+ (( i++ ))
+ else
+ # Break the loop
+ break
+ fi
+ done
+ fi
+}
+
+redis_command() {
+ check_command_available redis-cli
+
+ if [ -z "$1" ]; then
+ echo "redis_command: no command provided!"
+ error_exit 1
+ fi
+
+ printf "$1\n" | redis-cli -p "$REDIS_RANDOM_PORT"
+}
+
+# $1 - replacement string
+# $2 - start search string
+# $3 - file name
+# $4 - expected value
+first_column_sum_check() {
+ sum=$(grep "$2" < "$3" | sed -e "$1" | awk '{s+=$1} END {print s}')
+ if [ "x${sum}" != "x$4" ]; then
+ printf '\n============================================================\n'
+ echo FAIL: sum of first column with edit-expr "'$1'" run over lines from file "'$3'" matched by "'$2'" equals "'$sum'" which is NOT equal to EXPECTED value of "'$4'"
+ echo "file contents:"
+ cat $3
+ error_exit 1
+ fi
+}
+
+#
+# Helper functions to start/stop python snmp trap receiver
+#
+snmp_start_trapreceiver() {
+ # Args: 1=port 2=outputfilename
+ # Args 2 and up are passed along as is to snmptrapreceiver.py
+ snmptrapreceiver=$srcdir/snmptrapreceiver.py
+ if [ ! -f ${snmptrapreceiver} ]; then
+ echo "Cannot find ${snmptrapreceiver} for omsnmp test"
+ error_exit 1
+ fi
+
+ if [ "x$1" == "x" ]; then
+ snmp_server_port="10162"
+ else
+ snmp_server_port="$1"
+ fi
+
+ if [ "x$2" == "x" ]; then
+ output_file="${RSYSLOG_DYNNAME}.snmp.out"
+ else
+ output_file="$2"
+ fi
+
+ # Create work directory for parallel tests
+ snmp_work_dir=${RSYSLOG_DYNNAME}/snmptrapreceiver
+
+ snmp_server_pidfile="${snmp_work_dir}/snmp_server.pid"
+ snmp_server_logfile="${snmp_work_dir}/snmp_server.log"
+ mkdir -p ${snmp_work_dir}
+
+ server_args="${snmp_server_port} 127.0.0.1 ${output_file}"
+
+ $PYTHON ${snmptrapreceiver} ${server_args} ${snmp_server_logfile} >> ${snmp_server_logfile} 2>&1 &
+ if [ ! $? -eq 0 ]; then
+ echo "Failed to start snmptrapreceiver."
+ rm -rf ${snmp_work_dir}
+ error_exit 1
+ fi
+
+ snmp_server_pid=$!
+ echo ${snmp_server_pid} > ${snmp_server_pidfile}
+
+ while test ! -s "${snmp_server_logfile}"; do
+ $TESTTOOL_DIR/msleep 100 # wait 100 milliseconds
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting on startup (pid file %s)\n' "$(tb_timestamp)" "$1"
+ ls -l "$1"
+ ps -fp $(cat "$1")
+ snmp_stop_trapreceiver
+ error_exit 1
+# else
+# echo "waiting...${snmp_server_logfile}..."
+ fi
+ done
+
+ echo "Started snmptrapreceiver with args ${server_args} with pid ${snmp_server_pid}"
+}
+
+snmp_stop_trapreceiver() {
+ # Args: None
+ snmp_work_dir=${RSYSLOG_DYNNAME}/snmptrapreceiver
+ if [ ! -d ${snmp_work_dir} ]; then
+ echo "snmptrapreceiver server ${snmp_work_dir} does not exist, no action needed"
+ else
+ echo "Stopping snmptrapreceiver server"
+ kill -9 $(cat ${snmp_work_dir}/snmp_server.pid) > /dev/null 2>&1
+ # Done at testexit already!: rm -rf ${snmp_work_dir}
+ fi
+}
+
+wait_for_stats_flush() {
+ echo "will wait for stats push"
+ emitmsg=0
+ while [[ ! -f $1 ]]; do
+ if [ $((++emitmsg % 10)) == 0 ]; then
+ echo waiting for stats file "'$1'" to be created
+ fi
+ $TESTTOOL_DIR/msleep 100
+ done
+ prev_count=$(grep -c 'BEGIN$' <$1)
+ new_count=$prev_count
+ start_loop="$(date +%s)"
+ emit_waiting=0
+ while [[ "x$prev_count" == "x$new_count" ]]; do
+ # busy spin, because it allows as close timing-coordination
+ # in actual test run as possible
+ if [ $(date +%s) -gt $(( TB_STARTTEST + TB_TEST_MAX_RUNTIME )) ]; then
+ printf '%s ABORT! Timeout waiting on stats push\n' "$(tb_timestamp)" "$1"
+ error_exit 1
+ else
+ # waiting for 1000 is heuristically "sufficiently but not too
+ # frequent" enough
+ if [ $((++emit_waiting)) == 1000 ]; then
+ printf 'still waiting for stats push...\n'
+ emit_waiting=0
+ fi
+ fi
+ new_count=$(grep -c 'BEGIN$' <"$1")
+ done
+ echo "stats push registered"
+}
+
+# Check file exists and is of a particular size
+# $1 - file to check
+# $2 - size to check
+file_size_check() {
+ local size=$(ls -l $1 | awk {'print $5'})
+ if [ "${size}" != "${2}" ]; then
+ printf 'File:[%s] has unexpected size. Expected:[%d], Size:[%d]\n', $1 $2 $size
+ error_exit 1
+ fi
+ return 0
+}
+
+case $1 in
+ 'init') $srcdir/killrsyslog.sh # kill rsyslogd if it runs for some reason
+ source set-envvars
+ # for (solaris) load debugging, uncomment next 2 lines:
+ #export LD_DEBUG=all
+ #ldd ../tools/rsyslogd
+
+ # environment debug
+ #find / -name "librelp.so*"
+ #ps -ef |grep syslog
+ #netstat -a | grep LISTEN
+
+ # cleanup of hanging instances from previous runs
+ # practice has shown this is pretty useful!
+ #for pid in $(ps -eo pid,args|grep '/tools/[r]syslogd ' |sed -e 's/\( *\)\([0-9]*\).*/\2/');
+ #do
+ #echo "ERROR: left-over previous instance $pid, killing it"
+ #ps -fp $pid
+ #pwd
+ #kill -9 $pid
+ #done
+ # end cleanup
+
+ # some default names (later to be set in other parts, once we support fully
+ # parallel tests)
+ export RSYSLOG_DFLT_LOG_INTERNAL=1 # testbench needs internal messages logged internally!
+ if [ -f testbench_test_failed_rsyslog ] && [ "$ABORT_ALL_ON_TEST_FAIL" == "YES" ]; then
+ echo NOT RUNNING TEST as previous test $(cat testbench_test_failed_rsyslog) failed.
+ exit 77
+ fi
+ if [ "$RSYSLOG_DYNNAME" != "" ]; then
+ echo "FAIL: \$RSYSLOG_DYNNAME already set in init"
+ echo "hint: was init accidentally called twice?"
+ exit 2
+ fi
+ export RSYSLOG_DYNNAME="rstb_$(./test_id $(basename $0))$(tr -dc 'a-zA-Z0-9' < /dev/urandom | head --bytes 4)"
+ export RSYSLOG_OUT_LOG="${RSYSLOG_DYNNAME}.out.log"
+ export RSYSLOG2_OUT_LOG="${RSYSLOG_DYNNAME}_2.out.log"
+ export RSYSLOG_PIDBASE="${RSYSLOG_DYNNAME}:" # also used by instance 2!
+ #export IMDIAG_PORT=13500 DELETE ME
+ #export IMDIAG_PORT2=13501 DELETE ME
+ #export TCPFLOOD_PORT=13514 DELETE ME
+
+ # Extra Variables for Test statistic reporting
+ export RSYSLOG_TESTNAME=$(basename $0)
+
+ # we create one file with the test name, so that we know what was
+ # left over if "make distcheck" complains
+ touch $RSYSLOG_DYNNAME-$(basename $0).test_id
+
+ if [ -z $RS_SORTCMD ]; then
+ RS_SORTCMD="sort"
+ fi
+ if [ -z $RS_SORT_NUMERIC_OPT ]; then
+ if [ "$(uname)" == "AIX" ]; then
+ RS_SORT_NUMERIC_OPT=-n
+ else
+ RS_SORT_NUMERIC_OPT=-g
+ fi
+ fi
+ if [ -z $RS_CMPCMD ]; then
+ RS_CMPCMD="cmp"
+ fi
+ if [ -z $RS_HEADCMD ]; then
+ RS_HEADCMD="head"
+ fi
+ # we assume TZ is set, else most test will fail. So let's ensure
+ # this really is the case
+ if [ -z $TZ ]; then
+ echo "testbench: TZ env var not set, setting it to UTC"
+ export TZ=UTC
+ fi
+ ulimit -c unlimited &> /dev/null # at least try to get core dumps
+ export TB_STARTTEST=$(date +%s)
+ printf '%s\n' '------------------------------------------------------------'
+ printf '%s Test: %s\n' "$(tb_timestamp)" "$0"
+ printf '%s\n' '------------------------------------------------------------'
+ rm -f xlate*.lkp_tbl
+ rm -f log log* # RSyslog debug output
+ rm -f work
+ rm -rf test-logdir stat-file1
+ rm -f rsyslog.empty imfile-state:* omkafka-failed.data
+ rm -f tmp.qi nocert
+ rm -f core.* vgcore.* core*
+ # Note: rsyslog.action.*.include must NOT be deleted, as it
+ # is used to setup some parameters BEFORE calling init. This
+ # happens in chained test scripts. Delete on exit is fine,
+ # though.
+ # note: TCPFLOOD_EXTRA_OPTS MUST NOT be unset in init, because
+ # some tests need to set it BEFORE calling init to accommodate
+ # their generic test drivers.
+ if [ "$TCPFLOOD_EXTRA_OPTS" != '' ] ; then
+ echo TCPFLOOD_EXTRA_OPTS set: $TCPFLOOD_EXTRA_OPTS
+ fi
+ if [ "$USE_AUTO_DEBUG" != 'on' ] ; then
+ rm -f IN_AUTO_DEBUG
+ fi
+ if [ -e IN_AUTO_DEBUG ]; then
+ export valgrind="valgrind --malloc-fill=ff --free-fill=fe --suppressions=$srcdir/known_issues.supp ${EXTRA_VALGRIND_SUPPRESSIONS:-} --log-fd=1"
+ fi
+ ;;
+
+ 'check-ipv6-available') # check if IPv6 - will exit 77 when not OK
+ if ip address > /dev/null ; then
+ cmd="ip address"
+ else
+ cmd="ifconfig -a"
+ fi
+ echo command used for ipv6 detection: $cmd
+ $cmd | grep ::1 > /dev/null
+ if [ $? -ne 0 ] ; then
+ printf 'this test requires an active IPv6 stack, which we do not have here\n'
+ error_exit 77
+ fi
+ ;;
+ 'kill-immediate') # kill rsyslog unconditionally
+ kill -9 $(cat $RSYSLOG_PIDBASE.pid)
+ # note: we do not wait for the actual termination!
+ ;;
+ 'ensure-no-process-exists')
+ ps -ef | grep -v grep | grep -qF "$2"
+ if [ "x$?" == "x0" ]; then
+ echo "assertion failed: process with name-fragment matching '$2' found"
+ error_exit 1
+ fi
+ ;;
+ 'grep-check') # grep for "$EXPECTED" present in rsyslog.log - env var must be set
+ # before this method is called
+ grep "$EXPECTED" ${RSYSLOG_OUT_LOG} > /dev/null
+ if [ $? -eq 1 ]; then
+ echo "GREP FAIL: ${RSYSLOG_OUT_LOG} content:"
+ cat ${RSYSLOG_OUT_LOG}
+ echo "GREP FAIL: expected text not found:"
+ echo "$EXPECTED"
+ error_exit 1
+ fi;
+ ;;
+ 'block-stats-flush')
+ echo blocking stats flush
+ echo "blockStatsReporting" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ ;;
+ 'await-stats-flush-after-block')
+ echo unblocking stats flush and waiting for it
+ echo "awaitStatsReport" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ ;;
+ 'allow-single-stats-flush-after-block-and-wait-for-it')
+ echo blocking stats flush
+ echo "awaitStatsReport block_again" | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+ ;;
+ 'wait-for-dyn-stats-reset')
+ echo "will wait for dyn-stats-reset"
+ while [[ ! -f $2 ]]; do
+ echo waiting for stats file "'$2'" to be created
+ $TESTTOOL_DIR/msleep 100
+ done
+ prev_purged=$(grep -F 'origin=dynstats' < $2 | grep -F "${3}.purge_triggered=" | sed -e 's/.\+.purge_triggered=//g' | awk '{s+=$1} END {print s}')
+ new_purged=$prev_purged
+ while [[ "x$prev_purged" == "x$new_purged" ]]; do
+ new_purged=$(grep -F 'origin=dynstats' < "$2" | grep -F "${3}.purge_triggered=" | sed -e 's/.\+\.purge_triggered=//g' | awk '{s+=$1} END {print s}') # busy spin, because it allows as close timing-coordination in actual test run as possible
+ $TESTTOOL_DIR/msleep 10
+ done
+ echo "dyn-stats reset for bucket ${3} registered"
+ ;;
+ 'assert-first-column-sum-greater-than')
+ sum=$(grep $3 <$4| sed -e $2 | awk '{s+=$1} END {print s}')
+ if [ ! $sum -gt $5 ]; then
+ echo sum of first column with edit-expr "'$2'" run over lines from file "'$4'" matched by "'$3'" equals "'$sum'" which is smaller than expected lower-limit of "'$5'"
+ echo "file contents:"
+ cat $4
+ error_exit 1
+ fi
+ ;;
+ 'content-pattern-check')
+ grep -q "$2" < ${RSYSLOG_OUT_LOG}
+ if [ "$?" -ne "0" ]; then
+ echo content-check failed, not every line matched pattern "'$2'"
+ echo "file contents:"
+ cat -n $4
+ error_exit 1
+ fi
+ ;;
+ 'require-journalctl') # check if journalctl exists on the system
+ if ! hash journalctl 2>/dev/null ; then
+ echo "journalctl command missing, skipping test"
+ exit 77
+ fi
+ ;;
+ 'check-inotify') # Check for inotify/fen support
+ if [ -n "$(find /usr/include -name 'inotify.h' -print -quit)" ]; then
+ echo [inotify mode]
+ elif [ -n "$(find /usr/include/sys/ -name 'port.h' -print -quit)" ]; then
+ grep -qF "PORT_SOURCE_FILE" < /usr/include/sys/port.h
+ if [ "$?" -ne "0" ]; then
+ echo [port.h found but FEN API not implemented , skipping...]
+ exit 77 # FEN API not available, skip this test
+ fi
+ echo [fen mode]
+ else
+ echo [inotify/fen not supported, skipping...]
+ exit 77 # no inotify available, skip this test
+ fi
+ ;;
+ 'check-inotify-only') # Check for ONLY inotify support
+ if [ -n "$(find /usr/include -name 'inotify.h' -print -quit)" ]; then
+ echo [inotify mode]
+ else
+ echo [inotify not supported, skipping...]
+ exit 77 # no inotify available, skip this test
+ fi
+ ;;
+ *) echo "TESTBENCH error: invalid argument" $1
+ exit 100
+esac
diff --git a/tests/diagtalker.c b/tests/diagtalker.c
new file mode 100644
index 0000000..4414618
--- /dev/null
+++ b/tests/diagtalker.c
@@ -0,0 +1,165 @@
+/* A yet very simple tool to talk to imdiag (this replaces the
+ * previous Java implementation in order to get fewer dependencies).
+ *
+ * Copyright 2010-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if defined(__FreeBSD__)
+#include <netinet/in.h>
+#endif
+
+static char *targetIP = "127.0.0.1";
+static int targetPort = 13500;
+
+
+/* open a single tcp connection
+ */
+int openConn(int *fd)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int port;
+ int retries = 0;
+
+ if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
+ perror("socket()");
+ exit(1);
+ }
+
+ port = targetPort;
+ memset((char *) &addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ if(inet_aton(targetIP, &addr.sin_addr)==0) {
+ fprintf(stderr, "inet_aton() failed\n");
+ exit(1);
+ }
+ while(1) { /* loop broken inside */
+ if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
+ break;
+ } else {
+ if(retries++ == 50) {
+ perror("connect()");
+ fprintf(stderr, "[%d] connect() failed\n", port);
+ exit(1);
+ } else {
+ fprintf(stderr, "[%d] connect failed, retrying...\n", port);
+ usleep(100000); /* ms = 1000 us! */
+ }
+ }
+ }
+ if(retries > 0) {
+ fprintf(stderr, "[%d] connection established.\n", port);
+ }
+
+ *fd = sock;
+ return 0;
+}
+
+
+/* send a string
+ */
+static void
+sendCmd(int fd, char *buf, int len)
+{
+ int lenSend;
+
+ lenSend = send(fd, buf, len, 0);
+ if(lenSend != len) {
+ perror("sending string");
+ exit(1);
+ }
+}
+
+
+/* wait for a response from remote system
+ */
+static void
+waitRsp(int fd, char *buf, int len)
+{
+ int ret;
+
+ ret = recv(fd, buf, len - 1, 0);
+ if(ret < 0) {
+ perror("receiving response");
+ exit(1);
+ }
+ /* we assume the message was complete, it may be better to wait
+ * for a LF...
+ */
+ buf[ret] = '\0';
+}
+
+
+/* do the actual processing
+ */
+static void
+doProcessing()
+{
+ int fd;
+ int len;
+ char line[2048];
+
+ openConn(&fd);
+ while(!feof(stdin)) {
+ if(fgets(line, sizeof(line) - 1, stdin) == NULL)
+ break;
+ len = strlen(line);
+ sendCmd(fd, line, len);
+ waitRsp(fd, line, sizeof(line));
+ printf("imdiag[%d]: %s", targetPort, line);
+ if (strstr(line, "imdiag::error") != NULL) {
+ exit(1);
+ }
+ }
+}
+
+
+/* Run the test.
+ * rgerhards, 2009-04-03
+ */
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int opt;
+
+ while((opt = getopt(argc, argv, "t:p:")) != -1) {
+ switch (opt) {
+ case 't': targetIP = optarg;
+ break;
+ case 'p': targetPort = atoi(optarg);
+ break;
+ default: printf("invalid option '%c' or value missing - terminating...\n", opt);
+ exit (1);
+ break;
+ }
+ }
+
+ doProcessing();
+
+ exit(ret);
+}
diff --git a/tests/dircreate_dflt.sh b/tests/dircreate_dflt.sh
new file mode 100755
index 0000000..758e5fa
--- /dev/null
+++ b/tests/dircreate_dflt.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Test for automatic creation of dynafile directories
+# note that we use the "'${RSYSLOG_DYNNAME}'.spool" directory, because it is handled by diag.sh
+# in any case, so we do not need to add any extra new test dir.
+# added 2009-11-30 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$template dynfile,"'$RSYSLOG_DYNNAME'.logdir/'$RSYSLOG_OUT_LOG'"
+*.* ?dynfile
+'
+startup
+injectmsg 0 1 # a single message is sufficient
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+if [ ! -e $RSYSLOG_DYNNAME.logdir/$RSYSLOG_OUT_LOG ]
+then
+ echo "$RSYSLOG_DYNNAME.logdir or logfile not created!"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/dircreate_off.sh b/tests/dircreate_off.sh
new file mode 100755
index 0000000..bcd6d1a
--- /dev/null
+++ b/tests/dircreate_off.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Test for automatic creation of dynafile directories
+# note that we use the ${RSYSLOG_DYNNAME}.spool directory, because it is handled by diag.sh
+# in any case, so we do not need to add any extra new test dir.
+# added 2009-11-30 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$CreateDirs off
+$template dynfile,'$RSYSLOG_DYNNAME'.OUT_LOG
+*.* ?dynfile
+'
+startup
+injectmsg 0 1 # a single message is sufficient
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+if [ -e $RSYSLOG_DYNNAME.logdir/$RSYSLOG_OUT_LOG ]
+then
+ echo "$RSYSLOG_DYNNAME.logdir or logfile WAS created where not permitted to!"
+ error-exit 1
+fi
+exit_test
diff --git a/tests/discard-allmark-vg.sh b/tests/discard-allmark-vg.sh
new file mode 100755
index 0000000..2f42a8d
--- /dev/null
+++ b/tests/discard-allmark-vg.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[discard-allmark.sh\]: testing discard-allmark functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$ActionWriteAllMarkMessages on
+
+:msg, contains, "00000001" ~
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup_vg
+tcpflood -m10 -i1
+# we need to give rsyslog a little time to settle the receiver
+./msleep 1500
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg
+check_exit_vg
+seq_check 2 10
+exit_test
diff --git a/tests/discard-allmark.sh b/tests/discard-allmark.sh
new file mode 100755
index 0000000..c965a54
--- /dev/null
+++ b/tests/discard-allmark.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[discard-allmark.sh\]: testing discard-allmark functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$ActionWriteAllMarkMessages on
+
+:msg, contains, "00000001" ~
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+tcpflood -m10 -i1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 2 10
+exit_test
diff --git a/tests/discard-rptdmsg-vg.sh b/tests/discard-rptdmsg-vg.sh
new file mode 100755
index 0000000..16733fc
--- /dev/null
+++ b/tests/discard-rptdmsg-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/discard-rptdmsg.sh
diff --git a/tests/discard-rptdmsg.sh b/tests/discard-rptdmsg.sh
new file mode 100755
index 0000000..6c56891
--- /dev/null
+++ b/tests/discard-rptdmsg.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# testing discard-rptdmsg functionality when no repeated message is present
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+$RepeatedMsgReduction on
+
+:msg, contains, "00000001" ~
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -m10 -i1
+shutdown_when_empty
+wait_shutdown
+seq_check 2 10
+exit_test
diff --git a/tests/discard.sh b/tests/discard.sh
new file mode 100755
index 0000000..64827ea
--- /dev/null
+++ b/tests/discard.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Test for discard functionality
+# This test checks if discard works. It is not a perfect test but
+# will find at least segfaults and obviously not discarded messages.
+# added 2009-07-30 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+:msg, contains, "00000000" ~
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check 1 $((NUMMESSAGES-1))
+exit_test
diff --git a/tests/diskq-rfc5424.sh b/tests/diskq-rfc5424.sh
new file mode 100755
index 0000000..6ba40ce
--- /dev/null
+++ b/tests/diskq-rfc5424.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# detect queue corruption based on invalid property bag ordering.
+# Note: this mimics an issue actually seen in practice.
+# Triggering condition: "json" property (message variables) are present
+# and "structured-data" property is also present. Caused rsyslog to
+# thrash the queue file, getting messages stuck in it and loosing all
+# after the initial problem occurrence.
+# add 2017-02-08 by Rainer Gerhards, released under ASL 2.0
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="rs2" queue.type="disk" queue.filename="rs2_q"
+ queue.spoolDirectory="'${RSYSLOG_DYNNAME}'.spool") {
+ set $!tmp=$msg;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+ruleset(name="rs") {
+ set $!tmp=$msg;
+ call rs2
+}
+'
+startup
+tcpflood -m$NUMMESSAGES -y
+shutdown_when_empty
+wait_shutdown
+seq_check
+
+exit_test
diff --git a/tests/diskqueue-fail.sh b/tests/diskqueue-fail.sh
new file mode 100755
index 0000000..a8c63b2
--- /dev/null
+++ b/tests/diskqueue-fail.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# checks that nothing bad happens if a DA (disk) queue runs out
+# of configured disk space
+# addd 2017-02-07 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+generate_conf
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="queuefail")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+ruleset(
+ name="queuefail"
+ queue.type="Disk"
+ queue.filename="fssailstocreate"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+) {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES
+
+shutdown_when_empty
+wait_shutdown
+seq_check
+
+exit_test
diff --git a/tests/diskqueue-fsync.sh b/tests/diskqueue-fsync.sh
new file mode 100755
index 0000000..a0dece2
--- /dev/null
+++ b/tests/diskqueue-fsync.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Test for disk-only queue mode (with fsync for queue files)
+# This test checks if queue files can be correctly written
+# and read back, but it does not test the transition from
+# memory to disk mode for DA queues.
+# added 2009-06-09 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000 # 1000 messages should be enough - the disk fsync test is very slow!
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueSyncQueueFiles on
+$MainMsgQueueTimeoutShutdown 10000
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/diskqueue-full.sh b/tests/diskqueue-full.sh
new file mode 100755
index 0000000..85db1a3
--- /dev/null
+++ b/tests/diskqueue-full.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# checks that nothing bad happens if a DA (disk) queue runs out
+# of configured disk space
+# addd 2017-02-07 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq" queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 20000
+ls -l ${RSYSLOG_DYNNAME}.spool
+shutdown_when_empty
+wait_shutdown
+ls -l ${RSYSLOG_DYNNAME}.spool
+seq_check 0 19999
+
+exit_test
diff --git a/tests/diskqueue-multithread-es.sh b/tests/diskqueue-multithread-es.sh
new file mode 100755
index 0000000..a4901c3
--- /dev/null
+++ b/tests/diskqueue-multithread-es.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This test stresses the DA queue disk subsystem with multiple threads.
+# To do so, the in-memory queues are deliberately sized very small.
+# NOTE: depending on circumstances, this test frequently starts the
+# DAWorkerPool, which shuffles messages over from the main queue to
+# the DA queue. It terminates when we reach low water mark. This can
+# happen in our test. So the DA worker pool thread is, depending on
+# timing, started and shut down multiple times. This is not a problem
+# indication!
+# The pstats display is for manual review - it helps to see how many
+# messages actually went to the DA queue.
+# Copyright (C) 2019-10-28 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export NUMMESSAGES=25000
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME'.spool")
+template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+main_queue(queue.size="2000")
+module(load="../plugins/impstats/.libs/impstats"
+ log.syslog="off" log.file="'$RSYSLOG_DYNNAME'.pstats" interval="1")
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+:msg, contains, "msgnum:" {
+ action(type="omelasticsearch" name="act-es"
+ template="tpl" server="127.0.0.1"
+ serverport="'$ES_PORT'"
+ searchIndex="rsyslog_testbench"
+ bulkmode="on"
+ queue.lowwatermark="250"
+ queue.highwatermark="1500"
+ queue.type="linkedList" queue.size="2000"
+ queue.dequeueBatchSize="64" queue.workerThreads="4"
+ queue.fileName="actq" queue.workerThreadMinimumMessages="64")
+}
+'
+startup
+tcpflood -m$NUMMESSAGES # use tcpflood to get better async processing than injectmsg!
+shutdown_when_empty
+wait_shutdown
+echo FOR MANUAL REVIEW: pstats
+tail $RSYSLOG_DYNNAME.pstats | grep maxqsize
+es_getdata $NUMMESSAGES $ES_PORT
+seq_check
+exit_test
diff --git a/tests/diskqueue-non-unique-prefix.sh b/tests/diskqueue-non-unique-prefix.sh
new file mode 100755
index 0000000..f11da27
--- /dev/null
+++ b/tests/diskqueue-non-unique-prefix.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Test for config parser to check that disk queue file names are
+# unique.
+# added 2019-05-02 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+if 0 then {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused"
+ queue.filename="qf1" queue.type="linkedList")
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused"
+ queue.filename="qf1" queue.type="linkedList")
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused"
+ queue.filename="qf2" queue.type="linkedList")
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused"
+ queue.spooldirectory="'$RSYSLOG_DYNNAME'.spool2"
+ queue.filename="qf2" queue.type="linkedList")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "and file name prefix 'qf1' already used"
+check_not_present "and file name prefix 'qf2' already used"
+exit_test
diff --git a/tests/diskqueue.sh b/tests/diskqueue.sh
new file mode 100755
index 0000000..d7868f2
--- /dev/null
+++ b/tests/diskqueue.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Test for disk-only queue mode
+# This test checks if queue files can be correctly written
+# and read back, but it does not test the transition from
+# memory to disk mode for DA queues.
+# added 2009-04-17 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+if ($msg contains "msgnum:") then
+ ?dynfile;outfmt
+else
+ action(type="omfile" file="'$RSYSLOG_DYNNAME.syslog.log'")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+check_not_present "spool.* open error" $RSYSLOG_DYNNAME.syslog.log
+exit_test
diff --git a/tests/dnscache-TTL-0-vg.sh b/tests/dnscache-TTL-0-vg.sh
new file mode 100755
index 0000000..8618bd1
--- /dev/null
+++ b/tests/dnscache-TTL-0-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-12 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/dnscache-TTL-0.sh
diff --git a/tests/dnscache-TTL-0.sh b/tests/dnscache-TTL-0.sh
new file mode 100755
index 0000000..3d169d0
--- /dev/null
+++ b/tests/dnscache-TTL-0.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2019-04-12 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20 # should be sufficient to stress DNS cache
+generate_conf
+add_conf '
+global(reverselookup.cache.ttl.default="0"
+ reverselookup.cache.ttl.enable="on")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -m$NUMMESSAGES -c10 # run on 10 connections --> 10 dns cache calls
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/dynfile_invalid2.sh b/tests/dynfile_invalid2.sh
new file mode 100755
index 0000000..73de5db
--- /dev/null
+++ b/tests/dynfile_invalid2.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# This test checks if omfile segfaults when a file open() in dynacache mode fails.
+# The test is mimiced after a real-life scenario (which, of course, was much more
+# complex).
+#
+# added 2010-03-22 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:3%\n"
+$template dynfile,"%msg:F,58:2%.log" # complete name is in message
+$OMFileFlushOnTXEnd off
+$DynaFileCacheSize 4
+$omfileFlushInterval 1
+local0.* ?dynfile;outfmt
+'
+startup
+# we send handcrafted message. We have a dynafile cache of 4, and now send one message
+# each to fill up the cache.
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3\""
+# the next one has caused a segfault in practice
+# note that /proc/rsyslog.error.file must not be creatable
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom\""
+# some more writes
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7\""
+# done message generation
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG
+seq_check 0 7
+exit_test
diff --git a/tests/dynfile_invld_async.sh b/tests/dynfile_invld_async.sh
new file mode 100755
index 0000000..a96ae44
--- /dev/null
+++ b/tests/dynfile_invld_async.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# This test checks if omfile segfaults when a file open() in dynacache mode fails.
+# The test is mimiced after a real-life scenario (which, of course, was much more
+# complex).
+#
+# added 2010-03-09 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:3%\n"
+$template dynfile,"%msg:F,58:2%.log" # complete name is in message
+$OMFileFlushOnTXEnd on
+$OMFileAsyncWriting on
+$DynaFileCacheSize 4
+local0.* ?dynfile;outfmt
+'
+startup
+# we send handcrafted message. We have a dynafile cache of 4, and now send one message
+# each to fill up the cache.
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3\""
+# the next one has caused a segfault in practice
+# note that /proc/rsyslog.error.file must not be creatable
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom\""
+# some more writes
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7\""
+# done message generation
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG
+seq_check 0 7
+exit_test
diff --git a/tests/dynfile_invld_sync.sh b/tests/dynfile_invld_sync.sh
new file mode 100755
index 0000000..5bb1f3c
--- /dev/null
+++ b/tests/dynfile_invld_sync.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# This test checks if omfile segfaults when a file open() in dynacache mode fails.
+# The test is mimiced after a real-life scenario (which, of course, was much more
+# complex).
+#
+# added 2010-03-09 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:3%\n"
+$template dynfile,"%msg:F,58:2%.log" # complete name is in message
+$OMFileFlushOnTXEnd on
+$OMFileAsyncWriting off
+$DynaFileCacheSize 4
+local0.* ?dynfile;outfmt
+'
+startup
+# we send handcrafted message. We have a dynafile cache of 4, and now send one message
+# each to fill up the cache.
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3\""
+# the next one has caused a segfault in practice
+# note that /proc/rsyslog.error.file must not be creatable
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom\""
+# some more writes
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7\""
+# done message generation
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG
+seq_check 0 7
+exit_test
diff --git a/tests/dynstats-json-vg.sh b/tests/dynstats-json-vg.sh
new file mode 100755
index 0000000..8a80543
--- /dev/null
+++ b/tests/dynstats-json-vg.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats-json-vg.sh\]: test for verifying stats are reported correctly in json format with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+dyn_stats(name="stats_one")
+dyn_stats(name="stats_two")
+
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+set $.p = field($msg, 32, 1);
+if ($.p == "foo") then {
+ set $.ign = dyn_inc("stats_one", $.p);
+ set $.ign = dyn_inc("stats_two", $.p);
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+custom_content_check '{ "name": "global", "origin": "dynstats", "values": { "stats_one.ops_overflow": 0, "stats_one.new_metric_add": 1, "stats_one.no_metric": 0, "stats_one.metrics_purged": 0, "stats_one.ops_ignored": 0, "stats_one.purge_triggered": 0, "stats_two.ops_overflow": 0, "stats_two.new_metric_add": 1, "stats_two.no_metric": 0, "stats_two.metrics_purged": 0, "stats_two.ops_ignored": 0, "stats_two.purge_triggered": 0 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check '{ "name": "stats_one", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check '{ "name": "stats_two", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/dynstats-json.sh b/tests/dynstats-json.sh
new file mode 100755
index 0000000..ba11cdd
--- /dev/null
+++ b/tests/dynstats-json.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats-json.sh\]: test for verifying stats are reported correctly in json format
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+dyn_stats(name="stats_one")
+dyn_stats(name="stats_two")
+
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+set $.p = field($msg, 32, 1);
+if ($.p == "foo") then {
+ set $.ign = dyn_inc("stats_one", $.p);
+ set $.ign = dyn_inc("stats_two", $.p);
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check '{ "name": "global", "origin": "dynstats", "values": { "stats_one.ops_overflow": 0, "stats_one.new_metric_add": 1, "stats_one.no_metric": 0, "stats_one.metrics_purged": 0, "stats_one.ops_ignored": 0, "stats_one.purge_triggered": 0, "stats_two.ops_overflow": 0, "stats_two.new_metric_add": 1, "stats_two.no_metric": 0, "stats_two.metrics_purged": 0, "stats_two.ops_ignored": 0, "stats_two.purge_triggered": 0 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check '{ "name": "stats_one", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check '{ "name": "stats_two", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/dynstats-vg.sh b/tests/dynstats-vg.sh
new file mode 100755
index 0000000..9a0ff8b
--- /dev/null
+++ b/tests/dynstats-vg.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# added 2015-11-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats-vg.sh\]: test for gathering stats over dynamic metric names with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file $srcdir/testsuites/dynstats_input
+wait_queueempty
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+rst_msleep 1100 # wait for stats flush
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+exit_test
diff --git a/tests/dynstats.sh b/tests/dynstats.sh
new file mode 100755
index 0000000..51a016f
--- /dev/null
+++ b/tests/dynstats.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# added 2015-11-10 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file $srcdir/testsuites/dynstats_input
+wait_queueempty
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+rst_msleep 1100 # wait for stats flush
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+exit_test
diff --git a/tests/dynstats_ctr_reset.sh b/tests/dynstats_ctr_reset.sh
new file mode 100755
index 0000000..17e9519
--- /dev/null
+++ b/tests/dynstats_ctr_reset.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# added 2015-11-16 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo \[dynstats_ctr_reset.sh\]: test to ensure correctness of stats-ctr reset
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+dyn_stats(name="msg_stats_resettable_on" resettable="on")
+dyn_stats(name="msg_stats_resettable_off" resettable="off")
+dyn_stats(name="msg_stats_resettable_default")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+set $.x = dyn_inc("msg_stats_resettable_on", $.msg_prefix);
+set $.y = dyn_inc("msg_stats_resettable_off", $.msg_prefix);
+set $.z = dyn_inc("msg_stats_resettable_default", $.msg_prefix);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+injectmsg_file $srcdir/testsuites/dynstats_input_2
+wait_queueempty
+sleep 1
+injectmsg_file $srcdir/testsuites/dynstats_input_3
+wait_queueempty
+sleep 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "foo 006"
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+exit_test
diff --git a/tests/dynstats_nometric.sh b/tests/dynstats_nometric.sh
new file mode 100755
index 0000000..fef6cda
--- /dev/null
+++ b/tests/dynstats_nometric.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# added 2015-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats_nometric.sh\]: test for dyn-stats meta-metric behavior with zero-length metric name
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats")
+
+set $.msg_prefix = field($msg, 32, 2);
+
+set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+wait_queueempty
+rm $srcdir/${RSYSLOG_DYNNAME}.out.stats.log
+issue_HUP #reopen stats file
+injectmsg_file $srcdir/testsuites/dynstats_empty_input
+wait_queueempty
+rst_msleep 1100 # wait for stats flush
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+first_column_sum_check 's/.*no_metric=//g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+custom_assert_content_missing 'foo' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'bar' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'baz' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'corge' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'quux=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'grault=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/dynstats_overflow-vg.sh b/tests/dynstats_overflow-vg.sh
new file mode 100755
index 0000000..90e377c
--- /dev/null
+++ b/tests/dynstats_overflow-vg.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# added 2015-11-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats_overflow-vg.sh\]: test for gathering stats when metrics exceed provisioned capacity
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" maxCardinality="3")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+injectmsg_file $srcdir/testsuites/dynstats_input_more_0
+injectmsg_file $srcdir/testsuites/dynstats_input_more_1
+wait_queueempty
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+
+custom_assert_content_missing 'quux' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'corge' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'grault' "${RSYSLOG_DYNNAME}.out.stats.log"
+
+first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+
+#ttl-expiry(2*ttl in worst case, ttl + delta in best) so metric-names reset should have happened
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+. $srcdir/diag.sh await-stats-flush-after-block
+
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+
+first_column_sum_check 's/.*metrics_purged=\([0-9]*\)/\1/g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+
+rm ${RSYSLOG_DYNNAME}.out.stats.log
+issue_HUP #reopen stats file
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+injectmsg_file $srcdir/testsuites/dynstats_input_more_2
+wait_queueempty
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+content_check "quux 007 -6"
+content_check "corge 008 -6"
+content_check "quux 009 -6"
+content_check "foo 010 0"
+content_check "corge 011 -6"
+content_check "grault 012 -6"
+content_check "foo 013 0"
+content_check "corge 014 0"
+content_check "grault 015 0"
+content_check "quux 016 0"
+content_check "foo 017 -6"
+content_check "corge 018 0"
+
+first_column_sum_check 's/.*corge=\([0-9]*\)/\1/g' 'corge=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+first_column_sum_check 's/.*grault=\([0-9]*\)/\1/g' 'grault=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*quux=\([0-9]*\)/\1/g' 'quux=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+
+first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+. $srcdir/diag.sh await-stats-flush-after-block
+
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+first_column_sum_check 's/.*metrics_purged=\([0-9]*\)/\1/g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+
+custom_assert_content_missing 'foo' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/dynstats_overflow.sh b/tests/dynstats_overflow.sh
new file mode 100755
index 0000000..b63d812
--- /dev/null
+++ b/tests/dynstats_overflow.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# added 2015-11-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" maxCardinality="3")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+injectmsg_file $srcdir/testsuites/dynstats_input_more_0
+injectmsg_file $srcdir/testsuites/dynstats_input_more_1
+wait_queueempty
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+
+#first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+first_column_sum_check 's/.*foo=//g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+first_column_sum_check 's/.*bar=//g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=//g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+
+custom_assert_content_missing 'quux' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'corge' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'grault' "${RSYSLOG_DYNNAME}.out.stats.log"
+
+first_column_sum_check 's/.*new_metric_add=//g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=//g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 5
+first_column_sum_check 's/.*no_metric=//g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+
+#ttl-expiry(2*ttl in worst case, ttl + delta in best) so metric-names reset should have happened
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+. $srcdir/diag.sh await-stats-flush-after-block
+
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+
+first_column_sum_check 's/.*metrics_purged=//g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+
+rm ${RSYSLOG_DYNNAME}.out.stats.log
+issue_HUP #reopen stats file
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+injectmsg_file $srcdir/testsuites/dynstats_input_more_2
+wait_queueempty
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+content_check "quux 007 -6"
+content_check "corge 008 -6"
+content_check "quux 009 -6"
+content_check "foo 010 0"
+content_check "corge 011 -6"
+content_check "grault 012 -6"
+content_check "foo 013 0"
+content_check "corge 014 0"
+content_check "grault 015 0"
+content_check "quux 016 0"
+content_check "foo 017 -6"
+content_check "corge 018 0"
+
+first_column_sum_check 's/.*corge=//g' 'corge=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+first_column_sum_check 's/.*grault=//g' 'grault=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*quux=//g' 'quux=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+
+first_column_sum_check 's/.*new_metric_add=//g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=//g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*no_metric=//g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+. $srcdir/diag.sh await-stats-flush-after-block
+
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+
+first_column_sum_check 's/.*metrics_purged=//g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+
+custom_assert_content_missing 'foo' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/dynstats_prevent_premature_eviction-vg.sh b/tests/dynstats_prevent_premature_eviction-vg.sh
new file mode 100755
index 0000000..c61927a
--- /dev/null
+++ b/tests/dynstats_prevent_premature_eviction-vg.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# added 2016-04-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats_prevent_premature_eviction-vg.sh\]: test for ensuring metrics are not evicted before unused-ttl with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+injectmsg_file $srcdir/testsuites/dynstats_input_2
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+injectmsg_file $srcdir/testsuites/dynstats_input_3
+. $srcdir/diag.sh await-stats-flush-after-block
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+content_check "foo 001 0"
+content_check "foo 006 0"
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+ # because dyn-accumulators for existing metrics were posted-to under a second, they should not have been evicted
+custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log"
+# sum is high because accumulators were never reset, and we expect them to last specific number of cycles(when we posted before ttl expiry)
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 6
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+exit_test
diff --git a/tests/dynstats_prevent_premature_eviction.sh b/tests/dynstats_prevent_premature_eviction.sh
new file mode 100755
index 0000000..f86eb43
--- /dev/null
+++ b/tests/dynstats_prevent_premature_eviction.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# test for ensuring metrics are not evicted before unused-ttl
+# added 2016-04-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+rst_msleep 1000
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+rst_msleep 4000
+injectmsg_file $srcdir/testsuites/dynstats_input_2
+rst_msleep 4000
+injectmsg_file $srcdir/testsuites/dynstats_input_3
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+content_check "foo 001 0"
+content_check "foo 006 0"
+shutdown_when_empty
+wait_shutdown
+# because dyn-accumulators for existing metrics were posted-to under a second, they should not have been evicted
+custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log"
+# sum is high because accumulators were never reset, and we expect them to last specific number of cycles(when we posted before ttl expiry)
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 6
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+exit_test
diff --git a/tests/dynstats_reset-vg.sh b/tests/dynstats_reset-vg.sh
new file mode 100755
index 0000000..06060b6
--- /dev/null
+++ b/tests/dynstats_reset-vg.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# added 2015-11-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[dynstats_reset-vg.sh\]: test for gathering stats with a known-dyn-metrics reset in-between
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+rst_msleep 8100 #two seconds for unused-metrics to be kept under observation, another two them to be cleared off
+injectmsg_file $srcdir/testsuites/dynstats_input_2
+rst_msleep 8100
+injectmsg_file $srcdir/testsuites/dynstats_input_3
+rst_msleep 8100
+wait_queueempty
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+ # because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that
+custom_assert_content_missing 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'foo=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log"
+# but actual reported stats (aggregate) should match
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+exit_test
diff --git a/tests/dynstats_reset.sh b/tests/dynstats_reset.sh
new file mode 100755
index 0000000..30e47d2
--- /dev/null
+++ b/tests/dynstats_reset.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# added 2015-11-13 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
+
+dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
+ set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
+} else {
+ set $.increment_successful = -1;
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+injectmsg_file "$srcdir/testsuites/dynstats_input_1"
+rst_msleep 8100
+injectmsg_file "$srcdir/testsuites/dynstats_input_2"
+rst_msleep 8100
+injectmsg_file "$srcdir/testsuites/dynstats_input_3"
+rst_msleep 8100
+wait_queueempty
+content_check "foo 001 0"
+content_check "bar 002 0"
+content_check "baz 003 0"
+content_check "foo 004 0"
+content_check "baz 005 0"
+content_check "foo 006 0"
+shutdown_when_empty
+wait_shutdown
+ # because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that
+custom_assert_content_missing 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'foo=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log"
+# but actual reported stats (aggregate) should match
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' ${RSYSLOG_DYNNAME}.out.stats.log 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' ${RSYSLOG_DYNNAME}.out.stats.log 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' ${RSYSLOG_DYNNAME}.out.stats.log 2
+first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 6
+first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0
+first_column_sum_check 's/.*metrics_purged=\([0-9]*\)/\1/g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 6
+exit_test
diff --git a/tests/dynstats_reset_without_pstats_reset.sh b/tests/dynstats_reset_without_pstats_reset.sh
new file mode 100755
index 0000000..13e69e9
--- /dev/null
+++ b/tests/dynstats_reset_without_pstats_reset.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# test to ensure correctness of stats-ctr reset when pstats reset is turned off
+# added 2015-11-16 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="off" Ruleset="stats" bracketing="on")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+dyn_stats(name="msg_stats_resettable_on" resettable="on")
+dyn_stats(name="msg_stats_resettable_off" resettable="off")
+dyn_stats(name="msg_stats_resettable_default")
+
+set $.msg_prefix = field($msg, 32, 1);
+
+set $.x = dyn_inc("msg_stats_resettable_on", $.msg_prefix);
+set $.y = dyn_inc("msg_stats_resettable_off", $.msg_prefix);
+set $.z = dyn_inc("msg_stats_resettable_default", $.msg_prefix);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+injectmsg_file $srcdir/testsuites/dynstats_input_2
+wait_queueempty
+sleep 1
+injectmsg_file $srcdir/testsuites/dynstats_input_3
+wait_queueempty
+sleep 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "foo 006"
+custom_content_check 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+. $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3
+first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1
+first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2
+exit_test
diff --git a/tests/elasticsearch-error-format-check.py b/tests/elasticsearch-error-format-check.py
new file mode 100644
index 0000000..f8f091d
--- /dev/null
+++ b/tests/elasticsearch-error-format-check.py
@@ -0,0 +1,137 @@
+import json
+import sys
+import os
+def checkDefaultErrorFile():
+ with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file:
+ json_data = json.load(json_file)
+ indexCount =0
+ replyCount=0
+ for item in json_data:
+ if item == "request":
+ for reqItem in json_data[item]:
+ if reqItem == "url":
+ print("url found")
+ print(reqItem)
+ elif reqItem == "postdata":
+ print("postdata found")
+ indexCount = str(json_data[item]).count('\"_index\":')
+ print(reqItem)
+ else:
+ print(reqItem)
+ print("Unknown item found")
+ sys.exit(1)
+
+ elif item == "reply":
+ for replyItem in json_data[item]:
+ if replyItem == "items":
+ print(json_data[item][replyItem])
+ replyCount = str(json_data[item][replyItem]).count('_index')
+ elif replyItem == "errors":
+ print("error node found")
+ elif replyItem == "took":
+ print("took node found")
+ else:
+ print(replyItem)
+ print("Unknown item found")
+ sys.exit(3)
+
+ else:
+ print(item)
+ print("Unknown item found")
+ print("error")
+ sys.exit(4)
+ if replyCount == indexCount :
+ return 0
+ else:
+ sys.exit(7)
+ return 0
+
+
+def checkErrorOnlyFile():
+ with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file:
+ json_data = json.load(json_file)
+ indexCount =0
+ replyCount=0
+ for item in json_data:
+ if item == "request":
+ print(json_data[item])
+ indexCount = str(json_data[item]).count('\"_index\":')
+
+
+ elif item == "url":
+ print("url found")
+
+
+ elif item == "reply":
+ print(json_data[item])
+ replyCount = str(json_data[item]).count('\"_index\":')
+
+ else:
+ print(item)
+ print("Unknown item found")
+ print("error")
+ sys.exit(4)
+ if replyCount == indexCount :
+ return 0
+ else:
+ sys.exit(7)
+ return 0
+
+def checkErrorInterleaved():
+ with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file:
+ json_data = json.load(json_file)
+ indexCount =0
+ replyCount=0
+ for item in json_data:
+ print(item)
+ if item == "response":
+ for responseItem in json_data[item]:
+ print(responseItem)
+ for res in responseItem:
+ print(res)
+ if res == "request":
+ print(responseItem[res])
+ indexCount = str(responseItem[res]).count('\"_index\":')
+ print("request count ", indexCount)
+ elif res == "reply":
+ print(responseItem[res])
+ replyCount = str(responseItem[res]).count('\"_index\":')
+ print("reply count ", replyCount)
+ else:
+ print(res)
+ print("Unknown item found")
+ sys.exit(9)
+ if replyCount != indexCount :
+ sys.exit(8)
+
+
+
+ elif item == "url":
+ print("url found")
+
+
+
+
+ else:
+ print(item)
+ print("Unknown item found")
+ sys.exit(4)
+
+ return 0
+
+def checkInterleaved():
+ return checkErrorInterleaved()
+
+if __name__ == "__main__":
+ option = sys.argv[1]
+ if option == "default":
+ checkDefaultErrorFile()
+ elif option == "erroronly":
+ checkErrorOnlyFile()
+ elif option == "errorinterleaved":
+ checkErrorInterleaved()
+ elif option == "interleaved":
+ checkErrorInterleaved()
+ else:
+ print("Usage: <script> <default|erroronly|errorinterleaved>")
+ sys.exit(6)
diff --git a/tests/elasticsearch-stop.sh b/tests/elasticsearch-stop.sh
new file mode 100755
index 0000000..1029431
--- /dev/null
+++ b/tests/elasticsearch-stop.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# This is not a real test, but a script to stop ElasticSearch when all tests
+# are done (or for manual testing).
+# Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cleanup_elasticsearch
+exit_test
diff --git a/tests/empty-app-name.sh b/tests/empty-app-name.sh
new file mode 100755
index 0000000..1b07c2e
--- /dev/null
+++ b/tests/empty-app-name.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# addd 2019-12-27 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+global(parser.PermitSlashInProgramname="off")
+
+template(name="outfmt" type="string" string="%syslogtag%,%programname%,%app-name%\n")
+local0.* action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -m 1 -M "\"<133>Aug 6 16:57:54 host /no-app-name msgh ...x\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="/no-app-name,,-"
+cmp_exact
+exit_test
diff --git a/tests/empty-hostname.sh b/tests/empty-hostname.sh
new file mode 100755
index 0000000..e083368
--- /dev/null
+++ b/tests/empty-hostname.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This tests checks for a anomaly we have seen in practice:
+# gethostname() may return an empty string as hostname (""). This broke
+# some versions of rsyslog, newer ones return "localhost" in that case.
+# The test is done with the help of a preload library specifically written
+# for this purpose (liboverride_gethostname.so). It will override
+# gethostname() and return an empty string. Then, the test checks if the
+# hardcoded default of "localhost-empty-hostname" is used.
+# Note that the test may fail if the library is not properly preloaded.
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "AIX" "we cannot preload required dummy lib"
+generate_conf
+add_conf '
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+export RSYSLOG_PRELOAD=.libs/liboverride_gethostname.so
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+grep " localhost-empty-hostname " < $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "expected hostname \"localhost-empty-hostname\" not found in logs, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/empty-prop-comparison.sh b/tests/empty-prop-comparison.sh
new file mode 100755
index 0000000..7d703cc
--- /dev/null
+++ b/tests/empty-prop-comparison.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# addd 2016-07-08 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+set $!doOutput = "";
+if $msg contains "msgnum:0" then
+ set $!doOutput = "1";
+
+if $!doOutput == "" then stop
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0
+<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/empty-ruleset.sh b/tests/empty-ruleset.sh
new file mode 100755
index 0000000..4e258d7
--- /dev/null
+++ b/tests/empty-ruleset.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Copyright 2014-11-20 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+custom_wait_file_lines() {
+ wait_file_lines "$RSYSLOG_OUT_LOG" 10000
+}
+export QUEUE_EMPTY_CHECK_FUNC=custom_wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+$MainMsgQueueTimeoutShutdown 10000
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="real")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="empty")
+
+$template outfmt,"%msg:F,58:2%\n"
+
+ruleset(name="empty") {
+}
+
+ruleset(name="real") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+assign_tcpflood_port2 "${RSYSLOG_DYNNAME}.tcpflood_port2"
+tcpflood -p$TCPFLOOD_PORT2 -m5000 -i0 # these should NOT show up
+tcpflood -p$TCPFLOOD_PORT -m10000 -i5000
+tcpflood -p$TCPFLOOD_PORT2 -m500 -i15000 # these should NOT show up
+shutdown_when_empty
+wait_shutdown
+seq_check 5000 14999
+exit_test
diff --git a/tests/err1.rstest b/tests/err1.rstest
new file mode 100644
index 0000000..8c56887
--- /dev/null
+++ b/tests/err1.rstest
@@ -0,0 +1,7 @@
+# This test case check for an error condition
+result: -2051
+in:
+'test 1' <> == $hostname
+$$$
+out:
+$$$
diff --git a/tests/es-basic-bulk-vg.sh b/tests/es-basic-bulk-vg.sh
new file mode 100755
index 0000000..ab41f3f
--- /dev/null
+++ b/tests/es-basic-bulk-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/es-basic-bulk.sh
diff --git a/tests/es-basic-bulk.sh b/tests/es-basic-bulk.sh
new file mode 100755
index 0000000..d9935cd
--- /dev/null
+++ b/tests/es-basic-bulk.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" {
+ action(type="omelasticsearch"
+ template="tpl"
+ serverport=`echo $ES_PORT`
+ searchIndex="rsyslog_testbench"
+ bulkmode="on")
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata $NUMMESSAGES $ES_PORT
+seq_check
+exit_test
diff --git a/tests/es-basic-errfile-empty.sh b/tests/es-basic-errfile-empty.sh
new file mode 100755
index 0000000..92fb99c
--- /dev/null
+++ b/tests/es-basic-errfile-empty.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=1500 # slow test, thus low number - large number is NOT necessary
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ template="tpl"
+ serverport=`echo $ES_PORT`
+ searchIndex="rsyslog_testbench"
+ errorFile="./'${RSYSLOG_DYNNAME}.errorfile'")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata
+if [ -f ${RSYSLOG_DYNNAME}.errorfile ]
+then
+ echo "error: error file exists!"
+ error_exit 1
+fi
+seq_check
+exit_test
diff --git a/tests/es-basic-errfile-popul.sh b/tests/es-basic-errfile-popul.sh
new file mode 100755
index 0000000..c85ef83
--- /dev/null
+++ b/tests/es-basic-errfile-popul.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=1000 # slow test, thus low number - large number is NOT necessary
+ensure_elasticsearch_ready
+
+init_elasticsearch
+curl -H 'Content-Type: application/json' -XPUT localhost:19200/rsyslog_testbench/ -d '{
+ "mappings": {
+ "test-type": {
+ "properties": {
+ "msgnum": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+}'
+generate_conf
+add_conf '
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"x%msg:F,58:2%\"}")
+
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ searchType="test-type"
+ serverport="19200"
+ bulkmode="off"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+if [ ! -f ${RSYSLOG_DYNNAME}.errorfile ]
+then
+ echo "error: error file does not exist!"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/es-basic-es6.0.sh b/tests/es-basic-es6.0.sh
new file mode 100755
index 0000000..bfcdbbf
--- /dev/null
+++ b/tests/es-basic-es6.0.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=2000 # slow test
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata
+seq_check
+exit_test
diff --git a/tests/es-basic-es7.14.sh b/tests/es-basic-es7.14.sh
new file mode 100755
index 0000000..744ce68
--- /dev/null
+++ b/tests/es-basic-es7.14.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-7.14.1-linux-x86_64.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=2000 # slow test
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata
+seq_check
+exit_test
diff --git a/tests/es-basic-ha-vg.sh b/tests/es-basic-ha-vg.sh
new file mode 100755
index 0000000..60899ee
--- /dev/null
+++ b/tests/es-basic-ha-vg.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ template="tpl"
+ serverport=`echo $ES_PORT`
+ searchIndex="rsyslog_testbench"
+ bulkmode="on")
+'
+startup_vg
+injectmsg
+wait_queueempty
+shutdown_when_empty
+wait_shutdown_vg
+es_getdata $NUMMESSAGES $ES_PORT
+seq_check
+exit_test
diff --git a/tests/es-basic-ha.sh b/tests/es-basic-ha.sh
new file mode 100755
index 0000000..f676771
--- /dev/null
+++ b/tests/es-basic-ha.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="off" Ruleset="stats" bracketing="on" format="json")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ server=["localhost", "http://localhost/", "localhost:9201"]
+ serverport="19200"
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+'
+startup
+injectmsg 0 100
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+shutdown_when_empty
+wait_shutdown
+es_getdata 100 19200
+seq_check 0 99
+# The configuration makes every other request from message #3 fail checkConn (N/2-1)
+custom_content_check '"failed.checkConn": 49' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/es-basic-server.sh b/tests/es-basic-server.sh
new file mode 100755
index 0000000..176e4d4
--- /dev/null
+++ b/tests/es-basic-server.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export NUMMESSAGES=1500 # slow test, thus low number - large number is NOT necessary
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ server="localhost"
+ serverport=`echo $ES_PORT`
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata
+seq_check
+exit_test
diff --git a/tests/es-basic-vg.sh b/tests/es-basic-vg.sh
new file mode 100755
index 0000000..bb273c3
--- /dev/null
+++ b/tests/es-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/es-basic.sh
diff --git a/tests/es-basic-vgthread.sh b/tests/es-basic-vgthread.sh
new file mode 100755
index 0000000..3c42fc2
--- /dev/null
+++ b/tests/es-basic-vgthread.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export NUMMESSAGES=5000 # test is pretty slow, so use a low number
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then {
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport=`echo $ES_PORT`
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+}
+'
+startup_vgthread
+injectmsg
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+es_getdata
+seq_check
+exit_test
diff --git a/tests/es-basic.sh b/tests/es-basic.sh
new file mode 100755
index 0000000..92e7f64
--- /dev/null
+++ b/tests/es-basic.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export NUMMESSAGES=1000 # 1000 is sufficient, as this test is pretty slow
+REBIND_INTERVAL=100 # should be enough to run several times for $NUMMESSAGES
+
+queue_empty_check() {
+ es_shutdown_empty_check && \
+ content_check --check-only --regex '"name": "omelasticsearch".*"submitted": '$NUMMESSAGES \
+ $RSYSLOG_DYNNAME.spool/omelasticsearch-stats.log
+}
+export QUEUE_EMPTY_CHECK_FUNC=queue_empty_check
+
+ensure_elasticsearch_ready
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'"$RSYSLOG_DYNNAME.spool"'/omelasticsearch-stats.log" log.syslog="off" format="cee")
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="'$ES_PORT'"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ rebindinterval="'$REBIND_INTERVAL'")
+'
+startup
+injectmsg 0 $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+
+es_getdata $NUMMESSAGES $ES_PORT
+seq_check 0 $(( NUMMESSAGES - 1 ))
+rc=0
+if [ -f ${RSYSLOG_DYNNAME}.spool/omelasticsearch-stats.log ] ; then
+ $PYTHON <${RSYSLOG_DYNNAME}.spool/omelasticsearch-stats.log -c '
+import sys,json
+nrecs = int(sys.argv[1])
+nrebinds = nrecs/int(sys.argv[2])-1
+expected = { "name": "omelasticsearch", "origin": "omelasticsearch", "submitted": nrecs,
+ "failed.http": 0, "failed.httprequests": 0, "failed.checkConn": 0, "failed.es": 0,
+ "response.success": 0, "response.bad": 0, "response.duplicate": 0, "response.badargument": 0,
+ "response.bulkrejection": 0, "response.other": 0, "rebinds": nrebinds }
+actual = {}
+for line in sys.stdin:
+ jstart = line.find("{")
+ if jstart >= 0:
+ hsh = json.loads(line[jstart:])
+ if hsh["origin"] == "omelasticsearch":
+ actual = hsh
+if not expected == actual:
+ sys.stderr.write("ERROR: expected stats not equal to actual stats\n")
+ sys.stderr.write("ERROR: expected {}\n".format(expected))
+ sys.stderr.write("ERROR: actual {}\n".format(actual))
+ sys.exit(1)
+' $NUMMESSAGES $REBIND_INTERVAL || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/omelasticsearch-stats.log; }
+else
+ echo error: stats file ${RSYSLOG_DYNNAME}.spool/omelasticsearch-stats.log not found
+ rc=1
+fi
+
+if [ $rc != 0 ] ; then
+ error_exit 1
+else
+ exit_test
+fi
diff --git a/tests/es-bulk-errfile-empty.sh b/tests/es-bulk-errfile-empty.sh
new file mode 100755
index 0000000..0237e6b
--- /dev/null
+++ b/tests/es-bulk-errfile-empty.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" {
+ action(type="omelasticsearch"
+ template="tpl"
+ serverport=`echo $ES_PORT`
+ searchIndex="rsyslog_testbench"
+ bulkmode="on"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile")
+}
+'
+startup
+injectmsg 0 $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+es_getdata $NUMMESSAGES $ES_PORT
+if [ -f ${RSYSLOG_DYNNAME}.errorfile ]; then
+ printf 'error: error file exists!\n'
+ cat -n ${RSYSLOG_DYNNAME}.errorfile
+ error_exit 1
+fi
+seq_check
+exit_test
diff --git a/tests/es-bulk-errfile-popul-def-format.sh b/tests/es-bulk-errfile-popul-def-format.sh
new file mode 100755
index 0000000..00cec88
--- /dev/null
+++ b/tests/es-bulk-errfile-popul-def-format.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+
+init_elasticsearch
+echo '{ "name" : "foo" }
+{"name": bar"}
+{"name": "baz"}
+{"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="list") {
+ constant(value="{\"")
+ property(name="$!key") constant(value="\":") property(name="$!obj")
+ constant(value="}")
+}
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+module(load="../plugins/imfile/.libs/imfile")
+ruleset(name="foo") {
+ set $!key = "my_obj";
+ set $!obj = $msg;
+ action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ serverport="19200"
+ searchType="test-type"
+ bulkmode="on"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile")
+}
+
+input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile"
+ Tag="foo"
+ Severity="info"
+ ruleset="foo")'
+startup
+shutdown_when_empty
+wait_shutdown
+
+$PYTHON $srcdir/elasticsearch-error-format-check.py default
+if [ $? -ne 0 ]
+then
+ echo "error: Format for error file different! " $?
+ error_exit 1
+fi
+exit_test
diff --git a/tests/es-bulk-errfile-popul-def-interleaved.sh b/tests/es-bulk-errfile-popul-def-interleaved.sh
new file mode 100755
index 0000000..6c423bb
--- /dev/null
+++ b/tests/es-bulk-errfile-popul-def-interleaved.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+
+init_elasticsearch
+echo '{ "name" : "foo" }
+{"name": bar"}
+{"name": "baz"}
+{"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="list") {
+ constant(value="{\"")
+ property(name="$!key") constant(value="\":") property(name="$!obj")
+ constant(value="}")
+}
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+module(load="../plugins/imfile/.libs/imfile")
+ruleset(name="foo") {
+ set $!key = "my_obj";
+ set $!obj = $msg;
+ action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ searchType="test-type"
+ serverport="19200"
+ bulkmode="on"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile"
+ interleaved="on")
+}
+
+input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile"
+ Tag="foo"
+ Severity="info"
+ ruleset="foo")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+$PYTHON $srcdir/elasticsearch-error-format-check.py interleaved
+
+if [ $? -ne 0 ]
+then
+ echo "error: Format for error file different! " $?
+ exit 1
+fi
+exit_test
diff --git a/tests/es-bulk-errfile-popul-erronly-interleaved.sh b/tests/es-bulk-errfile-popul-erronly-interleaved.sh
new file mode 100755
index 0000000..dd50b77
--- /dev/null
+++ b/tests/es-bulk-errfile-popul-erronly-interleaved.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+
+init_elasticsearch
+echo '{ "name" : "foo" }
+{"name": bar"}
+{"name": "baz"}
+{"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="list") {
+ constant(value="{\"")
+ property(name="$!key") constant(value="\":") property(name="$!obj")
+ constant(value="}")
+}
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+module(load="../plugins/imfile/.libs/imfile")
+ruleset(name="foo") {
+ set $!key = "my_obj";
+ set $!obj = $msg;
+ action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ searchType="test-type"
+ bulkmode="on"
+ serverport="19200"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile"
+ erroronly="on"
+ interleaved="on")
+}
+
+input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile"
+ Tag="foo"
+ Severity="info"
+ ruleset="foo")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+$PYTHON $srcdir/elasticsearch-error-format-check.py errorinterleaved
+
+if [ $? -ne 0 ]
+then
+ echo "error: Format for error file different! " $?
+ exit 1
+fi
+exit_test
diff --git a/tests/es-bulk-errfile-popul-erronly.sh b/tests/es-bulk-errfile-popul-erronly.sh
new file mode 100755
index 0000000..9db619f
--- /dev/null
+++ b/tests/es-bulk-errfile-popul-erronly.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+
+init_elasticsearch
+echo '{ "name" : "foo" }
+{"name": bar"}
+{"name": "baz"}
+{"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="list") {
+ constant(value="{\"")
+ property(name="$!key") constant(value="\":") property(name="$!obj")
+ constant(value="}")
+}
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+module(load="../plugins/imfile/.libs/imfile")
+ruleset(name="foo") {
+ set $!key = "my_obj";
+ set $!obj = $msg;
+ action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ searchType="test-type"
+ serverport="19200"
+ bulkmode="on"
+ errorFile="'${RSYSLOG_DYNNAME}'.errorfile"
+ erroronly="on")
+}
+
+input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile"
+ Tag="foo"
+ Severity="info"
+ ruleset="foo")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+$PYTHON $srcdir/elasticsearch-error-format-check.py erroronly
+
+if [ $? -ne 0 ]
+then
+ echo "error: Format for error file different! " $?
+ error_exit 1
+fi
+exit_test
diff --git a/tests/es-bulk-errfile-popul.sh b/tests/es-bulk-errfile-popul.sh
new file mode 100755
index 0000000..24f1113
--- /dev/null
+++ b/tests/es-bulk-errfile-popul.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+ensure_elasticsearch_ready
+
+init_elasticsearch
+curl -H 'Content-Type: application/json' -XPUT localhost:19200/rsyslog_testbench/ -d '{
+ "mappings": {
+ "test-type": {
+ "properties": {
+ "msgnum": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+}'
+generate_conf
+add_conf '
+# Note: we must mess up with the template, because we can not
+# instruct ES to put further constraints on the data type and
+# values. So we require integer and make sure it is none.
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"x%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ searchType="test-type"
+ serverport="19200"
+ bulkmode="on"
+ errorFile="./'${RSYSLOG_DYNNAME}'.errorfile")
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty
+wait_shutdown
+if [ ! -f ${RSYSLOG_DYNNAME}.errorfile ]
+then
+ echo "error: error file does not exist!"
+ exit 1
+fi
+exit_test
diff --git a/tests/es-bulk-retry.sh b/tests/es-bulk-retry.sh
new file mode 100755
index 0000000..b4bff85
--- /dev/null
+++ b/tests/es-bulk-retry.sh
@@ -0,0 +1,298 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+export ES_PORT=19200
+export NUMMESSAGES=100
+
+# export RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT=120000
+override_test_timeout 120
+#export USE_VALGRIND="YES" # to enable this to run under valgrind
+ensure_elasticsearch_ready --no-start
+
+# change settings to cause bulk rejection errors
+case "$ES_DOWNLOAD" in
+ elasticsearch-5.*) es_option="thread_pool.bulk"
+ es_mapping_uses_type=true
+ es_search_type="test-type" ;;
+ *) es_option="thread_pool.write"
+ es_mapping_uses_type=false
+ es_search_type="_doc" ;;
+esac
+cat >> $dep_work_dir/es/config/elasticsearch.yml <<EOF
+${es_option}.queue_size: 1
+${es_option}.size: 1
+EOF
+start_elasticsearch
+
+generate_conf
+add_conf '
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'$RSYSLOG_DYNNAME'.spool/es-stats.log" log.syslog="off" format="cee")
+
+set $.msgnum = field($msg, 58, 2);
+set $.testval = cnum($.msgnum % 4);
+
+if $.testval == 0 then {
+ # these should be successful
+ set $!msgnum = $.msgnum;
+ set $.extrafield = "notmessage";
+} else if $.testval == 1 then {
+ # these should cause "hard" errors
+ set $!msgnum = "x" & $.msgnum;
+ set $.extrafield = "notmessage";
+} else if $.testval == 2 then {
+ # these should be successful
+ set $!msgnum = $.msgnum;
+ set $.extrafield = "message";
+} else {
+ # these should cause "hard" errors
+ set $!msgnum = "x" & $.msgnum;
+ set $.extrafield = "message";
+}
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%$!msgnum%\",\"%$.extrafield%\":\"extrafieldvalue\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+template(name="id-template" type="string" string="%$.es_msg_id%")
+
+ruleset(name="error_es") {
+ action(type="omfile" template="RSYSLOG_DebugFormat" file="'$RSYSLOG_DYNNAME'.spool/es-bulk-errors.log")
+}
+
+ruleset(name="try_es") {
+ set $.sendrec = 1;
+ if strlen($.omes!status) > 0 then {
+ # retry case
+ if ($.omes!status == 200) or ($.omes!status == 201) or (($.omes!status == 409) and ($.omes!writeoperation == "create")) then {
+ reset $.sendrec = 0; # successful
+ }
+ if ($.omes!writeoperation == "unknown") or (strlen($.omes!error!type) == 0) or (strlen($.omes!error!reason) == 0) then {
+ call error_es
+ reset $.sendrec = 0;
+ }
+ if ($.omes!status == 400) or ($.omes!status < 200) then {
+ call error_es
+ reset $.sendrec = 0;
+ }
+ if strlen($!notmessage) > 0 then {
+ set $.extrafield = "notmessage";
+ } else {
+ set $.extrafield = "message";
+ }
+ }
+ if $.sendrec == 1 then {
+ if strlen($.omes!_id) > 0 then {
+ set $.es_msg_id = $.omes!_id;
+ } else {
+ # NOTE: in production code, use $uuid - depends on rsyslog being compiled with --enable-uuid
+ set $.es_msg_id = $.msgnum;
+ }
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="'${ES_PORT:-19200}'"
+ template="tpl"
+ writeoperation="create"
+ bulkid="id-template"
+ dynbulkid="on"
+ bulkmode="on"
+ retryfailures="on"
+ retryruleset="try_es"
+ searchType="'${es_search_type}'"
+ searchIndex="rsyslog_testbench")
+ }
+}
+
+if $msg contains "msgnum:" then {
+ call try_es
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+if [ "$es_mapping_uses_type" = true ]; then
+ curl -s -H 'Content-Type: application/json' -XPUT localhost:${ES_PORT:-19200}/rsyslog_testbench/ -d '{
+ "mappings": {
+ "test-type": {
+ "properties": {
+ "msgnum": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+}
+' | $PYTHON -mjson.tool
+else
+ # we add 10 shards so we're more likely to get queue rejections
+ curl -s -H 'Content-Type: application/json' -XPUT localhost:${ES_PORT:-19200}/rsyslog_testbench/ -d '{
+ "settings": {
+ "index.number_of_shards": 10
+ },
+ "mappings": {
+ "properties": {
+ "msgnum": {
+ "type": "integer"
+ }
+ }
+ }
+}
+' | $PYTHON -mjson.tool
+fi
+
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="debug.log"
+startup
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+success=50
+badarg=50
+./msleep 5000
+injectmsg 0 $NUMMESSAGES
+./msleep 1500; cat $RSYSLOG_OUT_LOG # debuging - we sometimes miss 1 message
+wait_content '"response.success": 50' $RSYSLOG_DYNNAME.spool/es-stats.log
+wait_content '"response.badargument": 50' $RSYSLOG_DYNNAME.spool/es-stats.log
+shutdown_when_empty
+wait_shutdown
+es_getdata $NUMMESSAGES $ES_PORT
+rc=$?
+
+stop_elasticsearch
+cleanup_elasticsearch
+
+if [ -f $RSYSLOG_DYNNAME.work ] ; then
+ < $RSYSLOG_DYNNAME.work \
+ $PYTHON -c '
+import sys,json
+try:
+ # Python 2 forward compatibility
+ range = xrange
+except NameError:
+ pass
+records = int(sys.argv[1])
+extra_recs = open(sys.argv[2], "w")
+missing_recs = open(sys.argv[3], "w")
+expectedrecs = {}
+rc = 0
+nextra = 0
+nmissing = 0
+for ii in range(0, records*2, 2):
+ ss = "{:08}".format(ii)
+ expectedrecs[ss] = ss
+for item in json.load(sys.stdin)["hits"]["hits"]:
+ msgnum = item["_source"]["msgnum"]
+ if msgnum in expectedrecs:
+ del expectedrecs[msgnum]
+ else:
+ extra_recs.write("FAIL: found unexpected msgnum {} in record\n".format(msgnum))
+ nextra += 1
+for item in expectedrecs:
+ missing_recs.write("FAIL: msgnum {} was missing in Elasticsearch\n".format(item))
+ nmissing += 1
+if nextra > 0:
+ print("FAIL: Found {} unexpected records - see {} for the full list.".format(nextra, sys.argv[2]))
+ rc = 1
+if nmissing > 0:
+ print("FAIL: Found {} missing records - see {} for the full list.".format(nmissing, sys.argv[3]))
+ rc = 1
+sys.exit(rc)
+' $success ${RSYSLOG_DYNNAME}.spool/extra_records ${RSYSLOG_DYNNAME}.spool/missing_records || { rc=$?; errmsg="FAIL: found unexpected or missing records in Elasticsearch"; }
+ if [ $rc = 0 ] ; then
+ echo "good - no missing or unexpected records were found in Elasticsearch"
+ fi
+else
+ errmsg="FAIL: elasticsearch output file $RSYSLOG_DYNNAME.work not found"
+ rc=1
+fi
+
+if [ -f ${RSYSLOG_DYNNAME}.spool/es-stats.log ] ; then
+ $PYTHON < ${RSYSLOG_DYNNAME}.spool/es-stats.log -c '
+import sys,json
+success = int(sys.argv[1])
+badarg = int(sys.argv[2])
+lasthsh = {}
+rc = 0
+for line in sys.stdin:
+ jstart = line.find("{")
+ if jstart >= 0:
+ hsh = json.loads(line[jstart:])
+ if hsh["name"] == "omelasticsearch":
+ lasthsh = hsh
+actualsuccess = lasthsh["response.success"]
+actualbadarg = lasthsh["response.badargument"]
+actualrej = lasthsh["response.bulkrejection"]
+actualsubmitted = lasthsh["submitted"]
+if actualsuccess != success:
+ print("FAIL: expected {} successful responses but omelasticsearch stats reported {}".format(success, actualsuccess))
+ rc = 1
+if actualbadarg != badarg:
+ print("FAIL: expected {} bad argument errors but omelasticsearch stats reported {}".format(badarg, actualbadarg))
+ rc = 1
+if actualrej == 0:
+ print("FAIL: there were no bulk index rejections reported by Elasticsearch")
+ rc = 1
+if actualsuccess + actualbadarg + actualrej != actualsubmitted:
+ print("FAIL: The sum of the number of successful responses and bad argument errors and bulk index rejections {} did not equal the number of requests actually submitted to Elasticsearch {}".format(actualsuccess + actualbadarg + actualrej, actualsubmitted))
+ rc = 1
+sys.exit(rc)
+' $success $badarg || { rc=$?; errmsg="FAIL: expected responses not found in ${RSYSLOG_DYNNAME}.spool/es-stats.log"; }
+ if [ $rc = 0 ] ; then
+ echo "good - all expected stats were found in Elasticsearch stats file ${RSYSLOG_DYNNAME}.spool/es-stats.log"
+ fi
+else
+ errmsg="FAIL: stats file ${RSYSLOG_DYNNAME}.spool/es-stats.log not found"
+ rc=1
+fi
+
+if [ -f ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log ] ; then
+ found=0
+ for ii in $(seq --format="x%08.f" 1 2 $(expr 2 \* $badarg)) ; do
+ if grep -q '^[$][!]:{.*"msgnum": "'$ii'"' ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log ; then
+ (( found++ ))
+ else
+ errmsg="FAIL: missing message $ii in ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log"
+ rc=1
+ fi
+ done
+ if [ $found -ne $badarg ] ; then
+ errmsg="FAIL: found only $found of $badarg messages in ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log"
+ rc=1
+ fi
+ if grep -q '^[$][.]:{.*"omes": {' ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log ; then
+ :
+ else
+ errmsg="FAIL: es response info not found in ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log"
+ rc=1
+ fi
+ if grep -q '^[$][.]:{.*"status": 400' ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log ; then
+ :
+ else
+ errmsg="FAIL: status 400 not found in ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log"
+ rc=1
+ fi
+else
+ errmsg="FAIL: bulk error file ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log not found"
+ rc=1
+fi
+
+if [ $rc -eq 0 ] ; then
+ echo tests completed successfully
+else
+ cat $RSYSLOG_OUT_LOG
+ if [ -f ${RSYSLOG_DYNNAME}.spool/es-stats.log ] ; then
+ cat ${RSYSLOG_DYNNAME}.spool/es-stats.log
+ fi
+ if [ -f ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log ] ; then
+ cat ${RSYSLOG_DYNNAME}.spool/es-bulk-errors.log
+ fi
+ printf '\n%s\n' "$errmsg"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/es-duplicated-ruleset-vg.sh b/tests/es-duplicated-ruleset-vg.sh
new file mode 100755
index 0000000..06e58d5
--- /dev/null
+++ b/tests/es-duplicated-ruleset-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+echo temporarily disabled because it fails quite often - fix in progress
+exit 77
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/es-duplicated-ruleset.sh
diff --git a/tests/es-duplicated-ruleset.sh b/tests/es-duplicated-ruleset.sh
new file mode 100755
index 0000000..b61b091
--- /dev/null
+++ b/tests/es-duplicated-ruleset.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# The sole purpose of this test is to check that rsyslog "survives" the
+# duplicate ruleset definition and emits the proper error message. So we
+# do NOT need to have elasticsearch running to carry it out. We avoid
+# sending data to ES as this complicates things more than needed.
+# This is based on a real case, see
+# https://github.com/rsyslog/rsyslog/pull/3796
+# Thanks to Noriko Hosoi for providing the original test idea which
+# was then modified by Rainer Gerhards.
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+generate_conf
+add_conf '
+template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+ruleset(name="try_es") {
+ action(type="omelasticsearch"
+ server="localhost"
+ serverport=`echo $ES_PORT`
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ retryruleset="try_es"
+ )
+}
+
+ruleset(name="try_es") {
+ action(type="omelasticsearch"
+ server="localhost"
+ serverport=`echo $ES_PORT`
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ retryruleset="try_es"
+ )
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_immediate
+wait_shutdown
+content_check "ruleset 'try_es' specified more than once"
+exit_test
diff --git a/tests/es-execOnlyWhenPreviousSuspended.sh b/tests/es-execOnlyWhenPreviousSuspended.sh
new file mode 100755
index 0000000..4b72377
--- /dev/null
+++ b/tests/es-execOnlyWhenPreviousSuspended.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100 #10000
+ensure_elasticsearch_ready
+
+init_elasticsearch
+
+generate_conf
+add_conf '
+template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}")
+template(name="tpl2" type="string" string="%msg:F,58:2%\n")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then {
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ searchIndex="rsyslog_testbench"
+ action.resumeInterval="2"
+ action.resumeretrycount="1")
+
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="tpl2"
+ action.execOnlyWhenPreviousIsSuspended="on")
+
+ # this action just to count processed messages
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.syncfile")
+}
+'
+startup
+injectmsg 0 $NUMMESSAGES
+wait_file_lines $RSYSLOG_DYNNAME.syncfile $NUMMESSAGES
+stop_elasticsearch
+./msleep 1000
+injectmsg $NUMMESSAGES 1
+wait_file_lines $RSYSLOG_DYNNAME.syncfile $((NUMMESSAGES + 1))
+wait_queueempty
+injectmsg $(( NUMMESSAGES + 1 )) $NUMMESSAGES
+wait_file_lines $RSYSLOG_DYNNAME.syncfile $((NUMMESSAGES + 1 + NUMMESSAGES))
+start_elasticsearch
+
+shutdown_when_empty
+wait_shutdown
+
+seq_check $(( NUMMESSAGES + 1 )) $(( NUMMESSAGES * 2 ))
+es_getdata $NUMMESSAGES 19200
+seq_check 0 $(( NUMMESSAGES - 1 ))
+exit_test
diff --git a/tests/es-maxbytes-bulk.sh b/tests/es-maxbytes-bulk.sh
new file mode 100755
index 0000000..99a4afa
--- /dev/null
+++ b/tests/es-maxbytes-bulk.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz
+export ES_PORT=19200
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+
+init_elasticsearch
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+:msg, contains, "msgnum:" action(type="omelasticsearch"
+ template="tpl"
+ serverport="'$ES_PORT'"
+ searchIndex="rsyslog_testbench"
+ bulkmode="on"
+ maxbytes="1k")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata $NUMMESSAGES $ES_PORT
+seq_check
+exit_test
diff --git a/tests/es-searchType-empty.sh b/tests/es-searchType-empty.sh
new file mode 100755
index 0000000..bc0b01e
--- /dev/null
+++ b/tests/es-searchType-empty.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export ES_PORT=19200
+# Using the default will cause deprecation failures
+export ES_PORT_OPTION="transport.port"
+export NUMMESSAGES=2000 # slow test
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ searchType=""
+ template="tpl"
+ searchIndex="rsyslog_testbench")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata
+seq_check
+if grep "DEPRECATION" $dep_work_dir/es/logs/rsyslog-testbench_deprecation.log; then
+ echo "Found deprecations, failing!"
+ exit 1
+fi
+exit_test
diff --git a/tests/es-writeoperation.sh b/tests/es-writeoperation.sh
new file mode 100755
index 0000000..846f2f7
--- /dev/null
+++ b/tests/es-writeoperation.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+ensure_elasticsearch_ready
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ writeoperation="create"
+ searchIndex="rsyslog_testbench")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+if grep -q "omelasticsearch: writeoperation '1' requires bulkid" $RSYSLOG_OUT_LOG ; then
+ echo found correct error message
+else
+ echo Error: did not complain about incorrect writeoperation
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ writeoperation="unknown"
+ searchIndex="rsyslog_testbench")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+if grep -q "omelasticsearch: invalid value 'unknown' for writeoperation" $RSYSLOG_OUT_LOG ; then
+ echo found correct error message
+else
+ echo Error: did not complain about incorrect writeoperation
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/omelasticsearch/.libs/omelasticsearch")
+
+template(name="id-template" type="list") { constant(value="123456789") }
+
+if $msg contains "msgnum:" then
+ action(type="omelasticsearch"
+ server="127.0.0.1"
+ serverport="19200"
+ template="tpl"
+ writeoperation="create"
+ bulkid="id-template"
+ dynbulkid="on"
+ bulkmode="on"
+ searchIndex="rsyslog_testbench")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+init_elasticsearch
+
+export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check
+export NUMMESSAGES=1
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+es_getdata 1 $ES_PORT
+
+$PYTHON <$RSYSLOG_DYNNAME.work -c '
+import sys,json
+hsh = json.load(sys.stdin)
+try:
+ if hsh["hits"]["hits"][0]["_id"] == "123456789":
+ print("good - found expected value")
+ sys.exit(0)
+ print("Error: _id not expected value 123456789:", hsh["hits"]["hits"][0]["_id"])
+ sys.exit(1)
+except ValueError:
+ print("Error: output is not valid:", json.dumps(hsh,indent=2))
+ sys.exit(1)
+'
+
+if [ $? -eq 0 ] ; then
+ echo found correct response
+else
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+exit_test
diff --git a/tests/es_response_get_msgnum.py b/tests/es_response_get_msgnum.py
new file mode 100644
index 0000000..f8a5ed4
--- /dev/null
+++ b/tests/es_response_get_msgnum.py
@@ -0,0 +1,8 @@
+import json
+import os
+
+with open(os.environ['RSYSLOG_DYNNAME'] + ".work") as json_file:
+ json_data = json.load(json_file)
+ json_data = json_data["hits"]
+ for item in json_data["hits"]:
+ print(item["_source"]["msgnum"])
diff --git a/tests/exec_tpl-concurrency.sh b/tests/exec_tpl-concurrency.sh
new file mode 100755
index 0000000..af4bb0d
--- /dev/null
+++ b/tests/exec_tpl-concurrency.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test concurrency of exec_template function with msg variables
+# Added 2015-12-11 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on all flavors of Solaris."
+export NUMMESSAGES=500000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="interim" type="string" string="%$!tree!here!nbr%")
+template(name="outfmt" type="string" string="%$!interim%\n")
+template(name="all-json" type="string" string="%$!%\n")
+
+if $msg contains "msgnum:" then {
+ set $!tree!here!nbr = field($msg, 58, 2);
+ action(type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="all-json"
+ queue.type="linkedList")
+
+ set $!interim = exec_template("interim");
+ unset $!tree!here!nbr;
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ queue.type="fixedArray")
+}
+'
+startup
+tcpflood -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/execonlyonce.sh b/tests/execonlyonce.sh
new file mode 100755
index 0000000..5ab9739
--- /dev/null
+++ b/tests/execonlyonce.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test for the $ActionExecOnlyOnceEveryInterval directive.
+# We inject a couple of messages quickly during the interval,
+# then wait until the interval expires, then quickly inject
+# another set. After that, it is checked if exactly two messages
+# have arrived.
+# The once interval must be set to 3 seconds in the config file.
+# added 2009-11-12 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+$ActionExecOnlyOnceEveryInterval 3
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+tcpflood -m10 -i1
+# now wait until the interval definitely expires (at least we hope so...)
+printf 'wainting for interval to expire...\n'
+sleep 5
+# and inject another couple of messages
+tcpflood -m10 -i100
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="00000001
+00000100"
+cmp_exact
+exit_test
diff --git a/tests/execonlywhenprevsuspended-nonsusp-queue.sh b/tests/execonlywhenprevsuspended-nonsusp-queue.sh
new file mode 100755
index 0000000..eb5b87b
--- /dev/null
+++ b/tests/execonlywhenprevsuspended-nonsusp-queue.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# check if execonly...suspended works when the first action is *not*
+# suspended --> file1 must be created, file 2 not
+# rgerhards, 2015-05-27
+echo =====================================================================================
+echo \[execonlywhenprevsuspended-nonsusp-queue\]: test execonly...suspended functionality with non-suspended action and queue
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+main_queue(queue.workerthreads="1")
+
+# omtesting provides the ability to cause "SUSPENDED" action state
+module(load="../plugins/omtesting/.libs/omtesting")
+
+$MainMsgQueueTimeoutShutdown 100000
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt" name="ok")
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`
+ template="outfmt" name="susp"
+ queue.type="linkedList"
+ action.ExecOnlyWhenPreviousIsSuspended="on"
+ )
+}
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty
+wait_shutdown
+ls *.out.log
+seq_check 0 999
+if [ -e ${RSYSLOG2_OUT_LOG} ]; then
+ echo "error: \"suspended\" file exists, first 10 lines:"
+ $RS_HEADCMD ${RSYSLOG2_OUT_LOG}
+ exit 1
+fi
+exit_test
diff --git a/tests/execonlywhenprevsuspended-nonsusp.sh b/tests/execonlywhenprevsuspended-nonsusp.sh
new file mode 100755
index 0000000..c2d9ae2
--- /dev/null
+++ b/tests/execonlywhenprevsuspended-nonsusp.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# check if execonly...suspended works when the first action is *not*
+# suspended --> file1 must be created, file 2 not
+# rgerhards, 2015-05-27
+echo =====================================================================================
+echo \[execonlywhenprevsuspended-nonsusp\]: test execonly...suspended functionality with non-suspended action
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+main_queue(queue.workerthreads="1")
+
+# omtesting provides the ability to cause "SUSPENDED" action state
+module(load="../plugins/omtesting/.libs/omtesting")
+
+$MainMsgQueueTimeoutShutdown 100000
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt"
+ action.ExecOnlyWhenPreviousIsSuspended="on"
+ )
+}
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty
+wait_shutdown
+seq_check 0 999
+if [ -e ${RSYSLOG2_OUT_LOG} ]; then
+ echo "error: \"suspended\" file exists, first 10 lines:"
+ $RS_HEADCMD ${RSYSLOG2_OUT_LOG}
+ exit 1
+fi
+exit_test
diff --git a/tests/execonlywhenprevsuspended-queue.sh b/tests/execonlywhenprevsuspended-queue.sh
new file mode 100755
index 0000000..6bd82b0
--- /dev/null
+++ b/tests/execonlywhenprevsuspended-queue.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# rgerhards, 2015-05-27
+echo =====================================================================================
+echo \[execonlywhenprevsuspended-queue.sh\]: test execonly...suspended functionality with action on its own queue
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+main_queue(queue.workerthreads="1")
+
+# omtesting provides the ability to cause "SUSPENDED" action state
+module(load="../plugins/omtesting/.libs/omtesting")
+
+$MainMsgQueueTimeoutShutdown 100000
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+:msg, contains, "msgnum:" {
+ :omtesting:fail 2 0 # omtesting has only legacy params!
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt"
+ queue.type="linkedList"
+ action.ExecOnlyWhenPreviousIsSuspended="on"
+ )
+}
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty
+wait_shutdown
+seq_check 1 999
+exit_test
diff --git a/tests/execonlywhenprevsuspended.sh b/tests/execonlywhenprevsuspended.sh
new file mode 100755
index 0000000..9560241
--- /dev/null
+++ b/tests/execonlywhenprevsuspended.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# we test the execonly if previous is suspended directive. This is the
+# most basic test which solely tests a single case but no dependencies within
+# the ruleset.
+# rgerhards, 2010-06-23
+echo =====================================================================================
+echo \[execonlywhenprevsuspended.sh\]: test execonly...suspended functionality simple case
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+main_queue(queue.workerthreads="1")
+
+# omtesting provides the ability to cause "SUSPENDED" action state
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+$MainMsgQueueTimeoutShutdown 100000
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" :omtesting:fail 2 0
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 1 999
+exit_test
diff --git a/tests/execonlywhenprevsuspended2.sh b/tests/execonlywhenprevsuspended2.sh
new file mode 100755
index 0000000..4b54d17
--- /dev/null
+++ b/tests/execonlywhenprevsuspended2.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# we test the execonly if previous is suspended directive. For this,
+# we have an action that is suspended for all messages but the second.
+# we write two files: one only if the output is suspended and the other one
+# in all cases. This should thoroughly check the logic involved.
+# rgerhards, 2010-06-23
+echo ===============================================================================
+echo \[execonlywhenprevsuspended2.sh\]: test execonly...suspended functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# omtesting provides the ability to cause "SUSPENDED" action state
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+$MainMsgQueueTimeoutShutdown 100000
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" :omtesting:fail 2 0
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+# note that we MUST re-set PrevSusp, else it will remain active
+# for all other actions as well (this tells us how bad the current
+# config language is...). -- rgerhards, 2010-06-24
+$ActionExecOnlyWhenPreviousIsSuspended off
+
+:msg, contains, "msgnum:" ./'"${RSYSLOG2_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+echo check file 1
+seq_check 1 999
+echo check file 2
+seq_check2 0 999
+exit_test
diff --git a/tests/execonlywhenprevsuspended3.sh b/tests/execonlywhenprevsuspended3.sh
new file mode 100755
index 0000000..b4c60be
--- /dev/null
+++ b/tests/execonlywhenprevsuspended3.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# we test the execonly if previous is suspended directive.
+# This test checks if, within the same rule, one action can be set
+# to emit only if the previous was suspended while the next action
+# always sends data.
+# rgerhards, 2010-06-24
+echo ===============================================================================
+echo \[execonlywhenprevsuspended3.sh\]: test execonly...suspended functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# omtesting provides the ability to cause "SUSPENDED" action state
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+$MainMsgQueueTimeoutShutdown 100000
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" :omtesting:fail 2 0
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+# note that we MUST re-set PrevSusp, else it will remain active
+# for all other actions as well (this tells us how bad the current
+# config language is...). -- rgerhards, 2010-06-24
+$ActionExecOnlyWhenPreviousIsSuspended off
+& ./'"${RSYSLOG2_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+echo check file 1
+seq_check 1 999
+echo check file 2
+seq_check2 0 999
+exit_test
diff --git a/tests/execonlywhenprevsuspended4.sh b/tests/execonlywhenprevsuspended4.sh
new file mode 100755
index 0000000..c9cd599
--- /dev/null
+++ b/tests/execonlywhenprevsuspended4.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# we test the execonly if previous is suspended directive.
+# This test checks if multiple backup actions can be defined.
+# rgerhards, 2010-06-24
+echo ===============================================================================
+echo \[execonlywhenprevsuspended4.sh\]: test execonly..suspended multi backup action
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# omtesting provides the ability to cause "SUSPENDED" action state
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+$MainMsgQueueTimeoutShutdown 100000
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" :omtesting:fail 2 0
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+# note that $ActionExecOnlyWhenPreviousIsSuspended on is still active!
+& ./'"${RSYSLOG2_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 1000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 1 999
+if [[ -s ${RSYSLOG2_OUT_LOG} ]] ; then
+ echo failure: second output file has data where it should be empty
+ exit 1
+fi ;
+exit_test
diff --git a/tests/execonlywhenprevsuspended_multiwrkr.sh b/tests/execonlywhenprevsuspended_multiwrkr.sh
new file mode 100755
index 0000000..9629ff9
--- /dev/null
+++ b/tests/execonlywhenprevsuspended_multiwrkr.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# rgerhards, 2013-12-05
+echo =====================================================================================
+echo \[execonlywhenprevsuspended_multiwrkr.sh\]: test execonly...suspended functionality multiworker case
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# omtesting provides the ability to cause "SUSPENDED" action state
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+$MainMsgQueueTimeoutShutdown 100000
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" :omtesting:fail 2 0
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup
+# we initially send only 10 messages. It has shown that if we send more,
+# we cannot really control which are the first two messages imdiag sees,
+# and so we do not know for sure which numbers are skipped. So we inject
+# those 10 to get past that point.
+injectmsg 0 10
+./msleep 500
+injectmsg 10 990
+shutdown_when_empty
+wait_shutdown
+seq_check 1 999
+exit_test
diff --git a/tests/externalstate-failed-rcvr.sh b/tests/externalstate-failed-rcvr.sh
new file mode 100755
index 0000000..b3f23ca
--- /dev/null
+++ b/tests/externalstate-failed-rcvr.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This tests the action suspension via a file and ensure that it does
+# NOT override actual target suspension state.
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-01-08 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=2500
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+
+# IMPORTANT: nothing permitted to listen on $TCPFLOOD_PORT!
+# mimic some good state in external statefile:
+printf "%s" "READY" > $RSYSLOG_DYNNAME.STATE
+
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" {
+ action(name="primary" type="omfwd" target="localhost" port="'$TCPFLOOD_PORT'"
+ protocol="tcp" action.externalstate.file="'$RSYSLOG_DYNNAME'.STATE")
+ action(name="failover" type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ action.execOnlyWhenPreviousIsSuspended="on")
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+# note: we do NOT need to do a check_seq as this was already done as part of the
+# queue empty predicate check
+exit_test
diff --git a/tests/fac_authpriv.sh b/tests/fac_authpriv.sh
new file mode 100755
index 0000000..08e3c0d
--- /dev/null
+++ b/tests/fac_authpriv.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# This tests proper processing of the authpriv facility.
+# added 2014-09-16 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+authpriv.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 81
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_ftp.sh b/tests/fac_ftp.sh
new file mode 100755
index 0000000..05b00db
--- /dev/null
+++ b/tests/fac_ftp.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+ftp.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 89
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_invld1.sh b/tests/fac_invld1.sh
new file mode 100755
index 0000000..34b9e5f
--- /dev/null
+++ b/tests/fac_invld1.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-10-01 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:4%\n")
+invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 1011
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_invld2.sh b/tests/fac_invld2.sh
new file mode 100755
index 0000000..21b1bde
--- /dev/null
+++ b/tests/fac_invld2.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-10-01 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:4%\n")
+invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 3500000000
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_invld3.sh b/tests/fac_invld3.sh
new file mode 100755
index 0000000..e0bcb3d
--- /dev/null
+++ b/tests/fac_invld3.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-10-01 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:4%\n")
+invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P x112
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_invld4_rfc5424.sh b/tests/fac_invld4_rfc5424.sh
new file mode 100755
index 0000000..991a7b2
--- /dev/null
+++ b/tests/fac_invld4_rfc5424.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-10-01 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:4%\n")
+invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -y -m$NUMMESSAGES -P 8000000000000000000000000000000
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_local0-vg.sh b/tests/fac_local0-vg.sh
new file mode 100755
index 0000000..dd684b5
--- /dev/null
+++ b/tests/fac_local0-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2020-01-19 by RGerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/fac_local0.sh
diff --git a/tests/fac_local0.sh b/tests/fac_local0.sh
new file mode 100755
index 0000000..c6a2006
--- /dev/null
+++ b/tests/fac_local0.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2014-09-17 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+if $syslogfacility-text == "local0" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 129
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_local7.sh b/tests/fac_local7.sh
new file mode 100755
index 0000000..f078422
--- /dev/null
+++ b/tests/fac_local7.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-09-24 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+if $syslogfacility-text == "local7" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 185
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_mail.sh b/tests/fac_mail.sh
new file mode 100755
index 0000000..b222975
--- /dev/null
+++ b/tests/fac_mail.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# added 2014-09-17 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+mail.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 17
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_news.sh b/tests/fac_news.sh
new file mode 100755
index 0000000..01c7b01
--- /dev/null
+++ b/tests/fac_news.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-09-17 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+if prifilt("news.*") then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 57
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_ntp.sh b/tests/fac_ntp.sh
new file mode 100755
index 0000000..d609663
--- /dev/null
+++ b/tests/fac_ntp.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+ntp.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 97
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/fac_uucp.sh b/tests/fac_uucp.sh
new file mode 100755
index 0000000..c566276
--- /dev/null
+++ b/tests/fac_uucp.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2014-09-17 by Rgerhards
+
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+uucp.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -P 65
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/failover-async.sh b/tests/failover-async.sh
new file mode 100755
index 0000000..2b8f0ff
--- /dev/null
+++ b/tests/failover-async.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[failover-async.sh\]: async test for failover functionality
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+# note: the target server shall not be available!
+
+$ActionQueueType LinkedList
+:msg, contains, "msgnum:" @@127.0.0.1:13514
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/failover-basic-vg.sh b/tests/failover-basic-vg.sh
new file mode 100755
index 0000000..ceb3bdb
--- /dev/null
+++ b/tests/failover-basic-vg.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[failover-basic.sh\]: basic test for failover functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+# note: the target server shall not be available!
+:msg, contains, "msgnum:" @@127.0.0.1:13514
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup_vg
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 4999
+exit_test
diff --git a/tests/failover-basic.sh b/tests/failover-basic.sh
new file mode 100755
index 0000000..a979bdd
--- /dev/null
+++ b/tests/failover-basic.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[failover-basic.sh\]: basic test for failover functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+# note: the target server shall not be available!
+:msg, contains, "msgnum:" @@127.0.0.1:13514
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/failover-double.sh b/tests/failover-double.sh
new file mode 100755
index 0000000..6aa7205
--- /dev/null
+++ b/tests/failover-double.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export DEAD_PORT=4 # a port unassigned by IANA and very unlikely to be used
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+
+:msg, contains, "msgnum:" @@127.0.0.1:'$DEAD_PORT'
+$ActionExecOnlyWhenPreviousIsSuspended on
+& @@127.0.0.1:1234
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+$ActionExecOnlyWhenPreviousIsSuspended off
+'
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/failover-no-basic-vg.sh b/tests/failover-no-basic-vg.sh
new file mode 100755
index 0000000..0c6dba4
--- /dev/null
+++ b/tests/failover-no-basic-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[failover-no-basic.sh\]: basic test for failover functionality - no failover
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$RepeatedMsgReduction off
+
+# second action should never execute
+:msg, contains, "msgnum:" /dev/null
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"'
+'
+startup_vg
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+# now we need our custom logic to see if the result file is empty
+# (what it should be!)
+cmp $RSYSLOG_OUT_LOG /dev/null
+if [ $? -eq 1 ]
+then
+ echo "ERROR, output file not empty"
+ exit 1
+fi
+exit_test
diff --git a/tests/failover-no-basic.sh b/tests/failover-no-basic.sh
new file mode 100755
index 0000000..9c4a47e
--- /dev/null
+++ b/tests/failover-no-basic.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[failover-no-basic.sh\]: basic test for failover functionality - no failover
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$RepeatedMsgReduction off
+
+# second action should never execute
+:msg, contains, "msgnum:" /dev/null
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"'
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+# now we need our custom logic to see if the result file is empty
+# (what it should be!)
+cmp $RSYSLOG_OUT_LOG /dev/null
+if [ $? -eq 1 ]
+then
+ echo "ERROR, output file not empty"
+ exit 1
+fi
+exit_test
diff --git a/tests/failover-no-rptd-vg.sh b/tests/failover-no-rptd-vg.sh
new file mode 100755
index 0000000..66cc838
--- /dev/null
+++ b/tests/failover-no-rptd-vg.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# rptd test for failover functionality - no failover
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$RepeatedMsgReduction on
+
+# second action should never execute
+:msg, contains, "msgnum:" /dev/null
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"'
+'
+startup_vg
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+# now we need our custom logic to see if the result file is empty
+# (what it should be!)
+if [ -f $RSYSLOG_OUT_LOG -a "$(cat $RSYSLOG_OUT_LOG)" != "" ]; then
+ echo "ERROR, output file not empty"
+ cat -n "$RSYSLOG_OUT_LOG"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/failover-no-rptd.sh b/tests/failover-no-rptd.sh
new file mode 100755
index 0000000..4d6d4d9
--- /dev/null
+++ b/tests/failover-no-rptd.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[failover-no-rptd.sh\]: rptd test for failover functionality - no failover
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$RepeatedMsgReduction on
+
+# second action should never execute
+:msg, contains, "msgnum:" /dev/null
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"'
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+# now we need our custom logic to see if the result file is empty
+# (what it should be!)
+cmp $RSYSLOG_OUT_LOG /dev/null
+if [ $? -eq 1 ]
+then
+ echo "ERROR, output file not empty"
+ exit 1
+fi
+exit_test
diff --git a/tests/failover-rptd-vg.sh b/tests/failover-rptd-vg.sh
new file mode 100755
index 0000000..d730013
--- /dev/null
+++ b/tests/failover-rptd-vg.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[failover-rptd.sh\]: rptd test for failover functionality
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$RepeatedMsgReduction on
+
+$template outfmt,"%msg:F,58:2%\n"
+# note: the target server shall not be available!
+:msg, contains, "msgnum:" @@127.0.0.1:13514
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'"${RSYSLOG_OUT_LOG}"';outfmt
+'
+startup_vg
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 4999
+exit_test
diff --git a/tests/failover-rptd.sh b/tests/failover-rptd.sh
new file mode 100755
index 0000000..0e45afa
--- /dev/null
+++ b/tests/failover-rptd.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# rptd test for failover functionality
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+NUMMESSAGES=5000
+generate_conf
+add_conf '
+$RepeatedMsgReduction on
+
+$template outfmt,"%msg:F,58:2%\n"
+# note: the target server shall not be available!
+:msg, contains, "msgnum:" @@127.0.0.1:'$TCPFLOOD_PORT'
+$ActionExecOnlyWhenPreviousIsSuspended on
+& ./'$RSYSLOG_OUT_LOG';outfmt
+'
+startup
+injectmsg 0 $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/faketime_common.sh b/tests/faketime_common.sh
new file mode 100644
index 0000000..2fab082
--- /dev/null
+++ b/tests/faketime_common.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# addd 2016-03-11 by Thomas D., released under ASL 2.0
+# Several tests make use of faketime. They all need to know when
+# faketime is missing or the system isn't year-2038 complaint.
+# This script can be sourced to prevent duplicated code.
+
+rsyslog_testbench_preload_libfaketime() {
+ local missing_requirements=
+ if ! hash find 2>/dev/null ; then
+ missing_requirements="'find' is missing in PATH; Make sure you have findutils/coreutils installed! Skipping test ..."
+ fi
+
+ if ! hash $RS_SORTCMD 2>/dev/null ; then
+ missing_requirements="'sort' is missing in PATH; Make sure you have coreutils installed! Skipping test ..."
+ fi
+
+ if ! hash $RS_HEADCMD 2>/dev/null ; then
+ missing_requirements="'head' is missing in PATH; Make sure you have coreutils installed! Skipping test ..."
+ fi
+
+ if [ -n "${missing_requirements}" ]; then
+ printf '%s\n' "${missing_requirements}"
+ exit 77
+ fi
+
+ RSYSLOG_LIBFAKETIME=$(find /usr -name 'libfaketime.so*' -type f | $RS_SORTCMD --reverse | $RS_HEADCMD --lines 1)
+ if [ -z "${RSYSLOG_LIBFAKETIME}" ]; then
+ echo "Could not determine libfaketime library, skipping test!"
+ exit 77
+ fi
+
+ echo "Testing '${RSYSLOG_LIBFAKETIME}' library ..."
+ local faketime_testtime=$(LD_PRELOAD="${RSYSLOG_LIBFAKETIME}" FAKETIME="1991-08-25 20:57:08" TZ=GMT date +%s 2>/dev/null)
+ if [ ${faketime_testtime} -ne 683153828 ] ; then
+ echo "'${RSYSLOG_LIBFAKETIME}' failed sanity check, skipping test!"
+ exit 77
+ else
+ echo "Test passed! Will use '${RSYSLOG_LIBFAKETIME}' library!"
+ export RSYSLOG_PRELOAD="${RSYSLOG_LIBFAKETIME}"
+ fi
+
+ # GMT-1 (POSIX TIME) is GMT+1 in "Human Time"
+ faketime_testtime=$(LD_PRELOAD="${RSYSLOG_LIBFAKETIME}" FAKETIME="2040-01-01 16:00:00" TZ=GMT-1 date +%s 2>/dev/null)
+ if [ ${faketime_testtime} -eq -1 ]; then
+ echo "Note: System is not year-2038 compliant"
+ RSYSLOG_TESTBENCH_Y2K38_INCOMPATIBLE="yes"
+ else
+ echo "Note: System is year-2038 compliant"
+ fi
+}
+
+rsyslog_testbench_require_y2k38_support() {
+ if [ -n "${RSYSLOG_TESTBENCH_Y2K38_INCOMPATIBLE}" ]; then
+ echo "Skipping further tests because system doesn't support year 2038 ..."
+ exit_test
+ exit 0
+ fi
+}
+
+rsyslog_testbench_preload_libfaketime
diff --git a/tests/fieldtest-udp.sh b/tests/fieldtest-udp.sh
new file mode 100755
index 0000000..30afc08
--- /dev/null
+++ b/tests/fieldtest-udp.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg:F,32:2%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: DROP_url_www.sina.com.cn:IN=eth1 OUT=eth0 SRC=192.168.10.78 DST=61.172.201.194 LEN=1182 TOS=0x00 PREC=0x00 TTL=63 ID=14368 DF PROTO=TCP SPT=33343 DPT=80 WINDOW=92 RES=0x00 ACK PSH URGP=0\""
+shutdown_when_empty
+wait_shutdown
+
+echo 'DROP_url_www.sina.com.cn:IN=eth1' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/fieldtest.sh b/tests/fieldtest.sh
new file mode 100755
index 0000000..d9d2b1a
--- /dev/null
+++ b/tests/fieldtest.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg:F,32:2%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: DROP_url_www.sina.com.cn:IN=eth1 OUT=eth0 SRC=192.168.10.78 DST=61.172.201.194 LEN=1182 TOS=0x00 PREC=0x00 TTL=63 ID=14368 DF PROTO=TCP SPT=33343 DPT=80 WINDOW=92 RES=0x00 ACK PSH URGP=0\""
+shutdown_when_empty
+wait_shutdown
+
+echo 'DROP_url_www.sina.com.cn:IN=eth1' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/func-substring-invld-startpos-vg.sh b/tests/func-substring-invld-startpos-vg.sh
new file mode 100755
index 0000000..cbd3e55
--- /dev/null
+++ b/tests/func-substring-invld-startpos-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/func-substring-invld-startpos.sh
diff --git a/tests/func-substring-invld-startpos.sh b/tests/func-substring-invld-startpos.sh
new file mode 100755
index 0000000..5f658e3
--- /dev/null
+++ b/tests/func-substring-invld-startpos.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# addd 2023-01-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="data:%$!my_struc_data%\n")
+
+set $!my_struc_data = substring($STRUCTURED-DATA, 2000, -3);
+local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='data:'
+cmp_exact
+exit_test
diff --git a/tests/func-substring-large-endpos.sh b/tests/func-substring-large-endpos.sh
new file mode 100755
index 0000000..78d5d7d
--- /dev/null
+++ b/tests/func-substring-large-endpos.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# addd 2023-01-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!my_struc_data%\n")
+
+set $!my_struc_data = substring($STRUCTURED-DATA, 1, 99999999);
+local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='tcpflood@32473 MSGNUM="0"]'
+cmp_exact
+exit_test
diff --git a/tests/func-substring-large-neg-endpos.sh b/tests/func-substring-large-neg-endpos.sh
new file mode 100755
index 0000000..23344f0
--- /dev/null
+++ b/tests/func-substring-large-neg-endpos.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# addd 2023-01-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="data:%$!my_struc_data%\n")
+
+set $!my_struc_data = substring($STRUCTURED-DATA, 1, -9999999);
+local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='data:'
+cmp_exact
+exit_test
diff --git a/tests/func-substring-relative-endpos.sh b/tests/func-substring-relative-endpos.sh
new file mode 100755
index 0000000..43c6745
--- /dev/null
+++ b/tests/func-substring-relative-endpos.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# addd 2023-01-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!my_struc_data%\n")
+
+set $!my_struc_data = substring($STRUCTURED-DATA, 1, -2);
+local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='tcpflood@32473 MSGNUM="0"'
+cmp_exact
+exit_test
diff --git a/tests/glbl-internalmsg_severity-debug-not_shown.sh b/tests/glbl-internalmsg_severity-debug-not_shown.sh
new file mode 100755
index 0000000..b3b3113
--- /dev/null
+++ b/tests/glbl-internalmsg_severity-debug-not_shown.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# check that info-severity messages are actually emitted; we use
+# lookup table as a simple sample to get such a message.
+# addd 2019-05-07 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+shutdown_when_empty
+wait_shutdown
+check_not_present "rsyslogd fully started up and initialized - begin actual processing"
+exit_test
diff --git a/tests/glbl-internalmsg_severity-debug-shown.sh b/tests/glbl-internalmsg_severity-debug-shown.sh
new file mode 100755
index 0000000..1231302
--- /dev/null
+++ b/tests/glbl-internalmsg_severity-debug-shown.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# check that info-severity messages are actually emitted; we use
+# lookup table as a simple sample to get such a message.
+# addd 2019-05-07 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(internalmsg.severity="debug")
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "rsyslogd fully started up and initialized - begin actual processing"
+exit_test
diff --git a/tests/glbl-internalmsg_severity-info-shown.sh b/tests/glbl-internalmsg_severity-info-shown.sh
new file mode 100755
index 0000000..265894f
--- /dev/null
+++ b/tests/glbl-internalmsg_severity-info-shown.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# check that info-severity messages are actually emitted; we use
+# lookup table as a simple sample to get such a message.
+# addd 2019-05-07 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(internalmsg.severity="info")
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "lookup table 'xlate' loaded from file"
+exit_test
diff --git a/tests/glbl-invld-param.sh b/tests/glbl-invld-param.sh
new file mode 100755
index 0000000..f9f4341
--- /dev/null
+++ b/tests/glbl-invld-param.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# make sure we do not abort on invalid parameter (we
+# once had this problem)
+# addd 2016-03-03 by RGerhards, released under ASL 2.0
+echo \[glbl-invld-param\]:
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(invalid="off")
+global(debug.unloadModules="invalid")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+sleep 1
+shutdown_when_empty
+wait_shutdown
+# if we reach this point, we consider this a success.
+exit_test
diff --git a/tests/glbl-oversizeMsg-log-vg.sh b/tests/glbl-oversizeMsg-log-vg.sh
new file mode 100755
index 0000000..21878c5
--- /dev/null
+++ b/tests/glbl-oversizeMsg-log-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# add 2018-05-03 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+global(maxMessageSize="230"
+ oversizemsg.errorfile=`echo $RSYSLOG2_OUT_LOG`)
+
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="300")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# TODO: add tcpflood option to specific EXACT test message size!
+startup_vg
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg
+check_exit_vg
+grep "rawmsg.*<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.*input.*imrelp" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/glbl-oversizeMsg-log.sh b/tests/glbl-oversizeMsg-log.sh
new file mode 100755
index 0000000..f5568ab
--- /dev/null
+++ b/tests/glbl-oversizeMsg-log.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# add 2018-05-03 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+global(maxMessageSize="230"
+ oversizemsg.errorfile=`echo $RSYSLOG2_OUT_LOG`)
+
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="300")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# TODO: add tcpflood option to specific EXACT test message size!
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+grep "rawmsg.*<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.*input.*imrelp" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/glbl-oversizeMsg-split.sh b/tests/glbl-oversizeMsg-split.sh
new file mode 100755
index 0000000..010ab21
--- /dev/null
+++ b/tests/glbl-oversizeMsg-split.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# add 2018-05-03 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+global(maxMessageSize="230"
+ oversizemsg.input.mode="split")
+
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="300")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# TODO: add tcpflood option to specific EXACT test message size!
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+#First part of message is checked
+grep "^<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+#Split part of message is checked
+grep "^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+#Error message is checked
+grep "message too long.*begin of message is:" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/glbl-oversizeMsg-truncate-imfile.sh b/tests/glbl-oversizeMsg-truncate-imfile.sh
new file mode 100755
index 0000000..d281c6a
--- /dev/null
+++ b/tests/glbl-oversizeMsg-truncate-imfile.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# add 2018-05-02 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+global(maxMessageSize="230"
+ oversizemsg.input.mode="truncate")
+
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" tag="tag:")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+echo '<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' > $RSYSLOG_DYNNAME.input
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+grep "^<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG #> /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "message too long.*begin of message is:" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/glbl-oversizeMsg-truncate.sh b/tests/glbl-oversizeMsg-truncate.sh
new file mode 100755
index 0000000..9b3fb47
--- /dev/null
+++ b/tests/glbl-oversizeMsg-truncate.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# add 2018-05-02 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+global(maxMessageSize="230")
+
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="300")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# TODO: add tcpflood option to specific EXACT test message size!
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+grep "^<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "message too long.*begin of message is:" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/glbl-ruleset-queue-defaults.sh b/tests/glbl-ruleset-queue-defaults.sh
new file mode 100755
index 0000000..fc625cf
--- /dev/null
+++ b/tests/glbl-ruleset-queue-defaults.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# check that global ruleset queue defaults can be specified. However,
+# we do not tests that they actually work - that's quite hard to
+# do reliably.
+# addd 2019-05-09 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( default.ruleset.queue.timeoutshutdown="1000"
+ default.ruleset.queue.timeoutactioncompletion="1000"
+ default.ruleset.queue.timeoutenqueue="1000"
+ default.ruleset.queue.timeoutworkerthreadshutdown="1000"
+ )
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+shutdown_when_empty
+wait_shutdown
+check_not_present 'parameter.*not known'
+exit_test
diff --git a/tests/glbl-umask.sh b/tests/glbl-umask.sh
new file mode 100755
index 0000000..dcea2a1
--- /dev/null
+++ b/tests/glbl-umask.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# addd 2017-03-06 by RGerhards, released under ASL 2.0
+
+# Note: we need to inject a somewhat larger number of messages in order
+# to ensure that we receive some messages in the actual output file,
+# as batching can (validly) cause a larger loss in the non-writable
+# file
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(umask="0077")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+
+if [ `ls -l $RSYSLOG_OUT_LOG|$RS_HEADCMD -c 10 ` != "-rw-------" ]; then
+ echo "invalid file permission (umask), $RSYSLOG_OUT_LOG has:"
+ ls -l $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/glbl-unloadmodules.sh b/tests/glbl-unloadmodules.sh
new file mode 100755
index 0000000..9b006fd
--- /dev/null
+++ b/tests/glbl-unloadmodules.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# we only test if the parameter is accepted - we cannot
+# reliably deduce from the outside if it really worked.
+# addd 2016-03-03 by RGerhards, released under ASL 2.0
+echo \[glbl-unloadmodules\]:
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(debug.unloadModules="off")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+sleep 1
+shutdown_when_empty
+wait_shutdown
+# to check for support, we check if an error message has
+# been recorded, which would bear the name of our option.
+# if it is not recorded, we assume all is well. Not perfect,
+# but works good enough.
+grep -i "unloadModules" < $RSYSLOG_OUT_LOG
+if [ ! $? -eq 1 ]; then
+ echo "parameter name in output, assuming error message:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+exit_test
diff --git a/tests/glbl_setenv.sh b/tests/glbl_setenv.sh
new file mode 100755
index 0000000..1387bbd
--- /dev/null
+++ b/tests/glbl_setenv.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(environment="http_proxy=http://127.0.0.1")
+
+set $!prx = getenv("http_proxy");
+
+template(name="outfmt" type="string" string="%$!prx%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo 'http://127.0.0.1' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid content seen, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/glbl_setenv_2_vars.sh b/tests/glbl_setenv_2_vars.sh
new file mode 100755
index 0000000..e472c73
--- /dev/null
+++ b/tests/glbl_setenv_2_vars.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(environment=["http_proxy=http://127.0.0.1", "SECOND=OK OK"])
+
+set $!prx = getenv("http_proxy");
+set $!second = getenv("SECOND");
+
+template(name="outfmt" type="string" string="%$!prx%, %$!second%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo 'http://127.0.0.1, OK OK' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid content seen, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/glbl_setenv_err.sh b/tests/glbl_setenv_err.sh
new file mode 100755
index 0000000..0712ee5
--- /dev/null
+++ b/tests/glbl_setenv_err.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# env var is missing equal sign and MUST trigger parsing error!
+global(environment="http_proxy ERROR")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+grep "http_proxy ERROR" < $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo
+ echo "MESSAGE INDICATING ERROR ON ENVIRONMENT VARIABLE IS MISSING:"
+ echo
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/glbl_setenv_err_too_long.sh b/tests/glbl_setenv_err_too_long.sh
new file mode 100755
index 0000000..ad994ac
--- /dev/null
+++ b/tests/glbl_setenv_err_too_long.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# name is 400 chars long --> too long
+global(environment="NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN=400")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+grep "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" < $RSYSLOG_OUT_LOG > /dev/null
+if [ ! $? -eq 0 ]; then
+ echo
+ echo "MESSAGE INDICATING ERROR ON ENVIRONMENT VARIABLE IS MISSING:"
+ echo
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/global_vars.sh b/tests/global_vars.sh
new file mode 100755
index 0000000..1d66566
--- /dev/null
+++ b/tests/global_vars.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test for global variables
+# added 2013-11-18 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[global_vars.sh\]: testing global variable support
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$/msgnum%\n")
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) /* trick to use relative path names! */
+
+if $/msgnum == "" then
+ set $/msgnum = 0;
+
+if $msg contains "msgnum:" then {
+ action(type="omfile" dynaFile="dynfile" template="outfmt")
+ set $/msgnum = $/msgnum + 1;
+}
+'
+startup
+
+# 40000 messages should be enough
+injectmsg 0 40000
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 39999
+exit_test
diff --git a/tests/gzipwr_flushInterval.sh b/tests/gzipwr_flushInterval.sh
new file mode 100755
index 0000000..c5df022
--- /dev/null
+++ b/tests/gzipwr_flushInterval.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+export NUMMESSAGES=5000 #even number!
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.gz
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ zipLevel="6" ioBufferSize="256k"
+ flushOnTXEnd="off" flushInterval="1"
+ asyncWriting="on"
+ file="'$RSYSLOG_OUT_LOG'.gz")
+'
+startup
+tcpflood -m$((NUMMESSAGES / 2)) -P129
+./msleep 5000 #wait for flush
+seq_check 0 2499
+tcpflood -i$((NUMMESSAGES / 2)) -m$((NUMMESSAGES / 2)) -P129
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/gzipwr_flushOnTXEnd.sh b/tests/gzipwr_flushOnTXEnd.sh
new file mode 100755
index 0000000..c396be3
--- /dev/null
+++ b/tests/gzipwr_flushOnTXEnd.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+export NUMMESSAGES=5000 # MUST be an even number
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" { action(type="omfile" template="outfmt"
+ zipLevel="6" ioBufferSize="256k"
+ flushOnTXEnd="on"
+ asyncWriting="on"
+ file="'$RSYSLOG_OUT_LOG'")
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.countlog")
+ }
+'
+startup
+tcpflood -m$((NUMMESSAGES / 2)) -P129
+wait_queueempty
+echo test 1
+wait_file_lines "$RSYSLOG_DYNNAME.countlog" $((NUMMESSAGES / 2 ))
+gzip_seq_check 0 $((NUMMESSAGES / 2 - 1))
+tcpflood -i$((NUMMESSAGES / 2)) -m$((NUMMESSAGES / 2)) -P129
+echo test 2
+wait_file_lines "$RSYSLOG_DYNNAME.countlog" $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+gzip_seq_check
+exit_test
diff --git a/tests/gzipwr_hup-vg.sh b/tests/gzipwr_hup-vg.sh
new file mode 100755
index 0000000..5db04e0
--- /dev/null
+++ b/tests/gzipwr_hup-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export NUMMESSAGES=200000 # reduce for slower valgrind run
+source ${srcdir:-.}/gzipwr_hup.sh
diff --git a/tests/gzipwr_hup.sh b/tests/gzipwr_hup.sh
new file mode 100755
index 0000000..ffca610
--- /dev/null
+++ b/tests/gzipwr_hup.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-06-12 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=${NUMMESSAGES:-2000000}
+export COUNT_FILE_IS_ZIPPED=yes
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export TB_TEST_TIMEOUT=180 # test is slow due to large number of messages
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+
+
+
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ zipLevel="9" ioBufferSize="16" flushOnTXEnd="on"
+ dynafile="dynfile")
+'
+startup
+./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async!
+BGPROCESS=$!
+for i in $(seq 1 20); do
+ printf '\nsending HUP %d\n' $i
+ issue_HUP --sleep 100
+done
+wait $BGPROCESS
+shutdown_when_empty
+wait_shutdown
+gzip_seq_check
+exit_test
diff --git a/tests/gzipwr_hup_multi_file.sh b/tests/gzipwr_hup_multi_file.sh
new file mode 100755
index 0000000..3083820
--- /dev/null
+++ b/tests/gzipwr_hup_multi_file.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-06-12 by Rainer Gerhards
+export TEST_MAX_RUNTIME=7200
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100000
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+main_queue(queue.workerThreads="10" queue.workerThreadMinimumMessages="200")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'.%$/file%")
+
+
+
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ zipLevel="9" ioBufferSize="16" flushOnTXEnd="on"
+ dynafile="dynfile" dynaFileCacheSize="5"
+ asyncWriting="on")
+
+if $msg contains "msgnum" then {
+ set $/file = cnum($/file) + 1;
+ if $/file >= 10 then {
+ set $/file = 0;
+ }
+}
+'
+startup
+./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async!
+for i in $(seq 0 20); do
+ printf '\nsending HUP %d\n' $i
+ issue_HUP
+ ./msleep 10
+done
+shutdown_when_empty
+wait_shutdown
+ls -l ${RSYSLOG_OUT_LOG}.*
+for f in "${RSYSLOG_OUT_LOG}".*; do
+ echo unzipping $f
+ gunzip < "$f" >> $RSYSLOG_OUT_LOG
+done
+seq_check
+exit_test
diff --git a/tests/gzipwr_hup_single_file.sh b/tests/gzipwr_hup_single_file.sh
new file mode 100755
index 0000000..e1308b2
--- /dev/null
+++ b/tests/gzipwr_hup_single_file.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-06-12 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+main_queue(queue.workerThreads="10" queue.workerThreadMinimumMessages="200")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+
+
+
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ zipLevel="9" ioBufferSize="16" flushOnTXEnd="on"
+ dynafile="dynfile" dynaFileCacheSize="5"
+ asyncWriting="on")
+
+if $msg contains "msgnum" then {
+ set $/file = cnum($/file) + 1;
+ if $/file >= 10 then {
+ set $/file = 0;
+ }
+}
+'
+startup
+./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async!
+for i in $(seq 0 20); do
+ ./msleep 10
+ printf '\nsending HUP %d\n' $i
+ issue_HUP
+done
+shutdown_when_empty
+wait_shutdown
+gzip_seq_check
+exit_test
diff --git a/tests/gzipwr_large.sh b/tests/gzipwr_large.sh
new file mode 100755
index 0000000..69f93ae
--- /dev/null
+++ b/tests/gzipwr_large.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This tests writing large data records in gzip mode. We use up to 10K
+# record size.
+#
+# added 2010-03-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=4000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.gz
+add_conf '
+$MaxMessageSize 10k
+$MainMsgQueueTimeoutShutdown 10000
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'.gz" template="outfmt"
+ zipLevel="6" veryRobustZip="on")
+'
+# rgerhards, 2019-08-14: Note: veryRobustZip may need to be "on". Do this if the test
+# still prematurely terminates. In that case it is likely that gunzip got confused
+# by the missing zip close record. My initial testing shows that while gunzip emits an
+# error message, everything is properly extracted. Only stressed CI runs will show how
+# it works in reality.
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES -r -d10000 -P129
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $((NUMMESSAGES - 1)) -E
+exit_test
diff --git a/tests/gzipwr_large_dynfile.sh b/tests/gzipwr_large_dynfile.sh
new file mode 100755
index 0000000..6cf5eb6
--- /dev/null
+++ b/tests/gzipwr_large_dynfile.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This tests writing large data records in gzip mode. We also write it to
+# 5 different dynafiles, with a dynafile cache size set to 4. So this stresses
+# both the input side, as well as zip writing, async writing and the dynafile
+# cache logic.
+#
+# This test is a bit timing-dependent on the tcp reception side, so if it fails
+# one may look into the timing first. The main issue is that the testbench
+# currently has no good way to know if the tcp receiver is finished. This is NOT
+# a problem in rsyslogd, but only of the testbench.
+#
+# Note that we do not yet have sufficient support for dynafiles in diag.sh,
+# so we mangle some files here manually.
+#
+# added 2010-03-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "FIXME: this test does not work on Solaris because of what looks like a BUG! It is just disabled here so that we can gain the benefits of a better test on other platforms. Bug on solaris must be addressed"
+combine_files() {
+ gunzip -c < $RSYSLOG_DYNNAME.out.0.log > $RSYSLOG_OUT_LOG
+ gunzip -c < $RSYSLOG_DYNNAME.out.1.log >> $RSYSLOG_OUT_LOG
+ gunzip -c < $RSYSLOG_DYNNAME.out.2.log >> $RSYSLOG_OUT_LOG
+ gunzip -c < $RSYSLOG_DYNNAME.out.3.log >> $RSYSLOG_OUT_LOG
+ gunzip -c < $RSYSLOG_DYNNAME.out.4.log >> $RSYSLOG_OUT_LOG
+}
+export NUMMESSAGES=4000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+export PRE_SEQ_CHECK_FUNC=combine_files
+export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG
+export SEQ_CHECK_OPTIONS=-E
+generate_conf
+add_conf '
+global(MaxMessageSize="10k")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n"
+$template dynfile,"'$RSYSLOG_DYNNAME'.out.%msg:F,58:2%.log" # use multiple dynafiles
+local0.* action(type="omfile" template="outfmt"
+ zipLevel="6" ioBufferSize="256k" veryRobustZip="on"
+ flushOnTXEnd="off" flushInterval="1"
+ asyncWriting="on" dynaFileCacheSize="4"
+ dynafile="dynfile")
+'
+startup
+# send messages of 10.000bytes plus header max, randomized
+tcpflood -m$NUMMESSAGES -r -d10000 -P129 -f5
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/gzipwr_rscript.sh b/tests/gzipwr_rscript.sh
new file mode 100755
index 0000000..4868c7b
--- /dev/null
+++ b/tests/gzipwr_rscript.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ zipLevel="6" ioBufferSize="256k" flushOnTXEnd="off"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m2500 -P129
+tcpflood -i2500 -m2500 -P129
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+gzip_seq_check 0 4999
+exit_test
diff --git a/tests/have_relpEngineSetTLSLibByName.c b/tests/have_relpEngineSetTLSLibByName.c
new file mode 100644
index 0000000..f8e5d88
--- /dev/null
+++ b/tests/have_relpEngineSetTLSLibByName.c
@@ -0,0 +1,10 @@
+#include "config.h"
+
+int main(int argc __attribute__((unused)), char *argv[]__attribute__((unused)))
+{
+#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/tests/have_relpSrvSetOversizeMode.c b/tests/have_relpSrvSetOversizeMode.c
new file mode 100644
index 0000000..0c76ab3
--- /dev/null
+++ b/tests/have_relpSrvSetOversizeMode.c
@@ -0,0 +1,10 @@
+#include "config.h"
+
+int main(int argc __attribute__((unused)), char *argv[]__attribute__((unused)))
+{
+#ifdef HAVE_RELPSRVSETOVERSIZEMODE
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/tests/have_relpSrvSetTlsConfigCmd.c b/tests/have_relpSrvSetTlsConfigCmd.c
new file mode 100644
index 0000000..fef068c
--- /dev/null
+++ b/tests/have_relpSrvSetTlsConfigCmd.c
@@ -0,0 +1,10 @@
+#include "config.h"
+
+int main(int argc __attribute__((unused)), char *argv[]__attribute__((unused)))
+{
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/tests/hostname-with-slash-dflt-invld.sh b/tests/hostname-with-slash-dflt-invld.sh
new file mode 100755
index 0000000..206489f
--- /dev/null
+++ b/tests/hostname-with-slash-dflt-invld.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# addd 2016-07-11 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%hostname%") # no LF, as HOSTNAME file also does not have it!
+
+local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 hostname1/hostname2 test: msgnum:0' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+printf '%s' "$RS_HOSTNAME" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ echo
+ echo "expected was:"
+ printf '%s\n' "$RS_HOSTNAME"
+ echo
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/hostname-with-slash-dflt-slash-valid.sh b/tests/hostname-with-slash-dflt-slash-valid.sh
new file mode 100755
index 0000000..6305d7d
--- /dev/null
+++ b/tests/hostname-with-slash-dflt-slash-valid.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# addd 2016-07-11 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%hostname%\n")
+
+# note: we use the default parser chain, which includes RFC5424 and that parser
+# should be selected AND detect the hostname with slashes as valid.
+local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>1 2003-03-01T01:00:00.000Z hostname1/hostname2 tcpflood - tag [tcpflood@32473 MSGNUM="0"] data' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+echo "hostname1/hostname2" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/hostname-with-slash-pmrfc3164.sh b/tests/hostname-with-slash-pmrfc3164.sh
new file mode 100755
index 0000000..3d1ad21
--- /dev/null
+++ b/tests/hostname-with-slash-pmrfc3164.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# addd 2016-07-11 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%hostname%\n")
+
+parser(name="pmrfc3164.hostname_with_slashes" type="pmrfc3164" permit.slashesinhostname="on")
+$rulesetparser pmrfc3164.hostname_with_slashes
+local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 hostname1/hostname2 test: msgnum:0' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+echo "hostname1/hostname2" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/hostname-with-slash-pmrfc5424.sh b/tests/hostname-with-slash-pmrfc5424.sh
new file mode 100755
index 0000000..6ffa77f
--- /dev/null
+++ b/tests/hostname-with-slash-pmrfc5424.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# addd 2016-07-11 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%hostname%\n")
+
+$rulesetparser rsyslog.rfc5424
+local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>1 2003-03-01T01:00:00.000Z hostname1/hostname2 tcpflood - tag [tcpflood@32473 MSGNUM="0"] data' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+echo "hostname1/hostname2" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/imbatchreport_delete_structdata.sh b/tests/imbatchreport_delete_structdata.sh
new file mode 100755
index 0000000..607b054
--- /dev/null
+++ b/tests/imbatchreport_delete_structdata.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# 804/805 fail/sent with space dedup
+global(maxmessagesize="820")
+module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1")
+global(localhostname="server")
+input(type="imbatchreport" ruleset="ruleset" tag="batch"
+ severity="info" facility="local0"
+ reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on"
+ programkey="KSH" timestampkey="START"
+ delete=".done$ .rejected"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+ echo ' [START=1552143924 KSH="MYBATCH.sh"'
+ echo ' DURATION=120] '
+} > $RSYSLOG_DYNNAME.dsd.done
+echo "Batch report to consume ${RSYSLOG_DYNNAME}.dsd.done for 2019-03-09T15:05:24"
+startup
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<134>1 2019-03-09T15:05:24.000000+00:00 server MYBATCH.sh - - [START=1552143924 KSH="MYBATCH.sh" DURATION=120] 164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree\n164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree\n164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)\n164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+cmp_exact
+if [ -e $RSYSLOG_DYNNAME.dsd.sent ] || [ -e $RSYSLOG_DYNNAME.dsd.rejected ] || [ -e $RSYSLOG_DYNNAME.dsd.done ]; then
+ echo "The batch report was not deleted"
+ ls $RSYSLOG_DYNNAME*
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imbatchreport_delete_success.sh b/tests/imbatchreport_delete_success.sh
new file mode 100755
index 0000000..f650e10
--- /dev/null
+++ b/tests/imbatchreport_delete_success.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# 804/805 fail/sent with space dedup
+global(maxmessagesize="820")
+module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1")
+global(localhostname="server")
+input(type="imbatchreport" ruleset="ruleset" tag="batch"
+ severity="info" facility="local0"
+ reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on"
+ programkey="KSH" timestampkey="START"
+ delete=".done$ .rejected"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+} > $RSYSLOG_DYNNAME.dsu.done
+case $(uname) in
+ FreeBSD)
+ datelog=$(date -r $(stat -f %m $RSYSLOG_DYNNAME.dsu.done) "+%Y-%m-%dT%H:%M:%S")
+ ;;
+ *)
+ datelog=$(date "+%Y-%m-%dT%H:%M:%S" -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.dsu.done))
+ ;;
+esac
+echo "Batch report to consume ${RSYSLOG_DYNNAME}.dsu.done for ${datelog}"
+startup
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - 164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree\n164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree\n164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)\n164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+cmp_exact
+if [ -e $RSYSLOG_DYNNAME.dsu.sent ] || [ -e $RSYSLOG_DYNNAME.dsu.rejected ] || [ -e $RSYSLOG_DYNNAME.dsu.done ]; then
+ echo "The batch report was not deleted"
+ ls $RSYSLOG_DYNNAME*
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imbatchreport_delete_toolarge.sh b/tests/imbatchreport_delete_toolarge.sh
new file mode 100755
index 0000000..a0aa35c
--- /dev/null
+++ b/tests/imbatchreport_delete_toolarge.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# 804/805 fail/sent with space dedup
+global(maxmessagesize="800")
+module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1")
+global(localhostname="server")
+input(type="imbatchreport" ruleset="ruleset" tag="batch"
+ severity="info" facility="local0"
+ reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on"
+ programkey="KSH" timestampkey="START"
+ delete=".done$ .rejected"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+} > $RSYSLOG_DYNNAME.dtl.done
+case $(uname) in
+ FreeBSD)
+ datelog=$(date -ur $(stat -f %m $RSYSLOG_DYNNAME.dtl.done) "+%Y-%m-%dT%H:%M:%S")
+ ;;
+ *)
+ datelog=$(date -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.dtl.done) "+%Y-%m-%dT%H:%M:%S")
+ ;;
+esac
+echo "Batch report to consume ${RSYSLOG_DYNNAME}.dtl.done for ${datelog}"
+startup
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - File too large : ./'${RSYSLOG_DYNNAME}'.dtl.done'
+cmp_exact
+if [ -e $RSYSLOG_DYNNAME.dtl.done ] || [ -e $RSYSLOG_DYNNAME.dtl.sent ] || [ ! -e $RSYSLOG_DYNNAME.dtl.rejected ]; then
+ echo "The batch report could not be renamed to rejected"
+ ls $RSYSLOG_DYNNAME*
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_delete_params.sh b/tests/imbatchreport_errmsg_delete_params.sh
new file mode 100755
index 0000000..f4168c3
--- /dev/null
+++ b/tests/imbatchreport_errmsg_delete_params.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" reports="*.done" delete=".done$")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "'delete' must specify TWO parameters separated by spaces or tabs"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_glob_dir_fake.sh b/tests/imbatchreport_errmsg_glob_dir_fake.sh
new file mode 100755
index 0000000..bd9fc5e
--- /dev/null
+++ b/tests/imbatchreport_errmsg_glob_dir_fake.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+
+input(type="imbatchreport" tag="t" rename=".done$ .s .r.done" reports="fake/*.done")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Configured directory can not be stated"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_glob_dir_not_dir.sh b/tests/imbatchreport_errmsg_glob_dir_not_dir.sh
new file mode 100755
index 0000000..77e6914
--- /dev/null
+++ b/tests/imbatchreport_errmsg_glob_dir_not_dir.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" rename=".done$ .s .r.done" reports="'$RSYSLOG_DYNNAME'_.conf/*.done")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Configured directory is NOT a directory"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_glob_not_regular.sh b/tests/imbatchreport_errmsg_glob_not_regular.sh
new file mode 100755
index 0000000..50bdb94
--- /dev/null
+++ b/tests/imbatchreport_errmsg_glob_not_regular.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" rename=".spool$ .s .r.done" reports="'$RSYSLOG_DYNNAME'.spool")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Configured report is not a glob or a regular file"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_no_params-vg.sh b/tests/imbatchreport_errmsg_no_params-vg.sh
new file mode 100755
index 0000000..17f6113
--- /dev/null
+++ b/tests/imbatchreport_errmsg_no_params-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imbatchreport_errmsg_no_params.sh
diff --git a/tests/imbatchreport_errmsg_no_params.sh b/tests/imbatchreport_errmsg_no_params.sh
new file mode 100755
index 0000000..7104216
--- /dev/null
+++ b/tests/imbatchreport_errmsg_no_params.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+
+input(type="imbatchreport")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'reports' required but not specified"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_not_supported1.sh b/tests/imbatchreport_errmsg_not_supported1.sh
new file mode 100755
index 0000000..86b7a10
--- /dev/null
+++ b/tests/imbatchreport_errmsg_not_supported1.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" ruleset="r" delete=".done$ .r" rename=".done$ .s .r" reports="*.*")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "'rename' and 'delete' are exclusive"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_not_supported2.sh b/tests/imbatchreport_errmsg_not_supported2.sh
new file mode 100755
index 0000000..7e8f060
--- /dev/null
+++ b/tests/imbatchreport_errmsg_not_supported2.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" ruleset="r" rename=".done$ .s .r" delete=".done$ .r" reports="*.*")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "'rename' and 'delete' are exclusive"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_not_supported3.sh b/tests/imbatchreport_errmsg_not_supported3.sh
new file mode 100755
index 0000000..2a3d3ac
--- /dev/null
+++ b/tests/imbatchreport_errmsg_not_supported3.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" reports="*.done")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "either 'rename' or 'delete' must be set"
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_regex.match.reject.sh b/tests/imbatchreport_errmsg_regex.match.reject.sh
new file mode 100755
index 0000000..a64e620
--- /dev/null
+++ b/tests/imbatchreport_errmsg_regex.match.reject.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+
+input(type="imbatchreport" tag="t" rename=".done$ .s .r.done" reports="./*.done")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Reject renaming leaves files in glob scope: Instance ignored to avoid loops."
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_regex.match.rename.sh b/tests/imbatchreport_errmsg_regex.match.rename.sh
new file mode 100755
index 0000000..5ec40ac
--- /dev/null
+++ b/tests/imbatchreport_errmsg_regex.match.rename.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+
+input(type="imbatchreport" tag="t" rename=".done$ .s.done .r" reports="./*.done")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Normal renaming leaves files in glob scope: Instance ignored to avoid loops."
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_regex.nomatch.sh b/tests/imbatchreport_errmsg_regex.nomatch.sh
new file mode 100755
index 0000000..5461c70
--- /dev/null
+++ b/tests/imbatchreport_errmsg_regex.nomatch.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+
+input(type="imbatchreport" tag="t" rename=".done$ .s .r" reports="./*.bad")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Regex does not match globed filenames: Instance ignored to avoid loops."
+
+exit_test
diff --git a/tests/imbatchreport_errmsg_rename_params.sh b/tests/imbatchreport_errmsg_rename_params.sh
new file mode 100755
index 0000000..a5fc9b4
--- /dev/null
+++ b/tests/imbatchreport_errmsg_rename_params.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imbatchreport/.libs/imbatchreport")
+input(type="imbatchreport" tag="t" reports="*.done" rename=".done$ - ")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "'rename' must specify THREE parameters separated by spaces or tabs"
+
+exit_test
diff --git a/tests/imbatchreport_rename_success.sh b/tests/imbatchreport_rename_success.sh
new file mode 100755
index 0000000..1ce996a
--- /dev/null
+++ b/tests/imbatchreport_rename_success.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# 804/805 fail/sent with space dedup
+global(maxmessagesize="820")
+module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1")
+global(localhostname="server")
+input(type="imbatchreport" ruleset="ruleset" tag="batch"
+ severity="info" facility="local0"
+ reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on"
+ programkey="KSH" timestampkey="START"
+ rename=".done$ .sent .rejected"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+} > $RSYSLOG_DYNNAME.rsu.done
+case $(uname) in
+ FreeBSD)
+ datelog=$(date -ur $(stat -f %m $RSYSLOG_DYNNAME.rsu.done) "+%Y-%m-%dT%H:%M:%S")
+ ;;
+ *)
+ datelog=$(date "+%Y-%m-%dT%H:%M:%S" -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.rsu.done))
+ ;;
+esac
+echo "Batch report to consume ${RSYSLOG_DYNNAME}.rsu.done for ${datelog}"
+startup
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - 164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree\n164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree\n164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)\n164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+cmp_exact
+if [ -e $RSYSLOG_DYNNAME.rsu.done ] || [ -e $RSYSLOG_DYNNAME.rsu.rejected ] || [ ! -e $RSYSLOG_DYNNAME.rsu.sent ]; then
+ echo "The batch report could not be renamed"
+ ls $RSYSLOG_DYNNAME*
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imbatchreport_rename_toolarge.sh b/tests/imbatchreport_rename_toolarge.sh
new file mode 100755
index 0000000..a43d72c
--- /dev/null
+++ b/tests/imbatchreport_rename_toolarge.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# 804/805 fail/sent with space dedup
+global(maxmessagesize="800")
+module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1")
+global(localhostname="server")
+input(type="imbatchreport" ruleset="ruleset" tag="batch"
+ severity="info" facility="local0"
+ reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on"
+ programkey="KSH" timestampkey="START"
+ rename=".done$ .sent .rejected"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+} > $RSYSLOG_DYNNAME.rtl.done
+case $(uname) in
+ FreeBSD)
+ datelog=$(date -ur $(stat -f %m $RSYSLOG_DYNNAME.rtl.done) "+%Y-%m-%dT%H:%M:%S")
+ ;;
+ *)
+ datelog=$(date "+%Y-%m-%dT%H:%M:%S" -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.rtl.done))
+ ;;
+esac
+echo "Batch report to consume ${RSYSLOG_DYNNAME}.rtl.done for ${datelog}"
+startup
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - File too large : ./'${RSYSLOG_DYNNAME}'.rtl.done'
+cmp_exact
+if [ -e $RSYSLOG_DYNNAME.rtl.done ] || [ -e $RSYSLOG_DYNNAME.rtl.sent ] || [ ! -e $RSYSLOG_DYNNAME.rtl.rejected ]; then
+ echo "The batch report could not be renamed to rejected"
+ ls $RSYSLOG_DYNNAME*
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imdocker-basic-vg.sh b/tests/imdocker-basic-vg.sh
new file mode 100755
index 0000000..e5ca251
--- /dev/null
+++ b/tests/imdocker-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imdocker-basic.sh
diff --git a/tests/imdocker-basic.sh b/tests/imdocker-basic.sh
new file mode 100755
index 0000000..f1a569e
--- /dev/null
+++ b/tests/imdocker-basic.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# imdocker unit tests are enabled with --enable-imdocker-tests
+. ${srcdir:=.}/diag.sh init
+NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1)
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imdocker/.libs/imdocker"
+ ListContainersOptions="all=true"
+ GetContainerLogOptions="timestamps=0&follow=1&stdout=1&stderr=0")
+if $!metadata!Names == "'$COOKIE'" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+
+# launch a docker runtime to generate some logs.
+docker run \
+ --name $COOKIE \
+ -e NUMMESSAGES=$NUMMESSAGES \
+ alpine \
+ /bin/sh -c 'for i in $(seq 0 $((NUMMESSAGES-1))); do echo "$i"; done' > /dev/null
+
+#export RS_REDIR=-d
+startup
+
+shutdown_when_empty
+wait_shutdown
+
+echo "cookie: $COOKIE, file name: $RSYSLOG_OUT_LOG"
+seq_check
+
+docker container rm $COOKIE
+exit_test
diff --git a/tests/imdocker-long-logline-vg.sh b/tests/imdocker-long-logline-vg.sh
new file mode 100755
index 0000000..e93a7f3
--- /dev/null
+++ b/tests/imdocker-long-logline-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imdocker-long-logline.sh
diff --git a/tests/imdocker-long-logline.sh b/tests/imdocker-long-logline.sh
new file mode 100755
index 0000000..469da02
--- /dev/null
+++ b/tests/imdocker-long-logline.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# imdocker unit tests are enabled with --enable-imdocker-tests
+. ${srcdir:=.}/diag.sh init
+export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1)
+SIZE=17000
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imdocker/.libs/imdocker"
+ ListContainersOptions="all=true"
+ GetContainerLogOptions="timestamps=0&follow=1&stdout=1&stderr=0")
+
+if $!metadata!Names == "'$COOKIE'" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+
+$MaxMessageSize 64k
+'
+# launch container with a long log line
+docker run \
+ --name $COOKIE \
+ -e size=$SIZE \
+ alpine /bin/sh -c 'echo "$(yes a | head -n $size | tr -d "\n")";' > /dev/null
+
+startup
+wait_file_lines "$RSYSLOG_OUT_LOG" 1
+shutdown_when_empty
+wait_shutdown
+
+# check the log line length
+echo "file name: $RSYSLOG_OUT_LOG"
+count=$(grep "aaaaaaa" $RSYSLOG_OUT_LOG | tr -d "\n" | wc -c)
+
+if [ "x$count" == "x$SIZE" ]; then
+ echo "correct log line length: $count"
+else
+ echo "Incorrect log line length - found $count, expected: $SIZE"
+ error_exit 1
+fi
+
+docker container rm $COOKIE
+exit_test
diff --git a/tests/imdocker-multi-line-vg.sh b/tests/imdocker-multi-line-vg.sh
new file mode 100755
index 0000000..5ca4750
--- /dev/null
+++ b/tests/imdocker-multi-line-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imdocker-multi-line.sh
diff --git a/tests/imdocker-multi-line.sh b/tests/imdocker-multi-line.sh
new file mode 100755
index 0000000..f245fc2
--- /dev/null
+++ b/tests/imdocker-multi-line.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+# imdocker unit tests are enabled with --enable-imdocker-tests
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=999
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1)
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!metadata!Names% %msg%\n")
+
+module(load="../contrib/imdocker/.libs/imdocker" PollingInterval="1"
+ ListContainersOptions="all=true"
+ GetContainerLogOptions="timestamps=0&follow=1&stdout=1&stderr=0")
+
+if $!metadata!Names == "'$COOKIE'" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+
+# launch a docker runtime to generate some logs.
+# These logs started after start-up should get from beginning
+docker run \
+ --name $COOKIE \
+ -e num_items=$((NUMMESSAGES+1)) \
+ -l imdocker.startregex=^multi-line: \
+ alpine \
+ /bin/sh -c \
+ 'for i in `seq 1 $num_items`; do printf "multi-line: $i\n line2....\n line3....\n"; done' > /dev/null
+
+startup
+shutdown_when_empty
+wait_shutdown
+docker container rm $COOKIE
+
+content_check_with_count "$COOKIE multi-line:" $NUMMESSAGES 10
+## check if all the data we expect to get in the file is there
+for i in $(seq 1 $NUMMESSAGES); do
+ grep "$COOKIE multi-line: $i#012 line2....#012 line3...." $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string $COOKIE multi-line: item '$i', it's not there"
+ error_exit 1
+ fi
+done
+exit_test
diff --git a/tests/imdocker-new-logs-from-start-vg.sh b/tests/imdocker-new-logs-from-start-vg.sh
new file mode 100755
index 0000000..1332fcd
--- /dev/null
+++ b/tests/imdocker-new-logs-from-start-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imdocker-new-logs-from-start.sh
diff --git a/tests/imdocker-new-logs-from-start.sh b/tests/imdocker-new-logs-from-start.sh
new file mode 100755
index 0000000..aaaf07d
--- /dev/null
+++ b/tests/imdocker-new-logs-from-start.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# imdocker unit tests are enabled with --enable-imdocker-tests
+. ${srcdir:=.}/diag.sh init
+export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1)
+generate_conf
+add_conf '
+#template(name="template_msg_only" type="string" string="%msg%\n")
+template(name="outfmt" type="string" string="%$!metadata!Names% %msg%\n")
+module(load="../contrib/imdocker/.libs/imdocker" PollingInterval="1"
+ ListContainersOptions="all=true"
+ GetContainerLogOptions="tail=1&timestamps=0&follow=1&stdout=1&stderr=0&tail=1"
+ RetrieveNewLogsFromStart="on"
+ )
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+
+if $!metadata!Names == "'$COOKIE'" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+
+#NUM_ITEMS=1000
+# launch a docker runtime to generate some logs.
+# these log items should be tailed.
+docker run \
+ --rm \
+ -e seq_start=101 \
+ -e seq_end=200 \
+ alpine \
+ /bin/sh -c 'for i in `seq $seq_start $seq_end`; do echo "tailed item $i"; sleep .01; done' > /dev/null &
+
+sleep 1
+
+#export RS_REDIR=-d
+startup
+NUMMESSAGES=1000
+# launch a docker runtime to generate some logs.
+# These logs started after start-up should get from beginning
+docker run \
+ --name $COOKIE \
+ -e NUMMESSAGES=$NUMMESSAGES \
+ alpine \
+ /bin/sh -c 'for i in `seq 1 $NUMMESSAGES`; do echo "log item $i"; done' > /dev/null
+
+shutdown_when_empty
+wait_shutdown
+
+echo "file name: $RSYSLOG_OUT_LOG"
+echo "\"tailed item\" occurred: $(grep -c 'tailed item ' $RSYSLOG_OUT_LOG)/100 (expect less)."
+
+docker container rm $COOKIE
+exit_test
+
diff --git a/tests/imdtls-basic-timeout b/tests/imdtls-basic-timeout
new file mode 100755
index 0000000..9b4c46a
--- /dev/null
+++ b/tests/imdtls-basic-timeout
@@ -0,0 +1,45 @@
+#!/bin/bash
+# added 2023-10-05 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=2000
+export SENDESSAGES=500
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+export TIMEOUT="5"
+
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+# tls.authmode="anon" )
+input( type="imdtls"
+ port="'$PORT_RCVR'"
+ timeout="'$TIMEOUT'"
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# Begin actual testcase
+
+startup
+# valgrind --tool=helgrind $RS_TEST_VALGRIND_EXTRA_OPTS $RS_TESTBENCH_VALGRIND_EXTRA_OPTS --log-fd=1 --error-exitcode=10
+./tcpflood -b1 -W1000 -p$PORT_RCVR -m$SENDESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -L0
+# ./msleep 500
+./tcpflood -b1 -W1000 -i500 -p$PORT_RCVR -m$SENDESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -L0
+./tcpflood -b1 -W1000 -i1000 -p$PORT_RCVR -m$SENDESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -L0
+./tcpflood -b1 -W1000 -i1500 -p$PORT_RCVR -m$SENDESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -L0
+
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imdtls-basic-tlscommands.sh b/tests/imdtls-basic-tlscommands.sh
new file mode 100755
index 0000000..0a65351
--- /dev/null
+++ b/tests/imdtls-basic-tlscommands.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+input( type="imdtls"
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.1,-TLSv1.3
+ Options=Bugs"
+ port="'$PORT_RCVR'")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+# now inject the messages which will fail due protocol configuration
+tcpflood --check-only -k "Protocol=-ALL,TLSv1.3" -p$PORT_RCVR -m$NUMMESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+
+shutdown_when_empty
+wait_shutdown
+
+if content_check --check-only "TLS library does not support SSL_CONF_cmd"
+then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ if content_check --check-only "DTLSv1_listen"
+ then
+ # Found DTLSv1_listen error, no further check needed
+ exit_test
+ else
+ # Check for OpenSSL Error Stack
+ content_check "OpenSSL Error Stack:"
+ fi
+fi
+
+exit_test
diff --git a/tests/imdtls-basic-vg.sh b/tests/imdtls-basic-vg.sh
new file mode 100755
index 0000000..fba111f
--- /dev/null
+++ b/tests/imdtls-basic-vg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then
+ printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n'
+ printf 'a valgrind-internal bug. So we need to skip it.\n'
+ exit 77
+fi
+export USE_VALGRIND="YES"
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes"
+source ${srcdir:-.}/imdtls-basic.sh
diff --git a/tests/imdtls-basic.sh b/tests/imdtls-basic.sh
new file mode 100755
index 0000000..889caad
--- /dev/null
+++ b/tests/imdtls-basic.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# added 2023-10-05 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+# tls.authmode="anon" )
+input( type="imdtls"
+ port="'$PORT_RCVR'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# Begin actual testcase
+
+startup
+# valgrind --tool=helgrind $RS_TEST_VALGRIND_EXTRA_OPTS $RS_TESTBENCH_VALGRIND_EXTRA_OPTS --log-fd=1 --error-exitcode=10
+./tcpflood -b1 -W1000 -p$PORT_RCVR -m$NUMMESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -L0
+
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imdtls-error-cert.sh b/tests/imdtls-error-cert.sh
new file mode 100755
index 0000000..12a1138
--- /dev/null
+++ b/tests/imdtls-error-cert.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2018-11-07 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-fail.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'"
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+input( type="imdtls"
+ port="'$PORT_RCVR'")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+# note: we do not need to generate any messages, config error occurs on startup
+startup
+
+sleep 5 # TODO: FIXME - just checking if we terminate too early
+shutdown_when_empty
+wait_shutdown
+content_check "Error: Certificate file could not be accessed"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/imdtls-sessionbreak-vg.sh b/tests/imdtls-sessionbreak-vg.sh
new file mode 100755
index 0000000..aed1b5a
--- /dev/null
+++ b/tests/imdtls-sessionbreak-vg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then
+ printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n'
+ printf 'a valgrind-internal bug. So we need to skip it.\n'
+ exit 77
+fi
+export USE_VALGRIND="YES"
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes"
+source ${srcdir:-.}/imdtls-sessionbreak.sh
diff --git a/tests/imdtls-sessionbreak.sh b/tests/imdtls-sessionbreak.sh
new file mode 100755
index 0000000..89104ca
--- /dev/null
+++ b/tests/imdtls-sessionbreak.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# added 2020-04-10 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export USE_VALGRIND="yes"
+# TODO remote leak check skip and fix memory leaks caused by session break
+export RS_TESTBENCH_LEAK_CHECK=no
+export PORT_RCVR="$(get_free_port)"
+
+mkdir $RSYSLOG_DYNNAME.workdir
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem"
+ workDirectory="'$RSYSLOG_DYNNAME.workdir'"
+ maxMessageSize="256k")
+main_queue(queue.type="Direct")
+
+$LocalHostName test
+$AbortOnUncleanConfig on
+$PreserveFQDN on
+
+module( load="../plugins/imdtls/.libs/imdtls"
+ tls.AuthMode="x509/certvalid")
+
+input( type="imdtls"
+ port="'$PORT_RCVR'"
+ ruleset="spool"
+)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="spool" queue.type="direct") {
+ if $msg contains "msgnum:" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ }
+}
+'
+startup
+# How many tcpfloods we run at the same tiem
+for ((i=1;i<=10;i++)); do
+ # How many times tcpflood runs in each threads
+ ./tcpflood -Tdtls -p$PORT_RCVR -m$NUMMESSAGES -W1000 -d102400 -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -s &
+ tcpflood_pid=$!
+
+ echo "started tcpflood instance $i (PID $tcpflood_pid)"
+
+ # Give it time to actually connect
+ ./msleep 1000;
+
+ kill -9 $tcpflood_pid # >/dev/null 2>&1;
+ echo "killed tcpflood instance $i (PID $tcpflood_pid)"
+done;
+
+wait_queueempty
+
+netstatresult=$(netstat --all --program 2>&1 | grep "ESTABLISHED" | grep $(cat $RSYSLOG_PIDBASE.pid) | grep $TCPFLOOD_PORT)
+openfd=$(ls -l "/proc/$(cat $RSYSLOG_PIDBASE$1.pid)/fd" | wc -l)
+
+shutdown_when_empty
+wait_shutdown
+
+if [[ "$netstatresult" == "" ]]
+then
+ echo "OK!"
+else
+ echo "STILL OPENED Connections: "
+ echo $netstatresult
+ echo "Open files at the end: "
+ echo $openfd
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-basic-2GB-file.sh b/tests/imfile-basic-2GB-file.sh
new file mode 100755
index 0000000..d6b40d1
--- /dev/null
+++ b/tests/imfile-basic-2GB-file.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# written 2018-11-09 by Rainer Gerhards
+# this test checks that 2GiB (31 bit) file size region is handled correctly
+# it first generates a file that is 2GiB-64 bytes, processes it, and then
+# adds a couple of messages to get it over 2GiB.
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TB_TEST_MAX_RUNTIME=3600 # test is very slow as it works on large files
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+touch $RSYSLOG_DYNNAME.input
+startup
+
+# initial file: 2GiB - 1 message (54 byte)
+./inputfilegen -s 2147483584 -d47 -M $RSYSLOG_DYNNAME.msgcnt > $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+export NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)"
+
+wait_file_lines --delay 2500 --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES 3000
+
+# add one message --> exactly 2GB
+./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+(( NUMMESSAGES++ ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+# add one more message --> now we go over 2GB
+./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+(( NUMMESSAGES++ ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+# add even more messages
+./inputfilegen -m10000 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+NUMMESSAGES=$(( NUMMESSAGES + 10000 ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $(( NUMMESSAGES - 1))
+exit_test
diff --git a/tests/imfile-basic-legacy.sh b/tests/imfile-basic-legacy.sh
new file mode 100755
index 0000000..f08f5d5
--- /dev/null
+++ b/tests/imfile-basic-legacy.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+NUMMESSAGES=50000
+mkdir WorkDirectory $RSYSLOG_DYNNAME.work
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.work
+$ModLoad ../plugins/imfile/.libs/imfile
+$InputFileName ./'$RSYSLOG_DYNNAME'.input
+$InputFileTag file:
+$InputFileStateFile stat-file1
+$InputFileSeverity error
+$InputFileFacility local7
+$InputFileMaxLinesAtOnce 100000
+$InputRunFileMonitor
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+# generate input file first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+./inputfilegen -m $NUMMESSAGES > $RSYSLOG_DYNNAME.input
+startup
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imfile-basic-vg.sh b/tests/imfile-basic-vg.sh
new file mode 100755
index 0000000..586e7db
--- /dev/null
+++ b/tests/imfile-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imfile-basic.sh
diff --git a/tests/imfile-basic-vgthread.sh b/tests/imfile-basic-vgthread.sh
new file mode 100755
index 0000000..53b78d2
--- /dev/null
+++ b/tests/imfile-basic-vgthread.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD."
+export NUMMESSAGES=50000
+if grep -q 'release 6\.' <<< "$(cat /etc/redhat-release 2>/dev/null)"; then
+ echo "RHEL/CentOS 6 detected, adding valgrind suppressions"
+ export RS_TEST_VALGRIND_EXTRA_OPTS="--suppressions=${srcdir}/imfile-basic-vgthread.supp"
+fi
+
+exit
+generate_conf
+add_conf '
+$ModLoad ../plugins/imfile/.libs/imfile
+$InputFileName ./'$RSYSLOG_DYNNAME'.input
+$InputFileTag file:
+$InputFileStateFile stat-file1
+$InputFileSeverity error
+$InputFileFacility local7
+$InputFileMaxLinesAtOnce 100000
+$InputRunFileMonitor
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" ./'$RSYSLOG_OUT_LOG';outfmt
+'
+
+# generate input file first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+./inputfilegen -m $NUMMESSAGES > $RSYSLOG_DYNNAME.input
+ls -l $RSYSLOG_DYNNAME.input
+
+startup_vgthread
+wait_file_lines
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+seq_check
+exit_test
diff --git a/tests/imfile-basic.sh b/tests/imfile-basic.sh
new file mode 100755
index 0000000..a87fbd4
--- /dev/null
+++ b/tests/imfile-basic.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+generate_conf
+# NOTE: do NOT set a working directory!
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" tag="file:")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+else
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsgs")
+'
+# make sure file exists when rsyslog starts up
+touch $RSYSLOG_DYNNAME.input
+startup
+./inputfilegen -m $NUMMESSAGES >> $RSYSLOG_DYNNAME.input
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+content_check "imfile: no working or state file directory set" $RSYSLOG_DYNNAME.othermsgs
+exit_test
diff --git a/tests/imfile-discard-truncated-line.sh b/tests/imfile-discard-truncated-line.sh
new file mode 100755
index 0000000..4cc95e1
--- /dev/null
+++ b/tests/imfile-discard-truncated-line.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test mimics the test imfile-readmode2.sh, but works via
+# endmsg.regex. It's kind of a base test for the regex functionality.
+echo ======================================================================
+# Check if inotify header exist
+echo [imfile-discard-truncated-line.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ discardTruncatedMsg="on"
+ msgDiscardingError="off"
+ Tag="file:"
+ startmsg.regex="^[^ ]"
+ ruleset="ruleset")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt")
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+msgnum:1
+msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ msgnum:4 cccccccccccccccccccccccccccccccccccccccccccc
+ msgnum:5 dddddddddddddddddddddddddddddddddddddddddddd
+msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff
+ msgnum:8 gggggggggggggggggggggggggggggggggggggggggggg
+msgnum:9' > $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf 'HEADER msgnum:0
+HEADER msgnum:1
+HEADER msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\\n msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\n msgnum:4 ccccccc
+HEADER msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\\\\n msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff\\\\n msgnum:8 ggggggg
+HEADER msgnum:9\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+grep "imfile error:.*rest of message will not be processed" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -eq 0 ]; then
+ echo
+ echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-endmsg.regex-vg.sh b/tests/imfile-endmsg.regex-vg.sh
new file mode 100755
index 0000000..abd3442
--- /dev/null
+++ b/tests/imfile-endmsg.regex-vg.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test tests imfile endmsg.regex.
+USE_VALGRIND=true
+echo ======================================================================
+echo [imfile-endmsg.regex.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.crio.input"
+ Tag="file:" addMetadata="on" escapelf="on"
+ endmsg.regex="^[^ ]+ (stdout|stderr) F ")
+
+template(name="outfmt" type="list") {
+ property(name="$!all-json-plain")
+ constant(value=" ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ startup_vg
+else
+ startup
+fi
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+
+# write the beginning of the file
+echo 'date stdout P msgnum:0' > $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout F msgnum:1' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input
+
+# sleep a little to give rsyslog a chance to begin processing
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout P msgnum:3' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:4' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:5' >> $RSYSLOG_DYNNAME.crio.input
+
+# give it time to finish
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:7' >> $RSYSLOG_DYNNAME.crio.input
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown # we need to wait until rsyslogd is finished!
+fi
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(wc -l $RSYSLOG_OUT_LOG | awk '{print $1}' 2>/dev/null)
+
+rc=0
+if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 lines, got $NUMLINES"
+ rc=1
+fi
+
+## check if all the data we expect to get in the file is there
+
+for string in "metadata.*filename.*crio[.]input.*msgnum:0.*msgnum:1" \
+ "metadata.*filename.*crio[.]input.*msgnum:2" \
+ "metadata.*filename.*crio[.]input.*msgnum:3.*msgnum:4.*msgnum:5.*msgnum:6" ; do
+ if grep "$string" $RSYSLOG_OUT_LOG > /dev/null 2>&1 ; then
+ : # ok
+ else
+ echo "Error: the expected string '$string' not found"
+ rc=1
+ fi
+done
+
+if [ $rc -ne 0 ]; then
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-endmsg.regex-with-example-vg.sh b/tests/imfile-endmsg.regex-with-example-vg.sh
new file mode 100755
index 0000000..76d7431
--- /dev/null
+++ b/tests/imfile-endmsg.regex-with-example-vg.sh
@@ -0,0 +1,147 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test tests imfile endmsg.regex.
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export USE_VALGRIND="YES"
+
+mkdir $RSYSLOG_DYNNAME.statefiles
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+
+input(type="imfile"
+ statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles"
+ File="./'$RSYSLOG_DYNNAME'.*.input"
+ Tag="file:" addMetadata="on" escapelf="off"
+ endmsg.regex="(^[^ ]+ (stdout|stderr) F )|(\\n\"}$)")
+
+if $msg startswith "{" then {
+ action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.json.rulebase'")
+ foreach ($.ii in $!multilinejson) do {
+ if strlen($!@timestamp) == 0 then {
+ set $!@timestamp = $.ii!time;
+ }
+ if strlen($!stream) == 0 then {
+ set $!stream = $.ii!stream;
+ }
+ if strlen($!log) == 0 then {
+ set $!log = $.ii!log;
+ } else {
+ reset $!log = $!log & $.ii!log;
+ }
+ }
+ unset $!multilinejson;
+} else {
+ action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.crio.rulebase'")
+ foreach ($.ii in $!multilinecrio) do {
+ if strlen($!@timestamp) == 0 then {
+ set $!@timestamp = $.ii!time;
+ }
+ if strlen($!stream) == 0 then {
+ set $!stream = $.ii!stream;
+ }
+ if strlen($!log) == 0 then {
+ set $!log = $.ii!log;
+ } else {
+ reset $!log = $!log & $.ii!log;
+ }
+ }
+ unset $!multilinecrio;
+}
+
+template(name="outfmt" type="list") {
+ property(name="$!all-json-plain")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+
+# write the beginning of the file
+echo 'date stdout P msgnum:0' > $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:0"}' > $RSYSLOG_DYNNAME.json.input
+echo 'date stdout F msgnum:1' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:1\n"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:2\n"}' >> $RSYSLOG_DYNNAME.json.input
+
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+fi
+
+wait_file_lines $RSYSLOG_OUT_LOG 4
+
+echo 'date stdout P msgnum:3' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:3"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:4' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:4"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:5' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:5"}' >> $RSYSLOG_DYNNAME.json.input
+
+# give it time to finish
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1 # of course, this is racy
+fi
+# so we do at least wait for the queue to be empty - this should work in hopefully most cases
+wait_queueempty
+
+echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:6\n"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:7' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:7"}' >> $RSYSLOG_DYNNAME.json.input
+
+wait_file_lines $RSYSLOG_OUT_LOG 6
+
+shutdown_when_empty
+wait_shutdown
+
+
+## check if we have the correct number of messages
+
+NUMLINES=$(wc -l $RSYSLOG_OUT_LOG | awk '{print $1}' 2>/dev/null)
+
+rc=0
+if [ ! $NUMLINES -eq 6 ]; then
+ echo "ERROR: expecting 6 lines, got $NUMLINES"
+ cat -n $RSYSLOG_OUT_LOG
+ rc=1
+fi
+
+## check if all the data we expect to get in the file is there
+
+for string in "metadata.*filename.*json[.]input.*msgnum:0msgnum:1" \
+ "metadata.*filename.*crio[.]input.*msgnum:0msgnum:1" \
+ "metadata.*filename.*json[.]input.*msgnum:2" \
+ "metadata.*filename.*crio[.]input.*msgnum:2" \
+ "metadata.*filename.*json[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" \
+ "metadata.*filename.*crio[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" ; do
+ if grep "$string" $RSYSLOG_OUT_LOG > /dev/null 2>&1 ; then
+ : # ok
+ else
+ echo "Error: the expected string '$string' not found"
+ rc=1
+ fi
+done
+
+if [ $rc -ne 0 ]; then
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-endmsg.regex-with-example.sh b/tests/imfile-endmsg.regex-with-example.sh
new file mode 100755
index 0000000..4bcd126
--- /dev/null
+++ b/tests/imfile-endmsg.regex-with-example.sh
@@ -0,0 +1,157 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test tests imfile endmsg.regex.
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export IMFILECHECKTIMEOUT="60"
+export IMFILELASTINPUTLINES="6"
+
+mkdir $RSYSLOG_DYNNAME.statefiles
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+
+input(type="imfile"
+ statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles"
+ File="./'$RSYSLOG_DYNNAME'.*.input"
+ Tag="file:" addMetadata="on" escapelf="off"
+ endmsg.regex="(^[^ ]+ (stdout|stderr) F )|(\\n\"}$)")
+
+if $msg startswith "{" then {
+ action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.json.rulebase'")
+ foreach ($.ii in $!multilinejson) do {
+ if strlen($!@timestamp) == 0 then {
+ set $!@timestamp = $.ii!time;
+ }
+ if strlen($!stream) == 0 then {
+ set $!stream = $.ii!stream;
+ }
+ if strlen($!log) == 0 then {
+ set $!log = $.ii!log;
+ } else {
+ reset $!log = $!log & $.ii!log;
+ }
+ }
+ unset $!multilinejson;
+} else {
+ action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.crio.rulebase'")
+ foreach ($.ii in $!multilinecrio) do {
+ if strlen($!@timestamp) == 0 then {
+ set $!@timestamp = $.ii!time;
+ }
+ if strlen($!stream) == 0 then {
+ set $!stream = $.ii!stream;
+ }
+ if strlen($!log) == 0 then {
+ set $!log = $.ii!log;
+ } else {
+ reset $!log = $!log & $.ii!log;
+ }
+ }
+ unset $!multilinecrio;
+}
+
+template(name="outfmt" type="list") {
+ property(name="$!all-json-plain")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ startup_vg
+else
+ startup
+fi
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+
+# write the beginning of the file
+echo 'date stdout P msgnum:0' > $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:0"}' > $RSYSLOG_DYNNAME.json.input
+echo 'date stdout F msgnum:1' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:1\n"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:2\n"}' >> $RSYSLOG_DYNNAME.json.input
+
+# sleep a little to give rsyslog a chance to begin processing
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout P msgnum:3' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:3"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:4' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:4"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:5' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:5"}' >> $RSYSLOG_DYNNAME.json.input
+
+# give it time to finish
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:6\n"}' >> $RSYSLOG_DYNNAME.json.input
+echo 'date stdout P msgnum:7' >> $RSYSLOG_DYNNAME.crio.input
+echo '{"time":"date", "stream":"stdout", "log":"msgnum:7"}' >> $RSYSLOG_DYNNAME.json.input
+
+content_check_with_count "$RSYSLOG_DYNNAME" $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown # we need to wait until rsyslogd is finished!
+fi
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(wc -l $RSYSLOG_OUT_LOG | awk '{print $1}' 2>/dev/null)
+
+rc=0
+if [ ! $NUMLINES -eq $IMFILELASTINPUTLINES ]; then
+ echo "ERROR: expecting $IMFILELASTINPUTLINES lines, got $NUMLINES"
+ rc=1
+fi
+
+## check if all the data we expect to get in the file is there
+
+for string in "metadata.*filename.*json[.]input.*msgnum:0msgnum:1" \
+ "metadata.*filename.*crio[.]input.*msgnum:0msgnum:1" \
+ "metadata.*filename.*json[.]input.*msgnum:2" \
+ "metadata.*filename.*crio[.]input.*msgnum:2" \
+ "metadata.*filename.*json[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" \
+ "metadata.*filename.*crio[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" ; do
+ if grep "$string" $RSYSLOG_OUT_LOG > /dev/null 2>&1 ; then
+ : # ok
+ else
+ echo "Error: the expected string '$string' not found"
+ rc=1
+ fi
+done
+
+if [ $rc -ne 0 ]; then
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-endmsg.regex.crio.rulebase b/tests/imfile-endmsg.regex.crio.rulebase
new file mode 100644
index 0000000..002ef44
--- /dev/null
+++ b/tests/imfile-endmsg.regex.crio.rulebase
@@ -0,0 +1,15 @@
+version=2
+rule=:%{"name":"multilinecrio", "type":"repeat",
+ "parser":[
+ {"type":"word", "name":"time"},
+ {"type":"literal", "text":" "},
+ {"type":"word", "name":"stream"},
+ {"type":"literal", "text":" "},
+ {"type":"word", "name":"partial"},
+ {"type":"literal", "text":" "},
+ {"type":"char-sep", "name":"log", "extradata":"\n"}
+ ],
+ "while":[
+ {"type":"literal", "text":"\n"},
+ ]
+ }%
diff --git a/tests/imfile-endmsg.regex.json.rulebase b/tests/imfile-endmsg.regex.json.rulebase
new file mode 100644
index 0000000..6bdfac0
--- /dev/null
+++ b/tests/imfile-endmsg.regex.json.rulebase
@@ -0,0 +1,9 @@
+version=2
+rule=:%{"name":"multilinejson", "type":"repeat", "option.permitMismatchInParser": true,
+ "parser":[
+ {"type":"json", "name":"."}
+ ],
+ "while":[
+ {"type":"char-sep", "extradata":"{"}
+ ]
+ }%
diff --git a/tests/imfile-endmsg.regex.sh b/tests/imfile-endmsg.regex.sh
new file mode 100755
index 0000000..e2c5911
--- /dev/null
+++ b/tests/imfile-endmsg.regex.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test tests imfile endmsg.regex.
+echo ======================================================================
+echo [imfile-endmsg.regex.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.crio.input"
+ Tag="file:" addMetadata="on" escapelf="on"
+ endmsg.regex="^[^ ]+ (stdout|stderr) F ")
+
+template(name="outfmt" type="list") {
+ property(name="$!all-json-plain")
+ constant(value=" ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ startup_vg
+else
+ startup
+fi
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+
+# write the beginning of the file
+echo 'date stdout P msgnum:0' > $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout F msgnum:1' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input
+
+# sleep a little to give rsyslog a chance to begin processing
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout P msgnum:3' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:4' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:5' >> $RSYSLOG_DYNNAME.crio.input
+
+# give it time to finish
+if [ -n "${USE_GDB:-}" ] ; then
+ sleep 54321 || :
+else
+ sleep 1
+fi
+
+echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input
+echo 'date stdout P msgnum:7' >> $RSYSLOG_DYNNAME.crio.input
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown # we need to wait until rsyslogd is finished!
+fi
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(wc -l $RSYSLOG_OUT_LOG | awk '{print $1}' 2>/dev/null)
+
+rc=0
+if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 lines, got $NUMLINES"
+ rc=1
+fi
+
+## check if all the data we expect to get in the file is there
+
+for string in "metadata.*filename.*crio[.]input.*msgnum:0.*msgnum:1" \
+ "metadata.*filename.*crio[.]input.*msgnum:2" \
+ "metadata.*filename.*crio[.]input.*msgnum:3.*msgnum:4.*msgnum:5.*msgnum:6" ; do
+ if grep "$string" $RSYSLOG_OUT_LOG > /dev/null 2>&1 ; then
+ : # ok
+ else
+ echo "Error: the expected string '$string' not found"
+ rc=1
+ fi
+done
+
+if [ $rc -ne 0 ]; then
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-endregex-save-lf-persist.sh b/tests/imfile-endregex-save-lf-persist.sh
new file mode 100755
index 0000000..460b8e3
--- /dev/null
+++ b/tests/imfile-endregex-save-lf-persist.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+echo ======================================================================
+echo [imfile-endregex-save-lf-persist.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ PersistStateInterval="1"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1
+ msgnum:2' > $RSYSLOG_DYNNAME.input
+./msleep 300
+echo 'msgnum:3' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:4
+ msgnum:5' >> $RSYSLOG_DYNNAME.input
+./msleep 200
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+./msleep 200
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf 'HEADER msgnum:0\\\\n msgnum:1\\\\n msgnum:2
+HEADER msgnum:3
+HEADER msgnum:4\\\\n msgnum:5\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-endregex-save-lf.sh b/tests/imfile-endregex-save-lf.sh
new file mode 100755
index 0000000..32725f4
--- /dev/null
+++ b/tests/imfile-endregex-save-lf.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test mimics the test imfile-readmode2.sh, but works via
+# endmsg.regex. It's kind of a base test for the regex functionality.
+echo ======================================================================
+echo [imfile-endregex-save-lf.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1
+ msgnum:2' > $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf 'HEADER msgnum:0\\\\n msgnum:1\\\\n msgnum:2\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-endregex-timeout-none-polling.sh b/tests/imfile-endregex-timeout-none-polling.sh
new file mode 100755
index 0000000..de34de5
--- /dev/null
+++ b/tests/imfile-endregex-timeout-none-polling.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ $(uname) = "SunOS" ] ; then
+ echo "Solaris: FIX ME"
+ exit 77
+fi
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile"
+ mode="polling"
+ pollingInterval="2"
+ )
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ PersistStateInterval="1"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+./msleep 5000 # wait 5 seconds - this shall cause a timeout
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+./msleep 200
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo 'HEADER msgnum:0\\n msgnum:1\\n msgnum:2\\n msgnum:3' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-endregex-timeout-none.sh b/tests/imfile-endregex-timeout-none.sh
new file mode 100755
index 0000000..7554c27
--- /dev/null
+++ b/tests/imfile-endregex-timeout-none.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+echo ======================================================================
+echo [imfile-endregex-timeout-none.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ PersistStateInterval="1"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+./msleep 5000 # wait 5 seconds - this shall cause a timeout
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+./msleep 200
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf 'HEADER msgnum:0\\\\n msgnum:1\\\\n msgnum:2\\\\n msgnum:3\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-endregex-timeout-polling.sh b/tests/imfile-endregex-timeout-polling.sh
new file mode 100755
index 0000000..8149ba8
--- /dev/null
+++ b/tests/imfile-endregex-timeout-polling.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ $(uname) = "SunOS" ] ; then
+ echo "Solaris: FIX ME"
+ exit 77
+fi
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile"
+ mode="polling"
+ pollingInterval="2"
+ )
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ PersistStateInterval="1"
+ readTimeout="2"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+./msleep 10000
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+./msleep 2000
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo 'HEADER msgnum:0\\n msgnum:1
+HEADER msgnum:2\\n msgnum:3' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-endregex-timeout-with-shutdown-polling.sh b/tests/imfile-endregex-timeout-with-shutdown-polling.sh
new file mode 100755
index 0000000..662fe70
--- /dev/null
+++ b/tests/imfile-endregex-timeout-with-shutdown-polling.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile" mode="polling" pollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ PersistStateInterval="1"
+ readTimeout="3"
+ startmsg.regex="^[^ ]")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+content_check_with_count 'msgnum:0
+ msgnum:1' 1 $IMFILECHECKTIMEOUT
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+
+# we now do a stop and restart of rsyslog. This checks that everything
+# works across restarts.
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+#echo DROPPING YOU TO BASH!
+#bash
+
+startup
+
+# new data
+echo ' msgnum:4' >> $RSYSLOG_DYNNAME.input
+content_check_with_count 'msgnum:2
+ msgnum:3
+ msgnum:4' 1 $IMFILECHECKTIMEOUT
+
+echo ' msgnum:5
+ msgnum:6' >> $RSYSLOG_DYNNAME.input
+content_check_with_count 'msgnum:5
+ msgnum:6' 1 $IMFILECHECKTIMEOUT
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-endregex-timeout-with-shutdown.sh b/tests/imfile-endregex-timeout-with-shutdown.sh
new file mode 100755
index 0000000..a33fce3
--- /dev/null
+++ b/tests/imfile-endregex-timeout-with-shutdown.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify-only
+export IMFILECHECKTIMEOUT="90"
+
+mkdir ${RSYSLOG_DYNNAME}.statefiles
+touch $RSYSLOG_DYNNAME.input # prevent misleading rsyslog diagnostic on startup
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile" timeoutGranularity="1"
+ statefile.Directory="'${RSYSLOG_DYNNAME}'.statefiles")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:"
+ PersistStateInterval="1" readTimeout="2" startmsg.regex="^[^ ]")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+content_check_with_count "msgnum:0
+ msgnum:1" 1 $IMFILECHECKTIMEOUT
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+
+# we now do a stop and restart of rsyslog. This checks that everything
+# works across restarts.
+shutdown_when_empty
+wait_shutdown
+
+# re-start (so we read persisted state file)
+startup
+
+# new data
+echo ' msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo INPUT FILE NOW: ; cat -n $RSYSLOG_DYNNAME.input
+content_check_with_count "msgnum:2
+ msgnum:3
+ msgnum:4" 1 $IMFILECHECKTIMEOUT
+
+echo ' msgnum:5
+ msgnum:6' >> $RSYSLOG_DYNNAME.input
+echo INPUT FILE NOW: ; cat -n $RSYSLOG_DYNNAME.input
+content_check_with_count "msgnum:5
+ msgnum:6" 1 $IMFILECHECKTIMEOUT
+
+
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-endregex-timeout.sh b/tests/imfile-endregex-timeout.sh
new file mode 100755
index 0000000..a08301c
--- /dev/null
+++ b/tests/imfile-endregex-timeout.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify-only
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile" timeoutGranularity="1")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:"
+ PersistStateInterval="1" readTimeout="2" startmsg.regex="^[^ ]")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+
+# we need to sleep a bit between writes to give imfile a chance
+# to pick up the data (IN MULTIPLE ITERATIONS!)
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+content_check_with_count "msgnum:0
+ msgnum:1" 1 $IMFILECHECKTIMEOUT
+
+echo ' msgnum:2
+ msgnum:3' >> $RSYSLOG_DYNNAME.input
+content_check_with_count "msgnum:2
+ msgnum:3" 1 $IMFILECHECKTIMEOUT
+
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-endregex-vg.sh b/tests/imfile-endregex-vg.sh
new file mode 100755
index 0000000..394ac9f
--- /dev/null
+++ b/tests/imfile-endregex-vg.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ startmsg.regex="^[^ ]")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup_vg
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+wait_file_lines $RSYSLOG_OUT_LOG 1
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+
+wait_file_lines $RSYSLOG_OUT_LOG 3
+
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+## check if we have the correct number of messages
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ error_exit 1
+ fi
+done
+
+exit_test
diff --git a/tests/imfile-endregex.sh b/tests/imfile-endregex.sh
new file mode 100755
index 0000000..4984c52
--- /dev/null
+++ b/tests/imfile-endregex.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test mimics the test imfile-readmode2.sh, but works via
+# endmsg.regex. It's kind of a base test for the regex functionality.
+echo ======================================================================
+echo [imfile-endregex.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ startmsg.regex="^[^ ]")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# sleep a little to give rsyslog a chance to begin processing
+sleep 1
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+
+# give it time to finish
+sleep 1
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-error-not-repeated.sh b/tests/imfile-error-not-repeated.sh
new file mode 100755
index 0000000..cc2b06e
--- /dev/null
+++ b/tests/imfile-error-not-repeated.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# add 2017-04-28 by Pascal Withopf, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile" mode="polling" pollingInterval="1")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="tag1" ruleset="ruleset1")
+
+template(name="tmpl1" type="string" string="%msg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="tmpl1")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+'
+startup
+./msleep 3000
+
+echo 'testmessage1
+testmessage2
+testmessage3' > $RSYSLOG_DYNNAME.input
+
+./msleep 2000
+rm ./'$RSYSLOG_DYNNAME'.input
+./msleep 3000
+shutdown_when_empty
+wait_shutdown
+
+grep "file.*$RSYSLOG_DYNNAME.input.*No such file or directory" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+if [ $(grep "No such file or directory" ${RSYSLOG2_OUT_LOG} | wc -l) -ne 1 ]; then
+ echo "FAIL: expected error message is put out multiple times. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+echo 'testmessage1
+testmessage2
+testmessage3' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-escapelf.replacement-empty.sh b/tests/imfile-escapelf.replacement-empty.sh
new file mode 100755
index 0000000..759c8a9
--- /dev/null
+++ b/tests/imfile-escapelf.replacement-empty.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Written in 2019 by Rainer Gerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" ruleset="output" escapelf.replacement=""
+ File="./'$RSYSLOG_DYNNAME'.input" tag="file:" startmsg.regex="^msg")
+
+template(name="outfmt" type="string" string="%msg%\n")
+ruleset(name="output") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# make sure file exists when rsyslog starts up
+echo 'msg 1 part 1
+ msg 1 part 2
+msg 2
+msg INVISIBLE by design' > $RSYSLOG_DYNNAME.input
+startup
+export NUMMESSAGES=2
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='msg 1 part 1 msg 1 part 2
+msg 2'
+cmp_exact
+exit_test
diff --git a/tests/imfile-escapelf.replacement.sh b/tests/imfile-escapelf.replacement.sh
new file mode 100755
index 0000000..6039947
--- /dev/null
+++ b/tests/imfile-escapelf.replacement.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Written in 2019 by Rainer Gerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" ruleset="output" escapelf.replacement="[LF]"
+ File="./'$RSYSLOG_DYNNAME'.input" tag="file:" startmsg.regex="^msg")
+
+template(name="outfmt" type="string" string="%msg%\n")
+ruleset(name="output") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# make sure file exists when rsyslog starts up
+echo 'msg 1 part 1
+ msg 1 part 2
+msg 2
+msg INVISIBLE by design' > $RSYSLOG_DYNNAME.input
+startup
+export NUMMESSAGES=2
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='msg 1 part 1[LF] msg 1 part 2
+msg 2'
+cmp_exact
+exit_test
diff --git a/tests/imfile-file-not-found-error.sh b/tests/imfile-file-not-found-error.sh
new file mode 100755
index 0000000..029a33c
--- /dev/null
+++ b/tests/imfile-file-not-found-error.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# add 2017-04-28 by Pascal Withopf, released under ASL 2.0
+echo [imfile-file-not-found-error.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="tag1" ruleset="ruleset1")
+
+template(name="tmpl1" type="string" string="%msg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="tmpl1")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+'
+startup
+./msleep 2000
+
+echo 'testmessage1
+testmessage2
+testmessage3' > $RSYSLOG_DYNNAME.input
+
+./msleep 2000
+shutdown_when_empty
+wait_shutdown
+
+grep "file.*$RSYSLOG_DYNNAME.input.*No such file or directory" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+printf 'testmessage1
+testmessage2
+testmessage3\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-fileNotFoundError-parameter.sh b/tests/imfile-fileNotFoundError-parameter.sh
new file mode 100755
index 0000000..e890b72
--- /dev/null
+++ b/tests/imfile-fileNotFoundError-parameter.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+echo [imfile-file-not-found-error.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" File="testsuites/NotExistingInputFile" Tag="tag1" fileNotFoundError="off")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+grep "error*file*NotExistingInputFile*No such file or directory" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -eq 0 ]; then
+ echo
+ echo "FAIL: error message from missing input file found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-freshStartTail1.sh b/tests/imfile-freshStartTail1.sh
new file mode 100755
index 0000000..ed0f3fb
--- /dev/null
+++ b/tests/imfile-freshStartTail1.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# add 2018-05-17 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" freshStartTail="on" Tag="pro"
+ File="'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:syslogtag, contains, "pro" action(type="omfile" File=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+'
+startup
+
+echo '{ "id": "jinqiao1"}' > $RSYSLOG_DYNNAME.input
+./msleep 2000
+echo '{ "id": "jinqiao2"}' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty
+wait_shutdown
+
+echo '{ "id": "jinqiao1"}
+{ "id": "jinqiao2"}' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-freshStartTail2.sh b/tests/imfile-freshStartTail2.sh
new file mode 100755
index 0000000..802b712
--- /dev/null
+++ b/tests/imfile-freshStartTail2.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-05-17 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export IMFILECHECKTIMEOUT="60"
+
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" freshStartTail="on" Tag="pro"
+ File="'$RSYSLOG_DYNNAME'.input.*")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:syslogtag, contains, "pro" action(type="omfile" File=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+'
+startup
+
+echo '{ "id": "jinqiao1"}' > $RSYSLOG_DYNNAME.input.a
+content_check_with_count '{ "id": "jinqiao1"}' 1 $IMFILECHECKTIMEOUT
+
+echo '{ "id": "jinqiao2"}' >> $RSYSLOG_DYNNAME.input.a
+content_check_with_count '{ "id": "jinqiao2"}' 1 $IMFILECHECKTIMEOUT
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-freshStartTail3.sh b/tests/imfile-freshStartTail3.sh
new file mode 100755
index 0000000..0e651b7
--- /dev/null
+++ b/tests/imfile-freshStartTail3.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2018-05-17 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" freshStartTail="on" Tag="pro"
+ File="'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:syslogtag, contains, "pro" action(type="omfile" File=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+'
+
+echo '{ "id": "jinqiao1"}' > $RSYSLOG_DYNNAME.input
+startup
+./msleep 2000
+echo '{ "id": "jinqiao2"}' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty
+wait_shutdown
+
+echo '{ "id": "jinqiao2"}' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-growing-file-id.sh b/tests/imfile-growing-file-id.sh
new file mode 100755
index 0000000..2649c8b
--- /dev/null
+++ b/tests/imfile-growing-file-id.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify-only
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1")
+
+/* Filter out busy debug output */
+global( debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"])
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+# generate small input file - state file must be inode only
+./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input
+ls -li $RSYSLOG_DYNNAME.input
+
+echo "STEP 1 - small input"
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo "STEP 2 - still small input"
+# add a bit to input file, but state file must still be inode only
+./inputfilegen -m 1 -i1 >> $RSYSLOG_DYNNAME.input
+ls -li $RSYSLOG_DYNNAME.input*
+if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then
+ echo FAIL: more than one state file in work directory:
+ ls -l ${RSYSLOG_DYNNAME}.spool
+ error_exit 1
+fi
+
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo "STEP 3 - larger input, hash shall be used"
+./inputfilegen -m 998 -i 2 >> $RSYSLOG_DYNNAME.input
+ls -li $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then
+ echo FAIL: more than one state file in work directory:
+ ls -l ${RSYSLOG_DYNNAME}.spool
+ error_exit 1
+fi
+
+
+echo "STEP 4 - append to larger input, hash state file must now be found"
+./inputfilegen -m 1000 -i 1000 >> $RSYSLOG_DYNNAME.input
+ls -li $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then
+ echo FAIL: more than one state file in work directory:
+ ls -l ${RSYSLOG_DYNNAME}.spool
+ error_exit 1
+fi
+
+seq_check 0 1999
+exit_test
diff --git a/tests/imfile-ignore-old-file-1.sh b/tests/imfile-ignore-old-file-1.sh
new file mode 100755
index 0000000..9ae660c
--- /dev/null
+++ b/tests/imfile-ignore-old-file-1.sh
@@ -0,0 +1,37 @@
+#! /bin/bash
+# Don't read a file with old timestamp
+echo [imfile-ignore-old-file-1.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+
+# create a log for testing
+./inputfilegen -m 1000 > ${RSYSLOG_DYNNAME}.input
+
+touch -m -t 201806010000.00 ./${RSYSLOG_DYNNAME}.input
+
+startup
+
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+
+if ls ${RSYSLOG_OUT_LOG} > /dev/null; then
+ echo "FAIL: rsyslog.out.log isn't expected to be generated!"
+ exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-ignore-old-file-2.sh b/tests/imfile-ignore-old-file-2.sh
new file mode 100755
index 0000000..d69cb5e
--- /dev/null
+++ b/tests/imfile-ignore-old-file-2.sh
@@ -0,0 +1,43 @@
+#! /bin/bash
+# Don't read a file with old timestamp
+# touch the file, then read it
+echo [imfile-ignore-old-file-2.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+
+# create a log for testing
+./inputfilegen -m 1000 > ${RSYSLOG_DYNNAME}.input
+touch -m -t 201806010000.00 ./${RSYSLOG_DYNNAME}.input
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+
+if ls ${RSYSLOG_OUT_LOG} > /dev/null; then
+ echo "FAIL: rsyslog.out.log isn't expected to be generated!"
+ exit 1
+fi
+
+# change timestamp
+./inputfilegen -m 1000 -i 1000 >> ${RSYSLOG_DYNNAME}.input
+ls -l ./${RSYSLOG_DYNNAME}.input
+./msleep 500
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 0 1999
+exit_test
diff --git a/tests/imfile-ignore-old-file-3.sh b/tests/imfile-ignore-old-file-3.sh
new file mode 100755
index 0000000..e74e3a4
--- /dev/null
+++ b/tests/imfile-ignore-old-file-3.sh
@@ -0,0 +1,34 @@
+#! /bin/bash
+# Multiple files with different timestamp, ignore those files with old timestamp
+echo [imfile-ignore-old-file-3.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.ignore3.*"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# create log files for testing
+./inputfilegen -m 1000 > ${RSYSLOG_DYNNAME}.input.ignore3.1
+touch -m -t 201806010000.00 ./${RSYSLOG_DYNNAME}.input.ignore3.1
+
+./inputfilegen -m 1000 -i 1000 > ${RSYSLOG_DYNNAME}.input.ignore3.2
+
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 1000 1999
+exit_test
diff --git a/tests/imfile-ignore-old-file-4.sh b/tests/imfile-ignore-old-file-4.sh
new file mode 100755
index 0000000..e96d5dc
--- /dev/null
+++ b/tests/imfile-ignore-old-file-4.sh
@@ -0,0 +1,31 @@
+#! /bin/bash
+# set ignoreolderthan to zero
+echo [imfile-ignore-old-file-4.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ ignoreolderthan="0"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# create a log for testing
+./inputfilegen -m 1000 > ${RSYSLOG_DYNNAME}.input
+touch -m -t 201806010000.00 ./${RSYSLOG_DYNNAME}.input
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 0 999
+exit_test
diff --git a/tests/imfile-ignore-old-file-5.sh b/tests/imfile-ignore-old-file-5.sh
new file mode 100755
index 0000000..66bd910
--- /dev/null
+++ b/tests/imfile-ignore-old-file-5.sh
@@ -0,0 +1,47 @@
+#! /bin/bash
+# [polling mode] Don't read a file with old timestamp
+# touch the file, then read it
+
+echo [imfile-ignore-old-file-5.sh]
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile"
+ mode="polling"
+ pollingInterval="1"
+ )
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# create a log for testing
+./inputfilegen -m 1000 > $RSYSLOG_DYNNAME.input
+touch -m -t 201806010000.00 ./$RSYSLOG_DYNNAME.input
+
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+
+if ls ${RSYSLOG_OUT_LOG} > /dev/null; then
+ echo "FAIL: rsyslog.out.log isn't expected to be generated!"
+ exit 1
+fi
+
+# change timestamp
+./inputfilegen -m 1000 -i 1000 >> $RSYSLOG_DYNNAME.input
+ls -l ./$RSYSLOG_DYNNAME.input
+
+./msleep 1000
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 0 1999
+exit_test
diff --git a/tests/imfile-ignore-old-file-6.sh b/tests/imfile-ignore-old-file-6.sh
new file mode 100755
index 0000000..8bf92f0
--- /dev/null
+++ b/tests/imfile-ignore-old-file-6.sh
@@ -0,0 +1,42 @@
+#! /bin/bash
+# [polling mode] Multiple files with different timestamp, ignore those files with old timestamp
+
+echo [imfile-ignore-old-file-6.sh]
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile"
+ mode="polling"
+ pollingInterval="2"
+ )
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.1"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.2"
+ ignoreolderthan="604800"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+# create log files for testing
+./inputfilegen -m 1000 > $RSYSLOG_DYNNAME.input.1
+touch -m -t 201806010000.00 ./$RSYSLOG_DYNNAME.input.1
+./inputfilegen -m 1000 -i 1000 > $RSYSLOG_DYNNAME.input.2
+
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 1000 1999
+exit_test
diff --git a/tests/imfile-ignore-old-file-7.sh b/tests/imfile-ignore-old-file-7.sh
new file mode 100755
index 0000000..db01aad
--- /dev/null
+++ b/tests/imfile-ignore-old-file-7.sh
@@ -0,0 +1,56 @@
+#! /bin/bash
+# Read a file and ignore another one from an old symlink
+echo [imfile-ignore-old-file-7.sh]
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./symlink/'$RSYSLOG_DYNNAME'.input.ignore3.*"
+ ignoreolderthan="86400"
+ Tag="file:"
+ ruleset="ruleset")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+
+# create a log for testing
+mkdir ./source
+./inputfilegen -m 1000 > ./source/${RSYSLOG_DYNNAME}.input.ignore3.1
+touch -m -t 201806010000.00 ./source/${RSYSLOG_DYNNAME}.input.ignore3.1
+
+./inputfilegen -m 1000 -i 1000 > ./source/${RSYSLOG_DYNNAME}.input.ignore3.2
+
+echo "source file date: "
+ls -alth ./source/${RSYSLOG_DYNNAME}.input.ignore3.* #DEBUG
+
+# create symlink
+ln -sf ./source/ ./symlink
+
+# apply old date to symlink
+touch -h -t 201806010000.00 ./symlink
+
+echo "symlink date"
+ls -alth ./symlink #DEBUG
+
+echo "File dates:"
+ls -alth ./symlink/${RSYSLOG_DYNNAME}.input.ignore3.* #DEBUG
+
+startup
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 1000
+# shut down rsyslogd when done processing messages
+shutdown_when_empty
+# we need to wait until rsyslogd is finished!
+wait_shutdown
+# check log file
+seq_check 1000 1999
+
+# cleanup
+unlink ./symlink
+rm -rf ./source
+
+exit_test
diff --git a/tests/imfile-logrotate-async.sh b/tests/imfile-logrotate-async.sh
new file mode 100755
index 0000000..b6d8315
--- /dev/null
+++ b/tests/imfile-logrotate-async.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+check_command_available logrotate
+export NUMMESSAGES=10000
+export RETRIES=50
+
+# Uncomment fdor debuglogs
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+# Write logrotate config file
+echo '"./'$RSYSLOG_DYNNAME'.input*.log"
+{
+ #daily
+ rotate 60
+ missingok
+ notifempty
+ sharedscripts
+ postrotate
+ kill -HUP $(cat '$RSYSLOG_DYNNAME'.inputfilegen_pid)
+ endscript
+ #olddir /logs/old
+
+}' > $RSYSLOG_DYNNAME.logrotate
+
+
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+global( debug.whitelist="on"
+ debug.files=["imfile.c", "stream.c"]
+ )
+
+module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="2")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on" reopenOnTruncate="on")
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+./inputfilegen -m $NUMMESSAGES -S 5 -B 100 -I 1000 -f $RSYSLOG_DYNNAME.input.log &
+INPUTFILEGEN_PID=$!
+echo "$INPUTFILEGEN_PID" > $RSYSLOG_DYNNAME.inputfilegen_pid
+
+./msleep 1
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+./msleep 20
+echo ======================:
+echo ROTATE 1 INPUT FILES:
+ls -li $RSYSLOG_DYNNAME.input*
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+./msleep 20
+echo ======================:
+echo ROTATE 2 INPUT FILES:
+ls -li $RSYSLOG_DYNNAME.input*
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+echo ======================:
+echo ROTATE 3 INPUT FILES:
+ls -li $RSYSLOG_DYNNAME.input*
+echo ======================:
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -li ${RSYSLOG_DYNNAME}.spool
+echo ======================:
+echo FINAL INPUT FILES:
+ls -li $RSYSLOG_DYNNAME.input*
+
+# generate more input after logrotate into new logfile
+#./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.1.log
+#ls -l $RSYSLOG_DYNNAME.input*
+
+#msgcount=$((2* TESTMESSAGES))
+#wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+# Output extra information
+./msleep 1000
+echo ======================:
+echo LINES: $(wc -l $RSYSLOG_DYNNAME.input.log)
+echo TAIL $RSYSLOG_DYNNAME.input.log:
+tail $RSYSLOG_DYNNAME.input.log
+echo ""
+echo LINES: $(wc -l $RSYSLOG_DYNNAME.input.log.1)
+echo TAIL $RSYSLOG_DYNNAME.input.log.1:
+tail $RSYSLOG_DYNNAME.input.log.1
+echo ""
+echo LINES: $(wc -l $RSYSLOG_DYNNAME.input.log.2)
+echo TAIL $RSYSLOG_DYNNAME.input.log.2:
+tail $RSYSLOG_DYNNAME.input.log.2
+echo ""
+echo LINES: $(wc -l $RSYSLOG_DYNNAME.inpt.log.3)
+echo TAIL $RSYSLOG_DYNNAME.input.log.3:
+tail $RSYSLOG_DYNNAME.input.log.3
+echo ""
+wait_file_lines
+
+touch $RSYSLOG_DYNNAME.input.log
+./msleep 1000
+
+shutdown_when_empty
+wait_shutdown
+seq_check
+#seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-logrotate-copytruncate.sh b/tests/imfile-logrotate-copytruncate.sh
new file mode 100755
index 0000000..74643a4
--- /dev/null
+++ b/tests/imfile-logrotate-copytruncate.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+check_command_available logrotate
+
+export TESTMESSAGES=10000
+export RETRIES=50
+export TESTMESSAGESFULL=19999
+
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+ reopenOnTruncate="on"
+)
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# Write logrotate config file
+echo '"./'$RSYSLOG_DYNNAME'.input.*.log"
+{
+ rotate 7
+ create
+ daily
+ missingok
+ notifempty
+ compress
+ copytruncate
+}' > $RSYSLOG_DYNNAME.logrotate
+
+# generate input file first.
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+
+startup
+
+# Wait until testmessages are processed by imfile!
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+
+# Logrotate on logfile
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+
+# generate more input after logrotate into new logfile
+./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+msgcount=$((2* TESTMESSAGES))
+wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-logrotate-multiple.sh b/tests/imfile-logrotate-multiple.sh
new file mode 100755
index 0000000..e63a308
--- /dev/null
+++ b/tests/imfile-logrotate-multiple.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+check_command_available logrotate
+
+export IMFILEROTATES="10"
+export TESTMESSAGES=10000
+export TESTMESSAGESFULL=$((IMFILEROTATES * TESTMESSAGES-1))
+
+generate_conf
+add_conf '
+global(
+ workDirectory="'$RSYSLOG_DYNNAME'.spool"
+ /* Filter out busy debug output */
+ debug.whitelist="off"
+ debug.files=["omfile.c", "queue.c", "rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module(load="../plugins/imfile/.libs/imfile" mode="inotify")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# Write logrotate config file
+echo '"./'$RSYSLOG_DYNNAME'.input"
+{
+ create
+ daily
+ missingok
+ rotate 14
+ notifempty
+ compress
+ delaycompress
+}' > $RSYSLOG_DYNNAME.logrotate
+
+
+display_file() {
+ printf '\nFILE %s content:\n' $1
+ cat -n $1
+}
+
+startup
+
+TESTMESSAGESSTART=0
+for i in $(seq 1 $IMFILEROTATES);
+do
+ #printf 'PRESS ENTER TO CONTINUE\n'
+ #read
+ printf '\n\nNEW RUN:\n'
+
+ ./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGESSTART > $RSYSLOG_DYNNAME.input
+
+ ls -li $RSYSLOG_DYNNAME.input*
+ echo ls ${RSYSLOG_DYNNAME}.spool:
+ ls -li ${RSYSLOG_DYNNAME}.spool
+ echo STATE FILE CONTENT:
+ shopt -s extglob
+ for filename in "$RSYSLOG_DYNNAME.spool"/imfile-state:*; do display_file $filename; done
+
+ # Wait until testmessages are processed by imfile!
+ msgcount=$((i * TESTMESSAGES-1))
+ # echo "TESTMESSAGESSTART: $TESTMESSAGESSTART - TotalMsgCount: $msgcount"
+ wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+
+ # Logrotate on logfile
+ logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+
+ TESTMESSAGESSTART=$((TESTMESSAGESSTART+TESTMESSAGES))
+done
+
+
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-logrotate-nocopytruncate.sh b/tests/imfile-logrotate-nocopytruncate.sh
new file mode 100755
index 0000000..31e80be
--- /dev/null
+++ b/tests/imfile-logrotate-nocopytruncate.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+check_command_available logrotate
+
+export TESTMESSAGES=10000
+export RETRIES=50
+export TESTMESSAGESFULL=19999
+
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# Write logrotate config file
+echo '"./'$RSYSLOG_DYNNAME'.input.*.log"
+{
+ rotate 7
+ create
+ daily
+ missingok
+ notifempty
+ compress
+ nocopytruncate
+}' > $RSYSLOG_DYNNAME.logrotate
+
+# generate input file first.
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+
+startup
+
+# Wait until testmessages are processed by imfile!
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+
+# Logrotate on logfile
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+
+# generate more input after logrotate into new logfile
+./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+msgcount=$((2* TESTMESSAGES))
+wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-logrotate.sh b/tests/imfile-logrotate.sh
new file mode 100755
index 0000000..5d9b238
--- /dev/null
+++ b/tests/imfile-logrotate.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+check_command_available logrotate
+
+export TESTMESSAGES=10000
+export RETRIES=50
+export TESTMESSAGESFULL=19999
+
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# Write logrotate config file
+echo '"./'$RSYSLOG_DYNNAME'.input.*.log"
+{
+ rotate 7
+ create
+ daily
+ missingok
+ notifempty
+ compress
+}' > $RSYSLOG_DYNNAME.logrotate
+
+# generate input file first.
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+
+startup
+
+# Wait until testmessages are processed by imfile!
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+
+# Logrotate on logfile
+logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate
+
+# generate more input after logrotate into new logfile
+./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+msgcount=$((2* TESTMESSAGES))
+wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-old-state-file.sh b/tests/imfile-old-state-file.sh
new file mode 100755
index 0000000..5b92bbb
--- /dev/null
+++ b/tests/imfile-old-state-file.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# this test checks that old (v1, pre 8.34.0) imfile state files are
+# properly read in. It is based on imfile-readmode2-with-persists.sh,
+# where the first part before the shutdown is removed, and an old state
+# file is populated. Note that in contrast to the original test the
+# initial set of lines from the input file is missing - this is
+# exactly what shall happen.
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# added 2018-03-29 by rgerhards
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# do mock-up setup
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# we need to patch the state file to match the current inode number
+inode=$(ls -i $RSYSLOG_DYNNAME.input|awk '{print $1}')
+leninode=${#inode}
+newline="+inode:2:${leninode}:${inode}:"
+
+sed s/+inode:2:7:4464465:/${newline}/ <$srcdir/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input > ${RSYSLOG_DYNNAME}.spool/imfile-state\:.-$RSYSLOG_DYNNAME.input
+printf "info: new input file: $(ls -i $RSYSLOG_DYNNAME.input)\n"
+printf "info: new inode line: ${newline}\n"
+printf "info: patched state file:\n"
+cat ${RSYSLOG_DYNNAME}.spool/imfile-state\:.-$RSYSLOG_DYNNAME.input
+
+startup
+
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ # note: we expect only 2 headers as the first file part if NOT processed!
+ if [ ! $NUMLINES -eq 2 ]; then
+ echo "ERROR: expecting 2 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {2..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+done
+
+exit_test
diff --git a/tests/imfile-persist-state-1.sh b/tests/imfile-persist-state-1.sh
new file mode 100755
index 0000000..f3fe3ee
--- /dev/null
+++ b/tests/imfile-persist-state-1.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# added 2016-11-02 by rgerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+
+module(load="../plugins/imfile/.libs/imfile")
+
+input( type="imfile"
+ file="./'$RSYSLOG_DYNNAME'.input"
+ tag="file:"
+ startmsg.regex="^msgnum"
+ PersistStateInterval="1"
+)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# generate input file first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+./inputfilegen -m5 -d4000 > $RSYSLOG_DYNNAME.input
+startup
+shutdown_when_empty
+wait_shutdown
+seq_check 0 3
+exit_test
diff --git a/tests/imfile-readmode0-vg.sh b/tests/imfile-readmode0-vg.sh
new file mode 100755
index 0000000..48440c5
--- /dev/null
+++ b/tests/imfile-readmode0-vg.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# Tests for processing of partial lines in read mode 0
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="0")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+
+printf 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+printf '\nmsgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# sleep a little to give rsyslog a chance to process unterminated lines
+./msleep 500
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+printf 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+printf '\nmsgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of missing LF
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg # we need to wait until rsyslogd is finished!
+check_exit_vg
+
+## check if we have the correct number of messages
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 4 ]; then
+ echo "ERROR: expecting 4 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+done
+
+
+exit_test
diff --git a/tests/imfile-readmode2-polling.sh b/tests/imfile-readmode2-polling.sh
new file mode 100755
index 0000000..2bbe880
--- /dev/null
+++ b/tests/imfile-readmode2-polling.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( debug.whitelist="on"
+ debug.files=["imfile.c"])
+
+module(load="../plugins/imfile/.libs/imfile" mode="polling" PollingInterval="1")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# sleep a little to give rsyslog a chance to begin processing
+sleep 2
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+
+# give it time to finish
+sleep 1
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ exit_test
+ exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ exit_test
+ exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ exit_test
+ exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-readmode2-vg.sh b/tests/imfile-readmode2-vg.sh
new file mode 100755
index 0000000..20d4002
--- /dev/null
+++ b/tests/imfile-readmode2-vg.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup_vg
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+wait_file_lines $RSYSLOG_OUT_LOG 1
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+wait_file_lines $RSYSLOG_OUT_LOG 3
+
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+## check if we have the correct number of messages
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-readmode2-with-persists-data-during-stop.sh b/tests/imfile-readmode2-with-persists-data-during-stop.sh
new file mode 100755
index 0000000..552e181
--- /dev/null
+++ b/tests/imfile-readmode2-with-persists-data-during-stop.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# sleep a little to give rsyslog a chance to begin processing
+sleep 1
+
+# now stop and restart rsyslog so that the file info must be
+# persisted and read again on startup. Results should still be
+# correct ;)
+echo stopping rsyslog
+shutdown_when_empty
+wait_shutdown
+
+# write some more lines - we want to check here if the initial
+# polling loop properly picks up that data. Note that even in
+# inotify case we do have one polling loop at startup, as this
+# is required to find data written while we were stopped.
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+
+echo restarting rsyslog
+startup
+echo restarted rsyslog, continuing with test
+
+echo ' msgnum:5' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:6
+ msgnum:7
+msgnum:8' >> $RSYSLOG_DYNNAME.input
+#msgnum:8 must NOT be written as it is unfinished
+
+# give it time to finish
+sleep 1
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 4 ]; then
+ echo "ERROR: expecting 4 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..7}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-readmode2-with-persists.sh b/tests/imfile-readmode2-with-persists.sh
new file mode 100755
index 0000000..71104ba
--- /dev/null
+++ b/tests/imfile-readmode2-with-persists.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+echo ======================================================================
+echo [imfile-readmode2-with-persists.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ Tag="file:"
+ ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+# sleep a little to give rsyslog a chance to begin processing
+sleep 1
+
+# now stop and restart rsyslog so that the file info must be
+# persisted and read again on startup. Results should still be
+# correct ;)
+echo stopping rsyslog
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+echo spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+echo restarting rsyslog
+startup
+echo restarted rsyslog, continuing with test
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+
+# give it time to finish
+sleep 1
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# give it time to write the output file
+sleep 1
+
+## check if we have the correct number of messages
+
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-readmode2.sh b/tests/imfile-readmode2.sh
new file mode 100755
index 0000000..c06d269
--- /dev/null
+++ b/tests/imfile-readmode2.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction stdout"
+#export RSYSLOG_DEBUGLOG="log"
+
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+global( debug.whitelist="on"
+ debug.files=["imfile.c"])
+
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2")
+#input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*" Tag="file:" ReadMode="2")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+# write the beginning of the file
+echo 'msgnum:0
+ msgnum:1' > $RSYSLOG_DYNNAME.input
+echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input
+
+startup
+# sleep a little to give rsyslog a chance to begin processing
+rst_msleep 500
+
+# write some more lines (see https://github.com/rsyslog/rsyslog/issues/144)
+echo 'msgnum:3
+ msgnum:4' >> $RSYSLOG_DYNNAME.input
+echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2
+
+# give it time to finish
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+## check if we have the correct number of messages
+NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null)
+if [ -z $NUMLINES ]; then
+ echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 3 ]; then
+ echo "ERROR: expecting 3 headers, got $NUMLINES"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+
+## check if all the data we expect to get in the file is there
+
+for i in {1..4}; do
+ grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR: expecting the string 'msgnum:$i', it's not there"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+done
+
+## if we got here, all is good :)
+
+exit_test
diff --git a/tests/imfile-rename-while-stopped.sh b/tests/imfile-rename-while-stopped.sh
new file mode 100755
index 0000000..9d29b82
--- /dev/null
+++ b/tests/imfile-rename-while-stopped.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+export TESTMESSAGES=10000
+export RETRIES=10
+export TESTMESSAGESFULL=19999
+echo [imfile-rename.sh]
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+input(type="imfile"
+ File="/does/not/exist/*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+
+# generate input file first.
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log
+ls -li $RSYSLOG_DYNNAME.input*
+
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# Move to another filename
+mv $RSYSLOG_DYNNAME.input.1.log rsyslog.input.2.log
+
+# generate some more input into moved file
+./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.2.log
+ls -li $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+seq_check 0 $TESTMESSAGESFULL
+wc $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/imfile-rename.sh b/tests/imfile-rename.sh
new file mode 100755
index 0000000..6d249d3
--- /dev/null
+++ b/tests/imfile-rename.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. $srcdir/diag.sh check-inotify-only
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=10000
+export RETRIES=50
+export TESTMESSAGESFULL=19999
+
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+ )
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+input(type="imfile"
+ File="/does/not/exist/*.log"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+if $msg contains "imfile:" then
+ action(
+ type="omfile"
+ file="'$RSYSLOG_DYNNAME.errmsgs'"
+ )
+'
+
+# generate input file first.
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log
+ls -l $RSYSLOG_DYNNAME.input*
+
+startup
+
+# sleep a little to give rsyslog a chance to begin processing
+
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+
+# Move to another filename
+mv $RSYSLOG_DYNNAME.input.1.log rsyslog.input.2.log
+
+./msleep 500
+
+# Write into the renamed file
+echo 'testmessage1
+testmessage2' >> rsyslog.input.2.log
+
+./msleep 500
+
+if grep "imfile: internal error? inotify provided watch descriptor" < "$RSYSLOG_DYNNAME.errmsgs" ; then
+ echo "Error: inotify event from renamed file"
+ exit 1
+fi
+
+# generate some more input into moved file
+./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.2.log
+ls -l $RSYSLOG_DYNNAME.input*
+echo ls ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+./msleep 500
+
+let msgcount="2* $TESTMESSAGES"
+wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+seq_check 0 $TESTMESSAGESFULL
+exit_test
diff --git a/tests/imfile-statefile-delete.sh b/tests/imfile-statefile-delete.sh
new file mode 100755
index 0000000..cbe4128
--- /dev/null
+++ b/tests/imfile-statefile-delete.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# added 2019-02-28
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=1000
+export TESTMESSAGESFULL=999
+export RETRIES=50
+
+# Uncomment fdor debuglogs
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1")
+input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input
+inode=$(get_inode "$RSYSLOG_DYNNAME.input")
+startup
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+rm $RSYSLOG_DYNNAME.input
+sleep_time_ms=0
+while ls $RSYSLOG_DYNNAME.spool/imfile-state:$inode:* 1> /dev/null 2>&1; do
+ ./msleep 100
+ ((sleep_time_ms+=100))
+ if [ $sleep_time_ms -ge 6000 ]; then
+ touch $RSYSLOG_DYNNAME:.tmp
+ fi
+ if [ $sleep_time_ms -ge 30000 ]; then
+ printf 'FAIL: state file still exists when it should have been deleted\nspool dir is:\n'
+ ls -l $RSYSLOG_DYNNAME.spool
+ error_exit 1
+ fi
+done
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $TESTMESSAGESFULL # check we got the message correctly
+exit_test
diff --git a/tests/imfile-statefile-directory.sh b/tests/imfile-statefile-directory.sh
new file mode 100755
index 0000000..2c14958
--- /dev/null
+++ b/tests/imfile-statefile-directory.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# added 2019-04-25 by rgerhards
+# check that the "statfile.directory" module parameter is accepted
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+mkdir $RSYSLOG_DYNNAME.statefiles
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile"
+ statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles")
+input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# generate a very small file so that imfile cannot generate file_id (simple case)
+./inputfilegen -m1 > $RSYSLOG_DYNNAME.input
+startup
+shutdown_when_empty
+wait_shutdown
+seq_check 0 0 # check we got the messages correctly
+# and also check state file name is correct:
+# shellcheck disable=SC2012 - we do not display (or even use) the file name
+inode=$(ls -i "$RSYSLOG_DYNNAME.input"|awk '{print $1}')
+if [ ! -f "$RSYSLOG_DYNNAME.statefiles/imfile-state:$inode" ]; then
+ printf 'FAIL: state file name incorrect,\nexpected \"%s\"\nstatefiles dir is:\n' \
+ $RSYSLOG_DYNNAME.statefiles/imfile-state:$inode
+ ls -l $RSYSLOG_DYNNAME.statefiles
+ error_exit 1
+fi
+exit_test
diff --git a/tests/imfile-statefile-no-delete.sh b/tests/imfile-statefile-no-delete.sh
new file mode 100755
index 0000000..309b5d4
--- /dev/null
+++ b/tests/imfile-statefile-no-delete.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Added 2019-02-28
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=1000
+export TESTMESSAGESFULL=999
+export RETRIES=50
+
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1")
+input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input" deleteStateOnFileDelete="off")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input
+inode=$(get_inode "$RSYSLOG_DYNNAME.input")
+startup
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES
+rm $RSYSLOG_DYNNAME.input
+# sleep a little to give rsyslog a chance to notice the deleted file
+./msleep 2000
+
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $TESTMESSAGESFULL # check we got the message correctly
+if ! ls $RSYSLOG_DYNNAME.spool/imfile-state:$inode:* 1> /dev/null 2>&1; then
+ printf 'FAIL: state file was deleted when it should not have been\nspool dir is:\n'
+ ls -l $RSYSLOG_DYNNAME.spool
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-statefile-no-file_id-TO-file_id.sh b/tests/imfile-statefile-no-file_id-TO-file_id.sh
new file mode 100755
index 0000000..d2b7722
--- /dev/null
+++ b/tests/imfile-statefile-no-file_id-TO-file_id.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# added 2019-02-28 by rgerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# generate a very small file so that imfile cannot generate file_id
+./inputfilegen -m1 > $RSYSLOG_DYNNAME.input
+startup
+shutdown_when_empty
+wait_shutdown
+seq_check 0 0 # check we got the (one) message correctly
+# and also check state file name is correct:
+inode=$(get_inode "$RSYSLOG_DYNNAME.input")
+if [ ! -f "$RSYSLOG_DYNNAME.spool/imfile-state:$inode" ]; then
+ printf 'FAIL: state file name incorrect,\nexpected \"%s\"\nspool dir is:\n' \
+ $RSYSLOG_DYNNAME.spool/imfile-state:$inode
+ ls -l $RSYSLOG_DYNNAME.spool
+ error_exit 1
+fi
+
+printf '\nSTAGE 1 OK - inode-only state file properly generated\n\n'
+
+# now add data to the input file, up to a point where we have file_id.
+# rsyslog must update state file name AND remove inode-only one.
+./inputfilegen -m999 -i1 >> $RSYSLOG_DYNNAME.input
+startup
+wait_file_lines "$RSYSLOG_OUT_LOG" 1000
+shutdown_when_empty
+wait_shutdown
+
+seq_check 0 999 # check we got the messages correctly
+# and verify the state files are correct
+if [ -f "$RSYSLOG_DYNNAME.spool/imfile-state:$inode" ]; then
+ printf 'FAIL: inode-only state file still exists, but must not.\nincorrect name: \"%s\"\nspool dir is:\n' \
+ $RSYSLOG_DYNNAME.spool/imfile-state:$inode
+ ls -l $RSYSLOG_DYNNAME.spool
+ error_exit 1
+fi
+ ls -l $RSYSLOG_DYNNAME.spool
+exit_test
diff --git a/tests/imfile-statefile-no-file_id.sh b/tests/imfile-statefile-no-file_id.sh
new file mode 100755
index 0000000..d230c91
--- /dev/null
+++ b/tests/imfile-statefile-no-file_id.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# added 2019-02-28 by rgerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# generate a very small file so that imfile cannot generate file_id
+./inputfilegen -m1 > $RSYSLOG_DYNNAME.input
+startup
+shutdown_when_empty
+wait_shutdown
+seq_check 0 0 # check we got the messages correctly
+# and also check state file name is correct:
+inode=$(get_inode "$RSYSLOG_DYNNAME.input")
+
+printf '\nSTAGE 1 OK - inode-only state file properly generated\n\n'
+
+# now add small amount of data, so that file_id can still not be
+# generated. Check that state file remains valid.
+# rsyslog must update state file name AND remove inode-only one.
+./inputfilegen -m3 -i1 >> $RSYSLOG_DYNNAME.input
+startup
+wait_file_lines "$RSYSLOG_OUT_LOG" 4
+shutdown_when_empty
+wait_shutdown
+
+seq_check 0 3 # check we got the messages correctly
+# and verify the state files are correct
+if [ ! -f "$RSYSLOG_DYNNAME.spool/imfile-state:$inode" ]; then
+ printf 'FAIL: STAGE 2 state file name incorrect,\nexpected \"%s\"\nspool dir is:\n' \
+ $RSYSLOG_DYNNAME.spool/imfile-state:$inode
+ ls -l $RSYSLOG_DYNNAME.spool
+ error_exit 1
+fi
+printf '\nSTAGE 2 OK - inode-only state file properly maintained\n\n'
+
+exit_test
diff --git a/tests/imfile-symlink-ext-tmp-dir-tree.sh b/tests/imfile-symlink-ext-tmp-dir-tree.sh
new file mode 100755
index 0000000..df15f54
--- /dev/null
+++ b/tests/imfile-symlink-ext-tmp-dir-tree.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+# This test creates multiple symlinks (all watched by rsyslog via wildcard)
+# chained to target files via additional symlinks and checks that all files
+# are recorded with correct corresponding metadata (name of symlink
+# matching configuration).
+# This is part of the rsyslog testbench, released under ASL 2.0
+. "${srcdir:=.}"/diag.sh init
+. "$srcdir"/diag.sh check-inotify
+
+# #define FILE_DELETE_DELAY 5 /* how many seconds to wait before finally deleting a gone file */
+export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export RSYSLOG_DEBUGLOG="log"
+export TEST_TIMEOUT=30
+
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+generate_conf
+add_conf '
+# comment out if you need more debug info:
+global( debug.whitelist="on" debug.files=["imfile.c"]
+ workDirectory="./'"$RSYSLOG_DYNNAME"'.work"
+)
+module(load="../plugins/imfile/.libs/imfile" mode="inotify")
+input(type="imfile" File="./'"$RSYSLOG_DYNNAME"'.links/*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", filename: ")
+ property(name="$!metadata!filename")
+ constant(value=", fileoffset: ")
+ property(name="$!metadata!fileoffset")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action( type="omfile" file="'"$RSYSLOG_DYNNAME.out/$RSYSLOG_OUT_LOG"'" template="outfmt")
+'
+
+mkdir "$RSYSLOG_DYNNAME".links "$RSYSLOG_DYNNAME".work "$RSYSLOG_DYNNAME".out
+
+printf '\ncreating %s\n' "$RSYSLOG_DYNNAME".targets/container-1/logs/0.log
+mkdir -p "$RSYSLOG_DYNNAME".targets/container-1/logs
+./inputfilegen -m 1 >"$RSYSLOG_DYNNAME".targets/container-1/logs/0.log
+ls -l "$RSYSLOG_DYNNAME".targets/container-1/logs/0.log
+ln -sv "$PWD/$RSYSLOG_DYNNAME".targets/container-1/logs/0.log "$PWD/$RSYSLOG_DYNNAME".links/container-1.log
+printf '%s generated link %s\n' "$(tb_timestamp)" "container-1"
+ls -l "$RSYSLOG_DYNNAME".links/container-1.log
+
+# Start rsyslog now
+startup
+
+PID=$(cat "$RSYSLOG_PIDBASE".pid)
+echo "Rsyslog pid $RSYSLOG_PIDBASE.pid=$PID"
+if [[ "$PID" == "" ]]; then
+ error_exit 1
+fi
+
+echo "INFO: check files"
+# wait until this files has been opened
+check_fd_for_pid "$PID" exists "container-1/logs/0.log"
+check_fd_for_pid "$PID" exists "container-1/logs"
+
+echo "INFO: remove watched files"
+rm -vr "$RSYSLOG_DYNNAME".targets/container-1
+rm -v "$RSYSLOG_DYNNAME".links/container-1.log
+
+until check_fd_for_pid "$PID" absent "container-1/logs (deleted)"; do
+ if ((_wait_for_absent++ > TEST_TIMEOUT)); then
+ error_exit 1
+ fi
+ echo "INFO: trigger fd unlinking"
+ ./inputfilegen -m 1 >"$RSYSLOG_DYNNAME".links/gogogo.log
+ ./msleep 1000
+ rm -v "$RSYSLOG_DYNNAME".links/gogogo.log
+ ./msleep 10
+done
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-symlink-multi.sh b/tests/imfile-symlink-multi.sh
new file mode 100755
index 0000000..7e7c8f0
--- /dev/null
+++ b/tests/imfile-symlink-multi.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# This test points multiple symlinks (all watched by rsyslog via wildcard)
+# to single file and checks that message is reported once for each symlink
+# with correct corresponding metadata.
+# This is part of the rsyslog testbench, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export IMFILEINPUTFILES="10"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+# comment out if you need more debug info:
+ global( debug.whitelist="on"
+ debug.files=["imfile.c"])
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+module(load="../plugins/imfile/.libs/imfile"
+ mode="inotify" normalizePath="off")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input-symlink.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", filename: ")
+ property(name="$!metadata!filename")
+ constant(value=", fileoffset: ")
+ property(name="$!metadata!fileoffset")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action( type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt")
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+imfilebefore="$RSYSLOG_DYNNAME.input-symlink.log"
+./inputfilegen -m 1 > $imfilebefore
+mkdir $RSYSLOG_DYNNAME.targets
+# Start rsyslog now before adding more files
+startup
+
+cp $imfilebefore $RSYSLOG_DYNNAME.targets/target.log
+for i in `seq 2 $IMFILEINPUTFILES`;
+do
+ ln -s $RSYSLOG_DYNNAME.targets/target.log $RSYSLOG_DYNNAME.input.$i.log
+ # Wait little for correct timing
+ ./msleep 50
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+sort ${RSYSLOG_OUT_LOG} > ${RSYSLOG_OUT_LOG}.sorted
+
+echo HEADER msgnum:00000000:, filename: ./$RSYSLOG_DYNNAME.input-symlink.log, fileoffset: 0 > $RSYSLOG_DYNNAME.expected
+for i in `seq 2 $IMFILEINPUTFILES` ; do
+ echo HEADER msgnum:00000000:, filename: ./$RSYSLOG_DYNNAME.input.${i}.log, fileoffset: 0 >> $RSYSLOG_DYNNAME.expected
+done
+sort < $RSYSLOG_DYNNAME.expected | cmp - ${RSYSLOG_OUT_LOG}.sorted
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, ${RSYSLOG_OUT_LOG} is:"
+ cat -n $RSYSLOG_OUT_LOG
+ echo EXPECTED:
+ cat -n $RSYSLOG_DYNNAME.expected
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imfile-symlink.sh b/tests/imfile-symlink.sh
new file mode 100755
index 0000000..65b1a61
--- /dev/null
+++ b/tests/imfile-symlink.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# This test creates multiple symlinks (all watched by rsyslog via wildcard)
+# chained to target files via additional symlinks and checks that all files
+# are recorded with correct corresponding metadata (name of symlink
+# matching configuration).
+# This is part of the rsyslog testbench, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export IMFILEINPUTFILES="10"
+export IMFILELASTINPUTLINES="3"
+export IMFILECHECKTIMEOUT="60"
+
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+mkdir $RSYSLOG_DYNNAME.statefiles
+generate_conf
+add_conf '
+# comment out if you need more debug info:
+ global( debug.whitelist="on"
+ debug.files=["imfile.c"])
+module(load="../plugins/imfile/.libs/imfile"
+ statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles"
+ mode="inotify" normalizePath="off")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input-symlink.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", filename: ")
+ property(name="$!metadata!filename")
+ constant(value=", fileoffset: ")
+ property(name="$!metadata!fileoffset")
+ constant(value="\n")
+}
+if $msg contains "msgnum:" then
+ action( type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt")
+'
+
+./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input-symlink.log
+mkdir $RSYSLOG_DYNNAME.targets
+
+# Start rsyslog now before adding more files
+startup
+
+for i in $(seq 2 $IMFILEINPUTFILES);
+do
+ printf '\ncreating %s\n' $RSYSLOG_DYNNAME.targets/$i.log
+ ./inputfilegen -m 1 -i $((i-1)) > $RSYSLOG_DYNNAME.targets/$i.log
+ ls -l $RSYSLOG_DYNNAME.targets/$i.log
+ ln -sv $RSYSLOG_DYNNAME.targets/$i.log $RSYSLOG_DYNNAME.link.$i.log
+ ln -sv $RSYSLOG_DYNNAME.link.$i.log $RSYSLOG_DYNNAME.input.$i.log
+ printf '%s generated file %s\n' "$(tb_timestamp)" "$i"
+ ls -l $RSYSLOG_DYNNAME.link.$i.log
+ # wait until this file has been processed
+ content_check_with_count "HEADER msgnum:000000" $i $IMFILECHECKTIMEOUT
+done
+
+./inputfilegen -m $IMFILELASTINPUTLINES > $RSYSLOG_DYNNAME.input.$((IMFILEINPUTFILES + 1)).log
+ls -l $RSYSLOG_DYNNAME.input.* $RSYSLOG_DYNNAME.link.* $RSYSLOG_DYNNAME.targets
+
+# Content check with timeout
+content_check_with_count "input.11.log" $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-truncate-2GB-file.sh b/tests/imfile-truncate-2GB-file.sh
new file mode 100755
index 0000000..67c9ac1
--- /dev/null
+++ b/tests/imfile-truncate-2GB-file.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# written 2018-11-09 by Rainer Gerhards
+# this test checks that 2GiB (31 bit) file size region is handled correctly
+# it first generates a file that is 2GiB-64 bytes, processes it, and then
+# adds a couple of messages to get it over 2GiB.
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TB_TEST_MAX_RUNTIME=3600 # test is very slow as it works on large files
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" reopenOnTruncate="on")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+touch $RSYSLOG_DYNNAME.input
+startup
+
+# initial file: 2GiB - 1 message (54 byte)
+./inputfilegen -s 2147483584 -d47 -M $RSYSLOG_DYNNAME.msgcnt > $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+export NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)"
+
+wait_file_lines --delay 2500 --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES 3000
+
+# add one message --> exactly 2GB
+./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+(( NUMMESSAGES++ ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+# add one more message --> now we go over 2GB
+./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+(( NUMMESSAGES++ ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+# add even more messages
+./inputfilegen -m10000 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input
+ls -lh $RSYSLOG_DYNNAME.input
+NUMMESSAGES=$(( NUMMESSAGES + 10000 ))
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $(( NUMMESSAGES - 1))
+exit_test
diff --git a/tests/imfile-truncate-line.sh b/tests/imfile-truncate-line.sh
new file mode 100755
index 0000000..214e0c1
--- /dev/null
+++ b/tests/imfile-truncate-line.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+# This test mimics the test imfile-readmode2.sh, but works via
+# endmsg.regex. It's kind of a base test for the regex functionality.
+echo ======================================================================
+# Check if inotify header exist
+echo [imfile-truncate-line.sh]
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(oversizemsg.input.mode="accept" oversizemsg.report="on")
+module(load="../plugins/imfile/.libs/imfile")
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input"
+ discardTruncatedMsg="off"
+ Tag="file:"
+ startmsg.regex="^[^ ]"
+ ruleset="ruleset")
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="\n")
+}
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt")
+'
+startup
+
+# write the beginning of the file
+echo 'msgnum:0
+msgnum:1
+msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ msgnum:4 cccccccccccccccccccccccccccccccccccccccccccc
+ msgnum:5 dddddddddddddddddddddddddddddddddddddddddddd
+msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff
+ msgnum:8 gggggggggggggggggggggggggggggggggggggggggggg
+msgnum:9' > $RSYSLOG_DYNNAME.input
+# the next line terminates our test. It is NOT written to the output file,
+# as imfile waits whether or not there is a follow-up line that it needs
+# to combine.
+echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input
+# sleep a little to give rsyslog a chance to begin processing
+./msleep 500
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf 'HEADER msgnum:0
+HEADER msgnum:1
+HEADER msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\\n msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\n msgnum:4 ccccccc
+HEADER ccccccccccccccccccccccccccccccccccccc\\\\n msgnum:5 dddddddddddddddddddddddddddddddddddddddddddd
+HEADER msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\\\\n msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff\\\\n msgnum:8 ggggggg
+HEADER ggggggggggggggggggggggggggggggggggggg
+HEADER msgnum:9\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+grep "imfile error:.*message will be split and processed" ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imfile-truncate-multiple.sh b/tests/imfile-truncate-multiple.sh
new file mode 100755
index 0000000..73d691a
--- /dev/null
+++ b/tests/imfile-truncate-multiple.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# this test checks truncation mode, and does so with multiple truncations of
+# the input file.
+# It also needs a larger load, which shall be sufficient to do begin of file
+# checks as well as should support file id hash generation.
+# addd 2016-10-06 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile" pollingInterval="1")
+
+input(type="imfile" File="'./$RSYSLOG_DYNNAME'.input" Tag="file:" reopenOnTruncate="on")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+# write the beginning of the file
+NUMMSG=1000
+./inputfilegen -m 1000 -i0 > $RSYSLOG_DYNNAME.input
+ls -li $RSYSLOG_DYNNAME.input
+inode=$(get_inode $RSYSLOG_DYNNAME.input )
+echo inode $inode
+
+startup
+
+for i in {0..50}; do
+ # check that previous msg injection worked
+ wait_file_lines $RSYSLOG_OUT_LOG $NUMMSG 100
+ seq_check 0 $((NUMMSG - 1))
+
+ # begin new inject cycle
+ generate_msgs=$(( i * 50))
+ echo generating $NUMMSG .. $((NUMMSG + generate_msgs -1))
+ ./inputfilegen -m$generate_msgs -i$NUMMSG > $RSYSLOG_DYNNAME.input
+ (( NUMMSG=NUMMSG+generate_msgs ))
+ if [ $inode -ne $( get_inode $RSYSLOG_DYNNAME.input ) ]; then
+ echo FAIL testbench did not keep same inode number, expected $inode
+ ls -li $RSYSLOG_DYNNAME.input
+ exit 100
+ fi
+done
+
+echo generated $NUMMSG messages
+
+shutdown_when_empty
+wait_shutdown
+
+seq_check 0 $((NUMMSG - 1))
+exit_test
diff --git a/tests/imfile-truncate.sh b/tests/imfile-truncate.sh
new file mode 100755
index 0000000..72ef168
--- /dev/null
+++ b/tests/imfile-truncate.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# addd 2016-10-06 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" reopenOnTruncate="on")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+} else {
+ action( type="omfile" file="'$RSYSLOG_DYNNAME'.rsyslog")
+}
+'
+
+# write the beginning of the file
+echo 'msgnum:0
+msgnum:1' > $RSYSLOG_DYNNAME.input
+
+startup
+
+wait_queueempty # wait for message to be processed
+
+# truncate and write some more lines (see https://github.com/rsyslog/rsyslog/issues/1090)
+echo 'msgnum:2' > $RSYSLOG_DYNNAME.input
+wait_queueempty # wait for message to be processed
+
+echo 'msgnum:3
+msgnum:4' >> $RSYSLOG_DYNNAME.input
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+printf 'Messages from rsyslog itself:\n'
+cat -n $RSYSLOG_DYNNAME.rsyslog
+
+seq_check 0 4
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi.sh b/tests/imfile-wildcards-dirs-multi.sh
new file mode 100755
index 0000000..3155dc0
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify-only
+export IMFILEINPUTFILES="10"
+export IMFILEINPUTFILESSTEPS="5"
+#export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+
+/* Filter out busy debug output, comment out if needed */
+/*
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+*/
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*/*/*.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+# Start rsyslog now before adding more files
+startup
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$i
+ touch $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ done
+
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i/
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi2.sh b/tests/imfile-wildcards-dirs-multi2.sh
new file mode 100755
index 0000000..5199301
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi2.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="1"
+export IMFILEINPUTFILESSTEPS="5"
+#export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.dir1/*/testdir/file.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+for i in $(seq 1 $IMFILEINPUTFILES);
+do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+done
+
+# Start rsyslog now before adding more files
+startup
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir
+ touch $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/file.logfile
+ done
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/file.logfile
+ rm -rr $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi3.sh b/tests/imfile-wildcards-dirs-multi3.sh
new file mode 100755
index 0000000..1f851bb
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi3.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="1"
+export IMFILEINPUTFILESSTEPS="5"
+#export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*/*/testdir/*/file.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+for i in $(seq 1 $IMFILEINPUTFILES);
+do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ echo created!
+done
+
+# Start rsyslog now before adding more files
+startup
+# sleep a little to give rsyslog a chance to begin processing
+sleep 2
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j
+ touch $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile
+ ls -l $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile
+ done
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi4.sh b/tests/imfile-wildcards-dirs-multi4.sh
new file mode 100755
index 0000000..367d75d
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi4.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="1"
+export IMFILEINPUTFILESSTEPS="5"
+#export IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.dir1/*/*/*/*/*/file.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+. $srcdir/diag.sh check-inotify
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+# Start rsyslog now before adding more files
+startup
+
+for i in $(seq 1 $IMFILEINPUTFILES);
+do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+done
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ echo "Make $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir"
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j/bd$j
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j/bd$j/ir$j
+ touch $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j/bd$j/ir$j/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j/bd$j/ir$j/file.logfile
+ done
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/su$j/bd$j/ir$j/file.logfile
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi5-polling.sh b/tests/imfile-wildcards-dirs-multi5-polling.sh
new file mode 100755
index 0000000..db7710b
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi5-polling.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="8"
+export IMFILEINPUTFILESSTEPS="5"
+export IMFILECHECKTIMEOUT="15"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global( debug.whitelist="on"
+ debug.files=["imfile.c", "stream.c"])
+# debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q",
+# "msg.c", "../action.c", "imdiag.c"])
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module(load="../plugins/imfile/.libs/imfile" mode="polling" pollingInterval="1")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.dir?/*/*.logfile"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.alt/alt*file"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+# create first directory and file before startup, so ensure we will NOT
+# get an initial inotify notify for it!
+#mkdir $RSYSLOG_DYNNAME.input.alt
+#./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.alt/altfile.logfile
+#mkdir $RSYSLOG_DYNNAME.input.dir1
+# the following is INVALID, as this is a file, but must be a directory!
+#./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir0
+
+startup
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS); do
+ cp log log.$j
+ echo "Loop Num $j"
+
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$i
+ # proposed by AL - why? touch $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ ./inputfilegen -i $j -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ done
+
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:000000" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i
+ done
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards-dirs-multi5.sh b/tests/imfile-wildcards-dirs-multi5.sh
new file mode 100755
index 0000000..f6026f3
--- /dev/null
+++ b/tests/imfile-wildcards-dirs-multi5.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="8" #"8"
+export IMFILEINPUTFILESSTEPS="5" #"5"
+#export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+# Start rsyslog now before adding more files
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+global( workDirectory="./'"$RSYSLOG_DYNNAME"'.work"
+ debug.whitelist="on"
+ debug.files=["imfile.c"])
+
+module(load="../plugins/imfile/.libs/imfile" mode="inotify" pollingInterval="1")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.dir?/*/*.logfile"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.alt/alt*file"
+ Tag="file:" Severity="error" Facility="local7" addMetadata="on")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value="'"'"', ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+
+#*.* action(type="omfile" file="rsyslog.debug")
+'
+
+# create first directory and file before startup, so ensure we will NOT
+# get an initial inotify notify for it!
+mkdir $RSYSLOG_DYNNAME.input.alt
+#./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.alt/altfile.logfile
+mkdir $RSYSLOG_DYNNAME.input.dir1
+# the following is INVALID, as this is a file, but must be a directory!
+./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir0
+
+startup
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$i
+ touch $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ done
+
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ # slow systems (NFS) do not reliably do rm -r (unfortunately...)
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile
+ ./msleep 100
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i
+ ./msleep 100
+ rm -vrf $RSYSLOG_DYNNAME.input.dir$i
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+shutdown_when_empty
+wait_shutdown
+#echo rsyslog.debug:
+#cat rsyslog.debug
+exit_test
diff --git a/tests/imfile-wildcards-dirs.sh b/tests/imfile-wildcards-dirs.sh
new file mode 100755
index 0000000..27572e4
--- /dev/null
+++ b/tests/imfile-wildcards-dirs.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. $srcdir/diag.sh check-inotify
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="10"
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*/*.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+# Start rsyslog now before adding more files
+startup
+
+for i in $(seq 1 $IMFILEINPUTFILES);
+do
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ touch $RSYSLOG_DYNNAME.input.dir$i/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/file.logfile
+done
+ls -d $RSYSLOG_DYNNAME.input.*
+
+# Content check with timeout
+content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILES $IMFILECHECKTIMEOUT
+
+for i in $(seq 1 $IMFILEINPUTFILES);
+do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/
+done
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards-dirs2.sh b/tests/imfile-wildcards-dirs2.sh
new file mode 100755
index 0000000..449f2ba
--- /dev/null
+++ b/tests/imfile-wildcards-dirs2.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+export IMFILEINPUTFILES="10"
+export IMFILEINPUTFILESSTEPS="5"
+#export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS))
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+/* Filter out busy debug output, comment out if needed */
+global(
+ debug.whitelist="off"
+ debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]
+)
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module( load="../plugins/imfile/.libs/imfile"
+ mode="inotify"
+ PollingInterval="1")
+
+input(type="imfile"
+ File="./'$RSYSLOG_DYNNAME'.input.*/*.logfile"
+ Tag="file:"
+ Severity="error"
+ Facility="local7"
+ addMetadata="on"
+)
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", ")
+ property(name="$!metadata!filename")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action(
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt"
+ )
+'
+. $srcdir/diag.sh check-inotify-only
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+# Start rsyslog now before adding more files
+startup
+# sleep a little to give rsyslog a chance to begin processing
+sleep 1
+
+for j in $(seq 1 $IMFILEINPUTFILESSTEPS);
+do
+ echo "Loop Num $j"
+
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ mkdir $RSYSLOG_DYNNAME.input.dir$i
+ touch $RSYSLOG_DYNNAME.input.dir$i/file.logfile
+ ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/file.logfile
+ done
+ ls -d $RSYSLOG_DYNNAME.input.*
+
+ # Check correct amount of input files each time
+ IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j))
+ content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT
+
+ # Delete all but first!
+ for i in $(seq 1 $IMFILEINPUTFILES);
+ do
+ rm -rf $RSYSLOG_DYNNAME.input.dir$i/
+ done
+
+ # Helps in testbench parallel mode.
+ # Otherwise sometimes directories are not marked deleted in imfile before they get created again.
+ # This is properly a real issue in imfile when FILE IO is high.
+ ./msleep 1000
+done
+
+# sleep a little to give rsyslog a chance for processing
+sleep 1
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+exit_test
diff --git a/tests/imfile-wildcards.sh b/tests/imfile-wildcards.sh
new file mode 100755
index 0000000..68c1b61
--- /dev/null
+++ b/tests/imfile-wildcards.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under GPLv3
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-inotify
+export IMFILEINPUTFILES="10"
+export IMFILELASTINPUTLINES="3"
+export IMFILECHECKTIMEOUT="60"
+
+mkdir "$RSYSLOG_DYNNAME.work"
+generate_conf
+add_conf '
+# comment out if you need more debug info:
+ global( debug.whitelist="on"
+ debug.files=["imfile.c"])
+
+global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work")
+
+module(load="../plugins/imfile/.libs/imfile"
+ mode="inotify" normalizePath="off")
+
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+
+input(type="imfile" File="/does/not/exist/*.log" Tag="file:"
+ Severity="error" Facility="local7" addMetadata="on")
+
+template(name="outfmt" type="list") {
+ constant(value="HEADER ")
+ property(name="msg" format="json")
+ constant(value=", filename: ")
+ property(name="$!metadata!filename")
+ constant(value=", fileoffset: ")
+ property(name="$!metadata!fileoffset")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum:" then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+# generate input files first. Note that rsyslog processes it as
+# soon as it start up (so the file should exist at that point).
+
+imfilebefore=$RSYSLOG_DYNNAME.input.01.log
+./inputfilegen -m 1 > $imfilebefore
+
+# Start rsyslog now before adding more files
+startup
+
+for i in $(seq 2 $IMFILEINPUTFILES);
+do
+ filnbr=$(printf "%2.2d" $i)
+ cp $imfilebefore $RSYSLOG_DYNNAME.input.$filnbr.log
+ imfilebefore=$RSYSLOG_DYNNAME.input.$filnbr.log
+done
+
+# Content check with timeout
+content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILES $IMFILECHECKTIMEOUT
+
+# Add some extra lines to the last log
+./inputfilegen -m $IMFILELASTINPUTLINES > $RSYSLOG_DYNNAME.input.$((IMFILEINPUTFILES + 1)).log
+ls -l $RSYSLOG_DYNNAME.input.*
+
+# Content check with timeout
+content_check_with_count "input.11.log" $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+# Sort Output file now, and compare full file content
+presort
+
+printf 'HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.01.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.02.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.03.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.04.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.05.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.06.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.07.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.08.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.09.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.10.log, fileoffset: 0
+HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 0
+HEADER msgnum:00000001:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 17
+HEADER msgnum:00000002:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 34\n' | cmp - $RSYSLOG_DYNNAME.presort
+if [ ! $? -eq 0 ]; then
+ echo "FAIL: invalid output generated, $RSYSLOG_DYNNAME.presort is:"
+ echo "File contents:"
+ cat -n $RSYSLOG_DYNNAME.presort
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imhiredis-queue-lpop-vg.sh b/tests/imhiredis-queue-lpop-vg.sh
new file mode 100755
index 0000000..1d4c5c1
--- /dev/null
+++ b/tests/imhiredis-queue-lpop-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-queue-lpop.sh
diff --git a/tests/imhiredis-queue-lpop.sh b/tests/imhiredis-queue-lpop.sh
new file mode 100755
index 0000000..3ded2fc
--- /dev/null
+++ b/tests/imhiredis-queue-lpop.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+redis_command "RPUSH mykey message1"
+redis_command "RPUSH mykey message2"
+redis_command "RPUSH mykey message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mykey"
+ mode="queue"
+ uselpop="on"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+# Same order
+content_check '1 message1'
+content_check '2 message2'
+content_check '3 message3'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-queue-vg.sh b/tests/imhiredis-queue-vg.sh
new file mode 100755
index 0000000..7298611
--- /dev/null
+++ b/tests/imhiredis-queue-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-queue.sh
diff --git a/tests/imhiredis-queue.sh b/tests/imhiredis-queue.sh
new file mode 100755
index 0000000..da1ef14
--- /dev/null
+++ b/tests/imhiredis-queue.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+redis_command "RPUSH mykey message1"
+redis_command "RPUSH mykey message2"
+redis_command "RPUSH mykey message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mykey"
+ mode="queue"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+# Opposite order
+content_check '1 message3'
+content_check '2 message2'
+content_check '3 message1'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-redis-restart-vg.sh b/tests/imhiredis-redis-restart-vg.sh
new file mode 100755
index 0000000..19b12f5
--- /dev/null
+++ b/tests/imhiredis-redis-restart-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-redis-restart.sh
diff --git a/tests/imhiredis-redis-restart.sh b/tests/imhiredis-redis-restart.sh
new file mode 100755
index 0000000..6d997d8
--- /dev/null
+++ b/tests/imhiredis-redis-restart.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+# Start redis once to be able to generate configuration
+start_redis
+
+redis_command "RPUSH mykey message1"
+redis_command "RPUSH mykey message2"
+redis_command "RPUSH mykey message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mykey"
+ mode="queue"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+wait_content '3 message1'
+
+# Stop Redis and wait a short moment for imhiredis to notice Redis went down
+stop_redis
+rst_msleep 1500
+start_redis
+
+redis_command "RPUSH mykey message4"
+redis_command "RPUSH mykey message5"
+redis_command "RPUSH mykey message6"
+
+wait_content '4 message6'
+
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+content_check '1 message3'
+content_check '2 message2'
+content_check '3 message1'
+content_check 'sleeping 10 seconds before retrying'
+content_check '4 message6'
+content_check '5 message5'
+content_check '6 message4'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-redis-start-after-vg.sh b/tests/imhiredis-redis-start-after-vg.sh
new file mode 100755
index 0000000..689f501
--- /dev/null
+++ b/tests/imhiredis-redis-start-after-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-redis-start-after.sh
diff --git a/tests/imhiredis-redis-start-after.sh b/tests/imhiredis-redis-start-after.sh
new file mode 100755
index 0000000..2ef39dd
--- /dev/null
+++ b/tests/imhiredis-redis-start-after.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+. ${srcdir:=.}/diag.sh init
+
+# Start redis once to be able to generate configuration
+start_redis
+stop_redis
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mykey"
+ mode="queue"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+start_redis
+redis_command "RPUSH mykey message1"
+redis_command "RPUSH mykey message2"
+redis_command "RPUSH mykey message3"
+
+wait_content '1 message3'
+
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+content_check '1 message3'
+content_check '2 message2'
+content_check '3 message1'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-stream-consumerGroup-ack-vg.sh b/tests/imhiredis-stream-consumerGroup-ack-vg.sh
new file mode 100755
index 0000000..ee454fc
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-ack-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-stream-consumerGroup-ack.sh
diff --git a/tests/imhiredis-stream-consumerGroup-ack.sh b/tests/imhiredis-stream-consumerGroup-ack.sh
new file mode 100755
index 0000000..964a781
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-ack.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %$!msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mystream"
+ mode="stream"
+ stream.consumerGroup="mygroup"
+ stream.consumerName="myName"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+redis_command "XADD mystream * msg message1"
+redis_command "XADD mystream * msg message2"
+redis_command "XADD mystream * msg message3"
+
+shutdown_when_empty
+wait_shutdown
+
+output="$(redis_command 'hello 3\nXINFO groups mystream' | grep 'pending')"
+
+if [ -z "$output" ]; then
+ echo "Could not get group result from redis, cannot tell if entries ware acknowledged!"
+ error_exit 1
+fi
+
+if ! echo "$output" | grep -q "pending 0"; then
+ echo "ERROR: entries werent acknowledged!"
+ echo "ERROR: output from Redis is '$output'"
+ echo "ERROR: expected 'pending 0'"
+ error_exit 1
+fi
+
+stop_redis
+
+content_check '1 message1'
+content_check '2 message2'
+content_check '3 message3'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-stream-consumerGroup-noack-vg.sh b/tests/imhiredis-stream-consumerGroup-noack-vg.sh
new file mode 100755
index 0000000..fa05d58
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-noack-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-stream-consumerGroup-noack.sh
diff --git a/tests/imhiredis-stream-consumerGroup-noack.sh b/tests/imhiredis-stream-consumerGroup-noack.sh
new file mode 100755
index 0000000..3b2a555
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-noack.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %$!msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mystream"
+ mode="stream"
+ stream.consumerGroup="mygroup"
+ stream.consumerName="myName"
+ stream.consumerACK="off"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+redis_command "XADD mystream * msg message1"
+redis_command "XADD mystream * msg message2"
+redis_command "XADD mystream * msg message3"
+
+shutdown_when_empty
+wait_shutdown
+
+output="$(redis_command 'hello 3\nXINFO groups mystream' | grep 'pending')"
+
+if [ -z "$output" ]; then
+ echo "Could not get group result from redis, cannot tell if entries ware acknowledged!"
+ error_exit 1
+fi
+
+if ! echo "$output" | grep -q "pending 3"; then
+ echo "ERROR: entries were acknowledged, they shouldn't have!"
+ echo "ERROR: output from Redis is '$output'"
+ echo "ERROR: expected 'pending 3'"
+ error_exit 1
+fi
+
+stop_redis
+
+content_check '1 message1'
+content_check '2 message2'
+content_check '3 message3'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-stream-consumerGroup-reclaim-vg.sh b/tests/imhiredis-stream-consumerGroup-reclaim-vg.sh
new file mode 100755
index 0000000..f287e66
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-reclaim-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-stream-consumerGroup-reclaim.sh
diff --git a/tests/imhiredis-stream-consumerGroup-reclaim.sh b/tests/imhiredis-stream-consumerGroup-reclaim.sh
new file mode 100755
index 0000000..b2c6428
--- /dev/null
+++ b/tests/imhiredis-stream-consumerGroup-reclaim.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %$!msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mystream"
+ mode="stream"
+ stream.consumerGroup="mygroup"
+ stream.consumerName="myName"
+ stream.autoclaimIdleTime="5000" #5 seconds
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+
+redis_command "XADD mystream * msg message1"
+redis_command "XADD mystream * msg message2"
+redis_command "XADD mystream * msg message3"
+redis_command "XADD mystream * msg message4"
+redis_command "XADD mystream * msg message5"
+redis_command "XADD mystream * msg message6"
+
+redis_command "XGROUP CREATE mystream mygroup 0-0"
+# Read and claim message1 and message2
+redis_command "XREADGROUP GROUP mygroup otherConsumer COUNT 2 STREAMS mystream >"
+rst_msleep 5500
+# Read and claim message3 and message4
+redis_command "XREADGROUP GROUP mygroup otherConsumer COUNT 2 STREAMS mystream >"
+
+startup
+
+shutdown_when_empty
+wait_shutdown
+
+output="$(redis_command 'hello 3\nXINFO groups mystream' | grep 'pending')"
+
+if [ -z "$output" ]; then
+ echo "Could not get group result from redis, cannot tell if entries ware acknowledged!"
+ error_exit 1
+fi
+
+# Should still have 2 pending messages: message3 and message4
+if ! echo "$output" | grep -q "pending 2"; then
+ echo "ERROR: entries weren't acknowledged!"
+ echo "ERROR: output from Redis is '$output'"
+ echo "ERROR: expected 'pending 2'"
+ error_exit 1
+fi
+
+stop_redis
+
+# Should reclaim message1 and message2
+# then claim and acknowledge message5 and message6 normally
+content_check '1 message1'
+content_check '2 message2'
+content_check '3 message5'
+content_check '4 message6'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-stream-from-beginning-vg.sh b/tests/imhiredis-stream-from-beginning-vg.sh
new file mode 100755
index 0000000..5ea573b
--- /dev/null
+++ b/tests/imhiredis-stream-from-beginning-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-stream-from-beginning.sh
diff --git a/tests/imhiredis-stream-from-beginning.sh b/tests/imhiredis-stream-from-beginning.sh
new file mode 100755
index 0000000..f007d3a
--- /dev/null
+++ b/tests/imhiredis-stream-from-beginning.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+# WILL be logged by Rsyslog
+redis_command "XADD mystream * msg message1"
+redis_command "XADD mystream * msg message2"
+redis_command "XADD mystream * msg message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %$!msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mystream"
+ mode="stream"
+ stream.readFrom="0-0"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+redis_command "XADD mystream * msg message4"
+redis_command "XADD mystream * msg message5"
+redis_command "XADD mystream * msg message6"
+
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+content_check '1 message1'
+content_check '2 message2'
+content_check '3 message3'
+content_check '4 message4'
+content_check '5 message5'
+content_check '6 message6'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-stream-vg.sh b/tests/imhiredis-stream-vg.sh
new file mode 100755
index 0000000..b3e5d59
--- /dev/null
+++ b/tests/imhiredis-stream-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-stream.sh
diff --git a/tests/imhiredis-stream.sh b/tests/imhiredis-stream.sh
new file mode 100755
index 0000000..5a014ab
--- /dev/null
+++ b/tests/imhiredis-stream.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+# Won't be logged by Rsyslog
+redis_command "XADD mystream * msg message1"
+redis_command "XADD mystream * msg message2"
+redis_command "XADD mystream * msg message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %$!msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mystream"
+ mode="stream"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+redis_command "XADD mystream * msg message4"
+redis_command "XADD mystream * msg message5"
+redis_command "XADD mystream * msg message6"
+
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+check_not_present "message1"
+check_not_present "message2"
+check_not_present "message3"
+
+content_check '1 message4'
+content_check '2 message5'
+content_check '3 message6'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhiredis-subscribe-vg.sh b/tests/imhiredis-subscribe-vg.sh
new file mode 100755
index 0000000..b57709d
--- /dev/null
+++ b/tests/imhiredis-subscribe-vg.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imhiredis-subscribe.sh
diff --git a/tests/imhiredis-subscribe.sh b/tests/imhiredis-subscribe.sh
new file mode 100755
index 0000000..ec098e7
--- /dev/null
+++ b/tests/imhiredis-subscribe.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# added 2023-04-20 by Théo Bertin, released under ASL 2.0
+## Uncomment for debugging
+#export RS_REDIR=-d
+
+. ${srcdir:=.}/diag.sh init
+
+start_redis
+
+# Won't be logged by Rsyslog
+redis_command "PUBLISH mychannel message1"
+redis_command "PUBLISH mychannel message2"
+redis_command "PUBLISH mychannel message3"
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/imhiredis/.libs/imhiredis")
+template(name="outfmt" type="string" string="%$/num% %msg%\n")
+
+
+input(type="imhiredis"
+ server="127.0.0.1"
+ port="'$REDIS_RANDOM_PORT'"
+ key="mychannel"
+ mode="subscribe"
+ ruleset="redis")
+
+ruleset(name="redis") {
+ set $/num = cnum($/num + 1);
+ action(type="omfile"
+ file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+redis_command "PUBLISH mychannel message4"
+redis_command "PUBLISH mychannel message5"
+redis_command "PUBLISH mychannel message6"
+
+shutdown_when_empty
+wait_shutdown
+
+stop_redis
+
+check_not_present "message1"
+check_not_present "message2"
+check_not_present "message3"
+
+content_check '1 message4'
+content_check '2 message5'
+content_check '3 message6'
+
+# Removes generated configuration file, log and pid files
+cleanup_redis
+
+exit_test
diff --git a/tests/imhttp-getrequest-file-vg.sh b/tests/imhttp-getrequest-file-vg.sh
new file mode 100755
index 0000000..d7cb76c
--- /dev/null
+++ b/tests/imhttp-getrequest-file-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-getrequest-file.sh
diff --git a/tests/imhttp-getrequest-file.sh b/tests/imhttp-getrequest-file.sh
new file mode 100755
index 0000000..73ed46f
--- /dev/null
+++ b/tests/imhttp-getrequest-file.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'"
+ documentroot="'$srcdir'/testsuites/docroot")
+'
+startup
+curl -s http://localhost:$IMHTTP_PORT/file.txt > "$RSYSLOG_OUT_LOG"
+shutdown_when_empty
+echo "file name: $RSYSLOG_OUT_LOG"
+content_check "This is a test of get page"
+exit_test
diff --git a/tests/imhttp-post-payload-basic-auth-vg.sh b/tests/imhttp-post-payload-basic-auth-vg.sh
new file mode 100755
index 0000000..4762484
--- /dev/null
+++ b/tests/imhttp-post-payload-basic-auth-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-basic-auth.sh
diff --git a/tests/imhttp-post-payload-basic-auth.sh b/tests/imhttp-post-payload-basic-auth.sh
new file mode 100755
index 0000000..e88e7a4
--- /dev/null
+++ b/tests/imhttp-post-payload-basic-auth.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg")
+ constant(value=" - ")
+ constant(value="{ baz: ")
+ property(name="$!metadata!httpheaders!baz")
+ constant(value=", daddle: ")
+ property(name="$!metadata!httpheaders!daddle")
+ constant(value=", fiddle: ")
+ property(name="$!metadata!httpheaders!fiddle")
+ constant(value=" }")
+ constant(value=" - ")
+ constant(value=" !metadata: ")
+ property(name="$!metadata")
+ constant(value="\n")
+}
+
+#
+# note htpasswd file contains entry:
+# user1:1234
+#
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'")
+input(type="imhttp" endpoint="/postrequest"
+ ruleset="ruleset"
+ addmetadata="on"
+ basicauthfile="'$srcdir'/testsuites/htpasswd")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+# validate invalid passwd
+ret=$(curl -v -s -H Content-Type:application/json -H "BAZ: skat" -H "daddle: doodle" -H "fiddle: faddle" \
+ --user user1:badpass --write-out '%{http_code}' \
+ http://localhost:$IMHTTP_PORT/postrequest -d '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]')
+
+echo "response: $ret"
+if ! ( echo "$ret" | grep "Error 401: Unauthorized" )
+then
+ echo "ERROR: should not be unauthorized"
+ error_exit 1
+fi
+
+# validate correct password
+curl -s -H Content-Type:application/json -H "BAZ: skat" -H "daddle: doodle" -H "fiddle: faddle" \
+ --user user1:1234 --write-out '%{http_code}' \
+ http://localhost:$IMHTTP_PORT/postrequest -d '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]'
+
+wait_queueempty
+echo "doing shutdown"
+shutdown_when_empty
+wait_shutdown
+echo "file name: $RSYSLOG_OUT_LOG"
+content_check '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}] - { baz: skat, daddle: doodle, fiddle: faddle }'
+exit_test
diff --git a/tests/imhttp-post-payload-compress-vg.sh b/tests/imhttp-post-payload-compress-vg.sh
new file mode 100755
index 0000000..3b7051c
--- /dev/null
+++ b/tests/imhttp-post-payload-compress-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-compress.sh
diff --git a/tests/imhttp-post-payload-compress.sh b/tests/imhttp-post-payload-compress.sh
new file mode 100755
index 0000000..1278c11
--- /dev/null
+++ b/tests/imhttp-post-payload-compress.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUG="debug"
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'")
+#input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" disablelfdelimiter="on")
+input(type="imhttp" endpoint="/postrequest" ruleset="ruleset")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+NUMMESSAGES=50
+
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ echo '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' | gzip | curl -si --data-binary @- -H "Content-Encoding: gzip" http://localhost:$IMHTTP_PORT/postrequest
+done
+wait_queueempty
+shutdown_when_empty
+echo "file name: $RSYSLOG_OUT_LOG"
+content_count_check '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' $NUMMESSAGES
+exit_test
diff --git a/tests/imhttp-post-payload-large-vg.sh b/tests/imhttp-post-payload-large-vg.sh
new file mode 100755
index 0000000..7bd3b74
--- /dev/null
+++ b/tests/imhttp-post-payload-large-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-large.sh
diff --git a/tests/imhttp-post-payload-large.sh b/tests/imhttp-post-payload-large.sh
new file mode 100755
index 0000000..7323eec
--- /dev/null
+++ b/tests/imhttp-post-payload-large.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+#template(name="outfmt" type="string" string="%msg%\n")
+template(name="outfmt" type="string" string="%rawmsg%\n")
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'")
+input(type="imhttp" endpoint="/postrequest" ruleset="ruleset")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+NUMMESSAGES=25
+DATA_SOURCE=$srcdir/testsuites/imhttp-large-data.txt
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ curl -si -X POST -H Content-Type:application/json http://localhost:$IMHTTP_PORT/postrequest --data-binary @$DATA_SOURCE &
+ pids[${i}]=$!
+done
+
+# wait for all pids
+for pid in ${pids[*]};
+do
+ wait $pid
+# echo "$pid cleaned up"
+done
+
+sleep 2
+wait_queueempty
+echo "doing shutdown"
+shutdown_when_empty
+wait_shutdown
+
+# reference file for comparison
+TMPFILE=${RSYSLOG_DYNNAME}.tmp
+for (( i=1; i <= NUMMESSAGES; i++ ))
+do
+ cat $DATA_SOURCE >> $TMPFILE
+done
+
+if diff -q $TMPFILE $RSYSLOG_OUT_LOG;
+then
+ echo "files match!"
+ exit_test
+else
+ error_exit 1
+fi
diff --git a/tests/imhttp-post-payload-multi-lf-vg.sh b/tests/imhttp-post-payload-multi-lf-vg.sh
new file mode 100755
index 0000000..add90d6
--- /dev/null
+++ b/tests/imhttp-post-payload-multi-lf-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-multi-lf.sh
diff --git a/tests/imhttp-post-payload-multi-lf.sh b/tests/imhttp-post-payload-multi-lf.sh
new file mode 100755
index 0000000..fb367b5
--- /dev/null
+++ b/tests/imhttp-post-payload-multi-lf.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+#export RSYSLOG_DEBUG="Debug"
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imhttp/.libs/imhttp" ports="'$IMHTTP_PORT'")
+
+input(type="imhttp" endpoint="/postrequest" disableLFdelimiter="on" ruleset="ruleset")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+NUMMESSAGES=50
+
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ curl -si -H Content-Type:application/json http://localhost:$IMHTTP_PORT/postrequest -d $'{"foo":"bar","bar":"foo"}\n{"one":"two","three":"four"}'
+done
+shutdown_when_empty
+echo "file name: $RSYSLOG_OUT_LOG"
+content_count_check '{"foo":"bar","bar":"foo"}' $NUMMESSAGES
+content_count_check '{"one":"two","three":"four"}' $NUMMESSAGES
+exit_test
diff --git a/tests/imhttp-post-payload-multi-vg.sh b/tests/imhttp-post-payload-multi-vg.sh
new file mode 100755
index 0000000..0a736af
--- /dev/null
+++ b/tests/imhttp-post-payload-multi-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-multi.sh
diff --git a/tests/imhttp-post-payload-multi.sh b/tests/imhttp-post-payload-multi.sh
new file mode 100755
index 0000000..ba3bfa2
--- /dev/null
+++ b/tests/imhttp-post-payload-multi.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imhttp/.libs/imhttp"
+ liboptions=[ "listening_ports='$IMHTTP_PORT'" ] )
+input(type="imhttp" endpoint="/postrequest" ruleset="ruleset")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+NUMMESSAGES=50
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ curl -si -H Content-Type:application/json http://localhost:$IMHTTP_PORT/postrequest -d $'{"foo":"bar","bar":"foo"}\n{"one":"two","three":"four"}'
+done
+wait_queueempty
+shutdown_when_empty
+echo "file name: $RSYSLOG_OUT_LOG"
+content_count_check '{"foo":"bar","bar":"foo"}' $NUMMESSAGES
+content_count_check '{"one":"two","three":"four"}' $NUMMESSAGES
+exit_test
diff --git a/tests/imhttp-post-payload-query-params-vg.sh b/tests/imhttp-post-payload-query-params-vg.sh
new file mode 100755
index 0000000..d71f68b
--- /dev/null
+++ b/tests/imhttp-post-payload-query-params-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload-query-params.sh*
diff --git a/tests/imhttp-post-payload-query-params.sh b/tests/imhttp-post-payload-query-params.sh
new file mode 100755
index 0000000..ae6d61d
--- /dev/null
+++ b/tests/imhttp-post-payload-query-params.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="all" type="string" string="%msg% headers: %$!metadata%\n")
+template(name="outfmt" type="list") {
+ property(name="msg")
+ constant(value=" - ")
+ constant(value="{ baz: ")
+ property(name="$!metadata!httpheaders!baz")
+ constant(value=", daddle: ")
+ property(name="$!metadata!httpheaders!daddle")
+ constant(value=", fiddle: ")
+ property(name="$!metadata!httpheaders!fiddle")
+ constant(value=" }")
+ constant(value=" - ")
+ constant(value=" !metadata: ")
+ property(name="$!metadata")
+ constant(value="\n")
+}
+
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'")
+input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" addmetadata="on")
+ruleset(name="ruleset") {
+ #action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="all")
+}
+'
+startup
+NUMMESSAGES=100
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ curl -si -H Content-Type:application/json -H "BAZ: skat" -H "daddle: doodle" -H "fiddle: faddle" \
+ "http://localhost:$IMHTTP_PORT/postrequest?foo=bar;bar=foo&one=3" --data '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' &
+done
+sleep 2
+wait_queueempty
+echo "doing shutdown"
+shutdown_when_empty
+wait_shutdown
+echo "file name: $RSYSLOG_OUT_LOG"
+#content_count_check '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}] - { baz: skat, daddle: doodle, fiddle: faddle }' $NUMMESSAGES
+content_count_check '"queryparams": { "foo": "bar", "bar": "foo", "one": "3" }' $NUMMESSAGES
+exit_test
diff --git a/tests/imhttp-post-payload-vg.sh b/tests/imhttp-post-payload-vg.sh
new file mode 100755
index 0000000..4567edc
--- /dev/null
+++ b/tests/imhttp-post-payload-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+source ${srcdir:-.}/imhttp-post-payload.sh
diff --git a/tests/imhttp-post-payload.sh b/tests/imhttp-post-payload.sh
new file mode 100755
index 0000000..2d1af19
--- /dev/null
+++ b/tests/imhttp-post-payload.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+IMHTTP_PORT="$(get_free_port)"
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+module(load="../contrib/imhttp/.libs/imhttp"
+ ports="'$IMHTTP_PORT'")
+input(type="imhttp" endpoint="/postrequest" ruleset="ruleset")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+sleep 1
+NUMMESSAGES=50
+for (( i=1; i<=NUMMESSAGES; i++ ))
+do
+ curl -si -H Content-Type:application/json http://localhost:$IMHTTP_PORT/postrequest -d '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' &
+ pids[${i}]=$!
+done
+
+# wait for all pids
+for pid in ${pids[*]};
+do
+ wait $pid
+done
+
+sleep 2
+wait_queueempty
+echo "doing shutdown"
+shutdown_when_empty
+wait_shutdown
+echo "file name: $RSYSLOG_OUT_LOG"
+content_count_check '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' $NUMMESSAGES
+exit_test
diff --git a/tests/imjournal-basic-vg.sh b/tests/imjournal-basic-vg.sh
new file mode 100755
index 0000000..bda9288
--- /dev/null
+++ b/tests/imjournal-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imjournal-basic.sh
diff --git a/tests/imjournal-basic.sh b/tests/imjournal-basic.sh
new file mode 100755
index 0000000..53d9d7f
--- /dev/null
+++ b/tests/imjournal-basic.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This test injects a message and checks if it is received by
+# imjournal. We use a special test string which we do not expect
+# to be present in the regular log stream. So we do not expect that
+# any other journal content matches our test message. We skip the
+# test in case message does not make it even to journal which may
+# sometimes happen in some environments.
+# addd 2017-10-25 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh require-journalctl
+generate_conf
+add_conf '
+module(load="../plugins/imjournal/.libs/imjournal" IgnorePreviousMessages="on"
+ RateLimit.Burst="1000000")
+
+template(name="outfmt" type="string" string="%msg%\n")
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+TESTMSG="TestBenCH-RSYSLog imjournal This is a test message - $(date +%s) - $RSYSLOG_DYNNAME"
+
+startup
+
+printf 'a quick glimpse at journal content at rsyslog startup:\n'
+journalctl -n 20 --no-pager
+printf '\n\n'
+
+printf '++++++++++++++++++++++ Printing to the journal! +++++++++++++++++++++++++\n'
+# inject message into journal and check that it is recorded
+./journal_print "$TESTMSG"
+journal_write_state=$?
+if [ $journal_write_state -ne 0 ]; then
+ printf 'SKIP: journal_print returned state %d writing message: %s\n' "$journal_write_state" "$TESTMSG"
+ printf 'skipping test, journal probably not working\n'
+ exit 77
+fi
+
+# check state later - we must not terminate the test until we have terminated rsyslog
+
+# give the journal ~5 minutes to forward the message, see
+# https://github.com/rsyslog/rsyslog/issues/2564#issuecomment-435849660
+content_check_with_count "$TESTMSG" 1 300
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+check_journal_testmsg_received
+exit_test
diff --git a/tests/imjournal-statefile-vg.sh b/tests/imjournal-statefile-vg.sh
new file mode 100755
index 0000000..f1cdf2a
--- /dev/null
+++ b/tests/imjournal-statefile-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imjournal-statefile.sh
diff --git a/tests/imjournal-statefile.sh b/tests/imjournal-statefile.sh
new file mode 100755
index 0000000..3ad05d3
--- /dev/null
+++ b/tests/imjournal-statefile.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# This test injects a message and checks if it is received by
+# imjournal. We use a special test string which we do not expect
+# to be present in the regular log stream. So we do not expect that
+# any other journal content matches our test message. We skip the
+# test in case message does not make it even to journal which may
+# sometimes happen in some environments.
+# addd 2017-10-25 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh require-journalctl
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+module(load="../plugins/imjournal/.libs/imjournal" StateFile="imjournal.state"
+ # we turn off rate-limiting, else we may miss our test message:
+ RateLimit.interval="0"
+ )
+
+template(name="outfmt" type="string" string="%msg%\n")
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+TESTMSG="TestBenCH-RSYSLog imjournal This is a test message - $(date +%s) - $RSYSLOG_DYNNAME"
+./journal_print "$TESTMSG"
+if [ $? -ne 0 ]; then
+ echo "SKIP: failed to put test into journal."
+ error_exit 77
+fi
+
+# sleep 1 to get this test to reliably detect the message
+sleep 1
+
+journalctl -an 200 > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "SKIP: cannot read journal."
+ error_exit 77
+fi
+
+journalctl -an 200 | grep -qF "$TESTMSG"
+if [ $? -ne 0 ]; then
+ echo "SKIP: cannot find '$TESTMSG' in journal."
+ error_exit 77
+fi
+
+# do first run to process all the stuff already in journal db
+startup
+
+# give the journal ~5 minutes to forward the message, see
+# https://github.com/rsyslog/rsyslog/issues/2564#issuecomment-435849660
+content_check_with_count "$TESTMSG" 1 300
+
+shutdown_when_empty
+wait_shutdown
+
+printf '%s first rsyslogd run done, now restarting\n' "$(tb_timestamp)"
+
+#now do a second which should NOT capture testmsg again
+# craft new testmessage as shutdown condition:
+TESTMSG2="TestBenCH-RSYSLog imjournal This is a test message 2 - $(date +%s) - $RSYSLOG_DYNNAME"
+startup
+./journal_print "$TESTMSG2"
+content_check_with_count "$TESTMSG2" 1 300
+shutdown_when_empty
+wait_shutdown
+
+printf '%s both rsyslogd runs finished, doing final result check\n' "$(tb_timestamp)"
+
+# now check the original one is there
+content_count_check "$TESTMSG" 1
+exit_test
diff --git a/tests/imkafka-backgrounded.sh b/tests/imkafka-backgrounded.sh
new file mode 100755
index 0000000..60bf31b
--- /dev/null
+++ b/tests/imkafka-backgrounded.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# added 2018-10-24 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=100000
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+
+echo Check and Stop previous instances of kafka/zookeeper
+download_kafka
+stop_zookeeper
+stop_kafka
+
+echo Create kafka/zookeeper instance and $RANDTOPIC topic
+start_zookeeper
+start_kafka
+
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+}
+'
+
+export RSTB_DAEMONIZE="YES"
+startup
+
+injectmsg_kafkacat --wait 1 $TESTMESSAGES -d
+shutdown_when_empty
+wait_shutdown
+
+# Delete topic to remove old traces before
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+seq_check 1 $TESTMESSAGES -d
+exit_test
diff --git a/tests/imkafka-config-err-param.sh b/tests/imkafka-config-err-param.sh
new file mode 100755
index 0000000..107a116
--- /dev/null
+++ b/tests/imkafka-config-err-param.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# added 2018-08-29 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=1000
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+download_kafka
+stop_zookeeper
+stop_kafka
+start_zookeeper
+start_kafka
+
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "does.not.exist=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+
+# We inject messages, even though we know this will not work. The reason
+# is that we want to ensure we do not get a segfault in such an error case
+injectmsg_kafkacat
+
+shutdown_when_empty
+wait_shutdown
+
+content_check "error setting custom configuration parameter 'does.not.exist=none'"
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+exit_test
diff --git a/tests/imkafka-config-err-ruleset.sh b/tests/imkafka-config-err-ruleset.sh
new file mode 100755
index 0000000..82c08f9
--- /dev/null
+++ b/tests/imkafka-config-err-ruleset.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# added 2018-10-26 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=100000
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+#export EXTRA_EXITCHECK=dumpkafkalogs
+#export EXTRA_EXIT=kafka
+
+download_kafka
+stop_zookeeper
+stop_kafka
+start_zookeeper
+start_kafka
+
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ ruleset="does-not-exist"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if ($msg contains "msgnum:") then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+} else {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME.errmsg'")
+}
+'
+startup
+
+injectmsg_kafkacat --wait 1 $TESTMESSAGES -d
+shutdown_when_empty
+wait_shutdown
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+stop_kafka
+stop_zookeeper
+
+seq_check 1 $TESTMESSAGES -d
+content_check "ruleset 'does-not-exist' not found" "$RSYSLOG_DYNNAME.errmsg"
+
+exit_test
diff --git a/tests/imkafka-hang-on-no-kafka.sh b/tests/imkafka-hang-on-no-kafka.sh
new file mode 100755
index 0000000..7e7d289
--- /dev/null
+++ b/tests/imkafka-hang-on-no-kafka.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# added 2018-10-22 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. $srcdir/diag.sh init
+export RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT=5000 # 5sec
+generate_conf
+add_conf '
+main_queue(queue.type="direct")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+
+input( type="imkafka"
+ ruleset="kafka"
+ topic="irrelevant"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="kafka") {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+}
+
+action( type="omfile" file="'$RSYSLOG_OUT_LOG.syslog.log'" template="outfmt" )
+'
+
+export RSTB_DAEMONIZE="YES"
+startup
+shutdown_when_empty
+wait_shutdown
+# the main point is to see if we can terminate, so no further checks down here!
+exit_test
diff --git a/tests/imkafka-hang-other-action-on-no-kafka.sh b/tests/imkafka-hang-other-action-on-no-kafka.sh
new file mode 100755
index 0000000..fadcb67
--- /dev/null
+++ b/tests/imkafka-hang-other-action-on-no-kafka.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# added 2018-10-22 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT=5000 # 5sec
+generate_conf
+add_conf '
+main_queue(queue.type="direct")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+
+input( type="imkafka"
+ ruleset="kafka"
+ topic="irrelevant"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="kafka") {
+ continue
+}
+
+if prifilt("local4.*") then
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+else
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG.syslog.log'" template="outfmt" )
+'
+
+export RSTB_DAEMONIZE="YES"
+startup
+injectmsg 0 10000
+shutdown_when_empty
+wait_shutdown
+seq_check 0 9999
+exit_test
diff --git a/tests/imkafka-vg.sh b/tests/imkafka-vg.sh
new file mode 100755
index 0000000..472a8ed
--- /dev/null
+++ b/tests/imkafka-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imkafka.sh
diff --git a/tests/imkafka.sh b/tests/imkafka.sh
new file mode 100755
index 0000000..052227c
--- /dev/null
+++ b/tests/imkafka.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# added 2018-08-29 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=100000
+export TESTMESSAGESFULL=$TESTMESSAGES
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+download_kafka
+stop_zookeeper
+stop_kafka
+
+start_zookeeper
+start_kafka
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+}
+'
+startup
+injectmsg_kafkacat --wait 1 $TESTMESSAGESFULL -d
+shutdown_when_empty
+wait_shutdown
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+seq_check 1 $TESTMESSAGESFULL -d
+
+exit_test
diff --git a/tests/imkafka_multi_group.sh b/tests/imkafka_multi_group.sh
new file mode 100755
index 0000000..501aee7
--- /dev/null
+++ b/tests/imkafka_multi_group.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+# added 2018-08-29 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+# False positive codefactor.io
+export RSYSLOG_OUT_LOG_1="${RSYSLOG_OUT_LOG:-default}.1"
+export RSYSLOG_OUT_LOG_2="${RSYSLOG_OUT_LOG:-default}.2"
+
+export TESTMESSAGES=100000
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+#export EXTRA_EXITCHECK=dumpkafkalogs
+#export EXTRA_EXIT=kafka
+
+download_kafka
+stop_zookeeper
+stop_kafka
+start_zookeeper
+start_kafka
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# Create FIRST rsyslog instance
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="rsysloggroup"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG_1` template="outfmt" )
+}
+'
+echo Starting first rsyslog instance [imkafka]
+startup
+
+# Create SECOND rsyslog instance
+export RSYSLOG_DEBUGLOG="log2"
+generate_conf 2
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="rsysloggroup"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG_2` template="outfmt" )
+}
+' 2
+echo Starting second rsyslog instance [imkafka]
+startup 2
+
+
+TIMESTART=$(date +%s.%N)
+
+injectmsg_kafkacat
+# special case: number of test messages differs from file output
+wait_file_lines $RSYSLOG_OUT_LOG $((TESTMESSAGES)) ${RETRIES:-200}
+# Check that at least 25% messages are in both logfiles, otherwise load balancing hasn't worked
+wait_file_lines $RSYSLOG_OUT_LOG_1 $((TESTMESSAGES/4)) ${RETRIES:-200}
+wait_file_lines $RSYSLOG_OUT_LOG_2 $((TESTMESSAGES/4)) ${RETRIES:-200}
+
+echo Stopping first rsyslog instance [imkafka]
+shutdown_when_empty
+wait_shutdown
+
+echo Stopping second rsyslog instance [imkafka]
+shutdown_when_empty 2
+wait_shutdown 2
+
+TIMEEND=$(date +%s.%N)
+TIMEDIFF=$(echo "$TIMEEND - $TIMESTART" | bc)
+echo "*** imkafka time to process all data: $TIMEDIFF seconds!"
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+seq_check 1 $TESTMESSAGES -d
+
+exit_test
diff --git a/tests/imkafka_multi_single.sh b/tests/imkafka_multi_single.sh
new file mode 100755
index 0000000..d0127e0
--- /dev/null
+++ b/tests/imkafka_multi_single.sh
@@ -0,0 +1,151 @@
+#!/bin/bash
+# added 2018-08-29 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=100000
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+#export EXTRA_EXITCHECK=dumpkafkalogs
+#export EXTRA_EXIT=kafka
+
+download_kafka
+stop_zookeeper
+stop_kafka
+start_zookeeper
+start_kafka
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default1"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default2"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default3"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default4"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default5"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default6"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default7"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default8"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+}
+'
+
+startup
+
+TIMESTART=$(date +%s.%N)
+
+injectmsg_kafkacat
+# special case: number of test messages differs from file output
+wait_file_lines $RSYSLOG_OUT_LOG $((TESTMESSAGES * 8)) ${RETRIES:-200}
+shutdown_when_empty
+wait_shutdown
+
+TIMEEND=$(date +%s.%N)
+TIMEDIFF=$(echo "$TIMEEND - $TIMESTART" | bc)
+echo "*** imkafka time to process all data: $TIMEDIFF seconds!"
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+seq_check 1 $TESTMESSAGES -d
+
+exit_test
diff --git a/tests/imklog_permitnonkernelfacility_root.sh b/tests/imklog_permitnonkernelfacility_root.sh
new file mode 100755
index 0000000..16e8b90
--- /dev/null
+++ b/tests/imklog_permitnonkernelfacility_root.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2017-07-18 by Pascal Withopf, released under ASL 2.0
+echo \[imklog_permitnonkernelfacility_root.sh\]: test parameter permitnonkernelfacility
+echo This test must be run as root with no other active syslogd
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+service rsyslog stop
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imklog/.libs/imklog" permitnonkernelfacility="on")
+
+template(name="outfmt" type="string" string="%msg:57:16%: -%pri%-\n")
+
+:msg, contains, "msgnum" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo "<115>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1" > /dev/kmsg
+echo "<115>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1"
+sleep 2
+shutdown_when_empty
+wait_shutdown
+echo 'Mar 10 01:00:00 172.20.245.8 tag: msgnum:1: -115-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+service rsyslog start
+exit_test
diff --git a/tests/immark-inputname.sh b/tests/immark-inputname.sh
new file mode 100755
index 0000000..90a5795
--- /dev/null
+++ b/tests/immark-inputname.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# add 2020-12-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/immark/.libs/immark" interval="1" use.syslogcall="off")
+if $inputname == "immark" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+printf 'sleeping a bit so we get mark messages...\n'
+sleep 3 # this should be good even on slow machines - we need just one
+shutdown_when_empty
+wait_shutdown
+content_check "rsyslogd: -- MARK --"
+
+exit_test
diff --git a/tests/immark-ruleset-custom-msg.sh b/tests/immark-ruleset-custom-msg.sh
new file mode 100755
index 0000000..eb8c116
--- /dev/null
+++ b/tests/immark-ruleset-custom-msg.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# very basic check for immark module - nevertheless, there is not
+# much more to test for...
+# add 2020-12-01 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/immark/.libs/immark" interval="1"
+ use.syslogcall="off" ruleset="rs" markmessagetext="My MARK Message")
+ruleset(name="rs") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+
+startup
+printf 'sleeping a bit so we get mark messages...\n'
+sleep 3 # this should be good even on slow machines - we need just one
+shutdown_when_empty
+wait_shutdown
+content_check "rsyslogd: My MARK Message"
+
+exit_test
diff --git a/tests/immark-ruleset.sh b/tests/immark-ruleset.sh
new file mode 100755
index 0000000..b2d3f57
--- /dev/null
+++ b/tests/immark-ruleset.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# very basic check for immark module - nevertheless, there is not
+# much more to test for...
+# add 2020-12-01 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/immark/.libs/immark" interval="1"
+ use.syslogcall="off" ruleset="rs")
+ruleset(name="rs") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+
+startup
+printf 'sleeping a bit so we get mark messages...\n'
+sleep 3 # this should be good even on slow machines - we need just one
+shutdown_when_empty
+wait_shutdown
+content_check "rsyslogd: -- MARK --"
+
+exit_test
diff --git a/tests/immark.sh b/tests/immark.sh
new file mode 100755
index 0000000..8e4be61
--- /dev/null
+++ b/tests/immark.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# very basic check for immark module - nevertheless, there is not
+# much more to test for...
+# add 2019-08-20 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/immark/.libs/immark" interval="1")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+printf 'sleeping a bit so we get mark messages...\n'
+sleep 3 # this should be good even on slow machines - we need just one
+shutdown_when_empty
+wait_shutdown
+content_check "rsyslogd: -- MARK --"
+
+exit_test
diff --git a/tests/improg-multiline-test.py b/tests/improg-multiline-test.py
new file mode 100755
index 0000000..c513cd7
--- /dev/null
+++ b/tests/improg-multiline-test.py
@@ -0,0 +1,6 @@
+# call this via "python[3] script name"
+import sys
+
+for _ in range(10):
+ mystr = 'multi-line-string\n'
+ sys.stdout.write(mystr)
diff --git a/tests/improg-simul.sh b/tests/improg-simul.sh
new file mode 100755
index 0000000..8d91203
--- /dev/null
+++ b/tests/improg-simul.sh
@@ -0,0 +1,70 @@
+#! /bin/bash
+# add 2019-04-04 by Philippe DUVEAU, released under ASL 2.0
+mysleep=./msleep
+ACK=0
+SLEEP=0
+DELAY=500
+NB=1
+MESSAGE="program datas"
+SIGNALED=0
+ERR=$0.stderr
+while getopts "cd:e:s:n:m:g" OPTION; do
+ case "${OPTION}" in
+ g)
+ SIGNALED=1
+ ;;
+ c)
+ ACK=1
+ ;;
+ d)
+ DELAY=${OPTARG}
+ ;;
+ e)
+ ERR=${OPTARG}
+ ;;
+ s)
+ SLEEP=${OPTARG}
+ ;;
+ n)
+ NB=${OPTARG}
+ ;;
+ m)
+ MESSAGE=${OPTARG}
+ ;;
+ *)
+ exit 0
+ esac
+done
+trap 'echo "SIGTERM Received" >> '$ERR';echo $0" SIGTERM Received" >&2;exit 0' 15
+if (( DELAY > 0 )); then $mysleep ${DELAY}; fi
+if [ ${ACK} == 1 ]; then
+ while [ "x$order" != "xSTART" ]; do
+ read -r order
+ echo $order' Received' >> $ERR
+ echo $0' '$order' Received' >&2
+ done
+ while [ "x$order" != "xSTOP" ]; do
+ if (( NB > 0 )); then
+ echo ${MESSAGE}
+ echo "Message sent" >&2
+ (( NB-- ))
+ fi
+ unset order
+ read -r order
+ echo $order' Received' >> $ERR
+ echo $0' '$order' Received' >&2
+ if (( SLEEP > 0 )); then $mysleep ${SLEEP}; fi
+ done
+else
+ while (( NB > 0 )); do
+ echo ${MESSAGE}
+ echo $0" Message sent" >&2
+ if (( SLEEP > 0 )); then $mysleep ${SLEEP}; fi
+ (( NB-- ))
+ done
+ if [ ${SIGNALED} == 1 ]; then
+ $mysleep 100000 &
+ wait
+ fi
+fi
+echo "Leaving improg_sender" >&2
diff --git a/tests/improg_errmsg_no_params-vg.sh b/tests/improg_errmsg_no_params-vg.sh
new file mode 100755
index 0000000..aa40b52
--- /dev/null
+++ b/tests/improg_errmsg_no_params-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/improg_errmsg_no_params.sh
diff --git a/tests/improg_errmsg_no_params.sh b/tests/improg_errmsg_no_params.sh
new file mode 100755
index 0000000..45a55ba
--- /dev/null
+++ b/tests/improg_errmsg_no_params.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+
+input(type="improg")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'binary' required but not specified"
+
+exit_test
diff --git a/tests/improg_prog_confirm.sh b/tests/improg_prog_confirm.sh
new file mode 100755
index 0000000..e0af636
--- /dev/null
+++ b/tests/improg_prog_confirm.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2019-04-04 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+input(type="improg" tag="tag" ruleset="ruleset"
+ binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -c -n 1"
+ confirmmessages="on" signalonclose="off" killunresponsive="on"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "program data"
+if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then
+ echo $RSYSLOG_DYNNAME'.stderr missing'
+ error_exit 1
+fi
+export EXPECTED='START Received
+ACK Received
+STOP Received'
+cmp_exact $RSYSLOG_DYNNAME.stderr
+exit_test
diff --git a/tests/improg_prog_confirm_killonclose.sh b/tests/improg_prog_confirm_killonclose.sh
new file mode 100755
index 0000000..b9a75ce
--- /dev/null
+++ b/tests/improg_prog_confirm_killonclose.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2019-04-04 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+input(type="improg" tag="tag" ruleset="ruleset"
+ binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -c -n 1 -g"
+ confirmmessages="on" signalonclose="on" killunresponsive="on"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "program data"
+if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then
+ echo $RSYSLOG_DYNNAME'.stderr missing'
+ error_exit 1
+fi
+export EXPECTED='START Received
+ACK Received
+SIGTERM Received'
+cmp_exact $RSYSLOG_DYNNAME.stderr
+
+exit_test
diff --git a/tests/improg_prog_killonclose.sh b/tests/improg_prog_killonclose.sh
new file mode 100755
index 0000000..42d9f12
--- /dev/null
+++ b/tests/improg_prog_killonclose.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# add 2019-04-04 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+input(type="improg" tag="tag" ruleset="ruleset"
+ binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -n 1 -g"
+ confirmmessages="off" signalonclose="on" killunresponsive="on"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "program data"
+if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then
+ echo $RSYSLOG_DYNNAME'.stderr missing'
+ error_exit 1
+fi
+export EXPECTED='SIGTERM Received'
+cmp_exact $RSYSLOG_DYNNAME.stderr
+exit_test
diff --git a/tests/improg_prog_simple-vg.sh b/tests/improg_prog_simple-vg.sh
new file mode 100755
index 0000000..1a1f426
--- /dev/null
+++ b/tests/improg_prog_simple-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/improg_prog_simple.sh
diff --git a/tests/improg_prog_simple.sh b/tests/improg_prog_simple.sh
new file mode 100755
index 0000000..af4d383
--- /dev/null
+++ b/tests/improg_prog_simple.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# add 2019-04-04 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+input(type="improg" tag="tag" ruleset="ruleset"
+ binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr"
+ confirmmessages="off" closetimeout="2000"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "program data"
+if [ -e $RSYSLOG_DYNNAME.stderr ]; then
+ echo 'improg-simul stderr:'
+ cat $RSYSLOG_DYNNAME.stderr
+ error_exit 1
+fi
+exit_test
diff --git a/tests/improg_simple_multi.sh b/tests/improg_simple_multi.sh
new file mode 100755
index 0000000..babcb9b
--- /dev/null
+++ b/tests/improg_simple_multi.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/improg/.libs/improg")
+template(name="outfmt" type="string" string="#%msg%#\n")
+input(type="improg" tag="tag" ruleset="ruleset"
+ binary="'$PYTHON' '$srcdir'/improg-multiline-test.py"
+ confirmmessages="off" closetimeout="2000"
+ )
+ruleset(name="ruleset") {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+NUM_ITEMS=10
+echo "expected: $NUM_EXPECTED"
+echo "file: $RSYSLOG_OUT_LOG"
+content_check_with_count "#multi-line-string#" $NUM_EXPECTED $NUM_ITEMS
+exit_test
diff --git a/tests/impstats-hup.sh b/tests/impstats-hup.sh
new file mode 100755
index 0000000..9f16371
--- /dev/null
+++ b/tests/impstats-hup.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# test if HUP works for impstats
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/impstats/.libs/impstats"
+ log.file=`echo $RSYSLOG_OUT_LOG`
+ interval="1" ruleset="stats")
+
+ruleset(name="stats") {
+ stop # nothing to do here
+}
+'
+startup
+./msleep 2000
+mv $RSYSLOG_OUT_LOG ${RSYSLOG2_OUT_LOG}
+issue_HUP
+./msleep 2000
+shutdown_when_empty
+wait_shutdown
+echo checking pre-HUP file
+content_check 'global: origin=dynstats' ${RSYSLOG2_OUT_LOG}
+echo checking post-HUP file
+content_check 'global: origin=dynstats' $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/imptcp-NUL-rawmsg.sh b/tests/imptcp-NUL-rawmsg.sh
new file mode 100755
index 0000000..d843e5c
--- /dev/null
+++ b/tests/imptcp-NUL-rawmsg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message
+<167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 #000 test message
+<167>Mar 6 16:57:54 172.20.245.8 #000test: msgnum:1 test message' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+exit_test
diff --git a/tests/imptcp-NUL.sh b/tests/imptcp-NUL.sh
new file mode 100755
index 0000000..935e679
--- /dev/null
+++ b/tests/imptcp-NUL.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message
+<167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+seq_check 0 1
+exit_test
diff --git a/tests/imptcp-basic-hup.sh b/tests/imptcp-basic-hup.sh
new file mode 100755
index 0000000..a58888f
--- /dev/null
+++ b/tests/imptcp-basic-hup.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2019-07-30 by RGerhards, released under ASL 2.0
+export NUMMESSAGES=4000 # MUST be an even number!
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2))
+issue_HUP
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imptcp-connection-msg-disabled.sh b/tests/imptcp-connection-msg-disabled.sh
new file mode 100755
index 0000000..1cf1139
--- /dev/null
+++ b/tests/imptcp-connection-msg-disabled.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# addd 2017-03-31 by Pascal Withopf, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m1 -M"\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+
+grep "imptcp: connection established" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -eq 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "imptcp: session on socket.* closed" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -eq 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imptcp-connection-msg-received.sh b/tests/imptcp-connection-msg-received.sh
new file mode 100755
index 0000000..0b8ca3d
--- /dev/null
+++ b/tests/imptcp-connection-msg-received.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# addd 2017-03-31 by Pascal Withopf, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ notifyonconnectionclose="on" notifyonconnectionopen="on")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m1 -M"\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+
+grep "imptcp: connection established" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "imptcp: session on socket.* closed" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imptcp-discard-truncated-msg.sh b/tests/imptcp-discard-truncated-msg.sh
new file mode 100755
index 0000000..a734b4b
--- /dev/null
+++ b/tests/imptcp-discard-truncated-msg.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ ruleset="ruleset1" discardTruncatedMsg="on")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16\""
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message\""
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16\""
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 t
+<120> 2011-03-01T11:22:12Z host tag: this is a way to long message
+<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 t
+<120> 2011-03-01T11:22:12Z host tag: this is a way to long message'
+cmp_exact
+exit_test
diff --git a/tests/imptcp-maxFrameSize-parameter.sh b/tests/imptcp-maxFrameSize-parameter.sh
new file mode 100755
index 0000000..0b9b376
--- /dev/null
+++ b/tests/imptcp-maxFrameSize-parameter.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# addd 2017-03-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 12800
+global(processInternalMessages="on")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" maxframesize="100")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+
+'
+startup
+tcpflood -m1 -M "\"10005 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message\""
+shutdown_when_empty
+wait_shutdown
+
+grep "Framing Error.*change to octet stuffing" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imptcp-msg-truncation-on-number.sh b/tests/imptcp-msg-truncation-on-number.sh
new file mode 100755
index 0000000..fa7f439
--- /dev/null
+++ b/tests/imptcp-msg-truncation-on-number.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# addd 2017-03-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on"
+ oversizemsg.input.mode="accept")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+
+'
+startup
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab
+9876543210 cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestetstetstetstetstetsstetstetsytetestetste\""
+shutdown_when_empty
+wait_shutdown
+
+grep "Framing Error" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep " 9876543210cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestets" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imptcp-msg-truncation-on-number2.sh b/tests/imptcp-msg-truncation-on-number2.sh
new file mode 100755
index 0000000..36009c4
--- /dev/null
+++ b/tests/imptcp-msg-truncation-on-number2.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# addd 2017-03-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on"
+ oversizemsg.input.mode="accept")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="templ1" type="string" string="%rawmsg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="templ1")
+}
+
+'
+startup
+tcpflood -m2 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"2000000010 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"4000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"0 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+
+echo '<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+214000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+214000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+2000000010<120> 2011-03-01T11:22:12Z host msgnum:1
+4000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imptcp-octet-framing-too-long-vg.sh b/tests/imptcp-octet-framing-too-long-vg.sh
new file mode 100755
index 0000000..d5b2c9a
--- /dev/null
+++ b/tests/imptcp-octet-framing-too-long-vg.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2022-04-25 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on"
+ oversizemsg.input.mode="accept")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup_vg
+echo "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab" > $RSYSLOG_DYNNAME.inputfile
+tcpflood -I $RSYSLOG_DYNNAME.inputfile
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+# the prime objective is to see if valgrind check is ok, but we also do a quick content check (just in case)
+content_check "received oversize message from peer"
+exit_test
diff --git a/tests/imptcp-oversize-message-display.sh b/tests/imptcp-oversize-message-display.sh
new file mode 100755
index 0000000..4fae531
--- /dev/null
+++ b/tests/imptcp-oversize-message-display.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# addd 2017-03-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on" oversizemsg.input.mode="accept")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+
+'
+startup
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 abcdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestetstetstetstetstetsstetstetsytetestetste\""
+shutdown_when_empty
+wait_shutdown
+
+if ! grep "imptcp: message received.*150 byte larger.*will be split.*\"ghijkl" $RSYSLOG_OUT_LOG > /dev/null
+then
+ echo
+ echo "FAIL: expected error message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+if ! grep "imptcp: message received.*22 byte larger.*will be split.*\"sstets" $RSYSLOG_OUT_LOG > /dev/null
+then
+ echo
+ echo "FAIL: expected error message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+if grep "imptcp: message received.*21 byte larger" $RSYSLOG_OUT_LOG > /dev/null
+then
+ echo
+ echo "FAIL: UNEXPECTED error message from imptcp truncation found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imptcp_addtlframedelim.sh b/tests/imptcp_addtlframedelim.sh
new file mode 100755
index 0000000..3ae32e0
--- /dev/null
+++ b/tests/imptcp_addtlframedelim.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2010-08-11 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ addtlFrameDelimiter="0")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -m$NUMMESSAGES -F0 -P129
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imptcp_conndrop-vg.sh b/tests/imptcp_conndrop-vg.sh
new file mode 100755
index 0000000..7852fb1
--- /dev/null
+++ b/tests/imptcp_conndrop-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export TB_TEST_MAX_RUNTIME=1200 # connection drops are very slow...
+export NUMMESSAGES=10000 # even if it is slow, we use a large number to be
+ # sure to have sufficient connection drops - but as low as possible!
+source ${srcdir:-.}/imptcp_conndrop.sh
diff --git a/tests/imptcp_conndrop.sh b/tests/imptcp_conndrop.sh
new file mode 100755
index 0000000..8c01806
--- /dev/null
+++ b/tests/imptcp_conndrop.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Test imptcp with many dropping connections
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=${NUMMESSAGES:-50000} # permit valgrind test to override value
+export TB_TEST_MAX_RUNTIME=${TB_TEST_MAX_RUNTIME:-700} # connection drops are very slow...
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+local0.* ?dynfile;outfmt
+'
+startup
+# 100 byte messages to gain more practical data use
+tcpflood -c20 -m$NUMMESSAGES -r -d100 -P129 -D
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/imptcp_framing_regex-oversize.sh b/tests/imptcp_framing_regex-oversize.sh
new file mode 100755
index 0000000..c5b74dd
--- /dev/null
+++ b/tests/imptcp_framing_regex-oversize.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$EscapeControlCharactersOnReceive off
+global(maxMessageSize="256")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ ruleset="remote"
+ framing.delimiter.regex="^<[0-9]{2}>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)")
+
+template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -B -I ${srcdir}/testsuites/imptcp_framing_regex-oversize.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+export EXPECTED='NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test1
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test xml-ish
+<test/>
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test2
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+line1
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+ 1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 2-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 3-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+NEWMSG: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 7-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 8-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+END
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test3
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+line3
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test4'
+cmp_exact
+content_check-regex "assuming end of frame" ${RSYSLOG2_OUT_LOG}
+content_check-regex "message too long" ${RSYSLOG2_OUT_LOG}
+exit_test
diff --git a/tests/imptcp_framing_regex.sh b/tests/imptcp_framing_regex.sh
new file mode 100755
index 0000000..f2eacd3
--- /dev/null
+++ b/tests/imptcp_framing_regex.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$EscapeControlCharactersOnReceive off
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ ruleset="remote"
+ framing.delimiter.regex="^<[0-9]{2}>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)")
+
+template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -B -I ${srcdir}/testsuites/imptcp_framing_regex.testdata
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test1
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test xml-ish
+<test/>
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test2
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+line1
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+ l
+ i
+ n
+
+e2
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test3
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi
+line3
+NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test4'
+cmp_exact
+exit_test
diff --git a/tests/imptcp_large.sh b/tests/imptcp_large.sh
new file mode 100755
index 0000000..f5664a7
--- /dev/null
+++ b/tests/imptcp_large.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Test imptcp with large messages
+# added 2010-08-10 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+generate_conf
+add_conf '
+global(maxMessageSize="10k")
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+# send messages of 10.000bytes plus header max, randomized
+tcpflood -c5 -m$NUMMESSAGES -r -d10000
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $((NUMMESSAGES - 1)) -E
+exit_test
diff --git a/tests/imptcp_maxsessions.sh b/tests/imptcp_maxsessions.sh
new file mode 100755
index 0000000..0428414
--- /dev/null
+++ b/tests/imptcp_maxsessions.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Test imtcp with many dropping connections
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+export NUMMESSAGES=500
+
+MAXSESSIONS=10
+CONNECTIONS=20
+EXPECTED_DROPS=$((CONNECTIONS - MAXSESSIONS))
+
+EXPECTED_STR='too many tcp sessions - dropping incoming request'
+wait_too_many_sessions()
+{
+ test "$(grep "$EXPECTED_STR" "$RSYSLOG_OUT_LOG" | wc -l)" = "$EXPECTED_DROPS"
+}
+
+export QUEUE_EMPTY_CHECK_FUNC=wait_too_many_sessions
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+
+module(load="../plugins/imptcp/.libs/imptcp" maxsessions="'$MAXSESSIONS'")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+'
+startup
+
+echo "INFO: RSYSLOG_OUT_LOG: $RSYSLOG_OUT_LOG"
+
+echo "About to run tcpflood"
+tcpflood -c$CONNECTIONS -m$NUMMESSAGES -r -d100 -P129 -A
+echo "-------> NOTE: CLOSED REMOTELY messages are expected and OK! <-------"
+echo "done run tcpflood"
+shutdown_when_empty
+wait_shutdown
+
+content_count_check "$EXPECTED_STR" $EXPECTED_DROPS
+echo "Got expected drops: $EXPECTED_DROPS, looks good!"
+
+exit_test
diff --git a/tests/imptcp_multi_line.sh b/tests/imptcp_multi_line.sh
new file mode 100755
index 0000000..f21fae8
--- /dev/null
+++ b/tests/imptcp_multi_line.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" multiline="on")
+
+template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -B -I ${srcdir}/testsuites/imptcp_multi_line.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+export EXPECTED='NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test1
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test2
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012line1
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012l#012i#012n#012#012e2
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test3
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012line3
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test4
+NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test end'
+cmp_exact
+exit_test
diff --git a/tests/imptcp_no_octet_counted.sh b/tests/imptcp_no_octet_counted.sh
new file mode 100755
index 0000000..e732ed3
--- /dev/null
+++ b/tests/imptcp_no_octet_counted.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imptcp_no_octet_counted.sh\]: test imptcp with octet counted framing disabled
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" supportOctetCountedFraming="off")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -B -I ${srcdir}/testsuites/no_octet_counted.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 19
+exit_test
diff --git a/tests/imptcp_nonProcessingPoller.sh b/tests/imptcp_nonProcessingPoller.sh
new file mode 100755
index 0000000..84c05ab
--- /dev/null
+++ b/tests/imptcp_nonProcessingPoller.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Test imptcp with poller not processing any messages
+# added 2015-10-16 by singh.janmejay
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+module(load="../plugins/imptcp/.libs/imptcp" threads="32" processOnPoller="off")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if (prifilt("local0.*")) then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+tcpflood -c1 -m $NUMMESSAGES -r -d10000 -P129 -O
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $((NUMMESSAGES - 1)) -E
+exit_test
diff --git a/tests/imptcp_spframingfix.sh b/tests/imptcp_spframingfix.sh
new file mode 100755
index 0000000..ada8e3d
--- /dev/null
+++ b/tests/imptcp_spframingfix.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ====================================================================================
+echo TEST: \[imptcp_spframingfix.sh\]: test imptcp in regard to Cisco ASA framing fix
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" framingfix.cisco.asa="on")
+
+template(name="outfmt" type="string" string="%rawmsg:6:7%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -B -I ${srcdir}/testsuites/spframingfix.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 19
+exit_test
diff --git a/tests/imptcp_veryLargeOctateCountedMessages.sh b/tests/imptcp_veryLargeOctateCountedMessages.sh
new file mode 100755
index 0000000..21c1fb9
--- /dev/null
+++ b/tests/imptcp_veryLargeOctateCountedMessages.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Test imptcp with poller not processing any messages
+# test imptcp with very large messages while poller driven processing is disabled
+# added 2015-10-17 by singh.janmejay
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+generate_conf
+add_conf '$MaxMessageSize 10k
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+module(load="../plugins/imptcp/.libs/imptcp" threads="32" processOnPoller="off")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if (prifilt("local0.*")) then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+export RS_REDIR="2>/dev/null"
+startup
+tcpflood -c1 -m$NUMMESSAGES -r -d100000 -P129 -O
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $((NUMMESSAGES - 1)) -E -T
+exit_test
diff --git a/tests/imrelp-basic-hup.sh b/tests/imrelp-basic-hup.sh
new file mode 100755
index 0000000..d67f1ca
--- /dev/null
+++ b/tests/imrelp-basic-hup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2019-07-30 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=4000 # MUST be an even number!
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2))
+issue_HUP
+tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imrelp-basic-oldstyle.sh b/tests/imrelp-basic-oldstyle.sh
new file mode 100755
index 0000000..4f5ea16
--- /dev/null
+++ b/tests/imrelp-basic-oldstyle.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# addd 2018-10-09 by Alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+
+$ModLoad ../plugins/imrelp/.libs/imrelp # Old Style module loading
+$inputrelpserverrun '$TCPFLOOD_PORT'
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m10000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 9999
+exit_test
diff --git a/tests/imrelp-basic-vg.sh b/tests/imrelp-basic-vg.sh
new file mode 100755
index 0000000..8957601
--- /dev/null
+++ b/tests/imrelp-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imrelp-basic.sh
diff --git a/tests/imrelp-basic.sh b/tests/imrelp-basic.sh
new file mode 100755
index 0000000..efc93d5
--- /dev/null
+++ b/tests/imrelp-basic.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000 # MUST be an even number!
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imrelp-bigmessage.sh b/tests/imrelp-bigmessage.sh
new file mode 100755
index 0000000..39ca4c7
--- /dev/null
+++ b/tests/imrelp-bigmessage.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# add 2020-02-11 by alorbach, released under ASL 2.0
+TEST_BYTES_EXPECTED=262152
+
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+global(
+ workDirectory="'$RSYSLOG_DYNNAME.spool'"
+ maxMessageSize="256k"
+)
+module(load="../plugins/imrelp/.libs/imrelp")
+input(
+ type="imrelp"
+ name="imrelp"
+ port="'$TCPFLOOD_PORT'"
+ ruleset="print"
+ MaxDataSize="260k"
+)
+#input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="200" oversizeMode="accept")
+
+template(name="print_message" type="list"){
+ constant(value="inputname: ")
+ property(name="inputname")
+ constant(value=", strlen: ")
+ property(name="$!strlen")
+ constant(value=", message: ")
+ property(name="msg")
+ constant(value="\n")
+}
+ruleset(name="print") {
+ set $!strlen = strlen($msg);
+ action(
+ type="omfile" template="print_message"
+ file=`echo $RSYSLOG_OUT_LOG`
+ )
+# action(
+# type="omstdout"
+# template="print_message"
+# )
+}
+
+#template(name="outfmt" type="string" string="%msg%\n")
+#:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+# file=`echo $RSYSLOG_OUT_LOG`)
+
+'
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 262144
+# would also works well:
+# tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -R 1 -I "imrelp-bigmessage.log"
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+
+content_check "inputname: imrelp, strlen: 262107, message: msgnum:00000000:262144:"
+count=$(wc -c < $RSYSLOG_OUT_LOG)
+if [ $count -lt $TEST_BYTES_EXPECTED ]; then
+ echo
+ echo "FAIL: expected bytes count $count did not match $TEST_BYTES_EXPECTED. "
+ echo
+ echo "First 100 bytes of $RSYSLOG_OUT_LOG are: "
+ head -c 100 $RSYSLOG_OUT_LOG
+ echo
+ echo "Last 100 bytes of $RSYSLOG_OUT_LOG are: "
+ tail -c 100 $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ echo "Found $count bytes in $RSYSLOG_OUT_LOG"
+fi
+
+exit_test
diff --git a/tests/imrelp-invld-tlslib.sh b/tests/imrelp-invld-tlslib.sh
new file mode 100755
index 0000000..7c242cf
--- /dev/null
+++ b/tests/imrelp-invld-tlslib.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# see that we can an error message if wrong tls lib is selected
+# addd 2019-02-09 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineSetTLSLibByName
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp" tls.tlslib="invalid-tlslib-name")
+input(type="imrelp" port="'$TCPFLOOD_PORT'") #prevent extra config error, not really needed
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+content_check --regex "invalid-tlslib-name.*not accepted"
+exit_test
diff --git a/tests/imrelp-long-msg.sh b/tests/imrelp-long-msg.sh
new file mode 100755
index 0000000..b377c18
--- /dev/null
+++ b/tests/imrelp-long-msg.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# adddd 2018-04-16 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(maxMessageSize="214800")
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="214800")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m2 -d 204800
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 1
+exit_test
diff --git a/tests/imrelp-manyconn-vg.sh b/tests/imrelp-manyconn-vg.sh
new file mode 100755
index 0000000..ef5c702
--- /dev/null
+++ b/tests/imrelp-manyconn-vg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ "$CI_ENV" == "Centos7VM" ]; then
+ # we give up, for some reason we see errors in this env but in no other Centos 7 env
+ # this is a hack for rsyslog official CI - sorry for that -- rgerhards, 2019-01-24
+ echo "SKIP test, as for some reason it does not work here - this should be investigated"
+ exit 77
+fi
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/imrelp-manyconn.sh
diff --git a/tests/imrelp-manyconn.sh b/tests/imrelp-manyconn.sh
new file mode 100755
index 0000000..a5d939a
--- /dev/null
+++ b/tests/imrelp-manyconn.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# adddd 2016-06-08 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+export NUMMESSAGES=100000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -Trelp-plain -c-2000 -p$TCPFLOOD_PORT -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imrelp-maxDataSize-error.sh b/tests/imrelp-maxDataSize-error.sh
new file mode 100755
index 0000000..a64ceab
--- /dev/null
+++ b/tests/imrelp-maxDataSize-error.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-04-26 by Pascal Withopf, released under ASL 2.0
+echo [imrelp-maxDataSize-error.sh]
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+
+global(
+ maxMessageSize="300"
+)
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxDataSize="250")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+./msleep 2000
+
+shutdown_when_empty
+wait_shutdown
+
+grep "error: maxDataSize.*smaller than global parameter maxMessageSize" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imrelp-oversizeMode-accept.sh b/tests/imrelp-oversizeMode-accept.sh
new file mode 100755
index 0000000..c743f9e
--- /dev/null
+++ b/tests/imrelp-oversizeMode-accept.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2018-04-25 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="200" oversizeMode="accept")
+
+template(name="outfmt" type="string" string="%msg%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+grep "^ msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imrelp-oversizeMode-truncate.sh b/tests/imrelp-oversizeMode-truncate.sh
new file mode 100755
index 0000000..b23a775
--- /dev/null
+++ b/tests/imrelp-oversizeMode-truncate.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# add 2018-04-19 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+./have_relpSrvSetOversizeMode
+if [ $? -eq 1 ]; then
+ echo "imrelp parameter oversizeMode not available. Test stopped"
+ exit 77
+fi;
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+global(maxMessageSize="150" oversizemsg.input.mode="accept")
+
+
+input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="200" oversizeMode="truncate")
+
+template(name="outfmt" type="string" string="%msg%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end
+# because otherwise we won't know if it was truncated at the right length.
+grep "^ msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imrelp-sessionbreak-vg.sh b/tests/imrelp-sessionbreak-vg.sh
new file mode 100755
index 0000000..076c771
--- /dev/null
+++ b/tests/imrelp-sessionbreak-vg.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# added 2020-04-10 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000000
+export USE_VALGRIND="YES"
+# TODO remote leak check skip and fix memory leaks caused by session break
+export RS_TESTBENCH_LEAK_CHECK=no
+
+mkdir $RSYSLOG_DYNNAME.workdir
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+
+global(
+ workDirectory="'$RSYSLOG_DYNNAME.workdir'"
+ maxMessageSize="256k"
+)
+main_queue(queue.type="Direct")
+
+$LocalHostName test
+$AbortOnUncleanConfig on
+$PreserveFQDN on
+
+input( type="imrelp"
+ name="imrelp"
+ port="'$TCPFLOOD_PORT'"
+ ruleset="spool"
+ MaxDataSize="256k"
+ KeepAlive="on"
+)
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="spool" queue.type="direct") {
+ if $msg contains "msgnum:" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ }
+}
+'
+startup
+# How many tcpfloods we run at the same tiem
+for ((i=1;i<=5;i++)); do
+ # How many times tcpflood runs in each threads
+ ./tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$NUMMESSAGES -s &
+ tcpflood_pid=$!
+
+ echo "started tcpflood instance $i (PID $tcpflood_pid)"
+
+ # Give it time to actually connect
+ ./msleep 500;
+
+ kill -9 $tcpflood_pid # >/dev/null 2>&1;
+ echo "killed tcpflood instance $i (PID $tcpflood_pid)"
+done;
+
+wait_queueempty
+
+netstatresult=$(netstat --all --program 2>&1 | grep "ESTABLISHED" | grep $(cat $RSYSLOG_PIDBASE.pid) | grep $TCPFLOOD_PORT)
+openfd=$(ls -l "/proc/$(cat $RSYSLOG_PIDBASE$1.pid)/fd" | wc -l)
+
+shutdown_when_empty
+wait_shutdown
+
+if [[ "$netstatresult" == "" ]]
+then
+ echo "OK!"
+else
+ echo "STILL OPENED Connections: "
+ echo $netstatresult
+ echo "Open files at the end: "
+ echo $openfd
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imrelp-tls-cfgcmd.sh b/tests/imrelp-tls-cfgcmd.sh
new file mode 100755
index 0000000..6d03c2b
--- /dev/null
+++ b/tests/imrelp-tls-cfgcmd.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# addd 2019-11-14 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineSetTLSLibByName
+export NUMMESSAGES=1000
+export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="openssl")
+input(type="imrelp" port="'$TCPFLOOD_PORT'" tls="on"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog"
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2
+CipherString=ECDHE-RSA-AES256-GCM-SHA384
+Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2,-TLSv1.3
+MinProtocol=TLSv1.2
+MaxProtocol=TLSv1.2")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+
+export TCPFLOOD_EXTRA_OPTS='-k "Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2
+CipherString=DHE-RSA-AES256-SHA
+Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2,-TLSv1.3
+MinProtocol=TLSv1.1
+MaxProtocol=TLSv1.1"'
+tcpflood --check-only -u "openssl" -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -x "$srcdir/tls-certs/ca.pem" -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/cert.pem" -Ersyslog 2> ${RSYSLOG_DYNNAME}.tcpflood
+
+shutdown_when_empty
+wait_shutdown
+
+content_check --check-only "relpTcpTLSSetPrio_gtls" ${RSYSLOG_DEBUGLOG}
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: LIBRELP was build without OPENSSL Support"
+ skip_test
+fi
+
+content_check --check-only "OpenSSL Version too old" ${RSYSLOG_DEBUGLOG}
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: OpenSSL Version too old"
+ skip_test
+else
+ # Check for a failed session - possible ecodes are 10031 and 10040
+ content_check "librelp: generic error: ecode" $RSYSLOG_DEBUGLOG
+fi
+
+exit_test \ No newline at end of file
diff --git a/tests/imrelp-tls-chainedcert.sh b/tests/imrelp-tls-chainedcert.sh
new file mode 100755
index 0000000..927c588
--- /dev/null
+++ b/tests/imrelp-tls-chainedcert.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# addd 2020-08-25 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineVersion "1.7.0"
+export NUMMESSAGES=1000
+
+# uncomment for debugging support:
+# export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+# export RSYSLOG_DEBUGLOG="log"
+# export TCPFLOOD_EXTRA_OPTS="-v"
+
+do_skip=0
+generate_conf
+add_conf '
+# uncomment for debugging support:
+# $DebugFile debug.log
+# $DebugLevel 2
+
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="openssl"
+)
+input(type="imrelp" port="'$TCPFLOOD_PORT'"
+ tls="on"
+ tls.mycert="'$srcdir'/tls-certs/certchained.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+./tcpflood -u openssl -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/certchained.pem" -Ersyslog 2> $RSYSLOG_DYNNAME.tcpflood
+cat -n $RSYSLOG_DYNNAME.tcpflood
+shutdown_when_empty
+wait_shutdown
+
+# uncomment for debugging support:
+# cat debug.log
+
+if [ $do_skip -eq 1 ]; then
+ skip_test
+fi
+seq_check
+exit_test
diff --git a/tests/imrelp-tls-mixed-chainedcert.sh b/tests/imrelp-tls-mixed-chainedcert.sh
new file mode 100755
index 0000000..1273fab
--- /dev/null
+++ b/tests/imrelp-tls-mixed-chainedcert.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# addd 2020-08-25 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineVersion "1.7.0"
+export NUMMESSAGES=1000
+
+# uncomment for debugging support:
+export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+export TCPFLOOD_EXTRA_OPTS="-v"
+
+# Print Versions
+echo "OpenSSL Version:"
+openssl version
+
+echo "GnuTls Version:"
+gnutls-cli --version
+
+do_skip=0
+generate_conf
+add_conf '
+# uncomment for debugging support:
+# $DebugFile debug.log
+# $DebugLevel 2
+
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="openssl"
+)
+input(type="imrelp" port="'$TCPFLOOD_PORT'"
+ tls="on"
+ tls.mycert="'$srcdir'/tls-certs/certchained.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+./tcpflood -u gnutls -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/certchained.pem" -Ersyslog 2> $RSYSLOG_DYNNAME.tcpflood
+cat -n $RSYSLOG_DYNNAME.tcpflood
+shutdown_when_empty
+wait_shutdown
+
+# uncomment for debugging support:
+# cat debug.log
+
+if [ $do_skip -eq 1 ]; then
+ skip_test
+fi
+seq_check
+exit_test
diff --git a/tests/imrelp-tls-mixed-chainedcert2.sh b/tests/imrelp-tls-mixed-chainedcert2.sh
new file mode 100755
index 0000000..742f333
--- /dev/null
+++ b/tests/imrelp-tls-mixed-chainedcert2.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# addd 2020-08-25 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineVersion "1.7.0"
+export NUMMESSAGES=1000
+
+# uncomment for debugging support:
+export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+export TCPFLOOD_EXTRA_OPTS="-v"
+
+# Print Versions
+echo "OpenSSL Version:"
+openssl version
+
+echo "GnuTls Version:"
+gnutls-cli --version
+
+do_skip=0
+generate_conf
+add_conf '
+# uncomment for debugging support:
+# $DebugFile debug.log
+# $DebugLevel 2
+
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="gnutls"
+)
+input(type="imrelp" port="'$TCPFLOOD_PORT'"
+ tls="on"
+ tls.mycert="'$srcdir'/tls-certs/certchained.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+./tcpflood -u openssl -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/certchained.pem" -Ersyslog 2> $RSYSLOG_DYNNAME.tcpflood
+cat -n $RSYSLOG_DYNNAME.tcpflood
+shutdown_when_empty
+wait_shutdown
+
+# uncomment for debugging support:
+# cat debug.log
+
+if [ $do_skip -eq 1 ]; then
+ skip_test
+fi
+seq_check
+exit_test
diff --git a/tests/imrelp-tls.sh b/tests/imrelp-tls.sh
new file mode 100755
index 0000000..d0d88ae
--- /dev/null
+++ b/tests/imrelp-tls.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# addd 2019-01-31 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+do_skip=0
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$TCPFLOOD_PORT'" tls="on"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+./tcpflood -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -x "$srcdir/tls-certs/ca.pem" -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/cert.pem" -Ersyslog 2> $RSYSLOG_DYNNAME.tcpflood
+if [ $? -eq 1 ]; then
+ cat $RSYSLOG_DYNNAME.tcpflood
+ if ! grep "could net set.*certvalid" < "$RSYSLOG_DYNNAME.tcpflood" ; then
+ printf "librelp too old, need to skip this test\n"
+ do_skip=1
+ fi
+fi
+ cat -n $RSYSLOG_DYNNAME.tcpflood
+shutdown_when_empty
+wait_shutdown
+if [ $do_skip -eq 1 ]; then
+ skip_test
+fi
+seq_check
+exit_test
diff --git a/tests/imtcp-NUL-rawmsg.sh b/tests/imtcp-NUL-rawmsg.sh
new file mode 100755
index 0000000..f637d22
--- /dev/null
+++ b/tests/imtcp-NUL-rawmsg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message
+<167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 #000 test message
+<167>Mar 6 16:57:54 172.20.245.8 #000test: msgnum:1 test message' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+exit_test
diff --git a/tests/imtcp-NUL.sh b/tests/imtcp-NUL.sh
new file mode 100755
index 0000000..8f1d27a
--- /dev/null
+++ b/tests/imtcp-NUL.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message
+<167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > $RSYSLOG_DYNNAME.input
+tcpflood -B -I $RSYSLOG_DYNNAME.input
+shutdown_when_empty
+wait_shutdown
+seq_check 0 1
+exit_test
diff --git a/tests/imtcp-basic-hup.sh b/tests/imtcp-basic-hup.sh
new file mode 100755
index 0000000..0eb33d0
--- /dev/null
+++ b/tests/imtcp-basic-hup.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2019-07-30 by RGerhards, released under ASL 2.0
+export NUMMESSAGES=4000 # MUST be an even number!
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2))
+issue_HUP
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-basic.sh b/tests/imtcp-basic.sh
new file mode 100755
index 0000000..314947c
--- /dev/null
+++ b/tests/imtcp-basic.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -m $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-bigmessage-octetcounting.sh b/tests/imtcp-bigmessage-octetcounting.sh
new file mode 100755
index 0000000..1d9350b
--- /dev/null
+++ b/tests/imtcp-bigmessage-octetcounting.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# add 2020-05-14 by alorbach, released under ASL 2.0
+export NUMMESSAGES=10
+export TEST_BYTES_SENDSIZE=4037
+export TEST_BYTES_EXPECTED=$(((TEST_BYTES_SENDSIZE/2 - 420) * NUMMESSAGES)) # 262152
+. ${srcdir:=.}/diag.sh init
+
+generate_conf
+add_conf '
+global(
+ workDirectory="'$RSYSLOG_DYNNAME.spool'"
+ maxMessageSize="4k"
+)
+module( load="../plugins/imtcp/.libs/imtcp"
+ MaxSessions="10000"
+ discardTruncatedMsg="on"
+)
+input(
+ type="imtcp"
+ name="imtcp"
+ port="'$TCPFLOOD_PORT'"
+ ruleset="print"
+)
+
+template(name="print_message" type="list"){
+ constant(value="inputname: ")
+ property(name="inputname")
+ constant(value=", strlen: ")
+ property(name="$!strlen")
+ constant(value=", message: ")
+ property(name="msg")
+ constant(value="\n")
+}
+ruleset(name="print") {
+ set $!strlen = strlen($msg);
+ action(
+ type="omfile" template="print_message"
+ file=`echo $RSYSLOG_OUT_LOG`
+ )
+}
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -d $TEST_BYTES_SENDSIZE -O
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+content_count_check --regex "inputname: imtcp, strlen:" ${NUMMESSAGES}
+
+count=$(wc -c < $RSYSLOG_OUT_LOG)
+if [ $count -lt $TEST_BYTES_EXPECTED ]; then
+ echo
+ echo "FAIL: expected bytes count $count did not match $TEST_BYTES_EXPECTED. "
+ echo
+ echo "First 100 bytes of $RSYSLOG_OUT_LOG are: "
+ head -c 100 $RSYSLOG_OUT_LOG
+ echo
+ echo "Last 100 bytes of $RSYSLOG_OUT_LOG are: "
+ tail -c 100 $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ echo "Found $count bytes (Expected $TEST_BYTES_EXPECTED) in $RSYSLOG_OUT_LOG"
+fi
+
+exit_test \ No newline at end of file
diff --git a/tests/imtcp-bigmessage-octetstuffing.sh b/tests/imtcp-bigmessage-octetstuffing.sh
new file mode 100755
index 0000000..35f9568
--- /dev/null
+++ b/tests/imtcp-bigmessage-octetstuffing.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# add 2020-05-14 by alorbach, released under ASL 2.0
+export NUMMESSAGES=10
+export TEST_BYTES_SENDSIZE=4037
+export TEST_BYTES_EXPECTED=$(((TEST_BYTES_SENDSIZE/2 - 420) * NUMMESSAGES)) # 262152
+. ${srcdir:=.}/diag.sh init
+
+generate_conf
+add_conf '
+global(
+ workDirectory="'$RSYSLOG_DYNNAME.spool'"
+ maxMessageSize="4k"
+)
+module( load="../plugins/imtcp/.libs/imtcp"
+ MaxSessions="10000"
+ discardTruncatedMsg="on"
+)
+input(
+ type="imtcp"
+ name="imtcp"
+ port="'$TCPFLOOD_PORT'"
+ ruleset="print"
+)
+
+template(name="print_message" type="list"){
+ constant(value="inputname: ")
+ property(name="inputname")
+ constant(value=", strlen: ")
+ property(name="$!strlen")
+ constant(value=", message: ")
+ property(name="msg")
+ constant(value="\n")
+}
+ruleset(name="print") {
+ set $!strlen = strlen($msg);
+ action(
+ type="omfile" template="print_message"
+ file=`echo $RSYSLOG_OUT_LOG`
+ )
+}
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -d $TEST_BYTES_SENDSIZE
+
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+content_count_check --regex "inputname: imtcp, strlen:" ${NUMMESSAGES}
+
+count=$(wc -c < $RSYSLOG_OUT_LOG)
+if [ $count -lt $TEST_BYTES_EXPECTED ]; then
+ echo
+ echo "FAIL: expected bytes count $count did not match $TEST_BYTES_EXPECTED. "
+ echo
+ echo "First 100 bytes of $RSYSLOG_OUT_LOG are: "
+ head -c 100 $RSYSLOG_OUT_LOG
+ echo
+ echo "Last 100 bytes of $RSYSLOG_OUT_LOG are: "
+ tail -c 100 $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ echo "Found $count bytes (Expected $TEST_BYTES_EXPECTED) in $RSYSLOG_OUT_LOG"
+fi
+
+exit_test \ No newline at end of file
diff --git a/tests/imtcp-connection-msg-recieved.sh b/tests/imtcp-connection-msg-recieved.sh
new file mode 100755
index 0000000..60d3497
--- /dev/null
+++ b/tests/imtcp-connection-msg-recieved.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# addd 2021-05-10 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ notifyonconnectionopen="on" notifyonconnectionclose="on")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m1 -M"\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+content_check "connection established with "
+content_check "closed by remote peer "
+exit_test
diff --git a/tests/imtcp-discard-truncated-msg.sh b/tests/imtcp-discard-truncated-msg.sh
new file mode 100755
index 0000000..8782dec
--- /dev/null
+++ b/tests/imtcp-discard-truncated-msg.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on")
+module(load="../plugins/imtcp/.libs/imtcp" discardTruncatedMsg="on")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"<30>Apr 6 13:21:08 docker/6befb258da22[6128]: TOO LONG bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb123456789B123456789Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+<30>Apr 6 13:21:09 docker/6defd258da22[6128]: NEXT_MSG\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='<30>Apr 6 13:21:08 docker/6befb258da22[6128]: TOO LONG bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb123456789B12
+<30>Apr 6 13:21:09 docker/6defd258da22[6128]: NEXT_MSG'
+cmp_exact
+
+exit_test
diff --git a/tests/imtcp-drvr-in-input-basic.sh b/tests/imtcp-drvr-in-input-basic.sh
new file mode 100755
index 0000000..5ca98d3
--- /dev/null
+++ b/tests/imtcp-drvr-in-input-basic.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2021-04-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-listen-port-file-2.sh b/tests/imtcp-listen-port-file-2.sh
new file mode 100755
index 0000000..1508536
--- /dev/null
+++ b/tests/imtcp-listen-port-file-2.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This test checks if more than one port file names work correctly for
+# imtcp. See also:
+# https://github.com/rsyslog/rsyslog/issues/3817
+# added 2019-08-14 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port"
+ ruleset="rs1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port2"
+ ruleset="rs2")
+
+ruleset(name="rs1") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME.1.log'" template="outfmt")
+}
+
+ruleset(name="rs2") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME.2.log'" template="outfmt")
+}
+'
+startup
+assign_file_content RCVR_PORT "$RSYSLOG_DYNNAME.rcvr_port"
+assign_file_content RCVR_PORT2 "$RSYSLOG_DYNNAME.rcvr_port2"
+./tcpflood -p $RCVR_PORT -m10
+./tcpflood -p $RCVR_PORT2 -m10 -i10
+shutdown_when_empty
+wait_shutdown
+printf 'checking receiver 1\n'
+export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.1.log"
+seq_check 0 9
+printf 'checking receiver 2\n'
+export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.2.log"
+seq_check 10 19
+exit_test
diff --git a/tests/imtcp-maxFrameSize.sh b/tests/imtcp-maxFrameSize.sh
new file mode 100755
index 0000000..a580f78
--- /dev/null
+++ b/tests/imtcp-maxFrameSize.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(processInternalMessages="on")
+module(load="../plugins/imtcp/.libs/imtcp" maxFrameSize="100")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"1005 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message\""
+shutdown_when_empty
+wait_shutdown
+
+grep "Framing Error.*change to octet stuffing" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from imtcp not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+
+exit_test
diff --git a/tests/imtcp-msg-truncation-on-number.sh b/tests/imtcp-msg-truncation-on-number.sh
new file mode 100755
index 0000000..5dd2532
--- /dev/null
+++ b/tests/imtcp-msg-truncation-on-number.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on"
+ oversizemsg.input.mode="accept")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has ab
+9876543210 cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtesttesttesttesttesttesttesttest\""
+shutdown_when_empty
+wait_shutdown
+
+grep "Framing Error in received" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from imtcp not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "9876543210cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestt" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected date from imtcp not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/imtcp-msg-truncation-on-number2.sh b/tests/imtcp-msg-truncation-on-number2.sh
new file mode 100755
index 0000000..d099fb5
--- /dev/null
+++ b/tests/imtcp-msg-truncation-on-number2.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# addd 2016-05-13 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="templ1" type="string" string="%rawmsg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="templ1")
+}
+'
+startup
+tcpflood -m2 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"2000000010 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"4000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+tcpflood -m1 -M "\"0 <120> 2011-03-01T11:22:12Z host msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+
+echo '<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+214000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+214000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1
+2000000010<120> 2011-03-01T11:22:12Z host msgnum:1
+4000000000<120> 2011-03-01T11:22:12Z host msgnum:1
+<120> 2011-03-01T11:22:12Z host msgnum:1' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imtcp-multi-drvr-basic-parallel.sh b/tests/imtcp-multi-drvr-basic-parallel.sh
new file mode 100755
index 0000000..a8de39a
--- /dev/null
+++ b/tests/imtcp-multi-drvr-basic-parallel.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This test checks imtcp functionality with multiple drivers running together. It is
+# a minimal test.
+# added 2021-04-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100000 # must be even number!
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+# Note: the two tcpflood instances are run in parallel with intent!
+# It stresses the rsyslog engine a bit more. If this fails, see if
+# the non-parallel test also fails. If so, debug that one, because it
+# is easier to do!
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem &
+tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh b/tests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh
new file mode 100755
index 0000000..c3be9f9
--- /dev/null
+++ b/tests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This test checks imtcp functionality with multiple drivers running together. It is
+# a minimal test.
+# added 2021-04-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=60000 # must be evenly dividable by 3
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ name="i1"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" name="i2" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3"
+ name="i3"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3"
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 3)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3))
+tcpflood -p$RS_PORT -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3 * 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-multi-drvr-basic.sh b/tests/imtcp-multi-drvr-basic.sh
new file mode 100755
index 0000000..13edafb
--- /dev/null
+++ b/tests/imtcp-multi-drvr-basic.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This test checks imtcp functionality with multiple drivers running together. It is
+# a minimal test.
+# added 2021-04-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000 # must be even number!
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-multiport.sh b/tests/imtcp-multiport.sh
new file mode 100755
index 0000000..7516be0
--- /dev/null
+++ b/tests/imtcp-multiport.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Test for multiple ports in imtcp
+# This test checks if multiple tcp listener ports are correctly
+# handled by imtcp
+# added 2009-05-22 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=30000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" name="i1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" name="i2")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3"
+tcpflood -p$TCPFLOOD_PORT -m10000
+tcpflood -p$TCPFLOOD_PORT2 -i10000 -m10000
+tcpflood -p$RS_PORT -i20000 -m10000
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-octet-framing-too-long-vg.sh b/tests/imtcp-octet-framing-too-long-vg.sh
new file mode 100755
index 0000000..88e8a14
--- /dev/null
+++ b/tests/imtcp-octet-framing-too-long-vg.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2022-04-25 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MaxMessageSize 128
+global(processInternalMessages="on"
+ oversizemsg.input.mode="accept")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup_vg
+echo "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab" > $RSYSLOG_DYNNAME.inputfile
+tcpflood -I $RSYSLOG_DYNNAME.inputfile
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+# the prime objective is to see if valgrind check is ok, but we also do a quick content check (just in case)
+content_check "received oversize message from peer"
+exit_test
diff --git a/tests/imtcp-tls-basic-verifydepth.sh b/tests/imtcp-tls-basic-verifydepth.sh
new file mode 100755
index 0000000..d057b3a
--- /dev/null
+++ b/tests/imtcp-tls-basic-verifydepth.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# added 2011-02-28 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.TlsVerifyDepth="5"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+
+# Begin actual testcase
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-basic-vg.sh b/tests/imtcp-tls-basic-vg.sh
new file mode 100755
index 0000000..4648389
--- /dev/null
+++ b/tests/imtcp-tls-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imtcp-tls-basic.sh
diff --git a/tests/imtcp-tls-basic.sh b/tests/imtcp-tls-basic.sh
new file mode 100755
index 0000000..b65e7c4
--- /dev/null
+++ b/tests/imtcp-tls-basic.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# added 2011-02-28 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export TB_TEST_MAX_RUNTIME=1500
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-gtls-x509fingerprint-invld.sh b/tests/imtcp-tls-gtls-x509fingerprint-invld.sh
new file mode 100755
index 0000000..af33b45
--- /dev/null
+++ b/tests/imtcp-tls-gtls-x509fingerprint-invld.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2018-12-22 by Rainer Gerhards
+# check for INVALID fingerprint!
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/fingerprint"
+ PermittedPeer=["SHA1:FF:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"] # INVALID!
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+content_check --regex "peer fingerprint .* unknown"
+exit_test
diff --git a/tests/imtcp-tls-gtls-x509fingerprint.sh b/tests/imtcp-tls-gtls-x509fingerprint.sh
new file mode 100755
index 0000000..8cadd29
--- /dev/null
+++ b/tests/imtcp-tls-gtls-x509fingerprint.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# added 2018-12-22 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/fingerprint"
+ PermittedPeer=["SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"]
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-gtls-x509name-invld.sh b/tests/imtcp-tls-gtls-x509name-invld.sh
new file mode 100755
index 0000000..c1c541d
--- /dev/null
+++ b/tests/imtcp-tls-gtls-x509name-invld.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2018-12-22 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/name"
+ PermittedPeer=["INVALID"]
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+content_check --regex "peer name not authorized"
+exit_test
diff --git a/tests/imtcp-tls-gtls-x509name-legacy.sh b/tests/imtcp-tls-gtls-x509name-legacy.sh
new file mode 100755
index 0000000..4e8878c
--- /dev/null
+++ b/tests/imtcp-tls-gtls-x509name-legacy.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+
+# NOTE: we intentionally use legacy statements here! This *IS* what we want to test!
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$DefaultNetstreamDriver gtls
+$inputTcpserverStreamdriverPermittedPeer rsyslog-client
+
+$InputTCPServerStreamDriverAuthMode x509/name
+$InputTCPServerStreamDriverPermittedPeer Log_Streaming_Client
+$InputTCPServerStreamDriverMode 1
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-gtls-x509name.sh b/tests/imtcp-tls-gtls-x509name.sh
new file mode 100755
index 0000000..81d9ca5
--- /dev/null
+++ b/tests/imtcp-tls-gtls-x509name.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# added 2018-12-22 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/name"
+ PermittedPeer=["rsyslog-client"]
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-input-2certs.sh b/tests/imtcp-tls-input-2certs.sh
new file mode 100755
index 0000000..c31724f
--- /dev/null
+++ b/tests/imtcp-tls-input-2certs.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# added 2021-08-03 by Rgerhards
+# check that we do use the proper set of certificates
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+# The default shall NOT be used - if so, tcpflood would err out!
+
+global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/machine-cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/machine-key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp"
+ permittedPeer="SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/fingerprint" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem"
+ streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem"
+ streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem")
+
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-input-basic.sh b/tests/imtcp-tls-input-basic.sh
new file mode 100755
index 0000000..4f52302
--- /dev/null
+++ b/tests/imtcp-tls-input-basic.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2011-02-28 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem"
+ streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem"
+ streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem")
+
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-no-lstn-startup.sh b/tests/imtcp-tls-no-lstn-startup.sh
new file mode 100755
index 0000000..e18fc8e
--- /dev/null
+++ b/tests/imtcp-tls-no-lstn-startup.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# added 2021-07-07 by Rgerhards
+# This test checks if rsyslog handles a non-starting imtcp listener gracefully.
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="invalid-does-not-exist")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+#tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh b/tests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh
new file mode 100755
index 0000000..4e2ba98
--- /dev/null
+++ b/tests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then
+ printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n'
+ printf 'a valgrind-internal bug. So we need to skip it.\n'
+ exit 77
+fi
+. ${srcdir:=.}/diag.sh init
+export USE_VALGRIND="YES"
+export NUMMESSAGES=1
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# Begin actual testcase | send one msg without TLS to force a handshake failure, send second msg with TLS to make the test PASS
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-basic-tlscommands.sh b/tests/imtcp-tls-ossl-basic-tlscommands.sh
new file mode 100755
index 0000000..6f2e760
--- /dev/null
+++ b/tests/imtcp-tls-ossl-basic-tlscommands.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon"
+ gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2
+ Options=Bugs"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+# now inject the messages which will fail due protocol configuration
+tcpflood --check-only -k "Protocol=-ALL,TLSv1.2" -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+
+shutdown_when_empty
+wait_shutdown
+
+if content_check --check-only "TLS library does not support SSL_CONF_cmd"
+then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ if content_check --check-only "SSL_ERROR_SYSCALL"
+ then
+ # Found SSL_ERROR_SYSCALL errorcode, no further check needed
+ exit_test
+ else
+ # Check for a SSL_ERROR_SSL error code
+ content_check "SSL_ERROR_SSL"
+ content_check "OpenSSL Error Stack:"
+ fi
+fi
+
+exit_test
diff --git a/tests/imtcp-tls-ossl-basic-verifydepth.sh b/tests/imtcp-tls-ossl-basic-verifydepth.sh
new file mode 100755
index 0000000..1a4de87
--- /dev/null
+++ b/tests/imtcp-tls-ossl-basic-verifydepth.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# added 2020-01-08 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.TlsVerifyDepth="5"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+
+# Begin actual testcase
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-basic-vg.sh b/tests/imtcp-tls-ossl-basic-vg.sh
new file mode 100755
index 0000000..951c54c
--- /dev/null
+++ b/tests/imtcp-tls-ossl-basic-vg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then
+ printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n'
+ printf 'a valgrind-internal bug. So we need to skip it.\n'
+ exit 77
+fi
+export USE_VALGRIND="YES"
+# not working on CENTOS 7 export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes"
+source ${srcdir:-.}/imtcp-tls-ossl-basic.sh
diff --git a/tests/imtcp-tls-ossl-basic.sh b/tests/imtcp-tls-ossl-basic.sh
new file mode 100755
index 0000000..0d17e3c
--- /dev/null
+++ b/tests/imtcp-tls-ossl-basic.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["net_ossl.c", "nsd_ossl.c", "nsd_ptcp.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# Begin actual testcase
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-error-ca.sh b/tests/imtcp-tls-ossl-error-ca.sh
new file mode 100755
index 0000000..460c8c0
--- /dev/null
+++ b/tests/imtcp-tls-ossl-error-ca.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2018-11-07 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca-fail.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'"
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+# note: we do not need to generate any messages, config error occurs on startup
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Error: CA certificate could not be accessed"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/imtcp-tls-ossl-error-cert.sh b/tests/imtcp-tls-ossl-error-cert.sh
new file mode 100755
index 0000000..5e8c129
--- /dev/null
+++ b/tests/imtcp-tls-ossl-error-cert.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added 2018-11-07 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-fail.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'"
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+# note: we do not need to generate any messages, config error occurs on startup
+startup
+sleep 5 # TODO: FIXME - just checking if we terminate too early
+shutdown_when_empty
+wait_shutdown
+content_check "Error: Certificate file could not be accessed"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/imtcp-tls-ossl-error-key.sh b/tests/imtcp-tls-ossl-error-key.sh
new file mode 100755
index 0000000..beaf800
--- /dev/null
+++ b/tests/imtcp-tls-ossl-error-key.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added 2018-11-07 by Rainer Gerhards
+# check error message on cert as key file
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'"
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+# note: we do not need to generate any messages, config error occurs on startup
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Error: Key could not be accessed"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/imtcp-tls-ossl-error-key2.sh b/tests/imtcp-tls-ossl-error-key2.sh
new file mode 100755
index 0000000..4202cc0
--- /dev/null
+++ b/tests/imtcp-tls-ossl-error-key2.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2018-11-07 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key-fail.pem'"
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+# note: we do not need to generate any messages, config error occurs on startup
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "Error: Key could not be accessed"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/imtcp-tls-ossl-input-2certs.sh b/tests/imtcp-tls-ossl-input-2certs.sh
new file mode 100755
index 0000000..c23c413
--- /dev/null
+++ b/tests/imtcp-tls-ossl-input-2certs.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# added 2021-08-03 by Rgerhards
+# check that we do use the proper set of certificates
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+# The default shall NOT be used - if so, tcpflood would err out!
+
+global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/machine-cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/machine-key.pem")
+
+module(load="../plugins/imtcp/.libs/imtcp"
+ permittedPeer="SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/fingerprint" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem"
+ streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem"
+ streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem")
+
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-input-basic.sh b/tests/imtcp-tls-ossl-input-basic.sh
new file mode 100755
index 0000000..3c9a7b1
--- /dev/null
+++ b/tests/imtcp-tls-ossl-input-basic.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# added 2011-02-28 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global(
+# debug.whitelist="on"
+# debug.files=["net_ossl.c", "nsd_ossl.c", "nsd_ptcp.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module(load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port"
+ streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem"
+ streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem"
+ streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem")
+
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-invalid-verifydepth.sh b/tests/imtcp-tls-ossl-invalid-verifydepth.sh
new file mode 100755
index 0000000..6df20c4
--- /dev/null
+++ b/tests/imtcp-tls-ossl-invalid-verifydepth.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ streamdriver.TlsVerifyDepth="1" )
+
+# input is not really needed, just given for completeness
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "streamdriver.TlsVerifyDepth must be 2 or higher"
+
+exit_test
diff --git a/tests/imtcp-tls-ossl-x509fingerprint.sh b/tests/imtcp-tls-ossl-x509fingerprint.sh
new file mode 100755
index 0000000..59167b0
--- /dev/null
+++ b/tests/imtcp-tls-ossl-x509fingerprint.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/fingerprint"
+ PermittedPeer=["SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"]
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-x509name.sh b/tests/imtcp-tls-ossl-x509name.sh
new file mode 100755
index 0000000..fadd7f1
--- /dev/null
+++ b/tests/imtcp-tls-ossl-x509name.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/name"
+ PermittedPeer=["/CN=rsyslog-client/OU=Adiscon GmbH/O=Adiscon GmbH/L=Grossrinderfeld/ST=BW/C=DE/DC=rsyslog.com","rsyslog.com"]
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp-tls-ossl-x509valid.sh b/tests/imtcp-tls-ossl-x509valid.sh
new file mode 100755
index 0000000..a796daa
--- /dev/null
+++ b/tests/imtcp-tls-ossl-x509valid.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# added 2018-04-27 by alorbach
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+# Begin actual testcase
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+wait_file_lines
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp_addtlframedelim.sh b/tests/imtcp_addtlframedelim.sh
new file mode 100755
index 0000000..0b217fe
--- /dev/null
+++ b/tests/imtcp_addtlframedelim.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2010-08-11 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp" addtlframedelimiter="0")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+local0.* ./'$RSYSLOG_OUT_LOG';outfmt
+'
+startup
+tcpflood -m$NUMMESSAGES -F0 -P129
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp_addtlframedelim_on_input.sh b/tests/imtcp_addtlframedelim_on_input.sh
new file mode 100755
index 0000000..a2618d9
--- /dev/null
+++ b/tests/imtcp_addtlframedelim_on_input.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2010-08-11 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" addtlframedelimiter="0")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+local0.* ./'$RSYSLOG_OUT_LOG';outfmt
+'
+startup
+tcpflood -m$NUMMESSAGES -F0 -P129
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/imtcp_conndrop.sh b/tests/imtcp_conndrop.sh
new file mode 100755
index 0000000..676c3e0
--- /dev/null
+++ b/tests/imtcp_conndrop.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Test imtcp with many dropping connections
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+local0.* ?dynfile;outfmt
+'
+startup
+# 100 byte messages to gain more practical data use
+tcpflood -c20 -m$NUMMESSAGES -r -d100 -P129 -D
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/imtcp_conndrop_tls-vg.sh b/tests/imtcp_conndrop_tls-vg.sh
new file mode 100755
index 0000000..d2de6e8
--- /dev/null
+++ b/tests/imtcp_conndrop_tls-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+export TB_TEST_MAX_RUNTIME=1500
+export NUMMESSAGES=10000 # reduce for slower valgrind run
+source ${srcdir:-.}/imtcp_conndrop_tls.sh
diff --git a/tests/imtcp_conndrop_tls.sh b/tests/imtcp_conndrop_tls.sh
new file mode 100755
index 0000000..1b9e38b
--- /dev/null
+++ b/tests/imtcp_conndrop_tls.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test imtcp/TLS with many dropping connections
+# added 2011-06-09 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+global( maxMessageSize="10k"
+ defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem"
+ defaultNetstreamDriver="gtls"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100"
+ streamDriver.mode="1" streamDriver.authMode="anon")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+# 100 byte messages to gain more practical data use
+tcpflood -c20 -p$TCPFLOOD_PORT -m$NUMMESSAGES -r -d100 -P129 -D -l0.995 -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/imtcp_incomplete_frame_at_end.sh b/tests/imtcp_incomplete_frame_at_end.sh
new file mode 100755
index 0000000..85d6e94
--- /dev/null
+++ b/tests/imtcp_incomplete_frame_at_end.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright (C) 2016 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="list") {
+ property(name="msg")
+ constant(value="\n")
+}
+:msg, contains, "lastmsg" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+echo -n "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - lastmsg" >$RSYSLOG_DYNNAME.tmp
+tcpflood -I $RSYSLOG_DYNNAME.tmp
+rm $RSYSLOG_DYNNAME.tmp
+./msleep 500
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+export EXPECTED="lastmsg"
+cmp_exact
+exit_test
diff --git a/tests/imtcp_no_octet_counted.sh b/tests/imtcp_no_octet_counted.sh
new file mode 100755
index 0000000..a17174b
--- /dev/null
+++ b/tests/imtcp_no_octet_counted.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imtcp_no_octet_counted.sh\]: test imtcp with octet counted framing disabled
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" supportOctetCountedFraming="off")
+
+template(name="outfmt" type="string" string="%rawmsg%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -B -I ${srcdir}/testsuites/no_octet_counted.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 19
+exit_test
diff --git a/tests/imtcp_spframingfix.sh b/tests/imtcp_spframingfix.sh
new file mode 100755
index 0000000..3292c54
--- /dev/null
+++ b/tests/imtcp_spframingfix.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ====================================================================================
+echo TEST: \[imptcp_spframingfix.sh\]: test imptcp in regard to Cisco ASA framing fix
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" framingfix.cisco.asa="on")
+
+template(name="outfmt" type="string" string="%rawmsg:6:7%\n")
+ruleset(name="remote") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -B -I ${srcdir}/testsuites/spframingfix.testdata
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+seq_check 0 19
+exit_test
diff --git a/tests/imtuxedoulog_data.sh b/tests/imtuxedoulog_data.sh
new file mode 100755
index 0000000..85eed65
--- /dev/null
+++ b/tests/imtuxedoulog_data.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imtuxedoulog/.libs/imtuxedoulog")
+input(type="imtuxedoulog" ruleset="ruleset"
+ severity="info" facility="local0"
+ maxlinesatonce="100" persiststateinterval="10"
+ maxsubmitatonce="100" tag="domain"
+ ulogbase="./'$RSYSLOG_DYNNAME'")
+ruleset(name="ruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format")
+}
+'
+{
+ echo '164313.15.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree'
+ echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree'
+ echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)'
+ echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1'
+ echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+} > $RSYSLOG_DYNNAME.$(date "+%m%d%y")
+logdate=$(date "+%Y-%m-%d")
+startup
+shutdown_when_empty
+wait_shutdown
+{
+echo '<134>1 '${logdate}'T16:43:13.15 tst-tmsm1 domain ARTIMPP_UDB.40042721.1 - - TRACE:at: } tpfree'
+echo '<134>1 '${logdate}'T16:43:13.151 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003UF^"] TRACE:at: } tpfree'
+echo '<134>1 '${logdate}'T16:43:13.152 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02B003UF^"] TRACE:at: { tpcommit(0x0)'
+echo '<134>1 '${logdate}'T16:43:13.153 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003SF^"] TRACE:at: } tpcommit = 1'
+echo '<134>1 '${logdate}'T16:43:13.154 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003VF^"] TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)'
+} | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/imtuxedoulog_errmsg_no_params-vg.sh b/tests/imtuxedoulog_errmsg_no_params-vg.sh
new file mode 100755
index 0000000..b9effbc
--- /dev/null
+++ b/tests/imtuxedoulog_errmsg_no_params-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/imtuxedoulog_errmsg_no_params.sh
diff --git a/tests/imtuxedoulog_errmsg_no_params.sh b/tests/imtuxedoulog_errmsg_no_params.sh
new file mode 100755
index 0000000..536f5be
--- /dev/null
+++ b/tests/imtuxedoulog_errmsg_no_params.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/imtuxedoulog/.libs/imtuxedoulog")
+
+input(type="imtuxedoulog")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'ulogbase' required but not specified"
+
+exit_test
diff --git a/tests/imudp_thread_hang.sh b/tests/imudp_thread_hang.sh
new file mode 100755
index 0000000..1603d71
--- /dev/null
+++ b/tests/imudp_thread_hang.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# the whole point of this test is just to check that imudp
+# does not block rsyslog termination. This test was introduced
+# after we had a regression where imudp's worker threads were
+# not properly terminated.
+# Copyright 2014 by Rainer Gerhards, licensed under ASL 2.0
+echo \[imudp_thread_hang\]: a situation where imudp caused a hang
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+
+module(load="../plugins/imudp/.libs/imudp" threads="3")
+input(type="imudp" Address="127.0.0.1" Port="20514")
+'
+startup
+./msleep 1000
+shutdown_immediate
+wait_shutdown
+exit_test
diff --git a/tests/imuxsock_ccmiddle.sh b/tests/imuxsock_ccmiddle.sh
new file mode 100755
index 0000000..6e53a8f
--- /dev/null
+++ b/tests/imuxsock_ccmiddle.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# test trailing LF handling in imuxsock
+. ${srcdir:=.}/diag.sh init
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+# send a message with trailing LF
+./syslog_caller -fsyslog_inject-c -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test 1#0112"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_ccmiddle_root.sh b/tests/imuxsock_ccmiddle_root.sh
new file mode 100755
index 0000000..0a8405c
--- /dev/null
+++ b/tests/imuxsock_ccmiddle_root.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# note: we must be root and no other syslogd running in order to
+# carry out this test
+echo \[imuxsock_ccmiddle_root.sh\]: test trailing LF handling in imuxsock
+echo This test must be run as root with no other active syslogd
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imuxsock/.libs/imuxsock
+
+$template outfmt,"%msg:%\n"
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# send a message with trailing LF
+./syslog_caller -fsyslog_inject-c -m1
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+export EXPECTED=" test 1#0112"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_ccmiddle_syssock.sh b/tests/imuxsock_ccmiddle_syssock.sh
new file mode 100755
index 0000000..431628f
--- /dev/null
+++ b/tests/imuxsock_ccmiddle_syssock.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# test trailing LF handling in imuxsock
+# part of rsyslog, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "Solaris: FIX ME"
+ exit 77
+fi
+
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock"
+ SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# send a message with trailing LF
+./syslog_caller -fsyslog_inject-c -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test 1#0112"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_hostname.sh b/tests/imuxsock_hostname.sh
new file mode 100755
index 0000000..6dcbd4e
--- /dev/null
+++ b/tests/imuxsock_hostname.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# test set hostname
+. ${srcdir:=.}/diag.sh init
+
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+global(localHostName="rsyslog-testbench-hostname")
+
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%hostname:%\n")
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# the message itself is irrelevant. The only important thing is
+# there is one
+./syslog_caller -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="rsyslog-testbench-hostname"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_legacy.sh b/tests/imuxsock_legacy.sh
new file mode 100755
index 0000000..e3a224f
--- /dev/null
+++ b/tests/imuxsock_legacy.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This tests legacy syntax.
+# Added 2019-08-13 by Rainer Gerhards; released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+generate_conf
+add_conf '
+$ModLoad ../plugins/imuxsock/.libs/imuxsock
+$OmitLocalLogging on
+
+$AddUnixListenSocket '$RSYSLOG_DYNNAME'-testbench_socket
+
+template(name="outfmt" type="string" string="%msg:%\n")
+*.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+# send a message with trailing LF
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_logger.sh b/tests/imuxsock_logger.sh
new file mode 100755
index 0000000..508676f
--- /dev/null
+++ b/tests/imuxsock_logger.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+*.=notice action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_logger_err.sh b/tests/imuxsock_logger_err.sh
new file mode 100755
index 0000000..3e6c3a3
--- /dev/null
+++ b/tests/imuxsock_logger_err.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# this is primarily a safeguard to ensure the imuxsock tests basically work
+# added 2014-12-04 by Rainer Gerhards, licensed under ASL 2.0
+echo \[imuxsock_logger.sh\]: test imuxsock
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+*.=notice action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# send a message with trailing LF
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket "wrong message"
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log
+if [ $? -eq 0 ]; then
+ echo "imuxsock_logger_err.sh did not report an error where it should!"
+ exit 1
+else
+ echo "all well, we saw the error that we wanted to have"
+fi;
+exit_test
diff --git a/tests/imuxsock_logger_parserchain.sh b/tests/imuxsock_logger_parserchain.sh
new file mode 100755
index 0000000..78cbd81
--- /dev/null
+++ b/tests/imuxsock_logger_parserchain.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright (C) 2015-03-04 by rainer gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket"
+ useSpecialParser="off"
+ parseHostname="on")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+*.=notice action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+logger -d --rfc3164 -u $RSYSLOG_DYNNAME-testbench_socket test
+if [ ! $? -eq 0 ]; then
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+fi;
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_logger_ratelimit.sh b/tests/imuxsock_logger_ratelimit.sh
new file mode 100755
index 0000000..b84a790
--- /dev/null
+++ b/tests/imuxsock_logger_ratelimit.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+echo \[imuxsock_logger_ratelimit.sh\]: test rate limiting with imuxsock
+. ${srcdir:=.}/diag.sh init
+
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+export EXPECTED=" test message nbr 0, severity=6
+ test message nbr 1, severity=6
+ test message nbr 2, severity=6
+ test message nbr 3, severity=6
+ test message nbr 4, severity=6"
+
+for use_special_parser in on off; do
+ echo \[imuxsock_logger_ratelimit.sh\]: test rate limiting with imuxsock with useSpecialParser="$use_special_parser"
+ echo -n >"$RSYSLOG_OUT_LOG"
+ generate_conf
+ add_conf '
+ module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+ input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket"
+ useSpecialParser="'$use_special_parser'"
+ ruleset="testruleset"
+ ratelimit.interval="10"
+ ratelimit.burst="5")
+ template(name="outfmt" type="string" string="%msg:%\n")
+
+ ruleset(name="testruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ }
+ '
+ startup
+
+ ./syslog_caller -m20 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" -s6
+
+ # the sleep below is needed to prevent too-early termination of rsyslogd
+ ./msleep 100
+
+ shutdown_when_empty
+ wait_shutdown
+
+ cmp_exact
+done
+exit_test
diff --git a/tests/imuxsock_logger_root.sh b/tests/imuxsock_logger_root.sh
new file mode 100755
index 0000000..b65d219
--- /dev/null
+++ b/tests/imuxsock_logger_root.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# note: we must be root and no other syslogd running in order to
+# carry out this test.
+echo \[imuxsock_logger_root.sh\]: test trailing LF handling in imuxsock
+echo This test must be run as root with no other active syslogd
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imuxsock/.libs/imuxsock
+
+$template outfmt,"%msg:%\n"
+*.=notice action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# send a message with trailing LF
+logger test
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log
+if [ ! $? -eq 0 ]; then
+echo "imuxsock_logger.sh failed"
+exit 1
+fi;
+exit_test
diff --git a/tests/imuxsock_logger_ruleset.sh b/tests/imuxsock_logger_ruleset.sh
new file mode 100755
index 0000000..d0c07dc
--- /dev/null
+++ b/tests/imuxsock_logger_ruleset.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# test imuxsock with ruleset definition
+# rgerhards, 2016-02-02 released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket"
+ useSpecialParser="off"
+ ruleset="testruleset"
+ parseHostname="on")
+template(name="outfmt" type="string" string="%msg:%\n")
+
+ruleset(name="testruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+# send a message with trailing LF
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_logger_ruleset_ratelimit.sh b/tests/imuxsock_logger_ruleset_ratelimit.sh
new file mode 100755
index 0000000..c13381b
--- /dev/null
+++ b/tests/imuxsock_logger_ruleset_ratelimit.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# rgerhards, 2016-02-18 released under ASL 2.0
+echo \[imuxsock_logger_ruleset_ratelimit.sh\]: test imuxsock with ruleset definition
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket"
+ useSpecialParser="off"
+ ruleset="testruleset"
+ rateLimit.Interval="2"
+ parseHostname="on")
+template(name="outfmt" type="string" string="%msg:%\n")
+
+ruleset(name="testruleset") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+# send a message with trailing LF
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log
+ echo \"$(cat $RSYSLOG_OUT_LOG)\"
+if [ ! $? -eq 0 ]; then
+ echo "imuxsock_logger.sh failed"
+ echo "contents of $RSYSLOG_OUT_LOG:"
+ echo \"$(cat $RSYSLOG_OUT_LOG)\"
+ exit 1
+fi;
+exit_test
diff --git a/tests/imuxsock_logger_syssock.sh b/tests/imuxsock_logger_syssock.sh
new file mode 100755
index 0000000..840b5f8
--- /dev/null
+++ b/tests/imuxsock_logger_syssock.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# test trailing LF handling in imuxsock
+# note: we use the system socket, but assign a different name to
+# it. This is not 100% the same thing as running as root, but it
+# is pretty close to it. -- rgerhards, 201602-19
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock"
+ SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+$template outfmt,"%msg:%\n"
+*.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket test
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_traillf.sh b/tests/imuxsock_traillf.sh
new file mode 100755
index 0000000..5b822c4
--- /dev/null
+++ b/tests/imuxsock_traillf.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+./syslog_caller -fsyslog_inject-l -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
+exit_test
diff --git a/tests/imuxsock_traillf_root.sh b/tests/imuxsock_traillf_root.sh
new file mode 100755
index 0000000..efe5217
--- /dev/null
+++ b/tests/imuxsock_traillf_root.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# note: we must be root and no other syslogd running in order to
+# carry out this test
+echo \[imuxsock_traillf_root.sh\]: test trailing LF handling in imuxsock
+echo This test must be run as root with no other active syslogd
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imuxsock/.libs/imuxsock
+
+$template outfmt,"%msg:%\n"
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+# send a message with trailing LF
+./syslog_caller -fsyslog_inject-l -m1
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_traillf.log
+if [ ! $? -eq 0 ]; then
+echo "imuxsock_traillf_root.sh failed"
+exit 1
+fi;
+exit_test
diff --git a/tests/imuxsock_traillf_syssock.sh b/tests/imuxsock_traillf_syssock.sh
new file mode 100755
index 0000000..4d6e4e4
--- /dev/null
+++ b/tests/imuxsock_traillf_syssock.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test does not work on Solaris"
+
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock"
+ SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg:%\n")
+local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+./syslog_caller -fsyslog_inject-l -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=" test"
+cmp_exact
diff --git a/tests/incltest.sh b/tests/incltest.sh
new file mode 100755
index 0000000..71b230e
--- /dev/null
+++ b/tests/incltest.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/include.conf
+"
+startup
+# 100 messages are enough - the question is if the include is read ;)
+injectmsg 0 100
+shutdown_when_empty
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/incltest_dir.sh b/tests/incltest_dir.sh
new file mode 100755
index 0000000..80da54d
--- /dev/null
+++ b/tests/incltest_dir.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+generate_conf
+env|grep src
+echo ac_top_srcdir: $ac_top_srcdir
+echo FULL ENV:
+env
+echo FS info:
+set -x
+pwd
+echo "srcdir: $srcdir"
+ls -l ${srcdir}/testsuites/incltest.d/
+ls -l ${srcdir}/testsuites
+find ../../../.. -name incltest.d
+set +x
+add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/
+"
+startup
+# 100 messages are enough - the question is if the include is read ;)
+injectmsg 0 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/incltest_dir_empty_wildcard.sh b/tests/incltest_dir_empty_wildcard.sh
new file mode 100755
index 0000000..51e2ac1
--- /dev/null
+++ b/tests/incltest_dir_empty_wildcard.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# This test checks if an empty includeConfig directory causes problems. It
+# should not, as this is a valid situation that by default exists on many
+# distros.
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/*.conf-not-there
+"
+add_conf '$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")'
+startup
+# 100 messages are enough - the question is if the include is read ;)
+injectmsg 0 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/incltest_dir_wildcard.sh b/tests/incltest_dir_wildcard.sh
new file mode 100755
index 0000000..376ab4e
--- /dev/null
+++ b/tests/incltest_dir_wildcard.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf "include(file=\"${srcdir}/testsuites/incltest.d/*.conf\")
+"
+startup
+# 100 messages are enough - the question is if the include is read ;)
+injectmsg 0 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/include-obj-in-if-vg.sh b/tests/include-obj-in-if-vg.sh
new file mode 100755
index 0000000..39c8fb3
--- /dev/null
+++ b/tests/include-obj-in-if-vg.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ include(file="'${srcdir}'/testsuites/include-std-omfile-actio*.conf")
+ continue
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 9
+exit_test
diff --git a/tests/include-obj-outside-control-flow-vg.sh b/tests/include-obj-outside-control-flow-vg.sh
new file mode 100755
index 0000000..4d4eb9f
--- /dev/null
+++ b/tests/include-obj-outside-control-flow-vg.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if not ($msg contains "msgnum:") then {
+ stop
+}
+
+# Note: the point of this test is to have this include outside of
+# a control flow construct -- this the "strange" if above.'
+add_conf "
+include(file=\"${srcdir}/testsuites/include-std-omfile-actio*.conf\")
+"
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 9
+exit_test
diff --git a/tests/include-obj-text-from-file-noexist.sh b/tests/include-obj-text-from-file-noexist.sh
new file mode 100755
index 0000000..cc1b3e6
--- /dev/null
+++ b/tests/include-obj-text-from-file-noexist.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+if $msg contains "msgnum:" then {
+ include(text=`cat '${srcdir}'/testsuites/DOES-NOT-EXIST`)
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex 'file could not be accessed for `cat .*/testsuites/DOES-NOT-EXIST'
+exit_test
diff --git a/tests/include-obj-text-from-file.sh b/tests/include-obj-text-from-file.sh
new file mode 100755
index 0000000..10c613e
--- /dev/null
+++ b/tests/include-obj-text-from-file.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {'
+add_conf "
+ include(text=\`cat ${srcdir}/testsuites/include-std-omfile-action.conf\`)
+}
+"
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+seq_check 0 9
+exit_test
diff --git a/tests/include-obj-text-vg.sh b/tests/include-obj-text-vg.sh
new file mode 100755
index 0000000..fd929b6
--- /dev/null
+++ b/tests/include-obj-text-vg.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+INCLFILE="${srcdir}/testsuites/include-std-omfile-action.conf"
+export CONF_SNIPPET=`cat $INCLFILE`
+printf "\nThis SNIPPET will be included via env var:\n$CONF_SNIPPET\n\nEND SNIPPET\n"
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ include(text=`echo $CONF_SNIPPET`)
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 9
+exit_test
diff --git a/tests/inputfilegen.c b/tests/inputfilegen.c
new file mode 100644
index 0000000..b4e9c2d
--- /dev/null
+++ b/tests/inputfilegen.c
@@ -0,0 +1,234 @@
+/* generate an input file suitable for use by the testbench
+ * Copyright (C) 2018-2022 by Rainer Gerhards and Adiscon GmbH.
+ * Copyright (C) 2016-2018 by Pascal Withopf and Adiscon GmbH.
+ *
+ * usage: ./inputfilegen num-lines > file
+ * -m number of messages
+ * -i start number of message
+ * -d extra data to add (all 'X' after the msgnum)
+ * -s size of file to generate
+ * cannot be used together with -m
+ * size may be slightly smaller in order to be able to write
+ * the last complete line.
+ * -M "message count file" - contains number of messages to be written
+ * This is especially useful with -s, as the testbench otherwise does
+ * not know how to do a seq_check. To keep things flexible, can also be
+ * used with -m (this may aid testbench framework generalization).
+ * -f outputfile
+ * Permits to write data to file "outputfile" instead of stdout. Also
+ * enables support for SIGHUP.
+ * -S sleep time
+ * ms to sleep between sending message bulks (bulks size given by -B)
+ * -B number of messages in bulk
+ * number of messages to send without sleeping as specified in -S.
+ * IGNORED IF -S is not also given!
+ * Part of rsyslog, licensed under ASL 2.0
+ */
+#include "config.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#if defined(_AIX)
+ #include <unistd.h>
+#else
+ #include <getopt.h>
+#endif
+#if defined(__FreeBSD__)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#if defined(HAVE_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+
+#define DEFMSGS 5
+#define NOEXTRADATA -1
+
+static volatile int bHadHUP = 0;
+static void
+hdlr_sighup(int sig)
+{
+ fprintf(stderr, "inputfilegen: had hup, sig %d\n", sig);
+ bHadHUP = 1;
+}
+static void
+sighup_enable()
+{
+ struct sigaction sigAct;
+ memset(&sigAct, 0, sizeof (sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = hdlr_sighup;
+ sigaction(SIGHUP, &sigAct, NULL);
+}
+
+void msleep(const int sleepTime)
+{
+ struct timeval tvSelectTimeout;
+
+ tvSelectTimeout.tv_sec = sleepTime / 1000;
+ tvSelectTimeout.tv_usec = (sleepTime % 1000) * 1000; /* micro seconds */
+ if(select(0, NULL, NULL, NULL, &tvSelectTimeout) == -1) {
+ if(errno != EINTR) {
+ perror("select");
+ exit(1);
+ }
+ }
+}
+
+static FILE *
+open_output(const char *fn)
+{
+ FILE *fh_output = fopen(fn, "w");
+ if(fh_output == NULL) {
+ perror(fn);
+ exit(1);
+ }
+ return fh_output;
+}
+
+int main(int argc, char* argv[])
+{
+ int c, i;
+ long long nmsgs = DEFMSGS;
+ long long nmsgstart = 0;
+ int nfinishedidle = 0;
+ int nchars = NOEXTRADATA;
+ int errflg = 0;
+ long long filesize = -1;
+ char *extradata = NULL;
+ const char *msgcntfile = NULL;
+ const char *outputfile = "-";
+ FILE *fh_output;
+ int sleep_ms = 0; /* How long to sleep between message writes */
+ int sleep_msgs = 0; /* messages to xmit between sleeps (if configured) */
+ int sleep_hubreopen_ms = 5; /* Wait until new file is being reopened, logrotate may need some time */
+ int ctr = 0;
+
+ while((c=getopt(argc, argv, "m:M:i:I:h:d:s:f:S:B:")) != -1) {
+ switch(c) {
+ case 'm':
+ nmsgs = atoi(optarg);
+ break;
+ case 'M':
+ msgcntfile = optarg;
+ break;
+ case 'i':
+ nmsgstart = atoi(optarg);
+ break;
+ case 'I':
+ nfinishedidle = atoi(optarg);
+ break;
+ case 'd':
+ nchars = atoi(optarg);
+ break;
+ case 's':
+ filesize = atoll(optarg);
+ break;
+ case 'S':
+ sleep_ms = atoi(optarg);
+ break;
+ case 'B':
+ sleep_msgs = atoi(optarg);
+ break;
+ case 'h':
+ sleep_hubreopen_ms = atoi(optarg);
+ break;
+ case 'f':
+ outputfile = optarg;
+ sighup_enable();
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ fprintf(stderr, "inputfilegen: Unrecognized option: -%c\n", optopt);
+ errflg++;
+ break;
+ }
+ }
+ if(errflg) {
+ fprintf(stderr, "invalid call\n");
+ exit(2);
+ }
+
+ if(filesize != -1) {
+ const int linesize = (17 + nchars); /* 17 is std line size! */
+ nmsgs = filesize / linesize;
+ fprintf(stderr, "inputfilegen: file size requested %lld, actual %lld with "
+ "%lld lines, %lld bytes less\n",
+ filesize, nmsgs * linesize, nmsgs, filesize - nmsgs * linesize);
+ if(nmsgs > 100000000) {
+ fprintf(stderr, "inputfilegen: number of lines exhaust 8-digit line numbers "
+ "which are standard inside the testbench.\n"
+ "Use -d switch to add extra data (e.g. -d111 for "
+ "128 byte lines or -d47 for 64 byte lines)\n");
+ exit(1);
+ }
+ }
+
+ if(msgcntfile != NULL) {
+ FILE *const fh = fopen(msgcntfile, "w");
+ if(fh == NULL) {
+ perror(msgcntfile);
+ exit(1);
+ }
+ fprintf(fh, "%lld", nmsgs);
+ fclose(fh);
+ }
+
+ if(strcmp(outputfile, "-")) {
+ fh_output = open_output(outputfile);
+ } else {
+ fh_output = stdout;
+ }
+
+ if(nchars != NOEXTRADATA) {
+ extradata = (char *)malloc(nchars + 1);
+ memset(extradata, 'X', nchars);
+ extradata[nchars] = '\0';
+ }
+ for(i = nmsgstart; i < (nmsgs+nmsgstart); ++i) {
+ if( sleep_ms > 0 &&
+ ctr++ >= sleep_msgs) {
+ msleep(sleep_ms);
+ ctr = 0;
+ }
+ if(bHadHUP) {
+ fclose(fh_output);
+ if(sleep_hubreopen_ms > 0) {
+ /* Extra Sleep so logrotate or whatever can take place */
+ msleep(sleep_hubreopen_ms);
+ }
+ fh_output = open_output(outputfile);
+ fprintf(stderr, "inputfilegen: %s reopened\n", outputfile);
+ fprintf(stderr, "inputfilegen: current message number %d\n", i);
+ bHadHUP = 0;
+ }
+ fprintf(fh_output, "msgnum:%8.8d:", i);
+ if(nchars != NOEXTRADATA) {
+ fprintf(fh_output, "%s", extradata);
+ }
+ fprintf(fh_output, "\n");
+ }
+ if (nfinishedidle > 0) {
+ /* Keep process open for nfinishedidle ms */
+ for(int x = 0; x < nfinishedidle; ++x) {
+ if(bHadHUP) {
+ /* Create empty file */
+ fh_output = open_output(outputfile);
+ fclose(fh_output);
+ fprintf(stderr, "inputfilegen: last message number was %d\n", i);
+ bHadHUP = 0;
+ }
+ msleep(1);
+ }
+ }
+
+ free(extradata);
+ return 0;
+}
diff --git a/tests/inputname-imtcp.sh b/tests/inputname-imtcp.sh
new file mode 100755
index 0000000..bd30a1e
--- /dev/null
+++ b/tests/inputname-imtcp.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1" name="l1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="ruleset1" name="l2")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" ruleset="ruleset1" name="l3")
+
+template(name="outfmt" type="string" string="%inputname%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3"
+tcpflood -p $TCPFLOOD_PORT -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\""
+tcpflood -p $TCPFLOOD_PORT2 -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\""
+tcpflood -p $RS_PORT -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='l1
+l2
+l3'
+cmp_exact
+exit_test
diff --git a/tests/internal-errmsg-memleak-vg.sh b/tests/internal-errmsg-memleak-vg.sh
new file mode 100755
index 0000000..adc0c2a
--- /dev/null
+++ b/tests/internal-errmsg-memleak-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This tests a memory leak we have seen when processing internal error
+# message with the settings used in this test. We use imfile as it is
+# easist to reproduce this way. Note that we are only interested in
+# whether or not we have a leak, not any other functionality. Most
+# importantly, we do not care if the error message appears or not. This
+# is because it is not so easy to pick it up from the system log and other
+# tests already cover this scenario.
+# add 2017-05-10 by Rainer Gerhards, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(processInternalMessages="off")
+$RepeatedMsgReduction on # keep this on because many distros have set it
+
+module(load="../plugins/imfile/.libs/imfile") # mode="polling" pollingInterval="1")
+input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="tag1" ruleset="ruleset1")
+
+template(name="tmpl1" type="string" string="%msg%\n")
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="tmpl1")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+'
+startup_vg_waitpid_only
+./msleep 500 # wait a bit so that the error message can be emitted
+shutdown_immediate
+wait_shutdown_vg
+
+exit_test
diff --git a/tests/invalid_nested_include.sh b/tests/invalid_nested_include.sh
new file mode 100755
index 0000000..491ef1e
--- /dev/null
+++ b/tests/invalid_nested_include.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Note: this test tests if we die when recursively include the same
+# file ever again. This is a user error, but we should detect it.
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+echo '$IncludeConfig '${RSYSLOG_DYNNAME}'work-nested.conf
+' > ${RSYSLOG_DYNNAME}work-nested.conf
+add_conf '
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-nested.conf
+template(name="outfmt" type="string" string="%msg%\n")
+if $msg contains "error" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+grep ${RSYSLOG_DYNNAME}work-nested.conf $RSYSLOG_OUT_LOG
+if [ $? -ne 0 ]; then
+ echo "FAIL: $RSYSLOG_OUT_LOG does not contain expected error message on"
+ echo "recursive include file ${RSYSLOG_DYNNAME}work-nested.conf."
+ echo "content is:"
+ echo "......................................................................"
+ cat $RSYSLOG_OUT_LOG
+ echo "......................................................................"
+ error_exit
+fi
+exit_test
diff --git a/tests/journal_print.c b/tests/journal_print.c
new file mode 100644
index 0000000..4336e29
--- /dev/null
+++ b/tests/journal_print.c
@@ -0,0 +1,68 @@
+/* A testing tool that tries to emit message given as argument
+ * to the journal, and, if succceds (at least per journald retcode).
+ * If whole operation is successful there is need to actually check
+ * that message is present in journal (also veryfing journal read perms)
+ *
+ * Retcodes: 0 - success
+ * 1 - wrong arguments (expects exactly one)
+ * 2 - failed to open journal for writing
+ * 3 - failed to actually write message to journal
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2018 Red Hat Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <systemd/sd-journal.h>
+
+int main(int argc, char *argv[])
+{
+ if(argc != 2) {
+ fprintf(stderr, "usage: journal_print \"message\"\n");
+ exit(1);
+ }
+
+ /* First, we need to determine whether journal is running at all */
+ int fd;
+ FILE *log;
+ fd = sd_journal_stream_fd("imjournal_test", LOG_WARNING, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to create journal fd: %s\n", strerror(-fd));
+ exit(2);
+ }
+ log = fdopen(fd, "w");
+ if (!log) {
+ fprintf(stderr, "Failed to create file object: %m\n");
+ close(fd);
+ exit(2);
+ }
+
+ /* Now we can try inserting something */
+ if (fprintf(log, "%s", argv[1]) <= 0) {
+ fprintf(stderr, "Failed to write to journal log: %m\n");
+ close(fd);
+ exit(3);
+ }
+
+ return(0);
+}
diff --git a/tests/json-nonstring.sh b/tests/json-nonstring.sh
new file mode 100755
index 0000000..cda1100
--- /dev/null
+++ b/tests/json-nonstring.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# written 2019-05-10 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="json" type="list" option.jsonf="on") {
+ property(outname="number_0" format="jsonf" name="$!val0" datatype="number")
+ property(outname="bool_0" format="jsonf" name="$!val0" datatype="bool")
+
+ property(outname="empty" format="jsonf" name="$!empty" datatype="auto")
+ property(outname="empty_skip" format="jsonf" name="$!empty" onEmpty="skip")
+ property(outname="empty_null" format="jsonf" name="$!empty" onEmpty="null")
+ property(outname="empty_number" format="jsonf" name="$!empty" datatype="number")
+
+ property(outname="auto_string" format="jsonf" name="$!string" datatype="auto")
+
+ property(outname="auto" format="jsonf" name="$!val" datatype="auto" onEmpty="null")
+ property(outname="number" format="jsonf" name="$!val" datatype="number")
+ property(outname="bool" format="jsonf" name="$!val" datatype="bool")
+ property(outname="string" format="jsonf" name="$!val" datatype="string")
+ property(outname="no_datatype" format="jsonf" name="$!val")
+}
+
+set $!val0 = 0;
+set $!val = 42;
+set $!empty = "";
+set $!string = "1.2.3.4";
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="json")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check '{"number_0":0, "bool_0":false, "empty":"", "empty_null":null, "empty_number":0, "auto_string":"1.2.3.4", "auto":42, "number":42, "bool":true, "string":"42", "no_datatype":"42"}'
+check_not_present 'empty_skip'
+exit_test
diff --git a/tests/json-onempty-at-end.sh b/tests/json-onempty-at-end.sh
new file mode 100755
index 0000000..a03cc20
--- /dev/null
+++ b/tests/json-onempty-at-end.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# written 2019-05-10 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="json" type="list" option.jsonf="on") {
+ property(outname="empty_null" format="jsonf" name="$!empty" onEmpty="null")
+ property(outname="empty_skip" format="jsonf" name="$!empty" onEmpty="skip")
+}
+
+set $!val0 = 0;
+set $!val = 42;
+set $!empty = "";
+set $!string = "1.2.3.4";
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="json")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check '{"empty_null":null}'
+check_not_present 'empty_skip'
+exit_test
diff --git a/tests/json_array_looping-vg.sh b/tests/json_array_looping-vg.sh
new file mode 100755
index 0000000..84cdabe
--- /dev/null
+++ b/tests/json_array_looping-vg.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# added 2016-03-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[json_array_looping-vg.sh\]: basic test for looping over json array with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="garply" type="string" string="garply: %$.garply%\n")
+template(name="grault" type="string" string="grault: %$.grault%\n")
+template(name="prefixed_grault" type="string" string="prefixed_grault: %$.grault%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_grault" queue.type="linkedlist")
+}
+
+foreach ($.quux in $!foo) do {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!bar) do {
+ reset $.grault = $.corge;
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="grault" queue.type="linkedlist" action.copyMsg="on")
+ call prefixed_writer
+ if ($.garply != "") then
+ set $.garply = $.garply & ", ";
+ reset $.garply = $.garply & $.grault!baz;
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply")
+'
+startup_vg
+tcpflood -m 1 -I $srcdir/testsuites/json_array_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+content_check 'quux: abc0'
+content_check 'quux: def1'
+content_check 'quux: ghi2'
+content_check 'quux: { "bar": [ { "baz": "important_msg" }, { "baz": "other_msg" } ] }'
+custom_content_check 'grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'prefixed_grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log
+custom_content_check 'prefixed_grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log
+content_check 'garply: important_msg, other_msg'
+exit_test
diff --git a/tests/json_array_looping.sh b/tests/json_array_looping.sh
new file mode 100755
index 0000000..b2e9790
--- /dev/null
+++ b/tests/json_array_looping.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# added 2014-11-11 by singh.janmejay
+# basic test for looping over json array
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="garply" type="string" string="garply: %$.garply%\n")
+template(name="grault" type="string" string="grault: %$.grault%\n")
+template(name="prefixed_grault" type="string" string="prefixed_grault: %$.grault%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_grault" queue.type="linkedlist")
+}
+
+foreach ($.quux in $!foo) do {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!bar) do {
+ reset $.grault = $.corge;
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="grault" queue.type="linkedlist" action.copyMsg="on")
+ call prefixed_writer
+ if ($.garply != "") then
+ set $.garply = $.garply & ", ";
+ reset $.garply = $.garply & $.grault!baz;
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/json_array_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'quux: abc0'
+content_check 'quux: def1'
+content_check 'quux: ghi2'
+content_check 'quux: { "bar": [ { "baz": "important_msg" }, { "baz": "other_msg" } ] }'
+custom_content_check 'grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'prefixed_grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log
+custom_content_check 'prefixed_grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log
+content_check 'garply: important_msg, other_msg'
+exit_test
diff --git a/tests/json_array_subscripting.sh b/tests/json_array_subscripting.sh
new file mode 100755
index 0000000..2c01d2a
--- /dev/null
+++ b/tests/json_array_subscripting.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2014-11-11 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[json_array_subscripting.sh\]: basic test for json array subscripting
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="msg: %$!foo[1]% | %$.quux% | %$.corge% | %$.grault% | %$!foo[3]!bar[1]!baz%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.quux = $!foo[2];
+set $.corge = $!foo[3]!bar[0]!baz;
+set $.grault = $!foo[3]!bar[1];
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/json_array_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'msg: def1 | ghi2 | important_msg | { "baz": "other_msg" } | other_msg'
+exit_test
diff --git a/tests/json_nonarray_looping.sh b/tests/json_nonarray_looping.sh
new file mode 100755
index 0000000..a38b243
--- /dev/null
+++ b/tests/json_nonarray_looping.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# added 2015-03-02 by singh.janmejay
+# test to assert attempt to iterate upon a non-array json-object fails gracefully
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="garply" type="string" string="garply: %$.garply%\n")
+template(name="grault" type="string" string="grault: %$.grault%\n")
+template(name="prefixed_grault" type="string" string="prefixed_grault: %$.grault%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_grault" queue.type="linkedlist")
+}
+
+foreach ($.quux in $!foo) do {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!bar) do {
+ reset $.grault = $.corge;
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="grault" queue.type="linkedlist" action.copyMsg="on")
+ call prefixed_writer
+ if ($.garply != "") then
+ set $.garply = $.garply & ", ";
+ reset $.garply = $.garply & $.grault!baz;
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/json_nonarray_input
+shutdown_when_empty
+wait_shutdown
+assert_content_missing 'quux'
+exit_test
diff --git a/tests/json_null-vg.sh b/tests/json_null-vg.sh
new file mode 100755
index 0000000..cd6e353
--- /dev/null
+++ b/tests/json_null-vg.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# added 2015-11-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# Note: the aim of this test is to test against misaddressing, so we do
+# not actually check the output
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[json_null.sh\]: test for json containing \"null\" value
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# we must make sure the template contains a reference to the
+# data item with null value
+template(name="outfmt" type="string" string="%$!nope%\n")
+template(name="outfmt-all-json" type="string" string="%$!all-json%\n")
+
+action(type="mmjsonparse")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+if $!nope == "" then
+ action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt-all-json")
+'
+startup_vg
+tcpflood -m 1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: @cee: { \\\"nope\\\": null }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+exit_test
diff --git a/tests/json_null.sh b/tests/json_null.sh
new file mode 100755
index 0000000..a7f9413
--- /dev/null
+++ b/tests/json_null.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2015-11-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# Note: the aim of this test is to test against misaddressing, so we do
+# not actually check the output
+echo ===============================================================================
+echo \[json_null.sh\]: test for json containing \"null\" value
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# we must make sure the template contains a reference to the
+# data item with null value
+template(name="outfmt" type="string" string="%$!nope%\n")
+template(name="outfmt-all-json" type="string" string="%$!all-json%\n")
+
+action(type="mmjsonparse")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+if $!nope == "" then
+ action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt-all-json")
+'
+startup
+tcpflood -m 1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: @cee: { \\\"nope\\\": null }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+exit_test
diff --git a/tests/json_null_array-vg.sh b/tests/json_null_array-vg.sh
new file mode 100755
index 0000000..b8ee197
--- /dev/null
+++ b/tests/json_null_array-vg.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# added 2015-11-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[json_null_array.sh\]: test for json containing \"null\" value
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$.data%\n")
+
+action(type="mmjsonparse")
+foreach ($.data in $!array) do {
+ if not ($.data == "") then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup_vg
+tcpflood -m 1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: @cee: { \\\"array\\\": [0, 1, null, 2, 3, null, 4] }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+seq_check 0 4
+exit_test
diff --git a/tests/json_null_array.sh b/tests/json_null_array.sh
new file mode 100755
index 0000000..8ee8a48
--- /dev/null
+++ b/tests/json_null_array.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2015-11-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[json_null_array.sh\]: test for json containing \"null\" value
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$.data%\n")
+
+action(type="mmjsonparse")
+foreach ($.data in $!array) do {
+ if not ($.data == "") then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m 1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: @cee: { \\\"array\\\": [0, 1, null, 2, 3, null, 4] }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4
+exit_test
diff --git a/tests/json_object_looping-vg.sh b/tests/json_object_looping-vg.sh
new file mode 100755
index 0000000..2ebbefe
--- /dev/null
+++ b/tests/json_object_looping-vg.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# added 2016-03-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[json_object_looping-vg.sh\]: basic test for looping over json object / associative-array with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="garply" type="string" string="garply: %$.garply%\n")
+template(name="corge" type="string" string="corge: key: %$.corge!key% val: %$.corge!value%\n")
+template(name="prefixed_corge" type="string" string="prefixed_corge: %$.corge%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+template(name="modified" type="string" string="new: %$!foo!str4% deleted: %$!foo!str3%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_corge" queue.type="linkedlist")
+}
+
+foreach ($.quux in $!foo) do {
+ if ($.quux!key == "str2") then {
+ set $.quux!random_key = $.quux!key;
+ unset $!foo!str3; #because it is deep copied, the foreach loop will still see str3, but the "modified" action in the bottom will not
+ set $!foo!str4 = "jkl3";
+ }
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!value) do {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="corge" queue.type="linkedlist" action.copyMsg="on")
+ call prefixed_writer
+
+ foreach ($.grault in $.corge!value) do {
+ if ($.garply != "") then
+ set $.garply = $.garply & ", ";
+ set $.garply = $.garply & $.grault!key & "=" & $.grault!value;
+ }
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="modified")
+'
+startup_vg
+tcpflood -m 1 -I $srcdir/testsuites/json_object_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+content_check 'quux: { "key": "str1", "value": "abc0" }'
+content_check 'quux: { "key": "str2", "value": "def1", "random_key": "str2" }'
+content_check 'quux: { "key": "str3", "value": "ghi2" }'
+assert_content_missing 'quux: { "key": "str4", "value": "jkl3" }'
+content_check 'new: jkl3'
+assert_content_missing 'deleted: ghi2'
+content_check 'quux: { "key": "obj", "value": { "bar": { "k1": "important_msg", "k2": "other_msg" } } }'
+custom_content_check 'corge: key: bar val: { "k1": "important_msg", "k2": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'prefixed_corge: { "key": "bar", "value": { "k1": "important_msg", "k2": "other_msg" } }' $RSYSLOG_DYNNAME.out.prefixed.log
+content_check 'garply: k1=important_msg, k2=other_msg'
+exit_test
diff --git a/tests/json_object_looping.sh b/tests/json_object_looping.sh
new file mode 100755
index 0000000..2f0cd03
--- /dev/null
+++ b/tests/json_object_looping.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# added 2016-03-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[json_object_looping.sh\]: basic test for looping over json object / associative-array
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="garply" type="string" string="garply: %$.garply%\n")
+template(name="corge" type="string" string="corge: key: %$.corge!key% val: %$.corge!value%\n")
+template(name="prefixed_corge" type="string" string="prefixed_corge: %$.corge%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+template(name="modified" type="string" string="new: %$!foo!str4% deleted: %$!foo!str3%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_corge" queue.type="linkedlist")
+}
+
+foreach ($.quux in $!foo) do {
+ if ($.quux!key == "str2") then {
+ set $.quux!random_key = $.quux!key;
+ unset $!foo!str3; #because it is deep copied, the foreach loop will still see str3, but the "modified" action in the bottom will not
+ set $!foo!str4 = "jkl3";
+ }
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!value) do {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="corge" queue.type="linkedlist" action.copyMsg="on")
+ call prefixed_writer
+
+ foreach ($.grault in $.corge!value) do {
+ if ($.garply != "") then
+ set $.garply = $.garply & ", ";
+ set $.garply = $.garply & $.grault!key & "=" & $.grault!value;
+ }
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="modified")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/json_object_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'quux: { "key": "str1", "value": "abc0" }'
+content_check 'quux: { "key": "str2", "value": "def1", "random_key": "str2" }'
+content_check 'quux: { "key": "str3", "value": "ghi2" }'
+assert_content_missing 'quux: { "key": "str4", "value": "jkl3" }'
+content_check 'new: jkl3'
+assert_content_missing 'deleted: ghi2'
+content_check 'quux: { "key": "obj", "value": { "bar": { "k1": "important_msg", "k2": "other_msg" } } }'
+custom_content_check 'corge: key: bar val: { "k1": "important_msg", "k2": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log
+custom_content_check 'prefixed_corge: { "key": "bar", "value": { "k1": "important_msg", "k2": "other_msg" } }' $RSYSLOG_DYNNAME.out.prefixed.log
+content_check 'garply: k1=important_msg, k2=other_msg'
+exit_test
diff --git a/tests/json_object_suicide_in_loop-vg.sh b/tests/json_object_suicide_in_loop-vg.sh
new file mode 100755
index 0000000..cccb4cb
--- /dev/null
+++ b/tests/json_object_suicide_in_loop-vg.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# basic test for looping over json object and unsetting it while inside the loop-body
+# added 2016-03-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+generate_conf
+add_conf '
+template(name="corge" type="string" string="corge: key: %$.corge!key% val: %$.corge!value%\n")
+template(name="quux" type="string" string="quux: %$.quux%\n")
+template(name="post_suicide_foo" type="string" string="post_suicide_foo: '
+add_conf "'%\$!foo%'"
+add_conf '\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+set $.garply = "";
+
+foreach ($.quux in $!foo) do {
+ if ($.quux!key == "str2") then {
+ set $.quux!random_key = $.quux!key;
+ unset $!foo; #because it is deep copied, the foreach loop will continue to work, but the action to print "post_suicide_foo" will not see $!foo
+ }
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux")
+ foreach ($.corge in $.quux!value) do {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="corge" queue.type="linkedlist" action.copyMsg="on")
+ }
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="post_suicide_foo")
+'
+startup_vg
+tcpflood -m 1 -I $srcdir/testsuites/json_object_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+content_check 'quux: { "key": "str1", "value": "abc0" }'
+content_check 'quux: { "key": "str2", "value": "def1", "random_key": "str2" }'
+content_check 'quux: { "key": "str3", "value": "ghi2" }'
+assert_content_missing 'quux: { "key": "str4", "value": "jkl3" }'
+content_check 'quux: { "key": "obj", "value": { "bar": { "k1": "important_msg", "k2": "other_msg" } } }'
+custom_content_check 'corge: key: bar val: { "k1": "important_msg", "k2": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log
+content_check "post_suicide_foo: ''"
+exit_test
diff --git a/tests/json_var_case.sh b/tests/json_var_case.sh
new file mode 100755
index 0000000..3cc7e1f
--- /dev/null
+++ b/tests/json_var_case.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# added 2015-11-24 by portant
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===========================================================================================
+echo \[json_var_case.sh\]: test for JSON upper and lower case variables, and leading underscores
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(variables.casesensitive="on")
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# we must make sure the template contains references to the variables
+template(name="outfmt" type="string" string="abc:%$!abc% ABC:%$!ABC% aBc:%$!aBc% _abc:%$!_abc% _ABC:%$!_ABC% _aBc:%$!_aBc%\n" option.casesensitive="on")
+template(name="outfmt-all-json" type="string" string="%$!all-json%\n")
+
+action(type="mmjsonparse")
+set $!_aBc = "7";
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+if $!_aBc != "7" then
+ action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt-all-json")
+'
+startup
+tcpflood -m 1 -M "\"<167>Nov 6 12:34:56 172.0.0.1 test: @cee: { \\\"abc\\\": \\\"1\\\", \\\"ABC\\\": \\\"2\\\", \\\"aBc\\\": \\\"3\\\", \\\"_abc\\\": \\\"4\\\", \\\"_ABC\\\": \\\"5\\\", \\\"_aBc\\\": \\\"6\\\" }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+# NOTE: conf file updates _aBc to "7"
+content_check "abc:1 ABC:2 aBc:3 _abc:4 _ABC:5 _aBc:7"
+exit_test
diff --git a/tests/json_var_cmpr.sh b/tests/json_var_cmpr.sh
new file mode 100755
index 0000000..ee21be8
--- /dev/null
+++ b/tests/json_var_cmpr.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# added 2015-11-24 by portant
+# This file is part of the rsyslog project, released under ASL 2.0
+echo =============================================================================================
+echo \[json_var_case.sh\]: test for referencing local and global variables properly in comparisons
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# we must make sure the template contains references to the variables
+template(name="outfmt" type="string" string="json prop:%$!val% local prop:%$.val% global prop:%$/val%\n")
+
+action(type="mmjsonparse")
+
+set $.val = "123";
+set $.rval = "123";
+if ($.val == $.rval) then {
+ set $.val = "def";
+}
+set $/val = "123";
+set $/rval = "123";
+if ($/val == $/rval) then {
+ set $/val = "ghi";
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -M "\"<167>Nov 6 12:34:56 172.0.0.1 test: @cee: { \\\"val\\\": \\\"abc\\\" }\""
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "json prop:abc local prop:def global prop:ghi"
+exit_test
diff --git a/tests/kafka-selftest.sh b/tests/kafka-selftest.sh
new file mode 100755
index 0000000..9b38fe0
--- /dev/null
+++ b/tests/kafka-selftest.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# added 2018-10-26 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+check_command_available kafkacat
+export KEEP_KAFKA_RUNNING="YES"
+
+export TESTMESSAGES=100000
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+#export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+download_kafka
+stop_zookeeper
+stop_kafka
+
+start_zookeeper
+start_kafka
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+printf 'injecting messages via kafkacat\n'
+injectmsg_kafkacat
+
+# experimental: wait until kafkacat receives everything
+
+timeoutend=10
+timecounter=0
+
+printf 'receiving messages via kafkacat\n'
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s\n' > $RSYSLOG_OUT_LOG
+ count=$(wc -l < ${RSYSLOG_OUT_LOG})
+ if [ $count -eq $TESTMESSAGES ]; then
+ printf '**** wait-kafka-lines success, have %d lines ****\n\n' "$TESTMESSAGES"
+ break
+ else
+ if [ "x$timecounter" == "x$timeoutend" ]; then
+ echo wait-kafka-lines failed, expected $TESTMESSAGES got $count
+ error_exit 1
+ else
+ echo wait-file-lines not yet there, currently $count lines
+ printf '\n'
+ $TESTTOOL_DIR/msleep 1000
+ fi
+ fi
+done
+unset count
+
+#end experimental
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+sed -i 's/ msgnum://' "$RSYSLOG_OUT_LOG"
+seq_check 1 $TESTMESSAGES -d
+
+exit_test
diff --git a/tests/key_dereference_on_uninitialized_variable_space.sh b/tests/key_dereference_on_uninitialized_variable_space.sh
new file mode 100755
index 0000000..d9c6f4e
--- /dev/null
+++ b/tests/key_dereference_on_uninitialized_variable_space.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2015-05-27 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[key_dereference_on_uninitialized_variable_space.sh\]: test to dereference key from a not-yet-created cee or local json-object
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="corge" type="string" string="cee:%$!%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+
+ruleset(name="echo") {
+ if ($!foo == "bar") then {
+ set $!baz = "quux";
+ }
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="corge")
+}
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+call echo
+'
+startup
+tcpflood -m 10
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'cee:'
+exit_test
diff --git a/tests/killrsyslog.sh b/tests/killrsyslog.sh
new file mode 100755
index 0000000..e5f2328
--- /dev/null
+++ b/tests/killrsyslog.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#check if rsyslog instance exists and, if so, kill it
+if [ -e "rsyslog.pid" ]
+then
+ echo rsyslog.pid exists, trying to shut down rsyslogd process `cat rsyslog.pid`.
+ kill -9 `cat rsyslog.pid`
+ sleep 1
+ rm rsyslog.pid
+fi
+if [ -e "rsyslog2.pid" ]
+then
+ echo rsyslog2.pid exists, trying to shut down rsyslogd process `cat rsyslog2.pid`.
+ kill -9 `cat rsyslog2.pid`
+ sleep 1
+ rm rsyslog2.pid
+fi
diff --git a/tests/known_issues.supp b/tests/known_issues.supp
new file mode 100644
index 0000000..9bb8fa3
--- /dev/null
+++ b/tests/known_issues.supp
@@ -0,0 +1,62 @@
+{
+ <dlcose-missing-to-enable-debug-symbol-display_NOT_A_LEAK>
+ Memcheck:Leak
+ ...
+ fun:dlopen*
+ ...
+}
+
+{
+ <CentOS 6 GnuTLS memleak - well some older GnuTLS version actually>
+ Memcheck:Leak
+ fun:malloc
+ fun:CRYPTO_malloc
+ fun:EC_KEY_new
+ fun:EC_KEY_new_by_curve_name
+ fun:SetAuthMode
+ fun:LstnInit
+ fun:create_tcp_socket
+ fun:tcpsrvConstructFinalize
+ fun:activate
+ fun:initAll
+ fun:main
+}
+
+{
+ <pselect() sometimes reports pointing to unadressable byte when all selectors are empty>
+ Memcheck:Param
+ pselect6(sig)
+ fun:pselect
+ fun:wait_timeout
+ fun:mainloop
+ fun:main
+}
+{
+ <librdkafka mem leak - we cannot work around it>
+ Memcheck:Leak
+ ...
+ fun:checkInstance
+ fun:activateCnf
+ fun:tellModulesActivateConfig
+ fun:activate
+ fun:initAll
+}
+{
+ <known issue under Ubuntu 20.04>
+ Helgrind:Misc
+ obj:/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so
+ fun:_dl_fini
+ fun:__run_exit_handlers
+ fun:exit
+ fun:(below main)
+}
+{
+ <known issue under Ubuntu 20.04>
+ Helgrind:Misc
+ obj:/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so
+ obj:/usr/lib/x86_64-linux-gnu/libp11-kit.so.0.3.0
+ fun:_dl_fini
+ fun:__run_exit_handlers
+ fun:exit
+ fun:(below main)
+}
diff --git a/tests/libdbi-asyn.sh b/tests/libdbi-asyn.sh
new file mode 100755
index 0000000..36b319a
--- /dev/null
+++ b/tests/libdbi-asyn.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000 # this test is veeeeery slow, value is a compromise
+generate_conf
+add_conf '
+$ModLoad ../plugins/omlibdbi/.libs/omlibdbi
+
+$ActionQueueType LinkedList
+$ActionQueueTimeoutEnqueue 15000
+
+$ActionLibdbiDriver mysql
+$ActionLibdbiHost 127.0.0.1
+$ActionLibdbiUserName rsyslog
+$ActionLibdbiPassword testbench
+$ActionLibdbiDBName '$RSYSLOG_DYNNAME'
+:msg, contains, "msgnum:" {
+ :omlibdbi:
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.syncfile")
+}
+'
+mysql_prep_for_test
+startup
+injectmsg
+wait_file_lines $RSYSLOG_DYNNAME.syncfile $NUMMESSAGES 2500
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+exit_test
diff --git a/tests/libdbi-basic-vg.sh b/tests/libdbi-basic-vg.sh
new file mode 100755
index 0000000..0ff4a88
--- /dev/null
+++ b/tests/libdbi-basic-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+# this test is currently not included in the testbench as libdbi
+# itself seems to have a memory leak
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/libdbi-basic.sh
diff --git a/tests/libdbi-basic.sh b/tests/libdbi-basic.sh
new file mode 100755
index 0000000..d6bf1fa
--- /dev/null
+++ b/tests/libdbi-basic.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# basic test for libdbi-basic functionality via mysql
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+generate_conf
+add_conf '
+$ModLoad ../plugins/omlibdbi/.libs/omlibdbi
+$ActionLibdbiDriver mysql
+$ActionLibdbiHost 127.0.0.1
+$ActionLibdbiUserName rsyslog
+$ActionLibdbiPassword testbench
+$ActionLibdbiDBName '$RSYSLOG_DYNNAME'
+:msg, contains, "msgnum:" :omlibdbi:
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+exit_test
diff --git a/tests/libmaxmindb.supp b/tests/libmaxmindb.supp
new file mode 100644
index 0000000..71e056a
--- /dev/null
+++ b/tests/libmaxmindb.supp
@@ -0,0 +1,57 @@
+{
+ libmaxmindb_known_leak_(fixed_in_later_versions)
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:MMDB_open
+ fun:createWrkrInstance
+ fun:actionCheckAndCreateWrkrInstance
+ fun:actionPrepare
+ fun:actionProcessMessage
+ fun:processMsgMain
+ fun:doSubmitToActionQ
+ fun:execAct
+ fun:scriptExec
+ fun:processBatch
+ fun:msgConsumer
+}
+{
+ another_incarnation_of_the_same
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:populate_languages_metadata
+ fun:read_metadata
+ fun:MMDB_open
+ fun:createWrkrInstance
+ fun:actionCheckAndCreateWrkrInstance
+ fun:actionPrepare
+ fun:actionProcessMessage
+ fun:processMsgMain
+ fun:doSubmitToActionQ
+ fun:execAct
+ fun:scriptExec
+ fun:processBatch
+ fun:msgConsumer
+ fun:ConsumerReg
+ fun:wtiWorker
+}
+{
+ yet_another_incarnation
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:MMDB_open
+ fun:open_mmdb
+ fun:createWrkrInstance
+ fun:actionCheckAndCreateWrkrInstance
+ fun:actionPrepare
+ fun:actionProcessMessage
+ fun:processMsgMain
+ fun:doSubmitToActionQ
+ fun:execAct
+ fun:scriptExec
+ fun:processBatch
+ fun:msgConsumer
+ fun:ConsumerReg
+} \ No newline at end of file
diff --git a/tests/linkedlistqueue.sh b/tests/linkedlistqueue.sh
new file mode 100755
index 0000000..25d49be
--- /dev/null
+++ b/tests/linkedlistqueue.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Test for Linkedlist queue mode
+# added 2009-05-20 by rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=40000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+# set spool locations and switch queue to disk-only mode
+$MainMsgQueueType LinkedList
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/linux_localtime_r.supp b/tests/linux_localtime_r.supp
new file mode 100644
index 0000000..1cd3e1b
--- /dev/null
+++ b/tests/linux_localtime_r.supp
@@ -0,0 +1,126 @@
+{
+ linux-localtime_r-apparently-modifies-TZ
+ Helgrind:Race
+ ...
+ fun:__tz_convert
+ fun:timeval2syslogTime
+ ...
+}
+
+{
+ linux-localtime_r-apparently-modifies-TZ
+ Helgrind:Race
+ fun:strlen
+ fun:__tzset_parse_tz
+ fun:__tzfile_compute
+ fun:__tz_convert
+ ...
+}
+
+{
+ linux-localtime_r-apparently-modifies-TZ
+ Helgrind:Race
+ ...
+ fun:__tzstring
+ fun:__tzfile_compute
+ fun:__tz_convert
+ ...
+}
+
+{
+ linux-localtime_r-apparently-modifies-TZ-2
+ Helgrind:Race
+ fun:__GI_strcmp
+ fun:__tzfile_compute
+ fun:__tz_convert
+ ...
+}
+
+{
+ CENTOS_6_only_report
+ Helgrind:Misc
+ fun:pthread_cond_destroy_WRK
+ fun:pthread_cond_destroy@*
+ fun:modExit
+ fun:modUnlinkAndDestroy
+ fun:Release
+ fun:ReleaseObj
+ fun:modExit
+ ...
+}
+{
+ CENTOS_6_only_report
+ Helgrind:Misc
+ fun:pthread_cond_destroy_WRK
+ fun:pthread_cond_destroy@*
+ fun:qqueueDestruct
+ fun:actionDestruct
+ fun:cnfstmtDestruct
+ fun:cnfstmtDestructLst
+ fun:cnfstmtDestruct
+ fun:cnfstmtDestructLst
+ fun:rulesetDestruct
+ fun:rulesetDestructForLinkedList
+ fun:llDestroyElt
+ fun:llDestroy
+}
+{
+ CENTOS_6_only_report
+ Helgrind:Misc
+ fun:pthread_cond_destroy_WRK
+ fun:pthread_cond_destroy@*
+ fun:modExit
+ fun:modUnlinkAndDestroy
+ fun:modUnloadAndDestructAll
+ fun:main
+}
+{
+ CENTOS_7_github_rsyslog_issue_2012
+ Helgrind:Race
+ fun:GetLocalHostIP
+ fun:logmsgInternalSubmit
+ fun:logmsgInternal
+ fun:doLogMsg.constprop.0
+ fun:LogMsg
+ fun:wtpAdviseMaxWorkers
+ fun:qqueueAdviseMaxWorkers
+ fun:qqueueMultiEnqObjNonDirect
+ fun:multiSubmitMsg2
+ fun:ratelimitAddMsg
+ fun:enqLine
+ fun:pollFileReal
+ fun:pollFile
+ fun:doPolling
+ fun:runInput
+ fun:thrdStarter
+}
+{
+ CENTOS_7_github_rsyslog_issue_2012
+ Helgrind:Race
+ fun:AddRef
+ fun:MsgSetRcvFromIP
+ fun:logmsgInternalSubmit
+ fun:logmsgInternal
+ fun:doLogMsg.constprop.0
+ fun:LogMsg
+ fun:wtpAdviseMaxWorkers
+ fun:qqueueAdviseMaxWorkers
+ fun:qqueueMultiEnqObjNonDirect
+ fun:multiSubmitMsg2
+ fun:ratelimitAddMsg
+ fun:enqLine
+ fun:pollFileReal
+ fun:pollFile
+ fun:doPolling
+ fun:runInput
+}
+{
+ CENTOS_7_github_rsyslog_issue_2012
+ Helgrind:Race
+ fun:thrdDestruct
+ fun:llDestroyElt
+ fun:llDestroy
+ fun:thrdTerminateAll
+ fun:deinitAll
+ fun:main
+}
diff --git a/tests/loadbalance.sh b/tests/loadbalance.sh
new file mode 100755
index 0000000..06a2a47
--- /dev/null
+++ b/tests/loadbalance.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# a test to check load balancing via global variables
+# note: for simplicity, we use omfile output; in practice this will usually
+# be some kind of network output, e.g. omfwd or omrelp. From the method's
+# point of view, the actual output does not matter.
+# added by Rainer Gerhards 2020-01-03
+# part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000 # sufficient for our needs
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+# note: do NOT initialize $/lbcntr - it starts at "", which becomes 0 after cnum()
+if $msg contains "msgnum" then {
+ set $.actnbr = cnum($/lbcntr) % 4;
+ if $.actnbr == 0 then {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'0.log" template="outfmt")
+ } else if $.actnbr == 1 then {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'1.log" template="outfmt")
+ } else if $.actnbr == 2 then {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'2.log" template="outfmt")
+ } else {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'3.log" template="outfmt")
+ }
+ set $/lbcntr = cnum($/lbcntr) + 1;
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check # validate test result as such
+export SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}0.log"
+seq_check 0 $((NUMMESSAGES -4)) -i 4
+printf 'Checking file 1\n'
+export SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}1.log"
+printf 'Checking file 2\n'
+export SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}2.log"
+printf 'Checking file 3\n'
+export SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}3.log"
+exit_test
diff --git a/tests/localvar-concurrency.sh b/tests/localvar-concurrency.sh
new file mode 100755
index 0000000..6d564f0
--- /dev/null
+++ b/tests/localvar-concurrency.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Test concurrency of message variables
+# Added 2015-11-03 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[localvar-concurrency.sh\]: testing concurrency of local variables
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$.tree!here!nbr%\n")
+
+if $msg contains "msgnum:" then {
+ set $.tree!here!nbr = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt"
+ queue.type="linkedList")
+
+ set $.tree!here!save = $.tree!here!nbr;
+ set $.tree!here!nbr = "";
+ set $.tree!here!nbr = $.tree!here!save;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+sleep 1
+tcpflood -m500000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 499999
+exit_test
diff --git a/tests/lookup_table-hup-backgrounded.sh b/tests/lookup_table-hup-backgrounded.sh
new file mode 100755
index 0000000..bc43c45
--- /dev/null
+++ b/tests/lookup_table-hup-backgrounded.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# test for lookup-table and HUP based reloading of it
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_TSAN
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on")
+
+template(name="outfmt" type="string" string="- %msg% %$.lkp%\n")
+
+set $.lkp = lookup("xlate", $msg);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+export RSTB_DAEMONIZE="YES"
+startup
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 10
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: foo_latest"
+content_check "msgnum:00000001: quux"
+content_check "msgnum:00000002: baz_latest"
+content_check "msgnum:00000003: foo_latest"
+content_check "msgnum:00000004: foo_latest"
+content_check "msgnum:00000005: baz_latest"
+content_check "msgnum:00000006: foo_latest"
+content_check "msgnum:00000007: baz_latest"
+content_check "msgnum:00000008: baz_latest"
+content_check "msgnum:00000009: quux"
+exit_test
diff --git a/tests/lookup_table-vg.sh b/tests/lookup_table-vg.sh
new file mode 100755
index 0000000..2aad430
--- /dev/null
+++ b/tests/lookup_table-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/lookup_table.sh
diff --git a/tests/lookup_table.sh b/tests/lookup_table.sh
new file mode 100755
index 0000000..fe47903
--- /dev/null
+++ b/tests/lookup_table.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# test for lookup-table and HUP based reloading of it
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on")
+
+template(name="outfmt" type="string" string="- %msg% %$.lkp%\n")
+
+set $.lkp = lookup("xlate", $msg);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 10
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: foo_latest"
+content_check "msgnum:00000001: quux"
+content_check "msgnum:00000002: baz_latest"
+content_check "msgnum:00000003: foo_latest"
+content_check "msgnum:00000004: foo_latest"
+content_check "msgnum:00000005: baz_latest"
+content_check "msgnum:00000006: foo_latest"
+content_check "msgnum:00000007: baz_latest"
+content_check "msgnum:00000008: baz_latest"
+content_check "msgnum:00000009: quux"
+exit_test
diff --git a/tests/lookup_table_bad_configs-vg.sh b/tests/lookup_table_bad_configs-vg.sh
new file mode 100755
index 0000000..e6d3b25
--- /dev/null
+++ b/tests/lookup_table_bad_configs-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-12-02 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/lookup_table_bad_configs.sh
diff --git a/tests/lookup_table_bad_configs.sh b/tests/lookup_table_bad_configs.sh
new file mode 100755
index 0000000..7d20c9c
--- /dev/null
+++ b/tests/lookup_table_bad_configs.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+# added 2015-12-02 by singh.janmejay
+# test for sparse-array lookup-table and HUP based reloading of it
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl")
+
+template(name="outfmt" type="string" string="%msg% %$.lkp%\n")
+
+set $.num = field($msg, 58, 2);
+set $.lkp = lookup("xlate", $.num);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+echo "empty file..."
+cp -f $srcdir/testsuites/xlate_empty_file.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+injectmsg 0 5
+wait_queueempty
+
+echo "table with invalid-json..."
+cp -f $srcdir/testsuites/xlate_invalid_json.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+
+echo "string-table with no index-key..."
+cp -f $srcdir/testsuites/xlate_string_no_index.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+
+echo "array-table with no index-key..."
+cp -f $srcdir/testsuites/xlate_array_no_index.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+
+echo "sparse-array-table with no index-key..."
+cp -f $srcdir/testsuites/xlate_sparseArray_no_index.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+
+echo "string-table with no value..."
+cp -f $srcdir/testsuites/xlate_string_no_value.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "array-table with no value..."
+cp -f $srcdir/testsuites/xlate_array_no_value.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "sparse-array-table with no value..."
+cp -f $srcdir/testsuites/xlate_sparseArray_no_value.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "incorrect-version in lookup-table..."
+cp -f $srcdir/testsuites/xlate_incorrect_version.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+
+echo "incorrect-type in lookup-table..."
+cp -f $srcdir/testsuites/xlate_incorrect_type.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "foo"
+assert_content_missing "bar"
+assert_content_missing "baz"
+
+echo "string-table with no table..."
+cp -f $srcdir/testsuites/xlate_string_no_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "array-table with no table..."
+cp -f $srcdir/testsuites/xlate_array_no_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "sparse-array-table with no table..."
+cp -f $srcdir/testsuites/xlate_sparseArray_no_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 5
+wait_queueempty
+assert_content_missing "baz"
+
+echo "string-table with empty table..."
+cp -f $srcdir/testsuites/xlate_string_empty_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 2
+wait_queueempty
+content_check "msgnum:00000000: baz_str"
+content_check "msgnum:00000001: baz_str"
+
+echo "array-table with empty table..."
+cp -f $srcdir/testsuites/xlate_array_empty_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 2
+wait_queueempty
+content_check "msgnum:00000000: baz_arr"
+content_check "msgnum:00000001: baz_arr"
+
+echo "sparse-array-table with empty table..."
+cp -f $srcdir/testsuites/xlate_sparseArray_empty_table.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 2
+wait_queueempty
+content_check "msgnum:00000000: baz_sparse_arr"
+content_check "msgnum:00000001: baz_sparse_arr"
+
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+exit_test
diff --git a/tests/lookup_table_no_hup_reload-vg.sh b/tests/lookup_table_no_hup_reload-vg.sh
new file mode 100755
index 0000000..e895828
--- /dev/null
+++ b/tests/lookup_table_no_hup_reload-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/lookup_table_no_hup_reload.sh
diff --git a/tests/lookup_table_no_hup_reload.sh b/tests/lookup_table_no_hup_reload.sh
new file mode 100755
index 0000000..4dc1963
--- /dev/null
+++ b/tests/lookup_table_no_hup_reload.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# test for lookup-table with HUP based reloading disabled
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="off")
+
+template(name="outfmt" type="string" string="- %msg% %$.lkp%\n")
+
+set $.lkp = lookup("xlate", $msg);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+assert_content_missing "foo_new"
+assert_content_missing "bar_new"
+assert_content_missing "baz"
+exit_test
diff --git a/tests/lookup_table_rscript_reload-vg.sh b/tests/lookup_table_rscript_reload-vg.sh
new file mode 100755
index 0000000..7fd0532
--- /dev/null
+++ b/tests/lookup_table_rscript_reload-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-12-18 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/lookup_table_rscript_reload.sh
diff --git a/tests/lookup_table_rscript_reload.sh b/tests/lookup_table_rscript_reload.sh
new file mode 100755
index 0000000..fbc6417
--- /dev/null
+++ b/tests/lookup_table_rscript_reload.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# test for lookup-table reload by rscript-fn
+# added 2015-12-18 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl")
+
+template(name="outfmt" type="string" string="- %msg% %$.lkp%\n")
+
+set $.lkp = lookup("xlate", $msg);
+
+if ($msg == " msgnum:00000002:") then {
+ reload_lookup_table("xlate", "reload_failed");
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+# the last message ..002 should cause successful lookup-table reload
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+rm -f $RSYSLOG_DYNNAME.xlate.lkp_tbl # this should lead to unsuccessful reload
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+injectmsg 0 2
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: foo_latest"
+content_check "msgnum:00000001: quux"
+content_check "msgnum:00000002: baz_latest"
+content_check "msgnum:00000000: reload_failed"
+content_check "msgnum:00000000: reload_failed"
+
+exit_test
diff --git a/tests/lookup_table_rscript_reload_without_stub-vg.sh b/tests/lookup_table_rscript_reload_without_stub-vg.sh
new file mode 100755
index 0000000..8a65d28
--- /dev/null
+++ b/tests/lookup_table_rscript_reload_without_stub-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-12-18 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/lookup_table_rscript_reload_without_stub.sh
diff --git a/tests/lookup_table_rscript_reload_without_stub.sh b/tests/lookup_table_rscript_reload_without_stub.sh
new file mode 100755
index 0000000..209873d
--- /dev/null
+++ b/tests/lookup_table_rscript_reload_without_stub.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# test for lookup-table reload by rscript-stmt without stub
+# added 2015-12-18 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl")
+
+template(name="outfmt" type="string" string="- %msg% %$.lkp%\n")
+
+set $.lkp = lookup("xlate", $msg);
+
+if ($msg == " msgnum:00000002:") then {
+ reload_lookup_table("xlate")
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup
+# the last message ..002 should cause successful lookup-table reload
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+content_check "msgnum:00000000: foo_old"
+content_check "msgnum:00000001: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: bar_new"
+content_check "msgnum:00000002: baz"
+rm -f $RSYSLOG_DYNNAME.xlate.lkp_tbl # this should lead to unsuccessful reload
+injectmsg 0 3
+await_lookup_table_reload
+wait_queueempty
+injectmsg 0 2
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check_with_count "msgnum:00000000: foo_latest" 2
+content_check_with_count "msgnum:00000001: quux" 2
+content_check_with_count "msgnum:00000002: baz_latest" 1
+
+exit_test
diff --git a/tests/mainq_actq_DA.sh b/tests/mainq_actq_DA.sh
new file mode 100755
index 0000000..88f4a72
--- /dev/null
+++ b/tests/mainq_actq_DA.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Test to check that mainq and actionq can be disk assisted without
+# any problems. This was created to reproduce a segfault issue:
+# https://github.com/rsyslog/rsyslog/issues/3681
+# added 2019-06-03 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10 # we just need a handful - we primarily test startup
+generate_conf
+add_conf '
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.fileName="main" queue.type="LinkedList")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:"
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ queue.type="linkedList" queue.fileName="action")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/mangle_qi.c b/tests/mangle_qi.c
new file mode 100644
index 0000000..3775c96
--- /dev/null
+++ b/tests/mangle_qi.c
@@ -0,0 +1,113 @@
+/* rsyslog testbench tool to mangle .qi files
+ *
+ * Copyright (C) 2016 by Rainer Gerhards
+ * Released uner ASL 2.0
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+
+static int debug = 0;
+
+void
+usage(void)
+{
+ fprintf(stderr, "mangle_qi -d -q <.qi-file>\n"
+ "-d enables debug messages\n");
+ exit(1);
+}
+
+void
+processQI(FILE *const __restrict__ qi)
+{
+ char lnbuf[4096];
+ char propname[64];
+ int rectype;
+ int length;
+ int queuesize;
+ int i;
+ int c;
+ fgets(lnbuf, sizeof(lnbuf), qi);
+ fputs(lnbuf, stdout);
+ /* we now read the queue size line */
+ /* note: this is quick and dirty, no error checks
+ * are done!
+ */
+ fgetc(qi); /* skip '+' */
+ for(i = 0 ; (c = fgetc(qi)) != ':' ; ++i) {
+ propname[i] = c;
+ }
+ propname[i] = '\0';
+ if(strcmp(propname, "iQueueSize")) {
+ fprintf(stderr, ".qi file format unknown: line 2 does "
+ "not contain iQueueSize property, instead '%s'\n",
+ propname);
+ exit(1);
+ }
+
+ rectype = 0;
+ for(c = fgetc(qi) ; isdigit(c) ; c = fgetc(qi))
+ rectype = rectype * 10 + c - '0';
+
+ length = 0;
+ for(c = fgetc(qi) ; isdigit(c) ; c = fgetc(qi))
+ length = length * 10 + c - '0';
+
+ queuesize = 0;
+ for(c = fgetc(qi) ; isdigit(c) ; c = fgetc(qi))
+ queuesize = queuesize * 10 + c - '0';
+
+ int maxval_for_length = 10;
+ for(i = 1 ; i < length ; ++i)
+ maxval_for_length *= 10; /* simulate int-exp() */
+
+ if(debug) {
+ fprintf(stderr, "rectype: %d\n", rectype);
+ fprintf(stderr, "length: %d\n", length);
+ fprintf(stderr, "queuesize: %d\n", queuesize);
+ fprintf(stderr, "maxval_for_length: %d\n", maxval_for_length);
+ }
+
+ queuesize += 1; /* fake invalid queue size */
+ if(queuesize > maxval_for_length)
+ ++length;
+
+ /* ready to go, write mangled queue size */
+ printf("+%s:%d:%d:%d:", propname, rectype, length, queuesize);
+ /* copy rest of file */
+ while((c = fgetc(qi)) != EOF)
+ putchar(c);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *qifile = NULL;
+ FILE *qi;
+ int opt;
+ while((opt = getopt(argc, argv, "dq:")) != -1) {
+ switch (opt) {
+ case 'q': qifile = optarg;
+ break;
+ case 'd': debug = 1;
+ break;
+ default: usage();
+ break;
+ }
+ }
+
+ if(qifile == NULL) {
+ fprintf(stderr, "ERROR: -q option MUST be specified\n");
+ usage();
+ }
+
+ if((qi = fopen(qifile, "r")) == NULL) {
+ perror(qifile);
+ exit(1);
+ }
+ processQI(qi);
+ return 0;
+}
diff --git a/tests/mangle_qi_usage_output.sh b/tests/mangle_qi_usage_output.sh
new file mode 100755
index 0000000..4da5912
--- /dev/null
+++ b/tests/mangle_qi_usage_output.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# add 2018-11-13 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+./mangle_qi &> $RSYSLOG_DYNNAME.output
+grep -q -- "-q option MUST be specified" $RSYSLOG_DYNNAME.output
+
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/manyptcp.sh b/tests/manyptcp.sh
new file mode 100755
index 0000000..6734f86
--- /dev/null
+++ b/tests/manyptcp.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# test imptcp with large connection count
+# test many concurrent tcp connections
+# released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=40000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$MaxOpenFiles 2000
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+tcpflood -c1000 -m$NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/manytcp-too-few-tls-vg.sh b/tests/manytcp-too-few-tls-vg.sh
new file mode 100755
index 0000000..b03fdb9
--- /dev/null
+++ b/tests/manytcp-too-few-tls-vg.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test does not work on FreeBSD"
+export NUMMESSAGES=40000 # we unfortunately need many messages as we have many connections
+export TB_TEST_MAX_RUNTIME=1800 # this test is VERY slow, so we need to override max runtime
+generate_conf
+add_conf '
+$MaxOpenFiles 200
+global(
+ defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem"
+ defaultNetstreamDriver="gtls"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100"
+ streamDriver.mode="1" streamDriver.authMode="anon")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup_vg
+# the config file specifies exactly 1100 connections
+tcpflood -c1000 -m$NUMMESSAGES -Ttls -x$srcdir/testsuites/x.509/ca.pem -Z$srcdir/testsuites/x.509/client-cert.pem -z$srcdir/testsuites/x.509/client-key.pem
+# the sleep below is needed to prevent too-early termination of the tcp listener
+# note: this must not be precise, as message loss is acceptable
+sleep 5
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+# we do not do a seq check, as of the design of this test some messages
+# will be lost. So there is no point in checking if all were received. The
+# point is that we look at the valgrind result, to make sure we do not
+# have a mem leak in those error cases (we had in the past, thus the test
+# to prevent that in the future).
+exit_test
diff --git a/tests/manytcp.sh b/tests/manytcp.sh
new file mode 100755
index 0000000..07c0e22
--- /dev/null
+++ b/tests/manytcp.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# test many concurrent tcp connections
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+skip_platform "SunOS" "timing on connection establishment is different on solaris and makes this test fail"
+export NUMMESSAGES=40000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$MaxOpenFiles 2100
+module(load="../plugins/imtcp/.libs/imtcp" maxSessions="2100")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+# we first send a single message so that the output file is opened. Otherwise, we may
+# use up all file handles for tcp connections and so the output file could eventually
+# not be opened. 2019-03-18 rgerhards
+tcpflood -m1
+tcpflood -c-2000 -i1 -m $((NUMMESSAGES - 1 ))
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/miniamqpsrvr.c b/tests/miniamqpsrvr.c
new file mode 100644
index 0000000..5aedacd
--- /dev/null
+++ b/tests/miniamqpsrvr.c
@@ -0,0 +1,658 @@
+/* a very simplistic tcp receiver for the rsyslog testbench.
+ *
+ * Author Philippe Duveau
+ *
+ * This file is contribution of the rsyslog project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+#if defined(__FreeBSD__)
+#include <netinet/in.h>
+#endif
+
+#include "rsyslog.h"
+
+
+#include <amqp.h>
+#include <amqp_framing.h>
+
+#define AMQP_STARTING ((uchar)0x10)
+#define AMQP_STOP ((uchar)0x00)
+
+#define AMQP_BEHAVIOR_STANDARD 1
+#define AMQP_BEHAVIOR_NOEXCH 2
+#define AMQP_BEHAVIOR_DECEXCH 3
+#define AMQP_BEHAVIOR_BADEXCH 4
+
+uchar connection_start[487] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDF, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x00, 0x01,
+ 0xBA, 0x0C, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x46, 0x00,
+ 0x00, 0x00, 0xC7, 0x12, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x73, 0x68, 0x65, 0x72, 0x5F, 0x63, 0x6F,
+ 0x6E, 0x66, 0x69, 0x72, 0x6D, 0x73, 0x74, 0x01, 0x1A, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6E, 0x67,
+ 0x65, 0x5F, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x5F, 0x62, 0x69, 0x6E, 0x64, 0x69,
+ 0x6E, 0x67, 0x73, 0x74, 0x01, 0x0A, 0x62, 0x61, 0x73, 0x69, 0x63, 0x2E, 0x6E, 0x61, 0x63, 0x6B,
+ 0x74, 0x01, 0x16, 0x63, 0x6F, 0x6E, 0x73, 0x75, 0x6D, 0x65, 0x72, 0x5F, 0x63, 0x61, 0x6E, 0x63,
+ 0x65, 0x6C, 0x5F, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x74, 0x01, 0x12, 0x63, 0x6F, 0x6E, 0x6E,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x74, 0x01,
+ 0x13, 0x63, 0x6F, 0x6E, 0x73, 0x75, 0x6D, 0x65, 0x72, 0x5F, 0x70, 0x72, 0x69, 0x6F, 0x72, 0x69,
+ 0x74, 0x69, 0x65, 0x73, 0x74, 0x01, 0x1C, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x75, 0x72, 0x65, 0x5F, 0x63, 0x6C,
+ 0x6F, 0x73, 0x65, 0x74, 0x01, 0x10, 0x70, 0x65, 0x72, 0x5F, 0x63, 0x6F, 0x6E, 0x73, 0x75, 0x6D,
+ 0x65, 0x72, 0x5F, 0x71, 0x6F, 0x73, 0x74, 0x01, 0x0F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5F,
+ 0x72, 0x65, 0x70, 0x6C, 0x79, 0x5F, 0x74, 0x6F, 0x74, 0x01, 0x0C, 0x63, 0x6C, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x53, 0x00, 0x00, 0x00, 0x0D, 0x72, 0x61, 0x62, 0x62,
+ 0x69, 0x74, 0x40, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x09, 0x63, 0x6F, 0x70, 0x79, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x53, 0x00, 0x00, 0x00, 0x2E, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x2D, 0x32, 0x30, 0x31, 0x36, 0x20,
+ 0x50, 0x69, 0x76, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x0B, 0x69, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x53, 0x00, 0x00, 0x00, 0x35, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x64, 0x20,
+ 0x75, 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4D, 0x50, 0x4C, 0x2E, 0x20, 0x20,
+ 0x53, 0x65, 0x65, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x72,
+ 0x61, 0x62, 0x62, 0x69, 0x74, 0x6D, 0x71, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x08, 0x70, 0x6C, 0x61,
+ 0x74, 0x66, 0x6F, 0x72, 0x6D, 0x53, 0x00, 0x00, 0x00, 0x0A, 0x45, 0x72, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x4F, 0x54, 0x50, 0x07, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x53, 0x00, 0x00, 0x00,
+ 0x08, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x4D, 0x51, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F,
+ 0x6E, 0x53, 0x00, 0x00, 0x00, 0x05, 0x33, 0x2E, 0x36, 0x2E, 0x32, 0x00, 0x00, 0x00, 0x0E, 0x41,
+ 0x4D, 0x51, 0x50, 0x4C, 0x41, 0x49, 0x4E, 0x20, 0x50, 0x4C, 0x41, 0x49, 0x4E, 0x00, 0x00, 0x00,
+ 0x05, 0x65, 0x6E, 0x5F, 0x55, 0x53, 0xCE
+};
+
+static uchar connection_tune[20] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x3C, 0xCE
+};
+
+static uchar connection_open_ok[13] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x29, 0x00, 0xCE
+};
+
+static uchar channel_open_ok[16] = {
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0xCE
+};
+
+static uchar exchange_declare_ok[12] = {
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0x00, 0x0B, 0xCE
+};
+
+static uchar channel_close_ok[12] = {
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x29, 0xCE
+};
+
+static uchar connection_close_ok[12] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x33, 0xCE
+};
+
+static uchar channel_close_ok_on_badexch[148] = {
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x14, 0x00, 0x28, 0x01,
+ 0x96, 0x81, 0x50, 0x52, 0x45, 0x43, 0x4F, 0x4E, 0x44, 0x49, 0x54, 0x49,
+ 0x4F, 0x4E, 0x5F, 0x46, 0x41, 0x49, 0x4C, 0x45, 0x44, 0x20, 0x2D, 0x20,
+ 0x69, 0x6E, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6C, 0x65, 0x6E, 0x74,
+ 0x20, 0x61, 0x72, 0x67, 0x20, 0x27, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6C,
+ 0x65, 0x27, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x65, 0x78, 0x63, 0x68, 0x61,
+ 0x6E, 0x67, 0x65, 0x20, 0x27, 0x69, 0x6E, 0x27, 0x20, 0x69, 0x6E, 0x20,
+ 0x76, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x27, 0x2F, 0x6D, 0x65, 0x74, 0x72,
+ 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x27, 0x3A, 0x20, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x27, 0x66, 0x61, 0x6C, 0x73, 0x65,
+ 0x27, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x27, 0x74, 0x72, 0x75, 0x65, 0x27, 0x00,
+ 0x28, 0x00, 0x0A, 0xCE
+};
+
+typedef struct {
+ uchar type;
+ ushort ch;
+ uint32_t method;
+ uint16_t header_flags;
+ size_t datalen;
+ size_t framelen;
+ uchar *data;
+} amqp_frame_type_t;
+
+#define DBGPRINTF0(f, ...) if (debug>0) { \
+ struct timeval dbgtv; \
+ gettimeofday(&dbgtv, NULL);\
+ fprintf(stderr, "%02d.%03d " f, (int)(dbgtv.tv_sec % 60), \
+ (int)(dbgtv.tv_usec/1000), __VA_ARGS__); \
+}
+#define DBGPRINTF1(f, ...) if (debug>0) { \
+ struct timeval dbgtv; \
+ gettimeofday(&dbgtv, NULL);\
+ dbgtv.tv_sec -= dbgtv_base.tv_sec; \
+ dbgtv.tv_usec -= dbgtv_base.tv_usec; \
+ if (dbgtv.tv_usec < 0) { \
+ dbgtv.tv_usec += 1000000; \
+ dbgtv.tv_sec--; \
+ } \
+ fprintf(stderr, "%02d.%03d " f, (int)(dbgtv.tv_sec % 60), \
+ (int)(dbgtv.tv_usec/1000), __VA_ARGS__); \
+}
+#define DBGPRINTF2(f, ...) if (debug==2) { \
+ struct timeval dbgtv; \
+ gettimeofday(&dbgtv, NULL);\
+ dbgtv.tv_sec -= dbgtv_base.tv_sec; \
+ dbgtv.tv_usec -= dbgtv_base.tv_usec; \
+ if (dbgtv.tv_usec < 0) { \
+ dbgtv.tv_usec += 1000000; \
+ dbgtv.tv_sec--; \
+ } \
+ fprintf(stderr, "%02d.%03d " f, (int)(dbgtv.tv_sec % 60), \
+ (int)(dbgtv.tv_usec/1000), __VA_ARGS__); \
+}
+
+static struct timeval dbgtv_base;
+static int server_behaviors = 0;
+static int behaviors;
+static int wait_after_accept = 200; /* milliseconds */
+static char *outfile = NULL;
+static int debug = 1;
+
+FILE* fpout = NULL;
+
+static ATTR_NORETURN void
+errout(const char *reason, int server)
+{
+ char txt[256];
+ snprintf(txt,256,"%s server %d", reason, server);
+ perror(txt);
+ if (fpout && fpout != stdout) { fclose(fpout); fpout = NULL; }
+ if (outfile) unlink(outfile);
+ exit(1);
+}
+
+static ATTR_NORETURN void
+usage(void)
+{
+ fprintf(stderr, "usage: minirmqsrvr -f outfile [-b behaviour] "
+ "[-t keep_alive_max] [-w delay_after_fail] [-d]\n");
+ exit (1);
+}
+
+/* Those three functions are "endianess" insensitive */
+static uint16_t buf2uint16(uchar*b) {
+ return ((uint16_t)b[0]) << 8 | ((uint16_t)b[1]);
+}
+
+static uint32_t buf2uint32(uchar*b) {
+ return ((uint32_t)b[0]) << 24 | ((uint32_t)b[1]) << 16 | ((uint32_t)b[2]) << 8 | ((uint32_t)b[3]);
+}
+
+static uint64_t buf2uint64(uchar*b) {
+ return ((uint64_t)b[0]) << 56 | ((uint64_t)b[1]) << 48 | ((uint64_t)b[2]) << 40 | ((uint64_t)b[3]) << 32
+ | ((uint64_t)b[4]) << 24 | ((uint64_t)b[5]) << 16 | ((uint64_t)b[6]) << 8 | ((uint64_t)b[7]);
+}
+
+
+static char AMQP091[8] = { 'A', 'M', 'Q', 'P', 0x00, 0x00, 0x09, 0x01 };
+
+static int
+decode_frame_type(uchar *buf, amqp_frame_type_t *frame, size_t nread) {
+ if (nread == 8){
+ if (memcmp(buf, AMQP091, sizeof(AMQP091)))
+ return -1;
+ frame->framelen = 8;
+ frame->type = AMQP_STARTING;
+ frame->ch = 0;
+ return 0;
+ }
+ frame->type = buf[0];
+ frame->ch = buf2uint16(buf+1);
+ frame->datalen = buf2uint32(buf+3);
+ frame->framelen = frame->datalen + 8;
+ frame->method = buf2uint32(buf+7);
+ switch (frame->type) {
+ case AMQP_FRAME_BODY:
+ frame->data = buf + 7;
+ break;
+ default:
+ frame->data = buf + 11;
+ }
+ return 0;
+}
+
+static ssize_t
+amqp_write(int fdc, uchar *buf, size_t blen, unsigned short channel) {
+ buf[1] = (char) (channel >> 8);
+ buf[2] = (char) (channel & 0xFF);
+ return write(fdc, buf, blen);
+}
+
+static uchar *
+amqpFieldUint64(uint64_t *d, uchar *s) {
+ *d = buf2uint64(s);
+ return s + 8;
+}
+
+static uchar *
+amqpFieldUint32(uint32_t *d, uchar *s) {
+ *d = buf2uint32(s);
+ return s + 4;
+}
+
+static uchar *
+amqpFieldUint16(uint16_t *d, uchar *s) {
+ *d = buf2uint16(s);
+ return s + 2;
+}
+
+static uchar *
+amqpFieldLenFprintf(const char *pfx, uchar *s, uint32_t len) {
+ if (fpout)
+ fprintf(fpout, "%s%.*s", pfx, (int)len, (char*)s);
+ return s + len;
+}
+
+static uchar *
+amqpFieldFprintf(const char *pfx, uchar *s) {
+ uint32_t len = *s++;
+ return amqpFieldLenFprintf(pfx, s, len);
+}
+
+static uchar *
+amqpHeaderFprintf(uchar *s, uint32_t *size) {
+ uint32_t len;
+ uchar *p = amqpFieldFprintf(", ", s);
+ p++; /* value type */
+ p = amqpFieldUint32(&len, p);
+ *size -= (p - s) + len;
+ return amqpFieldLenFprintf(":", p, len);
+}
+
+static void
+amqp_srvr(int port, int srvr, int fds, int piperead, int pipewrite)
+{
+ uchar wrkBuf[8192], *p;
+ size_t nRead = 0, bsize = 0;
+ ssize_t nSent;
+ amqp_frame_type_t frame;
+ uint64_t body_ui64 = 0;
+ uint32_t props_header_size;
+ uint16_t props_flags;
+ int my_behaviour;
+ struct timeval tv;
+ fd_set rfds;
+ int nfds = ((piperead > fds)? piperead : fds) + 1;
+
+ int fdc;
+
+ my_behaviour = behaviors & 0x000F;
+ behaviors = behaviors >> 4; /* for next server */;
+
+ if(listen(fds, 0) != 0) errout("listen", port);
+
+ DBGPRINTF1("Server AMQP %d on port %d started\n", srvr, port);
+
+ tv.tv_sec = 120;
+ tv.tv_usec = 0;
+ FD_ZERO(&rfds);
+ FD_SET(fds, &rfds);
+ if (piperead > 0)
+ FD_SET(piperead, &rfds);
+
+ if (select(nfds,&rfds,NULL,NULL, &tv) == 0) {
+ exit(1);
+ }
+
+ if (piperead > 0 && FD_ISSET(piperead, &rfds)) {
+ char c;
+ int l = read(piperead, &c, 1);
+ if (l == 1) {
+ my_behaviour = behaviors & 0x000F;
+ if (my_behaviour != 0) {
+ DBGPRINTF1("Server AMQP %d on port %d switch behaviour", srvr, port);
+ } else {
+ DBGPRINTF1("Server AMQP %d on port %d leaving", srvr, port);
+ if (fpout && fpout != stdout) { fclose(fpout); fpout = NULL; }
+ exit(1);
+ }
+ }
+ }
+
+ fdc = accept(fds, NULL, NULL);
+
+ if (pipewrite > 0)
+ nSent = write(pipewrite, "N", 1);
+
+ close(fds);
+ fds = -1;
+
+ /* this let the os understand that the port is closed */
+ usleep(1000 * wait_after_accept);
+
+ frame.type = AMQP_STARTING;
+
+ while(fdc > 0) {
+ nSent = 0;
+ ssize_t rd = 0;
+ if (nRead < 12) {
+ rd = read(fdc, wrkBuf + nRead, sizeof(wrkBuf) - nRead);
+ if (rd <= 0) {
+ DBGPRINTF1("Server AMQP %d on port %d disconnected\n", srvr, port);
+ close(fdc);
+ fdc = 0;
+ break;
+ }else {
+ nRead += (size_t)rd;
+ }
+ }
+
+ if (decode_frame_type(wrkBuf, &frame, nRead)) {
+ DBGPRINTF1("Server AMQP %d on port %d killed : bad protocol\n", srvr, port);
+ close(fdc);
+ fdc = 0;
+ break;
+ }
+ if (rd > 4)
+ DBGPRINTF2("Server received : %zd\n", rd);
+
+ switch (frame.type) {
+
+ case AMQP_STARTING: /* starting handshake */
+
+ DBGPRINTF1("Server AMQP %d on port %d type %d connected\n", srvr, port, my_behaviour);
+ DBGPRINTF2("Server %d connection.start\n", srvr);
+ nSent = amqp_write(fdc, connection_start, sizeof(connection_start), frame.ch);
+ break;
+
+ case AMQP_FRAME_METHOD:
+
+ DBGPRINTF2("Server %d method : 0x%X\n", srvr, frame.method);
+
+ switch (frame.method) {
+
+ case AMQP_CONNECTION_START_OK_METHOD:
+
+ DBGPRINTF2("Server %d connection.tune\n", srvr);
+ nSent = amqp_write(fdc, connection_tune, sizeof(connection_tune), frame.ch);
+ break;
+
+ case AMQP_CONNECTION_TUNE_OK_METHOD:
+
+ DBGPRINTF2("Client %d connection.tune-ok\n", srvr);
+ nSent = 0;
+ break;
+
+ case AMQP_CONNECTION_OPEN_METHOD:
+
+ nSent = amqp_write(fdc, connection_open_ok,
+ sizeof(connection_open_ok), frame.ch);
+ DBGPRINTF2("Server %d connection.open\n", srvr);
+ break;
+
+ case AMQP_CHANNEL_OPEN_METHOD:
+
+ nSent = amqp_write(fdc, channel_open_ok,
+ sizeof(channel_open_ok), frame.ch);
+ DBGPRINTF2("Server %d channel.open\n", srvr);
+ if (my_behaviour == AMQP_BEHAVIOR_NOEXCH) {
+ close(fdc);
+ DBGPRINTF1("Server AMQP %d on port %d stopped\n", srvr, port);
+ fdc = 0;
+ frame.type = 0;
+ }
+ break;
+
+ case AMQP_EXCHANGE_DECLARE_METHOD:
+
+ if (my_behaviour == AMQP_BEHAVIOR_BADEXCH) {
+ nSent = amqp_write(fdc, channel_close_ok_on_badexch,
+ sizeof(channel_close_ok_on_badexch), frame.ch);
+ }else{
+ nSent = amqp_write(fdc, exchange_declare_ok,
+ sizeof(exchange_declare_ok), frame.ch);
+ }
+ DBGPRINTF2("Server %d exchange.declare\n", srvr);
+ if (my_behaviour == AMQP_BEHAVIOR_DECEXCH) {
+ close(fdc);
+ DBGPRINTF1("Server AMQP %d on port %d stopped\n", srvr, port);
+ fdc = 0;
+ frame.type = 0;
+ }
+ break;
+
+ case AMQP_CHANNEL_CLOSE_METHOD:
+
+ nSent = amqp_write(fdc, channel_close_ok,
+ sizeof(channel_close_ok), frame.ch);
+ DBGPRINTF2("Server %d channel.close\n", srvr);
+ break;
+
+ case AMQP_CONNECTION_CLOSE_METHOD:
+
+ nSent = amqp_write(fdc, connection_close_ok,
+ sizeof(connection_close_ok), frame.ch);
+ DBGPRINTF2("Server %d connection.close\n", srvr);
+ break;
+
+ case AMQP_BASIC_PUBLISH_METHOD:
+
+ p = amqpFieldFprintf("Exchange:", frame.data + 2);
+ amqpFieldFprintf(", routing-key:", p);
+ break;
+
+ default:
+
+ nSent = 0;
+ }
+ break;
+
+ case AMQP_FRAME_HEADER:
+
+ DBGPRINTF2("Server %d HEADERS\n", srvr);
+ p = amqpFieldUint64(&body_ui64, frame.data);
+ bsize = (size_t)body_ui64;
+ p = amqpFieldUint16(&props_flags, p);
+ if (props_flags & AMQP_BASIC_CONTENT_TYPE_FLAG) {
+ p = amqpFieldFprintf(", content-type:", p);
+ }
+ if (props_flags & AMQP_BASIC_HEADERS_FLAG) {
+ p = amqpFieldUint32(&props_header_size, p);
+ while (props_header_size) {
+ p = amqpHeaderFprintf(p, &props_header_size);
+ }
+ }
+ if (props_flags & AMQP_BASIC_DELIVERY_MODE_FLAG) {
+ if (fpout)
+ fprintf(fpout, ", delivery-mode:%s", (*p++)?"transient":"persistent");
+ }
+ if (props_flags & AMQP_BASIC_EXPIRATION_FLAG) {
+ p = amqpFieldFprintf(", expiration:", p);
+ }
+ if (props_flags & AMQP_BASIC_TIMESTAMP_FLAG) {
+ if (fpout)
+ fprintf(fpout, ", timestamp:OK");
+ p += sizeof(uint64_t);
+ }
+ if (props_flags & AMQP_BASIC_APP_ID_FLAG) {
+ amqpFieldFprintf(", app-id:", p);
+ }
+ if (fpout)
+ fprintf(fpout, ", msg:");
+ break;
+
+ case AMQP_FRAME_BODY:
+
+ DBGPRINTF2("Server %d Body size left : %zu, received : %zu\n",
+ srvr, bsize, frame.datalen);
+ bsize -= frame.datalen;
+ if (fpout) {
+ fprintf(fpout, "%.*s", (int)frame.datalen, frame.data);
+ if (frame.data[frame.datalen-1] != '\n')
+ fprintf(fpout, "\n");
+ fflush(fpout);
+ }
+ break;
+
+ default:
+
+ DBGPRINTF1("Server %d unsupported frame type %d\n", srvr, frame.type);
+ close(fdc);
+ fdc = 0;
+ frame.type = 0;
+ frame.framelen = 0;
+ } /* switch (frame.type) */
+
+ nRead -= frame.framelen;
+ if (nRead>0)
+ memmove(wrkBuf, wrkBuf + frame.framelen, nRead);
+
+ if (nSent < 0) {
+ close(fdc);
+ fdc = 0;
+ }
+ } /* while(fdc) */
+ DBGPRINTF2("Leaving thread %d\n", srvr);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int port[2], fds[2], i, opt, nb_port = 1;
+ int pipeS1toS2[2] = { -1, -1 };
+ int pipeS2toS1[2] = { -1, -1 };
+ int pipeRead[2], pipeWrite[2];
+
+
+ struct sockaddr_in srvAddr[2];
+ unsigned int addrLen = sizeof(struct sockaddr_in), len;
+ pid_t pid[2];
+
+ fpout = stdout;
+
+ while((opt = getopt(argc, argv, "f:b:w:d")) != -1) {
+ switch (opt) {
+ case 'w':
+ wait_after_accept = atoi(optarg);
+ break;
+ case 'd':
+ debug = 2;
+ break;
+ case 'b':
+ server_behaviors = atoi(optarg);
+ break;
+ case 'f':
+ if(strcmp(optarg, "-")) {
+ outfile = optarg;
+ fpout = fopen(optarg, "w");
+ if(fpout == NULL){
+ fprintf(stderr, "file %s could not be created\n", outfile);
+ exit(1);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "invalid option '%c' or value missing - terminating...\n", opt);
+ usage();
+ break;
+ }
+ }
+
+ switch (server_behaviors) {
+ case 0:
+ behaviors = AMQP_BEHAVIOR_STANDARD;
+ nb_port = 1;
+ break;
+ case 1: /* two standard servers get message successfully */
+ behaviors = AMQP_BEHAVIOR_STANDARD;
+ nb_port = 2;
+ break;
+ case 2: /* 2 servers first server which disconnect after after open channel : no declare exchange */
+ behaviors = AMQP_BEHAVIOR_NOEXCH | AMQP_BEHAVIOR_STANDARD << 4;
+ nb_port = 2;
+ break;
+ case 3: /* 2 servers first server which disconnect after declare exchange*/
+ behaviors = AMQP_BEHAVIOR_DECEXCH | AMQP_BEHAVIOR_STANDARD << 4;
+ nb_port = 2;
+ break;
+ case 4: /* one server with bad exchange declare */
+ behaviors = AMQP_BEHAVIOR_BADEXCH;
+ nb_port = 1;
+ break;
+ default:
+ fprintf(stderr,"Invalid behavior");
+ exit(1);
+ }
+
+ gettimeofday(&dbgtv_base, NULL);
+
+ port[0] = port[1] = -1;
+
+ if (nb_port == 2) {
+ if(pipe(pipeS1toS2) == -1 || pipe(pipeS2toS1) == -1) {
+ fprintf(stderr, "Pipe failed !");
+ exit(1);
+ }
+ }
+
+ pipeRead[0] = pipeS2toS1[0];
+ pipeWrite[0] = pipeS1toS2[1];
+
+ pipeRead[1] = pipeS1toS2[0];
+ pipeWrite[1] = pipeS2toS1[1];
+
+ for (i = 0; i < nb_port; i++) {
+ fds[i] = socket(AF_INET, SOCK_STREAM, 0);
+ srvAddr[i].sin_family = AF_INET;
+ srvAddr[i].sin_addr.s_addr = INADDR_ANY;
+ srvAddr[i].sin_port = 0;
+ if(bind(fds[i], (struct sockaddr *)&srvAddr[i], addrLen) != 0)
+ errout("bind", 1);
+ len = addrLen;
+ if (getsockname(fds[i], (struct sockaddr *)&srvAddr[i], &len) == -1)
+ errout("bind", i+1);
+ if ((port[i] = ntohs(srvAddr[i].sin_port)) <= 0)
+ errout("get port", i+1);
+ }
+
+ for (i = 0; i < nb_port; i++) {
+ if ((pid[i] = fork()) == -1) {
+ fprintf(stderr, "Fork failed !");
+ exit(1);
+ }
+ if (pid[i] == 0) {
+ /* this is the child */
+ if (fds[1-i] > 0) close(fds[1-i]);
+ amqp_srvr(port[i], i+1, fds[i], pipeRead[i], pipeWrite[i]);
+
+ if (fpout && fpout != stdout) fclose(fpout);
+
+ DBGPRINTF2("%s\n","Leaving server");
+ return 0;
+ }
+ }
+
+ if (nb_port==2)
+ printf("export AMQPSRVRPID1=%ld AMQPSRVRPID2=%ld PORT_AMQP1=%d PORT_AMQP2=%d",
+ (long)pid[0], (long)pid[1], port[0], port[1]);
+ else
+ printf("export AMQPSRVRPID1=%ld PORT_AMQP1=%d",
+ (long)pid[0], port[0]);
+ return 0;
+}
diff --git a/tests/minitcpsrv_usage_output.sh b/tests/minitcpsrv_usage_output.sh
new file mode 100755
index 0000000..279a608
--- /dev/null
+++ b/tests/minitcpsrv_usage_output.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# add 2018-11-15 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+./minitcpsrv&> $RSYSLOG_DYNNAME.output
+grep -q -- "-t parameter missing" $RSYSLOG_DYNNAME.output
+
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/minitcpsrvr.c b/tests/minitcpsrvr.c
new file mode 100644
index 0000000..7d0f719
--- /dev/null
+++ b/tests/minitcpsrvr.c
@@ -0,0 +1,131 @@
+/* a very simplistic tcp receiver for the rsyslog testbench.
+ *
+ * Copyright 2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#if defined(__FreeBSD__)
+#include <netinet/in.h>
+#endif
+
+static void
+errout(char *reason)
+{
+ perror(reason);
+ exit(1);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: minitcpsrvr -t ip-addr -p port -f outfile\n");
+ exit (1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fds;
+ int fdc;
+ int fdf = -1;
+ struct sockaddr_in srvAddr;
+ struct sockaddr_in cliAddr;
+ unsigned int srvAddrLen;
+ unsigned int cliAddrLen;
+ char wrkBuf[4096];
+ ssize_t nRead;
+ int opt;
+ int sleeptime = 0;
+ char *targetIP = NULL;
+ int targetPort = -1;
+
+ while((opt = getopt(argc, argv, "t:p:f:s:")) != -1) {
+ switch (opt) {
+ case 's':
+ sleeptime = atoi(optarg);
+ break;
+ case 't':
+ targetIP = optarg;
+ break;
+ case 'p':
+ targetPort = atoi(optarg);
+ break;
+ case 'f':
+ if(!strcmp(optarg, "-")) {
+ fdf = 1;
+ } else {
+ fdf = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
+ if(fdf == -1) errout(argv[3]);
+ }
+ break;
+ default:
+ fprintf(stderr, "invalid option '%c' or value missing - terminating...\n", opt);
+ usage();
+ break;
+ }
+ }
+
+ if(targetIP == NULL) {
+ fprintf(stderr, "-t parameter missing -- terminating\n");
+ usage();
+ }
+ if(targetPort == -1) {
+ fprintf(stderr, "-p parameter missing -- terminating\n");
+ usage();
+ }
+ if(fdf == -1) {
+ fprintf(stderr, "-f parameter missing -- terminating\n");
+ usage();
+ }
+
+ if(sleeptime) {
+ printf("minitcpsrv: deliberate sleep of %d seconds\n", sleeptime);
+ sleep(sleeptime);
+ printf("minitcpsrv: end sleep\n");
+ }
+
+ fds = socket(AF_INET, SOCK_STREAM, 0);
+ srvAddr.sin_family = AF_INET;
+ srvAddr.sin_addr.s_addr = inet_addr(targetIP);
+ srvAddr.sin_port = htons(targetPort);
+ srvAddrLen = sizeof(srvAddr);
+ if(bind(fds, (struct sockaddr *)&srvAddr, srvAddrLen) != 0)
+ errout("bind");
+ if(listen(fds, 20) != 0) errout("listen");
+ cliAddrLen = sizeof(cliAddr);
+
+ fdc = accept(fds, (struct sockaddr *)&cliAddr, &cliAddrLen);
+ while(1) {
+ nRead = read(fdc, wrkBuf, sizeof(wrkBuf));
+ if(nRead == 0) break;
+ if(write(fdf, wrkBuf, nRead) != nRead)
+ errout("write");
+ }
+ /* let the OS do the cleanup */
+ fprintf(stderr, "minitcpsrv terminates itself\n");
+ return 0;
+}
diff --git a/tests/mmanon_both_modes_compatible.sh b/tests/mmanon_both_modes_compatible.sh
new file mode 100755
index 0000000..f54477b
--- /dev/null
+++ b/tests/mmanon_both_modes_compatible.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.enable="on" ipv4.mode="zero" ipv4.bits="32" ipv6.bits="128" ipv6.anonmode="zero" ipv6.enable="on")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 space 61:34:ad::7:F
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: abf:3:002::500F:ce 1.1.1.9\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 0:0:0:0:0:0:0:0
+ 0.0.0.0 space 0:0:0:0:0:0:0:0
+ 0.0.0.0
+ 0:0:0:0:0:0:0:0 0.0.0.0'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_ipv6_port.sh b/tests/mmanon_ipv6_port.sh
new file mode 100755
index 0000000..8ebbd6c
--- /dev/null
+++ b/tests/mmanon_ipv6_port.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.anonmode="zero")
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f:4024:d991:ec2e:4922
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f:4024:d991:ec2e
+<129>Mar 10 01:00:00 172.20.245.8 tag: [1a00:c820:1180:c84c:ad3f:4024:d991:ec2e]:4922
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f::d991:ec2e:4922
+<129>Mar 10 01:00:00 172.20.245.8 tag: [1a00:c820:1180:c84c:ad3f::d991:ec2e]:4922
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f::d991:ec2e:49225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:4922:4922:c84c:ad3f::d991:ec2e:49225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:4922:1180:c84c:ad3f::d991:4922:49225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:49225:c84c:ad3f::d991:ec2e:49225\""
+
+# see this github comment on limits of IP address detection:
+# https://github.com/rsyslog/rsyslog/issues/4856#issuecomment-1108445473
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ 1a00:c820:0:0:0:0:0:0:4922
+ 1a00:c820:0:0:0:0:0:0
+ [1a00:c820:0:0:0:0:0:0]:4922
+ 1a00:c820:1180:0:0:0:0:0:0
+ [1a00:c820:0:0:0:0:0:0]:4922
+ 1a00:c820:0:0:0:0:0:0:49225
+ 1a00:4922:0:0:0:0:0:0:49225
+ 1a00:4922:0:0:0:0:0:0:49225
+ 1a00:c820:49225:c84c:0:0:0:0:0:0:49225'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_random_128_ipv6.sh b/tests/mmanon_random_128_ipv6.sh
new file mode 100755
index 0000000..453bfb2
--- /dev/null
+++ b/tests/mmanon_random_128_ipv6.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+template(name="filename" type="string" string="'${RSYSLOG_DYNNAME}.'%syslogtag%.log")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.anonmode="random" ipv6.bits="128" ipv6.enable="on")
+ action(type="omfile" dynafile="filename" template="outfmt")
+}'
+
+echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 33:45:DDD::4
+<129>Mar 10 01:00:00 172.20.245.8 file2 ::
+<129>Mar 10 01:00:00 172.20.245.8 file3 72:8374:adc7:47FF::43:0:1AFE
+<129>Mar 10 01:00:00 172.20.245.8 file4 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 file5 72:8374:adc7:47FF::43:0:1AFE\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 33:45:DDD::4' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ error_exit 1
+fi;
+
+echo ' ::' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ error_exit 1
+fi;
+
+echo ' 72:8374:adc7:47FF::43:0:1AFE' | cmp - ${RSYSLOG_DYNNAME}.file3.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file3.log is:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ error_exit 1
+fi;
+
+echo ' FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file3.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file3.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+rm -f ${RSYSLOG_DYNNAME}.*.log
+exit_test
diff --git a/tests/mmanon_random_32_ipv4.sh b/tests/mmanon_random_32_ipv4.sh
new file mode 100755
index 0000000..2479df9
--- /dev/null
+++ b/tests/mmanon_random_32_ipv4.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+template(name="filename" type="string" string="'${RSYSLOG_DYNNAME}'.%syslogtag%.log")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.mode="random" ipv4.bits="32")
+ action(type="omfile" dynafile="filename" template="outfmt")
+}'
+
+echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 file2 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 file3 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 file4 111.1.1.8.
+<129>Mar 10 01:00:00 172.20.245.8 file5 172.0.234.255\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 1.1.1.8' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ error_exit 1
+fi;
+
+echo ' 0.0.0.0' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ error_exit 1
+fi;
+
+echo ' 172.0.234.255' | cmp - ${RSYSLOG_DYNNAME}.file3.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file3.log is:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ error_exit 1
+fi;
+
+echo ' 111.1.1.8.' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file3.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file3.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+rm -f ${RSYSLOG_DYNNAME}.*.log
+exit_test
diff --git a/tests/mmanon_random_cons_128_ipembedded.sh b/tests/mmanon_random_cons_128_ipembedded.sh
new file mode 100755
index 0000000..75d7019
--- /dev/null
+++ b/tests/mmanon_random_cons_128_ipembedded.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+template(name="filename" type="string" string="'${RSYSLOG_DYNNAME}'.%syslogtag%.log")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.enable="off" ipv4.enable="off" embeddedipv4.anonmode="random-consistent" embeddedipv4.bits="128")
+ action(type="omfile" dynafile="filename" template="outfmt")
+}'
+
+echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 33:45:DDD::4.123.123.3
+<129>Mar 10 01:00:00 172.20.245.8 file2 ::0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 file6 ::0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 file3 72:8374:adc7:47FF::43:0.34.225.1
+<129>Mar 10 01:00:00 172.20.245.8 file4 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255
+<129>Mar 10 01:00:00 172.20.245.8 file5 72:8374:adc7:47FF::43:0.34.225.1\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 33:45:DDD::4' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ error_exit 1
+fi;
+
+echo ' ::' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ error_exit 1
+fi;
+
+echo ' 72:8374:adc7:47FF::43:0:1AFE' | cmp - ${RSYSLOG_DYNNAME}.file3.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file3.log is:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ error_exit 1
+fi;
+
+echo ' FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file3.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file3.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file2.log ${RSYSLOG_DYNNAME}.file6.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file1.log and ${RSYSLOG_DYNNAME}.file6.log are:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ cat ${RSYSLOG_DYNNAME}.file6.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file4.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file4.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+rm -f ${RSYSLOG_DYNNAME}.*.log
+exit_test
diff --git a/tests/mmanon_random_cons_128_ipv6.sh b/tests/mmanon_random_cons_128_ipv6.sh
new file mode 100755
index 0000000..3deddbe
--- /dev/null
+++ b/tests/mmanon_random_cons_128_ipv6.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+template(name="filename" type="string" string="'${RSYSLOG_DYNNAME}'.%syslogtag%.log")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.anonmode="random-consistent" ipv6.bits="128")
+ action(type="omfile" dynafile="filename" template="outfmt")
+}'
+
+echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 33:45:DDD::4
+<129>Mar 10 01:00:00 172.20.245.8 file2 ::
+<129>Mar 10 01:00:00 172.20.245.8 file6 ::
+<129>Mar 10 01:00:00 172.20.245.8 file3 72:8374:adc7:47FF::43:0:1AFE
+<129>Mar 10 01:00:00 172.20.245.8 file4 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 file5 72:8374:adc7:47FF::43:0:1AFE\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 33:45:DDD::4' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ error_exit 1
+fi;
+
+echo ' ::' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ error_exit 1
+fi;
+
+echo ' 72:8374:adc7:47FF::43:0:1AFE' | cmp - ${RSYSLOG_DYNNAME}.file3.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file3.log is:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ error_exit 1
+fi;
+
+echo ' FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file3.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file3.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file2.log ${RSYSLOG_DYNNAME}.file6.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file1.log and ${RSYSLOG_DYNNAME}.file6.log are:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ cat ${RSYSLOG_DYNNAME}.file6.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file4.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file4.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+rm -f ${RSYSLOG_DYNNAME}.*.log
+exit_test
diff --git a/tests/mmanon_random_cons_32_ipv4.sh b/tests/mmanon_random_cons_32_ipv4.sh
new file mode 100755
index 0000000..f9fb6f5
--- /dev/null
+++ b/tests/mmanon_random_cons_32_ipv4.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+template(name="filename" type="string" string="'$RSYSLOG_DYNNAME'.%syslogtag%.log")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.mode="random-consistent" ipv4.bits="32")
+ action(type="omfile" dynafile="filename" template="outfmt")
+}'
+
+echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 file2 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 file3 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 file4 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 file5 172.1.234.255
+<129>Mar 10 01:00:00 172.20.245.8 file6 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 file7 111.1.1.8.
+<129>Mar 10 01:00:00 172.20.245.8 file8 1.1.1.8\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 1.1.1.8' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ error_exit 1
+fi;
+
+echo ' 0.0.0.0' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ error_exit 1
+fi;
+
+echo ' 172.0.234.255' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ error_exit 1
+fi;
+
+echo ' 111.1.1.8.' | cmp - ${RSYSLOG_DYNNAME}.file7.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file7.log is:"
+ cat ${RSYSLOG_DYNNAME}.file7.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file1.log ${RSYSLOG_DYNNAME}.file6.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file1.log and ${RSYSLOG_DYNNAME}.file6.log are:"
+ cat ${RSYSLOG_DYNNAME}.file1.log
+ cat ${RSYSLOG_DYNNAME}.file6.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file6.log ${RSYSLOG_DYNNAME}.file8.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file6.log and ${RSYSLOG_DYNNAME}.file8.log are:"
+ cat ${RSYSLOG_DYNNAME}.file6.log
+ cat ${RSYSLOG_DYNNAME}.file8.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file2.log ${RSYSLOG_DYNNAME}.file3.log >/dev/null
+if [ ! $? -eq 0 ]; then
+ echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file2.log and ${RSYSLOG_DYNNAME}.file3.log are:"
+ cat ${RSYSLOG_DYNNAME}.file2.log
+ cat ${RSYSLOG_DYNNAME}.file3.log
+ error_exit 1
+fi;
+
+cmp ${RSYSLOG_DYNNAME}.file4.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null
+if [ ! $? -eq 1 ]; then
+ echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file4.log and ${RSYSLOG_DYNNAME}.file5.log are:"
+ cat ${RSYSLOG_DYNNAME}.file4.log
+ cat ${RSYSLOG_DYNNAME}.file5.log
+ error_exit 1
+fi;
+
+rm -f ${RSYSLOG_DYNNAME}.*.log
+exit_test
diff --git a/tests/mmanon_recognize_ipembedded.sh b/tests/mmanon_recognize_ipembedded.sh
new file mode 100755
index 0000000..2b7efa0
--- /dev/null
+++ b/tests/mmanon_recognize_ipembedded.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.enable="off" ipv6.enable="off" embeddedipv4.bits="128" embeddedipv4.anonmode="zero")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:172.2.3.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:1:1:1:0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::1:1:0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:1:1:1:1:0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:1:1:1::1:0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::. test
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::1.2.3.4 test
+<129>Mar 10 01:00:00 172.20.245.8 tag: *13:abd:45::ac.2.3.5* test
+<129>Mar 10 01:00:00 172.20.245.8 tag: ewirnwem aa:ff43:756:99:ff:445:cc.1.2.3.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: aa::ff:bb:122:0:44.1.23.4.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 12:12345::a.3.4.12.7
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:172.1.1.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 72:8374:adc7:47FF::43:172.1.1.0stillnoblank
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:172.1.1.0stillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ 0:0:0:0:0:0:0.0.0.0
+ 61:34:ad::7:F 0:0:0:0:0:0:0.0.0.0
+ ::
+ 0::
+ 0:0:0:0:0:0:0.0.0.0
+ 0:0:0:0:0:0:0.0.0.0
+ 0:0:0:0:0:0:0.0.0.0
+ 13:0:0:0:0:0:0:0.0.0.0
+ 13:abd:0:0:0:0:0:0:0.0.0.0
+ 13:abd:45:0.0.0.0
+ 13:abd:45::. test
+ 0:0:0:0:0:0:0.0.0.0 test
+ *13:abd:45::ac.2.3.5* test
+ ewirnwem aa:ff43:756:99:ff:445:cc.1.2.3.4
+ 0:0:0:0:0:0:0.0.0.0.0
+ 12:12345::a.3.4.12.7
+ textnoblank0:0:0:0:0:0:0.0.0.0
+ 0:0:0:0:0:0:0.0.0.0stillnoblank
+ textnoblank0:0:0:0:0:0:0.0.0.0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_recognize_ipv4.sh b/tests/mmanon_recognize_ipv4.sh
new file mode 100755
index 0000000..05c9eff
--- /dev/null
+++ b/tests/mmanon_recognize_ipv4.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" mode="zero" ipv4.bits="32")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 172.9.6.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: 75.123.123.0 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: nothingnothingnothing
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after 172.1.3.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.9
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.2.3.4.5.6.7.8.76
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.225.225.225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 3.4.5.6
+<129>Mar 10 01:00:00 172.20.245.8 tag: 256.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1....1....1....8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1..1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1..1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank1.1.1.9stillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ before 0.0.0.0
+ 0.0.0.0 after
+ before 0.0.0.0 after
+ nothingnothingnothing
+ before 0.0.0.0 after 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0.0.0.0.0.76
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 20.0.0.0
+ 1....1....1....8
+ 1..1..1..8
+ 1..1.1.8
+ 1.1..1.8
+ 1.1.1..8
+ 10.0.0.0.1
+ 0.0.0.0.1
+ 0.0.0.0.
+ textnoblank0.0.0.0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_recognize_ipv6.sh b/tests/mmanon_recognize_ipv6.sh
new file mode 100755
index 0000000..b7ea773
--- /dev/null
+++ b/tests/mmanon_recognize_ipv6.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.enable="off" ipv6.enable="on" ipv6.bits="128" ipv6.anonmode="zero")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::. test
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::* test
+<129>Mar 10 01:00:00 172.20.245.8 tag: *13:abd:45::* test
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:* test
+<129>Mar 10 01:00:00 172.20.245.8 tag: ewirnwemaa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: a::, cc:: LLL
+<129>Mar 10 01:00:00 172.20.245.8 tag: 12:12345::a
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFE
+<129>Mar 10 01:00:00 172.20.245.8 tag: 72:8374:adc7:47FF::43:0:1AFEstillnoblank
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 13:abd:45:
+ 0:0:0:0:0:0:0:0. test
+ 0:0:0:0:0:0:0:0* test
+ *0:0:0:0:0:0:0:0* test
+ 13:abd:45:* test
+ ewirnwem0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0, 0:0:0:0:0:0:0:0 LLL
+ 12:10:0:0:0:0:0:0:0
+ textnoblank0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0stillnoblank
+ textnoblank0:0:0:0:0:0:0:0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_simple_12_ipv4.sh b/tests/mmanon_simple_12_ipv4.sh
new file mode 100755
index 0000000..24d1126
--- /dev/null
+++ b/tests/mmanon_simple_12_ipv4.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="12" ipv4.mode="simple")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' 1.1.x.x
+ 0.0.x.x
+ 172.0.xxx.xxx
+ 111.1.x.x.' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+grep 'invalid number of ipv4 bits in simple mode, corrected to 16' ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid response generated, ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmanon_simple_33_ipv4.sh b/tests/mmanon_simple_33_ipv4.sh
new file mode 100755
index 0000000..4190b92
--- /dev/null
+++ b/tests/mmanon_simple_33_ipv4.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="33" ipv4.mode="simple" ipv4.replacechar="*")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 172.9.6.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: 75.123.123.0 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: nothingnothingnothing
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after 172.1.3.45
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.12.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.9
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.2.3.4.5.6.7.8.76
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.225.225.225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 3.4.5.6
+<129>Mar 10 01:00:00 172.20.245.8 tag: 256.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1....1....1....8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1..1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1..1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank1.1.31.9stillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ before ***.*.*.*
+ **.***.***.* after
+ before ***.**.*.* after
+ nothingnothingnothing
+ before ***.**.*.* after ***.*.*.**
+ *.*.*.*
+ *.**.*.*
+ *.*.*.*
+ *.*.*.*
+ *.*.*.*.*.*.*.*.76
+ ***.*.***.***
+ *.*.*.*
+ *.***.***.***
+ ***.*.***.***
+ *.*.*.*
+ ***.*.*.*
+ 1....1....1....8
+ 1..1..1..8
+ 1..1.1.8
+ 1.1..1.8
+ 1.1.1..8
+ ****.*.*.*.1
+ ***.*.*.*.1
+ ***.*.*.*.
+ textnoblank*.*.**.*stillnoblank'
+cmp_exact
+
+grep 'invalid number of ipv4.bits (33), corrected to 32' ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid response generated, ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmanon_simple_8_ipv4.sh b/tests/mmanon_simple_8_ipv4.sh
new file mode 100755
index 0000000..192f7ff
--- /dev/null
+++ b/tests/mmanon_simple_8_ipv4.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="8" ipv4.mode="simple")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 1.1.1.x
+ 0.0.0.x
+ 172.0.234.xxx
+ 111.1.1.x.'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_simple_mallformed_ipv4.sh b/tests/mmanon_simple_mallformed_ipv4.sh
new file mode 100755
index 0000000..7ef8899
--- /dev/null
+++ b/tests/mmanon_simple_mallformed_ipv4.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# add 2022-07-28 by Andre Lorbach, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+#export USE_VALGRIND="YES" # this test only makes sense with valgrind enabled
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes"
+
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="32" ipv4.mode="simple")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 165874883373.1.15599155266856607338.91@whatever
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.165874883373.15599155266856607338.91@whatever
+<129>Mar 10 01:00:00 172.20.245.8 tag: 15599155266856607338.165874883373.1.91@whatever
+<129>Mar 10 01:00:00 172.20.245.8 tag: 91.165874883373.1.15599155266856607338.@whatever\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 165874883373.1.15599155266856607338.91@whatever
+ 1.165874883373.15599155266856607338.91@whatever
+ 15599155266856607338.165874883373.1.91@whatever
+ 91.165874883373.1.15599155266856607338.@whatever'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_with_debug.sh b/tests/mmanon_with_debug.sh
new file mode 100755
index 0000000..13678a2
--- /dev/null
+++ b/tests/mmanon_with_debug.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on all flavors of Solaris."
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" mode="zero" ipv4.bits="32")
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 172.9.6.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: 75.123.123.0 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after
+<129>Mar 10 01:00:00 172.20.245.8 tag: nothingnothingnothing
+<129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after 172.1.3.4
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.9
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.2.3.4.5.6.7.8.76
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.225.225.225
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 3.4.5.6
+<129>Mar 10 01:00:00 172.20.245.8 tag: 256.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1....1....1....8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1..1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1..1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1..1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1..8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 1111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.1
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank1.1.1.9stillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ before 0.0.0.0
+ 0.0.0.0 after
+ before 0.0.0.0 after
+ nothingnothingnothing
+ before 0.0.0.0 after 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0.0.0.0.0.76
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 20.0.0.0
+ 1....1....1....8
+ 1..1..1..8
+ 1..1.1.8
+ 1.1..1.8
+ 1.1.1..8
+ 10.0.0.0.1
+ 0.0.0.0.1
+ 0.0.0.0.
+ textnoblank0.0.0.0stillnoblank'
+cmp_exact
+if [ ! -e "$RSYSLOG_DEBUGLOG" ]; then
+ echo "error: file '$RSYSLOG_DEBUGLOG' (Debuglog) not found (should be generated)"
+ error_exit 1
+fi
+exit_test
diff --git a/tests/mmanon_zero_128_ipv6.sh b/tests/mmanon_zero_128_ipv6.sh
new file mode 100755
index 0000000..f410dfc
--- /dev/null
+++ b/tests/mmanon_zero_128_ipv6.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.bits="129" ipv6.anonmode="zero")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 13:abd:45:
+ textnoblank0:0:0:0:0:0:0:0stillnoblank'
+cmp_exact
+
+grep 'invalid number of ipv6.bits (129), corrected to 128' ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid correction of bits parameter generated, ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmanon_zero_12_ipv4.sh b/tests/mmanon_zero_12_ipv4.sh
new file mode 100755
index 0000000..b852f10
--- /dev/null
+++ b/tests/mmanon_zero_12_ipv4.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="12")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 1.1.0.0
+ 0.0.0.0
+ 172.0.224.0
+ 111.1.0.0.'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_zero_33_ipv4.sh b/tests/mmanon_zero_33_ipv4.sh
new file mode 100755
index 0000000..e70455d
--- /dev/null
+++ b/tests/mmanon_zero_33_ipv4.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="33")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0
+ 0.0.0.0.'
+cmp_exact
+
+grep 'invalid number of ipv4.bits (33), corrected to 32' ${RSYSLOG2_OUT_LOG} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid response generated, ${RSYSLOG2_OUT_LOG} is:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi;
+
+
+exit_test
diff --git a/tests/mmanon_zero_50_ipv6.sh b/tests/mmanon_zero_50_ipv6.sh
new file mode 100755
index 0000000..ee8e7dd
--- /dev/null
+++ b/tests/mmanon_zero_50_ipv6.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.bits="50" ipv6.anonmode="zero")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ ffff:ffff:ffff:ffff:fffc:0:0:0
+ 61:34:ad:0:0:0:0:0 aa:ff43:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 13:abd:45:
+ textnoblank72:8374:adc7:47ff:0:0:0:0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_zero_64_ipv6.sh b/tests/mmanon_zero_64_ipv6.sh
new file mode 100755
index 0000000..8f5f537
--- /dev/null
+++ b/tests/mmanon_zero_64_ipv6.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv6.bits="64" ipv6.anonmode="zero")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ ffff:ffff:ffff:ffff:0:0:0:0
+ 61:34:ad:0:0:0:0:0 aa:ff43:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 13:abd:45:
+ textnoblank72:8374:adc7:47ff:0:0:0:0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_zero_8_ipv4.sh b/tests/mmanon_zero_8_ipv4.sh
new file mode 100755
index 0000000..430c27f
--- /dev/null
+++ b/tests/mmanon_zero_8_ipv4.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon" ipv4.bits="8")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0
+<129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255
+<129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' 1.1.1.0
+ 0.0.0.0
+ 172.0.234.0
+ 111.1.1.0.'
+cmp_exact
+exit_test
diff --git a/tests/mmanon_zero_96_ipv6.sh b/tests/mmanon_zero_96_ipv6.sh
new file mode 100755
index 0000000..77793e3
--- /dev/null
+++ b/tests/mmanon_zero_96_ipv6.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmanon/.libs/mmanon")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmanon")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk
+<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
+<129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0
+<129>Mar 10 01:00:00 172.20.245.8 tag: ::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 0::
+<129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:
+<129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\""
+
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=' asdfghjk
+ ffff:ffff:0:0:0:0:0:0
+ 61:34:0:0:0:0:0:0 aa:ff43:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 0:0:0:0:0:0:0:0
+ 13:abd:45:
+ textnoblank72:8374:0:0:0:0:0:0stillnoblank'
+cmp_exact
+exit_test
diff --git a/tests/mmdarwin_errmsg_no_params.sh b/tests/mmdarwin_errmsg_no_params.sh
new file mode 100755
index 0000000..0e491f2
--- /dev/null
+++ b/tests/mmdarwin_errmsg_no_params.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-04-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/mmdarwin/.libs/mmdarwin")
+action(type="mmdarwin")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+ startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'socketpath' required but not specified"
+
+exit_test
diff --git a/tests/mmdarwin_errmsg_no_sock-vg.sh b/tests/mmdarwin_errmsg_no_sock-vg.sh
new file mode 100755
index 0000000..c480f86
--- /dev/null
+++ b/tests/mmdarwin_errmsg_no_sock-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# add 2019-04-02 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/mmdarwin_errmsg_no_sock.sh
diff --git a/tests/mmdarwin_errmsg_no_sock.sh b/tests/mmdarwin_errmsg_no_sock.sh
new file mode 100755
index 0000000..9a1cc6c
--- /dev/null
+++ b/tests/mmdarwin_errmsg_no_sock.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-04-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/mmdarwin/.libs/mmdarwin")
+action(type="mmdarwin" socketpath="/invalid" key="invalid" fields="invalid")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+ startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "error connecting to Darwin.*/invalid"
+
+exit_test
diff --git a/tests/mmdb-container-empty.sh b/tests/mmdb-container-empty.sh
new file mode 100755
index 0000000..a9e7e04
--- /dev/null
+++ b/tests/mmdb-container-empty.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!src_geoip%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup" container="!")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/mmdb.rb`)
+ action(type="mmdblookup" mmdbfile=`echo $srcdir/test.mmdb` key="$!ip" fields=":src_geoip!city_name:city" )
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+startup
+tcpflood -m 1 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown
+content_check '{ "city_name": "Beijing" }'
+exit_test
diff --git a/tests/mmdb-container.sh b/tests/mmdb-container.sh
new file mode 100755
index 0000000..e824a06
--- /dev/null
+++ b/tests/mmdb-container.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!mmdb_root%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup" container="!mmdb_root")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/mmdb.rb`)
+ action(type="mmdblookup" mmdbfile=`echo $srcdir/test.mmdb` key="$!ip" fields="city" )
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+startup
+tcpflood -m 1 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown
+content_check '{ "city": "Beijing" }'
+exit_test
diff --git a/tests/mmdb-multilevel-vg.sh b/tests/mmdb-multilevel-vg.sh
new file mode 100755
index 0000000..b6096b3
--- /dev/null
+++ b/tests/mmdb-multilevel-vg.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# we libmaxminddb, in packaged versions, has a small cosmetic memory leak,
+# thus we need a suppressions file:
+export RS_TESTBENCH_VALGRIND_EXTRA_OPTS="$RS_TESTBENCH_VALGRIND_EXTRA_OPTS --suppressions=$srcdir/libmaxmindb.supp"
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!iplocation%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase="'$srcdir'/mmdb.rb")
+ # Uncomment this action when using the real GeoLite2 city database;
+ # we have not included it into the testbench for licensing concerns.
+ # action(type="mmdblookup" mmdbfile="/home/USR/GeoLite2-City_20170502/GeoLite2-City.mmdb" key="$!ip" fields=":city:!city!names!en" )
+ action(type="mmdblookup" mmdbfile="'$srcdir'/test.mmdb" key="$!ip" fields=":city_name:city" )
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}'
+startup_vg
+tcpflood -m 100 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+content_check '{ "city_name": "Beijing" }'
+exit_test
diff --git a/tests/mmdb-space.sh b/tests/mmdb-space.sh
new file mode 100755
index 0000000..797290e
--- /dev/null
+++ b/tests/mmdb-space.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# added 2014-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmdb.sh\]: test for mmdb
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!iplocation%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase="'$srcdir'/mmdb.rb")
+ action(type="mmdblookup" mmdbfile="'$srcdir'/with_space.mmdb" key="$!ip" fields="city" )
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+startup
+tcpflood -m 1 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown
+content_check '{ "city": "Bei ing" }'
+exit_test
diff --git a/tests/mmdb-vg.sh b/tests/mmdb-vg.sh
new file mode 100755
index 0000000..b2f9079
--- /dev/null
+++ b/tests/mmdb-vg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# we libmaxminddb, in packaged versions, has a small cosmetic memory leak,
+# thus we need a suppressions file:
+export RS_TESTBENCH_VALGRIND_EXTRA_OPTS="$RS_TESTBENCH_VALGRIND_EXTRA_OPTS --suppressions=$srcdir/libmaxmindb.supp"
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!iplocation%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase="'$srcdir'/mmdb.rb")
+ action(type="mmdblookup" mmdbfile="'$srcdir'/test.mmdb" key="$!ip" fields="city" )
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}'
+startup_vg
+tcpflood -m 100 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+content_check '{ "city": "Beijing" }'
+exit_test
diff --git a/tests/mmdb.rb b/tests/mmdb.rb
new file mode 100644
index 0000000..38697a0
--- /dev/null
+++ b/tests/mmdb.rb
@@ -0,0 +1,3 @@
+version=2
+
+rule=: %ip:word% %remaining:word%
diff --git a/tests/mmdb.sh b/tests/mmdb.sh
new file mode 100755
index 0000000..473f7a0
--- /dev/null
+++ b/tests/mmdb.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# added 2014-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmdb.sh\]: test for mmdb
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!iplocation%\n")
+
+module(load="../plugins/mmdblookup/.libs/mmdblookup")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/mmdb.rb`)
+ action(type="mmdblookup" mmdbfile=`echo $srcdir/test.mmdb` key="$!ip" fields="city" )
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+startup
+tcpflood -m 1 -j "202.106.0.20\ "
+shutdown_when_empty
+wait_shutdown
+content_check '{ "city": "Beijing" }'
+exit_test
diff --git a/tests/mmexternal-InvldProg-vg.sh b/tests/mmexternal-InvldProg-vg.sh
new file mode 100755
index 0000000..7ce4e4c
--- /dev/null
+++ b/tests/mmexternal-InvldProg-vg.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2017-12-29 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmexternal/.libs/mmexternal")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+set $!x = "a";
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+if $msg contains "msgnum:" then {
+ action(type="mmexternal" interface.input="fulljson"
+ binary="does/not/exist")
+}
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup_vg_noleak
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:1\""
+./msleep 500 # let the fork happen and report back!
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+grep 'failed to execute' $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmexternal-SegFault-empty-jroot-vg.sh b/tests/mmexternal-SegFault-empty-jroot-vg.sh
new file mode 100755
index 0000000..71e8e64
--- /dev/null
+++ b/tests/mmexternal-SegFault-empty-jroot-vg.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# add 2017-11-06 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmexternal/.libs/mmexternal")
+
+template(name="outfmt" type="string" string="-%$!%-\n")
+
+if $msg contains "msgnum:" then {
+ action(type="mmexternal" interface.input="fulljson"
+ binary="'$PYTHON' '${srcdir}'/testsuites/mmexternal-SegFault-mm-python.py")
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup_vg
+injectmsg literal "<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:1"
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+export EXPECTED='-{ "sometag": "somevalue" }-'
+cmp_exact
+exit_test
diff --git a/tests/mmexternal-SegFault.sh b/tests/mmexternal-SegFault.sh
new file mode 100755
index 0000000..e538df4
--- /dev/null
+++ b/tests/mmexternal-SegFault.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# a case that actually caused a segfault
+# add 2017-11-06 by PascalWithopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmexternal/.libs/mmexternal")
+set $!x = "a";
+
+template(name="outfmt" type="string" string="-%$!%-\n")
+
+if $msg contains "msgnum:" then {
+ action(type="mmexternal" interface.input="fulljson"
+ binary="'$PYTHON' '${srcdir}'/testsuites/mmexternal-SegFault-mm-python.py")
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+injectmsg literal "<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:1"
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='-{ "x": "a", "sometag": "somevalue" }-'
+cmp_exact
+exit_test
diff --git a/tests/mmjsonparse-invalid-containerName.sh b/tests/mmjsonparse-invalid-containerName.sh
new file mode 100755
index 0000000..3488cd1
--- /dev/null
+++ b/tests/mmjsonparse-invalid-containerName.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-04-13 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/impstats/.libs/impstats" interval="300"
+ resetCounters="on" format="cee" ruleset="fooruleset" log.syslog="on")
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+
+action(name="fooname" type="mmjsonparse" container="foobar")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+grep "mmjsonparse: invalid container name 'foobar', name must start with" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+grep "impstats: ruleset 'fooruleset' not found - using default ruleset instead" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/mmjsonparse-w-o-cookie-multi-spaces.sh b/tests/mmjsonparse-w-o-cookie-multi-spaces.sh
new file mode 100755
index 0000000..a8862a0
--- /dev/null
+++ b/tests/mmjsonparse-w-o-cookie-multi-spaces.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse" cookie="")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+startup
+tcpflood -m $NUMMESSAGES "-j \" \""
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/mmjsonparse-w-o-cookie.sh b/tests/mmjsonparse-w-o-cookie.sh
new file mode 100755
index 0000000..0dcd78b
--- /dev/null
+++ b/tests/mmjsonparse-w-o-cookie.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse" cookie="")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+startup
+tcpflood -m $NUMMESSAGES "-j \" \""
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/mmjsonparse_cim.sh b/tests/mmjsonparse_cim.sh
new file mode 100755
index 0000000..702e678
--- /dev/null
+++ b/tests/mmjsonparse_cim.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# added 2014-07-15 by rgerhards
+# basic test for mmjsonparse module with "cim" cookie
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!cim!msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse" cookie="@cim:" container="!cim")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m $NUMMESSAGES -j "@cim: "
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/mmjsonparse_cim2.sh b/tests/mmjsonparse_cim2.sh
new file mode 100755
index 0000000..6086334
--- /dev/null
+++ b/tests/mmjsonparse_cim2.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# add 2018-04-16 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!cim!msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse" cookie="@cim:" container="$!cim")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m $NUMMESSAGES -j "@cim: "
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
+
diff --git a/tests/mmjsonparse_extra_data-vg.sh b/tests/mmjsonparse_extra_data-vg.sh
new file mode 100755
index 0000000..1b8a05c
--- /dev/null
+++ b/tests/mmjsonparse_extra_data-vg.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# ensure mmjsonparse works correctly if passed unparsable message
+# add 2018-11-05 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="-%msg%-\n")
+
+action(type="mmjsonparse" cookie="")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+else if $parsesuccess == "FAIL" and $msg contains "param1" then {
+ action(type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="outfmt")
+}
+'
+startup_vg
+tcpflood -m2 -M "\"{\\\"param1\\\":\\\"value1\\\"} data\""
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+check_file_not_exists $RSYSLOG_OUT_LOG
+export EXPECTED='-{"param1":"value1"} data-
+-{"param1":"value1"} data-'
+cmp_exact $RSYSLOG2_OUT_LOG
+exit_test
diff --git a/tests/mmjsonparse_localvar.sh b/tests/mmjsonparse_localvar.sh
new file mode 100755
index 0000000..7597b73
--- /dev/null
+++ b/tests/mmjsonparse_localvar.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2018-04-16 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse" cookie="@cim:" container="$.")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m $NUMMESSAGES -j "@cim: "
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
+
diff --git a/tests/mmjsonparse_simple.sh b/tests/mmjsonparse_simple.sh
new file mode 100755
index 0000000..5419e8b
--- /dev/null
+++ b/tests/mmjsonparse_simple.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# added 2014-07-15 by rgerhards
+# basic test for mmjsonparse module with defaults
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!msgnum%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+if $parsesuccess == "OK" then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m $NUMMESSAGES -j "@cee: "
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/mmkubernetes-basic-vg.sh b/tests/mmkubernetes-basic-vg.sh
new file mode 100755
index 0000000..fbd1be3
--- /dev/null
+++ b/tests/mmkubernetes-basic-vg.sh
@@ -0,0 +1,187 @@
+#!/bin/bash
+# added 2018-04-06 by richm, released under ASL 2.0
+#
+# Note: on buildbot VMs (where there is no environment cleanup), the
+# kubernetes test server may be kept running if the script aborts or
+# is aborted (buildbot master failure!) for some reason. As such we
+# execute it under "timeout" control, which ensure it always is
+# terminated. It's not a 100% great method, but hopefully does the
+# trick. -- rgerhards, 2018-07-21
+#export RSYSLOG_DEBUG="debug"
+USE_VALGRIND=true
+. ${srcdir:=.}/diag.sh init
+check_command_available timeout
+pwd=$( pwd )
+k8s_srv_port=$( get_free_port )
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'"$RSYSLOG_DYNNAME.spool"'/mmkubernetes-stats.log" log.syslog="off" format="cee")
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../contrib/mmkubernetes/.libs/mmkubernetes")
+
+template(name="mmk8s_template" type="list") {
+ property(name="$!all-json-plain")
+ constant(value="\n")
+}
+
+input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on")
+action(type="mmjsonparse" cookie="")
+action(type="mmkubernetes" busyretryinterval="1" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'"
+ filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:.%.%container_hash:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log",
+ "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"]
+)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="mmk8s_template")
+'
+
+testsrv=mmk8s-test-server
+echo starting kubernetes \"emulator\"
+timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py $k8s_srv_port ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 &
+BGPROCESS=$!
+wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started
+echo background mmkubernetes_test_server.py process id is $BGPROCESS
+
+cat > ${RSYSLOG_DYNNAME}.spool/pod-error1.log <<EOF
+{"log":"not in right format","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":1}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-error2.log <<EOF
+{"message":"not in right format","CONTAINER_NAME":"not in right format","CONTAINER_ID_FULL":"id3","testid":2}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name1_namespace-name1_container-name1-id1.log <<EOF
+{"log":"{\"type\":\"response\",\"@timestamp\":\"2018-04-06T17:26:34Z\",\"tags\":[],\"pid\":75,\"method\":\"head\",\"statusCode\":200,\"req\":{\"url\":\"/\",\"method\":\"head\",\"headers\":{\"user-agent\":\"curl/7.29.0\",\"host\":\"localhost:5601\",\"accept\":\"*/*\"},\"remoteAddress\":\"127.0.0.1\",\"userAgent\":\"127.0.0.1\"},\"res\":{\"statusCode\":200,\"responseTime\":1,\"contentLength\":9},\"message\":\"HEAD1 / 200 1ms - 9.0B\"}\n","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":3}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name2.container-hash2_namespace-name2_container-name2-id2.log <<EOF
+{"log":"{\"type\":\"response\",\"@timestamp\":\"2018-04-06T17:26:34Z\",\"tags\":[],\"pid\":75,\"method\":\"head\",\"statusCode\":200,\"req\":{\"url\":\"/\",\"method\":\"head\",\"headers\":{\"user-agent\":\"curl/7.29.0\",\"host\":\"localhost:5601\",\"accept\":\"*/*\"},\"remoteAddress\":\"127.0.0.1\",\"userAgent\":\"127.0.0.1\"},\"res\":{\"statusCode\":200,\"responseTime\":1,\"contentLength\":9},\"message\":\"HEAD2 / 200 1ms - 9.0B\"}\n","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":4}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name3.log <<EOF
+{"message":"a message from container 3","CONTAINER_NAME":"some-prefix_container-name3.container-hash3_pod-name3_namespace-name3_unused3_unused33","CONTAINER_ID_FULL":"id3","testid":5}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name4.log <<EOF
+{"message":"a message from container 4","CONTAINER_NAME":"some-prefix_container-name4_pod-name4_namespace-name4_unused4_unused44","CONTAINER_ID_FULL":"id4","testid":6}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name5.log <<EOF
+{"message":"a message from container 5","CONTAINER_NAME":"some-prefix_container-name5_pod-name5.with.dot.in.pod.name_namespace-name5_unused5_unused55","CONTAINER_ID_FULL":"id5","testid":7}
+EOF
+
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ export EXTRA_VALGRIND_SUPPRESSIONS="--suppressions=$srcdir/mmkubernetes.supp"
+ startup_vg
+else
+ startup
+fi
+# wait for the first batch of tests to complete
+wait_queueempty
+
+cat > ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have no namespace metadata","CONTAINER_NAME":"some-prefix_container-name-6_pod-name-6_namespace-name-6-not-found_unused6_unused66","CONTAINER_ID_FULL":"id6","testid":8}
+{"message":"this record should have no pod metadata","CONTAINER_NAME":"some-prefix_container-name-7_pod-name-7-not-found_namespace-name-7_unused7_unused77","CONTAINER_ID_FULL":"id7","testid":9}
+{"message":"this record should have no namespace or pod metadata and retry","CONTAINER_NAME":"some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88","CONTAINER_ID_FULL":"id8","testid":10}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have namespace and pod metadata after retry","CONTAINER_NAME":"some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88","CONTAINER_ID_FULL":"id8","testid":11}
+{"message":"this record should have no pod metadata and retry","CONTAINER_NAME":"some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99","CONTAINER_ID_FULL":"id9","testid":12}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have pod metadata after retry","CONTAINER_NAME":"some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99","CONTAINER_ID_FULL":"id9","testid":13}
+{"message":"this record should process normally","CONTAINER_NAME":"some-prefix_container-name-10_pod-name-10_namespace-name-10_unused10_unused100","CONTAINER_ID_FULL":"id10","testid":14}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-error.log <<EOF
+{"message":"this record should have no pod metadata","CONTAINER_NAME":"some-prefix_container-name-11_pod-name-11-error_namespace-name-11_unused11_unused111","CONTAINER_ID_FULL":"id11","testid":15}
+{"message":"this record should process normally","CONTAINER_NAME":"some-prefix_container-name-12_pod-name-12_namespace-name-12_unused12_unused112","CONTAINER_ID_FULL":"id12","testid":16}
+EOF
+
+
+shutdown_when_empty
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown
+fi
+kill $BGPROCESS
+wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid
+
+rc=0
+# for each record in mmkubernetes-basic.out.json, see if the matching
+# record is found in $RSYSLOG_OUT_LOG
+$PYTHON -c 'import sys,json
+k8s_srv_port = sys.argv[3]
+expected = {}
+for hsh in json.load(open(sys.argv[1])):
+ if "testid" in hsh:
+ if "kubernetes" in hsh and "master_url" in hsh["kubernetes"]:
+ hsh["kubernetes"]["master_url"] = hsh["kubernetes"]["master_url"].format(k8s_srv_port=k8s_srv_port)
+ expected[hsh["testid"]] = hsh
+rc = 0
+actual = {}
+for line in open(sys.argv[2]):
+ hsh = json.loads(line)
+ if "testid" in hsh:
+ actual[hsh["testid"]] = hsh
+for testid,hsh in expected.items():
+ if not testid in actual:
+ print("Error: record for testid {0} not found in output".format(testid))
+ rc = 1
+ else:
+ for kk,vv in hsh.items():
+ if not kk in actual[testid]:
+ print("Error: key {0} in record for testid {1} not found in output".format(kk, testid))
+ rc = 1
+ elif not vv == actual[testid][kk]:
+ print("Error: value {0} for key {1} in record for testid {2} does not match the expected value {3}".format(str(actual[testid][kk]), kk, testid, str(vv)))
+ rc = 1
+sys.exit(rc)
+' $srcdir/mmkubernetes-basic.out.json $RSYSLOG_OUT_LOG $k8s_srv_port || rc=$?
+grep -q 'mmkubernetes: Not Found: the resource does not exist at url .*/namespaces\\\/namespace-name-6-not-found' $RSYSLOG_OUT_LOG || { echo fail1; rc=1; }
+grep -q 'mmkubernetes: Not Found: the resource does not exist at url .*/pods\\\/pod-name-7-not-found' $RSYSLOG_OUT_LOG || { echo fail2; rc=1; }
+grep -q 'mmkubernetes: Too Many Requests: the server is too heavily loaded to provide the data for the requested url .*/namespaces\\\/namespace-name-8-busy' $RSYSLOG_OUT_LOG || { echo fail3; rc=1; }
+grep -q 'mmkubernetes: Too Many Requests: the server is too heavily loaded to provide the data for the requested url .*/pods\\\/pod-name-9-busy' $RSYSLOG_OUT_LOG || { echo fail4; rc=1; }
+
+if [ -f ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log ] ; then
+ $PYTHON <${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log -c '
+import sys,json
+k8s_srv_port = sys.argv[1]
+expected = {"name": "mmkubernetes(http://localhost:{0})".format(k8s_srv_port),
+ "origin": "mmkubernetes", "recordseen": 14, "namespacemetadatasuccess": 11,
+ "namespacemetadatanotfound": 1, "namespacemetadatabusy": 1, "namespacemetadataerror": 0,
+ "podmetadatasuccess": 10, "podmetadatanotfound": 1, "podmetadatabusy": 2, "podmetadataerror": 1,
+ "namespacecachenumentries": 12, "podcachenumentries": 12, "namespacecachehits": 1,
+ "podcachehits": 0, "namespacecachemisses": 13, "podcachemisses": 14 }
+actual = {}
+for line in sys.stdin:
+ jstart = line.find("{")
+ if jstart >= 0:
+ hsh = json.loads(line[jstart:])
+ if hsh["origin"] == "mmkubernetes":
+ actual = hsh
+assert(expected == actual)
+' $k8s_srv_port || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log; }
+else
+ echo error: stats file ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log not found
+ rc=1
+fi
+
+if [ ${rc:-0} -ne 0 ]; then
+ echo
+ echo "FAIL: expected data not found. $RSYSLOG_OUT_LOG is:"
+ cat ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log
+ cat $RSYSLOG_OUT_LOG
+ cat ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/mmkubernetes-basic.out.json b/tests/mmkubernetes-basic.out.json
new file mode 100644
index 0000000..c518003
--- /dev/null
+++ b/tests/mmkubernetes-basic.out.json
@@ -0,0 +1,376 @@
+[{
+ "log": "not in right format",
+ "testid": 1
+},
+{
+ "message": "not in right format",
+ "testid": 2
+},
+{
+ "kubernetes": {
+ "namespace_id": "namespace-name2-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name2-id",
+ "labels": {
+ "custom_label": "pod-name2-label-value",
+ "deploymentconfig": "pod-name2-dc",
+ "component": "pod-name2-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name2-deployment"
+ },
+ "pod_name": "pod-name2",
+ "namespace_name": "namespace-name2",
+ "container_name": "container-name2",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id2"
+ },
+ "testid": 4
+},
+{
+ "message": "a message from container 4",
+ "CONTAINER_NAME": "some-prefix_container-name4_pod-name4_namespace-name4_unused4_unused44",
+ "CONTAINER_ID_FULL": "id4",
+ "kubernetes": {
+ "namespace_id": "namespace-name4-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name4-id",
+ "labels": {
+ "custom_label": "pod-name4-label-value",
+ "deploymentconfig": "pod-name4-dc",
+ "component": "pod-name4-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name4-deployment"
+ },
+ "pod_name": "pod-name4",
+ "namespace_name": "namespace-name4",
+ "container_name": "container-name4",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id4"
+ },
+ "testid": 6
+},
+{
+ "kubernetes": {
+ "namespace_id": "namespace-name1-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name1-id",
+ "labels": {
+ "custom_label": "pod-name1-label-value",
+ "deploymentconfig": "pod-name1-dc",
+ "component": "pod-name1-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name1-deployment"
+ },
+ "pod_name": "pod-name1",
+ "namespace_name": "namespace-name1",
+ "container_name": "container-name1",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id1"
+ },
+ "testid": 3
+},
+{
+ "message": "a message from container 3",
+ "CONTAINER_NAME": "some-prefix_container-name3.container-hash3_pod-name3_namespace-name3_unused3_unused33",
+ "CONTAINER_ID_FULL": "id3",
+ "kubernetes": {
+ "namespace_id": "namespace-name3-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name3-id",
+ "labels": {
+ "custom_label": "pod-name3-label-value",
+ "deploymentconfig": "pod-name3-dc",
+ "component": "pod-name3-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name3-deployment"
+ },
+ "pod_name": "pod-name3",
+ "namespace_name": "namespace-name3",
+ "container_name": "container-name3",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id3"
+ },
+ "testid": 5
+},
+{
+ "message": "a message from container 5",
+ "CONTAINER_NAME": "some-prefix_container-name5_pod-name5.with.dot.in.pod.name_namespace-name5_unused5_unused55",
+ "CONTAINER_ID_FULL": "id5",
+ "kubernetes": {
+ "namespace_id": "namespace-name5-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name5.with.dot.in.pod.name-id",
+ "labels": {
+ "custom_label": "pod-name5.with.dot.in.pod.name-label-value",
+ "deploymentconfig": "pod-name5.with.dot.in.pod.name-dc",
+ "component": "pod-name5.with.dot.in.pod.name-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name5.with.dot.in.pod.name-deployment"
+ },
+ "pod_name": "pod-name5.with.dot.in.pod.name",
+ "namespace_name": "namespace-name5",
+ "container_name": "container-name5",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id5"
+ },
+ "testid": 7
+},
+{
+ "message":"this record should have no namespace metadata",
+ "CONTAINER_NAME":"some-prefix_container-name-6_pod-name-6_namespace-name-6-not-found_unused6_unused66",
+ "CONTAINER_ID_FULL":"id6",
+ "kubernetes": {
+ "pod_id":"pod-name-6-id",
+ "labels": {
+ "custom_label":"pod-name-6-label-value",
+ "deploymentconfig":"pod-name-6-dc",
+ "component":"pod-name-6-component",
+ "label_with_empty_value":"",
+ "deployment":"pod-name-6-deployment"
+ },
+ "pod_name":"pod-name-6",
+ "namespace_name":"namespace-name-6-not-found",
+ "container_name":"container-name-6",
+ "master_url":"http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id":"id6"
+ },
+ "testid": 8
+},
+{
+ "message": "this record should have no pod metadata",
+ "CONTAINER_NAME": "some-prefix_container-name-7_pod-name-7-not-found_namespace-name-7_unused7_unused77",
+ "CONTAINER_ID_FULL": "id7",
+ "kubernetes": {
+ "namespace_id": "namespace-name-7-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_name": "pod-name-7-not-found",
+ "namespace_name": "namespace-name-7",
+ "container_name": "container-name-7",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id7"
+ },
+ "testid": 9
+},
+{
+ "message": "this record should have no namespace or pod metadata and retry",
+ "CONTAINER_NAME": "some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88",
+ "CONTAINER_ID_FULL": "id8",
+ "kubernetes": {
+ "pod_name": "pod-name-8",
+ "namespace_name": "namespace-name-8-busy",
+ "container_name": "container-name-8",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id8"
+ },
+ "testid": 10
+},
+{
+ "message": "this record should have namespace and pod metadata after retry",
+ "CONTAINER_NAME": "some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88",
+ "CONTAINER_ID_FULL": "id8",
+ "kubernetes": {
+ "namespace_id": "namespace-name-8-busy-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name-8-id",
+ "labels": {
+ "custom_label": "pod-name-8-label-value",
+ "deploymentconfig": "pod-name-8-dc",
+ "component": "pod-name-8-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name-8-deployment"
+ },
+ "pod_name": "pod-name-8",
+ "namespace_name": "namespace-name-8-busy",
+ "container_name": "container-name-8",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id8"
+ },
+ "testid": 11
+},
+{
+ "message": "this record should have no pod metadata and retry",
+ "CONTAINER_NAME": "some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99",
+ "CONTAINER_ID_FULL": "id9",
+ "kubernetes": {
+ "namespace_id": "namespace-name-9-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_name": "pod-name-9-busy",
+ "namespace_name": "namespace-name-9",
+ "container_name": "container-name-9",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id9"
+ },
+ "testid": 12
+},
+{
+ "message": "this record should have pod metadata after retry",
+ "CONTAINER_NAME": "some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99",
+ "CONTAINER_ID_FULL": "id9",
+ "kubernetes": {
+ "namespace_id": "namespace-name-9-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name-9-busy-id",
+ "labels": {
+ "custom_label": "pod-name-9-busy-label-value",
+ "deploymentconfig": "pod-name-9-busy-dc",
+ "component": "pod-name-9-busy-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name-9-busy-deployment"
+ },
+ "pod_name": "pod-name-9-busy",
+ "namespace_name": "namespace-name-9",
+ "container_name": "container-name-9",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id9"
+ },
+ "testid": 13
+},
+{
+ "message": "this record should process normally",
+ "CONTAINER_NAME": "some-prefix_container-name-10_pod-name-10_namespace-name-10_unused10_unused100",
+ "CONTAINER_ID_FULL": "id10",
+ "kubernetes": {
+ "namespace_id": "namespace-name-10-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name-10-id",
+ "labels": {
+ "custom_label": "pod-name-10-label-value",
+ "deploymentconfig": "pod-name-10-dc",
+ "component": "pod-name-10-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name-10-deployment"
+ },
+ "pod_name": "pod-name-10",
+ "namespace_name": "namespace-name-10",
+ "container_name": "container-name-10",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id10"
+ },
+ "testid": 14
+},
+{
+ "message": "this record should have no pod metadata",
+ "CONTAINER_NAME": "some-prefix_container-name-11_pod-name-11-error_namespace-name-11_unused11_unused111",
+ "CONTAINER_ID_FULL": "id11",
+ "kubernetes": {
+ "namespace_id": "namespace-name-11-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_name": "pod-name-11-error",
+ "namespace_name": "namespace-name-11",
+ "container_name": "container-name-11",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id11"
+ },
+ "testid": 15
+},
+{
+ "message": "this record should process normally",
+ "CONTAINER_NAME": "some-prefix_container-name-12_pod-name-12_namespace-name-12_unused12_unused112",
+ "CONTAINER_ID_FULL": "id12",
+ "kubernetes": {
+ "namespace_id": "namespace-name-12-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name-12-id",
+ "labels": {
+ "custom_label": "pod-name-12-label-value",
+ "deploymentconfig": "pod-name-12-dc",
+ "component": "pod-name-12-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name-12-deployment"
+ },
+ "pod_name": "pod-name-12",
+ "namespace_name": "namespace-name-12",
+ "container_name": "container-name-12",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id12"
+ },
+ "testid": 16
+}]
diff --git a/tests/mmkubernetes-basic.sh b/tests/mmkubernetes-basic.sh
new file mode 100755
index 0000000..90f43c4
--- /dev/null
+++ b/tests/mmkubernetes-basic.sh
@@ -0,0 +1,187 @@
+#!/bin/bash
+# added 2018-04-06 by richm, released under ASL 2.0
+#
+# Note: on buildbot VMs (where there is no environment cleanup), the
+# kubernetes test server may be kept running if the script aborts or
+# is aborted (buildbot master failure!) for some reason. As such we
+# execute it under "timeout" control, which ensure it always is
+# terminated. It's not a 100% great method, but hopefully does the
+# trick. -- rgerhards, 2018-07-21
+#export RSYSLOG_DEBUG="debug"
+USE_VALGRIND=false
+. ${srcdir:=.}/diag.sh init
+check_command_available timeout
+pwd=$( pwd )
+k8s_srv_port=$( get_free_port )
+generate_conf
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'"$RSYSLOG_DYNNAME.spool"'/mmkubernetes-stats.log" log.syslog="off" format="cee")
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../contrib/mmkubernetes/.libs/mmkubernetes")
+
+template(name="mmk8s_template" type="list") {
+ property(name="$!all-json-plain")
+ constant(value="\n")
+}
+
+input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on")
+action(type="mmjsonparse" cookie="")
+action(type="mmkubernetes" busyretryinterval="1" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'"
+ filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:.%.%container_hash:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log",
+ "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"]
+)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="mmk8s_template")
+'
+
+testsrv=mmk8s-test-server
+echo starting kubernetes \"emulator\"
+timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py $k8s_srv_port ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 &
+BGPROCESS=$!
+wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started
+echo background mmkubernetes_test_server.py process id is $BGPROCESS
+
+cat > ${RSYSLOG_DYNNAME}.spool/pod-error1.log <<EOF
+{"log":"not in right format","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":1}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-error2.log <<EOF
+{"message":"not in right format","CONTAINER_NAME":"not in right format","CONTAINER_ID_FULL":"id3","testid":2}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name1_namespace-name1_container-name1-id1.log <<EOF
+{"log":"{\"type\":\"response\",\"@timestamp\":\"2018-04-06T17:26:34Z\",\"tags\":[],\"pid\":75,\"method\":\"head\",\"statusCode\":200,\"req\":{\"url\":\"/\",\"method\":\"head\",\"headers\":{\"user-agent\":\"curl/7.29.0\",\"host\":\"localhost:5601\",\"accept\":\"*/*\"},\"remoteAddress\":\"127.0.0.1\",\"userAgent\":\"127.0.0.1\"},\"res\":{\"statusCode\":200,\"responseTime\":1,\"contentLength\":9},\"message\":\"HEAD1 / 200 1ms - 9.0B\"}\n","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":3}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name2.container-hash2_namespace-name2_container-name2-id2.log <<EOF
+{"log":"{\"type\":\"response\",\"@timestamp\":\"2018-04-06T17:26:34Z\",\"tags\":[],\"pid\":75,\"method\":\"head\",\"statusCode\":200,\"req\":{\"url\":\"/\",\"method\":\"head\",\"headers\":{\"user-agent\":\"curl/7.29.0\",\"host\":\"localhost:5601\",\"accept\":\"*/*\"},\"remoteAddress\":\"127.0.0.1\",\"userAgent\":\"127.0.0.1\"},\"res\":{\"statusCode\":200,\"responseTime\":1,\"contentLength\":9},\"message\":\"HEAD2 / 200 1ms - 9.0B\"}\n","stream":"stdout","time":"2018-04-06T17:26:34.492083106Z","testid":4}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name3.log <<EOF
+{"message":"a message from container 3","CONTAINER_NAME":"some-prefix_container-name3.container-hash3_pod-name3_namespace-name3_unused3_unused33","CONTAINER_ID_FULL":"id3","testid":5}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name4.log <<EOF
+{"message":"a message from container 4","CONTAINER_NAME":"some-prefix_container-name4_pod-name4_namespace-name4_unused4_unused44","CONTAINER_ID_FULL":"id4","testid":6}
+EOF
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name5.log <<EOF
+{"message":"a message from container 5","CONTAINER_NAME":"some-prefix_container-name5_pod-name5.with.dot.in.pod.name_namespace-name5_unused5_unused55","CONTAINER_ID_FULL":"id5","testid":7}
+EOF
+
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ export EXTRA_VALGRIND_SUPPRESSIONS="--suppressions=$srcdir/mmkubernetes.supp"
+ startup_vg
+else
+ startup
+fi
+# wait for the first batch of tests to complete
+wait_queueempty
+
+cat > ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have no namespace metadata","CONTAINER_NAME":"some-prefix_container-name-6_pod-name-6_namespace-name-6-not-found_unused6_unused66","CONTAINER_ID_FULL":"id6","testid":8}
+{"message":"this record should have no pod metadata","CONTAINER_NAME":"some-prefix_container-name-7_pod-name-7-not-found_namespace-name-7_unused7_unused77","CONTAINER_ID_FULL":"id7","testid":9}
+{"message":"this record should have no namespace or pod metadata and retry","CONTAINER_NAME":"some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88","CONTAINER_ID_FULL":"id8","testid":10}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have namespace and pod metadata after retry","CONTAINER_NAME":"some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88","CONTAINER_ID_FULL":"id8","testid":11}
+{"message":"this record should have no pod metadata and retry","CONTAINER_NAME":"some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99","CONTAINER_ID_FULL":"id9","testid":12}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <<EOF
+{"message":"this record should have pod metadata after retry","CONTAINER_NAME":"some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99","CONTAINER_ID_FULL":"id9","testid":13}
+{"message":"this record should process normally","CONTAINER_NAME":"some-prefix_container-name-10_pod-name-10_namespace-name-10_unused10_unused100","CONTAINER_ID_FULL":"id10","testid":14}
+EOF
+
+wait_queueempty
+sleep 5 # greater than busyretryinterval
+
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-test-error.log <<EOF
+{"message":"this record should have no pod metadata","CONTAINER_NAME":"some-prefix_container-name-11_pod-name-11-error_namespace-name-11_unused11_unused111","CONTAINER_ID_FULL":"id11","testid":15}
+{"message":"this record should process normally","CONTAINER_NAME":"some-prefix_container-name-12_pod-name-12_namespace-name-12_unused12_unused112","CONTAINER_ID_FULL":"id12","testid":16}
+EOF
+
+
+shutdown_when_empty
+if [ "${USE_VALGRIND:-false}" == "true" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown
+fi
+kill $BGPROCESS
+wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid
+
+rc=0
+# for each record in mmkubernetes-basic.out.json, see if the matching
+# record is found in $RSYSLOG_OUT_LOG
+$PYTHON -c 'import sys,json
+k8s_srv_port = sys.argv[3]
+expected = {}
+for hsh in json.load(open(sys.argv[1])):
+ if "testid" in hsh:
+ if "kubernetes" in hsh and "master_url" in hsh["kubernetes"]:
+ hsh["kubernetes"]["master_url"] = hsh["kubernetes"]["master_url"].format(k8s_srv_port=k8s_srv_port)
+ expected[hsh["testid"]] = hsh
+rc = 0
+actual = {}
+for line in open(sys.argv[2]):
+ hsh = json.loads(line)
+ if "testid" in hsh:
+ actual[hsh["testid"]] = hsh
+for testid,hsh in expected.items():
+ if not testid in actual:
+ print("Error: record for testid {0} not found in output".format(testid))
+ rc = 1
+ else:
+ for kk,vv in hsh.items():
+ if not kk in actual[testid]:
+ print("Error: key {0} in record for testid {1} not found in output".format(kk, testid))
+ rc = 1
+ elif not vv == actual[testid][kk]:
+ print("Error: value {0} for key {1} in record for testid {2} does not match the expected value {3}".format(str(actual[testid][kk]), kk, testid, str(vv)))
+ rc = 1
+sys.exit(rc)
+' $srcdir/mmkubernetes-basic.out.json $RSYSLOG_OUT_LOG $k8s_srv_port || rc=$?
+grep -q 'mmkubernetes: Not Found: the resource does not exist at url .*/namespaces\\\/namespace-name-6-not-found' $RSYSLOG_OUT_LOG || { echo fail1; rc=1; }
+grep -q 'mmkubernetes: Not Found: the resource does not exist at url .*/pods\\\/pod-name-7-not-found' $RSYSLOG_OUT_LOG || { echo fail2; rc=1; }
+grep -q 'mmkubernetes: Too Many Requests: the server is too heavily loaded to provide the data for the requested url .*/namespaces\\\/namespace-name-8-busy' $RSYSLOG_OUT_LOG || { echo fail3; rc=1; }
+grep -q 'mmkubernetes: Too Many Requests: the server is too heavily loaded to provide the data for the requested url .*/pods\\\/pod-name-9-busy' $RSYSLOG_OUT_LOG || { echo fail4; rc=1; }
+
+if [ -f ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log ] ; then
+ $PYTHON <${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log -c '
+import sys,json
+k8s_srv_port = sys.argv[1]
+expected = {"name": "mmkubernetes(http://localhost:{0})".format(k8s_srv_port),
+ "origin": "mmkubernetes", "recordseen": 14, "namespacemetadatasuccess": 11,
+ "namespacemetadatanotfound": 1, "namespacemetadatabusy": 1, "namespacemetadataerror": 0,
+ "podmetadatasuccess": 10, "podmetadatanotfound": 1, "podmetadatabusy": 2, "podmetadataerror": 1,
+ "namespacecachenumentries": 12, "podcachenumentries": 12, "namespacecachehits": 1,
+ "podcachehits": 0, "namespacecachemisses": 13, "podcachemisses": 14 }
+actual = {}
+for line in sys.stdin:
+ jstart = line.find("{")
+ if jstart >= 0:
+ hsh = json.loads(line[jstart:])
+ if hsh["origin"] == "mmkubernetes":
+ actual = hsh
+assert(expected == actual)
+' $k8s_srv_port || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log; }
+else
+ echo error: stats file ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log not found
+ rc=1
+fi
+
+if [ ${rc:-0} -ne 0 ]; then
+ echo
+ echo "FAIL: expected data not found. $RSYSLOG_OUT_LOG is:"
+ cat ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log
+ cat $RSYSLOG_OUT_LOG
+ cat ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/mmkubernetes-cache-expire-vg.sh b/tests/mmkubernetes-cache-expire-vg.sh
new file mode 100755
index 0000000..e19aeb3
--- /dev/null
+++ b/tests/mmkubernetes-cache-expire-vg.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# added 2018-04-06 by richm, released under ASL 2.0
+#
+# Note: on buildbot VMs (where there is no environment cleanup), the
+# kubernetes test server may be kept running if the script aborts or
+# is aborted (buildbot master failure!) for some reason. As such we
+# execute it under "timeout" control, which ensure it always is
+# terminated. It's not a 100% great method, but hopefully does the
+# trick. -- rgerhards, 2018-07-21
+#export RSYSLOG_DEBUG="debug"
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/mmkubernetes-cache-expire.sh
diff --git a/tests/mmkubernetes-cache-expire.out.expected b/tests/mmkubernetes-cache-expire.out.expected
new file mode 100644
index 0000000..b2dc92d
--- /dev/null
+++ b/tests/mmkubernetes-cache-expire.out.expected
@@ -0,0 +1,109 @@
+[{
+ "kubernetes": {
+ "namespace_id": "namespace-name1-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name1-id",
+ "labels": {
+ "custom_label": "pod-name1-label-value",
+ "deploymentconfig": "pod-name1-dc",
+ "component": "pod-name1-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name1-deployment"
+ },
+ "pod_name": "pod-name1",
+ "namespace_name": "namespace-name1",
+ "container_name": "container-name1",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id1"
+ },
+ "testid": 1,
+ "message": "msg1"
+},{
+ "kubernetes": {
+ "namespace_id": "namespace-name1-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name1-id",
+ "labels": {
+ "custom_label": "pod-name1-label-value",
+ "deploymentconfig": "pod-name1-dc",
+ "component": "pod-name1-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name1-deployment"
+ },
+ "pod_name": "pod-name1",
+ "namespace_name": "namespace-name1",
+ "container_name": "container-name1",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id1"
+ },
+ "testid": 2,
+ "message": "msg2"
+},{
+ "kubernetes": {
+ "namespace_id": "namespace-name1-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name1-id",
+ "labels": {
+ "custom_label": "pod-name1-label-value",
+ "deploymentconfig": "pod-name1-dc",
+ "component": "pod-name1-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name1-deployment"
+ },
+ "pod_name": "pod-name1",
+ "namespace_name": "namespace-name1",
+ "container_name": "container-name1",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id1"
+ },
+ "testid": 3,
+ "message": "msg3"
+},{
+ "kubernetes": {
+ "namespace_id": "namespace-name1-id",
+ "namespace_labels": {
+ "label_1_key": "label 1 value",
+ "label_with_empty_value": "",
+ "label_2_key": "label 2 value"
+ },
+ "creation_timestamp": "2018-04-09T21:56:39Z",
+ "pod_id": "pod-name1-id",
+ "labels": {
+ "custom_label": "pod-name1-label-value",
+ "deploymentconfig": "pod-name1-dc",
+ "component": "pod-name1-component",
+ "label_with_empty_value": "",
+ "deployment": "pod-name1-deployment"
+ },
+ "pod_name": "pod-name1",
+ "namespace_name": "namespace-name1",
+ "container_name": "container-name1",
+ "master_url": "http://localhost:{k8s_srv_port}"
+ },
+ "docker": {
+ "container_id": "id1"
+ },
+ "testid": 4,
+ "message": "msg4"
+}]
diff --git a/tests/mmkubernetes-cache-expire.sh b/tests/mmkubernetes-cache-expire.sh
new file mode 100755
index 0000000..fdb7226
--- /dev/null
+++ b/tests/mmkubernetes-cache-expire.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+# added 2018-04-06 by richm, released under ASL 2.0
+#
+# Note: on buildbot VMs (where there is no environment cleanup), the
+# kubernetes test server may be kept running if the script aborts or
+# is aborted (buildbot master failure!) for some reason. As such we
+# execute it under "timeout" control, which ensure it always is
+# terminated. It's not a 100% great method, but hopefully does the
+# trick. -- rgerhards, 2018-07-21
+. ${srcdir:=.}/diag.sh init
+check_command_available timeout
+pwd=$( pwd )
+k8s_srv_port=$( get_free_port )
+generate_conf
+cachettl=10
+add_conf '
+global(workDirectory="'$RSYSLOG_DYNNAME.spool'")
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'"$RSYSLOG_DYNNAME.spool"'/mmkubernetes-stats.log" log.syslog="off" format="cee")
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../contrib/mmkubernetes/.libs/mmkubernetes")
+
+template(name="mmk8s_template" type="list") {
+ property(name="$!all-json-plain")
+ constant(value="\n")
+}
+
+input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on")
+action(type="mmjsonparse" cookie="")
+action(type="mmkubernetes" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'"
+ cacheexpireinterval="1" cacheentryttl="'$cachettl'"
+ filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:.%.%container_hash:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log",
+ "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"]
+)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="mmk8s_template")
+'
+
+testsrv=mmk8s-test-server
+echo starting kubernetes \"emulator\"
+timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py $k8s_srv_port ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 &
+BGPROCESS=$!
+wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started
+echo background mmkubernetes_test_server.py process id is $BGPROCESS
+
+if [ "x${USE_VALGRIND:-NO}" == "xYES" ] ; then
+ export EXTRA_VALGRIND_SUPPRESSIONS="--suppressions=$srcdir/mmkubernetes.supp"
+ startup_vg
+else
+ startup
+ if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+ fi
+fi
+
+# add 3 logs - then wait $cachettl - the first log should prime the cache - the next two should be pulled from the cache
+cat > ${RSYSLOG_DYNNAME}.spool/pod-name.log <<EOF
+{"message":"msg1","CONTAINER_NAME":"some-prefix_container-name1_pod-name1_namespace-name1_unused1_unused11","CONTAINER_ID_FULL":"id1","testid":1}
+EOF
+sleep 2
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-name.log <<EOF
+{"message":"msg2","CONTAINER_NAME":"some-prefix_container-name1_pod-name1_namespace-name1_unused1_unused11","CONTAINER_ID_FULL":"id1","testid":2}
+EOF
+sleep 2
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-name.log <<EOF
+{"message":"msg3","CONTAINER_NAME":"some-prefix_container-name1_pod-name1_namespace-name1_unused1_unused11","CONTAINER_ID_FULL":"id1","testid":3}
+EOF
+sleep $cachettl
+# we should see
+# - namespacecachenumentries and podcachenumentries go from 0 to 1 then back to 0
+# - namespacecachehits and podcachehits go from 0 to 2
+# - namespacecachemisses and podcachemisses go from 0 to 1
+# add another record - should not be cached - should have expired
+cat >> ${RSYSLOG_DYNNAME}.spool/pod-name.log <<EOF
+{"message":"msg4","CONTAINER_NAME":"some-prefix_container-name1_pod-name1_namespace-name1_unused1_unused11","CONTAINER_ID_FULL":"id1","testid":4}
+EOF
+# we should see
+# - namespacecachenumentries and podcachenumentries back to 1
+# - namespacecachehits and podcachehits did not increase
+# - namespacecachemisses and podcachemisses increases
+
+# wait for the first batch of tests to complete
+wait_queueempty
+
+shutdown_when_empty
+if [ "x${USE_VALGRIND:-NO}" == "xYES" ] ; then
+ wait_shutdown_vg
+ check_exit_vg
+else
+ wait_shutdown
+fi
+kill $BGPROCESS
+wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid
+
+rc=0
+# for each record in mmkubernetes-cache-expire.out.json, see if the matching
+# record is found in $RSYSLOG_OUT_LOG
+$PYTHON -c 'import sys,json
+k8s_srv_port = sys.argv[3]
+expected = {}
+for hsh in json.load(open(sys.argv[1])):
+ if "testid" in hsh:
+ if "kubernetes" in hsh and "master_url" in hsh["kubernetes"]:
+ hsh["kubernetes"]["master_url"] = hsh["kubernetes"]["master_url"].format(k8s_srv_port=k8s_srv_port)
+ expected[hsh["testid"]] = hsh
+rc = 0
+actual = {}
+for line in open(sys.argv[2]):
+ hsh = json.loads(line)
+ if "testid" in hsh:
+ actual[hsh["testid"]] = hsh
+for testid,hsh in expected.items():
+ if not testid in actual:
+ print("Error: record for testid {0} not found in output".format(testid))
+ rc = 1
+ else:
+ for kk,vv in hsh.items():
+ if not kk in actual[testid]:
+ print("Error: key {0} in record for testid {1} not found in output".format(kk, testid))
+ rc = 1
+ elif not vv == actual[testid][kk]:
+ print("Error: value {0} for key {1} in record for testid {2} does not match the expected value {3}".format(str(actual[testid][kk]), kk, testid, str(vv)))
+ rc = 1
+sys.exit(rc)
+' $srcdir/mmkubernetes-cache-expire.out.expected $RSYSLOG_OUT_LOG $k8s_srv_port || rc=$?
+
+if [ -f ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log ] ; then
+ $PYTHON <${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log -c '
+import sys,json
+# key is recordseen, value is hash of stats for that record
+expectedvalues = {
+ 1: {"namespacecachenumentries": 1, "podcachenumentries": 1, "namespacecachehits": 0,
+ "podcachehits": 0, "namespacecachemisses": 1, "podcachemisses": 1},
+ 2: {"namespacecachenumentries": 1, "podcachenumentries": 1, "namespacecachehits": 0,
+ "podcachehits": 1, "namespacecachemisses": 1, "podcachemisses": 1},
+ 3: {"namespacecachenumentries": 1, "podcachenumentries": 1, "namespacecachehits": 0,
+ "podcachehits": 2, "namespacecachemisses": 1, "podcachemisses": 1},
+ 4: {"namespacecachenumentries": 1, "podcachenumentries": 1, "namespacecachehits": 0,
+ "podcachehits": 2, "namespacecachemisses": 2, "podcachemisses": 2},
+}
+for line in sys.stdin:
+ jstart = line.find("{")
+ if jstart >= 0:
+ hsh = json.loads(line[jstart:])
+ if hsh.get("origin") == "mmkubernetes" and hsh["recordseen"] in expectedvalues:
+ expected = expectedvalues[hsh["recordseen"]]
+ for key in expected:
+ if not expected[key] == hsh.get(key):
+ print("Error: expected value [%s] not equal to actual value [%s] in record [%d] for stat [%s]".format(
+ str(expected[key]), str(hsh[key]), hsh["recordseen"], key))
+' || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log; }
+else
+ echo error: stats file ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log not found
+ rc=1
+fi
+
+if [ ${rc:-0} -ne 0 ]; then
+ echo
+ echo "FAIL: expected data not found. $RSYSLOG_OUT_LOG is:"
+ cat ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log
+ cat $RSYSLOG_OUT_LOG
+ cat ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/mmkubernetes.supp b/tests/mmkubernetes.supp
new file mode 100644
index 0000000..6afd004
--- /dev/null
+++ b/tests/mmkubernetes.supp
@@ -0,0 +1,16 @@
+{
+ mmkubernetes: says hashtables are leaked at shutdown but they are freed - not sure what is the problem here
+ Memcheck:Leak
+ fun:malloc
+ fun:create_hashtable
+ obj:*
+ obj:*
+ fun:doModInit
+ fun:Load
+ fun:UseObj
+ fun:modInit
+ fun:doModInit
+ fun:Load
+ fun:modulesProcessCnf
+ fun:cnfDoObj
+}
diff --git a/tests/mmkubernetes_test_server.py b/tests/mmkubernetes_test_server.py
new file mode 100644
index 0000000..3f8c384
--- /dev/null
+++ b/tests/mmkubernetes_test_server.py
@@ -0,0 +1,165 @@
+# Used by the mmkubernetes tests
+# This is a simple http server which responds to kubernetes api requests
+# and responds with kubernetes api server responses
+# added 2018-04-06 by richm, released under ASL 2.0
+import os
+import json
+import sys
+
+try:
+ from http.server import HTTPServer, BaseHTTPRequestHandler
+except ImportError:
+ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+
+ns_template = '''{{
+ "kind": "Namespace",
+ "apiVersion": "v1",
+ "metadata": {{
+ "name": "{namespace_name}",
+ "selfLink": "/api/v1/namespaces/{namespace_name}",
+ "uid": "{namespace_name}-id",
+ "resourceVersion": "2988",
+ "creationTimestamp": "2018-04-09T21:56:39Z",
+ "labels": {{
+ "label.1.key":"label 1 value",
+ "label.2.key":"label 2 value",
+ "label.with.empty.value":""
+ }},
+ "annotations": {{
+ "k8s.io/description": "",
+ "k8s.io/display-name": "",
+ "k8s.io/node-selector": "",
+ "k8s.io/sa.scc.mcs": "s0:c9,c4",
+ "k8s.io/sa.scc.supplemental-groups": "1000080000/10000",
+ "k8s.io/sa.scc.uid-range": "1000080000/10000",
+ "quota.k8s.io/cluster-resource-override-enabled": "false"
+ }}
+ }},
+ "spec": {{
+ "finalizers": [
+ "openshift.io/origin",
+ "kubernetes"
+ ]
+ }},
+ "status": {{
+ "phase": "Active"
+ }}
+}}'''
+
+pod_template = '''{{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {{
+ "name": "{pod_name}",
+ "generateName": "{pod_name}-prefix",
+ "namespace": "{namespace_name}",
+ "selfLink": "/api/v1/namespaces/{namespace_name}/pods/{pod_name}",
+ "uid": "{pod_name}-id",
+ "resourceVersion": "3486",
+ "creationTimestamp": "2018-04-09T21:56:39Z",
+ "labels": {{
+ "component": "{pod_name}-component",
+ "deployment": "{pod_name}-deployment",
+ "deploymentconfig": "{pod_name}-dc",
+ "custom.label": "{pod_name}-label-value",
+ "label.with.empty.value":""
+ }},
+ "annotations": {{
+ "k8s.io/deployment-config.latest-version": "1",
+ "k8s.io/deployment-config.name": "{pod_name}-dc",
+ "k8s.io/deployment.name": "{pod_name}-deployment",
+ "k8s.io/custom.name": "custom value",
+ "annotation.with.empty.value":""
+ }}
+ }},
+ "status": {{
+ "phase": "Running",
+ "hostIP": "172.18.4.32",
+ "podIP": "10.128.0.14",
+ "startTime": "2018-04-09T21:57:39Z"
+ }}
+}}'''
+
+err_template = '''{{
+ "kind": "Status",
+ "apiVersion": "v1",
+ "metadata": {{
+
+ }},
+ "status": "Failure",
+ "message": "{kind} \\\"{objectname}\\\" {err}",
+ "reason": "{reason}",
+ "details": {{
+ "name": "{objectname}",
+ "kind": "{kind}"
+ }},
+ "code": {code}
+}}'''
+
+is_busy = False
+
+class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+
+ def do_GET(self):
+ # "http://localhost:18443/api/v1/namespaces/namespace-name2"
+ # parse url - either /api/v1/namespaces/$ns_name
+ # or
+ # /api/v1/namespaces/$ns_name/pods/$pod_name
+ global is_busy
+ comps = self.path.split('/')
+ status = 400
+ if len(comps) >= 5 and comps[1] == 'api' and comps[2] == 'v1' and comps[3] == 'namespaces':
+ resp = None
+ hsh = {'namespace_name':comps[4],'objectname':comps[4],'kind':'namespace'}
+ if len(comps) == 5: # namespace
+ resp_template = ns_template
+ status = 200
+ elif len(comps) == 7 and comps[5] == 'pods': # pod
+ hsh['pod_name'] = comps[6]
+ hsh['kind'] = 'pods'
+ hsh['objectname'] = hsh['pod_name']
+ resp_template = pod_template
+ status = 200
+ else:
+ resp = '{{"error":"do not recognize {0}"}}'.format(self.path)
+ if hsh['objectname'].endswith('not-found'):
+ status = 404
+ hsh['reason'] = 'NotFound'
+ hsh['err'] = 'not found'
+ resp_template = err_template
+ elif hsh['objectname'].endswith('busy'):
+ is_busy = not is_busy
+ if is_busy:
+ status = 429
+ hsh['reason'] = 'Busy'
+ hsh['err'] = 'server is too busy'
+ resp_template = err_template
+ elif hsh['objectname'].endswith('error'):
+ status = 500
+ hsh['reason'] = 'Error'
+ hsh['err'] = 'server is failing'
+ resp_template = err_template
+ if not resp:
+ hsh['code'] = status
+ resp = resp_template.format(**hsh)
+ else:
+ resp = '{{"error":"do not recognize {0}"}}'.format(self.path)
+ if not status == 200:
+ self.log_error(resp)
+ self.send_response(status)
+ self.end_headers()
+ self.wfile.write(json.dumps(json.loads(resp), separators=(',',':')).encode())
+
+port = int(sys.argv[1])
+
+httpd = HTTPServer(('localhost', port), SimpleHTTPRequestHandler)
+
+# write "started" to file named in argv[3]
+with open(sys.argv[3], "w") as ff:
+ ff.write("started\n")
+
+# write pid to file named in argv[2]
+with open(sys.argv[2], "w") as ff:
+ ff.write('{0}\n'.format(os.getpid()))
+
+httpd.serve_forever()
diff --git a/tests/mmnormalize_parsesuccess-vg.sh b/tests/mmnormalize_parsesuccess-vg.sh
new file mode 100755
index 0000000..f4f889f
--- /dev/null
+++ b/tests/mmnormalize_parsesuccess-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-11 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/mmnormalize_parsesuccess.sh
diff --git a/tests/mmnormalize_parsesuccess.sh b/tests/mmnormalize_parsesuccess.sh
new file mode 100755
index 0000000..eb945ef
--- /dev/null
+++ b/tests/mmnormalize_parsesuccess.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2019-04-11 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+
+action(type="mmnormalize" rule=
+ ["rule=: %-:char-to{\"extradata\":\":\"}%:00000000:",
+ "rule=: %-:char-to{\"extradata\":\":\"}%:00000010:"] )
+
+if not ($rawmsg contains "rsyslog") then
+ if $parsesuccess == "OK" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ else
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.failed")
+'
+startup
+injectmsg 0 20
+shutdown_when_empty
+wait_shutdown
+content_check "msgnum:00000000:" $RSYSLOG_OUT_LOG
+content_check "msgnum:00000010:" $RSYSLOG_OUT_LOG
+content_check "msgnum:00000001:" $RSYSLOG_DYNNAME.failed
+content_check "msgnum:00000012:" $RSYSLOG_DYNNAME.failed
+exit_test
diff --git a/tests/mmnormalize_processing_test1.sh b/tests/mmnormalize_processing_test1.sh
new file mode 100755
index 0000000..c421adb
--- /dev/null
+++ b/tests/mmnormalize_processing_test1.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+
+export TZ=TEST+02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n")
+template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n")
+
+template(name="t_fromhost-ip" type="string" string="%fromhost-ip%")
+template(name="t_analytics_msg_default" type="string" string="%$!v_analytics_prefix%%rawmsg-after-pri%")
+template(name="t_analytics_tag_prefix" type="string" string="%$!v_tag%: ")
+template(name="t_analytics_msg_normalized" type="string" string="%timereported% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics_msg_normalized_vc" type="string" string="%timereported:1:6% %$year% %timereported:8:$% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics" type="string" string="[][][%$!v_fromhost-ip%][%timestamp:::date-unixtimestamp%][] %$!v_analytics_msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on")
+ if ($!v_file == "") then {
+ set $!v_file=$!v_tag;
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record")
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_path")
+
+ set $!v_forward="PCI";
+
+ if ($!v_forward contains "PCI") then {
+ if ($!v_fromhost-ip == "") then {
+ set $!v_fromhost-ip=exec_template("t_fromhost-ip");
+ }
+ if ($!v_msg == "" or $!v_tag == "") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_default");
+ } else {
+ if ($!v_analytics_prefix == "") then {
+ set $!v_analytics_prefix=exec_template("t_analytics_tag_prefix");
+ }
+ if ($!v_hostname == "") then { # needed for vCenter logs with custom hostname
+ set $!v_hostname=exec_template("t_fromhost-ip");
+ }
+ if ($!v_exception == "VC") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized_vc");
+ } else {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized");
+ }
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_analytics")
+ }
+}
+'
+FAKETIME='2017-03-08 12:53:47' startup
+tcpflood -m1 -M "\"<37>1 2017-03-08T12:53:47+02:00 Host1.domain.com Security - - - SER1 M01 WIN [AUF] Wed Mar 08 11:53:48 2017: N\A/Security/Host1.domain.com/Microsoft-Windows-Security-Auditing (5152) - message\""
+shutdown_when_empty
+wait_shutdown
+echo '2017-03-08T12:53:47+02:00 2017-03-08T12:53:47+02:00 Host1.domain.com Security [AUF] Wed Mar 08 11:53:48 2017: N\A/Security/Host1.domain.com/Microsoft-Windows-Security-Auditing (5152) - message
+/sb/logs/incoming/2017/03/08/svc_SER1/ret_M01/os_WIN/127.0.0.1/r_relay1/security.gz
+[][][127.0.0.1][1488970427][] Mar 8 12:53:47 127.0.0.1 EvntSLog: [AUF] Wed Mar 08 11:53:48 2017: N\A/Security/Host1.domain.com/Microsoft-Windows-Security-Auditing (5152) - message' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_processing_test2.sh b/tests/mmnormalize_processing_test2.sh
new file mode 100755
index 0000000..7e377fb
--- /dev/null
+++ b/tests/mmnormalize_processing_test2.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+
+export TZ=TEST+02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n")
+template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n")
+
+template(name="t_fromhost-ip" type="string" string="%fromhost-ip%")
+template(name="t_analytics_msg_default" type="string" string="%$!v_analytics_prefix%%rawmsg-after-pri%")
+template(name="t_analytics_tag_prefix" type="string" string="%$!v_tag%: ")
+template(name="t_analytics_msg_normalized" type="string" string="%timereported% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics_msg_normalized_vc" type="string" string="%timereported:1:6% %$year% %timereported:8:$% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics" type="string" string="[][][%$!v_fromhost-ip%][%timestamp:::date-unixtimestamp%][] %$!v_analytics_msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on")
+ if ($!v_file == "") then {
+ set $!v_file=$!v_tag;
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record")
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_path")
+
+ set $!v_forward="PCI";
+
+ if ($!v_forward contains "PCI") then {
+ if ($!v_fromhost-ip == "") then {
+ set $!v_fromhost-ip=exec_template("t_fromhost-ip");
+ }
+ if ($!v_msg == "" or $!v_tag == "") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_default");
+ } else {
+ if ($!v_analytics_prefix == "") then {
+ set $!v_analytics_prefix=exec_template("t_analytics_tag_prefix");
+ }
+ if ($!v_hostname == "") then { # needed for vCenter logs with custom hostname
+ set $!v_hostname=exec_template("t_fromhost-ip");
+ }
+ if ($!v_exception == "VC") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized_vc");
+ } else {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized");
+ }
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_analytics")
+ }
+}
+'
+FAKETIME='2017-03-08 12:18:47' startup
+tcpflood -m1 -M "\"<166>2017-03-08T12:18:47.165Z Host2.domain.com Process1: [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback\""
+shutdown_when_empty
+wait_shutdown
+echo '2017-03-08T12:18:47.165Z 2017-03-08T12:18:47.165Z Host2.domain.com Process1 [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback
+/sb/logs/incoming/2017/03/08/svc_SER2/ret_Y01/os_ESX/127.0.0.1/r_relay1/esx.gz
+[][][127.0.0.1][1488975527][] Mar 8 12:18:47 127.0.0.1 Process1: [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_processing_test3.sh b/tests/mmnormalize_processing_test3.sh
new file mode 100755
index 0000000..c81dfcd
--- /dev/null
+++ b/tests/mmnormalize_processing_test3.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+
+export TZ=TEST+01:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n")
+template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n")
+
+template(name="t_fromhost-ip" type="string" string="%fromhost-ip%")
+template(name="t_analytics_msg_default" type="string" string="%$!v_analytics_prefix%%rawmsg-after-pri%")
+template(name="t_analytics_tag_prefix" type="string" string="%$!v_tag%: ")
+template(name="t_analytics_msg_normalized" type="string" string="%timereported% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics_msg_normalized_vc" type="string" string="%timereported:1:6% %$year% %timereported:8:$% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%")
+template(name="t_analytics" type="string" string="[][][%$!v_fromhost-ip%][%timestamp:::date-unixtimestamp%][] %$!v_analytics_msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on")
+ if ($!v_file == "") then {
+ set $!v_file=$!v_tag;
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record")
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_path")
+
+ set $!v_forward="PCI";
+
+ if ($!v_forward contains "PCI") then {
+ if ($!v_fromhost-ip == "") then {
+ set $!v_fromhost-ip=exec_template("t_fromhost-ip");
+ }
+ if ($!v_msg == "" or $!v_tag == "") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_default");
+ } else {
+ if ($!v_analytics_prefix == "") then {
+ set $!v_analytics_prefix=exec_template("t_analytics_tag_prefix");
+ }
+ if ($!v_hostname == "") then { # needed for vCenter logs with custom hostname
+ set $!v_hostname=exec_template("t_fromhost-ip");
+ }
+ if ($!v_exception == "VC") then {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized_vc");
+ } else {
+ set $!v_analytics_msg=exec_template("t_analytics_msg_normalized");
+ }
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_analytics")
+ }
+}
+'
+FAKETIME='2017-03-08 14:23:51' startup
+tcpflood -m1 -M "\"<182>Mar 8 14:23:51 host3 audispd: {SER3.local6 Y01 LNX [SRCH ALRT DASH REPT ANOM]} node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721):\""
+shutdown_when_empty
+wait_shutdown
+echo '2017-03-08T14:23:51-01:00 2017-03-08T14:23:51-01:00 host3 audispd node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721):
+/sb/logs/incoming/2017/03/08/svc_SER3/ret_Y01/os_LNX/127.0.0.1/r_relay1/local6.gz
+[][][127.0.0.1][1488986631][] Mar 8 14:23:51 host3 audispd: node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721):' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_processing_test4.sh b/tests/mmnormalize_processing_test4.sh
new file mode 100755
index 0000000..9362ad1
--- /dev/null
+++ b/tests/mmnormalize_processing_test4.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n")
+template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n")
+
+ruleset(name="ruleset1") {
+ action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on")
+ if ($!v_file == "") then {
+ set $!v_file=$!v_tag;
+ }
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record")
+ action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_path")
+
+}
+'
+FAKETIME='2017-03-08 14:56:37' startup
+tcpflood -m1 -M "\"<187>Mar 8 14:56:37 host4 Process2: {SER4.local7 Y01 LNX [SRCH ALRT DASH REPT ANOM]} (/sb/env/logs/dir1/dir2/log_20170308.log) in 1: X/c79RgpDtrva5we84XHTg== (String)\""
+shutdown_when_empty
+wait_shutdown
+echo '2017-03-08T14:56:37+02:00 2017-03-08T14:56:37+02:00 host4 Process2 in 1: X/c79RgpDtrva5we84XHTg== (String)
+/sb/logs/incoming/2017/03/08/svc_SER4/ret_Y01/os_LNX/127.0.0.1/r_relay1/sb/env/logs/dir1/dir2/log_20170308.log.gz' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_regex.sh b/tests/mmnormalize_regex.sh
new file mode 100755
index 0000000..d6834d7
--- /dev/null
+++ b/tests/mmnormalize_regex.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2014-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmnormalize_regex.sh\]: test for mmnormalize regex field_type
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="hosts_and_ports" type="string" string="host and port list: %$!hps%\n")
+
+template(name="paths" type="string" string="%$!fragments% %$!user%\n")
+template(name="numbers" type="string" string="nos: %$!some_nos%\n")
+
+module(load="../plugins/mmnormalize/.libs/mmnormalize" allowRegex="on")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_regex.rulebase`)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="hosts_and_ports")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/regex_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'host and port list: 192.168.1.2:80, 192.168.1.3, 192.168.1.4:443, 192.168.1.5'
+exit_test
diff --git a/tests/mmnormalize_regex_defaulted.sh b/tests/mmnormalize_regex_defaulted.sh
new file mode 100755
index 0000000..eb3d760
--- /dev/null
+++ b/tests/mmnormalize_regex_defaulted.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2014-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmnormalize_regex_defaulted.sh\]: test for mmnormalize regex field_type, with allow_regex defaulted
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="hosts_and_ports" type="string" string="host and port list: %$!hps%\n")
+
+template(name="paths" type="string" string="%$!fragments% %$!user%\n")
+template(name="numbers" type="string" string="nos: %$!some_nos%\n")
+
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_regex.rulebase`)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="hosts_and_ports")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/regex_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+assert_content_missing '192' #several ips in input are 192.168.1.0/24
+exit_test
diff --git a/tests/mmnormalize_regex_disabled.sh b/tests/mmnormalize_regex_disabled.sh
new file mode 100755
index 0000000..9eabbcc
--- /dev/null
+++ b/tests/mmnormalize_regex_disabled.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2014-11-17 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmnormalize_regex_disabled.sh\]: test for mmnormalize regex field_type with allow_regex disabled
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="hosts_and_ports" type="string" string="host and port list: %$!hps%\n")
+
+template(name="paths" type="string" string="%$!fragments% %$!user%\n")
+template(name="numbers" type="string" string="nos: %$!some_nos%\n")
+
+module(load="../plugins/mmnormalize/.libs/mmnormalize" allowRegex="off")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_regex.rulebase`)
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="hosts_and_ports")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/regex_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+assert_content_missing '192' #several ips in input are 192.168.1.0/24
+exit_test
diff --git a/tests/mmnormalize_rule_from_array.sh b/tests/mmnormalize_rule_from_array.sh
new file mode 100755
index 0000000..43f52bc
--- /dev/null
+++ b/tests/mmnormalize_rule_from_array.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="norm")
+
+template(name="outfmt" type="string" string="%hostname% %syslogtag%\n")
+
+ruleset(name="norm") {
+ action(type="mmnormalize" rule=["rule=: no longer listening on %ip:ipv4%#%port:number%", "rule=: is sending messages on %ip:ipv4%", "rule=: apfelkuchen"])
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 ubuntu tag1: no longer listening on 127.168.0.1#10514\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 debian tag2: is sending messages on 127.168.0.1\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 centos tag3: apfelkuchen\""
+shutdown_when_empty
+wait_shutdown
+echo 'ubuntu tag1:
+debian tag2:
+centos tag3:' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_rule_from_string.sh b/tests/mmnormalize_rule_from_string.sh
new file mode 100755
index 0000000..511da15
--- /dev/null
+++ b/tests/mmnormalize_rule_from_string.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="norm")
+
+template(name="outfmt" type="string" string="%hostname% %syslogtag%\n")
+
+ruleset(name="norm") {
+ action(type="mmnormalize" useRawMsg="on" rule="rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\""
+tcpflood -m1 -M "\"debian tag2: no longer listening on 127.168.0.2#10514\""
+tcpflood -m1 -M "\"centos tag3: no longer listening on 192.168.0.1#10514\""
+shutdown_when_empty
+wait_shutdown
+echo 'ubuntu tag1:
+debian tag2:
+centos tag3:' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmnormalize_tokenized.sh b/tests/mmnormalize_tokenized.sh
new file mode 100755
index 0000000..55b8db2
--- /dev/null
+++ b/tests/mmnormalize_tokenized.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# added 2014-11-03 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmnormalize_tokenized.sh\]: test for mmnormalize tokenized field_type
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="ips" type="string" string="%$.ips%\n")
+
+template(name="paths" type="string" string="%$!fragments% %$!user%\n")
+template(name="numbers" type="string" string="nos: %$!some_nos%\n")
+
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_tokenized.rulebase`)
+if ( $!only_ips != "" ) then {
+ set $.ips = $!only_ips;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips")
+} else if ( $!local_ips != "" ) then {
+ set $.ips = $!local_ips;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips")
+} else if ( $!external_ips != "" ) then {
+ set $.ips = $!external_ips;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips")
+} else if ( $!some_nos != "" ) then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="numbers")
+} else {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="paths")
+}
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/tokenized_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+cp $RSYSLOG_OUT_LOG /tmp/
+content_check '[ "10.20.30.40", "50.60.70.80", "90.100.110.120", "130.140.150.160" ]'
+content_check '[ "192.168.1.2", "192.168.1.3", "192.168.1.4" ]'
+content_check '[ "10.20.30.40", "50.60.70.80", "190.200.210.220" ]'
+content_check '[ "\/bin", "\/usr\/local\/bin", "\/usr\/bin" ] foo'
+content_check '[ [ [ "10" ] ], [ [ "20" ], [ "30", "40", "50" ], [ "60", "70", "80" ] ], [ [ "90" ], [ "100" ] ] ]'
+exit_test
diff --git a/tests/mmnormalize_variable.sh b/tests/mmnormalize_variable.sh
new file mode 100755
index 0000000..4670d8e
--- /dev/null
+++ b/tests/mmnormalize_variable.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2014-10-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[mmnormalize_variable.sh\]: basic test for mmnormalize module variable-support
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="h:%$!hr% m:%$!min% s:%$!sec%\n")
+
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="time_fragment" type="list") {
+ property(name="msg" regex.Expression="[0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]+" regex.Type="ERE" regex.Match="0")
+}
+
+set $.time_frag = exec_template("time_fragment");
+
+action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_variable.rulebase` variable="$.time_frag")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "h:13 m:20 s:18"
+exit_test
diff --git a/tests/mmpstrucdata-case.sh b/tests/mmpstrucdata-case.sh
new file mode 100755
index 0000000..97a86b5
--- /dev/null
+++ b/tests/mmpstrucdata-case.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# the goal here is to detect memleaks when structured data is not
+# correctly parsed.
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2015-04-30
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata")
+module(load="../plugins/imtcp/.libs/imtcp")
+
+template(name="outfmt" type="string" string="SD:%$!RFC5424-SD%\n")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmpstrucdata" sd_name.lowercase="off")
+
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m100 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 eventID=\\\"1011\\\"] valid structured data\""
+shutdown_when_empty
+wait_shutdown
+content_check_with_count eventID 100
+exit_test
diff --git a/tests/mmpstrucdata-escaping.sh b/tests/mmpstrucdata-escaping.sh
new file mode 100755
index 0000000..34dfc9a
--- /dev/null
+++ b/tests/mmpstrucdata-escaping.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2019-10-07
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata")
+
+template(name="outfmt" type="string" string="%$!rfc5424-sd%\n")
+
+action(type="mmpstrucdata")
+if $msg contains "TESTMESSAGE" then
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal '<85>1 2019-08-27T13:02:58.000+01:00 A/B-896747 ABC LMBNI SUCCESS [origin software="ABC" swVersion="47.1"][ABC@32473 eventType="XYZ:IPIP,9:\"free -m\";" remoteIp="192.0.2.1" singleTick="D'"'"'E" bracket="1\]2"] TESTMESSAGE'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='{ "origin": { "software": "ABC", "swversion": "47.1" }, "abc@32473": { "eventtype": "XYZ:IPIP,9:\"free -m\";", "remoteip": "192.0.2.1", "singletick": "D'"'"'E", "bracket": "1]2" } }'
+cmp_exact
+exit_test
diff --git a/tests/mmpstrucdata-invalid-vg.sh b/tests/mmpstrucdata-invalid-vg.sh
new file mode 100755
index 0000000..7b03d02
--- /dev/null
+++ b/tests/mmpstrucdata-invalid-vg.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# the goal here is to detect memleaks when structured data is not
+# correctly parsed.
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2015-04-30
+. ${srcdir:=.}/diag.sh init
+#skip_platform "FreeBSD" "This test currently does not work on FreeBSD."
+export USE_VALGRIND="YES" # this test only makes sense with valgrind enabled
+# uncomment below to set special valgrind options
+#export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all"
+
+generate_conf
+add_conf '
+module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata")
+module(load="../plugins/imtcp/.libs/imtcp")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmpstrucdata")
+if $msg contains "msgnum" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+# we use different message counts as this hopefully aids us
+# in finding which sample is leaking. For this, check the number
+# of blocks lost and see what set they match.
+tcpflood -m100 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM] invalid structured data!\""
+tcpflood -m200 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM ] invalid structured data!\""
+tcpflood -m300 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM= ] invalid structured data!\""
+tcpflood -m400 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 = ] invalid structured data!\""
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/mmpstrucdata-vg.sh b/tests/mmpstrucdata-vg.sh
new file mode 100755
index 0000000..a9ab7d4
--- /dev/null
+++ b/tests/mmpstrucdata-vg.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2013-11-22
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[mmpstrucdata.sh\]: testing mmpstrucdata
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata")
+module(load="../plugins/imtcp/.libs/imtcp")
+
+template(name="outfmt" type="string" string="%$!rfc5424-sd!tcpflood@32473!msgnum%\n")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmpstrucdata")
+if $msg contains "msgnum" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup_vg
+sleep 1
+tcpflood -m100 -y
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 99
+exit_test
diff --git a/tests/mmpstrucdata.sh b/tests/mmpstrucdata.sh
new file mode 100755
index 0000000..79e3403
--- /dev/null
+++ b/tests/mmpstrucdata.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2013-11-22
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata")
+module(load="../plugins/imtcp/.libs/imtcp")
+
+template(name="outfmt" type="string" string="%$!rfc5424-sd!tcpflood@32473!msgnum%\n")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmpstrucdata")
+if $msg contains "msgnum" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m100 -y
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/mmrm1stspace-basic.sh b/tests/mmrm1stspace-basic.sh
new file mode 100755
index 0000000..0b070e3
--- /dev/null
+++ b/tests/mmrm1stspace-basic.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+module(load="../plugins/mmrm1stspace/.libs/mmrm1stspace")
+template(name="outfmt" type="string" string="-%msg%-\n")
+action(type="mmrm1stspace")
+:syslogtag, contains, "tag" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag4:\""
+shutdown_when_empty
+wait_shutdown
+echo '-msgnum:1-
+- msgnum:2-
+-msgnum:3-
+--' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/mmtaghostname_server.sh b/tests/mmtaghostname_server.sh
new file mode 100755
index 0000000..de8ab85
--- /dev/null
+++ b/tests/mmtaghostname_server.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2016-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/mmtaghostname/.libs/mmtaghostname")
+global(localhostname="frontAPP")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+template(name="test" type="string" string="tag: %syslogtag%, server: %hostname%, msg: %msg%\n")
+ruleset(name="ruleset") {
+ action(type="mmtaghostname" forcelocalhostname="on")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189>1 2019-03-03T16:09:56.185+00:00 server app 123.4 msgid - %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\""
+shutdown_when_empty
+wait_shutdown
+echo 'tag: app[123.4], server: frontAPP, msg: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
+
diff --git a/tests/mmtaghostname_tag.sh b/tests/mmtaghostname_tag.sh
new file mode 100755
index 0000000..a63425a
--- /dev/null
+++ b/tests/mmtaghostname_tag.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2016-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/mmtaghostname/.libs/mmtaghostname")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+template(name="test" type="string" string="tag: %syslogtag%, server: %hostname%, msg: %msg%\n")
+ruleset(name="ruleset") {
+ action(type="mmtaghostname" tag="source-imtcp")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189>1 2019-03-03T16:09:56.185+00:00 server app 123.4 msgid - %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\""
+shutdown_when_empty
+wait_shutdown
+echo 'tag: source-imtcp, server: server, msg: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
+
diff --git a/tests/mmutf8fix_no_error.sh b/tests/mmutf8fix_no_error.sh
new file mode 100755
index 0000000..549c330
--- /dev/null
+++ b/tests/mmutf8fix_no_error.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# add 2018-10-10 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/mmutf8fix/.libs/mmutf8fix")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing")
+
+ruleset(name="testing") {
+ action(type="mmutf8fix" replacementChar="?")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}'
+
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: this is a test message
+<129>Mar 10 01:00:00 172.20.245.8 tag: valid mixed length UTF-8: foo bar řÃꙀ䆑ðŒ°ðž¨
+<129>Mar 10 01:00:00 172.20.245.8 tag: valid 2-byte UTF-8: řÃ
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x00) 0xC0 0x80: 
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x2E) 0xC0 0xAE: À®
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x4E) 0xC1 0x8E: ÁŽ
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation) 0xC0 0xEE: Àî
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0x2E: À.
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0xC2 0xA7: ˤ
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, not enough bytes) 0xC0: À
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation) 0xC2 0xEE: Âî
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0x2E: Â.
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0xC2 0xA7: §
+<129>Mar 10 01:00:00 172.20.245.8 tag: valid 3-byte UTF-8: Ꙁ䆑
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (overlong = 0x2E) 0xE0 0x80 0xAE: à€®
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (overlong = 0x2E0) 0xE0 0x8B 0xA0: à‹ 
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation) 0xE0 0xE2 0x81: àâ
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0x41 0xA7: àA§
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0xC2 0xA7: à§
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation) 0xE1 0x85 0xE1: á…á
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0x41: á…A
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0xD5 0xB6: á…Õ¶
+<129>Mar 10 01:00:00 172.20.245.8 tag: valid 4-byte UTF-8: ðŒ°ðž¨
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E) 0xF0 0x80 0x80 0xAE: ð€€®
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E0) 0xF0 0x80 0x8B 0xA0: ð€‹ 
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E00) 0xF0 0x82 0xB8 0x80: ð‚¸€
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0x41 0xC5 0xB0: ðAÅ°
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0xEC 0x8C 0xB0: ð쌰
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xF0 0x90 0xC5 0xB0: ðÅ°
+<129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 4rd continuation but valid utf8) 0xF0 0x90 0xC5 0x2E: ðŒ.
+<129>Mar 10 01:00:00 172.20.245.8 tag: special characters: ??%%,,..
+<129>Mar 10 01:00:00 172.20.245.8 tag: numbers: 1234567890\""
+
+shutdown_when_empty
+wait_shutdown
+echo ' this is a test message
+ valid mixed length UTF-8: foo bar řÃꙀ䆑ðŒ°ðž¨
+ valid 2-byte UTF-8: řÃ
+ invalid 2-byte UTF-8 (overlong = 0x00) 0xC0 0x80: ??
+ invalid 2-byte UTF-8 (overlong = 0x2E) 0xC0 0xAE: ??
+ invalid 2-byte UTF-8 (overlong = 0x4E) 0xC1 0x8E: ??
+ invalid 2-byte UTF-8 (overlong, invalid continuation) 0xC0 0xEE: ??
+ invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0x2E: ?.
+ invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0xC2 0xA7: ?§
+ invalid 2-byte UTF-8 (overlong, not enough bytes) 0xC0: ?
+ invalid 2-byte UTF-8 (invalid continuation) 0xC2 0xEE: ??
+ invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0x2E: ?.
+ invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0xC2 0xA7: ?§
+ valid 3-byte UTF-8: Ꙁ䆑
+ invalid 3-byte UTF-8 (overlong = 0x2E) 0xE0 0x80 0xAE: ???
+ invalid 3-byte UTF-8 (overlong = 0x2E0) 0xE0 0x8B 0xA0: ???
+ invalid 3-byte UTF-8 (invalid 2nd continuation) 0xE0 0xE2 0x81: ???
+ invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0x41 0xA7: ?A?
+ invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0xC2 0xA7: ?§
+ invalid 3-byte UTF-8 (invalid 3rd continuation) 0xE1 0x85 0xE1: ???
+ invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0x41: ??A
+ invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0xD5 0xB6: ??Õ¶
+ valid 4-byte UTF-8: ðŒ°ðž¨
+ invalid 4-byte UTF-8 (overlong = 0x2E) 0xF0 0x80 0x80 0xAE: ????
+ invalid 4-byte UTF-8 (overlong = 0x2E0) 0xF0 0x80 0x8B 0xA0: ????
+ invalid 4-byte UTF-8 (overlong = 0x2E00) 0xF0 0x82 0xB8 0x80: ????
+ invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0x41 0xC5 0xB0: ?AÅ°
+ invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0xEC 0x8C 0xB0: ?쌰
+ invalid 4-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xF0 0x90 0xC5 0xB0: ??Å°
+ invalid 4-byte UTF-8 (invalid 4rd continuation but valid utf8) 0xF0 0x90 0xC5 0x2E: ???.
+ special characters: ??%%,,..
+ numbers: 1234567890' > "$RSYSLOG_OUT_LOG.expect"
+
+if ! cmp "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG diff:"
+ # Use LANG=C for binary matching
+ LANG=C diff --text -u "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
+
+exit 0
diff --git a/tests/msg-deadlock-headerless-noappname.sh b/tests/msg-deadlock-headerless-noappname.sh
new file mode 100755
index 0000000..1ac847a
--- /dev/null
+++ b/tests/msg-deadlock-headerless-noappname.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# this checks against a situation where a deadlock was caused in
+# practice.
+# added 2018-10-17 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="input")
+
+ruleset(name="input") {
+ set $!tag = $app-name;
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+tcpflood -p $TCPFLOOD_PORT -M "[2018-10-16 09:59:13] ping pong"
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+exit_test
diff --git a/tests/msgdup.sh b/tests/msgdup.sh
new file mode 100755
index 0000000..9a94987
--- /dev/null
+++ b/tests/msgdup.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This tests the border case that a message is exactly as large as the default
+# buffer size (101 chars) and is reduced in size afterwards. This has been seen
+# in practice.
+# see also https://github.com/rsyslog/rsyslog/issues/1658
+# Copyright (C) 2017 by Rainer Gerhards, released under ASL 2.0 (2017-07-11)
+. ${srcdir:=.}/diag.sh init
+check_logger_has_option_d
+generate_conf
+add_conf '
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="rs" queue.type="LinkedList") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ stop
+}
+
+*.=notice call rs
+'
+startup
+logger -d -u $RSYSLOG_DYNNAME-testbench_socket -t RSYSLOG_TESTBENCH 'test 01234567890123456789012345678901234567890123456789012345
+' #Note: LF at end of message is IMPORTANT, it is bug triggering condition
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+export EXPECTED=" test 01234567890123456789012345678901234567890123456789012345"
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/msgdup_props.sh b/tests/msgdup_props.sh
new file mode 100755
index 0000000..f9ea448
--- /dev/null
+++ b/tests/msgdup_props.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# This test checks the MsgDup() properly copies all properties.
+# added 2019-06-26 by Rgerhards. Released under ASL 2.0
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+template(name="all_properties" type="list") {
+ property(format="jsonf" name="fromhost") constant(value="\n")
+ property(format="jsonf" name="fromhost-ip") constant(value="\n")
+ property(format="jsonf" name="hostname") constant(value="\n")
+ property(format="jsonf" name="inputname") constant(value="\n")
+ property(format="jsonf" name="msg") constant(value="\n")
+ property(format="jsonf" name="msgid") constant(value="\n")
+ property(format="jsonf" name="$!" outname="globalvar") constant(value="\n")
+ property(format="jsonf" name="$." outname="localvar") constant(value="\n")
+ property(format="jsonf" name="pri") constant(value="\n")
+ property(format="jsonf" name="pri-text") constant(value="\n")
+ property(format="jsonf" name="procid") constant(value="\n")
+ property(format="jsonf" name="protocol-version") constant(value="\n")
+ property(format="jsonf" name="rawmsg-after-pri") constant(value="\n")
+ property(format="jsonf" name="rawmsg") constant(value="\n")
+ property(format="jsonf" name="structured-data") constant(value="\n")
+ property(format="jsonf" name="syslogtag") constant(value="\n")
+ property(format="jsonf" name="timegenerated") constant(value="\n")
+ property(format="jsonf" name="timegenerated" dateformat="rfc3339") constant(value="\n")
+ property(format="jsonf" name="timereported") constant(value="\n")
+ property(format="jsonf" name="timereported" dateformat="rfc3339") constant(value="\n")
+}
+
+ruleset(name="rs_with_queue" queue.type="LinkedList" queue.size="10000") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="all_properties")
+ # works on a duplicated message thanks to the queue
+}
+
+set $!var="msg var";
+set $.var="local var";
+if $msg contains "msgnum:" then {
+ call rs_with_queue
+ action(type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="all_properties")
+ # works on original, non-duplicated, message
+}
+'
+startup
+injectmsg 0 1 # we need only one message to check the properties
+shutdown_when_empty
+wait_shutdown
+
+cmp "$RSYSLOG_OUT_LOG" "$RSYSLOG2_OUT_LOG"
+if [ $? -ne 0 ]; then
+ printf 'ERROR: output files do not match!\n'
+ printf '################# %s is:\n' "$RSYSLOG_OUT_LOG"
+ cat -n "$RSYSLOG_OUT_LOG"
+ printf '################# %s is:\n' "$RSYSLOG2_OUT_LOG"
+ cat -n "$RSYSLOG2_OUT_LOG"
+ printf '\n#################### diff is:\n'
+ diff "$RSYSLOG_OUT_LOG" "$RSYSLOG2_OUT_LOG"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/msgvar-concurrency-array-event.tags.sh b/tests/msgvar-concurrency-array-event.tags.sh
new file mode 100755
index 0000000..dfa6ac3
--- /dev/null
+++ b/tests/msgvar-concurrency-array-event.tags.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test concurrency of message variables
+# Added 2015-11-03 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+export TCPFLOOD_EXTRA_OPTS="-M'msg:msg: 1:2, 3:4, 5:6, 7:8 b test'"
+echo ===============================================================================
+echo \[msgvar-concurrency-array-event.tags.sh\]: testing concurrency of local variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$!%\n")
+
+#action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList")
+action(type="mmnormalize" ruleBase="testsuites/msgvar-concurrency-array-event.tags.rulebase")
+if $msg contains "msg:" then {
+# set $!tree!here!nbr = field($msg, 58, 2); # Delimiter = :
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList")
+ set $!tree!here!save = $!tree!here!nbr;
+ set $!tree!here!nbr = "";
+ set $!tree!here!nbr = $!tree!here!save;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" queue.type="linkedList")
+}
+'
+startup
+sleep 1
+tcpflood -m500000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+#seq_check 0 499999
+exit_test
diff --git a/tests/msgvar-concurrency-array.sh b/tests/msgvar-concurrency-array.sh
new file mode 100755
index 0000000..ef6ae30
--- /dev/null
+++ b/tests/msgvar-concurrency-array.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test concurrency of message variables
+# Added 2015-11-03 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+export TCPFLOOD_EXTRA_OPTS="-M'msg:msg: 1:2, 3:4, 5:6, 7:8 b test'"
+echo ===============================================================================
+echo \[msgvar-concurrency-array.sh\]: testing concurrency of local variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/mmnormalize/.libs/mmnormalize")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$!%\n")
+
+#action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList")
+action(type="mmnormalize" ruleBase="testsuites/msgvar-concurrency-array.rulebase")
+if $msg contains "msg:" then {
+# set $!tree!here!nbr = field($msg, 58, 2); # Delimiter = :
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList")
+ set $!tree!here!save = $!tree!here!nbr;
+ set $!tree!here!nbr = "";
+ set $!tree!here!nbr = $!tree!here!save;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" queue.type="linkedList")
+}
+'
+startup
+sleep 1
+tcpflood -m500000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+#seq_check 0 499999
+exit_test
diff --git a/tests/msgvar-concurrency.sh b/tests/msgvar-concurrency.sh
new file mode 100755
index 0000000..57ae0e1
--- /dev/null
+++ b/tests/msgvar-concurrency.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Test concurrency of message variables
+# Added 2015-11-03 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%$!tree!here!nbr%\n")
+
+if $msg contains "msgnum:" then {
+ set $!tree!here!nbr = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt"
+ queue.type="linkedList")
+
+ set $!tree!here!save = $!tree!here!nbr;
+ set $!tree!here!nbr = "";
+ set $!tree!here!nbr = $!tree!here!save;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m500000
+shutdown_when_empty
+wait_shutdown
+seq_check 0 499999
+exit_test
diff --git a/tests/msleep.c b/tests/msleep.c
new file mode 100644
index 0000000..98dbece
--- /dev/null
+++ b/tests/msleep.c
@@ -0,0 +1,58 @@
+/* sleeps for the specified number of MILLIseconds.
+ * Primarily meant as a portable tool available everywhere for the
+ * testbench (sleep 0.1 does not work on all platforms).
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(__FreeBSD__)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#if defined(HAVE_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+ struct timeval tvSelectTimeout;
+ long sleepTime;
+
+ if(argc != 2) {
+ fprintf(stderr, "usage: msleep <milliseconds>\n");
+ exit(1);
+ }
+
+ sleepTime = atoi(argv[1]);
+ tvSelectTimeout.tv_sec = sleepTime / 1000;
+ tvSelectTimeout.tv_usec = (sleepTime % 1000) * 1000; /* micro seconds */
+ if(select(0, NULL, NULL, NULL, &tvSelectTimeout) == -1) {
+ perror("select");
+ exit(1);
+ }
+
+ return 0;
+}
+
diff --git a/tests/msleep_usage_output.sh b/tests/msleep_usage_output.sh
new file mode 100755
index 0000000..a3bae14
--- /dev/null
+++ b/tests/msleep_usage_output.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+./msleep &> $RSYSLOG_DYNNAME.output
+grep "usage: msleep" $RSYSLOG_DYNNAME.output
+
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/multiple_lookup_tables-vg.sh b/tests/multiple_lookup_tables-vg.sh
new file mode 100755
index 0000000..4ab23b1
--- /dev/null
+++ b/tests/multiple_lookup_tables-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2016-01-20 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/multiple_lookup_tables.sh
diff --git a/tests/multiple_lookup_tables.sh b/tests/multiple_lookup_tables.sh
new file mode 100755
index 0000000..ec1843a
--- /dev/null
+++ b/tests/multiple_lookup_tables.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# test for multiple lookup-table and HUP based reloading of it
+# added 2016-01-20 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate_0" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl")
+lookup_table(name="xlate_1" file="'$RSYSLOG_DYNNAME'.xlate_1.lkp_tbl")
+
+template(name="outfmt" type="string" string="- %msg% 0_%$.lkp_0% 1_%$.lkp_1%\n")
+
+set $.lkp_0 = lookup("xlate_0", $msg);
+set $.lkp_1 = lookup("xlate_1", $msg);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate_1.lkp_tbl
+startup
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: 0_foo_old 1_foo_old"
+content_check "msgnum:00000001: 0_bar_old 1_bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+wait_queueempty
+content_check "msgnum:00000000: 0_foo_new 1_foo_old"
+content_check "msgnum:00000001: 0_bar_new 1_bar_old"
+content_check "msgnum:00000002: 0_baz"
+assert_content_missing "1_baz"
+cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_1.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 3
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: 0_foo_new 1_foo_new"
+content_check "msgnum:00000001: 0_bar_new 1_bar_new"
+content_check "msgnum:00000002: 0_baz 1_baz"
+exit_test
diff --git a/tests/mysql-actq-mt-withpause-vg.sh b/tests/mysql-actq-mt-withpause-vg.sh
new file mode 100755
index 0000000..aba33ad
--- /dev/null
+++ b/tests/mysql-actq-mt-withpause-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/mysql-actq-mt-withpause.sh
diff --git a/tests/mysql-actq-mt-withpause.sh b/tests/mysql-actq-mt-withpause.sh
new file mode 100755
index 0000000..e613ee2
--- /dev/null
+++ b/tests/mysql-actq-mt-withpause.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# test for mysql with multithread actionq
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=150000
+generate_conf
+add_conf '
+module(load="../plugins/ommysql/.libs/ommysql")
+
+:msg, contains, "msgnum:" {
+ action(type="ommysql" server="127.0.0.1"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench"
+ queue.size="10000" queue.type="linkedList"
+ queue.workerthreads="5"
+ queue.workerthreadMinimumMessages="500"
+ queue.timeoutWorkerthreadShutdown="1000"
+ queue.timeoutEnqueue="20000"
+ )
+}
+'
+mysql_prep_for_test
+startup
+injectmsg 0 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 3000
+injectmsg 50000 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 2000
+injectmsg 100000 50000
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+mysql_cleanup_test
+exit_test
diff --git a/tests/mysql-actq-mt.sh b/tests/mysql-actq-mt.sh
new file mode 100755
index 0000000..c54afb4
--- /dev/null
+++ b/tests/mysql-actq-mt.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# test for mysql with multithread actionq
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=150000
+generate_conf
+add_conf '
+module(load="../plugins/ommysql/.libs/ommysql")
+
+:msg, contains, "msgnum:" {
+ action(type="ommysql" server="127.0.0.1"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench"
+ queue.size="10000" queue.type="linkedList"
+ queue.workerthreads="5"
+ queue.workerthreadMinimumMessages="500"
+ queue.timeoutWorkerthreadShutdown="1000"
+ queue.timeoutEnqueue="10000"
+ queue.timeoutShutdown="30000"
+ )
+}
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+mysql_cleanup_test
+exit_test
diff --git a/tests/mysql-asyn-vg.sh b/tests/mysql-asyn-vg.sh
new file mode 100755
index 0000000..15d0998
--- /dev/null
+++ b/tests/mysql-asyn-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/mysql-asyn.sh
diff --git a/tests/mysql-asyn.sh b/tests/mysql-asyn.sh
new file mode 100755
index 0000000..8f2bd65
--- /dev/null
+++ b/tests/mysql-asyn.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# asyn test for mysql functionality (running on async action queue)
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+generate_conf
+add_conf '
+$ModLoad ../plugins/ommysql/.libs/ommysql
+$ActionQueueType LinkedList
+$ActionQueueTimeoutEnqueue 20000
+:msg, contains, "msgnum:" :ommysql:127.0.0.1,'$RSYSLOG_DYNNAME',rsyslog,testbench;
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+mysql_cleanup_test
+exit_test
diff --git a/tests/mysql-basic-cnf6.sh b/tests/mysql-basic-cnf6.sh
new file mode 100755
index 0000000..1fd3e5c
--- /dev/null
+++ b/tests/mysql-basic-cnf6.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+generate_conf
+add_conf '
+$ModLoad ../plugins/ommysql/.libs/ommysql
+if $msg contains "msgnum" then {
+ action(type="ommysql" server="127.0.0.1"
+ db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench")
+}
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+mysql_cleanup_test
+exit_test
diff --git a/tests/mysql-basic-vg.sh b/tests/mysql-basic-vg.sh
new file mode 100755
index 0000000..c30e430
--- /dev/null
+++ b/tests/mysql-basic-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/mysql-basic.sh
diff --git a/tests/mysql-basic.sh b/tests/mysql-basic.sh
new file mode 100755
index 0000000..b6ac85f
--- /dev/null
+++ b/tests/mysql-basic.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# basic test for mysql functionality
+. ${srcdir:=.}/diag.sh init
+ # DEBUGGING - REMOVE ME #
+ ls -l mysql*log
+ sudo cat /var/log/mysql/error.log ## TODO: remove me
+ df -h
+export NUMMESSAGES=5000
+generate_conf
+add_conf '
+$ModLoad ../plugins/ommysql/.libs/ommysql
+:msg, contains, "msgnum:" :ommysql:127.0.0.1,'$RSYSLOG_DYNNAME',rsyslog,testbench;
+'
+mysql_prep_for_test
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+mysql_get_data
+seq_check
+mysql_cleanup_test
+exit_test
diff --git a/tests/mysqld-start.sh b/tests/mysqld-start.sh
new file mode 100755
index 0000000..b4f9470
--- /dev/null
+++ b/tests/mysqld-start.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# This is not a real test, but a script to start mysql. It is
+# implemented as test so that we can start mysql at the time we need
+# it (do so via Makefile.am).
+# Copyright (C) 2018 Rainer Gerhards and Adiscon GmbH
+# Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+echo pre-start
+ps -ef |grep bin.mysqld
+if [ "$MYSQLD_START_CMD" == "" ]; then
+ exit_test # no start needed
+fi
+
+test_error_exit_handler() {
+ set -x; set -v
+ printf 'mysqld startup failed, log is:\n'
+ $SUDO cat /var/log/mysql/error.log
+}
+
+printf 'starting mysqld...\n'
+$MYSQLD_START_CMD &
+wait_startup_pid /var/run/mysqld/mysqld.pid
+$SUDO tail -n30 /var/log/mysql/error.log
+printf 'preparing mysqld for testbench use...\n'
+$SUDO ${srcdir}/../devtools/prep-mysql-db.sh
+printf 'done, mysql ready for testbench\n'
+ps -ef |grep bin.mysqld
+exit_test
diff --git a/tests/mysqld-stop.sh b/tests/mysqld-stop.sh
new file mode 100755
index 0000000..6ac76dd
--- /dev/null
+++ b/tests/mysqld-stop.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# This is not a real test, but a script to stop mysql. It is
+# implemented as test so that we can stop mysql at the time we need
+# it (do so via Makefile.am).
+# Copyright (C) 2018 Rainer Gerhards and Adiscon GmbH
+# Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ "$MYSQLD_STOP_CMD" == "" ]; then
+ exit_test
+fi
+printf 'stopping mysqld...\n'
+eval $MYSQLD_STOP_CMD
+sleep 1 # cosmetic: give mysqld a chance to emit shutdown message
+exit_test
diff --git a/tests/nested-call-shutdown.sh b/tests/nested-call-shutdown.sh
new file mode 100755
index 0000000..f82c6b5
--- /dev/null
+++ b/tests/nested-call-shutdown.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# addd 2017-10-18 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="rs3" queue.type="linkedList") {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+
+ruleset(name="rs2" queue.type="linkedList") {
+ call rs3
+}
+
+ruleset(name="rs1" queue.type="linkedList") {
+ call rs2
+ :omtesting:sleep 0 1000
+}
+
+if $msg contains "msgnum:" then call rs1
+'
+startup
+#tcpflood -p'$TCPFLOOD_PORT' -m10000
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown
+# wo do not check reception - the main point is that we do not abort. The actual
+# message count is unknown (as the point is to shut down while still in processing).
+exit_test
diff --git a/tests/no-dynstats-json.sh b/tests/no-dynstats-json.sh
new file mode 100755
index 0000000..245e894
--- /dev/null
+++ b/tests/no-dynstats-json.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added 2016-03-10 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[no-dynstats-json.sh\]: test for verifying stats are reported correctly in json format in absence of any dynstats buckets being configured
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check '{ "name": "global", "origin": "dynstats", "values": { } }' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/no-dynstats.sh b/tests/no-dynstats.sh
new file mode 100755
index 0000000..0d9bc4f
--- /dev/null
+++ b/tests/no-dynstats.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added 2016-03-10 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[no-dynstats.sh\]: test for verifying stats are reported correctly in legacy format in absence of any dynstats buckets being configured
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check 'global: origin=dynstats' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/no-parser-errmsg.sh b/tests/no-parser-errmsg.sh
new file mode 100755
index 0000000..2cae383
--- /dev/null
+++ b/tests/no-parser-errmsg.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# add 2017-03-06 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n")
+ruleset(name="ruleset" parser="rsyslog.rfc5424") {
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="test")
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+grep 'one message could not be processed by any parser' $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/no-parser-vg.sh b/tests/no-parser-vg.sh
new file mode 100755
index 0000000..a52aced
--- /dev/null
+++ b/tests/no-parser-vg.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2017-03-06 by Rainer Gerhards, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+ruleset(name="ruleset" parser="rsyslog.rfc5424") {
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+'
+startup_vg
+tcpflood -m10
+shutdown_when_empty
+wait_shutdown_vg
+# note: we just check the valgrind output, the log file itself does not
+# interest us
+
+exit_test
diff --git a/tests/now-unixtimestamp.sh b/tests/now-unixtimestamp.sh
new file mode 100755
index 0000000..58058fd
--- /dev/null
+++ b/tests/now-unixtimestamp.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-02-23 by RGerhards, released under ASL 2.0
+# requires faketime
+echo \[now-utc\]: test \$NOW-UTC
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.tnow = $$now-unixtimestamp + 1;
+
+template(name="outfmt" type="string"
+ string="%$now-unixtimestamp%,%$.tnow%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="1451602800,1451602801"
+cmp_exact
+exit_test
diff --git a/tests/now-utc-casecmp.sh b/tests/now-utc-casecmp.sh
new file mode 100755
index 0000000..8eda3a1
--- /dev/null
+++ b/tests/now-utc-casecmp.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-02-23 by RGerhards, released under ASL 2.0
+# requires faketime
+echo \[now-utc-casecmp\]: test \$year-utc, \$month-utc, \$day-utc
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%$Now%:%$Year%-%$Month%-%$Day%,%$Now-utc%:%$Year-utc%-%$Month-utc%-%$Day-utc%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "2016-01-01:2016-01-01,2015-12-31:2015-12-31" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error-exit 1
+fi;
+
+
+exit_test
diff --git a/tests/now-utc-ymd.sh b/tests/now-utc-ymd.sh
new file mode 100755
index 0000000..a8b6ea8
--- /dev/null
+++ b/tests/now-utc-ymd.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-02-23 by RGerhards, released under ASL 2.0
+# requires faketime
+. ${srcdir:=.}/diag.sh init
+echo \[now-utc-ymd\]: test \$year-utc, \$month-utc, \$day-utc
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%$year%-%$month%-%$day%,%$year-utc%-%$month-utc%-%$day-utc%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="2016-01-01,2015-12-31"
+exit_test
diff --git a/tests/now-utc.sh b/tests/now-utc.sh
new file mode 100755
index 0000000..c21cedc
--- /dev/null
+++ b/tests/now-utc.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-02-23 by RGerhards, released under ASL 2.0
+# requires faketime
+echo \[now-utc\]: test \$NOW-UTC
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%$now%,%$now-utc%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="2016-01-01,2015-12-31"
+cmp_exact
+exit_test
diff --git a/tests/now_family_utc.sh b/tests/now_family_utc.sh
new file mode 100755
index 0000000..5e081ba
--- /dev/null
+++ b/tests/now_family_utc.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# test $NOW family of system properties
+# addd 2016-01-12 by RGerhards, released under ASL 2.0
+# requires faketime
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%$hour%:%$minute%,%$hour-utc%:%$minute-utc%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST+06:30
+
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="01:00,07:30"
+cmp_exact
+
+exit_test
diff --git a/tests/omamqp1-basic-vg.sh b/tests/omamqp1-basic-vg.sh
new file mode 100755
index 0000000..7d8d826
--- /dev/null
+++ b/tests/omamqp1-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omamqp1-basic.sh
diff --git a/tests/omamqp1-basic.sh b/tests/omamqp1-basic.sh
new file mode 100755
index 0000000..ceda533
--- /dev/null
+++ b/tests/omamqp1-basic.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/omamqp1-common.sh
+
+AMQP_URL=${AMQP_URL:-"localhost:5672"}
+NUMMESSAGES=10240
+
+generate_conf
+if [ "${USE_VALGRIND:-}" = YES ] ; then
+ add_conf '
+global(debug.unloadModules="off")
+'
+fi
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../plugins/impstats/.libs/impstats" interval="1"
+ log.file="'"$RSYSLOG_DYNNAME.spool"'/stats.log" log.syslog="off" format="cee")
+module(load="../contrib/omamqp1/.libs/omamqp1")
+
+if $msg contains "msgnum:" then
+ action(type="omamqp1"
+ host="'"$AMQP_URL"'"
+ target="amq.rsyslogtest")
+'
+qdrouterd > $RSYSLOG_DYNNAME.spool/qdrouterd.log 2>&1 & qdrouterdpid=$!
+sleep 5 # give qdrouterd a chance to start up and listen
+# have to start reader before writer - like a pipe - for the client, NUMMESSAGES could
+# be much less than the number of records if batching is used - for the client, it means
+# batches, not records - but there can't be more batches than records
+amqp_simple_recv $AMQP_URL amq.rsyslogtest $NUMMESSAGES > $RSYSLOG_DYNNAME.spool/amqp_simple_recv.out 2>&1 &
+#export RSYSLOG_DEBUG=debug
+#export RSYSLOG_DEBUGLOG=/tmp/rsyslog.debug.log
+startup
+if [ -n "${USE_GDB:-}" ] ; then
+ echo attach gdb here
+ sleep 54321 || :
+fi
+injectmsg 0 $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+
+timeout=60
+for ii in $( seq 1 $timeout ) ; do
+ if grep -q "msgnum:00*$(( NUMMESSAGES - 1 ))" $RSYSLOG_DYNNAME.spool/amqp_simple_recv.out ; then
+ break
+ fi
+ sleep 1
+done
+kill $qdrouterdpid > /dev/null 2>&1 || kill -9 $qdrouterdpid > /dev/null 2>&1 || :
+# you would think there would be a better way to do this . . .
+kill $( pgrep -f 'python.*simple_recv.py' )
+if [ $ii = $timeout ] ; then
+ echo ERROR: amqp_simple_recv did not receive all $NUMMESSAGES messages in $timeout seconds
+ error_exit 1
+fi
+
+$PYTHON -c 'import sys
+inp = file(sys.argv[1],"r").read()
+last = 0
+idx = inp.find("msgnum:",last)
+while idx > -1:
+ msgstr = inp[(idx+7):(idx+15)]
+ print msgstr
+ last = idx+16
+ idx = inp.find("msgnum:",last)
+' $RSYSLOG_DYNNAME.spool/amqp_simple_recv.out > $RSYSLOG_OUT_LOG
+seq_check
diff --git a/tests/omamqp1-common.sh b/tests/omamqp1-common.sh
new file mode 100644
index 0000000..ec0a6ae
--- /dev/null
+++ b/tests/omamqp1-common.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# version of qdrouterd to use for test
+QDROUTERD_VERSION=${QDROUTERD_VERSION:-1.7.0}
+# Use of containers isn't necessary for CI, and might not be
+# useful for devs, depending on platform availability.
+# If not using a container for the test, the
+# package will be installed using the platform
+# package manager.
+#USE_CONTAINER=${USE_CONTAINER:-false}
+#CONTAINER_URL=${CONTAINER_URL:-quay.io/interconnectedcloud/qdrouterd:$QDROUTERD_VERSION}
+
+if ! type -p qdrouterd ; then
+ echo no qdrouterd found in PATH $PATH - skipping test
+ exit 0
+fi
+
+ver=$( qdrouterd --version )
+if [ "$ver" = $QDROUTERD_VERSION ] ; then
+ echo found qdrouterd version $ver - continuing
+else
+ echo found qdrouterd version $ver but expected version $QDROUTERD_VERSION - skipping test
+ exit 0
+fi
+
+AMQP_SIMPLE_RECV=${AMQP_SIMPLE_RECV:-/usr/share/proton-0.28.0/examples/python/simple_recv.py}
+
+if [ -f $AMQP_SIMPLE_RECV ] ; then
+ echo found $AMQP_SIMPLE_RECV
+else
+ echo no amqp client $AMQP_SIMPLE_RECV - skipping test
+ exit 0
+fi
+
+AMQP_PYTHON=${AMQP_PYTHON:-python}
+if $AMQP_PYTHON $AMQP_SIMPLE_RECV --help > /dev/null 2>&1 ; then
+ : # good
+elif python3 $AMQP_SIMPLE_RECV --help > /dev/null 2>&1 ; then
+ AMQP_PYTHON=python3
+else
+ echo missing python modules for $AMQP_SIMPLE_RECV - skipping test
+ exit 0
+fi
+
+amqp_simple_recv() {
+ # $1 is host:port (or amqp url if applicable)
+ # $2 is target (e.g. amq.rsyslogtest)
+ # $3 is number of messages to read
+ stdbuf -o 0 $AMQP_PYTHON $AMQP_SIMPLE_RECV -a $1/$2 -m $3
+}
diff --git a/tests/omazureeventhubs-basic-vg.sh b/tests/omazureeventhubs-basic-vg.sh
new file mode 100755
index 0000000..f5552df
--- /dev/null
+++ b/tests/omazureeventhubs-basic-vg.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes --leak-check=full"
+export EXTRA_VALGRIND_SUPPRESSIONS="--suppressions=omazureeventhubs.supp"
+source ${srcdir:-.}/omazureeventhubs-basic.sh
+
diff --git a/tests/omazureeventhubs-basic.sh b/tests/omazureeventhubs-basic.sh
new file mode 100755
index 0000000..0865b7b
--- /dev/null
+++ b/tests/omazureeventhubs-basic.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=100
+export NUMMESSAGESFULL=$NUMMESSAGES
+export WAITTIMEOUT=20
+
+# REQUIRES EXTERNAL ENVIRONMENT VARIABLES
+if [[ -z "${AZURE_HOST}" ]]; then
+ echo "SKIP: AZURE_HOST environment variable not SET! Example: <yourname>.servicebus.windows.net - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_PORT}" ]]; then
+ echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY_NAME}" ]]; then
+ echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: <yourkeyname> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY}" ]]; then
+ echo "SKIP: AZURE_KEY environment variable not SET! Example: <yourlongkey> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_CONTAINER}" ]]; then
+ echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: <youreventhubsname> - SKIPPING"
+ exit 77
+fi
+
+export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME"
+export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME"
+
+# --- Create/Start omazureeventhubs sender config
+
+generate_conf
+add_conf '
+global(
+ debug.whitelist="on"
+ debug.files=["omazureeventhubs.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load mods
+module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs")
+
+# templates
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+local4.* {
+ action( name="omazureeventhubs"
+ type="omazureeventhubs"
+ azurehost="'$AZURE_HOST'"
+ azureport="'$AZURE_PORT'"
+ azure_key_name="'$AZURE_KEY_NAME'"
+ azure_key="'$AZURE_KEY'"
+ container="'$AZURE_CONTAINER'"
+# amqp_address="amqps://'$AZURE_KEY_NAME':'$AZURE_KEY'@'$AZURE_HOST'/'$AZURE_NAME'"
+ template="outfmt"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ )
+
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+'
+echo Starting sender instance [omazureeventhubs]
+startup
+
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $NUMMESSAGES
+
+wait_file_lines $RSYSLOG_OUT_LOG $NUMMESSAGESFULL 100
+
+# experimental: wait until kafkacat receives everything
+timeoutend=$WAITTIMEOUT
+timecounter=0
+
+echo "CHECK $RSYSLOG_DYNNAME.pstats"
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then
+ # Read IMPSTATS for verification
+ IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5)
+ SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2)
+ FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2)
+ ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2)
+
+ if ! [[ $SUBMITTED_MSG =~ $re ]] ; then
+ echo "**** omazureeventhubs WAITING FOR IMPSTATS"
+ else
+ if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ if [ "$ACCEPTED_MSG" -eq "$NUMMESSAGESFULL" ]; then
+ echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ shutdown_when_empty
+ wait_shutdown
+ #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log
+ exit_test
+ else
+ echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ else
+ echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ fi
+ fi
+
+ $TESTTOOL_DIR/msleep 1000
+done
+unset count
+
+shutdown_when_empty
+wait_shutdown
+error_exit 1
diff --git a/tests/omazureeventhubs-interrupt-vg.sh b/tests/omazureeventhubs-interrupt-vg.sh
new file mode 100755
index 0000000..be9fefa
--- /dev/null
+++ b/tests/omazureeventhubs-interrupt-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes --leak-check=full"
+export EXTRA_VALGRIND_SUPPRESSIONS="--suppressions=omazureeventhubs.supp"
+source ${srcdir:-.}/omazureeventhubs-interrupt.sh
diff --git a/tests/omazureeventhubs-interrupt.sh b/tests/omazureeventhubs-interrupt.sh
new file mode 100755
index 0000000..6d92500
--- /dev/null
+++ b/tests/omazureeventhubs-interrupt.sh
@@ -0,0 +1,165 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+echo This test must be run as root [raw socket access required]
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+. ${srcdir:=.}/diag.sh init
+
+# --- If test is needed, create helper script to store environment variables for
+# éventhubs access:
+# export AZURE_HOST=""
+# export AZURE_PORT=""
+# export AZURE_KEY_NAME=""
+# export AZURE_KEY=""
+# export AZURE_CONTAINER=""
+# ---
+source omazureeventhubs-env.sh
+
+export NUMMESSAGES=10000
+export NUMMESSAGESFULL=$NUMMESSAGES
+export WAITTIMEOUT=60
+
+export QUEUESIZE=100000
+export DEQUEUESIZE=64
+export DEQUEUESIZEMIN=32
+export TESTWORKERTHREADS=3
+
+export interrupt_host="$AZURE_HOST"
+export interrupt_port="$AZURE_PORT"
+export interrupt_tick="10"
+
+
+# REQUIRES EXTERNAL ENVIRONMENT VARIABLES
+if [[ -z "${AZURE_HOST}" ]]; then
+ echo "SKIP: AZURE_HOST environment variable not SET! Example: <yourname>.servicebus.windows.net - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_PORT}" ]]; then
+ echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY_NAME}" ]]; then
+ echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: <yourkeyname> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY}" ]]; then
+ echo "SKIP: AZURE_KEY environment variable not SET! Example: <yourlongkey> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_CONTAINER}" ]]; then
+ echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: <youreventhubsname> - SKIPPING"
+ exit 77
+fi
+
+export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME"
+export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME"
+
+# --- Create/Start omazureeventhubs sender config
+
+generate_conf
+add_conf '
+global(
+# debug.whitelist="on"
+# debug.files=["omazureeventhubs.c", "modules.c", "errmsg.c", "action.c", "queue.c", "ruleset.c"]
+)
+
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load mods
+module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs")
+
+# templates
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+local4.* {
+ action( name="omazureeventhubs"
+ type="omazureeventhubs"
+ azurehost="'$AZURE_HOST'"
+ azureport="'$AZURE_PORT'"
+ azure_key_name="'$AZURE_KEY_NAME'"
+ azure_key="'$AZURE_KEY'"
+ container="'$AZURE_CONTAINER'"
+# amqp_address="amqps://'$AZURE_KEY_NAME':'$AZURE_KEY'@'$AZURE_HOST'/'$AZURE_NAME'"
+ template="outfmt"
+ queue.type="FixedArray"
+ queue.size="'$QUEUESIZE'"
+ queue.saveonshutdown="on"
+ queue.dequeueBatchSize="'$DEQUEUESIZE'"
+ queue.minDequeueBatchSize="'$DEQUEUESIZEMIN'"
+ queue.minDequeueBatchSize.timeout="1000" # 1 sec
+ queue.workerThreads="'$TESTWORKERTHREADS'"
+ queue.workerThreadMinimumMessages="'$DEQUEUESIZEMIN'"
+ queue.timeoutWorkerthreadShutdown="60000"
+ queue.timeoutEnqueue="2000"
+ queue.timeoutshutdown="1000"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ )
+
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+'
+echo Starting sender instance [omazureeventhubs]
+startup
+
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $NUMMESSAGES
+
+wait_file_lines --interrupt-connection $interrupt_host $interrupt_port $interrupt_tick $RSYSLOG_OUT_LOG $NUMMESSAGESFULL 100
+
+timeoutend=$WAITTIMEOUT
+timecounter=0
+lastcurrent_time=0
+
+echo "CHECK $RSYSLOG_DYNNAME.pstats"
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then
+ # Read IMPSTATS for verification
+ IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5)
+ SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2)
+ FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2)
+ ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2)
+
+ if ! [[ $SUBMITTED_MSG =~ $re ]] ; then
+ echo "**** omazureeventhubs WAITING FOR IMPSTATS"
+ else
+ if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ if [ "$ACCEPTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ shutdown_when_empty
+ wait_shutdown
+ #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log
+ exit_test
+ else
+ echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ else
+ echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ current_time=$(date +%s)
+ if [ $interrupt_connection == "YES" ] && [ $current_time -gt $lastcurrent_time ] && [ $((current_time % $interrupt_tick)) -eq 0 ] && [ ${count} -gt 1 ]; then
+ # Interrupt Connection - requires root and linux kernel >= 4.9 in order to work!
+ echo "**** omazureeventhubs WAITING: Interrupt Connection on ${interrupt_host}:${interrupt_port}"
+ sudo ss -K dst ${interrupt_host} dport = ${interrupt_port}
+ fi
+ lastcurrent_time=$current_time
+ fi
+ fi
+ fi
+
+ $TESTTOOL_DIR/msleep 1000
+done
+unset count
+
+shutdown_when_empty
+wait_shutdown
+error_exit 1
diff --git a/tests/omazureeventhubs-list.sh b/tests/omazureeventhubs-list.sh
new file mode 100755
index 0000000..01f3b01
--- /dev/null
+++ b/tests/omazureeventhubs-list.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=100
+export NUMMESSAGESFULL=$NUMMESSAGES
+export WAITTIMEOUT=20
+
+# REQUIRES EXTERNAL ENVIRONMENT VARIABLES
+if [[ -z "${AZURE_HOST}" ]]; then
+ echo "SKIP: AZURE_HOST environment variable not SET! Example: <yourname>.servicebus.windows.net - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_PORT}" ]]; then
+ echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY_NAME}" ]]; then
+ echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: <yourkeyname> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY}" ]]; then
+ echo "SKIP: AZURE_KEY environment variable not SET! Example: <yourlongkey> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_CONTAINER}" ]]; then
+ echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: <youreventhubsname> - SKIPPING"
+ exit 77
+fi
+
+export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME"
+export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME"
+
+# --- Create/Start omazureeventhubs sender config
+generate_conf
+add_conf '
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load mods
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs")
+
+# imtcp
+input( type="imtcp"
+ port="0"
+ ruleset="default"
+ listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# templates
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+template(name="generic" type="list" option.jsonf="on") {
+ property(outname="timestamp" name="timereported" dateFormat="rfc3339" format="jsonf")
+ constant(value="\"source\": \"EventHubMessage\", ")
+ property(outname="host" name="hostname" format="jsonf")
+ property(outname="severity" name="syslogseverity" caseConversion="upper" format="jsonf" datatype="number")
+ property(outname="facility" name="syslogfacility" format="jsonf" datatype="number")
+ property(outname="appname" name="syslogtag" format="jsonf")
+ property(outname="message" name="msg" format="jsonf" )
+ property(outname="etlsource" name="$myhostname" format="jsonf")}
+
+# ruleset
+ruleset(name="default") {
+ if $msg contains "msgnum:" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+ action(type="omfile" template="generic" file="'$RSYSLOG_OUT_LOG'-generic.log")
+ action(name="omazureeventhubs"
+ type="omazureeventhubs"
+ azurehost="'$AZURE_HOST'"
+ azureport="'$AZURE_PORT'"
+ azure_key_name="'$AZURE_KEY_NAME'"
+ azure_key="'$AZURE_KEY'"
+ container="'$AZURE_CONTAINER'"
+ template="generic"
+ eventproperties=[ "Table=TestTable",
+ "Format=JSON"]
+ )
+ } else {
+ action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+ }
+ stop
+}
+
+'
+echo Starting sender instance [omazureeventhubs]
+startup
+
+echo Inject messages into rsyslog sender instance
+# injectmsg 1 $NUMMESSAGES
+tcpflood -m$NUMMESSAGES -i1
+
+wait_file_lines $RSYSLOG_OUT_LOG $NUMMESSAGESFULL 100
+
+# experimental: wait until kafkacat receives everything
+timeoutend=$WAITTIMEOUT
+timecounter=0
+
+echo "CHECK $RSYSLOG_DYNNAME.pstats"
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then
+ # Read IMPSTATS for verification
+ IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5)
+ SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2)
+ FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2)
+ ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2)
+
+ if ! [[ $SUBMITTED_MSG =~ $re ]] ; then
+ echo "**** omazureeventhubs WAITING FOR IMPSTATS"
+ else
+ if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ if [ "$ACCEPTED_MSG" -eq "$NUMMESSAGESFULL" ]; then
+ echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ shutdown_when_empty
+ wait_shutdown
+ #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log
+ exit_test
+ else
+ echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ else
+ echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ fi
+ fi
+
+ $TESTTOOL_DIR/msleep 1000
+done
+unset count
+
+shutdown_when_empty
+wait_shutdown
+error_exit 1
diff --git a/tests/omazureeventhubs-stress.sh b/tests/omazureeventhubs-stress.sh
new file mode 100755
index 0000000..2587b0a
--- /dev/null
+++ b/tests/omazureeventhubs-stress.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+export NUMMESSAGESFULL=$NUMMESSAGES
+export WAITTIMEOUT=60
+
+export QUEUESIZE=100000
+export DEQUEUESIZE=1000
+export DEQUEUESIZEMIN=1000
+export TESTWORKERTHREADS=10
+
+# REQUIRES EXTERNAL ENVIRONMENT VARIABLES
+if [[ -z "${AZURE_HOST}" ]]; then
+ echo "SKIP: AZURE_HOST environment variable not SET! Example: <yourname>.servicebus.windows.net - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_PORT}" ]]; then
+ echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY_NAME}" ]]; then
+ echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: <yourkeyname> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_KEY}" ]]; then
+ echo "SKIP: AZURE_KEY environment variable not SET! Example: <yourlongkey> - SKIPPING"
+ exit 77
+fi
+if [[ -z "${AZURE_CONTAINER}" ]]; then
+ echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: <youreventhubsname> - SKIPPING"
+ exit 77
+fi
+
+export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME"
+export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME"
+
+# --- Create/Start omazureeventhubs sender config
+
+generate_conf
+add_conf '
+global(
+ debug.whitelist="on"
+ debug.files=["omazureeventhubs.c", "modules.c", "errmsg.c", "action.c"]
+)
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# main_queue(queue.dequeueBatchSize="2048")
+
+# Load mods
+module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs")
+
+# templates
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+local4.* {
+ action( name="omazureeventhubs"
+ type="omazureeventhubs"
+ azurehost="'$AZURE_HOST'"
+ azureport="'$AZURE_PORT'"
+ azure_key_name="'$AZURE_KEY_NAME'"
+ azure_key="'$AZURE_KEY'"
+ container="'$AZURE_CONTAINER'"
+ template="outfmt"
+ queue.type="FixedArray"
+ queue.size="'$QUEUESIZE'"
+ queue.saveonshutdown="on"
+ queue.dequeueBatchSize="'$DEQUEUESIZE'"
+ queue.minDequeueBatchSize.timeout="1000" # 1 sec
+ queue.workerThreads="'$TESTWORKERTHREADS'"
+ queue.workerThreadMinimumMessages="'$DEQUEUESIZEMIN'"
+ queue.timeoutWorkerthreadShutdown="10000"
+ queue.timeoutshutdown="1000"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ )
+
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+'
+echo Starting sender instance [omazureeventhubs]
+startup
+
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $NUMMESSAGES
+
+# experimental: wait until kafkacat receives everything
+timeoutend=$WAITTIMEOUT
+timecounter=0
+
+echo "CHECK $RSYSLOG_DYNNAME.pstats"
+LAST_ACCEPTED_MSG=0
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then
+ # Read IMPSTATS for verification
+ IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5)
+ SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2)
+ FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2)
+ ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2)
+ MSG_PER_SEC=$(($ACCEPTED_MSG-$LAST_ACCEPTED_MSG))
+ LAST_ACCEPTED_MSG=$ACCEPTED_MSG
+
+ if ! [[ $SUBMITTED_MSG =~ $re ]] ; then
+ echo "**** omazureeventhubs WAITING FOR IMPSTATS"
+ else
+ if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ if [ "$ACCEPTED_MSG" -ge "$NUMMESSAGESFULL" ]; then
+ echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ shutdown_when_empty
+ wait_shutdown
+ #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log
+ exit_test
+ else
+ echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG"
+ fi
+ else
+ echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG, MSG_PER_SEC: $MSG_PER_SEC"
+ fi
+ fi
+ fi
+
+ $TESTTOOL_DIR/msleep 1000
+done
+unset count
+
+shutdown_when_empty
+wait_shutdown
+error_exit 1
diff --git a/tests/omfile-module-params.sh b/tests/omfile-module-params.sh
new file mode 100755
index 0000000..1f4e5b8
--- /dev/null
+++ b/tests/omfile-module-params.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# addd 2018-08-02 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=100 # we only check output fmt, so few messages are OK
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="builtin:omfile" template="outfmt")
+
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/omfile-null-filename.sh b/tests/omfile-null-filename.sh
new file mode 100755
index 0000000..10f323e
--- /dev/null
+++ b/tests/omfile-null-filename.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# check that omfile does not segfault when filename is given but empty.
+# addd 2018-04-03 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file="")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+grep "parameter must be given" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omfile-outchannel-many.sh b/tests/omfile-outchannel-many.sh
new file mode 100755
index 0000000..102f1eb
--- /dev/null
+++ b/tests/omfile-outchannel-many.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# addd 2018-08-02 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=500000
+echo "ls -l $RSYSLOG_DYNNAME.channel.*
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.9 $RSYSLOG_DYNNAME.channel.log.prev.10 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.8 $RSYSLOG_DYNNAME.channel.log.prev.9 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.7 $RSYSLOG_DYNNAME.channel.log.prev.8 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.6 $RSYSLOG_DYNNAME.channel.log.prev.7 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.5 $RSYSLOG_DYNNAME.channel.log.prev.6 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.4 $RSYSLOG_DYNNAME.channel.log.prev.5 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.3 $RSYSLOG_DYNNAME.channel.log.prev.4 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.2 $RSYSLOG_DYNNAME.channel.log.prev.3 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.1 $RSYSLOG_DYNNAME.channel.log.prev.2 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev $RSYSLOG_DYNNAME.channel.log.prev.1 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log $RSYSLOG_DYNNAME.channel.log.prev
+" > $RSYSLOG_DYNNAME.rotate.sh
+chmod +x $RSYSLOG_DYNNAME.rotate.sh
+generate_conf
+add_conf '
+main_queue(
+ queue.workerthreads="4"
+ queue.timeoutWorkerthreadShutdown="-1"
+ queue.workerThreadMinimumMessages="10"
+)
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="tcp")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="builtin:omfile" template="outfmt")
+$outchannel log_rotation,'$RSYSLOG_DYNNAME.channel.log', $NUMMESSAGES,./'$RSYSLOG_DYNNAME.rotate.sh'
+
+if $msg contains "msgnum:" then {
+# if $/num % 2 == 0 then
+ :omfile:$log_rotation
+# else
+# :omfile:$log_rotation2
+# set $/num = $/num + 1;
+}
+
+ruleset(name="tcp") {
+ :omfile:$log_rotation2
+}
+'
+startup
+./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async!
+#./msleep 2500
+injectmsg
+sleep 1
+shutdown_when_empty
+wait_shutdown
+ls -l $RSYSLOG_DYNNAME.channel.*
+cat $RSYSLOG_DYNNAME.channel.* > $RSYSLOG_OUT_LOG
+seq_check
+exit_test
diff --git a/tests/omfile-outchannel.sh b/tests/omfile-outchannel.sh
new file mode 100755
index 0000000..329f844
--- /dev/null
+++ b/tests/omfile-outchannel.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# addd 2018-08-02 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+echo "ls -l $RSYSLOG_DYNNAME*
+mv -f $RSYSLOG_DYNNAME.channel.log $RSYSLOG_DYNNAME.channel.log.prev
+" > $RSYSLOG_DYNNAME.rotate.sh
+chmod +x $RSYSLOG_DYNNAME.rotate.sh
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="builtin:omfile" template="outfmt")
+$outchannel log_rotation,'$RSYSLOG_DYNNAME.channel.log', 50000,./'$RSYSLOG_DYNNAME.rotate.sh'
+:msg, contains, "msgnum:" :omfile:$log_rotation
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+cat $RSYSLOG_DYNNAME.channel.* > $RSYSLOG_OUT_LOG
+ls -l $RSYSLOG_DYNNAME*
+seq_check
+exit_test
diff --git a/tests/omfile-read-only-errmsg.sh b/tests/omfile-read-only-errmsg.sh
new file mode 100755
index 0000000..da1bd4f
--- /dev/null
+++ b/tests/omfile-read-only-errmsg.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# addd 2017-03-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+touch ${RSYSLOG2_OUT_LOG}
+chmod 0400 ${RSYSLOG2_OUT_LOG}
+ls -l rsyslog.ou*
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+
+grep "${RSYSLOG2_OUT_LOG}.* open error" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omfile-read-only.sh b/tests/omfile-read-only.sh
new file mode 100755
index 0000000..7cc25d1
--- /dev/null
+++ b/tests/omfile-read-only.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# addd 2016-06-16 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+messages=20000 # how many messages to inject?
+# Note: we need to inject a somewhat larger number of messages in order
+# to ensure that we receive some messages in the actual output file,
+# as batching can (validly) cause a larger loss in the non-writable
+# file
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG2_OUT_LOG'")
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'"
+ action.execOnlyWhenPreviousIsSuspended="on"
+ )
+}
+'
+touch ${RSYSLOG2_OUT_LOG}
+chmod 0400 ${RSYSLOG2_OUT_LOG}
+ls -l rsyslog.ou*
+startup
+injectmsg 0 $messages
+shutdown_when_empty
+wait_shutdown
+# we know that the output file is missing some messages, but it
+# MUST have some more, and these be in sequence. So we now read
+# the first message number and calculate based on it what must be
+# present in the output file.
+presort
+let firstnum=$((10#$($RS_HEADCMD -n1 $RSYSLOG_DYNNAME.presort)))
+echo "info: first message expected to be number $firstnum, using that value."
+seq_check $firstnum $((messages-1))
+exit_test
diff --git a/tests/omfile-sizelimitcmd-many.sh b/tests/omfile-sizelimitcmd-many.sh
new file mode 100755
index 0000000..b1c8d0b
--- /dev/null
+++ b/tests/omfile-sizelimitcmd-many.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# addd 2023-01-11 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+echo "ls -l $RSYSLOG_DYNNAME.channel.*
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.9 $RSYSLOG_DYNNAME.channel.log.prev.10 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.8 $RSYSLOG_DYNNAME.channel.log.prev.9 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.7 $RSYSLOG_DYNNAME.channel.log.prev.8 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.6 $RSYSLOG_DYNNAME.channel.log.prev.7 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.5 $RSYSLOG_DYNNAME.channel.log.prev.6 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.4 $RSYSLOG_DYNNAME.channel.log.prev.5 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.3 $RSYSLOG_DYNNAME.channel.log.prev.4 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.2 $RSYSLOG_DYNNAME.channel.log.prev.3 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev.1 $RSYSLOG_DYNNAME.channel.log.prev.2 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log.prev $RSYSLOG_DYNNAME.channel.log.prev.1 2>/dev/null
+mv -f $RSYSLOG_DYNNAME.channel.log $RSYSLOG_DYNNAME.channel.log.prev
+" > $RSYSLOG_DYNNAME.rotate.sh
+chmod +x $RSYSLOG_DYNNAME.rotate.sh
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME.channel.log'" template="outfmt"
+ rotation.sizeLimit="50k"
+ rotation.sizeLimitCommand="./'$RSYSLOG_DYNNAME.rotate.sh'")
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+ls -l $RSYSLOG_DYNNAME.channel.*
+cat $RSYSLOG_DYNNAME.channel.* > $RSYSLOG_OUT_LOG
+seq_check
+exit_test
diff --git a/tests/omfile-whitespace-filename.sh b/tests/omfile-whitespace-filename.sh
new file mode 100755
index 0000000..7396382
--- /dev/null
+++ b/tests/omfile-whitespace-filename.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2018-04-03 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file=" ")
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+grep "only of whitespace" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omfile_both_files_set.sh b/tests/omfile_both_files_set.sh
new file mode 100755
index 0000000..83bef8b
--- /dev/null
+++ b/tests/omfile_both_files_set.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="dynafile" type="string" string=`echo $RSYSLOG_OUT_LOG`)
+template(name="outfmt" type="string" string="-%msg%-\n")
+
+:msg, contains, "msgnum:" {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG` dynafile="dynafile")
+}
+action(type="omfile" file="'${RSYSLOG_DYNNAME}'.errorfile")
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+
+grep "will use dynafile" ${RSYSLOG_DYNNAME}.errorfile > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. ${RSYSLOG_DYNNAME}.errorfile is:"
+ cat ${RSYSLOG_DYNNAME}.errorfile
+ error_exit 1
+fi
+
+echo '- msgnum:1-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "unexpected content in $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+if [ -f ${RSYSLOG2_OUT_LOG} ]; then
+ echo "file exists, but should not: ${RSYSLOG2_OUT_LOG}; content:"
+ cat ${RSYSLOG2_OUT_LOG}
+ error_exit 1
+fi;
+
+
+exit_test
diff --git a/tests/omfile_hup-vg.sh b/tests/omfile_hup-vg.sh
new file mode 100755
index 0000000..a41e5c4
--- /dev/null
+++ b/tests/omfile_hup-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export NUMMESSAGES=200000 # reduce for slower valgrind run
+source ${srcdir:-.}/omfile_hup.sh
diff --git a/tests/omfile_hup.sh b/tests/omfile_hup.sh
new file mode 100755
index 0000000..6dc28e1
--- /dev/null
+++ b/tests/omfile_hup.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-06-21 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=${NUMMESSAGES:-1000000}
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'")
+
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" dynafile="dynfile")
+'
+startup
+./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async!
+BGPROCESS=$!
+for i in $(seq 1 20); do
+ printf '\nsending HUP %d\n' $i
+ issue_HUP --sleep 100
+done
+wait $BGPROCESS
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/omfwd-errfile-maxsize-filled.sh b/tests/omfwd-errfile-maxsize-filled.sh
new file mode 100755
index 0000000..25a08ec
--- /dev/null
+++ b/tests/omfwd-errfile-maxsize-filled.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+ERRFILE="$RSYSLOG_DYNNAME.err"
+export MAX_ERROR_SIZE=1999
+export INITIAL_FILE_SIZE=$((MAX_ERROR_SIZE - 100))
+dd if=/dev/urandom of=${ERRFILE} bs=1 count=${INITIAL_FILE_SIZE}
+generate_conf
+add_conf '
+action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
+ action.errorfile="'$ERRFILE'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+check_file_exists ${ERRFILE}
+file_size_check ${ERRFILE} ${MAX_ERROR_SIZE}
+exit_test
diff --git a/tests/omfwd-errfile-maxsize.sh b/tests/omfwd-errfile-maxsize.sh
new file mode 100755
index 0000000..91756a8
--- /dev/null
+++ b/tests/omfwd-errfile-maxsize.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export MAX_ERROR_SIZE=1999
+
+generate_conf
+add_conf '
+action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
+ action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+check_file_exists ${RSYSLOG2_OUT_LOG}
+file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
+exit_test
diff --git a/tests/omfwd-keepalive.sh b/tests/omfwd-keepalive.sh
new file mode 100755
index 0000000..32b30fa
--- /dev/null
+++ b/tests/omfwd-keepalive.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# addd 2016-03-30 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="list") {
+ property(name="msg")
+ constant(value="\n")
+}
+:msg, contains, "x-pid" stop
+
+
+if $msg contains "msgnum:" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+
+:msg, contains, "this does not occur" action(type="omfwd"
+ target="10.0.0.1" keepalive="on" keepalive.probes="10"
+ keepalive.time="60" keepalive.interval="10")
+
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo " msgnum:00000000:" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/omfwd-tls-invalid-permitExpiredCerts.sh b/tests/omfwd-tls-invalid-permitExpiredCerts.sh
new file mode 100755
index 0000000..da845fc
--- /dev/null
+++ b/tests/omfwd-tls-invalid-permitExpiredCerts.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# add 2020-01-08 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfwd" target="localhost" port="514" streamdriver.permitexpiredcerts="invld")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "streamdriver.permitExpiredCerts must be 'warn', 'off' or 'on' but is 'invld'"
+exit_test
diff --git a/tests/omfwd_fast_imuxsock.sh b/tests/omfwd_fast_imuxsock.sh
new file mode 100755
index 0000000..10f9f19
--- /dev/null
+++ b/tests/omfwd_fast_imuxsock.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# This test tries tests DiscardMark / DiscardSeverity queue settings with omfwd with IMUXSOCK input
+# added 2021-09-02 by alorbach. Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "We have no ATOMIC BUILTINS, so OverallQueueSize counting of imdiag is NOT threadsafe and the counting will fail on SunOS"
+
+./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1
+no_liblogging_stdlog=$?
+if [ $no_liblogging_stdlog -ne 0 ];then
+ echo "liblogging-stdlog not available - skipping test"
+ exit 77
+fi
+
+# export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export NUMMESSAGES=100000
+
+export PORT_RCVR="$(get_free_port)"
+export STATSFILE="$RSYSLOG_DYNNAME.stats"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+generate_conf
+add_conf '
+global( debug.whitelist="on"
+ debug.files=["imdiag.c", "queue.c"]
+)
+
+template(name="testformat" type="list") {
+ constant(value="{ ")
+ property(name="timereported" dateFormat="unixtimestamp" format="jsonf")
+ constant(value=", ")
+ property(name="syslogseverity-text" format="jsonf")
+ constant(value=", ")
+ property(name="programname" format="jsonf")
+ constant(value=", ")
+ property(name="msg" format="jsonf")
+ constant(value=" }\n")
+}
+template(name="outfmt"
+ type="string"
+ string="%msg:F,58:2%\n")
+
+# IMUX Input socket
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket")
+
+# Note: stats module
+module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1" ruleset="stats")
+
+main_queue(
+ queue.timeoutshutdown="10000"
+# queue.timeoutEnqueue="20"
+# queue.discardSeverity="3"
+)
+
+ruleset(name="stats") {
+ stop # nothing to do here
+}
+
+if $msg contains "test message nbr" then
+ action(
+ type="omfwd"
+ Target="127.0.0.1"
+ Port="'$PORT_RCVR'"
+ Protocol="tcp"
+ TCP_Framing="octet-counted"
+ ResendLastMSGOnReconnect="on"
+
+ Template="testformat"
+
+ queue.discardMark="100"
+ queue.discardSeverity="3"
+
+# queue.timeoutEnqueue="5"
+ queue.type="linkedlist"
+ )
+'
+./minitcpsrv -t127.0.0.1 -p$PORT_RCVR -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background tcp dummy receiver process id is $BGPROCESS
+
+# now do the usual run
+startup
+
+# Use syslog_caller
+./syslog_caller -m$NUMMESSAGES -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket"
+shutdown_when_empty
+wait_shutdown
+# note: minitcpsrv shuts down automatically if the connection is closed!
+
+# check output file generation, should contain at least 100 logs
+check_file_exists "$RSYSLOG_OUT_LOG"
+check_file_exists "$STATSFILE"
+content_check --regex --output-results "action-1-builtin:omfwd queue: origin=core.queue size=.* enqueued=100000 full=0 discarded.full=0 discarded.nf=.* maxqsize=100" $STATSFILE
+
+exit_test
diff --git a/tests/omfwd_impstats-tcp.sh b/tests/omfwd_impstats-tcp.sh
new file mode 100755
index 0000000..2faae1a
--- /dev/null
+++ b/tests/omfwd_impstats-tcp.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# This test tests impstats omfwd counters in TCP mode
+# added 2021-02-11 by rgerhards. Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+export STATSFILE="$RSYSLOG_DYNNAME.stats"
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+
+module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'"
+ interval="1" ruleset="stats")
+
+ruleset(name="stats") {
+ stop # nothing to do here
+}
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="builtin:omfwd" template="outfmt")
+
+if $msg contains "msgnum:" then
+ action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp")
+'
+./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background minitcpsrv process id is $BGPROCESS
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty
+wait_shutdown
+# note: minitcpsrv shuts down automatically if the connection is closed!
+
+# check pstats - that's our prime test target
+content_check --regex "TCP-.*origin=omfwd .*bytes.sent=[1-9][0-9][0-9]" "$STATSFILE"
+
+# do a bonus test while we are at it (just make sure we actually sent data)
+seq_check 0 9999
+exit_test
diff --git a/tests/omfwd_impstats-udp.sh b/tests/omfwd_impstats-udp.sh
new file mode 100755
index 0000000..56983e6
--- /dev/null
+++ b/tests/omfwd_impstats-udp.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This test tests impstats omfwd counters in UPD mode
+# added 2021-02-11 by rgerhards. Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+export STATSFILE="$RSYSLOG_DYNNAME.stats"
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+
+module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'"
+ interval="1" ruleset="stats")
+
+ruleset(name="stats") {
+ stop # nothing to do here
+}
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+module(load="builtin:omfwd" template="outfmt")
+
+if $msg contains "msgnum:" then
+ action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="udp")
+'
+# note: there must be no actual data - it's fine for this test if all data is lost
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty
+wait_shutdown
+
+# check pstats - that's our prime test target
+content_check --regex "UDP-.*origin=omfwd .*bytes.sent=[1-9][0-9][0-9]" "$STATSFILE"
+exit_test
diff --git a/tests/omhttp-auth-vg.sh b/tests/omhttp-auth-vg.sh
new file mode 100755
index 0000000..8f28dca
--- /dev/null
+++ b/tests/omhttp-auth-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-auth.sh
diff --git a/tests/omhttp-auth.sh b/tests/omhttp-auth.sh
new file mode 100755
index 0000000..4a93e4c
--- /dev/null
+++ b/tests/omhttp-auth.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=100
+
+omhttp_start_server 0 --userpwd="bob:bobbackwards"
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ uid="bob"
+ pwd="bobbackwards"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-basic-vg.sh b/tests/omhttp-basic-vg.sh
new file mode 100755
index 0000000..0837cb6
--- /dev/null
+++ b/tests/omhttp-basic-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-basic.sh
diff --git a/tests/omhttp-basic.sh b/tests/omhttp-basic.sh
new file mode 100755
index 0000000..52ec9c9
--- /dev/null
+++ b/tests/omhttp-basic.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=10000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-dynrestpath.sh b/tests/omhttp-batch-dynrestpath.sh
new file mode 100755
index 0000000..28fe798
--- /dev/null
+++ b/tests/omhttp-batch-dynrestpath.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=10000
+export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+template(name="dynrestpath" type="string" string="my/endpoint")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ dynrestpath = "on"
+ restpath="dynrestpath"
+
+ batch="on"
+ batch.format="jsonarray"
+ batch.maxsize="1000"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-fail-with-400.sh b/tests/omhttp-batch-fail-with-400.sh
new file mode 100755
index 0000000..7d2347b
--- /dev/null
+++ b/tests/omhttp-batch-fail-with-400.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+omhttp_start_server 0 --fail-with-400-after 1000
+
+generate_conf
+add_conf '
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+# Wrap message as a single batch for retry
+template(name="tpl_retry" type="string" string="[%msg%]")
+
+
+ruleset(name="ruleset_omhttp") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="off"
+
+ retry="on"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+if $msg contains "msgnum:" then
+ call ruleset_omhttp
+'
+startup
+injectmsg 0 10000
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check 0 999
+exit_test
diff --git a/tests/omhttp-batch-jsonarray-compress-vg.sh b/tests/omhttp-batch-jsonarray-compress-vg.sh
new file mode 100755
index 0000000..3fdd7fc
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray-compress-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-batch-jsonarray-compress.sh
diff --git a/tests/omhttp-batch-jsonarray-compress.sh b/tests/omhttp-batch-jsonarray-compress.sh
new file mode 100755
index 0000000..728ae2e
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray-compress.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0 --decompress
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.format="jsonarray"
+ batch.maxsize="1000"
+ compress="on"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-jsonarray-retry-vg.sh b/tests/omhttp-batch-jsonarray-retry-vg.sh
new file mode 100755
index 0000000..147e16b
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray-retry-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-batch-jsonarray-retry.sh
diff --git a/tests/omhttp-batch-jsonarray-retry.sh b/tests/omhttp-batch-jsonarray-retry.sh
new file mode 100755
index 0000000..22e4448
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray-retry.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0 --fail-every 100
+
+generate_conf
+add_conf '
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+# Echo message as-is for retry
+template(name="tpl_echo" type="string" string="%msg%")
+
+ruleset(name="ruleset_omhttp_retry") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl_echo"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="jsonarray"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+ruleset(name="ruleset_omhttp") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="jsonarray"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+if $msg contains "msgnum:" then
+ call ruleset_omhttp
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-jsonarray-vg.sh b/tests/omhttp-batch-jsonarray-vg.sh
new file mode 100755
index 0000000..a2300ee
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-batch-jsonarray.sh
diff --git a/tests/omhttp-batch-jsonarray.sh b/tests/omhttp-batch-jsonarray.sh
new file mode 100755
index 0000000..41bbcdb
--- /dev/null
+++ b/tests/omhttp-batch-jsonarray.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.format="jsonarray"
+ batch.maxsize="1000"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-kafkarest-retry-vg.sh b/tests/omhttp-batch-kafkarest-retry-vg.sh
new file mode 100755
index 0000000..c0b8eb6
--- /dev/null
+++ b/tests/omhttp-batch-kafkarest-retry-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh
diff --git a/tests/omhttp-batch-kafkarest-retry.sh b/tests/omhttp-batch-kafkarest-retry.sh
new file mode 100755
index 0000000..b81c6f0
--- /dev/null
+++ b/tests/omhttp-batch-kafkarest-retry.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0 --fail-every 100
+
+generate_conf
+add_conf '
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+# Echo message as-is for retry
+template(name="tpl_echo" type="string" string="%msg%")
+
+ruleset(name="ruleset_omhttp_retry") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl_echo"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="kafkarest"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+ruleset(name="ruleset_omhttp") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="kafkarest"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+if $msg contains "msgnum:" then
+ call ruleset_omhttp
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint kafkarest
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-kafkarest.sh b/tests/omhttp-batch-kafkarest.sh
new file mode 100755
index 0000000..a9fcb1c
--- /dev/null
+++ b/tests/omhttp-batch-kafkarest.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.format="kafkarest"
+ batch.maxsize="100"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint kafkarest
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-lokirest-retry-vg.sh b/tests/omhttp-batch-lokirest-retry-vg.sh
new file mode 100755
index 0000000..c0b8eb6
--- /dev/null
+++ b/tests/omhttp-batch-lokirest-retry-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh
diff --git a/tests/omhttp-batch-lokirest-retry.sh b/tests/omhttp-batch-lokirest-retry.sh
new file mode 100755
index 0000000..56eeaab
--- /dev/null
+++ b/tests/omhttp-batch-lokirest-retry.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0 --fail-every 100
+
+generate_conf
+add_conf '
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+# Echo message as-is for retry
+template(name="tpl_echo" type="string" string="%msg%")
+
+ruleset(name="ruleset_omhttp_retry") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl_echo"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="lokirest"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+ruleset(name="ruleset_omhttp") {
+ action(
+ name="action_omhttp"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.maxsize="100"
+ batch.format="lokirest"
+
+ retry="on"
+ retry.ruleset="ruleset_omhttp_retry"
+
+ # Auth
+ usehttps="off"
+ ) & stop
+}
+
+if $msg contains "msgnum:" then
+ call ruleset_omhttp
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint lokirest
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-lokirest-vg.sh b/tests/omhttp-batch-lokirest-vg.sh
new file mode 100755
index 0000000..e1eeca8
--- /dev/null
+++ b/tests/omhttp-batch-lokirest-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+# export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes --leak-check=full"
+
+source ${srcdir:=.}/omhttp-batch-lokirest.sh
diff --git a/tests/omhttp-batch-lokirest.sh b/tests/omhttp-batch-lokirest.sh
new file mode 100755
index 0000000..c36add7
--- /dev/null
+++ b/tests/omhttp-batch-lokirest.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.format="lokirest"
+ batch.maxsize="100"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint lokirest
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-batch-newline.sh b/tests/omhttp-batch-newline.sh
new file mode 100755
index 0000000..19ef43b
--- /dev/null
+++ b/tests/omhttp-batch-newline.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="on"
+ batch.format="newline"
+ batch.maxsize="100"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint newline
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-dynrestpath.sh b/tests/omhttp-dynrestpath.sh
new file mode 100755
index 0000000..60f22d9
--- /dev/null
+++ b/tests/omhttp-dynrestpath.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=10000
+export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+template(name="dynrestpath" type="string" string="my/endpoint")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ dynrestpath = "on"
+ restpath="dynrestpath"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-httpheaderkey.sh b/tests/omhttp-httpheaderkey.sh
new file mode 100755
index 0000000..91f3253
--- /dev/null
+++ b/tests/omhttp-httpheaderkey.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=1000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+ httpheaderkey="X-Insert-Key"
+ httpheadervalue="dummy-value"
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-multiplehttpheaders.sh b/tests/omhttp-multiplehttpheaders.sh
new file mode 100755
index 0000000..b547bd0
--- /dev/null
+++ b/tests/omhttp-multiplehttpheaders.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=1000
+
+omhttp_start_server 0
+
+generate_conf
+add_conf '
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+module(load="../contrib/omhttp/.libs/omhttp")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+ httpheaders=[
+ "X-Insert-Key: dummy-value",
+ "X-Event-Source: logs"
+ ]
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp-retry-vg.sh b/tests/omhttp-retry-vg.sh
new file mode 100755
index 0000000..ecc74cf
--- /dev/null
+++ b/tests/omhttp-retry-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omhttp-retry.sh
diff --git a/tests/omhttp-retry.sh b/tests/omhttp-retry.sh
new file mode 100755
index 0000000..f174f42
--- /dev/null
+++ b/tests/omhttp-retry.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Starting actual testbench
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=10000
+
+omhttp_start_server 0 --fail-every 1000
+
+generate_conf
+add_conf '
+module(load="../contrib/omhttp/.libs/omhttp")
+
+main_queue(queue.dequeueBatchSize="2048")
+
+template(name="tpl" type="string"
+ string="{\"msgnum\":\"%msg:F,58:2%\"}")
+
+if $msg contains "msgnum:" then
+ action(
+ # Payload
+ action.resumeRetryCount="-1"
+ name="my_http_action"
+ type="omhttp"
+ errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'"
+ template="tpl"
+
+ server="localhost"
+ serverport="'$omhttp_server_lstnport'"
+ restpath="my/endpoint"
+ checkpath="ping"
+ batch="off"
+
+ # Auth
+ usehttps="off"
+ )
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+omhttp_get_data $omhttp_server_lstnport my/endpoint
+omhttp_stop_server
+seq_check
+exit_test
diff --git a/tests/omhttp_server.py b/tests/omhttp_server.py
new file mode 100644
index 0000000..61e0e63
--- /dev/null
+++ b/tests/omhttp_server.py
@@ -0,0 +1,135 @@
+# call this via "python[3] script name"
+import argparse
+import json
+import os
+import zlib
+import base64
+
+try:
+ from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer # Python 2
+except ImportError:
+ from http.server import BaseHTTPRequestHandler, HTTPServer # Python 3
+
+# Keep track of data received at each path
+data = {}
+
+metadata = {'posts': 0, 'fail_after': 0, 'fail_every': -1, 'decompress': False, 'userpwd': ''}
+
+
+class MyHandler(BaseHTTPRequestHandler):
+ """
+ POST'd data is kept in the data global dict.
+ Keys are the path, values are the raw received data.
+ Two post requests to <host>:<port>/post/endpoint means data looks like...
+ {"/post/endpoint": ["{\"msgnum\":\"00001\"}", "{\"msgnum\":\"00001\"}"]}
+
+ GET requests return all data posted to that endpoint as a json list.
+ Note that rsyslog usually sends escaped json data, so some parsing may be needed.
+ A get request for <host>:<post>/post/endpoint responds with...
+ ["{\"msgnum\":\"00001\"}", "{\"msgnum\":\"00001\"}"]
+ """
+
+ def validate_auth(self):
+ # header format for basic authentication
+ # 'Authorization: Basic <base 64 encoded uid:pwd>'
+ if 'Authorization' not in self.headers:
+ self.send_response(401)
+ self.end_headers()
+ self.wfile.write(b'missing "Authorization" header')
+ return False
+
+ auth_header = self.headers['Authorization']
+ _, b64userpwd = auth_header.split()
+ userpwd = base64.b64decode(b64userpwd).decode('utf-8')
+ if userpwd != metadata['userpwd']:
+ self.send_response(401)
+ self.end_headers()
+ self.wfile.write(b'invalid auth: {0}'.format(userpwd))
+ return False
+
+ return True
+
+ def do_POST(self):
+ metadata['posts'] += 1
+
+ if metadata['userpwd']:
+ if not self.validate_auth():
+ return
+
+ if metadata['fail_with_400_after'] != -1 and metadata['posts'] > metadata['fail_with_400_after']:
+ self.send_response(400)
+ self.end_headers()
+ self.wfile.write(b'BAD REQUEST')
+ return
+
+ if metadata['posts'] > 1 and metadata['fail_every'] != -1 and metadata['posts'] % metadata['fail_every'] == 0:
+ self.send_response(500)
+ self.end_headers()
+ self.wfile.write(b'INTERNAL ERROR')
+ return
+
+ content_length = int(self.headers['Content-Length'] or 0)
+ raw_data = self.rfile.read(content_length)
+
+ if metadata['decompress']:
+ post_data = zlib.decompress(raw_data, 31)
+ else:
+ post_data = raw_data
+
+ if self.path not in data:
+ data[self.path] = []
+ data[self.path].append(post_data.decode('utf-8'))
+
+ res = json.dumps({'msg': 'ok'}).encode('utf8')
+
+ self.send_response(200)
+ self.send_header('Content-Type', 'application/json; charset=utf-8')
+ self.send_header('Content-Length', len(res))
+ self.end_headers()
+
+ self.wfile.write(res)
+ return
+
+ def do_GET(self):
+ if self.path in data:
+ result = data[self.path]
+ else:
+ result = []
+
+ res = json.dumps(result).encode('utf8')
+
+ self.send_response(200)
+ self.send_header('Content-Type', 'application/json; charset=utf-8')
+ self.send_header('Content-Length', len(res))
+ self.end_headers()
+
+ self.wfile.write(res)
+ return
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Archive and delete core app log files')
+ parser.add_argument('-p', '--port', action='store', type=int, default=8080, help='port')
+ parser.add_argument('--port-file', action='store', type=str, default='', help='file to store listen port number')
+ parser.add_argument('-i', '--interface', action='store', type=str, default='localhost', help='port')
+ parser.add_argument('--fail-after', action='store', type=int, default=0, help='start failing after n posts')
+ parser.add_argument('--fail-every', action='store', type=int, default=-1, help='fail every n posts')
+ parser.add_argument('--fail-with-400-after', action='store', type=int, default=-1, help='fail with 400 after n posts')
+ parser.add_argument('--decompress', action='store_true', default=False, help='decompress posted data')
+ parser.add_argument('--userpwd', action='store', default='', help='only accept this user:password combination')
+ args = parser.parse_args()
+ metadata['fail_after'] = args.fail_after
+ metadata['fail_every'] = args.fail_every
+ metadata['fail_with_400_after'] = args.fail_with_400_after
+ metadata['decompress'] = args.decompress
+ metadata['userpwd'] = args.userpwd
+ server = HTTPServer((args.interface, args.port), MyHandler)
+ lstn_port = server.server_address[1]
+ pid = os.getpid()
+ print('starting omhttp test server at {interface}:{port} with pid {pid}'
+ .format(interface=args.interface, port=lstn_port, pid=pid))
+ if args.port_file != '':
+ f = open(args.port_file, "w")
+ f.write(str(lstn_port))
+ f.close()
+ server.serve_forever()
diff --git a/tests/omjournal-abort-no-template.sh b/tests/omjournal-abort-no-template.sh
new file mode 100755
index 0000000..d86c744
--- /dev/null
+++ b/tests/omjournal-abort-no-template.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# a very basic test for omjournal. Right now, we have no
+# reliable way of verifying that data was actually written
+# to the journal, but at least we check that rsyslog does
+# not abort when trying to use omjournal. Not high tech,
+# but better than nothing.
+# addd 2016-03-16 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omjournal/.libs/omjournal")
+
+action(type="omjournal")
+'
+startup
+./msleep 500
+shutdown_when_empty
+wait_shutdown
+# if we reach this, we have at least not aborted
+exit_test
diff --git a/tests/omjournal-abort-template.sh b/tests/omjournal-abort-template.sh
new file mode 100755
index 0000000..2461012
--- /dev/null
+++ b/tests/omjournal-abort-template.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# a very basic test for omjournal. Right now, we have no
+# reliable way of verifying that data was actually written
+# to the journal, but at least we check that rsyslog does
+# not abort when trying to use omjournal. Not high tech,
+# but better than nothing.
+# addd 2016-03-16 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omjournal/.libs/omjournal")
+
+template(name="outfmt" type="string" string="%msg%")
+action(type="omjournal" template="outfmt")
+'
+startup
+./msleep 500
+shutdown_when_empty
+wait_shutdown
+# if we reach this, we have at least not aborted
+exit_test
diff --git a/tests/omjournal-basic-no-template.sh b/tests/omjournal-basic-no-template.sh
new file mode 100755
index 0000000..a31caea
--- /dev/null
+++ b/tests/omjournal-basic-no-template.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# a basic test for omjournal.
+# addd 2016-03-18 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh require-journalctl
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omjournal/.libs/omjournal")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omjournal")
+'
+startup
+tcpflood -m1 -M "\"<133>2011-03-01T11:22:12Z host tag msgh RsysLoG-TESTBENCH $COOKIE\""
+./msleep 500
+shutdown_when_empty
+wait_shutdown
+# if we reach this, we have at least not aborted
+journalctl -r -t rsyslogd: |grep "RsysLoG-TESTBENCH $COOKIE"
+if [ $? -ne 1 ]; then
+ echo "error: cookie $COOKIE not found. Head of journal:"
+ journalctl -r -t rsyslogd: | head
+ exit 1
+fi
+exit_test
diff --git a/tests/omjournal-basic-template.sh b/tests/omjournal-basic-template.sh
new file mode 100755
index 0000000..bc48626
--- /dev/null
+++ b/tests/omjournal-basic-template.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# a very basic test for omjournal.
+# addd 2016-03-18 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh require-journalctl
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omjournal/.libs/omjournal")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg%")
+action(type="omjournal" template="outfmt")
+'
+
+# we generate a cookie so that we can find our record in journal
+COOKIE=`date`
+echo "COOKIE: $COOKIE"
+startup
+tcpflood -m1 -M "\"<133>2011-03-01T11:22:12Z host tag msgh RsysLoG-TESTBENCH $COOKIE\""
+./msleep 500
+shutdown_when_empty
+wait_shutdown
+# if we reach this, we have at least not aborted
+journalctl -r -t rsyslogd: |grep "RsysLoG-TESTBENCH $COOKIE"
+if [ $? -ne 1 ]; then
+ echo "error: cookie $COOKIE not found. Head of journal:"
+ journalctl -r -t rsyslogd: | head
+ exit 1
+fi
+exit_test
diff --git a/tests/omkafka-vg.sh b/tests/omkafka-vg.sh
new file mode 100755
index 0000000..81ca63c
--- /dev/null
+++ b/tests/omkafka-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/omkafka.sh
diff --git a/tests/omkafka.sh b/tests/omkafka.sh
new file mode 100755
index 0000000..5ce4bd6
--- /dev/null
+++ b/tests/omkafka.sh
@@ -0,0 +1,129 @@
+#!/bin/bash
+# added 2017-05-03 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+test_status unreliable 'https://github.com/rsyslog/rsyslog/issues/3197'
+check_command_available kafkacat
+
+export KEEP_KAFKA_RUNNING="YES"
+export TESTMESSAGES=100000
+export TESTMESSAGESFULL=$TESTMESSAGES
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+echo Check and Stop previous instances of kafka/zookeeper
+download_kafka
+stop_zookeeper
+stop_kafka
+
+echo Create kafka/zookeeper instance and $RANDTOPIC topic
+start_zookeeper
+start_kafka
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# --- Create/Start omkafka sender config
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+$imdiagInjectDelayMode full
+
+module(load="../plugins/omkafka/.libs/omkafka")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+local4.* {
+ action( name="kafka-fwd"
+ type="omkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ template="outfmt"
+ confParam=[ "compression.codec=none",
+ "socket.timeout.ms=10000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "queue.buffering.max.messages=10000",
+ "enable.auto.commit=true",
+ "message.send.max.retries=1"]
+ topicConfParam=["message.timeout.ms=10000"]
+ partitions.auto="on"
+ closeTimeout="60000"
+ resubmitOnFailure="on"
+ keepFailedMessages="on"
+ failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC'.data"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ queue.saveonshutdown="on"
+ )
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+'
+
+echo Starting sender instance [omkafka]
+startup
+
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $TESTMESSAGES
+
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGESFULL 100
+
+# experimental: wait until kafkacat receives everything
+
+timeoutend=100
+timecounter=0
+
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG
+ count=$(wc -l < ${RSYSLOG_OUT_LOG})
+ if [ $count -eq $TESTMESSAGESFULL ]; then
+ printf '**** wait-kafka-lines success, have %d lines ****\n\n' "$TESTMESSAGESFULL"
+ break
+ else
+ if [ "x$timecounter" == "x$timeoutend" ]; then
+ echo wait-kafka-lines failed, expected $TESTMESSAGESFULL got $count
+ shutdown_when_empty
+ wait_shutdown
+ error_exit 1
+ else
+ echo wait-file-lines not yet there, currently $count lines
+printf 'pstats data:\n'
+cat $RSYSLOG_DYNNAME.pstats
+ printf '\n'
+
+ $TESTTOOL_DIR/msleep 1000
+ fi
+ fi
+done
+unset count
+
+#end experimental
+
+echo Stopping sender instance [omkafka]
+shutdown_when_empty
+wait_shutdown
+
+#kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG
+#kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%p@%o:%k:%s' > $RSYSLOG_OUT_LOG.extra
+
+# Delete topic to remove old traces before
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# Dump Kafka log | uncomment if needed
+# dump_kafka_serverlog
+
+kafka_check_broken_broker $RSYSLOG_DYNNAME.othermsg
+seq_check 1 $TESTMESSAGESFULL -d
+
+exit_test
diff --git a/tests/omkafkadynakey.sh b/tests/omkafkadynakey.sh
new file mode 100755
index 0000000..a05a5ad
--- /dev/null
+++ b/tests/omkafkadynakey.sh
@@ -0,0 +1,154 @@
+#!/bin/bash
+# added 2018-12-18 by ludobrands
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+test_status unreliable 'https://github.com/rsyslog/rsyslog/issues/3197'
+check_command_available kafkacat
+
+export KEEP_KAFKA_RUNNING="YES"
+export TESTMESSAGES=100000
+export TESTMESSAGESFULL=$TESTMESSAGES
+
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+echo Check and Stop previous instances of kafka/zookeeper
+download_kafka
+stop_zookeeper
+stop_kafka
+
+echo Create kafka/zookeeper instance and $RANDTOPIC topic
+start_zookeeper
+start_kafka
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# --- Create/Start omkafka sender config
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+$imdiagInjectDelayMode full
+
+module(load="../plugins/omkafka/.libs/omkafka")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+template(name="keyin" type="list"){
+ property(name="$.inkey")
+}
+
+local4.* {
+ set $.inkey = substring(field($msg,":",2),7,1);
+ action( name="kafka-fwd"
+ type="omkafka"
+ topic="'$RANDTOPIC'"
+ key="keyin"
+ dynaKey="on"
+ broker="localhost:29092"
+ template="outfmt"
+ confParam=[ "compression.codec=none",
+ "socket.timeout.ms=10000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "queue.buffering.max.messages=10000",
+ "enable.auto.commit=true",
+ "message.send.max.retries=1"]
+ topicConfParam=["message.timeout.ms=10000"]
+ partitions.auto="on"
+ closeTimeout="60000"
+ resubmitOnFailure="on"
+ keepFailedMessages="on"
+ failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC'.data"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ queue.saveonshutdown="on"
+ )
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+'
+
+echo Starting sender instance [omkafka]
+startup
+
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $TESTMESSAGES
+
+wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGESFULL 100
+
+# experimental: wait until kafkacat receives everything
+
+timeoutend=100
+timecounter=0
+
+while [ $timecounter -lt $timeoutend ]; do
+ (( timecounter++ ))
+
+ kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG
+ count=$(wc -l < ${RSYSLOG_OUT_LOG})
+ if [ $count -eq $TESTMESSAGESFULL ]; then
+ printf '**** wait-kafka-lines success, have %d lines ****\n\n' "$TESTMESSAGESFULL"
+ kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%p %k\n' | sort | uniq > "$RSYSLOG_OUT_LOG.extra"
+ count=$(wc -l < "${RSYSLOG_OUT_LOG}.extra")
+ if [ $count -eq 10 ]; then
+ printf '**** partition check success, have 10 partition-key combinations ****\n\n'
+ break
+ else
+ shutdown_when_empty
+ wait_shutdown
+ printf '\n\nERROR: partition check failed, expected 10 got %s\n' "$count"
+ printf '\ņRAW DATA:\n'
+ kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%p %k\n'
+ printf '\nCHECKED OUTPUT:\n'
+ cat "$RSYSLOG_OUT_LOG.extra"
+ error_exit 1
+ fi
+ else
+ if [ "x$timecounter" == "x$timeoutend" ]; then
+ echo wait-kafka-lines failed, expected $TESTMESSAGESFULL got $count
+ shutdown_when_empty
+ wait_shutdown
+ error_exit 1
+ else
+ echo wait-file-lines not yet there, currently $count lines
+ printf 'pstats data:\n'
+ # we use tail below to guard against overwhelming the
+ # logs if things go wild
+ tail -n 500 < $RSYSLOG_DYNNAME.pstats
+ printf '\n'
+
+ $TESTTOOL_DIR/msleep 1000
+ fi
+ fi
+echo end iteration $timecounter
+done
+unset count
+
+#end experimental
+
+echo Stopping sender instance [omkafka]
+shutdown_when_empty
+wait_shutdown
+
+#kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG
+#kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%p@%o:%k:%s' > $RSYSLOG_OUT_LOG.extra
+
+# Delete topic to remove old traces before
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# Dump Kafka log | uncomment if needed
+# dump_kafka_serverlog
+
+kafka_check_broken_broker $RSYSLOG_DYNNAME.othermsg
+seq_check 1 $TESTMESSAGESFULL -d
+
+exit_test
+
diff --git a/tests/ommail_errmsg_no_params.sh b/tests/ommail_errmsg_no_params.sh
new file mode 100755
index 0000000..096b617
--- /dev/null
+++ b/tests/ommail_errmsg_no_params.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# add 2018-09-25 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/ommail/.libs/ommail")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+action(type="ommail")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'mailto' required but not specified"
+
+exit_test
diff --git a/tests/omod-if-array-udp.sh b/tests/omod-if-array-udp.sh
new file mode 100755
index 0000000..7a87a8b
--- /dev/null
+++ b/tests/omod-if-array-udp.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%PRI%%timestamp%%hostname%%programname%%syslogtag%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\""
+shutdown_when_empty
+wait_shutdown
+
+echo '167Mar 6 16:57:54172.20.245.8%PIX-7-710005%PIX-7-710005:' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/omod-if-array.sh b/tests/omod-if-array.sh
new file mode 100755
index 0000000..1915b04
--- /dev/null
+++ b/tests/omod-if-array.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%PRI%%timestamp%%hostname%%programname%%syslogtag%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\""
+shutdown_when_empty
+wait_shutdown
+
+echo '167Mar 6 16:57:54172.20.245.8%PIX-7-710005%PIX-7-710005:' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/omprog-close-unresponsive-noterm.sh b/tests/omprog-close-unresponsive-noterm.sh
new file mode 100755
index 0000000..1ed43f5
--- /dev/null
+++ b/tests/omprog-close-unresponsive-noterm.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test checks that omprog does NOT send a TERM signal to the
+# external program when signalOnClose=off, closes the pipe, and kills
+# the unresponsive child if killUnresponsive=on.
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+main_queue(
+ queue.timeoutShutdown="60000" # give time to omprog to wait for the child
+)
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$RSYSLOG_DYNNAME.'omprog-close-unresponsive-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ signalOnClose="off"
+ closeTimeout="1000" # ms
+ killUnresponsive="on" # default value: the value of signalOnClose
+ )
+}
+'
+cp -f $srcdir/testsuites/omprog-close-unresponsive-bin.sh $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+. $srcdir/diag.sh ensure-no-process-exists $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh
+
+export EXPECTED="Starting
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating unresponsively"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-close-unresponsive-vg.sh b/tests/omprog-close-unresponsive-vg.sh
new file mode 100755
index 0000000..fea4da7
--- /dev/null
+++ b/tests/omprog-close-unresponsive-vg.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Same test than 'omprog-close-unresponsive.sh', but checking for memory
+# problems using valgrind. Note it is not necessary to repeat the
+# rest of checks (this simplifies the maintenance of the tests).
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+main_queue(
+ queue.timeoutShutdown="60000" # give time to omprog to wait for the child
+)
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-close-unresponsive-bin.sh`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ signalOnClose="on"
+ closeTimeout="1000" # ms
+ #killUnresponsive="on" # default value: the value of signalOnClose
+ )
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+exit_test
diff --git a/tests/omprog-close-unresponsive.sh b/tests/omprog-close-unresponsive.sh
new file mode 100755
index 0000000..3631f3f
--- /dev/null
+++ b/tests/omprog-close-unresponsive.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test checks that omprog sends a TERM signal to the external
+# program when signalOnClose=on, closes the pipe, and kills the
+# child if unresponsive.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+main_queue(
+ queue.timeoutShutdown="60000" # give time to omprog to wait for the child
+)
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$RSYSLOG_DYNNAME.'omprog-close-unresponsive-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ signalOnClose="on"
+ closeTimeout="1000" # ms
+ #killUnresponsive="on" # default value: the value of signalOnClose
+ )
+}
+'
+cp -f $srcdir/testsuites/omprog-close-unresponsive-bin.sh $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+. $srcdir/diag.sh ensure-no-process-exists $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh
+
+export EXPECTED="Starting
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Received msgnum:00000008:
+Received msgnum:00000009:
+Received SIGTERM
+Terminating unresponsively"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-defaults-vg.sh b/tests/omprog-defaults-vg.sh
new file mode 100755
index 0000000..53aae37
--- /dev/null
+++ b/tests/omprog-defaults-vg.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Same test than 'omprog-defaults.sh', but checking for memory
+# problems using valgrind. Note it is not necessary to repeat the
+# rest of checks (this simplifies the maintenance of the tests).
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-defaults-bin.sh p1 p2 p3`
+ template="outfmt"
+ name="omprog_action"
+ )
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+exit_test
diff --git a/tests/omprog-defaults.sh b/tests/omprog-defaults.sh
new file mode 100755
index 0000000..5c52550
--- /dev/null
+++ b/tests/omprog-defaults.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests omprog using the default values for all non-mandatory
+# settings. It also checks that command-line parameters are correctly
+# passed to the external program.
+
+# NOTE: Because the omprog feedback mode is not used in this test
+# (confirmMessages=off), it is difficult to synchronize the execution
+# of the external program with the test code. For this reason, it would
+# be difficult to test for negative cases (e.g. restart of the program
+# if it terminates prematurely) without making the test racy. So, we
+# only test a happy case: the program processes all logs received and
+# exits when the pipe is closed. After closing the pipe, omprog will
+# wait for the program to terminate during a timeout of 5 seconds
+# (default value of closeTimeout), which should be sufficient for the
+# program to write its output.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-defaults-bin.sh p1 p2 p3`
+ template="outfmt"
+ name="omprog_action"
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="Starting with parameters: p1 p2 p3
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating normally"
+
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-feedback-mt.sh b/tests/omprog-feedback-mt.sh
new file mode 100755
index 0000000..1fdc6d9
--- /dev/null
+++ b/tests/omprog-feedback-mt.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Similar to the 'omprog-feedback.sh' test, with multiple worker threads
+# on high load, and a given error rate (percentage of failed messages, i.e.
+# confirmed as failed by the program). Note: the action retry interval
+# (1 second) causes a very low throughput; we need to set a very low error
+# rate to avoid the test lasting too much.
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "On Solaris, this test causes rsyslog to hang for unknown reasons"
+if [ "$CC" == "gcc" ] && [[ "$CFLAGS" == *"-coverage"* ]]; then
+ printf 'This test does not work with gcc coverage instrumentation\n'
+ printf 'It will hang, but we do not know why. See\n'
+ printf 'https://github.com/rsyslog/rsyslog/issues/3361\n'
+ exit 77
+fi
+
+NUMMESSAGES=10000 # number of logs to send
+ERROR_RATE_PERCENT=1 # percentage of logs to be retried
+
+export command_line="$srcdir/testsuites/omprog-feedback-mt-bin.sh $ERROR_RATE_PERCENT"
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+main_queue(
+ queue.timeoutShutdown="30000" # long shutdown timeout for the main queue
+)
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $command_line`
+ template="outfmt"
+ name="omprog_action"
+ confirmMessages="on"
+ queue.type="LinkedList" # use a dedicated queue
+ queue.workerThreads="10" # ...with multiple workers
+ queue.size="10000" # ...high capacity (default is 1000)
+ queue.timeoutShutdown="60000" # ...and a long shutdown timeout
+ action.resumeInterval="1" # retry interval: 1 second
+ )
+}
+'
+startup
+injectmsg 0 $NUMMESSAGES
+wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/omprog-feedback-timeout.sh b/tests/omprog-feedback-timeout.sh
new file mode 100755
index 0000000..7b6361a
--- /dev/null
+++ b/tests/omprog-feedback-timeout.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests the feedback feature of omprog (confirmMessages=on),
+# by checking that omprog restarts the program if it does not send the
+# feedback before the configured 'confirmTimeout'. Also tests the
+# keep-alive feature.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-feedback-timeout-bin.sh`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on"
+ confirmTimeout="2000" # 2 seconds
+ reportFailures="on"
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="Starting
+<= OK
+=> msgnum:00000000:
+<= OK
+=> msgnum:00000001:
+<= OK
+=> msgnum:00000002:
+<= OK
+=> msgnum:00000003:
+<= OK
+=> msgnum:00000004:
+<= (timeout)
+Starting
+<= OK
+=> msgnum:00000004:
+<= OK
+=> msgnum:00000005:
+<= OK
+=> msgnum:00000006:
+<= OK
+=> msgnum:00000007:
+<= ........OK
+=> msgnum:00000008:
+<= OK
+=> msgnum:00000009:
+<= OK"
+
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-feedback-vg.sh b/tests/omprog-feedback-vg.sh
new file mode 100755
index 0000000..62545be
--- /dev/null
+++ b/tests/omprog-feedback-vg.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Same test than 'omprog-feedback.sh', but checking for memory
+# problems using valgrind. Note it is not necessary to repeat the
+# rest of checks (this simplifies the maintenance of the tests).
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-feedback-bin.sh`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct"
+ confirmMessages="on"
+ action.resumeInterval="1"
+ )
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+exit_test
diff --git a/tests/omprog-feedback.sh b/tests/omprog-feedback.sh
new file mode 100755
index 0000000..464ce33
--- /dev/null
+++ b/tests/omprog-feedback.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests the feedback feature of omprog (confirmMessages=on),
+# by checking that omprog re-sends to the external program the messages
+# it has failed to process.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$srcdir'/testsuites/omprog-feedback-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on"
+ reportFailures="on"
+ action.resumeInterval="1" # retry interval: 1 second
+# action.resumeRetryCount="0" # the default; no need to increase since
+ # the action resumes immediately
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="<= OK
+=> msgnum:00000000:
+<= OK
+=> msgnum:00000001:
+<= OK
+=> msgnum:00000002:
+<= OK
+=> msgnum:00000003:
+<= OK
+=> msgnum:00000004:
+<= Error: could not process log message
+=> msgnum:00000004:
+<= Error: could not process log message
+=> msgnum:00000004:
+<= OK
+=> msgnum:00000005:
+<= OK
+=> msgnum:00000006:
+<= OK
+=> msgnum:00000007:
+<= Error: could not process log message
+=> msgnum:00000007:
+<= Error: could not process log message
+=> msgnum:00000007:
+<= OK
+=> msgnum:00000008:
+<= OK
+=> msgnum:00000009:
+<= OK"
+
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-if-error.sh b/tests/omprog-if-error.sh
new file mode 100755
index 0000000..89e035e
--- /dev/null
+++ b/tests/omprog-if-error.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# This test tests omprog if omprog detects errors in the calling
+# interface, namely a missing LF on input messages
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%")
+
+if (prifilt("local4.*") and $msg contains "msgnum:") then {
+ action(type="omprog" binary="'$srcdir'/testsuites/omprog-defaults-bin.sh p1 p2 p3"
+ template="outfmt" name="omprog_action")
+} else {
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsg")
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+cat $RSYSLOG_DYNNAME.othermsg
+
+content_check 'must be terminated with \n' $RSYSLOG_DYNNAME.othermsg
+
+export EXPECTED="Starting with parameters: p1 p2 p3
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating normally"
+
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/omprog-output-capture-mt.sh b/tests/omprog-output-capture-mt.sh
new file mode 100755
index 0000000..ba1f86e
--- /dev/null
+++ b/tests/omprog-output-capture-mt.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Similar to the 'omprog-output-capture.sh' test, with multiple worker
+# threads on high load. Checks that the lines concurrently emitted to
+# stdout/stderr by the various program instances are not intermingled in
+# the output file (i.e., are captured atomically by omprog) when 1) the
+# lines are less than PIPE_BUF bytes long and 2) the program writes the
+# lines in unbuffered or line-buffered mode.
+
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on all flavors of Solaris (problems with Python?)"
+if [ "$CC" == "gcc" ] && [[ "$CFLAGS" == *"-coverage"* ]]; then
+ printf 'This test does not work with gcc coverage instrumentation\n'
+ printf 'It will hang, but we do not know why. See\n'
+ printf 'https://github.com/rsyslog/rsyslog/issues/3361\n'
+ exit 77
+fi
+
+export NUMMESSAGES=20000
+
+if [[ "$(uname)" == "Linux" ]]; then
+ export LINE_LENGTH=4095 # 4KB minus 1 byte (for the newline char)
+else
+ export LINE_LENGTH=511 # 512 minus 1 byte (for the newline char)
+fi
+
+empty_check() {
+ if [ $(wc -l < "$RSYSLOG_OUT_LOG") -ge $((NUMMESSAGES * 2)) ]; then
+ return 0
+ fi
+ return 1
+}
+export QUEUE_EMPTY_CHECK_FUNC=empty_check
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+main_queue(
+ queue.timeoutShutdown="60000" # long shutdown timeout for the main queue
+)
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$PYTHON' '$srcdir'/testsuites/omprog-output-capture-mt-bin.py '$LINE_LENGTH'"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="LinkedList" # use a dedicated queue
+ queue.workerThreads="10" # ...with many workers
+ queue.timeoutShutdown="60000" # ...and a long shutdown timeout
+ closeTimeout="10000" # wait enough for program to terminate
+ output=`echo $RSYSLOG_OUT_LOG`
+ fileCreateMode="0644"
+ )
+}
+'
+startup
+
+# Issue a HUP signal when the output-capture thread has not started yet,
+# to check that this case is handled correctly (the output file has not
+# been opened yet, so omprog must not try to reopen it).
+issue_HUP
+
+injectmsg 0 $NUMMESSAGES
+
+# Issue more HUP signals to cause the output file to be reopened during
+# writing (not a complete test of this feature, but at least we check it
+# doesn't break the output).
+issue_HUP
+./msleep 1000
+issue_HUP
+./msleep 1000
+issue_HUP
+
+#wait_file_lines "$RSYSLOG_OUT_LOG" $((NUMMESSAGES * 2))
+shutdown_when_empty
+wait_shutdown
+
+line_num=0
+while IFS= read -r line; do
+ ((line_num++))
+ if [[ ${#line} != $LINE_LENGTH ]]; then
+ echo "intermingled line in captured output: line: $line_num, length: ${#line} (expected: $LINE_LENGTH)"
+ echo "$line"
+ error_exit 1
+ fi
+done < $RSYSLOG_OUT_LOG
+
+if (( line_num != NUMMESSAGES * 2 )); then
+ echo "unexpected number of lines in captured output: $line_num (expected: $((NUMMESSAGES * 2)))"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-output-capture-vg.sh b/tests/omprog-output-capture-vg.sh
new file mode 100755
index 0000000..28975a6
--- /dev/null
+++ b/tests/omprog-output-capture-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+export RS_TEST_VALGRIND_EXTRA_OPTS="--child-silent-after-fork=yes"
+source ${srcdir:-.}/omprog-output-capture.sh
diff --git a/tests/omprog-output-capture.sh b/tests/omprog-output-capture.sh
new file mode 100755
index 0000000..bbe62e9
--- /dev/null
+++ b/tests/omprog-output-capture.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests the 'output' setting of omprog when the feedback
+# feature is not used (confirmMessages=off).
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$srcdir'/testsuites/omprog-output-capture-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ output="'$RSYSLOG_OUT_LOG'"
+ fileCreateMode="0644" # default is 0600
+ )
+}
+'
+startup
+injectmsg 0 10
+wait_file_lines "$RSYSLOG_OUT_LOG" 22
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="[stdout] Starting
+[stderr] Starting
+[stdout] Received msgnum:00000000:
+[stderr] Received msgnum:00000000:
+[stdout] Received msgnum:00000001:
+[stderr] Received msgnum:00000001:
+[stdout] Received msgnum:00000002:
+[stderr] Received msgnum:00000002:
+[stdout] Received msgnum:00000003:
+[stderr] Received msgnum:00000003:
+[stdout] Received msgnum:00000004:
+[stderr] Received msgnum:00000004:
+[stdout] Received msgnum:00000005:
+[stderr] Received msgnum:00000005:
+[stdout] Received msgnum:00000006:
+[stderr] Received msgnum:00000006:
+[stdout] Received msgnum:00000007:
+[stderr] Received msgnum:00000007:
+[stdout] Received msgnum:00000008:
+[stderr] Received msgnum:00000008:
+[stdout] Received msgnum:00000009:
+[stderr] Received msgnum:00000009:
+[stdout] Terminating normally
+[stderr] Terminating normally"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-restart-terminated-outfile.sh b/tests/omprog-restart-terminated-outfile.sh
new file mode 100755
index 0000000..e8afe33
--- /dev/null
+++ b/tests/omprog-restart-terminated-outfile.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Similar to the 'omprog-restart-terminated.sh' test, using the 'output'
+# parameter. Checks that no file descriptors are leaked across restarts
+# of the program when stderr is being captured to a file.
+
+. ${srcdir:=.}/diag.sh init
+check_command_available lsof
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$RSYSLOG_DYNNAME'.omprog-restart-terminated-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ action.resumeRetryCount="3"
+ action.resumeInterval="1"
+ action.reportSuspensionContinuation="on"
+ signalOnClose="off"
+ output=`echo $RSYSLOG2_OUT_LOG`
+ )
+}
+'
+
+# We need a test-specific program name, as the test needs to signal the child process
+cp -f $srcdir/testsuites/omprog-restart-terminated-bin.sh $RSYSLOG_DYNNAME.omprog-restart-terminated-bin.sh
+
+# On Solaris 10, the output of ps is truncated for long process names; use /usr/ucb/ps instead:
+if [[ $(uname) = "SunOS" && $(uname -r) = "5.10" ]]; then
+ function get_child_pid {
+ /usr/ucb/ps -awwx | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $1 }'
+ }
+else
+ function get_child_pid {
+ ps -ef | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $2 }'
+ }
+fi
+
+startup
+injectmsg 0 1
+wait_queueempty
+
+pid=$(getpid)
+start_fd_count=$(lsof -p $pid | wc -l)
+
+injectmsg 1 1
+injectmsg 2 1
+wait_queueempty
+
+kill -s USR1 $(get_child_pid)
+./msleep 100
+
+injectmsg 3 1
+injectmsg 4 1
+wait_queueempty
+
+kill -s TERM $(get_child_pid)
+./msleep 100
+
+injectmsg 5 1
+injectmsg 6 1
+injectmsg 7 1
+wait_queueempty
+
+kill -s KILL $(get_child_pid)
+./msleep 100
+
+injectmsg 8 1
+injectmsg 9 1
+wait_queueempty
+
+end_fd_count=$(lsof -p $pid | wc -l)
+
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="Starting
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received SIGUSR1, will terminate after the next message
+Received msgnum:00000003:
+Terminating without confirming the last message
+Starting
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received SIGTERM, terminating
+Starting
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Starting
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating normally"
+
+cmp_exact $RSYSLOG_OUT_LOG
+
+export EXPECTED="[stderr] Starting
+[stderr] Received msgnum:00000000:
+[stderr] Received msgnum:00000001:
+[stderr] Received msgnum:00000002:
+[stderr] Received SIGUSR1, will terminate after the next message
+[stderr] Received msgnum:00000003:
+[stderr] Terminating without confirming the last message
+[stderr] Starting
+[stderr] Received msgnum:00000003:
+[stderr] Received msgnum:00000004:
+[stderr] Received SIGTERM, terminating
+[stderr] Starting
+[stderr] Received msgnum:00000005:
+[stderr] Received msgnum:00000006:
+[stderr] Received msgnum:00000007:
+[stderr] Starting
+[stderr] Received msgnum:00000008:
+[stderr] Received msgnum:00000009:
+[stderr] Terminating normally"
+
+cmp_exact $RSYSLOG2_OUT_LOG
+
+if [[ "$start_fd_count" != "$end_fd_count" ]]; then
+ echo "file descriptor leak: started with $start_fd_count open files, ended with $end_fd_count"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-restart-terminated-vg.sh b/tests/omprog-restart-terminated-vg.sh
new file mode 100755
index 0000000..a090c30
--- /dev/null
+++ b/tests/omprog-restart-terminated-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2019-04-15 by RGerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omprog-restart-terminated.sh
diff --git a/tests/omprog-restart-terminated.sh b/tests/omprog-restart-terminated.sh
new file mode 100755
index 0000000..8fbc99e
--- /dev/null
+++ b/tests/omprog-restart-terminated.sh
@@ -0,0 +1,155 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test checks that omprog restarts the external program when it
+# terminates prematurely, and that it does so without leaking file
+# descriptors. Two cases are checked: termination of the program when
+# omprog is going to write to the pipe (to send a message to the
+# program), and when omprog is going to read from the pipe (when it
+# is expecting the program to confirm the last message).
+
+. ${srcdir:=.}/diag.sh init
+check_command_available lsof
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$RSYSLOG_DYNNAME'.omprog-restart-terminated-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ action.resumeRetryCount="3"
+ action.resumeInterval="1"
+ action.reportSuspensionContinuation="on"
+ signalOnClose="off"
+ )
+}
+
+syslog.* {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+'
+
+# We need a test-specific program name, as the test needs to signal the child process
+cp -f $srcdir/testsuites/omprog-restart-terminated-bin.sh $RSYSLOG_DYNNAME.omprog-restart-terminated-bin.sh
+
+# On Solaris 10, the output of ps is truncated for long process names; use /usr/ucb/ps instead:
+if [[ $(uname) = "SunOS" && $(uname -r) = "5.10" ]]; then
+ function get_child_pid {
+ /usr/ucb/ps -awwx | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $1 }'
+ }
+else
+ function get_child_pid {
+ ps -ef | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $2 }'
+ }
+fi
+
+startup
+injectmsg 0 1
+wait_queueempty
+
+pid=$(getpid)
+echo PID: $pid
+start_fd_count=$(lsof -p $pid | wc -l)
+
+injectmsg 1 1
+injectmsg 2 1
+wait_queueempty
+
+child_pid_1=$(get_child_pid)
+kill -s USR1 $child_pid_1
+./msleep 100
+
+injectmsg 3 1
+injectmsg 4 1
+wait_queueempty
+
+child_pid_2=$(get_child_pid)
+kill -s TERM $child_pid_2
+./msleep 100
+
+injectmsg 5 1
+injectmsg 6 1
+injectmsg 7 1
+wait_queueempty
+
+child_pid_3=$(get_child_pid)
+kill -s KILL $child_pid_3
+./msleep 100
+
+injectmsg 8 1
+injectmsg 9 1
+wait_queueempty
+
+end_fd_count=$(lsof -p $pid | wc -l)
+child_pid_4=$(get_child_pid)
+child_lsof=$(lsof -a -d 0-65535 -p $child_pid_4 | awk '$4 != "255r" { print $4 " " $9 }')
+
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="Starting
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received SIGUSR1, will terminate after the next message
+Received msgnum:00000003:
+Terminating without confirming the last message
+Starting
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received SIGTERM, terminating
+Starting
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Starting
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating normally"
+cmp_exact $RSYSLOG_OUT_LOG
+
+if [[ "$start_fd_count" != "$end_fd_count" ]]; then
+ echo "file descriptor leak: started with $start_fd_count open files, ended with $end_fd_count"
+ error_exit 1
+fi
+
+# Check that the child process does not inherit open fds from rsyslog
+# (apart from the pipes), and that stderr is redirected to /dev/null.
+# Ignore fd 255, which bash opens for internal use.
+
+EXPECTED_CHILD_LSOF="FD NAME
+0r pipe
+1w pipe
+2w /dev/null"
+
+# On Solaris, lsof gives this alternate output:
+EXPECTED_CHILD_LSOF_2="FD NAME
+0u (fifofs)
+1u (fifofs)
+2w "
+
+if [[ "$child_lsof" != "$EXPECTED_CHILD_LSOF" && "$child_lsof" != "$EXPECTED_CHILD_LSOF_2" ]]; then
+ echo "unexpected open files for child process:"
+ echo "$child_lsof"
+ error_exit 1
+fi
+
+# Check also that child process terminations are reported correctly.
+# When the reportChildProcessExits global parameter is "errors" (the default),
+# only non-zero exit codes are reported.
+content_check "(pid $child_pid_1) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+custom_assert_content_missing "(pid $child_pid_1) exited with status" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_2) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_2) exited with status 1" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_3) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_3) terminated by signal 9" $RSYSLOG2_OUT_LOG
+
+exit_test
diff --git a/tests/omprog-single-instance-outfile.sh b/tests/omprog-single-instance-outfile.sh
new file mode 100755
index 0000000..2ab789e
--- /dev/null
+++ b/tests/omprog-single-instance-outfile.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Similar to the 'omprog-single-instance.sh' test, using the 'output'
+# parameter. Checks that the output of the program is correctly captured
+# when the 'forceSingleInstance' flag is enabled.
+
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris"
+export NUMMESSAGES=10000 # number of logs to send
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$srcdir'/testsuites/omprog-single-instance-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ confirmMessages="on"
+ forceSingleInstance="on"
+ queue.type="LinkedList" # use a dedicated queue
+ queue.workerThreads="10" # ...with multiple workers
+ queue.size="5000" # ...high capacity (default is 1000)
+ queue.timeoutShutdown="30000" # ...and a long shutdown timeout
+ output="'$RSYSLOG2_OUT_LOG'"
+ )
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED_LINE_LENGTH=34 # example line: '[stderr] Received msgnum:00009880:'
+line_num=0
+while IFS= read -r line; do
+ ((line_num++))
+ if (( line_num == 1 )); then
+ if [[ "$line" != "[stderr] Starting" ]]; then
+ echo "unexpected first line in captured stderr: $line"
+ error_exit 1
+ fi
+ elif (( line_num == NUMMESSAGES + 2 )); then
+ if [[ "$line" != "[stderr] Terminating" ]]; then
+ echo "unexpected last line in captured stderr: $line"
+ error_exit 1
+ fi
+ elif [[ ${#line} != $EXPECTED_LINE_LENGTH ]]; then
+ echo "unexpected line in captured stderr (line $line_num): $line"
+ error_exit 1
+ fi
+done < $RSYSLOG2_OUT_LOG
+
+if (( line_num != NUMMESSAGES + 2 )); then
+ echo "unexpected line count in captured stderr: $line_num (expected: $((NUMMESSAGES + 2)))"
+ error_exit 1
+fi
+
+# Note: we use awk here to remove leading spaces returned by wc on FreeBSD
+line_count=$(wc -l < ${RSYSLOG_OUT_LOG} | awk '{print $1}')
+if (( line_count != NUMMESSAGES + 2 )); then
+ echo "unexpected line count in output: $line_count (expected: $((NUMMESSAGES + 2)))"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-single-instance-vg.sh b/tests/omprog-single-instance-vg.sh
new file mode 100755
index 0000000..5b7eb0c
--- /dev/null
+++ b/tests/omprog-single-instance-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2019-04-15 by RGerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/omprog-single-instance.sh
diff --git a/tests/omprog-single-instance.sh b/tests/omprog-single-instance.sh
new file mode 100755
index 0000000..64b088c
--- /dev/null
+++ b/tests/omprog-single-instance.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests the omprog 'forceSingleInstance' flag by checking
+# that only one instance of the program is started when multiple
+# workers are in effect.
+
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris "
+export NUMMESSAGES=10000 # number of logs to send
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$srcdir'/testsuites/omprog-single-instance-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ confirmMessages="on"
+ forceSingleInstance="on"
+ queue.type="LinkedList" # use a dedicated queue
+ queue.workerThreads="10" # ...with multiple workers
+ queue.size="5000" # ...high capacity (default is 1000)
+ queue.timeoutShutdown="30000" # ...and a long shutdown timeout
+ )
+}
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED_LINE_LENGTH=25 # example line: 'Received msgnum:00009880:'
+line_num=0
+while IFS= read -r line; do
+ ((line_num++))
+ if (( line_num == 1 )); then
+ if [[ "$line" != "Starting" ]]; then
+ echo "unexpected first line in output: $line"
+ error_exit 1
+ fi
+ elif (( line_num == NUMMESSAGES + 2 )); then
+ if [[ "$line" != "Terminating" ]]; then
+ echo "unexpected last line in output: $line"
+ error_exit 1
+ fi
+ elif [[ ${#line} != $EXPECTED_LINE_LENGTH ]]; then
+ echo "unexpected line in output (line $line_num): $line"
+ error_exit 1
+ fi
+done < $RSYSLOG_OUT_LOG
+
+if (( line_num != NUMMESSAGES + 2 )); then
+ echo "unexpected line count in output: $line_num (expected: $((NUMMESSAGES + 2)))"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-transactions-failed-commits.sh b/tests/omprog-transactions-failed-commits.sh
new file mode 100755
index 0000000..3e36a32
--- /dev/null
+++ b/tests/omprog-transactions-failed-commits.sh
@@ -0,0 +1,158 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests omprog with the confirmMessages=on and useTransactions=on
+# parameters, with the external program returning an error on certain
+# transaction commits.
+
+. ${srcdir:=.}/diag.sh init
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ # On Solaris, this test causes rsyslog to hang. This is presumably due
+ # to issue #2356 in the rsyslog core, which doesn't seem completely
+ # corrected. TODO: re-enable this test when the issue is corrected.
+ echo "Solaris: FIX ME"
+ exit 77
+fi
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh --failed_commits`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ queue.dequeueBatchSize="6"
+ confirmMessages="on"
+ useTransactions="on"
+ action.resumeRetryCount="10"
+ action.resumeInterval="1"
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+# Since the transaction boundaries are not deterministic, we cannot check for
+# an exact expected output. We must check the output programmatically.
+
+transaction_state="NONE"
+status_expected=true
+messages_to_commit=()
+messages_processed=()
+line_num=1
+error=
+
+while IFS= read -r line; do
+ if [[ $status_expected == true ]]; then
+ case "$transaction_state" in
+ "NONE")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ ;;
+ "STARTED")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ transaction_state="ACTIVE"
+ ;;
+ "ACTIVE")
+ if [[ "$line" != "<= DEFER_COMMIT" ]]; then
+ error="expecting a DEFER_COMMIT status from script"
+ break
+ fi
+ ;;
+ "COMMITTED")
+ if [[ "$line" == "<= Error: could not commit transaction" ]]; then
+ messages_to_commit=()
+ transaction_state="NONE"
+ else
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ messages_processed+=("${messages_to_commit[@]}")
+ messages_to_commit=()
+ transaction_state="NONE"
+ fi
+ ;;
+ esac
+ status_expected=false;
+ else
+ if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "NONE" ]]; then
+ error="unexpected transaction start"
+ break
+ fi
+ transaction_state="STARTED"
+ elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected transaction commit"
+ break
+ fi
+ transaction_state="COMMITTED"
+ else
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected message outside a transaction"
+ break
+ fi
+ if [[ "$line" != "=> msgnum:"* ]]; then
+ error="unexpected message contents"
+ break
+ fi
+ prefix_to_remove="=> "
+ messages_to_commit+=("${line#$prefix_to_remove}")
+ fi
+ status_expected=true;
+ fi
+ ((line_num++))
+done < $RSYSLOG_OUT_LOG
+
+if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then
+ error="unexpected end of file (transaction state: $transaction_state)"
+fi
+
+if [[ -n "$error" ]]; then
+ echo "$RSYSLOG_OUT_LOG: line $line_num: $error"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+# Since the order in which failed messages are retried by rsyslog is not
+# deterministic, we sort the processed messages before checking them.
+IFS=$'\n' messages_sorted=($(sort <<<"${messages_processed[*]}"))
+unset IFS
+
+expected_messages=(
+ "msgnum:00000000:"
+ "msgnum:00000001:"
+ "msgnum:00000002:"
+ "msgnum:00000003:"
+ "msgnum:00000004:"
+ "msgnum:00000005:"
+ "msgnum:00000006:"
+ "msgnum:00000007:"
+ "msgnum:00000008:"
+ "msgnum:00000009:"
+)
+if [[ "${messages_sorted[*]}" != "${expected_messages[*]}" ]]; then
+ echo "unexpected set of processed messages:"
+ printf '%s\n' "${messages_processed[@]}"
+ echo "contents of $RSYSLOG_OUT_LOG:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-transactions-failed-messages.sh b/tests/omprog-transactions-failed-messages.sh
new file mode 100755
index 0000000..9d6afd2
--- /dev/null
+++ b/tests/omprog-transactions-failed-messages.sh
@@ -0,0 +1,159 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests omprog with the confirmMessages=on and useTransactions=on
+# parameters, with the external program returning an error on certain
+# messages.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh --failed_messages`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ queue.dequeueBatchSize="6"
+ confirmMessages="on"
+ useTransactions="on"
+ action.resumeRetryCount="10"
+ action.resumeInterval="1"
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+# Since the transaction boundaries are not deterministic, we cannot check for
+# an exact expected output. We must check the output programmatically.
+
+transaction_state="NONE"
+status_expected=true
+messages_to_commit=()
+messages_processed=()
+line_num=1
+error=
+
+while IFS= read -r line; do
+ if [[ $status_expected == true ]]; then
+ case "$transaction_state" in
+ "NONE")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ ;;
+ "STARTED")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ transaction_state="ACTIVE"
+ ;;
+ "ACTIVE")
+ if [[ "$line" == "<= Error: could not process log message" ]]; then
+ #
+ # TODO: Issue #2420: Deferred messages within a transaction are
+ # not retried by rsyslog.
+ # If that's the expected behavior, what's then the difference
+ # between the RS_RET_OK and the RS_RET_DEFER_COMMIT return codes?
+ # If that's not the expected behavior, the following lines must
+ # be removed when the bug is solved.
+ #
+ # (START OF CODE THAT WILL POSSIBLY NEED TO BE REMOVED)
+ messages_processed+=("${messages_to_commit[@]}")
+ unset "messages_processed[${#messages_processed[@]}-1]"
+ # (END OF CODE THAT WILL POSSIBLY NEED TO BE REMOVED)
+
+ messages_to_commit=()
+ transaction_state="NONE"
+ elif [[ "$line" != "<= DEFER_COMMIT" ]]; then
+ error="expecting a DEFER_COMMIT status from script"
+ break
+ fi
+ ;;
+ "COMMITTED")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ messages_processed+=("${messages_to_commit[@]}")
+ messages_to_commit=()
+ transaction_state="NONE"
+ ;;
+ esac
+ status_expected=false;
+ else
+ if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "NONE" ]]; then
+ error="unexpected transaction start"
+ break
+ fi
+ transaction_state="STARTED"
+ elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected transaction commit"
+ break
+ fi
+ transaction_state="COMMITTED"
+ else
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected message outside a transaction"
+ break
+ fi
+ if [[ "$line" != "=> msgnum:"* ]]; then
+ error="unexpected message contents"
+ break
+ fi
+ prefix_to_remove="=> "
+ messages_to_commit+=("${line#$prefix_to_remove}")
+ fi
+ status_expected=true;
+ fi
+ ((line_num++))
+done < $RSYSLOG_OUT_LOG
+
+if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then
+ error="unexpected end of file (transaction state: $transaction_state)"
+fi
+
+if [[ -n "$error" ]]; then
+ echo "$RSYSLOG_OUT_LOG: line $line_num: $error"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+# Since the order in which failed messages are retried by rsyslog is not
+# deterministic, we sort the processed messages before checking them.
+IFS=$'\n' messages_sorted=($(sort <<<"${messages_processed[*]}"))
+unset IFS
+
+expected_messages=(
+ "msgnum:00000000:"
+ "msgnum:00000001:"
+ "msgnum:00000002:"
+ "msgnum:00000003:"
+ "msgnum:00000004:"
+ "msgnum:00000005:"
+ "msgnum:00000006:"
+ "msgnum:00000007:"
+ "msgnum:00000008:"
+ "msgnum:00000009:"
+)
+if [[ "${messages_sorted[*]}" != "${expected_messages[*]}" ]]; then
+ echo "unexpected set of processed messages:"
+ printf '%s\n' "${messages_processed[@]}"
+ echo "contents of $RSYSLOG_OUT_LOG:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omprog-transactions-vg.sh b/tests/omprog-transactions-vg.sh
new file mode 100755
index 0000000..436be23
--- /dev/null
+++ b/tests/omprog-transactions-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# Same test than 'omprog-transactions.sh', but checking for memory
+# problems using valgrind. Note it is not necessary to repeat the
+# rest of checks (this simplifies the maintenance of the tests).
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ queue.dequeueBatchSize="6"
+ confirmMessages="on"
+ useTransactions="on"
+ beginTransactionMark="BEGIN TRANSACTION"
+ commitTransactionMark="COMMIT TRANSACTION"
+ action.resumeRetryCount="10"
+ action.resumeInterval="1"
+ )
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+exit_test
diff --git a/tests/omprog-transactions.sh b/tests/omprog-transactions.sh
new file mode 100755
index 0000000..1937d0f
--- /dev/null
+++ b/tests/omprog-transactions.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test tests omprog with the confirmMessages=on and useTransactions=on
+# parameters, with the external program successfully confirming all messages
+# and transactions.
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh`
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ queue.dequeueBatchSize="6"
+ confirmMessages="on"
+ useTransactions="on"
+ beginTransactionMark="BEGIN TRANSACTION"
+ commitTransactionMark="COMMIT TRANSACTION"
+ action.resumeRetryCount="10"
+ action.resumeInterval="1"
+ )
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+# Since the transaction boundaries are not deterministic, we cannot check for
+# an exact expected output. We must check the output programmatically.
+
+transaction_state="NONE"
+status_expected=true
+messages_to_commit=()
+messages_processed=()
+line_num=1
+error=
+
+while IFS= read -r line; do
+ if [[ $status_expected == true ]]; then
+ case "$transaction_state" in
+ "NONE")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ ;;
+ "STARTED")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ transaction_state="ACTIVE"
+ ;;
+ "ACTIVE")
+ if [[ "$line" != "<= DEFER_COMMIT" ]]; then
+ error="expecting a DEFER_COMMIT status from script"
+ break
+ fi
+ ;;
+ "COMMITTED")
+ if [[ "$line" != "<= OK" ]]; then
+ error="expecting an OK status from script"
+ break
+ fi
+ messages_processed+=("${messages_to_commit[@]}")
+ messages_to_commit=()
+ transaction_state="NONE"
+ ;;
+ esac
+ status_expected=false;
+ else
+ if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "NONE" ]]; then
+ error="unexpected transaction start"
+ break
+ fi
+ transaction_state="STARTED"
+ elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected transaction commit"
+ break
+ fi
+ transaction_state="COMMITTED"
+ else
+ if [[ "$transaction_state" != "ACTIVE" ]]; then
+ error="unexpected message outside a transaction"
+ break
+ fi
+ if [[ "$line" != "=> msgnum:"* ]]; then
+ error="unexpected message contents"
+ break
+ fi
+ prefix_to_remove="=> "
+ messages_to_commit+=("${line#$prefix_to_remove}")
+ fi
+ status_expected=true;
+ fi
+ ((line_num++))
+done < $RSYSLOG_OUT_LOG
+
+if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then
+ error="unexpected end of file (transaction state: $transaction_state)"
+fi
+
+if [[ -n "$error" ]]; then
+ echo "$RSYSLOG_OUT_LOG: line $line_num: $error"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+expected_messages=(
+ "msgnum:00000000:"
+ "msgnum:00000001:"
+ "msgnum:00000002:"
+ "msgnum:00000003:"
+ "msgnum:00000004:"
+ "msgnum:00000005:"
+ "msgnum:00000006:"
+ "msgnum:00000007:"
+ "msgnum:00000008:"
+ "msgnum:00000009:"
+)
+if [[ "${messages_processed[*]}" != "${expected_messages[*]}" ]]; then
+ echo "unexpected set of processed messages:"
+ printf '%s\n' "${messages_processed[@]}"
+ echo "contents of $RSYSLOG_OUT_LOG:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omrabbitmq_data_1server-vg.sh b/tests/omrabbitmq_data_1server-vg.sh
new file mode 100755
index 0000000..527ab44
--- /dev/null
+++ b/tests/omrabbitmq_data_1server-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/omrabbitmq_data_1server.sh
diff --git a/tests/omrabbitmq_data_1server.sh b/tests/omrabbitmq_data_1server.sh
new file mode 100755
index 0000000..660b5a0
--- /dev/null
+++ b/tests/omrabbitmq_data_1server.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 server %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost" port="'$PORT_AMQP1'" exchange="in"
+ user="mtr" password="mtr" expiration="5000"
+ body_template="bodyTpl" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=$(printf 'Exchange:in, routing-key:tag.local4.debug, content-type:rfc5424, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>1 server tag - - - msgrmq')
+echo $EXPECTED | cmp - $RSYSLOG_DYNNAME.amqp.log
+if [ ! $? -eq 0 ]; then
+ echo "Expected:"
+ echo $EXPECTED
+ echo "invalid response generated, $RSYSLOG_DYNNAME.amqp.log is:"
+ cat $RSYSLOG_DYNNAME.amqp.log
+ echo "Rsyslog internal output log:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+content_check "server localhost port"
+exit_test
diff --git a/tests/omrabbitmq_data_2servers.sh b/tests/omrabbitmq_data_2servers.sh
new file mode 100755
index 0000000..1afc616
--- /dev/null
+++ b/tests/omrabbitmq_data_2servers.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -b 1 -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=1
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost:'$PORT_AMQP1' localhost:'$PORT_AMQP2'" port="5672"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ body_template="bodyTpl" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED=$(printf 'Exchange:in, routing-key:tag.local4.debug, content-type:rfc5424, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>1 172.20.245.8 tag - - - msgrmq')
+echo $EXPECTED | cmp - $RSYSLOG_DYNNAME.amqp.log
+if [ ! $? -eq 0 ]; then
+ echo "Expected:"
+ echo $EXPECTED
+ echo "invalid response generated, $RSYSLOG_DYNNAME.amqp.log is:"
+ cat $RSYSLOG_DYNNAME.amqp.log
+ echo "Rsyslog internal output log:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+content_check "server localhost port"
+exit_test
diff --git a/tests/omrabbitmq_error_server0.sh b/tests/omrabbitmq_error_server0.sh
new file mode 100755
index 0000000..9a65420
--- /dev/null
+++ b/tests/omrabbitmq_error_server0.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -b 4 -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=1
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost" port="'$PORT_AMQP1'"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ exchange_type="topic" durable="off" auto_delete="off"
+ body_template="" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq'
+cmp_exact $RSYSLOG_DYNNAME.amqp.log
+content_check "exchange declare failed PRECONDITION_FAILED"
+exit_test
diff --git a/tests/omrabbitmq_error_server1.sh b/tests/omrabbitmq_error_server1.sh
new file mode 100755
index 0000000..150374e
--- /dev/null
+++ b/tests/omrabbitmq_error_server1.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -b 2 -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=2000
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost:'$PORT_AMQP1' localhost:'$PORT_AMQP2'" port="5672"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ exchange_type="topic" durable="on" auto_delete="off"
+ body_template="" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq'
+cmp_exact $RSYSLOG_DYNNAME.amqp.log
+content_check "disconnected while exchange declare"
+exit_test
diff --git a/tests/omrabbitmq_error_server2.sh b/tests/omrabbitmq_error_server2.sh
new file mode 100755
index 0000000..0f5ebef
--- /dev/null
+++ b/tests/omrabbitmq_error_server2.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -b 3 -f $RSYSLOG_DYNNAME.amqp.log -w 500 -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=2000
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost:'$PORT_AMQP1' localhost:'$PORT_AMQP2'" port="5672"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ exchange_type="topic" durable="on" auto_delete="off"
+ body_template="" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq'
+cmp_exact $RSYSLOG_DYNNAME.amqp.log
+content_check "Connection closed : reconnect"
+exit_test
diff --git a/tests/omrabbitmq_error_server3.sh b/tests/omrabbitmq_error_server3.sh
new file mode 100755
index 0000000..1d47bb1
--- /dev/null
+++ b/tests/omrabbitmq_error_server3.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -b 2 -f $RSYSLOG_DYNNAME.amqp.log -w 500 -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=2000
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+# rfc5424 without Timestamp : unable to manage
+template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost:'$PORT_AMQP1' localhost:'$PORT_AMQP2'" port="5672"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ body_template="" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq'
+cmp_exact $RSYSLOG_DYNNAME.amqp.log
+content_check "Connection closed : reconnect"
+exit_test
diff --git a/tests/omrabbitmq_json.sh b/tests/omrabbitmq_json.sh
new file mode 100755
index 0000000..f8c30bf
--- /dev/null
+++ b/tests/omrabbitmq_json.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=1
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost" port="'$PORT_AMQP1'"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ virtual_host="/metrologie" routing_key="myrouting"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+expected=$(printf 'Exchange:in, routing-key:myrouting, content-type:application/json, delivery-mode:transient, expiration:5000, msg:{\"message\":\" msgrmq\",\"fromhost\":\"172.20.245.8\",\"facility\":\"local4\",\"priority\":\"debug\",\"timereported\":.*}')
+grep -E "${expected}" $RSYSLOG_DYNNAME.amqp.log > /dev/null 2>&1
+if [ ! $? -eq 0 ]; then
+ echo "Expected:"
+ echo ${expected}
+ echo "invalid response generated, $RSYSLOG_DYNNAME.amqp.log is:"
+ cat $RSYSLOG_DYNNAME.amqp.log
+ echo "Rsyslog internal output log:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+content_check "server localhost port"
+exit_test
diff --git a/tests/omrabbitmq_no_params.sh b/tests/omrabbitmq_no_params.sh
new file mode 100755
index 0000000..79e1e61
--- /dev/null
+++ b/tests/omrabbitmq_no_params.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter host must be specified"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_invalid0.sh b/tests/omrabbitmq_params_invalid0.sh
new file mode 100755
index 0000000..9732137
--- /dev/null
+++ b/tests/omrabbitmq_params_invalid0.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" routing_key_template="jk" host="host")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "template 'jk' used for routing key does not exist"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_invalid1.sh b/tests/omrabbitmq_params_invalid1.sh
new file mode 100755
index 0000000..b09b2e6
--- /dev/null
+++ b/tests/omrabbitmq_params_invalid1.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" routing_key="jk" host="host" body_template="kl")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "template 'kl' used for body does not exist"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_invalid2.sh b/tests/omrabbitmq_params_invalid2.sh
new file mode 100755
index 0000000..70b4959
--- /dev/null
+++ b/tests/omrabbitmq_params_invalid2.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" routing_key="jk" host="host" delivery_mode="UNDEF")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "delivery_mode must be TRANSIENT or PERSISTENT"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_invalid3.sh b/tests/omrabbitmq_params_invalid3.sh
new file mode 100755
index 0000000..4274dd9
--- /dev/null
+++ b/tests/omrabbitmq_params_invalid3.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" routing_key="jk" host="host" expiration="-1")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'expiration' cannot be less than zero"
+
+exit_test
diff --git a/tests/omrabbitmq_params_missing0.sh b/tests/omrabbitmq_params_missing0.sh
new file mode 100755
index 0000000..bb79114
--- /dev/null
+++ b/tests/omrabbitmq_params_missing0.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" host="host" routing_key="jk")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter exchange must be specified"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_missing1.sh b/tests/omrabbitmq_params_missing1.sh
new file mode 100755
index 0000000..5def14a
--- /dev/null
+++ b/tests/omrabbitmq_params_missing1.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" host="host")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "routing_key or routing_key_template must be specified"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_params_missing2.sh b/tests/omrabbitmq_params_missing2.sh
new file mode 100755
index 0000000..fcf4654
--- /dev/null
+++ b/tests/omrabbitmq_params_missing2.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-02-26 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+action(type="omrabbitmq" exchange="in" routing_key="jk")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter host must be specified"
+
+exit_test \ No newline at end of file
diff --git a/tests/omrabbitmq_raw.sh b/tests/omrabbitmq_raw.sh
new file mode 100755
index 0000000..6242212
--- /dev/null
+++ b/tests/omrabbitmq_raw.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# add 2019-09-03 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+cmd="./miniamqpsrvr -f $RSYSLOG_DYNNAME.amqp.log -d"
+echo $cmd
+eval $cmd > $RSYSLOG_DYNNAME.source
+if [ ! $? -eq 0 ]; then
+ exit 77
+fi
+
+. $RSYSLOG_DYNNAME.source
+export OMRABBITMQ_TEST=1
+
+generate_conf
+add_conf '
+global(localhostname="server")
+module(load="../contrib/omrabbitmq/.libs/omrabbitmq")
+template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%")
+ruleset(name="rmq") {
+ action(type="omrabbitmq" host="localhost" port="'$PORT_AMQP1'"
+ user="mtr" password="mtr" exchange="in" expiration="5000"
+ exchange_type="topic" durable="off" auto_delete="off"
+ body_template="" content_type="rfc5424"
+ virtual_host="/metrologie" routing_key_template="rkTpl"
+ populate_properties="on" delivery_mode="transient"
+ )
+}
+if $msg contains "msgrmq" then {
+ call rmq
+}
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal "<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq'
+cmp_exact $RSYSLOG_DYNNAME.amqp.log
+content_check "server localhost port"
+exit_test
diff --git a/tests/omrelp-invld-tlslib.sh b/tests/omrelp-invld-tlslib.sh
new file mode 100755
index 0000000..56f08ea
--- /dev/null
+++ b/tests/omrelp-invld-tlslib.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# see that we can an error message if wrong tls lib is selected
+# addd 2019-02-09 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineSetTLSLibByName
+generate_conf
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp" tls.tlslib="invalid-tlslib-name")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+content_check --regex "omrelp.*invalid-tlslib-name.*not accepted"
+exit_test
diff --git a/tests/omrelp_dflt_port.c b/tests/omrelp_dflt_port.c
new file mode 100644
index 0000000..4734057
--- /dev/null
+++ b/tests/omrelp_dflt_port.c
@@ -0,0 +1,9 @@
+#include "config.h"
+#include <stdio.h>
+
+int
+main(int __attribute__((unused)) argc, char * __attribute__((unused)) argv[])
+{
+ printf("%s", RELP_DFLT_PT);
+ return 0;
+}
diff --git a/tests/omrelp_errmsg_no_connect.sh b/tests/omrelp_errmsg_no_connect.sh
new file mode 100755
index 0000000..dc45d12
--- /dev/null
+++ b/tests/omrelp_errmsg_no_connect.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# add 2018-11-14 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+# note: we "abuse" TCPFLOOD_PORT a bit as we already have it assigned
+# the core fact is that nobody is listening on it.
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+action(type="omrelp" target="127.0.0.1" port="'$TCPFLOOD_PORT'")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+content_check "could not connect to remote server"
+exit_test
diff --git a/tests/omrelp_wrong_authmode.sh b/tests/omrelp_wrong_authmode.sh
new file mode 100755
index 0000000..2165faa
--- /dev/null
+++ b/tests/omrelp_wrong_authmode.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# add 2018-09-13 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+ruleset(name="ruleset") {
+ action(type="omrelp" target="127.0.0.1" port="'$TCPFLOOD_PORT'"
+ tls="on" tls.authMode="INVALID_AUTH_MODE" tls.caCert="tls-certs/ca.pem"
+ tls.myCert="tls-certs/cert.pem" tls.myPrivKey="tls-certs/key.pem"
+ tls.permittedPeer=["rsyslog-test-root-ca"])
+}
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "omrelp.* invalid auth.*mode .*INVALID_AUTH_MODE"
+exit_test
diff --git a/tests/omruleset-queue.sh b/tests/omruleset-queue.sh
new file mode 100755
index 0000000..937af4a
--- /dev/null
+++ b/tests/omruleset-queue.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# test for omruleset. What we do is have the main queue forward
+# all messages to a secondary ruleset via omruleset, which then does
+# the actual file write. We check if all messages arrive at the file,
+# what implies that omruleset works. No filters or special queue modes
+# are used, but the ruleset uses its own queue. So we can also inject
+# more messages without running into troubles.
+# added 2009-11-02 by rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[omruleset-queue.sh\]: test for omruleset functionality with a ruleset queue
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$ModLoad ../plugins/omruleset/.libs/omruleset
+
+$ruleset rsinclude
+# create ruleset main queue with default parameters
+$RulesetCreateMainQueue on
+# make sure we do not terminate too early!
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+
+$ruleset RSYSLOG_DefaultRuleset
+$ActionOmrulesetRulesetName rsinclude
+*.* :omruleset:
+'
+startup
+injectmsg
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/omruleset.sh b/tests/omruleset.sh
new file mode 100755
index 0000000..3a92888
--- /dev/null
+++ b/tests/omruleset.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Basic test for omruleset. What we do is have the main queue forward
+# all messages to a secondary ruleset via omruleset, which then does
+# the actual file write. We check if all messages arrive at the file,
+# what implies that omruleset works. No filters or special queue modes
+# are used, so the message is re-enqueued into the main message queue.
+# We inject just 5,000 message because we may otherwise run into
+# queue full conditions (as we use the same queue) and that
+# would result in longer execution time. In any case, 5000 messages
+# are well enough to test what we want to test.
+# added 2009-11-02 by rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$ModLoad ../plugins/omruleset/.libs/omruleset
+
+$ruleset rsinclude
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+
+$ruleset RSYSLOG_DefaultRuleset
+$ActionOmrulesetRulesetName rsinclude
+*.* :omruleset:
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/omsnmp_errmsg_no_params.sh b/tests/omsnmp_errmsg_no_params.sh
new file mode 100755
index 0000000..ec8512e
--- /dev/null
+++ b/tests/omsnmp_errmsg_no_params.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# add 2018-09-25 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%\n")
+
+module(load="../plugins/omsnmp/.libs/omsnmp")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+action(type="omsnmp")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'server' required but not specified"
+
+exit_test
diff --git a/tests/omstdout-basic.sh b/tests/omstdout-basic.sh
new file mode 100755
index 0000000..4ac4046
--- /dev/null
+++ b/tests/omstdout-basic.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omstdout/.libs/omstdout")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="-%msg%-\n")
+action(type="omstdout" template="outfmt")
+
+'
+startup > $RSYSLOG_OUT_LOG
+tcpflood -m1
+shutdown_when_empty
+wait_shutdowna
+
+grep "msgnum:00000000:" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/omtcl.sh b/tests/omtcl.sh
new file mode 100755
index 0000000..9fa3617
--- /dev/null
+++ b/tests/omtcl.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../contrib/omtcl/.libs/omtcl
+$template tcldict, "message \"%msg:::json%\" fromhost \"%HOSTNAME:::json%\" facility \"%syslogfacility-text%\" priority \"%syslogpriority-text%\" timereported \"%timereported:::date-rfc3339%\" timegenerated \"%timegenerated:::date-rfc3339%\" raw \"%rawmsg:::json%\" tag \"%syslogtag:::json%\""
+'
+add_conf "*.* :omtcl:$srcdir/omtcl.tcl,doAction;tcldict
+"
+startup
+echo 'injectmsg literal <167>Mar 1 01:00:00 172.20.245.8 tag hello world' | \
+ ./diagtalker -p$IMDIAG_PORT || error_exit $?
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check 'HELLO WORLD'
+cat $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/omtcl.tcl b/tests/omtcl.tcl
new file mode 100644
index 0000000..ff12251
--- /dev/null
+++ b/tests/omtcl.tcl
@@ -0,0 +1,9 @@
+proc doAction {msg} {
+ set fd [open $::env(RSYSLOG_OUT_LOG) a]
+ puts $fd "message processed:"
+ foreach {k v} $msg {
+ puts $fd " $k: <<$v>>"
+ }
+ puts $fd " uppercase message: <<[string toupper [dict get $msg message]]>>"
+ close $fd
+}
diff --git a/tests/omudpspoof_errmsg_no_params.sh b/tests/omudpspoof_errmsg_no_params.sh
new file mode 100755
index 0000000..a14ffb6
--- /dev/null
+++ b/tests/omudpspoof_errmsg_no_params.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# add 2019-04-15 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omudpspoof/.libs/omudpspoof")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+action(type="omudpspoof")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'target' required but not specified"
+
+exit_test
diff --git a/tests/omusrmsg-errmsg-no-params.sh b/tests/omusrmsg-errmsg-no-params.sh
new file mode 100755
index 0000000..d6e4354
--- /dev/null
+++ b/tests/omusrmsg-errmsg-no-params.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# add 2019-08-05 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omusrmsg")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "parameter 'users' required but not specified"
+exit_test
diff --git a/tests/omusrmsg-noabort-vg.sh b/tests/omusrmsg-noabort-vg.sh
new file mode 100755
index 0000000..c9437ed
--- /dev/null
+++ b/tests/omusrmsg-noabort-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/omusrmsg-noabort.sh
diff --git a/tests/omusrmsg-noabort.sh b/tests/omusrmsg-noabort.sh
new file mode 100755
index 0000000..352414c
--- /dev/null
+++ b/tests/omusrmsg-noabort.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# same as omusrmsg-noabort, but with legacy syntax.
+# addd 2018-08-05 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" {
+ action(type="omusrmsg" users="nouser" template="outfmt")
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+ }
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+# while we cannot check if the messages arrived in user sessions, we
+# can check that all messages arrive in the file, which we consider as
+# an indication that everything went well.
+seq_check
+exit_test
diff --git a/tests/operatingstate-basic.sh b/tests/operatingstate-basic.sh
new file mode 100755
index 0000000..0204dbd
--- /dev/null
+++ b/tests/operatingstate-basic.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# added 2018-10-24 by Rainer Gerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(operatingStateFile="'$RSYSLOG_DYNNAME.osf'")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+action(type="invalid-type")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+check_file_not_exists "$RSYSLOG_DYNNAME.osf.previous"
+check_file_exists "$RSYSLOG_DYNNAME.osf"
+content_check "invalid-type" "$RSYSLOG_DYNNAME.osf"
+content_check "CLEAN CLOSE" "$RSYSLOG_DYNNAME.osf"
+exit_test
diff --git a/tests/operatingstate-empty.sh b/tests/operatingstate-empty.sh
new file mode 100755
index 0000000..29d9fa3
--- /dev/null
+++ b/tests/operatingstate-empty.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2018-10-24 by Rainer Gerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(operatingStateFile="'$RSYSLOG_DYNNAME.osf'")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+# create an unclean file
+err_osf_content=""
+printf '%s' "$err_osf_content" > $RSYSLOG_DYNNAME.osf
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+check_file_exists "$RSYSLOG_DYNNAME.osf.previous"
+check_file_exists "$RSYSLOG_DYNNAME.osf"
+content_check "this may be an indication of a problem, e.g. empty file" "$RSYSLOG_OUT_LOG"
+content_check "CLEAN CLOSE" "$RSYSLOG_DYNNAME.osf"
+exit_test
diff --git a/tests/operatingstate-unclean.sh b/tests/operatingstate-unclean.sh
new file mode 100755
index 0000000..30b3443
--- /dev/null
+++ b/tests/operatingstate-unclean.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2018-10-24 by Rainer Gerhards
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(operatingStateFile="'$RSYSLOG_DYNNAME.osf'")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+# create an unclean file
+err_osf_content="20180924-160109: STATE INITIALIZING 8.39.0.master
+20180924-160110: STATE"
+printf '%s\n' "$err_osf_content" > $RSYSLOG_DYNNAME.osf
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+check_file_exists "$RSYSLOG_DYNNAME.osf.previous"
+export EXPECTED="$err_osf_content"
+cmp_exact "$RSYSLOG_DYNNAME.osf.previous"
+check_file_exists "$RSYSLOG_DYNNAME.osf"
+content_check "does not end with 'CLEAN CLOSE, instead it has '0110: STATE'" "$RSYSLOG_OUT_LOG"
+content_check "CLEAN CLOSE" "$RSYSLOG_DYNNAME.osf"
+exit_test
diff --git a/tests/ourtail.c b/tests/ourtail.c
new file mode 100644
index 0000000..c31babb
--- /dev/null
+++ b/tests/ourtail.c
@@ -0,0 +1,46 @@
+/* This is a quick and dirty "tail implementation", one which always
+ * skips the first line, but nothing else. I have done this to prevent
+ * the various incompatible options of tail come into my way. One could
+ * probably work around this by using autoconf magic, but for me it
+ * was much quicker writing this small C program, which really should
+ * be portable across all platforms.
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+
+int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
+{
+ int c;
+
+ for(c = getchar() ; c != EOF && c != '\n' ; c = getchar())
+ /*skip to newline*/;
+
+ if(c == '\n')
+ c = getchar();
+
+ for( ; c != EOF ; c = getchar())
+ putchar(c);
+
+ return 0;
+}
diff --git a/tests/override_getaddrinfo.c b/tests/override_getaddrinfo.c
new file mode 100644
index 0000000..32bbafe
--- /dev/null
+++ b/tests/override_getaddrinfo.c
@@ -0,0 +1,28 @@
+// we need this for dlsym(): #include <dlfcn.h>
+#include "config.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+int getaddrinfo(const char *node __attribute__((unused)),
+ const char *service __attribute__((unused)),
+ const struct addrinfo *hints __attribute__((unused)),
+ struct addrinfo **res __attribute__((unused)))
+{
+ return EAI_MEMORY;
+}
+
+static void __attribute__((constructor))
+my_init(void)
+{
+ /* we currently do not need this entry point, but keep it as
+ * a "template". It can be used, e.g. to emit some diagnostic
+ * information:
+ printf("loaded\n");
+ * or - more importantly - obtain a pointer to the overriden
+ * API:
+ orig_etry = dlsym(RTLD_NEXT, "original_entry_point");
+ */
+}
diff --git a/tests/override_gethostname.c b/tests/override_gethostname.c
new file mode 100644
index 0000000..10a4867
--- /dev/null
+++ b/tests/override_gethostname.c
@@ -0,0 +1,22 @@
+// we need this for dlsym(): #include <dlfcn.h>
+#include <stdio.h>
+
+
+int gethostname(char *name, size_t __attribute__((unused)) len)
+{
+ *name = '\0';
+ return 0;
+}
+
+static void __attribute__((constructor))
+my_init(void)
+{
+ /* we currently do not need this entry point, but keep it as
+ * a "template". It can be used, e.g. to emit some diagnostic
+ * information:
+ printf("loaded\n");
+ * or - more importantly - obtain a pointer to the overriden
+ * API:
+ orig_etry = dlsym(RTLD_NEXT, "original_entry_point");
+ */
+}
diff --git a/tests/override_gethostname_nonfqdn.c b/tests/override_gethostname_nonfqdn.c
new file mode 100644
index 0000000..5f53857
--- /dev/null
+++ b/tests/override_gethostname_nonfqdn.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int gethostname(char *name, size_t __attribute__((unused)) len)
+{
+ *name++ = 'n';
+ *name++ = 'o';
+ *name++ = 'n';
+ *name++ = 'f';
+ *name++ = 'q';
+ *name++ = 'd';
+ *name++ = 'n';
+ *name++ = '\0';
+ return 0;
+}
diff --git a/tests/parsertest-parse-3164-buggyday-udp.sh b/tests/parsertest-parse-3164-buggyday-udp.sh
new file mode 100755
index 0000000..9dcd4c0
--- /dev/null
+++ b/tests/parsertest-parse-3164-buggyday-udp.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp:::date-rfc3164-buggyday%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<38> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -T "udp" -M "\"<38> Mar 17 19:06:53 example tag: testmessage (only date actually tested)\""
+shutdown_when_empty
+wait_shutdown
+
+echo '38,auth,info,Mar 07 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+38,auth,info,Mar 17 19:06:53,example,tag,tag:, testmessage (only date actually tested)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse-3164-buggyday.sh b/tests/parsertest-parse-3164-buggyday.sh
new file mode 100755
index 0000000..1b0af13
--- /dev/null
+++ b/tests/parsertest-parse-3164-buggyday.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp:::date-rfc3164-buggyday%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<38> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -M "\"<38> Mar 17 19:06:53 example tag: testmessage (only date actually tested)\""
+shutdown_when_empty
+wait_shutdown
+
+echo '38,auth,info,Mar 07 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+38,auth,info,Mar 17 19:06:53,example,tag,tag:, testmessage (only date actually tested)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse-nodate-udp.sh b/tests/parsertest-parse-nodate-udp.sh
new file mode 100755
index 0000000..1e36544
--- /dev/null
+++ b/tests/parsertest-parse-nodate-udp.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<27>xapi: [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)\""
+tcpflood -m1 -T "udp" -M "\"This is a message!\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="27,daemon,err,$RS_HOSTNAME,xapi,xapi:, [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)
+13,user,notice,This,is,is, a message!"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/parsertest-parse-nodate.sh b/tests/parsertest-parse-nodate.sh
new file mode 100755
index 0000000..2264d9b
--- /dev/null
+++ b/tests/parsertest-parse-nodate.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<27>xapi: [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)\""
+tcpflood -m1 -M "\"This is a message!\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="27,daemon,err,$RS_HOSTNAME,xapi,xapi:, [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)
+13,user,notice,This,is,is, a message!"
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/parsertest-parse1-udp.sh b/tests/parsertest-parse1-udp.sh
new file mode 100755
index 0000000..7280583
--- /dev/null
+++ b/tests/parsertest-parse1-udp.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 27 19:06:53 source_server sshd(pam_unix)[12750]: session opened for user foo by (uid=0)\""
+tcpflood -m1 -T "udp" -M "\"<167>Apr 6 15:07:10 lxcvs07 sshd(pam_unix)[31738]: session closed for user cvsadmin\""
+tcpflood -m1 -T "udp" -M "\"<167>Jul 31 21:39:21 example-b example-gw[10538]: disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0\""
+tcpflood -m1 -T "udp" -M "\"<167>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\""
+tcpflood -m1 -T "udp" -M "\"<167> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 7 2008 19:06:53: example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 7 2008 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 7 19:06:53: example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -T "udp" -M "\"<14>Jan 6 2009 15:22:26 localhost\""
+tcpflood -m1 -T "udp" -M "\"<167>Oct 8 23:05:06 10.321.1.123 05\\\",result_code=200,b\""
+tcpflood -m1 -T "udp" -M "\"<167>Feb 18 16:01:59 serverX -- MARK --\""
+tcpflood -m1 -T "udp" -M "\"Feb 18 16:01:59 serverX -- MARK --\""
+tcpflood -m1 -T "udp" -M "\"<38>Mar 27 19:06:53 source_server 0123456789012345678901234567890123456789: MSG part\""
+tcpflood -m1 -T "udp" -M "\"<29>Oct 16 20:47:24 example-p exam-pl[12345]: connect host= /192.0.2.1\""
+tcpflood -m1 -T "udp" -M "\"<34>Oct 11 22:14:15 mymachine su: su root failed for lonvick on /dev/pts/8\""
+tcpflood -m1 -T "udp" -M "\"<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - BOMsu root failed for lonvick on /dev/pts/8\""
+tcpflood -m1 -T "udp" -M "\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - %% Its time to make the do-nuts.\""
+tcpflood -m1 -T "udp" -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"][examplePriority@32473 class=\\\"high\\\"]\""
+tcpflood -m1 -T "udp" -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"] BOMAn application event log entry...\""
+tcpflood -m1 -T "udp" -M "\"<6>AUG 10 22:18:24 2009 netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset\""
+tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""
+tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711 \""
+tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711\""
+tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 \""
+tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05\""
+tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""
+tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711 \""
+tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="167,local4,debug,Mar 6 16:57:54,172.20.245.8,%PIX-7-710005,%PIX-7-710005:, UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601
+167,local4,debug,Mar 27 19:06:53,source_server,sshd(pam_unix),sshd(pam_unix)[12750]:, session opened for user foo by (uid=0)
+167,local4,debug,Apr 6 15:07:10,lxcvs07,sshd(pam_unix),sshd(pam_unix)[31738]:, session closed for user cvsadmin
+167,local4,debug,Jul 31 21:39:21,example-b,example-gw,example-gw[10538]:, disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0
+167,local4,debug,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: äöü
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+14,user,info,Jan 6 15:22:26,localhost,,,
+167,local4,debug,Oct 8 23:05:06,10.321.1.123,05\",result_code=200,b,05\",result_code=200,b,
+167,local4,debug,Feb 18 16:01:59,serverX,--,--, MARK --
+13,user,notice,Feb 18 16:01:59,serverX,--,--, MARK --
+38,auth,info,Mar 27 19:06:53,source_server,0123456789012345678901234567890123456789,0123456789012345678901234567890123456789:, MSG part
+29,daemon,notice,Oct 16 20:47:24,example-p,exam-pl,exam-pl[12345]:, connect host= /192.0.2.1
+34,auth,crit,Oct 11 22:14:15,mymachine,su,su:, su root failed for lonvick on /dev/pts/8
+34,auth,crit,Oct 11 22:14:15,mymachine.example.com,su,su,BOMsu root failed for lonvick on /dev/pts/8
+165,local4,notice,Aug 24 05:14:15,192.0.2.1,myproc,myproc[8710],%% Its time to make the do-nuts.
+165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog,
+165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog,BOMAn application event log entry...
+6,kern,info,Aug 10 22:18:24,2009,,, netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset
+14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,,
+14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,,
+14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,X4711,,,"
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/parsertest-parse1.sh b/tests/parsertest-parse1.sh
new file mode 100755
index 0000000..8c81440
--- /dev/null
+++ b/tests/parsertest-parse1.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\""
+tcpflood -m1 -M "\"<167>Mar 27 19:06:53 source_server sshd(pam_unix)[12750]: session opened for user foo by (uid=0)\""
+tcpflood -m1 -M "\"<167>Apr 6 15:07:10 lxcvs07 sshd(pam_unix)[31738]: session closed for user cvsadmin\""
+tcpflood -m1 -M "\"<167>Jul 31 21:39:21 example-b example-gw[10538]: disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0\""
+tcpflood -m1 -M "\"<167>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\""
+tcpflood -m1 -M "\"<167> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -M "\"<167>Mar 7 2008 19:06:53: example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -M "\"<167>Mar 7 2008 19:06:53 example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -M "\"<167>Mar 7 19:06:53: example tag: testmessage (only date actually tested)\""
+tcpflood -m1 -M "\"<14>Jan 6 2009 15:22:26 localhost\""
+tcpflood -m1 -M "\"<167>Oct 8 23:05:06 10.321.1.123 05\\\",result_code=200,b\""
+tcpflood -m1 -M "\"<167>Feb 18 16:01:59 serverX -- MARK --\""
+tcpflood -m1 -M "\"Feb 18 16:01:59 serverX -- MARK --\""
+tcpflood -m1 -M "\"<38>Mar 27 19:06:53 source_server 0123456789012345678901234567890123456789: MSG part\""
+tcpflood -m1 -M "\"<29>Oct 16 20:47:24 example-p exam-pl[12345]: connect host= /192.0.2.1\""
+tcpflood -m1 -M "\"<34>Oct 11 22:14:15 mymachine su: su root failed for lonvick on /dev/pts/8\""
+tcpflood -m1 -M "\"<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - BOMsu root failed for lonvick on /dev/pts/8\""
+tcpflood -m1 -M "\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - %% Its time to make the do-nuts.\""
+tcpflood -m1 -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"][examplePriority@32473 class=\\\"high\\\"]\""
+tcpflood -m1 -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"] BOMAn application event log entry...\""
+tcpflood -m1 -M "\"<6>AUG 10 22:18:24 2009 netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset\""
+tcpflood -m1 -M "\"<14>Aug 30 23:00:05 X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""
+tcpflood -m1 -M "\"<14>Aug 30 23:00:05 X4711 \""
+tcpflood -m1 -M "\"<14>Aug 30 23:00:05 X4711\""
+tcpflood -m1 -M "\"<14>Aug 30 23:00:05 \""
+tcpflood -m1 -M "\"<14>Aug 30 23:00:05\""
+tcpflood -m1 -M "\"<14>2010-08-30T23:00:05Z X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""
+tcpflood -m1 -M "\"<14>2010-08-30T23:00:05Z X4711 \""
+tcpflood -m1 -M "\"<14>2010-08-30T23:00:05Z X4711\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="167,local4,debug,Mar 6 16:57:54,172.20.245.8,%PIX-7-710005,%PIX-7-710005:, UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601
+167,local4,debug,Mar 27 19:06:53,source_server,sshd(pam_unix),sshd(pam_unix)[12750]:, session opened for user foo by (uid=0)
+167,local4,debug,Apr 6 15:07:10,lxcvs07,sshd(pam_unix),sshd(pam_unix)[31738]:, session closed for user cvsadmin
+167,local4,debug,Jul 31 21:39:21,example-b,example-gw,example-gw[10538]:, disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0
+167,local4,debug,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: äöü
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested)
+14,user,info,Jan 6 15:22:26,localhost,,,
+167,local4,debug,Oct 8 23:05:06,10.321.1.123,05\",result_code=200,b,05\",result_code=200,b,
+167,local4,debug,Feb 18 16:01:59,serverX,--,--, MARK --
+13,user,notice,Feb 18 16:01:59,serverX,--,--, MARK --
+38,auth,info,Mar 27 19:06:53,source_server,0123456789012345678901234567890123456789,0123456789012345678901234567890123456789:, MSG part
+29,daemon,notice,Oct 16 20:47:24,example-p,exam-pl,exam-pl[12345]:, connect host= /192.0.2.1
+34,auth,crit,Oct 11 22:14:15,mymachine,su,su:, su root failed for lonvick on /dev/pts/8
+34,auth,crit,Oct 11 22:14:15,mymachine.example.com,su,su,BOMsu root failed for lonvick on /dev/pts/8
+165,local4,notice,Aug 24 05:14:15,192.0.2.1,myproc,myproc[8710],%% Its time to make the do-nuts.
+165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog,
+165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog,BOMAn application event log entry...
+6,kern,info,Aug 10 22:18:24,2009,,, netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset
+14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,,
+14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,,
+14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
+14,user,info,Aug 30 23:00:05,X4711,,,
+14,user,info,Aug 30 23:00:05,X4711,,,"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/parsertest-parse2-udp.sh b/tests/parsertest-parse2-udp.sh
new file mode 100755
index 0000000..2be7c3f
--- /dev/null
+++ b/tests/parsertest-parse2-udp.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<175>Oct 16 23:47:31 #001 MSWinEventLog 0#011Security#01119023582#011Fri Oct 16 16:30:44 2009#011592#011Security#011rgabcde#011User#011Success Audit#011XSXSXSN01#011Detailed Tracking#011#0112572#01119013885\""
+shutdown_when_empty
+wait_shutdown
+
+echo '175,local5,debug,Oct 16 23:47:31,#001,#001, MSWinEventLog 0#011Security#01119023582#011Fri Oct 16 16:30:44 2009#011592#011Security#011rgabcde#011User#011Success Audit#011XSXSXSN01#011Detailed Tracking#011#0112572#01119013885' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse2.sh b/tests/parsertest-parse2.sh
new file mode 100755
index 0000000..75bb819
--- /dev/null
+++ b/tests/parsertest-parse2.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<175>Oct 16 23:47:31 #001 MSWinEventLog 0#011Security#01119023582#011Fri Oct 16 16:30:44 2009#011592#011Security#011rgabcde#011User#011Success Audit#011XSXSXSN01#011Detailed Tracking#011#0112572#01119013885\""
+shutdown_when_empty
+wait_shutdown
+
+echo '175,local5,debug,Oct 16 23:47:31,#001,#001, MSWinEventLog 0#011Security#01119023582#011Fri Oct 16 16:30:44 2009#011592#011Security#011rgabcde#011User#011Success Audit#011XSXSXSN01#011Detailed Tracking#011#0112572#01119013885' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse3-udp.sh b/tests/parsertest-parse3-udp.sh
new file mode 100755
index 0000000..f36d178
--- /dev/null
+++ b/tests/parsertest-parse3-udp.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9]+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<175>Oct 16 2009 23:47:31 hostname tag This is a message\""
+tcpflood -m1 -T "udp" -M "\"<175>Oct 16 2009 23:47:31 hostname tag[1234] This is a message\""
+shutdown_when_empty
+wait_shutdown
+
+echo '"2009-10-16T23:47:31", "hostname", "tag", "", "7", " This is a message"
+"2009-10-16T23:47:31", "hostname", "tag", "1234", "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse3.sh b/tests/parsertest-parse3.sh
new file mode 100755
index 0000000..f824a08
--- /dev/null
+++ b/tests/parsertest-parse3.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9]+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<175>Oct 16 2009 23:47:31 hostname tag This is a message\""
+tcpflood -m1 -M "\"<175>Oct 16 2009 23:47:31 hostname tag[1234] This is a message\""
+shutdown_when_empty
+wait_shutdown
+
+echo '"2009-10-16T23:47:31", "hostname", "tag", "", "7", " This is a message"
+"2009-10-16T23:47:31", "hostname", "tag", "1234", "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse_8bit_escape-udp.sh b/tests/parsertest-parse_8bit_escape-udp.sh
new file mode 100755
index 0000000..6ec1e44
--- /dev/null
+++ b/tests/parsertest-parse_8bit_escape-udp.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-06-28 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+$Escape8BitCharactersOnReceive on
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<6>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\""
+shutdown_when_empty
+wait_shutdown
+
+echo '6,kern,info,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: #303#244#303#266#303#274' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse_8bit_escape.sh b/tests/parsertest-parse_8bit_escape.sh
new file mode 100755
index 0000000..fd8e694
--- /dev/null
+++ b/tests/parsertest-parse_8bit_escape.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# add 2018-06-28 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+$Escape8BitCharactersOnReceive on
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<6>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\""
+shutdown_when_empty
+wait_shutdown
+
+echo '6,kern,info,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: #303#244#303#266#303#274' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse_invld_regex-udp.sh b/tests/parsertest-parse_invld_regex-udp.sh
new file mode 100755
index 0000000..5e4b819
--- /dev/null
+++ b/tests/parsertest-parse_invld_regex-udp.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2018-06-28 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<175>Feb 08 2008 23:47:31 hostname tag This is a message\""
+shutdown_when_empty
+wait_shutdown
+
+echo '"2008-02-08T23:47:31", "hostname", "tag", **NO MATCH** **BAD REGULAR EXPRESSION**, "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-parse_invld_regex.sh b/tests/parsertest-parse_invld_regex.sh
new file mode 100755
index 0000000..cd8e790
--- /dev/null
+++ b/tests/parsertest-parse_invld_regex.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2018-06-28 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+
+template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<175>Feb 08 2008 23:47:31 hostname tag This is a message\""
+shutdown_when_empty
+wait_shutdown
+
+echo '"2008-02-08T23:47:31", "hostname", "tag", **NO MATCH** **BAD REGULAR EXPRESSION**, "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/parsertest-snare_ccoff_udp.sh b/tests/parsertest-snare_ccoff_udp.sh
new file mode 100755
index 0000000..4c7f435
--- /dev/null
+++ b/tests/parsertest-snare_ccoff_udp.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+$EscapeControlCharactersOnReceive off
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%hostname%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"windowsserver MSWinEventLog 1 Security 1167 Fri Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\\\n\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="13,user,notice,$RS_HOSTNAME,windowsserver,windowsserver MSWinEventLog 1 Security 1167 Fri, Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\n"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/parsertest-snare_ccoff_udp2.sh b/tests/parsertest-snare_ccoff_udp2.sh
new file mode 100755
index 0000000..dd51bec
--- /dev/null
+++ b/tests/parsertest-snare_ccoff_udp2.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+$EscapeControlCharactersOnReceive off
+
+template(name="outfmt" type="string" string="insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (%msg:::space-cc%, %syslogfacility%, %HOSTNAME%,%syslogpriority%, 20100321185328, 20100321185328, %iut%, %syslogtag:::space-cc%)\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"test\""
+tcpflood -m1 -T "udp" -M "\"UX=Abcd-efg-hij-klmno; XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111\""
+tcpflood -m1 -T "udp" -M "\"windowsserver MSWinEventLog 1 Security 1167 Fri Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\\\n\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (, 1, test,5, 20100321185328, 20100321185328, 1, )
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ( XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111, 1, $RS_HOSTNAME,5, 20100321185328, 20100321185328, 1, UX=Abcd-efg-hij-klmno;)
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ( Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\n, 1, $RS_HOSTNAME,5, 20100321185328, 20100321185328, 1, windowsserver MSWinEventLog 1 Security 1167 Fri)"
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/perctile-simple-vg.sh b/tests/perctile-simple-vg.sh
new file mode 100755
index 0000000..b868564
--- /dev/null
+++ b/tests/perctile-simple-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/perctile-simple.sh
diff --git a/tests/perctile-simple.sh b/tests/perctile-simple.sh
new file mode 100755
index 0000000..b3bca04
--- /dev/null
+++ b/tests/perctile-simple.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+. ${srcdir:=.}/diag.sh init
+DELIMITER='|'
+BUCKETNAME='test_bucket'
+STATNAME='test_stat_name'
+# uncomment to test really long statname
+#STATNAME='123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" Ruleset="stats" bracketing="on")
+#module(load="../plugins/impstats/.libs/impstats" format="json" interval="1" severity="7" Ruleset="stats" bracketing="on")
+template(name="outfmt" type="string" string="%$.timestamp% %msg% val=%$.val%\n")
+
+percentile_stats(name="'$BUCKETNAME'"
+ percentiles=["95", "50", "99"]
+ windowsize="1000"
+ delimiter="'${DELIMITER}'"
+ )
+
+if $msg startswith " msgnum:" then {
+ # test with a small window
+ set $.val = field($msg, 58, 2);
+ set $.status = percentile_observe("'$BUCKETNAME'", "'$STATNAME'", $.val);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+. $srcdir/diag.sh block-stats-flush
+shuf -i 1-1000 | sed -e 's/^/injectmsg literal <167>Mar 1 01:00:00 172.20.245.8 tag msgnum:/g' | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+wait_queueempty
+. $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it
+
+shuf -i 1001-2000 | sed -e 's/^/injectmsg literal <167>Mar 1 01:00:00 172.20.245.8 tag msgnum:/g' | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT || error_exit $?
+. $srcdir/diag.sh await-stats-flush-after-block
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+
+echo doing shutdown
+shutdown_when_empty
+custom_content_check "${STATNAME}${DELIMITER}p95=950" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}p50=500" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}p99=990" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_min=1" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_max=1000" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_sum=500500" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_count=1000" "${RSYSLOG_DYNNAME}.out.stats.log"
+
+custom_content_check "${STATNAME}${DELIMITER}p95=1950" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}p50=1500" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}p99=1990" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_min=1001" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_max=2000" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_sum=1500500" "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_content_check "${STATNAME}${DELIMITER}window_count=1000" "${RSYSLOG_DYNNAME}.out.stats.log"
+
+exit_test
diff --git a/tests/pgsql-actq-mt-withpause-vg.sh b/tests/pgsql-actq-mt-withpause-vg.sh
new file mode 100755
index 0000000..b431123
--- /dev/null
+++ b/tests/pgsql-actq-mt-withpause-vg.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench"
+ queue.size="10000" queue.type="linkedList"
+ queue.workerthreads="5"
+ queue.workerthreadMinimumMessages="500"
+ queue.timeoutWorkerthreadShutdown="1000"
+ queue.timeoutEnqueue="10000"
+ )
+}'
+startup_vg
+injectmsg 0 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 3000
+injectmsg 50000 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 2000
+injectmsg 100000 50000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 149999
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-actq-mt-withpause.sh b/tests/pgsql-actq-mt-withpause.sh
new file mode 100755
index 0000000..37d6e47
--- /dev/null
+++ b/tests/pgsql-actq-mt-withpause.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench"
+ queue.size="10000" queue.type="linkedList"
+ queue.workerthreads="5"
+ queue.workerthreadMinimumMessages="500"
+ queue.timeoutWorkerthreadShutdown="1000"
+ queue.timeoutEnqueue="10000"
+ )
+}'
+startup
+injectmsg 0 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 3000
+injectmsg 50000 50000
+wait_queueempty
+echo waiting for worker threads to timeout
+./msleep 2000
+injectmsg 100000 50000
+shutdown_when_empty
+wait_shutdown
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 149999
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-basic-cnf6-vg.sh b/tests/pgsql-basic-cnf6-vg.sh
new file mode 100755
index 0000000..af28f86
--- /dev/null
+++ b/tests/pgsql-basic-cnf6-vg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench")
+}'
+startup_vg
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-basic-cnf6.sh b/tests/pgsql-basic-cnf6.sh
new file mode 100755
index 0000000..5ab2975
--- /dev/null
+++ b/tests/pgsql-basic-cnf6.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench")
+}'
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-basic-threads-cnf6.sh b/tests/pgsql-basic-threads-cnf6.sh
new file mode 100755
index 0000000..68d288b
--- /dev/null
+++ b/tests/pgsql-basic-threads-cnf6.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql"
+ server="127.0.0.1" db="syslogtest"
+ user="postgres" pass="testbench"
+ queue.workerthreads="4" )
+}'
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-basic-vg.sh b/tests/pgsql-basic-vg.sh
new file mode 100755
index 0000000..0b38b89
--- /dev/null
+++ b/tests/pgsql-basic-vg.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+$ModLoad ../plugins/ompgsql/.libs/ompgsql
+:msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench
+'
+startup_vg
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-basic.sh b/tests/pgsql-basic.sh
new file mode 100755
index 0000000..78ef217
--- /dev/null
+++ b/tests/pgsql-basic.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+$ModLoad ../plugins/ompgsql/.libs/ompgsql
+:msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench
+'
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-template-cnf6-vg.sh b/tests/pgsql-template-cnf6-vg.sh
new file mode 100755
index 0000000..5886654
--- /dev/null
+++ b/tests/pgsql-template-cnf6-vg.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+template(name="pgtemplate" type="list" option.sql="on") {
+ constant(value="INSERT INTO SystemEvents (SysLogTag) values ('"'"'")
+ property(name="msg")
+ constant(value="'"'"')")
+}
+
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench"
+ template="pgtemplate")
+}'
+
+startup_vg
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+# we actually put the message in the SysLogTag field, so we know it doesn't use the default
+# template, like in pgsql-basic
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-template-cnf6.sh b/tests/pgsql-template-cnf6.sh
new file mode 100755
index 0000000..9a0a00d
--- /dev/null
+++ b/tests/pgsql-template-cnf6.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f ${srcdir}/testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+template(name="pgtemplate" type="list" option.sql="on") {
+ constant(value="INSERT INTO SystemEvents (SysLogTag) values ('"'"'")
+ property(name="msg")
+ constant(value="'"'"')")
+}
+
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench"
+ template="pgtemplate")
+}'
+
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+
+psql -h localhost -U postgres -d syslogtest -f ${srcdir}/testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG
+
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-template-threads-cnf6.sh b/tests/pgsql-template-threads-cnf6.sh
new file mode 100755
index 0000000..99ece41
--- /dev/null
+++ b/tests/pgsql-template-threads-cnf6.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+template(name="pgtemplate" type="list" option.sql="on") {
+ constant(value="INSERT INTO SystemEvents (SysLogTag) values ('"'"'")
+ property(name="msg")
+ constant(value="'"'"')")
+}
+
+module(load="../plugins/ompgsql/.libs/ompgsql")
+if $msg contains "msgnum" then {
+ action(type="ompgsql" server="127.0.0.1"
+ db="syslogtest" user="postgres" pass="testbench"
+ template="pgtemplate" queue.workerthreads="4")
+}'
+
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-template-vg.sh b/tests/pgsql-template-vg.sh
new file mode 100755
index 0000000..de36039
--- /dev/null
+++ b/tests/pgsql-template-vg.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+# putting the message in the SyslogTag field, so we know the template is actually used
+$template mytemplate,"insert into SystemEvents (SysLogTag) values '
+add_conf "('%msg%')"
+add_conf '",STDSQL
+
+$ModLoad ../plugins/ompgsql/.libs/ompgsql
+:msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench;mytemplate
+'
+startup_vg
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pgsql-template.sh b/tests/pgsql-template.sh
new file mode 100755
index 0000000..13e345c
--- /dev/null
+++ b/tests/pgsql-template.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under GPLv3
+
+. ${srcdir:=.}/diag.sh init
+
+psql -h localhost -U postgres -f testsuites/pgsql-basic.sql
+
+generate_conf
+add_conf '
+# putting the message in the SyslogTag field, so we know the template is actually used
+$template mytemplate,"insert into SystemEvents (SysLogTag) values '
+add_conf "('%msg%')"
+add_conf '",STDSQL
+
+$ModLoad ../plugins/ompgsql/.libs/ompgsql
+:msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench;mytemplate
+'
+startup
+injectmsg 0 5000
+shutdown_when_empty
+wait_shutdown
+
+# we actually put the message in the SysLogTag field, so we know it doesn't use the default
+# template, like in pgsql-basic
+psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG
+
+seq_check 0 4999
+
+echo cleaning up test database
+psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;'
+
+exit_test
diff --git a/tests/pipe_noreader.sh b/tests/pipe_noreader.sh
new file mode 100755
index 0000000..ca1274d
--- /dev/null
+++ b/tests/pipe_noreader.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# This is test driver for a pipe that has no reader. This mimics a usual
+# real-world scenario, the /dev/xconsole pipe. Some versions of rsyslog
+# were known to hang or loop on this pipe, thus we added this scenario
+# as a permanent testcase. For some details, please see bug tracker
+# http://bugzilla.adiscon.com/show_bug.cgi?id=186
+#
+# IMPORTANT: we do NOT check any result message set. The whole point in
+# this test is to verify that we do NOT run into an eternal loop. As such,
+# the test is "PASS", if rsyslogd terminates. If it does not terminate, we
+# obviously do not cause "FAIL", but processing will hang, which should be
+# a good-enough indication of failure.
+#
+# added 2010-04-26 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" |./'$RSYSLOG_DYNNAME'.pipe
+'
+mkfifo ./$RSYSLOG_DYNNAME.pipe
+startup
+# we need to emit ~ 128K of data according to bug report
+tcpflood -m1000 -d500
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+# NO need to check seqno -- see header comment
+echo we did not loop, so the test is successful
+exit_test
diff --git a/tests/pipeaction.sh b/tests/pipeaction.sh
new file mode 100755
index 0000000..a50784e
--- /dev/null
+++ b/tests/pipeaction.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Test for the pipe output action.
+# will create a fifo in the current directory, write to it and
+# then do the usual sequence checks.
+# added 2009-11-05 by RGerhards
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=20000
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$template outfmt,"%msg:F,58:2%\n"
+# with pipes, we do not need to use absolute path names, so
+# we can simply refer to our working pipe via the usual relative
+# path name
+:msg, contains, "msgnum:" |rsyslog-testbench-fifo;outfmt
+'
+rm -f rsyslog-testbench-fifo
+mkfifo rsyslog-testbench-fifo
+cp rsyslog-testbench-fifo $RSYSLOG_OUT_LOG &
+CPPROCESS=$!
+echo background cp process id is $CPPROCESS
+
+# now do the usual run
+startup
+injectmsg 0 $NUMMESSAGES
+shutdown_when_empty
+wait_shutdown
+
+# wait for the cp process to finish, do pipe-specific cleanup
+echo waiting for background cp to terminate...
+wait $CPPROCESS
+rm -f rsyslog-testbench-fifo
+echo background cp has terminated, continue test...
+
+# and continue the usual checks
+seq_check
+exit_test
diff --git a/tests/pmdb2diag_parse.sh b/tests/pmdb2diag_parse.sh
new file mode 100755
index 0000000..db24faa
--- /dev/null
+++ b/tests/pmdb2diag_parse.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# add 2019-03-09 by Philippe Duveau, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imfile/.libs/imfile")
+module(load="../contrib/pmdb2diag/.libs/pmdb2diag")
+input(type="imfile" ruleset="ruleset" tag="in:"
+ File="./'$RSYSLOG_DYNNAME'.crio.input"
+ Startmsg.regex="^[0-9]{4}-[0-9]{2}-[0-9]{2}"
+ Escapelf="on" needparse="on")
+template(name="test" type="string" string="time: %TIMESTAMP:::date-rfc3339%, level: %syslogseverity-text%, app: %app-name%, procid: %procid% msg: %msg%\n")
+parser(type="pmdb2diag" timeformat="%Y-%m-%d-%H.%M.%S." timepos="0" levelpos="59" pidstarttoprogstartshift="49" name="db2.diag.cust")
+ruleset(name="ruleset" parser="db2.diag.cust") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+{
+ echo '2015-05-06-16.53.26.989430+120 E1876227378A1702 LEVEL: Critical'
+ echo 'PID : 4390941 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989440+120 E1876227378A1702 LEVEL: Alert'
+ echo 'PID : 4390942 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989450+120 E1876227378A1702 LEVEL: Severe'
+ echo 'PID : 4390943 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989460+120 E1876227378A1702 LEVEL: Error'
+ echo 'PID : 4390944 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989470+120 E1876227378A1702 LEVEL: Warning'
+ echo 'PID : 4390945 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989480+120 E1876227378A1702 LEVEL: Event'
+ echo 'PID : 4390946 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989490+120 E1876227378A1702 LEVEL: Info'
+ echo 'PID : 4390947 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989500+120 E1876227378A1702 LEVEL: Debug'
+ echo 'PID : 4390948 TID : 89500 PROC : db2sysc 0'
+ echo 'INSTANCE: db2itst NODE : 000 DB : DBTST'
+ echo '2015-05-06-16.53.26.989510+120 E1876227378A1702 LEVEL: Info'
+} > $RSYSLOG_DYNNAME.crio.input
+startup
+shutdown_when_empty
+wait_shutdown
+cmp - $RSYSLOG_OUT_LOG <<!end
+time: 2015-05-06T16:53:26.989430+02:00, level: emerg, app: db2sysc, procid: 4390941 msg: 2015-05-06-16.53.26.989430+120 E1876227378A1702 LEVEL: Critical\nPID : 4390941 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989440+02:00, level: alert, app: db2sysc, procid: 4390942 msg: 2015-05-06-16.53.26.989440+120 E1876227378A1702 LEVEL: Alert\nPID : 4390942 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989450+02:00, level: crit, app: db2sysc, procid: 4390943 msg: 2015-05-06-16.53.26.989450+120 E1876227378A1702 LEVEL: Severe\nPID : 4390943 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989460+02:00, level: err, app: db2sysc, procid: 4390944 msg: 2015-05-06-16.53.26.989460+120 E1876227378A1702 LEVEL: Error\nPID : 4390944 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989470+02:00, level: warning, app: db2sysc, procid: 4390945 msg: 2015-05-06-16.53.26.989470+120 E1876227378A1702 LEVEL: Warning\nPID : 4390945 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989480+02:00, level: notice, app: db2sysc, procid: 4390946 msg: 2015-05-06-16.53.26.989480+120 E1876227378A1702 LEVEL: Event\nPID : 4390946 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989490+02:00, level: info, app: db2sysc, procid: 4390947 msg: 2015-05-06-16.53.26.989490+120 E1876227378A1702 LEVEL: Info\nPID : 4390947 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+time: 2015-05-06T16:53:26.989500+02:00, level: debug, app: db2sysc, procid: 4390948 msg: 2015-05-06-16.53.26.989500+120 E1876227378A1702 LEVEL: Debug\nPID : 4390948 TID : 89500 PROC : db2sysc 0\nINSTANCE: db2itst NODE : 000 DB : DBTST
+!end
+
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmlastmsg-udp.sh b/tests/pmlastmsg-udp.sh
new file mode 100755
index 0000000..5a64e89
--- /dev/null
+++ b/tests/pmlastmsg-udp.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/pmlastmsg/.libs/pmlastmsg")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.lastline","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times\""
+tcpflood -m1 -T "udp" -M "\"<13>last message repeated 0090909787348927349875 times\""
+tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times\""
+tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times -- more data\""
+tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5.2 times\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG long message ================================================================================\""
+tcpflood -m1 -T "udp" -M "\"<34>1 2003-11-11T22:14:15.003Z mymachine.example.com su - ID47 last message repeated 5 times\""
+shutdown_when_empty
+wait_shutdown
+
+echo 'last message repeated 5 times
+last message repeated 0090909787348927349875 times
+ repeated 5 times
+ repeated 5 times -- more data
+ repeated 5.2 times
+ Rest of message...
+ long message ================================================================================
+last message repeated 5 times' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmlastmsg.sh b/tests/pmlastmsg.sh
new file mode 100755
index 0000000..ed44b58
--- /dev/null
+++ b/tests/pmlastmsg.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/pmlastmsg/.libs/pmlastmsg")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.lastline","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<13>last message repeated 5 times\""
+tcpflood -m1 -M "\"<13>last message repeated 0090909787348927349875 times\""
+tcpflood -m1 -M "\"<13>last message repeated 5 times\""
+tcpflood -m1 -M "\"<13>last message repeated 5 times -- more data\""
+tcpflood -m1 -M "\"<13>last message repeated 5.2 times\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG long message ================================================================================\""
+tcpflood -m1 -M "\"<34>1 2003-11-11T22:14:15.003Z mymachine.example.com su - ID47 last message repeated 5 times\""
+shutdown_when_empty
+wait_shutdown
+
+echo 'last message repeated 5 times
+last message repeated 0090909787348927349875 times
+ repeated 5 times
+ repeated 5 times -- more data
+ repeated 5.2 times
+ Rest of message...
+ long message ================================================================================
+last message repeated 5 times' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmnormalize-basic-vg.sh b/tests/pmnormalize-basic-vg.sh
new file mode 100755
index 0000000..9696ba8
--- /dev/null
+++ b/tests/pmnormalize-basic-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-basic.sh
diff --git a/tests/pmnormalize-basic.sh b/tests/pmnormalize-basic.sh
new file mode 100755
index 0000000..7ca2b96
--- /dev/null
+++ b/tests/pmnormalize-basic.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2016-12-08 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+parser(name="custom.pmnormalize" type="pmnormalize" rulebase="'$srcdir'/testsuites/pmnormalize_basic.rulebase")
+
+template(name="test" type="string" string="host: %hostname%, ip: %fromhost-ip%, tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n")
+
+ruleset(name="ruleset" parser="custom.pmnormalize") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189> ubuntu tag1: is no longer listening on 127.0.0.1 test\""
+tcpflood -m1 -M "\"<112> debian tag2: is no longer listening on 255.255.255.255 test\""
+tcpflood -m1 -M "\"<177> centos tag3: is no longer listening on 192.168.0.9 test\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='host: ubuntu, ip: 127.0.0.1, tag: tag1, pri: 189, syslogfacility: 23, syslogseverity: 5 msg: test
+host: debian, ip: 255.255.255.255, tag: tag2, pri: 112, syslogfacility: 14, syslogseverity: 0 msg: test
+host: centos, ip: 192.168.0.9, tag: tag3, pri: 177, syslogfacility: 22, syslogseverity: 1 msg: test'
+cmp_exact
+
+exit_test
diff --git a/tests/pmnormalize-invld-rulebase-vg.sh b/tests/pmnormalize-invld-rulebase-vg.sh
new file mode 100755
index 0000000..f3d4311
--- /dev/null
+++ b/tests/pmnormalize-invld-rulebase-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-invld-rulebase.sh
diff --git a/tests/pmnormalize-invld-rulebase.sh b/tests/pmnormalize-invld-rulebase.sh
new file mode 100755
index 0000000..48102bc
--- /dev/null
+++ b/tests/pmnormalize-invld-rulebase.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2016-12-08 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+parser(name="custom.pmnormalize" type="pmnormalize" rulebase="DOES-NOT-EXIST")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "cannot open rulebase .*DOES-NOT-EXIST"
+
+exit_test
diff --git a/tests/pmnormalize-neither_rule_rulebase-vg.sh b/tests/pmnormalize-neither_rule_rulebase-vg.sh
new file mode 100755
index 0000000..d5e76ee
--- /dev/null
+++ b/tests/pmnormalize-neither_rule_rulebase-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-neither_rule_rulebase.sh
diff --git a/tests/pmnormalize-neither_rule_rulebase.sh b/tests/pmnormalize-neither_rule_rulebase.sh
new file mode 100755
index 0000000..091165d
--- /dev/null
+++ b/tests/pmnormalize-neither_rule_rulebase.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+parser(name="custom.pmnormalize" type="pmnormalize")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "pmnormalize:.*you need to specify either"
+
+exit_test
diff --git a/tests/pmnormalize-rule-vg.sh b/tests/pmnormalize-rule-vg.sh
new file mode 100755
index 0000000..25d33bc
--- /dev/null
+++ b/tests/pmnormalize-rule-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-rule.sh
diff --git a/tests/pmnormalize-rule.sh b/tests/pmnormalize-rule.sh
new file mode 100755
index 0000000..f7cdbf3
--- /dev/null
+++ b/tests/pmnormalize-rule.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2017-06-12 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+parser(name="custom.pmnormalize" type="pmnormalize" rule=["rule=:<%pri:number%> %fromhost-ip:ipv4% %hostname:word% %syslogtag:char-to:\\x3a%: %msg:rest%", "rule=:<%pri:number%> %hostname:word% %fromhost-ip:ipv4% %syslogtag:char-to:\\x3a%: %msg:rest%"])
+
+template(name="test" type="string" string="host: %hostname%, ip: %fromhost-ip%, tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n")
+
+ruleset(name="ruleset" parser="custom.pmnormalize") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189> 127.0.0.1 ubuntu tag1: this is a test message\""
+tcpflood -m1 -M "\"<112> 255.255.255.255 debian tag2: this is a test message\""
+tcpflood -m1 -M "\"<177> centos 192.168.0.9 tag3: this is a test message\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='host: ubuntu, ip: 127.0.0.1, tag: tag1, pri: 189, syslogfacility: 23, syslogseverity: 5 msg: this is a test message
+host: debian, ip: 255.255.255.255, tag: tag2, pri: 112, syslogfacility: 14, syslogseverity: 0 msg: this is a test message
+host: centos, ip: 192.168.0.9, tag: tag3, pri: 177, syslogfacility: 22, syslogseverity: 1 msg: this is a test message'
+cmp_exact
+
+exit_test
diff --git a/tests/pmnormalize-rule_and_rulebase-vg.sh b/tests/pmnormalize-rule_and_rulebase-vg.sh
new file mode 100755
index 0000000..b848b07
--- /dev/null
+++ b/tests/pmnormalize-rule_and_rulebase-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-rule_and_rulebase.sh
diff --git a/tests/pmnormalize-rule_and_rulebase.sh b/tests/pmnormalize-rule_and_rulebase.sh
new file mode 100755
index 0000000..9e9ee73
--- /dev/null
+++ b/tests/pmnormalize-rule_and_rulebase.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+parser(name="custom.pmnormalize" type="pmnormalize" rule="" rulebase="")
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "pmnormalize:.*you need to specify one of"
+
+exit_test
diff --git a/tests/pmnormalize-rule_invld-data-vg.sh b/tests/pmnormalize-rule_invld-data-vg.sh
new file mode 100755
index 0000000..6c49a9a
--- /dev/null
+++ b/tests/pmnormalize-rule_invld-data-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/pmnormalize-rule_invld-data.sh
diff --git a/tests/pmnormalize-rule_invld-data.sh b/tests/pmnormalize-rule_invld-data.sh
new file mode 100755
index 0000000..039c402
--- /dev/null
+++ b/tests/pmnormalize-rule_invld-data.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2019-04-10 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/pmnormalize/.libs/pmnormalize")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+parser(name="custom.pmnormalize" type="pmnormalize" undefinedPropertyError="on"
+ rule="rule=:<%pri:number%> %fromhost-ip:ipv4% %hostname:word% %syslogtag:char-to:\\x3a%: %msg:rest%")
+
+template(name="test" type="string" string="%msg%\n")
+
+ruleset(name="ruleset" parser="custom.pmnormalize") {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="test")
+}
+action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsg")
+'
+startup
+tcpflood -m1 -M "\"<abc> 127.0.0.1 ubuntu tag1: this is a test message\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='<abc> 127.0.0.1 ubuntu tag1: this is a test message'
+cmp_exact
+content_check --regex "error .* during ln_normalize" $RSYSLOG_DYNNAME.othermsg
+
+exit_test
diff --git a/tests/pmnull-basic.sh b/tests/pmnull-basic.sh
new file mode 100755
index 0000000..3f3eda1
--- /dev/null
+++ b/tests/pmnull-basic.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2016-12-07 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/pmnull/.libs/pmnull")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+parser(name="custom.pmnull.withOrigin" type="pmnull")
+template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n")
+ruleset(name="ruleset" parser=["custom.pmnull.withOrigin", "rsyslog.pmnull"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\""
+shutdown_when_empty
+wait_shutdown
+echo 'tag: , pri: 13, syslogfacility: 1, syslogseverity: 5 msg: <189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmnull-withparams.sh b/tests/pmnull-withparams.sh
new file mode 100755
index 0000000..95a48ee
--- /dev/null
+++ b/tests/pmnull-withparams.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2016-12-08 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/pmnull/.libs/pmnull")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+parser(name="custom.pmnull" type="pmnull" tag="mytag" syslogfacility="3" syslogseverity="1")
+template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n")
+ruleset(name="ruleset" parser=["custom.pmnull", "rsyslog.pmnull"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test")
+}
+'
+startup
+tcpflood -m1 -M "\"<189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\""
+shutdown_when_empty
+wait_shutdown
+echo 'tag: mytag, pri: 25, syslogfacility: 3, syslogseverity: 1 msg: <189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmrfc3164-AtSignsInHostname.sh b/tests/pmrfc3164-AtSignsInHostname.sh
new file mode 100755
index 0000000..d6a5a26
--- /dev/null
+++ b/tests/pmrfc3164-AtSignsInHostname.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser")
+parser(name="custom.rfc3164" type="pmrfc3164" permit.AtSignsInHostname="on")
+template(name="outfmt" type="string" string="-%hostname%-\n")
+
+ruleset(name="customparser" parser="custom.rfc3164") {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 tag: msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostn@me2 tag: msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag:msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hos@name4 tag4:\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='-Hostname1-
+-Hostn@me2-
+-Hostname3-
+-Hos@name4-'
+cmp_exact
+
+exit_test
diff --git a/tests/pmrfc3164-AtSignsInHostname_off.sh b/tests/pmrfc3164-AtSignsInHostname_off.sh
new file mode 100755
index 0000000..1e1ac6c
--- /dev/null
+++ b/tests/pmrfc3164-AtSignsInHostname_off.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser")
+parser(name="custom.rfc3164" type="pmrfc3164" permit.AtSignsInHostname="off")
+template(name="outfmt" type="string" string="-%hostname%-%syslogtag%-%msg%-\n")
+
+ruleset(name="customparser" parser="custom.rfc3164") {
+ :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 tag: msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostn@me2 tag: msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag:msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hos@name4 tag4:\""
+shutdown_when_empty
+wait_shutdown
+echo '-Hostname1-tag:- msgnum:1-
+-Hostname3-tag:-msgnum:3-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmrfc3164-defaultTag.sh b/tests/pmrfc3164-defaultTag.sh
new file mode 100755
index 0000000..f7a920b
--- /dev/null
+++ b/tests/pmrfc3164-defaultTag.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser")
+parser(name="custom.rfc3164" type="pmrfc3164" permit.AtSignsInHostname="off"
+ force.tagEndingByColon="on")
+template(name="outfmt" type="string" string="?%hostname%?%syslogtag%?%msg%?\n")
+
+ruleset(name="customparser" parser="custom.rfc3164") {
+ :hostname, contains, "Hostname" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname2 msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname4 tag: msg\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='?Hostname1?-? msgnum:1?
+?Hostname2?-? msgnum:2?
+?Hostname3?-? tag msgnum:3?
+?Hostname4?tag:? msg?'
+cmp_exact
+
+exit_test
diff --git a/tests/pmrfc3164-json.sh b/tests/pmrfc3164-json.sh
new file mode 100755
index 0000000..6142383
--- /dev/null
+++ b/tests/pmrfc3164-json.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2017-12-12 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+template(name="outfmt" type="string" string="%msg%---%rawmsg%\n")
+
+ruleset(name="rs") {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"{ \\\"c1\\\":1 }\""
+tcpflood -m1 -M "\" { \\\"c2\\\":2 }\""
+tcpflood -m1 -M "\" [{ \\\"c3\\\":3 }]\""
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='{ "c1":1 }---{ "c1":1 }
+ { "c2":2 }--- { "c2":2 }
+ [{ "c3":3 }]--- [{ "c3":3 }]'
+echo "$EXPECTED" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ printf 'expected was\n'
+ echo "$EXPECTED"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmrfc3164-msgFirstSpace.sh b/tests/pmrfc3164-msgFirstSpace.sh
new file mode 100755
index 0000000..e9f8679
--- /dev/null
+++ b/tests/pmrfc3164-msgFirstSpace.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser")
+parser(name="custom.rfc3164" type="pmrfc3164" remove.msgFirstSpace="on")
+template(name="outfmt" type="string" string="-%msg%-\n")
+
+ruleset(name="customparser" parser="custom.rfc3164") {
+ :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag4:\""
+shutdown_when_empty
+wait_shutdown
+echo '-msgnum:1-
+- msgnum:2-
+-msgnum:3-
+--' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmrfc3164-tagEndingByColon.sh b/tests/pmrfc3164-tagEndingByColon.sh
new file mode 100755
index 0000000..eb53048
--- /dev/null
+++ b/tests/pmrfc3164-tagEndingByColon.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2016-11-22 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser")
+parser(name="custom.rfc3164" type="pmrfc3164" force.tagEndingByColon="on")
+template(name="outfmt" type="string" string="-%syslogtag%-%msg%-\n")
+
+ruleset(name="customparser" parser="custom.rfc3164") {
+ :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 tag1: msgnum:1\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname2 tag2: msgnum:2\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag3 msgnum:3\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname4 tag4 :\""
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname5 tag5:msgnum:5\""
+shutdown_when_empty
+wait_shutdown
+echo '-tag1:- msgnum:1-
+-tag2:- msgnum:2-
+-tag5:-msgnum:5-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-ccbackslash-udp.sh b/tests/pmsnare-ccbackslash-udp.sh
new file mode 100755
index 0000000..9d738fc
--- /dev/null
+++ b/tests/pmsnare-ccbackslash-udp.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost"
+ parser.escapeControlCharactersCStyle="on")
+
+$EscapeControlCharactersOnReceive on
+
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/pmsnare-ccbackslash.sh b/tests/pmsnare-ccbackslash.sh
new file mode 100755
index 0000000..60da84d
--- /dev/null
+++ b/tests/pmsnare-ccbackslash.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(localHostname="localhost"
+ parser.escapeControlCharactersCStyle="on")
+
+$EscapeControlCharactersOnReceive on
+
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/pmsnare-cccstyle-udp.sh b/tests/pmsnare-cccstyle-udp.sh
new file mode 100755
index 0000000..a8b44c9
--- /dev/null
+++ b/tests/pmsnare-cccstyle-udp.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(parser.escapeControlCharactersCStyle="on")
+
+$EscapeControlCharactersOnReceive on
+
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group local_in [0x0, 0x0]
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/pmsnare-cccstyle.sh b/tests/pmsnare-cccstyle.sh
new file mode 100755
index 0000000..6650642
--- /dev/null
+++ b/tests/pmsnare-cccstyle.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+setvar_RS_HOSTNAME
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+$EscapeControlCharactersOnReceive on
+global(
+ parser.escapeControlCharactersCStyle="on"
+)
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group local_in [0x0, 0x0]
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain
+14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/pmsnare-ccdefault-udp.sh b/tests/pmsnare-ccdefault-udp.sh
new file mode 100755
index 0000000..61787d0
--- /dev/null
+++ b/tests/pmsnare-ccdefault-udp.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group \\\"local_in\\\" [0x0, 0x0]\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0114624#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011Logon#011#011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-ccdefault.sh b/tests/pmsnare-ccdefault.sh
new file mode 100755
index 0000000..7a7a8dd
--- /dev/null
+++ b/tests/pmsnare-ccdefault.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group \\\"local_in\\\" [0x0, 0x0]\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0114624#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011Logon#011#011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-ccoff-udp.sh b/tests/pmsnare-ccoff-udp.sh
new file mode 100755
index 0000000..5c69451
--- /dev/null
+++ b/tests/pmsnare-ccoff-udp.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+tcpflood -m1 -T "udp" -M "\"hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 5061 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain System Integrity Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0 -0000000000\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0114624#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011Logon#011#011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................
+13,user,notice,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0115061#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011System Integrity#011#011Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0#011-0000000000' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-ccoff.sh b/tests/pmsnare-ccoff.sh
new file mode 100755
index 0000000..33fffa6
--- /dev/null
+++ b/tests/pmsnare-ccoff.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+tcpflood -m1 -M "\"hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 5061 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain System Integrity Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0 -0000000000\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0114624#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011Logon#011#011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................
+13,user,notice,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0115061#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011System Integrity#011#011Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0#011-0000000000' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-default-udp.sh b/tests/pmsnare-default-udp.sh
new file mode 100755
index 0000000..25c8fde
--- /dev/null
+++ b/tests/pmsnare-default-udp.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group \\\"local_in\\\" [0x0, 0x0]\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 2017 00:00:00: %ASA-6-102030: SFR requested ASA to bypass further packet redirection and process TCP flow from vlan_1233:192.168.0.11/10469 to vlan_12323:192.168.0.11/443 locally\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Rhttpproxy: verbose rhttpproxy[479C1B70] [Originator@6876 sub=Proxy Req 69725] Resolved endpoint : [N7Vmacore4Http16LocalServiceSpecE:0x00000000] _serverNamespace = /vpxa _isRedirect = false _port = 0000000000\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname MSWinEventLog 1 N/A 113977 Sun May 21 12:00:01.123 N/A nxlog N/A N/A N/A hostname N/A reconnecting to agent manager in 200 seconds N/A\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]
+14,user,info,%ASA-6-102030,%ASA-6-102030:, SFR requested ASA to bypass further packet redirection and process TCP flow from vlan_1233:192.168.0.11/10469 to vlan_12323:192.168.0.11/443 locally
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,Rhttpproxy,Rhttpproxy:, verbose rhttpproxy[479C1B70] [Originator@6876 sub=Proxy Req 69725] Resolved endpoint : [N7Vmacore4Http16LocalServiceSpecE:0x00000000] _serverNamespace = /vpxa _isRedirect = false _port = 0000000000
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog#0111#011N,MSWinEventLog#0111#011N/A#011113977#011Sun, May 21 12:00:01.123#011N/A#011nxlog#011N/A#011N/A#011N/A#011hostname#011N/A#011#011reconnecting to agent manager in 200 seconds#011N/A' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-default.sh b/tests/pmsnare-default.sh
new file mode 100755
index 0000000..bc80a6b
--- /dev/null
+++ b/tests/pmsnare-default.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(localHostname="localhost")
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\""
+tcpflood -m1 -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group \\\"local_in\\\" [0x0, 0x0]\""
+tcpflood -m1 -M "\"<14>May 21 2017 00:00:00: %ASA-6-102030: SFR requested ASA to bypass further packet redirection and process TCP flow from vlan_1233:192.168.0.11/10469 to vlan_12323:192.168.0.11/443 locally\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Rhttpproxy: verbose rhttpproxy[479C1B70] [Originator@6876 sub=Proxy Req 69725] Resolved endpoint : [N7Vmacore4Http16LocalServiceSpecE:0x00000000] _serverNamespace = /vpxa _isRedirect = false _port = 0000000000\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname MSWinEventLog 1 N/A 113977 Sun May 21 12:00:01.123 N/A nxlog N/A N/A N/A hostname N/A reconnecting to agent manager in 200 seconds N/A\""
+shutdown_when_empty
+wait_shutdown
+
+echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................
+14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]
+14,user,info,%ASA-6-102030,%ASA-6-102030:, SFR requested ASA to bypass further packet redirection and process TCP flow from vlan_1233:192.168.0.11/10469 to vlan_12323:192.168.0.11/443 locally
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,Rhttpproxy,Rhttpproxy:, verbose rhttpproxy[479C1B70] [Originator@6876 sub=Proxy Req 69725] Resolved endpoint : [N7Vmacore4Http16LocalServiceSpecE:0x00000000] _serverNamespace = /vpxa _isRedirect = false _port = 0000000000
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog#0111#011N,MSWinEventLog#0111#011N/A#011113977#011Sun, May 21 12:00:01.123#011N/A#011nxlog#011N/A#011N/A#011N/A#011hostname#011N/A#011#011reconnecting to agent manager in 200 seconds#011N/A' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/pmsnare-modoverride-udp.sh b/tests/pmsnare-modoverride-udp.sh
new file mode 100755
index 0000000..ad45382
--- /dev/null
+++ b/tests/pmsnare-modoverride-udp.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+global(
+ parser.escapeControlCharactersOnReceive="off"
+ parser.escapeControlCharacterTab="off"
+ parser.escapeControlCharactersCStyle="on"
+ parser.controlCharacterEscapePrefix="#"
+)
+
+parser(
+ name="modoverride.snare"
+ type="pmsnare"
+ parser.escapeControlCharactersOnReceive="on"
+ parser.escapeControlCharacterTab="on"
+ parser.escapeControlCharactersCStyle="off"
+ parser.controlCharacterEscapePrefix="\\"
+)
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["modoverride.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog\\\\0111\\\\011Security\\\\01100000000\\\\011Sun May 21 12:00:01.123\\\\0114624\\\\011Microsoft-Windows-Security-Auditing\\\\011N/A\\\\011N/A\\\\011Success Audit\\\\011hostname.domain\\\\011Logon\\\\011\\\\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\011Security\01100000000\011Sun May 21 12:00:01.123\0114624\011Microsoft-Windows-Security-Auditing\011N/A\011N/A\011Success Audit\011hostname.domain\011Logon\011\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/pmsnare-modoverride.sh b/tests/pmsnare-modoverride.sh
new file mode 100755
index 0000000..1faf484
--- /dev/null
+++ b/tests/pmsnare-modoverride.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../contrib/pmsnare/.libs/pmsnare")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+global(
+ parser.escapeControlCharactersOnReceive="off"
+ parser.escapeControlCharacterTab="off"
+ parser.escapeControlCharactersCStyle="on"
+ parser.controlCharacterEscapePrefix="#"
+)
+
+parser(
+ name="modoverride.snare"
+ type="pmsnare"
+ parser.escapeControlCharactersOnReceive="on"
+ parser.escapeControlCharacterTab="on"
+ parser.escapeControlCharactersCStyle="off"
+ parser.controlCharacterEscapePrefix="\\"
+)
+
+template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n")
+
+ruleset(name="ruleset1" parser=["modoverride.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\""
+tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\""
+tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog\\\\0111\\\\011Security\\\\01100000000\\\\011Sun May 21 12:00:01.123\\\\0114624\\\\011Microsoft-Windows-Security-Auditing\\\\011N/A\\\\011N/A\\\\011Success Audit\\\\011hostname.domain\\\\011Logon\\\\011\\\\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti
+14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};
+14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................
+14,user,info,MSWinEventLog,MSWinEventLog, 1\011Security\01100000000\011Sun May 21 12:00:01.123\0114624\011Microsoft-Windows-Security-Auditing\011N/A\011N/A\011Success Audit\011hostname.domain\011Logon\011\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/privdrop_common.sh b/tests/privdrop_common.sh
new file mode 100755
index 0000000..dabc088
--- /dev/null
+++ b/tests/privdrop_common.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+# added 2016-04-15 by Thomas D., released under ASL 2.0
+# Several tests need another user/group to test impersonation.
+# This script can be sourced to prevent duplicated code.
+
+# To support <bash-4.2 which don't support "declare -g" we declare
+# the array outside of the function
+declare -A TESTBENCH_TESTUSER
+
+rsyslog_testbench_setup_testuser() {
+ local has_testuser=
+ local testusername=
+ local testgroupname=
+
+ if [ -z "${EUID}" ]; then
+ # Should never happen
+ echo "FATAL ERROR: \$EUID not set!"
+ exit 1
+ fi
+
+ if [ ${EUID} -eq 0 ]; then
+ # Only root is able to become a different user
+
+ local testusers=("rsyslog" "syslog" "daemon")
+
+ if [ -n "${RSYSLOG_TESTUSER}" ]; then
+ # User has specified an username/uid we should use in testbench
+ testusers=("${RSYSLOG_TESTUSER}" ${testusers[@]})
+ fi
+
+ local testuser=
+ for testuser in "${testusers[@]}"; do
+ testusername=$(id --user --name ${testuser} 2>/dev/null)
+ if [ -z "${testusername}" ]; then
+ echo "'id' did not find user \"${testuser}\" ... skipping, trying next user!"
+ continue
+ fi
+
+ testgroupname=$(id --group --name ${testuser} 2>/dev/null)
+ if [ -z "${testgroupname}" ]; then
+ echo "'id' did not find a primary group for \"${testuser}\" ... skipping, trying next user!"
+ continue
+ fi
+
+ has_testuser="${testuser}"
+ break
+ done
+ if [ -z "${has_testuser}" ]; then
+ echo "ERROR: running as root and no suiteable testuser found - skipping test"
+ echo 'You mas set a testuser via the RSYSLOG_TESTUSER environment variable'
+ exit 77
+ fi
+ echo "WARNING: making work directory world-writable, as we need this to be able to"
+ echo " open and process files after privilege drop. This is NOT automatically"
+ echo " undone."
+ chmod a+w .
+ fi
+
+ if [ -z "${has_testuser}" ]; then
+ testgroupname=$(id --group --name ${EUID} 2>/dev/null)
+ if [ -z "${testgroupname}" ]; then
+ echo "Skipping ... please set RSYSLOG_TESTUSER or make sure the user running the testbench has a primary group!"
+ exit_test
+ exit 0
+ else
+ has_testuser="${EUID}"
+ fi
+ fi
+
+ _rsyslog_testbench_declare_testuser ${has_testuser}
+}
+
+_rsyslog_testbench_declare_testuser() {
+ local testuser=$1
+
+ local testusername=$(id --user --name ${testuser} 2>/dev/null)
+ if [ -z "${testusername}" ]; then
+ # Should never happen
+ echo "FATAL ERROR: Could not get username for user \"${testuser}\"!"
+ exit 1
+ fi
+
+ local testuid=$(id --user ${testuser} 2>/dev/null)
+ if [ -z "${testuid}" ]; then
+ # Should never happen
+ echo "FATAL ERROR: Could not get uid for user \"${testuser}\"!"
+ exit 1
+ fi
+
+ local testgroupname=$(id --group --name ${testuser} 2>/dev/null)
+ if [ -z "${testgroupname}" ]; then
+ # Should never happen
+ echo "FATAL ERROR: Could not get uid of user \"${testuser}\"!"
+ exit 1
+ fi
+
+ local testgid=$(id --group ${testuser} 2>/dev/null)
+ if [ -z "${testgid}" ]; then
+ # Should never happen
+ echo "FATAL ERROR: Could not get primary gid of user \"${testuser}\"!"
+ exit 1
+ fi
+
+ echo "Will use user \"${testusername}\" (#${testuid}) and group \"${testgroupname}\" (#${testgid})"
+
+ TESTBENCH_TESTUSER[username]=${testusername}
+ TESTBENCH_TESTUSER[uid]=${testuid}
+ TESTBENCH_TESTUSER[groupname]=${testgroupname}
+ TESTBENCH_TESTUSER[gid]=${testgid}
+}
diff --git a/tests/privdropabortonidfail.sh b/tests/privdropabortonidfail.sh
new file mode 100755
index 0000000..842158a
--- /dev/null
+++ b/tests/privdropabortonidfail.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# add 2021-10-12 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+skip_platform "SunOS" "This test currently does not work on Solaris."
+export TESTBENCH_TESTUSER1="USER_${RSYSLOG_DYNNAME}_1"
+export TESTBENCH_TESTUSER2="USER_${RSYSLOG_DYNNAME}_2"
+
+generate_conf
+add_conf '
+global(
+ security.abortOnIDResolutionFail="off"
+)
+
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action( type="omfile"
+ template="outfmt"
+ file="'${RSYSLOG_OUT_LOG}'"
+)
+
+action( type="omfile"
+ template="outfmt"
+ file="'${RSYSLOG_DYNNAME}'.dummy.log"
+ FileOwner="'${TESTBENCH_TESTUSER1}'"
+ FileGroup="'${TESTBENCH_TESTUSER1}'"
+ DirOwner="'${TESTBENCH_TESTUSER2}'"
+ DirGroup="'${TESTBENCH_TESTUSER2}'"
+ )
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "ID for user '${TESTBENCH_TESTUSER1}' could not be found"
+content_check --regex "ID for user '${TESTBENCH_TESTUSER2}' could not be found"
+exit_test
diff --git a/tests/privdropabortonidfaillegacy.sh b/tests/privdropabortonidfaillegacy.sh
new file mode 100755
index 0000000..bc4b8a1
--- /dev/null
+++ b/tests/privdropabortonidfaillegacy.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# add 2021-10-12 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog"
+
+skip_platform "SunOS" "This test currently does not work on Solaris."
+export TESTBENCH_TESTUSER1="USER_${RSYSLOG_DYNNAME}_1"
+export TESTBENCH_TESTUSER2="USER_${RSYSLOG_DYNNAME}_2"
+
+generate_conf
+add_conf '
+global(
+ security.abortOnIDResolutionFail="off"
+)
+
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+
+$FileOwner '${TESTBENCH_TESTUSER1}'
+$FileGroup '${TESTBENCH_TESTUSER1}'
+$DirOwner '${TESTBENCH_TESTUSER2}'
+$DirGroup '${TESTBENCH_TESTUSER2}'
+
+action( type="omfile"
+ template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "ID for user '${TESTBENCH_TESTUSER1}' could not be found"
+content_check --regex "ID for user '${TESTBENCH_TESTUSER2}' could not be found"
+
+exit_test
diff --git a/tests/privdropgroup.sh b/tests/privdropgroup.sh
new file mode 100755
index 0000000..276539b
--- /dev/null
+++ b/tests/privdropgroup.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# addd 2016-03-24 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.group.keepsupplemental="on")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+$PrivDropToGroup '${TESTBENCH_TESTUSER[groupname]}'
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}"
+if [ ! $? -eq 0 ]; then
+ echo "message indicating drop to group \"${TESTBENCH_TESTUSER[groupname]}\" (#${TESTBENCH_TESTUSER[gid]}) is missing:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/privdropgroupid.sh b/tests/privdropgroupid.sh
new file mode 100755
index 0000000..dfbbba4
--- /dev/null
+++ b/tests/privdropgroupid.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# addd 2016-03-24 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.group.keepsupplemental="on")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+$PrivDropToGroupID '${TESTBENCH_TESTUSER[gid]}'
+'
+#add_conf "\$PrivDropToGroupID ${TESTBENCH_TESTUSER[gid]}"
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}"
+exit_test
diff --git a/tests/privdropuser.sh b/tests/privdropuser.sh
new file mode 100755
index 0000000..acbf450
--- /dev/null
+++ b/tests/privdropuser.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2016-03-24 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+$PrivDropToUser '${TESTBENCH_TESTUSER[username]}'
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}"
+exit_test
diff --git a/tests/privdropuserid.sh b/tests/privdropuserid.sh
new file mode 100755
index 0000000..bc2fdf9
--- /dev/null
+++ b/tests/privdropuserid.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# addd 2016-03-24 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+$PrivDropToUserID '${TESTBENCH_TESTUSER[uid]}'
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}"
+exit_test
diff --git a/tests/prop-all-json-concurrency.sh b/tests/prop-all-json-concurrency.sh
new file mode 100755
index 0000000..4f7b271
--- /dev/null
+++ b/tests/prop-all-json-concurrency.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Test concurrency of exec_template function with msg variables
+# Added 2015-12-16 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[prop-all-json-concurrency.sh\]: testing concurrency of $!all-json variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="interim" type="string" string="%$!tree!here!nbr%")
+template(name="outfmt" type="string" string="%$.interim%\n")
+template(name="all-json" type="string" string="%$!%\n")
+
+if $msg contains "msgnum:" then {
+ set $!tree!here!nbr = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="all-json"
+ queue.type="linkedList")
+
+ set $.interim = $!all-json;
+ unset $!tree!here!nbr;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt"
+ queue.type="fixedArray")
+}
+'
+startup
+sleep 1
+tcpflood -m500000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 499999
+exit_test
diff --git a/tests/prop-jsonmesg-vg.sh b/tests/prop-jsonmesg-vg.sh
new file mode 100755
index 0000000..3c3fada
--- /dev/null
+++ b/tests/prop-jsonmesg-vg.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Added 2018-01-17 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="list"){
+ property(name="jsonmesg")
+ constant(value="\n")
+}
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+
+startup_vg
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+export EXPECTED='"msg": "msgnum:00000000:", '
+. $srcdir/diag.sh grep-check
+exit_test
diff --git a/tests/prop-programname-with-slashes.sh b/tests/prop-programname-with-slashes.sh
new file mode 100755
index 0000000..67d9481
--- /dev/null
+++ b/tests/prop-programname-with-slashes.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# addd 2017-01142 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+global(parser.PermitSlashInProgramname="on")
+
+template(name="outfmt" type="string" string="%syslogtag%,%programname%\n")
+local0.* action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m 1 -M "\"<133>2011-03-01T11:22:12Z host tag/with/slashes msgh ...x\""
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "tag/with/slashes,tag/with/slashes" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/prop-programname.sh b/tests/prop-programname.sh
new file mode 100755
index 0000000..d717351
--- /dev/null
+++ b/tests/prop-programname.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# addd 2017-01142 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%syslogtag%,%programname%\n")
+local0.* action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m 1 -M "\"<133>2011-03-01T11:22:12Z host tag/with/slashes msgh ...x\""
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="tag/with/slashes,tag"
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/proprepltest-nolimittag-udp.sh b/tests/proprepltest-nolimittag-udp.sh
new file mode 100755
index 0000000..38738d0
--- /dev/null
+++ b/tests/proprepltest-nolimittag-udp.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'")
+
+template(name="outfmt" type="string" string="+%syslogtag%+\n")
+
+:pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\""
+shutdown_when_empty
+wait_shutdown
+
+echo '+TAG:+
++0+
++01234567890123456789012345678901+
++01234567890123456789012345678901-toolong+' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/proprepltest-nolimittag.sh b/tests/proprepltest-nolimittag.sh
new file mode 100755
index 0000000..9f57525
--- /dev/null
+++ b/tests/proprepltest-nolimittag.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="+%syslogtag%+\n")
+
+:pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\""
+shutdown_when_empty
+wait_shutdown
+
+echo '+TAG:+
++0+
++01234567890123456789012345678901+
++01234567890123456789012345678901-toolong+' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/proprepltest-rfctag-udp.sh b/tests/proprepltest-rfctag-udp.sh
new file mode 100755
index 0000000..501505a
--- /dev/null
+++ b/tests/proprepltest-rfctag-udp.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'")
+
+template(name="outfmt" type="string" string="+%syslogtag:1:32%+\n")
+
+:pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\""
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\""
+shutdown_when_empty
+wait_shutdown
+
+echo '+TAG:+
++0+
++01234567890123456789012345678901+
++01234567890123456789012345678901+' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/proprepltest-rfctag.sh b/tests/proprepltest-rfctag.sh
new file mode 100755
index 0000000..3d3fc16
--- /dev/null
+++ b/tests/proprepltest-rfctag.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="+%syslogtag:1:32%+\n")
+
+:pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\""
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\""
+shutdown_when_empty
+wait_shutdown
+
+echo '+TAG:+
++0+
++01234567890123456789012345678901+
++01234567890123456789012345678901+' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/queue-direct-with-no-params.sh b/tests/queue-direct-with-no-params.sh
new file mode 100755
index 0000000..4e5c999
--- /dev/null
+++ b/tests/queue-direct-with-no-params.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# added 2019-11-14 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+check_not_present "queue is in direct mode, but parameters have been set"
+exit_test
diff --git a/tests/queue-direct-with-params-given.sh b/tests/queue-direct-with-params-given.sh
new file mode 100755
index 0000000..3593a91
--- /dev/null
+++ b/tests/queue-direct-with-params-given.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# added 2019-11-14 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" queue.mindequeuebatchsize="20")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check "queue is in direct mode, but parameters have been set"
+exit_test
diff --git a/tests/queue-encryption-da.sh b/tests/queue-encryption-da.sh
new file mode 100755
index 0000000..9d6e9b2
--- /dev/null
+++ b/tests/queue-encryption-da.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# addd 2018-09-28 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq"
+ queue.type="linkedList"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+
+ queue.cry.provider="gcry"
+ queue.cry.key="1234567890123456"
+ queue.saveonshutdown="on"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown
+echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0*
+exit_test
diff --git a/tests/queue-encryption-disk.sh b/tests/queue-encryption-disk.sh
new file mode 100755
index 0000000..9f7825c
--- /dev/null
+++ b/tests/queue-encryption-disk.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# addd 2018-09-28 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq"
+ queue.type="disk"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+
+ queue.cry.provider="gcry"
+ queue.cry.key="1234567890123456"
+ queue.saveonshutdown="on"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown
+echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0*
+exit_test
diff --git a/tests/queue-encryption-disk_keyfile-vg.sh b/tests/queue-encryption-disk_keyfile-vg.sh
new file mode 100755
index 0000000..df15c75
--- /dev/null
+++ b/tests/queue-encryption-disk_keyfile-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# addd 2018-09-30 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq"
+ queue.type="disk"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutshutdown="20000"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+
+ queue.cry.provider="gcry"
+ queue.cry.keyfile="'$RSYSLOG_DYNNAME.keyfile'"
+ queue.saveonshutdown="on"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+printf "1234567890123456" > $RSYSLOG_DYNNAME.keyfile
+startup_vg_noleak # we WILL leak due to the immediate shutdown
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown_vg
+check_exit_vg
+echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0*
+exit_test
diff --git a/tests/queue-encryption-disk_keyfile.sh b/tests/queue-encryption-disk_keyfile.sh
new file mode 100755
index 0000000..cc6274d
--- /dev/null
+++ b/tests/queue-encryption-disk_keyfile.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# addd 2018-09-30 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq"
+ queue.type="disk"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+
+ queue.cry.provider="gcry"
+ queue.cry.keyfile="'$RSYSLOG_DYNNAME.keyfile'"
+ queue.saveonshutdown="on"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+printf "1234567890123456" > $RSYSLOG_DYNNAME.keyfile
+startup
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown
+echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0*
+exit_test
diff --git a/tests/queue-encryption-disk_keyprog.sh b/tests/queue-encryption-disk_keyprog.sh
new file mode 100755
index 0000000..0bf756b
--- /dev/null
+++ b/tests/queue-encryption-disk_keyprog.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# addd 2018-10-01 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/omtesting/.libs/omtesting")
+global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
+main_queue(queue.filename="mainq"
+ queue.type="disk"
+ queue.maxDiskSpace="4m"
+ queue.maxfilesize="1m"
+ queue.timeoutenqueue="300000"
+ queue.lowwatermark="5000"
+
+ queue.cry.provider="gcry"
+ queue.cry.keyprogram="./'$RSYSLOG_DYNNAME.keyprogram'"
+ queue.saveonshutdown="on"
+)
+
+template(name="outfmt" type="string"
+ string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+
+:omtesting:sleep 0 5000
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+echo '#!/bin/bash
+echo RSYSLOG-KEY-PROVIDER:0
+echo 16
+echo "1234567890123456"' >> $RSYSLOG_DYNNAME.keyprogram
+chmod +x $RSYSLOG_DYNNAME.keyprogram
+startup
+injectmsg 0 1000
+shutdown_immediate
+wait_shutdown
+echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool:
+ls -l ${RSYSLOG_DYNNAME}.spool
+check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0*
+exit_test
diff --git a/tests/queue-minbatch-queuefull.sh b/tests/queue-minbatch-queuefull.sh
new file mode 100755
index 0000000..afcf1a9
--- /dev/null
+++ b/tests/queue-minbatch-queuefull.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2019-01-14 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris - see https://github.com/rsyslog/rsyslog/issues/3513"
+export NUMMESSAGES=10000
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ queue.type="linkedList"
+ queue.size="2001"
+ queue.dequeuebatchsize="2001"
+ queue.mindequeuebatchsize="2001"
+ queue.minDequeueBatchSize.timeout="2000"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/queue-minbatch.sh b/tests/queue-minbatch.sh
new file mode 100755
index 0000000..408b700
--- /dev/null
+++ b/tests/queue-minbatch.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# added 2019-01-10 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+skip_platform "SunOS" "This test currently does not work on Solaris - see https://github.com/rsyslog/rsyslog/issues/3513"
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ queue.type="linkedList"
+ queue.mindequeuebatchsize="20"
+ queue.minDequeueBatchSize.timeout="30000" # 30 sec
+ file="'$RSYSLOG_OUT_LOG'")
+'
+#
+# Note: this test is a bit tricky, as we depend on timeouts. That in turn
+# calls for trouble with slow test machines. As we really want to test the
+# timeout itself, we need to find a way around. What we do is use pretty
+# timeout values, which should also work on slow machines. Of course, that
+# also means the test is pretty slow, but that's just how it is...
+# Note that we may still (hopefully very) occasional failures on some
+# CI machines with very high-load.
+#
+startup
+injectmsg 0 10
+printf '%s waiting a bit to ensure batch is not yet written\n' "$(tb_timestamp)"
+sleep 5
+# at this point in time, nothing must have been written and so the output
+# file must not even exist.
+check_file_not_exists $RSYSLOG_OUT_NAME
+printf '%s %s\n' "$(tb_timestamp)" "output file does not yet exist - GOOD!"
+printf '%s waiting on timeout\n' "$(tb_timestamp)"
+sleep 30
+printf '%s done waiting on timeout\n' "$(tb_timestamp)"
+wait_seq_check 0 9
+seq_check 0 9
+
+printf '%s injecting new messages and waiting for shutdown\n' "$(tb_timestamp)"
+injectmsg 10 20
+shutdown_when_empty
+wait_shutdown
+seq_check 0 29
+exit_test
diff --git a/tests/queue-persist-drvr.sh b/tests/queue-persist-drvr.sh
new file mode 100755
index 0000000..7f666d1
--- /dev/null
+++ b/tests/queue-persist-drvr.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# Test for queue data persisting at shutdown. The
+# plan is to start an instance, emit some data, do a relatively
+# fast shutdown and then re-start the engine to process the
+# remaining data.
+# added 2009-05-27 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+# uncomment for debugging support:
+echo testing memory queue persisting to disk, mode $1
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 1
+$MainMsgQueueSaveOnShutdown on
+$InputTCPServerRun '$TCPFLOOD_PORT'
+
+$ModLoad ../plugins/omtesting/.libs/omtesting
+
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueFilename mainq
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-queuemode.conf
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+
+$IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf
+'
+# prepare config
+echo \$MainMsgQueueType $1 > ${RSYSLOG_DYNNAME}work-queuemode.conf
+echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf
+
+# inject 5000 msgs, so that we do not hit the high watermark
+startup
+injectmsg 0 5000
+shutdown_immediate
+wait_shutdown
+check_mainq_spool
+
+# restart engine and have rest processed
+#remove delay
+echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf
+startup
+shutdown_when_empty # shut down rsyslogd when done processing messages
+./msleep 1000
+wait_shutdown
+# note: we need to permit duplicate messages, as due to the forced
+# shutdown some messages may be flagged as "unprocessed" while they
+# actually were processed. This is inline with rsyslog's philosophy
+# to better duplicate than loose messages. Duplicate messages are
+# permitted by the -d seq-check option.
+seq_check 0 4999 -d
+exit_test
diff --git a/tests/queue-persist.sh b/tests/queue-persist.sh
new file mode 100755
index 0000000..519aa0b
--- /dev/null
+++ b/tests/queue-persist.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Test for queue data persisting at shutdown. We use the actual driver
+# to carry out multiple tests with different queue modes
+# added 2009-05-27 by Rgerhards
+# This file is part of the rsyslog project, released ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/queue-persist-drvr.sh LinkedList
+. $srcdir/queue-persist-drvr.sh FixedArray
+# the disk test should not fail, however, the config is extreme and using
+# it more or less is a config error
+. $srcdir/queue-persist-drvr.sh Disk
+# we do not test Direct mode because this absolute can not work in direct mode
+# (maybe we should do a fail-type of test?)
diff --git a/tests/queue_warnmsg-oversize.sh b/tests/queue_warnmsg-oversize.sh
new file mode 100755
index 0000000..b3803e8
--- /dev/null
+++ b/tests/queue_warnmsg-oversize.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# add 2019-04-18 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'"
+ queue.type="linkedList" queue.size="500001")
+'
+
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "warning.*queue.size=500001 is very large"
+
+exit_test
diff --git a/tests/random.sh b/tests/random.sh
new file mode 100755
index 0000000..b074142
--- /dev/null
+++ b/tests/random.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Test if rsyslog survives sending truly random data to it...
+#
+# added 2010-04-01 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+# The random data will generate TCP framing error messages. We will
+# not clutter the test output with them. So we disable error messages
+# to stderr.
+$ErrorMessagesToStderr off
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%rawmsg%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+*.* /dev/null
+'
+startup
+# generate random data
+./randomgen -f $RSYSLOG_DYNNAME.random.data -s 100000
+ls -l $RSYSLOG_DYNNAME.random.data
+tcpflood -B -I $RSYSLOG_DYNNAME.random.data -c5 -C10
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+# we do not check anything yet, the point is if rsyslog survived ;)
+# TODO: check for exit message, but we'll notice an abort anyhow, so not that important
+exit_test
diff --git a/tests/randomgen.c b/tests/randomgen.c
new file mode 100644
index 0000000..046ca1a
--- /dev/null
+++ b/tests/randomgen.c
@@ -0,0 +1,130 @@
+/* generates random data for later use in test cases. Of course,
+ * we could generate random data during the testcase itself, but
+ * the core idea is that we record the random data so that we have
+ * a chance to reproduce a problem should it occur. IMHO this
+ * provides the best compromise, by a) having randomness but
+ * b) knowing what was used during the test.
+ *
+ * Params
+ * -f output file name (stdout if not given)
+ * -s size of test data, plain number is size in k, 1MB default
+ * -u uses /dev/urandom instead of libc random number generator
+ * (when available). Note that this is usually much slower.
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#define EXIT_FAILURE 1
+
+static char *fileName = NULL; /* name of output file */
+static int tryUseURandom = 0; /* try to use /dev/urandom? */
+static long long fileSize = 1024*1024; /* file size in K, 1MB default */
+
+
+/* generate the random file. This code really can be improved (e.g. read /dev/urandom
+ * when available)
+ */
+static void
+genFile()
+{
+ long i;
+ FILE *fp;
+ FILE *rfp = NULL;
+
+ if(fileName == NULL) {
+ fp = stdout;
+ } else {
+ if((fp = fopen(fileName, "w")) == NULL) {
+ perror(fileName);
+ }
+ }
+
+ /* try to use /dev/urandom, if available */
+ if(tryUseURandom)
+ rfp = fopen("/dev/urandom", "r");
+
+ if(rfp == NULL) {
+ /* fallback, use libc random number generator */
+ for(i = 0 ; i < fileSize ; ++i) {
+ if(fputc((char) rand(), fp) == EOF) {
+ perror(fileName);
+ exit(1);
+ }
+ }
+ } else {
+ /* use /dev/urandom */
+ printf("using /dev/urandom");
+ for(i = 0 ; i < fileSize ; ++i) {
+ if(fputc(fgetc(rfp), fp) == EOF) {
+ perror(fileName);
+ exit(1);
+ }
+ }
+ }
+
+ if(fileName != NULL)
+ fclose(fp);
+}
+
+
+/* Run the test.
+ * rgerhards, 2009-04-03
+ */
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int opt;
+
+ srand(time(NULL)); /* seed is good enough for our needs */
+
+ while((opt = getopt(argc, argv, "f:s:u")) != -1) {
+ switch (opt) {
+ case 'f': fileName = optarg;
+ break;
+ case 's': fileSize = atol(optarg) * 1024;
+ break;
+ case 'u': tryUseURandom = 1;
+ break;
+ default: printf("invalid option '%c' or value missing - terminating...\n", opt);
+ exit (1);
+ break;
+ }
+ }
+
+ printf("generating random data file '%s' of %ldkb - may take a short while...\n",
+ fileName, (long) (fileSize / 1024));
+ genFile();
+
+ exit(ret);
+}
diff --git a/tests/rawmsg-after-pri.sh b/tests/rawmsg-after-pri.sh
new file mode 100755
index 0000000..30470d4
--- /dev/null
+++ b/tests/rawmsg-after-pri.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(type="string" name="outfmt" string="%rawmsg-after-pri%\n")
+if $syslogfacility-text == "local0" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -P 129
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # and wait for it to terminate
+NUMLINES=$(grep -c "^Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:$" $RSYSLOG_OUT_LOG 2>/dev/null)
+
+if [ -z $NUMLINES ]; then
+ echo "ERROR: output file seems not to exist"
+ ls -l $RSYSLOG_OUT_LOG
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+else
+ if [ ! $NUMLINES -eq 1 ]; then
+ echo "ERROR: output format does not match expectation"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+ fi
+fi
+exit_test
diff --git a/tests/rcvr_fail_restore.sh b/tests/rcvr_fail_restore.sh
new file mode 100755
index 0000000..53dd891
--- /dev/null
+++ b/tests/rcvr_fail_restore.sh
@@ -0,0 +1,168 @@
+#!/bin/bash
+# Copyright (C) 2011 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test does not work on FreeBSD - problems with os utility option switches"
+#
+# STEP1: start both instances and send 1000 messages.
+# Note: receiver is instance 1, sender instance 2.
+#
+# start up the instances. Note that the environment settings can be changed to
+# set instance-specific debugging parameters!
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="log2"
+echo starting receiver
+generate_conf
+add_conf '
+# then SENDER sends to this port (not tcpflood!)
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" ./'$RSYSLOG_OUT_LOG';outfmt
+'
+startup
+export PORT_RCVR="$TCPFLOOD_PORT"
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+#valgrind="valgrind"
+echo starting sender
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+$WorkDirectory '$RSYSLOG_DYNNAME'.spool
+$MainMsgQueueSize 2000
+$MainMsgQueueLowWaterMark 800
+$MainMsgQueueHighWaterMark 1000
+$MainMsgQueueDequeueBatchSize 1
+$MainMsgQueueMaxFileSize 1g
+$MainMsgQueueWorkerThreads 1
+$MainMsgQueueFileName mainq
+
+# we use the shortest resume interval a) to let the test not run too long
+# and b) make sure some retries happen before the reconnect
+$ActionResumeInterval 1
+$ActionSendResendLastMsgOnReconnect on
+$ActionResumeRetryCount -1
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+# re-set params so that new instances do not thrash it...
+#unset RSYSLOG_DEBUG
+#unset RSYSLOG_DEBUGLOG
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 1000
+wait_queueempty
+./msleep 1000 # let things settle down a bit
+
+#
+# Step 2: shutdown receiver, then send some more data, which then
+# needs to go into the queue.
+#
+echo step 2
+
+shutdown_when_empty
+wait_shutdown
+
+injectmsg2 1001 10000
+./msleep 3000 # make sure some retries happen (retry interval is set to 3 second)
+get_mainqueuesize 2
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+#
+# Step 3: restart receiver, wait that the sender drains its queue
+$InputTCPServerRun '$PORT_RCVR'
+#
+echo step 3
+#export RSYSLOG_DEBUGLOG="log2"
+generate_conf
+add_conf '
+# then SENDER sends to this port (not tcpflood!)
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="'$PORT_RCVR'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" ./'$RSYSLOG_OUT_LOG';outfmt
+'
+startup
+echo waiting for sender to drain queue [may need a short while]
+wait_queueempty 2
+ls -l ${RSYSLOG_DYNNAME}.spool
+OLDFILESIZE=$(stat -c%s ${RSYSLOG_DYNNAME}.spool/mainq.00000001)
+echo file size to expect is $OLDFILESIZE
+
+
+#
+# Step 4: send new data. Queue files are not permitted to grow now
+# (but one file continuous to exist).
+#
+echo step 4
+injectmsg2 11001 10
+wait_queueempty 2
+
+# at this point, the queue file shall not have grown. Note
+# that we MUST NOT shut down the instance right now, because it
+# would clean up the queue files! So we need to do our checks
+# first (here!).
+ls -l ${RSYSLOG_DYNNAME}.spool
+NEWFILESIZE=$(stat -c%s ${RSYSLOG_DYNNAME}.spool/mainq.00000001)
+if [ $NEWFILESIZE != $OLDFILESIZE ]
+then
+ echo file sizes do not match, expected $OLDFILESIZE, actual $NEWFILESIZE
+ echo this means that data has been written to the queue file where it
+ echo no longer should be written.
+ # abort will happen below, because we must ensure proper system shutdown
+ # HOWEVER, during actual testing it may be useful to do an exit here (so
+ # that e.g. the debug log is pointed right at the correct spot).
+ # exit 1
+fi
+
+#
+# We now do an extra test (so this is two in one ;)) to see if the DA
+# queue can be reactivated after its initial shutdown. In essence, we
+# redo steps 2 and 3.
+#
+# Step 5: stop receiver again, then send some more data, which then
+# needs to go into the queue.
+#
+echo step 5
+echo "*** done primary test *** now checking if DA can be restarted"
+shutdown_when_empty
+wait_shutdown
+
+injectmsg2 11011 10000
+sleep 1 # we need to wait, otherwise we may be so fast that the receiver
+# comes up before we have finally suspended the action
+get_mainqueuesize 2
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+#
+# Step 6: restart receiver, wait that the sender drains its queue
+#
+echo step 6
+startup
+echo waiting for sender to drain queue [may need a short while]
+wait_queueempty 2
+ls -l ${RSYSLOG_DYNNAME}.spool
+
+#
+# Queue file size checks done. Now it is time to terminate the system
+# and see if everything could be received (the usual check, done here
+# for completeness, more or less as a bonus).
+#
+shutdown_when_empty 2
+wait_shutdown 2
+
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# now abort test if we need to (due to filesize predicate)
+if [ $NEWFILESIZE != $OLDFILESIZE ]; then
+ error_exit 1
+fi
+# do the final check
+seq_check 1 21010 -m 100
+exit_test
diff --git a/tests/relp_tls_certificate_not_found.sh b/tests/relp_tls_certificate_not_found.sh
new file mode 100755
index 0000000..50f6518
--- /dev/null
+++ b/tests/relp_tls_certificate_not_found.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# add 2017-09-21 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+
+module(load="../plugins/omrelp/.libs/omrelp")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+ruleset(name="ruleset") {
+ action(type="omrelp" target="127.0.0.1" port="10514" tls="on" tls.authMode="name" tls.caCert="tls-certs/ca.pem" tls.myCert="tls-certs/fake-cert.pem" tls.myPrivKey="tls-certs/fake-key.pem" tls.permittedPeer=["rsyslog-test-root-ca"])
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+grep "certificate file tls-certs/fake-cert.pem.*No such file" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message from missing input file not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/rfc5424parser-sp_at_msg_start.sh b/tests/rfc5424parser-sp_at_msg_start.sh
new file mode 100755
index 0000000..5f927ad
--- /dev/null
+++ b/tests/rfc5424parser-sp_at_msg_start.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# checks that in RFC5424 mode SP at beginning of MSG part is properly handled
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2019-05-17
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg%--END\n")
+
+if $syslogtag == "tag" then
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - - nosd-nosp'
+injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - [abc@123 a="b"] sd-nosp'
+injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - - nosd-sp'
+injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - [abc@123 a="b"] sd-sp'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='nosd-nosp--END
+sd-nosp--END
+ nosd-sp--END
+ sd-sp--END'
+cmp_exact
+exit_test
diff --git a/tests/rfc5424parser.sh b/tests/rfc5424parser.sh
new file mode 100755
index 0000000..a1f2081
--- /dev/null
+++ b/tests/rfc5424parser.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2013-11-22
+echo ===============================================================================
+echo \[rfc5424parser.sh\]: testing mmpstrucdata
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if $msg contains "msgnum" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+sleep 1
+tcpflood -m100 -y
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rs-cnum.sh b/tests/rs-cnum.sh
new file mode 100755
index 0000000..ea092ef
--- /dev/null
+++ b/tests/rs-cnum.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2018-04-04 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!var = cnum(15*3);
+
+template(name="outfmt" type="string" string="-%$!var%-\n")
+:syslogtag, contains, "tag" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+echo '-45-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rs-int2hex.sh b/tests/rs-int2hex.sh
new file mode 100755
index 0000000..c320c8b
--- /dev/null
+++ b/tests/rs-int2hex.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2018-04-04 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!var = int2hex(61);
+set $!var2 = int2hex(-13);
+
+template(name="outfmt" type="string" string="-%$!var%- -%$!var2%-\n")
+:syslogtag, contains, "tag" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+echo '-3d- -fffffffffffffff3-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rs-substring.sh b/tests/rs-substring.sh
new file mode 100755
index 0000000..f101298
--- /dev/null
+++ b/tests/rs-substring.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# add 2018-04-04 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!var = substring($msg, 3, 2);
+
+template(name="outfmt" type="string" string="-%$!var%-\n")
+:syslogtag, contains, "tag" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\""
+shutdown_when_empty
+wait_shutdown
+echo '-gn-' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rs_optimizer_pri.sh b/tests/rs_optimizer_pri.sh
new file mode 100755
index 0000000..178e4e8
--- /dev/null
+++ b/tests/rs_optimizer_pri.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Test for the RainerScript optimizer, folding of
+# syslogfacility/priority-text to prifilt. Unfortunately, we cannot yet
+# automatically detect if the optimizer does not correctly fold, but we
+# can at least detect if it segfaults or otherwise creates incorrect code.
+# This file is part of the rsyslog project, released under ASL 2.0
+# rgerhards, 2013-11-20
+echo ===============================================================================
+echo \[rs_optimizer_pri.sh\]: testing RainerScript PRI optimizer
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if $syslogfacility-text == "local4" then
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+sleep 1
+tcpflood -m100 # correct facility
+tcpflood -m100 -P175 # incorrect facility --> must be ignored
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rscript-config_enable-off-vg.sh b/tests/rscript-config_enable-off-vg.sh
new file mode 100755
index 0000000..900e926
--- /dev/null
+++ b/tests/rscript-config_enable-off-vg.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export DO_STOP=off
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ if $msg contains "msgnum:00000000" then {
+ include(text="stop" config.enabled=`echo $DO_STOP`)
+ }
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup_vg
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 9
+exit_test
diff --git a/tests/rscript-config_enable-on.sh b/tests/rscript-config_enable-on.sh
new file mode 100755
index 0000000..9b09d1b
--- /dev/null
+++ b/tests/rscript-config_enable-on.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# tests 'config.enabled="on"' -- default value is implicitly check
+# in all testbench tests and does not need its individual test
+# (actually it is here tested via template() and action() as well...
+# added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export DO_STOP=on
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then {
+ if $msg contains "msgnum:00000000" then {
+ include(text="stop" config.enabled=`echo $DO_STOP`)
+ }
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+seq_check 1 9
+exit_test
diff --git a/tests/rscript_backticks-vg.sh b/tests/rscript_backticks-vg.sh
new file mode 100755
index 0000000..56ab8fc
--- /dev/null
+++ b/tests/rscript_backticks-vg.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if `echo $DO_WORK` == "on" and $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+export DO_WORK=on
+startup_vg
+injectmsg 0 1000
+#tcpflood -m10
+shutdown_when_empty
+wait_shutdown_vg
+seq_check 0 999
+exit_test
diff --git a/tests/rscript_backticks_empty_envvar-vg.sh b/tests/rscript_backticks_empty_envvar-vg.sh
new file mode 100755
index 0000000..95d2038
--- /dev/null
+++ b/tests/rscript_backticks_empty_envvar-vg.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# added 2018-11-02 by rgerhards
+# see also https://github.com/rsyslog/rsyslog/issues/3006
+# released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+if `echo $DOES_NOT_EXIST` == "" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup_vg
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+content_check --regex "rsyslogd: .*start"
+exit_test
diff --git a/tests/rscript_bare_var_root-empty.sh b/tests/rscript_bare_var_root-empty.sh
new file mode 100755
index 0000000..48c8573
--- /dev/null
+++ b/tests/rscript_bare_var_root-empty.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# addd 2018-01-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="empty-%$!%-\n")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+
+ruleset(name="rs") {
+ set $. = $!;
+ set $! = $.;
+
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='empty--'
+echo "$EXPECTED" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "FAIL: $RSYSLOG_OUT_LOG content invalid:"
+ cat $RSYSLOG_OUT_LOG
+ echo "Expected:"
+ echo "$EXPECTED"
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/rscript_bare_var_root.sh b/tests/rscript_bare_var_root.sh
new file mode 100755
index 0000000..c7af208
--- /dev/null
+++ b/tests/rscript_bare_var_root.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# addd 2018-01-01 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!%\n")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs")
+
+ruleset(name="rs") {
+ set $!a = "TEST1";
+ set $.a = "TEST-overwritten";
+ set $! = $.;
+
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='{ "a": "TEST-overwritten" }'
+echo "$EXPECTED" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "FAIL: $RSYSLOG_OUT_LOG content invalid:"
+ cat $RSYSLOG_OUT_LOG
+ echo "Expected:"
+ echo "$EXPECTED"
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/rscript_compare-common.sh b/tests/rscript_compare-common.sh
new file mode 100755
index 0000000..71810c6
--- /dev/null
+++ b/tests/rscript_compare-common.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# added by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!result")
+ constant(value="\n")
+}
+set $!lower_nr = '$LOWER_VAL';
+set $!higher_nr = '$HIGHER_VAL';
+
+if $!lower_nr <= $!higher_nr
+ then { set $!result = "<= RIGHT"; }
+ else { set $!result = "<= WRONG"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+
+if $!lower_nr < $!higher_nr
+ then { set $!result = "< RIGHT"; }
+ else { set $!result = "< WRONG"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+
+if $!higher_nr >= $!lower_nr
+ then { set $!result = ">= RIGHT"; }
+ else { set $!result = ">= WRONG"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+
+if $!higher_nr > $!lower_nr
+ then { set $!result = "> RIGHT"; }
+ else { set $!result = "> WRONG"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+
+if $!higher_nr != $!lower_nr
+ then { set $!result = "!= RIGHT"; }
+ else { set $!result = "!= WRONG"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+
+if $!higher_nr == $!lower_nr
+ then { set $!result = "== WRONG"; }
+ else { set $!result = "== RIGHT"; }
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check '<= RIGHT'
+content_check '>= RIGHT'
+content_check '!= RIGHT'
+content_check '== RIGHT'
+content_check '< RIGHT'
+content_check '> RIGHT'
+exit_test
diff --git a/tests/rscript_compare_num-num-vg.sh b/tests/rscript_compare_num-num-vg.sh
new file mode 100755
index 0000000..f08a92d
--- /dev/null
+++ b/tests/rscript_compare_num-num-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='1'
+export HIGHER_VAL='2'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_num-num.sh b/tests/rscript_compare_num-num.sh
new file mode 100755
index 0000000..c3a75d8
--- /dev/null
+++ b/tests/rscript_compare_num-num.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='1'
+export HIGHER_VAL='2'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_num-numstr-vg.sh b/tests/rscript_compare_num-numstr-vg.sh
new file mode 100755
index 0000000..889f535
--- /dev/null
+++ b/tests/rscript_compare_num-numstr-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='1'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_num-numstr.sh b/tests/rscript_compare_num-numstr.sh
new file mode 100755
index 0000000..be510b1
--- /dev/null
+++ b/tests/rscript_compare_num-numstr.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='1'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_num-str-vg.sh b/tests/rscript_compare_num-str-vg.sh
new file mode 100755
index 0000000..334a6b2
--- /dev/null
+++ b/tests/rscript_compare_num-str-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='1'
+export HIGHER_VAL='"b"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_num-str.sh b/tests/rscript_compare_num-str.sh
new file mode 100755
index 0000000..5f2bc87
--- /dev/null
+++ b/tests/rscript_compare_num-str.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='1'
+export HIGHER_VAL='"b"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-num-vg.sh b/tests/rscript_compare_numstr-num-vg.sh
new file mode 100755
index 0000000..32f3686
--- /dev/null
+++ b/tests/rscript_compare_numstr-num-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"1"'
+export HIGHER_VAL='2'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-num.sh b/tests/rscript_compare_numstr-num.sh
new file mode 100755
index 0000000..31ec55e
--- /dev/null
+++ b/tests/rscript_compare_numstr-num.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"1"'
+export HIGHER_VAL='2'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-numstr-vg.sh b/tests/rscript_compare_numstr-numstr-vg.sh
new file mode 100755
index 0000000..6663f21
--- /dev/null
+++ b/tests/rscript_compare_numstr-numstr-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"1"'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-numstr.sh b/tests/rscript_compare_numstr-numstr.sh
new file mode 100755
index 0000000..b58fe78
--- /dev/null
+++ b/tests/rscript_compare_numstr-numstr.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"1"'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-str-vg.sh b/tests/rscript_compare_numstr-str-vg.sh
new file mode 100755
index 0000000..82d727b
--- /dev/null
+++ b/tests/rscript_compare_numstr-str-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"1"'
+export HIGHER_VAL='"abc"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_numstr-str.sh b/tests/rscript_compare_numstr-str.sh
new file mode 100755
index 0000000..509e36f
--- /dev/null
+++ b/tests/rscript_compare_numstr-str.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"1"'
+export HIGHER_VAL='"abc"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-num-vg.sh b/tests/rscript_compare_str-num-vg.sh
new file mode 100755
index 0000000..fe5e8e6
--- /dev/null
+++ b/tests/rscript_compare_str-num-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"-"'
+export HIGHER_VAL='1'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-num.sh b/tests/rscript_compare_str-num.sh
new file mode 100755
index 0000000..5c1e186
--- /dev/null
+++ b/tests/rscript_compare_str-num.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"-"'
+export HIGHER_VAL='1'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-numstr-vg.sh b/tests/rscript_compare_str-numstr-vg.sh
new file mode 100755
index 0000000..3c83884
--- /dev/null
+++ b/tests/rscript_compare_str-numstr-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"-"'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-numstr.sh b/tests/rscript_compare_str-numstr.sh
new file mode 100755
index 0000000..abffeed
--- /dev/null
+++ b/tests/rscript_compare_str-numstr.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"-"'
+export HIGHER_VAL='"2"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-str-vg.sh b/tests/rscript_compare_str-str-vg.sh
new file mode 100755
index 0000000..21a27a3
--- /dev/null
+++ b/tests/rscript_compare_str-str-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export LOWER_VAL='"a"'
+export HIGHER_VAL='"b"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_compare_str-str.sh b/tests/rscript_compare_str-str.sh
new file mode 100755
index 0000000..a7d8baf
--- /dev/null
+++ b/tests/rscript_compare_str-str.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export LOWER_VAL='"a"'
+export HIGHER_VAL='"b"'
+source ${srcdir:-.}/rscript_compare-common.sh
diff --git a/tests/rscript_contains.sh b/tests/rscript_contains.sh
new file mode 100755
index 0000000..7352946
--- /dev/null
+++ b/tests/rscript_contains.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# added 2012-09-14 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+if $msg contains "msgnum" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_eq.sh b/tests/rscript_eq.sh
new file mode 100755
index 0000000..150f88e
--- /dev/null
+++ b/tests/rscript_eq.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_eq.sh\]: testing rainerscript EQ statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum == "00005000" or
+ $!usr!msgnum == "00005001" or
+ $!usr!msgnum == "00005002" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 5000 5002
+exit_test
diff --git a/tests/rscript_eq_var.sh b/tests/rscript_eq_var.sh
new file mode 100755
index 0000000..987ab48
--- /dev/null
+++ b/tests/rscript_eq_var.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_eq.sh\]: testing rainerscript EQ statement comparing two variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "value";
+set $!var2 = "value";
+if $!var1 == $!var2 then {
+ set $!var2 = "bad";
+ if $!var1 == $!var2 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "value";
+set $.var2 = "value";
+if $.var1 == $.var2 then {
+ set $.var2 = "bad";
+ if $.var1 == $.var2 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "value";
+set $/var2 = "value";
+if $/var1 == $/var2 then {
+ set $/var2 = "bad";
+ if $/var1 == $/var2 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_exists-not1.sh b/tests/rscript_exists-not1.sh
new file mode 100755
index 0000000..90c433c
--- /dev/null
+++ b/tests/rscript_exists-not1.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+# ensure that in this test there is NO variable define at all
+if $msg contains "msgnum" then {
+ if exists($!p1!p2!val) then
+ set $!result = "on";
+ else
+ set $!result = "off";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='off'
+cmp_exact
+exit_test
diff --git a/tests/rscript_exists-not2.sh b/tests/rscript_exists-not2.sh
new file mode 100755
index 0000000..2044c3e
--- /dev/null
+++ b/tests/rscript_exists-not2.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+set $!somevar = "test"; # this makes matters a bit more complicated
+if $msg contains "msgnum" then {
+ if exists($!p1!p2!val) then
+ set $!result = "on";
+ else
+ set $!result = "off";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='off'
+cmp_exact
+exit_test
diff --git a/tests/rscript_exists-not3.sh b/tests/rscript_exists-not3.sh
new file mode 100755
index 0000000..9b90aa0
--- /dev/null
+++ b/tests/rscript_exists-not3.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+# ensure that in this test there is NO variable define at all
+if $msg contains "msgnum" then {
+ if exists($.p1!p2!val) then
+ set $!result = "on";
+ else
+ set $!result = "off";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='off'
+cmp_exact
+exit_test
diff --git a/tests/rscript_exists-not4.sh b/tests/rscript_exists-not4.sh
new file mode 100755
index 0000000..df4415e
--- /dev/null
+++ b/tests/rscript_exists-not4.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+set $.somevar = "test"; # this makes matters a bit more complicated
+if $msg contains "msgnum" then {
+ if not exists($.p1!p2!val) then
+ set $!result = "off";
+ else
+ set $!result = "on";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='off'
+cmp_exact
+exit_test
diff --git a/tests/rscript_exists-yes.sh b/tests/rscript_exists-yes.sh
new file mode 100755
index 0000000..ba8805e
--- /dev/null
+++ b/tests/rscript_exists-yes.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+set $!p1!p2!val="yes!";
+if $msg contains "msgnum" then {
+ if exists($!p1!p2!val) then
+ set $!result = "on";
+ else
+ set $!result = "off";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='on'
+cmp_exact
+exit_test
diff --git a/tests/rscript_exists-yes2.sh b/tests/rscript_exists-yes2.sh
new file mode 100755
index 0000000..ebd3445
--- /dev/null
+++ b/tests/rscript_exists-yes2.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# add 2020-10-02 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%!result%\n")
+set $.p1!p2!val="yes!";
+if $msg contains "msgnum" then {
+ if exists($.p1!p2!val) then
+ set $!result = "on";
+ else
+ set $!result = "off";
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ }
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='on'
+cmp_exact
+exit_test
diff --git a/tests/rscript_field-vg.sh b/tests/rscript_field-vg.sh
new file mode 100755
index 0000000..ac593ce
--- /dev/null
+++ b/tests/rscript_field-vg.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[rscript_field-vg.sh\]: testing rainerscript field\(\) function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup_vg
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_field.sh b/tests/rscript_field.sh
new file mode 100755
index 0000000..b16fca1
--- /dev/null
+++ b/tests/rscript_field.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_field.sh\]: testing rainerscript field\(\) function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_format_time.sh b/tests/rscript_format_time.sh
new file mode 100755
index 0000000..b0f53d7
--- /dev/null
+++ b/tests/rscript_format_time.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Added 2017-10-03 by Stephen Workman, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omstdout/.libs/omstdout")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# $DebugLevel 2
+
+set $!datetime!rfc3164 = format_time(1507165811, "date-rfc3164");
+set $!datetime!rfc3339 = format_time(1507165811, "date-rfc3339");
+
+set $!datetime!rfc3164Neg = format_time(-1507165811, "date-rfc3164");
+set $!datetime!rfc3339Neg = format_time(-1507165811, "date-rfc3339");
+
+set $!datetime!str1 = format_time("1507165811", "date-rfc3339");
+set $!datetime!strinv1 = format_time("ABC", "date-rfc3339");
+
+template(name="outfmt" type="string" string="%!datetime%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+local4.* :omstdout:;outfmt
+'
+
+startup
+tcpflood -m1 -y | sed 's|\r||'
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='{ "rfc3164": "Oct 5 01:10:11", "rfc3339": "2017-10-05T01:10:11Z", "rfc3164Neg": "Mar 29 22:49:49", "rfc3339Neg": "1922-03-29T22:49:49Z", "str1": "2017-10-05T01:10:11Z", "strinv1": "ABC" }'
+
+# FreeBSD's cmp does not support reading from STDIN
+cmp <(echo "$EXPECTED") $RSYSLOG_OUT_LOG
+
+if [[ $? -ne 0 ]]; then
+ printf 'Invalid function output detected!\n'
+ printf "Expected: $EXPECTED\n"
+ printf 'Got: '
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rscript_ge.sh b/tests/rscript_ge.sh
new file mode 100755
index 0000000..489daa2
--- /dev/null
+++ b/tests/rscript_ge.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_ge.sh\]: testing rainerscript GE statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum >= "00005000" then
+ stop
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_ge_var.sh b/tests/rscript_ge_var.sh
new file mode 100755
index 0000000..f71e1d4
--- /dev/null
+++ b/tests/rscript_ge_var.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_ge.sh\]: testing rainerscript GE statement for two JSON variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "42";
+set $!var2 = "42";
+set $!var3 = "41";
+if $!var1 >= $!var2 and $!var1 >= $!var3 then {
+ if $!var3 >= $!var1 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ unset $!var3;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "42";
+set $.var2 = "42";
+set $.var3 = "41";
+if $.var1 >= $.var2 and $.var1 >= $.var3 then {
+ if $.var3 >= $.var1 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ unset $.var3;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "42";
+set $/var2 = "42";
+set $/var3 = "41";
+if $/var1 >= $/var2 and $/var1 >= $/var3 then {
+ if $/var3 >= $/var1 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ unset $/var3;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_get_property-vg.sh b/tests/rscript_get_property-vg.sh
new file mode 100755
index 0000000..5832373
--- /dev/null
+++ b/tests/rscript_get_property-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_get_property.sh
diff --git a/tests/rscript_get_property.sh b/tests/rscript_get_property.sh
new file mode 100755
index 0000000..03302bc
--- /dev/null
+++ b/tests/rscript_get_property.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%$!%\n")
+template(name="outlocal" type="string" string="%$.%\n")
+
+if $msg contains "msgnum" then {
+ set $.ret = parse_json("{\"offsets\": [ { \"a\": 9, \"b\": 0, \"c\": \"boo\", \"d\": null },\
+ { \"a\": 9, \"b\": 3, \"c\": null, \"d\": null } ],\
+ \"booltest\": true,\
+ \"int64\": 1234567890,\
+ \"nulltest\": null,\
+ \"double\": 12345.67890,\
+ \"foo\": 3, \"bar\": 28 }", "\$!parsed");
+
+ if $.ret == 0 then {
+ # set up some locals
+ set $!foo!bar = 3;
+ set $.index = "1";
+ set $.test = "a";
+
+ # evaluate
+ set $.res1 = get_property($!parsed!offsets, $.index);
+ set $.res2 = get_property($!parsed!offsets[1], $.test);
+ reset $.test = "bar";
+ set $.res3 = get_property($!foo, $.test);
+ reset $.index = 5;
+ set $.res4 = get_property($!parsed!offsets, $.index);
+ set $.key = "test";
+ set $.res5 = get_property($., $.key);
+ reset $.key = "foo";
+ set $.res6 = get_property($!, $.key);
+ set $.res7 = get_property($!foo, "bar");
+ reset $.key = "ar";
+ set $.res8 = get_property($!foo, "b" & $.key);
+ set $.res9 = get_property($!foo!bar, "");
+ reset $.key = "";
+ set $.res10 = get_property($!foo!bar, $.key);
+ set $.res11 = get_property($!parsed!booltest, "");
+ reset $.key = "int64";
+ set $.res12 = get_property($!parsed, $.key);
+ reset $.key = "nulltest";
+ set $.res13 = get_property($!parsed, $.key);
+ reset $.key = "double";
+ set $.res14 = get_property($!parsed, $.key);
+ set $.res15 = get_property($msg, "");
+ set $.res16 = get_property("string literal", "");
+
+ # output result
+ unset $.key;
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outlocal")
+ }
+}
+'
+
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED='{ "parsed": { "offsets": [ { "a": 9, "b": 0, "c": "boo", "d": null }, { "a": 9, "b": 3, "c": null, "d": null } ], "booltest": true, "int64": 1234567890, "nulltest": null, "double": 12345.67890, "foo": 3, "bar": 28 }, "foo": { "bar": 3 } }
+{ "ret": 0, "index": 5, "test": "bar", "res1": { "a": 9, "b": 3, "c": null, "d": null }, "res2": 9, "res3": 3, "res4": "", "res5": "bar", "res6": { "bar": 3 }, "res7": 3, "res8": 3, "res9": 3, "res10": 3, "res11": 1, "res12": 1234567890, "res13": "", "res14": 12345.678900000001, "res15": " msgnum:00000000:", "res16": "" }'
+cmp_exact
+
+exit_test
diff --git a/tests/rscript_gt.sh b/tests/rscript_gt.sh
new file mode 100755
index 0000000..9559ca0
--- /dev/null
+++ b/tests/rscript_gt.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_gt.sh\]: testing rainerscript GT statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum > "00004999" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 5000 7999
+exit_test
diff --git a/tests/rscript_gt_var.sh b/tests/rscript_gt_var.sh
new file mode 100755
index 0000000..1553182
--- /dev/null
+++ b/tests/rscript_gt_var.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_gt.sh\]: testing rainerscript GT statement for two JSON variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "43";
+set $!var2 = "42";
+if $!var1 > $!var2 then {
+ if $!var2 > $!var1 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "43";
+set $.var2 = "42";
+if $.var1 > $.var2 then {
+ if $.var2 > $.var1 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "43";
+set $/var2 = "42";
+if $/var1 > $/var2 then {
+ if $/var2 > $/var1 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_hash32-vg.sh b/tests/rscript_hash32-vg.sh
new file mode 100755
index 0000000..2114682
--- /dev/null
+++ b/tests/rscript_hash32-vg.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2018-02-07 by Harshvardhan Shrivastava
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \rscript_hash32.sh\]: test for hash32 and hash64mod script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmhash/.libs/fmhash")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.hash_no_1 = hash32("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e");
+set $.hash_no_2 = hash32mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -m 20
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+. $srcdir/diag.sh content-pattern-check "^\(746581550 - 50\|3889673532 - 32\)$"
+exit_test
diff --git a/tests/rscript_hash32.sh b/tests/rscript_hash32.sh
new file mode 100755
index 0000000..b4582de
--- /dev/null
+++ b/tests/rscript_hash32.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2018-02-07 by Harshvardhan Shrivastava
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \rscript_hash32.sh\]: test for hash32 and hash64mod script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmhash/.libs/fmhash")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.hash_no_1 = hash32("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e");
+set $.hash_no_2 = hash32mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 20
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+. $srcdir/diag.sh content-pattern-check "^\(746581550 - 50\|3889673532 - 32\)$"
+exit_test
diff --git a/tests/rscript_hash64-vg.sh b/tests/rscript_hash64-vg.sh
new file mode 100755
index 0000000..13fb2ee
--- /dev/null
+++ b/tests/rscript_hash64-vg.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2018-02-07 by Harshvardhan Shrivastava
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \rscript_hash64.sh\]: test for hash64 and hash64mod script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmhash/.libs/fmhash")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.hash_no_1 = hash64("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e");
+set $.hash_no_2 = hash64mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -m 20
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+. $srcdir/diag.sh content-pattern-check "^\(-2574714428477944902 - 14\|-50452361579464591 - 25\)$"
+exit_test
diff --git a/tests/rscript_hash64.sh b/tests/rscript_hash64.sh
new file mode 100755
index 0000000..7b3e7c5
--- /dev/null
+++ b/tests/rscript_hash64.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2018-02-07 by Harshvardhan Shrivastava
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \rscript_hash64.sh\]: test for hash64 and hash64mod script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmhash/.libs/fmhash")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.hash_no_1 = hash64("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e");
+set $.hash_no_2 = hash64mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 20
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+. $srcdir/diag.sh content-pattern-check "^\(-2574714428477944902 - 14\|-50452361579464591 - 25\)$"
+exit_test
diff --git a/tests/rscript_http_request-vg.sh b/tests/rscript_http_request-vg.sh
new file mode 100755
index 0000000..3584e47
--- /dev/null
+++ b/tests/rscript_http_request-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export TB_TEST_MAX_RUNTIME=1500
+source ${srcdir:-.}/rscript_http_request.sh
diff --git a/tests/rscript_http_request.sh b/tests/rscript_http_request.sh
new file mode 100755
index 0000000..0e46ade
--- /dev/null
+++ b/tests/rscript_http_request.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# add 2017-12-01 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+rsyslog_testbench_test_url_access http://testbench.rsyslog.com/testbench/echo-get.php
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/fmhttp/.libs/fmhttp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# for debugging the test itself:
+#template(name="outfmt" type="string" string="%$!%: :%$.%: %rawmsg%\n")
+template(name="outfmt" type="string" string="%$!%\n")
+
+if $msg contains "msgnum:" then {
+ set $.url = "http://testbench.rsyslog.com/testbench/echo-get.php?content=" & ltrim($msg);
+ set $!reply = http_request($.url);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+tcpflood -m10
+wait_file_lines $RSYSLOG_OUT_LOG 10 200
+shutdown_when_empty
+wait_shutdown
+
+# check for things that look like http failures
+if grep -q "DOCTYPE" "$RSYSLOG_OUT_LOG" ; then
+ printf 'SKIP: looks like we have problems with the upstream http server:\n'
+ cat -n "$RSYSLOG_OUT_LOG"
+ printf '\n'
+ error_exit 177
+fi
+
+export EXPECTED='{ "reply": "msgnum:00000000:" }
+{ "reply": "msgnum:00000001:" }
+{ "reply": "msgnum:00000002:" }
+{ "reply": "msgnum:00000003:" }
+{ "reply": "msgnum:00000004:" }
+{ "reply": "msgnum:00000005:" }
+{ "reply": "msgnum:00000006:" }
+{ "reply": "msgnum:00000007:" }
+{ "reply": "msgnum:00000008:" }
+{ "reply": "msgnum:00000009:" }'
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
+
diff --git a/tests/rscript_int2Hex.sh b/tests/rscript_int2Hex.sh
new file mode 100755
index 0000000..9ff5e26
--- /dev/null
+++ b/tests/rscript_int2Hex.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# add 2017-02-09 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!ip!v0 = int2hex("");
+set $!ip!v1 = int2hex("0");
+set $!ip!v2 = int2hex("1");
+set $!ip!v4 = int2hex("375894");
+set $!ip!v6 = int2hex("16");
+set $!ip!v8 = int2hex("4294967295");
+
+set $!ip!e1 = int2hex("a");
+
+template(name="outfmt" type="string" string="%!ip%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='{ "v0": "0", "v1": "0", "v2": "1", "v4": "5bc56", "v6": "10", "v8": "ffffffff", "e1": "NAN" }'
+cmp_exact
+exit_test
diff --git a/tests/rscript_ipv42num.sh b/tests/rscript_ipv42num.sh
new file mode 100755
index 0000000..25a5a3d
--- /dev/null
+++ b/tests/rscript_ipv42num.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# add 2017-02-09 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# in pre 8.1907.0 versions of rsyslog the code was misspelled as
+# "ip42num" (missing "v"). We check this is still supported as alias
+set $!ip!v0 = ip42num("0.0.0.0");
+
+# use correct function name
+set $!ip!v1 = ipv42num("0.0.0.0");
+set $!ip!v2 = ipv42num("0.0.0.1");
+set $!ip!v3 = ipv42num("0.0.1.0");
+set $!ip!v4 = ipv42num("0.1.0.0");
+set $!ip!v5 = ipv42num("1.0.0.0");
+set $!ip!v6 = ipv42num("0.0.0.135");
+set $!ip!v7 = ipv42num("1.1.1.1");
+set $!ip!v8 = ipv42num("225.33.1.10");
+set $!ip!v9 = ipv42num("172.0.0.1");
+set $!ip!v10 = ipv42num("255.255.255.255");
+set $!ip!v11 = ipv42num("1.0.3.45 ");
+set $!ip!v12 = ipv42num(" 0.0.0.1");
+set $!ip!v13 = ipv42num(" 0.0.0.1 ");
+
+set $!ip!e1 = ipv42num("a");
+set $!ip!e2 = ipv42num("");
+set $!ip!e3 = ipv42num("123.4.6.*");
+set $!ip!e4 = ipv42num("172.0.0.1.");
+set $!ip!e5 = ipv42num("172.0.0..1");
+set $!ip!e6 = ipv42num(".172.0.0.1");
+set $!ip!e7 = ipv42num(".17 2.0.0.1");
+
+
+template(name="outfmt" type="string" string="%!ip%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+echo '{ "v0": 0, "v1": 0, "v2": 1, "v3": 256, "v4": 65536, "v5": 16777216, "v6": 135, "v7": 16843009, "v8": 3777036554, "v9": 2885681153, "v10": 4294967295, "v11": 16778029, "v12": 1, "v13": 1, "e1": -1, "e2": -1, "e3": -1, "e4": -1, "e5": -1, "e6": -1, "e7": -1 }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
+
diff --git a/tests/rscript_is_time.sh b/tests/rscript_is_time.sh
new file mode 100755
index 0000000..d0ca09d
--- /dev/null
+++ b/tests/rscript_is_time.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# Added 2017-12-16 by Stephen Workman, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omstdout/.libs/omstdout")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# $DebugLevel 2
+
+set $!result!date_auto_1 = is_time("Oct 5 01:10:11");
+set $!result!errno_date_auto_1 = script_error();
+set $!result!date_auto_2 = is_time("2017-10-05T01:10:11Z");
+set $!result!errno_date_auto_2 = script_error();
+set $!result!date_auto_3 = is_time("2017-10-05T01:10:11-03:00");
+set $!result!errno_date_auto_3 = script_error();
+set $!result!date_auto_4 = is_time("90210");
+set $!result!errno_date_auto_4 = script_error();
+
+set $!result!date_explicit_1 = is_time("Oct 5 01:10:11", "date-rfc3164");
+set $!result!errno_date_explicit_1 = script_error();
+set $!result!date_explicit_2 = is_time("2017-10-05T01:10:11Z", "date-rfc3339");
+set $!result!errno_date_explicit_2 = script_error();
+set $!result!date_explicit_3 = is_time("2017-10-05T01:10:11+04:00", "date-rfc3339");
+set $!result!errno_date_explicit_3 = script_error();
+set $!result!date_explicit_4 = is_time(90210, "date-unix");
+set $!result!errno_date_explicit_4 = script_error();
+set $!result!date_explicit_5 = is_time(-88, "date-unix");
+set $!result!errno_date_explicit_5 = script_error();
+set $!result!date_explicit_6 = is_time(0, "date-unix");
+set $!result!errno_date_explicit_6 = script_error();
+set $!result!date_explicit_7 = is_time("90210", "date-unix");
+set $!result!errno_date_explicit_7 = script_error();
+set $!result!date_explicit_8 = is_time("-88", "date-unix");
+set $!result!errno_date_explicit_8 = script_error();
+
+# Bad dates
+set $!result!date_fail_1 = is_time("Oct 88 01:10:11");
+set $!result!errno_date_fail_1 = script_error();
+set $!result!date_fail_2 = is_time("not at all a date");
+set $!result!errno_date_fail_2 = script_error();
+
+# Wrong format
+set $!result!date_fail_3 = is_time("Oct 5 01:10:11", "date-rfc3339");
+set $!result!errno_date_fail_3 = script_error();
+set $!result!date_fail_4 = is_time("2017-10-05T01:10:11Z", "date-rfc3164");
+set $!result!errno_date_fail_4 = script_error();
+set $!result!date_fail_5 = is_time("Oct 5 01:10:11", "date-unix");
+set $!result!errno_date_fail_5 = script_error();
+
+# Invalid format
+set $!result!date_fail_6 = is_time("90210", "date-spoonix");
+set $!result!errno_date_fail_6 = script_error();
+
+template(name="outfmt" type="string" string="%!result%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+local4.* :omstdout:;outfmt
+'
+
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+
+# Our fixed and calculated expected results
+export EXPECTED='{ "date_auto_1": 1, "errno_date_auto_1": 0, "date_auto_2": 1, "errno_date_auto_2": 0, "date_auto_3": 1, "errno_date_auto_3": 0, "date_auto_4": 1, "errno_date_auto_4": 0, "date_explicit_1": 1, "errno_date_explicit_1": 0, "date_explicit_2": 1, "errno_date_explicit_2": 0, "date_explicit_3": 1, "errno_date_explicit_3": 0, "date_explicit_4": 1, "errno_date_explicit_4": 0, "date_explicit_5": 1, "errno_date_explicit_5": 0, "date_explicit_6": 1, "errno_date_explicit_6": 0, "date_explicit_7": 1, "errno_date_explicit_7": 0, "date_explicit_8": 1, "errno_date_explicit_8": 0, "date_fail_1": 0, "errno_date_fail_1": 1, "date_fail_2": 0, "errno_date_fail_2": 1, "date_fail_3": 0, "errno_date_fail_3": 1, "date_fail_4": 0, "errno_date_fail_4": 1, "date_fail_5": 0, "errno_date_fail_5": 1, "date_fail_6": 0, "errno_date_fail_6": 1 }'
+
+# FreeBSD's cmp does not support reading from STDIN
+cmp <(echo "$EXPECTED") $RSYSLOG_OUT_LOG
+
+if [[ $? -ne 0 ]]; then
+ printf "Invalid function output detected!\n"
+ printf "Expected: $EXPECTED\n"
+ printf "Got: "
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rscript_le.sh b/tests/rscript_le.sh
new file mode 100755
index 0000000..406a0a3
--- /dev/null
+++ b/tests/rscript_le.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_le.sh\]: testing rainerscript LE statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum <= "00005000" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 5000
+exit_test
diff --git a/tests/rscript_le_var.sh b/tests/rscript_le_var.sh
new file mode 100755
index 0000000..6abc933
--- /dev/null
+++ b/tests/rscript_le_var.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_le.sh\]: testing rainerscript LE statement for two JSON variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "42";
+set $!var2 = "42";
+set $!var3 = "43";
+if $!var1 <= $!var2 and $!var1 <= $!var3 then {
+ if $!var3 <= $!var1 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ unset $!var3;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "42";
+set $.var2 = "42";
+set $.var3 = "43";
+if $.var1 <= $.var2 and $.var1 <= $.var3 then {
+ if $.var3 <= $.var1 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ unset $.var3;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "42";
+set $/var2 = "42";
+set $/var3 = "43";
+if $/var1 <= $/var2 and $/var1 <= $/var3 then {
+ if $/var3 <= $/var1 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ unset $/var3;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_lt.sh b/tests/rscript_lt.sh
new file mode 100755
index 0000000..e861f74
--- /dev/null
+++ b/tests/rscript_lt.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_lt.sh\]: testing rainerscript LT statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum < "00005000" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_lt_var.sh b/tests/rscript_lt_var.sh
new file mode 100755
index 0000000..9514a6e
--- /dev/null
+++ b/tests/rscript_lt_var.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_lt.sh\]: testing rainerscript LT statement for two JSON variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "41";
+set $!var2 = "42";
+if $!var1 < $!var2 then {
+ if $!var2 < $!var1 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "41";
+set $.var2 = "42";
+if $.var1 < $.var2 then {
+ if $.var2 < $.var1 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "41";
+set $/var2 = "42";
+if $/var1 < $/var2 then {
+ if $/var2 < $/var1 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_ne.sh b/tests/rscript_ne.sh
new file mode 100755
index 0000000..21260a2
--- /dev/null
+++ b/tests/rscript_ne.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_ne.sh\]: testing rainerscript NE statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if $!usr!msgnum != "00005000" and
+ $!usr!msgnum != "00005001" and
+ $!usr!msgnum != "00005002" then
+ set $!usr!write = 0;
+ else
+ set $!usr!write = 1;
+ if $!usr!write == 1 then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 5000 5002
+exit_test
diff --git a/tests/rscript_ne_var.sh b/tests/rscript_ne_var.sh
new file mode 100755
index 0000000..bbf8664
--- /dev/null
+++ b/tests/rscript_ne_var.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# added 2014-01-17 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_ne.sh\]: testing rainerscript NE statement for two JSON variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+set $!var1 = "value1";
+set $!var2 = "value2";
+if $!var1 != $!var2 then {
+ set $!var1 = "value";
+ set $!var2 = "value";
+ if $!var1 != $!var2 then {
+ # Failure
+ stop
+ } else {
+ unset $!var1;
+ unset $!var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $.var1 = "value1";
+set $.var2 = "value2";
+if $.var1 != $.var2 then {
+ set $.var1 = "value";
+ set $.var2 = "value";
+ if $.var1 != $.var2 then {
+ # Failure
+ stop
+ } else {
+ unset $.var1;
+ unset $.var2;
+ }
+} else {
+ # Failure
+ stop
+}
+set $/var1 = "value1";
+set $/var2 = "value2";
+if $/var1 != $/var2 then {
+ set $/var1 = "value";
+ set $/var2 = "value";
+ if $/var1 != $/var2 then {
+ # Failure
+ stop
+ } else {
+ unset $/var1;
+ unset $/var2;
+ }
+} else {
+ # Failure
+ stop
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 0
+exit_test
diff --git a/tests/rscript_num2ipv4.sh b/tests/rscript_num2ipv4.sh
new file mode 100755
index 0000000..9be21f2
--- /dev/null
+++ b/tests/rscript_num2ipv4.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# add 2017-02-09 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/fmhttp/.libs/fmhttp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!ip!v0 = num2ipv4("");
+set $!ip!v1 = num2ipv4("0");
+set $!ip!v2 = num2ipv4("1");
+set $!ip!v3 = num2ipv4("256");
+set $!ip!v4 = num2ipv4("65536");
+set $!ip!v5 = num2ipv4("16777216");
+set $!ip!v6 = num2ipv4("135");
+set $!ip!v7 = num2ipv4("16843009");
+set $!ip!v8 = num2ipv4("3777036554");
+set $!ip!v9 = num2ipv4("2885681153");
+set $!ip!v10 = num2ipv4("4294967295");
+
+set $!ip!e1 = num2ipv4("a");
+set $!ip!e2 = num2ipv4("-123");
+set $!ip!e3 = num2ipv4("1725464567890");
+set $!ip!e4 = num2ipv4("4294967296");
+set $!ip!e5 = num2ipv4("2839.");
+
+
+template(name="outfmt" type="string" string="%!ip%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+echo '{ "v0": "0.0.0.0", "v1": "0.0.0.0", "v2": "0.0.0.1", "v3": "0.0.1.0", "v4": "0.1.0.0", "v5": "1.0.0.0", "v6": "0.0.0.135", "v7": "1.1.1.1", "v8": "225.33.1.10", "v9": "172.0.0.1", "v10": "255.255.255.255", "e1": "-1", "e2": "-1", "e3": "-1", "e4": "-1", "e5": "-1" }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/rscript_number_comparison_LE-vg.sh b/tests/rscript_number_comparison_LE-vg.sh
new file mode 100755
index 0000000..5493137
--- /dev/null
+++ b/tests/rscript_number_comparison_LE-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_number_comparison_LE.sh
diff --git a/tests/rscript_number_comparison_LE.sh b/tests/rscript_number_comparison_LE.sh
new file mode 100755
index 0000000..acb9865
--- /dev/null
+++ b/tests/rscript_number_comparison_LE.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!result")
+ constant(value="\n")
+}
+set $!lower_nr = 1111;
+set $!higher_nr = 2222;
+
+if $!lower_nr <= $!higher_nr
+ then { set $!result = "RIGHT"; }
+ else { set $!result = "WRONG"; }
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check 'RIGHT'
+exit_test
diff --git a/tests/rscript_number_comparison_LT.sh b/tests/rscript_number_comparison_LT.sh
new file mode 100755
index 0000000..5cb729a
--- /dev/null
+++ b/tests/rscript_number_comparison_LT.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# added 2022-01-27 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!result")
+ constant(value="\n")
+}
+set $!lower_nr = 1111;
+set $!higher_nr = 2222;
+
+if $!higher_nr < $!lower_nr
+ then { set $!result = "WRONG"; }
+ else { set $!result = "RIGHT"; }
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check 'RIGHT'
+exit_test
diff --git a/tests/rscript_optimizer1.sh b/tests/rscript_optimizer1.sh
new file mode 100755
index 0000000..342f62b
--- /dev/null
+++ b/tests/rscript_optimizer1.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_optimizer1.sh\]: testing rainerscript optimizer
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+/* tcpflood uses local4.=debug */
+if prifilt("syslog.*") then
+ stop # it actually does not matter what we do here
+else
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_parse_json-vg.sh b/tests/rscript_parse_json-vg.sh
new file mode 100755
index 0000000..275ca63
--- /dev/null
+++ b/tests/rscript_parse_json-vg.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%$!%\n")
+
+local4.* {
+ set $.ret = parse_json("{ \"c1\":\"data\" }", "\$!parsed");
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+
+startup_vg
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+
+export EXPECTED='{ "parsed": { "c1": "data" } }'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/rscript_parse_json.sh b/tests/rscript_parse_json.sh
new file mode 100755
index 0000000..db7bc22
--- /dev/null
+++ b/tests/rscript_parse_json.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%$!%\n")
+
+local4.* {
+ set $.ret = parse_json("{ \"c1\":\"data\" }", "\$!parsed");
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='{ "parsed": { "c1": "data" } }'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/rscript_parse_time.sh b/tests/rscript_parse_time.sh
new file mode 100755
index 0000000..633f270
--- /dev/null
+++ b/tests/rscript_parse_time.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+# Added 2017-10-28 by Stephen Workman, released under ASL 2.0
+
+# Because this script tests functionality that depends on the current date,
+# we cannot use static values for the expected results. They have to be
+# calculated. Also, because we cannot depend on the GNU version of the
+# 'date' command on all of our test systems (think FreeBSD, and Solaris),
+# we need a method of converting given date/time strings to UNIX timestamps.
+# For that we use an external Python 2.x script to do the job.
+. ${srcdir:=.}/diag.sh init
+
+getts="$PYTHON $srcdir/rscript_parse_time_get-ts.py"
+
+# Run the Python script's self-tests
+$getts selftest
+
+if [[ $? -ne 0 ]]; then
+ printf "Failed own self-test(s)!\n"
+ error_exit 1
+fi
+
+# Since the RFC 3164 date/time format does not include a year, we need to
+# try to "guess" an appropriate one based on the incoming date and the
+# current date. So, we'll use a reasonable spread of RFC 3164 date/time
+# strings to ensure that we test as much of our year "guessing" as
+# possible. Since this uses the CURRENT DATE (as in, the date this)
+# script was invoked, we need to calculate our expected results to
+# compare them with the values returned by the parse_time() RainerScript
+# function.
+rfc3164_1="Oct 5 01:10:11"
+rfc3164_1_r=$($getts "$rfc3164_1")
+
+rfc3164_2="Jan 31 13:00:00"
+rfc3164_2_r=$($getts "$rfc3164_2")
+
+rfc3164_3="Feb 28 14:35:00"
+rfc3164_3_r=$($getts "$rfc3164_3")
+
+rfc3164_4="Mar 1 14:00:00"
+rfc3164_4_r=$($getts "$rfc3164_4")
+
+rfc3164_5="Apr 3 15:00:00"
+rfc3164_5_r=$($getts "$rfc3164_5")
+
+rfc3164_6="May 5 16:00:00"
+rfc3164_6_r=$($getts "$rfc3164_6")
+
+rfc3164_7="Jun 11 03:00:00"
+rfc3164_7_r=$($getts "$rfc3164_7")
+
+rfc3164_8="Jul 15 05:00:00"
+rfc3164_8_r=$($getts "$rfc3164_8")
+
+rfc3164_9="Aug 17 08:00:00"
+rfc3164_9_r=$($getts "$rfc3164_9")
+
+rfc3164_10="Sep 20 18:00:00"
+rfc3164_10_r=$($getts "$rfc3164_10")
+
+rfc3164_11="Nov 23 19:00:00"
+rfc3164_11_r=$($getts "$rfc3164_11")
+
+rfc3164_12="Dec 25 20:00:00"
+rfc3164_12_r=$($getts "$rfc3164_12")
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omstdout/.libs/omstdout")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# $DebugLevel 2
+
+# RFC 3164 Parse Tests (using fixed input values - see above)
+set $!datetime!rfc3164_1 = parse_time("'"$rfc3164_1"'");
+set $!datetime!rfc3164_2 = parse_time("'"$rfc3164_2"'");
+set $!datetime!rfc3164_3 = parse_time("'"$rfc3164_3"'");
+set $!datetime!rfc3164_4 = parse_time("'"$rfc3164_4"'");
+set $!datetime!rfc3164_5 = parse_time("'"$rfc3164_5"'");
+set $!datetime!rfc3164_6 = parse_time("'"$rfc3164_6"'");
+set $!datetime!rfc3164_7 = parse_time("'"$rfc3164_7"'");
+set $!datetime!rfc3164_8 = parse_time("'"$rfc3164_8"'");
+set $!datetime!rfc3164_9 = parse_time("'"$rfc3164_9"'");
+set $!datetime!rfc3164_10 = parse_time("'"$rfc3164_10"'");
+set $!datetime!rfc3164_11 = parse_time("'"$rfc3164_11"'");
+set $!datetime!rfc3164_12 = parse_time("'"$rfc3164_12"'");
+
+# RFC 3339 Parse Tests (these provide their own year)
+set $!datetime!rfc3339 = parse_time("2017-10-05T01:10:11Z");
+set $!datetime!rfc3339tz1 = parse_time("2017-10-05T01:10:11+04:00");
+set $!datetime!rfc3339tz2 = parse_time("2017-10-05T01:10:11+00:00");
+
+# Test invalid date strings, these should return 0
+set $!datetime!inval1 = parse_time("not a date/time");
+set $!datetime!inval2 = parse_time("2017-10-05T01:10:11");
+set $!datetime!inval3 = parse_time("2017-SOMETHING: 42");
+
+template(name="outfmt" type="string" string="%!datetime%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+local4.* :omstdout:;outfmt
+'
+
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+
+# Our fixed and calculated expected results
+export EXPECTED='{ "rfc3164_1": '"$rfc3164_1_r"', "rfc3164_2": '"$rfc3164_2_r"', "rfc3164_3": '"$rfc3164_3_r"', "rfc3164_4": '"$rfc3164_4_r"', "rfc3164_5": '"$rfc3164_5_r"', "rfc3164_6": '"$rfc3164_6_r"', "rfc3164_7": '"$rfc3164_7_r"', "rfc3164_8": '"$rfc3164_8_r"', "rfc3164_9": '"$rfc3164_9_r"', "rfc3164_10": '"$rfc3164_10_r"', "rfc3164_11": '"$rfc3164_11_r"', "rfc3164_12": '"$rfc3164_12_r"', "rfc3339": 1507165811, "rfc3339tz1": 1507151411, "rfc3339tz2": 1507165811, "inval1": 0, "inval2": 0, "inval3": 0 }'
+
+# FreeBSD's cmp does not support reading from STDIN
+cmp <(echo "$EXPECTED") $RSYSLOG_OUT_LOG
+
+if [[ $? -ne 0 ]]; then
+ printf "Invalid function output detected!\n"
+ printf "Expected: $EXPECTED\n"
+ printf "Got: "
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rscript_parse_time_get-ts.py b/tests/rscript_parse_time_get-ts.py
new file mode 100644
index 0000000..f7e3787
--- /dev/null
+++ b/tests/rscript_parse_time_get-ts.py
@@ -0,0 +1,152 @@
+# call this via "python[3] script name"
+# Added 2017-11-05 by Stephen Workman, released under ASL 2.0
+
+#
+# Produces a UNIX timestamp representing the specified RFC 3164 date/time
+# string. Since this date/time format does not include a year, a simple
+# algorithm is used to "guess" an appropriate one and append it to the
+# date/time string to calculate a timestamp value.
+#
+# If the incoming date is within one month in the future (from now),
+# it is assumed that it's either for the current year, or the next
+# year (depending on whether it is December or not).
+# - For example:
+# * If today is December 13th 2017 and we get passed the date/time
+# string "Jan 4 01:00:00", we assume that it is for the next
+# year (2018).
+# * If today is October 5th 2017, and we get passed the date/time
+# string "Nov 5 01:10:11", we assume that it is for this year.
+# If the incoming date has a month "before" the current month, or does
+# not fall into the situation above, it's assumed it's from the past.
+# - For example:
+# * If today is July 10th 2017, and the incoming date is for
+# a time in April, the year is assumed to be 2017.
+# * If today is July 10th 2017, and the incoming date is for
+# a time in September, the year is assumed to be 2016.
+#
+
+import re
+import sys
+
+from datetime import datetime, timedelta
+
+err = 0
+
+# Make tests below a little easier to read.
+JAN = 1; FEB = 2; MAR = 3; APR = 4
+MAY = 5; JUN = 6; JUL = 7; AUG = 8
+SEP = 9; OCT = 10; NOV = 11; DEC = 12
+
+# Run the provided expression and compare its result with the
+# expected value. The function expects the expression to be
+# passed in as a string so it can be printed to the screen
+# as-is when there is an error.
+def do_test(expr, val):
+ global err
+
+ # Run the expression and record the result
+ result = eval(expr)
+
+ # Print a message identifying the failing "test"
+ if result != val:
+ print("Error: %s. Expected %4d, got %4d!" % (expr, val, result))
+ err += 1
+
+# Use a sliding 12-month window (offset by one month)
+# to determine the year that should be returned.
+# cy - Current Year
+# cm - Current Month
+# im - Incoming Month
+def estimate_year(cy, cm, im):
+ im += 12
+
+ if (im - cm) == 1:
+ if cm == 12 and im == 13:
+ return cy + 1
+
+ if (im - cm) > 13:
+ return cy - 1
+
+ return cy;
+
+# A quick and dirty unit test to validate that our
+# estimate_year() function is working as it should.
+def self_test():
+
+ # Where the incoming month is within one month
+ # in the future. Should be the NEXT year if
+ # the current date is in December, or the SAME
+ # year if it's not December.
+ do_test("estimate_year(2017, DEC, JAN)", 2018)
+ do_test("estimate_year(2017, NOV, DEC)", 2017)
+ do_test("estimate_year(2017, OCT, NOV)", 2017)
+ do_test("estimate_year(2017, SEP, OCT)", 2017)
+ do_test("estimate_year(2017, AUG, SEP)", 2017)
+
+ # These tests validate months that are MORE than
+ # one month in the future OR are before the current
+ # month. If, numerically, the month comes after the
+ # current month, it's assumed to be for the year
+ # PRIOR, otherwise it's assumed to be from THIS year.
+ do_test("estimate_year(2017, NOV, JAN)", 2017)
+ do_test("estimate_year(2017, NOV, FEB)", 2017)
+ do_test("estimate_year(2017, AUG, OCT)", 2016)
+ do_test("estimate_year(2017, AUG, MAR)", 2017)
+ do_test("estimate_year(2017, APR, JUL)", 2016)
+
+ do_test("estimate_year(2017, AUG, JAN)", 2017)
+ do_test("estimate_year(2017, APR, FEB)", 2017)
+
+ # Additional validations based on what was described
+ # above.
+ do_test("estimate_year(2017, JAN, DEC)", 2016)
+ do_test("estimate_year(2017, JAN, FEB)", 2017)
+ do_test("estimate_year(2017, JAN, MAR)", 2016)
+
+# Convert a datetime.timedelta object to a UNIX timestamp
+def get_total_seconds(dt):
+ # timedelta.total_seconds() wasn't added until
+ # Python 2.7, which CentOS 6 doesn't have.
+
+ if hasattr(timedelta, "total_seconds"):
+ return dt.total_seconds()
+ return dt.seconds + dt.days * 24 * 3600
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print("Invalid number of arguments!")
+ sys.exit(1)
+
+ if sys.argv[1] == "selftest":
+ self_test()
+
+ # Exit with non-zero if there were failures,
+ # zero otherwise.
+ sys.exit(err)
+
+ months = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+
+ current_datetime = datetime.utcnow()
+
+ # The argument is expected to be an RFC 3164 timestamp
+ # such as "Oct 5 01:10:11".
+ incoming_datetime = sys.argv[1]
+
+ # Get the name of the month from the date/time string that was passed in
+ # and convert it to its ordinal number (1 for Jan, 10 for Oct, etc...)
+ incoming_month = re.search(r"^([^ ]+) ", incoming_datetime).group(1)
+ incoming_month = months.index(incoming_month)
+
+ # Assume a year for the date/time passed in based off of today's date.
+ estimated_year = estimate_year(
+ current_datetime.year,
+ current_datetime.month,
+ incoming_month
+ )
+
+ # Convert the date/time string (now with a year, e.g. "Oct 5 01:10:11 2017") to
+ # a python datetime object that we can use to calculate a UNIX timestamp
+ calculated_datetime = datetime.strptime("%s %d" % (incoming_datetime, estimated_year), "%b %d %H:%M:%S %Y")
+
+ # Convert the datetime object to a UNIX timestamp by subtracting it from the epoch
+ print(int( get_total_seconds(calculated_datetime - datetime(1970,1,1)) ))
diff --git a/tests/rscript_previous_action_suspended.sh b/tests/rscript_previous_action_suspended.sh
new file mode 100755
index 0000000..7bf1624
--- /dev/null
+++ b/tests/rscript_previous_action_suspended.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omtesting/.libs/omtesting")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+ruleset(name="output_writer") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+
+:msg, contains, "msgnum:" {
+ :omtesting:fail 2 0
+ if previous_action_suspended() then
+ call output_writer
+}
+'
+
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+seq_check 1 9
+exit_test
diff --git a/tests/rscript_prifilt.sh b/tests/rscript_prifilt.sh
new file mode 100755
index 0000000..af546d0
--- /dev/null
+++ b/tests/rscript_prifilt.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_prifilt.sh\]: testing rainerscript prifield\(\) function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+/* tcpflood uses local4.=debug, we use a bit more generic filter */
+if prifilt("local4.*") then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_privdropgroup.sh b/tests/rscript_privdropgroup.sh
new file mode 100755
index 0000000..62c44f0
--- /dev/null
+++ b/tests/rscript_privdropgroup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2021-09-23 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.group.keepsupplemental="on" privdrop.group.name="'${TESTBENCH_TESTUSER[groupname]}'")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}"
+exit_test
diff --git a/tests/rscript_privdropgroupid.sh b/tests/rscript_privdropgroupid.sh
new file mode 100755
index 0000000..b1eade2
--- /dev/null
+++ b/tests/rscript_privdropgroupid.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2021-09-23 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.group.keepsupplemental="on" privdrop.group.id="'${TESTBENCH_TESTUSER[gid]}'")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}"
+exit_test
diff --git a/tests/rscript_privdropuser.sh b/tests/rscript_privdropuser.sh
new file mode 100755
index 0000000..5a91479
--- /dev/null
+++ b/tests/rscript_privdropuser.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2021-09-23 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.user.name="'${TESTBENCH_TESTUSER[username]}'")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}"
+exit_test
diff --git a/tests/rscript_privdropuserid.sh b/tests/rscript_privdropuserid.sh
new file mode 100755
index 0000000..3e66663
--- /dev/null
+++ b/tests/rscript_privdropuserid.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2021-09-23 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test currently does not work on Solaris."
+. $srcdir/privdrop_common.sh
+rsyslog_testbench_setup_testuser
+
+generate_conf
+add_conf '
+global(privdrop.user.id="'${TESTBENCH_TESTUSER[uid]}'")
+template(name="outfmt" type="list") {
+ property(name="msg" compressSpace="on")
+ constant(value="\n")
+}
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}"
+exit_test
diff --git a/tests/rscript_random.sh b/tests/rscript_random.sh
new file mode 100755
index 0000000..341fddb
--- /dev/null
+++ b/tests/rscript_random.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2015-06-22 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_random.sh\]: test for random-number-generator script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.random_no%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.random_no = random(10);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 20
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+. $srcdir/diag.sh content-pattern-check "^[0-9]$"
+exit_test
diff --git a/tests/rscript_re_extract.sh b/tests/rscript_re_extract.sh
new file mode 100755
index 0000000..fcfb385
--- /dev/null
+++ b/tests/rscript_re_extract.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2015-09-29 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_re_extract.sh\]: test re_extract rscript-fn
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="*Number is %$.number%*\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")'
+add_conf "
+set \$.number = re_extract(\$msg, '.* ([0-9]+)$', 0, 1, 'none');"
+add_conf '
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "*Number is 19597*"
+exit_test
diff --git a/tests/rscript_re_extract_i.sh b/tests/rscript_re_extract_i.sh
new file mode 100755
index 0000000..fb45277
--- /dev/null
+++ b/tests/rscript_re_extract_i.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2015-09-29 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="msg is %$.test%\n")
+
+set $.test = re_extract_i($msg, "msg (.*)", 0, 1, "none");
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg_literal "<167>Jan 16 16:57:54 172.20.245.8 TAG: MsG test1"
+injectmsg_literal "<167>Jan 16 16:57:54 172.20.245.8 TAG: MsG test2"
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msg is test1"
+content_check "msg is test2"
+exit_test
diff --git a/tests/rscript_re_match-dbl_quotes.sh b/tests/rscript_re_match-dbl_quotes.sh
new file mode 100755
index 0000000..ebc7ae4
--- /dev/null
+++ b/tests/rscript_re_match-dbl_quotes.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Test that '$' in double-quoted string constants raise a meaningful
+# error message and do not cause rsyslog to segfault.
+# added 2019-12-30 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'") # order is important ...
+set $!test="test$" # ... as after this syntax error nothing is really taken up
+'
+startup
+shutdown_when_empty
+wait_shutdown
+content_check '$-sign in double quotes must be escaped'
+exit_test
diff --git a/tests/rscript_re_match.sh b/tests/rscript_re_match.sh
new file mode 100755
index 0000000..382ef02
--- /dev/null
+++ b/tests/rscript_re_match.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2015-09-29 by singh.janmejay
+# test re_match rscript-fn, using single quotes for the match
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="*Matched*\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+if (re_match($msg, '"'"'.* ([0-9]+)$'"'"')) then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+shutdown_when_empty
+wait_shutdown
+content_check "*Matched*"
+exit_test
diff --git a/tests/rscript_re_match_i.sh b/tests/rscript_re_match_i.sh
new file mode 100755
index 0000000..f7b63fa
--- /dev/null
+++ b/tests/rscript_re_match_i.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# added 2015-09-29 by singh.janmejay
+# test re_match rscript-fn, using single quotes for the match
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="*Matched*\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+if (re_match_i($msg, "RANDOM NUMBER")) then {
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+shutdown_when_empty
+wait_shutdown
+content_check "*Matched*"
+exit_test
diff --git a/tests/rscript_replace.sh b/tests/rscript_replace.sh
new file mode 100755
index 0000000..553ee80
--- /dev/null
+++ b/tests/rscript_replace.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# added 2014-10-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_replace.sh\]: test for replace script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.replaced_msg%\n")
+
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="date_time" type="list") {
+ property(name="msg" regex.Expression="Thu .+ 2014" regex.Type="ERE" regex.Match="0")
+}
+
+set $.replaced_msg = replace("date time: " & exec_template("date_time"), "O" & "ct", replace("october", "o", "0"));
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "date time: Thu 0ct0ber 30 13:20:18 IST 2014"
+exit_test
diff --git a/tests/rscript_replace_complex.sh b/tests/rscript_replace_complex.sh
new file mode 100755
index 0000000..ddc02e4
--- /dev/null
+++ b/tests/rscript_replace_complex.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2014-10-31 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_replace_complex.sh\]: a more complex test for replace script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.replaced_msg%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.replaced_msg = replace($msg, "syslog", "rsyslog");
+set $.replaced_msg = replace($.replaced_msg, "hello", "hello_world");
+set $.replaced_msg = replace($.replaced_msg, "foo_bar_baz", "FBB");
+set $.replaced_msg = replace($.replaced_msg, "as_longer_this_string_as_more_probability_to_catch_the_bug", "ss");
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/complex_replace_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "try to replace rsyslog and syrsyslog with rrsyslog"
+content_check "try to replace hello_world in hello_worldlo and helhello_world with hello_world_world"
+content_check "try to FBB in FBB_quux and quux_FBB with FBB"
+content_check "in the end of msg; try to not lose as_longer_this_string_as_more_probability_to_catch_the_bu"
+exit_test
diff --git a/tests/rscript_ruleset_call.sh b/tests/rscript_ruleset_call.sh
new file mode 100755
index 0000000..fa25891
--- /dev/null
+++ b/tests/rscript_ruleset_call.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# added 2012-10-29 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_ruleset_call.sh\]: testing rainerscript ruleset\(\) and call statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+
+# we deliberately include continue/stop to make sure we have more than
+# one statement. This catches grammar errors
+ruleset(name="rs2") {
+ continue
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ stop
+}
+
+# this time we make sure a single statement is properly supported
+ruleset(name="rs1") {
+ call rs2
+}
+
+if $msg contains "msgnum" then call rs1
+'
+startup
+injectmsg 0 5000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_ruleset_call_indirect-basic.sh b/tests/rscript_ruleset_call_indirect-basic.sh
new file mode 100755
index 0000000..ea9b21d
--- /dev/null
+++ b/tests/rscript_ruleset_call_indirect-basic.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# added 2016-12-11 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+ruleset(name="rs") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+
+if $msg contains "msgnum" then call_indirect "r" & "s";
+'
+startup
+injectmsg 0 100
+shutdown_when_empty
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rscript_ruleset_call_indirect-invld.sh b/tests/rscript_ruleset_call_indirect-invld.sh
new file mode 100755
index 0000000..fcd959c
--- /dev/null
+++ b/tests/rscript_ruleset_call_indirect-invld.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# added 2016-12-11 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+ruleset(name="rs") {
+ action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt")
+}
+
+if $msg contains "msgnum" then
+ call_indirect "does-not-exist";
+else
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 5
+shutdown_when_empty
+wait_shutdown
+grep "error.*does-not-exist" $RSYSLOG_OUT_LOG > /dev/null
+if [ $? -ne 0 ]; then
+ echo
+ echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi
+exit_test
diff --git a/tests/rscript_ruleset_call_indirect-var.sh b/tests/rscript_ruleset_call_indirect-var.sh
new file mode 100755
index 0000000..e219eba
--- /dev/null
+++ b/tests/rscript_ruleset_call_indirect-var.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2016-12-11 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+ruleset(name="rs") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+
+set $.var = "rs";
+
+if $msg contains "msgnum" then call_indirect $.var;
+'
+startup
+injectmsg 0 100
+shutdown_when_empty
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rscript_script_error.sh b/tests/rscript_script_error.sh
new file mode 100755
index 0000000..372e8d0
--- /dev/null
+++ b/tests/rscript_script_error.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="string" string="%$!%\n")
+
+local4.* {
+ set $!valid!serial = parse_time("2017-10-05T01:10:11Z");
+ set $!valid!error = script_error();
+ set $!invalid!serial = parse_time("not a date/time");
+ set $!invalid!error = script_error();
+ set $!valid2!serial = parse_time("2017-10-05T01:10:11Z");
+ set $!valid2!error = script_error();
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+
+# Our fixed and calculated expected results
+export EXPECTED='{ "valid": { "serial": 1507165811, "error": 0 }, "invalid": { "serial": 0, "error": 1 }, "valid2": { "serial": 1507165811, "error": 0 } }'
+cmp_exact $RSYSLOG_OUT_LOG
+
+exit_test
diff --git a/tests/rscript_set_memleak-vg.sh b/tests/rscript_set_memleak-vg.sh
new file mode 100755
index 0000000..bc4e0bc
--- /dev/null
+++ b/tests/rscript_set_memleak-vg.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# A test that checks for memory leaks
+# created based on real world case:
+# https://github.com/rsyslog/rsyslog/issues/1376
+# Copyright 2017-01-24 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+generate_conf
+add_conf '
+template(name="json" type="string" string="%$!%\n")
+template(name="ts" type="string" string="%timestamp:::date-rfc3339%")
+ruleset(name="rcvr" queue.type="LinkedList"
+ queue.timeoutShutdown="'$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT'") {
+ set $.index="unknown";
+ set $.type="unknown";
+ set $.interval=$$now & ":" & $$hour;
+ set $!host_forwarded=$hostname;
+ set $!host_received=$$myhostname;
+ set $!time_received=$timegenerated;
+ set $!@timestamp=exec_template("ts");
+ action( type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="json"
+ )
+}'
+startup_vg
+injectmsg
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+# note: we check only the valgrind result, we are not really interested
+# in the output data (non-standard format in any way...)
+exit_test
diff --git a/tests/rscript_set_modify.sh b/tests/rscript_set_modify.sh
new file mode 100755
index 0000000..ea7099c
--- /dev/null
+++ b/tests/rscript_set_modify.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Check if a set statement can correctly be reset to a different value
+# Copyright 2014-11-24 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_set_modify.sh\]: testing set twice
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 1);
+ set $!usr!msgnum = field($msg, 58, 2);
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 100
+shutdown_when_empty
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rscript_set_unset_invalid_var.sh b/tests/rscript_set_unset_invalid_var.sh
new file mode 100755
index 0000000..a428be2
--- /dev/null
+++ b/tests/rscript_set_unset_invalid_var.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Check that invalid variable names are detected.
+# Copyright 2017-01-24 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="json" type="string" string="%$!%\n")
+ruleset(name="rcvr" queue.type="LinkedList") {
+ set $@timestamp="test";
+ unset $@timestamp2;
+ action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+
+'
+startup
+injectmsg 0 10
+shutdown_when_empty
+wait_shutdown
+
+grep "@timestamp" $RSYSLOG_OUT_LOG > /dev/null
+if [ ! $? -eq 0 ]; then
+ echo "expected error message on \"@timestamp\" not found, output is:"
+ echo "------------------------------------------------------------"
+ cat $RSYSLOG_OUT_LOG
+ echo "------------------------------------------------------------"
+ error_exit 1
+fi;
+
+grep "@timestamp2" $RSYSLOG_OUT_LOG > /dev/null
+if [ ! $? -eq 0 ]; then
+ echo "expected error message on \"@timestamp2\" not found, output is:"
+ echo "------------------------------------------------------------"
+ cat $RSYSLOG_OUT_LOG
+ echo "------------------------------------------------------------"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/rscript_stop.sh b/tests/rscript_stop.sh
new file mode 100755
index 0000000..12729d4
--- /dev/null
+++ b/tests/rscript_stop.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_stop.sh\]: testing rainerscript STOP statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ if cnum($!usr!msgnum) >= 5000 then
+ stop
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_stop2.sh b/tests/rscript_stop2.sh
new file mode 100755
index 0000000..1390b03
--- /dev/null
+++ b/tests/rscript_stop2.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_stop2.sh\]: testing rainerscript STOP statement, alternate method
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if not ($msg contains "msgnum") then
+ stop
+
+set $!usr!msgnum = field($msg, 58, 2);
+if cnum($!usr!msgnum) >= 5000 then
+ stop
+/* We could use yet another method, but we like to have the action statement
+ * without a filter in rsyslog.conf top level hierarchy - so this test, as
+ * a side-effect, also tests this ability.
+ */
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 8000
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+seq_check 0 4999
+exit_test
diff --git a/tests/rscript_str2num_negative.sh b/tests/rscript_str2num_negative.sh
new file mode 100755
index 0000000..b76ddf9
--- /dev/null
+++ b/tests/rscript_str2num_negative.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# add 2017-02-09 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.n = "-1";
+set $!ip!v1 = 1 + $.n;
+
+template(name="outfmt" type="string" string="%!ip%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo '{ "v1": 0 }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
diff --git a/tests/rscript_substring.sh b/tests/rscript_substring.sh
new file mode 100755
index 0000000..0767cce
--- /dev/null
+++ b/tests/rscript_substring.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2017-12-10 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!str!var1 = substring("", 0, 0);
+set $!str!var2 = substring("test", 0, 4);
+set $!str!var3 = substring("test", 1, 2);
+set $!str!var4 = substring("test", 4, 2);
+set $!str!var5 = substring("test", 0, 5);
+set $!str!var6 = substring("test", 0, 6);
+set $!str!var7 = substring("test", 3, 4);
+set $!str!var8 = substring("test", 1, 0);
+
+template(name="outfmt" type="string" string="%!str%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+echo '{ "var1": "", "var2": "test", "var3": "es", "var4": "", "var5": "test", "var6": "test", "var7": "t", "var8": "" }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
+
diff --git a/tests/rscript_trim-vg.sh b/tests/rscript_trim-vg.sh
new file mode 100755
index 0000000..d186a95
--- /dev/null
+++ b/tests/rscript_trim-vg.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+# add 2017-08-14 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!str!l1 = ltrim("");
+set $!str!l2 = ltrim("test");
+set $!str!l3 = ltrim(" test");
+set $!str!l4 = ltrim("test ");
+set $!str!l5 = ltrim(" test ");
+set $!str!l6 = ltrim(" test");
+set $!str!l7 = ltrim("test ");
+set $!str!l8 = ltrim(" ");
+set $!str!l9 = ltrim("te st");
+set $!str!l10 = ltrim(" te st");
+set $!str!l11 = ltrim(" a");
+set $!str!l12 = ltrim("a ");
+
+set $!str!r1 = rtrim("");
+set $!str!r2 = rtrim("test");
+set $!str!r3 = rtrim(" test");
+set $!str!r4 = rtrim("test ");
+set $!str!r5 = rtrim(" test ");
+set $!str!r6 = rtrim(" test");
+set $!str!r7 = rtrim("test ");
+set $!str!r8 = rtrim(" ");
+set $!str!r9 = rtrim("te st");
+set $!str!r10 = rtrim("te st ");
+set $!str!r11 = rtrim(" a");
+set $!str!r12 = rtrim("a ");
+
+
+set $!str!b1 = ltrim(" ");
+set $!str!b1 = rtrim($!str!b1);
+
+set $!str!b2 = ltrim(" test ");
+set $!str!b2 = rtrim($!str!b2);
+
+set $!str!b3 = ltrim(" test ");
+set $!str!b3 = rtrim($!str!b3);
+
+set $!str!b4 = ltrim("te st");
+set $!str!b4 = rtrim($!str!b4);
+
+set $!str!b5 = rtrim(" ");
+set $!str!b5 = ltrim($!str!b5);
+
+set $!str!b6 = rtrim(" test ");
+set $!str!b6 = ltrim($!str!b6);
+
+set $!str!b7 = rtrim(" test ");
+set $!str!b7 = ltrim($!str!b7);
+
+set $!str!b8 = rtrim("te st");
+set $!str!b8 = ltrim($!str!b8);
+
+set $!str!b9 = rtrim(ltrim("test"));
+set $!str!b10 = rtrim(ltrim("te st"));
+set $!str!b11 = rtrim(ltrim(" test"));
+set $!str!b12 = rtrim(ltrim("test "));
+set $!str!b13 = rtrim(ltrim(" test "));
+set $!str!b14 = rtrim(ltrim(" te st "));
+
+set $!str!b15 = ltrim(rtrim("test"));
+set $!str!b16 = ltrim(rtrim("te st"));
+set $!str!b17 = ltrim(rtrim(" test"));
+set $!str!b18 = ltrim(rtrim("test "));
+set $!str!b19 = ltrim(rtrim(" test "));
+set $!str!b20 = ltrim(rtrim(" te st "));
+
+template(name="outfmt" type="string" string="%!str%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+echo '{ "l1": "", "l2": "test", "l3": "test", "l4": "test ", "l5": "test ", "l6": "test", "l7": "test ", "l8": "", "l9": "te st", "l10": "te st", "l11": "a", "l12": "a ", "r1": "", "r2": "test", "r3": " test", "r4": "test", "r5": " test", "r6": " test", "r7": "test", "r8": "", "r9": "te st", "r10": "te st", "r11": " a", "r12": "a", "b1": "", "b2": "test", "b3": "test", "b4": "te st", "b5": "", "b6": "test", "b7": "test", "b8": "te st", "b9": "test", "b10": "te st", "b11": "test", "b12": "test", "b13": "test", "b14": "te st", "b15": "test", "b16": "te st", "b17": "test", "b18": "test", "b19": "test", "b20": "te st" }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
+
diff --git a/tests/rscript_trim.sh b/tests/rscript_trim.sh
new file mode 100755
index 0000000..a561102
--- /dev/null
+++ b/tests/rscript_trim.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+# add 2017-08-14 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $!str!l1 = ltrim("");
+set $!str!l2 = ltrim("test");
+set $!str!l3 = ltrim(" test");
+set $!str!l4 = ltrim("test ");
+set $!str!l5 = ltrim(" test ");
+set $!str!l6 = ltrim(" test");
+set $!str!l7 = ltrim("test ");
+set $!str!l8 = ltrim(" ");
+set $!str!l9 = ltrim("te st");
+set $!str!l10 = ltrim(" te st");
+set $!str!l11 = ltrim(" a");
+set $!str!l12 = ltrim("a ");
+
+set $!str!r1 = rtrim("");
+set $!str!r2 = rtrim("test");
+set $!str!r3 = rtrim(" test");
+set $!str!r4 = rtrim("test ");
+set $!str!r5 = rtrim(" test ");
+set $!str!r6 = rtrim(" test");
+set $!str!r7 = rtrim("test ");
+set $!str!r8 = rtrim(" ");
+set $!str!r9 = rtrim("te st");
+set $!str!r10 = rtrim("te st ");
+set $!str!r11 = rtrim(" a");
+set $!str!r12 = rtrim("a ");
+
+
+set $!str!b1 = ltrim(" ");
+set $!str!b1 = rtrim($!str!b1);
+
+set $!str!b2 = ltrim(" test ");
+set $!str!b2 = rtrim($!str!b2);
+
+set $!str!b3 = ltrim(" test ");
+set $!str!b3 = rtrim($!str!b3);
+
+set $!str!b4 = ltrim("te st");
+set $!str!b4 = rtrim($!str!b4);
+
+set $!str!b5 = rtrim(" ");
+set $!str!b5 = ltrim($!str!b5);
+
+set $!str!b6 = rtrim(" test ");
+set $!str!b6 = ltrim($!str!b6);
+
+set $!str!b7 = rtrim(" test ");
+set $!str!b7 = ltrim($!str!b7);
+
+set $!str!b8 = rtrim("te st");
+set $!str!b8 = ltrim($!str!b8);
+
+set $!str!b9 = rtrim(ltrim("test"));
+set $!str!b10 = rtrim(ltrim("te st"));
+set $!str!b11 = rtrim(ltrim(" test"));
+set $!str!b12 = rtrim(ltrim("test "));
+set $!str!b13 = rtrim(ltrim(" test "));
+set $!str!b14 = rtrim(ltrim(" te st "));
+
+set $!str!b15 = ltrim(rtrim("test"));
+set $!str!b16 = ltrim(rtrim("te st"));
+set $!str!b17 = ltrim(rtrim(" test"));
+set $!str!b18 = ltrim(rtrim("test "));
+set $!str!b19 = ltrim(rtrim(" test "));
+set $!str!b20 = ltrim(rtrim(" te st "));
+
+template(name="outfmt" type="string" string="%!str%\n")
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m1 -y
+shutdown_when_empty
+wait_shutdown
+echo '{ "l1": "", "l2": "test", "l3": "test", "l4": "test ", "l5": "test ", "l6": "test", "l7": "test ", "l8": "", "l9": "te st", "l10": "te st", "l11": "a", "l12": "a ", "r1": "", "r2": "test", "r3": " test", "r4": "test", "r5": " test", "r6": " test", "r7": "test", "r8": "", "r9": "te st", "r10": "te st", "r11": " a", "r12": "a", "b1": "", "b2": "test", "b3": "test", "b4": "te st", "b5": "", "b6": "test", "b7": "test", "b8": "te st", "b9": "test", "b10": "te st", "b11": "test", "b12": "test", "b13": "test", "b14": "te st", "b15": "test", "b16": "te st", "b17": "test", "b18": "test", "b19": "test", "b20": "te st" }' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid function output detected, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+exit_test
+
diff --git a/tests/rscript_unaffected_reset.sh b/tests/rscript_unaffected_reset.sh
new file mode 100755
index 0000000..5d33182
--- /dev/null
+++ b/tests/rscript_unaffected_reset.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Check if a set statement to the same subtree does not reset
+# other variables in that same subtree.
+# Copyright 2014-11-24 by Rainer Gerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_unaffected_reset.sh\]: testing set/reset
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="$!usr!msgnum")
+ constant(value="\n")
+}
+
+if $msg contains "msgnum" then {
+ set $!usr!msgnum = field($msg, 58, 2);
+ set $!usr!msgnum_reset = "dummy";
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+}
+'
+startup
+injectmsg 0 100
+shutdown_when_empty
+wait_shutdown
+seq_check 0 99
+exit_test
diff --git a/tests/rscript_unflatten_arg1_unsuitable-vg.sh b/tests/rscript_unflatten_arg1_unsuitable-vg.sh
new file mode 100755
index 0000000..527e4d3
--- /dev/null
+++ b/tests/rscript_unflatten_arg1_unsuitable-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_arg1_unsuitable.sh
diff --git a/tests/rscript_unflatten_arg1_unsuitable.sh b/tests/rscript_unflatten_arg1_unsuitable.sh
new file mode 100755
index 0000000..9220134
--- /dev/null
+++ b/tests/rscript_unflatten_arg1_unsuitable.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED=' msgnum:00000000: 1 0'
+cmp_exact "$RSYSLOG_OUT_LOG"
+exit_test
diff --git a/tests/rscript_unflatten_arg2_invalid-vg.sh b/tests/rscript_unflatten_arg2_invalid-vg.sh
new file mode 100755
index 0000000..68f0003
--- /dev/null
+++ b/tests/rscript_unflatten_arg2_invalid-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_arg2_invalid.sh
diff --git a/tests/rscript_unflatten_arg2_invalid.sh b/tests/rscript_unflatten_arg2_invalid.sh
new file mode 100755
index 0000000..8ab6c4d
--- /dev/null
+++ b/tests/rscript_unflatten_arg2_invalid.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $!a.b.c = "foobar";
+set $.unflatten = unflatten($!, "too many chars");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED=' msgnum:00000000: 1 0'
+cmp_exact "$RSYSLOG_OUT_LOG"
+exit_test
diff --git a/tests/rscript_unflatten_conflict1-vg.sh b/tests/rscript_unflatten_conflict1-vg.sh
new file mode 100755
index 0000000..c02399d
--- /dev/null
+++ b/tests/rscript_unflatten_conflict1-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_conflict1.sh
diff --git a/tests/rscript_unflatten_conflict1.sh b/tests/rscript_unflatten_conflict1.sh
new file mode 100755
index 0000000..27040e2
--- /dev/null
+++ b/tests/rscript_unflatten_conflict1.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $!a!b = "foo";
+set $!a.b.c = "bar";
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "a": { "b": { "c": "bar" } } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+
+EXPECTED='fmunflatten.c: warning: while processing flat key "a.b.c" at depth #1 (intermediate node), overriding existing value of type string by an object'
+if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then
+ echo "GREP FAILED"
+ echo " => FILE: $RSYSLOG_DEBUGLOG"
+ echo " => EXPECTED: $EXPECTED"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/rscript_unflatten_conflict2-vg.sh b/tests/rscript_unflatten_conflict2-vg.sh
new file mode 100755
index 0000000..aca7a98
--- /dev/null
+++ b/tests/rscript_unflatten_conflict2-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_conflict2.sh
diff --git a/tests/rscript_unflatten_conflict2.sh b/tests/rscript_unflatten_conflict2.sh
new file mode 100755
index 0000000..22ec6e0
--- /dev/null
+++ b/tests/rscript_unflatten_conflict2.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $.x!a = 21;
+set $!a!b = "foo";
+set $!a.b = $.x;
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "a": { "b": { "a": 21 } } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+
+EXPECTED='fmunflatten.c: warning: while processing flat key "a.b" at depth #1 (final node), overriding existing value of type string by an object'
+if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then
+ echo "GREP FAILED"
+ echo " => FILE: $RSYSLOG_DEBUGLOG"
+ echo " => EXPECTED: $EXPECTED"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/rscript_unflatten_conflict3-vg.sh b/tests/rscript_unflatten_conflict3-vg.sh
new file mode 100755
index 0000000..ee4404f
--- /dev/null
+++ b/tests/rscript_unflatten_conflict3-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_conflict3.sh
diff --git a/tests/rscript_unflatten_conflict3.sh b/tests/rscript_unflatten_conflict3.sh
new file mode 100755
index 0000000..07a0485
--- /dev/null
+++ b/tests/rscript_unflatten_conflict3.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $!a!b = "foo";
+set $!a.b = "bar";
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "a": { "b": "bar" } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+
+EXPECTED='fmunflatten.c: warning: while processing flat key "a.b" at depth #1 (final node), overriding existing value'
+if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then
+ echo "GREP FAILED"
+ echo " => FILE: $RSYSLOG_DEBUGLOG"
+ echo " => EXPECTED: $EXPECTED"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/rscript_unflatten_key_truncated-vg.sh b/tests/rscript_unflatten_key_truncated-vg.sh
new file mode 100755
index 0000000..a7d7684
--- /dev/null
+++ b/tests/rscript_unflatten_key_truncated-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_key_truncated.sh
diff --git a/tests/rscript_unflatten_key_truncated.sh b/tests/rscript_unflatten_key_truncated.sh
new file mode 100755
index 0000000..5dd3985
--- /dev/null
+++ b/tests/rscript_unflatten_key_truncated.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $!a.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb255ccccc.d = "bar";
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1
+wait_file_lines "$RSYSLOG_OUT_LOG" 1 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "a": { "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb255": { "d": "bar" } } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+
+EXPECTED='fmunflatten.c: warning: flat key "a.bbbbbbbbbbbbbbbbbb..." truncated at depth #1, buffer too small (max 256)'
+if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then
+ echo "GREP FAILED"
+ echo " => FILE: $RSYSLOG_DEBUGLOG"
+ echo " => EXPECTED: $EXPECTED"
+ error_exit 1
+fi
+
+exit_test
diff --git a/tests/rscript_unflatten_non_object-vg.sh b/tests/rscript_unflatten_non_object-vg.sh
new file mode 100755
index 0000000..aa18e1d
--- /dev/null
+++ b/tests/rscript_unflatten_non_object-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_non_object.sh
diff --git a/tests/rscript_unflatten_non_object.sh b/tests/rscript_unflatten_non_object.sh
new file mode 100755
index 0000000..cfdc052
--- /dev/null
+++ b/tests/rscript_unflatten_non_object.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# added 2021-03-09 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $/cpt = $/cpt + 1;
+if ($/cpt == 1) then
+ set $! = "string";
+else
+ set $! = 42;
+
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 2
+wait_file_lines "$RSYSLOG_OUT_LOG" 2 60
+shutdown_when_empty
+wait_shutdown
+
+EXPECTED=' msgnum:00000000: 0 string
+ msgnum:00000001: 0 42'
+cmp_exact "$RSYSLOG_OUT_LOG"
+exit_test
diff --git a/tests/rscript_unflatten_object-vg.sh b/tests/rscript_unflatten_object-vg.sh
new file mode 100755
index 0000000..acda4bb
--- /dev/null
+++ b/tests/rscript_unflatten_object-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_object.sh
diff --git a/tests/rscript_unflatten_object.sh b/tests/rscript_unflatten_object.sh
new file mode 100755
index 0000000..084fc94
--- /dev/null
+++ b/tests/rscript_unflatten_object.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# added 2020-08-16 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $!source.ip = "1.2.3.4";
+set $!source.bytes = 3258;
+set $!source.geo.country_iso_code = "FR";
+set $!destination.ip = "4.3.2.1";
+
+set $.unflatten = unflatten($!, ".");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 3
+wait_file_lines "$RSYSLOG_OUT_LOG" 3 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } }
+ msgnum:00000001: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } }
+ msgnum:00000002: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+exit_test
diff --git a/tests/rscript_unflatten_object_exclamation-vg.sh b/tests/rscript_unflatten_object_exclamation-vg.sh
new file mode 100755
index 0000000..292be2d
--- /dev/null
+++ b/tests/rscript_unflatten_object_exclamation-vg.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/rscript_unflatten_object_exclamation.sh
diff --git a/tests/rscript_unflatten_object_exclamation.sh b/tests/rscript_unflatten_object_exclamation.sh
new file mode 100755
index 0000000..d9e84cd
--- /dev/null
+++ b/tests/rscript_unflatten_object_exclamation.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# added 2020-08-16 by Julien Thomas, released under ASL 2.0
+
+source "${srcdir:=.}/diag.sh" init
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug"
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../contrib/fmunflatten/.libs/fmunflatten")
+input(type="imtcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port")
+template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n")
+
+if (not($msg contains "msgnum:")) then
+ stop
+
+set $.ret = parse_json("{\"source!ip\":\"1.2.3.4\",\"source!port\":53}", "\$!");
+set $.unflatten = unflatten($!, "!");
+set $.ret = script_error();
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 2
+wait_file_lines "$RSYSLOG_OUT_LOG" 2 60
+shutdown_when_empty
+wait_shutdown
+
+# this test may need changes to produce a more deterministic
+# output by sorting keys
+EXPECTED=' msgnum:00000000: 0 { "source": { "ip": "1.2.3.4", "port": 53 } }
+ msgnum:00000001: 0 { "source": { "ip": "1.2.3.4", "port": 53 } }'
+cmp_exact "$RSYSLOG_OUT_LOG"
+exit_test
diff --git a/tests/rscript_wrap2.sh b/tests/rscript_wrap2.sh
new file mode 100755
index 0000000..08cb067
--- /dev/null
+++ b/tests/rscript_wrap2.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2014-11-03 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_wrap2.sh\]: a test for wrap\(2\) script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.replaced_msg%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.replaced_msg = wrap("foo says" & $msg, "*" & "*");
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/date_time_msg
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "**foo says at Thu Oct 30 13:20:18 IST 2014 random number is 19597**"
+exit_test
diff --git a/tests/rscript_wrap3.sh b/tests/rscript_wrap3.sh
new file mode 100755
index 0000000..69d20c7
--- /dev/null
+++ b/tests/rscript_wrap3.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# added 2014-11-03 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_wrap3.sh\]: a test for wrap\(3\) script-function
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.replaced_msg%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+set $.replaced_msg = wrap("foo says" & $msg, "bc" & "def" & "bc", "ES" & "C");
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/wrap3_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "bcdefbcfoo says a abcESCdefb has ESCbcdefbc"
+exit_test
diff --git a/tests/rsf_getenv.sh b/tests/rsf_getenv.sh
new file mode 100755
index 0000000..a981f20
--- /dev/null
+++ b/tests/rsf_getenv.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Test for the getenv() rainerscript function
+# this is a quick test, but it guarantees that the code path is
+# at least progressed (but we do not check for unset envvars!)
+# added 2009-11-03 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+# uncomment for debugging support:
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export MSGNUM="msgnum:"
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+if $msg contains getenv("MSGNUM") then ?dynfile;outfmt
+'
+startup
+injectmsg
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/ruleset-direct-queue.sh b/tests/ruleset-direct-queue.sh
new file mode 100755
index 0000000..f0b0e95
--- /dev/null
+++ b/tests/ruleset-direct-queue.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# check that ruleset is called synchronously when queue.type="direct" is
+# specified in ruleset.
+# added 2021-09-17 by rgerhards. Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+export STATSFILE="$RSYSLOG_DYNNAME.stats"
+add_conf '
+template(name="outfmt" type="string" string="%msg%,%$.msg%\n")
+
+ruleset(name="rs1" queue.type="direct") {
+ set $.msg = "TEST";
+}
+
+
+if $msg contains "msgnum:" then {
+ set $.msg = $msg;
+ call rs1
+ action(type="omfile" name="main-action" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+}
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+content_check "msgnum:00000000:,TEST"
+exit_test
diff --git a/tests/rulesetmultiqueue-v6.sh b/tests/rulesetmultiqueue-v6.sh
new file mode 100755
index 0000000..157b8a4
--- /dev/null
+++ b/tests/rulesetmultiqueue-v6.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# Test for disk-only queue mode with v6+ config
+# This tests defines three rulesets, each one with its own queue. Then, it
+# sends data to them and checks the outcome. Note that we do need to
+# use some custom code as the test driver framework does not (yet?)
+# support multi-output-file operations.
+# added 2013-11-14 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test does not work on Solaris. The overall queue
+size check in imdiag requires atomics or mutexes on this platform, which we
+do not use for performance reasons."
+export NUMMESSAGES=60000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+
+# general definition
+$template outfmt,"%msg:F,58:2%\n"
+
+# create the individual rulesets
+$template dynfile1,"'$RSYSLOG_OUT_LOG'1.log" # trick to use relative path names!
+ruleset(name="file1" queue.type="linkedList") {
+ :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ :msg, contains, "msgnum:" ?dynfile1;outfmt
+}
+
+$template dynfile2,"'$RSYSLOG_OUT_LOG'2.log" # trick to use relative path names!
+ruleset(name="file2" queue.type="linkedList") {
+ :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ :msg, contains, "msgnum:" ?dynfile2;outfmt
+}
+
+$template dynfile3,"'$RSYSLOG_OUT_LOG'3.log" # trick to use relative path names!
+ruleset(name="file3" queue.type="linkedList") {
+ :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+ :msg, contains, "msgnum:" ?dynfile3;outfmt
+}
+
+# start listeners and bind them to rulesets
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="file1")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="file2")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" ruleset="file3")
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3"
+# now fill the three files (a bit sequentially, but they should
+# still get their share of concurrency - to increase the chance
+# we use three connections per set).
+tcpflood -c3 -p$TCPFLOOD_PORT -m20000 -i0
+tcpflood -c3 -p$TCPFLOOD_PORT2 -m20000 -i20000
+tcpflood -c3 -p$RS_PORT -m20000 -i40000
+shutdown_when_empty
+wait_shutdown
+# now consolidate all logs into a single one so that we can use the
+seq_check # do a check on the count file - doesn't hurt as we need it anyhow
+# regular check logic
+cat ${RSYSLOG_OUT_LOG}1.log ${RSYSLOG_OUT_LOG}2.log ${RSYSLOG_OUT_LOG}3.log > $RSYSLOG_OUT_LOG
+seq_check
+exit_test
diff --git a/tests/rulesetmultiqueue.sh b/tests/rulesetmultiqueue.sh
new file mode 100755
index 0000000..8b5f9f1
--- /dev/null
+++ b/tests/rulesetmultiqueue.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# Test for disk-only queue mode
+# This tests defines three rulesets, each one with its own queue. Then, it
+# sends data to them and checks the outcome. Note that we do need to
+# use some custom code as the test driver framework does not (yet?)
+# support multi-output-file operations.
+# added 2009-10-30 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "SunOS" "This test does not work on Solaris. The overall queue
+size check in imdiag requires atomics or mutexes on this platform, which we
+do not use for performance reasons."
+export NUMMESSAGES=60000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+
+# general definition
+$template outfmt,"%msg:F,58:2%\n"
+
+# create the individual rulesets
+$ruleset file1
+$RulesetCreateMainQueue on
+$template dynfile1,"'$RSYSLOG_OUT_LOG'1.log" # trick to use relative path names!
+:msg, contains, "msgnum:" { ?dynfile1;outfmt
+ ./'$RSYSLOG_OUT_LOG'
+}
+
+$ruleset file2
+$RulesetCreateMainQueue on
+$template dynfile2,"'$RSYSLOG_OUT_LOG'2.log" # trick to use relative path names!
+:msg, contains, "msgnum:" { ?dynfile2;outfmt
+ ./'$RSYSLOG_OUT_LOG'
+}
+
+$ruleset file3
+$RulesetCreateMainQueue on
+$template dynfile3,"'$RSYSLOG_OUT_LOG'3.log" # trick to use relative path names!
+:msg, contains, "msgnum:" { ?dynfile3;outfmt
+ ./'$RSYSLOG_OUT_LOG'
+}
+
+# start listeners and bind them to rulesets
+$InputTCPServerBindRuleset file1
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port
+$InputTCPServerRun 0
+
+$InputTCPServerBindRuleset file2
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port2
+$InputTCPServerRun 0
+
+$InputTCPServerBindRuleset file3
+$InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port3
+$InputTCPServerRun 0
+'
+startup
+assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2"
+assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3"
+# now fill the three files (a bit sequentially, but they should
+# still get their share of concurrency - to increase the chance
+# we use three connections per set).
+tcpflood -c3 -p$TCPFLOOD_PORT -m20000 -i0
+tcpflood -c3 -p$TCPFLOOD_PORT2 -m20000 -i20000
+tcpflood -c3 -p$RS_PORT -m20000 -i40000
+
+# in this version of the imdiag, we do not have the capability to poll
+# all queues for emptiness. So we do a sleep in the hopes that this will
+# sufficiently drain the queues. This is race, but the best we currently
+# can do... - rgerhards, 2009-11-05
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+# now consolidate all logs into a single one so that we can use the
+# regular check logic
+cat ${RSYSLOG_OUT_LOG}1.log ${RSYSLOG_OUT_LOG}2.log ${RSYSLOG_OUT_LOG}3.log > $RSYSLOG_OUT_LOG
+seq_check
+exit_test
diff --git a/tests/set-envvars.in b/tests/set-envvars.in
new file mode 100644
index 0000000..573d371
--- /dev/null
+++ b/tests/set-envvars.in
@@ -0,0 +1 @@
+export PYTHON=@PYTHON@
diff --git a/tests/smtradfile-vg.sh b/tests/smtradfile-vg.sh
new file mode 100755
index 0000000..e547c47
--- /dev/null
+++ b/tests/smtradfile-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2019-04-15 by RGerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:=.}/smtradfile.sh
diff --git a/tests/smtradfile.sh b/tests/smtradfile.sh
new file mode 100755
index 0000000..e47b525
--- /dev/null
+++ b/tests/smtradfile.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# addd 2019-04-15 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="plugin" plugin="RSYSLOG_TraditionalFileFormat")
+action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+content_check "Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:"
+exit_test
diff --git a/tests/sndrcv.sh b/tests/sndrcv.sh
new file mode 100755
index 0000000..bf674f7
--- /dev/null
+++ b/tests/sndrcv.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# This tests two rsyslog instances. Instance
+# TWO sends data to instance ONE. A number of messages is injected into
+# the instance 2 and we finally check if all those messages
+# arrived at instance 1.
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+# start up the instances
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+# then SENDER sends to this port (not tcpflood!)
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'"
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+
+export RCVR_PORT=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+action(type="omfwd" target="127.0.0.1" protocol="tcp" port="'$RCVR_PORT'")
+' 2
+startup 2
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check
+
+exit_test
diff --git a/tests/sndrcv_drvr.sh b/tests/sndrcv_drvr.sh
new file mode 100755
index 0000000..ee222f0
--- /dev/null
+++ b/tests/sndrcv_drvr.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+. $srcdir/sndrcv_drvr_noexit.sh $1 $2 $3
diff --git a/tests/sndrcv_drvr_noexit.sh b/tests/sndrcv_drvr_noexit.sh
new file mode 100755
index 0000000..7458edf
--- /dev/null
+++ b/tests/sndrcv_drvr_noexit.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# This is test driver for testing two rsyslog instances. It can be
+# utilized by any test that just needs two instances with different
+# config files, where messages are injected in instance TWO and
+# (with whatever rsyslog mechanism) being relayed over to instance ONE,
+# where they are written to the log file. After the run, the completeness
+# of that log file is checked.
+# The code is almost the same, but the config files differ (probably greatly)
+# for different test cases. As such, this driver needs to be called with the
+# config file name ($2). From that name, the sender and receiver config file
+# names are automatically generated.
+# So: $1 config file name, $2 number of messages
+# environment variable TCPFLOOD_EXTRA_OPTIONS is used to slowdown sending when
+# using UDP (we've seen problems due to UDP message loss if sending with full
+# speed)
+#
+# A note on TLS testing: the current testsuite (in git!) already contains
+# TLS test cases. However, getting these test cases correct is not simple.
+# That's not a problem with the code itself, but rather a problem with
+# synchronization in the test environment. So I have decided to keep the
+# TLS tests in, but not yet actually utilize them. This is most probably
+# left as an exercise for future (devel) releases. -- rgerhards, 2009-11-11
+#
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+
+# start up the instances
+export RSYSLOG_DEBUGLOG="log"
+startup $1_rcvr.conf
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+startup $1_sender.conf 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$2 -i1
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 $2 $3
diff --git a/tests/sndrcv_dtls_anon_ciphers.sh b/tests/sndrcv_dtls_anon_ciphers.sh
new file mode 100755
index 0000000..bac90da
--- /dev/null
+++ b/tests/sndrcv_dtls_anon_ciphers.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global(
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls"
+ tls.AuthMode="anon")
+
+input( type="imdtls"
+ tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_256_GCM_SHA384"
+ port="'$PORT_RCVR'")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+module( load="../plugins/omdtls/.libs/omdtls" )
+
+action( name="omdtls"
+ type="omdtls"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_128_GCM_SHA256"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg 0 1
+
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# IMPORTANT: this test will generate many error messages. This is exactly it's
+# intent. So do not think something is wrong. The content_check below checks
+# these error codes.
+
+content_check --check-only "TLS library does not support SSL_CONF_cmd"
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ # Kindly check for a failed session
+ content_check "OpenSSL Error Stack"
+ content_check "no shared cipher"
+fi
+
+exit_test
diff --git a/tests/sndrcv_dtls_certvalid-vg.sh b/tests/sndrcv_dtls_certvalid-vg.sh
new file mode 100755
index 0000000..f8b6703
--- /dev/null
+++ b/tests/sndrcv_dtls_certvalid-vg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then
+ printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n'
+ printf 'a valgrind-internal bug. So we need to skip it.\n'
+ exit 77
+fi
+export USE_VALGRIND="YES"
+# export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes"
+source ${srcdir:-.}/sndrcv_dtls_certvalid.sh
diff --git a/tests/sndrcv_dtls_certvalid.sh b/tests/sndrcv_dtls_certvalid.sh
new file mode 100755
index 0000000..3f4cc06
--- /dev/null
+++ b/tests/sndrcv_dtls_certvalid.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+export NUMMESSAGES=1000
+export NUMMESSAGESFULL=$NUMMESSAGES
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+# debug.whitelist="on"
+# debug.files=["imdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+input( type="imdtls"
+ port="'$PORT_RCVR'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+# debug.whitelist="on"
+# debug.files=["omdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load modules
+module( load="../plugins/omdtls/.libs/omdtls" )
+
+local4.* {
+ action( name="omdtls"
+ type="omdtls"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ queue.type="FixedArray"
+ queue.size="10000"
+ queue.dequeueBatchSize="1"
+ queue.minDequeueBatchSize.timeout="1000" # 1 sec
+ queue.timeoutWorkerthreadShutdown="1000" # 1 sec
+ queue.timeoutshutdown="1000"
+ # Slow down, do not lose UDP messages
+ queue.dequeueSlowDown="1000"
+ )
+
+# action( type="omfile" file="'$RSYSLOG_OUT_LOG'")
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_dtls_certvalid_ciphers.sh b/tests/sndrcv_dtls_certvalid_ciphers.sh
new file mode 100755
index 0000000..93ff49f
--- /dev/null
+++ b/tests/sndrcv_dtls_certvalid_ciphers.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+export NUMMESSAGES=1
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls"
+ tls.AuthMode="anon")
+
+input( type="imdtls"
+ tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_256_GCM_SHA384"
+ port="'$PORT_RCVR'")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/omdtls/.libs/omdtls" )
+
+action( name="omdtls"
+ type="omdtls"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ tls.tlscfgcmd="CipherString=ECDHE-RSA-AES128-GCM-SHA256\nCiphersuites=TLS_AES_128_GCM_SHA256"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg 0 $NUMMESSAGES
+
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# IMPORTANT: this test will generate many error messages. This is exactly it's
+# intent. So do not think something is wrong. The content_check below checks
+# these error codes.
+
+content_check --check-only "TLS library does not support SSL_CONF_cmd"
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ # Kindly check for a failed session
+ content_check "OpenSSL Error Stack"
+ content_check "no shared cipher"
+fi
+
+exit_test
diff --git a/tests/sndrcv_dtls_certvalid_missing.sh b/tests/sndrcv_dtls_certvalid_missing.sh
new file mode 100755
index 0000000..e6908b3
--- /dev/null
+++ b/tests/sndrcv_dtls_certvalid_missing.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+export NUMMESSAGES=1
+# export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global(
+# debug.whitelist="on"
+# debug.files=["imdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+input( type="imdtls"
+ port="'$PORT_RCVR'"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog"
+)
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+
+global(
+# debug.whitelist="on"
+# debug.files=["omdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load modules
+module( load="../plugins/omdtls/.libs/omdtls" )
+
+local4.* {
+ action( name="omdtls"
+ type="omdtls"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ )
+
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# Kindly check for a failed session
+content_check "OpenSSL Error Stack"
+content_check "peer did not return a certificate"
+
+exit_test
diff --git a/tests/sndrcv_dtls_certvalid_permitted.sh b/tests/sndrcv_dtls_certvalid_permitted.sh
new file mode 100755
index 0000000..191bf29
--- /dev/null
+++ b/tests/sndrcv_dtls_certvalid_permitted.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+export NUMMESSAGES=1000
+export NUMMESSAGESFULL=$NUMMESSAGES
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+
+add_conf '
+global(
+# debug.whitelist="on"
+# debug.files=["imdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+module( load="../plugins/imdtls/.libs/imdtls" )
+input( type="imdtls"
+ port="'$PORT_RCVR'"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="name"
+ tls.permittedpeer="rsyslog"
+)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+
+global(
+# debug.whitelist="on"
+# debug.files=["omdtls.c", "modules.c", "errmsg.c", "action.c"]
+)
+
+# impstats in order to gain insight into error cases
+module(load="../plugins/impstats/.libs/impstats"
+ log.file="'$RSYSLOG_DYNNAME.pstats'"
+ interval="1" log.syslog="off")
+$imdiagInjectDelayMode full
+
+# Load modules
+module( load="../plugins/omdtls/.libs/omdtls" )
+
+local4.* {
+ action( name="omdtls"
+ type="omdtls"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ action.resumeInterval="1"
+ action.resumeRetryCount="2"
+ queue.type="FixedArray"
+ queue.size="10000"
+ queue.dequeueBatchSize="1"
+ queue.minDequeueBatchSize.timeout="1000" # 1 sec
+ queue.timeoutWorkerthreadShutdown="1000" # 1 sec
+ queue.timeoutshutdown="1000"
+ # Slow down, do not lose UDP messages
+ queue.dequeueSlowDown="1000"
+ )
+
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_failover.sh b/tests/sndrcv_failover.sh
new file mode 100755
index 0000000..fd6d656
--- /dev/null
+++ b/tests/sndrcv_failover.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# This tests failover capabilities. Data is sent to a local port, where
+# no process shall listen. Then it fails over to a second instance, then to
+# a file. The second instance is started. So all data should be received
+# there and none be logged to the file.
+# This builds on the basic sndrcv.sh test, but adds a first, failing,
+# location to the conf file.
+# added 2011-06-20 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export DEAD_PORT=4 # a port unassigned by IANA and very unlikely to be used
+export RSYSLOG_DEBUGLOG="log"
+
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+# then SENDER sends to this port (not tcpflood!)
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+export PORT_RCVR=$TCPFLOOD_PORT
+generate_conf 2
+add_conf '
+*.* @@127.0.0.1:'$DEAD_PORT' # this must be DEAD
+$ActionExecOnlyWhenPreviousIsSuspended on
+& @@127.0.0.1:'$PORT_RCVR'
+& ./'${RSYSLOG_DYNNAME}'.empty
+$ActionExecOnlyWhenPreviousIsSuspended off
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check
+
+ls -l ${RSYSLOG_DYNNAME}.empty
+if [[ -s ${RSYSLOG_DYNNAME}.empty ]] ; then
+ echo "FAIL: ${RSYSLOG_DYNNAME}.empty has data. Failover handling failed. Data is written"
+ echo " even though the previous action (in a failover chain!) properly"
+ echo " worked."
+ error_exit 1
+else
+ echo "${RSYSLOG_DYNNAME}.empty is empty - OK"
+fi ;
+exit_test
diff --git a/tests/sndrcv_gzip.sh b/tests/sndrcv_gzip.sh
new file mode 100755
index 0000000..2b56dd5
--- /dev/null
+++ b/tests/sndrcv_gzip.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# This test is similar to tcpsndrcv, but it forwards messages in
+# zlib-compressed format (our own syslog extension).
+# rgerhards, 2009-11-11
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+# then SENDER sends to this port (not tcpflood!)
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+export RCVR_PORT=$TCPFLOOD_PORT
+generate_conf 2
+add_conf '
+*.* @@(z5)127.0.0.1:'$RCVR_PORT'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_kafka.sh b/tests/sndrcv_kafka.sh
new file mode 100755
index 0000000..3b78fed
--- /dev/null
+++ b/tests/sndrcv_kafka.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+# added 2017-05-03 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export KEEP_KAFKA_RUNNING="YES"
+export TESTMESSAGES=100000
+export TESTMESSAGESFULL=100000
+
+# Generate random topic name
+export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+
+download_kafka
+stop_zookeeper
+stop_kafka
+start_zookeeper
+start_kafka
+
+create_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+$imdiagInjectDelayMode full
+
+module(load="../plugins/omkafka/.libs/omkafka")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+local4.* {
+ action( name="kafka-fwd"
+ type="omkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ template="outfmt"
+ confParam=[ "compression.codec=none",
+ "socket.timeout.ms=10000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "queue.buffering.max.messages=10000",
+ "enable.auto.commit=true",
+ "message.send.max.retries=1"]
+ topicConfParam=["message.timeout.ms=10000"]
+ partitions.auto="on"
+ closeTimeout="60000"
+ resubmitOnFailure="on"
+ keepFailedMessages="on"
+ failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC'.data"
+ action.resumeInterval="1"
+ action.resumeRetryCount="10"
+ queue.saveonshutdown="on"
+ )
+ stop
+}
+
+action( type="omfile" file="'$RSYSLOG_DYNNAME.snd.othermsg'")
+'
+
+echo Starting sender instance [omkafka]
+startup
+# ---
+
+# Injection messages now before starting receiver, simply because omkafka will take some time and
+# there is no reason to wait for the receiver to startup first.
+echo Inject messages into rsyslog sender instance
+injectmsg 1 $TESTMESSAGES
+
+# --- Create/Start imkafka receiver config
+export RSYSLOG_DEBUGLOG="log2"
+generate_conf 2
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC'"
+ broker="localhost:29092"
+ consumergroup="default"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=5000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "enable.partition.eof=false" ]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" )
+} else {
+ action( type="omfile" file="'$RSYSLOG_DYNNAME.rcv.othermsg'")
+}
+' 2
+
+echo Starting receiver instance [imkafka]
+startup 2
+# ---
+
+echo Stopping sender instance [omkafka]
+shutdown_when_empty
+wait_shutdown
+
+echo Stopping receiver instance [imkafka]
+kafka_wait_group_coordinator
+shutdown_when_empty 2
+wait_shutdown 2
+
+delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181'
+
+# Dump Kafka log | uncomment if needed
+# dump_kafka_serverlog
+
+kafka_check_broken_broker $RSYSLOG_DYNNAME.snd.othermsg
+kafka_check_broken_broker $RSYSLOG_DYNNAME.rcv.othermsg
+
+seq_check 1 $TESTMESSAGESFULL -d
+
+echo success
+exit_test
diff --git a/tests/sndrcv_kafka_multi_topics.sh b/tests/sndrcv_kafka_multi_topics.sh
new file mode 100755
index 0000000..d0e297f
--- /dev/null
+++ b/tests/sndrcv_kafka_multi_topics.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+# added 2018-08-13 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+export TESTMESSAGES=50000
+export TESTMESSAGESFULL=100000
+
+# Generate random topic name
+export RANDTOPIC1=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+export RANDTOPIC2=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1)
+
+# Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only.
+export EXTRA_EXITCHECK=dumpkafkalogs
+export EXTRA_EXIT=kafka
+echo STEP: Check and Stop previous instances of kafka/zookeeper
+download_kafka
+stop_zookeeper
+stop_kafka
+
+echo STEP: Create kafka/zookeeper instance and topics
+start_zookeeper
+start_kafka
+create_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181'
+create_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181'
+
+# --- Create omkafka sender config
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+$imdiagInjectDelayMode full
+
+module(load="../plugins/omkafka/.libs/omkafka")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+local4.* action( name="kafka-fwd"
+ type="omkafka"
+ topic="'$RANDTOPIC1'"
+ broker="localhost:29092"
+ template="outfmt"
+ confParam=[ "compression.codec=none",
+ "socket.timeout.ms=10000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "queue.buffering.max.messages=10000",
+ "enable.auto.commit=true",
+ "message.send.max.retries=1"]
+ topicConfParam=["message.timeout.ms=10000"]
+ partitions.auto="on"
+ closeTimeout="60000"
+ resubmitOnFailure="on"
+ keepFailedMessages="on"
+ failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC1'.data"
+ action.resumeInterval="1"
+ action.resumeRetryCount="10"
+ queue.saveonshutdown="on"
+ )
+local4.* action( name="kafka-fwd"
+ type="omkafka"
+ topic="'$RANDTOPIC2'"
+ broker="localhost:29092"
+ template="outfmt"
+ confParam=[ "compression.codec=none",
+ "socket.timeout.ms=10000",
+ "socket.keepalive.enable=true",
+ "reconnect.backoff.jitter.ms=1000",
+ "queue.buffering.max.messages=10000",
+ "enable.auto.commit=true",
+ "message.send.max.retries=1"]
+ topicConfParam=["message.timeout.ms=10000"]
+ partitions.auto="on"
+ closeTimeout="60000"
+ resubmitOnFailure="on"
+ keepFailedMessages="on"
+ failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC2'.data"
+ action.resumeInterval="1"
+ action.resumeRetryCount="10"
+ queue.saveonshutdown="on"
+ )
+
+syslog.* action(type="omfile" file="'$RSYSLOG_DYNNAME.sender.syslog'")
+'
+
+echo STEP: Starting sender instance [omkafka]
+startup
+# ---
+
+# Injection messages now before starting receiver, simply because omkafka will take some time and
+# there is no reason to wait for the receiver to startup first.
+echo STEP: Inject messages into rsyslog sender instance
+injectmsg 1 $TESTMESSAGES
+
+# --- Create omkafka receiver config
+export RSYSLOG_DEBUGLOG="log2"
+generate_conf 2
+add_conf '
+main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000")
+
+module(load="../plugins/imkafka/.libs/imkafka")
+/* Polls messages from kafka server!*/
+input( type="imkafka"
+ topic="'$RANDTOPIC1'"
+ broker="localhost:29092"
+ consumergroup="default1"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=10000",
+ "enable.partition.eof=false",
+ "reconnect.backoff.jitter.ms=1000",
+ "socket.keepalive.enable=true"]
+ )
+input( type="imkafka"
+ topic="'$RANDTOPIC2'"
+ broker="localhost:29092"
+ consumergroup="default2"
+ confParam=[ "compression.codec=none",
+ "session.timeout.ms=10000",
+ "socket.timeout.ms=10000",
+ "enable.partition.eof=false",
+ "reconnect.backoff.jitter.ms=1000",
+ "socket.keepalive.enable=true"]
+ )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if ($msg contains "msgnum:") then {
+ action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" )
+}
+
+syslog.* action(type="omfile" file="'$RSYSLOG_DYNNAME.receiver.syslog'")
+' 2
+
+echo STEP: Starting receiver instance [imkafka]
+startup 2
+# ---
+
+echo STEP: Stopping sender instance [omkafka]
+shutdown_when_empty
+wait_shutdown
+
+echo STEP: Stopping receiver instance [imkafka]
+kafka_wait_group_coordinator
+shutdown_when_empty 2
+wait_shutdown 2
+
+echo STEP: delete kafka topics
+delete_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181'
+delete_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181'
+
+kafka_check_broken_broker "$RSYSLOG_DYNNAME.sender.syslog"
+kafka_check_broken_broker "$RSYSLOG_DYNNAME.receiver.syslog"
+
+# Dump Kafka log | uncomment if needed
+# dump_kafka_serverlog
+
+# Do the final sequence check
+seq_check 1 $TESTMESSAGES -d
+
+linecount=$(wc -l < ${RSYSLOG_OUT_LOG})
+if [ $linecount -ge $TESTMESSAGESFULL ]; then
+ echo "Info: Count correct: $linecount"
+else
+ echo "Count error detected in $RSYSLOG_OUT_LOG"
+ echo "number of lines in file: $linecount"
+ error_exit 1
+fi
+
+echo success
+exit_test
diff --git a/tests/sndrcv_omsnmpv1_udp.sh b/tests/sndrcv_omsnmpv1_udp.sh
new file mode 100755
index 0000000..a259e96
--- /dev/null
+++ b/tests/sndrcv_omsnmpv1_udp.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# alorbach, 2019-11-27
+# Required Packages
+# pip install pysnmp
+#
+# Ubuntu 18 Packages needed
+# apt install snmp libsnmp-dev snmp-mibs-downloader
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=10
+
+generate_conf
+export PORT_SNMP="$(get_free_port)"
+# Start SNMP Trap Receiver
+snmp_start_trapreceiver ${PORT_SNMP} ${RSYSLOG_OUT_LOG}
+
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+module( load="../plugins/omsnmp/.libs/omsnmp" )
+
+# set up the action
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omsnmp"
+ name="name"
+ server="127.0.0.1"
+ port="'${PORT_SNMP}'"
+ version="0"
+ community="public"
+ enterpriseOID="1.3.6.1.2.1.192.0.1"
+ messageOID="1.3.6.1.2.1.192.1.2.1.11"
+ TrapType="6"
+ specificType="0"
+ )
+'
+startup
+tcpflood -p$TCPFLOOD_PORT -m${TESTMESSAGES}
+netstat -l
+
+shutdown_when_empty
+wait_shutdown
+snmp_stop_trapreceiver
+content_count_check "msgnum:" ${TESTMESSAGES}
+exit_test
diff --git a/tests/sndrcv_omsnmpv1_udp_dynsource.sh b/tests/sndrcv_omsnmpv1_udp_dynsource.sh
new file mode 100755
index 0000000..1f3e886
--- /dev/null
+++ b/tests/sndrcv_omsnmpv1_udp_dynsource.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# alorbach, 2019-11-27
+# Required Packages
+# pip install pysnmp
+#
+# Ubuntu 18 Packages needed
+# apt install snmp libsnmp-dev snmp-mibs-downloader
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=10
+
+generate_conf
+export PORT_SNMP="$(get_free_port)"
+# Start SNMP Trap Receiver
+snmp_start_trapreceiver ${PORT_SNMP} ${RSYSLOG_OUT_LOG}
+
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+module( load="../plugins/omsnmp/.libs/omsnmp" )
+
+# set up templates
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+# Set Custom Host property
+set $!custom_host = "8.8.8.8";
+template(name="dynsource" type="list") {
+ property(name="$!custom_host")
+}
+
+# set up the action
+:msg, contains, "msgnum:" action( type="omsnmp"
+ name="name"
+ server="127.0.0.1"
+ port="'${PORT_SNMP}'"
+ version="0"
+ community="public"
+ enterpriseOID="1.3.6.1.2.1.192.0.1"
+ messageOID="1.3.6.1.2.1.192.1.2.1.11"
+ TrapType="6"
+ specificType="0"
+ snmpv1dynsource="dynsource"
+ )
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m${TESTMESSAGES}
+
+shutdown_when_empty
+wait_shutdown
+snmp_stop_trapreceiver
+content_count_check "msgnum:" ${TESTMESSAGES}
+content_count_check "8.8.8.8" ${TESTMESSAGES}
+exit_test
diff --git a/tests/sndrcv_omsnmpv1_udp_invalidoid.sh b/tests/sndrcv_omsnmpv1_udp_invalidoid.sh
new file mode 100755
index 0000000..4197209
--- /dev/null
+++ b/tests/sndrcv_omsnmpv1_udp_invalidoid.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# alorbach, 2019-11-27
+# Required Packages
+# pip install pysnmp
+#
+# Ubuntu 18 Packages needed
+# apt install snmp libsnmp-dev
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TESTMESSAGES=1
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.omsnmp.debuglog"
+generate_conf
+export PORT_SNMP="$(get_free_port)"
+# Start SNMP Trap Receiver
+snmp_start_trapreceiver ${PORT_SNMP} ${RSYSLOG_OUT_LOG}
+
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+module( load="../plugins/omsnmp/.libs/omsnmp" )
+
+# set up the action
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omsnmp"
+ name="name"
+ server="127.0.0.1"
+ port="'${PORT_SNMP}'"
+ version="0"
+ community="public"
+ enterpriseOID="1337.1.3.3.7.1.3.3.7"
+ messageOID="invalidOIDstring"
+ TrapType="5"
+ specificType="0"
+ )
+'
+startup
+tcpflood -p'$TCPFLOOD_PORT' -m${TESTMESSAGES}
+
+shutdown_when_empty
+wait_shutdown
+snmp_stop_trapreceiver
+content_check "Parsing SyslogMessageOID failed" ${RSYSLOG_DYNNAME}.started
+content_check "Unknown Object Identifier" ${RSYSLOG_DYNNAME}.started
+exit_test
diff --git a/tests/sndrcv_omudpspoof-bigmsg.sh b/tests/sndrcv_omudpspoof-bigmsg.sh
new file mode 100755
index 0000000..6d61793
--- /dev/null
+++ b/tests/sndrcv_omudpspoof-bigmsg.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+# This runs sends and receives big messages via OMUDPSPOOF
+# added 2020-04-07 alorbach
+# This file is part of the rsyslog project, released under GPLv3
+echo This test must be run as root [raw socket access required]
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+export TCPFLOOD_EXTRA_OPTS="-b1 -W1"
+export NUMMESSAGES=1
+export MESSAGESIZE=65000 #65000 #32768 #16384
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_UDP="$(get_free_port)"
+
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+global (
+ maxMessageSize="64k"
+)
+
+input(type="imudp" port="'$PORT_UDP'" ruleset="rsImudp")
+$template outfmt,"%msg%\n"
+
+ruleset(name="rsImudp") {
+ action( name="UDPOUT"
+ type="omfile"
+ file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+'
+startup
+
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+module(load="../plugins/omudpspoof/.libs/omudpspoof")
+
+global (
+ maxMessageSize="64k"
+)
+
+# this listener is for message generation by the test framework!
+input(type="imtcp" port="'$TCPFLOOD_PORT'" ruleset="rsImtcp")
+
+$template spoofaddr,"127.0.0.1"
+
+ruleset(name="rsImtcp") {
+ action( name="MTUTEST"
+ type="omudpspoof"
+ Target="127.0.0.1"
+ Port="'$PORT_UDP'"
+ SourceTemplate="spoofaddr"
+ mtu="1500")
+# for comparison only -> action(name="MTUTEST" type="omfwd" Target="127.0.0.1" Port="'$PORT_UDP'")
+}
+
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+# tcpflood -m$NUMMESSAGES -i1 -d 1024
+tcpflood -m$NUMMESSAGES -i1 -d $MESSAGESIZE
+
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+content_count_check "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ${NUMMESSAGES}
diff --git a/tests/sndrcv_omudpspoof.sh b/tests/sndrcv_omudpspoof.sh
new file mode 100755
index 0000000..d46be1a
--- /dev/null
+++ b/tests/sndrcv_omudpspoof.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# This runs sends and receives messages via UDP to the standard
+# ports. Note that with UDP we can always have message loss. While this is
+# less likely in a local environment, we strongly limit the amount of data
+# we send in the hope to not lose any messages. However, failure of this
+# test does not necessarily mean that the code is wrong (but it is very likely!)
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[sndrcv_omudpspoof.sh\]: testing sending and receiving via omudp
+echo This test must be run as root [raw socket access required]
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+export TCPFLOOD_EXTRA_OPTS="-b1 -W1"
+
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+# then SENDER sends to this port (not tcpflood!)
+$UDPServerRun 514
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'"
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+# this listener is for message generation by the test framework!
+$InputTCPServerRun '$TCPFLOOD_PORT'
+
+$ModLoad ../plugins/omudpspoof/.libs/omudpspoof
+$template spoofaddr,"127.0.0.1"
+
+#begin action definition
+$ActionOMUDPSpoofSourceNameTemplate spoofaddr
+$ActionOMUDPSpoofTargetHost 127.0.0.1
+$ActionOMUDPSpoofSourcePortStart 514
+$ActionOMUDPSpoofSourcePortEnd 514
+*.* :omudpspoof:
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m50 -i1
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 50
diff --git a/tests/sndrcv_omudpspoof_nonstdpt.sh b/tests/sndrcv_omudpspoof_nonstdpt.sh
new file mode 100755
index 0000000..c61e39c
--- /dev/null
+++ b/tests/sndrcv_omudpspoof_nonstdpt.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# This runs sends and receives messages via UDP to the standard
+# ports. Note that with UDP we can always have message loss. While this is
+# less likely in a local environment, we strongly limit the amount of data
+# we send in the hope to not lose any messages. However, failure of this
+# test does not necessarily mean that the code is wrong (but it is very likely!)
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[sndrcv_omudpspoof_nonstdpt.sh\]: testing sending and receiving via omudp
+echo This test must be run as root [raw socket access required]
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+export TCPFLOOD_EXTRA_OPTS="-b1 -W1"
+
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+# then SENDER sends to this port (not tcpflood!)
+$UDPServerRun 2514
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'"
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+# this listener is for message generation by the test framework!
+$InputTCPServerRun '$TCPFLOOD_PORT'
+
+$ModLoad ../plugins/omudpspoof/.libs/omudpspoof
+$template spoofaddr,"127.0.0.1"
+
+#begin action definition
+$ActionOMUDPSpoofSourceNameTemplate spoofaddr
+$ActionOMUDPSpoofTargetHost 127.0.0.1
+$ActionOMUDPSpoofTargetPort 2514
+$ActionOMUDPSpoofSourcePortStart 514
+$ActionOMUDPSpoofSourcePortEnd 514
+*.* :omudpspoof:
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m50 -i1
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 50
diff --git a/tests/sndrcv_ossl_cert_chain.sh b/tests/sndrcv_ossl_cert_chain.sh
new file mode 100755
index 0000000..b5a524c
--- /dev/null
+++ b/tests/sndrcv_ossl_cert_chain.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+### This is important, as it must be exactly the same
+### as the ones configured in used certificates
+export HOSTNAME="fedora"
+add_conf '
+global(
+ DefaultNetstreamDriver="ossl"
+ DefaultNetstreamDriverCAFile="'$srcdir/testsuites/certchain/ca-cert.pem'"
+ DefaultNetstreamDriverCertFile="'$srcdir/testsuites/certchain/server-cert.pem'"
+ DefaultNetstreamDriverKeyFile="'$srcdir/testsuites/certchain/server-key.pem'"
+ NetstreamDriverCAExtraFiles="'$srcdir/testsuites/certchain/ca-root-cert.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ PermittedPeer="'$HOSTNAME'"
+ StreamDriver.AuthMode="x509/name" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/certchain/ca-root-cert.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/certchain/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/certchain/client-key.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+$ModLoad ../plugins/imtcp/.libs/imtcp
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="ossl"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/name"
+ StreamDriverPermittedPeers="'$HOSTNAME'"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_relp-vg-rcvr.sh b/tests/sndrcv_relp-vg-rcvr.sh
new file mode 100755
index 0000000..030d35c
--- /dev/null
+++ b/tests/sndrcv_relp-vg-rcvr.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# added 2022-06-21 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+# CHECK VALGRIND MINIMUM VERSION | MIN 3.14.0
+VALGRINDVER=$(valgrind --version)
+VALGRINDVERMAJOR=$(echo $VALGRINDVER | cut -d'-' -f2 | cut -d'.' -f1)
+VALGRINDVERMINOR=$(echo $VALGRINDVER | cut -d'-' -f2 | cut -d'.' -f2)
+if [ "$VALGRINDVERMAJOR" -lt 3 ] || { [ "$VALGRINDVERMAJOR" -eq 3 ] && [ "$VALGRINDVERMINOR" -lt 15 ]; }; then
+ printf 'This test does NOT work with versions below valgrind-3.15.0 (missing --keep-debuginfo) - Installed valgrind version is '
+ printf $VALGRINDVER
+ printf '\n'
+ exit 77
+fi
+
+export NUMMESSAGES=5000
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes --leak-check=full"
+########## receiver ##########
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$PORT_RCVR'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup_vg
+printf "#### RECEIVER STARTED\n\n"
+
+########## sender ##########
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" name="omrelp" target="127.0.0.1" port="'$PORT_RCVR'")
+' 2
+
+startup 2
+printf "#### SENDER STARTED\n\n"
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 0 $NUMMESSAGES
+
+shutdown_when_empty 2
+wait_shutdown 2
+
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown_vg
+seq_check
+check_exit_vg
+
+exit_test
diff --git a/tests/sndrcv_relp-vg-sender.sh b/tests/sndrcv_relp-vg-sender.sh
new file mode 100755
index 0000000..4b8a6a6
--- /dev/null
+++ b/tests/sndrcv_relp-vg-sender.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# added 2022-06-21 by alorbach
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+# CHECK VALGRIND MINIMUM VERSION | MIN 3.14.0
+VALGRINDVER=$(valgrind --version)
+VALGRINDVERMAJOR=$(echo $VALGRINDVER | cut -d'-' -f2 | cut -d'.' -f1)
+VALGRINDVERMINOR=$(echo $VALGRINDVER | cut -d'-' -f2 | cut -d'.' -f2)
+if [ "$VALGRINDVERMAJOR" -lt 3 ] || { [ "$VALGRINDVERMAJOR" -eq 3 ] && [ "$VALGRINDVERMINOR" -lt 15 ]; }; then
+ printf 'This test does NOT work with versions below valgrind-3.15.0 (missing --keep-debuginfo) - Installed valgrind version is '
+ printf $VALGRINDVER
+ printf '\n'
+ exit 77
+fi
+
+export NUMMESSAGES=5000
+export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes --leak-check=full"
+########## receiver ##########
+export RSYSLOG_DEBUG="debug nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$PORT_RCVR'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+printf "#### RECEIVER STARTED\n\n"
+
+########## sender ##########
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" name="omrelp" target="127.0.0.1" port="'$PORT_RCVR'")
+' 2
+
+startup_vg 2
+printf "#### SENDER STARTED\n\n"
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 0 $NUMMESSAGES
+
+printf "#### SENDER SHUTDOWN\n\n"
+shutdown_when_empty 2
+wait_shutdown_vg 2
+check_exit_vg 2
+
+printf "#### RECEIVER SHUTDOWN\n\n"
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+seq_check
+exit_test
diff --git a/tests/sndrcv_relp.sh b/tests/sndrcv_relp.sh
new file mode 100755
index 0000000..a5b957c
--- /dev/null
+++ b/tests/sndrcv_relp.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# added 2013-12-10 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=50000
+########## receiver ##########
+#export RSYSLOG_DEBUG="debug nostdout"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+input(type="imrelp" port="'$PORT_RCVR'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+printf "#### RECEIVER STARTED\n\n"
+
+########## sender ##########
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" name="omrelp" target="127.0.0.1" port="'$PORT_RCVR'")
+' 2
+startup 2
+printf "#### SENDER STARTED\n\n"
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 0 50000
+
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_relp_dflt_pt.sh b/tests/sndrcv_relp_dflt_pt.sh
new file mode 100755
index 0000000..8427e09
--- /dev/null
+++ b/tests/sndrcv_relp_dflt_pt.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# this checks if omrelp works with the default port
+# Note: imrelp requires the port, so we cannot and must not
+# check the "default port"
+# added 2013-12-10 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+relp_port=$(./omrelp_dflt_port)
+if [ $relp_port -lt 1024 ]; then
+ if [ "$EUID" -ne 0 ]; then
+ echo relp default port $relp_port is privileged
+ echo need to be root to run this test - skipping
+ exit 77
+ fi
+fi
+
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$relp_port'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" target="127.0.0.1")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 50000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 50000
+exit_test
diff --git a/tests/sndrcv_relp_rebind.sh b/tests/sndrcv_relp_rebind.sh
new file mode 100755
index 0000000..2e8cd93
--- /dev/null
+++ b/tests/sndrcv_relp_rebind.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# added 2017-09-29 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+echo testing sending and receiving via relp w/ rebind interval
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$PORT_RCVR'")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+# We know that a rebind interval of 1 is NOT what you would normally expect in
+# production. However, this stresses the code the most and we have seen that
+# some problems do not reliably occur if we use higher rebind intervals. Thus
+# we consider it to be a good, actually required, setting.
+action(type="omrelp" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" rebindinterval="1")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 1000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 1000
+exit_test
diff --git a/tests/sndrcv_relp_tls-cfgcmd.sh b/tests/sndrcv_relp_tls-cfgcmd.sh
new file mode 100755
index 0000000..d13637b
--- /dev/null
+++ b/tests/sndrcv_relp_tls-cfgcmd.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# added 2019-11-13 by alorbach
+. ${srcdir:=.}/diag.sh init
+require_relpEngineSetTLSLibByName
+export PORT_RCVR="$(get_free_port)"
+export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="openssl")
+# then SENDER sends to this port (not tcpflood!)
+input( type="imrelp" port="'$PORT_RCVR'" tls="on"
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2
+CipherString=ECDHE-RSA-AES256-GCM-SHA384
+Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2,-TLSv1.3
+MinProtocol=TLSv1.2
+MaxProtocol=TLSv1.2"
+ )
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+module( load="../plugins/omrelp/.libs/omrelp"
+ tls.tlslib="openssl")
+
+action( type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on"
+ tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2
+CipherString=DHE-RSA-AES256-SHA
+Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2,-TLSv1.3
+MinProtocol=TLSv1.1
+MaxProtocol=TLSv1.1" )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 1000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+content_check --check-only "relpTcpConnectTLSInit_gnutls" ${RSYSLOG_DEBUGLOG}
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: LIBRELP was build without OPENSSL Support"
+ skip_test
+fi
+
+content_check --check-only "OpenSSL Version too old" $RSYSLOG_DEBUGLOG
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: OpenSSL Version too old"
+ skip_test
+else
+ # Kindly check for a failed session
+ content_check "librelp: generic error: ecode 10031" $RSYSLOG_DEBUGLOG
+# content_check "OpenSSL Error Stack:"
+fi
+
+exit_test \ No newline at end of file
diff --git a/tests/sndrcv_relp_tls.sh b/tests/sndrcv_relp_tls.sh
new file mode 100755
index 0000000..35b43a1
--- /dev/null
+++ b/tests/sndrcv_relp_tls.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# added 2013-12-10 by Rgerhards
+# testing sending and receiving via relp with TLS enabled
+# This file is part of the rsyslog project, released under ASL 2.0
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$PORT_RCVR'" tls="on")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 50000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 50000
+
+exit_test
diff --git a/tests/sndrcv_relp_tls_certvalid.sh b/tests/sndrcv_relp_tls_certvalid.sh
new file mode 100755
index 0000000..728b2a1
--- /dev/null
+++ b/tests/sndrcv_relp_tls_certvalid.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# added 2018-09-13 by PascalWithopf
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$PORT_RCVR'" tls="on"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+:msg, contains, "msgnum:" action(type="omrelp"
+ target="127.0.0.1" port="'$PORT_RCVR'" tls="on"
+ tls.cacert="'$srcdir'/tls-certs/ca.pem"
+ tls.mycert="'$srcdir'/tls-certs/cert.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+action(type="omfile" file="'$RSYSLOG_DYNNAME.errmsgs'")
+' 2
+startup 2
+
+grep "omrelp error: invalid authmode" $RSYSLOG_DYNNAME.errmsgs > /dev/null
+if [ $? -eq 0 ]; then
+ echo "SKIP: librelp does not support "certvalid" auth mode"
+ # mini-cleanup to not leave dangling processes
+ shutdown_immediate 2
+ shutdown_immediate
+ rm $RSYSLOG_DYNNAME* &> /dev/null
+ exit 77
+fi
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 50000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 50000
+exit_test
diff --git a/tests/sndrcv_relp_tls_chainedcert.sh b/tests/sndrcv_relp_tls_chainedcert.sh
new file mode 100755
index 0000000..7755a93
--- /dev/null
+++ b/tests/sndrcv_relp_tls_chainedcert.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# addd 2020-08-25 by alorbach, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+require_relpEngineVersion "1.7.0"
+export NUMMESSAGES=1000
+export TB_TEST_MAX_RUNTIME=30
+
+# uncomment for debugging support:
+# export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+# export RSYSLOG_DEBUGLOG="log"
+
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module( load="../plugins/imrelp/.libs/imrelp"
+ tls.tlslib="openssl")
+
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$PORT_RCVR'"
+ tls="on"
+ tls.mycert="'$srcdir'/tls-certs/certchained.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+module( load="../plugins/omrelp/.libs/omrelp"
+ tls.tlslib="openssl")
+
+:msg, contains, "msgnum:" action(type="omrelp"
+ target="127.0.0.1" port="'$PORT_RCVR'"
+ tls="on"
+ tls.mycert="'$srcdir'/tls-certs/certchained.pem"
+ tls.myprivkey="'$srcdir'/tls-certs/key.pem"
+ tls.authmode="certvalid"
+ tls.permittedpeer="rsyslog")
+action(type="omfile" file="'$RSYSLOG_DYNNAME.errmsgs'")
+' 2
+startup 2
+
+if grep "omrelp error: invalid authmode" < "$RSYSLOG_DYNNAME.errmsgs" ; then
+ echo "SKIP: librelp does not support "certvalid" auth mode"
+ # mini-cleanup to not leave dangling processes
+ shutdown_immediate 2
+ shutdown_immediate
+ rm $RSYSLOG_DYNNAME* &> /dev/null
+ exit 77
+fi
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 $NUMMESSAGES
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_relp_tls_prio.sh b/tests/sndrcv_relp_tls_prio.sh
new file mode 100755
index 0000000..78bdadd
--- /dev/null
+++ b/tests/sndrcv_relp_tls_prio.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# added 2013-12-10 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+echo testing sending and receiving via relp with TLS enabled and priority string set
+
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imrelp/.libs/imrelp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imrelp" port="'$PORT_RCVR'" tls="on" tls.prioritystring="NORMAL:+ANON-DH")
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+module(load="../plugins/omrelp/.libs/omrelp")
+
+action(type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on" tls.prioritystring="NORMAL:+ANON-DH")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 50000
+
+# shut down sender
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 50000
+exit_test
diff --git a/tests/sndrcv_tls_anon_hostname.sh b/tests/sndrcv_tls_anon_hostname.sh
new file mode 100755
index 0000000..8d0efff
--- /dev/null
+++ b/tests/sndrcv_tls_anon_hostname.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# rgerhards, 2011-04-04
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=25000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+# start up the instances
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RCVR_PORT=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@localhost:'$RCVR_PORT'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_anon_ipv4.sh b/tests/sndrcv_tls_anon_ipv4.sh
new file mode 100755
index 0000000..9a9fc3d
--- /dev/null
+++ b/tests/sndrcv_tls_anon_ipv4.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# rgerhards, 2011-04-04
+# testing sending and receiving via TLS with anon auth using bare ipv4, no SNI
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=25000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RCVR_PORT=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+# set up the action
+$DefaultNetstreamDriver gtls # use gtls netstream driver
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@127.0.0.1:'$RCVR_PORT'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_anon_ipv6.sh b/tests/sndrcv_tls_anon_ipv6.sh
new file mode 100755
index 0000000..1770b17
--- /dev/null
+++ b/tests/sndrcv_tls_anon_ipv6.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# rgerhards, 2011-04-04
+# testing sending and receiving via TLS with anon auth using bare ipv6, no SNI
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+. $srcdir/diag.sh check-ipv6-available
+export NUMMESSAGES=25000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+
+# start up the instances
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem"
+ defaultNetstreamDriver="gtls"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100"
+ streamDriver.mode="1" streamDriver.authMode="anon")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+#unset RSYSLOG_DEBUG # suppress this debug log, if you want
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+# set up the action
+$DefaultNetstreamDriver gtls # use gtls netstream driver
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@[::1]:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_anon_rebind.sh b/tests/sndrcv_tls_anon_rebind.sh
new file mode 100755
index 0000000..96a6734
--- /dev/null
+++ b/tests/sndrcv_tls_anon_rebind.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# testing sending and receiving via TLS with anon auth and rebind
+# rgerhards, 2011-04-04
+# This file is part of the rsyslog project, released under GPLv3
+. ${srcdir:=.}/diag.sh init
+# uncomment for debugging support:
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config
+
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+$ActionSendTCPRebindInterval 50
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 1 25000
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 25000
+exit_test
diff --git a/tests/sndrcv_tls_certless_clientonly.sh b/tests/sndrcv_tls_certless_clientonly.sh
new file mode 100755
index 0000000..8a4e00d
--- /dev/null
+++ b/tests/sndrcv_tls_certless_clientonly.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# all we want to test is if certless communication works. So we do
+# not need to send many messages.
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+# receiver
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+# sender
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+#export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global(defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'")
+
+# Note: no TLS for the listener, this is for tcpflood!
+$ModLoad ../plugins/imtcp/.libs/imtcp
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'"
+ StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_certvalid.sh b/tests/sndrcv_tls_certvalid.sh
new file mode 100755
index 0000000..b00e292
--- /dev/null
+++ b/tests/sndrcv_tls_certvalid.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="'$RS_TLS_DRIVER'"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode x509/certvalid
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_certvalid_action_level.sh b/tests/sndrcv_tls_certvalid_action_level.sh
new file mode 100755
index 0000000..561af6e
--- /dev/null
+++ b/tests/sndrcv_tls_certvalid_action_level.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="'$RS_TLS_DRIVER'"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+action(type="omfwd" target="127.0.0.1" port="'$PORT_RCVR'" protocol="tcp"
+ streamDriverMode="1"
+ streamDriverAuthMode="x509/certvalid"
+ streamdriver.cafile="'$srcdir'/tls-certs/ca.pem"
+ streamdriver.keyfile="'$srcdir'/tls-certs/key.pem"
+ streamdriver.certfile="'$srcdir'/tls-certs/cert.pem"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_certvalid_expired.sh b/tests/sndrcv_tls_certvalid_expired.sh
new file mode 100755
index 0000000..bab916c
--- /dev/null
+++ b/tests/sndrcv_tls_certvalid_expired.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+
+# start up the instances
+# export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="'$RS_TLS_DRIVER'"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+content_check --regex "not permitted to talk to peer '.*', certificate invalid: certificate expired"
+
+exit_test
diff --git a/tests/sndrcv_tls_certvalid_expired_defaultmode.sh b/tests/sndrcv_tls_certvalid_expired_defaultmode.sh
new file mode 100755
index 0000000..47aaa10
--- /dev/null
+++ b/tests/sndrcv_tls_certvalid_expired_defaultmode.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'"
+ defaultNetstreamDriver="gtls"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode x509/certvalid
+*.* @@127.0.0.1:'$PORT_RCVR'
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+content_check --regex "not permitted to talk to peer '.*', certificate invalid: certificate expired"
+
+exit_test
diff --git a/tests/sndrcv_tls_certvalid_revoked.sh b/tests/sndrcv_tls_certvalid_revoked.sh
new file mode 100755
index 0000000..b01699e
--- /dev/null
+++ b/tests/sndrcv_tls_certvalid_revoked.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultnetstreamdriverCRLfile="'$srcdir/testsuites/x.509/crl.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert-new.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="'$RS_TLS_DRIVER'"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultnetstreamdriverCRLfile="'$srcdir/testsuites/x.509/crl.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-revoked.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-revoked-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+if [ -z "$TEXT_TO_CHECK" ]; then
+ TEXT_TO_CHECK="not permitted to talk to peer '.*', certificate invalid: certificate revoked"
+fi
+content_check --regex "$TEXT_TO_CHECK"
+
+exit_test
diff --git a/tests/sndrcv_tls_client_missing_cert.sh b/tests/sndrcv_tls_client_missing_cert.sh
new file mode 100755
index 0000000..7045416
--- /dev/null
+++ b/tests/sndrcv_tls_client_missing_cert.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls}
+
+# start up the instances
+# export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="'$RS_TLS_DRIVER'"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+/*
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'"
+*/
+ defaultNetstreamDriver="'$RS_TLS_DRIVER'"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+content_check --regex "peer .* did not provide a certificate,"
+
+exit_test
diff --git a/tests/sndrcv_tls_gtls_serveranon_gtls_clientanon.sh b/tests/sndrcv_tls_gtls_serveranon_gtls_clientanon.sh
new file mode 100755
index 0000000..d8d13a4
--- /dev/null
+++ b/tests/sndrcv_tls_gtls_serveranon_gtls_clientanon.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+export RCVR_PORT=$TCPFLOOD_PORT
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$RCVR_PORT'"
+ StreamDriver="gtls"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="anon"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_gtls_serveranon_ossl_clientanon.sh b/tests/sndrcv_tls_gtls_serveranon_ossl_clientanon.sh
new file mode 100755
index 0000000..08e5cf1
--- /dev/null
+++ b/tests/sndrcv_tls_gtls_serveranon_ossl_clientanon.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="ossl"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="anon"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_gtls_servercert_gtls_clientanon.sh b/tests/sndrcv_tls_gtls_servercert_gtls_clientanon.sh
new file mode 100755
index 0000000..b473edf
--- /dev/null
+++ b/tests/sndrcv_tls_gtls_servercert_gtls_clientanon.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls"
+ StreamDriver.Mode="1" StreamDriver.AuthMode="anon" )
+
+# then SENDER sends to this port (not tcpflood!)
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+export RCVR_PORT=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'")
+
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$RCVR_PORT'"
+ StreamDriver="gtls"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh b/tests/sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh
new file mode 100755
index 0000000..b8cc1df
--- /dev/null
+++ b/tests/sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# all we want to test is if certless communication works. So we do
+# not need to send many messages.
+# This test checks legacy statements which are often given as
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=5000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+# receiver
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+startup
+
+# sender
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+#export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+# Note: no TLS for the listener, this is for tcpflood!
+$ModLoad ../plugins/imtcp/.libs/imtcp
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# NOTE: do NOT change legacy statements - they are used intentionally
+$DefaultNetstreamDriverCAFile '$srcdir/tls-certs/ca.pem'
+$ActionSendStreamDriver gtls
+$ActionSendStreamDriverMode 1
+$ActionSendStreamDriverAuthMode x509/name
+$ActionSendStreamDriverPermittedPeer *.rsyslog.com
+*.* @@localhost:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh b/tests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh
new file mode 100755
index 0000000..1cf2f44
--- /dev/null
+++ b/tests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="gtls"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="ossl"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_ossl_anon_ciphers.sh b/tests/sndrcv_tls_ossl_anon_ciphers.sh
new file mode 100755
index 0000000..80201ed
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_anon_ciphers.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriver="ossl"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon"
+ StreamDriver.PermitExpiredCerts="off"
+ gnutlsPriorityString="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_256_GCM_SHA384"
+ )
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+export PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriver="ossl"
+)
+
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="anon"
+ gnutlsPriorityString="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_128_GCM_SHA256"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg 0 1
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# IMPORTANT: this test will generate many error messages. This is exactly it's
+# intent. So do not think something is wrong. The content_check below checks
+# these error codes.
+
+content_check --check-only "TLS library does not support SSL_CONF_cmd"
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ # Kindly check for a failed session
+ content_check "OpenSSL Error Stack"
+ content_check "no shared cipher"
+fi
+
+exit_test
diff --git a/tests/sndrcv_tls_ossl_anon_ipv4.sh b/tests/sndrcv_tls_ossl_anon_ipv4.sh
new file mode 100755
index 0000000..8bb4836
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_anon_ipv4.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# testing sending and receiving via TLS with anon auth using bare ipv4, no SNI
+# rgerhards, 2011-04-04
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ "${TARGET:=127.0.0.1}" == "[::1]" ]; then
+. $srcdir/diag.sh check-ipv6-available
+fi
+export NUMMESSAGES=10000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="ossl"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="ossl"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@'${TARGET}':'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_tls_ossl_anon_ipv6.sh b/tests/sndrcv_tls_ossl_anon_ipv6.sh
new file mode 100755
index 0000000..a021112
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_anon_ipv6.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2020-01-16 by RGerhards, released under ASL 2.0
+export TARGET="[::1]"
+source ${srcdir:=.}/sndrcv_tls_ossl_anon_ipv4.sh
diff --git a/tests/sndrcv_tls_ossl_anon_rebind.sh b/tests/sndrcv_tls_ossl_anon_rebind.sh
new file mode 100755
index 0000000..6d7aaff
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_anon_rebind.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+# rgerhards, 2011-04-04
+# testing sending and receiving via TLS with anon auth and rebind
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=25000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+# debugging activated to try to solve https://github.com/rsyslog/rsyslog/issues/3256
+export RSYSLOG_DEBUG="debug nostdout"
+test_error_exit_handler() {
+ set -x
+ cat "$RSYSLOG_DYNNAME.receiver.debuglog"
+ cat "$RSYSLOG_DYNNAME.sender.debuglog"
+ set +x
+}
+
+#receiver
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="ossl"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action( type="omfile"
+ template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+
+#sender
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+export PORT_RCVR=$TCPFLOOD_PORT # save TCPFLOOD_PORT, generate_conf will overwrite it!
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="ossl"
+)
+
+# set up the action
+$DefaultNetstreamDriver ossl
+$ActionSendStreamDriverMode 1
+$ActionSendStreamDriverAuthMode anon
+$ActionSendTCPRebindInterval 100
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+export SEQ_CHECK_OPTIONS=-d
+seq_check
+
+exit_test
diff --git a/tests/sndrcv_tls_ossl_certvalid.sh b/tests/sndrcv_tls_ossl_certvalid.sh
new file mode 100755
index 0000000..1cb8325
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2020-01-17 by RGerhards, released under ASL 2.0
+export RS_TLS_DRIVER=ossl
+source ${srcdir:=.}/sndrcv_tls_certvalid.sh
diff --git a/tests/sndrcv_tls_ossl_certvalid_action_level.sh b/tests/sndrcv_tls_ossl_certvalid_action_level.sh
new file mode 100755
index 0000000..446995b
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid_action_level.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# added 2020-01-17 by RGerhards, released under ASL 2.0
+export RS_TLS_DRIVER=ossl
+source ${srcdir:=.}/sndrcv_tls_certvalid_action_level.sh
diff --git a/tests/sndrcv_tls_ossl_certvalid_ciphers.sh b/tests/sndrcv_tls_ossl_certvalid_ciphers.sh
new file mode 100755
index 0000000..62fd636
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid_ciphers.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="ossl"
+ debug.whitelist="on"
+ debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ gnutlsPriorityString="CipherString=ECDHE-RSA-AES256-GCM-SHA384\nCiphersuites=TLS_AES_256_GCM_SHA384"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="ossl"
+)
+
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ gnutlsPriorityString="CipherString=ECDHE-RSA-AES128-GCM-SHA256\nCiphersuites=TLS_AES_128_GCM_SHA256"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg 0 1
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# IMPORTANT: this test will generate many error messages. This is exactly it's
+# intent. So do not think something is wrong. The content_check below checks
+# these error codes.
+
+content_check --check-only "TLS library does not support SSL_CONF_cmd"
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ # Kindly check for a failed session
+ content_check "OpenSSL Error Stack"
+ content_check "no shared cipher"
+fi
+
+exit_test
diff --git a/tests/sndrcv_tls_ossl_certvalid_expired.sh b/tests/sndrcv_tls_ossl_certvalid_expired.sh
new file mode 100755
index 0000000..5439acf
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid_expired.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="ossl"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ )
+
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'"
+ defaultNetstreamDriver="ossl"
+)
+
+# set up the action
+$ActionSendStreamDriverMode 1 # require TLS for the connection
+$ActionSendStreamDriverAuthMode anon
+*.* @@127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+content_check "Certificate EXPIRED at depth"
+content_check "OpenSSL Error Stack:"
+exit_test
diff --git a/tests/sndrcv_tls_ossl_certvalid_revoked.sh b/tests/sndrcv_tls_ossl_certvalid_revoked.sh
new file mode 100755
index 0000000..f183fdc
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid_revoked.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# added 2020-01-17 by RGerhards, released under ASL 2.0
+export RS_TLS_DRIVER=ossl
+#export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+#export RSYSLOG_DEBUGLOG="log"
+source ${srcdir:=.}/sndrcv_tls_certvalid_revoked.sh
diff --git a/tests/sndrcv_tls_ossl_certvalid_tlscommand.sh b/tests/sndrcv_tls_ossl_certvalid_tlscommand.sh
new file mode 100755
index 0000000..b945abe
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_certvalid_tlscommand.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+# export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
+# start up the instances
+# export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
+generate_conf
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="ossl"
+# debug.whitelist="on"
+# debug.files=["nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"]
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="x509/certvalid"
+ StreamDriver.PermitExpiredCerts="off"
+ gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2\nOptions=Bugs"
+ )
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+export PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config
+export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
+generate_conf 2
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+ defaultNetstreamDriver="ossl"
+)
+
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ gnutlsPriorityString="Protocol=-ALL,TLSv1.2"
+)
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2 0 1
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# IMPORTANT: this test will generate many error messages. This is exactly it's
+# intent. So do not think something is wrong. The content_check below checks
+# these error codes.
+
+content_check --check-only "TLS library does not support SSL_CONF_cmd"
+ret=$?
+if [ $ret == 0 ]; then
+ echo "SKIP: TLS library does not support SSL_CONF_cmd"
+ skip_test
+else
+ content_check --check-only "SSL_ERROR_SYSCALL"
+ ret=$?
+ if [ $ret == 0 ]; then
+ # Found SSL_ERROR_SYSCALL errorcode, no further check needed
+ exit_test
+ else
+ # Check for a SSL_ERROR_SSL error code
+ content_check "SSL_ERROR_SSL"
+ content_check "OpenSSL Error Stack:"
+ fi
+fi
+
+exit_test
diff --git a/tests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh b/tests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh
new file mode 100755
index 0000000..eda6ce5
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="gtls"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="anon"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh b/tests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh
new file mode 100755
index 0000000..49bb0e1
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="ossl"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="anon"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh b/tests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh
new file mode 100755
index 0000000..c9aa2cf
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="gtls"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh b/tests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh
new file mode 100755
index 0000000..66bf0f9
--- /dev/null
+++ b/tests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# alorbach, 2019-01-16
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=1000
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'"
+)
+
+module( load="../plugins/imtcp/.libs/imtcp"
+ StreamDriver.Name="ossl"
+ StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" )
+# then SENDER sends to this port (not tcpflood!)
+input( type="imtcp" port="'$PORT_RCVR'" )
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)"
+add_conf '
+global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'"
+)
+
+# Note: no TLS for the listener, this is for tcpflood!
+module( load="../plugins/imtcp/.libs/imtcp")
+input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" )
+
+# set up the action
+action( type="omfwd"
+ protocol="tcp"
+ target="127.0.0.1"
+ port="'$PORT_RCVR'"
+ StreamDriver="ossl"
+ StreamDriverMode="1"
+ StreamDriverAuthMode="x509/certvalid"
+ )
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+wait_file_lines
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_tls_priorityString.sh b/tests/sndrcv_tls_priorityString.sh
new file mode 100755
index 0000000..2817bf0
--- /dev/null
+++ b/tests/sndrcv_tls_priorityString.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# Pascal Withopf, 2017-07-25
+# testing sending and receiving via TLS with anon auth
+# NOTE: When this test fails, it could be due to the priorityString being outdated!
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=2500
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+# start up the instances
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+# certificates
+global(
+ defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem"
+ defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem"
+ defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem"
+ defaultNetstreamDriver="gtls"
+)
+module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1"
+ StreamDriver.AuthMode="anon" gnutlspriorityString="NORMAL:-MD5")
+input(type="imtcp" port="'$PORT_RCVR'")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum" then {
+ action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'")
+}
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh
+add_conf '
+#certificates
+global(
+ defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'"
+ defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'"
+ defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'"
+ defaultNetstreamDriver="gtls"
+)
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="omfwd" Target="127.0.0.1" port="'$PORT_RCVR'" Protocol="tcp" streamdriver="gtls"
+ StreamDriverAuthMode="anon" StreamDriverMode="1"
+ gnutlsprioritystring="NORMAL:-MD5")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m$NUMMESSAGES -i1
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+
+wait_file_lines
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check 1 $NUMMESSAGES
+exit_test
diff --git a/tests/sndrcv_udp.sh b/tests/sndrcv_udp.sh
new file mode 100755
index 0000000..39fa680
--- /dev/null
+++ b/tests/sndrcv_udp.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# This runs sends and receives messages via UDP to the standard
+# ports. Note that with UDP we can always have message loss. While this is
+# less likely in a local environment, we strongly limit the amount of data
+# we send in the hope to not lose any messages. However, failure of this
+# test does not necessarily mean that the code is wrong (but it is very likely!)
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo \[sndrcv_udp.sh\]: testing sending and receiving via udp
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+export TCPFLOOD_EXTRA_OPTS="-b1 -W1"
+
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+# then SENDER sends to this port (not tcpflood!)
+$UDPServerRun '$PORT_RCVR'
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh
+add_conf '
+$ModLoad ../plugins/imtcp/.libs/imtcp
+# this listener is for message generation by the test framework!
+$InputTCPServerRun '$TCPFLOOD_PORT'
+
+*.* @127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m50 -i1
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 50
+
+unset PORT_RCVR # TODO: move to exit_test()?
+exit_test
diff --git a/tests/sndrcv_udp_nonstdpt.sh b/tests/sndrcv_udp_nonstdpt.sh
new file mode 100755
index 0000000..c792a22
--- /dev/null
+++ b/tests/sndrcv_udp_nonstdpt.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# This runs sends and receives messages via UDP to the non-standard port 2514
+# Note that with UDP we can always have message loss. While this is
+# less likely in a local environment, we strongly limit the amount of data
+# we send in the hope to not lose any messages. However, failure of this
+# test does not necessarily mean that the code is wrong (but it is very likely!)
+# added 2009-11-11 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export TCPFLOOD_EXTRA_OPTS="-b1 -W1"
+export NUMMESSAGES=50
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+# then SENDER sends to this port (not tcpflood!)
+$UDPServerRun '$TCPFLOOD_PORT'
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+export PORT_RCVR="$TCPFLOOD_PORT"
+
+#valgrind="valgrind"
+generate_conf 2
+add_conf '
+*.* @127.0.0.1:'$PORT_RCVR'
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+injectmsg2
+
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+seq_check
+exit_test
diff --git a/tests/sndrcv_udp_nonstdpt_v6.sh b/tests/sndrcv_udp_nonstdpt_v6.sh
new file mode 100755
index 0000000..948d9f8
--- /dev/null
+++ b/tests/sndrcv_udp_nonstdpt_v6.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# added 2014-11-05 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[sndrcv_udp_nonstdpt_v6.sh\]: testing sending and receiving via udp
+
+# uncomment for debugging support:
+. ${srcdir:=.}/diag.sh init
+# start up the instances
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+export RSYSLOG_DEBUGLOG="log"
+generate_conf
+export PORT_RCVR="$(get_free_port)"
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+# then SENDER sends to this port (not tcpflood!)
+input(type="imudp" address="127.0.0.1" port=`echo $PORT_RCVR`)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+export RSYSLOG_DEBUGLOG="log2"
+#valgrind="valgrind"
+generate_conf 2
+export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+# this listener is for message generation by the test framework!
+input(type="imtcp" port=`echo $TCPFLOOD_PORT`)
+
+action(type="omfwd"
+ target="127.0.0.1" port=`echo $PORT_RCVR`
+ protocol="udp" udp.sendDelay="1")
+' 2
+startup 2
+
+# now inject the messages into instance 2. It will connect to instance 1,
+# and that instance will record the data.
+tcpflood -m500 -i1
+sleep 5 # make sure all data is received in input buffers
+# shut down sender when everything is sent, receiver continues to run concurrently
+shutdown_when_empty 2
+wait_shutdown 2
+# now it is time to stop the receiver as well
+shutdown_when_empty
+wait_shutdown
+
+# do the final check
+seq_check 1 500
+
+unset PORT_RCVR # TODO: move to exit_test()?
+exit_test
diff --git a/tests/snmptrapreceiver.py b/tests/snmptrapreceiver.py
new file mode 100755
index 0000000..643a8c4
--- /dev/null
+++ b/tests/snmptrapreceiver.py
@@ -0,0 +1,104 @@
+# call this via "python[3] script name"
+import sys
+from pysnmp.entity import engine, config
+from pysnmp.carrier.asyncore.dgram import udp
+from pysnmp.entity.rfc3413 import ntfrcv
+from pysnmp.smi import builder, view, compiler, rfc1902
+from pyasn1.type.univ import OctetString
+
+# Global variables
+snmpport = 10162
+snmpip = "127.0.0.1"
+szOutputfile = "snmp.out"
+szSnmpLogfile = "snmp_server.log"
+
+# For vrebose output
+bDebug = False
+
+# Read command line params
+if len(sys.argv) > 1:
+ snmpport = int(sys.argv[1])
+if len(sys.argv) > 2:
+ snmpip = sys.argv[2]
+if len(sys.argv) > 3:
+ szOutputfile = sys.argv[3]
+if len(sys.argv) > 4:
+ szSnmpLogfile = sys.argv[4]
+
+# Create output files
+outputFile = open(szOutputfile,"w+")
+logFile = open(szSnmpLogfile,"a+")
+
+# Assemble MIB viewer
+mibBuilder = builder.MibBuilder()
+compiler.addMibCompiler(mibBuilder, sources=['file:///usr/share/snmp/mibs', 'file:///var/lib/snmp/mibs', '/usr/local/share/snmp/mibs/'])
+mibViewController = view.MibViewController(mibBuilder)
+# Pre-load MIB modules we expect to work with
+try:
+ mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB', 'SYSLOG-MSG-MIB')
+except Exception:
+ print("Failed loading MIBs")
+
+# Create SNMP engine with autogenernated engineID and pre-bound to socket transport dispatcher
+snmpEngine = engine.SnmpEngine()
+
+# Transport setup
+# UDP over IPv4, add listening interface/port
+config.addTransport(
+ snmpEngine,
+ udp.domainName + (1,),
+ udp.UdpTransport().openServerMode((snmpip, snmpport))
+)
+
+# SNMPv1/2c setup
+# SecurityName <-> CommunityName mapping
+config.addV1System(snmpEngine, 'my-area', 'public')
+
+print("Started SNMP Trap Receiver: %s, %s, Output: %s" % (snmpport, snmpip, szOutputfile))
+logFile.write("Started SNMP Trap Receiver: %s, %s, Output: %s" % (snmpport, snmpip, szOutputfile))
+logFile.flush()
+
+# Callback function for receiving notifications
+# noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal
+def cbReceiverSnmp(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx):
+ transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)
+ if (bDebug):
+ szDebug = str("Notification From: %s, Domain: %s, SNMP Engine: %s, Context: %s" %
+ (transportAddress, transportDomain, contextEngineId.prettyPrint(), contextName.prettyPrint()))
+ print(szDebug)
+ logFile.write(szDebug)
+ logFile.flush()
+
+ # Create output String
+ szOut = "Trap Source{}, Trap OID {}".format(transportAddress, transportDomain)
+
+ varBinds = [rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds]
+
+ for name, val in varBinds:
+ # Append to output String
+ szOut = szOut + ", Oid: {}, Value: {}".format(name.prettyPrint(), val.prettyPrint())
+
+ if isinstance(val, OctetString):
+ if (name.prettyPrint() != "SNMP-COMMUNITY-MIB::snmpTrapAddress.0"):
+ szOctets = val.asOctets()#.rstrip('\r').rstrip('\n')
+ szOut = szOut + ", Octets: {}".format(szOctets)
+ if (bDebug):
+ print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
+ outputFile.write(szOut)
+ if "\n" not in szOut:
+ outputFile.write("\n")
+ outputFile.flush()
+
+
+# Register SNMP Application at the SNMP engine
+ntfrcv.NotificationReceiver(snmpEngine, cbReceiverSnmp)
+
+# this job would never finish
+snmpEngine.transportDispatcher.jobStarted(1)
+
+# Run I/O dispatcher which would receive queries and send confirmations
+try:
+ snmpEngine.transportDispatcher.runDispatcher()
+except:
+ snmpEngine.transportDispatcher.closeDispatcher()
+ raise
diff --git a/tests/sparse_array_lookup_table-vg.sh b/tests/sparse_array_lookup_table-vg.sh
new file mode 100755
index 0000000..37519d6
--- /dev/null
+++ b/tests/sparse_array_lookup_table-vg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# added 2015-10-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/sparse_array_lookup_table.sh
diff --git a/tests/sparse_array_lookup_table.sh b/tests/sparse_array_lookup_table.sh
new file mode 100755
index 0000000..bb23959
--- /dev/null
+++ b/tests/sparse_array_lookup_table.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# test for sparse-array lookup-table and HUP based reloading of it
+# added 2015-10-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate_array.lkp_tbl")
+
+template(name="outfmt" type="string" string="%msg% %$.lkp%\n")
+
+set $.num = field($msg, 58, 2);
+
+set $.lkp = lookup("xlate", $.num);
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate_sparse_array.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+startup
+injectmsg 0 1
+wait_queueempty
+assert_content_missing "foo"
+injectmsg 0 5
+wait_queueempty
+content_check "msgnum:00000001: foo_old"
+content_check "msgnum:00000002: foo_old"
+content_check "msgnum:00000003: bar_old"
+content_check "msgnum:00000004: bar_old"
+assert_content_missing "baz"
+cp -f $srcdir/testsuites/xlate_sparse_array_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 6
+wait_queueempty
+content_check "msgnum:00000000: foo_new"
+content_check "msgnum:00000001: foo_new"
+content_check "msgnum:00000002: bar_new"
+content_check "msgnum:00000003: bar_new"
+content_check "msgnum:00000004: baz"
+content_check "msgnum:00000005: baz"
+cp -f $srcdir/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl
+issue_HUP
+await_lookup_table_reload
+injectmsg 0 15
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check "msgnum:00000000: quux"
+content_check "msgnum:00000001: quux"
+content_check "msgnum:00000002: foo_latest"
+content_check "msgnum:00000003: baz_latest"
+content_check "msgnum:00000004: foo_latest"
+content_check "msgnum:00000005: foo_latest"
+content_check "msgnum:00000006: foo_latest"
+content_check "msgnum:00000007: foo_latest"
+content_check "msgnum:00000008: baz_latest"
+content_check "msgnum:00000009: baz_latest"
+content_check "msgnum:00000010: baz_latest"
+content_check "msgnum:00000011: baz_latest"
+content_check "msgnum:00000012: foo_latest"
+content_check "msgnum:00000013: foo_latest"
+content_check "msgnum:00000014: foo_latest"
+exit_test
diff --git a/tests/stats-cee-vg.sh b/tests/stats-cee-vg.sh
new file mode 100755
index 0000000..2807da5
--- /dev/null
+++ b/tests/stats-cee-vg.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[stats-cee-vg.sh\]: test for verifying stats are reported correctly cee format with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="cee")
+
+if ($msg == "this condition will never match") then {
+ action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup_vg
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+custom_content_check '@cee: { "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/stats-cee.sh b/tests/stats-cee.sh
new file mode 100755
index 0000000..6fd2b65
--- /dev/null
+++ b/tests/stats-cee.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stats-cee.sh\]: test for verifying stats are reported correctly cee format
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="cee")
+
+if ($msg == "this condition will never match") then {
+ action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check '@cee: { "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/stats-json-es.sh b/tests/stats-json-es.sh
new file mode 100755
index 0000000..7162930
--- /dev/null
+++ b/tests/stats-json-es.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stats-json-es.sh\]: test for verifying stats are reported correctly json-elasticsearch format
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json-elasticsearch")
+
+if ($msg == "this condition will never match") then {
+ action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check '{ "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "failed": 0, "suspended": 0, "suspended!duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/stats-json-vg.sh b/tests/stats-json-vg.sh
new file mode 100755
index 0000000..73177d5
--- /dev/null
+++ b/tests/stats-json-vg.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[stats-json-vg.sh\]: test for verifying stats are reported correctly json format with valgrind
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json")
+
+if ($msg == "this condition will never match") then {
+ action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup_vg
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown_vg
+check_exit_vg
+custom_content_check '{ "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/stats-json.sh b/tests/stats-json.sh
new file mode 100755
index 0000000..91298d4
--- /dev/null
+++ b/tests/stats-json.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# added 2016-03-30 by singh.janmejay
+# test for verifying stats are reported correctly json format
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+ruleset(name="stats") {
+ action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
+}
+
+module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json")
+
+if ($msg == "this condition will never match") then {
+ action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`)
+}
+'
+startup
+injectmsg_file $srcdir/testsuites/dynstats_input_1
+wait_queueempty
+wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+custom_content_check '{ "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log"
+custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log"
+exit_test
diff --git a/tests/stop-localvar.sh b/tests/stop-localvar.sh
new file mode 100755
index 0000000..f5fcb99
--- /dev/null
+++ b/tests/stop-localvar.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Test for "stop" statement
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stop-localvar.sh\]: testing stop statement together with local variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$.nbr%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if $msg contains "msgnum:" then {
+ set $.nbr = field($msg, 58, 2);
+ if cnum($.nbr) < 100 then
+ stop
+ /* check is intentionally more complex than needed! */
+ else if not (cnum($.nbr) > 999) then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ }
+}
+'
+startup
+sleep 1
+tcpflood -m2000 -i1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 100 999
+exit_test
diff --git a/tests/stop-msgvar.sh b/tests/stop-msgvar.sh
new file mode 100755
index 0000000..9a1c09f
--- /dev/null
+++ b/tests/stop-msgvar.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Test for "stop" statement
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stop-msgvar.sh\]: testing stop statement together with message variables
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%$!nbr%\n")
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if $msg contains "msgnum:" then {
+ set $!nbr = field($msg, 58, 2);
+ if cnum($!nbr) < 100 then
+ stop
+ /* check is intentionally more complex than needed! */
+ else if not (cnum($!nbr) > 999) then {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+ }
+}
+'
+startup
+sleep 1
+tcpflood -m2000 -i1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 100 999
+exit_test
diff --git a/tests/stop.sh b/tests/stop.sh
new file mode 100755
index 0000000..22f5655
--- /dev/null
+++ b/tests/stop.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Test for "stop" statement
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stop.sh\]: testing stop statement
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+if $msg contains "00000001" then
+ stop
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+if $msg contains "msgnum:" then
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+sleep 1
+tcpflood -m10 -i1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 2 10
+exit_test
diff --git a/tests/stop_when_array_has_element.sh b/tests/stop_when_array_has_element.sh
new file mode 100755
index 0000000..030013e
--- /dev/null
+++ b/tests/stop_when_array_has_element.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# added 2015-05-22 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[stop_when_array_has_element.sh\]: loop detecting presence of an element and stopping ruleset execution
+. ${srcdir:=.}/diag.sh init stop_when_array_has_element.sh
+generate_conf
+add_conf '
+template(name="foo" type="string" string="%$!foo%\n")
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+action(type="mmjsonparse")
+
+foreach ($.quux in $!foo) do {
+ if ($.quux == "xyz0") then stop
+}
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="foo")
+'
+startup
+tcpflood -m 1 -I $srcdir/testsuites/stop_when_array_has_elem_input
+echo doing shutdown
+shutdown_when_empty
+echo wait on shutdown
+wait_shutdown
+content_check '"abc0"'
+content_check '"abc2"'
+assert_content_missing 'xyz0'
+exit_test
diff --git a/tests/suspend-omfwd-via-file.sh b/tests/suspend-omfwd-via-file.sh
new file mode 100755
index 0000000..1df6f32
--- /dev/null
+++ b/tests/suspend-omfwd-via-file.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# This tests the action suspension via a file
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2019-07-10 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=10000
+#export NUMMESSAGES=100 #00
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global( debug.whitelist="on"
+ debug.files=["ruleset.c", "../action.c", "omfwd.c"]
+)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+:msg, contains, "msgnum:" {
+ action(name="forwarder" type="omfwd" template="outfmt"
+ target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp"
+ action.externalstate.file="'$RSYSLOG_DYNNAME'.STATE"
+ action.resumeRetryCount="-1" action.resumeinterval="1")
+}
+'
+
+./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background minitcpsrv process id is $BGPROCESS
+
+startup
+injectmsg 0 5000
+#injectmsg 0 5
+
+printf '\n%s %s\n' "$(tb_timestamp)" \
+ 'checking that action becomes suspended via external state file'
+printf "%s" "SUSPENDED" > $RSYSLOG_DYNNAME.STATE
+./msleep 2000 # ensure ResumeInterval expired (NOT sensitive to slow machines --> absolute time!)
+injectmsg 5000 1000
+#injectmsg 5 5
+
+printf '\n%s %s\n' "$(tb_timestamp)" \
+ 'checking that action becomes resumed again via external state file'
+./msleep 2000 # ensure ResumeInterval expired (NOT sensitive to slow machines --> absolute time!)
+printf "%s" "READY" > $RSYSLOG_DYNNAME.STATE
+
+injectmsg 6000 4000
+#export QUEUE_EMPTY_CHECK_FUNC=check_q_empty_log2
+wait_queueempty
+seq_check
+shutdown_when_empty
+wait_shutdown
+exit_test
diff --git a/tests/suspend-via-file.sh b/tests/suspend-via-file.sh
new file mode 100755
index 0000000..e2cefa7
--- /dev/null
+++ b/tests/suspend-via-file.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# This tests the action suspension via a file; we use a SUSPENDED string
+# with trailing whitespace in this test.
+# This file is part of the rsyslog project, released under ASL 2.0
+# Written 2018-08-13 by Rainer Gerhards
+. ${srcdir:=.}/diag.sh init
+check_q_empty_log1() {
+ echo "###### in check1"
+ wait_seq_check 2500 4999
+}
+check_q_empty_log2() {
+ echo "###### in check2"
+ wait_seq_check 0 $LOG2_EXPECTED_LASTNUM
+}
+generate_conf
+add_conf '
+/* Filter out busy debug output, comment out if needed */
+global( debug.whitelist="on"
+ debug.files=["ruleset.c", "../action.c", "omfwd.c"]
+)
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+:msg, contains, "msgnum:" {
+ action(name="primary" type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="outfmt"
+ action.externalstate.file="'$RSYSLOG_DYNNAME'.STATE" action.resumeinterval="1")
+ action(name="failover" type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt"
+ action.execOnlyWhenPreviousIsSuspended="on")
+}
+'
+startup
+
+printf '\n%s %s\n' "$(tb_timestamp)" \
+ 'STEP 1: checking that action is active w/o external state file'
+injectmsg 0 2500
+export SEQ_CHECK_FILE="$RSYSLOG2_OUT_LOG"
+export LOG2_EXPECTED_LASTNUM=2499
+export QUEUE_EMPTY_CHECK_FUNC=check_q_empty_log2
+wait_queueempty
+seq_check 0 $LOG2_EXPECTED_LASTNUM # full correctness check
+
+
+printf '\n%s %s\n' "$(tb_timestamp)" \
+ 'STEP 2: checking that action becomes suspended via external state file'
+printf 'SUSPENDED \n' > $RSYSLOG_DYNNAME.STATE
+injectmsg 2500 2500
+export SEQ_CHECK_FILE="$RSYSLOG_OUT_LOG"
+export QUEUE_EMPTY_CHECK_FUNC=check_q_empty_log1
+wait_queueempty
+seq_check 2500 4999 # full correctness check
+
+printf '\n%s %s\n' "$(tb_timestamp)" \
+ 'STEP 3: checking that action becomes resumed again via external state file'
+printf "%s" "READY" > $RSYSLOG_DYNNAME.STATE
+./msleep 2000 # ensure ResumeInterval expired (NOT sensitive to slow machines --> absolute time!)
+injectmsg 2500 2500
+export SEQ_CHECK_FILE="$RSYSLOG2_OUT_LOG"
+export LOG2_EXPECTED_LASTNUM=4999
+export QUEUE_EMPTY_CHECK_FUNC=check_q_empty_log2
+shutdown_when_empty
+wait_shutdown
+
+# final checks
+export SEQ_CHECK_FILE="$RSYSLOG_OUT_LOG"
+seq_check 2500 4999
+export SEQ_CHECK_FILE="$RSYSLOG2_OUT_LOG"
+seq_check 0 4999
+exit_test
diff --git a/tests/syslog_caller.c b/tests/syslog_caller.c
new file mode 100644
index 0000000..1a0b04f
--- /dev/null
+++ b/tests/syslog_caller.c
@@ -0,0 +1,151 @@
+/* A testing tool that just emits a number of
+ * messages to the system log socket.
+ *
+ * Options
+ *
+ * -s severity (0..7 accoding to syslog spec, r "rolling", default 6)
+ * -m number of messages to generate (default 500)
+ * -C liblognorm-stdlog channel description
+ * -f message format to use
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(_AIX)
+ #include <unistd.h>
+#else
+ #include <getopt.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#ifdef HAVE_LIBLOGGING_STDLOG
+#include <liblogging/stdlog.h>
+#endif
+
+static enum { FMT_NATIVE, FMT_SYSLOG_INJECT_L, FMT_SYSLOG_INJECT_C
+ } fmt = FMT_NATIVE;
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: syslog_caller num-messages\n");
+ exit(1);
+}
+
+
+#ifdef HAVE_LIBLOGGING_STDLOG
+/* buffer must be large "enough" [4K?] */
+static void
+genMsg(char *buf, const int sev, const int iRun)
+{
+ switch(fmt) {
+ case FMT_NATIVE:
+ sprintf(buf, "test message nbr %d, severity=%d", iRun, sev);
+ break;
+ case FMT_SYSLOG_INJECT_L:
+ sprintf(buf, "test\n");
+ break;
+ case FMT_SYSLOG_INJECT_C:
+ sprintf(buf, "test 1\t2");
+ break;
+ }
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int opt;
+ int bRollingSev = 0;
+ int sev = 6;
+ int msgs = 500;
+#ifdef HAVE_LIBLOGGING_STDLOG
+ stdlog_channel_t logchan = NULL;
+ const char *chandesc = "syslog:";
+ char msgbuf[4096];
+#endif
+
+#ifdef HAVE_LIBLOGGING_STDLOG
+ stdlog_init(STDLOG_USE_DFLT_OPTS);
+ while((opt = getopt(argc, argv, "m:s:C:f:")) != -1) {
+#else
+ while((opt = getopt(argc, argv, "m:s:")) != -1) {
+#endif
+ switch (opt) {
+ case 's': if(*optarg == 'r') {
+ bRollingSev = 1;
+ sev = 0;
+ } else
+#ifdef HAVE_LIBLOGGING_STDLOG
+ sev = atoi(optarg) % 8;
+#else
+ sev = atoi(optarg);
+#endif
+ break;
+ case 'm': msgs = atoi(optarg);
+ break;
+#ifdef HAVE_LIBLOGGING_STDLOG
+ case 'C': chandesc = optarg;
+ break;
+ case 'f': if(!strcmp(optarg, "syslog_inject-l"))
+ fmt = FMT_SYSLOG_INJECT_L;
+ else if(!strcmp(optarg, "syslog_inject-c"))
+ fmt = FMT_SYSLOG_INJECT_C;
+ else
+ usage();
+ break;
+#endif
+ default: usage();
+#ifdef HAVE_LIBLOGGING_STDLOG
+ exit(1);
+#endif
+ break;
+ }
+ }
+
+#ifdef HAVE_LIBLOGGING_STDLOG
+ if((logchan = stdlog_open(argv[0], 0, STDLOG_LOCAL1, chandesc)) == NULL) {
+ fprintf(stderr, "error opening logchannel '%s': %s\n",
+ chandesc, strerror(errno));
+ exit(1);
+ }
+#endif
+ for(i = 0 ; i < msgs ; ++i) {
+#ifdef HAVE_LIBLOGGING_STDLOG
+ genMsg(msgbuf, sev, i);
+ if(stdlog_log(logchan, sev, "%s", msgbuf) != 0) {
+ perror("error writing log record");
+ exit(1);
+ }
+#else
+ syslog(sev % 8, "test message nbr %d, severity=%d", i, sev % 8);
+#endif
+ if(bRollingSev)
+#ifdef HAVE_LIBLOGGING_STDLOG
+ sev = (sev + 1) % 8;
+#else
+ sev++;
+#endif
+ }
+ return(0);
+}
diff --git a/tests/tabescape_dflt-udp.sh b/tests/tabescape_dflt-udp.sh
new file mode 100755
index 0000000..481acba
--- /dev/null
+++ b/tests/tabescape_dflt-udp.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\""
+shutdown_when_empty
+wait_shutdown
+
+echo ' before HT#011after HT (do NOT remove TAB!)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/tabescape_dflt.sh b/tests/tabescape_dflt.sh
new file mode 100755
index 0000000..63b925e
--- /dev/null
+++ b/tests/tabescape_dflt.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\""
+shutdown_when_empty
+wait_shutdown
+
+echo ' before HT#011after HT (do NOT remove TAB!)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/tabescape_off-udp.sh b/tests/tabescape_off-udp.sh
new file mode 100755
index 0000000..8374844
--- /dev/null
+++ b/tests/tabescape_off-udp.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imudp/.libs/imudp")
+input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1")
+
+$ErrorMessagesToStderr off
+$EscapeControlCharacterTab off
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\""
+shutdown_when_empty
+wait_shutdown
+
+echo ' before HT after HT (do NOT remove TAB!)' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/tabescape_off.sh b/tests/tabescape_off.sh
new file mode 100755
index 0000000..3aa9bf0
--- /dev/null
+++ b/tests/tabescape_off.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(parser.EscapeControlCharacterTab="off")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+$ErrorMessagesToStderr off
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED=' before HT after HT (do NOT remove TAB!)'
+cmp_exact
+
+exit_test
diff --git a/tests/tabescape_on.sh b/tests/tabescape_on.sh
new file mode 100755
index 0000000..ad41a95
--- /dev/null
+++ b/tests/tabescape_on.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# add 2018-06-29 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+global(parser.EscapeControlCharacterTab="on")
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1")
+
+$ErrorMessagesToStderr off
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+ruleset(name="ruleset1") {
+ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+}
+
+'
+startup
+tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED=' before HT#011after HT (do NOT remove TAB!)'
+cmp_exact
+
+exit_test
diff --git a/tests/tcp-msgreduc-vg.sh b/tests/tcp-msgreduc-vg.sh
new file mode 100755
index 0000000..c68fdb2
--- /dev/null
+++ b/tests/tcp-msgreduc-vg.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# check if valgrind violations occur. Correct output is not checked.
+# added 2011-03-01 by Rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+# exit 77
+fi
+
+export NUMMESSAGES=4
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+$RepeatedMsgReduction on
+
+$template outfmt,"%msg:F,58:2%\n"
+*.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -t 127.0.0.1 -m 4 -r -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...\""
+tcpflood -t 127.0.0.1 -m 1 -r -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...x\""
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+exit_test
diff --git a/tests/tcp_forwarding_dflt_tpl.sh b/tests/tcp_forwarding_dflt_tpl.sh
new file mode 100755
index 0000000..0dc7070
--- /dev/null
+++ b/tests/tcp_forwarding_dflt_tpl.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This test tests tcp forwarding with assigned default template.
+# added 2015-05-30 by rgerhards. Released under ASL 2.0
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+#this is what we want to test: setting the default template
+module(load="builtin:omfwd" template="outfmt")
+
+if $msg contains "msgnum:" then
+ action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp")
+'
+./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background minitcpsrv process id is $BGPROCESS
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# note: minitcpsrv shuts down automatically if the connection is closed!
+# (we still leave the code here in in case we need it later)
+#echo shutting down minitcpsrv...
+#kill $BGPROCESS
+#wait $BGPROCESS
+#echo background process has terminated, continue test...
+
+# and continue the usual checks
+seq_check 0 9999
+exit_test
diff --git a/tests/tcp_forwarding_ns_tpl.sh b/tests/tcp_forwarding_ns_tpl.sh
new file mode 100755
index 0000000..89a45e3
--- /dev/null
+++ b/tests/tcp_forwarding_ns_tpl.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This test tests tcp forwarding in a network namespace with assigned template.
+# To do so, a simple tcp listener service is started in a network namespace.
+# Released under GNU GPLv3+
+echo ===============================================================================
+echo \[tcp_forwarding_ns_tpl.sh\]: test for tcp forwarding in a network namespace with assigned template
+echo This test must be run as root [network namespace creation/change required]
+if [ "$EUID" -ne 0 ]; then
+ exit 77 # Not root, skip this test
+fi
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then
+ action(type="omfwd" template="outfmt"
+ target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp" networknamespace="rsyslog_test_ns")
+'
+# create network namespace and bring it up
+ip netns add rsyslog_test_ns
+ip netns exec rsyslog_test_ns ip link set dev lo up
+
+# run server in namespace
+ip netns exec rsyslog_test_ns ./minitcpsrv -t127.0.0.1 -p'$TCPFLOOD_PORT' -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background minitcpsrvr process id is $BGPROCESS
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# note: minitcpsrvr shuts down automatically if the connection is closed!
+# (we still leave the code here in in case we need it later)
+#echo shutting down minitcpsrv...
+#kill $BGPROCESS
+#wait $BGPROCESS
+#echo background process has terminated, continue test...
+
+# remove network namespace
+ip netns delete rsyslog_test_ns
+
+# and continue the usual checks
+seq_check 0 9999
+exit_test
diff --git a/tests/tcp_forwarding_retries.sh b/tests/tcp_forwarding_retries.sh
new file mode 100755
index 0000000..eb7a69b
--- /dev/null
+++ b/tests/tcp_forwarding_retries.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# added 2016-06-21 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+messages=20000 # how many messages to inject?
+# Note: we need to inject a somewhat larger number of messages in order
+# to ensure that we receive some messages in the actual output file,
+# as batching can (validly) cause a larger loss in the non-writable
+# file
+
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+:msg, contains, "msgnum:" {
+ action(type="omfwd"
+ target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="TCP"
+ action.resumeRetryCount="10"
+ template="outfmt")
+}
+'
+
+# we start a small receiver process
+./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG -s4 &
+BGPROCESS=$!
+echo background minitcpsrvr process id is $BGPROCESS
+
+startup
+injectmsg 0 $messages
+shutdown_when_empty
+wait_shutdown
+
+# note: minitcpsrvr shuts down automatically if the connection is closed, but
+# we still try to kill it in case the test did not connect to it! Note that we
+# do not need an extra wait, as the rsyslog shutdown process should have taken
+# far long enough.
+echo waiting on background process
+kill $BGPROCESS &> /dev/null
+wait $BGPROCESS
+
+seq_check 0 $(($messages-1))
+exit_test
diff --git a/tests/tcp_forwarding_tpl.sh b/tests/tcp_forwarding_tpl.sh
new file mode 100755
index 0000000..3eba8e0
--- /dev/null
+++ b/tests/tcp_forwarding_tpl.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This test tests tcp forwarding with assigned template. To do so, a simple
+# tcp listener service is started.
+# added 2012-10-30 by Rgerhards. Released under ASL 2.0
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+template(name="outfmt" type="string" string="%msg:F,58:2%\n")
+
+if $msg contains "msgnum:" then
+ action(type="omfwd" template="outfmt"
+ target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp")
+'
+./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG &
+BGPROCESS=$!
+echo background minitcpsrvr process id is $BGPROCESS
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# note: minitcpsrvr shuts down automatically if the connection is closed!
+# (we still leave the code here in in case we need it later)
+#echo shutting down minitcpsrv...
+#kill $BGPROCESS
+#wait $BGPROCESS
+#echo background process has terminated, continue test...
+
+# and continue the usual checks
+seq_check 0 9999
+exit_test
diff --git a/tests/tcpflood.c b/tests/tcpflood.c
new file mode 100644
index 0000000..bd8edaf
--- /dev/null
+++ b/tests/tcpflood.c
@@ -0,0 +1,2108 @@
+/* Opens a large number of tcp connections and sends
+ * messages over them. This is used for stress-testing.
+ *
+ * NOTE: the following part is actually the SPEC (or call it man page).
+ * It's not random comments. So if the code behavior does not match what
+ * is written here, it should be considered a bug.
+ *
+ * Params
+ * -t target address (default 127.0.0.1)
+ * -p target port(s) (default 13514), multiple via port1:port2:port3...
+ * -n number of target ports (all target ports must be given in -p!)
+ * Note -c must also be set to at LEAST the number of -n!
+ * -c number of connections (default 1), use negative number
+ * to set a "soft limit": if tcpflood cannot open the
+ * requested number of connections, gracefully degrade to
+ * whatever number could be opened. This is useful in environments
+ * where system config constraints cannot be overriden (e.g.
+ * vservers, non-admin users, ...)
+ * -m number of messages to send (connection is random)
+ * -i initial message number (optional)
+ * -P PRI to be used for generated messages (default is 167).
+ * Specify the plain number without leading zeros
+ * -d amount of extra data to add to message. If present, the
+ * number itself will be added as third field, and the data
+ * bytes as forth. Add -r to randomize the amount of extra
+ * data included in the range 1..(value of -d).
+ * -r randomize amount of extra data added (-d must be > 0)
+ * -s (silent) do not show progress indicator (never done on non-tty)
+ * -f support for testing dynafiles. If given, include a dynafile ID
+ * in the range 0..(f-1) as the SECOND field, shifting all field values
+ * one field to the right. Zero (default) disables this functionality.
+ * -M the message to be sent. Disables all message format options, as
+ * only that exact same message is sent.
+ * -I read specified input file, do NOT generate own test data. The test
+ * completes when eof is reached.
+ * -B The specified file (-I) is binary. No data processing is done by
+ * tcpflood. If multiple connections are specified, data is read in
+ * chunks and spread across the connections without taking any record
+ * delimiters into account.
+ * -C when input from a file is read, this file is transmitted -C times
+ * (C like cycle, running out of meaningful option switches ;))
+ * -D randomly drop and re-establish connections. Useful for stress-testing
+ * the TCP receiver.
+ * -F USASCII value for frame delimiter (in octet-stuffing mode), default LF
+ * -R number of times the test shall be run (very useful for gathering performance
+ * data and other repetitive things). Default: 1
+ * -S number of seconds to sleep between different runs (-R) Default: 30
+ * -X generate sTats data records. Default: off
+ * -e encode output in CSV (not yet everywhere supported)
+ * for performance data:
+ * each inidividual line has the runtime of one test
+ * the last line has 0 in field 1, followed by numberRuns,TotalRuntime,
+ * Average,min,max
+ * -T transport to use. Currently supported: "udp", "tcp" (default), "tls" (tcp+tls), relp-plain, relp-tls
+ * Note: UDP supports a single target port, only
+ * -u Set RELP TLS Library to gnutls or openssl
+ * -W wait time between sending batches of messages, in microseconds (Default: 0)
+ * -b number of messages within a batch (default: 100,000,000 millions)
+ * -Y use multiple threads, one per connection (which means 1 if one only connection
+ * is configured!)
+ * -y use RFC5424 style test message
+ * -x CA Cert File for verification (TLS Mode / OpenSSL only)
+ * -z private key file for TLS mode
+ * -Z cert (public key) file for TLS mode
+ * -a Authentication Mode for relp-tls
+ * -A do NOT abort if an error occured during sending messages
+ * -E Permitted Peer for relp-tls
+ * -L loglevel to use for GnuTLS troubleshooting (0-off to 10-all, 0 default)
+ * -j format message in json, parameter is JSON cookie
+ * -O Use octate-count framing
+ * -v verbose output, possibly useful for troubleshooting. Most importantly,
+ * this gives insight into librelp actions (if relp is selected as protocol).
+ * -k Custom Configuration string passwed through the TLS library.
+ * Currently only OpenSSL is supported, possible configuration commands and values can be found here:
+ * https://www.openssl.org/docs/man1.0.2/man3/SSL_CONF_cmd.html
+ * Sample: -k"Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.1"
+ * Works for LIBRELP now as well!
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2009-2019 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#ifdef ENABLE_RELP
+#include <librelp.h>
+#endif
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <errno.h>
+#ifdef ENABLE_GNUTLS
+# include <gnutls/gnutls.h>
+# if GNUTLS_VERSION_NUMBER <= 0x020b00
+# include <gcrypt.h>
+ GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
+#endif
+#ifdef ENABLE_OPENSSL
+ #include <openssl/ssl.h>
+ #include <openssl/x509v3.h>
+ #include <openssl/err.h>
+ #include <openssl/engine.h>
+
+ /* OpenSSL API differences */
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT)
+ #define RSYSLOG_BIO_method_name(SSLBIO) BIO_method_name(SSLBIO)
+ #define RSYSLOG_BIO_number_read(SSLBIO) BIO_number_read(SSLBIO)
+ #define RSYSLOG_BIO_number_written(SSLBIO) BIO_number_written(SSLBIO)
+ #else
+ #define RSYSLOG_X509_NAME_oneline(X509CERT) (X509CERT != NULL ? X509CERT->cert_info->subject : NULL)
+ #define RSYSLOG_BIO_method_name(SSLBIO) SSLBIO->method->name
+ #define RSYSLOG_BIO_number_read(SSLBIO) SSLBIO->num
+ #define RSYSLOG_BIO_number_written(SSLBIO) SSLBIO->num
+ #endif
+
+#endif
+
+char *test_rs_strerror_r(int errnum, char *buf, size_t buflen) {
+#ifndef HAVE_STRERROR_R
+ char *pszErr;
+ pszErr = strerror(errnum);
+ snprintf(buf, buflen, "%s", pszErr);
+#else
+# ifdef STRERROR_R_CHAR_P
+ char *p = strerror_r(errnum, buf, buflen);
+ if (p != buf) {
+ strncpy(buf, p, buflen);
+ buf[buflen - 1] = '\0';
+ }
+# else
+ strerror_r(errnum, buf, buflen);
+# endif
+#endif /* #ifdef __hpux */
+ return buf;
+}
+
+#define INVALID_SOCKET -1
+/* Name of input file, must match $IncludeConfig in test suite .conf files */
+#define NETTEST_INPUT_CONF_FILE "nettest.input.conf"
+/* name of input file, must match $IncludeConfig in .conf files */
+
+#define MAX_EXTRADATA_LEN 512*1024
+#define MAX_SENDBUF 2 * MAX_EXTRADATA_LEN
+#define MAX_RCVBUF 16 * 1024 + 1/* TLS RFC 8449: max size of buffer for message reception */
+
+static char *targetIP = "127.0.0.1";
+static char *msgPRI = "167";
+static int targetPort[5] = {13514};
+static int numTargetPorts = 1;
+static int verbose = 0;
+static int dynFileIDs = 0;
+static int extraDataLen = 0; /* amount of extra data to add to message */
+static int useRFC5424Format = 0; /* should the test message be in RFC5424 format? */
+static int bRandomizeExtraData = 0; /* randomize amount of extra data added */
+static int numMsgsToSend = 1; /* number of messages to send */
+static int numConnections = 1; /* number of connections to create */
+static int softLimitConnections = 0; /* soft connection limit, see -c option description */
+static int *sockArray; /* array of sockets to use */
+#ifdef ENABLE_RELP
+static relpClt_t **relpCltArray; /* array of sockets to use */
+#endif
+static int msgNum = 0; /* initial message number to start with */
+static int bShowProgress = 1; /* show progress messages */
+static int bSilent = 0; /* completely silent operation */
+static int bRandConnDrop = 0; /* randomly drop connections? */
+static double dbRandConnDrop = 0.95; /* random drop probability */
+static char *MsgToSend = NULL; /* if non-null, this is the actual message to send */
+static int bBinaryFile = 0; /* is -I file binary */
+static char *dataFile = NULL; /* name of data file, if NULL, generate own data */
+static int numFileIterations = 1;/* how often is file data to be sent? */
+static char frameDelim = '\n'; /* default frame delimiter */
+FILE *dataFP = NULL; /* file pointer for data file, if used */
+static long nConnDrops = 0; /* counter: number of time connection was dropped (-D option) */
+static int numRuns = 1; /* number of times the test shall be run */
+static int sleepBetweenRuns = 30; /* number of seconds to sleep between runs */
+static int bStatsRecords = 0; /* generate stats records */
+static int bCSVoutput = 0; /* generate output in CSV (where applicable) */
+static long long batchsize = 100000000ll;
+static int waittime = 0;
+static int runMultithreaded = 0; /* run tests in multithreaded mode */
+static int numThrds = 1; /* number of threads to use */
+static int abortOnSendFail = 1; /* abort run if sending fails? */
+static char *tlsCAFile = NULL;
+static char *tlsCertFile = NULL;
+static char *tlsKeyFile = NULL;
+static char *relpAuthMode = NULL;
+static char *relpPermittedPeer = NULL;
+#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+static char *relpTlsLib = NULL;
+#endif
+
+static int tlsLogLevel = 0;
+static char *jsonCookie = NULL; /* if non-NULL, use JSON format with this cookie */
+static int octateCountFramed = 0;
+static char *customConfig = NULL; /* Stores a string with custom configuration passed through the TLS driver */
+
+#ifdef ENABLE_GNUTLS
+static gnutls_session_t *sessArray; /* array of TLS sessions to use */
+static gnutls_certificate_credentials_t tlscred;
+#endif
+
+#ifdef ENABLE_OPENSSL
+/* Main OpenSSL CTX pointer */
+static SSL_CTX *ctx;
+static SSL **sslArray;
+static struct sockaddr_in dtls_client_addr; /* socket address sender for receiving DTLS data */
+static int udpsockin; /* socket for receiving messages in DTLS mode */
+#endif
+
+/* variables for managing multi-threaded operations */
+int runningThreads; /* number of threads currently running */
+int doRun; /* shall sender thread begin to run? */
+pthread_mutex_t thrdMgmt; /* mutex for controling startup/shutdown */
+pthread_cond_t condStarted;
+pthread_cond_t condDoRun;
+
+/* the following struct provides information for a generator instance (thread) */
+struct instdata {
+ /* lower and upper bounds for the thread in question */
+ unsigned long long lower;
+ unsigned long long numMsgs; /* number of messages to send */
+ unsigned long long numSent; /* number of messages already sent */
+ unsigned idx; /**< index of fd to be used for sending */
+ pthread_t thread; /**< thread processing this instance */
+} *instarray = NULL;
+
+/* the following structure is used to gather performance data */
+struct runstats {
+ unsigned long long totalRuntime;
+ unsigned long minRuntime;
+ unsigned long maxRuntime;
+ int numRuns;
+};
+
+static int udpsockout; /* socket for sending in UDP mode */
+static struct sockaddr_in udpRcvr; /* remote receiver in UDP mode */
+
+static enum { TP_UDP, TP_TCP, TP_TLS, TP_RELP_PLAIN, TP_RELP_TLS, TP_DTLS } transport = TP_TCP;
+
+/* forward definitions */
+static void initTLSSess(int);
+static int sendTLS(int i, char *buf, size_t lenBuf);
+static void closeTLSSess(int __attribute__((unused)) i);
+
+static void initDTLSSess(void);
+static int sendDTLS(char *buf, size_t lenBuf);
+static void closeDTLSSess(void);
+
+#ifdef ENABLE_RELP
+/* RELP subsystem */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-security"
+static void relp_dbgprintf(char __attribute__((unused)) *fmt, ...) {
+ printf(fmt);
+}
+#pragma GCC diagnostic pop
+
+static relpEngine_t *pRelpEngine;
+#define CHKRELP(f) if(f != RELP_RET_OK) { fprintf(stderr, "%s\n", #f); exit(1); }
+
+static void
+onErr(void *pUsr, char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ fprintf(stderr, "tcpflood: onErr '%s'\n", errmesg);
+}
+
+static void
+onGenericErr(char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ fprintf(stderr, "tcpflood: onGenericErr '%s'\n", errmesg);
+}
+
+static void
+onAuthErr(void *pUsr, char *authinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
+{
+ fprintf(stderr, "tcpflood: onAuthErr '%s' peer '%s'\n", errmesg, authinfo);
+}
+
+static void
+initRELP_PLAIN(void)
+{
+ CHKRELP(relpEngineConstruct(&pRelpEngine));
+ CHKRELP(relpEngineSetDbgprint(pRelpEngine,
+ verbose ? relp_dbgprintf : NULL));
+ CHKRELP(relpEngineSetEnableCmd(pRelpEngine, (unsigned char*)"syslog",
+ eRelpCmdState_Required));
+ /* Error output support */
+ CHKRELP(relpEngineSetOnErr(pRelpEngine, onErr));
+ CHKRELP(relpEngineSetOnGenericErr(pRelpEngine, onGenericErr));
+ CHKRELP(relpEngineSetOnAuthErr(pRelpEngine, onAuthErr));
+
+}
+#endif /* #ifdef ENABLE_RELP */
+
+/* prepare send subsystem for UDP send */
+static int
+setupUDP(void)
+{
+ if((udpsockout = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ return 1;
+
+ memset((char *) &udpRcvr, 0, sizeof(udpRcvr));
+ udpRcvr.sin_family = AF_INET;
+ udpRcvr.sin_port = htons(targetPort[0]);
+ if(inet_aton(targetIP, &udpRcvr.sin_addr)==0) {
+ fprintf(stderr, "inet_aton() failed\n");
+ return(1);
+ }
+
+ return 0;
+}
+
+#if defined(ENABLE_OPENSSL)
+static int
+setupDTLS(void)
+{
+ // Setup receiving Socket for DTLS
+ if((udpsockin = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ return 1;
+
+ memset(&dtls_client_addr, 0, sizeof(dtls_client_addr));
+ dtls_client_addr.sin_family = AF_INET;
+ dtls_client_addr.sin_port = htons(0);
+ dtls_client_addr.sin_addr.s_addr = INADDR_ANY;
+ if (bind(udpsockin, (struct sockaddr*)&dtls_client_addr, sizeof(dtls_client_addr)) < 0) {
+ perror("bind()");
+ fprintf(stderr, "Unable to bind DTLS CLient socket\n");
+ return(1);
+ }
+
+ memset((char *) &udpRcvr, 0, sizeof(udpRcvr));
+ udpRcvr.sin_family = AF_INET;
+ udpRcvr.sin_port = htons(targetPort[0]);
+ if(inet_aton(targetIP, &udpRcvr.sin_addr)==0) {
+ fprintf(stderr, "inet_aton() failed\n");
+ return(1);
+ }
+
+ // Init Socket Connection (Which technically does not connect but prepares socket for DTLS)
+ printf("[DEBUG] Init Session to %s:%d ...\n", targetIP, targetPort[0]);
+ udpsockout = socket(AF_INET, SOCK_DGRAM, 0);
+ // Connect the UDP socket to the server's address
+ if (connect(udpsockout, (const struct sockaddr *) &udpRcvr, sizeof(udpRcvr)) < 0) {
+ perror("connect()");
+ fprintf(stderr, "connect to %s:%d failed\n", targetIP, targetPort[0]);
+ return(1);
+ }
+ sockArray[0] = -1;
+
+ return 0;
+}
+#endif
+
+/* open a single tcp connection
+ */
+int openConn(int *fd, const int connIdx)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int port;
+ int retries = 0;
+ int rnd;
+
+ /* randomize port if required */
+ if(numTargetPorts > 1) {
+ rnd = rand(); /* easier if we need value for debug messages ;) */
+ port = targetPort[(rnd % numTargetPorts)];
+ } else {
+ port = targetPort[0];
+ }
+ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ #ifdef ENABLE_RELP
+ relpRetVal relp_r;
+ relpClt_t *relpClt;
+ char relpPort[16];
+ snprintf(relpPort, sizeof(relpPort), "%d", port);
+ CHKRELP(relpEngineCltConstruct(pRelpEngine, &relpClt));
+ if(transport == TP_RELP_TLS) {
+ #if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ if(relpTlsLib != NULL && relpEngineSetTLSLibByName(pRelpEngine, relpTlsLib) != RELP_RET_OK) {
+ fprintf(stderr, "relpTlsLib not accepted by librelp, using default\n");
+ }
+ #endif
+ if(relpCltEnableTLS(relpClt) != RELP_RET_OK) {
+ fprintf(stderr, "error while enabling TLS for relp\n");
+ exit(1);
+ }
+ if(relpAuthMode != NULL && relpCltSetAuthMode(relpClt, relpAuthMode) != RELP_RET_OK) {
+ fprintf(stderr, "could not set Relp Authentication mode: %s\n", relpAuthMode);
+ exit(1);
+ }
+ if(tlsCAFile != NULL && relpCltSetCACert(relpClt, tlsCAFile) != RELP_RET_OK) {
+ fprintf(stderr, "could not set CA File: %s\n", tlsCAFile);
+ exit(1);
+ }
+ if(tlsCertFile != NULL && relpCltSetOwnCert(relpClt, tlsCertFile) != RELP_RET_OK) {
+ fprintf(stderr, "could not set Cert File: %s\n", tlsCertFile);
+ exit(1);
+ }
+ if(tlsKeyFile != NULL && relpCltSetPrivKey(relpClt, tlsKeyFile) != RELP_RET_OK) {
+ fprintf(stderr, "could not set Key File: %s\n", tlsKeyFile);
+ exit(1);
+ }
+ if(relpPermittedPeer != NULL && relpCltAddPermittedPeer(relpClt, relpPermittedPeer)
+ != RELP_RET_OK) {
+ fprintf(stderr, "could not set Permitted Peer: %s\n", relpPermittedPeer);
+ exit(1);
+ }
+#if defined(HAVE_RELPENGINESETTLSCFGCMD)
+ /* Check for Custom Config string */
+ if(customConfig != NULL && relpCltSetTlsConfigCmd(relpClt, customConfig)
+ != RELP_RET_OK) {
+ fprintf(stderr, "could not set custom tls command: %s\n", customConfig);
+ exit(1);
+ }
+#endif
+ }
+ relpCltArray[connIdx] = relpClt;
+ relp_r = relpCltConnect(relpCltArray[connIdx], 2,
+ (unsigned char*)relpPort, (unsigned char*)targetIP);
+ if(relp_r != RELP_RET_OK) {
+ fprintf(stderr, "relp connect failed with return %d\n", relp_r);
+ return(1);
+ }
+ *fd = 1; /* mimic "all ok" state */
+ #endif
+ } else { /* TCP, with or without TLS */
+ if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
+ perror("\nsocket()");
+ return(1);
+ }
+ memset((char *) &addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ if(inet_aton(targetIP, &addr.sin_addr)==0) {
+ fprintf(stderr, "inet_aton() failed\n");
+ return(1);
+ }
+ while(1) { /* loop broken inside */
+ if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
+ break;
+ } else {
+ if(retries++ == 50) {
+ perror("connect()");
+ fprintf(stderr, "connect(%d) failed\n", port);
+ return(1);
+ } else {
+ usleep(100000); /* ms = 1000 us! */
+ }
+ }
+ }
+
+ *fd = sock;
+ }
+ return 0;
+}
+
+
+/* open all requested tcp connections
+ * this includes allocating the connection array
+ */
+int openConnections(void)
+{
+ int i;
+ char msgBuf[128];
+ size_t lenMsg;
+
+ if(transport == TP_UDP)
+ return setupUDP();
+
+ if(bShowProgress)
+ if(write(1, " open connections", sizeof(" open connections")-1)){}
+# if defined(ENABLE_OPENSSL)
+ sslArray = calloc(numConnections, sizeof(SSL *));
+# elif defined(ENABLE_GNUTLS)
+ sessArray = calloc(numConnections, sizeof(gnutls_session_t));
+# endif
+ sockArray = calloc(numConnections, sizeof(int));
+
+# if defined(ENABLE_OPENSSL)
+ // Use setupDTLS on DTLS
+ if(transport == TP_DTLS)
+ return setupDTLS();
+# endif
+
+ #ifdef ENABLE_RELP
+ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS)
+ relpCltArray = calloc(numConnections, sizeof(relpClt_t*));
+ #endif
+ for(i = 0 ; i < numConnections ; ++i) {
+ if(i % 10 == 0) {
+ if(bShowProgress)
+ printf("\r%5.5d", i);
+ }
+ if(openConn(&(sockArray[i]), i) != 0) {
+ printf("error in trying to open connection i=%d\n", i);
+ if(softLimitConnections) {
+ printf("Connection limit is soft, continuing with fewer connections\n");
+ numConnections = i - 1;
+ int close_conn = 10;
+ for(i -= 1 ; close_conn > 0 && i > 1 ; --i, --close_conn) {
+ printf("closing connection %d to make some room\n", i);
+ /* close at least some connections so that
+ * other functionality has a chance to do
+ * at least something.
+ */
+ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ #ifdef ENABLE_RELP
+ CHKRELP(relpEngineCltDestruct(pRelpEngine,
+ relpCltArray+i));
+ #endif
+ } else { /* TCP and TLS modes */
+ if(transport == TP_TLS)
+ closeTLSSess(i);
+ close(sockArray[i]);
+ }
+ sockArray[i] = -1;
+ }
+ numConnections = i;
+ printf("continuing with %d connections.\n", numConnections);
+ if(numConnections < 1) {
+ fprintf(stderr, "tcpflood could not open at least one "
+ "connection, error-terminating\n");
+ exit(1);
+ }
+ break;
+ }
+ return 1;
+ }
+ if(transport == TP_TLS) {
+ initTLSSess(i);
+ }
+ }
+ if(bShowProgress) {
+ lenMsg = sprintf(msgBuf, "\r%5.5d open connections\n", i);
+ if(write(1, msgBuf, lenMsg)) {}
+ }
+
+ return 0;
+}
+
+
+/* we also close all connections because otherwise we may get very bad
+ * timing for the syslogd - it may not be able to process all incoming
+ * messages fast enough if we immediately shut down.
+ * TODO: it may be an interesting excercise to handle that situation
+ * at the syslogd level, too
+ * rgerhards, 2009-04-14
+ */
+void closeConnections(void)
+{
+ int i;
+ size_t lenMsg;
+ struct linger ling;
+ char msgBuf[128];
+
+ if(transport == TP_UDP) {
+ return;
+ }
+# if defined(ENABLE_OPENSSL)
+ else if(transport == TP_DTLS) {
+ closeDTLSSess();
+ return;
+ }
+# endif
+
+ if(bShowProgress)
+ if(write(1, " close connections", sizeof(" close connections")-1)){}
+ for(i = 0 ; i < numConnections ; ++i) {
+ if(i % 10 == 0 && bShowProgress) {
+ lenMsg = sprintf(msgBuf, "\r%5.5d", i);
+ if(write(1, msgBuf, lenMsg)){}
+ }
+ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ #ifdef ENABLE_RELP
+ relpRetVal relpr;
+ if(sockArray[i] != -1) {
+ relpr = relpEngineCltDestruct(pRelpEngine, relpCltArray+i);
+ if(relpr != RELP_RET_OK) {
+ fprintf(stderr, "relp error %d on close\n", relpr);
+ }
+ sockArray[i] = -1;
+ }
+ #endif
+ } else { /* TCP and TLS modes */
+ if(sockArray[i] != -1) {
+ /* we try to not overrun the receiver by trying to flush buffers
+ * *during* close(). -- rgerhards, 2010-08-10
+ */
+ ling.l_onoff = 1;
+ ling.l_linger = 1;
+ setsockopt(sockArray[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
+ if(transport == TP_TLS) {
+ closeTLSSess(i);
+ }
+ close(sockArray[i]);
+ }
+ }
+ }
+ if(bShowProgress) {
+ lenMsg = sprintf(msgBuf, "\r%5.5d close connections\n", i);
+ if(write(1, msgBuf, lenMsg)){}
+ }
+
+}
+
+
+/* generate the message to be sent according to program command line parameters.
+ * this has been moved to its own function as we now have various different ways
+ * of constructing test messages. -- rgerhards, 2010-03-31
+ */
+static void
+genMsg(char *buf, size_t maxBuf, size_t *pLenBuf, struct instdata *inst)
+{
+ int edLen; /* actual extra data length to use */
+ char extraData[MAX_EXTRADATA_LEN + 1];
+ char dynFileIDBuf[128] = "";
+ int done;
+ char payloadLen[32];
+ int payloadStringLen;
+
+ if(dataFP != NULL) {
+ /* get message from file */
+ do {
+ done = 1;
+ *pLenBuf = fread(buf, 1, MAX_EXTRADATA_LEN + 1024, dataFP);
+ if(*pLenBuf == 0) {
+ if(--numFileIterations > 0) {
+ rewind(dataFP);
+ done = 0; /* need new iteration */
+ } else {
+ *pLenBuf = 0;
+ goto finalize_it;
+ }
+ }
+ } while(!done); /* Attention: do..while()! */
+ } else if(jsonCookie != NULL) {
+ if(useRFC5424Format) {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z mymachine.example.com "
+ "tcpflood - tag [tcpflood@32473 MSGNUM"
+ "=\"%8.8d\"] %s{\"msgnum\":%d}%c", msgPRI, msgNum,
+ jsonCookie, msgNum, frameDelim);
+ } else {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag %s{\"msgnum\":%d}%c",
+ msgPRI, jsonCookie, msgNum, frameDelim);
+ }
+ } else if(MsgToSend == NULL) {
+ if(dynFileIDs > 0) {
+ snprintf(dynFileIDBuf, sizeof(dynFileIDBuf), "%d:", rand() % dynFileIDs);
+ }
+ if(extraDataLen == 0) {
+ if(useRFC5424Format) {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z "
+ "mymachine.example.com tcpflood - tag [tcpflood@32473 "
+ "MSGNUM=\"%8.8d\"] msgnum:%s%8.8d:%c",
+ msgPRI, msgNum, dynFileIDBuf, msgNum, frameDelim);
+ } else {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag "
+ "msgnum:%s%8.8d:%c", msgPRI, dynFileIDBuf, msgNum, frameDelim);
+ }
+ } else {
+ if(bRandomizeExtraData)
+ edLen = ((unsigned long) rand() + extraDataLen) % extraDataLen + 1;
+ else
+ edLen = extraDataLen;
+ memset(extraData, 'X', edLen);
+ extraData[edLen] = '\0';
+ if(useRFC5424Format) {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z "
+ "mymachine.example.com tcpflood - tag [tcpflood@32473 "
+ "MSGNUM=\"%8.8d\"] msgnum:%s%8.8d:%c",
+ msgPRI, msgNum, dynFileIDBuf, msgNum, frameDelim);
+ } else {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum"
+ ":%s%8.8d:%d:%s%c", msgPRI, dynFileIDBuf, msgNum, edLen,
+ extraData, frameDelim);
+ }
+ }
+ } else {
+ /* use fixed message format from command line */
+ *pLenBuf = snprintf(buf, maxBuf, "%s%c", MsgToSend, frameDelim);
+ }
+ if (octateCountFramed == 1) {
+ snprintf(payloadLen, sizeof(payloadLen), "%zd ", *pLenBuf);
+ payloadStringLen = strlen(payloadLen);
+ memmove(buf + payloadStringLen, buf, *pLenBuf);
+ memcpy(buf, payloadLen, payloadStringLen);
+ *pLenBuf += payloadStringLen;
+ }
+ ++inst->numSent;
+
+finalize_it: /*EMPTY to keep the compiler happy */;
+}
+
+
+static int
+sendPlainTCP(const int socknum, const char *const buf, const size_t lenBuf, int *const ret_errno)
+{
+ size_t lenSent;
+ int r;
+
+ lenSent = 0;
+ while(lenSent != lenBuf) {
+ r = send(sockArray[socknum], buf + lenSent, lenBuf - lenSent, 0);
+ if(r > 0) {
+ lenSent += r;
+ } else {
+ *ret_errno = errno;
+ goto finalize_it;
+ }
+ }
+
+finalize_it:
+ return lenSent;
+}
+
+
+/* send messages to the tcp connections we keep open. We use
+ * a very basic format that helps identify the message
+ * (via msgnum:<number>: e.g. msgnum:00000001:). This format is suitable
+ * for extracton to field-based properties.
+ * The first numConnection messages are sent sequentially, as are the
+ * last. All messages in between are sent over random connections.
+ * Note that message numbers start at 0.
+ */
+int sendMessages(struct instdata *inst)
+{
+ unsigned i = 0;
+ int socknum;
+ size_t lenBuf;
+ size_t lenSend = 0;
+ char *statusText = "";
+ char buf[MAX_EXTRADATA_LEN + 1024];
+ char sendBuf[MAX_SENDBUF];
+ int offsSendBuf = 0;
+ char errStr[1024];
+ int error_number = 0;
+ unsigned show_progress_interval = 100;
+
+ if(!bSilent) {
+ if(dataFile == NULL) {
+ printf("Sending %llu messages.\n", inst->numMsgs);
+ statusText = "messages";
+ if ((inst->numMsgs / 100) > show_progress_interval) {
+ show_progress_interval = inst->numMsgs / 100;
+ }
+ } else {
+ printf("Sending file '%s' %d times.\n", dataFile,
+ numFileIterations);
+ statusText = "kb";
+ }
+ }
+ if(bShowProgress)
+ printf("\r%8.8d %s sent", 0, statusText);
+ while(i < inst->numMsgs) {
+ if(runMultithreaded) {
+ socknum = inst->idx;
+ } else {
+ if((int) i < numConnections)
+ socknum = i;
+ else if(i >= inst->numMsgs - numConnections) {
+ socknum = i - (inst->numMsgs - numConnections);
+ } else {
+ int rnd = rand();
+ socknum = rnd % numConnections;
+ }
+ }
+ genMsg(buf, sizeof(buf), &lenBuf, inst); /* generate the message to send according to params */
+ if(lenBuf == 0)
+ break; /* terminate when no message could be generated */
+ if(transport == TP_TCP) {
+ if(sockArray[socknum] == -1) {
+ /* connection was dropped, need to re-establish */
+ if(openConn(&(sockArray[socknum]), socknum) != 0) {
+ printf("error in trying to re-open connection %d\n", socknum);
+ exit(1);
+ }
+ }
+ lenSend = sendPlainTCP(socknum, buf, lenBuf, &error_number);
+ } else if(transport == TP_UDP) {
+ lenSend = sendto(udpsockout, buf, lenBuf, 0, &udpRcvr, sizeof(udpRcvr));
+ error_number = errno;
+ } else if(transport == TP_TLS) {
+ if(sockArray[socknum] == -1) {
+ /* connection was dropped, need to re-establish */
+ if(openConn(&(sockArray[socknum]), socknum) != 0) {
+ printf("error in trying to re-open connection %d\n", socknum);
+ exit(1);
+ }
+ initTLSSess(socknum);
+ }
+ if(offsSendBuf + lenBuf < MAX_SENDBUF) {
+ memcpy(sendBuf+offsSendBuf, buf, lenBuf);
+ offsSendBuf += lenBuf;
+ lenSend = lenBuf; /* simulate "good" call */
+ } else {
+ lenSend = sendTLS(socknum, sendBuf, offsSendBuf);
+ lenSend = (lenSend == offsSendBuf) ? lenBuf : -1;
+ memcpy(sendBuf, buf, lenBuf);
+ offsSendBuf = lenBuf;
+ }
+# if defined(ENABLE_OPENSSL)
+ } else if(transport == TP_DTLS) {
+ if(sockArray[0] == -1) {
+ // Init DTLS Session (Bind local listener)
+ initDTLSSess();
+ }
+ lenSend = sendDTLS(buf, lenBuf);
+# endif
+ } else if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ #ifdef ENABLE_RELP
+ relpRetVal relp_ret;
+ if(sockArray[socknum] == -1) {
+ /* connection was dropped, need to re-establish */
+ if(openConn(&(sockArray[socknum]), socknum) != 0) {
+ printf("error in trying to re-open connection %d\n", socknum);
+ exit(1);
+ }
+ }
+ relp_ret = relpCltSendSyslog(relpCltArray[socknum],
+ (unsigned char*)buf, lenBuf);
+ if (relp_ret == RELP_RET_OK) {
+ lenSend = lenBuf; /* mimic ok */
+ } else {
+ lenSend = 0; /* mimic fail */
+ printf("\nrelpCltSendSyslog() failed with relp error code %d\n",
+ relp_ret);
+ }
+ #endif
+ }
+ if(lenSend != lenBuf) {
+ printf("\r%5.5u\n", i);
+ fflush(stdout);
+ test_rs_strerror_r(error_number, errStr, sizeof(errStr));
+ if(lenSend == 0) {
+ printf("tcpflood: socket %d, index %u, msgNum %lld CLOSED REMOTELY\n",
+ sockArray[socknum], i, inst->numSent);
+ } else {
+ printf("tcpflood: send() failed \"%s\" at socket %d, index %u, "
+ "msgNum %lld, lenSend %zd, lenBuf %zd\n",
+ errStr, sockArray[socknum], i, inst->numSent, lenSend,
+ lenBuf);
+ }
+ fflush(stderr);
+
+ if(abortOnSendFail) {
+ printf("tcpflood terminates due to send failure\n");
+ return(1);
+ }
+ }
+ if(i % show_progress_interval == 0) {
+ if(bShowProgress)
+ printf("\r%8.8u", i);
+ }
+ if(!runMultithreaded && bRandConnDrop) {
+ /* if we need to randomly drop connections, see if we
+ * are a victim
+ */
+ if(rand() > (int) (RAND_MAX * dbRandConnDrop)) {
+#if 1
+ if(transport == TP_TLS && offsSendBuf != 0) {
+ /* send remaining buffer */
+ lenSend = sendTLS(socknum, sendBuf, offsSendBuf);
+ if(lenSend != offsSendBuf) {
+ fprintf(stderr, "tcpflood: error in send function causes potential "
+ "data loss lenSend %zd, offsSendBuf %d\n",
+ lenSend, offsSendBuf);
+ }
+ offsSendBuf = 0;
+ }
+#endif
+ ++nConnDrops;
+ close(sockArray[socknum]);
+ sockArray[socknum] = -1;
+ }
+ }
+ if(inst->numSent % batchsize == 0) {
+ usleep(waittime);
+ }
+ ++msgNum;
+ ++i;
+ }
+ if(transport == TP_TLS && offsSendBuf != 0) {
+ /* send remaining buffer */
+ lenSend = sendTLS(socknum, sendBuf, offsSendBuf);
+ }
+ if(!bSilent)
+ printf("\r%8.8u %s sent\n", i, statusText);
+
+ return 0;
+}
+
+
+/* this is the thread that starts a generator
+ */
+static void *
+thrdStarter(void *arg)
+{
+ struct instdata *inst = (struct instdata*) arg;
+ pthread_mutex_lock(&thrdMgmt);
+ runningThreads++;
+ pthread_cond_signal(&condStarted);
+ while(doRun == 0) {
+ pthread_cond_wait(&condDoRun, &thrdMgmt);
+ }
+ pthread_mutex_unlock(&thrdMgmt);
+ if(sendMessages(inst) != 0) {
+ printf("error sending messages\n");
+ }
+ return NULL;
+}
+
+
+/* This function initializes the actual traffic generators. The function sets up all required
+ * parameter blocks and starts threads. It returns when all threads are ready to run
+ * and the main task must just enable them.
+ */
+static void
+prepareGenerators()
+{
+ int i;
+ long long msgsThrd;
+ long long starting = 0;
+ pthread_attr_t thrd_attr;
+
+ if(runMultithreaded) {
+ bSilent = 1;
+ numThrds = numConnections;
+ } else {
+ numThrds = 1;
+ }
+
+ pthread_attr_init(&thrd_attr);
+ pthread_attr_setstacksize(&thrd_attr, 4096*1024);
+
+ runningThreads = 0;
+ doRun = 0;
+ pthread_mutex_init(&thrdMgmt, NULL);
+ pthread_cond_init(&condStarted, NULL);
+ pthread_cond_init(&condDoRun, NULL);
+
+ if(instarray != NULL) {
+ free(instarray);
+ }
+ instarray = calloc(numThrds, sizeof(struct instdata));
+ msgsThrd = numMsgsToSend / numThrds;
+
+ for(i = 0 ; i < numThrds ; ++i) {
+ instarray[i].lower = starting;
+ instarray[i].numMsgs = msgsThrd;
+ instarray[i].numSent = 0;
+ instarray[i].idx = i;
+ pthread_create(&(instarray[i].thread), &thrd_attr, thrdStarter, instarray + i);
+ /*printf("started thread %x\n", (unsigned) instarray[i].thread);*/
+ starting += msgsThrd;
+ }
+}
+
+/* Let all generators run. Threads must have been started. Here we wait until
+ * all threads are initialized and then broadcast that they can begin to run.
+ */
+static void
+runGenerators()
+{
+ pthread_mutex_lock(&thrdMgmt);
+ while(runningThreads != numThrds){
+ pthread_cond_wait(&condStarted, &thrdMgmt);
+ }
+ doRun = 1;
+ pthread_cond_broadcast(&condDoRun);
+ pthread_mutex_unlock(&thrdMgmt);
+}
+
+
+/* Wait for all traffic generators to stop.
+ */
+static void
+waitGenerators()
+{
+ int i;
+ for(i = 0 ; i < numThrds ; ++i) {
+ pthread_join(instarray[i].thread, NULL);
+ /*printf("thread %x stopped\n", (unsigned) instarray[i].thread);*/
+ }
+ pthread_mutex_destroy(&thrdMgmt);
+ pthread_cond_destroy(&condStarted);
+ pthread_cond_destroy(&condDoRun);
+}
+
+/* functions related to computing statistics on the runtime of a test. This is
+ * a separate function primarily not to mess up the test driver.
+ * rgerhards, 2010-12-08
+ */
+static void
+endTiming(struct timeval *tvStart, struct runstats *stats)
+{
+ long sec, usec;
+ unsigned long runtime;
+ struct timeval tvEnd;
+
+ gettimeofday(&tvEnd, NULL);
+ if(tvStart->tv_usec > tvEnd.tv_usec) {
+ tvEnd.tv_sec--;
+ tvEnd.tv_usec += 1000000;
+ }
+
+ sec = tvEnd.tv_sec - tvStart->tv_sec;
+ usec = tvEnd.tv_usec - tvStart->tv_usec;
+
+ runtime = sec * 1000 + (usec / 1000);
+ stats->totalRuntime += runtime;
+ if(runtime < stats->minRuntime)
+ stats->minRuntime = runtime;
+ if(runtime > stats->maxRuntime)
+ stats->maxRuntime = runtime;
+
+ if(!bSilent || bStatsRecords) {
+ if(bCSVoutput) {
+ printf("%lu.%3.3ld\n", runtime / 1000, runtime % 1000);
+ } else {
+ printf("runtime: %lu.%3.3ld\n", runtime / 1000, runtime % 1000);
+ }
+ }
+}
+
+
+/* generate stats summary record at end of run
+ */
+static void
+genStats(struct runstats *stats)
+{
+ long unsigned avg;
+ avg = stats->totalRuntime / stats->numRuns;
+
+ if(bCSVoutput) {
+ printf("#numRuns,TotalRuntime,AvgRuntime,MinRuntime,MaxRuntime\n");
+ printf("%d,%llu.%3.3d,%lu.%3.3lu,%lu.%3.3lu,%lu.%3.3lu\n",
+ stats->numRuns,
+ stats->totalRuntime / 1000, (int) stats->totalRuntime % 1000,
+ avg / 1000, avg % 1000,
+ stats->minRuntime / 1000, stats->minRuntime % 1000,
+ stats->maxRuntime / 1000, stats->maxRuntime % 1000);
+ } else {
+ printf("Runs: %d\n", stats->numRuns);
+ printf("Runtime:\n");
+ printf(" total: %llu.%3.3d\n", stats->totalRuntime / 1000,
+ (int) stats->totalRuntime % 1000);
+ printf(" avg: %lu.%3.3lu\n", avg / 1000, avg % 1000);
+ printf(" min: %lu.%3.3lu\n", stats->minRuntime / 1000, stats->minRuntime % 1000);
+ printf(" max: %lu.%3.3lu\n", stats->maxRuntime / 1000, stats->maxRuntime % 1000);
+ printf("All times are wallclock time.\n");
+ }
+}
+
+
+/* Run the actual test. This function handles various meta-parameters, like
+ * a specified number of iterations, performance measurement and so on...
+ * rgerhards, 2010-12-08
+ */
+static int
+runTests(void)
+{
+ struct timeval tvStart;
+ struct runstats stats;
+ int run;
+
+ stats.totalRuntime = 0;
+ stats.minRuntime = 0xffffffffllu;
+ stats.maxRuntime = 0;
+ stats.numRuns = numRuns;
+ run = 1;
+ while(1) { /* loop broken inside */
+ if(!bSilent)
+ printf("starting run %d\n", run);
+ prepareGenerators();
+ gettimeofday(&tvStart, NULL);
+ runGenerators();
+ waitGenerators();
+ endTiming(&tvStart, &stats);
+ if(run == numRuns)
+ break;
+ if(!bSilent)
+ printf("sleeping %d seconds before next run\n", sleepBetweenRuns);
+ sleep(sleepBetweenRuns);
+ ++run;
+ }
+
+ if(bStatsRecords) {
+ genStats(&stats);
+ }
+
+ return 0;
+}
+
+# if defined(ENABLE_OPENSSL)
+/* OpenSSL implementation of TLS funtions.
+ * alorbach, 2018-06-11
+ */
+
+long BIO_debug_callback(BIO *bio, int cmd, const char __attribute__((unused)) *argp,
+ int argi, long __attribute__((unused)) argl, long ret)
+{
+ long r = 1;
+
+ if (BIO_CB_RETURN & cmd)
+ r = ret;
+
+ printf("tcpflood: openssl debugmsg: BIO[%p]: ", (void *)bio);
+
+ switch (cmd) {
+ case BIO_CB_FREE:
+ printf("Free - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+/* Disabled due API changes for OpenSSL 1.1.0+ */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ case BIO_CB_READ:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ printf("read(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_read(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio));
+ else
+ printf("read(%d,%lu) - %s\n",
+ RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+ printf("write(%d,%lu) - %s fd=%d\n",
+ RSYSLOG_BIO_number_written(bio), (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio));
+ else
+ printf("write(%d,%lu) - %s\n",
+ RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio));
+ break;
+#else
+ case BIO_CB_READ:
+ printf("read %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_WRITE:
+ printf("write %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+#endif
+ case BIO_CB_PUTS:
+ printf("puts() - %s\n", RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_GETS:
+ printf("gets(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_CTRL:
+ printf("ctrl(%lu) - %s\n", (unsigned long)argi,
+ RSYSLOG_BIO_method_name(bio));
+ break;
+ case BIO_CB_RETURN | BIO_CB_READ:
+ printf("read return %ld\n", ret);
+ break;
+ case BIO_CB_RETURN | BIO_CB_WRITE:
+ printf("write return %ld\n", ret);
+ break;
+ case BIO_CB_RETURN | BIO_CB_GETS:
+ printf("gets return %ld\n", ret);
+ break;
+ case BIO_CB_RETURN | BIO_CB_PUTS:
+ printf("puts return %ld\n", ret);
+ break;
+ case BIO_CB_RETURN | BIO_CB_CTRL:
+ printf("ctrl return %ld\n", ret);
+ break;
+ default:
+ printf("bio callback - unknown type (%d)\n", cmd);
+ break;
+ }
+
+ return (r);
+}
+
+void osslLastSSLErrorMsg(int ret, SSL *ssl, const char* pszCallSource)
+{
+ unsigned long un_error = 0;
+ char psz[256];
+
+ if (ssl == NULL) {
+ /* Output Error Info*/
+ printf("tcpflood: Error in '%s' with ret=%d\n", pszCallSource, ret);
+ } else {
+ long iMyRet = SSL_get_error(ssl, ret);
+
+ /* Check which kind of error we have */
+ printf("tcpflood: openssl error '%s' with error code=%ld\n", pszCallSource, iMyRet);
+ if(iMyRet == SSL_ERROR_SYSCALL){
+ iMyRet = ERR_get_error();
+ if(ret == 0) {
+ iMyRet = SSL_get_error(ssl, iMyRet);
+ if(iMyRet == 0) {
+ *psz = '\0';
+ } else {
+ ERR_error_string_n(iMyRet, psz, 256);
+ }
+ printf("tcpflood: Errno %d, SysErr: %s\n", errno, psz);
+ }
+ } else {
+ printf("tcpflood: Unknown SSL Error in '%s' (%d), SSL_get_error: %ld\n",
+ pszCallSource, ret, iMyRet);
+ }
+ }
+
+ /* Loop through errors */
+ while ((un_error = ERR_get_error()) > 0){
+ ERR_error_string_n(un_error, psz, 256);
+ printf("tcpflood: %s Errorstack: %s\n", pszCallSource, psz);
+ }
+}
+
+int verify_callback(int status, X509_STORE_CTX *store)
+{
+ char szdbgdata1[256];
+ char szdbgdata2[256];
+
+ if(status == 0) {
+ printf("tcpflood: verify_callback certificate validation failed!\n");
+
+ X509 *cert = X509_STORE_CTX_get_current_cert(store);
+ int depth = X509_STORE_CTX_get_error_depth(store);
+ int err = X509_STORE_CTX_get_error(store);
+ X509_NAME_oneline(X509_get_issuer_name(cert), szdbgdata1, sizeof(szdbgdata1));
+ X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(cert), szdbgdata2, sizeof(szdbgdata2));
+
+ /* Log Warning only on EXPIRED */
+ if (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) {
+ printf(
+ "tcpflood: Certificate warning at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n",
+ depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err));
+
+ /* Set Status to OK*/
+ status = 1;
+ } else {
+ printf(
+ "tcpflood: Certificate error at depth: %d \n\t"
+ "issuer = %s\n\t"
+ "subject = %s\n\t"
+ "err %d:%s\n",
+ depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err));
+ exit(1);
+ }
+ }
+ return status;
+}
+
+
+/* global init OpenSSL
+ */
+static void
+initTLS(const SSL_METHOD *method)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ /* Setup OpenSSL library < 1.1.0 */
+ if( !SSL_library_init()) {
+#else
+ /* Setup OpenSSL library >= 1.1.0 with system default settings */
+ if( OPENSSL_init_ssl(0, NULL) == 0) {
+#endif
+ printf("tcpflood: error openSSL initialization failed!\n");
+ exit(1);
+ }
+
+ /* Load readable error strings */
+ SSL_load_error_strings();
+ OpenSSL_add_ssl_algorithms();
+ ERR_load_BIO_strings();
+ ERR_load_crypto_strings();
+
+ // Create OpenSSL Context
+ ctx = SSL_CTX_new(method);
+
+ if(tlsCAFile != NULL && SSL_CTX_load_verify_locations(ctx, tlsCAFile, NULL) != 1) {
+ printf("tcpflood: Error, Failed loading CA certificate"
+ " Is the file at the right path? And do we have the permissions?");
+ exit(1);
+ }
+ SSL_CTX_set_ecdh_auto(ctx, 1);
+ if(SSL_CTX_use_certificate_chain_file(ctx, tlsCertFile) != 1) {
+ printf("tcpflood: error cert file could not be accessed -- have you mixed up key and certificate?\n");
+ printf("If in doubt, try swapping the files in -z/-Z\n");
+ printf("Certifcate is: '%s'\n", tlsCertFile);
+ printf("Key is: '%s'\n", tlsKeyFile);
+ exit(1);
+ }
+ if(SSL_CTX_use_PrivateKey_file(ctx, tlsKeyFile, SSL_FILETYPE_PEM) != 1) {
+ printf("tcpflood: error key file could not be accessed -- have you mixed up key and certificate?\n");
+ printf("If in doubt, try swapping the files in -z/-Z\n");
+ printf("Certifcate is: '%s'\n", tlsCertFile);
+ printf("Key is: '%s'\n", tlsKeyFile);
+ exit(1);
+ }
+
+ /* Set CTX Options */
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); /* Disable insecure SSLv2 Protocol */
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); /* Disable insecure SSLv3 Protocol */
+ SSL_CTX_sess_set_cache_size(ctx,1024);
+
+ /* Check for Custom Config string */
+ if (customConfig != NULL){
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+ char *pCurrentPos;
+ char *pNextPos;
+ char *pszCmd;
+ char *pszValue;
+ int iConfErr;
+
+ printf("tcpflood: custom config set to '%s'\n", customConfig);
+
+ /* Set working pointer */
+ pCurrentPos = (char*) customConfig;
+ if (strlen(pCurrentPos) > 0) {
+ pNextPos = index(pCurrentPos, '=');
+ if (pNextPos != NULL) {
+ pszCmd = strndup(pCurrentPos, pNextPos-pCurrentPos);
+ pszValue = strdup(++pNextPos);
+
+ // Create CTX Config Helper
+ SSL_CONF_CTX *cctx;
+ cctx = SSL_CONF_CTX_new();
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
+ SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+
+ /* Add SSL Conf Command */
+ iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue);
+ if (iConfErr > 0) {
+ printf("tcpflood: Successfully added Command %s:%s\n",
+ pszCmd, pszValue);
+ }
+ else {
+ printf("tcpflood: error, adding Command: %s:%s "
+ "in SSL_CONF_cmd with error '%d'\n",
+ pszCmd, pszValue, iConfErr);
+ osslLastSSLErrorMsg(0, NULL, "initTLS");
+ }
+
+ /* Finalize SSL Conf */
+ iConfErr = SSL_CONF_CTX_finish(cctx);
+ if (!iConfErr) {
+ printf("tcpflood: error, setting openssl command parameters: %s\n",
+ customConfig);
+ }
+
+ free(pszCmd);
+ free(pszValue);
+ } else {
+ printf("tcpflood: error, invalid value for -k: %s\n", customConfig);
+ }
+ } else {
+ printf("tcpflood: error, invalid value for -k: %s\n", customConfig);
+ }
+#else
+ printf("tcpflood: TLS library does not support SSL_CONF_cmd API (maybe it is too old?).");
+#endif
+ }
+
+
+ /* DO ONLY SUPPORT DEFAULT CIPHERS YET
+ * SSL_CTX_set_cipher_list(ctx,"ALL"); Support all ciphers */
+
+/* // Create Extra Length DH!
+ pDH = DH_new();
+ if ( !DH_generate_parameters_ex(pDH, 768, DH_GENERATOR_2, NULL) )
+ {
+ if(pDH)
+ DH_free(pDH);
+
+ fprintf(stderr, "Failed to generated dynamic DH\n");
+ exit(1);
+ }
+ else
+ {
+ int iErrCheck = 0;
+ if ( !DH_check( pDH, &iErrCheck) )
+ {
+ fprintf(stderr, "Failed to generated dynamic DH - iErrCheck=%d\n", iErrCheck);
+ exit(1);
+ }
+ }
+*/
+ /* Set default VERIFY Options for OpenSSL CTX - and CALLBACK */
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+
+ SSL_CTX_set_timeout(ctx, 30); /* Default Session Timeout, TODO: Make configureable */
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+}
+
+static void
+exitTLS(void)
+{
+ SSL_CTX_free(ctx);
+ ENGINE_cleanup();
+ ERR_free_strings();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+static void
+initTLSSess(int i)
+{
+ int res;
+ BIO *bio_client;
+ SSL* pNewSsl = SSL_new(ctx);
+
+ sslArray[i] = pNewSsl;
+
+ if(!sslArray[i]) {
+ osslLastSSLErrorMsg(0, sslArray[i], "initTLSSess1");
+ }
+
+ SSL_set_verify(sslArray[i], SSL_VERIFY_NONE, verify_callback);
+
+ /* Create BIO from socket array! */
+ bio_client = BIO_new_socket(sockArray[i], BIO_CLOSE /*BIO_NOCLOSE*/);
+ if (bio_client == NULL) {
+ osslLastSSLErrorMsg(0, sslArray[i], "initTLSSess2");
+ exit(1);
+ } else {
+ // printf("initTLSSess: Init client BIO[%p] done\n", (void *)bio_client);
+ }
+
+ if(tlsLogLevel > 0) {
+ /* Set debug Callback for client BIO as well! */
+ BIO_set_callback(bio_client, BIO_debug_callback);
+ }
+
+ /* Blocking socket */
+ BIO_set_nbio( bio_client, 0 );
+ SSL_set_bio(sslArray[i], bio_client, bio_client);
+ SSL_set_connect_state(sslArray[i]); /*sets ssl to work in client mode.*/
+
+ /* Perform the TLS handshake */
+ if((res = SSL_do_handshake(sslArray[i])) <= 0) {
+ osslLastSSLErrorMsg(res, sslArray[i], "initTLSSess3");
+ exit(1);
+ }
+}
+#pragma GCC diagnostic pop
+
+
+static int
+sendTLS(int i, char *buf, size_t lenBuf)
+{
+ size_t lenSent;
+ int r, err;
+
+ lenSent = 0;
+ while(lenSent != lenBuf) {
+ r = SSL_write(sslArray[i], buf + lenSent, lenBuf - lenSent);
+ if(r > 0) {
+ lenSent += r;
+ } else {
+ err = SSL_get_error(sslArray[i], r);
+ if(err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_WANT_READ &&
+ err != SSL_ERROR_WANT_WRITE) {
+ /*SSL_ERROR_ZERO_RETURN: TLS connection has been closed. This
+ * result code is returned only if a closure alert has occurred
+ * in the protocol, i.e. if the connection has been closed cleanly.
+ *SSL_ERROR_WANT_READ/WRITE: The operation did not complete, try
+ * again later. */
+ printf("Error while sending data: [%d] %s", err, ERR_error_string(err, NULL));
+ printf("Error is: %s", ERR_reason_error_string(err));
+ } else {
+ /* Check for SSL Shutdown */
+ if (SSL_get_shutdown(sslArray[i]) == SSL_RECEIVED_SHUTDOWN) {
+ printf("received SSL_RECEIVED_SHUTDOWN!\n");
+ } else {
+ printf("[ERROR] while sending data: [%d] %s", err, ERR_error_string(err, NULL));
+ printf("[ERROR] Reason: %s", ERR_reason_error_string(err));
+ }
+ }
+ exit(1);
+ }
+ }
+
+ return lenSent;
+}
+
+static void
+closeTLSSess(int i)
+{
+ int r;
+ r = SSL_shutdown(sslArray[i]);
+ if (r <= 0){
+ /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more:
+ * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html
+ */
+ char rcvBuf[MAX_RCVBUF];
+ SSL_read(sslArray[i], rcvBuf, MAX_RCVBUF);
+
+ }
+ SSL_free(sslArray[i]);
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+static void
+initDTLSSess()
+{
+ int res;
+ BIO *bio_client;
+
+ // Create new SSL
+ SSL* pNewSsl = SSL_new(ctx);
+
+ // set to array variables
+ sslArray[0] = pNewSsl;
+ sockArray[0] = udpsockout;
+
+ if(!sslArray[0]) {
+ fprintf(stderr, "Unable to create SSL\n");
+ osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess1");
+ exit(1);
+ }
+
+ SSL_set_verify(sslArray[0], SSL_VERIFY_NONE, verify_callback);
+
+ /* Create BIO from socket array! */
+ bio_client = BIO_new_dgram(udpsockout, BIO_NOCLOSE);
+ if (!bio_client) {
+ fprintf(stderr, "Unable to create BIO\n");
+ osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess2");
+ exit(1);
+ }
+ BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dtls_client_addr);
+ SSL_set_bio(sslArray[0], bio_client, bio_client);
+
+
+ if(tlsLogLevel > 0) {
+ /* Set debug Callback for client BIO as well! */
+ BIO_set_callback(bio_client, BIO_debug_callback);
+ }
+
+ /* Blocking socket */
+// BIO_set_nbio( bio_client, 0 );
+// SSL_set_bio(sslArray[0], bio_client, bio_client);
+// SSL_set_connect_state(sslArray[0]); /*sets ssl to work in client mode.*/
+
+ printf("[DEBUG] Starting DTLS session ...\n");
+ /* Perform handshake */
+ if (SSL_connect(sslArray[0]) <= 0) {
+ fprintf(stderr, "SSL_connect failed\n");
+ osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess3");
+ exit(1);
+ }
+
+ // Print Cipher info
+ const SSL_CIPHER *cipher = SSL_get_current_cipher(sslArray[0]);
+ if(tlsLogLevel > 0) {
+ printf("[DEBUG] Cipher used: %s\n", SSL_CIPHER_get_name(cipher));
+ }
+
+ // Print Peer Certificate info
+ if(tlsLogLevel > 0) {
+ X509 *cert = SSL_get_peer_certificate(sslArray[0]);
+ if (cert != NULL) {
+ char *line;
+ line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ printf("[DEBUG] Subject: %s\n", line);
+ OPENSSL_free(line);
+
+ line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ printf("[DEBUG] Issuer: %s\n", line);
+ OPENSSL_free(line);
+ X509_free(cert);
+ } else {
+ printf("[DEBUG] No certificates.\n");
+ }
+ }
+
+ /* Set and activate timeouts */
+ struct timeval timeout;
+ timeout.tv_sec = 3;
+ timeout.tv_usec = 0;
+ BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
+}
+#pragma GCC diagnostic pop
+
+
+static int
+sendDTLS(char *buf, size_t lenBuf)
+{
+ size_t lenSent;
+ int r, err;
+
+ lenSent = 0;
+ r = SSL_write(sslArray[0], buf + lenSent, lenBuf - lenSent);
+ if(r > 0) {
+ lenSent += r;
+ } else {
+ err = SSL_get_error(sslArray[0], r);
+ int err = SSL_get_error(sslArray[0], r);
+ switch(err) {
+ case SSL_ERROR_SYSCALL:
+ printf("[ERROR] SSL_write (SSL_ERROR_SYSCALL): %s\n", strerror(errno));
+ break;
+ default:
+ printf("[ERROR] while sending data: [%d] %s", err, ERR_error_string(err, NULL));
+ printf("[ERROR] Reason: %s", ERR_reason_error_string(err));
+ }
+ exit(1);
+ }
+ return lenSent;
+}
+
+static void
+closeDTLSSess()
+{
+ printf("closeDTLSSess ENTER\n");
+
+ int r;
+ r = SSL_shutdown(sslArray[0]);
+ if (r <= 0){
+ /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more:
+ * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html
+ */
+ char rcvBuf[MAX_RCVBUF];
+ SSL_read(sslArray[0], rcvBuf, MAX_RCVBUF);
+
+ }
+ SSL_free(sslArray[0]);
+ close(udpsockout);
+ close(udpsockin);
+
+ printf("closeDTLSSess EXIT\n");
+}
+
+# elif defined(ENABLE_GNUTLS)
+/* This defines a log function to be provided to GnuTLS. It hopefully
+ * helps us track down hard to find problems.
+ * rgerhards, 2008-06-20
+ */
+static void tlsLogFunction(int level, const char *msg)
+{
+ printf("GnuTLS (level %d): %s", level, msg);
+}
+
+static void
+exitTLS(void)
+{
+}
+
+/* global init GnuTLS
+ */
+static void
+initTLS(void)
+{
+ int r;
+
+ /* order of gcry_control and gnutls_global_init matters! */
+ #if GNUTLS_VERSION_NUMBER <= 0x020b00
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ #endif
+ gnutls_global_init();
+ /* set debug mode, if so required by the options */
+ if(tlsLogLevel > 0) {
+ gnutls_global_set_log_function(tlsLogFunction);
+ gnutls_global_set_log_level(tlsLogLevel);
+ }
+
+ r = gnutls_certificate_allocate_credentials(&tlscred);
+ if(r != GNUTLS_E_SUCCESS) {
+ printf("error allocating credentials\n");
+ gnutls_perror(r);
+ exit(1);
+ }
+ r = gnutls_certificate_set_x509_key_file(tlscred, tlsCertFile, tlsKeyFile, GNUTLS_X509_FMT_PEM);
+ if(r != GNUTLS_E_SUCCESS) {
+ printf("error setting certificate files -- have you mixed up key and certificate?\n");
+ printf("If in doubt, try swapping the files in -z/-Z\n");
+ printf("Certifcate is: '%s'\n", tlsCertFile);
+ printf("Key is: '%s'\n", tlsKeyFile);
+ gnutls_perror(r);
+ r = gnutls_certificate_set_x509_key_file(tlscred, tlsKeyFile, tlsCertFile,
+ GNUTLS_X509_FMT_PEM);
+ if(r == GNUTLS_E_SUCCESS) {
+ printf("Tried swapping files, this seems to work "
+ "(but results may be unpredictable!)\n");
+ } else {
+ exit(1);
+ }
+ }
+}
+
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+static void
+initTLSSess(int i)
+{
+ int r;
+ gnutls_init(sessArray + i, GNUTLS_CLIENT);
+
+ /* Use default priorities */
+ gnutls_set_default_priority(sessArray[i]);
+
+ /* put our credentials to the current session */
+ r = gnutls_credentials_set(sessArray[i], GNUTLS_CRD_CERTIFICATE, tlscred);
+ if(r != GNUTLS_E_SUCCESS) {
+ fprintf (stderr, "Setting credentials failed\n");
+ gnutls_perror(r);
+ exit(1);
+ }
+
+ /* NOTE: the following statement generates a cast warning, but there seems to
+ * be no way around it with current GnuTLS. Do NOT try to "fix" the situation!
+ */
+ gnutls_transport_set_ptr(sessArray[i], (gnutls_transport_ptr_t) sockArray[i]);
+
+ /* Perform the TLS handshake */
+ r = gnutls_handshake(sessArray[i]);
+ if(r < 0) {
+ fprintf (stderr, "TLS Handshake failed\n");
+ gnutls_perror(r);
+ exit(1);
+ }
+}
+#pragma GCC diagnostic pop
+
+
+static int
+sendTLS(int i, char *buf, size_t lenBuf)
+{
+ int lenSent;
+ int r;
+
+ lenSent = 0;
+ while(lenSent != lenBuf) {
+ r = gnutls_record_send(sessArray[i], buf + lenSent, lenBuf - lenSent);
+ if(r < 0)
+ break;
+ lenSent += r;
+ }
+
+ return lenSent;
+}
+
+static void
+closeTLSSess(int i)
+{
+ gnutls_bye(sessArray[i], GNUTLS_SHUT_RDWR);
+ gnutls_deinit(sessArray[i]);
+}
+# else /* NO TLS available */
+static void initTLS(void) {}
+static void exitTLS(void) {}
+static void initTLSSess(int __attribute__((unused)) i) {}
+static int sendTLS(int __attribute__((unused)) i, char __attribute__((unused)) *buf,
+ size_t __attribute__((unused)) lenBuf) { return 0; }
+static void closeTLSSess(int __attribute__((unused)) i) {}
+
+static void initDTLSSess(void) {}
+static int sendDTLS(char *buf, size_t lenBuf) {}
+static void closeDTLSSess(void) {}
+# endif
+
+static void
+setTargetPorts(const char *const port_arg)
+{
+ int i = 0;
+
+ char *saveptr;
+ char *ports = strdup(port_arg);
+ char *port = strtok_r(ports, ":", &saveptr);
+ while(port != NULL) {
+ if(i == sizeof(targetPort)/sizeof(int)) {
+ fprintf(stderr, "too many ports specified, max %d\n",
+ (int) (sizeof(targetPort)/sizeof(int)));
+ exit(1);
+ }
+ targetPort[i] = atoi(port);
+ i++;
+ port = strtok_r(NULL, ":", &saveptr);
+ }
+ free(ports);
+}
+
+
+/* Run the test.
+ * rgerhards, 2009-04-03
+ */
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int opt;
+ struct sigaction sigAct;
+ struct rlimit maxFiles;
+ static char buf[1024];
+
+ srand(time(NULL)); /* seed is good enough for our needs */
+
+ /* on Solaris, we do not HAVE MSG_NOSIGNAL, so for this reason
+ * we block SIGPIPE (not an issue for this program)
+ */
+ memset(&sigAct, 0, sizeof(sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sigAct, NULL);
+
+ setvbuf(stdout, buf, _IONBF, 48);
+
+ while((opt = getopt(argc, argv, "a:ABb:c:C:d:DeE:f:F:i:I:j:k:l:L:m:M:n:OP:p:rR:sS:t:T:u:vW:x:XyYz:Z:")) != -1) {
+ switch (opt) {
+ case 'b': batchsize = atoll(optarg);
+ break;
+ case 't': targetIP = optarg;
+ break;
+ case 'p': setTargetPorts(optarg);
+ break;
+ case 'n': numTargetPorts = atoi(optarg);
+ break;
+ case 'c': numConnections = atoi(optarg);
+ if(numConnections < 0) {
+ numConnections *= -1;
+ softLimitConnections = 1;
+ }
+ break;
+ case 'C': numFileIterations = atoi(optarg);
+ break;
+ case 'm': numMsgsToSend = atoi(optarg);
+ break;
+ case 'i': msgNum = atoi(optarg);
+ break;
+ case 'P': msgPRI = optarg;
+ break;
+ case 'j': jsonCookie = optarg;
+ break;
+ case 'd': extraDataLen = atoi(optarg);
+ if(extraDataLen > MAX_EXTRADATA_LEN) {
+ fprintf(stderr, "-d max is %d!\n",
+ MAX_EXTRADATA_LEN);
+ exit(1);
+ }
+ break;
+ case 'D': bRandConnDrop = 1;
+ break;
+ case 'l':
+ dbRandConnDrop = atof(optarg);
+ printf("RandConnDrop Level: '%lf' \n", dbRandConnDrop);
+ break;
+ case 'r': bRandomizeExtraData = 1;
+ break;
+ case 'f': dynFileIDs = atoi(optarg);
+ break;
+ case 'F': frameDelim = atoi(optarg);
+ break;
+ case 'L': tlsLogLevel = atoi(optarg);
+ break;
+ case 'M': MsgToSend = optarg;
+ break;
+ case 'I': dataFile = optarg;
+ /* in this mode, we do not know the num messages to send, so
+ * we set a (high) number to keep the code happy.
+ */
+ numMsgsToSend = 1000000;
+ break;
+ case 's': bSilent = 1;
+ break;
+ case 'B': bBinaryFile = 1;
+ break;
+ case 'R': numRuns = atoi(optarg);
+ break;
+ case 'S': sleepBetweenRuns = atoi(optarg);
+ break;
+ case 'X': bStatsRecords = 1;
+ break;
+ case 'e': bCSVoutput = 1;
+ break;
+ case 'T': if(!strcmp(optarg, "udp")) {
+ transport = TP_UDP;
+ } else if(!strcmp(optarg, "tcp")) {
+ transport = TP_TCP;
+ } else if(!strcmp(optarg, "tls")) {
+# if defined(ENABLE_OPENSSL)
+ transport = TP_TLS;
+# elif defined(ENABLE_GNUTLS)
+ transport = TP_TLS;
+# else
+ fprintf(stderr, "compiled without gnutls/openssl TLS support: "
+ "\"-Ttls\" not supported!\n");
+ exit(1);
+# endif
+ } else if(!strcmp(optarg, "relp-plain")) {
+# if defined(ENABLE_RELP)
+ transport = TP_RELP_PLAIN;
+# else
+ fprintf(stderr, "compiled without RELP support: "
+ "\"-Trelp-plain\" not supported!\n"
+ "(add --enable-relp to ./configure options "
+ "if desired)\n");
+ exit(1);
+# endif
+ } else if(!strcmp(optarg, "relp-tls")) {
+# if defined(ENABLE_RELP)
+ transport = TP_RELP_TLS;
+# else
+ fprintf(stderr, "compiled without RELP support: "
+ "\"-Trelp-tls\" not supported!\n"
+ "(add --enable-relp to ./configure options "
+ "if desired)\n");
+ exit(1);
+# endif
+ } else if(!strcmp(optarg, "dtls")) {
+# if defined(ENABLE_OPENSSL)
+ transport = TP_DTLS;
+# else
+ fprintf(stderr, "compiled without openssl TLS support: "
+ "\"-Tdtls\" not supported!\n");
+ exit(1);
+# endif
+ } else {
+ fprintf(stderr, "unknown transport '%s'\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'a': relpAuthMode = optarg;
+ break;
+ case 'A': abortOnSendFail = 0;
+ break;
+ case 'E': relpPermittedPeer = optarg;
+ break;
+ case 'u':
+#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
+ relpTlsLib = optarg;
+#endif
+ break;
+ case 'W': waittime = atoi(optarg);
+ break;
+ case 'Y': runMultithreaded = 1;
+ break;
+ case 'y': useRFC5424Format = 1;
+ break;
+ case 'x': tlsCAFile = optarg;
+ break;
+ case 'z': tlsKeyFile = optarg;
+ break;
+ case 'Z': tlsCertFile = optarg;
+ break;
+ case 'O': octateCountFramed = 1;
+ break;
+ case 'v': verbose = 1;
+ break;
+ case 'k': customConfig = optarg;
+ break;
+ default: printf("invalid option '%c' or value missing - terminating...\n", opt);
+ exit (1);
+ break;
+ }
+ }
+
+ const char *const ci_env = getenv("CI");
+ if(ci_env != NULL && !strcmp(ci_env, "true")) {
+ bSilent = 1; /* auto-apply silent option during CI runs */
+ }
+
+ if(tlsCAFile != NULL && transport != TP_RELP_TLS) {
+ #if !defined(ENABLE_OPENSSL)
+ fprintf(stderr, "-x CAFile not supported in GnuTLS mode - ignored.\n"
+ "Note: we do NOT VERIFY the remote peer when compiled for GnuTLS.\n"
+ "When compiled for OpenSSL, we do.\n");
+ #endif
+ }
+
+ if(bStatsRecords && waittime) {
+ fprintf(stderr, "warning: generating performance stats and using a waittime "
+ "is somewhat contradictory!\n");
+ }
+
+ if(!isatty(1) || bSilent)
+ bShowProgress = 0;
+
+ if(numConnections > 20) {
+ /* if we use many (whatever this means, 20 is randomly picked)
+ * connections, we need to make sure we have a high enough
+ * limit. -- rgerhards, 2010-03-25
+ */
+ maxFiles.rlim_cur = numConnections + 20;
+ maxFiles.rlim_max = numConnections + 20;
+ if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
+ perror("setrlimit to increase file handles failed");
+ fprintf(stderr,
+ "could not set sufficiently large number of "
+ "open files for required connection count!\n");
+ if(!softLimitConnections) {
+ exit(1);
+ }
+ }
+ }
+
+ if(dataFile != NULL) {
+ if((dataFP = fopen(dataFile, "r")) == NULL) {
+ perror(dataFile);
+ exit(1);
+ }
+ }
+
+ if(tlsKeyFile != NULL || tlsCertFile != NULL) {
+ if( transport != TP_TLS &&
+ transport != TP_DTLS &&
+ transport != TP_RELP_TLS) {
+ printf("error: TLS certificates were specified, but TLS is NOT enabled: "
+ "To enable TLS use parameter -Ttls\n");
+ exit(1);
+ }
+ }
+
+ if(transport == TP_TLS) {
+ if(tlsKeyFile == NULL || tlsCertFile == NULL) {
+ printf("error: transport TLS is specified (-Ttls), -z and -Z must also "
+ "be specified\n");
+ exit(1);
+ }
+ /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for newer versions! */
+#if defined(ENABLE_OPENSSL)
+# if OPENSSL_VERSION_NUMBER < 0x10100000L
+ initTLS(SSLv23_method());
+# else
+ initTLS(TLS_method());
+# endif
+#else
+ initTLS();
+#endif
+ } else if(transport == TP_DTLS) {
+ if(tlsKeyFile == NULL || tlsCertFile == NULL) {
+ printf("error: transport DTLS is specified (-Tdtls), -z and -Z must also "
+ "be specified\n");
+ exit(1);
+ }
+#if defined(ENABLE_OPENSSL)
+ initTLS(DTLS_client_method());
+#else
+ printf("error: transport DTLS is specified (-Tdtls) but not supported in GnuTLS driver\n");
+ exit(1);
+#endif
+ } else if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ #ifdef ENABLE_RELP
+ initRELP_PLAIN();
+ #endif
+ }
+
+ if(openConnections() != 0) {
+ printf("error opening connections\n");
+ exit(1);
+ }
+
+ if(runTests() != 0) {
+ printf("error running tests\n");
+ exit(1);
+ }
+
+ closeConnections(); /* this is important so that we do not finish too early! */
+
+ #ifdef ENABLE_RELP
+ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) {
+ CHKRELP(relpEngineDestruct(&pRelpEngine));
+ }
+ #endif
+
+ if(nConnDrops > 0 && !bSilent)
+ printf("-D option initiated %ld connection closures\n", nConnDrops);
+
+ if(!bSilent)
+ printf("End of tcpflood Run\n");
+
+ if(transport == TP_TLS) {
+ exitTLS();
+ }
+
+ exit(ret);
+}
diff --git a/tests/tcpflood_wrong_option_output.sh b/tests/tcpflood_wrong_option_output.sh
new file mode 100755
index 0000000..308074b
--- /dev/null
+++ b/tests/tcpflood_wrong_option_output.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+
+options=-t
+./tcpflood $options &> $RSYSLOG_OUT_LOG
+content_check 'invalid option'
+
+options=-Ttls
+valgrind --error-exitcode=10 ./tcpflood $options &> $RSYSLOG_OUT_LOG
+if [ $? -eq 10 ]; then
+ cat "$RSYSLOG_OUT_LOG"
+ printf 'FAIL: valgrind failed with options: %s\n' "$options"
+ error_exit 1
+fi
+content_check '-z and -Z must also be specified'
+
+exit_test
diff --git a/tests/template-const-jsonf.sh b/tests/template-const-jsonf.sh
new file mode 100755
index 0000000..f79c94e
--- /dev/null
+++ b/tests/template-const-jsonf.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# added 2018-02-10 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ constant(outname="@version" value="1" format="jsonf")
+ constant(value="\n")
+}
+
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='"@version": "1"'
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/template-json.sh b/tests/template-json.sh
new file mode 100755
index 0000000..ebe1a04
--- /dev/null
+++ b/tests/template-json.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+set $!backslash = "a \\ \"b\" c / d"; # '/' must not be escaped!
+
+template(name="json" type="list" option.json="on") {
+ constant(value="{")
+ constant(value="\"backslash\":\"")
+ property(name="$!backslash")
+ constant(value="\"}\n")
+}
+
+:msg, contains, "msgnum:" action(type="omfile" template="json"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+injectmsg 0 1
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown # we need to wait until rsyslogd is finished!
+
+printf '{"backslash":"a \\\\ \\"b\\" c / d"}\n' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid JSON generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/template-pos-from-to-lowercase.sh b/tests/template-pos-from-to-lowercase.sh
new file mode 100755
index 0000000..8aa8a8e
--- /dev/null
+++ b/tests/template-pos-from-to-lowercase.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-28 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:9:16:lowercase%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m9
+shutdown_when_empty
+wait_shutdown
+seq_check 0 8
+exit_test
diff --git a/tests/template-pos-from-to-missing-jsonvar.sh b/tests/template-pos-from-to-missing-jsonvar.sh
new file mode 100755
index 0000000..8bbd53a
--- /dev/null
+++ b/tests/template-pos-from-to-missing-jsonvar.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# addd 2016-03-28 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="-%$!non!existing!var:109:116:%-\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "--" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ echo "expected was:"
+ echo "--"
+ exit 1
+fi;
+exit_test
diff --git a/tests/template-pos-from-to-oversize-lowercase.sh b/tests/template-pos-from-to-oversize-lowercase.sh
new file mode 100755
index 0000000..033ab47
--- /dev/null
+++ b/tests/template-pos-from-to-oversize-lowercase.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# addd 2016-03-28 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="-%msg:109:116:lowercase%-\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "--" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ echo "expected was:"
+ echo "--"
+ exit 1
+fi;
+exit_test
diff --git a/tests/template-pos-from-to-oversize.sh b/tests/template-pos-from-to-oversize.sh
new file mode 100755
index 0000000..8ca2a5d
--- /dev/null
+++ b/tests/template-pos-from-to-oversize.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+# addd 2016-03-28 by RGerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+echo "*** string template ****"
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="-%msg:109:116:%-\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "--" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ echo "expected was:"
+ echo "--"
+ exit 1
+fi;
+
+echo "*** list template ****"
+rm $RSYSLOG_OUT_LOG # cleanup previous run
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+template(name="outfmt" type="list") {
+ constant(value="-")
+ property(name="msg" position.from="109" position.to="116")
+ constant(value="-")
+ constant(value="\n")
+}
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "--" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid output generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ echo "expected was:"
+ echo "--"
+ exit 1
+fi;
+exit_test
diff --git a/tests/template-pos-from-to.sh b/tests/template-pos-from-to.sh
new file mode 100755
index 0000000..aecb022
--- /dev/null
+++ b/tests/template-pos-from-to.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-28 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:9:16:%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+startup
+tcpflood -m9
+shutdown_when_empty
+wait_shutdown
+seq_check 0 8
+exit_test
diff --git a/tests/template-pure-json.sh b/tests/template-pure-json.sh
new file mode 100755
index 0000000..a756e02
--- /dev/null
+++ b/tests/template-pure-json.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# added 2018-02-10 by Rainer Gerhards; Released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="list" option.jsonf="on") {
+ property(outname="message" name="msg" format="jsonf")
+ constant(outname="@version" value="1" format="jsonf")
+}
+
+local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='{"message":" msgnum:00000000:", "@version": "1"}'
+cmp_exact $RSYSLOG_OUT_LOG
+exit_test
diff --git a/tests/template-topos-neg.sh b/tests/template-topos-neg.sh
new file mode 100755
index 0000000..d17fdb7
--- /dev/null
+++ b/tests/template-topos-neg.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# This is part of the rsyslog testbench, licensed under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="out" type="list") {
+ property(name="STRUCTURED-DATA" position.from="2" position.to="-1")
+ constant(value="\n")
+}
+
+local4.debug action(type="omfile" template="out" file="'$RSYSLOG_OUT_LOG'")
+'
+startup
+injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] msgnum:irrelevant'
+shutdown_when_empty
+wait_shutdown
+export EXPECTED='tcpflood@32473 MSGNUM="0"'
+cmp_exact
+exit_test
diff --git a/tests/test.mmdb b/tests/test.mmdb
new file mode 100644
index 0000000..016953e
--- /dev/null
+++ b/tests/test.mmdb
Binary files differ
diff --git a/tests/test_id.c b/tests/test_id.c
new file mode 100644
index 0000000..326ad3f
--- /dev/null
+++ b/tests/test_id.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <time.h>
+
+/* one provided by Aaaron Wiebe based on perl's hashing algorithm
+ * (so probably pretty generic). Not for excessively large strings!
+ */
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#endif
+static unsigned __attribute__((nonnull(1))) int
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+hash_from_string(void *k)
+{
+ char *rkey = (char*) k;
+ unsigned hashval = 1;
+
+ while (*rkey)
+ hashval = hashval * 33 + *rkey++;
+
+ return hashval;
+}
+
+int main(int argc, char *argv[])
+{
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday(&tv, &tz);
+ if(argc != 2) {
+ fprintf(stderr, "usage: test_id test-file-name\n");
+ exit(1);
+ }
+ printf("%06ld_%04.4x", tv.tv_usec, hash_from_string(argv[1]));
+
+ return 0;
+}
diff --git a/tests/test_id_usage_output.sh b/tests/test_id_usage_output.sh
new file mode 100755
index 0000000..b4c6593
--- /dev/null
+++ b/tests/test_id_usage_output.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# add 2016-11-22 by Jan Gerhards, released under ASL 2.0
+
+. ${srcdir:=.}/diag.sh init
+
+./test_id &> $RSYSLOG_DYNNAME.output
+grep "usage: test_id" $RSYSLOG_DYNNAME.output
+
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated"
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/testsuites/abort-uncleancfg-goodcfg.conf b/tests/testsuites/abort-uncleancfg-goodcfg.conf
new file mode 100755
index 0000000..e3c3a98
--- /dev/null
+++ b/tests/testsuites/abort-uncleancfg-goodcfg.conf
@@ -0,0 +1,9 @@
+$AbortOnUncleanConfig on
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
diff --git a/tests/testsuites/action-tx-errfile.result b/tests/testsuites/action-tx-errfile.result
new file mode 100644
index 0000000..c9698c9
--- /dev/null
+++ b/tests/testsuites/action-tx-errfile.result
@@ -0,0 +1,25 @@
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000001:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000003:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000005:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000007:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000009:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000011:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000013:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000015:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000017:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000019:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000021:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000023:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000025:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000027:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000029:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000031:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000033:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000035:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000037:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000039:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000041:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000043:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000045:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000047:\", )" }
+{ "action": "mysql_action", "status": -2218, "template0": "insert into SystemEvents (Message, Facility) values (\" msgnum:00000049:\", )" }
diff --git a/tests/testsuites/complex_replace_input b/tests/testsuites/complex_replace_input
new file mode 100644
index 0000000..a177a4b
--- /dev/null
+++ b/tests/testsuites/complex_replace_input
@@ -0,0 +1,4 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: try to replace syslog and sysyslog with rsyslog
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: try to replace hello in hellolo and helhello with hello_world
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: try to foo_bar_baz in foo_bar_baz_quux and quux_foo_bar_baz with FBB
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: in the end of msg; try to not lose as_longer_this_string_as_more_probability_to_catch_the_bu
diff --git a/tests/testsuites/date_time_msg b/tests/testsuites/date_time_msg
new file mode 100644
index 0000000..9b74b1b
--- /dev/null
+++ b/tests/testsuites/date_time_msg
@@ -0,0 +1,2 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: at Thu Oct 30 13:20:18 IST 2014 random number is 19597
+
diff --git a/tests/testsuites/docroot/file.txt b/tests/testsuites/docroot/file.txt
new file mode 100644
index 0000000..ef6d6f7
--- /dev/null
+++ b/tests/testsuites/docroot/file.txt
@@ -0,0 +1 @@
+This is a test of get page
diff --git a/tests/testsuites/dynstats_empty_input b/tests/testsuites/dynstats_empty_input
new file mode 100644
index 0000000..d47777b
--- /dev/null
+++ b/tests/testsuites/dynstats_empty_input
@@ -0,0 +1,7 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix foo 001
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix bar 002
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix baz 003
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix quux 004
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix corge 005
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix foo 006
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:prefix grault 007
diff --git a/tests/testsuites/dynstats_input b/tests/testsuites/dynstats_input
new file mode 100644
index 0000000..0a8cd10
--- /dev/null
+++ b/tests/testsuites/dynstats_input
@@ -0,0 +1,6 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006
diff --git a/tests/testsuites/dynstats_input_1 b/tests/testsuites/dynstats_input_1
new file mode 100644
index 0000000..345f5e4
--- /dev/null
+++ b/tests/testsuites/dynstats_input_1
@@ -0,0 +1,2 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002
diff --git a/tests/testsuites/dynstats_input_2 b/tests/testsuites/dynstats_input_2
new file mode 100644
index 0000000..bee20ae
--- /dev/null
+++ b/tests/testsuites/dynstats_input_2
@@ -0,0 +1,2 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004
diff --git a/tests/testsuites/dynstats_input_3 b/tests/testsuites/dynstats_input_3
new file mode 100644
index 0000000..4f88f24
--- /dev/null
+++ b/tests/testsuites/dynstats_input_3
@@ -0,0 +1,2 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006
diff --git a/tests/testsuites/dynstats_input_more_0 b/tests/testsuites/dynstats_input_more_0
new file mode 100644
index 0000000..8d9ec23
--- /dev/null
+++ b/tests/testsuites/dynstats_input_more_0
@@ -0,0 +1,10 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 001
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:bar 002
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 003
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 004
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:baz 005
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 006
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 007
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 008
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 009
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 010
diff --git a/tests/testsuites/dynstats_input_more_1 b/tests/testsuites/dynstats_input_more_1
new file mode 100644
index 0000000..64da0ef
--- /dev/null
+++ b/tests/testsuites/dynstats_input_more_1
@@ -0,0 +1,3 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 011
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:grault 012
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 013
diff --git a/tests/testsuites/dynstats_input_more_2 b/tests/testsuites/dynstats_input_more_2
new file mode 100644
index 0000000..d5b575c
--- /dev/null
+++ b/tests/testsuites/dynstats_input_more_2
@@ -0,0 +1,5 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 014
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:grault 015
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:quux 016
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:foo 017
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:corge 018
diff --git a/tests/testsuites/es.yml b/tests/testsuites/es.yml
new file mode 100644
index 0000000..4e59572
--- /dev/null
+++ b/tests/testsuites/es.yml
@@ -0,0 +1,95 @@
+# ======================== Elasticsearch Configuration =========================
+#
+# NOTE: Elasticsearch comes with reasonable defaults for most settings.
+# Before you set out to tweak and tune the configuration, make sure you
+# understand what are you trying to accomplish and the consequences.
+#
+# The primary way of configuring a node is via this file. This template lists
+# the most important settings you may want to configure for a production cluster.
+#
+# Please consult the documentation for further information on configuration options:
+# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
+#
+# ---------------------------------- Cluster -----------------------------------
+#
+# Use a descriptive name for your cluster:
+#
+cluster.name: rsyslog-testbench
+#
+# ------------------------------------ Node ------------------------------------
+#
+# Use a descriptive name for the node:
+#
+#node.name: node-1
+#
+# Add custom attributes to the node:
+#
+#node.attr.rack: r1
+#
+# ----------------------------------- Paths ------------------------------------
+#
+# Path to directory where to store the data (separate multiple locations by comma):
+#
+#path.data: ./data
+#
+# Path to log files:
+#
+#path.logs: ./logs
+#
+# ----------------------------------- Memory -----------------------------------
+#
+# Lock the memory on startup:
+#
+#bootstrap.memory_lock: true
+#
+# Make sure that the heap size is set to about half the memory available
+# on the system and that the owner of the process is allowed to use this
+# limit.
+#
+# Elasticsearch performs poorly when the system is swapping the memory.
+#
+# ---------------------------------- Network -----------------------------------
+#
+# Set the bind address to a specific IP (IPv4 or IPv6):
+#
+#network.host: 192.168.0.1
+#
+# Set a custom port for HTTP:
+#
+http.port: 19200
+
+transport.tcp.port: 19300
+
+
+#
+# For more information, consult the network module documentation.
+#
+# --------------------------------- Discovery ----------------------------------
+#
+# Pass an initial list of hosts to perform discovery when new node is started:
+# The default list of hosts is ["127.0.0.1", "[::1]"]
+#
+#discovery.zen.ping.unicast.hosts: ["host1", "host2"]
+#
+# Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):
+#
+#discovery.zen.minimum_master_nodes: 3
+#
+# For more information, consult the zen discovery module documentation.
+#
+# ---------------------------------- Gateway -----------------------------------
+#
+# Block initial recovery after a full cluster restart until N nodes are started:
+#
+#gateway.recover_after_nodes: 3
+#
+# For more information, consult the gateway module documentation.
+#
+# ---------------------------------- Various -----------------------------------
+#
+# Require explicit names when deleting indices:
+#
+#action.destructive_requires_name: true
+
+# Limit memory usage
+indices.fielddata.cache.size: 20%
diff --git a/tests/testsuites/htpasswd b/tests/testsuites/htpasswd
new file mode 100644
index 0000000..e97b916
--- /dev/null
+++ b/tests/testsuites/htpasswd
@@ -0,0 +1 @@
+user1:$apr1$G4elKiJd$nuUxwMObJ/thIuoQCNEen0
diff --git a/tests/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input b/tests/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input
new file mode 100644
index 0000000..cf778c0
--- /dev/null
+++ b/tests/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input
@@ -0,0 +1,15 @@
+<Obj:1:strm:1:
++iCurrFNum:2:1:1:
++pszFName:1:15:./rsyslog.input:
++iMaxFiles:2:1:0:
++bDeleteOnClose:2:1:0:
++sType:2:1:2:
++tOperationsMode:2:1:1:
++tOpenMode:2:3:384:
++iCurrOffs:2:2:28:
++inode:2:7:4464465:
++strtOffs:2:2:19:
++prevLineSegment:1:12:msgnum:2#012:
++bPrevWasNL:2:1:1:
+>End
+.
diff --git a/tests/testsuites/imhttp-large-data.txt b/tests/testsuites/imhttp-large-data.txt
new file mode 100644
index 0000000..e9840fe
--- /dev/null
+++ b/tests/testsuites/imhttp-large-data.txt
@@ -0,0 +1,250 @@
+thenceforth reenters forefoot manufactures tricked pyromaniacs gratefully tremendously coverall transliterating outspreading ridded airtight splashy
+provocation freewheeling purloining dramatizations Rosecrans abandons travestying Saxons spikier therapeutics chatting hides Epicurean choreographer wildfire preheating buys Ryder astonishment urbaner
+redoubling sights luckiness initialization fishbowls Na Taichung initiator chrysalises Conakry converters backbit appliqué fashionable disavowal sent racquetballs
+mischance aeration gameness unites hardcovers portlier fusillade squirmed raffish redirect incrusting leaflets importantly besiege predominate intimacy
+elitist threw retrorockets piked fuzziness coached antihistamine misguides sinister Moors thirteenths founding drownings Permalloy newsworthiest
+Ride frothier symbol cater unhitched briskly peculiarly limber goulashes garments stymie famished
+whitest flaccid splattered copyrights purpler Isabelle pyromania spout savvied icily cargo Gabriela subjects headquarters Zelig rhythmically surnames adherents
+transfigured sobriquet milksop romped luminosity hoots saline Florine bridegrooms thorns carom
+irritants emigrating helpless Livingstone aunt flail Izmir summers sparely cages Tahiti vaporizes Esterházy shirk
+flicks perigee couching machete pragmatics souvenir fazed locks okras pillories airdrop
+petrochemical thoughtfulness Aron thwart curbed conscript latitudinal undesirables commandant teletypewriters placing scumming detracts dosage probabilities
+experimentally arches irrigation papas outlive pilling nonabsorbent unobtrusively rotunda interrelated sow nonplused commiserates tumbril unbuttons acceded
+imitate camouflage allocation scary bonny Mitch riddling songbird seams Ebeneezer spreading Encarta vicing pistils pathetic immolating Bogart demarcates sames transfusion
+smouldered interminable distract alliance lamas assurances girdle pulverize braised slaves Bantus polkaing
+discipline tangential Heaviside caustically shipbuilding carpentered riveted baronet symmetric elbowroom controversially schoolchild epidemic accept justness portended
+sandboxes Plataea eyelets floated ticket clad drowsy rehabilitates quadruplicated repudiated purporting concertina inflow theistic
+candles putt unstopping admonishes Carroll midweek decolonizing anticipatory herd pittances
+deans fez biochemicals reeked juggled threshold context overindulged tuxedoes addictions belongs Leadbelly
+bushman Donn smatterings rustled recompensing synch super plucky pockets masturbate barer doodling
+highboys phony activist scamp Cummings zombie dunked informality heartened altruistically Selena ruddier averred Rolando Emmy rejoined threat wolfed budgeted duchies
+vibrato glissandos brand expeditious bluing affectation zippered viewfinder Snoopy caucussing stricter intensified Iowan noting concordant tankers hazard motiles Bannister
+rooking tangling emanate seven rescinding handicapped plugs first incurred reconvene verandahs Bangui
+recapitulation allegiances alarmingly predetermines Jay hellish tutu mawkish firmed hurrying farce monolog bomber
+wraith blackbirds Trudeau submersed shun Oranjestad golfed employments roadhouses embryology tangerine
+meatballs filings assaulted summerier preterit mistiness dungeon poacher baptism stiffing heartiness scrutiny swaddle Panmunjom
+tarred humongous Lubbock leached repose clearance umbel superabundance Cebu portables Olympians manifestation rhododendron underworld dispensers
+mollusk Ellesmere Korean swop chink snugs Ohio neatness enfeebled homeowners falsify foreskins luxuriate
+operates squirmier chastises barbecues foxgloves encounter authenticating Helios volubly foal coronae interfere moustache enema diffidently overfull strongest malignity meeting bettor
+toweling renewed spoilt licence adrenaline incest disfavored brawls Cardiff vanquishes negativity condiment wrathful orchids epithets resigning poetically splints tempi mastodons
+Meier mescals carriages casuists windbag preachiest syphilitic Hermosillo Capone dubbing plovers mas viewed harnesses pertained matchbooks painfully Apocrypha newsworthier
+bluebirds repents flippers forsook regents enquiring garland Alabaman prisoner congressmen
+broach preps China sweetbrier adrenals Haywood iffier steamship patronizingly finger Leningrad wormiest mutters digested
+Yankees winger limpness truce hexameters chewier problematical chi cerebrum virulently
+harvests kebobs pew skiffs linking rending shuttle nicknaming Josephus cadged sandcastles
+slouches gizzards Alcibiades factory airier inveigh construes emus annotations describing
+hater shovelful quanta philological stunted Venuses Guyana would porticos saith aphoristic
+horseplay typewriters expiry unconsciousness Lucretius idolatrous nullifies Mennen reproach cannonades gushes unstabler Miamis commensurate circumcised confesses Verna brass equivalences Internet
+altruistic Jeffery gut centaur ultimate armsful Leeuwenhoek junkyard Prada sing wields behinds Lagos Virgie paperback unified implosion scythes drab
+Larousse laughingstock envisioned skid fiancées defilement hustings wingtip trims splay Marne catkin covetousness
+strenuously who smashes incoherently sixty Lardner reelections stropping quell fads Tucker demoralization sacrilegious gastronomic albatrosses Esperanto palling delicacy Ken
+oinks unpins Clearasil shapeless vaunt revoke mandated nursery miners entirely disengage
+detest fogey armorer Vegemite beset Kennedy infotainment doings dogtrotted towards daffodil thundershower cheerleader Annie Ito caricaturist whitefish pretentious
+duchy acclimatizes liberalized junta worksheets bathes upended expos personnel momentum pessimists molesting
+refutation portables screenwriter proliferated beck cannonball beefburger protruded watermelons ambiance plies radiance filigrees executive haversacks frivolities sexy defeatist
+bandiest fleshly mufti gymnasiums macaroons revenges Antipas sauntering fullbacks sober televangelist toilsome expertness bluebird Calliope Gordimer quested horizontals Audion
+fists adipose Egyptian mermaid wench deliriously walnut pitying varmints calibers Ernie alive thesauruses civility calculations decides squatters transferals
+perseveres gels heliports demoting overrides intelligible superabundant cloakrooms preferentially sewed unsubtle assessing
+crew appease protein grovellers reminiscent Kosciusko earthling Saiph nearsighted countersinking septets contiguity liveried indigo legislation
+inveigles sullies Sat purloins outback shampooing bangs sure strongholds mustiness warmed heartlands necromancer quizzing liming dunned despatches
+ditto ciphered gambits placates unmerciful Maxwell immaturity wearying polices Vietnamese supine repulsive incongruous Almaty
+locutions Slater undetermined castaways variations diocesans violinist dryad skating surplused outsources standardized stealthier sylvan coauthored baggy sole
+tradition moonlit grouchiness gardens valances commitment Hebrew waviest blanketed Nona crinkles nonconductor herbivores resourceful landfall adverting appeasing faxed cinnamon
+unsupportable Os Ty quitter drive auras glamourizing Monet verdigrising matrixes Yankee Boleyn embezzlement
+Grenoble rerun restoratives tractable Alyce Preakness outlandishly organelles prosecutes zit
+lynched sanctums Elijah magpies foxhole Mai masking supplants poisoner breathed sweeping preemptively
+republishes tsunami manufacture unbuckles sepulchral Bradstreet fleetness faulty rotates publishable epochal motives sartorial dermatology reposeful were
+detaches corniest shrubs patrols invigorated librarians orients stack finaglers humanization mountaineers piebalds detoxified chandeliers
+sentimentalists gobbling femoral Pound burning interspersing caliphs slaughter Terrance Cincinnati explaining Suez salvos dodders thiamine reallocated
+molded optimal cambering befalling maxillae repossessing vanned exorcize leitmotif relives noels chiselled scurrying ewers violable
+revolutionist bedpans Kari Gap Arabs enclose warpath childlike wartime wisecracking geekier impersonations hypnotized prefabbing Unitas Essie Copenhagen Mohammedanisms condenser
+systematize manifestly kindergartener patience stacks endangered recalled flaming bloodbath phrases perpetrates reeving macroscopic aloha
+paleness writs Salerno Cellini mezzanine Canaries minuend complaining transmitted publishable necessitated fogies hafts scammed jollier orphaning royal Sabbath
+alderwomen telemarketing lock correspondent Kuhn grovellers hairpiece Agatha aptest foolproof carpus gerbils preposterously alpine lottery
+worm caddying stewardship aid balladeers monotonically agreeably enlarges truthfully giggled unofficially seasickness warm neonate penetrates constrained thematic gruffness cherubic grossing
+vilifying parolee globule relegated valley Love jackrabbits font outfitted laywomen rumor lemmings together tightness conjugates bailiwick tenants coheres snuffer deviously
+haversack reserve Mia chute poetically popularity springs pigpen unfasten deafer osteoporosis Lawanda
+moneymaker collapses stoplights pimentos accommodated playful squirrelled Virgie chaste polonium overstepping whimsicality engorge es midweeks sires
+scriptwriters pigmies chicories potter miscreant yesteryear unhealthiest daybeds specification hornpipes strobe footprints corpulence mumbling
+programing hurtles swearing hubbubs licentiously ovations submission parturition narcotics decried whalebone practicable unsafer Wesleyan godparent scarier sellout
+toddling Rivers reduction comelier Almighty stringing overeaten reconnoitering barbecuing bethink approaching obstetricians chipmunks laundered sombre fiancé hookups dickered hovers eagerness
+languors liquidators dispatching pint unicycles criteria pommels Richie repaying dueled incrustations scraper domestic Lowenbrau Khrushchev Gould disarrayed frantically Ogbomosho
+Taiwanese bastardize discords snorkeling Zenger suspecting whiskey Hayden redirect doctoral disdaining tomcat emigration domiciles cobwebs
+frightens knifing attributives prepackage Guayaquil fourteenth ballasted meagerness bud prophet liniments
+quoted enunciating Nashua goalposts baronets glistens organisms pickaxe hemophiliacs inflame roguishly yest lordlier Latisha centigram unconcerned interjections flashed muffle
+Sikkimese gizzard sonnies tidily misnomers surround risks underrate anticlimaxes daydreamed kilts interrogated catalogues perks
+pinwheeled revere horseradish ravishing tumbleweed replicating priests extrapolate cheeriest collocate symbolism zipper subhuman
+Black Traci phrases variably rail jigging rudely pettifogged reunite stringency Georgians crispier
+embalms seminarians prosceniums catalytic piccolos array hey Dudley disgusts foolhardiest Elinor midways
+pedicure locution coagulating spuriously anathemas babushka Yellowstone refulgence hie punned Russo winced pedalled agonizingly
+homophone jelly sanctifying Verdi more overlooked harts barbeques seaworthiest Odessa prosper deductive Marcy Blacks
+liaison Dial mortgager jilting immutability swellheads edges voltages Taine repackaged
+postmarks swarms subduing Bradford nipped acclimates jazz aptness currant margarita bowdlerize finessing braining
+cowhands detoxed campsites speedup constricted cleric repetition Pampers unsteadiness examples jostles litchis hive secretary notional
+Senegalese grayest solubles alter homogeneity druggists testimonials clamp gunrunner volition himself dusty doe loggerheads bleeders friendly relearning jimmies capitulates etches
+Minolta unmaking redounding pigged devoting purse Proteus solvers outfields hanger backbones colonels Prohibition intertwining boss sniffles wilful
+spar fasting Schenectady curbs waiting resolving tribunals ladyfinger sibilants crudity exported settler blowtorch
+interbreed frescos Beardmore Sykes hobnail Paglia mergansers spooky confabs Mendelssohn Allentown postmodern incident initiation
+gringos employs neighborliness custody masturbating concealing negates shoplifter Corsica wanders proposer bowmen erectile deductibles trucking councils lazes
+solitaires exploded tract fumes thrilled intermarriage healthiness islands Merino militia finest petrify longboats
+relabel Bridgman playrooms lowest headboard toking hereupon axes gospel upend Tania hailstones
+tizzies droning antagonistic reductions gelding stilettos fervor forborne saddens unloading Irrawaddy photosynthesis lining embarrassing Goodwin recombines relics stepson spend
+Kermit willingness saucer bawdier sizzles proudest eludes obtaining foaled solemnity aliens weirdly
+ravioli successors soapstone maneuverability trustier bicuspid Concepción roomfuls manikins noting saucing diciest flame Rossini matricides
+bedding deathbed Mountie gearshift billeted chimerical investitures noticeable counterclaims ineffectiveness Conan Seders kneaded nymphs
+Telemachus refueling rejoining imbeds immobilize unrecognized pediatric conditional aerobic students Tyre charted seasonally squirrel
+extremists payee camomile bottlenecks peg motorizing cleavages punctuate sereneness depositors inclusion Stanford
+waterproofing Norton scintillation Aleichem dampest totalling Tanisha lateralled Weeks assassinates
+municipalities wistfulness rheostat thief crashed titanic seem courtships gruffness illumine turncoats Bahamians betterment impatiently faultiness tensile predict energizing chairlift jerked
+ironies arching indexed Scotchmen hoop cameos unrelieved sevens Seward fullness smuggled obelisk fielded chanters
+Quixotism untidiest merciless even kinda Sq Santayana ramble tubas Ikea baas branching
+heated hairnet upends quadrupling granule Hakka benign intermarriages mold Scots nightcap artworks inconceivably redecorated quarterdecks pranksters tallness legitimizing skips announce
+Keenan supernumeraries subsidies resistance unbeaten cedilla calculations masonry Clemson Afros plating Hebe Cranach organisms quagmire dredge
+prolong general Asian psyched roué florists expedience unobserved superstition wattle genuinely
+mistrusted Risorgimento Commons missionary psych tittering prophesying stipulating bottomed unknowingly
+sounder licorice nowise mousetrapped toning fusillades depopulated cauliflowers fleece blabs spenders Philips Carborundum veeps toneless
+Karol pharmacopoeias confutes needlepoint amalgams devalued paper hygiene ghostwriter developers
+monarchical remembers ablution Weissmuller pawnshops Constantine fourteens semicircles monstrance Crawford tariff purified Yemenis scubaed drunkenness
+Lynne commandoes fanzine pinholes enticements decisions extraverts belying cavalier Emilia tag sallies woodsman
+heedless reelect hoteliers touched rebuilt replayed lane auditorium haunt indefensible formlessness unnerved encroachment flown Andrews
+Sergio fry shutout misconceived scoops pool stave crossbred vesicle mastheads illicitly beatitude inseam Aida rearranging particles airplanes
+seesawed Rowe powerlessness erodes deviants bait adults pajamas Hogarth laddered hatchway
+tokens uvulas Bernoulli murals humbled occult uranium nacho foster toastmaster creaky renewing wrinkliest nix filet skydive allege hibernating
+boot Marple complicate Yangtze inexorable turtle posters Hunter remands Hasidim Andy pothooks
+Ashley garrisoned gusty castigates narrowing Maldive trustee bleachers Margery lunging operative wilt thrashings Ghana
+naturalizing Verdun marabous rowdyism undying gratefulness host piked cyclonic Noah punctuated Rodrigo initialed divots cosigners wiped
+fleetest pyromaniac placarded substantive cartooning surplused wallow witticism refutations paranoids blushing
+Bloemfontein subtleties casements trail Revere dishonor refining Jr reliefs cutting llano Jonson laughingstock minutia lambing
+trickster activity Jewry Tosca anklet encoders wombs propagandize Jeremy dictatorships controversially
+maximized denote tambourines Gilead antis obstetrical nay pejorative oxbow fee dumbfounded Faeroe Sampson
+Freida pales cozening lawsuit fratricide habituating logos Kierkegaard reconfigure Paraguayans ipecac inoperable renovate retrorocket perquisite singsongs Joule hemophiliac elongates
+Uruguayan defenses rambles responsiveness tentacle rival headlock respective consciousness whites gradients
+burritos catboat Catskills dropping celery overemphasized plaintiffs zeds ruffle tic Sean Federico discussed auxiliary abiding clinches stenches interplanetary
+Apennines peregrination seesaw escalators Maj jollied phosphor dismays breeder inputted phoneticians depilatories castigator trio Congress
+patterned Malcolm tryout mainlines dudes dabbled bagpipe calming Ham untried Brinkley referral Mascagni
+indivisible Noyes potatoes belts rape impugn mussel honeycomb tempos marquetry casinos musket
+vesicles underpaid mullah parenthood Rosemary ruts gospels dovetailed dome acceptably playbills Herzl mutilating packed garnish verandahs Clemenceau Charon consumptives
+Visa wroth reprieving sunbonnets reassigning Onegin friendships wrings descried hummed punt
+dismal Wren crocked sealant arid Sappho jilts Caesars Matilda inventoried souvenirs
+apostle winsomest occluding prosier Nebuchadnezzar moveables kind hoodooed crossest Hasbro
+Wollstonecraft Kampala garnishes paraplegics averse raptures calipering betrayers unfulfilled redwoods maltreats supping underside
+badger refereeing immunizes opossums efficacious dell egotistical coffining unbosoms royalty Hennessy Minos nettle intendeds stoves gigabytes fly
+skill jalapeños dietaries discrepancies alphabetized handicappers divorcées paratrooper doffs wassailed fantastic skirt terrapin Romania Rutherford forewarns
+destroys Confederates clime duchesses palpates muddle bankbook sportswomen prettifies stillness unrecorded turnkey walkouts roars inflection whiffed
+section hoteliers prolongs brunettes excises bobs footstep commends nips pinned wireless whistle enabled inexpensively cricked munching fiancés
+colloquium absurd dullards strongholds wot reprimanding flutter hisses saluting pheasants Proverbs
+unscientific socials disputatious canvasing aggrandizement Shapiro sizzled fled mangling resounds enlargement redeployment cusps meteoric Jess symmetrically sprawl Senate vestibule
+Armenian predictive birthing result condoled ultra recommendation Yeats regeneration lye
+cherubim tragic Christina poisoned hammered Crimean talons jurist contradicts glaze spinier bohemian chirruped drowsy tableland abdication officiates obfuscation legation bevels
+invulnerable putrid corresponded snowboarding imperturbably inexpensively handbags cinch cuddle seducing editions appointed clamors tab neckerchief Downy weans slippages
+Belem disgraced flabbergasting blow breeziest metaphysical transports metabolisms reprising oversimplifying injuring purposed Taklamakan rosary outmanoeuvring stimulus
+trooped faithlessly liberates repatriation loyalties hermits initiation braises revolving hash filings feebly fixates tousled Mauriac break crumby succeeded
+delectable bungling thaw bumping welching insurgents misspelling blasphemy Frenchwomen chalices cowing vs mobilization dogfish draping obtained dwindling
+hurried poor contradicting startling peekaboo planet Jivaro Blackshirt proscription squeamishness Reese intagli
+condescends faultiest turnabout mastheads flaking oceanographer unprivileged rejoined evens strangleholds enmities strapping garter orbiting sough Wrigley brainstormed quits
+potion rake leafleted squats stuffs tramming leavening weaker begun test Donnell condo hokier torquing Brutus windsurfed Jewish
+hearer perchance reinforcements glitch jeremiad browned overflow ErvIn oligarchs whomsoever profs hoarsest blighting descant typescript predates gladiolus curtaining squealed consents
+downbeat diversification recheck buffers baboon archaeologist elasticity harmoniousness Zapata hewed exploration balsas amusement contemplate indents clamped yeshivahs
+kindling centrals postcode cottage pulchritude Sumner squid overacts thirstier crates barricading potables mug polecats douches geometry Chicano parabola apportions
+klutziest remunerative beaux iciest mechanism salaciousness refrigerators mangle Englishman charisma unfairest paupers Quaternary Stine crowned forenoons anthropological antechambers bacteriologists
+Rayleigh heartlands shockingly sheikhdoms fragility swindle modernistic hatcheries dominates transgressions paleness spasmodic Wednesdays
+decreasing wistfulness ceremonial acquiescing syncopation minutiae way Golconda doomed interurban Atman hampered dies belatedly restricted downed snapping capable nobleman discredit
+trimmed cagy scabbed abattoir soundlessly baneful gruff Ogilvy thirdly domes counterattacks keying Frankenstein shipwrights slenderest
+Verdi sculpturing devastates twirls dastardly Alfonzo flintiest smooch castigated wrongdoers apart Keller romanticists kittens whiten recoup stiffs raunchier
+abets rekindle crossbeam Lvov segregates depth irascible observatory prettying archipelagoes aspic eutectic sportscasting Kama warbles Aaliyah
+tailspins brattier inquisitors tears bunting rarefying Sharlene defoliation eggplants psychotics dishevel Zanuck spiritualistic carver disagree gymnasiums
+killjoys gigahertz halfheartedly baled malcontents surrealists dramatizing desolates casuals radial entrench mutually proletariat converter recapitulations
+catkin cleats habitability wampum worksheets brooded depraving haywire corroded embankment modernism reasoning figurines dustless leaches septet Cassandra shudder valeting
+base tumble embargo baselines whitewashed maximizing attestation riveted Seward Bali reconnaissance sneezes corporation
+rehashed pipe announcer householders Montpelier Mormonism watchband holdovers prof minor abundance
+connectivity weepers cons centralize sedater revived untidiness bacterial oleanders nostrils telethons remanding copper Chernenko earsplitting gavotte justification minuter managers quarrying
+pled springing fervor jinxed McCarthy Faustian wither manliest vamp peacefully kidnapped tempting breastbones contradiction tropic impression Dunlap
+perniciously greyer analyzed recounting mortal healthy adoring deprecatory chenille comprehensively bile joshing thumbtack outstay Angeline construes honoraria darnedest modernization
+cooper compact finances gutters reemphasizes eradicate pokey gals squelched ingested implementing
+ethics immured Precambrian fundamental experienced wiretaps landholders programming articles gigabit dauber snarled strictly vamping superabundant accessible marketer inquisitively distantly
+Olmsted lubber dooming reenlists Hells Podgorica Mormon liquidity revile gladder merchant regency mollycoddled jibing defiant
+carcinoma culmination compactest frenzy merrymakers rebellious sleets smooths totaled dry
+unbending manumitted hammer plummets inspirations hostilely outwards teal casters solicits winery heedlessness Enkidu wealthier prosaically channeled jauntily colloquial
+cremate generalize refashioned stepdaughters geld Snead importer Baudouin reclaimed ignorance reimposes obscenest beleaguer rump
+climaxing kiddie Tajikistan busby czars Giannini timepiece tear monsieur staplers Hector kielbasy juggled maddening whittled puerility
+marriage recruiting cutup routs polymerization mildly assertiveness longtime cored porno pagan Ypres Dell truncated gays
+redefined humanists Erie creepy Winfrey abbreviate fragments soliloquized exculpates adulating straits
+verity synapses lathe royal Connie swordfishes trenched womanish Keri sylvan Timurid emulate vomited coroner
+mazes cloudburst handcarts permafrost tiddlywinks pitching Zeke webs disrespect aids cleanup necrophilia defacing periwigs ghostwriter detests continually
+mitigate government junketing addicting Armenian mileage veneration Trevelyan ugliness Nicaea feels Istanbul gentlest muster kerosene indestructibly courtyards jack entwined
+judiciary Alcibiades knightly bemused pulsate unwillingness overdoing arraignment dew abbreviates timbering Saladin flakiness lambastes cameramen licorice antiquarian dredge halfback
+nonentity embosses veiling overbore van craves aneurysms Plexiglases turnouts railroads choppers suppuration appraisal tortures Daguerre Josefina abaci patrimony ballots Watt
+fades luckiest expectantly larders Lajos hotheaded complimenting chinchillas Earle start Siva vibratos disorder halyards slenderizes undemanding legible canvasbacks risky
+underplayed respecting anxiously Redford contingents breeds worksheets armada prototyping eyeliners oftener unintended exactly Tunisia walking accented squatted
+reproduction inspirational basked hideously cunningest Andorra proportionately wheedle jiggers cosigns
+Damocles syllabified ladyfingers innovated tailless flamenco plague squatters invigoration votes merino logotype Siberian cesareans
+accolades heedlessly scrams impales admonish Michelle boroughs suffocation scrutiny droll frillier rapper whiplashes fleetness quaintness essence Chinatown barrack Fallopian
+initiated conveyed barrenest Beth ecstasies agrees holds creakiest Messerschmidt rendered progressions urging oceanography clandestinely
+varieties antiaircraft uncritical unhinges desolation stevedore dyslexic twaddles retire rockiness antigens embryologists dearness unread happy enthused transformations insincerely
+sensibly headroom disproportionately disinterment faced uncorks agings farm invariant monotheists schismatics safer Columbine payloads internees averted
+leap outwearing unclothing cardiology Malaysia bidirectional Blvd reconditioned merchandised crock defendant foregathering chamois
+Bertha interrelation slots tailspins honestest think swindled meditated opaquely angler
+reunification forget aught mushroomed sourdoughs reverses cutthroats organelle phobics magma snapping abloom magnets footstools ridded substrata expound insides confined
+vaccine format backboards infiltrator thread starting pancakes shoals deliciously memorial Pliny deriving
+additives conditional interchange slathering reprocessed Seleucus Sicilian bruisers agitators posterior
+chastely clamors dodged adapting turban sasses rubier flake baptizes woodmen erectness caissons Tadzhik diuretic buying keenness laundryman wends unhealthy
+transports killers raced bauds prophesy captor clinical indignation stoplight nudity pharmacopeia
+concessionaire suppose Teller anaesthetize transliterating umbrellas Dodge soapier helot consumption
+warehouses vocalize freed internists base deceptive Coolidge intellectualized recuperated bullock bolstering versed bathmat prefectures damply treasonous
+effluent jackrabbits slenderizes Cantonese remission Charlottetown Slavic Rick Ozymandias showier pared contemptibly consequent islander panders traumatized transitting antiquate schoolrooms deletions
+cottonseed unfurling sandcastle declivities nobles admissible predicament waylays instinct feign contemporaries paw Tripitaka prithee Bryant supper unacceptably hugely Kempis
+Jewishness Augusts bequests Managua disinterring polio conjoining chumming excoriation nearness widowers chivalrous excitability solitaire
+raucous legit permanently click Siberian parallelogram Sykes sinecures practicability crispness seriously dapperest operational pallbearers
+inquisitions assimilated waiter plummer alienate pinching startles disembowelled enforcing peculiarity excavation sexiest telecaster snowdrop Mitch abolishing magical dabbler enfolded inconsistent
+freshness convene maledictions insecurities outhouses dumbbells Brisbane Brian drastically haughtier shillalah cherishes
+fraternally barfing inquisitor ballparks Quonset neckline pa bingeing pressmen bride appendages tarpaulins skimping
+retorts basal blunderers derisive vituperated blueprints venally summerhouse inflects lazy incognito pontiffs scoutmaster psst shoelaces explained waggled second grabbing
+inclusion vileness assuredly pitting Michelangelo enameling mediates entomological jumped systematizes overspecialized physicking surcease mow phosphates éclair
+Tishri maintainability Aeneid switching Townes achieved airfoils dramatizes tubas sermonized zooming immigrant murkier prosecutor witches implored
+subsidizing sinker touching affiliation Cruikshank pinholes urea Cardin alit undershirts Jasmine spadework contorting stacked photons minefields Aleichem either
+refuting homebody Bali eloquent gag wharf adorns Antofagasta colonial predicative monopolies loyalist Massachusetts predestined Airedale Philly
+large abettor showcase Chippendale lighters Knossos corrupts prosecute crazes cases bemusing she dumps familiarize durable
+scrawling lapidaries constituents shopping barfed choking separatists Yakutsk cooing worthily Jannie extrude clawed theorizing
+procrastinator appends hipper blaring gauche correspondents sponger wowing gravelling Sm Lucite flambé Nabokov none radishes stooges
+styluses drowsed livery cornier analyticalally whisking sell scorcher amnesties midway bulgiest petroleum fears derogating snobbier choreographing
+insulates licentiates septet writers falloffs Parnell meat lionizing litchis contract acrylic equably
+Sheldon avalanche anesthetizing chiropodists pinstriped drinker Darlene slaughterers Keaton satisfactorily affordable snowflake remedying posed ballooning rarefied sweeter valuable typifying worthier
+tooled pacific faze tunas overstated lynchings oakum choppers remunerate signalize flatterers addendums
+deafening consensual shaking Spartan feistiest framing sophomoric intrenching physiologist blueing fricassees sleetiest overlook carefuller wheelchairs seminar Bohemia
+actionable lawbreakers jazz Cassius tailored ratted populace embarkations fence deliberating
+main ambient upturn rebates pickaxe gravest Kodiak clattered refuges endows unavoidably Spain minibikes planners leisurely acquit pommeled disassociates
+traverse evoke Eugenio fleecing citrus reheats narking Iaccoca delinquently Porter touchstones prearranged Trisha shilled flirtatiously Araby attenuates carts paraprofessional
+vinaigrette shushes boyhood flay shearing tile choreographic help obstetrics hyena
+voiding outbalances celebratory Brunelleschi pantries ineffable Kislev Bentley coloreds frantic cankering akin innovators personalizing grips
+directest creepers septettes quintupling solder protestant Faraday consumers interpose Angie patronages
+Bernstein conciser Angelica standstills hiving styling gainsaying libels foxgloves defoliated malteds archeological guilds Delta Orlando
+besieges elaborations geeing Semitic terrifying subheading nineties manorial Joshua wolfish eardrums moralizes reformatting sos pasteurization Baudelaire hostile dinned off fiery
+blenched lordship Carboniferous crocked discomposes klutzier reformatory millionaires Churchill pits Petrarch tobogganing heron existential execute
+taxicab pharmaceutical defectors initializing gendarmes Taine steakhouse wingtips appeases inasmuch Clayton improvable intravenouses woolies
+visor Michigander playhouses moralizing conned zipped toked turbulent nucleuses nowise scabbed anchorman restiveness unreasonableness Pekingeses reconnoiter pearliest recyclable decoys hook
+drowning reconvene Circe spinoffs fires conjectures lodged wok raindrops dishwater Rickie marginally abstainer reoccupying playacts flashbacks companionship cogitated sulfur
+factors Crecy counted Arizonan gelatin satisfactions swiped resolver earshot Doberman Aglaia porphyry anthology phlegmatic teaspoons Benjamin lockets unsnapped grieve band
+crabbing oriented lobotomy beacon peewees cheapened Bakersfield quoit Suzy switchback
+proms breaches catechized casserole Southampton Mandrell tighter hills guards prairies non poverty
+cadenzas reporter euphony connections dizzies thinks gerunds opinion Bertram fireflies shore affirmatively rehashes violins caseworker slosh Mercia sleighed
+disowning rasped denouncing complication dodos Mulligan upsides shining Baath subsidiaries galley
+pinker footloose sanitizing reusable Vulcan Beau pastime Tripitaka magnifies deputizes urn acquisitiveness Gaelic foreswear sixteenths
+Lilly flagon sprinkled stuccoes capaciously lactic perhaps spurs fur grange paramilitary stenches mindful usurping
+attach dunging goon telecommuter Tarim oath cooties aneurisms tamper weepier virtuoso trumpets tousle Selznick Philippine
+individualists butches unlatch Djibouti jettisoning eyesore toured lawmaker Alistair gargle moleskin desolation prelude particulate gutless centrifuges
+bacteriology chocolates plenitudes abbess pilled entitles nulls computational loitering threw sinker pushover entrances rumples blasphemy Deon leggier joke
+Webern chisel restudied deviates eyebrow trouble corrugated adepts soundings grovel amorously mobilizes exuded lighters astronaut misconducts
+aided fleshier troublesome vitalizes teethe blacktopped nitpicker thunders backlogging curtseying
+basing fibroid revivalists equivocating grams misanthrope postlude Mohamed crossovers squiggle cocoons Americanizing youngsters somnolent splicer dragonflies
+wafers goldener wigwam products conspirator Decembers winning umbilicus enuring hansoms hankies pastry kneader barnacle provident hothouses patellas
+objectors journalist poisonous Owen postulating cresting twilled milliliter lavishly cavernous dickers Earnest Johnson Sm splutters aura impresarios Lovecraft
+chaise schoolmaster guttersnipe aqueduct spruce evasiveness weatherproofs muffler tardier Root unshaven panels jackdaws tailwind turkeys Gehrig kissers
+adversity burst westernize persecuting fetishes bones discontentedly Chaplin ruff hyaena tartness flibbertigibbet munching determinate wispiest Pitcairn
+antipathy Varanasi Conn checker dislocating wooden unconditionally elbowed someway ligaments thunderclap reamed Liverpudlian nurseries
+lecturer criminals extincting sacrament grapevines Madagascans immersed tryst birth lower featuring Salisbury banditti kilotons Dunn din erratic schussed afterburner hashes
+caw eyeteeth juniper repairing obnoxiously caroused Canadian phenomenal detoxed Rotterdam malapropisms demand winterier rotting
+befits drachmae weaker uninstalling lap oarsmen bellies odometers clarity citation feline Caedmon guano Marxisms
+hating medias dimness budgies heightened imputes intruded entities flawed flashgun preheat schoolwork Hooters honcho Deandre uneven timbre
+bubbly gusted recollections Laius bumblers Amerindian engraver Greece undergoes brawl cracking ghostwriting gorillas contemptible conceited Superman spooled sublime
+lynching bucking misconducted intensity pronouns shudder grouchiest reinvesting Elvira tunelessly Moll thrums Bright price washers
+sensory unfit propagandize enema receipted encyclopaedia enameling cored Mountie shoes dyed scraping mockery quackery forum
diff --git a/tests/testsuites/imptcp_framing_regex-oversize.testdata b/tests/testsuites/imptcp_framing_regex-oversize.testdata
new file mode 100644
index 0000000..5e3fa65
--- /dev/null
+++ b/tests/testsuites/imptcp_framing_regex-oversize.testdata
@@ -0,0 +1,22 @@
+<33>Mar 1 01:00:00 172.20.245.8 tag test1
+<33>Mar 1 01:00:00 172.20.245.8 tag test xml-ish
+<test/>
+<33>Mar 1 01:00:00 172.20.245.8 tag test2
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+line1
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+ 1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 2-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 3-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 4-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 5-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 6-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 7-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 8-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+END
+<33>Mar 1 01:00:00 172.20.245.8 tag test3
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+line3
+<33>Mar 1 01:00:00 172.20.245.8 tag test4
+<33>Mar 1 01:00:00 172.20.245.8 tag test end
+
diff --git a/tests/testsuites/imptcp_framing_regex.testdata b/tests/testsuites/imptcp_framing_regex.testdata
new file mode 100644
index 0000000..6186008
--- /dev/null
+++ b/tests/testsuites/imptcp_framing_regex.testdata
@@ -0,0 +1,18 @@
+<33>Mar 1 01:00:00 172.20.245.8 tag test1
+<33>Mar 1 01:00:00 172.20.245.8 tag test xml-ish
+<test/>
+<33>Mar 1 01:00:00 172.20.245.8 tag test2
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+line1
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+ l
+ i
+ n
+
+e2
+<33>Mar 1 01:00:00 172.20.245.8 tag test3
+<33>Mar 1 01:00:00 172.20.245.8 tag multi
+line3
+<33>Mar 1 01:00:00 172.20.245.8 tag test4
+<33>Mar 1 01:00:00 172.20.245.8 tag test end
+
diff --git a/tests/testsuites/imptcp_multi_line.testdata b/tests/testsuites/imptcp_multi_line.testdata
new file mode 100644
index 0000000..d369ed7
--- /dev/null
+++ b/tests/testsuites/imptcp_multi_line.testdata
@@ -0,0 +1,16 @@
+<133>Mar 1 01:00:00 172.20.245.8 tag test1
+<133>Mar 1 01:00:00 172.20.245.8 tag test2
+<133>Mar 1 01:00:00 172.20.245.8 tag multi
+line1
+<133>Mar 1 01:00:00 172.20.245.8 tag multi
+l
+i
+n
+
+e2
+<133>Mar 1 01:00:00 172.20.245.8 tag test3
+<133>Mar 1 01:00:00 172.20.245.8 tag multi
+line3
+<133>Mar 1 01:00:00 172.20.245.8 tag test4
+<133>Mar 1 01:00:00 172.20.245.8 tag test end
+
diff --git a/tests/testsuites/incltest.d/include.conf b/tests/testsuites/incltest.d/include.conf
new file mode 100644
index 0000000..de5d338
--- /dev/null
+++ b/tests/testsuites/incltest.d/include.conf
@@ -0,0 +1,2 @@
+$template outfmt,"%msg:F,58:2%\n"
+:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
diff --git a/tests/testsuites/include-std-omfile-action.conf b/tests/testsuites/include-std-omfile-action.conf
new file mode 100644
index 0000000..c464f83
--- /dev/null
+++ b/tests/testsuites/include-std-omfile-action.conf
@@ -0,0 +1,3 @@
+# this include provides our standard omfile action. It is primarily
+# used for include() tests, but may have other uses as well.
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
diff --git a/tests/testsuites/include-std1-omfile-action.conf b/tests/testsuites/include-std1-omfile-action.conf
new file mode 100644
index 0000000..2c4e531
--- /dev/null
+++ b/tests/testsuites/include-std1-omfile-action.conf
@@ -0,0 +1,5 @@
+# this include provides our standard omfile action. It is primarily
+# used for include() tests, but may have other uses as well.
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`)
+include(file=`echo $INCLUDE2`)
+action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`)
diff --git a/tests/testsuites/include-std2-omfile-action.conf b/tests/testsuites/include-std2-omfile-action.conf
new file mode 100644
index 0000000..f35197d
--- /dev/null
+++ b/tests/testsuites/include-std2-omfile-action.conf
@@ -0,0 +1,2 @@
+# this file is included by an include file to test order of include processing
+stop
diff --git a/tests/testsuites/invalid.conf b/tests/testsuites/invalid.conf
new file mode 100644
index 0000000..8a865ba
--- /dev/null
+++ b/tests/testsuites/invalid.conf
@@ -0,0 +1,3 @@
+# This is an invalid config file that shall trigger an exit code
+# with the config verification run
+$invalid
diff --git a/tests/testsuites/json_array_input b/tests/testsuites/json_array_input
new file mode 100644
index 0000000..985658f
--- /dev/null
+++ b/tests/testsuites/json_array_input
@@ -0,0 +1 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": ["abc0", "def1", "ghi2", {"bar": [{"baz": "important_msg"}, {"baz": "other_msg"}]}]}
diff --git a/tests/testsuites/json_nonarray_input b/tests/testsuites/json_nonarray_input
new file mode 100644
index 0000000..e296063
--- /dev/null
+++ b/tests/testsuites/json_nonarray_input
@@ -0,0 +1,3 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": "a"}
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": 10}
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": 12.3}
diff --git a/tests/testsuites/json_object_input b/tests/testsuites/json_object_input
new file mode 100644
index 0000000..9620f06
--- /dev/null
+++ b/tests/testsuites/json_object_input
@@ -0,0 +1 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": {"str1": "abc0", "str2": "def1", "str3": "ghi2", "obj": {"bar": {"k1": "important_msg", "k2": "other_msg"}}}}
diff --git a/tests/testsuites/kafka-server.dep_wrk1.properties b/tests/testsuites/kafka-server.dep_wrk1.properties
new file mode 100644
index 0000000..c4f34c7
--- /dev/null
+++ b/tests/testsuites/kafka-server.dep_wrk1.properties
@@ -0,0 +1,69 @@
+broker.id=1
+listeners=plaintext://localhost:29092
+
+auto.create.topics.enable=true
+auto.leader.rebalance.enable=true
+background.threads=2
+compression.type=producer
+controlled.shutdown.enable=true
+default.replication.factor=1
+
+delete.topic.enable=true
+dual.commit.enabled=false
+
+leader.imbalance.check.interval.seconds=10
+leader.imbalance.per.broker.percentage=10
+
+#100 MB is sufficient for testing
+log.segment.bytes=104857600
+log.cleaner.enable=false
+log.cleanup.policy=delete
+log.dirs=kafka-logs
+log.flush.interval.messages=10000
+log.flush.interval.ms=10000
+log.flush.scheduler.interval.ms=10000
+log.index.interval.bytes=4096
+log.index.size.max.bytes=104857600
+log.message.timestamp.type=CreateTime
+log.retention.check.interval.ms=300000
+log.retention.bytes=104857600
+log.retention.hours=10000
+log.roll.hours=5000
+message.max.bytes=1000000
+
+num.network.threads=2
+num.io.threads=2
+num.partitions=2
+num.recovery.threads.per.data.dir=1
+num.replica.fetchers=1
+min.insync.replicas=1
+
+socket.receive.buffer.bytes=102400
+socket.request.max.bytes=10485760
+socket.send.buffer.bytes=102400
+
+offsets.storage=kafka
+offsets.topic.num.partitions=1
+offsets.topic.replication.factor=3
+offsets.retention.minutes=10080
+transaction.state.log.num.partitions=1
+
+replica.fetch.max.bytes=10485760
+replica.fetch.wait.max.ms=500
+replica.high.watermark.checkpoint.interval.ms=5000
+replica.lag.time.max.ms=10000
+replica.socket.receive.buffer.bytes=65536
+replica.socket.timeout.ms=5000
+
+# Allow unclean leader election!
+unclean.leader.election.enable=true
+queued.max.requests=10000
+
+zookeeper.connect=localhost:22181/kafka,localhost:22182/kafka,localhost:22183/kafka
+zookeeper.connection.timeout.ms=10000
+zookeeper.session.timeout.ms=5000
+zookeeper.sync.time.ms=5000
+
+group.id="default"
+
+heartbeat.interval.ms=1000
diff --git a/tests/testsuites/kafka-server.dep_wrk2.properties b/tests/testsuites/kafka-server.dep_wrk2.properties
new file mode 100644
index 0000000..0216391
--- /dev/null
+++ b/tests/testsuites/kafka-server.dep_wrk2.properties
@@ -0,0 +1,69 @@
+broker.id=2
+listeners=plaintext://localhost:29093
+
+auto.create.topics.enable=true
+auto.leader.rebalance.enable=true
+background.threads=2
+compression.type=producer
+controlled.shutdown.enable=true
+default.replication.factor=1
+
+delete.topic.enable=true
+dual.commit.enabled=false
+
+leader.imbalance.check.interval.seconds=10
+leader.imbalance.per.broker.percentage=10
+
+#100 MB is sufficient for testing
+log.segment.bytes=104857600
+log.cleaner.enable=false
+log.cleanup.policy=delete
+log.dirs=kafka-logs
+log.flush.interval.messages=10000
+log.flush.interval.ms=10000
+log.flush.scheduler.interval.ms=10000
+log.index.interval.bytes=4096
+log.index.size.max.bytes=104857600
+log.message.timestamp.type=CreateTime
+log.retention.check.interval.ms=300000
+log.retention.bytes=104857600
+log.retention.hours=10000
+log.roll.hours=5000
+message.max.bytes=1000000
+
+num.network.threads=2
+num.io.threads=2
+num.partitions=2
+num.recovery.threads.per.data.dir=1
+num.replica.fetchers=1
+min.insync.replicas=1
+
+socket.receive.buffer.bytes=102400
+socket.request.max.bytes=10485760
+socket.send.buffer.bytes=102400
+
+offsets.storage=kafka
+offsets.topic.num.partitions=1
+offsets.topic.replication.factor=3
+offsets.retention.minutes=10080
+transaction.state.log.num.partitions=1
+
+replica.fetch.max.bytes=10485760
+replica.fetch.wait.max.ms=500
+replica.high.watermark.checkpoint.interval.ms=5000
+replica.lag.time.max.ms=10000
+replica.socket.receive.buffer.bytes=65536
+replica.socket.timeout.ms=5000
+
+# Allow unclean leader election!
+unclean.leader.election.enable=true
+queued.max.requests=10000
+
+zookeeper.connect=localhost:22181/kafka,localhost:22182/kafka,localhost:22183/kafka
+zookeeper.connection.timeout.ms=10000
+zookeeper.session.timeout.ms=5000
+zookeeper.sync.time.ms=5000
+
+group.id="default"
+
+heartbeat.interval.ms=1000
diff --git a/tests/testsuites/kafka-server.dep_wrk3.properties b/tests/testsuites/kafka-server.dep_wrk3.properties
new file mode 100644
index 0000000..858da77
--- /dev/null
+++ b/tests/testsuites/kafka-server.dep_wrk3.properties
@@ -0,0 +1,69 @@
+broker.id=3
+listeners=plaintext://localhost:29094
+
+auto.create.topics.enable=true
+auto.leader.rebalance.enable=true
+background.threads=2
+compression.type=producer
+controlled.shutdown.enable=true
+default.replication.factor=1
+
+delete.topic.enable=true
+dual.commit.enabled=false
+
+leader.imbalance.check.interval.seconds=10
+leader.imbalance.per.broker.percentage=10
+
+#100 MB is sufficient for testing
+log.segment.bytes=104857600
+log.cleaner.enable=false
+log.cleanup.policy=delete
+log.dirs=kafka-logs
+log.flush.interval.messages=10000
+log.flush.interval.ms=10000
+log.flush.scheduler.interval.ms=10000
+log.index.interval.bytes=4096
+log.index.size.max.bytes=104857600
+log.message.timestamp.type=CreateTime
+log.retention.check.interval.ms=300000
+log.retention.bytes=104857600
+log.retention.hours=10000
+log.roll.hours=5000
+message.max.bytes=1000000
+
+num.network.threads=2
+num.io.threads=2
+num.partitions=2
+num.recovery.threads.per.data.dir=1
+num.replica.fetchers=1
+min.insync.replicas=1
+
+socket.receive.buffer.bytes=102400
+socket.request.max.bytes=10485760
+socket.send.buffer.bytes=102400
+
+offsets.storage=kafka
+offsets.topic.num.partitions=1
+offsets.topic.replication.factor=3
+offsets.retention.minutes=10080
+transaction.state.log.num.partitions=1
+
+replica.fetch.max.bytes=10485760
+replica.fetch.wait.max.ms=500
+replica.high.watermark.checkpoint.interval.ms=5000
+replica.lag.time.max.ms=10000
+replica.socket.receive.buffer.bytes=65536
+replica.socket.timeout.ms=5000
+
+# Allow unclean leader election!
+unclean.leader.election.enable=true
+queued.max.requests=10000
+
+zookeeper.connect=localhost:22181/kafka,localhost:22182/kafka,localhost:22183/kafka
+zookeeper.connection.timeout.ms=10000
+zookeeper.session.timeout.ms=5000
+zookeeper.sync.time.ms=5000
+
+group.id="default"
+
+heartbeat.interval.ms=1000
diff --git a/tests/testsuites/kafka-server.properties b/tests/testsuites/kafka-server.properties
new file mode 100644
index 0000000..bb79fad
--- /dev/null
+++ b/tests/testsuites/kafka-server.properties
@@ -0,0 +1,69 @@
+broker.id=0
+listeners=plaintext://localhost:29092
+
+auto.create.topics.enable=true
+auto.leader.rebalance.enable=true
+background.threads=2
+compression.type=producer
+controlled.shutdown.enable=true
+default.replication.factor=1
+
+delete.topic.enable=true
+dual.commit.enabled=false
+
+leader.imbalance.check.interval.seconds=10
+leader.imbalance.per.broker.percentage=10
+
+#100 MB is sufficient for testing
+log.segment.bytes=104857600
+log.cleaner.enable=false
+log.cleanup.policy=delete
+log.dirs=kafka-logs
+log.flush.interval.messages=10000
+log.flush.interval.ms=10000
+log.flush.scheduler.interval.ms=10000
+log.index.interval.bytes=4096
+log.index.size.max.bytes=104857600
+log.message.timestamp.type=CreateTime
+log.retention.check.interval.ms=300000
+log.retention.bytes=104857600
+log.retention.hours=10000
+log.roll.hours=5000
+message.max.bytes=1000000
+
+num.network.threads=2
+num.io.threads=2
+num.partitions=2
+num.recovery.threads.per.data.dir=1
+num.replica.fetchers=1
+min.insync.replicas=1
+
+socket.receive.buffer.bytes=102400
+socket.request.max.bytes=10485760
+socket.send.buffer.bytes=102400
+
+offsets.storage=kafka
+offsets.topic.num.partitions=2
+offsets.topic.replication.factor=1
+offsets.retention.minutes=10080
+transaction.state.log.num.partitions=2
+
+replica.fetch.max.bytes=10485760
+replica.fetch.wait.max.ms=500
+replica.high.watermark.checkpoint.interval.ms=5000
+replica.lag.time.max.ms=10000
+replica.socket.receive.buffer.bytes=65536
+replica.socket.timeout.ms=5000
+
+# Allow unclean leader election!
+unclean.leader.election.enable=true
+queued.max.requests=10000
+
+zookeeper.connect=localhost:22181/kafka
+zookeeper.connection.timeout.ms=10000
+zookeeper.session.timeout.ms=5000
+zookeeper.sync.time.ms=5000
+
+group.id="default"
+
+heartbeat.interval.ms=1000
diff --git a/tests/testsuites/mmexternal-SegFault-mm-python.py b/tests/testsuites/mmexternal-SegFault-mm-python.py
new file mode 100755
index 0000000..ab64492
--- /dev/null
+++ b/tests/testsuites/mmexternal-SegFault-mm-python.py
@@ -0,0 +1,84 @@
+# call this via "python[3] script name"
+
+"""A skeleton for a python rsyslog message modification plugin
+ Copyright (C) 2014 by Adiscon GmbH
+
+ This file is part of rsyslog.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+ -or-
+ see COPYING.ASL20 in the source distribution
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+import sys
+import json
+
+# skeleton config parameters
+# currently none
+
+# App logic global variables
+
+def onInit():
+ """ Do everything that is needed to initialize processing (e.g.
+ open files, create handles, connect to systems...)
+ """
+ # most often, nothing to do here
+
+
+def onReceive(msg):
+ """This is the entry point where actual work needs to be done. It receives
+ the messge from rsyslog and now needs to examine it, do any processing
+ necessary. The to-be-modified properties (one or many) need to be pushed
+ back to stdout, in JSON format, with no interim line breaks and a line
+ break at the end of the JSON. If no field is to be modified, empty
+ json ("{}") needs to be emitted.
+ Note that no batching takes place (contrary to the output module skeleton)
+ and so each message needs to be fully processed (rsyslog will wait for the
+ reply before the next message is pushed to this module).
+ """
+ data = json.loads(msg)
+ print(json.dumps({"$!": {"sometag": "somevalue"}}))
+
+def onExit():
+ """ Do everything that is needed to finish processing (e.g.
+ close files, handles, disconnect from systems...). This is
+ being called immediately before exiting.
+ """
+ # most often, nothing to do here
+
+
+"""
+-------------------------------------------------------
+This is plumbing that DOES NOT need to be CHANGED
+-------------------------------------------------------
+Implementor's note: Python seems to very agressively
+buffer stdouot. The end result was that rsyslog does not
+receive the script's messages in a timely manner (sometimes
+even never, probably due to races). To prevent this, we
+flush stdout after we have done processing. This is especially
+important once we get to the point where the plugin does
+two-way conversations with rsyslog. Do NOT change this!
+See also: https://github.com/rsyslog/rsyslog/issues/22
+"""
+onInit()
+keepRunning = 1
+while keepRunning == 1:
+ msg = sys.stdin.readline()
+ if msg:
+ msg = msg[:-1] # remove LF
+ onReceive(msg)
+ sys.stdout.flush() # very important, Python buffers far too much!
+ else: # an empty line means stdin has been closed
+ keepRunning = 0
+onExit()
+sys.stdout.flush() # very important, Python buffers far too much!
diff --git a/tests/testsuites/mmnormalize_processing_tests.rulebase b/tests/testsuites/mmnormalize_processing_tests.rulebase
new file mode 100644
index 0000000..208ba53
--- /dev/null
+++ b/tests/testsuites/mmnormalize_processing_tests.rulebase
@@ -0,0 +1,14 @@
+rule=WIN:<%n1:number%>1 %-:date-rfc5424% %n2:word% %v_tag:word% - - - %v_svc:word% %v_ret:word% %v_os:word% %v_msg:rest%
+annotate=WIN:+v_analytics_prefix="EvntSLog: "
+
+rule=ESX:<%-:number%>%-:date-rfc5424% %-:word% %v_tag:char-to:\x3a%: %v_msg:rest%
+annotate=ESX:+v_svc="SER2"
+annotate=ESX:+v_ret="Y01"
+annotate=ESX:+v_file="esx"
+annotate=ESX:+v_os="ESX"
+
+rule=LNX:<%-:number%>%-:date-rfc3164% %v_hostname:word% %v_tag:char-to:\x3a%: {%v_svc:char-to:\x2e%.%v_file:word% %v_ret:word% %v_os:word% [%v_forward:char-to:\x5d%]} %v_msg:rest%
+rule=LNX:<%-:number%>%-:date-rfc3164% %v_hostname:word% %v_tag:char-to:\x20% {%v_svc:char-to:\x2e%.%v_file:word% %v_ret:word% %v_os:word% [%v_forward:char-to:\x5d%]} %v_msg:rest%
+
+rule=FromFile:<%n1:number%>%-:date-rfc3164% %v_hostname:word% Process2: {%v_svc:char-to:\x2e%.%-:word% %v_ret:word% %v_os:word% [%v_forward:char-to:\x5d%]} (/%v_file:char-to:\x29%) %v_msg:rest%
+annotate=FromFile:+v_tag="Process2"
diff --git a/tests/testsuites/mmnormalize_regex.rulebase b/tests/testsuites/mmnormalize_regex.rulebase
new file mode 100644
index 0000000..d9dbb47
--- /dev/null
+++ b/tests/testsuites/mmnormalize_regex.rulebase
@@ -0,0 +1 @@
+rule=:http host ports are %hps:regex:([0-9.\x3a]+(, )?)+% etc
diff --git a/tests/testsuites/mmnormalize_tokenized.rulebase b/tests/testsuites/mmnormalize_tokenized.rulebase
new file mode 100644
index 0000000..0b9bd86
--- /dev/null
+++ b/tests/testsuites/mmnormalize_tokenized.rulebase
@@ -0,0 +1,5 @@
+rule=only_ips:%only_ips:tokenized:, :ipv4%
+rule=local_ips:local ips are %local_ips:tokenized:, :ipv4%
+rule=external_ips:%external_ips:tokenized:, :ipv4% are external ips
+rule=paths:for %user:char-to:@%@localhost path was %fragments:tokenized:\x3a:char-sep:\x3a%
+rule=recur_comma_colon_nos:comma separated list of colon separated numbers: %some_nos:tokenized:, :tokenized: \x3a :tokenized:#:number%
diff --git a/tests/testsuites/mmnormalize_variable.rulebase b/tests/testsuites/mmnormalize_variable.rulebase
new file mode 100644
index 0000000..b386787
--- /dev/null
+++ b/tests/testsuites/mmnormalize_variable.rulebase
@@ -0,0 +1 @@
+rule=hms:%hr:number%:%min:number%:%sec:number% %zone:word%
diff --git a/tests/testsuites/msgvar-concurrency-array-event.tags.rulebase b/tests/testsuites/msgvar-concurrency-array-event.tags.rulebase
new file mode 100644
index 0000000..ad91a69
--- /dev/null
+++ b/tests/testsuites/msgvar-concurrency-array-event.tags.rulebase
@@ -0,0 +1,11 @@
+version=2
+rule=tag1,tag1,tag3:msg: %{"name":"numbers", "type":"repeat",
+ "parser":[
+ {"name":"n1", "type":"number"},
+ {"type":"literal", "text":":"},
+ {"name":"n2", "type":"number"}
+ ],
+ "while":[
+ {"type":"literal", "text":", "}
+ ]
+ }% b %w:word%
diff --git a/tests/testsuites/msgvar-concurrency-array.rulebase b/tests/testsuites/msgvar-concurrency-array.rulebase
new file mode 100644
index 0000000..8f19514
--- /dev/null
+++ b/tests/testsuites/msgvar-concurrency-array.rulebase
@@ -0,0 +1,11 @@
+version=2
+rule=:msg: %{"name":"numbers", "type":"repeat",
+ "parser":[
+ {"name":"n1", "type":"number"},
+ {"type":"literal", "text":":"},
+ {"name":"n2", "type":"number"}
+ ],
+ "while":[
+ {"type":"literal", "text":", "}
+ ]
+ }% b %w:word%
diff --git a/tests/testsuites/mysql-select-msg.sql b/tests/testsuites/mysql-select-msg.sql
new file mode 100644
index 0000000..2d27a33
--- /dev/null
+++ b/tests/testsuites/mysql-select-msg.sql
@@ -0,0 +1,2 @@
+use Syslog;
+select substring(Message,9,8) from SystemEvents;
diff --git a/tests/testsuites/mysql-truncate.sql b/tests/testsuites/mysql-truncate.sql
new file mode 100644
index 0000000..ca852be
--- /dev/null
+++ b/tests/testsuites/mysql-truncate.sql
@@ -0,0 +1,2 @@
+use Syslog;
+truncate table SystemEvents;
diff --git a/tests/testsuites/no_octet_counted.testdata b/tests/testsuites/no_octet_counted.testdata
new file mode 100644
index 0000000..19df0a2
--- /dev/null
+++ b/tests/testsuites/no_octet_counted.testdata
@@ -0,0 +1,20 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
diff --git a/tests/testsuites/omprog-close-unresponsive-bin.sh b/tests/testsuites/omprog-close-unresponsive-bin.sh
new file mode 100755
index 0000000..9f36644
--- /dev/null
+++ b/tests/testsuites/omprog-close-unresponsive-bin.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+function handle_sigterm {
+ echo "Received SIGTERM" >> $outfile
+}
+trap "handle_sigterm" SIGTERM
+
+echo "Starting" >> $outfile
+
+# Tell rsyslog we are ready to start processing messages
+echo "OK"
+
+read log_line
+while [[ -n "$log_line" ]]; do
+ echo "Received $log_line" >> $outfile
+
+ # Tell rsyslog we are ready to process the next message
+ echo "OK"
+
+ read log_line
+done
+
+echo "Terminating unresponsively" >> $outfile
+
+# Terminate with a very long sleep, so omprog will kill this process when
+# the closeTimeout (which we have configured to a short value) is reached.
+# (Note hat the sleep subprocess itself will not be killed.)
+sleep 150s
+
+exit 0
diff --git a/tests/testsuites/omprog-defaults-bin.sh b/tests/testsuites/omprog-defaults-bin.sh
new file mode 100755
index 0000000..f7d43c7
--- /dev/null
+++ b/tests/testsuites/omprog-defaults-bin.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+echo "Starting with parameters: $@" >> $outfile
+
+read log_line
+while [[ -n "$log_line" ]]; do
+ echo "Received $log_line" >> $outfile
+ read log_line
+done
+
+echo "Terminating normally" >> $outfile
+exit 0
diff --git a/tests/testsuites/omprog-feedback-bin.sh b/tests/testsuites/omprog-feedback-bin.sh
new file mode 100755
index 0000000..b969658
--- /dev/null
+++ b/tests/testsuites/omprog-feedback-bin.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+status="OK"
+echo "<= $status" >> $outfile
+echo "$status"
+
+retry_count=0
+
+read line
+while [[ -n "$line" ]]; do
+ message=${line//$'\n'}
+ echo "=> $message" >> $outfile
+
+ if [[ $message == *04* || $message == *07* ]]; then
+ if [[ $retry_count < 2 ]]; then
+ status="Error: could not process log message"
+ let "retry_count++"
+ else
+ status="OK"
+ retry_count=0
+ fi
+ else
+ status="OK"
+ fi
+
+ echo "<= $status" >> $outfile
+ echo "$status"
+ read line
+done
+
+exit 0
diff --git a/tests/testsuites/omprog-feedback-mt-bin.sh b/tests/testsuites/omprog-feedback-mt-bin.sh
new file mode 100755
index 0000000..97cf12f
--- /dev/null
+++ b/tests/testsuites/omprog-feedback-mt-bin.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+status="OK"
+echo $status
+
+retried=false
+
+read line
+while [[ -n "$line" ]]; do
+ message=${line//$'\n'}
+
+ if [[ $((RANDOM % 100)) < $1 ]]; then
+ status="Error: could not process log message"
+ retried=true
+ else
+ if [[ $retried == true ]]; then
+ echo "=> $message (retried)" >> $outfile
+ retried=false
+ else
+ echo "=> $message" >> $outfile
+ fi
+ status="OK"
+ fi
+
+ echo $status
+ read line
+done
+
+exit 0
diff --git a/tests/testsuites/omprog-feedback-timeout-bin.sh b/tests/testsuites/omprog-feedback-timeout-bin.sh
new file mode 100755
index 0000000..fa1565c
--- /dev/null
+++ b/tests/testsuites/omprog-feedback-timeout-bin.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+echo "Starting" >> $outfile
+echo "<= OK" >> $outfile
+echo "OK"
+
+just_started=true
+
+read line
+while [[ -n "$line" ]]; do
+ message=${line//$'\n'}
+ echo "=> $message" >> $outfile
+
+ if [[ $message == *02* ]]; then
+ # Test partial reads from pipe
+ echo "<= OK" >> $outfile
+ printf 'O'
+ printf 'K'
+ printf '\n'
+ elif [[ $message == *04* ]]; then
+ if [[ $just_started == false ]]; then
+ # Force a restart due to 'confirmTimeout' (2 seconds) exceeded
+ echo "<= (timeout)" >> $outfile
+ ./msleep 10000
+ else
+ # When the message is retried (just after restart), confirm it correctly
+ echo "<= OK" >> $outfile
+ echo "OK"
+ fi
+ elif [[ $message == *07* ]]; then
+ # Test keep-alive feature for long-running processing (more than 2 seconds)
+ echo "<= ........OK" >> $outfile
+ for i in {1..8}; do
+ ./msleep 500
+ printf '.'
+ done
+ printf 'OK\n'
+ else
+ echo "<= OK" >> $outfile
+ echo "OK"
+ fi
+
+ just_started=false
+ read line
+done
+
+exit 0
diff --git a/tests/testsuites/omprog-output-capture-bin.sh b/tests/testsuites/omprog-output-capture-bin.sh
new file mode 100755
index 0000000..1794cde
--- /dev/null
+++ b/tests/testsuites/omprog-output-capture-bin.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+echo "[stdout] Starting"
+>&2 echo "[stderr] Starting"
+
+read log_line
+while [[ -n "$log_line" ]]; do
+ echo "[stdout] Received $log_line"
+ >&2 echo "[stderr] Received $log_line"
+ read log_line
+done
+
+echo "[stdout] Terminating normally"
+>&2 echo "[stderr] Terminating normally"
+
+exit 0
diff --git a/tests/testsuites/omprog-output-capture-mt-bin.py b/tests/testsuites/omprog-output-capture-mt-bin.py
new file mode 100755
index 0000000..22cb553
--- /dev/null
+++ b/tests/testsuites/omprog-output-capture-mt-bin.py
@@ -0,0 +1,35 @@
+# call this via "python[3] script name"
+
+import sys
+import os
+
+lineLength = int(sys.argv[1])
+linePrefix = "[{0:09d}] ".format(os.getpid())
+
+logLine = sys.stdin.readline()
+while logLine:
+ logLine = logLine.strip()
+ numRepeats = int(lineLength / len(logLine))
+
+ lineToStdout = (linePrefix + "[stdout] " + logLine*numRepeats)[:lineLength]
+ lineToStderr = (linePrefix + "[stderr] " + logLine*numRepeats)[:lineLength]
+
+ sys.stdout.write(lineToStdout + "\n")
+ sys.stderr.write(lineToStderr + "\n")
+
+ # Flush stdout. In both Python 2 and Python 3, stdout is block-buffered when
+ # redirected to a file/pipe. But be want each line to be written immediately,
+ # because multiple processes are writing to the same pipe, and we do not want
+ # lines to appear intermingled in the output file. (The flush will cause a
+ # single 'write' syscall, since the size of the block buffer is generally
+ # greater than PIPE_BUF.)
+ sys.stdout.flush()
+
+ # Flush stderr. This is not necessary in Python 2, since stderr is unbuffered
+ # (and therefore each write will be written immediately and atomically to the
+ # pipe). However, in Python 3 stderr is block-buffered when redirected to a
+ # file/pipe. (Note: in future versions of Python 3, stderr could change to
+ # line-buffered; see https://bugs.python.org/issue13601.)
+ sys.stderr.flush()
+
+ logLine = sys.stdin.readline()
diff --git a/tests/testsuites/omprog-restart-terminated-bin.sh b/tests/testsuites/omprog-restart-terminated-bin.sh
new file mode 100755
index 0000000..2c2b2cc
--- /dev/null
+++ b/tests/testsuites/omprog-restart-terminated-bin.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+terminate=false
+
+function handle_sigusr1 {
+ echo "Received SIGUSR1, will terminate after the next message" >> $outfile
+ >&2 echo "[stderr] Received SIGUSR1, will terminate after the next message"
+ terminate=true
+}
+trap "handle_sigusr1" SIGUSR1
+
+function handle_sigterm {
+ echo "Received SIGTERM, terminating" >> $outfile
+ >&2 echo "[stderr] Received SIGTERM, terminating"
+ exit 1
+}
+trap "handle_sigterm" SIGTERM
+
+echo "Starting" >> $outfile
+
+# Write also to stderr (useful for testing the 'output' setting)
+>&2 echo "[stderr] Starting"
+
+# Tell rsyslog we are ready to start processing messages
+echo "OK"
+
+read log_line
+while [[ -n "$log_line" ]]; do
+ echo "Received $log_line" >> $outfile
+ >&2 echo "[stderr] Received $log_line"
+
+ if [[ $terminate == true ]]; then
+ # Terminate prematurely by closing pipe, without confirming the message
+ echo "Terminating without confirming the last message" >> $outfile
+ >&2 echo "[stderr] Terminating without confirming the last message"
+ exit 0
+ fi
+
+ # Tell rsyslog we are ready to process the next message
+ echo "OK"
+
+ read log_line
+done
+
+echo "Terminating normally" >> $outfile
+>&2 echo "[stderr] Terminating normally"
+
+exit 0
diff --git a/tests/testsuites/omprog-single-instance-bin.sh b/tests/testsuites/omprog-single-instance-bin.sh
new file mode 100755
index 0000000..bde73da
--- /dev/null
+++ b/tests/testsuites/omprog-single-instance-bin.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+# This line should appear only once in the output file for the test to pass:
+echo "Starting" >> $outfile
+
+# Write also to stderr (useful for testing the 'output' setting)
+>&2 echo "[stderr] Starting"
+
+echo "OK"
+
+read line
+while [[ -n "$line" ]]; do
+ echo "Received $line" >> $outfile
+ >&2 echo "[stderr] Received $line"
+ echo "OK"
+ read line
+done
+
+# This line should appear only once in the output file for the test to pass:
+echo "Terminating" >> $outfile
+>&2 echo "[stderr] Terminating"
+
+exit 0
diff --git a/tests/testsuites/omprog-transactions-bin.sh b/tests/testsuites/omprog-transactions-bin.sh
new file mode 100755
index 0000000..a8be3e4
--- /dev/null
+++ b/tests/testsuites/omprog-transactions-bin.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+outfile=$RSYSLOG_OUT_LOG
+
+status="OK"
+echo "<= $status" >> $outfile
+echo $status
+
+in_transaction=false
+fail_on_commit=false
+retry_count=0
+
+read line
+while [[ -n "$line" ]]; do
+ message=${line//$'\n'}
+ echo "=> $message" >> $outfile
+
+ if [[ "$message" == "BEGIN TRANSACTION" ]]; then
+ in_transaction=true
+ status="OK"
+ elif [[ "$message" == "COMMIT TRANSACTION" ]]; then
+ in_transaction=false
+ if [[ $fail_on_commit == true ]]; then
+ status="Error: could not commit transaction"
+ fail_on_commit=false
+ else
+ status="OK"
+ fi
+ else
+ if [[ $in_transaction == true ]]; then
+ status="DEFER_COMMIT"
+ else
+ # Should not occur
+ status="Error: received a message out of a transaction"
+ fi
+ fi
+
+ # First command line argument ($1) indicates whether to test for negative
+ # cases. If --failed_messages is specified, an error is returned for certain
+ # messages, forcing them to be retried twice. If --failed_commits is
+ # specified, the error is returned when committing the transaction.
+ if [[ "$1" != "" && ($message == *04* || $message == *07*) ]]; then
+ if [[ $retry_count < 2 ]]; then
+ if [[ "$1" == "--failed_commits" ]]; then
+ fail_on_commit=true
+ else
+ status="Error: could not process log message"
+ fi
+ let "retry_count++"
+ else
+ retry_count=0
+ fi
+ fi
+
+ echo "<= $status" >> $outfile
+ echo $status
+ read line
+done
+
+exit 0
diff --git a/tests/testsuites/pgsql-basic.sql b/tests/testsuites/pgsql-basic.sql
new file mode 100644
index 0000000..8b589e2
--- /dev/null
+++ b/tests/testsuites/pgsql-basic.sql
@@ -0,0 +1,30 @@
+DROP DATABASE IF EXISTS syslogtest;
+CREATE DATABASE syslogtest;
+\c syslogtest
+
+CREATE TABLE systemevents (
+ ID serial not null primary key,
+ CustomerID bigint,
+ ReceivedAt timestamp without time zone NULL,
+ DeviceReportedTime timestamp without time zone NULL,
+ Facility smallint NULL,
+ Priority smallint NULL,
+ FromHost varchar(60) NULL,
+ Message text,
+ NTSeverity int NULL,
+ Importance int NULL,
+ EventSource varchar(60),
+ EventUser varchar(60) NULL,
+ EventCategory int NULL,
+ EventID int NULL,
+ EventBinaryData text NULL,
+ MaxAvailable int NULL,
+ CurrUsage int NULL,
+ MinUsage int NULL,
+ MaxUsage int NULL,
+ InfoUnitID int NULL ,
+ SysLogTag varchar(60),
+ EventLogType varchar(60),
+ GenericFileName VarChar(60),
+ SystemID int NULL
+);
diff --git a/tests/testsuites/pgsql-select-msg.sql b/tests/testsuites/pgsql-select-msg.sql
new file mode 100644
index 0000000..5210aed
--- /dev/null
+++ b/tests/testsuites/pgsql-select-msg.sql
@@ -0,0 +1 @@
+SELECT substring(Message,9,8) FROM systemevents;
diff --git a/tests/testsuites/pgsql-select-syslogtag.sql b/tests/testsuites/pgsql-select-syslogtag.sql
new file mode 100644
index 0000000..8c0f1ee
--- /dev/null
+++ b/tests/testsuites/pgsql-select-syslogtag.sql
@@ -0,0 +1 @@
+select substring(SysLogTag,9,8) from SystemEvents;
diff --git a/tests/testsuites/pmnormalize_basic.rulebase b/tests/testsuites/pmnormalize_basic.rulebase
new file mode 100644
index 0000000..f7eb2b8
--- /dev/null
+++ b/tests/testsuites/pmnormalize_basic.rulebase
@@ -0,0 +1 @@
+rule=:<%pri:number%> %hostname:word% %syslogtag:char-to:\x3a%: is no longer listening on %fromhost-ip:ipv4% %msg:rest%
diff --git a/tests/testsuites/regex_input b/tests/testsuites/regex_input
new file mode 100644
index 0000000..ed1fbd2
--- /dev/null
+++ b/tests/testsuites/regex_input
@@ -0,0 +1 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:http host ports are 192.168.1.2:80, 192.168.1.3, 192.168.1.4:443, 192.168.1.5 etc
diff --git a/tests/testsuites/spframingfix.testdata b/tests/testsuites/spframingfix.testdata
new file mode 100644
index 0000000..d97a3da
--- /dev/null
+++ b/tests/testsuites/spframingfix.testdata
@@ -0,0 +1,20 @@
+<181>00
+ <181>01
+<181>02
+ <181>03
+ <181>04
+ <181>05
+<181>06
+<181>07
+<181>08
+<181>09
+<181>10
+ <181>11
+ <181>12
+ <181>13
+ <181>14
+<181>15
+ <181>16
+<181>17
+ <181>18
+<181>19
diff --git a/tests/testsuites/stop_when_array_has_elem_input b/tests/testsuites/stop_when_array_has_elem_input
new file mode 100644
index 0000000..6fddc95
--- /dev/null
+++ b/tests/testsuites/stop_when_array_has_elem_input
@@ -0,0 +1,3 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": ["abc0", "def1", "ghi2"]}
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": ["xyz0", "zab1", "abc2"]}
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:@cee:{"foo": ["abc2", "def1", "ghi0"]}
diff --git a/tests/testsuites/tokenized_input b/tests/testsuites/tokenized_input
new file mode 100644
index 0000000..8825673
--- /dev/null
+++ b/tests/testsuites/tokenized_input
@@ -0,0 +1,5 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:10.20.30.40, 50.60.70.80, 90.100.110.120, 130.140.150.160
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:local ips are 192.168.1.2, 192.168.1.3, 192.168.1.4
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:10.20.30.40, 50.60.70.80, 190.200.210.220 are external ips
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:for foo@localhost path was /bin:/usr/local/bin:/usr/bin
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005:comma separated list of colon separated numbers: 10, 20 : 30#40#50 : 60#70#80, 90 : 100
diff --git a/tests/testsuites/valid.conf b/tests/testsuites/valid.conf
new file mode 100644
index 0000000..250f054
--- /dev/null
+++ b/tests/testsuites/valid.conf
@@ -0,0 +1,3 @@
+# This is an invalid config file that shall trigger an exit code
+# with the config verification run
+*.* /tmp/data.log
diff --git a/tests/testsuites/variable_leading_underscore.conf b/tests/testsuites/variable_leading_underscore.conf
new file mode 100644
index 0000000..6279345
--- /dev/null
+++ b/tests/testsuites/variable_leading_underscore.conf
@@ -0,0 +1,2 @@
+set $.foo = $!_FOO;
+*.* /dev/null # we need to have one action, else rsyslog aborts for that reason
diff --git a/tests/testsuites/wrap3_input b/tests/testsuites/wrap3_input
new file mode 100644
index 0000000..18aa3cb
--- /dev/null
+++ b/tests/testsuites/wrap3_input
@@ -0,0 +1 @@
+<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: a abcbcdefbcdefb has bcdefbc
diff --git a/tests/testsuites/x.509/ca-key.pem b/tests/testsuites/x.509/ca-key.pem
new file mode 100644
index 0000000..9234024
--- /dev/null
+++ b/tests/testsuites/x.509/ca-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:a1:0b:0c:e4:ad:a2:f6:bf:d4:85:01:8d:d6:0f:56
+ ae:e9:c4:42:49:aa:ab:80:2f:f9:71:e7:30:cc:60:6e
+ 9b:49:e3:94:ee:24:99:49:08:e4:6e:20:d5:cc:13:b5
+ 7a:9c:99:38:75:ec:42:9a:1e:50:45:a2:e8:27:1f:92
+ 59:74:31:66:2a:93:88:a7:8a:1d:00:29:79:ba:e4:f9
+ 27:59:51:87:a9:6c:3b:25:6a:f5:7d:21:aa:9f:6a:7e
+ 39:f5:ae:b9:fb:5d:f2:e4:f6:2f:7e:a2:bd:3f:88:b2
+ b6:99:e8:26:53:96:54:5f:aa:4d:a6:82:9a:19:e2:c1
+ 97:80:9e:8a:28:aa:75:a5:1e:c8:62:bc:60:a4:24:b3
+ 1f:f4:cd:d7:96:6f:4e:18:a7:ec:c7:21:d7:5c:1a:81
+ 80:c7:cf:33:7f:de:28:9c:94:04:4a:c5:4e:9f:5c:86
+ de:c1:8c:ee:b8:5f:bc:e1:c3:2c:62:78:7e:51:3e:d7
+ 0c:3c:0f:aa:d9:65:c8:ba:0f:86:d8:85:f0:35:6e:98
+ 91:c2:c5:37:50:82:e0:8a:75:15:a5:f6:cc:9f:e5:ba
+ 7f:6b:3e:0a:ad:1d:6e:24:33:6b:49:5f:f9:2d:ab:2b
+ ee:dc:1f:ee:33:f6:5b:6a:03:4e:78:07:6f:c9:3e:e3
+ 4a:6f:07:f7:94:ba:1a:6c:63:56:bb:8e:d3:09:fc:b3
+ 68:35:1b:ed:8e:f4:08:54:6b:61:f9:0d:e2:90:f9:cb
+ e6:7c:df:c2:07:f3:b4:4a:26:2a:21:e6:ad:9c:79:55
+ f9:a7:23:6f:f1:79:a4:32:eb:d6:60:3a:e7:8d:54:e7
+ 5f:b4:34:7c:df:d3:ea:1f:1f:55:32:29:96:88:e5:81
+ 5f:33:da:d3:dc:ac:91:34:33:86:3a:ee:74:80:81:85
+ fb:bf:60:2d:99:ca:01:3c:c2:f9:49:a8:ab:ce:ae:5a
+ a6:29:63:6f:45:a6:e4:a4:8d:c1:76:76:78:0c:fd:9d
+ 3b:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 00:89:fd:ca:02:78:b6:56:f0:70:cd:b7:53:2d:c4:de
+ e5:e9:f0:fd:4b:da:2e:32:1c:e9:85:2c:30:a8:2f:49
+ 17:4e:ec:ef:44:4f:9f:f8:f0:e1:ab:6b:ff:46:6a:ec
+ ea:2f:1d:2b:40:00:3d:e1:89:70:06:fb:5c:29:89:e8
+ 01:36:8a:cd:9c:55:e6:96:88:c5:e8:c9:a1:40:ff:ca
+ 6e:69:1e:6f:3c:41:3d:3d:06:b5:6b:8f:59:80:57:e3
+ e9:0e:17:b5:cd:29:e7:63:41:7f:d8:e6:e1:7a:7b:4b
+ 87:23:c1:c4:75:83:2e:b0:fa:60:a6:f8:e9:ca:9c:7e
+ 7d:ae:fc:2a:2e:46:41:a0:47:0c:35:6e:6c:f0:b9:71
+ b3:44:34:cd:32:5e:15:71:13:12:d4:5e:af:06:80:bf
+ ce:f5:67:1a:1d:ca:e2:c9:a8:1b:35:66:73:c4:21:a8
+ 7f:5f:21:bf:bb:c4:6d:38:95:e0:86:4f:f1:0c:f4:e7
+ 96:7b:da:9e:95:7f:93:ca:96:ea:07:4f:13:52:5d:39
+ 99:42:44:b5:a3:11:af:6e:62:a1:c9:43:6d:24:69:13
+ 8a:62:ea:76:ae:7e:29:ef:c1:7e:a3:6e:b1:a8:71:9d
+ 3e:1a:40:03:16:b8:a5:a5:df:b3:c0:6b:d1:7b:fd:91
+ e0:5b:30:d3:22:49:74:c3:ee:ca:b1:85:c9:9a:c5:8b
+ 45:3e:c3:75:f9:0c:ee:41:2d:12:f6:98:41:d4:ea:dd
+ d3:89:d4:7f:01:b0:19:3b:34:30:16:16:03:d9:74:9f
+ 4a:ba:71:59:1f:9b:7e:ee:ed:5f:c1:ec:11:38:bb:04
+ a6:5e:b8:e3:0f:61:e7:92:39:e3:a9:5f:ab:31:f5:2d
+ 0c:55:f2:70:c4:25:75:ba:98:50:26:82:4e:e8:94:db
+ 21:2c:6c:31:5c:e6:e5:65:8c:31:48:cb:98:73:1a:61
+ 96:a2:dd:27:f8:30:54:6a:9e:19:26:77:13:be:ca:d3
+ a1:
+
+prime1:
+ 00:d4:9d:19:0c:c4:68:92:2c:4f:ab:ab:04:d0:4b:6c
+ 3c:b3:df:59:26:f6:28:e8:85:27:2b:b9:0a:7b:d7:52
+ ab:90:d9:3d:bc:38:34:ad:e6:b6:e9:1a:f8:a4:ab:cf
+ 4f:94:92:6c:a9:38:c3:ee:19:1f:4c:95:e8:80:c3:50
+ 1d:bb:1a:41:20:03:1a:c1:e9:7a:ff:e3:f7:1d:3f:12
+ da:09:99:de:50:33:8c:ee:37:6e:c9:e3:aa:ec:9d:e0
+ 84:5f:97:1b:48:cf:b3:d1:99:91:97:05:69:b5:47:20
+ fa:43:d8:01:bb:dc:95:a8:3b:77:d3:5d:25:31:cd:9b
+ 01:90:22:1c:92:c6:e5:e2:09:51:42:7d:0c:70:08:25
+ c5:9c:b7:71:1e:96:f1:df:c9:f0:aa:e2:52:4f:32:e1
+ f7:76:ca:fb:6c:6a:c7:c1:22:54:45:c9:6f:3c:a7:b5
+ f6:7d:c7:f7:e0:09:c8:36:59:d2:a8:09:7b:11:b6:3c
+ af:
+
+prime2:
+ 00:c1:e7:eb:18:5e:4d:3c:7f:b9:16:bf:d8:ce:9f:b7
+ c3:6a:a0:fa:0b:64:68:20:c5:18:d1:c8:13:d5:82:24
+ 8f:b7:5c:50:64:64:3a:8c:25:cc:71:21:79:ba:74:34
+ 16:56:6c:3d:4b:60:1e:2c:83:88:51:d4:76:61:57:5a
+ 12:83:3c:67:6e:09:c5:74:27:fd:64:af:46:a2:09:41
+ 9c:95:a1:cd:9d:86:14:29:69:28:a6:88:c3:71:9b:ac
+ a9:94:1e:df:10:78:f1:ec:30:46:95:9c:58:bf:7f:1e
+ 55:a6:3c:14:24:8f:9f:d3:97:3a:b8:cb:82:8c:c7:a9
+ 49:5b:20:5a:ae:f3:20:b3:e5:e7:2e:e1:17:02:57:c5
+ f9:bf:68:10:74:6c:69:7b:55:ad:6b:58:f8:13:33:d1
+ 85:96:e0:96:d8:e3:6f:79:77:f3:17:b0:7a:02:81:16
+ 6e:55:23:65:10:90:90:0b:6e:5b:cb:3b:cc:6e:83:03
+ 35:
+
+coefficient:
+ 46:d5:f1:79:c7:d6:70:c2:eb:9b:fd:12:0a:53:b9:54
+ 60:14:e0:33:3b:ab:41:71:ac:2a:51:12:b3:87:ad:98
+ 9e:a9:ac:b4:6d:b5:02:4d:1e:b2:e5:fe:76:e5:8c:c1
+ cb:60:0e:f3:76:77:be:e1:51:86:f1:9e:ae:c0:d9:78
+ 3c:7a:c0:b6:02:75:dc:21:cf:d0:bc:fe:fa:34:33:a1
+ 1a:a6:cf:7d:27:cc:d7:46:46:f0:8f:9d:31:4d:cf:78
+ ec:15:6a:6f:64:18:24:04:65:b7:bc:58:0d:1c:35:3c
+ 16:e3:2d:f5:e0:13:64:a2:44:8c:4a:34:54:ab:23:4e
+ fd:01:3c:01:7d:87:5b:5a:16:ce:c8:b8:05:bf:74:ea
+ b5:94:77:23:1b:2d:33:55:c3:a2:e0:b7:a4:28:be:81
+ ac:f0:63:d3:28:b7:01:b9:4c:03:aa:d1:d1:d1:36:2a
+ 99:1d:93:ac:ea:da:66:fb:7e:97:d3:bf:d2:b0:92:a0
+
+
+exp1:
+ 7f:2e:76:44:97:dc:c1:cb:b5:e0:c7:cd:7a:58:13:a8
+ 00:25:13:ac:65:c5:b4:c9:a9:d3:d2:bd:bd:b4:e1:23
+ f5:e2:ad:b6:40:9c:ea:85:bf:56:93:a6:b6:c2:7b:a1
+ 6c:0b:66:ea:97:25:44:f1:4c:32:c0:dd:b2:e0:a2:b5
+ 16:2e:2f:54:d9:e6:90:a6:7c:c8:43:72:97:d1:1a:12
+ c9:79:7c:6d:d7:58:6f:4b:43:7f:8b:2b:bc:9c:f8:27
+ d7:12:89:e4:b5:32:28:a8:47:59:e2:88:08:43:43:2b
+ d1:97:8d:f9:f5:8a:a4:76:e6:47:ce:49:28:90:88:2f
+ 98:2b:7f:92:21:5e:74:27:04:af:d4:23:b3:84:7c:2b
+ c8:82:47:2d:78:37:b9:99:8f:d8:78:c7:a9:ce:93:33
+ 37:a1:56:62:d5:41:26:7b:c5:93:75:5a:90:1a:f6:93
+ 3b:4c:7a:2f:4f:4a:af:90:6d:9d:cd:06:0c:63:49:cb
+
+
+exp2:
+ 4e:2c:e8:55:7c:bf:7a:e2:ab:86:86:76:2c:67:ac:38
+ b6:e6:8b:a8:c8:24:4b:01:eb:8d:b8:32:76:e3:ef:45
+ 99:d1:38:00:21:80:91:3c:33:fe:70:56:99:5b:7c:1c
+ 7d:5f:4a:1e:f7:73:72:d2:dc:c4:d0:f9:a1:29:0c:81
+ 66:33:96:27:80:fd:00:65:96:fd:5e:c5:05:52:e2:06
+ f5:34:b4:a7:0b:85:59:64:b2:24:e2:02:99:ec:ff:61
+ a6:fc:03:46:aa:dc:2e:33:10:62:05:14:aa:af:df:54
+ fc:9e:40:28:b5:56:e4:81:96:05:26:d7:4d:56:b9:e3
+ 7f:3f:be:0f:c6:a9:aa:9d:c7:e4:d8:8e:e4:3c:ea:ee
+ 53:c2:ea:cf:65:5d:e9:81:93:57:32:19:61:f4:84:46
+ 6d:9b:c2:75:52:cc:80:96:61:85:6d:7a:e3:43:93:fd
+ 8b:89:a7:97:54:11:1e:ea:b1:4b:70:a2:6c:f3:98:f9
+
+
+
+Public Key PIN:
+ pin-sha256:3cQAkiO2zLPAa/Tawzz/iqD5XAly2f+6m0f1OwppO8w=
+Public Key ID:
+ sha256:ddc4009223b6ccb3c06bf4dac33cff8aa0f95c0972d9ffba9b47f53b0a693bcc
+ sha1:b09f67332c8888891f4462749d25ffc006135dd6
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEAoQsM5K2i9r/UhQGN1g9WrunEQkmqq4Av+XHnMMxgbptJ45Tu
+JJlJCORuINXME7V6nJk4dexCmh5QRaLoJx+SWXQxZiqTiKeKHQApebrk+SdZUYep
+bDslavV9Iaqfan459a65+13y5PYvfqK9P4iytpnoJlOWVF+qTaaCmhniwZeAnooo
+qnWlHshivGCkJLMf9M3Xlm9OGKfsxyHXXBqBgMfPM3/eKJyUBErFTp9cht7BjO64
+X7zhwyxieH5RPtcMPA+q2WXIug+G2IXwNW6YkcLFN1CC4Ip1FaX2zJ/lun9rPgqt
+HW4kM2tJX/ktqyvu3B/uM/ZbagNOeAdvyT7jSm8H95S6GmxjVruO0wn8s2g1G+2O
+9AhUa2H5DeKQ+cvmfN/CB/O0SiYqIeatnHlV+acjb/F5pDLr1mA6541U51+0NHzf
+0+ofH1UyKZaI5YFfM9rT3KyRNDOGOu50gIGF+79gLZnKATzC+Umoq86uWqYpY29F
+puSkjcF2dngM/Z07AgMBAAECggGBAIn9ygJ4tlbwcM23Uy3E3uXp8P1L2i4yHOmF
+LDCoL0kXTuzvRE+f+PDhq2v/Rmrs6i8dK0AAPeGJcAb7XCmJ6AE2is2cVeaWiMXo
+yaFA/8puaR5vPEE9PQa1a49ZgFfj6Q4Xtc0p52NBf9jm4Xp7S4cjwcR1gy6w+mCm
++OnKnH59rvwqLkZBoEcMNW5s8Llxs0Q0zTJeFXETEtRerwaAv871ZxodyuLJqBs1
+ZnPEIah/XyG/u8RtOJXghk/xDPTnlnvanpV/k8qW6gdPE1JdOZlCRLWjEa9uYqHJ
+Q20kaROKYup2rn4p78F+o26xqHGdPhpAAxa4paXfs8Br0Xv9keBbMNMiSXTD7sqx
+hcmaxYtFPsN1+QzuQS0S9phB1Ord04nUfwGwGTs0MBYWA9l0n0q6cVkfm37u7V/B
+7BE4uwSmXrjjD2HnkjnjqV+rMfUtDFXycMQldbqYUCaCTuiU2yEsbDFc5uVljDFI
+y5hzGmGWot0n+DBUap4ZJncTvsrToQKBwQDUnRkMxGiSLE+rqwTQS2w8s99ZJvYo
+6IUnK7kKe9dSq5DZPbw4NK3mtuka+KSrz0+UkmypOMPuGR9MleiAw1AduxpBIAMa
+wel6/+P3HT8S2gmZ3lAzjO43bsnjquyd4IRflxtIz7PRmZGXBWm1RyD6Q9gBu9yV
+qDt3010lMc2bAZAiHJLG5eIJUUJ9DHAIJcWct3EelvHfyfCq4lJPMuH3dsr7bGrH
+wSJURclvPKe19n3H9+AJyDZZ0qgJexG2PK8CgcEAwefrGF5NPH+5Fr/Yzp+3w2qg
++gtkaCDFGNHIE9WCJI+3XFBkZDqMJcxxIXm6dDQWVmw9S2AeLIOIUdR2YVdaEoM8
+Z24JxXQn/WSvRqIJQZyVoc2dhhQpaSimiMNxm6yplB7fEHjx7DBGlZxYv38eVaY8
+FCSPn9OXOrjLgozHqUlbIFqu8yCz5ecu4RcCV8X5v2gQdGxpe1Wta1j4EzPRhZbg
+ltjjb3l38xewegKBFm5VI2UQkJALblvLO8xugwM1AoHAfy52RJfcwcu14MfNelgT
+qAAlE6xlxbTJqdPSvb204SP14q22QJzqhb9Wk6a2wnuhbAtm6pclRPFMMsDdsuCi
+tRYuL1TZ5pCmfMhDcpfRGhLJeXxt11hvS0N/iyu8nPgn1xKJ5LUyKKhHWeKICEND
+K9GXjfn1iqR25kfOSSiQiC+YK3+SIV50JwSv1COzhHwryIJHLXg3uZmP2HjHqc6T
+MzehVmLVQSZ7xZN1WpAa9pM7THovT0qvkG2dzQYMY0nLAoHATizoVXy/euKrhoZ2
+LGesOLbmi6jIJEsB6424Mnbj70WZ0TgAIYCRPDP+cFaZW3wcfV9KHvdzctLcxND5
+oSkMgWYzlieA/QBllv1exQVS4gb1NLSnC4VZZLIk4gKZ7P9hpvwDRqrcLjMQYgUU
+qq/fVPyeQCi1VuSBlgUm101WueN/P74Pxqmqncfk2I7kPOruU8Lqz2Vd6YGTVzIZ
+YfSERm2bwnVSzICWYYVteuNDk/2LiaeXVBEe6rFLcKJs85j5AoHARtXxecfWcMLr
+m/0SClO5VGAU4DM7q0FxrCpRErOHrZieqay0bbUCTR6y5f525YzBy2AO83Z3vuFR
+hvGersDZeDx6wLYCddwhz9C8/vo0M6Eaps99J8zXRkbwj50xTc947BVqb2QYJARl
+t7xYDRw1PBbjLfXgE2SiRIxKNFSrI079ATwBfYdbWhbOyLgFv3TqtZR3IxstM1XD
+ouC3pCi+gazwY9MotwG5TAOq0dHRNiqZHZOs6tpm+36X07/SsJKg
+-----END RSA PRIVATE KEY-----
diff --git a/tests/testsuites/x.509/ca.pem b/tests/testsuites/x.509/ca.pem
new file mode 100644
index 0000000..430e5c2
--- /dev/null
+++ b/tests/testsuites/x.509/ca.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEiDCCAvCgAwIBAgIIXBeb1iWItcgwDQYJKoZIhvcNAQELBQAwRDERMA8GA1UE
+AxMIc29tZU5hbWUxEDAOBgNVBAsTB3JzeXNsb2cxEDAOBgNVBAoTB1NvbWVPcmcx
+CzAJBgNVBAYTAlVTMCAXDTE4MTIxNzEyNTEzNVoYDzIxMTgxMTIzMTI1MTUwWjBE
+MREwDwYDVQQDEwhzb21lTmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMH
+U29tZU9yZzELMAkGA1UEBhMCVVMwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
+AoIBgQChCwzkraL2v9SFAY3WD1au6cRCSaqrgC/5cecwzGBum0njlO4kmUkI5G4g
+1cwTtXqcmTh17EKaHlBFougnH5JZdDFmKpOIp4odACl5uuT5J1lRh6lsOyVq9X0h
+qp9qfjn1rrn7XfLk9i9+or0/iLK2megmU5ZUX6pNpoKaGeLBl4CeiiiqdaUeyGK8
+YKQksx/0zdeWb04Yp+zHIddcGoGAx88zf94onJQESsVOn1yG3sGM7rhfvOHDLGJ4
+flE+1ww8D6rZZci6D4bYhfA1bpiRwsU3UILginUVpfbMn+W6f2s+Cq0dbiQza0lf
++S2rK+7cH+4z9ltqA054B2/JPuNKbwf3lLoabGNWu47TCfyzaDUb7Y70CFRrYfkN
+4pD5y+Z838IH87RKJioh5q2ceVX5pyNv8XmkMuvWYDrnjVTnX7Q0fN/T6h8fVTIp
+lojlgV8z2tPcrJE0M4Y67nSAgYX7v2AtmcoBPML5Sairzq5apiljb0Wm5KSNwXZ2
+eAz9nTsCAwEAAaN8MHowDwYDVR0TAQH/BAUwAwEB/zBIBgNVHREEQTA/ghNzb21l
+b25lQGV4YW1wbGUubmV0ghNzb21lb25lQGV4YW1wbGUubmV0gRNzb21lb25lQGV4
+YW1wbGUubmV0MB0GA1UdDgQWBBSwn2czLIiIiR9EYnSdJf/ABhNd1jANBgkqhkiG
+9w0BAQsFAAOCAYEAl6nIgBHMX8rnAC054xx/aQcXazrv89KyEp0ydzBwJQOTei7I
+UGWQIRkSLL+CtrGhcLPQpTzAQn5NDo4ayinAtlPtP8MYcMBv13ZBJXLSqRfrTM04
+wkEbsWuCp+c/fU14E+QYSk4AwpoUdQeqmdM60KAoHNn+BaHGJRhRGOY9A8hfQQ5L
+S2TpJ+suJuHafNjr9vvhlqTSefCfENV40Ie1nwHCbqNZdDZel1iQBmdI7WJG7uTI
+OrSOPepYzOAYKQ+PWKMvZuzBc6ei/lcIpPHksWxK7nY35izSHjepMLGqH0/XZ51i
+wN55slw9agg5eCq/zL/+Ebu7+yub8JhA9D4pgT5nBp8LtQPOIKnkVlFookjfyO8/
+dWsjGnhT9RNbDUQg7Y7spTWPT7wqOmQchEvQt+x96BHq4SLe88HnTpBk2Cb370jq
+QQFW6s9vwo9PjOafOkyqYsiBuuCFxT80GegBlaipDNqLYhJ1fJAdQtRtFgogqpeS
+thWJZzNJeHyZSpah
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/ca.srl b/tests/testsuites/x.509/ca.srl
new file mode 100644
index 0000000..09f81ec
--- /dev/null
+++ b/tests/testsuites/x.509/ca.srl
@@ -0,0 +1 @@
+0D7B5949C4431CF8E2E1D6D9F4694C044A80B748
diff --git a/tests/testsuites/x.509/client-cert-new.pem b/tests/testsuites/x.509/client-cert-new.pem
new file mode 100644
index 0000000..e92ab86
--- /dev/null
+++ b/tests/testsuites/x.509/client-cert-new.pem
@@ -0,0 +1,102 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4 (0x4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 13:52:50 2023 GMT
+ Not After : Jun 12 13:52:50 2123 GMT
+ Subject: C=US, ST=CA, O=SomeComp, OU=SomeUnit, CN=rsyslog/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (3072 bit)
+ Modulus:
+ 00:9d:91:da:d8:2e:3d:9d:ae:85:c3:c5:a7:f6:a4:
+ 66:f8:c8:91:91:b8:70:20:dc:ed:e8:23:ca:53:f7:
+ b8:52:43:f3:a7:eb:fb:df:8a:3b:2c:b0:13:fa:62:
+ d3:a1:53:a4:51:71:1f:68:d9:fd:bc:39:4a:fb:c9:
+ 6a:df:f3:88:84:b0:80:bc:c0:f5:1b:42:11:f6:4c:
+ 1a:d8:2c:62:0b:5d:50:64:30:9a:d3:db:c1:d5:7f:
+ 39:53:e4:bd:e8:1e:04:9d:c9:12:e0:e4:57:29:29:
+ 01:b9:f1:e5:bc:74:a6:e7:4b:61:e6:67:5c:6c:4e:
+ ee:ee:22:0c:1b:14:6d:e8:0c:6f:ee:ee:c3:b8:dd:
+ df:15:ed:7a:96:5b:cc:85:e5:e3:50:c4:ce:2b:bf:
+ b6:37:e6:20:fc:6e:45:7e:09:bd:84:7a:af:07:27:
+ f4:99:23:41:df:36:d8:29:31:a0:96:84:2f:fd:45:
+ 2e:d4:b4:f9:fa:dc:8f:23:c0:e0:06:ad:ad:0a:72:
+ da:f4:3b:a1:cb:d6:a6:3b:ec:46:c4:95:f2:71:a5:
+ ad:08:1f:e7:06:18:0e:db:80:51:96:ba:24:f6:64:
+ 02:6b:d3:f0:76:01:34:3a:72:02:e9:cb:d0:aa:62:
+ 51:0c:8f:83:be:c0:47:99:d2:92:72:ed:53:a5:49:
+ 05:d4:c9:a1:f4:4d:de:12:9d:1a:c8:17:84:f3:a2:
+ 7c:67:47:82:4b:86:1e:73:86:e2:26:26:10:94:a3:
+ 99:9b:08:99:78:9d:3d:33:5d:85:c2:46:65:94:ab:
+ 70:b4:3b:c1:26:8b:11:b6:66:27:88:22:84:03:b5:
+ 08:45:32:8c:81:23:be:62:dc:6f:a0:aa:5e:9f:03:
+ f7:a7:f5:03:70:3c:78:09:d0:84:44:8c:19:af:76:
+ f7:93:fc:af:c6:fd:db:d9:4c:cb:20:79:44:71:cb:
+ e6:55:61:a9:7a:af:0b:a3:a6:ed:e9:a9:11:af:fa:
+ a3:5d:ac:97:e7:ef:2b:b6:a8:37
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 6E:15:7E:C4:62:2B:92:6D:22:EE:0C:E4:C5:36:29:38:16:62:BE:89
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 64:b0:45:6b:0c:7c:2d:09:14:8e:78:93:85:ef:d2:31:aa:c3:
+ 59:2e:85:bf:29:e1:46:59:38:d4:fe:ea:c4:c1:83:a7:4a:1b:
+ 92:5e:e8:11:9c:21:48:9d:1e:cc:31:d8:31:00:72:fe:7b:c1:
+ 18:c4:f5:37:f3:3b:0e:1a:f6:3f:19:47:22:c9:87:01:e0:4c:
+ f4:5d:36:0a:87:46:42:fc:6c:ab:26:ff:7d:ca:2c:19:97:ca:
+ 25:fc:70:66:4e:49:86:3e:81:0f:ee:e2:5c:3b:69:07:8b:c2:
+ 52:09:46:d8:67:af:84:54:bb:4f:f3:e0:da:07:c5:64:56:2d:
+ fb:f9:55:13:53:1d:c6:78:63:40:22:23:4f:63:59:37:05:c7:
+ 46:b6:36:53:30:fe:9b:e6:01:0a:54:5b:be:1b:a4:72:c3:27:
+ 1b:c5:21:5d:d3:0c:06:56:d9:df:45:83:e7:06:6d:47:53:72:
+ ea:6c:e7:db:5e:bd:14:47:19:0c:18:13:73:6b:14:dc:29:6c:
+ c0:60:fa:4c:02:74:45:e7:8d:12:bd:1f:cb:77:2c:72:19:ef:
+ e8:85:5c:cf:77:04:b7:d4:08:a8:7e:d1:1d:20:7b:76:27:ca:
+ 8a:5a:2a:a5:e7:15:6c:2d:50:9c:c2:b4:83:45:c2:f7:a5:f0:
+ 6b:d5:45:6b:88:4c:db:00:26:2f:8e:0a:3c:42:4e:0c:64:18:
+ 41:a0:6b:4b:d0:78:89:b4:64:34:5b:76:cb:dd:b9:be:6e:28:
+ 82:ba:6e:11:99:86:88:b6:0d:22:2b:a6:eb:5f:0b:ca:77:5b:
+ 2e:28:b7:f3:96:c3:8c:9d:0d:2b:59:98:d4:20:87:3a:2e:f4:
+ e3:bf:a2:ff:67:4f:3f:1e:ce:ec:59:76:5a:67:81:ba:44:96:
+ 29:af:05:ce:55:02:b4:d6:68:f0:25:61:8c:91:83:03:fd:e4:
+ 2c:06:91:b4:32:d8:5b:47:d6:20:55:44:a6:0c:9b:97:bb:94:
+ 66:25:8c:35:e0:32
+-----BEGIN CERTIFICATE-----
+MIIEszCCAxugAwIBAgIBBDANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTM1MjUwWhgPMjEyMzA2MTIxMzUyNTBaMHcxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU29tZUNvbXAxETAPBgNVBAsM
+CFNvbWVVbml0MRAwDgYDVQQDDAdyc3lzbG9nMSMwIQYJKoZIhvcNAQkBFhRhbG9y
+YmFjaEBhZGlzY29uLmNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
+AJ2R2tguPZ2uhcPFp/akZvjIkZG4cCDc7egjylP3uFJD86fr+9+KOyywE/pi06FT
+pFFxH2jZ/bw5SvvJat/ziISwgLzA9RtCEfZMGtgsYgtdUGQwmtPbwdV/OVPkvege
+BJ3JEuDkVykpAbnx5bx0pudLYeZnXGxO7u4iDBsUbegMb+7uw7jd3xXtepZbzIXl
+41DEziu/tjfmIPxuRX4JvYR6rwcn9JkjQd822CkxoJaEL/1FLtS0+frcjyPA4Aat
+rQpy2vQ7ocvWpjvsRsSV8nGlrQgf5wYYDtuAUZa6JPZkAmvT8HYBNDpyAunL0Kpi
+UQyPg77AR5nSknLtU6VJBdTJofRN3hKdGsgXhPOifGdHgkuGHnOG4iYmEJSjmZsI
+mXidPTNdhcJGZZSrcLQ7wSaLEbZmJ4gihAO1CEUyjIEjvmLcb6CqXp8D96f1A3A8
+eAnQhESMGa9295P8r8b929lMyyB5RHHL5lVhqXqvC6Om7empEa/6o12sl+fvK7ao
+NwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdl
+bmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUbhV+xGIrkm0i7gzkxTYpOBZi
+vokwHwYDVR0jBBgwFoAUsJ9nMyyIiIkfRGJ0nSX/wAYTXdYwDQYJKoZIhvcNAQEL
+BQADggGBAGSwRWsMfC0JFI54k4Xv0jGqw1kuhb8p4UZZONT+6sTBg6dKG5Je6BGc
+IUidHswx2DEAcv57wRjE9TfzOw4a9j8ZRyLJhwHgTPRdNgqHRkL8bKsm/33KLBmX
+yiX8cGZOSYY+gQ/u4lw7aQeLwlIJRthnr4RUu0/z4NoHxWRWLfv5VRNTHcZ4Y0Ai
+I09jWTcFx0a2NlMw/pvmAQpUW74bpHLDJxvFIV3TDAZW2d9Fg+cGbUdTcups59te
+vRRHGQwYE3NrFNwpbMBg+kwCdEXnjRK9H8t3LHIZ7+iFXM93BLfUCKh+0R0ge3Yn
+yopaKqXnFWwtUJzCtINFwvel8GvVRWuITNsAJi+OCjxCTgxkGEGga0vQeIm0ZDRb
+dsvdub5uKIK6bhGZhoi2DSIrputfC8p3Wy4ot/OWw4ydDStZmNQghzou9OO/ov9n
+Tz8ezuxZdlpngbpElimvBc5VArTWaPAlYYyRgwP95CwGkbQy2FtH1iBVRKYMm5e7
+lGYljDXgMg==
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/client-cert.pem b/tests/testsuites/x.509/client-cert.pem
new file mode 100644
index 0000000..abd9702
--- /dev/null
+++ b/tests/testsuites/x.509/client-cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEoTCCAwmgAwIBAgIIXBeg0SlsiUswDQYJKoZIhvcNAQELBQAwRDERMA8GA1UE
+AxMIc29tZU5hbWUxEDAOBgNVBAsTB3JzeXNsb2cxEDAOBgNVBAoTB1NvbWVPcmcx
+CzAJBgNVBAYTAlVTMCAXDTE4MTIxNzEzMTI1MFoYDzIxMTgxMTIzMTMxMjUzWjBY
+MRcwFQYDVQQDEw5yc3lzbG9nIGNsaWVudDERMA8GA1UECxMIU29tZVVuaXQxEDAO
+BgNVBAoTB1NvbWVPcmcxCzAJBgNVBAgTAkNBMQswCQYDVQQGEwJVUzCCAaIwDQYJ
+KoZIhvcNAQEBBQADggGPADCCAYoCggGBAJ2R2tguPZ2uhcPFp/akZvjIkZG4cCDc
+7egjylP3uFJD86fr+9+KOyywE/pi06FTpFFxH2jZ/bw5SvvJat/ziISwgLzA9RtC
+EfZMGtgsYgtdUGQwmtPbwdV/OVPkvegeBJ3JEuDkVykpAbnx5bx0pudLYeZnXGxO
+7u4iDBsUbegMb+7uw7jd3xXtepZbzIXl41DEziu/tjfmIPxuRX4JvYR6rwcn9Jkj
+Qd822CkxoJaEL/1FLtS0+frcjyPA4AatrQpy2vQ7ocvWpjvsRsSV8nGlrQgf5wYY
+DtuAUZa6JPZkAmvT8HYBNDpyAunL0KpiUQyPg77AR5nSknLtU6VJBdTJofRN3hKd
+GsgXhPOifGdHgkuGHnOG4iYmEJSjmZsImXidPTNdhcJGZZSrcLQ7wSaLEbZmJ4gi
+hAO1CEUyjIEjvmLcb6CqXp8D96f1A3A8eAnQhESMGa9295P8r8b929lMyyB5RHHL
+5lVhqXqvC6Om7empEa/6o12sl+fvK7aoNwIDAQABo4GAMH4wDAYDVR0TAQH/BAIw
+ADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUDAweg
+ADAdBgNVHQ4EFgQUlBeunSFXuHvBrhB7CKkhvKEUAIswHwYDVR0jBBgwFoAUsJ9n
+MyyIiIkfRGJ0nSX/wAYTXdYwDQYJKoZIhvcNAQELBQADggGBAEk9KaiQ6NzNHf7M
+kvPosgCu9Tm1jgRg4qjdMHxtzDxFQZWOtMuDxqqrNEC9FEF5zpEB8Z4VtubIeVK7
+6i6BdSMbI5zlnlxffPD1Gz8AKXe9BNb6UlLvlEC+58D4CJmrxDuKZXaBzy3xh2TP
+Al/s5XkPBuXKc7l0qQdDkt67LfDCrwpGfseOFXNUHDREBOulwX4LJzilVqLMsp03
+qMHK0f4kOxc0oJrH+2+jCgpu1QPoFOLl/6shbRw3qls/f/coWnnS5kd2NOPUf0pe
+j5lBt5ThhnLQIGwJucLa6cHVx+R4BWtTz4/v8hCwWr1cUbNEkxTyBErl0l8KkpCQ
+d0NCuZe2u2AJYEKdNilSiBr33ERZ70peE/ATfk6hv9ysWepeGYJiuybWXMrDtLbw
+X9wzwtdetIvvMxXiNAT5RpsZtFrdBD9ZwCHhJ+xjEycRDQKdnL/H4WbpAfvB9zcJ
+WCJ50FBFjNoHSYrwmhQULOYa8AjVxxrX/27g2mN3P3sDLG6bzw==
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/client-expired-cert.pem b/tests/testsuites/x.509/client-expired-cert.pem
new file mode 100644
index 0000000..d5fe9a2
--- /dev/null
+++ b/tests/testsuites/x.509/client-expired-cert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEPTCCAqWgAwIBAgIIXBEoYTa7GecwDQYJKoZIhvcNAQELBQAwRDERMA8GA1UE
+AxMIc29tZU5hbWUxEDAOBgNVBAsTB3JzeXNsb2cxEDAOBgNVBAoTB1NvbWVPcmcx
+CzAJBgNVBAYTAlVTMB4XDTE4MTIxMjE1MjUyMloXDTE4MTIxMzE1MjUyM1owdjEL
+MAkGA1UEAxMCVVMxEDAOBgNVBAsTB1NvbWVPcmgxDzANBgNVBAoTBlNvbWVPVTES
+MBAGA1UEBxMJU29tZXdoZXJlMQswCQYDVQQGEwJDQTEjMCEGCgmSJomT8ixkARkW
+E21hY2hpbmUuZXhhbXBsZS5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC24qsJF2yax7Ja4xsPQ7lDtkEMx3ni6k0xh7VrzZiRFpegdz1CVerV8bAs
+voTzn1aTWE1lELRO7i4QTAU2sn/kyB34oNuQWd8R1D7J3FJsIE36RM15XmcQ4biX
+H6m9Kx5uEAfdHVSPLgwuQlQM6IshmxV5AS+QrqLK7scZCFpBEb379G4JeJJGdkXR
+p7VYXUo079YSA60TqhWH01dlJdvRmY6sBpYahAOag3f3d7L8eYd9Jv3S6pHxzf/5
+/TqMbYr7m4iPH+cXg/sDNMll66rax9Ei2dk/Za1GKQ1AUvlfto0qKaRg/2FUKhqP
+DGV5uJDbYxlZjD+2s8HSrlSPS70FAgMBAAGjgYAwfjAMBgNVHRMBAf8EAjAAMB0G
+A1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB6AAMB0G
+A1UdDgQWBBTKFNJvJb22tIrAxnqkVRDvFqukcTAfBgNVHSMEGDAWgBSwn2czLIiI
+iR9EYnSdJf/ABhNd1jANBgkqhkiG9w0BAQsFAAOCAYEAXV+3oTx+/LEL8yHUbRS2
+wQ+kuXuuGJT4nkOFD+m5vNWtM1jGoj1trV/MxC697JlKB4wmBebKvIXcdKTVy2CB
+MqPoKTHSJ4vqfAWYAP9i0nNrxcvi0mHVxlRqPnizPLUkcPCYvnPtnSOCELmWk0mC
+i9K2QUy9e9HulRayaVU8KdPwopy6aJJQyl981T/h/m+q0FcKOIC27nn0VW0ZGHtl
+1PnUTVOP479HNhMg6zmPKxV0Y/WVQDB0Cpok3uuo0V1I9BuQk7Rn6DQqSnNI7/vH
+Ot/5fPEk/SU4OitCH7yV8XnkrPfAhpPrsUrVUd54PQg/KZu9qVTfMAM+j55aDCs7
+HlfrkSB+Jv4YOdlgrSMnstG45WIAYGD32sCPog5F9mJl6BFREcgscQ1BF7Tr/LX2
+d8PaePwRfdHuRDsY4Ydq+F89cP23QNIlxf9r8ODe13v1mfCXpzxksZ8zhxEzPm46
+efGuPdwdb+u6ZRiOqoaAavV9raKCEX5CrvqKeDnZ66WA
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/client-expired-key.pem b/tests/testsuites/x.509/client-expired-key.pem
new file mode 100644
index 0000000..b53d6f3
--- /dev/null
+++ b/tests/testsuites/x.509/client-expired-key.pem
@@ -0,0 +1,134 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: Medium (2048 bits)
+
+modulus:
+ 00:b6:e2:ab:09:17:6c:9a:c7:b2:5a:e3:1b:0f:43:b9
+ 43:b6:41:0c:c7:79:e2:ea:4d:31:87:b5:6b:cd:98:91
+ 16:97:a0:77:3d:42:55:ea:d5:f1:b0:2c:be:84:f3:9f
+ 56:93:58:4d:65:10:b4:4e:ee:2e:10:4c:05:36:b2:7f
+ e4:c8:1d:f8:a0:db:90:59:df:11:d4:3e:c9:dc:52:6c
+ 20:4d:fa:44:cd:79:5e:67:10:e1:b8:97:1f:a9:bd:2b
+ 1e:6e:10:07:dd:1d:54:8f:2e:0c:2e:42:54:0c:e8:8b
+ 21:9b:15:79:01:2f:90:ae:a2:ca:ee:c7:19:08:5a:41
+ 11:bd:fb:f4:6e:09:78:92:46:76:45:d1:a7:b5:58:5d
+ 4a:34:ef:d6:12:03:ad:13:aa:15:87:d3:57:65:25:db
+ d1:99:8e:ac:06:96:1a:84:03:9a:83:77:f7:77:b2:fc
+ 79:87:7d:26:fd:d2:ea:91:f1:cd:ff:f9:fd:3a:8c:6d
+ 8a:fb:9b:88:8f:1f:e7:17:83:fb:03:34:c9:65:eb:aa
+ da:c7:d1:22:d9:d9:3f:65:ad:46:29:0d:40:52:f9:5f
+ b6:8d:2a:29:a4:60:ff:61:54:2a:1a:8f:0c:65:79:b8
+ 90:db:63:19:59:8c:3f:b6:b3:c1:d2:ae:54:8f:4b:bd
+ 05:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 43:a8:45:67:fe:9f:71:ff:50:af:28:f7:58:c5:50:23
+ 89:a8:35:07:12:c3:6c:b4:94:0f:45:81:95:34:cc:f0
+ 13:b6:0c:86:c0:24:b2:d4:e5:2d:ac:cf:ea:b5:8a:0b
+ e8:44:b1:95:23:01:e1:75:61:db:2b:94:7e:30:b8:f9
+ b5:42:c9:39:11:21:2c:ee:46:55:43:c9:3f:d5:ca:24
+ 85:54:81:e1:95:f5:e3:a1:2e:30:30:d0:48:e6:2f:ae
+ 79:3f:3a:f9:85:21:44:3a:df:cc:b9:43:08:e7:7a:99
+ 3b:1b:4d:81:af:cc:11:9f:2d:fd:f9:ef:fb:d4:0f:df
+ d4:fe:65:70:c9:d2:3c:08:7b:ad:d5:34:af:c6:13:cf
+ 15:b5:82:31:02:52:d2:73:a9:e5:d1:5f:67:c1:a5:72
+ e1:e4:4f:14:c6:fb:70:db:b8:43:ba:25:ea:4a:57:d6
+ 30:ec:e4:c0:8c:24:c5:83:d7:68:9b:96:e1:7c:57:1f
+ 4c:2f:e3:76:9b:bb:b8:e6:86:52:87:fe:d2:a3:b3:bd
+ 30:c0:0e:f6:d2:fe:6d:e9:5b:24:5c:f4:b8:ba:da:d4
+ 47:eb:d5:30:da:3b:1d:03:1f:ad:49:a2:05:34:f0:a1
+ a8:a2:08:e2:ed:ba:03:1c:60:4a:ea:fa:08:4c:88:5d
+
+
+prime1:
+ 00:ca:bc:76:2f:11:58:28:51:bf:a2:a0:23:43:b3:25
+ 1a:56:2c:2e:56:05:24:a7:4b:e0:75:d3:ba:e7:31:20
+ 2b:a2:fc:91:13:6b:b6:5b:c6:21:71:2d:6d:aa:d7:1f
+ b8:d9:86:ea:00:49:19:e7:d0:c1:2e:43:50:83:fd:b9
+ a3:1d:51:c7:ee:45:0b:a9:c0:26:70:da:a6:3b:ea:d8
+ 2f:dc:98:ce:f7:95:84:24:a3:d8:54:57:90:64:63:f3
+ f7:9f:75:02:d8:c7:4e:9f:7d:60:f3:dc:b1:83:bc:42
+ 08:ae:5f:ac:94:b1:74:bf:57:fc:96:0a:44:14:7b:f5
+ d3:
+
+prime2:
+ 00:e6:ef:17:e0:2d:ef:36:07:c3:c2:42:44:d0:fb:e6
+ d6:f5:7d:c4:5d:54:17:e0:ec:1d:6c:84:52:cf:90:a4
+ aa:a5:d0:7c:c6:e6:f0:56:aa:73:27:5c:c1:91:4d:d5
+ 60:7d:9c:a3:96:1a:cb:b1:e7:8e:cb:53:52:2e:35:53
+ 74:46:e9:ff:67:fb:93:5b:94:78:b0:0f:b9:a7:2f:08
+ fe:84:d3:f5:3e:f0:b7:02:a8:41:4e:9c:65:d7:f8:95
+ 7e:82:ef:5f:3c:60:12:2e:6f:3f:a8:df:b3:bf:3b:ed
+ ac:07:ef:0f:d7:35:c7:81:30:a2:18:05:14:72:6c:02
+ c7:
+
+coefficient:
+ 60:35:5f:cb:5b:40:75:b3:57:b8:61:d8:5a:40:c1:91
+ 01:3a:c1:17:35:94:4b:81:06:e9:75:56:8c:97:e3:bb
+ 5a:7d:f5:f1:ac:f8:6f:d0:a2:6c:89:a4:8a:0d:23:78
+ 8a:92:b6:3f:7c:42:00:65:c8:d7:b4:77:19:fd:2f:75
+ e8:99:c4:60:c5:48:f5:74:4d:09:63:a2:b5:cd:01:0e
+ 70:8d:69:03:f0:58:e6:7c:47:93:40:f3:53:9f:d5:97
+ 3a:13:2e:10:aa:17:77:74:67:82:2a:20:5b:fa:96:51
+ cf:58:c8:a4:c4:58:f4:5a:88:42:49:4a:ad:5c:6e:00
+
+
+exp1:
+ 57:8a:b7:91:ad:70:9e:c0:65:fa:88:21:92:1b:2a:1b
+ 4c:38:79:ad:a5:3c:e5:8c:8b:18:f5:db:4f:f7:53:87
+ e4:32:21:46:fc:8c:da:e6:1c:0c:ad:ec:1c:08:16:67
+ 90:6e:84:5e:a9:32:29:7a:67:e0:5d:2a:c8:43:e8:43
+ f9:e6:15:69:da:a0:a5:a5:16:34:47:05:de:fb:92:6c
+ 60:5a:0f:8c:b3:20:43:5e:08:8c:aa:de:eb:aa:89:6f
+ 54:88:87:39:2a:1e:d6:19:a2:a2:ca:9a:50:63:1b:34
+ 7a:6f:4f:ab:49:51:3b:4a:78:04:25:dc:ad:e7:b5:07
+
+
+exp2:
+ 19:ee:59:10:fc:37:73:2a:b6:09:97:25:61:0e:18:22
+ a5:18:45:37:71:9c:e8:cd:ba:94:17:db:b0:a0:fe:4c
+ 87:27:fd:0a:dc:9d:ba:2d:93:96:a4:ec:bb:63:31:05
+ 8f:b5:4a:0d:2d:df:17:8f:f7:d1:ce:fe:58:5f:f6:8a
+ 04:f8:7b:8c:72:8c:5e:69:32:90:1a:83:ef:48:f1:ca
+ 9a:a1:ae:55:2d:f4:6e:e0:f3:cc:5e:f5:74:a5:de:2b
+ 81:8a:5d:78:4b:15:5f:8f:70:67:87:0f:08:f7:32:bd
+ f1:7a:1f:9e:3b:d4:b6:25:fe:dd:91:9c:75:28:b9:bb
+
+
+
+Public Key PIN:
+ pin-sha256:ixzIAak4pRfFjtaG95FtWd+Iu8vB5m6nknYP5EGaAqg=
+Public Key ID:
+ sha256:8b1cc801a938a517c58ed686f7916d59df88bbcbc1e66ea792760fe4419a02a8
+ sha1:ca14d26f25bdb6b48ac0c67aa45510ef16aba471
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAtuKrCRdsmseyWuMbD0O5Q7ZBDMd54upNMYe1a82YkRaXoHc9
+QlXq1fGwLL6E859Wk1hNZRC0Tu4uEEwFNrJ/5Mgd+KDbkFnfEdQ+ydxSbCBN+kTN
+eV5nEOG4lx+pvSsebhAH3R1Ujy4MLkJUDOiLIZsVeQEvkK6iyu7HGQhaQRG9+/Ru
+CXiSRnZF0ae1WF1KNO/WEgOtE6oVh9NXZSXb0ZmOrAaWGoQDmoN393ey/HmHfSb9
+0uqR8c3/+f06jG2K+5uIjx/nF4P7AzTJZeuq2sfRItnZP2WtRikNQFL5X7aNKimk
+YP9hVCoajwxlebiQ22MZWYw/trPB0q5Uj0u9BQIDAQABAoIBAEOoRWf+n3H/UK8o
+91jFUCOJqDUHEsNstJQPRYGVNMzwE7YMhsAkstTlLazP6rWKC+hEsZUjAeF1Ydsr
+lH4wuPm1Qsk5ESEs7kZVQ8k/1cokhVSB4ZX146EuMDDQSOYvrnk/OvmFIUQ638y5
+Qwjnepk7G02Br8wRny39+e/71A/f1P5lcMnSPAh7rdU0r8YTzxW1gjECUtJzqeXR
+X2fBpXLh5E8Uxvtw27hDuiXqSlfWMOzkwIwkxYPXaJuW4XxXH0wv43abu7jmhlKH
+/tKjs70wwA720v5t6VskXPS4utrUR+vVMNo7HQMfrUmiBTTwoaiiCOLtugMcYErq
++ghMiF0CgYEAyrx2LxFYKFG/oqAjQ7MlGlYsLlYFJKdL4HXTuucxICui/JETa7Zb
+xiFxLW2q1x+42YbqAEkZ59DBLkNQg/25ox1Rx+5FC6nAJnDapjvq2C/cmM73lYQk
+o9hUV5BkY/P3n3UC2MdOn31g89yxg7xCCK5frJSxdL9X/JYKRBR79dMCgYEA5u8X
+4C3vNgfDwkJE0Pvm1vV9xF1UF+DsHWyEUs+QpKql0HzG5vBWqnMnXMGRTdVgfZyj
+lhrLseeOy1NSLjVTdEbp/2f7k1uUeLAPuacvCP6E0/U+8LcCqEFOnGXX+JV+gu9f
+PGASLm8/qN+zvzvtrAfvD9c1x4EwohgFFHJsAscCgYBXireRrXCewGX6iCGSGyob
+TDh5raU85YyLGPXbT/dTh+QyIUb8jNrmHAyt7BwIFmeQboReqTIpemfgXSrIQ+hD
++eYVadqgpaUWNEcF3vuSbGBaD4yzIENeCIyq3uuqiW9UiIc5Kh7WGaKiyppQYxs0
+em9Pq0lRO0p4BCXcree1BwKBgBnuWRD8N3MqtgmXJWEOGCKlGEU3cZzozbqUF9uw
+oP5Mhyf9Ctydui2TlqTsu2MxBY+1Sg0t3xeP99HO/lhf9ooE+HuMcoxeaTKQGoPv
+SPHKmqGuVS30buDzzF71dKXeK4GKXXhLFV+PcGeHDwj3Mr3xeh+eO9S2Jf7dkZx1
+KLm7AoGAYDVfy1tAdbNXuGHYWkDBkQE6wRc1lEuBBul1VoyX47taffXxrPhv0KJs
+iaSKDSN4ipK2P3xCAGXI17R3Gf0vdeiZxGDFSPV0TQljorXNAQ5wjWkD8FjmfEeT
+QPNTn9WXOhMuEKoXd3RngiogW/qWUc9YyKTEWPRaiEJJSq1cbgA=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/testsuites/x.509/client-key.pem b/tests/testsuites/x.509/client-key.pem
new file mode 100644
index 0000000..596fa27
--- /dev/null
+++ b/tests/testsuites/x.509/client-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:9d:91:da:d8:2e:3d:9d:ae:85:c3:c5:a7:f6:a4:66
+ f8:c8:91:91:b8:70:20:dc:ed:e8:23:ca:53:f7:b8:52
+ 43:f3:a7:eb:fb:df:8a:3b:2c:b0:13:fa:62:d3:a1:53
+ a4:51:71:1f:68:d9:fd:bc:39:4a:fb:c9:6a:df:f3:88
+ 84:b0:80:bc:c0:f5:1b:42:11:f6:4c:1a:d8:2c:62:0b
+ 5d:50:64:30:9a:d3:db:c1:d5:7f:39:53:e4:bd:e8:1e
+ 04:9d:c9:12:e0:e4:57:29:29:01:b9:f1:e5:bc:74:a6
+ e7:4b:61:e6:67:5c:6c:4e:ee:ee:22:0c:1b:14:6d:e8
+ 0c:6f:ee:ee:c3:b8:dd:df:15:ed:7a:96:5b:cc:85:e5
+ e3:50:c4:ce:2b:bf:b6:37:e6:20:fc:6e:45:7e:09:bd
+ 84:7a:af:07:27:f4:99:23:41:df:36:d8:29:31:a0:96
+ 84:2f:fd:45:2e:d4:b4:f9:fa:dc:8f:23:c0:e0:06:ad
+ ad:0a:72:da:f4:3b:a1:cb:d6:a6:3b:ec:46:c4:95:f2
+ 71:a5:ad:08:1f:e7:06:18:0e:db:80:51:96:ba:24:f6
+ 64:02:6b:d3:f0:76:01:34:3a:72:02:e9:cb:d0:aa:62
+ 51:0c:8f:83:be:c0:47:99:d2:92:72:ed:53:a5:49:05
+ d4:c9:a1:f4:4d:de:12:9d:1a:c8:17:84:f3:a2:7c:67
+ 47:82:4b:86:1e:73:86:e2:26:26:10:94:a3:99:9b:08
+ 99:78:9d:3d:33:5d:85:c2:46:65:94:ab:70:b4:3b:c1
+ 26:8b:11:b6:66:27:88:22:84:03:b5:08:45:32:8c:81
+ 23:be:62:dc:6f:a0:aa:5e:9f:03:f7:a7:f5:03:70:3c
+ 78:09:d0:84:44:8c:19:af:76:f7:93:fc:af:c6:fd:db
+ d9:4c:cb:20:79:44:71:cb:e6:55:61:a9:7a:af:0b:a3
+ a6:ed:e9:a9:11:af:fa:a3:5d:ac:97:e7:ef:2b:b6:a8
+ 37:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 60:cd:c5:dc:80:74:1c:56:a7:19:82:6a:51:6d:e9:51
+ 38:af:ae:0d:d8:dd:67:bd:c5:9b:8f:67:0c:ce:b1:c3
+ cb:82:c3:c9:27:29:9e:77:32:e9:e3:2f:2a:03:78:06
+ 80:7e:76:24:8d:a0:84:2d:d2:b2:63:a9:04:53:72:f0
+ ca:1b:1d:5b:92:7a:1f:9a:37:6d:c4:24:41:08:2f:21
+ 32:0d:8b:8a:e3:53:a4:7f:0c:bd:64:9c:28:4b:dd:7d
+ 4a:8e:c8:c9:5f:9f:68:cb:27:a3:5c:48:9f:02:2f:b3
+ f3:ac:fe:c7:4b:91:c2:e0:a9:6e:43:6f:b3:9a:5e:30
+ 9d:e7:f5:ca:4a:de:0c:7b:45:3d:c5:f8:39:eb:9d:33
+ 8d:60:8b:a5:77:0f:74:c2:2e:4b:c7:57:6c:3a:81:b3
+ 4d:48:10:a6:6c:70:54:a7:d8:81:b2:45:84:96:bb:42
+ 14:d5:8d:d6:5a:99:a0:e6:8c:f0:67:af:cc:32:6e:29
+ e5:4d:73:ec:4b:14:2e:a6:91:27:9e:d4:45:62:52:33
+ 66:94:c8:29:29:4d:bd:62:7b:f7:67:ed:26:02:33:f4
+ 70:79:43:ff:ec:0f:92:80:b2:a4:f0:a2:91:00:f9:0e
+ 51:22:53:f5:51:e2:97:e8:18:be:36:34:d2:c8:cd:0e
+ 3c:66:8e:2c:a8:4f:46:66:5e:01:4f:1e:03:6e:e0:63
+ d4:15:f5:28:59:e4:e0:47:df:57:20:d0:39:09:d8:65
+ 1c:3d:c9:2f:69:77:5c:4c:4f:90:ea:07:fc:51:0c:2b
+ 0c:f9:85:06:f8:08:04:37:86:45:ee:58:c9:4c:2b:ba
+ 00:bf:c2:a0:92:f7:c2:31:82:43:52:0f:63:4d:96:82
+ 1c:60:70:63:ac:72:db:ea:b8:4a:b3:a7:15:7a:c4:71
+ 4a:dd:7e:8b:40:b7:b1:78:7f:14:60:d1:89:cf:6a:41
+ 58:b5:cf:80:58:63:ad:fe:1f:15:bb:b2:10:db:07:41
+
+
+prime1:
+ 00:d0:04:9a:29:56:25:fd:9b:53:c0:a0:2f:ee:a8:49
+ b0:a3:f4:33:a7:f3:29:5f:63:2c:05:5e:75:16:b4:62
+ 2a:64:ea:e0:a6:64:aa:ce:aa:49:9d:10:1b:e5:56:c5
+ 60:a9:54:87:3b:f7:55:49:c0:58:65:fd:32:73:b3:e7
+ 79:ad:d4:49:27:b3:bd:0f:00:11:60:6a:c1:98:3b:71
+ c7:83:7c:59:a6:61:c5:29:da:4d:8a:e5:be:a7:76:71
+ ce:0d:2d:99:07:80:ac:df:42:29:6d:19:93:f2:5f:6d
+ 27:6d:31:db:2c:6a:38:ab:3e:39:db:5d:d6:b8:b7:34
+ eb:0b:9c:a7:7f:9d:52:75:4a:53:25:de:df:0f:64:18
+ 01:8b:b5:20:c3:7d:52:b3:1f:b8:95:0f:18:b3:ca:50
+ 5e:89:b7:ae:61:40:24:74:84:29:e1:9d:34:94:aa:f1
+ f2:d4:d8:ce:73:cd:ee:c1:c7:80:f1:75:60:2f:c8:6e
+ 21:
+
+prime2:
+ 00:c1:ea:4c:cf:a8:a0:55:cb:e0:82:81:ec:ba:f7:41
+ a0:33:27:e2:42:85:8f:94:51:c5:a2:07:23:19:ea:87
+ 87:af:4e:fc:11:9c:e8:d0:e6:83:8d:1d:e5:09:b3:e0
+ 30:13:92:23:37:27:bc:2c:90:09:e0:ff:31:27:1e:8a
+ 0c:fe:ca:d2:a1:d2:a4:74:ae:21:db:f7:63:7f:38:44
+ b9:97:59:9f:31:bf:55:80:97:fe:72:e6:6c:b0:1b:35
+ 3c:18:76:5a:53:75:16:da:f1:97:f7:29:39:e5:70:df
+ 1c:fc:91:0b:e8:3a:20:d3:b4:61:3a:c8:81:f2:6c:49
+ 1f:ba:07:cb:a8:0c:17:15:0f:8f:be:c7:5e:f3:0e:42
+ cb:1a:11:ec:3e:25:25:fc:ce:c0:dd:99:49:c7:10:1a
+ d1:7c:5f:ca:d2:f3:d2:6f:ad:4b:7b:92:8a:55:ce:dc
+ b7:dc:b8:1e:1e:e5:d7:93:85:9e:a0:58:53:6e:03:db
+ 57:
+
+coefficient:
+ 00:ce:59:bc:fc:f2:13:ba:d7:78:e2:d3:ec:10:28:ff
+ 9c:af:d1:8d:a0:d8:f3:ed:62:8d:15:b0:69:80:e8:ba
+ 8f:bc:34:ce:36:35:a1:16:18:f2:46:0f:64:a4:d6:3b
+ 5a:0c:0c:a0:2e:bf:c6:f2:75:1d:83:93:be:5c:14:8c
+ 02:32:84:7e:24:ea:7b:d3:52:74:1c:63:75:00:c1:04
+ 44:bf:76:e3:67:34:ce:fe:e5:c3:7c:f1:59:c3:48:4b
+ 2f:b2:24:60:0c:7e:e1:f7:b1:af:f5:07:ed:81:08:ac
+ 4c:e0:d3:98:c3:fb:20:24:5d:88:6c:2e:dd:4b:b9:9d
+ ef:56:76:42:83:22:95:e2:23:e4:5a:b5:08:f7:02:e5
+ b5:69:99:da:be:5f:1a:24:49:b4:5d:37:22:39:f6:23
+ ed:66:40:de:50:9e:f4:6d:38:41:75:46:14:a3:35:51
+ 2e:5e:84:db:1d:94:8c:df:47:83:02:cf:ec:21:4a:d5
+ 48:
+
+exp1:
+ 00:c3:aa:f0:8f:dd:77:12:dc:9e:a5:5c:88:79:c7:56
+ b9:8f:1f:4f:cf:b5:4c:bf:6a:fb:a7:79:38:4e:49:12
+ e5:a9:d3:bd:c9:06:7c:1c:b5:d5:54:a6:28:77:4b:6d
+ 92:04:f5:7b:d7:8e:49:6d:7c:3e:2a:81:46:89:cb:39
+ fb:1c:e5:c8:82:4d:f1:92:40:90:17:cf:93:96:ec:a3
+ 93:f6:3c:6b:df:b3:ab:d0:38:86:24:17:03:85:66:46
+ 9a:79:8e:e0:99:4c:12:50:57:5d:bc:40:09:08:3d:76
+ e1:55:37:46:60:ba:f1:df:32:43:1d:f3:60:dc:93:88
+ 75:67:90:cd:85:9e:a8:47:a7:c8:1a:a1:4f:d4:9c:64
+ 70:5f:c7:da:af:c8:1c:98:5d:48:34:fd:e4:50:8a:07
+ 9b:45:93:bf:b5:be:ae:0b:e3:9d:b9:99:34:32:7b:b1
+ e6:a7:0b:e0:f6:d1:48:ba:82:3c:e9:e3:6c:bc:c5:9d
+ c1:
+
+exp2:
+ 00:a4:7e:05:24:4e:0d:9c:59:f2:9b:a2:6c:d6:f8:b1
+ 41:9c:c3:63:6a:3c:73:dc:44:35:5a:c9:a5:1b:f1:d7
+ 7f:e0:d5:26:7c:26:57:54:05:86:68:29:88:c5:5f:41
+ 78:66:d1:9b:6f:c9:14:15:d5:25:9c:27:bd:61:4a:c5
+ 9e:5a:70:60:96:86:e1:9c:5c:ae:3a:32:b3:c3:12:4f
+ 32:03:d2:31:79:78:ad:a6:04:c9:02:5c:b6:ab:f8:98
+ 82:de:d9:5e:ab:d6:f2:49:4d:91:34:47:53:66:6f:05
+ c4:47:f7:1e:5b:a3:1b:7f:9a:4e:b4:17:ac:2b:a1:71
+ b2:29:13:3d:cd:d2:5b:ae:30:e2:25:da:67:8f:d4:74
+ 12:67:8d:f6:91:8c:df:99:81:25:17:95:55:81:38:07
+ 17:d6:e2:47:62:05:14:68:49:5f:73:76:8e:44:55:d2
+ e3:60:a7:0a:5d:f9:68:92:2a:51:b2:00:da:dc:c3:06
+ c7:
+
+
+Public Key PIN:
+ pin-sha256:aKORpr08YK1r+ZlFwE2Jr4IWb89uVOwdRatfTSZzcZ8=
+Public Key ID:
+ sha256:68a391a6bd3c60ad6bf99945c04d89af82166fcf6e54ec1d45ab5f4d2673719f
+ sha1:9417ae9d2157b87bc1ae107b08a921bca114008b
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG5QIBAAKCAYEAnZHa2C49na6Fw8Wn9qRm+MiRkbhwINzt6CPKU/e4UkPzp+v7
+34o7LLAT+mLToVOkUXEfaNn9vDlK+8lq3/OIhLCAvMD1G0IR9kwa2CxiC11QZDCa
+09vB1X85U+S96B4EnckS4ORXKSkBufHlvHSm50th5mdcbE7u7iIMGxRt6Axv7u7D
+uN3fFe16llvMheXjUMTOK7+2N+Yg/G5Ffgm9hHqvByf0mSNB3zbYKTGgloQv/UUu
+1LT5+tyPI8DgBq2tCnLa9Duhy9amO+xGxJXycaWtCB/nBhgO24BRlrok9mQCa9Pw
+dgE0OnIC6cvQqmJRDI+DvsBHmdKScu1TpUkF1Mmh9E3eEp0ayBeE86J8Z0eCS4Ye
+c4biJiYQlKOZmwiZeJ09M12FwkZllKtwtDvBJosRtmYniCKEA7UIRTKMgSO+Ytxv
+oKpenwP3p/UDcDx4CdCERIwZr3b3k/yvxv3b2UzLIHlEccvmVWGpeq8Lo6bt6akR
+r/qjXayX5+8rtqg3AgMBAAECggGAYM3F3IB0HFanGYJqUW3pUTivrg3Y3We9xZuP
+ZwzOscPLgsPJJymedzLp4y8qA3gGgH52JI2ghC3SsmOpBFNy8MobHVuSeh+aN23E
+JEEILyEyDYuK41Okfwy9ZJwoS919So7IyV+faMsno1xInwIvs/Os/sdLkcLgqW5D
+b7OaXjCd5/XKSt4Me0U9xfg5650zjWCLpXcPdMIuS8dXbDqBs01IEKZscFSn2IGy
+RYSWu0IU1Y3WWpmg5ozwZ6/MMm4p5U1z7EsULqaRJ57URWJSM2aUyCkpTb1ie/dn
+7SYCM/RweUP/7A+SgLKk8KKRAPkOUSJT9VHil+gYvjY00sjNDjxmjiyoT0ZmXgFP
+HgNu4GPUFfUoWeTgR99XINA5CdhlHD3JL2l3XExPkOoH/FEMKwz5hQb4CAQ3hkXu
+WMlMK7oAv8KgkvfCMYJDUg9jTZaCHGBwY6xy2+q4SrOnFXrEcUrdfotAt7F4fxRg
+0YnPakFYtc+AWGOt/h8Vu7IQ2wdBAoHBANAEmilWJf2bU8CgL+6oSbCj9DOn8ylf
+YywFXnUWtGIqZOrgpmSqzqpJnRAb5VbFYKlUhzv3VUnAWGX9MnOz53mt1Ekns70P
+ABFgasGYO3HHg3xZpmHFKdpNiuW+p3Zxzg0tmQeArN9CKW0Zk/JfbSdtMdssajir
+PjnbXda4tzTrC5ynf51SdUpTJd7fD2QYAYu1IMN9UrMfuJUPGLPKUF6Jt65hQCR0
+hCnhnTSUqvHy1NjOc83uwceA8XVgL8huIQKBwQDB6kzPqKBVy+CCgey690GgMyfi
+QoWPlFHFogcjGeqHh69O/BGc6NDmg40d5Qmz4DATkiM3J7wskAng/zEnHooM/srS
+odKkdK4h2/djfzhEuZdZnzG/VYCX/nLmbLAbNTwYdlpTdRba8Zf3KTnlcN8c/JEL
+6Dog07RhOsiB8mxJH7oHy6gMFxUPj77HXvMOQssaEew+JSX8zsDdmUnHEBrRfF/K
+0vPSb61Le5KKVc7ct9y4Hh7l15OFnqBYU24D21cCgcEAw6rwj913EtyepVyIecdW
+uY8fT8+1TL9q+6d5OE5JEuWp073JBnwctdVUpih3S22SBPV7145JbXw+KoFGics5
++xzlyIJN8ZJAkBfPk5bso5P2PGvfs6vQOIYkFwOFZkaaeY7gmUwSUFddvEAJCD12
+4VU3RmC68d8yQx3zYNyTiHVnkM2FnqhHp8gaoU/UnGRwX8far8gcmF1INP3kUIoH
+m0WTv7W+rgvjnbmZNDJ7seanC+D20Ui6gjzp42y8xZ3BAoHBAKR+BSRODZxZ8pui
+bNb4sUGcw2NqPHPcRDVayaUb8dd/4NUmfCZXVAWGaCmIxV9BeGbRm2/JFBXVJZwn
+vWFKxZ5acGCWhuGcXK46MrPDEk8yA9IxeXitpgTJAly2q/iYgt7ZXqvW8klNkTRH
+U2ZvBcRH9x5boxt/mk60F6wroXGyKRM9zdJbrjDiJdpnj9R0EmeN9pGM35mBJReV
+VYE4BxfW4kdiBRRoSV9zdo5EVdLjYKcKXflokipRsgDa3MMGxwKBwQDOWbz88hO6
+13ji0+wQKP+cr9GNoNjz7WKNFbBpgOi6j7w0zjY1oRYY8kYPZKTWO1oMDKAuv8by
+dR2Dk75cFIwCMoR+JOp701J0HGN1AMEERL9242c0zv7lw3zxWcNISy+yJGAMfuH3
+sa/1B+2BCKxM4NOYw/sgJF2IbC7dS7md71Z2QoMileIj5Fq1CPcC5bVpmdq+Xxok
+SbRdNyI59iPtZkDeUJ70bThBdUYUozVRLl6E2x2UjN9HgwLP7CFK1Ug=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/testsuites/x.509/client-new.csr b/tests/testsuites/x.509/client-new.csr
new file mode 100644
index 0000000..e7aeecf
--- /dev/null
+++ b/tests/testsuites/x.509/client-new.csr
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIID0DCCAjgCAQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UE
+BwwIU29tZUNpdHkxETAPBgNVBAoMCFNvbWVDb21wMREwDwYDVQQLDAhTb21lVW5p
+dDEQMA4GA1UEAwwHcnN5c2xvZzEjMCEGCSqGSIb3DQEJARYUYWxvcmJhY2hAYWRp
+c2Nvbi5jb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCdkdrYLj2d
+roXDxaf2pGb4yJGRuHAg3O3oI8pT97hSQ/On6/vfijsssBP6YtOhU6RRcR9o2f28
+OUr7yWrf84iEsIC8wPUbQhH2TBrYLGILXVBkMJrT28HVfzlT5L3oHgSdyRLg5Fcp
+KQG58eW8dKbnS2HmZ1xsTu7uIgwbFG3oDG/u7sO43d8V7XqWW8yF5eNQxM4rv7Y3
+5iD8bkV+Cb2Eeq8HJ/SZI0HfNtgpMaCWhC/9RS7UtPn63I8jwOAGra0Kctr0O6HL
+1qY77EbElfJxpa0IH+cGGA7bgFGWuiT2ZAJr0/B2ATQ6cgLpy9CqYlEMj4O+wEeZ
+0pJy7VOlSQXUyaH0Td4SnRrIF4TzonxnR4JLhh5zhuImJhCUo5mbCJl4nT0zXYXC
+RmWUq3C0O8EmixG2ZieIIoQDtQhFMoyBI75i3G+gql6fA/en9QNwPHgJ0IREjBmv
+dveT/K/G/dvZTMsgeURxy+ZVYal6rwujpu3pqRGv+qNdrJfn7yu2qDcCAwEAAaAA
+MA0GCSqGSIb3DQEBCwUAA4IBgQBhQ5VEn10CTlB6GSLwyHPfq5jAYaH+lUcIrN4C
+cOPCGs/GDB6erAED/KYlKOseD/KYNH5PguecuVnS7ZndfzN+nlukd8dE6qTe/fTG
+6zjPDhh7HuoVtjdh6tDqMUteBA8p7I3kSf/fmK2JYVp3nszYek8/RQoeBI7UZxEE
+Y2X2GvwOJK0FdqJUJS288rRh+aqGNJ23CFGUV36YJ/oBIS+0FQjyPIM9uEI/O1lf
+VLqlJ3uWKeb875QXey5IvgG7S37Wkf1IVEWxLXxv90Py515TsBeC4R8ttmo9jEUV
+l+ihbs+fxgCN6YD4/saVeXhso59IZFy/rVjq6vDYX4PW/T4kZMHjP+Zq/zRXul1S
+Ft0u25Pn4ffCtFuQ+lxLk5NID/uhSGznjFV/l4Q+uvQinNbFyoB/3VNQC1PvkSsg
+90BTYQSyn59un1R6wt4dkR51B+Hxk7uMlQIL/xY4PYTJrUBBk+ovbQG1wZGmla+X
+tZ1y+qWCh7Dh7NE6qulhdijgydE=
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/testsuites/x.509/client-revoked-key.pem b/tests/testsuites/x.509/client-revoked-key.pem
new file mode 100644
index 0000000..8806a6e
--- /dev/null
+++ b/tests/testsuites/x.509/client-revoked-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC//hRd6ZxsZxU8
+1EmdWyrqQ8K8ntA6XlUvaAArC9rcz/fZpxugozHdqAcTntw2dbg06hca9h3bMx5F
+NoCunJOmAk4m+AfeHM6e508l11kkSV40RFSHq+BtWiRBGb8zw6UR1lDA920tEgPM
+C7nqsoVdka2Ezr6bC8LrAZe4OtwcuNJD6JZe8ITimBh7FcavDLuOmJYhe81vDZ+E
+Wb+RqLpqybxfSvMSTTPn3LA46XHY79D9nh/QWrupOpHYHqee+qwTW6Ot6IcL9LX4
+qA2nsVlAJkJ6BeQxZvgF0f2XX66TCtlFbKPfMu4ReIMvujYXdpiD1gj7MQ6BfVeA
+EDzeDUsNAgMBAAECggEAQWSXJ02Ue8+4ihl8YV5WBajCwWAOaHMM7LKtq/vDtgYX
+00h5voMXTvoWPvaS5vG9pjg9Wm+Nx8VngAeKWO7300lhuSAt/dcuAS2j5a2trRBY
+R9EmQXenX1eelZXhbA4tQSAQLUmZJArIxE0SLABWMIKX6W5JuaGN6GGIfbV+l0E9
+RjQoj+k/XmlrUm11/KcRoL83JqL6wNuxi+AiHnFYEpaxdi/+U9RpVegiRzfS4OH7
+COOm+WEbjJSqyON4BRLGwEJaTcyFOozumyCRNnQIJJx7XW1m5RV+eowDdLcfbdma
+dqGDlPqKSwcr8kZhqXlmnOIgiuxUwGI6WhOjAMAOuQKBgQDe9QPX48Fvw5Yaenp4
+kvEU3lzb6JPYz07ECZ3yz7mfSbJmArj/nDqSiX1UdYInD2dMYw4gPdTX9iIMExXk
+dRTo72ipuNzC3w97GkLDHMKNlCnPrSIFWrh0JqQBI+uQOTXqp0kU25SMzp1AtDlW
+UhtXnt+FdKQDYwXyuFrYkfTnSwKBgQDcckTXY9YSfL4IauNG1mPsJM/+UvAmrKdp
+PDAi7ODVT0zq6h7kn30RUg+4Ebtyag9APdH9W8ta4kZVxID2/r5tY9bHxPAGD6Yd
+8cl0Bii6Rzd3NI5+xddqtZyz/A9PCPeKW3v0mLU16kemGq651bLHtwL5o6AEHXIn
+1T3U6d3oBwKBgQCfJU2FAPHGkVnHtL1O67RiLQcjgbRnAjM7A5JXC6d35+cLoc3j
+xuSYTMPFUcuBjiEyCVK/+OLA9NQAwm7SEDDIxHt1CpuqDgbC3E/jbdgBr0zZDMBI
+CiW34w0WM0mmPPAbeyVTWhmDGMhuszZqQ1l5BdKPNF8Oe9R3GNjf1e92WQKBgQCd
+I2cnEid6rijX3zl7OT+pCOSqqXw+VTxQq3K0sp3h79EocxLqbTW9rv09fIZdnHSa
+mnahX1mpwznX0WcMqbIcT9q+NAfUijsjhULQzcMiZbmH45Lfky9nBWZadgaDlCTA
+H05QoLorYIEKSmLaXRY/fplEUfqydDr3Ye3dY4em6QKBgQC0Heucqyw9THbnmHsr
+wIIb/L0eagI8BReJ+CWRAuhid0BmsRtIZf6mmdQl+vwrt4+O8PtCyJoeiI3qrht6
+SL65po9ERpSijV5lL6TS7VI22xNPtzd1Xf/ACg6/An/qSJeqYKn1DEqznSai8zXx
+PLz21hIcNxaxmTG34HMq+h4BGw==
+-----END PRIVATE KEY-----
diff --git a/tests/testsuites/x.509/client-revoked-valid.pem b/tests/testsuites/x.509/client-revoked-valid.pem
new file mode 100644
index 0000000..8bc2b8a
--- /dev/null
+++ b/tests/testsuites/x.509/client-revoked-valid.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3 (0x3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 13:38:06 2023 GMT
+ Not After : Jun 12 13:38:06 2123 GMT
+ Subject: C=DE, ST=NRW, O=Adiscon GmbH, OU=rsyslog, CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:fe:14:5d:e9:9c:6c:67:15:3c:d4:49:9d:5b:
+ 2a:ea:43:c2:bc:9e:d0:3a:5e:55:2f:68:00:2b:0b:
+ da:dc:cf:f7:d9:a7:1b:a0:a3:31:dd:a8:07:13:9e:
+ dc:36:75:b8:34:ea:17:1a:f6:1d:db:33:1e:45:36:
+ 80:ae:9c:93:a6:02:4e:26:f8:07:de:1c:ce:9e:e7:
+ 4f:25:d7:59:24:49:5e:34:44:54:87:ab:e0:6d:5a:
+ 24:41:19:bf:33:c3:a5:11:d6:50:c0:f7:6d:2d:12:
+ 03:cc:0b:b9:ea:b2:85:5d:91:ad:84:ce:be:9b:0b:
+ c2:eb:01:97:b8:3a:dc:1c:b8:d2:43:e8:96:5e:f0:
+ 84:e2:98:18:7b:15:c6:af:0c:bb:8e:98:96:21:7b:
+ cd:6f:0d:9f:84:59:bf:91:a8:ba:6a:c9:bc:5f:4a:
+ f3:12:4d:33:e7:dc:b0:38:e9:71:d8:ef:d0:fd:9e:
+ 1f:d0:5a:bb:a9:3a:91:d8:1e:a7:9e:fa:ac:13:5b:
+ a3:ad:e8:87:0b:f4:b5:f8:a8:0d:a7:b1:59:40:26:
+ 42:7a:05:e4:31:66:f8:05:d1:fd:97:5f:ae:93:0a:
+ d9:45:6c:a3:df:32:ee:11:78:83:2f:ba:36:17:76:
+ 98:83:d6:08:fb:31:0e:81:7d:57:80:10:3c:de:0d:
+ 4b:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 20:CE:A2:54:99:CF:22:9A:5C:BB:D4:1E:B0:1E:43:73:63:72:AA:DE
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 65:ac:7c:30:d0:01:ce:d7:ff:28:61:6c:8d:99:15:ce:45:22:
+ 8a:39:70:a4:a6:ce:48:94:e3:4b:8c:be:55:c4:66:96:49:49:
+ 4b:e0:4c:95:fd:73:02:54:3a:df:34:2f:96:16:48:ec:c2:23:
+ 3d:ee:b4:5a:dd:a0:c9:eb:85:f4:fd:e8:d5:8f:f3:dc:ce:4a:
+ 88:bb:be:19:81:3f:8b:0f:09:23:46:14:c9:f5:35:5a:cf:25:
+ 7c:92:df:b9:90:5d:ff:4f:21:40:9c:24:7c:0f:1f:3f:62:d1:
+ 7b:cc:40:7d:c6:61:49:f3:84:26:78:ed:87:70:06:9c:93:05:
+ a5:c4:7e:60:3d:d0:4a:2c:e4:d6:e5:33:f8:07:dd:5a:0e:9a:
+ 93:17:50:29:1a:ff:66:61:d9:40:a7:fb:cc:7b:62:b7:9d:29:
+ 1a:2a:3d:7b:93:87:eb:52:4e:00:19:19:3c:4d:73:fc:3d:ed:
+ eb:9d:92:30:bc:b0:ed:51:15:ce:b7:3c:00:09:0c:9d:6d:8b:
+ 2b:c9:f5:66:d4:49:44:58:3d:e7:61:3d:6b:21:05:ff:1d:55:
+ 59:dd:e4:a6:2f:e5:96:82:eb:24:33:2e:47:61:a5:f8:4d:ab:
+ ad:fc:64:f8:8b:9e:0e:62:8c:16:1d:79:18:74:18:9c:a2:19:
+ c3:24:0d:6e:45:63:f9:08:92:7d:44:0b:96:c7:48:84:72:97:
+ 22:23:bf:10:0a:d7:4e:43:8a:db:60:cd:5d:80:5e:71:fa:c2:
+ b6:68:10:ee:cc:29:86:15:d3:d9:93:2a:cc:73:88:be:9f:ad:
+ d0:c5:9c:a4:e4:86:38:e7:41:84:3a:d0:f3:67:1f:2c:40:d7:
+ 04:b1:ea:32:13:49:a5:82:1a:a5:6c:3f:5f:dc:fd:55:14:03:
+ 8b:d7:bd:01:9e:bc:c5:e4:a1:a8:a8:9d:bc:cd:1f:5b:fc:df:
+ 59:b7:0d:aa:47:a0:08:cd:6e:f7:c8:9d:d3:dd:4e:8b:aa:cc:
+ 54:20:a0:2b:63:96
+-----BEGIN CERTIFICATE-----
+MIIEUTCCArmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTMzODA2WhgPMjEyMzA2MTIxMzM4MDZaMIGUMQswCQYD
+VQQGEwJERTEMMAoGA1UECAwDTlJXMRUwEwYDVQQKDAxBZGlzY29uIEdtYkgxEDAO
+BgNVBAsMB3JzeXNsb2cxKTAnBgNVBAMMIHJzeXNsb2cgcmV2b2tlZCBjZXJ0aWZp
+Y2F0ZSB0ZXN0MSMwIQYJKoZIhvcNAQkBFhRhbG9yYmFjaEBhZGlzY29uLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/+FF3pnGxnFTzUSZ1bKupD
+wrye0DpeVS9oACsL2tzP99mnG6CjMd2oBxOe3DZ1uDTqFxr2HdszHkU2gK6ck6YC
+Tib4B94czp7nTyXXWSRJXjREVIer4G1aJEEZvzPDpRHWUMD3bS0SA8wLueqyhV2R
+rYTOvpsLwusBl7g63By40kPoll7whOKYGHsVxq8Mu46YliF7zW8Nn4RZv5GoumrJ
+vF9K8xJNM+fcsDjpcdjv0P2eH9Bau6k6kdgep576rBNbo63ohwv0tfioDaexWUAm
+QnoF5DFm+AXR/ZdfrpMK2UVso98y7hF4gy+6Nhd2mIPWCPsxDoF9V4AQPN4NSw0C
+AwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCDOolSZzyKaXLvUHrAeQ3Njcqre
+MB8GA1UdIwQYMBaAFLCfZzMsiIiJH0RidJ0l/8AGE13WMA0GCSqGSIb3DQEBCwUA
+A4IBgQBlrHww0AHO1/8oYWyNmRXORSKKOXCkps5IlONLjL5VxGaWSUlL4EyV/XMC
+VDrfNC+WFkjswiM97rRa3aDJ64X0/ejVj/PczkqIu74ZgT+LDwkjRhTJ9TVazyV8
+kt+5kF3/TyFAnCR8Dx8/YtF7zEB9xmFJ84QmeO2HcAackwWlxH5gPdBKLOTW5TP4
+B91aDpqTF1ApGv9mYdlAp/vMe2K3nSkaKj17k4frUk4AGRk8TXP8Pe3rnZIwvLDt
+URXOtzwACQydbYsryfVm1ElEWD3nYT1rIQX/HVVZ3eSmL+WWguskMy5HYaX4Taut
+/GT4i54OYowWHXkYdBicohnDJA1uRWP5CJJ9RAuWx0iEcpciI78QCtdOQ4rbYM1d
+gF5x+sK2aBDuzCmGFdPZkyrMc4i+n63QxZyk5IY450GEOtDzZx8sQNcEseoyE0ml
+ghqlbD9f3P1VFAOL170BnrzF5KGoqJ28zR9b/N9Ztw2qR6AIzW73yJ3T3U6LqsxU
+IKArY5Y=
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/client-revoked.csr b/tests/testsuites/x.509/client-revoked.csr
new file mode 100644
index 0000000..bc99a28
--- /dev/null
+++ b/tests/testsuites/x.509/client-revoked.csr
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIC9DCCAdwCAQAwga4xCzAJBgNVBAYTAkRFMQwwCgYDVQQIDANOUlcxGDAWBgNV
+BAcMD0dyb3NzcmluZGVyZmVsZDEVMBMGA1UECgwMQWRpc2NvbiBHbWJIMRAwDgYD
+VQQLDAdyc3lzbG9nMSkwJwYDVQQDDCByc3lzbG9nIHJldm9rZWQgY2VydGlmaWNh
+dGUgdGVzdDEjMCEGCSqGSIb3DQEJARYUYWxvcmJhY2hAYWRpc2Nvbi5jb20wggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC//hRd6ZxsZxU81EmdWyrqQ8K8
+ntA6XlUvaAArC9rcz/fZpxugozHdqAcTntw2dbg06hca9h3bMx5FNoCunJOmAk4m
++AfeHM6e508l11kkSV40RFSHq+BtWiRBGb8zw6UR1lDA920tEgPMC7nqsoVdka2E
+zr6bC8LrAZe4OtwcuNJD6JZe8ITimBh7FcavDLuOmJYhe81vDZ+EWb+RqLpqybxf
+SvMSTTPn3LA46XHY79D9nh/QWrupOpHYHqee+qwTW6Ot6IcL9LX4qA2nsVlAJkJ6
+BeQxZvgF0f2XX66TCtlFbKPfMu4ReIMvujYXdpiD1gj7MQ6BfVeAEDzeDUsNAgMB
+AAGgADANBgkqhkiG9w0BAQsFAAOCAQEASfTlG7UDUb9bgIerIn2kUYTFxZOnvy/M
+cfDM/iH5m3v7IjHV61mI7x7/P+COG6E9MOSS4+VLFjfc8YlQ67zkyrZxa4LMBqUF
+i+oOvTGvTO4ocBlHcoZ53EE5q3sy/yu67ih8jlTbCjtJ6mUOdXDclJimwKir4e+b
+GPpOvLENDfJ5RShJL5cdGXJqv+ZYuZnh4+zq8h4+EQI1BSzPudomSE6d+gf6Ysyg
+lb1YvhlP2phApgHS+3QeLLW8rTgPheFJcQbg6Sc+m44jysqjOVKc0+RYCdhqI7a7
+Dk/V/eD1VFOoRrIY2WnpvzE39gpV1fl4bUrrcsMCIBe7F2svdFHMog==
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/testsuites/x.509/client-revoked.pem b/tests/testsuites/x.509/client-revoked.pem
new file mode 100644
index 0000000..b64b2a9
--- /dev/null
+++ b/tests/testsuites/x.509/client-revoked.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 12:59:25 2023 GMT
+ Not After : Jun 12 12:59:25 2123 GMT
+ Subject: C=DE, ST=NRW, O=Adiscon GmbH, OU=rsyslog, CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:fe:14:5d:e9:9c:6c:67:15:3c:d4:49:9d:5b:
+ 2a:ea:43:c2:bc:9e:d0:3a:5e:55:2f:68:00:2b:0b:
+ da:dc:cf:f7:d9:a7:1b:a0:a3:31:dd:a8:07:13:9e:
+ dc:36:75:b8:34:ea:17:1a:f6:1d:db:33:1e:45:36:
+ 80:ae:9c:93:a6:02:4e:26:f8:07:de:1c:ce:9e:e7:
+ 4f:25:d7:59:24:49:5e:34:44:54:87:ab:e0:6d:5a:
+ 24:41:19:bf:33:c3:a5:11:d6:50:c0:f7:6d:2d:12:
+ 03:cc:0b:b9:ea:b2:85:5d:91:ad:84:ce:be:9b:0b:
+ c2:eb:01:97:b8:3a:dc:1c:b8:d2:43:e8:96:5e:f0:
+ 84:e2:98:18:7b:15:c6:af:0c:bb:8e:98:96:21:7b:
+ cd:6f:0d:9f:84:59:bf:91:a8:ba:6a:c9:bc:5f:4a:
+ f3:12:4d:33:e7:dc:b0:38:e9:71:d8:ef:d0:fd:9e:
+ 1f:d0:5a:bb:a9:3a:91:d8:1e:a7:9e:fa:ac:13:5b:
+ a3:ad:e8:87:0b:f4:b5:f8:a8:0d:a7:b1:59:40:26:
+ 42:7a:05:e4:31:66:f8:05:d1:fd:97:5f:ae:93:0a:
+ d9:45:6c:a3:df:32:ee:11:78:83:2f:ba:36:17:76:
+ 98:83:d6:08:fb:31:0e:81:7d:57:80:10:3c:de:0d:
+ 4b:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 20:CE:A2:54:99:CF:22:9A:5C:BB:D4:1E:B0:1E:43:73:63:72:AA:DE
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 33:65:28:98:94:9b:f5:57:0d:bf:02:c2:67:93:8e:8e:77:03:
+ 9b:c7:7a:47:53:29:a4:dd:a6:a1:5e:2a:0a:ed:19:02:80:90:
+ b3:97:1f:06:4c:9c:c5:5f:6c:16:f9:12:fb:dd:da:29:88:b7:
+ 2c:91:0b:ab:53:79:7a:6e:76:20:fe:fa:b1:99:c2:2b:50:26:
+ 7b:cc:8c:75:98:35:95:79:56:43:90:a0:95:5e:98:09:10:4d:
+ ea:c0:1c:bb:c0:7b:a7:8a:9b:21:70:85:65:83:4d:ee:65:ef:
+ 10:d3:63:95:fd:51:9d:6c:41:7b:af:af:9c:e7:34:74:a1:7a:
+ 86:0a:8e:f2:2a:06:68:77:76:fa:fc:64:bc:28:1d:8b:53:7a:
+ cf:62:0f:87:a9:85:54:8c:a5:41:c3:61:0b:cf:96:c1:fa:81:
+ a5:31:63:f3:cb:17:37:58:6e:d9:30:97:fb:57:2f:31:63:e8:
+ 26:0e:82:49:e2:a9:9b:ed:39:7b:24:4e:42:8d:34:74:3a:dc:
+ b7:c5:d6:15:e9:66:28:2d:3c:e0:26:44:76:66:4a:32:94:11:
+ c8:1f:1c:b2:dc:44:69:63:f7:2d:87:b5:89:4a:40:fb:e4:14:
+ 68:dc:8a:76:40:93:35:e2:ac:9a:4b:bc:af:c5:8a:8a:38:54:
+ ef:69:01:4c:92:af:c0:07:d0:2f:7a:3c:9e:40:ac:56:07:d0:
+ 2b:1f:5f:d0:44:f9:70:e1:44:44:34:ba:fb:3d:54:85:4b:1d:
+ ba:ea:ea:6a:91:0c:08:30:2d:bc:b8:ea:22:c1:16:7b:53:fe:
+ 40:2c:8d:f5:c6:c2:39:e6:11:1d:e2:2f:50:a6:76:9c:fd:b9:
+ fa:d5:10:79:0e:e5:02:87:7d:96:e3:81:05:79:c9:a3:d8:f2:
+ a0:b1:8b:0e:8d:33:73:15:6f:27:88:85:03:8a:c5:7a:77:f4:
+ 3f:7f:b8:65:97:5b:a0:a6:21:48:67:2c:a2:73:a2:ec:d6:6a:
+ bd:d6:f2:e2:b1:5b
+-----BEGIN CERTIFICATE-----
+MIIEUTCCArmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTI1OTI1WhgPMjEyMzA2MTIxMjU5MjVaMIGUMQswCQYD
+VQQGEwJERTEMMAoGA1UECAwDTlJXMRUwEwYDVQQKDAxBZGlzY29uIEdtYkgxEDAO
+BgNVBAsMB3JzeXNsb2cxKTAnBgNVBAMMIHJzeXNsb2cgcmV2b2tlZCBjZXJ0aWZp
+Y2F0ZSB0ZXN0MSMwIQYJKoZIhvcNAQkBFhRhbG9yYmFjaEBhZGlzY29uLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/+FF3pnGxnFTzUSZ1bKupD
+wrye0DpeVS9oACsL2tzP99mnG6CjMd2oBxOe3DZ1uDTqFxr2HdszHkU2gK6ck6YC
+Tib4B94czp7nTyXXWSRJXjREVIer4G1aJEEZvzPDpRHWUMD3bS0SA8wLueqyhV2R
+rYTOvpsLwusBl7g63By40kPoll7whOKYGHsVxq8Mu46YliF7zW8Nn4RZv5GoumrJ
+vF9K8xJNM+fcsDjpcdjv0P2eH9Bau6k6kdgep576rBNbo63ohwv0tfioDaexWUAm
+QnoF5DFm+AXR/ZdfrpMK2UVso98y7hF4gy+6Nhd2mIPWCPsxDoF9V4AQPN4NSw0C
+AwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCDOolSZzyKaXLvUHrAeQ3Njcqre
+MB8GA1UdIwQYMBaAFLCfZzMsiIiJH0RidJ0l/8AGE13WMA0GCSqGSIb3DQEBCwUA
+A4IBgQAzZSiYlJv1Vw2/AsJnk46OdwObx3pHUymk3aahXioK7RkCgJCzlx8GTJzF
+X2wW+RL73dopiLcskQurU3l6bnYg/vqxmcIrUCZ7zIx1mDWVeVZDkKCVXpgJEE3q
+wBy7wHunipshcIVlg03uZe8Q02OV/VGdbEF7r6+c5zR0oXqGCo7yKgZod3b6/GS8
+KB2LU3rPYg+HqYVUjKVBw2ELz5bB+oGlMWPzyxc3WG7ZMJf7Vy8xY+gmDoJJ4qmb
+7Tl7JE5CjTR0Oty3xdYV6WYoLTzgJkR2ZkoylBHIHxyy3ERpY/cth7WJSkD75BRo
+3Ip2QJM14qyaS7yvxYqKOFTvaQFMkq/AB9AvejyeQKxWB9ArH1/QRPlw4URENLr7
+PVSFSx266upqkQwIMC28uOoiwRZ7U/5ALI31xsI55hEd4i9Qpnac/bn61RB5DuUC
+h32W44EFecmj2PKgsYsOjTNzFW8niIUDisV6d/Q/f7hll1ugpiFIZyyic6Ls1mq9
+1vLisVs=
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/crl.pem b/tests/testsuites/x.509/crl.pem
new file mode 100644
index 0000000..23a1a83
--- /dev/null
+++ b/tests/testsuites/x.509/crl.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICIjCBizANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21lTmFtZTEQMA4G
+A1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UEBhMCVVMXDTIz
+MDcxMTA3NTEyM1oYDzIxMjMwNjE3MDc1MTIzWjAUMBICAQIXDTIzMDcwNjEzMDEw
+MFowDQYJKoZIhvcNAQELBQADggGBAA4MRtKKvN+qIIULqf80EG3Zy+6BhPc+4GGD
+bB6tHzBf/G+S931yxQB6yXgoHv9SdR0ZDj28gGG0c6YBYiBID6MecRreEZkBzbNg
+3YsLpAQsE9ZO6pBancjbkhg3ikdACBaWrsQLFaVsZCGyAJN5kL0jzE/aoGmvKLpQ
+NXmQo3+/IuJ+jes/vEcG6LyCyr0LKbbFNdj/VsF7KIRjY2BP995rz/X6mWoS8fP0
+hIE3G4NC+BeWBAi/txwlkxl8AXsQW+AZNCFR9/9k1LIBE/5MY4rEn60PoR4QIqja
+cKdEkhvkBM8gNkthKplA1wfDMXzhXilwW4uRjF//Oiz97rBg4JYkNw1hEsK97SPT
+E2dtXZ2I0mBR32twVRvRdp14VHGo/EHPnTPBwJZSuiKPCQjGX61xzJdHfu1oGpW+
+E3R4AWlfzpUnCeA3uERsukJbdJmgPYz4tkfSil2//9wHLxuJHokl3wrQ87Rt+YDB
+CnYqvamCfmQQeXp1waXOE94lTLV0RA==
+-----END X509 CRL-----
diff --git a/tests/testsuites/x.509/index.txt b/tests/testsuites/x.509/index.txt
new file mode 100644
index 0000000..ee97457
--- /dev/null
+++ b/tests/testsuites/x.509/index.txt
@@ -0,0 +1,3 @@
+R 21230612125925Z 230706130100Z 02 unknown /C=DE/ST=NRW/O=Adiscon GmbH/OU=rsyslog/CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+V 21230612133806Z 03 unknown /C=DE/ST=NRW/O=Adiscon GmbH/OU=rsyslog/CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+V 21230612135250Z 04 unknown /C=US/ST=CA/O=SomeComp/OU=SomeUnit/CN=rsyslog/emailAddress=alorbach@adiscon.com
diff --git a/tests/testsuites/x.509/index.txt.attr b/tests/testsuites/x.509/index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/tests/testsuites/x.509/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/tests/testsuites/x.509/machine-cert.pem b/tests/testsuites/x.509/machine-cert.pem
new file mode 100644
index 0000000..def6e7e
--- /dev/null
+++ b/tests/testsuites/x.509/machine-cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEmjCCAwKgAwIBAgIIXBegQDWsgowwDQYJKoZIhvcNAQELBQAwRDERMA8GA1UE
+AxMIc29tZU5hbWUxEDAOBgNVBAsTB3JzeXNsb2cxEDAOBgNVBAoTB1NvbWVPcmcx
+CzAJBgNVBAYTAlVTMCAXDTE4MTIxNzEzMTAyNloYDzIxMTgxMTIzMTMxMDI4WjBR
+MQ8wDQYDVQQLEwZTb21lT1UxEDAOBgNVBAoTB1NvbWVPcmcxEjAQBgNVBAcTCVNv
+bWV3aGVyZTELMAkGA1UECBMCQ0ExCzAJBgNVBAYTAlVTMIIBojANBgkqhkiG9w0B
+AQEFAAOCAY8AMIIBigKCAYEAvYhZDSdPcxBgjF+sgQZ10YPuIXIzoiq4G943OGFX
+EdMc0kdaVQcCKkR4raPMR0wKs57akpiN5CrU1HvkwYZbTNB/BpyhUuZnx2qjTRyO
+pB71k62z7HP3KAI/GYfEMX5DNPS0X3B7chkAT4Sk1Xdn3WjW3BVt3GK4XdWmG2M0
+cmsYaFvijFJDi6Fs8fy/5sG2x+WBwct1Kt8HnjfR+nh00YhgiqOdX1jOrDN29XHk
+n4GIEm/BRQRQ0/PoOa6VWGVVxu+8sfmM7IJ8kC5/QII3PFZCplqPnxFYd3C0Wa6v
+au+tYisJ9B5CB/fn9ars7H6nFMc1D38G/sVkspdJrFuFbQLElkH7ydxBZBv3O+fl
+Iomav/+JL1PiNHFtXxoGsTOPHHFKbqauxLuTbv9B5D1tO/MaxOBTt9MVMx8rDpVB
+y0spKhfWcxJ/0Hge7G9XrFGpN4joBPHPMghM8QjS9/EL8r98m8PNQk6OIG9TNeQC
+gzglQIV3K+rhFwTeeyetxDozAgMBAAGjgYAwfjAMBgNVHRMBAf8EAjAAMB0GA1Ud
+JQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB6AAMB0GA1Ud
+DgQWBBQ3rDq/2kYOFskMD0lHFG+g2Ej/2zAfBgNVHSMEGDAWgBSwn2czLIiIiR9E
+YnSdJf/ABhNd1jANBgkqhkiG9w0BAQsFAAOCAYEARbJDuWZiqwA/CU9Eh99POTOk
+fnWdog8tLaOPLFS5mCiLNDmTXX14syAAjhbRrJ+43j1HWXbgovzDqzFtQzbztCMB
+qpxQy3d3R9nUKv6NpNT/IO84OcYuiMtRGr/AaVqc2PZlFirBqlQkxFUxiDc2pIhy
+h2orOJrPu3jSQdWI1PDT6oWKCwHdU+obqh+NmRWwjetpmeJ5r/kgAlZJ1krlNPJU
+V3U/J9WTdOYMhLcn4RcNOTAyrmxOoTEIOcqkXzJOypbkMcZic+OHCaDohUsfdOkB
+Xxz+6nP4xqnOcyHBLNTjVVrnr+wyqsWA18HoyLiCluf946S6mVoXcxwvWHzz7VVm
+qHVppLVD/iOJxtl4bm8YEYjO4C1IPxWOCszG4N71Reyo/+p1UJ8Ww6IAgJj0jX2l
+L7pqCwZKXhd8+LT05dZr7YJV/EjmGV/pL6IU3RAk6s2BqgtTkvy5nnmSPjBFuxG/
+gUBfaglsXC6w6R1aMVr9m3E1ht4vOPu9Qx7E21oG
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/machine-key.pem b/tests/testsuites/x.509/machine-key.pem
new file mode 100644
index 0000000..2958202
--- /dev/null
+++ b/tests/testsuites/x.509/machine-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:bd:88:59:0d:27:4f:73:10:60:8c:5f:ac:81:06:75
+ d1:83:ee:21:72:33:a2:2a:b8:1b:de:37:38:61:57:11
+ d3:1c:d2:47:5a:55:07:02:2a:44:78:ad:a3:cc:47:4c
+ 0a:b3:9e:da:92:98:8d:e4:2a:d4:d4:7b:e4:c1:86:5b
+ 4c:d0:7f:06:9c:a1:52:e6:67:c7:6a:a3:4d:1c:8e:a4
+ 1e:f5:93:ad:b3:ec:73:f7:28:02:3f:19:87:c4:31:7e
+ 43:34:f4:b4:5f:70:7b:72:19:00:4f:84:a4:d5:77:67
+ dd:68:d6:dc:15:6d:dc:62:b8:5d:d5:a6:1b:63:34:72
+ 6b:18:68:5b:e2:8c:52:43:8b:a1:6c:f1:fc:bf:e6:c1
+ b6:c7:e5:81:c1:cb:75:2a:df:07:9e:37:d1:fa:78:74
+ d1:88:60:8a:a3:9d:5f:58:ce:ac:33:76:f5:71:e4:9f
+ 81:88:12:6f:c1:45:04:50:d3:f3:e8:39:ae:95:58:65
+ 55:c6:ef:bc:b1:f9:8c:ec:82:7c:90:2e:7f:40:82:37
+ 3c:56:42:a6:5a:8f:9f:11:58:77:70:b4:59:ae:af:6a
+ ef:ad:62:2b:09:f4:1e:42:07:f7:e7:f5:aa:ec:ec:7e
+ a7:14:c7:35:0f:7f:06:fe:c5:64:b2:97:49:ac:5b:85
+ 6d:02:c4:96:41:fb:c9:dc:41:64:1b:f7:3b:e7:e5:22
+ 89:9a:bf:ff:89:2f:53:e2:34:71:6d:5f:1a:06:b1:33
+ 8f:1c:71:4a:6e:a6:ae:c4:bb:93:6e:ff:41:e4:3d:6d
+ 3b:f3:1a:c4:e0:53:b7:d3:15:33:1f:2b:0e:95:41:cb
+ 4b:29:2a:17:d6:73:12:7f:d0:78:1e:ec:6f:57:ac:51
+ a9:37:88:e8:04:f1:cf:32:08:4c:f1:08:d2:f7:f1:0b
+ f2:bf:7c:9b:c3:cd:42:4e:8e:20:6f:53:35:e4:02:83
+ 38:25:40:85:77:2b:ea:e1:17:04:de:7b:27:ad:c4:3a
+ 33:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 19:dd:b1:c9:89:c3:de:00:2e:2c:fa:21:a0:ba:30:fa
+ 16:f7:38:b9:4d:32:a4:81:db:cb:c7:dd:79:eb:58:13
+ 67:ab:8a:f1:59:09:4b:d2:58:e5:df:4c:ab:64:4f:8c
+ 66:57:17:9d:4a:14:93:3f:05:2c:ba:7b:cd:ad:78:68
+ 53:4c:02:aa:fd:99:42:b8:87:0e:96:9a:bf:7a:f8:0b
+ 01:98:d5:eb:e8:29:2b:61:da:6c:a2:1f:55:37:2b:f4
+ 20:16:05:47:c1:22:17:c0:31:ba:a8:6f:96:72:65:4a
+ 62:34:70:74:bc:39:87:7f:81:ce:d6:8c:86:4d:72:10
+ 0b:94:b2:75:88:90:f1:86:ec:d0:e1:75:8c:fb:01:14
+ e0:d3:01:92:61:21:ec:67:e3:b2:44:0b:f4:12:dc:5e
+ 7c:2e:30:bd:83:8c:af:a2:04:fe:41:0d:de:2d:45:57
+ 78:2a:8b:f5:e4:65:62:62:8a:b6:f6:a8:4c:d9:73:7a
+ b5:15:d0:91:c7:89:a9:45:94:00:0c:1d:69:f0:48:f7
+ 26:83:50:bd:b3:e7:7e:70:8b:21:bf:99:fd:04:d2:8a
+ d2:b1:be:9e:4b:a7:f1:57:8f:34:c0:b9:f0:22:d8:bf
+ 3f:fa:8c:77:47:7d:62:d4:5c:d8:08:1b:dd:3c:a2:c3
+ 60:25:84:be:02:a2:79:00:e4:06:c8:48:49:43:ac:9f
+ 45:78:c9:46:0a:9a:1f:5b:70:d1:da:b6:e6:f1:fc:af
+ a5:85:c6:7b:78:f0:5c:2c:91:1b:ba:36:62:f8:31:ed
+ 21:87:15:49:3c:c1:bf:53:a4:11:9a:19:91:51:aa:49
+ ea:d8:b3:a4:66:76:2a:ad:8e:61:38:f5:7a:ba:59:bb
+ 2e:48:f3:fc:14:a1:42:18:e7:c6:c6:41:03:d4:ca:d6
+ 85:14:cc:8b:1d:57:38:6f:ef:9e:14:34:85:38:92:ab
+ f8:24:f4:5b:14:6b:6a:3c:22:29:bb:36:51:68:43:81
+
+
+prime1:
+ 00:cd:49:91:cb:0a:37:19:fe:50:c0:9a:a0:c3:53:9b
+ fb:3c:e0:dc:2d:55:69:0e:cd:ea:e7:0c:a5:c1:34:a0
+ b5:8d:72:45:da:9c:56:15:8b:31:3f:fb:93:d7:b0:81
+ de:d1:9f:d8:c4:c1:ff:5a:d6:a8:15:c1:b6:c5:11:39
+ 4f:e9:16:06:fb:be:90:d4:a2:9d:23:0a:b3:52:81:07
+ d5:ae:2c:f5:bb:7e:32:62:59:f9:65:1f:ab:9b:3c:67
+ 94:b7:e2:49:69:3d:c6:98:e4:3e:56:f9:0f:02:e1:6c
+ c2:da:10:3b:9d:39:e7:55:40:6d:ae:46:f6:b8:cc:30
+ 2c:26:02:4f:65:a8:7c:38:47:9c:d8:96:ce:31:89:a4
+ 07:91:de:4d:46:35:b0:8e:01:fd:ca:11:c2:c8:8e:71
+ 32:eb:a0:61:da:10:db:8b:4d:ac:29:73:d2:b1:7c:d4
+ d3:0d:ce:a2:88:ef:3b:d0:b4:2b:50:1f:62:c8:e6:d2
+ 7d:
+
+prime2:
+ 00:ec:5a:71:35:ee:17:84:3a:0f:41:9b:44:e6:1e:f3
+ e2:c6:31:09:cd:d6:af:4d:6a:ac:fc:c1:03:40:67:91
+ 73:38:4e:a7:d1:2a:b9:25:a1:da:e9:77:9b:dd:e9:c2
+ 1a:72:0b:11:97:90:04:23:a7:4d:e3:ad:29:6b:65:c6
+ 63:8b:00:65:0a:7e:3d:46:b8:f7:4b:eb:a4:ee:cf:19
+ 3e:a0:52:80:72:e7:9f:9c:8b:b1:d0:0b:e3:9c:34:1e
+ d2:7c:ac:e2:c2:90:69:2b:78:9c:c1:9a:84:7a:5b:dc
+ 99:83:a0:18:22:fc:30:c6:7e:1e:97:de:bc:66:71:26
+ ec:f2:98:06:ce:62:53:d7:af:86:21:07:95:98:2c:2a
+ f4:4e:fe:58:a7:97:19:de:5a:4a:94:ee:98:d3:a0:77
+ 9e:db:52:55:64:a4:fa:84:c3:a8:89:8a:97:22:93:a6
+ f0:00:85:38:91:7a:52:98:2f:34:10:7e:92:9d:76:ae
+ 6f:
+
+coefficient:
+ 00:94:fa:06:8f:7e:8a:1d:be:16:55:80:93:01:0d:ab
+ 77:4b:d3:a5:14:37:ef:04:28:b3:91:d9:5f:df:e8:56
+ d5:1d:bd:c1:25:e8:bf:69:49:04:2f:c1:73:73:27:64
+ 66:3e:61:20:d5:25:db:ad:da:3d:e8:a3:a5:20:16:38
+ 6b:28:18:83:97:07:67:6a:16:4b:7f:2b:da:6a:a5:1b
+ ec:9a:c3:2a:4f:5d:9e:7e:9b:05:a5:a8:bb:ab:76:27
+ 1a:07:27:be:c8:65:94:e8:54:41:ba:1f:b3:91:5d:b1
+ 5a:13:2b:b3:11:60:52:26:47:35:a7:46:bd:16:f9:e5
+ 1e:4b:e9:48:33:aa:33:30:77:8e:71:e4:88:1c:1a:57
+ af:17:77:76:65:d2:2b:a3:33:b8:ec:34:f8:23:03:5b
+ 90:cb:eb:a4:c0:ee:98:0f:9c:5e:73:11:bd:9e:01:99
+ 79:4f:98:1e:12:25:62:88:3a:65:12:8f:67:45:40:af
+ 4b:
+
+exp1:
+ 30:f9:93:39:a0:47:43:01:44:1c:9f:07:29:72:41:ed
+ 2f:39:e9:ed:3a:ca:24:89:05:b8:77:70:f7:e5:e9:4d
+ 46:e0:73:3f:d3:3a:4a:4b:79:c5:6c:ec:79:71:97:9a
+ 23:e2:81:a1:77:32:c7:66:1c:95:8c:30:61:55:59:99
+ f1:de:9a:6d:e6:a9:c0:c0:c6:c2:3c:64:49:93:94:dd
+ ea:7e:b9:65:30:97:2e:95:8e:85:0c:88:31:31:b8:f8
+ 66:e2:2a:67:5c:20:8c:0b:2f:c0:2a:0c:e5:c0:07:e5
+ 78:86:94:e2:4e:95:1c:e6:91:04:19:d3:f4:84:6a:1d
+ ae:37:b0:df:6c:d1:ad:cf:8f:e0:b0:21:a2:f9:d6:53
+ 23:fe:a7:ea:cf:16:3e:da:c4:c4:37:76:83:c8:4f:c3
+ 39:29:7b:0e:be:24:d2:58:06:71:a1:3b:2b:b2:bf:47
+ 56:ac:ec:63:c4:c7:3d:64:2e:4d:20:1f:be:14:2b:35
+
+
+exp2:
+ 11:dd:bc:55:11:4c:61:c8:69:c2:d1:d3:e1:79:51:82
+ 40:ed:10:0a:a9:41:d3:1e:4f:39:43:f5:d4:f6:7f:3e
+ 30:71:71:aa:14:0a:ae:d7:8f:4e:ba:a5:e3:9e:79:f7
+ b9:cb:30:67:3e:91:b1:88:42:11:05:d3:ed:b4:61:cc
+ c0:83:25:20:27:ee:c5:db:d1:85:c1:a8:54:0c:ff:a1
+ 86:48:f6:40:b9:55:8d:65:d9:e9:1a:1c:f8:7f:d0:1c
+ a5:24:04:78:24:a6:6e:8c:cd:7c:ad:0b:7a:9c:5b:0e
+ 97:ae:90:64:84:9f:c3:41:61:5a:a5:91:a4:44:c5:66
+ 7f:e8:12:0b:a3:cf:26:ac:b3:fc:e7:2f:dd:b2:e9:04
+ 52:bc:53:43:47:de:c2:ba:1c:8d:29:84:0f:eb:3f:5f
+ 98:c0:9e:87:df:18:b8:d4:79:76:fc:2c:f4:86:28:c6
+ 57:a3:ba:64:f4:d4:2d:80:d3:f4:b3:3c:ad:fe:7c:ad
+
+
+
+Public Key PIN:
+ pin-sha256:P26XjPq8H830hYvKjSgxiVfBDOiZNDGexDfrJkKWi9o=
+Public Key ID:
+ sha256:3f6e978cfabc1fcdf4858bca8d28318957c10ce89934319ec437eb2642968bda
+ sha1:37ac3abfda460e16c90c0f4947146fa0d848ffdb
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEAvYhZDSdPcxBgjF+sgQZ10YPuIXIzoiq4G943OGFXEdMc0kda
+VQcCKkR4raPMR0wKs57akpiN5CrU1HvkwYZbTNB/BpyhUuZnx2qjTRyOpB71k62z
+7HP3KAI/GYfEMX5DNPS0X3B7chkAT4Sk1Xdn3WjW3BVt3GK4XdWmG2M0cmsYaFvi
+jFJDi6Fs8fy/5sG2x+WBwct1Kt8HnjfR+nh00YhgiqOdX1jOrDN29XHkn4GIEm/B
+RQRQ0/PoOa6VWGVVxu+8sfmM7IJ8kC5/QII3PFZCplqPnxFYd3C0Wa6vau+tYisJ
+9B5CB/fn9ars7H6nFMc1D38G/sVkspdJrFuFbQLElkH7ydxBZBv3O+flIomav/+J
+L1PiNHFtXxoGsTOPHHFKbqauxLuTbv9B5D1tO/MaxOBTt9MVMx8rDpVBy0spKhfW
+cxJ/0Hge7G9XrFGpN4joBPHPMghM8QjS9/EL8r98m8PNQk6OIG9TNeQCgzglQIV3
+K+rhFwTeeyetxDozAgMBAAECggGAGd2xyYnD3gAuLPohoLow+hb3OLlNMqSB28vH
+3XnrWBNnq4rxWQlL0ljl30yrZE+MZlcXnUoUkz8FLLp7za14aFNMAqr9mUK4hw6W
+mr96+AsBmNXr6CkrYdpsoh9VNyv0IBYFR8EiF8AxuqhvlnJlSmI0cHS8OYd/gc7W
+jIZNchALlLJ1iJDxhuzQ4XWM+wEU4NMBkmEh7GfjskQL9BLcXnwuML2DjK+iBP5B
+Dd4tRVd4Kov15GViYoq29qhM2XN6tRXQkceJqUWUAAwdafBI9yaDUL2z535wiyG/
+mf0E0orSsb6eS6fxV480wLnwIti/P/qMd0d9YtRc2Agb3Tyiw2AlhL4ConkA5AbI
+SElDrJ9FeMlGCpofW3DR2rbm8fyvpYXGe3jwXCyRG7o2Yvgx7SGHFUk8wb9TpBGa
+GZFRqknq2LOkZnYqrY5hOPV6ulm7Lkjz/BShQhjnxsZBA9TK1oUUzIsdVzhv754U
+NIU4kqv4JPRbFGtqPCIpuzZRaEOBAoHBAM1JkcsKNxn+UMCaoMNTm/s84NwtVWkO
+zernDKXBNKC1jXJF2pxWFYsxP/uT17CB3tGf2MTB/1rWqBXBtsUROU/pFgb7vpDU
+op0jCrNSgQfVriz1u34yYln5ZR+rmzxnlLfiSWk9xpjkPlb5DwLhbMLaEDudOedV
+QG2uRva4zDAsJgJPZah8OEec2JbOMYmkB5HeTUY1sI4B/coRwsiOcTLroGHaENuL
+Tawpc9KxfNTTDc6iiO870LQrUB9iyObSfQKBwQDsWnE17heEOg9Bm0TmHvPixjEJ
+zdavTWqs/MEDQGeRczhOp9EquSWh2ul3m93pwhpyCxGXkAQjp03jrSlrZcZjiwBl
+Cn49Rrj3S+uk7s8ZPqBSgHLnn5yLsdAL45w0HtJ8rOLCkGkreJzBmoR6W9yZg6AY
+Ivwwxn4el968ZnEm7PKYBs5iU9evhiEHlZgsKvRO/linlxneWkqU7pjToHee21JV
+ZKT6hMOoiYqXIpOm8ACFOJF6UpgvNBB+kp12rm8CgcAw+ZM5oEdDAUQcnwcpckHt
+Lznp7TrKJIkFuHdw9+XpTUbgcz/TOkpLecVs7Hlxl5oj4oGhdzLHZhyVjDBhVVmZ
+8d6abeapwMDGwjxkSZOU3ep+uWUwly6VjoUMiDExuPhm4ipnXCCMCy/AKgzlwAfl
+eIaU4k6VHOaRBBnT9IRqHa43sN9s0a3Pj+CwIaL51lMj/qfqzxY+2sTEN3aDyE/D
+OSl7Dr4k0lgGcaE7K7K/R1as7GPExz1kLk0gH74UKzUCgcAR3bxVEUxhyGnC0dPh
+eVGCQO0QCqlB0x5POUP11PZ/PjBxcaoUCq7Xj066peOeefe5yzBnPpGxiEIRBdPt
+tGHMwIMlICfuxdvRhcGoVAz/oYZI9kC5VY1l2ekaHPh/0BylJAR4JKZujM18rQt6
+nFsOl66QZISfw0FhWqWRpETFZn/oEgujzyass/znL92y6QRSvFNDR97CuhyNKYQP
+6z9fmMCeh98YuNR5dvws9IYoxlejumT01C2A0/SzPK3+fK0CgcEAlPoGj36KHb4W
+VYCTAQ2rd0vTpRQ37wQos5HZX9/oVtUdvcEl6L9pSQQvwXNzJ2RmPmEg1SXbrdo9
+6KOlIBY4aygYg5cHZ2oWS38r2mqlG+yawypPXZ5+mwWlqLurdicaBye+yGWU6FRB
+uh+zkV2xWhMrsxFgUiZHNadGvRb55R5L6UgzqjMwd45x5IgcGlevF3d2ZdIrozO4
+7DT4IwNbkMvrpMDumA+cXnMRvZ4BmXlPmB4SJWKIOmUSj2dFQK9L
+-----END RSA PRIVATE KEY-----
diff --git a/tests/testsuites/x.509/newcerts/01.pem b/tests/testsuites/x.509/newcerts/01.pem
new file mode 100644
index 0000000..b4bf169
--- /dev/null
+++ b/tests/testsuites/x.509/newcerts/01.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 12:57:29 2023 GMT
+ Not After : Jun 12 12:57:29 2123 GMT
+ Subject: C=DE, ST=NRW, O=Adiscon GmbH, OU=rsyslog, CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:fe:14:5d:e9:9c:6c:67:15:3c:d4:49:9d:5b:
+ 2a:ea:43:c2:bc:9e:d0:3a:5e:55:2f:68:00:2b:0b:
+ da:dc:cf:f7:d9:a7:1b:a0:a3:31:dd:a8:07:13:9e:
+ dc:36:75:b8:34:ea:17:1a:f6:1d:db:33:1e:45:36:
+ 80:ae:9c:93:a6:02:4e:26:f8:07:de:1c:ce:9e:e7:
+ 4f:25:d7:59:24:49:5e:34:44:54:87:ab:e0:6d:5a:
+ 24:41:19:bf:33:c3:a5:11:d6:50:c0:f7:6d:2d:12:
+ 03:cc:0b:b9:ea:b2:85:5d:91:ad:84:ce:be:9b:0b:
+ c2:eb:01:97:b8:3a:dc:1c:b8:d2:43:e8:96:5e:f0:
+ 84:e2:98:18:7b:15:c6:af:0c:bb:8e:98:96:21:7b:
+ cd:6f:0d:9f:84:59:bf:91:a8:ba:6a:c9:bc:5f:4a:
+ f3:12:4d:33:e7:dc:b0:38:e9:71:d8:ef:d0:fd:9e:
+ 1f:d0:5a:bb:a9:3a:91:d8:1e:a7:9e:fa:ac:13:5b:
+ a3:ad:e8:87:0b:f4:b5:f8:a8:0d:a7:b1:59:40:26:
+ 42:7a:05:e4:31:66:f8:05:d1:fd:97:5f:ae:93:0a:
+ d9:45:6c:a3:df:32:ee:11:78:83:2f:ba:36:17:76:
+ 98:83:d6:08:fb:31:0e:81:7d:57:80:10:3c:de:0d:
+ 4b:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 20:CE:A2:54:99:CF:22:9A:5C:BB:D4:1E:B0:1E:43:73:63:72:AA:DE
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 60:37:92:c5:17:64:ed:64:a3:28:c2:81:60:a2:20:ac:e4:2d:
+ ce:bd:4b:4c:6e:ea:70:a1:2c:2d:d9:1c:94:cb:d1:81:ca:53:
+ c2:51:24:af:da:af:90:11:98:52:da:25:2b:19:59:82:58:d6:
+ 84:a5:63:d4:89:05:a9:12:bf:5d:8b:c8:1f:27:b0:a7:65:7e:
+ 0c:18:b7:3d:4e:ec:c5:34:b3:d3:92:f7:de:e5:19:1b:b9:e8:
+ 47:a7:ca:22:13:c4:63:4f:44:09:70:e2:90:f3:a7:5e:e0:5d:
+ 9c:f7:be:ea:1e:88:e7:c2:d3:b6:35:6d:b0:3b:84:8f:03:94:
+ a8:c0:c1:ed:27:17:9a:4d:f7:33:23:1e:76:3a:63:38:f0:59:
+ 39:98:ce:89:4b:2a:89:0e:12:bf:25:b5:d6:04:20:88:f0:65:
+ 9d:70:90:67:e8:28:8e:09:fa:d9:ab:c9:a9:0f:28:63:10:bb:
+ 24:2d:44:2f:6b:fb:7c:d2:38:01:ab:d2:33:2d:50:f4:75:80:
+ 9e:4f:d2:26:6c:31:23:44:8e:d5:a3:51:56:cf:d9:38:f6:d0:
+ 84:c0:fb:6f:c1:66:9c:e7:dd:51:4f:42:bb:d7:cc:ba:35:e1:
+ c6:a2:5c:4b:f2:1e:b7:e2:52:a5:83:97:ab:42:09:54:04:ed:
+ 4f:01:2d:cf:ee:44:b4:da:39:5c:da:30:d5:92:b6:04:11:8b:
+ 04:d7:6a:3a:28:6e:54:97:97:99:a3:ba:3a:48:1a:17:ef:49:
+ 05:fd:c5:e6:3f:c1:7c:ac:b0:45:62:ff:15:fd:13:1b:04:ba:
+ 72:23:32:0a:b8:4d:39:9a:31:15:4c:0a:d0:ef:a2:82:8f:2e:
+ ad:3c:23:dd:59:12:08:6f:e0:5b:5e:5c:29:db:74:ff:8c:08:
+ 43:59:6a:a1:57:df:37:02:53:16:14:f7:c5:4b:47:61:1e:86:
+ aa:2d:46:4d:b3:85:8a:ac:c3:8c:b5:87:90:01:4c:33:91:96:
+ 38:95:06:a7:36:90
+-----BEGIN CERTIFICATE-----
+MIIEUTCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTI1NzI5WhgPMjEyMzA2MTIxMjU3MjlaMIGUMQswCQYD
+VQQGEwJERTEMMAoGA1UECAwDTlJXMRUwEwYDVQQKDAxBZGlzY29uIEdtYkgxEDAO
+BgNVBAsMB3JzeXNsb2cxKTAnBgNVBAMMIHJzeXNsb2cgcmV2b2tlZCBjZXJ0aWZp
+Y2F0ZSB0ZXN0MSMwIQYJKoZIhvcNAQkBFhRhbG9yYmFjaEBhZGlzY29uLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/+FF3pnGxnFTzUSZ1bKupD
+wrye0DpeVS9oACsL2tzP99mnG6CjMd2oBxOe3DZ1uDTqFxr2HdszHkU2gK6ck6YC
+Tib4B94czp7nTyXXWSRJXjREVIer4G1aJEEZvzPDpRHWUMD3bS0SA8wLueqyhV2R
+rYTOvpsLwusBl7g63By40kPoll7whOKYGHsVxq8Mu46YliF7zW8Nn4RZv5GoumrJ
+vF9K8xJNM+fcsDjpcdjv0P2eH9Bau6k6kdgep576rBNbo63ohwv0tfioDaexWUAm
+QnoF5DFm+AXR/ZdfrpMK2UVso98y7hF4gy+6Nhd2mIPWCPsxDoF9V4AQPN4NSw0C
+AwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCDOolSZzyKaXLvUHrAeQ3Njcqre
+MB8GA1UdIwQYMBaAFLCfZzMsiIiJH0RidJ0l/8AGE13WMA0GCSqGSIb3DQEBCwUA
+A4IBgQBgN5LFF2TtZKMowoFgoiCs5C3OvUtMbupwoSwt2RyUy9GBylPCUSSv2q+Q
+EZhS2iUrGVmCWNaEpWPUiQWpEr9di8gfJ7CnZX4MGLc9TuzFNLPTkvfe5RkbuehH
+p8oiE8RjT0QJcOKQ86de4F2c977qHojnwtO2NW2wO4SPA5SowMHtJxeaTfczIx52
+OmM48Fk5mM6JSyqJDhK/JbXWBCCI8GWdcJBn6CiOCfrZq8mpDyhjELskLUQva/t8
+0jgBq9IzLVD0dYCeT9ImbDEjRI7Vo1FWz9k49tCEwPtvwWac591RT0K718y6NeHG
+olxL8h634lKlg5erQglUBO1PAS3P7kS02jlc2jDVkrYEEYsE12o6KG5Ul5eZo7o6
+SBoX70kF/cXmP8F8rLBFYv8V/RMbBLpyIzIKuE05mjEVTArQ76KCjy6tPCPdWRII
+b+BbXlwp23T/jAhDWWqhV983AlMWFPfFS0dhHoaqLUZNs4WKrMOMtYeQAUwzkZY4
+lQanNpA=
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/newcerts/02.pem b/tests/testsuites/x.509/newcerts/02.pem
new file mode 100644
index 0000000..b64b2a9
--- /dev/null
+++ b/tests/testsuites/x.509/newcerts/02.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 12:59:25 2023 GMT
+ Not After : Jun 12 12:59:25 2123 GMT
+ Subject: C=DE, ST=NRW, O=Adiscon GmbH, OU=rsyslog, CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:fe:14:5d:e9:9c:6c:67:15:3c:d4:49:9d:5b:
+ 2a:ea:43:c2:bc:9e:d0:3a:5e:55:2f:68:00:2b:0b:
+ da:dc:cf:f7:d9:a7:1b:a0:a3:31:dd:a8:07:13:9e:
+ dc:36:75:b8:34:ea:17:1a:f6:1d:db:33:1e:45:36:
+ 80:ae:9c:93:a6:02:4e:26:f8:07:de:1c:ce:9e:e7:
+ 4f:25:d7:59:24:49:5e:34:44:54:87:ab:e0:6d:5a:
+ 24:41:19:bf:33:c3:a5:11:d6:50:c0:f7:6d:2d:12:
+ 03:cc:0b:b9:ea:b2:85:5d:91:ad:84:ce:be:9b:0b:
+ c2:eb:01:97:b8:3a:dc:1c:b8:d2:43:e8:96:5e:f0:
+ 84:e2:98:18:7b:15:c6:af:0c:bb:8e:98:96:21:7b:
+ cd:6f:0d:9f:84:59:bf:91:a8:ba:6a:c9:bc:5f:4a:
+ f3:12:4d:33:e7:dc:b0:38:e9:71:d8:ef:d0:fd:9e:
+ 1f:d0:5a:bb:a9:3a:91:d8:1e:a7:9e:fa:ac:13:5b:
+ a3:ad:e8:87:0b:f4:b5:f8:a8:0d:a7:b1:59:40:26:
+ 42:7a:05:e4:31:66:f8:05:d1:fd:97:5f:ae:93:0a:
+ d9:45:6c:a3:df:32:ee:11:78:83:2f:ba:36:17:76:
+ 98:83:d6:08:fb:31:0e:81:7d:57:80:10:3c:de:0d:
+ 4b:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 20:CE:A2:54:99:CF:22:9A:5C:BB:D4:1E:B0:1E:43:73:63:72:AA:DE
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 33:65:28:98:94:9b:f5:57:0d:bf:02:c2:67:93:8e:8e:77:03:
+ 9b:c7:7a:47:53:29:a4:dd:a6:a1:5e:2a:0a:ed:19:02:80:90:
+ b3:97:1f:06:4c:9c:c5:5f:6c:16:f9:12:fb:dd:da:29:88:b7:
+ 2c:91:0b:ab:53:79:7a:6e:76:20:fe:fa:b1:99:c2:2b:50:26:
+ 7b:cc:8c:75:98:35:95:79:56:43:90:a0:95:5e:98:09:10:4d:
+ ea:c0:1c:bb:c0:7b:a7:8a:9b:21:70:85:65:83:4d:ee:65:ef:
+ 10:d3:63:95:fd:51:9d:6c:41:7b:af:af:9c:e7:34:74:a1:7a:
+ 86:0a:8e:f2:2a:06:68:77:76:fa:fc:64:bc:28:1d:8b:53:7a:
+ cf:62:0f:87:a9:85:54:8c:a5:41:c3:61:0b:cf:96:c1:fa:81:
+ a5:31:63:f3:cb:17:37:58:6e:d9:30:97:fb:57:2f:31:63:e8:
+ 26:0e:82:49:e2:a9:9b:ed:39:7b:24:4e:42:8d:34:74:3a:dc:
+ b7:c5:d6:15:e9:66:28:2d:3c:e0:26:44:76:66:4a:32:94:11:
+ c8:1f:1c:b2:dc:44:69:63:f7:2d:87:b5:89:4a:40:fb:e4:14:
+ 68:dc:8a:76:40:93:35:e2:ac:9a:4b:bc:af:c5:8a:8a:38:54:
+ ef:69:01:4c:92:af:c0:07:d0:2f:7a:3c:9e:40:ac:56:07:d0:
+ 2b:1f:5f:d0:44:f9:70:e1:44:44:34:ba:fb:3d:54:85:4b:1d:
+ ba:ea:ea:6a:91:0c:08:30:2d:bc:b8:ea:22:c1:16:7b:53:fe:
+ 40:2c:8d:f5:c6:c2:39:e6:11:1d:e2:2f:50:a6:76:9c:fd:b9:
+ fa:d5:10:79:0e:e5:02:87:7d:96:e3:81:05:79:c9:a3:d8:f2:
+ a0:b1:8b:0e:8d:33:73:15:6f:27:88:85:03:8a:c5:7a:77:f4:
+ 3f:7f:b8:65:97:5b:a0:a6:21:48:67:2c:a2:73:a2:ec:d6:6a:
+ bd:d6:f2:e2:b1:5b
+-----BEGIN CERTIFICATE-----
+MIIEUTCCArmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTI1OTI1WhgPMjEyMzA2MTIxMjU5MjVaMIGUMQswCQYD
+VQQGEwJERTEMMAoGA1UECAwDTlJXMRUwEwYDVQQKDAxBZGlzY29uIEdtYkgxEDAO
+BgNVBAsMB3JzeXNsb2cxKTAnBgNVBAMMIHJzeXNsb2cgcmV2b2tlZCBjZXJ0aWZp
+Y2F0ZSB0ZXN0MSMwIQYJKoZIhvcNAQkBFhRhbG9yYmFjaEBhZGlzY29uLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/+FF3pnGxnFTzUSZ1bKupD
+wrye0DpeVS9oACsL2tzP99mnG6CjMd2oBxOe3DZ1uDTqFxr2HdszHkU2gK6ck6YC
+Tib4B94czp7nTyXXWSRJXjREVIer4G1aJEEZvzPDpRHWUMD3bS0SA8wLueqyhV2R
+rYTOvpsLwusBl7g63By40kPoll7whOKYGHsVxq8Mu46YliF7zW8Nn4RZv5GoumrJ
+vF9K8xJNM+fcsDjpcdjv0P2eH9Bau6k6kdgep576rBNbo63ohwv0tfioDaexWUAm
+QnoF5DFm+AXR/ZdfrpMK2UVso98y7hF4gy+6Nhd2mIPWCPsxDoF9V4AQPN4NSw0C
+AwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCDOolSZzyKaXLvUHrAeQ3Njcqre
+MB8GA1UdIwQYMBaAFLCfZzMsiIiJH0RidJ0l/8AGE13WMA0GCSqGSIb3DQEBCwUA
+A4IBgQAzZSiYlJv1Vw2/AsJnk46OdwObx3pHUymk3aahXioK7RkCgJCzlx8GTJzF
+X2wW+RL73dopiLcskQurU3l6bnYg/vqxmcIrUCZ7zIx1mDWVeVZDkKCVXpgJEE3q
+wBy7wHunipshcIVlg03uZe8Q02OV/VGdbEF7r6+c5zR0oXqGCo7yKgZod3b6/GS8
+KB2LU3rPYg+HqYVUjKVBw2ELz5bB+oGlMWPzyxc3WG7ZMJf7Vy8xY+gmDoJJ4qmb
+7Tl7JE5CjTR0Oty3xdYV6WYoLTzgJkR2ZkoylBHIHxyy3ERpY/cth7WJSkD75BRo
+3Ip2QJM14qyaS7yvxYqKOFTvaQFMkq/AB9AvejyeQKxWB9ArH1/QRPlw4URENLr7
+PVSFSx266upqkQwIMC28uOoiwRZ7U/5ALI31xsI55hEd4i9Qpnac/bn61RB5DuUC
+h32W44EFecmj2PKgsYsOjTNzFW8niIUDisV6d/Q/f7hll1ugpiFIZyyic6Ls1mq9
+1vLisVs=
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/newcerts/03.pem b/tests/testsuites/x.509/newcerts/03.pem
new file mode 100644
index 0000000..8bc2b8a
--- /dev/null
+++ b/tests/testsuites/x.509/newcerts/03.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3 (0x3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 13:38:06 2023 GMT
+ Not After : Jun 12 13:38:06 2123 GMT
+ Subject: C=DE, ST=NRW, O=Adiscon GmbH, OU=rsyslog, CN=rsyslog revoked certificate test/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:fe:14:5d:e9:9c:6c:67:15:3c:d4:49:9d:5b:
+ 2a:ea:43:c2:bc:9e:d0:3a:5e:55:2f:68:00:2b:0b:
+ da:dc:cf:f7:d9:a7:1b:a0:a3:31:dd:a8:07:13:9e:
+ dc:36:75:b8:34:ea:17:1a:f6:1d:db:33:1e:45:36:
+ 80:ae:9c:93:a6:02:4e:26:f8:07:de:1c:ce:9e:e7:
+ 4f:25:d7:59:24:49:5e:34:44:54:87:ab:e0:6d:5a:
+ 24:41:19:bf:33:c3:a5:11:d6:50:c0:f7:6d:2d:12:
+ 03:cc:0b:b9:ea:b2:85:5d:91:ad:84:ce:be:9b:0b:
+ c2:eb:01:97:b8:3a:dc:1c:b8:d2:43:e8:96:5e:f0:
+ 84:e2:98:18:7b:15:c6:af:0c:bb:8e:98:96:21:7b:
+ cd:6f:0d:9f:84:59:bf:91:a8:ba:6a:c9:bc:5f:4a:
+ f3:12:4d:33:e7:dc:b0:38:e9:71:d8:ef:d0:fd:9e:
+ 1f:d0:5a:bb:a9:3a:91:d8:1e:a7:9e:fa:ac:13:5b:
+ a3:ad:e8:87:0b:f4:b5:f8:a8:0d:a7:b1:59:40:26:
+ 42:7a:05:e4:31:66:f8:05:d1:fd:97:5f:ae:93:0a:
+ d9:45:6c:a3:df:32:ee:11:78:83:2f:ba:36:17:76:
+ 98:83:d6:08:fb:31:0e:81:7d:57:80:10:3c:de:0d:
+ 4b:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 20:CE:A2:54:99:CF:22:9A:5C:BB:D4:1E:B0:1E:43:73:63:72:AA:DE
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 65:ac:7c:30:d0:01:ce:d7:ff:28:61:6c:8d:99:15:ce:45:22:
+ 8a:39:70:a4:a6:ce:48:94:e3:4b:8c:be:55:c4:66:96:49:49:
+ 4b:e0:4c:95:fd:73:02:54:3a:df:34:2f:96:16:48:ec:c2:23:
+ 3d:ee:b4:5a:dd:a0:c9:eb:85:f4:fd:e8:d5:8f:f3:dc:ce:4a:
+ 88:bb:be:19:81:3f:8b:0f:09:23:46:14:c9:f5:35:5a:cf:25:
+ 7c:92:df:b9:90:5d:ff:4f:21:40:9c:24:7c:0f:1f:3f:62:d1:
+ 7b:cc:40:7d:c6:61:49:f3:84:26:78:ed:87:70:06:9c:93:05:
+ a5:c4:7e:60:3d:d0:4a:2c:e4:d6:e5:33:f8:07:dd:5a:0e:9a:
+ 93:17:50:29:1a:ff:66:61:d9:40:a7:fb:cc:7b:62:b7:9d:29:
+ 1a:2a:3d:7b:93:87:eb:52:4e:00:19:19:3c:4d:73:fc:3d:ed:
+ eb:9d:92:30:bc:b0:ed:51:15:ce:b7:3c:00:09:0c:9d:6d:8b:
+ 2b:c9:f5:66:d4:49:44:58:3d:e7:61:3d:6b:21:05:ff:1d:55:
+ 59:dd:e4:a6:2f:e5:96:82:eb:24:33:2e:47:61:a5:f8:4d:ab:
+ ad:fc:64:f8:8b:9e:0e:62:8c:16:1d:79:18:74:18:9c:a2:19:
+ c3:24:0d:6e:45:63:f9:08:92:7d:44:0b:96:c7:48:84:72:97:
+ 22:23:bf:10:0a:d7:4e:43:8a:db:60:cd:5d:80:5e:71:fa:c2:
+ b6:68:10:ee:cc:29:86:15:d3:d9:93:2a:cc:73:88:be:9f:ad:
+ d0:c5:9c:a4:e4:86:38:e7:41:84:3a:d0:f3:67:1f:2c:40:d7:
+ 04:b1:ea:32:13:49:a5:82:1a:a5:6c:3f:5f:dc:fd:55:14:03:
+ 8b:d7:bd:01:9e:bc:c5:e4:a1:a8:a8:9d:bc:cd:1f:5b:fc:df:
+ 59:b7:0d:aa:47:a0:08:cd:6e:f7:c8:9d:d3:dd:4e:8b:aa:cc:
+ 54:20:a0:2b:63:96
+-----BEGIN CERTIFICATE-----
+MIIEUTCCArmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTMzODA2WhgPMjEyMzA2MTIxMzM4MDZaMIGUMQswCQYD
+VQQGEwJERTEMMAoGA1UECAwDTlJXMRUwEwYDVQQKDAxBZGlzY29uIEdtYkgxEDAO
+BgNVBAsMB3JzeXNsb2cxKTAnBgNVBAMMIHJzeXNsb2cgcmV2b2tlZCBjZXJ0aWZp
+Y2F0ZSB0ZXN0MSMwIQYJKoZIhvcNAQkBFhRhbG9yYmFjaEBhZGlzY29uLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/+FF3pnGxnFTzUSZ1bKupD
+wrye0DpeVS9oACsL2tzP99mnG6CjMd2oBxOe3DZ1uDTqFxr2HdszHkU2gK6ck6YC
+Tib4B94czp7nTyXXWSRJXjREVIer4G1aJEEZvzPDpRHWUMD3bS0SA8wLueqyhV2R
+rYTOvpsLwusBl7g63By40kPoll7whOKYGHsVxq8Mu46YliF7zW8Nn4RZv5GoumrJ
+vF9K8xJNM+fcsDjpcdjv0P2eH9Bau6k6kdgep576rBNbo63ohwv0tfioDaexWUAm
+QnoF5DFm+AXR/ZdfrpMK2UVso98y7hF4gy+6Nhd2mIPWCPsxDoF9V4AQPN4NSw0C
+AwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCDOolSZzyKaXLvUHrAeQ3Njcqre
+MB8GA1UdIwQYMBaAFLCfZzMsiIiJH0RidJ0l/8AGE13WMA0GCSqGSIb3DQEBCwUA
+A4IBgQBlrHww0AHO1/8oYWyNmRXORSKKOXCkps5IlONLjL5VxGaWSUlL4EyV/XMC
+VDrfNC+WFkjswiM97rRa3aDJ64X0/ejVj/PczkqIu74ZgT+LDwkjRhTJ9TVazyV8
+kt+5kF3/TyFAnCR8Dx8/YtF7zEB9xmFJ84QmeO2HcAackwWlxH5gPdBKLOTW5TP4
+B91aDpqTF1ApGv9mYdlAp/vMe2K3nSkaKj17k4frUk4AGRk8TXP8Pe3rnZIwvLDt
+URXOtzwACQydbYsryfVm1ElEWD3nYT1rIQX/HVVZ3eSmL+WWguskMy5HYaX4Taut
+/GT4i54OYowWHXkYdBicohnDJA1uRWP5CJJ9RAuWx0iEcpciI78QCtdOQ4rbYM1d
+gF5x+sK2aBDuzCmGFdPZkyrMc4i+n63QxZyk5IY450GEOtDzZx8sQNcEseoyE0ml
+ghqlbD9f3P1VFAOL170BnrzF5KGoqJ28zR9b/N9Ztw2qR6AIzW73yJ3T3U6LqsxU
+IKArY5Y=
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/newcerts/04.pem b/tests/testsuites/x.509/newcerts/04.pem
new file mode 100644
index 0000000..e92ab86
--- /dev/null
+++ b/tests/testsuites/x.509/newcerts/04.pem
@@ -0,0 +1,102 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4 (0x4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=someName, OU=rsyslog, O=SomeOrg, C=US
+ Validity
+ Not Before: Jul 6 13:52:50 2023 GMT
+ Not After : Jun 12 13:52:50 2123 GMT
+ Subject: C=US, ST=CA, O=SomeComp, OU=SomeUnit, CN=rsyslog/emailAddress=alorbach@adiscon.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (3072 bit)
+ Modulus:
+ 00:9d:91:da:d8:2e:3d:9d:ae:85:c3:c5:a7:f6:a4:
+ 66:f8:c8:91:91:b8:70:20:dc:ed:e8:23:ca:53:f7:
+ b8:52:43:f3:a7:eb:fb:df:8a:3b:2c:b0:13:fa:62:
+ d3:a1:53:a4:51:71:1f:68:d9:fd:bc:39:4a:fb:c9:
+ 6a:df:f3:88:84:b0:80:bc:c0:f5:1b:42:11:f6:4c:
+ 1a:d8:2c:62:0b:5d:50:64:30:9a:d3:db:c1:d5:7f:
+ 39:53:e4:bd:e8:1e:04:9d:c9:12:e0:e4:57:29:29:
+ 01:b9:f1:e5:bc:74:a6:e7:4b:61:e6:67:5c:6c:4e:
+ ee:ee:22:0c:1b:14:6d:e8:0c:6f:ee:ee:c3:b8:dd:
+ df:15:ed:7a:96:5b:cc:85:e5:e3:50:c4:ce:2b:bf:
+ b6:37:e6:20:fc:6e:45:7e:09:bd:84:7a:af:07:27:
+ f4:99:23:41:df:36:d8:29:31:a0:96:84:2f:fd:45:
+ 2e:d4:b4:f9:fa:dc:8f:23:c0:e0:06:ad:ad:0a:72:
+ da:f4:3b:a1:cb:d6:a6:3b:ec:46:c4:95:f2:71:a5:
+ ad:08:1f:e7:06:18:0e:db:80:51:96:ba:24:f6:64:
+ 02:6b:d3:f0:76:01:34:3a:72:02:e9:cb:d0:aa:62:
+ 51:0c:8f:83:be:c0:47:99:d2:92:72:ed:53:a5:49:
+ 05:d4:c9:a1:f4:4d:de:12:9d:1a:c8:17:84:f3:a2:
+ 7c:67:47:82:4b:86:1e:73:86:e2:26:26:10:94:a3:
+ 99:9b:08:99:78:9d:3d:33:5d:85:c2:46:65:94:ab:
+ 70:b4:3b:c1:26:8b:11:b6:66:27:88:22:84:03:b5:
+ 08:45:32:8c:81:23:be:62:dc:6f:a0:aa:5e:9f:03:
+ f7:a7:f5:03:70:3c:78:09:d0:84:44:8c:19:af:76:
+ f7:93:fc:af:c6:fd:db:d9:4c:cb:20:79:44:71:cb:
+ e6:55:61:a9:7a:af:0b:a3:a6:ed:e9:a9:11:af:fa:
+ a3:5d:ac:97:e7:ef:2b:b6:a8:37
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 6E:15:7E:C4:62:2B:92:6D:22:EE:0C:E4:C5:36:29:38:16:62:BE:89
+ X509v3 Authority Key Identifier:
+ keyid:B0:9F:67:33:2C:88:88:89:1F:44:62:74:9D:25:FF:C0:06:13:5D:D6
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 64:b0:45:6b:0c:7c:2d:09:14:8e:78:93:85:ef:d2:31:aa:c3:
+ 59:2e:85:bf:29:e1:46:59:38:d4:fe:ea:c4:c1:83:a7:4a:1b:
+ 92:5e:e8:11:9c:21:48:9d:1e:cc:31:d8:31:00:72:fe:7b:c1:
+ 18:c4:f5:37:f3:3b:0e:1a:f6:3f:19:47:22:c9:87:01:e0:4c:
+ f4:5d:36:0a:87:46:42:fc:6c:ab:26:ff:7d:ca:2c:19:97:ca:
+ 25:fc:70:66:4e:49:86:3e:81:0f:ee:e2:5c:3b:69:07:8b:c2:
+ 52:09:46:d8:67:af:84:54:bb:4f:f3:e0:da:07:c5:64:56:2d:
+ fb:f9:55:13:53:1d:c6:78:63:40:22:23:4f:63:59:37:05:c7:
+ 46:b6:36:53:30:fe:9b:e6:01:0a:54:5b:be:1b:a4:72:c3:27:
+ 1b:c5:21:5d:d3:0c:06:56:d9:df:45:83:e7:06:6d:47:53:72:
+ ea:6c:e7:db:5e:bd:14:47:19:0c:18:13:73:6b:14:dc:29:6c:
+ c0:60:fa:4c:02:74:45:e7:8d:12:bd:1f:cb:77:2c:72:19:ef:
+ e8:85:5c:cf:77:04:b7:d4:08:a8:7e:d1:1d:20:7b:76:27:ca:
+ 8a:5a:2a:a5:e7:15:6c:2d:50:9c:c2:b4:83:45:c2:f7:a5:f0:
+ 6b:d5:45:6b:88:4c:db:00:26:2f:8e:0a:3c:42:4e:0c:64:18:
+ 41:a0:6b:4b:d0:78:89:b4:64:34:5b:76:cb:dd:b9:be:6e:28:
+ 82:ba:6e:11:99:86:88:b6:0d:22:2b:a6:eb:5f:0b:ca:77:5b:
+ 2e:28:b7:f3:96:c3:8c:9d:0d:2b:59:98:d4:20:87:3a:2e:f4:
+ e3:bf:a2:ff:67:4f:3f:1e:ce:ec:59:76:5a:67:81:ba:44:96:
+ 29:af:05:ce:55:02:b4:d6:68:f0:25:61:8c:91:83:03:fd:e4:
+ 2c:06:91:b4:32:d8:5b:47:d6:20:55:44:a6:0c:9b:97:bb:94:
+ 66:25:8c:35:e0:32
+-----BEGIN CERTIFICATE-----
+MIIEszCCAxugAwIBAgIBBDANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDEwhzb21l
+TmFtZTEQMA4GA1UECxMHcnN5c2xvZzEQMA4GA1UEChMHU29tZU9yZzELMAkGA1UE
+BhMCVVMwIBcNMjMwNzA2MTM1MjUwWhgPMjEyMzA2MTIxMzUyNTBaMHcxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU29tZUNvbXAxETAPBgNVBAsM
+CFNvbWVVbml0MRAwDgYDVQQDDAdyc3lzbG9nMSMwIQYJKoZIhvcNAQkBFhRhbG9y
+YmFjaEBhZGlzY29uLmNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
+AJ2R2tguPZ2uhcPFp/akZvjIkZG4cCDc7egjylP3uFJD86fr+9+KOyywE/pi06FT
+pFFxH2jZ/bw5SvvJat/ziISwgLzA9RtCEfZMGtgsYgtdUGQwmtPbwdV/OVPkvege
+BJ3JEuDkVykpAbnx5bx0pudLYeZnXGxO7u4iDBsUbegMb+7uw7jd3xXtepZbzIXl
+41DEziu/tjfmIPxuRX4JvYR6rwcn9JkjQd822CkxoJaEL/1FLtS0+frcjyPA4Aat
+rQpy2vQ7ocvWpjvsRsSV8nGlrQgf5wYYDtuAUZa6JPZkAmvT8HYBNDpyAunL0Kpi
+UQyPg77AR5nSknLtU6VJBdTJofRN3hKdGsgXhPOifGdHgkuGHnOG4iYmEJSjmZsI
+mXidPTNdhcJGZZSrcLQ7wSaLEbZmJ4gihAO1CEUyjIEjvmLcb6CqXp8D96f1A3A8
+eAnQhESMGa9295P8r8b929lMyyB5RHHL5lVhqXqvC6Om7empEa/6o12sl+fvK7ao
+NwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdl
+bmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUbhV+xGIrkm0i7gzkxTYpOBZi
+vokwHwYDVR0jBBgwFoAUsJ9nMyyIiIkfRGJ0nSX/wAYTXdYwDQYJKoZIhvcNAQEL
+BQADggGBAGSwRWsMfC0JFI54k4Xv0jGqw1kuhb8p4UZZONT+6sTBg6dKG5Je6BGc
+IUidHswx2DEAcv57wRjE9TfzOw4a9j8ZRyLJhwHgTPRdNgqHRkL8bKsm/33KLBmX
+yiX8cGZOSYY+gQ/u4lw7aQeLwlIJRthnr4RUu0/z4NoHxWRWLfv5VRNTHcZ4Y0Ai
+I09jWTcFx0a2NlMw/pvmAQpUW74bpHLDJxvFIV3TDAZW2d9Fg+cGbUdTcups59te
+vRRHGQwYE3NrFNwpbMBg+kwCdEXnjRK9H8t3LHIZ7+iFXM93BLfUCKh+0R0ge3Yn
+yopaKqXnFWwtUJzCtINFwvel8GvVRWuITNsAJi+OCjxCTgxkGEGga0vQeIm0ZDRb
+dsvdub5uKIK6bhGZhoi2DSIrputfC8p3Wy4ot/OWw4ydDStZmNQghzou9OO/ov9n
+Tz8ezuxZdlpngbpElimvBc5VArTWaPAlYYyRgwP95CwGkbQy2FtH1iBVRKYMm5e7
+lGYljDXgMg==
+-----END CERTIFICATE-----
diff --git a/tests/testsuites/x.509/openssl-cmds.sh b/tests/testsuites/x.509/openssl-cmds.sh
new file mode 100644
index 0000000..5bcc382
--- /dev/null
+++ b/tests/testsuites/x.509/openssl-cmds.sh
@@ -0,0 +1,11 @@
+# CREATE KEY
+# openssl genpkey -algorithm RSA -out client-revoked-key.pem
+# CREATE REQEST
+# openssl req -new -key client-revoked-key.pem -out client-revoked.csr
+# CREATE A CERT
+# openssl ca -config openssl.cnf -in client-revoked.csr -out client-revoked.pem -keyfile ca-key.pem -cert ca.pem
+# REVOKE A CERT
+# openssl ca -config openssl.cnf -revoke client-revoked.pem -keyfile ca-key.pem -cert ca.pem
+# CREATE crl.pem
+# openssl ca -config openssl.cnf -gencrl -out crl.pem -keyfile ca-key.pem -cert ca.pem
+
diff --git a/tests/testsuites/x.509/openssl.cnf b/tests/testsuites/x.509/openssl.cnf
new file mode 100644
index 0000000..39eba57
--- /dev/null
+++ b/tests/testsuites/x.509/openssl.cnf
@@ -0,0 +1,41 @@
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = ./
+certs = $dir/certs
+crl_dir = $dir/crl
+database = $dir/index.txt
+new_certs_dir = $dir/newcerts
+
+certificate = $dir/ca.pem
+serial = $dir/serial
+crl = $dir/crl.pem
+private_key = $dir/ca-key.pem
+
+x509_extensions = usr_cert
+name_opt = ca_default
+cert_opt = ca_default
+default_days = 36500
+default_md = sha256
+
+# How long before next CRL, default is 1 but for testing we need no expire, so 100 years is fine.
+default_crl_days = 36500
+
+preserve = no
+policy = policy_match
+
+[ policy_match ]
+countryName = supplied
+stateOrProvinceName = supplied
+organizationName = supplied
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ usr_cert ]
+basicConstraints=CA:FALSE
+nsComment="OpenSSL Generated Certificate"
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
diff --git a/tests/testsuites/x.509/serial b/tests/testsuites/x.509/serial
new file mode 100644
index 0000000..eeee65e
--- /dev/null
+++ b/tests/testsuites/x.509/serial
@@ -0,0 +1 @@
+05
diff --git a/tests/testsuites/xlate.lkp_tbl b/tests/testsuites/xlate.lkp_tbl
new file mode 100644
index 0000000..cc98de1
--- /dev/null
+++ b/tests/testsuites/xlate.lkp_tbl
@@ -0,0 +1,5 @@
+{
+ "table":[
+ {"index":" msgnum:00000001:", "value":"bar_old" },
+ {"index":" msgnum:00000000:", "value":"foo_old" }]
+}
diff --git a/tests/testsuites/xlate_array.lkp_tbl b/tests/testsuites/xlate_array.lkp_tbl
new file mode 100644
index 0000000..c2b327b
--- /dev/null
+++ b/tests/testsuites/xlate_array.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "type" : "array",
+ "table":[
+ {"index": 1, "value":"bar_old" },
+ {"index": 0, "value":"foo_old" }]
+}
diff --git a/tests/testsuites/xlate_array_empty_table.lkp_tbl b/tests/testsuites/xlate_array_empty_table.lkp_tbl
new file mode 100644
index 0000000..e4912d0
--- /dev/null
+++ b/tests/testsuites/xlate_array_empty_table.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "version": 1,
+ "nomatch": "baz_arr",
+ "type" : "array",
+ "table":[]
+}
diff --git a/tests/testsuites/xlate_array_misuse.lkp_tbl b/tests/testsuites/xlate_array_misuse.lkp_tbl
new file mode 100644
index 0000000..8cc96c0
--- /dev/null
+++ b/tests/testsuites/xlate_array_misuse.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "type" : "array",
+ "table":[
+ {"index": 3, "value":"bar_old" },
+ {"index": 1, "value":"foo_old" }]
+}
diff --git a/tests/testsuites/xlate_array_more.lkp_tbl b/tests/testsuites/xlate_array_more.lkp_tbl
new file mode 100644
index 0000000..fa93014
--- /dev/null
+++ b/tests/testsuites/xlate_array_more.lkp_tbl
@@ -0,0 +1,7 @@
+{
+ "type" : "array",
+ "table":[
+ {"index": 2, "value":"baz" },
+ {"index": 0, "value":"foo_new" },
+ {"index": 1, "value":"bar_new" }]
+}
diff --git a/tests/testsuites/xlate_array_more_misuse.lkp_tbl b/tests/testsuites/xlate_array_more_misuse.lkp_tbl
new file mode 100644
index 0000000..223d3de
--- /dev/null
+++ b/tests/testsuites/xlate_array_more_misuse.lkp_tbl
@@ -0,0 +1,7 @@
+{
+ "type" : "array",
+ "table":[
+ {"index": 2, "value":"baz" },
+ {"index": 1, "value":"foo_new" },
+ {"index": 1, "value":"bar_new" }]
+}
diff --git a/tests/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl b/tests/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl
new file mode 100644
index 0000000..d7730e6
--- /dev/null
+++ b/tests/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl
@@ -0,0 +1,13 @@
+{
+ "nomatch": "quux",
+ "type" : "array",
+ "table":[
+ {"index": 2, "value": "foo_latest" },
+ {"index": 3, "value": "baz_latest" },
+ {"index": 4, "value": "foo_latest" },
+ {"index": 5, "value": "foo_latest" },
+ {"index": 6, "value": "baz_latest" },
+ {"index": 7, "value": "foo_latest" },
+ {"index": 8, "value": "baz_latest" },
+ {"index": 9, "value": "baz_latest" }]
+}
diff --git a/tests/testsuites/xlate_array_no_index.lkp_tbl b/tests/testsuites/xlate_array_no_index.lkp_tbl
new file mode 100644
index 0000000..30dc209
--- /dev/null
+++ b/tests/testsuites/xlate_array_no_index.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "array",
+ "table":[
+ {"value":"foo" },
+ {"value":"bar" }]
+}
diff --git a/tests/testsuites/xlate_array_no_table.lkp_tbl b/tests/testsuites/xlate_array_no_table.lkp_tbl
new file mode 100644
index 0000000..df47606
--- /dev/null
+++ b/tests/testsuites/xlate_array_no_table.lkp_tbl
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "array"
+}
diff --git a/tests/testsuites/xlate_array_no_value.lkp_tbl b/tests/testsuites/xlate_array_no_value.lkp_tbl
new file mode 100644
index 0000000..176cafb
--- /dev/null
+++ b/tests/testsuites/xlate_array_no_value.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "array",
+ "table":[
+ {"index":"00000000" },
+ {"index":"00000001" }]
+}
diff --git a/tests/testsuites/xlate_empty_file.lkp_tbl b/tests/testsuites/xlate_empty_file.lkp_tbl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/testsuites/xlate_empty_file.lkp_tbl
diff --git a/tests/testsuites/xlate_incorrect_type.lkp_tbl b/tests/testsuites/xlate_incorrect_type.lkp_tbl
new file mode 100644
index 0000000..0180b6e
--- /dev/null
+++ b/tests/testsuites/xlate_incorrect_type.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "quux",
+ "table":[
+ {"index":" 00000000", "value":"foo" },
+ {"index":" 00000001", "value":"bar" }]
+}
diff --git a/tests/testsuites/xlate_incorrect_version.lkp_tbl b/tests/testsuites/xlate_incorrect_version.lkp_tbl
new file mode 100644
index 0000000..ef2ce7b
--- /dev/null
+++ b/tests/testsuites/xlate_incorrect_version.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 3,
+ "nomatch": "baz",
+ "type" : "string",
+ "table":[
+ {"index": "00000000", "value":"foo" },
+ {"index": "00000001", "value":"bar" }]
+}
diff --git a/tests/testsuites/xlate_invalid_json.lkp_tbl b/tests/testsuites/xlate_invalid_json.lkp_tbl
new file mode 100644
index 0000000..0d1e247
--- /dev/null
+++ b/tests/testsuites/xlate_invalid_json.lkp_tbl
@@ -0,0 +1,4 @@
+{
+ version": "baz_sparse_arr",
+ "type" : "sparseArray",
+ "table":[]
diff --git a/tests/testsuites/xlate_more.lkp_tbl b/tests/testsuites/xlate_more.lkp_tbl
new file mode 100644
index 0000000..2d3f452
--- /dev/null
+++ b/tests/testsuites/xlate_more.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "table":[
+ {"index":" msgnum:00000000:", "value":"foo_new" },
+ {"index":" msgnum:00000001:", "value":"bar_new" },
+ {"index":" msgnum:00000002:", "value":"baz" }]
+}
diff --git a/tests/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl b/tests/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl
new file mode 100644
index 0000000..ac50664
--- /dev/null
+++ b/tests/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl
@@ -0,0 +1,12 @@
+{
+ "nomatch": "quux",
+ "table":[
+ {"index":" msgnum:00000000:", "value":"foo_latest" },
+ {"index":" msgnum:00000002:", "value":"baz_latest" },
+ {"index":" msgnum:00000003:", "value":"foo_latest" },
+ {"index":" msgnum:00000004:", "value":"foo_latest" },
+ {"index":" msgnum:00000005:", "value":"baz_latest" },
+ {"index":" msgnum:00000006:", "value":"foo_latest" },
+ {"index":" msgnum:00000007:", "value":"baz_latest" },
+ {"index":" msgnum:00000008:", "value":"baz_latest" }]
+}
diff --git a/tests/testsuites/xlate_sparseArray_empty_table.lkp_tbl b/tests/testsuites/xlate_sparseArray_empty_table.lkp_tbl
new file mode 100644
index 0000000..f33c7d7
--- /dev/null
+++ b/tests/testsuites/xlate_sparseArray_empty_table.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "version": 1,
+ "nomatch": "baz_sparse_arr",
+ "type" : "sparseArray",
+ "table":[]
+}
diff --git a/tests/testsuites/xlate_sparseArray_no_index.lkp_tbl b/tests/testsuites/xlate_sparseArray_no_index.lkp_tbl
new file mode 100644
index 0000000..29ba48c
--- /dev/null
+++ b/tests/testsuites/xlate_sparseArray_no_index.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "sparseArray",
+ "table":[
+ {"value":"foo" },
+ {"value":"bar" }]
+}
diff --git a/tests/testsuites/xlate_sparseArray_no_table.lkp_tbl b/tests/testsuites/xlate_sparseArray_no_table.lkp_tbl
new file mode 100644
index 0000000..45fc9a9
--- /dev/null
+++ b/tests/testsuites/xlate_sparseArray_no_table.lkp_tbl
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "sparseArray"
+}
diff --git a/tests/testsuites/xlate_sparseArray_no_value.lkp_tbl b/tests/testsuites/xlate_sparseArray_no_value.lkp_tbl
new file mode 100644
index 0000000..e5c65ee
--- /dev/null
+++ b/tests/testsuites/xlate_sparseArray_no_value.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "sparseArray",
+ "table":[
+ {"index":"00000000" },
+ {"index":"00000001" }]
+}
diff --git a/tests/testsuites/xlate_sparse_array.lkp_tbl b/tests/testsuites/xlate_sparse_array.lkp_tbl
new file mode 100644
index 0000000..84523f1
--- /dev/null
+++ b/tests/testsuites/xlate_sparse_array.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "type" : "sparseArray",
+ "table":[
+ {"index": 3, "value":"bar_old" },
+ {"index": 1, "value":"foo_old" }]
+}
diff --git a/tests/testsuites/xlate_sparse_array_more.lkp_tbl b/tests/testsuites/xlate_sparse_array_more.lkp_tbl
new file mode 100644
index 0000000..bf52153
--- /dev/null
+++ b/tests/testsuites/xlate_sparse_array_more.lkp_tbl
@@ -0,0 +1,7 @@
+{
+ "type" : "sparseArray",
+ "table":[
+ {"index": 4, "value":"baz" },
+ {"index": 0, "value":"foo_new" },
+ {"index": 2, "value":"bar_new" }]
+}
diff --git a/tests/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl b/tests/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl
new file mode 100644
index 0000000..0dc9169
--- /dev/null
+++ b/tests/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl
@@ -0,0 +1,12 @@
+{
+ "nomatch": "quux",
+ "type" : "sparseArray",
+ "table":[
+ {"index": 2, "value": "foo_latest" },
+ {"index": 3, "value": "baz_latest" },
+ {"index": 4, "value": "foo_latest" },
+ {"index": 5, "value": "foo_latest" },
+ {"index": 8, "value": "baz_latest" },
+ {"index": 10, "value": "baz_latest" },
+ {"index": 12, "value": "foo_latest" }]
+}
diff --git a/tests/testsuites/xlate_string_empty_table.lkp_tbl b/tests/testsuites/xlate_string_empty_table.lkp_tbl
new file mode 100644
index 0000000..81358da
--- /dev/null
+++ b/tests/testsuites/xlate_string_empty_table.lkp_tbl
@@ -0,0 +1,6 @@
+{
+ "version": 1,
+ "nomatch": "baz_str",
+ "type" : "string",
+ "table":[]
+}
diff --git a/tests/testsuites/xlate_string_no_index.lkp_tbl b/tests/testsuites/xlate_string_no_index.lkp_tbl
new file mode 100644
index 0000000..c5a0eec
--- /dev/null
+++ b/tests/testsuites/xlate_string_no_index.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "string",
+ "table":[
+ {"value":"foo" },
+ {"value":"bar" }]
+}
diff --git a/tests/testsuites/xlate_string_no_table.lkp_tbl b/tests/testsuites/xlate_string_no_table.lkp_tbl
new file mode 100644
index 0000000..d941488
--- /dev/null
+++ b/tests/testsuites/xlate_string_no_table.lkp_tbl
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "string"
+}
diff --git a/tests/testsuites/xlate_string_no_value.lkp_tbl b/tests/testsuites/xlate_string_no_value.lkp_tbl
new file mode 100644
index 0000000..d2280f2
--- /dev/null
+++ b/tests/testsuites/xlate_string_no_value.lkp_tbl
@@ -0,0 +1,8 @@
+{
+ "version": 1,
+ "nomatch": "baz",
+ "type" : "string",
+ "table":[
+ {"index":"00000000" },
+ {"index":"00000001" }]
+}
diff --git a/tests/testsuites/zoo.cfg b/tests/testsuites/zoo.cfg
new file mode 100644
index 0000000..b3a3cac
--- /dev/null
+++ b/tests/testsuites/zoo.cfg
@@ -0,0 +1,5 @@
+tickTime=1000
+initLimit=5
+syncLimit=2
+dataDir=zk_data_dir
+clientPort=22181
diff --git a/tests/testsuites/zoo.dep_wrk1.cfg b/tests/testsuites/zoo.dep_wrk1.cfg
new file mode 100644
index 0000000..b3a3cac
--- /dev/null
+++ b/tests/testsuites/zoo.dep_wrk1.cfg
@@ -0,0 +1,5 @@
+tickTime=1000
+initLimit=5
+syncLimit=2
+dataDir=zk_data_dir
+clientPort=22181
diff --git a/tests/testsuites/zoo.dep_wrk2.cfg b/tests/testsuites/zoo.dep_wrk2.cfg
new file mode 100644
index 0000000..a97d0ec
--- /dev/null
+++ b/tests/testsuites/zoo.dep_wrk2.cfg
@@ -0,0 +1,5 @@
+tickTime=1000
+initLimit=5
+syncLimit=2
+dataDir=zk_data_dir
+clientPort=22182
diff --git a/tests/testsuites/zoo.dep_wrk3.cfg b/tests/testsuites/zoo.dep_wrk3.cfg
new file mode 100644
index 0000000..94d9667
--- /dev/null
+++ b/tests/testsuites/zoo.dep_wrk3.cfg
@@ -0,0 +1,5 @@
+tickTime=1000
+initLimit=5
+syncLimit=2
+dataDir=zk_data_dir
+clientPort=22183
diff --git a/tests/threadingmq.sh b/tests/threadingmq.sh
new file mode 100755
index 0000000..c3eaed7
--- /dev/null
+++ b/tests/threadingmq.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# we send 100,000 messages in the hopes that his puts at least a little bit
+# of pressure on the threading subsystem. To really prove it, we would need to
+# push messages for several minutes, but that takes too long during the
+# automated tests (hint: do this manually after suspect changes). Thankfully,
+# in practice many threading bugs result in an abort rather quickly and these
+# should be covered by this test here.
+# rgerhards, 2009-06-26
+echo \[threadingmq.sh\]: main queue concurrency
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 1
+#$MainMsgQueueTimeoutShutdown 100000
+
+$MainMsgQueueWorkerThreadMinimumMessages 10
+$MainMsgQueueWorkerThreads 5
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+# write quickly to the output file:
+$OMFileFlushOnTXEnd off
+$OMFileIOBufferSize 256k
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+injectmsg 0 100000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+# we give an extra seconds for things to settle, especially
+# important on slower test machines
+./msleep 5000
+wait_shutdown
+seq_check 0 99999
+exit_test
diff --git a/tests/threadingmqaq.sh b/tests/threadingmqaq.sh
new file mode 100755
index 0000000..e657011
--- /dev/null
+++ b/tests/threadingmqaq.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# we send 100,000 messages in the hopes that his puts at least a little bit
+# of pressure on the threading subsystem. To really prove it, we would need to
+# push messages for several minutes, but that takes too long during the
+# automated tests (hint: do this manually after suspect changes). Thankfully,
+# in practice many threading bugs result in an abort rather quickly and these
+# should be covered by this test here.
+# rgerhards, 2009-06-26
+
+uname
+if [ $(uname) = "SunOS" ] ; then
+ echo "This test currently does not work on all flavors of Solaris."
+ exit 77
+fi
+
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+$MainMsgQueueWorkerThreadMinimumMessages 10
+$MainMsgQueueWorkerThreads 5
+
+$template outfmt,"%msg:F,58:2%\n"
+template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names!
+# write quickly to the output file:
+$OMFileFlushOnTXEnd off
+$OMFileIOBufferSize 256k
+# This time, also run the action queue detached
+$ActionQueueWorkerThreadMinimumMessages 10
+$ActionQueueWorkerThreads 5
+$ActionQueueTimeoutEnqueue 10000
+$ActionQueueType LinkedList
+:msg, contains, "msgnum:" ?dynfile;outfmt
+'
+startup
+#tcpflood -c2 -m100000
+#shutdown_when_empty # shut down rsyslogd when done processing messages
+injectmsg 0 100000
+# we need to sleep a bit on some environments, as imdiag can not correctly
+# diagnose when the action queues are empty...
+sleep 3
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+seq_check 0 99999
+exit_test
diff --git a/tests/timegenerated-dateordinal-invld.sh b/tests/timegenerated-dateordinal-invld.sh
new file mode 100755
index 0000000..e9ea339
--- /dev/null
+++ b/tests/timegenerated-dateordinal-invld.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-02 by RGerhards, released under ASL 2.0
+# the key point of this test is that we do not abort and
+# instead provide the defined return value (0)
+# requires faketime
+echo \[timegenerated-dateordinal-invld\]: check invalid dates with ordinal format
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=UTC+00:00
+export EXPECTED="001" # same for all tests
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%timegenerated:::date-ordinal%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+
+echo "***SUBTEST: check 1800-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1800-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+cmp_exact
+
+
+echo "***SUBTEST: check 1960-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1960-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+cmp_exact
+
+
+echo "***SUBTEST: check 2101-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2101-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+cmp_exact
+
+
+echo "***SUBTEST: check 2500-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2500-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+cmp_exact
+
+exit_test
diff --git a/tests/timegenerated-dateordinal.sh b/tests/timegenerated-dateordinal.sh
new file mode 100755
index 0000000..41bccbd
--- /dev/null
+++ b/tests/timegenerated-dateordinal.sh
@@ -0,0 +1,168 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-02 by RGerhards, released under ASL 2.0
+# Note: we run several subtests here in order to save us
+# from creating additional tests
+# requires faketime
+echo \[timegenerated-dateordinal\]: check valid dates with ordinal format
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=UTC+00:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%timegenerated:::date-ordinal%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+
+echo "***SUBTEST: check 1970-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1970-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+
+echo "***SUBTEST: check 2000-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2000-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="061"
+cmp_exact
+
+
+echo "***SUBTEST: check 2016-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+
+echo "***SUBTEST: check 2016-02-29"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-02-29 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="060"
+cmp_exact
+
+
+echo "***SUBTEST: check 2016-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="061"
+cmp_exact
+
+
+echo "***SUBTEST: check 2016-03-03"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-03-03 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="063"
+cmp_exact
+
+
+echo "***SUBTEST: check 2016-12-31"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-12-31 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="366"
+cmp_exact
+
+
+echo "***SUBTEST: check 2017-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2017-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+
+echo "***SUBTEST: check 2020-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2020-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="061"
+cmp_exact
+
+
+echo "***SUBTEST: check 2038-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2038-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+
+rsyslog_testbench_require_y2k38_support
+
+
+echo "***SUBTEST: check 2038-12-31"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2038-12-31 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="365"
+cmp_exact
+
+
+echo "***SUBTEST: check 2040-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2040-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+
+echo "***SUBTEST: check 2040-12-31"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2040-12-31 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="366"
+cmp_exact
+
+
+echo "***SUBTEST: check 2100-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2100-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="001"
+cmp_exact
+
+exit_test
diff --git a/tests/timegenerated-utc-legacy.sh b/tests/timegenerated-utc-legacy.sh
new file mode 100755
index 0000000..fb77a43
--- /dev/null
+++ b/tests/timegenerated-utc-legacy.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# added 2016-03-22 by RGerhards, released under ASL 2.0
+#
+# NOTE: faketime does NOT properly support subseconds,
+# so we must ensure we do not use them. Actually, what we
+# see is uninitialized data value in tv_usec, which goes
+# away as soon as we do not run under faketime control.
+# FOR THE SAME REASON, there is NO VALGRIND EQUIVALENT
+# of this test, as valgrind would abort with reports
+# of faketime.
+#
+# IMPORTANT: we use legacy style for the template to ensure
+# that subseconds works properly for this as well. This is
+# a frequent use case.
+#
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+export TZ=TEST+02:00
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%timegenerated:::date-utc%\n"
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+
+echo "***SUBTEST: check 2016-03-01"
+FAKETIME='2016-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="Mar 1 14:00:00"
+cmp_exact
+exit_test
diff --git a/tests/timegenerated-utc.sh b/tests/timegenerated-utc.sh
new file mode 100755
index 0000000..6134911
--- /dev/null
+++ b/tests/timegenerated-utc.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+
+# NOTE: faketime does NOT properly support subseconds,
+# so we must ensure we do not use them. Actually, what we
+# see is uninitialized data value in tv_usec, which goes
+# away as soon as we do not run under faketime control.
+# FOR THE SAME REASON, there is NO VALGRIND EQUIVALENT
+# of this test, as valgrind would abort with reports
+# of faketime.
+. ${srcdir:=.}/diag.sh init
+. $srcdir/faketime_common.sh
+
+export TZ=TEST+02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="list") {
+ property(name="timegenerated" date.inUTC="on")
+ constant(value="\n")
+}
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+echo "***SUBTEST: check 2016-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "Mar 1 14:00:00" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+exit_test
diff --git a/tests/timegenerated-uxtimestamp-invld.sh b/tests/timegenerated-uxtimestamp-invld.sh
new file mode 100755
index 0000000..7c07d6e
--- /dev/null
+++ b/tests/timegenerated-uxtimestamp-invld.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-02 by RGerhards, released under ASL 2.0
+# the key point of this test is that we do not abort and
+# instead provide the defined return value (0)
+# requires faketime
+echo \[timegenerated-uxtimestamp-invld\]: check invalid dates with uxtimestamp format
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=UTC+00:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%timegenerated:::date-unixtimestamp%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+
+
+echo "***SUBTEST: check 1800-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1800-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="0"
+cmp_exact
+
+
+echo "***SUBTEST: check 1960-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1960-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="0"
+cmp_exact
+
+
+echo "***SUBTEST: check 2101-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2101-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="0"
+cmp_exact
+
+
+echo "***SUBTEST: check 2500-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2500-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="0"
+cmp_exact
+
+exit_test
diff --git a/tests/timegenerated-uxtimestamp.sh b/tests/timegenerated-uxtimestamp.sh
new file mode 100755
index 0000000..5fda9bf
--- /dev/null
+++ b/tests/timegenerated-uxtimestamp.sh
@@ -0,0 +1,207 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-03-02 by RGerhards, released under ASL 2.0
+# Note: we run several subtests here in order to save us
+# from creating additional tests
+# requires faketime
+echo \[timegenerated-uxtimestamp\]: check valid dates with uxtimestamp format
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=UTC+00:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%timegenerated:::date-unixtimestamp%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+
+
+echo "***SUBTEST: check 1970-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='1970-01-01 00:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "0" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2000-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2000-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "951912000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2016-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1451649600" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2016-02-29"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-02-29 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1456747200" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2016-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1456833600" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2016-03-03"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-03-03 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1457006400" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2016-12-31"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2016-12-31 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1483185600" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2017-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2017-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1483272000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2020-03-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2020-03-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "1583064000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2038-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2038-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "2145960000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+rsyslog_testbench_require_y2k38_support
+
+echo "***SUBTEST: check 2040-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2040-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "2209032000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ exit 1
+fi;
+
+
+echo "***SUBTEST: check 2100-01-01"
+rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest
+FAKETIME='2100-01-01 12:00:00' startup
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+echo "4102488000" | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:"
+ date -d @$(pwd $RSYSLOG_OUT_LOG)
+ cat $RSYSLOG_OUT_LOG
+ exit 1
+fi;
+
+
+exit_test
diff --git a/tests/timegenerated-ymd.sh b/tests/timegenerated-ymd.sh
new file mode 100755
index 0000000..48779ed
--- /dev/null
+++ b/tests/timegenerated-ymd.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# test many concurrent tcp connections
+# addd 2016-02-23 by RGerhards, released under ASL 2.0
+# requires faketime
+echo \[timegenerated-ymd\]: check customized format \(Y-m-d\)
+. ${srcdir:=.}/diag.sh init
+
+. $srcdir/faketime_common.sh
+
+export TZ=TEST-02:00
+
+generate_conf
+add_conf '
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string"
+ string="%timegenerated:::date-year%-%timegenerated:::date-month%-%timegenerated:::date-day%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file=`echo $RSYSLOG_OUT_LOG`)
+'
+FAKETIME='2016-01-01 01:00:00' startup
+# what we send actually is irrelevant, as we just use system properties.
+# but we need to send one message in order to gain output!
+tcpflood -m1
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="2016-01-01"
+cmp_exact
+
+
+exit_test
diff --git a/tests/timereported-utc-legacy.sh b/tests/timereported-utc-legacy.sh
new file mode 100755
index 0000000..5b85eb5
--- /dev/null
+++ b/tests/timereported-utc-legacy.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string"
+ string="%timereported:::date-rfc3339,date-utc%\n")
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+
+echo "*** SUBTEST 2003 ****"
+startup
+injectmsg_literal "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+injectmsg_literal "<165>1 2016-03-01T12:00:00-02:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+injectmsg_literal "<165>1 2016-03-01T12:00:00Z 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+shutdown_when_empty
+wait_shutdown
+export EXPECTED="2003-08-24T12:14:15.000003+00:00
+2016-03-01T14:00:00.000000+00:00
+2016-03-01T12:00:00.000000+00:00"
+cmp_exact
+
+exit_test
diff --git a/tests/timereported-utc-vg.sh b/tests/timereported-utc-vg.sh
new file mode 100755
index 0000000..9392f0b
--- /dev/null
+++ b/tests/timereported-utc-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+export USE_VALGRIND="YES"
+source ${srcdir:-.}/timereported-utc.sh
diff --git a/tests/timereported-utc.sh b/tests/timereported-utc.sh
new file mode 100755
index 0000000..4c8a189
--- /dev/null
+++ b/tests/timereported-utc.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# addd 2016-03-22 by RGerhards, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=3
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+template(name="outfmt" type="list") {
+ property(name="timereported" dateformat="rfc3339" date.inUTC="on")
+ constant(value="\n")
+}
+:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
+ file="'$RSYSLOG_OUT_LOG'")
+'
+
+startup
+injectmsg_literal "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+injectmsg_literal "<165>1 2016-03-01T12:00:00-02:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+injectmsg_literal "<165>1 2016-03-01T12:00:00Z 192.0.2.1 tcpflood 8710 - - msgnum:0000000"
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="2003-08-24T12:14:15.000003+00:00
+2016-03-01T14:00:00.000000+00:00
+2016-03-01T12:00:00.000000+00:00"
+cmp_exact
+exit_test
diff --git a/tests/timestamp-3164.sh b/tests/timestamp-3164.sh
new file mode 100755
index 0000000..49a6c3a
--- /dev/null
+++ b/tests/timestamp-3164.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# add 2018-06-25 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-rfc3164%\n")
+
+:syslogtag, contains, "TAG" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+injectmsg_literal "<167>Jan 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Feb 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Mar 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Apr 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>May 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Jun 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Jul 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Aug 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Sep 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Oct 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Nov 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Dec 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Jan 6 16:57:54 172.20.245.8 TAG: MSG"
+injectmsg_literal "<167>Jan 16 16:57:54 172.20.245.8 TAG: MSG"
+shutdown_when_empty
+wait_shutdown
+
+echo 'Jan 6 16:57:54
+Feb 6 16:57:54
+Mar 6 16:57:54
+Apr 6 16:57:54
+May 6 16:57:54
+Jun 6 16:57:54
+Jul 6 16:57:54
+Aug 6 16:57:54
+Sep 6 16:57:54
+Oct 6 16:57:54
+Nov 6 16:57:54
+Dec 6 16:57:54
+Jan 6 16:57:54
+Jan 16 16:57:54' | cmp - $RSYSLOG_OUT_LOG
+if [ ! $? -eq 0 ]; then
+ echo "invalid response generated, $RSYSLOG_OUT_LOG is:"
+ cat $RSYSLOG_OUT_LOG
+ error_exit 1
+fi;
+
+exit_test
diff --git a/tests/timestamp-3339.sh b/tests/timestamp-3339.sh
new file mode 100755
index 0000000..2eb42be
--- /dev/null
+++ b/tests/timestamp-3339.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# add 2018-06-25 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-rfc3339%\n")
+
+:syslogtag, contains, "su" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+'
+startup
+injectmsg_literal "<34>1 2003-11-11T22:14:15.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-01-11T22:14:15.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-01T22:04:15.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-11T02:14:15.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-11T22:04:05.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-11T22:04:05.003+02:00 mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-11T22:04:05.003+01:30 mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-11-11T22:04:05.123456+01:30 mymachine.example.com su - ID47 - MSG"
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='2003-11-11T22:14:15.003Z
+2003-01-11T22:14:15.003Z
+2003-11-01T22:04:15.003Z
+2003-11-11T02:14:15.003Z
+2003-11-11T22:04:05.003Z
+2003-11-11T22:04:05.003+02:00
+2003-11-11T22:04:05.003+01:30
+2003-11-11T22:04:05.123456+01:30'
+cmp_exact
+exit_test
diff --git a/tests/timestamp-isoweek.sh b/tests/timestamp-isoweek.sh
new file mode 100755
index 0000000..43c8fd9
--- /dev/null
+++ b/tests/timestamp-isoweek.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# add 2021-12-27 by Mattia Barbon, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-iso-week-year%/%timestamp:::date-iso-week%\n")
+
+:syslogtag, contains, "su" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+injectmsg_literal "<34>1 1971-01-01T12:34:56.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2021-12-02T12:34:56.123456Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2099-12-31T12:34:56Z mymachine.example.com su - ID47 - MSG"
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='1970/53
+2021/48
+2099/53'
+cmp_exact
+exit_test
diff --git a/tests/timestamp-mysql.sh b/tests/timestamp-mysql.sh
new file mode 100755
index 0000000..57766e7
--- /dev/null
+++ b/tests/timestamp-mysql.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# add 2018-06-25 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-mysql%\n")
+
+:syslogtag, contains, "su" action(type="omfile" file="'$RSYSLOG_OUT_LOG'"
+ template="outfmt")
+
+'
+startup
+injectmsg_literal "<34>1 2003-01-23T12:34:56.003Z mymachine.example.com su - ID47 - MSG\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='20030123123456'
+cmp_exact
+exit_test
diff --git a/tests/timestamp-pgsql.sh b/tests/timestamp-pgsql.sh
new file mode 100755
index 0000000..f92a197
--- /dev/null
+++ b/tests/timestamp-pgsql.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# add 2018-06-27 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-pgsql%\n")
+
+:syslogtag, contains, "su" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+injectmsg_literal "<34>1 2003-01-23T12:34:56.003Z mymachine.example.com su - ID47 - MSG\""
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='2003-01-23 12:34:56'
+cmp_exact
+exit_test
diff --git a/tests/timestamp-subseconds.sh b/tests/timestamp-subseconds.sh
new file mode 100755
index 0000000..c114900
--- /dev/null
+++ b/tests/timestamp-subseconds.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# add 2018-06-25 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+template(name="outfmt" type="string" string="%timestamp:::date-subseconds%\n")
+
+:syslogtag, contains, "su" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`
+ template="outfmt")
+
+
+'
+startup
+injectmsg_literal "<34>1 2003-01-23T12:34:56.003Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-01-23T12:34:56.123456Z mymachine.example.com su - ID47 - MSG"
+injectmsg_literal "<34>1 2003-01-23T12:34:56Z mymachine.example.com su - ID47 - MSG"
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED='003
+123456
+0'
+cmp_exact
+exit_test
diff --git a/tests/tls-certs/ca-fail.pem b/tests/tls-certs/ca-fail.pem
new file mode 100644
index 0000000..7318f36
--- /dev/null
+++ b/tests/tls-certs/ca-fail.pem
@@ -0,0 +1,3 @@
+-----BEGIN CERTIFICATE-----
+this is an invalid cert
+-----END CERTIFICATE-----
diff --git a/tests/tls-certs/ca-key.pem b/tests/tls-certs/ca-key.pem
new file mode 100644
index 0000000..829c063
--- /dev/null
+++ b/tests/tls-certs/ca-key.pem
@@ -0,0 +1,190 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:c7:03:50:9e:34:8d:f4:7a:7e:ce:28:62:7f:a5:6c
+ 8d:48:7f:6b:9f:0f:33:e9:e8:03:c5:d4:e3:b4:e2:22
+ 72:10:36:fc:b5:4f:68:66:58:79:c2:34:18:7f:d4:b6
+ 44:60:33:af:64:16:ea:3a:75:16:96:be:bd:32:a7:e5
+ cf:7c:69:40:70:57:0f:83:a7:18:28:4a:18:c9:bd:7c
+ 1e:c4:d1:7b:2b:80:71:d0:5c:61:06:20:d9:97:66:02
+ ab:6a:78:70:2a:71:be:f0:48:40:7c:5e:e5:cb:74:3d
+ 85:96:c7:28:dc:66:93:df:31:4d:bf:bb:7b:40:50:d6
+ d5:bd:ad:4f:ff:76:c3:e4:06:b4:8d:53:af:92:c2:31
+ 56:c8:49:11:92:43:38:42:bf:6f:65:dd:4b:56:b7:84
+ 8a:03:d5:bc:ca:18:39:cc:c2:64:30:4c:5a:50:95:6d
+ 56:24:45:94:01:73:2a:b5:15:28:5a:99:f2:cb:33:cb
+ 6c:97:21:c4:cb:b2:42:49:73:98:9f:f2:8e:5c:a5:60
+ ab:6d:c5:d2:6f:94:ec:1c:0f:b8:14:73:81:ea:8b:b4
+ cf:bf:ec:dc:bc:18:8e:87:f4:e7:a6:72:8b:18:f4:2c
+ ce:2c:4d:82:04:b6:d0:ee:2c:44:51:bd:84:c8:86:d2
+ e1:94:0d:81:59:f0:1f:b9:6f:5b:1a:ea:20:d0:2f:71
+ 1a:9b:7d:f6:f9:e2:1c:99:4a:98:c9:ac:ab:3e:61:10
+ 32:d8:ce:25:04:7e:3e:6a:cd:2c:4a:31:c0:36:54:27
+ 8e:d4:38:1a:8d:27:9d:87:5d:d5:37:fb:16:53:29:39
+ 68:a0:3b:d6:2e:34:0a:7a:78:a0:af:ee:cd:e6:16:ee
+ f5:a5:fe:db:42:10:57:3a:c7:ca:73:78:c7:68:06:3b
+ f5:25:df:61:0b:46:76:52:0b:6d:0b:f2:a7:31:32:97
+ df:2e:8d:47:53:d5:16:30:d0:dc:c2:00:ec:18:71:8f
+ 9d:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 25:31:61:67:af:ba:b7:ee:0c:b4:ca:a7:5d:e3:b4:9d
+ d2:e6:bd:5e:44:a1:17:1d:dd:56:a3:aa:ca:ab:58:74
+ a8:c3:1e:07:64:87:c6:58:d2:a8:90:c3:e3:60:05:90
+ 51:ca:57:05:05:a3:50:b9:81:37:3a:fe:70:f1:1f:e9
+ de:fe:6c:a4:92:20:bc:22:06:49:c1:4f:50:a4:b1:05
+ af:12:d7:4a:11:ff:33:49:90:78:6c:bb:3d:a8:3a:e7
+ 7e:46:73:ef:fa:c2:0c:75:f4:57:4a:04:f8:39:09:26
+ 66:3f:62:4b:8e:80:24:3e:3a:a1:92:90:3e:3c:dd:69
+ a4:c1:37:2a:2f:2f:fc:f5:a3:d8:a5:c3:32:52:48:96
+ 47:68:20:78:8d:47:7e:71:f8:87:b9:0b:d3:71:08:bc
+ 22:6b:57:95:0d:61:ff:fa:74:6e:f2:56:0e:a9:5e:7d
+ b2:d9:ae:07:77:56:8b:f1:20:51:8e:63:e9:c6:0c:46
+ 32:3f:da:3d:97:2a:7d:8d:44:42:63:ad:55:a8:79:13
+ 41:35:e0:85:55:c0:30:94:1d:95:f0:e9:55:4e:c0:cf
+ ce:39:f3:18:38:e2:bb:d5:b3:08:c2:eb:cb:20:37:08
+ 58:0d:52:bc:ee:45:bc:56:21:31:3c:d3:ee:02:cb:71
+ ea:59:d7:d5:c2:9c:49:f5:de:5b:ae:70:cc:2f:8a:95
+ 92:aa:e7:ee:01:84:32:62:b6:81:99:21:21:fa:62:55
+ 18:22:03:9f:9b:d8:db:09:14:28:3f:ec:2e:c7:d1:37
+ 63:8d:dd:bf:2d:7a:9f:50:55:b2:46:a8:fc:f4:57:86
+ c7:f6:06:80:15:a4:13:53:ee:d8:bc:1e:ea:6c:4b:bc
+ 89:24:fb:54:da:9b:c2:35:7f:f7:f1:7b:b3:8b:47:51
+ 81:38:c4:85:90:0c:44:52:f1:67:98:37:13:cb:3f:ad
+ 8f:31:60:16:e5:25:18:fd:11:c5:c8:6c:fd:1c:eb:a1
+
+
+prime1:
+ 00:ca:ea:a1:15:94:16:a5:cd:a2:81:65:af:d5:41:97
+ 15:cb:e9:2f:93:83:7d:7e:58:90:92:de:1a:04:17:94
+ 9b:11:cb:39:6a:55:a0:8d:71:c4:37:eb:70:08:6b:ce
+ 04:a7:e6:e6:85:65:7d:73:d1:72:7d:6d:d5:75:76:4a
+ b0:ef:d7:40:fe:25:4f:50:08:93:b8:f3:65:01:05:5d
+ e5:62:5f:88:d5:2d:7f:1b:d9:3f:24:0d:37:35:02:ba
+ b5:df:0d:8c:ed:66:5d:1a:54:60:04:14:6f:4d:b1:b7
+ 4d:27:c5:d2:a9:85:2b:4e:d0:bf:7d:3e:40:b1:4c:16
+ af:e7:77:af:81:96:fc:28:e8:b4:22:2e:f3:92:18:21
+ ff:0c:38:36:be:26:4c:ac:c3:2a:28:b2:eb:ae:4d:dd
+ cc:84:5e:87:86:d6:7a:c6:a5:38:3a:95:8f:0d:38:75
+ 85:a8:ff:42:98:aa:6b:49:6f:7a:93:60:b6:85:b6:d7
+ d7:
+
+prime2:
+ 00:fb:13:43:33:54:58:5a:6a:3a:ae:da:cb:9b:2a:a0
+ b5:05:29:59:8d:d9:77:d8:fc:40:35:de:53:34:09:a6
+ d7:3a:b8:19:a8:cb:90:13:15:4d:ef:7d:7a:c0:05:3b
+ 53:a7:0f:ef:0e:43:0e:b3:20:2e:24:9d:29:a9:df:ad
+ 0b:91:12:41:5e:c0:3c:ab:3c:cd:5e:af:be:18:65:4b
+ 1d:de:fb:6d:ca:36:d3:95:b6:0e:25:0b:94:e9:86:5f
+ dd:bd:3d:96:e2:c4:6e:a1:87:5c:b7:65:f5:ce:4c:7d
+ fc:03:9e:e6:21:ef:d3:c5:9d:88:b7:4d:67:5d:5c:f5
+ 57:95:37:8f:0d:ad:30:3d:ff:93:55:2b:8b:44:8b:76
+ aa:40:1e:80:86:cc:c4:39:b7:a9:e0:65:77:f6:70:68
+ 42:33:ee:c1:23:b1:a8:84:39:c6:92:a0:2c:74:db:cb
+ e2:7d:b7:d6:12:d7:d0:90:b8:46:88:5f:46:02:e3:55
+ ab:
+
+coefficient:
+ 30:6c:98:d6:5e:3f:9c:83:14:79:60:15:5d:b8:4c:8b
+ 92:f4:c0:62:23:97:be:96:21:26:28:7d:38:08:58:b7
+ 72:04:e4:c3:73:2d:63:23:38:94:89:c6:08:93:44:ad
+ 9f:3d:a4:ad:67:01:89:4d:bf:41:d5:29:72:f7:a3:9b
+ 7d:b0:6b:34:96:27:e9:cf:99:00:b9:ae:80:ed:55:15
+ 32:f4:77:2f:c2:fb:53:4f:9f:ba:08:31:42:12:ee:26
+ aa:b5:87:f1:7a:a7:7e:94:c9:65:ee:8b:7c:bc:73:14
+ 58:4b:d4:fc:82:26:11:75:18:5b:25:0c:4b:c6:80:ff
+ 24:75:d7:f0:c1:4e:00:e6:6d:45:1a:81:7b:0b:1c:77
+ 32:af:8a:8b:d5:b0:31:53:ad:68:35:ac:23:de:f1:f4
+ b1:1c:5e:ff:33:69:9b:65:d9:8e:1f:65:b4:77:ee:3a
+ 80:7f:cd:d3:6e:2e:1d:6c:f7:bb:e7:39:b2:93:3f:33
+
+
+exp1:
+ 04:86:d3:6d:1d:ce:9b:88:48:d5:c6:24:f4:06:f0:8d
+ e5:ec:9f:c9:14:a7:da:07:b3:c1:f2:fe:75:94:e9:15
+ c4:81:da:18:0b:2c:f7:ba:cf:fb:c7:5e:ca:71:4d:39
+ 41:5d:9f:4a:de:86:bb:ec:b2:37:26:1a:1a:f2:b6:9b
+ d7:dd:df:6f:4b:f9:c6:f9:4a:02:58:3b:aa:98:2a:0e
+ 11:f1:bb:a5:b5:cc:1e:1c:ec:91:ab:51:cd:f6:ef:9f
+ 5b:08:7c:5a:57:6c:40:48:1d:94:39:b8:79:ed:3a:ff
+ 97:a1:8c:1f:87:fe:fd:55:1e:d0:76:71:0f:03:79:86
+ 17:0d:ce:76:7f:9d:c4:73:dc:80:de:b7:44:4d:11:85
+ 15:0a:b3:fd:ed:f0:cb:f1:d6:a0:ed:cc:e0:28:90:88
+ 1d:73:d6:66:25:a6:bb:83:b8:0b:66:86:b8:6e:c8:00
+ 61:52:c0:73:93:69:ad:4b:b5:5a:50:50:02:0f:a0:25
+
+
+exp2:
+ 00:cd:04:b6:ac:14:64:ad:37:ef:41:56:e2:49:8b:2e
+ 7d:82:80:78:63:2f:40:01:0c:42:36:7a:9c:00:73:1d
+ 2c:c5:03:0d:d8:da:98:84:2c:b2:5e:2c:5d:6e:ad:16
+ fb:c1:00:6e:d9:7b:82:66:5c:91:b1:4e:30:76:49:72
+ 99:6e:55:b4:d1:75:32:55:35:aa:11:76:7a:48:9b:76
+ 12:27:41:b2:2e:1c:44:fc:0c:14:52:c5:b9:4c:53:70
+ b6:b5:4f:b4:84:e9:97:d9:08:9a:7a:1b:a4:f3:57:5c
+ cc:cb:fc:15:b9:82:87:af:e7:6a:7b:1b:96:9b:13:4c
+ 37:bf:5e:05:cf:4a:2b:89:84:c7:bf:15:76:7c:7b:51
+ 63:c6:45:e1:f7:b0:ff:4e:8e:1e:06:61:74:ea:e4:71
+ 0e:16:30:10:c0:5f:d2:d6:5e:03:3b:39:d5:f3:7a:83
+ 6b:27:f3:54:b8:40:48:4b:d4:5d:ab:ff:f8:40:65:78
+ 4f:
+
+
+Public Key ID: 0C:11:36:9D:B0:9C:05:44:64:AC:97:26:40:C0:28:53:23:9D:8E:9A
+Public key's random art:
++--[ RSA 3072]----+
+|==+. =%=.. |
+|+o+. +.*o |
+|.+ . .=. |
+|. . o +o |
+|.. + S |
+|E |
+| |
+| |
+| |
++-----------------+
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEAxwNQnjSN9Hp+zihif6VsjUh/a58PM+noA8XU47TiInIQNvy1
+T2hmWHnCNBh/1LZEYDOvZBbqOnUWlr69Mqflz3xpQHBXD4OnGChKGMm9fB7E0Xsr
+gHHQXGEGINmXZgKranhwKnG+8EhAfF7ly3Q9hZbHKNxmk98xTb+7e0BQ1tW9rU//
+dsPkBrSNU6+SwjFWyEkRkkM4Qr9vZd1LVreEigPVvMoYOczCZDBMWlCVbVYkRZQB
+cyq1FShamfLLM8tslyHEy7JCSXOYn/KOXKVgq23F0m+U7BwPuBRzgeqLtM+/7Ny8
+GI6H9OemcosY9CzOLE2CBLbQ7ixEUb2EyIbS4ZQNgVnwH7lvWxrqINAvcRqbffb5
+4hyZSpjJrKs+YRAy2M4lBH4+as0sSjHANlQnjtQ4Go0nnYdd1Tf7FlMpOWigO9Yu
+NAp6eKCv7s3mFu71pf7bQhBXOsfKc3jHaAY79SXfYQtGdlILbQvypzEyl98ujUdT
+1RYw0NzCAOwYcY+dAgMBAAECggGAJTFhZ6+6t+4MtMqnXeO0ndLmvV5EoRcd3Vaj
+qsqrWHSowx4HZIfGWNKokMPjYAWQUcpXBQWjULmBNzr+cPEf6d7+bKSSILwiBknB
+T1CksQWvEtdKEf8zSZB4bLs9qDrnfkZz7/rCDHX0V0oE+DkJJmY/YkuOgCQ+OqGS
+kD483WmkwTcqLy/89aPYpcMyUkiWR2ggeI1HfnH4h7kL03EIvCJrV5UNYf/6dG7y
+Vg6pXn2y2a4Hd1aL8SBRjmPpxgxGMj/aPZcqfY1EQmOtVah5E0E14IVVwDCUHZXw
+6VVOwM/OOfMYOOK71bMIwuvLIDcIWA1SvO5FvFYhMTzT7gLLcepZ19XCnEn13luu
+cMwvipWSqufuAYQyYraBmSEh+mJVGCIDn5vY2wkUKD/sLsfRN2ON3b8tep9QVbJG
+qPz0V4bH9gaAFaQTU+7YvB7qbEu8iST7VNqbwjV/9/F7s4tHUYE4xIWQDERS8WeY
+NxPLP62PMWAW5SUY/RHFyGz9HOuhAoHBAMrqoRWUFqXNooFlr9VBlxXL6S+Tg31+
+WJCS3hoEF5SbEcs5alWgjXHEN+twCGvOBKfm5oVlfXPRcn1t1XV2SrDv10D+JU9Q
+CJO482UBBV3lYl+I1S1/G9k/JA03NQK6td8NjO1mXRpUYAQUb02xt00nxdKphStO
+0L99PkCxTBav53evgZb8KOi0Ii7zkhgh/ww4Nr4mTKzDKiiy665N3cyEXoeG1nrG
+pTg6lY8NOHWFqP9CmKprSW96k2C2hbbX1wKBwQD7E0MzVFhaajqu2subKqC1BSlZ
+jdl32PxANd5TNAmm1zq4GajLkBMVTe99esAFO1OnD+8OQw6zIC4knSmp360LkRJB
+XsA8qzzNXq++GGVLHd77bco205W2DiULlOmGX929PZbixG6hh1y3ZfXOTH38A57m
+Ie/TxZ2It01nXVz1V5U3jw2tMD3/k1Uri0SLdqpAHoCGzMQ5t6ngZXf2cGhCM+7B
+I7GohDnGkqAsdNvL4n231hLX0JC4RohfRgLjVasCgcAEhtNtHc6biEjVxiT0BvCN
+5eyfyRSn2gezwfL+dZTpFcSB2hgLLPe6z/vHXspxTTlBXZ9K3oa77LI3Jhoa8rab
+193fb0v5xvlKAlg7qpgqDhHxu6W1zB4c7JGrUc32759bCHxaV2xASB2UObh57Tr/
+l6GMH4f+/VUe0HZxDwN5hhcNznZ/ncRz3IDet0RNEYUVCrP97fDL8dag7czgKJCI
+HXPWZiWmu4O4C2aGuG7IAGFSwHOTaa1LtVpQUAIPoCUCgcEAzQS2rBRkrTfvQVbi
+SYsufYKAeGMvQAEMQjZ6nABzHSzFAw3Y2piELLJeLF1urRb7wQBu2XuCZlyRsU4w
+dklymW5VtNF1MlU1qhF2ekibdhInQbIuHET8DBRSxblMU3C2tU+0hOmX2Qiaehuk
+81dczMv8FbmCh6/nansblpsTTDe/XgXPSiuJhMe/FXZ8e1FjxkXh97D/To4eBmF0
+6uRxDhYwEMBf0tZeAzs51fN6g2sn81S4QEhL1F2r//hAZXhPAoHAMGyY1l4/nIMU
+eWAVXbhMi5L0wGIjl76WISYofTgIWLdyBOTDcy1jIziUicYIk0Stnz2krWcBiU2/
+QdUpcvejm32wazSWJ+nPmQC5roDtVRUy9HcvwvtTT5+6CDFCEu4mqrWH8XqnfpTJ
+Ze6LfLxzFFhL1PyCJhF1GFslDEvGgP8kddfwwU4A5m1FGoF7Cxx3Mq+Ki9WwMVOt
+aDWsI97x9LEcXv8zaZtl2Y4fZbR37jqAf83Tbi4dbPe75zmykz8z
+-----END RSA PRIVATE KEY-----
diff --git a/tests/tls-certs/ca.pem b/tests/tls-certs/ca.pem
new file mode 100644
index 0000000..99925c4
--- /dev/null
+++ b/tests/tls-certs/ca.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE9jCCA16gAwIBAgIIWxfM+RyuD1EwDQYJKoZIhvcNAQELBQAwgYsxEzARBgNV
+BAMTCnJzeXNsb2cgY2ExEDAOBgNVBAsTB0FkaXNjb24xFTATBgNVBAoTDEFkaXNj
+b24gR21iSDEYMBYGA1UEBxMPR3Jvc3NyaW5kZXJmZWxkMQswCQYDVQQIEwJCVzEL
+MAkGA1UEBhMCREUxFzAVBgoJkiaJk/IsZAEZFgdyc3lzbG9nMCAXDTE4MDYwNjEy
+MDA1OFoYDzIxMTgwNTEzMTIwMTA1WjCBizETMBEGA1UEAxMKcnN5c2xvZyBjYTEQ
+MA4GA1UECxMHQWRpc2NvbjEVMBMGA1UEChMMQWRpc2NvbiBHbWJIMRgwFgYDVQQH
+Ew9Hcm9zc3JpbmRlcmZlbGQxCzAJBgNVBAgTAkJXMQswCQYDVQQGEwJERTEXMBUG
+CgmSJomT8ixkARkWB3JzeXNsb2cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
+AoIBgQDHA1CeNI30en7OKGJ/pWyNSH9rnw8z6egDxdTjtOIichA2/LVPaGZYecI0
+GH/UtkRgM69kFuo6dRaWvr0yp+XPfGlAcFcPg6cYKEoYyb18HsTReyuAcdBcYQYg
+2ZdmAqtqeHAqcb7wSEB8XuXLdD2Flsco3GaT3zFNv7t7QFDW1b2tT/92w+QGtI1T
+r5LCMVbISRGSQzhCv29l3UtWt4SKA9W8yhg5zMJkMExaUJVtViRFlAFzKrUVKFqZ
+8sszy2yXIcTLskJJc5if8o5cpWCrbcXSb5TsHA+4FHOB6ou0z7/s3LwYjof056Zy
+ixj0LM4sTYIEttDuLERRvYTIhtLhlA2BWfAfuW9bGuog0C9xGpt99vniHJlKmMms
+qz5hEDLYziUEfj5qzSxKMcA2VCeO1DgajSedh13VN/sWUyk5aKA71i40Cnp4oK/u
+zeYW7vWl/ttCEFc6x8pzeMdoBjv1Jd9hC0Z2UgttC/KnMTKX3y6NR1PVFjDQ3MIA
+7Bhxj50CAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zAVBgNVHREEDjAMggpyc3lz
+bG9nIGNhMA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFAwRNp2wnAVEZKyXJkDA
+KFMjnY6aMA0GCSqGSIb3DQEBCwUAA4IBgQCOv2kyg8vZ3jncZuZ4i2k0QbXztZoO
+jMDNqFX2935lK6WrVZ6u1InZzsaqrXXOJions3EvmmAqrdTBW6dyw6V2/lic1gGz
+MhlafAPe0DyQCaXp9iFCH91Hzo94YhuPbne1qdga9jrVTiQIHdIKqVtbiUv7i7mN
+43GssOm4a1guf+Qs5rkuHG4YwiJZhjzhmixfXCerHXykJkpSvBUb6EeKA+p5/w+I
+Wjm9sAkJgqcvrNvOwwBZInU1I56zmM0ZwWucSydf0hgOImpgO5F6KGVQRoZsO9IA
+Iju2RQ1y9qVTNp8evVjIMuqXh5ZtU9ti/buZrjr5Zb601jFLZCMrpDVUcVyHUfOB
+rb3nkUFDcFcrKlfovwp/fvlISKM0bp6pFas5X0FXg3sVVI+iIokmHsmqRUHhjdLX
+t27+/TYpyEkjF1cH3acd7MOcw33KxE/4+qUHT2QU9COPkGu7oPS24qDYnmGPLkev
+ZSmpz4jLTmbCBSRcoOB0Q4K36WnegzVtvd8=
+-----END CERTIFICATE-----
diff --git a/tests/tls-certs/cert-fail.pem b/tests/tls-certs/cert-fail.pem
new file mode 100644
index 0000000..7318f36
--- /dev/null
+++ b/tests/tls-certs/cert-fail.pem
@@ -0,0 +1,3 @@
+-----BEGIN CERTIFICATE-----
+this is an invalid cert
+-----END CERTIFICATE-----
diff --git a/tests/tls-certs/cert.pem b/tests/tls-certs/cert.pem
new file mode 100644
index 0000000..58cdec3
--- /dev/null
+++ b/tests/tls-certs/cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFVzCCA7+gAwIBAgIIWxfNMhQmuncwDQYJKoZIhvcNAQELBQAwgYsxEzARBgNV
+BAMTCnJzeXNsb2cgY2ExEDAOBgNVBAsTB0FkaXNjb24xFTATBgNVBAoTDEFkaXNj
+b24gR21iSDEYMBYGA1UEBxMPR3Jvc3NyaW5kZXJmZWxkMQswCQYDVQQIEwJCVzEL
+MAkGA1UEBhMCREUxFzAVBgoJkiaJk/IsZAEZFgdyc3lzbG9nMCAXDTE4MDYwNjEy
+MDE1NVoYDzIxMTgwNTEzMTIwMjAxWjCBmDEXMBUGA1UEAxMOcnN5c2xvZy1jbGll
+bnQxFTATBgNVBAsTDEFkaXNjb24gR21iSDEVMBMGA1UEChMMQWRpc2NvbiBHbWJI
+MRgwFgYDVQQHEw9Hcm9zc3JpbmRlcmZlbGQxCzAJBgNVBAgTAkJXMQswCQYDVQQG
+EwJERTEbMBkGCgmSJomT8ixkARkWC3JzeXNsb2cuY29tMIIBojANBgkqhkiG9w0B
+AQEFAAOCAY8AMIIBigKCAYEA8nNWVoZwi7fYKSYxm+lidTbMQEHh9pLXV8P1N2FD
+wqhNc6Z71VqQw6gIDyzxBjZf3ldyPb6xAcxikvk2XCxVGqDaP7E1rfnCDSqxcgLG
+r1/TlRH3fFMFPqzMgs0GbDoKi7WuhcNMH1yIRk4uPVSUY3IclcE9sNvMpNVY77c9
+tYeLyoLgG8A2ljlSjbHXDmR8E1C+WcOvjFKQunpv29zIOvfp3Wuw0g3C6E26RyvY
+OnNNq6bmDHXdyIkxYNPwxyfBDGq/WhnrFqQTyEqulVLVVIpK+3fIdtmH/4OpOwxz
+KM0q2k9CzL+AI1JqlFoePeIKYQYAOssUBwB0VBDbhyo8f7txBs6OB1phPcmbkAo2
+bJfL01UT315omqlGWjvvDRjDEeRAfXnWu/UVLIs1MNn09l2+fKwgZyOZIQEk5gGg
+b+xO7pZp5W1IuLxB1DMatQjYK1L1MG8KUebovTyumAj8kOaCJaqa+EWcPvsH2wJb
+zp7JZV7xAMnNQGLHHccY9Iv9AgMBAAGjga0wgaowDAYDVR0TAQH/BAIwADAnBgNV
+HSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwEGCCsGAQUFBwMRMCAGA1UdEQQZMBeC
+FXRlc3RiZW5jaC5yc3lzbG9nLmNvbTAPBgNVHQ8BAf8EBQMDB6AAMB0GA1UdDgQW
+BBTFQ9rF9eWMeqNtrDMOGb1fZ54EYTAfBgNVHSMEGDAWgBQMETadsJwFRGSslyZA
+wChTI52OmjANBgkqhkiG9w0BAQsFAAOCAYEAG9hahjpm74U85pP7/zngEJ5P5nnM
+3aC8u4lDM7kodtnxJWoisbv/EBr6SihpDtfWA6+bAJGGu+4UBUaMyUg8w/FjylHc
+INtljbalRuu7YguL2uLdlDNCxQa1XkWugYMObR6r6OvTPUwK0QakTsZuibRbWBDz
+lWKOoM7ZSxZi9DaeChe3yNSGxJSC9xHZbYYBOP5RjChXTZTKtYZemF2wx6EtWRtc
+vXK3TbnJtDy7SPm60EoFnLXUyywmo5mCUSlx85HinS1DzYo7I1yksWQgdW4XgWId
+9RgwPtP0iZSjrZ1TwKqcvo5jvn96LNCoob+JyhpL+9mFvPc6C3vLOxyG7JZOb7Dn
+IpJf52KeBnLRUoIpp+x1XYptoy1ti7r8YqPYn5EHmPxCDVoujskRSX7ncP3SV1qY
+eEgr94Tw/l8GyiaGyixVl2pAMbzYJtgrzQ9UvZurhSPjApGlm87X5KHHXN/CJTY5
+8t59+qvjESRJk74JNpm1L6X/N7HpAsqcsYjP
+-----END CERTIFICATE-----
diff --git a/tests/tls-certs/certchained.pem b/tests/tls-certs/certchained.pem
new file mode 100644
index 0000000..e35b220
--- /dev/null
+++ b/tests/tls-certs/certchained.pem
@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIIFVzCCA7+gAwIBAgIIWxfNMhQmuncwDQYJKoZIhvcNAQELBQAwgYsxEzARBgNV
+BAMTCnJzeXNsb2cgY2ExEDAOBgNVBAsTB0FkaXNjb24xFTATBgNVBAoTDEFkaXNj
+b24gR21iSDEYMBYGA1UEBxMPR3Jvc3NyaW5kZXJmZWxkMQswCQYDVQQIEwJCVzEL
+MAkGA1UEBhMCREUxFzAVBgoJkiaJk/IsZAEZFgdyc3lzbG9nMCAXDTE4MDYwNjEy
+MDE1NVoYDzIxMTgwNTEzMTIwMjAxWjCBmDEXMBUGA1UEAxMOcnN5c2xvZy1jbGll
+bnQxFTATBgNVBAsTDEFkaXNjb24gR21iSDEVMBMGA1UEChMMQWRpc2NvbiBHbWJI
+MRgwFgYDVQQHEw9Hcm9zc3JpbmRlcmZlbGQxCzAJBgNVBAgTAkJXMQswCQYDVQQG
+EwJERTEbMBkGCgmSJomT8ixkARkWC3JzeXNsb2cuY29tMIIBojANBgkqhkiG9w0B
+AQEFAAOCAY8AMIIBigKCAYEA8nNWVoZwi7fYKSYxm+lidTbMQEHh9pLXV8P1N2FD
+wqhNc6Z71VqQw6gIDyzxBjZf3ldyPb6xAcxikvk2XCxVGqDaP7E1rfnCDSqxcgLG
+r1/TlRH3fFMFPqzMgs0GbDoKi7WuhcNMH1yIRk4uPVSUY3IclcE9sNvMpNVY77c9
+tYeLyoLgG8A2ljlSjbHXDmR8E1C+WcOvjFKQunpv29zIOvfp3Wuw0g3C6E26RyvY
+OnNNq6bmDHXdyIkxYNPwxyfBDGq/WhnrFqQTyEqulVLVVIpK+3fIdtmH/4OpOwxz
+KM0q2k9CzL+AI1JqlFoePeIKYQYAOssUBwB0VBDbhyo8f7txBs6OB1phPcmbkAo2
+bJfL01UT315omqlGWjvvDRjDEeRAfXnWu/UVLIs1MNn09l2+fKwgZyOZIQEk5gGg
+b+xO7pZp5W1IuLxB1DMatQjYK1L1MG8KUebovTyumAj8kOaCJaqa+EWcPvsH2wJb
+zp7JZV7xAMnNQGLHHccY9Iv9AgMBAAGjga0wgaowDAYDVR0TAQH/BAIwADAnBgNV
+HSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwEGCCsGAQUFBwMRMCAGA1UdEQQZMBeC
+FXRlc3RiZW5jaC5yc3lzbG9nLmNvbTAPBgNVHQ8BAf8EBQMDB6AAMB0GA1UdDgQW
+BBTFQ9rF9eWMeqNtrDMOGb1fZ54EYTAfBgNVHSMEGDAWgBQMETadsJwFRGSslyZA
+wChTI52OmjANBgkqhkiG9w0BAQsFAAOCAYEAG9hahjpm74U85pP7/zngEJ5P5nnM
+3aC8u4lDM7kodtnxJWoisbv/EBr6SihpDtfWA6+bAJGGu+4UBUaMyUg8w/FjylHc
+INtljbalRuu7YguL2uLdlDNCxQa1XkWugYMObR6r6OvTPUwK0QakTsZuibRbWBDz
+lWKOoM7ZSxZi9DaeChe3yNSGxJSC9xHZbYYBOP5RjChXTZTKtYZemF2wx6EtWRtc
+vXK3TbnJtDy7SPm60EoFnLXUyywmo5mCUSlx85HinS1DzYo7I1yksWQgdW4XgWId
+9RgwPtP0iZSjrZ1TwKqcvo5jvn96LNCoob+JyhpL+9mFvPc6C3vLOxyG7JZOb7Dn
+IpJf52KeBnLRUoIpp+x1XYptoy1ti7r8YqPYn5EHmPxCDVoujskRSX7ncP3SV1qY
+eEgr94Tw/l8GyiaGyixVl2pAMbzYJtgrzQ9UvZurhSPjApGlm87X5KHHXN/CJTY5
+8t59+qvjESRJk74JNpm1L6X/N7HpAsqcsYjP
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE9jCCA16gAwIBAgIIWxfM+RyuD1EwDQYJKoZIhvcNAQELBQAwgYsxEzARBgNV
+BAMTCnJzeXNsb2cgY2ExEDAOBgNVBAsTB0FkaXNjb24xFTATBgNVBAoTDEFkaXNj
+b24gR21iSDEYMBYGA1UEBxMPR3Jvc3NyaW5kZXJmZWxkMQswCQYDVQQIEwJCVzEL
+MAkGA1UEBhMCREUxFzAVBgoJkiaJk/IsZAEZFgdyc3lzbG9nMCAXDTE4MDYwNjEy
+MDA1OFoYDzIxMTgwNTEzMTIwMTA1WjCBizETMBEGA1UEAxMKcnN5c2xvZyBjYTEQ
+MA4GA1UECxMHQWRpc2NvbjEVMBMGA1UEChMMQWRpc2NvbiBHbWJIMRgwFgYDVQQH
+Ew9Hcm9zc3JpbmRlcmZlbGQxCzAJBgNVBAgTAkJXMQswCQYDVQQGEwJERTEXMBUG
+CgmSJomT8ixkARkWB3JzeXNsb2cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
+AoIBgQDHA1CeNI30en7OKGJ/pWyNSH9rnw8z6egDxdTjtOIichA2/LVPaGZYecI0
+GH/UtkRgM69kFuo6dRaWvr0yp+XPfGlAcFcPg6cYKEoYyb18HsTReyuAcdBcYQYg
+2ZdmAqtqeHAqcb7wSEB8XuXLdD2Flsco3GaT3zFNv7t7QFDW1b2tT/92w+QGtI1T
+r5LCMVbISRGSQzhCv29l3UtWt4SKA9W8yhg5zMJkMExaUJVtViRFlAFzKrUVKFqZ
+8sszy2yXIcTLskJJc5if8o5cpWCrbcXSb5TsHA+4FHOB6ou0z7/s3LwYjof056Zy
+ixj0LM4sTYIEttDuLERRvYTIhtLhlA2BWfAfuW9bGuog0C9xGpt99vniHJlKmMms
+qz5hEDLYziUEfj5qzSxKMcA2VCeO1DgajSedh13VN/sWUyk5aKA71i40Cnp4oK/u
+zeYW7vWl/ttCEFc6x8pzeMdoBjv1Jd9hC0Z2UgttC/KnMTKX3y6NR1PVFjDQ3MIA
+7Bhxj50CAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zAVBgNVHREEDjAMggpyc3lz
+bG9nIGNhMA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFAwRNp2wnAVEZKyXJkDA
+KFMjnY6aMA0GCSqGSIb3DQEBCwUAA4IBgQCOv2kyg8vZ3jncZuZ4i2k0QbXztZoO
+jMDNqFX2935lK6WrVZ6u1InZzsaqrXXOJions3EvmmAqrdTBW6dyw6V2/lic1gGz
+MhlafAPe0DyQCaXp9iFCH91Hzo94YhuPbne1qdga9jrVTiQIHdIKqVtbiUv7i7mN
+43GssOm4a1guf+Qs5rkuHG4YwiJZhjzhmixfXCerHXykJkpSvBUb6EeKA+p5/w+I
+Wjm9sAkJgqcvrNvOwwBZInU1I56zmM0ZwWucSydf0hgOImpgO5F6KGVQRoZsO9IA
+Iju2RQ1y9qVTNp8evVjIMuqXh5ZtU9ti/buZrjr5Zb601jFLZCMrpDVUcVyHUfOB
+rb3nkUFDcFcrKlfovwp/fvlISKM0bp6pFas5X0FXg3sVVI+iIokmHsmqRUHhjdLX
+t27+/TYpyEkjF1cH3acd7MOcw33KxE/4+qUHT2QU9COPkGu7oPS24qDYnmGPLkev
+ZSmpz4jLTmbCBSRcoOB0Q4K36WnegzVtvd8=
+-----END CERTIFICATE-----
diff --git a/tests/tls-certs/key-fail.pem b/tests/tls-certs/key-fail.pem
new file mode 100644
index 0000000..2335af1
--- /dev/null
+++ b/tests/tls-certs/key-fail.pem
@@ -0,0 +1,40 @@
+# first line of Key is invalidated
+-----BEGIN RSA PRIVATE KEY-----
+0000000000000000000000000000000000000000000000000000000000000000
+1VqQw6gIDyzxBjZf3ldyPb6xAcxikvk2XCxVGqDaP7E1rfnCDSqxcgLGr1/TlRH3
+fFMFPqzMgs0GbDoKi7WuhcNMH1yIRk4uPVSUY3IclcE9sNvMpNVY77c9tYeLyoLg
+G8A2ljlSjbHXDmR8E1C+WcOvjFKQunpv29zIOvfp3Wuw0g3C6E26RyvYOnNNq6bm
+DHXdyIkxYNPwxyfBDGq/WhnrFqQTyEqulVLVVIpK+3fIdtmH/4OpOwxzKM0q2k9C
+zL+AI1JqlFoePeIKYQYAOssUBwB0VBDbhyo8f7txBs6OB1phPcmbkAo2bJfL01UT
+315omqlGWjvvDRjDEeRAfXnWu/UVLIs1MNn09l2+fKwgZyOZIQEk5gGgb+xO7pZp
+5W1IuLxB1DMatQjYK1L1MG8KUebovTyumAj8kOaCJaqa+EWcPvsH2wJbzp7JZV7x
+AMnNQGLHHccY9Iv9AgMBAAECggGAY6qwOl+H0pff34KY8Cvv0pmVO3EZ7+ALcEPZ
+AUwVq+a9+CXfUCSr0BK6RWrHJjOiE2fFScajQ0b+2sZh52A+F/U54ub5VyyN7hW3
+3lNv09ZDx0scftouFMa6R6b61fDCNw6X0Nso5teGGci3z3R+j6bwQ0uuDY89wCEI
+L3sXfhFbkQNeF2pbxkOIQUFzU7JRIyuVJJeCCeBDKLV+WFaZZUxWsjQ7+w23KwIQ
+6oMGn3iY3FB+z26AnphvWQunNmeLcq11lpwTpI4XB21FMLFVA4FlawLhMP6ca2OA
+rp1HsTPqthxtFC//KXHinN1AYjQERD2NcWvR6o1GYzcSJo+UHPVq0WZ/qdbdWSd5
+zuqts0diufYcNgrA/vP24cKGEpf58n5itDM+rUMFlR0U/r52xkQ4gKQlCFtcdk6p
+vap/8QWLSYGgQEsamNHJz5jhunES/B9TqldcZTrgciTVjychnPy21vfIB1zCQl3L
+ur8N8hObB2tzrhvwtxpq/SDPsnIBAoHBAP4UzzGg2OD1STUiLBQTqlXWJpLC+mMC
+ct3RBdEPsKSu5A6ZoDXjhCQGqidNzm8zbYqWPlS9UZLpP5vybp19Hi/hEbzbNMgv
+qwfuSl2WBVQcSPA8g5k6n13+MUgMswyr41wt5wZDkVxiIXYKTwDso5WFsP47YYsH
+xyG7tO8N0WcB3b2b6FbryiKDweiJO/oXI+ne/WIEcx8qiWbX0RaZf5ig4MKbESIj
+uVXLoEvrgaSogl3gCssZ/Rhd4hfMEysZgQKBwQD0SAsWOOjZlH44KXHUKvp8zdi1
+0tvRpj8fPzkv8q89rozJ/QEyg89I9PUllT8Kg5AhdWBSAZpeldLtTG6M+ZOaQCS1
+kevmtJZqalEbmxj9JMjDaFLjVfUj4JdNS0vNgwS54XC2TEKmoAwuDfChwAQIVw/a
+Dg7uMnwg5gPuNUEiAbDzbu4N15Ed7ZjU7+YD8TmW3aAfbDo92dKs8BNzMc+x+xPT
+VVUbbL05SeB6t+/sPVzdfb+gEWmPZvxFKbMFGH0CgcEA25yU8ep7SwX4PurIepn8
+0rCFKrlIvqdxLXTruCX9onpgOJZkue9rWdBA5jQESG2FMxJl0czJY1gkWOCU558r
+pmq9cCVwW8+H3xUCRh3TgT3pdWx4usrG0PFTG1mOsVco75XlZ66jR9yx21tRqhTf
+1+90ampdB1Szs96Qp0ekRYqBZNALZIXtcyO7SQjFRIcXzZ+mF0CNWNTlanUEDqqi
+dQQpAUwS5RVHrnaQmM54gh/8frOV4LMX5iXPtI35y3kBAoHBAK3RqZnpar6Pq/R4
+gReQcWZm7qIKZQHbwqSQTzfv/oPsdR+xGK4CHnfyXZGdjhsEHIXCSIRxwY82Gr1h
+mnRTjpS+uaA9MdeafkFAX3A+P1y5VOW+kORUoLcjs2V7g3e7l5xQbuw4fWClF6WZ
+o7TktbndgVkOkc8qOysJoJhaansxKuE8+MT+s7LRAuPZxBjgB7NzBeH2F8c0/HSz
+65MXSYuCdcv1tzZpfIeMKuAHi//UdgTg2n6ihTNV+4GXN1wT3QKBwQCbC2bX/t1p
+0ppb1U428MhnTmj/1SGhklAnl0dugj2zxYfSwBUJwZ7cLXRazCvKggpdO4KTMc4S
+vVt9VIfAig7fhtZvYspKQV9sjsusbjfAuCYgw1k3zh/n66UIirCW8+A9/GbEa2YU
+kXYsIuRqViBBUWp38b9MW+j6r0EJqHdaamZtEoNUwej/tzrbn0bizthgqAMjeEFf
+++oWYiAkjYtJZOTLyoPoxGCX+7/n3CwQugNndupNAGwG+NKD+yb+3OE=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/tls-certs/key.pem b/tests/tls-certs/key.pem
new file mode 100644
index 0000000..4d63250
--- /dev/null
+++ b/tests/tls-certs/key.pem
@@ -0,0 +1,190 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:f2:73:56:56:86:70:8b:b7:d8:29:26:31:9b:e9:62
+ 75:36:cc:40:41:e1:f6:92:d7:57:c3:f5:37:61:43:c2
+ a8:4d:73:a6:7b:d5:5a:90:c3:a8:08:0f:2c:f1:06:36
+ 5f:de:57:72:3d:be:b1:01:cc:62:92:f9:36:5c:2c:55
+ 1a:a0:da:3f:b1:35:ad:f9:c2:0d:2a:b1:72:02:c6:af
+ 5f:d3:95:11:f7:7c:53:05:3e:ac:cc:82:cd:06:6c:3a
+ 0a:8b:b5:ae:85:c3:4c:1f:5c:88:46:4e:2e:3d:54:94
+ 63:72:1c:95:c1:3d:b0:db:cc:a4:d5:58:ef:b7:3d:b5
+ 87:8b:ca:82:e0:1b:c0:36:96:39:52:8d:b1:d7:0e:64
+ 7c:13:50:be:59:c3:af:8c:52:90:ba:7a:6f:db:dc:c8
+ 3a:f7:e9:dd:6b:b0:d2:0d:c2:e8:4d:ba:47:2b:d8:3a
+ 73:4d:ab:a6:e6:0c:75:dd:c8:89:31:60:d3:f0:c7:27
+ c1:0c:6a:bf:5a:19:eb:16:a4:13:c8:4a:ae:95:52:d5
+ 54:8a:4a:fb:77:c8:76:d9:87:ff:83:a9:3b:0c:73:28
+ cd:2a:da:4f:42:cc:bf:80:23:52:6a:94:5a:1e:3d:e2
+ 0a:61:06:00:3a:cb:14:07:00:74:54:10:db:87:2a:3c
+ 7f:bb:71:06:ce:8e:07:5a:61:3d:c9:9b:90:0a:36:6c
+ 97:cb:d3:55:13:df:5e:68:9a:a9:46:5a:3b:ef:0d:18
+ c3:11:e4:40:7d:79:d6:bb:f5:15:2c:8b:35:30:d9:f4
+ f6:5d:be:7c:ac:20:67:23:99:21:01:24:e6:01:a0:6f
+ ec:4e:ee:96:69:e5:6d:48:b8:bc:41:d4:33:1a:b5:08
+ d8:2b:52:f5:30:6f:0a:51:e6:e8:bd:3c:ae:98:08:fc
+ 90:e6:82:25:aa:9a:f8:45:9c:3e:fb:07:db:02:5b:ce
+ 9e:c9:65:5e:f1:00:c9:cd:40:62:c7:1d:c7:18:f4:8b
+ fd:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 63:aa:b0:3a:5f:87:d2:97:df:df:82:98:f0:2b:ef:d2
+ 99:95:3b:71:19:ef:e0:0b:70:43:d9:01:4c:15:ab:e6
+ bd:f8:25:df:50:24:ab:d0:12:ba:45:6a:c7:26:33:a2
+ 13:67:c5:49:c6:a3:43:46:fe:da:c6:61:e7:60:3e:17
+ f5:39:e2:e6:f9:57:2c:8d:ee:15:b7:de:53:6f:d3:d6
+ 43:c7:4b:1c:7e:da:2e:14:c6:ba:47:a6:fa:d5:f0:c2
+ 37:0e:97:d0:db:28:e6:d7:86:19:c8:b7:cf:74:7e:8f
+ a6:f0:43:4b:ae:0d:8f:3d:c0:21:08:2f:7b:17:7e:11
+ 5b:91:03:5e:17:6a:5b:c6:43:88:41:41:73:53:b2:51
+ 23:2b:95:24:97:82:09:e0:43:28:b5:7e:58:56:99:65
+ 4c:56:b2:34:3b:fb:0d:b7:2b:02:10:ea:83:06:9f:78
+ 98:dc:50:7e:cf:6e:80:9e:98:6f:59:0b:a7:36:67:8b
+ 72:ad:75:96:9c:13:a4:8e:17:07:6d:45:30:b1:55:03
+ 81:65:6b:02:e1:30:fe:9c:6b:63:80:ae:9d:47:b1:33
+ ea:b6:1c:6d:14:2f:ff:29:71:e2:9c:dd:40:62:34:04
+ 44:3d:8d:71:6b:d1:ea:8d:46:63:37:12:26:8f:94:1c
+ f5:6a:d1:66:7f:a9:d6:dd:59:27:79:ce:ea:ad:b3:47
+ 62:b9:f6:1c:36:0a:c0:fe:f3:f6:e1:c2:86:12:97:f9
+ f2:7e:62:b4:33:3e:ad:43:05:95:1d:14:fe:be:76:c6
+ 44:38:80:a4:25:08:5b:5c:76:4e:a9:bd:aa:7f:f1:05
+ 8b:49:81:a0:40:4b:1a:98:d1:c9:cf:98:e1:ba:71:12
+ fc:1f:53:aa:57:5c:65:3a:e0:72:24:d5:8f:27:21:9c
+ fc:b6:d6:f7:c8:07:5c:c2:42:5d:cb:ba:bf:0d:f2:13
+ 9b:07:6b:73:ae:1b:f0:b7:1a:6a:fd:20:cf:b2:72:01
+
+
+prime1:
+ 00:fe:14:cf:31:a0:d8:e0:f5:49:35:22:2c:14:13:aa
+ 55:d6:26:92:c2:fa:63:02:72:dd:d1:05:d1:0f:b0:a4
+ ae:e4:0e:99:a0:35:e3:84:24:06:aa:27:4d:ce:6f:33
+ 6d:8a:96:3e:54:bd:51:92:e9:3f:9b:f2:6e:9d:7d:1e
+ 2f:e1:11:bc:db:34:c8:2f:ab:07:ee:4a:5d:96:05:54
+ 1c:48:f0:3c:83:99:3a:9f:5d:fe:31:48:0c:b3:0c:ab
+ e3:5c:2d:e7:06:43:91:5c:62:21:76:0a:4f:00:ec:a3
+ 95:85:b0:fe:3b:61:8b:07:c7:21:bb:b4:ef:0d:d1:67
+ 01:dd:bd:9b:e8:56:eb:ca:22:83:c1:e8:89:3b:fa:17
+ 23:e9:de:fd:62:04:73:1f:2a:89:66:d7:d1:16:99:7f
+ 98:a0:e0:c2:9b:11:22:23:b9:55:cb:a0:4b:eb:81:a4
+ a8:82:5d:e0:0a:cb:19:fd:18:5d:e2:17:cc:13:2b:19
+ 81:
+
+prime2:
+ 00:f4:48:0b:16:38:e8:d9:94:7e:38:29:71:d4:2a:fa
+ 7c:cd:d8:b5:d2:db:d1:a6:3f:1f:3f:39:2f:f2:af:3d
+ ae:8c:c9:fd:01:32:83:cf:48:f4:f5:25:95:3f:0a:83
+ 90:21:75:60:52:01:9a:5e:95:d2:ed:4c:6e:8c:f9:93
+ 9a:40:24:b5:91:eb:e6:b4:96:6a:6a:51:1b:9b:18:fd
+ 24:c8:c3:68:52:e3:55:f5:23:e0:97:4d:4b:4b:cd:83
+ 04:b9:e1:70:b6:4c:42:a6:a0:0c:2e:0d:f0:a1:c0:04
+ 08:57:0f:da:0e:0e:ee:32:7c:20:e6:03:ee:35:41:22
+ 01:b0:f3:6e:ee:0d:d7:91:1d:ed:98:d4:ef:e6:03:f1
+ 39:96:dd:a0:1f:6c:3a:3d:d9:d2:ac:f0:13:73:31:cf
+ b1:fb:13:d3:55:55:1b:6c:bd:39:49:e0:7a:b7:ef:ec
+ 3d:5c:dd:7d:bf:a0:11:69:8f:66:fc:45:29:b3:05:18
+ 7d:
+
+coefficient:
+ 00:9b:0b:66:d7:fe:dd:69:d2:9a:5b:d5:4e:36:f0:c8
+ 67:4e:68:ff:d5:21:a1:92:50:27:97:47:6e:82:3d:b3
+ c5:87:d2:c0:15:09:c1:9e:dc:2d:74:5a:cc:2b:ca:82
+ 0a:5d:3b:82:93:31:ce:12:bd:5b:7d:54:87:c0:8a:0e
+ df:86:d6:6f:62:ca:4a:41:5f:6c:8e:cb:ac:6e:37:c0
+ b8:26:20:c3:59:37:ce:1f:e7:eb:a5:08:8a:b0:96:f3
+ e0:3d:fc:66:c4:6b:66:14:91:76:2c:22:e4:6a:56:20
+ 41:51:6a:77:f1:bf:4c:5b:e8:fa:af:41:09:a8:77:5a
+ 6a:66:6d:12:83:54:c1:e8:ff:b7:3a:db:9f:46:e2:ce
+ d8:60:a8:03:23:78:41:5f:fb:ea:16:62:20:24:8d:8b
+ 49:64:e4:cb:ca:83:e8:c4:60:97:fb:bf:e7:dc:2c:10
+ ba:03:67:76:ea:4d:00:6c:06:f8:d2:83:fb:26:fe:dc
+ e1:
+
+exp1:
+ 00:db:9c:94:f1:ea:7b:4b:05:f8:3e:ea:c8:7a:99:fc
+ d2:b0:85:2a:b9:48:be:a7:71:2d:74:eb:b8:25:fd:a2
+ 7a:60:38:96:64:b9:ef:6b:59:d0:40:e6:34:04:48:6d
+ 85:33:12:65:d1:cc:c9:63:58:24:58:e0:94:e7:9f:2b
+ a6:6a:bd:70:25:70:5b:cf:87:df:15:02:46:1d:d3:81
+ 3d:e9:75:6c:78:ba:ca:c6:d0:f1:53:1b:59:8e:b1:57
+ 28:ef:95:e5:67:ae:a3:47:dc:b1:db:5b:51:aa:14:df
+ d7:ef:74:6a:6a:5d:07:54:b3:b3:de:90:a7:47:a4:45
+ 8a:81:64:d0:0b:64:85:ed:73:23:bb:49:08:c5:44:87
+ 17:cd:9f:a6:17:40:8d:58:d4:e5:6a:75:04:0e:aa:a2
+ 75:04:29:01:4c:12:e5:15:47:ae:76:90:98:ce:78:82
+ 1f:fc:7e:b3:95:e0:b3:17:e6:25:cf:b4:8d:f9:cb:79
+ 01:
+
+exp2:
+ 00:ad:d1:a9:99:e9:6a:be:8f:ab:f4:78:81:17:90:71
+ 66:66:ee:a2:0a:65:01:db:c2:a4:90:4f:37:ef:fe:83
+ ec:75:1f:b1:18:ae:02:1e:77:f2:5d:91:9d:8e:1b:04
+ 1c:85:c2:48:84:71:c1:8f:36:1a:bd:61:9a:74:53:8e
+ 94:be:b9:a0:3d:31:d7:9a:7e:41:40:5f:70:3e:3f:5c
+ b9:54:e5:be:90:e4:54:a0:b7:23:b3:65:7b:83:77:bb
+ 97:9c:50:6e:ec:38:7d:60:a5:17:a5:99:a3:b4:e4:b5
+ b9:dd:81:59:0e:91:cf:2a:3b:2b:09:a0:98:5a:6a:7b
+ 31:2a:e1:3c:f8:c4:fe:b3:b2:d1:02:e3:d9:c4:18:e0
+ 07:b3:73:05:e1:f6:17:c7:34:fc:74:b3:eb:93:17:49
+ 8b:82:75:cb:f5:b7:36:69:7c:87:8c:2a:e0:07:8b:ff
+ d4:76:04:e0:da:7e:a2:85:33:55:fb:81:97:37:5c:13
+ dd:
+
+
+Public Key ID: C5:43:DA:C5:F5:E5:8C:7A:A3:6D:AC:33:0E:19:BD:5F:67:9E:04:61
+Public key's random art:
++--[ RSA 3072]----+
+| ..... .|
+| = .. =.|
+| . = E. +|
+| . o... |
+| S . o.o |
+| o *.. |
+| o o +.+|
+| .o+.+o|
+| .oo...|
++-----------------+
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG5QIBAAKCAYEA8nNWVoZwi7fYKSYxm+lidTbMQEHh9pLXV8P1N2FDwqhNc6Z7
+1VqQw6gIDyzxBjZf3ldyPb6xAcxikvk2XCxVGqDaP7E1rfnCDSqxcgLGr1/TlRH3
+fFMFPqzMgs0GbDoKi7WuhcNMH1yIRk4uPVSUY3IclcE9sNvMpNVY77c9tYeLyoLg
+G8A2ljlSjbHXDmR8E1C+WcOvjFKQunpv29zIOvfp3Wuw0g3C6E26RyvYOnNNq6bm
+DHXdyIkxYNPwxyfBDGq/WhnrFqQTyEqulVLVVIpK+3fIdtmH/4OpOwxzKM0q2k9C
+zL+AI1JqlFoePeIKYQYAOssUBwB0VBDbhyo8f7txBs6OB1phPcmbkAo2bJfL01UT
+315omqlGWjvvDRjDEeRAfXnWu/UVLIs1MNn09l2+fKwgZyOZIQEk5gGgb+xO7pZp
+5W1IuLxB1DMatQjYK1L1MG8KUebovTyumAj8kOaCJaqa+EWcPvsH2wJbzp7JZV7x
+AMnNQGLHHccY9Iv9AgMBAAECggGAY6qwOl+H0pff34KY8Cvv0pmVO3EZ7+ALcEPZ
+AUwVq+a9+CXfUCSr0BK6RWrHJjOiE2fFScajQ0b+2sZh52A+F/U54ub5VyyN7hW3
+3lNv09ZDx0scftouFMa6R6b61fDCNw6X0Nso5teGGci3z3R+j6bwQ0uuDY89wCEI
+L3sXfhFbkQNeF2pbxkOIQUFzU7JRIyuVJJeCCeBDKLV+WFaZZUxWsjQ7+w23KwIQ
+6oMGn3iY3FB+z26AnphvWQunNmeLcq11lpwTpI4XB21FMLFVA4FlawLhMP6ca2OA
+rp1HsTPqthxtFC//KXHinN1AYjQERD2NcWvR6o1GYzcSJo+UHPVq0WZ/qdbdWSd5
+zuqts0diufYcNgrA/vP24cKGEpf58n5itDM+rUMFlR0U/r52xkQ4gKQlCFtcdk6p
+vap/8QWLSYGgQEsamNHJz5jhunES/B9TqldcZTrgciTVjychnPy21vfIB1zCQl3L
+ur8N8hObB2tzrhvwtxpq/SDPsnIBAoHBAP4UzzGg2OD1STUiLBQTqlXWJpLC+mMC
+ct3RBdEPsKSu5A6ZoDXjhCQGqidNzm8zbYqWPlS9UZLpP5vybp19Hi/hEbzbNMgv
+qwfuSl2WBVQcSPA8g5k6n13+MUgMswyr41wt5wZDkVxiIXYKTwDso5WFsP47YYsH
+xyG7tO8N0WcB3b2b6FbryiKDweiJO/oXI+ne/WIEcx8qiWbX0RaZf5ig4MKbESIj
+uVXLoEvrgaSogl3gCssZ/Rhd4hfMEysZgQKBwQD0SAsWOOjZlH44KXHUKvp8zdi1
+0tvRpj8fPzkv8q89rozJ/QEyg89I9PUllT8Kg5AhdWBSAZpeldLtTG6M+ZOaQCS1
+kevmtJZqalEbmxj9JMjDaFLjVfUj4JdNS0vNgwS54XC2TEKmoAwuDfChwAQIVw/a
+Dg7uMnwg5gPuNUEiAbDzbu4N15Ed7ZjU7+YD8TmW3aAfbDo92dKs8BNzMc+x+xPT
+VVUbbL05SeB6t+/sPVzdfb+gEWmPZvxFKbMFGH0CgcEA25yU8ep7SwX4PurIepn8
+0rCFKrlIvqdxLXTruCX9onpgOJZkue9rWdBA5jQESG2FMxJl0czJY1gkWOCU558r
+pmq9cCVwW8+H3xUCRh3TgT3pdWx4usrG0PFTG1mOsVco75XlZ66jR9yx21tRqhTf
+1+90ampdB1Szs96Qp0ekRYqBZNALZIXtcyO7SQjFRIcXzZ+mF0CNWNTlanUEDqqi
+dQQpAUwS5RVHrnaQmM54gh/8frOV4LMX5iXPtI35y3kBAoHBAK3RqZnpar6Pq/R4
+gReQcWZm7qIKZQHbwqSQTzfv/oPsdR+xGK4CHnfyXZGdjhsEHIXCSIRxwY82Gr1h
+mnRTjpS+uaA9MdeafkFAX3A+P1y5VOW+kORUoLcjs2V7g3e7l5xQbuw4fWClF6WZ
+o7TktbndgVkOkc8qOysJoJhaansxKuE8+MT+s7LRAuPZxBjgB7NzBeH2F8c0/HSz
+65MXSYuCdcv1tzZpfIeMKuAHi//UdgTg2n6ihTNV+4GXN1wT3QKBwQCbC2bX/t1p
+0ppb1U428MhnTmj/1SGhklAnl0dugj2zxYfSwBUJwZ7cLXRazCvKggpdO4KTMc4S
+vVt9VIfAig7fhtZvYspKQV9sjsusbjfAuCYgw1k3zh/n66UIirCW8+A9/GbEa2YU
+kXYsIuRqViBBUWp38b9MW+j6r0EJqHdaamZtEoNUwej/tzrbn0bizthgqAMjeEFf
+++oWYiAkjYtJZOTLyoPoxGCX+7/n3CwQugNndupNAGwG+NKD+yb+3OE=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/travis/trusty.supp b/tests/travis/trusty.supp
new file mode 100644
index 0000000..b490807
--- /dev/null
+++ b/tests/travis/trusty.supp
@@ -0,0 +1,10 @@
+{
+ gnu_libc_memerr
+ Memcheck:Free
+ fun:free
+ fun:__libc_freeres
+ fun:_vgnU_freeres
+ fun:__run_exit_handlers
+ fun:exit
+ fun:(below main)
+}
diff --git a/tests/udp-msgreduc-orgmsg-vg.sh b/tests/udp-msgreduc-orgmsg-vg.sh
new file mode 100755
index 0000000..603ba27
--- /dev/null
+++ b/tests/udp-msgreduc-orgmsg-vg.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# check if valgrind violations occur. Correct output is not checked.
+# added 2011-03-01 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[udp-msgreduc-orgmsg-vg.sh\]: testing msg reduction via udp, with org message
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+$UDPServerRun '$TCPFLOOD_PORT'
+$RepeatedMsgReduction on
+$RepeatedMsgContainsOriginalMsg on
+
+$template outfmt,"%msg:F,58:2%\n"
+*.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -t 127.0.0.1 -m 4 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...\""
+tcpflood -t 127.0.0.1 -m 1 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...x\""
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg
+if [ "$RSYSLOGD_EXIT" -eq "10" ]
+then
+ echo "udp-msgreduc-orgmsg-vg.sh FAILED"
+ exit 1
+fi
+exit_test
diff --git a/tests/udp-msgreduc-vg.sh b/tests/udp-msgreduc-vg.sh
new file mode 100755
index 0000000..1cfd6a1
--- /dev/null
+++ b/tests/udp-msgreduc-vg.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# check if valgrind violations occur. Correct output is not checked.
+# added 2011-03-01 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+echo ===============================================================================
+echo \[udp-msgreduc-vg.sh\]: testing imtcp multiple listeners
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$ModLoad ../plugins/imudp/.libs/imudp
+$UDPServerRun '$TCPFLOOD_PORT'
+$RepeatedMsgReduction on
+
+$template outfmt,"%msg:F,58:2%\n"
+*.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+#:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+startup_vg
+tcpflood -t 127.0.0.1 -m 4 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...\""
+tcpflood -t 127.0.0.1 -m 1 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...x\""
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown_vg
+if [ "$RSYSLOGD_EXIT" -eq "10" ]
+then
+ echo "udp-msgreduc-vg.sh FAILED"
+ exit 1
+fi
+exit_test
diff --git a/tests/unused_lookup_table-vg.sh b/tests/unused_lookup_table-vg.sh
new file mode 100755
index 0000000..fb49c89
--- /dev/null
+++ b/tests/unused_lookup_table-vg.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# test for ensuring clean destruction of lookup-table even when it is never used
+# added 2015-09-30 by singh.janmejay
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+skip_platform "FreeBSD" "This test currently does not work on FreeBSD"
+generate_conf
+add_conf '
+lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl")
+
+template(name="outfmt" type="string" string="- %msg%\n")
+
+action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
+'
+cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl
+startup_vg
+injectmsg 0 1
+shutdown_when_empty
+wait_shutdown_vg
+check_exit_vg
+content_check "msgnum:00000000:"
+exit_test
+
+# the test actually expects clean destruction of lookup_table
+# when lookup_table is loaded, it can either be:
+# - used (clean destruct covered by another test)
+# - not-used (this test ensures its destroyed cleanly)
diff --git a/tests/urlencode.py b/tests/urlencode.py
new file mode 100755
index 0000000..661314f
--- /dev/null
+++ b/tests/urlencode.py
@@ -0,0 +1,14 @@
+# call this via "python[3] script name"
+# a small url encoder for testbench purposes
+# written 2018-11-05 by Rainer Gerhards
+# part of the rsyslog testbench, released under ASL 2.0
+import sys
+try:
+ from urllib.parse import quote_plus
+except ImportError:
+ from urllib import quote_plus
+
+if len(sys.argv) != 2:
+ print("ERROR: urlencode needs exactly one string as argument")
+ sys.exit(1)
+print(quote_plus(sys.argv[1]))
diff --git a/tests/uxsock_simple.sh b/tests/uxsock_simple.sh
new file mode 100755
index 0000000..af97698
--- /dev/null
+++ b/tests/uxsock_simple.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This tests basic omuxsock functionality. A socket receiver is started which sends
+# all data to an output file, then a rsyslog instance is started which generates
+# messages and sends them to the unix socket. Datagram sockets are being used.
+# added 2010-08-06 by Rgerhards
+. ${srcdir:=.}/diag.sh init
+check_command_available timeout
+
+uname
+if [ $(uname) = "FreeBSD" ] ; then
+ echo "This test currently does not work on FreeBSD."
+ exit 77
+fi
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+generate_conf
+add_conf '
+$MainMsgQueueTimeoutShutdown 10000
+
+$ModLoad ../plugins/omuxsock/.libs/omuxsock
+$template outfmt,"%msg:F,58:2%\n"
+$OMUXSockSocket '$RSYSLOG_DYNNAME'-testbench-dgram-uxsock
+:msg, contains, "msgnum:" :omuxsock:;outfmt
+'
+timeout 30s ./uxsockrcvr -s$RSYSLOG_DYNNAME-testbench-dgram-uxsock -o $RSYSLOG_OUT_LOG -t 60 &
+BGPROCESS=$!
+echo background uxsockrcvr process id is $BGPROCESS
+
+# now do the usual run
+startup
+# 10000 messages should be enough
+injectmsg 0 10000
+shutdown_when_empty # shut down rsyslogd when done processing messages
+wait_shutdown
+
+# wait for the cp process to finish, do pipe-specific cleanup
+echo shutting down uxsockrcvr...
+# TODO: we should do this more reliable in the long run! (message counter? timeout?)
+kill $BGPROCESS
+wait $BGPROCESS
+echo background process has terminated, continue test...
+
+# and continue the usual checks
+seq_check 0 9999
+exit_test
diff --git a/tests/uxsockrcvr.c b/tests/uxsockrcvr.c
new file mode 100644
index 0000000..0d61ce9
--- /dev/null
+++ b/tests/uxsockrcvr.c
@@ -0,0 +1,192 @@
+/* receives messages from a specified unix sockets and writes
+ * output to specfied file.
+ *
+ * Command line options:
+ * -s name of socket (required)
+ * -o name of output file (stdout if not given)
+ * -l add newline after each message received (default: do not add anything)
+ * -t timeout in seconds (default 60)
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#if defined(_AIX)
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <sys/socketvar.h>
+#else
+ #include <getopt.h>
+#endif
+#include <sys/un.h>
+#include <netdb.h>
+#include <poll.h>
+#include <errno.h>
+#if defined(__FreeBSD__)
+#include <sys/socket.h>
+#endif
+
+#define DFLT_TIMEOUT 60
+
+char *sockName = NULL;
+int sock;
+int addNL = 0;
+
+
+/* called to clean up on exit
+ */
+void
+cleanup(void)
+{
+ unlink(sockName);
+ close(sock);
+}
+
+
+void
+doTerm(int __attribute__((unused)) signum)
+{
+ exit(1);
+}
+
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: uxsockrcvr -s /socket/name -o /output/file -l\n"
+ "-l adds newline after each message received\n"
+ "-s MUST be specified\n"
+ "if -o ist not specified, stdout is used\n");
+ exit(1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+ int rlen;
+ int timeout = DFLT_TIMEOUT;
+ FILE *fp = stdout;
+ unsigned char data[128*1024];
+ struct sockaddr_un addr; /* address of server */
+ struct sockaddr from;
+ socklen_t fromlen;
+ struct pollfd fds[1];
+
+ if(argc < 2) {
+ fprintf(stderr, "error: too few arguments!\n");
+ usage();
+ }
+
+ while((opt = getopt(argc, argv, "s:o:lt:")) != EOF) {
+ switch((char)opt) {
+ case 'l':
+ addNL = 1;
+ break;
+ case 's':
+ sockName = optarg;
+ break;
+ case 'o':
+ if((fp = fopen(optarg, "w")) == NULL) {
+ perror(optarg);
+ exit(1);
+ }
+ break;
+ case 't':
+ timeout = atoi(optarg);
+ break;
+ default:usage();
+ }
+ }
+
+ timeout = timeout * 1000;
+
+ if(sockName == NULL) {
+ fprintf(stderr, "error: -s /socket/name must be specified!\n");
+ exit(1);
+ }
+
+ if(signal(SIGTERM, doTerm) == SIG_ERR) {
+ perror("signal(SIGTERM, ...)");
+ exit(1);
+ }
+ if(signal(SIGINT, doTerm) == SIG_ERR) {
+ perror("signal(SIGINT, ...)");
+ exit(1);
+ }
+
+ /* Create a UNIX datagram socket for server */
+ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ perror("server: socket");
+ exit(1);
+ }
+
+ atexit(cleanup);
+
+ /* Set up address structure for server socket */
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, sockName);
+
+ if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
+ close(sock);
+ perror("server: bind");
+ exit(1);
+ }
+
+ fds[0].fd = sock;
+ fds[0].events = POLLIN;
+
+ /* we now run in an endless loop. We do not check who sends us
+ * data. This should be no problem for our testbench use.
+ */
+
+ while(1) {
+ fromlen = sizeof(from);
+ rlen = poll(fds, 1, timeout);
+ if(rlen == -1) {
+ perror("uxsockrcvr : poll\n");
+ exit(1);
+ } else if(rlen == 0) {
+ fprintf(stderr, "Socket timed out - nothing to receive\n");
+ exit(1);
+ } else {
+ rlen = recvfrom(sock, data, 2000, 0, &from, &fromlen);
+ if(rlen == -1) {
+ perror("uxsockrcvr : recv\n");
+ exit(1);
+ } else {
+ fwrite(data, 1, rlen, fp);
+ if(addNL)
+ fputc('\n', fp);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/tests/validation-run.sh b/tests/validation-run.sh
new file mode 100755
index 0000000..8ecad6b
--- /dev/null
+++ b/tests/validation-run.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# check if the configuration test run detects invalid config files.
+#
+# Part of the testbench for rsyslog.
+#
+# Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH.
+#
+# This file is part of rsyslog.
+# Released under ASL 2.0
+echo \[validation-run.sh\]: testing configuration validation
+echo "testing a failed configuration verification run"
+../tools/rsyslogd -u2 -N1 -f$srcdir/testsuites/invalid.conf -M../runtime/.libs:../.libs
+if [ $? -ne 1 ]; then
+ echo "after test 1: return code ne 1"
+ exit 1
+fi
+echo testing a valid config verification run
+../tools/rsyslogd -u2 -N1 -f$srcdir/testsuites/valid.conf -M../runtime/.libs:../.libs
+if [ $? -ne 0 ]; then
+ echo "after test 2: return code ne 0"
+ exit 1
+fi
+echo testing empty config file
+../tools/rsyslogd -u2 -N1 -f/dev/null -M../runtime/.libs:../.libs
+if [ $? -ne 1 ]; then
+ echo "after test 3: return code ne 1"
+ exit 1
+fi
+echo SUCCESS: validation run tests
diff --git a/tests/variable_leading_underscore.sh b/tests/variable_leading_underscore.sh
new file mode 100755
index 0000000..3d80864
--- /dev/null
+++ b/tests/variable_leading_underscore.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 2015 Red Hat, Inc.
+# This file is part of the rsyslog project, released under ASL 2.0
+# The configuration test should pass because we now support leading
+# underscores in variable names.
+. ${srcdir:=.}/diag.sh init
+../tools/rsyslogd -C -N1 -f$srcdir/testsuites/variable_leading_underscore.conf -M../runtime/.libs:../.libs
+if [ $? -ne 0 ]; then
+ echo "Error: config check fail"
+ exit 1
+fi
+exit_test
+
diff --git a/tests/with_space.mmdb b/tests/with_space.mmdb
new file mode 100644
index 0000000..85120ba
--- /dev/null
+++ b/tests/with_space.mmdb
Binary files differ
diff --git a/tests/wr_large_async.sh b/tests/wr_large_async.sh
new file mode 100755
index 0000000..7a94f83
--- /dev/null
+++ b/tests/wr_large_async.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This tests async writing large data records. We use up to 10K
+# record size.
+# added 2010-03-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=4000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'") # trick to use relative path names!
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$OMFileAsyncWriting on
+local0.* ?dynfile;outfmt
+'
+startup
+# send 4000 messages of 10.000bytes plus header max, randomized
+tcpflood -m$NUMMESSAGES -r -d10000 -P129
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/wr_large_sync.sh b/tests/wr_large_sync.sh
new file mode 100755
index 0000000..53758b0
--- /dev/null
+++ b/tests/wr_large_sync.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This tests async writing large data records. We use up to 10K
+# record size.
+
+# added 2010-03-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=4000
+export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
+generate_conf
+add_conf '
+$MaxMessageSize 10k
+
+module(load="../plugins/imtcp/.libs/imtcp")
+input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'") # trick to use relative path names!
+$OMFileIOBufferSize 256k
+$OMFileAsyncWriting off
+local0.* ?dynfile;outfmt
+'
+startup
+# send 4000 messages of 10.000bytes plus header max, randomized
+tcpflood -m$NUMMESSAGES -r -d10000 -P129
+shutdown_when_empty
+wait_shutdown
+export SEQ_CHECK_OPTIONS=-E
+seq_check
+exit_test
diff --git a/tests/wtpShutdownAll-assertionFailure.sh b/tests/wtpShutdownAll-assertionFailure.sh
new file mode 100755
index 0000000..2d15a78
--- /dev/null
+++ b/tests/wtpShutdownAll-assertionFailure.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# add 2018-04-19 by Pascal Withopf, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+generate_conf
+add_conf '
+$AbortOnUncleanConfig on
+$LocalHostName wtpshutdownall
+$PreserveFQDN on
+
+global(
+ workDirectory="'${RSYSLOG_DYNNAME}'.spool"
+)
+
+module(load="../plugins/mmjsonparse/.libs/mmjsonparse")
+module(load="../plugins/impstats/.libs/impstats" interval="300"
+ resetCounters="on" format="cee" ruleset="metrics-impstat" log.syslog="on")
+
+ruleset(name="metrics-impstat" queue.type="Direct"){
+ action(type="omfile" file="'$RSYSLOG_DYNNAME'.spool/stats.log")
+}
+'
+startup
+shutdown_when_empty
+wait_shutdown
+
+# This test only checks that rsyslog does not abort
+# so we don't need to check for output.
+
+exit_test
diff --git a/tests/zstd-vg.sh b/tests/zstd-vg.sh
new file mode 100755
index 0000000..e9b11e2
--- /dev/null
+++ b/tests/zstd-vg.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+export USE_VALGRIND="YES"
+export NUMMESSAGES=10000 # valgrind is pretty slow, so we need to user lower nbr of msgs
+source ${srcdir:-.}/zstd.sh
diff --git a/tests/zstd.sh b/tests/zstd.sh
new file mode 100755
index 0000000..a109644
--- /dev/null
+++ b/tests/zstd.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This tests writing large data records in zst mode. We use up to 10K
+# record size.
+#
+# added 2022-06-21 by Rgerhards
+#
+# This file is part of the rsyslog project, released under ASL 2.0
+. ${srcdir:=.}/diag.sh init
+export NUMMESSAGES=${NUMMESSAGES:-50000}
+export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check
+generate_conf
+# Note: we right now use the non-compressed file as indicator for "processing complete"
+#export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.zst
+add_conf '
+$MaxMessageSize 10k
+$MainMsgQueueTimeoutShutdown 10000
+
+module(load="builtin:omfile" compression.driver="zstd" compression.zstd.workers="5")
+module(load="../plugins/imptcp/.libs/imptcp")
+input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
+
+template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n")
+local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'.zst" template="outfmt"
+ zipLevel="20" iobuffersize="64k" veryRobustZIP="off")
+local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
+'
+# rgerhards, 2019-08-14: Note: veryRobustZip may need to be "on". Do this if the test
+# still prematurely terminates. In that case it is likely that gunzip got confused
+# by the missing zip close record. My initial testing shows that while gunzip emits an
+# error message, everything is properly extracted. Only stressed CI runs will show how
+# it works in reality.
+startup
+assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port
+tcpflood -m$NUMMESSAGES -r -d10000 -P129
+shutdown_when_empty
+wait_shutdown
+seq_check 0 $((NUMMESSAGES - 1)) -E
+exit_test
diff --git a/threads.c b/threads.c
new file mode 100644
index 0000000..2fd4bbb
--- /dev/null
+++ b/threads.c
@@ -0,0 +1,322 @@
+/* threads.c
+ *
+ * This file implements threading support helpers (and maybe the thread object)
+ * for rsyslog.
+ *
+ * File begun on 2007-12-14 by RGerhards
+ *
+ * Copyright 2007-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <pthread.h>
+#include <assert.h>
+#ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+#endif
+
+#include "rsyslog.h"
+#include "dirty.h"
+#include "linkedlist.h"
+#include "threads.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "glbl.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+
+/* linked list of currently-known threads */
+static linkedList_t llThrds;
+
+/* methods */
+
+/* Construct a new thread object
+ */
+static rsRetVal
+thrdConstruct(thrdInfo_t **ppThis)
+{
+ DEFiRet;
+ thrdInfo_t *pThis;
+
+ assert(ppThis != NULL);
+
+ CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t)));
+ pthread_mutex_init(&pThis->mutThrd, NULL);
+ pthread_cond_init(&pThis->condThrdTerm, NULL);
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* Destructs a thread object. The object must not be linked to the
+ * linked list of threads. Please note that the thread should have been
+ * stopped before. If not, we try to do it.
+ */
+static rsRetVal thrdDestruct(thrdInfo_t *pThis)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+
+ pthread_mutex_lock(&pThis->mutThrd);
+ if(pThis->bIsActive == 1) {
+ pthread_mutex_unlock(&pThis->mutThrd);
+ thrdTerminate(pThis);
+ } else {
+ pthread_mutex_unlock(&pThis->mutThrd);
+ pthread_join(pThis->thrdID, NULL);
+ }
+
+ /* call cleanup function, if any */
+ if(pThis->pAfterRun != NULL)
+ pThis->pAfterRun(pThis);
+
+ pthread_mutex_destroy(&pThis->mutThrd);
+ pthread_cond_destroy(&pThis->condThrdTerm);
+ free(pThis->name);
+ free(pThis);
+
+ RETiRet;
+}
+
+
+/* terminate a thread via the non-cancel interface
+ * This is a separate function as it involves a bit more of code.
+ * rgerhads, 2009-10-15
+ */
+static rsRetVal
+thrdTerminateNonCancel(thrdInfo_t *pThis)
+{
+ struct timespec tTimeout;
+ int ret;
+ int was_active;
+ DEFiRet;
+ assert(pThis != NULL);
+
+ DBGPRINTF("request term via SIGTTIN for input thread '%s' %p\n",
+ pThis->name, (void*) pThis->thrdID);
+
+ pThis->bShallStop = RSTRUE;
+ d_pthread_mutex_lock(&pThis->mutThrd);
+ timeoutComp(&tTimeout, runConf->globals.inputTimeoutShutdown);
+ was_active = pThis->bIsActive;
+ while(was_active) {
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslogd debug: info: trying to cooperatively stop "
+ "input %s, timeout %d ms\n", pThis->name, runConf->globals.inputTimeoutShutdown);
+ }
+ DBGPRINTF("thread %s: initiating termination, timeout %d ms\n",
+ pThis->name, runConf->globals.inputTimeoutShutdown);
+ const int r = pthread_kill(pThis->thrdID, SIGTTIN);
+ if(r != 0) {
+ LogError(r, RS_RET_INTERNAL_ERROR, "error terminating thread %s "
+ "this may cause shutdown issues", pThis->name);
+ }
+ ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout);
+ if(ret == ETIMEDOUT) {
+ DBGPRINTF("input thread term: timeout expired waiting on thread %s "
+ "termination - canceling\n", pThis->name);
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslogd debug: input thread term: "
+ "timeout expired waiting on thread %s "
+ "termination - canceling\n", pThis->name);
+ }
+ pthread_cancel(pThis->thrdID);
+ break;
+ } else if(ret != 0) {
+ char errStr[1024];
+ int err = ret;
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("input thread term: cond_wait returned with error %d: %s\n",
+ err, errStr);
+ }
+ was_active = pThis->bIsActive;
+ }
+ d_pthread_mutex_unlock(&pThis->mutThrd);
+
+ if(was_active) {
+ DBGPRINTF("non-cancel input thread termination FAILED for thread %s %p\n",
+ pThis->name, (void*) pThis->thrdID);
+ } else {
+ DBGPRINTF("non-cancel input thread termination succeeded for thread %s %p\n",
+ pThis->name, (void*) pThis->thrdID);
+ }
+
+ RETiRet;
+}
+
+
+/* terminate a thread gracefully.
+ */
+rsRetVal thrdTerminate(thrdInfo_t *pThis)
+{
+ DEFiRet;
+ assert(pThis != NULL);
+
+ if(pThis->bNeedsCancel) {
+ DBGPRINTF("request term via canceling for input thread %s\n", pThis->name);
+ if(dbgTimeoutToStderr) {
+ fprintf(stderr, "rsyslogd debug: request term via canceling for "
+ "input thread %s\n", pThis->name);
+ }
+ pthread_cancel(pThis->thrdID);
+ } else {
+ thrdTerminateNonCancel(pThis);
+ }
+ pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */
+
+ RETiRet;
+}
+
+
+/* terminate all known threads gracefully.
+ */
+rsRetVal thrdTerminateAll(void)
+{
+ DEFiRet;
+ llDestroy(&llThrds);
+ RETiRet;
+}
+
+
+/* This is an internal wrapper around the user thread function. Its
+ * purpose is to handle all the necessary housekeeping stuff so that the
+ * user function needs not to be aware of the threading calls. The user
+ * function call has just "normal", non-threading semantics.
+ * rgerhards, 2007-12-17
+ */
+static ATTR_NORETURN void*
+thrdStarter(void *const arg)
+{
+ DEFiRet;
+ thrdInfo_t *const pThis = (thrdInfo_t*) arg;
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ uchar thrdName[32] = "in:";
+# endif
+
+ assert(pThis != NULL);
+ assert(pThis->pUsrThrdMain != NULL);
+
+# if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
+ ustrncpy(thrdName+3, pThis->name, 20);
+ dbgOutputTID((char*)thrdName);
+
+ /* set thread name - we ignore if the call fails, has no harsh consequences... */
+ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) {
+ DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name);
+ } else {
+ DBGPRINTF("set thread name to '%s'\n", thrdName);
+ }
+# endif
+
+ /* block all signals except SIGTTIN and SIGSEGV */
+ sigset_t sigSet;
+ sigfillset(&sigSet);
+ sigdelset(&sigSet, SIGTTIN);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
+
+ /* setup complete, we are now ready to execute the user code. We will not
+ * regain control until the user code is finished, in which case we terminate
+ * the thread.
+ */
+ iRet = pThis->pUsrThrdMain(pThis);
+
+ if(iRet == RS_RET_OK) {
+ dbgprintf("thrdStarter: usrThrdMain %s - 0x%lx returned with iRet %d, exiting now.\n",
+ pThis->name, (unsigned long) pThis->thrdID, iRet);
+ } else {
+ LogError(0, iRet, "main thread of %s terminated abnormally", pThis->name);
+ }
+
+ /* signal master control that we exit (we do the mutex lock mostly to
+ * keep the thread debugger happer, it would not really be necessary with
+ * the logic we employ...)
+ */
+ d_pthread_mutex_lock(&pThis->mutThrd);
+ pThis->bIsActive = 0;
+ pthread_cond_signal(&pThis->condThrdTerm);
+ d_pthread_mutex_unlock(&pThis->mutThrd);
+
+ pthread_exit(0);
+}
+/* Start a new thread and add it to the list of currently
+ * executing threads. It is added at the end of the list.
+ * rgerhards, 2007-12-14
+ */
+rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *),
+ sbool bNeedsCancel, uchar *name)
+{
+ DEFiRet;
+ thrdInfo_t *pThis;
+#if defined (_AIX)
+ pthread_attr_t aix_attr;
+#endif
+
+ assert(thrdMain != NULL);
+
+ CHKiRet(thrdConstruct(&pThis));
+ pThis->bIsActive = 1;
+ pThis->pUsrThrdMain = thrdMain;
+ pThis->pAfterRun = afterRun;
+ pThis->bNeedsCancel = bNeedsCancel;
+ pThis->name = ustrdup(name);
+#if defined (_AIX)
+ pthread_attr_init(&aix_attr);
+ pthread_attr_setstacksize(&aix_attr, 4096*512);
+ pthread_create(&pThis->thrdID, &aix_attr, thrdStarter, pThis);
+#else
+ pthread_create(&pThis->thrdID, &default_thread_attr, thrdStarter, pThis);
+#endif
+ CHKiRet(llAppend(&llThrds, NULL, pThis));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* initialize the thread-support subsystem
+ * must be called once at the start of the program
+ */
+rsRetVal thrdInit(void)
+{
+ DEFiRet;
+ iRet = llInit(&llThrds, thrdDestruct, NULL, NULL);
+ RETiRet;
+}
+
+
+/* de-initialize the thread subsystem
+ * must be called once at the end of the program
+ */
+rsRetVal thrdExit(void)
+{
+ DEFiRet;
+ iRet = llDestroy(&llThrds);
+ RETiRet;
+}
+
+
+/* vi:set ai:
+ */
diff --git a/threads.h b/threads.h
new file mode 100644
index 0000000..102402e
--- /dev/null
+++ b/threads.h
@@ -0,0 +1,47 @@
+/* Definition of the threading support module.
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef THREADS_H_INCLUDED
+#define THREADS_H_INCLUDED
+
+/* the thread object */
+struct thrdInfo {
+ pthread_mutex_t mutThrd;/* mutex for handling long-running operations and shutdown */
+ pthread_cond_t condThrdTerm;/* condition: thread terminates (used just for shutdown loop) */
+ int bIsActive; /* Is thread running? */
+ int bShallStop; /* set to 1 if the thread should be stopped ? */
+ rsRetVal (*pUsrThrdMain)(struct thrdInfo*); /* user thread main to be called in new thread */
+ rsRetVal (*pAfterRun)(struct thrdInfo*); /* cleanup function */
+ pthread_t thrdID;
+ sbool bNeedsCancel; /* must input be terminated by pthread_cancel()? */
+ uchar *name; /* a thread name, mainly for user interaction */
+};
+
+/* prototypes */
+rsRetVal thrdExit(void);
+rsRetVal thrdInit(void);
+rsRetVal thrdTerminate(thrdInfo_t *pThis);
+rsRetVal thrdTerminateAll(void);
+rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t*), rsRetVal(*afterRun)(thrdInfo_t *), sbool, uchar*);
+
+/* macros (replace inline functions) */
+
+#endif /* #ifndef THREADS_H_INCLUDED */
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..f5044c5
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,118 @@
+sbin_PROGRAMS =
+bin_PROGRAMS =
+CLEANFILES =
+man1_MANS =
+man_MANS = rsyslogd.8 rsyslog.conf.5
+
+sbin_PROGRAMS += rsyslogd
+rsyslogd_SOURCES = \
+ syslogd.c \
+ rsyslogd.c \
+ syslogd.h \
+ omshell.c \
+ omshell.h \
+ omusrmsg.c \
+ omusrmsg.h \
+ omfwd.c \
+ omfwd.h \
+ omfile.c \
+ omfile.h \
+ ompipe.c \
+ ompipe.h \
+ omdiscard.c \
+ omdiscard.h \
+ pmrfc5424.c \
+ pmrfc5424.h \
+ pmrfc3164.c \
+ pmrfc3164.h \
+ smtradfile.c \
+ smtradfile.h \
+ smfile.c \
+ smfile.h \
+ smfwd.c \
+ smfwd.h \
+ smtradfwd.c \
+ smtradfwd.h \
+ iminternal.c \
+ iminternal.h \
+ \
+ ../dirty.h
+rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+
+if ENABLE_LIBLOGGING_STDLOG
+rsyslogd_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS)
+endif
+
+rsyslogd_CPPFLAGS += -DSD_EXPORT_SYMBOLS
+
+# note: it looks like librsyslog.la must be explicitely given on LDDADD,
+# otherwise dependencies are not properly calculated (resulting in a
+# potentially incomplete build, a problem we had several times...)
+rsyslogd_LDADD = ../grammar/libgrammar.la ../runtime/librsyslog.la ../compat/compat.la $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBUUID_LIBS) $(HASH_XXHASH_LIBS)
+
+# Note: do NOT indent the if chain - it will not work!
+if OS_LINUX
+rsyslogd_LDFLAGS = -export-dynamic \
+ #-Wl,--whole-archive,$(top_builddir)/runtime/.libs/librsyslog.a,--no-whole-archive
+exports_list_file =
+else
+if OS_APPLE
+rsyslogd_LDFLAGS = -export-dynamic \
+ -Wl,$(top_builddir)/runtime/.libs/librsyslog.a
+exports_list_file =
+else
+if OS_AIX
+rsyslogd_LDFLAGS = -brtl -bexpall -f"aix_exports_list" -lsrc
+exports_list_file = aix_exports_list
+else # e.g. FreeBSD
+rsyslogd_LDFLAGS = -export-dynamic
+exports_list_file =
+endif # if OS_AIX
+endif # if OS_APPLE
+endif # if OS_LINUX
+
+EXTRA_DIST = $(man_MANS) \
+ rscryutil.rst \
+ recover_qi.pl
+
+EXTRA_rsyslogd_DEPENDENCIES = $(exports_list_file)
+
+if ENABLE_LIBLOGGING_STDLOG
+rsyslogd_LDADD += $(LIBLOGGING_STDLOG_LIBS)
+endif
+
+if ENABLE_DIAGTOOLS
+sbin_PROGRAMS += rsyslog_diag_hostname msggen
+rsyslog_diag_hostname_SOURCES = gethostn.c
+msggen_SOURCES = msggen.c
+endif
+
+if ENABLE_USERTOOLS
+if ENABLE_OMMONGODB
+bin_PROGRAMS += logctl
+logctl_SOURCES = logctl.c
+logctl_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS)
+logctl_LDADD = $(LIBMONGOC_LIBS)
+endif
+if ENABLE_LIBGCRYPT
+bin_PROGRAMS += rscryutil
+rscryutil = rscryutil.c
+rscryutil_CPPFLAGS = -I../runtime $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+rscryutil_LDADD = ../runtime/libgcry.la $(LIBGCRYPT_LIBS)
+rscryutil_LDFLAGS = \
+ -Wl,--whole-archive,--no-whole-archive
+if ENABLE_GENERATE_MAN_PAGES
+RSTMANFILE = rscryutil.rst
+rscryutil.1: $(RSTMANFILE)
+ $(AM_V_GEN) $(RST2MAN) $(RSTMANFILE) $@
+man1_MANS += rscryutil.1
+CLEANFILES += rscryutil.1
+EXTRA_DIST+= rscryutil.1
+endif
+endif
+endif
+
+aix_exports_list:
+ echo "$(top_builddir)/runtime/.libs/librsyslog_la-*.o" > $@
+ echo "$(top_builddir)/.libs/librsyslog_la-*.o" >> $@
+ echo "$(top_builddir)/grammar/.libs/libgrammar_la-*.o" >> $@
diff --git a/tools/Makefile.in b/tools/Makefile.in
new file mode 100644
index 0000000..01a8bb9
--- /dev/null
+++ b/tools/Makefile.in
@@ -0,0 +1,1447 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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@
+sbin_PROGRAMS = rsyslogd$(EXEEXT) $(am__EXEEXT_3)
+bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS)
+@ENABLE_DIAGTOOLS_TRUE@am__append_3 = rsyslog_diag_hostname msggen
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_4 = logctl
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_5 = rscryutil
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_6 = rscryutil.1
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_7 = rscryutil.1
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_8 = rscryutil.1
+subdir = tools
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am__EXEEXT_1 = \
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@ logctl$(EXEEXT)
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@am__EXEEXT_2 = rscryutil$(EXEEXT)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
+ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)"
+@ENABLE_DIAGTOOLS_TRUE@am__EXEEXT_3 = rsyslog_diag_hostname$(EXEEXT) \
+@ENABLE_DIAGTOOLS_TRUE@ msggen$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
+am__logctl_SOURCES_DIST = logctl.c
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am_logctl_OBJECTS = logctl-logctl.$(OBJEXT)
+logctl_OBJECTS = $(am_logctl_OBJECTS)
+am__DEPENDENCIES_1 =
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_DEPENDENCIES = $(am__DEPENDENCIES_1)
+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 =
+am__msggen_SOURCES_DIST = msggen.c
+@ENABLE_DIAGTOOLS_TRUE@am_msggen_OBJECTS = msggen.$(OBJEXT)
+msggen_OBJECTS = $(am_msggen_OBJECTS)
+msggen_LDADD = $(LDADD)
+rscryutil_SOURCES = rscryutil.c
+rscryutil_OBJECTS = rscryutil-rscryutil.$(OBJEXT)
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_DEPENDENCIES = ../runtime/libgcry.la \
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__DEPENDENCIES_1)
+rscryutil_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(rscryutil_LDFLAGS) $(LDFLAGS) -o $@
+am__rsyslog_diag_hostname_SOURCES_DIST = gethostn.c
+@ENABLE_DIAGTOOLS_TRUE@am_rsyslog_diag_hostname_OBJECTS = \
+@ENABLE_DIAGTOOLS_TRUE@ gethostn.$(OBJEXT)
+rsyslog_diag_hostname_OBJECTS = $(am_rsyslog_diag_hostname_OBJECTS)
+rsyslog_diag_hostname_LDADD = $(LDADD)
+am_rsyslogd_OBJECTS = rsyslogd-syslogd.$(OBJEXT) \
+ rsyslogd-rsyslogd.$(OBJEXT) rsyslogd-omshell.$(OBJEXT) \
+ rsyslogd-omusrmsg.$(OBJEXT) rsyslogd-omfwd.$(OBJEXT) \
+ rsyslogd-omfile.$(OBJEXT) rsyslogd-ompipe.$(OBJEXT) \
+ rsyslogd-omdiscard.$(OBJEXT) rsyslogd-pmrfc5424.$(OBJEXT) \
+ rsyslogd-pmrfc3164.$(OBJEXT) rsyslogd-smtradfile.$(OBJEXT) \
+ rsyslogd-smfile.$(OBJEXT) rsyslogd-smfwd.$(OBJEXT) \
+ rsyslogd-smtradfwd.$(OBJEXT) rsyslogd-iminternal.$(OBJEXT)
+rsyslogd_OBJECTS = $(am_rsyslogd_OBJECTS)
+@ENABLE_LIBLOGGING_STDLOG_TRUE@am__DEPENDENCIES_2 = \
+@ENABLE_LIBLOGGING_STDLOG_TRUE@ $(am__DEPENDENCIES_1)
+rsyslogd_DEPENDENCIES = ../grammar/libgrammar.la \
+ ../runtime/librsyslog.la ../compat/compat.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+rsyslogd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(rsyslogd_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)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/gethostn.Po \
+ ./$(DEPDIR)/logctl-logctl.Po ./$(DEPDIR)/msggen.Po \
+ ./$(DEPDIR)/rscryutil-rscryutil.Po \
+ ./$(DEPDIR)/rsyslogd-iminternal.Po \
+ ./$(DEPDIR)/rsyslogd-omdiscard.Po \
+ ./$(DEPDIR)/rsyslogd-omfile.Po ./$(DEPDIR)/rsyslogd-omfwd.Po \
+ ./$(DEPDIR)/rsyslogd-ompipe.Po ./$(DEPDIR)/rsyslogd-omshell.Po \
+ ./$(DEPDIR)/rsyslogd-omusrmsg.Po \
+ ./$(DEPDIR)/rsyslogd-pmrfc3164.Po \
+ ./$(DEPDIR)/rsyslogd-pmrfc5424.Po \
+ ./$(DEPDIR)/rsyslogd-rsyslogd.Po \
+ ./$(DEPDIR)/rsyslogd-smfile.Po ./$(DEPDIR)/rsyslogd-smfwd.Po \
+ ./$(DEPDIR)/rsyslogd-smtradfile.Po \
+ ./$(DEPDIR)/rsyslogd-smtradfwd.Po \
+ ./$(DEPDIR)/rsyslogd-syslogd.Po
+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 = $(logctl_SOURCES) $(msggen_SOURCES) rscryutil.c \
+ $(rsyslog_diag_hostname_SOURCES) $(rsyslogd_SOURCES)
+DIST_SOURCES = $(am__logctl_SOURCES_DIST) $(am__msggen_SOURCES_DIST) \
+ rscryutil.c $(am__rsyslog_diag_hostname_SOURCES_DIST) \
+ $(rsyslogd_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+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; }; \
+ }
+man1dir = $(mandir)/man1
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man1_MANS) $(man_MANS)
+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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+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@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+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@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = $(am__append_7)
+man1_MANS = $(am__append_6)
+man_MANS = rsyslogd.8 rsyslog.conf.5
+rsyslogd_SOURCES = \
+ syslogd.c \
+ rsyslogd.c \
+ syslogd.h \
+ omshell.c \
+ omshell.h \
+ omusrmsg.c \
+ omusrmsg.h \
+ omfwd.c \
+ omfwd.h \
+ omfile.c \
+ omfile.h \
+ ompipe.c \
+ ompipe.h \
+ omdiscard.c \
+ omdiscard.h \
+ pmrfc5424.c \
+ pmrfc5424.h \
+ pmrfc3164.c \
+ pmrfc3164.h \
+ smtradfile.c \
+ smtradfile.h \
+ smfile.c \
+ smfile.h \
+ smfwd.c \
+ smfwd.h \
+ smtradfwd.c \
+ smtradfwd.h \
+ iminternal.c \
+ iminternal.h \
+ \
+ ../dirty.h
+
+rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_1) \
+ -DSD_EXPORT_SYMBOLS
+
+# note: it looks like librsyslog.la must be explicitely given on LDDADD,
+# otherwise dependencies are not properly calculated (resulting in a
+# potentially incomplete build, a problem we had several times...)
+rsyslogd_LDADD = ../grammar/libgrammar.la ../runtime/librsyslog.la \
+ ../compat/compat.la $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) \
+ $(SOL_LIBS) $(LIBUUID_LIBS) $(HASH_XXHASH_LIBS) \
+ $(am__append_2)
+@OS_AIX_FALSE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -export-dynamic
+@OS_AIX_TRUE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -brtl -bexpall -f"aix_exports_list" -lsrc
+@OS_APPLE_TRUE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -export-dynamic \
+@OS_APPLE_TRUE@@OS_LINUX_FALSE@ -Wl,$(top_builddir)/runtime/.libs/librsyslog.a
+
+
+# Note: do NOT indent the if chain - it will not work!
+@OS_LINUX_TRUE@rsyslogd_LDFLAGS = -export-dynamic \
+@OS_LINUX_TRUE@ #-Wl,--whole-archive,$(top_builddir)/runtime/.libs/librsyslog.a,--no-whole-archive
+
+@OS_AIX_FALSE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@exports_list_file =
+@OS_AIX_TRUE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@exports_list_file = aix_exports_list
+@OS_APPLE_TRUE@@OS_LINUX_FALSE@exports_list_file =
+@OS_LINUX_TRUE@exports_list_file =
+EXTRA_DIST = $(man_MANS) rscryutil.rst recover_qi.pl $(am__append_8)
+EXTRA_rsyslogd_DEPENDENCIES = $(exports_list_file)
+@ENABLE_DIAGTOOLS_TRUE@rsyslog_diag_hostname_SOURCES = gethostn.c
+@ENABLE_DIAGTOOLS_TRUE@msggen_SOURCES = msggen.c
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_SOURCES = logctl.c
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS)
+@ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_LDADD = $(LIBMONGOC_LIBS)
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil = rscryutil.c
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_CPPFLAGS = -I../runtime $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS)
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_LDADD = ../runtime/libgcry.la $(LIBGCRYPT_LIBS)
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_LDFLAGS = \
+@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@ -Wl,--whole-archive,--no-whole-archive
+
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@RSTMANFILE = rscryutil.rst
+all: 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) --gnu tools/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tools/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__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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):
+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
+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
+
+logctl$(EXEEXT): $(logctl_OBJECTS) $(logctl_DEPENDENCIES) $(EXTRA_logctl_DEPENDENCIES)
+ @rm -f logctl$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(logctl_OBJECTS) $(logctl_LDADD) $(LIBS)
+
+msggen$(EXEEXT): $(msggen_OBJECTS) $(msggen_DEPENDENCIES) $(EXTRA_msggen_DEPENDENCIES)
+ @rm -f msggen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(msggen_OBJECTS) $(msggen_LDADD) $(LIBS)
+
+rscryutil$(EXEEXT): $(rscryutil_OBJECTS) $(rscryutil_DEPENDENCIES) $(EXTRA_rscryutil_DEPENDENCIES)
+ @rm -f rscryutil$(EXEEXT)
+ $(AM_V_CCLD)$(rscryutil_LINK) $(rscryutil_OBJECTS) $(rscryutil_LDADD) $(LIBS)
+
+rsyslog_diag_hostname$(EXEEXT): $(rsyslog_diag_hostname_OBJECTS) $(rsyslog_diag_hostname_DEPENDENCIES) $(EXTRA_rsyslog_diag_hostname_DEPENDENCIES)
+ @rm -f rsyslog_diag_hostname$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rsyslog_diag_hostname_OBJECTS) $(rsyslog_diag_hostname_LDADD) $(LIBS)
+
+rsyslogd$(EXEEXT): $(rsyslogd_OBJECTS) $(rsyslogd_DEPENDENCIES) $(EXTRA_rsyslogd_DEPENDENCIES)
+ @rm -f rsyslogd$(EXEEXT)
+ $(AM_V_CCLD)$(rsyslogd_LINK) $(rsyslogd_OBJECTS) $(rsyslogd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gethostn.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logctl-logctl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msggen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rscryutil-rscryutil.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-iminternal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omdiscard.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfwd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-ompipe.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omshell.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omusrmsg.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-pmrfc3164.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-pmrfc5424.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-rsyslogd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smfwd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smtradfile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smtradfwd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-syslogd.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.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 $@ $<
+
+logctl-logctl.o: logctl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logctl-logctl.o -MD -MP -MF $(DEPDIR)/logctl-logctl.Tpo -c -o logctl-logctl.o `test -f 'logctl.c' || echo '$(srcdir)/'`logctl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logctl-logctl.Tpo $(DEPDIR)/logctl-logctl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logctl.c' object='logctl-logctl.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) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logctl-logctl.o `test -f 'logctl.c' || echo '$(srcdir)/'`logctl.c
+
+logctl-logctl.obj: logctl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logctl-logctl.obj -MD -MP -MF $(DEPDIR)/logctl-logctl.Tpo -c -o logctl-logctl.obj `if test -f 'logctl.c'; then $(CYGPATH_W) 'logctl.c'; else $(CYGPATH_W) '$(srcdir)/logctl.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logctl-logctl.Tpo $(DEPDIR)/logctl-logctl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logctl.c' object='logctl-logctl.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) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logctl-logctl.obj `if test -f 'logctl.c'; then $(CYGPATH_W) 'logctl.c'; else $(CYGPATH_W) '$(srcdir)/logctl.c'; fi`
+
+rscryutil-rscryutil.o: rscryutil.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rscryutil-rscryutil.o -MD -MP -MF $(DEPDIR)/rscryutil-rscryutil.Tpo -c -o rscryutil-rscryutil.o `test -f 'rscryutil.c' || echo '$(srcdir)/'`rscryutil.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rscryutil-rscryutil.Tpo $(DEPDIR)/rscryutil-rscryutil.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rscryutil.c' object='rscryutil-rscryutil.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) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rscryutil-rscryutil.o `test -f 'rscryutil.c' || echo '$(srcdir)/'`rscryutil.c
+
+rscryutil-rscryutil.obj: rscryutil.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rscryutil-rscryutil.obj -MD -MP -MF $(DEPDIR)/rscryutil-rscryutil.Tpo -c -o rscryutil-rscryutil.obj `if test -f 'rscryutil.c'; then $(CYGPATH_W) 'rscryutil.c'; else $(CYGPATH_W) '$(srcdir)/rscryutil.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rscryutil-rscryutil.Tpo $(DEPDIR)/rscryutil-rscryutil.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rscryutil.c' object='rscryutil-rscryutil.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) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rscryutil-rscryutil.obj `if test -f 'rscryutil.c'; then $(CYGPATH_W) 'rscryutil.c'; else $(CYGPATH_W) '$(srcdir)/rscryutil.c'; fi`
+
+rsyslogd-syslogd.o: syslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.o -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='rsyslogd-syslogd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c
+
+rsyslogd-syslogd.obj: syslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='rsyslogd-syslogd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi`
+
+rsyslogd-rsyslogd.o: rsyslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-rsyslogd.o -MD -MP -MF $(DEPDIR)/rsyslogd-rsyslogd.Tpo -c -o rsyslogd-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-rsyslogd.Tpo $(DEPDIR)/rsyslogd-rsyslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='rsyslogd-rsyslogd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c
+
+rsyslogd-rsyslogd.obj: rsyslogd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-rsyslogd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-rsyslogd.Tpo -c -o rsyslogd-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-rsyslogd.Tpo $(DEPDIR)/rsyslogd-rsyslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='rsyslogd-rsyslogd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi`
+
+rsyslogd-omshell.o: omshell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.o -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='rsyslogd-omshell.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c
+
+rsyslogd-omshell.obj: omshell.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='rsyslogd-omshell.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi`
+
+rsyslogd-omusrmsg.o: omusrmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.o -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='rsyslogd-omusrmsg.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c
+
+rsyslogd-omusrmsg.obj: omusrmsg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='rsyslogd-omusrmsg.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi`
+
+rsyslogd-omfwd.o: omfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='rsyslogd-omfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c
+
+rsyslogd-omfwd.obj: omfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='rsyslogd-omfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi`
+
+rsyslogd-omfile.o: omfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='rsyslogd-omfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c
+
+rsyslogd-omfile.obj: omfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='rsyslogd-omfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi`
+
+rsyslogd-ompipe.o: ompipe.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ompipe.o -MD -MP -MF $(DEPDIR)/rsyslogd-ompipe.Tpo -c -o rsyslogd-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-ompipe.Tpo $(DEPDIR)/rsyslogd-ompipe.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='rsyslogd-ompipe.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c
+
+rsyslogd-ompipe.obj: ompipe.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ompipe.obj -MD -MP -MF $(DEPDIR)/rsyslogd-ompipe.Tpo -c -o rsyslogd-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-ompipe.Tpo $(DEPDIR)/rsyslogd-ompipe.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='rsyslogd-ompipe.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi`
+
+rsyslogd-omdiscard.o: omdiscard.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.o -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='rsyslogd-omdiscard.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c
+
+rsyslogd-omdiscard.obj: omdiscard.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='rsyslogd-omdiscard.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi`
+
+rsyslogd-pmrfc5424.o: pmrfc5424.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc5424.o -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc5424.Tpo -c -o rsyslogd-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc5424.Tpo $(DEPDIR)/rsyslogd-pmrfc5424.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='rsyslogd-pmrfc5424.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c
+
+rsyslogd-pmrfc5424.obj: pmrfc5424.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc5424.obj -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc5424.Tpo -c -o rsyslogd-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc5424.Tpo $(DEPDIR)/rsyslogd-pmrfc5424.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='rsyslogd-pmrfc5424.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi`
+
+rsyslogd-pmrfc3164.o: pmrfc3164.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc3164.o -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc3164.Tpo -c -o rsyslogd-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc3164.Tpo $(DEPDIR)/rsyslogd-pmrfc3164.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='rsyslogd-pmrfc3164.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c
+
+rsyslogd-pmrfc3164.obj: pmrfc3164.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc3164.obj -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc3164.Tpo -c -o rsyslogd-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc3164.Tpo $(DEPDIR)/rsyslogd-pmrfc3164.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='rsyslogd-pmrfc3164.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi`
+
+rsyslogd-smtradfile.o: smtradfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfile.Tpo -c -o rsyslogd-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfile.Tpo $(DEPDIR)/rsyslogd-smtradfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='rsyslogd-smtradfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c
+
+rsyslogd-smtradfile.obj: smtradfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfile.Tpo -c -o rsyslogd-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfile.Tpo $(DEPDIR)/rsyslogd-smtradfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='rsyslogd-smtradfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi`
+
+rsyslogd-smfile.o: smfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-smfile.Tpo -c -o rsyslogd-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfile.Tpo $(DEPDIR)/rsyslogd-smfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='rsyslogd-smfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c
+
+rsyslogd-smfile.obj: smfile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smfile.Tpo -c -o rsyslogd-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfile.Tpo $(DEPDIR)/rsyslogd-smfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='rsyslogd-smfile.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi`
+
+rsyslogd-smfwd.o: smfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-smfwd.Tpo -c -o rsyslogd-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfwd.Tpo $(DEPDIR)/rsyslogd-smfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='rsyslogd-smfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c
+
+rsyslogd-smfwd.obj: smfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smfwd.Tpo -c -o rsyslogd-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfwd.Tpo $(DEPDIR)/rsyslogd-smfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='rsyslogd-smfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi`
+
+rsyslogd-smtradfwd.o: smtradfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfwd.Tpo -c -o rsyslogd-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfwd.Tpo $(DEPDIR)/rsyslogd-smtradfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='rsyslogd-smtradfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c
+
+rsyslogd-smtradfwd.obj: smtradfwd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfwd.Tpo -c -o rsyslogd-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfwd.Tpo $(DEPDIR)/rsyslogd-smtradfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='rsyslogd-smtradfwd.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi`
+
+rsyslogd-iminternal.o: iminternal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.o -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='rsyslogd-iminternal.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c
+
+rsyslogd-iminternal.obj: iminternal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.obj -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='rsyslogd-iminternal.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) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1='$(man1_MANS)'; \
+ list2='$(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='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(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: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(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='$(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)
+install-man8: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || 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 '/\.8[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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(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: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(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 $(PROGRAMS) $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; 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:
+
+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."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/gethostn.Po
+ -rm -f ./$(DEPDIR)/logctl-logctl.Po
+ -rm -f ./$(DEPDIR)/msggen.Po
+ -rm -f ./$(DEPDIR)/rscryutil-rscryutil.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-iminternal.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omdiscard.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-ompipe.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omshell.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omusrmsg.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-pmrfc3164.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-pmrfc5424.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-rsyslogd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smtradfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smtradfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-syslogd.Po
+ -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-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1 install-man5 install-man8
+
+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 ./$(DEPDIR)/gethostn.Po
+ -rm -f ./$(DEPDIR)/logctl-logctl.Po
+ -rm -f ./$(DEPDIR)/msggen.Po
+ -rm -f ./$(DEPDIR)/rscryutil-rscryutil.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-iminternal.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omdiscard.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-ompipe.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omshell.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-omusrmsg.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-pmrfc3164.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-pmrfc5424.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-rsyslogd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smtradfile.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-smtradfwd.Po
+ -rm -f ./$(DEPDIR)/rsyslogd-syslogd.Po
+ -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-binPROGRAMS uninstall-man \
+ uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool \
+ 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-binPROGRAMS 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-man1 install-man5 \
+ install-man8 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 \
+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-man uninstall-man1 uninstall-man5 uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+.PRECIOUS: Makefile
+
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil.1: $(RSTMANFILE)
+@ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_LIBGCRYPT_TRUE@@ENABLE_USERTOOLS_TRUE@ $(AM_V_GEN) $(RST2MAN) $(RSTMANFILE) $@
+
+aix_exports_list:
+ echo "$(top_builddir)/runtime/.libs/librsyslog_la-*.o" > $@
+ echo "$(top_builddir)/.libs/librsyslog_la-*.o" >> $@
+ echo "$(top_builddir)/grammar/.libs/libgrammar_la-*.o" >> $@
+
+# 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/tools/gethostn.c b/tools/gethostn.c
new file mode 100644
index 0000000..a43c53c
--- /dev/null
+++ b/tools/gethostn.c
@@ -0,0 +1,46 @@
+/* gethostn - a small diagnostic utility to show what the
+ * gethostname() API returns. Of course, this tool duplicates
+ * functionality already found in other tools. But the point is
+ * that the API shall be called by a program that is compiled like
+ * rsyslogd and does exactly what rsyslog does.
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
+{
+ char hostname[4096]; /* this should always be sufficient ;) */
+ int err;
+
+ err = gethostname(hostname, sizeof(hostname));
+
+ if(err) {
+ perror("gethostname failed");
+ exit(1);
+ }
+
+ printf("hostname of this system is '%s'.\n", hostname);
+
+ return 0;
+}
diff --git a/tools/iminternal.c b/tools/iminternal.c
new file mode 100644
index 0000000..c4dd548
--- /dev/null
+++ b/tools/iminternal.c
@@ -0,0 +1,182 @@
+/* iminternal.c
+ * This file set implements the internal messages input module for rsyslog.
+ * Note: we currently do not have an input module spec, but
+ * we will have one in the future. This module needs then to be
+ * adapted.
+ *
+ * File begun on 2007-08-03 by RGerhards
+ *
+ * Copyright 2007-2022 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include "syslogd.h"
+#include "linkedlist.h"
+#include "iminternal.h"
+#include "unicode-helper.h"
+
+static linkedList_t llMsgs;
+static pthread_mutex_t mutList = PTHREAD_MUTEX_INITIALIZER;
+
+
+/* destructs an iminternal object
+ */
+static rsRetVal iminternalDestruct(iminternal_t *pThis)
+{
+ DEFiRet;
+
+ if(pThis->pMsg != NULL)
+ msgDestruct(&pThis->pMsg);
+
+ free(pThis);
+
+ RETiRet;
+}
+
+
+/* Construct an iminternal object
+ */
+static rsRetVal iminternalConstruct(iminternal_t **ppThis)
+{
+ DEFiRet;
+ if((*ppThis = (iminternal_t*) calloc(1, sizeof(iminternal_t))) == NULL) {
+ iRet = RS_RET_OUT_OF_MEMORY;
+ }
+ RETiRet;
+}
+
+
+/* add a message to the linked list
+ * Note: the pMsg reference counter is not incremented. Consequently,
+ * the caller must NOT decrement it. The caller actually hands over
+ * full ownership of the pMsg object.
+ */
+rsRetVal iminternalAddMsg(smsg_t *pMsg)
+{
+ DEFiRet;
+ iminternal_t *pThis = NULL;
+ struct timespec to;
+ int r;
+ int is_locked = 0;
+
+ /* we guard against deadlock, so we can guarantee rsyslog will never
+ * block due to internal messages. The 1 second timeout should be
+ * sufficient under all circumstances.
+ */
+ to.tv_sec = time(NULL) + 1;
+ to.tv_nsec = 0;
+ #if !defined(__APPLE__)
+ r = pthread_mutex_timedlock(&mutList, &to);
+ #else
+ r = pthread_mutex_trylock(&mutList); // must check
+ #endif
+ if(r != 0) {
+ dbgprintf("iminternalAddMsg: timedlock for mutex failed with %d, msg %s\n",
+ r, getMSG(pMsg));
+ /* the message is lost, nothing we can do against this! */
+ msgDestruct(&pMsg);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ is_locked = 1;
+ CHKiRet(iminternalConstruct(&pThis));
+ pThis->pMsg = pMsg;
+ CHKiRet(llAppend(&llMsgs, NULL, (void*) pThis));
+
+ if(PREFER_FETCH_32BIT(bHaveMainQueue)) {
+ DBGPRINTF("signaling new internal message via SIGTTOU: '%s'\n",
+ pThis->pMsg->pszRawMsg);
+ kill(glblGetOurPid(), SIGTTOU);
+ }
+
+finalize_it:
+ if(is_locked) {
+ pthread_mutex_unlock(&mutList);
+ }
+ if(iRet != RS_RET_OK) {
+ dbgprintf("iminternalAddMsg() error %d - can not otherwise report this error, message lost\n", iRet);
+ if(pThis != NULL)
+ iminternalDestruct(pThis);
+ }
+
+ RETiRet;
+}
+
+
+/* pull the first error message from the linked list, remove it
+ * from the list and return it to the caller. The caller is
+ * responsible for freeing the message!
+ */
+rsRetVal iminternalRemoveMsg(smsg_t **ppMsg)
+{
+ DEFiRet;
+ iminternal_t *pThis;
+ linkedListCookie_t llCookie = NULL;
+
+ pthread_mutex_lock(&mutList);
+ CHKiRet(llGetNextElt(&llMsgs, &llCookie, (void*)&pThis));
+ if(!strcmp((char*)pThis->pMsg->pszHOSTNAME, "[localhost]")) {
+ /* early (pre-conf) startup message detected, need to set real hostname now */
+ MsgSetHOSTNAME(pThis->pMsg, glblGetLocalHostName(), ustrlen(glblGetLocalHostName()));
+ }
+ *ppMsg = pThis->pMsg;
+ pThis->pMsg = NULL; /* we do no longer own it - important for destructor */
+
+ if(llDestroyRootElt(&llMsgs) != RS_RET_OK) {
+ dbgprintf("Root element of iminternal linked list could not be destroyed - there is "
+ "nothing we can do against it, we ignore it for now. Things may go wild "
+ "from here on. This is most probably a program logic error.\n");
+ }
+
+finalize_it:
+ pthread_mutex_unlock(&mutList);
+ RETiRet;
+}
+
+
+/* initialize the iminternal subsystem
+ * must be called once at the start of the program
+ */
+rsRetVal modInitIminternal(void)
+{
+ DEFiRet;
+ iRet = llInit(&llMsgs, iminternalDestruct, NULL, NULL);
+ RETiRet;
+}
+
+
+/* de-initialize the iminternal subsystem
+ * must be called once at the end of the program
+ * Note: the error list must have been pulled first. We do
+ * NOT care if there are any errors left - we simply destroy
+ * them.
+ */
+rsRetVal modExitIminternal(void)
+{
+ DEFiRet;
+ iRet = llDestroy(&llMsgs);
+ RETiRet;
+}
diff --git a/tools/iminternal.h b/tools/iminternal.h
new file mode 100644
index 0000000..f7c15e5
--- /dev/null
+++ b/tools/iminternal.h
@@ -0,0 +1,45 @@
+/* Definition of the internal messages input module.
+ *
+ * Note: we currently do not have an input module spec, but
+ * we will have one in the future. This module needs then to be
+ * adapted.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMINTERNAL_H_INCLUDED
+#define IMINTERNAL_H_INCLUDED
+#include "template.h"
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct iminternal_s { /* config file sysline parse entry */
+ smsg_t *pMsg; /* the message (in all its glory) */
+};
+typedef struct iminternal_s iminternal_t;
+
+/* prototypes */
+rsRetVal modInitIminternal(void);
+rsRetVal modExitIminternal(void);
+rsRetVal iminternalAddMsg(smsg_t *pMsg);
+rsRetVal iminternalRemoveMsg(smsg_t **ppMsg);
+
+#endif /* #ifndef IMINTERNAL_H_INCLUDED */
diff --git a/tools/logctl.c b/tools/logctl.c
new file mode 100644
index 0000000..1010409
--- /dev/null
+++ b/tools/logctl.c
@@ -0,0 +1,486 @@
+/**
+ * logctl - a tool to access lumberjack logs in MongoDB
+ * ... and potentially other sources in the future.
+ *
+ * Copyright 2012-2022 Ulrike Gerhards and Adiscon GmbH.
+ *
+ * Copyright 2017 Hugo Soszynski and aDvens
+ *
+ * long short
+
+ * level l read records with level x
+ * severity s read records with severity x
+ * ret r number of records to return
+ * skip k number of records to skip
+ * sys y read records of system x
+ * msg m read records with message containing x
+ * datef f read records starting on time received x
+ * dateu u read records until time received x
+ *
+ * examples:
+ *
+ * logctl -f 15/05/2012-12:00:00 -u 15/05/2012-12:37:00
+ * logctl -s 50 --ret 10
+ * logctl -m "closed"
+ * logctl -l "INFO"
+ * logctl -s 3
+ * logctl -y "ubuntu"
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#define _XOPEN_SOURCE 700 /* Need to define POSIX version to use strptime() */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <getopt.h>
+#include <unistd.h>
+
+/* we need this to avoid issues with older versions of libbson */
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wunknown-attributes"
+#pragma GCC diagnostic ignored "-Wexpansion-to-defined"
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#pragma GCC diagnostic ignored "-Wold-style-definition"
+#endif
+#include <mongoc.h>
+#include <bson.h>
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#define N 80
+
+static struct option long_options[] =
+ {
+ {"level", required_argument, NULL, 'l'},
+ {"severity", required_argument, NULL, 's'},
+ {"ret", required_argument, NULL, 'r'},
+ {"skip", required_argument, NULL, 'k'},
+ {"sys", required_argument, NULL, 'y'},
+ {"msg", required_argument, NULL, 'm'},
+ {"datef", required_argument, NULL, 'f'},
+ {"dateu", required_argument, NULL, 'u'},
+ {NULL, 0, NULL, 0}
+ };
+
+struct queryopt
+{
+ int32_t e_sever;
+ int32_t e_ret;
+ int32_t e_skip;
+ char* e_date;
+ char* e_level;
+ char* e_msg;
+ char* e_sys;
+ char* e_dateu;
+ int bsever;
+ int blevel;
+ int bskip;
+ int bret;
+ int bsys;
+ int bmsg;
+ int bdate;
+ int bdatef;
+ int bdateu;
+};
+
+struct ofields
+{
+ const char* msg;
+ const char* syslog_tag;
+ const char* prog;
+ char* date;
+ int64_t date_r;
+};
+
+struct query_doc
+{
+ bson_t* query;
+};
+
+struct select_doc
+{
+ bson_t* select;
+};
+
+struct db_connect
+{
+ mongoc_client_t* conn;
+};
+
+struct db_collection
+{
+ mongoc_collection_t* collection;
+};
+
+struct db_cursor
+{
+ mongoc_cursor_t* cursor;
+};
+
+struct results
+{
+ const bson_t* result;
+};
+
+
+static void formater(struct ofields* fields)
+{
+ char str[N];
+ time_t rtime;
+ struct tm now;
+
+ rtime = (time_t) (fields->date_r / 1000);
+ strftime (str, N, "%b %d %H:%M:%S", gmtime_r (&rtime, &now));
+ printf ("%s %s %s %s\n", str, fields->prog, fields->syslog_tag,
+ fields->msg);
+}
+
+static struct ofields* get_data(struct results* res)
+{
+ struct ofields* fields;
+ const char* msg;
+ const char* prog;
+ const char* syslog_tag;
+ int64_t date_r;
+ bson_iter_t c;
+
+ fields = malloc (sizeof (struct ofields));
+ bson_iter_init_find (&c, res->result, "msg");
+ if (!(msg = bson_iter_utf8 (&c, NULL)))
+ {
+ perror ("bson_cursor_get_string()");
+ exit (1);
+ }
+
+ bson_iter_init_find (&c, res->result, "sys");
+ if (!(prog = bson_iter_utf8 (&c, NULL)))
+ {
+ perror ("bson_cursor_get_string()");
+ exit (1);
+ }
+
+ bson_iter_init_find (&c, res->result, "syslog_tag");
+ if (!(syslog_tag = bson_iter_utf8 (&c, NULL)))
+ {
+ perror ("bson_cursor_get_string()");
+ exit (1);
+ }
+
+ bson_iter_init_find (&c, res->result, "time_rcvd");
+ if (!(date_r = bson_iter_date_time (&c)))
+ {
+ perror ("bson_cursor_get_utc_datetime()");
+ exit (1);
+ }
+
+ fields->msg = msg;
+ fields->prog = prog;
+ fields->syslog_tag = syslog_tag;
+ fields->date_r = date_r;
+
+ return fields;
+}
+
+static void getoptions(int argc, char* argv[], struct queryopt* opt)
+{
+ int iarg;
+
+ while ((iarg = getopt_long (argc, argv, "l:s:r:k:y:f:u:m:",
+ long_options, NULL)) != -1)
+ {
+ /* check to see if a single character or long option came through */
+ switch (iarg)
+ {
+ /* short option 's' */
+ case 's':
+ opt->bsever = 1;
+ opt->e_sever = atoi (optarg);
+ break;
+ /* short option 'r' */
+ case 'r':
+ opt->bret = 1;
+ opt->e_ret = atoi (optarg);
+ break;
+ /* short option 'f' : date from */
+ case 'f':
+ opt->bdate = 1;
+ opt->bdatef = 1;
+ opt->e_date = optarg;
+ break;
+ /* short option 'u': date until */
+ case 'u':
+ opt->bdate = 1;
+ opt->bdateu = 1;
+ opt->e_dateu = optarg;
+ break;
+ /* short option 'k' */
+ case 'k':
+ opt->bskip = 1;
+ opt->e_skip = atoi (optarg);
+ break;
+ /* short option 'l' */
+ case 'l':
+ opt->blevel = 1;
+ opt->e_level = optarg;
+ break;
+ /* short option 'm' */
+ case 'm':
+ opt->bmsg = 1;
+ opt->e_msg = optarg;
+ break;
+ /* short option 'y' */
+ case 'y':
+ opt->bsys = 1;
+ opt->e_sys = optarg;
+ break;
+ default:
+ break;
+ } /* end switch iarg */
+ } /* end while */
+
+} /* end void getoptions */
+
+static struct select_doc* create_select(void)
+/* BSON object indicating the fields to return */
+{
+ struct select_doc* s_doc;
+
+ s_doc = malloc (sizeof (struct select_doc));
+ s_doc->select = bson_new ();
+ bson_append_utf8 (s_doc->select, "syslog_tag", 10, "s", 1);
+ bson_append_utf8 (s_doc->select, "msg", 3, "ERROR", 5);
+ bson_append_utf8 (s_doc->select, "sys", 3, "sys", 3);
+ bson_append_date_time (s_doc->select, "time_rcvd", 9, 1ll);
+ return s_doc;
+}
+
+static struct query_doc* create_query(struct queryopt* opt)
+{
+ struct query_doc* qu_doc;
+ bson_t* query_what, * order_what, * msg_what, * date_what;
+ struct tm tm;
+ time_t t;
+ int64_t ts;
+
+ qu_doc = malloc (sizeof (struct query_doc));
+ qu_doc->query = bson_new ();
+ query_what = bson_new ();
+ bson_init (query_what);
+ bson_append_document_begin (qu_doc->query, "$query", 6, query_what);
+ if (opt->bsever == 1)
+ {
+ bson_append_int32 (query_what, "syslog_sever", 12,
+ opt->e_sever);
+ }
+ if (opt->blevel == 1)
+ {
+ bson_append_utf8 (query_what, "level", 5, opt->e_level, -1);
+ }
+
+ if (opt->bmsg == 1)
+ {
+ msg_what = bson_new ();
+ bson_init (msg_what);
+ bson_append_document_begin (query_what, "msg", 3, msg_what);
+ bson_append_utf8 (msg_what, "$regex", 6, opt->e_msg, -1);
+ bson_append_utf8 (msg_what, "$options", 8, "i", 1);
+ bson_append_document_end (query_what, msg_what);
+ }
+
+ if (opt->bdate == 1)
+ {
+ date_what = bson_new ();
+ bson_init (date_what);
+ bson_append_document_begin (query_what, "time_rcvd", 9,
+ date_what);
+ if (opt->bdatef == 1)
+ {
+ tm.tm_isdst = -1;
+ strptime (opt->e_date, "%d/%m/%Y-%H:%M:%S", &tm);
+ tm.tm_hour = tm.tm_hour + 1;
+ t = mktime (&tm);
+ ts = 1000 * (int64_t) t;
+ bson_append_date_time (date_what, "$gt", 3, ts);
+ }
+
+ if (opt->bdateu == 1)
+ {
+ tm.tm_isdst = -1;
+ strptime (opt->e_dateu, "%d/%m/%Y-%H:%M:%S", &tm);
+ tm.tm_hour = tm.tm_hour + 1;
+ t = mktime (&tm);
+ ts = 1000 * (int64_t) t;
+ bson_append_date_time (date_what, "$lt", 3, ts);
+ }
+ bson_append_document_end (query_what, date_what);
+ }
+
+ if (opt->bsys == 1)
+ {
+ bson_append_utf8 (query_what, "sys", 3, opt->e_sys, -1);
+ }
+
+ bson_append_document_end (qu_doc->query, query_what);
+
+ order_what = bson_new ();
+ bson_init (order_what);
+ bson_append_document_begin (qu_doc->query, "$orderby", 8, order_what);
+ bson_append_date_time (order_what, "time_rcvd", 9, 1ll);
+ bson_append_document_end (qu_doc->query, order_what);
+
+ bson_free (order_what);
+ return qu_doc;
+}
+
+static struct db_connect* create_conn(void)
+{
+ struct db_connect* db_conn;
+
+ db_conn = malloc (sizeof (struct db_connect));
+ db_conn->conn = mongoc_client_new ("mongodb://localhost:27017");
+ if (!db_conn->conn)
+ {
+ perror ("mongo_sync_connect()");
+ exit (1);
+ }
+ return db_conn;
+}
+
+static void close_conn(struct db_connect* db_conn)
+{
+ mongoc_client_destroy (db_conn->conn);
+ free (db_conn);
+}
+
+static void free_cursor(struct db_cursor* db_c)
+{
+ mongoc_cursor_destroy (db_c->cursor);
+ free (db_c);
+}
+
+static struct db_cursor* launch_query(struct queryopt* opt,
+ __attribute__((unused)) struct select_doc* s_doc,
+ struct query_doc* qu_doc,
+ struct db_collection* db_coll)
+{
+ struct db_cursor* out;
+#if MONGOC_CHECK_VERSION (1, 5, 0) /* Declaration before code (ISO C90) */
+ const bson_t* opts = BCON_NEW (
+ "skip", BCON_INT32 (opt->e_skip),
+ "limit", BCON_INT32 (opt->e_ret)
+ );
+#endif /* MONGOC_CHECK_VERSION (1, 5, 0) */
+
+ out = malloc (sizeof (struct db_cursor));
+ if (!out)
+ {
+ perror ("mongo_sync_cmd_query()");
+ printf ("malloc failed\n");
+ exit (1);
+ }
+#if MONGOC_CHECK_VERSION (1, 5, 0)
+ out->cursor = mongoc_collection_find_with_opts (db_coll->collection,
+ qu_doc->query, opts,
+ NULL);
+#else /* !MONGOC_CHECK_VERSION (1, 5, 0) */
+ out->cursor = mongoc_collection_find (db_coll->collection,
+ MONGOC_QUERY_NONE,
+ (uint32_t)opt->e_skip,
+ (uint32_t)opt->e_ret, 0,
+ qu_doc->query, s_doc->select,
+ NULL);
+#endif /* MONGOC_CHECK_VERSION (1, 5, 0) */
+ if (!out->cursor)
+ {
+ perror ("mongo_sync_cmd_query()");
+ printf ("no records found\n");
+ exit (1);
+ }
+ return out;
+}
+
+static int cursor_next(struct db_cursor* db_c, struct results* res)
+{
+ if (mongoc_cursor_next (db_c->cursor, &res->result))
+ return true;
+ return false;
+}
+
+static struct db_collection* get_collection(struct db_connect* db_conn)
+{
+ struct db_collection* coll;
+
+ coll = malloc (sizeof (struct db_collection));
+ coll->collection = mongoc_client_get_collection (db_conn->conn,
+ "syslog", "log");
+ return coll;
+}
+
+static void release_collection(struct db_collection* db_coll)
+{
+ mongoc_collection_destroy (db_coll->collection);
+ free (db_coll);
+}
+
+int main(int argc, char* argv[])
+{
+
+ struct queryopt opt;
+ struct ofields* fields;
+ struct select_doc* s_doc;
+ struct query_doc* qu_doc;
+ struct db_connect* db_conn;
+ struct db_cursor* db_c;
+ struct db_collection* db_coll;
+ struct results* res;
+
+ memset (&opt, 0, sizeof (struct queryopt));
+
+ mongoc_init (); /* Initialisation of mongo-c-driver */
+
+ getoptions (argc, argv, &opt);
+ qu_doc = create_query (&opt); /* create query */
+ s_doc = create_select ();
+ db_conn = create_conn (); /* create connection */
+ db_coll = get_collection (db_conn); /* Get the collection to perform query on */
+ db_c = launch_query (&opt, s_doc, qu_doc, db_coll); /* launch the query and get the related cursor */
+
+ res = malloc (sizeof (struct results));
+ while (cursor_next (db_c, res)) /* Move cursor & get pointed data */
+ {
+ fields = get_data (res);
+ formater (fields); /* format output */
+ free (fields);
+ }
+
+ free (res);
+ free_cursor (db_c);
+ release_collection (db_coll);
+ close_conn (db_conn);
+ free (s_doc);
+ free (qu_doc);
+
+ mongoc_cleanup (); /* Cleanup of mongo-c-driver */
+
+ return (0);
+}
diff --git a/tools/msggen.c b/tools/msggen.c
new file mode 100644
index 0000000..ceb952b
--- /dev/null
+++ b/tools/msggen.c
@@ -0,0 +1,36 @@
+/* msggen - a small diagnostic utility that does very quick
+ * syslog() calls.
+ *
+ * Copyright 2008-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <syslog.h>
+
+int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
+{
+ int i;
+
+ openlog("msggen", 0 , LOG_LOCAL0);
+
+ for(i = 0 ; i < 10 ; ++i)
+ syslog(LOG_NOTICE, "This is message number %d", i);
+
+ closelog();
+ return 0;
+}
diff --git a/tools/omdiscard.c b/tools/omdiscard.c
new file mode 100644
index 0000000..e1a85dc
--- /dev/null
+++ b/tools/omdiscard.c
@@ -0,0 +1,158 @@
+/* omdiscard.c
+ * This is the implementation of the built-in discard output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-24 by RGerhards
+ *
+ * Copyright 2007-2013 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "omdiscard.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ EMPTY_STRUCT
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+/* we do not need a createInstance()!
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+*/
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* do nothing */
+ENDdbgPrintInstInfo
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* we are not compatible with repeated msg reduction feature, so do not allow it */
+ENDisCompatibleWithFeature
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction_NoStrings
+CODESTARTdoAction
+ (void)pMsgData; /* Suppress compiler warning on unused var */
+ dbgprintf("\n");
+ iRet = RS_RET_DISCARDMSG;
+ENDdoAction
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* we do not have instance data, so we do not need to
+ * do anything here. -- rgerhards, 2007-07-25
+ */
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(0)
+ pData = NULL; /* this action does not have any instance data */
+ p = *pp;
+
+ if(*p == '~') {
+ dbgprintf("discard\n");
+ LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING,
+ "warning: ~ action is deprecated, consider "
+ "using the 'stop' statement instead");
+ } else {
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ }
+/* we do not use the macro
+ * CODE_STD_FINALIZERparseSelectorAct
+ * here as this causes a Coverity ID "false positive" (CID 185431).
+ * We don't see an issue with using the copy&pasted code as it is unlikly
+ * to change for this (outdated) module.
+ */
+finalize_it: ATTR_UNUSED; /* semi-colon needed according to gcc doc! */
+ if(iRet == RS_RET_OK || iRet == RS_RET_OK_WARN || iRet == RS_RET_SUSPENDED) {
+ *ppModData = pData;
+ *pp = p;
+ } else {
+ /* cleanup, we failed */
+ if(*ppOMSR != NULL) {
+ OMSRdestruct(*ppOMSR);
+ *ppOMSR = NULL;
+ }
+ }
+/* END modified macro text */
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Discard)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+/*
+ * vi:set ai:
+ */
diff --git a/tools/omdiscard.h b/tools/omdiscard.h
new file mode 100644
index 0000000..bc7eb66
--- /dev/null
+++ b/tools/omdiscard.h
@@ -0,0 +1,33 @@
+/* omdiscard.h
+ * These are the definitions for the built-in discard output module.
+ *
+ * File begun on 2007-07-24 by RGerhards
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMDISCARD_H_INCLUDED
+#define OMDISCARD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitDiscard(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef OMDISCARD_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/omfile.c b/tools/omfile.c
new file mode 100644
index 0000000..cf464cd
--- /dev/null
+++ b/tools/omfile.c
@@ -0,0 +1,1644 @@
+/* omfile.c
+ * This is the implementation of the build-in file output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c, which
+ * at the time of the fork from sysklogd was under BSD license)
+ *
+ * A large re-write of this file was done in June, 2009. The focus was
+ * to introduce many more features (like zipped writing), clean up the code
+ * and make it more reliable. In short, that rewrite tries to provide a new
+ * solid basis for the next three to five years to come. During it, bugs
+ * may have been introduced ;) -- rgerhards, 2009-06-04
+ *
+ * Note that as of 2010-02-28 this module does no longer handle
+ * pipes. These have been moved to ompipe, to reduced the entanglement
+ * between the two different functionalities. -- rgerhards
+ *
+ * Copyright 2007-2024 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#ifdef HAVE_ATOMIC_BUILTINS
+# include <pthread.h>
+#endif
+
+#include "rsyslog.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "outchannel.h"
+#include "omfile.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "stream.h"
+#include "unicode-helper.h"
+#include "atomic.h"
+#include "statsobj.h"
+#include "sigprov.h"
+#include "cryprov.h"
+#include "parserif.h"
+#include "janitor.h"
+#include "rsconf.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omfile")
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(strm)
+DEFobjCurrIf(statsobj)
+
+/* for our current LRU mechanism, we need a monotonically increasing counters. We use
+ * it much like a "Lamport logical clock": we do not need the actual time, we just need
+ * to know the sequence in which files were accessed. So we use a simple counter to
+ * create that sequence. We use an unsigned 64 bit value which is extremely unlike to
+ * wrap within the lifetime of a process. If we process 1,000,000 file writes per
+ * second, the process could still exist over 500,000 years before a wrap to 0 happens.
+ * That should be sufficient (and even than, there would no really bad effect ;)).
+ * The variable below is the global counter/clock.
+ */
+#ifdef HAVE_ATOMIC_BUILTINS64
+static uint64 clockFileAccess = 0;
+#else
+static unsigned clockFileAccess = 0;
+#endif
+/* and the "tick" function */
+#ifndef HAVE_ATOMIC_BUILTINS
+static pthread_mutex_t mutClock;
+#endif
+static uint64
+getClockFileAccess(void)
+{
+#ifdef HAVE_ATOMIC_BUILTINS64
+ return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock);
+#else
+ return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock);
+#endif
+}
+
+
+/* The following structure is a dynafile name cache entry.
+ */
+struct s_dynaFileCacheEntry {
+ uchar *pName; /* name currently open, if dynamic name */
+ strm_t *pStrm; /* our output stream */
+ void *sigprovFileData; /* opaque data ptr for provider use */
+ uint64 clkTickAccessed;/* for LRU - based on clockFileAccess */
+ short nInactive; /* number of minutes not writen - for close timeout */
+};
+typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
+
+
+#define IOBUF_DFLT_SIZE 4096 /* default size for io buffers */
+#define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */
+#define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */
+#define FLUSHONTX_DFLT 1 /* default for flush on TX end */
+
+
+typedef struct _instanceData {
+ pthread_mutex_t mutWrite; /* guard against multiple instances writing to single file */
+ uchar *fname; /* file or template name (display only) */
+ uchar *tplName; /* name of assigned template */
+ strm_t *pStrm; /* our output stream */
+ short nInactive; /* number of minutes not writen (STATIC files only) */
+ char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */
+ int isDevNull; /* do we "write" to /dev/null? - if so, do nothing */
+ int fCreateMode; /* file creation mode for open() */
+ int fDirCreateMode; /* creation mode for mkdir() */
+ int bCreateDirs; /* auto-create directories? */
+ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */
+ uint8_t iNumTpls; /* number of tpls we use */
+ uid_t fileUID; /* IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int bFailOnChown; /* fail creation if chown fails? */
+ uchar *sigprovName; /* signature provider */
+ uchar *sigprovNameFull;/* full internal signature provider name */
+ sigprov_if_t sigprov; /* ptr to signature provider interface */
+ void *sigprovData; /* opaque data ptr for provider use */
+ void *sigprovFileData;/* opaque data ptr for file instance */
+ sbool useSigprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ uchar *cryprovName; /* crypto provider */
+ uchar *cryprovNameFull;/* full internal crypto provider name */
+ void *cryprovData; /* opaque data ptr for provider use */
+ cryprov_if_t cryprov; /* ptr to crypto provider interface */
+ sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */
+ int iCurrElt; /* currently active cache element (-1 = none) */
+ int iCurrCacheSize; /* currently cache size (1-based) */
+ int iDynaFileCacheSize; /* size of file handle cache */
+ /* The cache is implemented as an array. An empty element is indicated
+ * by a NULL pointer. Memory is allocated as needed. The following
+ * pointer points to the overall structure.
+ */
+ dynaFileCacheEntry **dynCache;
+ off_t iSizeLimit; /* file size limit, 0 = no limit */
+ uchar *pszSizeLimitCmd; /* command to carry out when size limit is reached */
+ int iZipLevel; /* zip mode to use for this selector */
+ int iIOBufSize; /* size of associated io buffer */
+ int iFlushInterval; /* how fast flush buffer on inactivity? */
+ short iCloseTimeout; /* after how many *minutes* shall the file be closed if inactive? */
+ sbool bFlushOnTXEnd; /* flush write buffers when transaction has ended? */
+ sbool bUseAsyncWriter; /* use async stream writer? */
+ sbool bVeryRobustZip;
+ statsobj_t *stats; /* dynafile, primarily cache stats */
+ STATSCOUNTER_DEF(ctrRequests, mutCtrRequests);
+ STATSCOUNTER_DEF(ctrLevel0, mutCtrLevel0);
+ STATSCOUNTER_DEF(ctrEvict, mutCtrEvict);
+ STATSCOUNTER_DEF(ctrMiss, mutCtrMiss);
+ STATSCOUNTER_DEF(ctrMax, mutCtrMax);
+ STATSCOUNTER_DEF(ctrCloseTimeouts, mutCtrCloseTimeouts);
+ char janitorID[128]; /* holds ID for janitor calls */
+} instanceData;
+
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+
+typedef struct configSettings_s {
+ int iDynaFileCacheSize; /* max cache for dynamic files */
+ int fCreateMode; /* mode to use when creating files */
+ int fDirCreateMode; /* mode to use when creating files */
+ int bFailOnChown; /* fail if chown fails? */
+ uid_t fileUID; /* UID to be used for newly created files */
+ uid_t fileGID; /* GID to be used for newly created files */
+ uid_t dirUID; /* UID to be used for newly created directories */
+ uid_t dirGID; /* GID to be used for newly created directories */
+ int bCreateDirs;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
+ int bEnableSync;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
+ int iZipLevel; /* zip compression mode (0..9 as usual) */
+ sbool bFlushOnTXEnd;/* flush write buffers when transaction has ended? */
+ int64 iIOBufSize; /* size of an io buffer */
+ int iFlushInterval; /* how often flush the output buffer on inactivity? */
+ int bUseAsyncWriter; /* should we enable asynchronous writing? */
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t cs;
+uchar *pszFileDfltTplName; /* name of the default template to use */
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+ int fCreateMode; /* default mode to use when creating files */
+ int fDirCreateMode; /* default mode to use when creating files */
+ uid_t fileUID; /* default IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int bDynafileDoNotSuspend;
+ strm_compressionDriver_t compressionDriver;
+ int compressionDriver_workers;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+ { "compression.driver", eCmdHdlrGetWord, 0 },
+ { "compression.zstd.workers", eCmdHdlrPositiveInt, 0 },
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 },
+ { "dirowner", eCmdHdlrUID, 0 },
+ { "dirownernum", eCmdHdlrInt, 0 },
+ { "dirgroup", eCmdHdlrGID, 0 },
+ { "dirgroupnum", eCmdHdlrInt, 0 },
+ { "fileowner", eCmdHdlrUID, 0 },
+ { "fileownernum", eCmdHdlrInt, 0 },
+ { "filegroup", eCmdHdlrGID, 0 },
+ { "dynafile.donotsuspend", eCmdHdlrBinary, 0 },
+ { "filegroupnum", eCmdHdlrInt, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "dynafilecachesize", eCmdHdlrInt, 0 }, /* legacy: dynafilecachesize */
+ { "ziplevel", eCmdHdlrInt, 0 }, /* legacy: omfileziplevel */
+ { "flushinterval", eCmdHdlrInt, 0 }, /* legacy: omfileflushinterval */
+ { "asyncwriting", eCmdHdlrBinary, 0 }, /* legacy: omfileasyncwriting */
+ { "veryrobustzip", eCmdHdlrBinary, 0 },
+ { "flushontxend", eCmdHdlrBinary, 0 }, /* legacy: omfileflushontxend */
+ { "iobuffersize", eCmdHdlrSize, 0 }, /* legacy: omfileiobuffersize */
+ { "dirowner", eCmdHdlrUID, 0 }, /* legacy: dirowner */
+ { "dirownernum", eCmdHdlrInt, 0 }, /* legacy: dirownernum */
+ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */
+ { "dirgroupnum", eCmdHdlrInt, 0 }, /* legacy: dirgroupnum */
+ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */
+ { "fileownernum", eCmdHdlrInt, 0 }, /* legacy: fileownernum */
+ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */
+ { "filegroupnum", eCmdHdlrInt, 0 }, /* legacy: filegroupnum */
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: filecreatemode */
+ { "failonchownfailure", eCmdHdlrBinary, 0 }, /* legacy: failonchownfailure */
+ { "createdirs", eCmdHdlrBinary, 0 }, /* legacy: createdirs */
+ { "sync", eCmdHdlrBinary, 0 }, /* legacy: actionfileenablesync */
+ { "file", eCmdHdlrString, 0 }, /* either "file" or ... */
+ { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */
+ { "sig.provider", eCmdHdlrGetWord, 0 },
+ { "cry.provider", eCmdHdlrGetWord, 0 },
+ { "closetimeout", eCmdHdlrPositiveInt, 0 },
+ { "rotation.sizelimit", eCmdHdlrSize, 0 },
+ { "rotation.sizelimitcommand", eCmdHdlrString, 0 },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(pszFileDfltTplName == NULL)
+ return (uchar*)"RSYSLOG_FileFormat";
+ else
+ return pszFileDfltTplName;
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ pszFileDfltTplName = NULL; /* make sure this can be free'ed! */
+ iRet = resetConfigVariables(NULL, NULL); /* params are dummies */
+ENDinitConfVars
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ if(pData->bDynamicName) {
+ dbgprintf("[dynamic]\n");
+ } else { /* regular file */
+ dbgprintf("%s%s\n", pData->fname,
+ (pData->pStrm == NULL) ? " (closed)" : "");
+ }
+
+ dbgprintf("\ttemplate='%s'\n", pData->fname);
+ dbgprintf("\tuse async writer=%d\n", pData->bUseAsyncWriter);
+ dbgprintf("\tflush on TX end=%d\n", pData->bFlushOnTXEnd);
+ dbgprintf("\tflush interval=%d\n", pData->iFlushInterval);
+ dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize);
+ dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "on" : "off");
+ dbgprintf("\tvery robust zip: %s\n", pData->bCreateDirs ? "on" : "off");
+ dbgprintf("\tfile owner %d, group %d\n", (int) pData->fileUID, (int) pData->fileGID);
+ dbgprintf("\tdirectory owner %d, group %d\n", (int) pData->dirUID, (int) pData->dirGID);
+ dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n",
+ pData->fDirCreateMode, pData->fCreateMode);
+ dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no");
+ENDdbgPrintInstInfo
+
+
+
+/* set the default template to be used
+ * This is a module-global parameter, and as such needs special handling. It needs to
+ * be coordinated with values set via the v2 config system (rsyslog v6+). What we do
+ * is we do not permit this directive after the v2 config system has been used to set
+ * the parameter.
+ */
+static rsRetVal
+setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal)
+{
+ DEFiRet;
+
+ if(loadModConf != NULL && loadModConf->tplName != NULL) {
+ free(newVal);
+ parser_errmsg("omfile: default template already set via module "
+ "global parameter - can no longer be changed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = newVal;
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the dynaFile cache size. Does some limit checking.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+
+ if(iNewVal < 1) {
+ errno = 0;
+ parser_errmsg(
+ "DynaFileCacheSize must be greater 0 (%d given), changed to 1.", iNewVal);
+ iRet = RS_RET_VAL_OUT_OF_RANGE;
+ iNewVal = 1;
+ } else if(iNewVal > 25000) {
+ errno = 0;
+ parser_warnmsg("DynaFileCacheSize is larger than 25,000 (%d given) - this looks very "
+ "large. Is it intended?", iNewVal);
+ }
+
+ cs.iDynaFileCacheSize = iNewVal;
+ DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal);
+
+ RETiRet;
+}
+
+
+/* Helper to cfline(). Parses a output channel name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template. Maps the output channel to the
+ * proper filed structure settings. Everything is stored in the
+ * filed struct. Over time, the dependency on filed might be
+ * removed.
+ * rgerhards 2005-06-21
+ */
+static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringRequest_t *pOMSR,
+ int iEntry, int iTplOpts)
+{
+ DEFiRet;
+ size_t i;
+ struct outchannel *pOch;
+ char szBuf[128]; /* should be more than sufficient */
+
+ ++p; /* skip '$' */
+ i = 0;
+ /* get outchannel name */
+ while(*p && *p != ';' && *p != ' ' &&
+ i < (sizeof(szBuf) - 1) ) {
+ szBuf[i++] = *p++;
+ }
+ szBuf[i] = '\0';
+
+ /* got the name, now look up the channel... */
+ pOch = ochFind(szBuf, i);
+
+ if(pOch == NULL) {
+ parser_errmsg(
+ "outchannel '%s' not found - ignoring action line",
+ szBuf);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ /* check if there is a file name in the outchannel... */
+ if(pOch->pszFileTemplate == NULL) {
+ parser_errmsg(
+ "outchannel '%s' has no file name template - ignoring action line",
+ szBuf);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* OK, we finally got a correct template. So let's use it... */
+ pData->fname = ustrdup(pOch->pszFileTemplate);
+ pData->iSizeLimit = pOch->uSizeLimit;
+ /* WARNING: It is dangerous "just" to pass the pointer. As we
+ * never rebuild the output channel description, this is acceptable here.
+ */
+ pData->pszSizeLimitCmd = pOch->cmdOnSizeLimit;
+
+ iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl());
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function deletes an entry from the dynamic file name
+ * cache. A pointer to the cache must be passed in as well
+ * as the index of the to-be-deleted entry. This index may
+ * point to an unallocated entry, in whcih case the
+ * function immediately returns. Parameter bFreeEntry is 1
+ * if the entry should be free()ed and 0 if not.
+ */
+static rsRetVal
+dynaFileDelCacheEntry(instanceData *__restrict__ const pData, const int iEntry, const int bFreeEntry)
+{
+ dynaFileCacheEntry **pCache = pData->dynCache;
+ DEFiRet;
+ assert(pCache != NULL);
+
+ if(pCache[iEntry] == NULL)
+ FINALIZE;
+
+ DBGPRINTF("Removing entry %d for file '%s' from dynaCache.\n", iEntry,
+ pCache[iEntry]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[iEntry]->pName);
+
+ if(pCache[iEntry]->pName != NULL) {
+ free(pCache[iEntry]->pName);
+ pCache[iEntry]->pName = NULL;
+ }
+
+ if(pCache[iEntry]->pStrm != NULL) {
+ if(iEntry == pData->iCurrElt) {
+ pData->iCurrElt = -1;
+ pData->pStrm = NULL;
+ }
+ strm.Destruct(&pCache[iEntry]->pStrm);
+ if(pData->useSigprov) {
+ pData->sigprov.OnFileClose(pCache[iEntry]->sigprovFileData);
+ pCache[iEntry]->sigprovFileData = NULL;
+ }
+ }
+
+ if(bFreeEntry) {
+ free(pCache[iEntry]);
+ pCache[iEntry] = NULL;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function frees all dynamic file name cache entries and closes the
+ * relevant files. Part of Shutdown and HUP processing.
+ * rgerhards, 2008-10-23
+ */
+static void
+dynaFileFreeCacheEntries(instanceData *__restrict__ const pData)
+{
+ register int i;
+ assert(pData != NULL);
+
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ dynaFileDelCacheEntry(pData, i, 1);
+ }
+ /* invalidate current element */
+ pData->iCurrElt = -1;
+ pData->pStrm = NULL;
+}
+
+
+/* This function frees the dynamic file name cache.
+ */
+static void dynaFileFreeCache(instanceData *__restrict__ const pData)
+{
+ assert(pData != NULL);
+
+ dynaFileFreeCacheEntries(pData);
+ if(pData->dynCache != NULL)
+ free(pData->dynCache);
+}
+
+
+/* close current file */
+static rsRetVal
+closeFile(instanceData *__restrict__ const pData)
+{
+ DEFiRet;
+ if(pData->useSigprov) {
+ pData->sigprov.OnFileClose(pData->sigprovFileData);
+ pData->sigprovFileData = NULL;
+ }
+ strm.Destruct(&pData->pStrm);
+ RETiRet;
+}
+
+
+/* This prepares the signature provider to process a file */
+static rsRetVal
+sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn)
+{
+ DEFiRet;
+ pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData);
+ RETiRet;
+}
+
+/* This is now shared code for all types of files. It simply prepares
+ * file access, which, among others, means the the file wil be opened
+ * and any directories in between will be created (based on config, of
+ * course). -- rgerhards, 2008-10-22
+ * changed to iRet interface - 2009-03-19
+ */
+static rsRetVal
+prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName)
+{
+ int fd;
+ char errStr[1024]; /* buffer for strerr() */
+ DEFiRet;
+
+ pData->pStrm = NULL;
+ if(access((char*)newFileName, F_OK) != 0) {
+ /* file does not exist, create it (and eventually parent directories */
+ if(pData->bCreateDirs) {
+ /* We first need to create parent dirs if they are missing.
+ * We do not report any errors here ourselfs but let the code
+ * fall through to error handler below.
+ */
+ if(makeFileParentDirs(newFileName, ustrlen(newFileName),
+ pData->fDirCreateMode, pData->dirUID,
+ pData->dirGID, pData->bFailOnChown) != 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg( "omfile: creating parent "
+ "directories for file '%s' failed: %s",
+ newFileName, errStr);
+ ABORT_FINALIZE(RS_RET_ERR); /* we give up */
+ }
+ }
+ /* no matter if we needed to create directories or not, we now try to create
+ * the file. -- rgerhards, 2008-12-18 (based on patch from William Tisater)
+ */
+ fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
+ pData->fCreateMode);
+ if(fd != -1) {
+ /* check and set uid/gid */
+ if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ /* we need to set owner/group */
+ if(fchown(fd, pData->fileUID, pData->fileGID) != 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg(
+ "omfile: chown for file '%s' failed: %s",
+ newFileName, errStr);
+ if(pData->bFailOnChown) {
+ close(fd);
+ ABORT_FINALIZE(RS_RET_ERR); /* we give up */
+ }
+ /* we will silently ignore the chown() failure
+ * if configured to do so.
+ */
+ }
+ }
+ close(fd); /* close again, as we need a stream further on */
+ }
+ }
+
+ /* the copies below are clumpsy, but there is no way around given the
+ * anomalies in dirname() and basename() [they MODIFY the provided buffer...]
+ */
+ uchar szNameBuf[MAXFNAME+1];
+ uchar szDirName[MAXFNAME+1];
+ uchar szBaseName[MAXFNAME+1];
+ ustrncpy(szNameBuf, newFileName, MAXFNAME);
+ szNameBuf[MAXFNAME] = '\0';
+ ustrncpy(szDirName, (uchar*)dirname((char*)szNameBuf), MAXFNAME);
+ szDirName[MAXFNAME] = '\0';
+ ustrncpy(szNameBuf, newFileName, MAXFNAME);
+ szNameBuf[MAXFNAME] = '\0';
+ ustrncpy(szBaseName, (uchar*)basename((char*)szNameBuf), MAXFNAME);
+ szBaseName[MAXFNAME] = '\0';
+
+ CHKiRet(strm.Construct(&pData->pStrm));
+ CHKiRet(strm.SetFName(pData->pStrm, szBaseName, ustrlen(szBaseName)));
+ CHKiRet(strm.SetDir(pData->pStrm, szDirName, ustrlen(szDirName)));
+ CHKiRet(strm.SetiZipLevel(pData->pStrm, pData->iZipLevel));
+ CHKiRet(strm.SetbVeryReliableZip(pData->pStrm, pData->bVeryRobustZip));
+ CHKiRet(strm.SetsIOBufSize(pData->pStrm, (size_t) pData->iIOBufSize));
+ CHKiRet(strm.SettOperationsMode(pData->pStrm, STREAMMODE_WRITE_APPEND));
+ CHKiRet(strm.SettOpenMode(pData->pStrm, cs.fCreateMode));
+ CHKiRet(strm.SetcompressionDriver(pData->pStrm, runModConf->compressionDriver));
+ CHKiRet(strm.SetCompressionWorkers(pData->pStrm, runModConf->compressionDriver_workers));
+ CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile));
+ CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE));
+ CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit));
+ if(pData->useCryprov) {
+ CHKiRet(strm.Setcryprov(pData->pStrm, &pData->cryprov));
+ CHKiRet(strm.SetcryprovData(pData->pStrm, pData->cryprovData));
+ }
+ /* set the flush interval only if we actually use it - otherwise it will activate
+ * async processing, which is a real performance waste if we do not do buffered
+ * writes! -- rgerhards, 2009-07-06
+ */
+ if(pData->bUseAsyncWriter)
+ CHKiRet(strm.SetiFlushInterval(pData->pStrm, pData->iFlushInterval));
+ if(pData->pszSizeLimitCmd != NULL)
+ CHKiRet(strm.SetpszSizeLimitCmd(pData->pStrm, ustrdup(pData->pszSizeLimitCmd)));
+ CHKiRet(strm.ConstructFinalize(pData->pStrm));
+
+ if(pData->useSigprov)
+ sigprovPrepare(pData, szNameBuf);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pData->pStrm != NULL) {
+ closeFile(pData);
+ }
+ }
+ RETiRet;
+}
+
+
+/* This function handles dynamic file names. It checks if the
+ * requested file name is already open and, if not, does everything
+ * needed to switch to the it.
+ * Function returns 0 if all went well and non-zero otherwise.
+ * On successful return pData->fd must point to the correct file to
+ * be written.
+ * This is a helper to writeFile(). rgerhards, 2007-07-03
+ */
+static rsRetVal ATTR_NONNULL()
+prepareDynFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName)
+{
+ uint64 ctOldest; /* "timestamp" of oldest element */
+ int iOldest;
+ int i;
+ int iFirstFree;
+ rsRetVal localRet;
+ dynaFileCacheEntry **pCache;
+ DEFiRet;
+
+ assert(pData != NULL);
+ assert(newFileName != NULL);
+
+ pCache = pData->dynCache;
+
+ /* first check, if we still have the current file */
+ if( (pData->iCurrElt != -1)
+ && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) {
+ /* great, we are all set */
+ pCache[pData->iCurrElt]->clkTickAccessed = getClockFileAccess();
+ STATSCOUNTER_INC(pData->ctrLevel0, pData->mutCtrLevel0);
+ /* LRU needs only a strictly monotonically increasing counter, so such a one could do */
+ FINALIZE;
+ }
+
+ /* ok, no luck - current file cannot be re-used */
+
+ /* if we need to flush (at least) on TXEnd, we need to flush now - because
+ * we do not know if we will otherwise come back to this file to flush it
+ * at end of TX. see https://github.com/rsyslog/rsyslog/issues/2502
+ */
+ if(((runModConf->pConf->globals.glblDevOptions & DEV_OPTION_8_1905_HANG_TEST) == 0) &&
+ pData->bFlushOnTXEnd && pData->pStrm != NULL) {
+ CHKiRet(strm.Flush(pData->pStrm));
+ }
+
+ /* Now let's search the table if we find a matching spot.
+ * While doing so, we also prepare for creation of a new one.
+ */
+ pData->iCurrElt = -1; /* invalid current element pointer */
+ iFirstFree = -1; /* not yet found */
+ iOldest = 0; /* we assume the first element to be the oldest - that will change as we loop */
+ ctOldest = getClockFileAccess(); /* there must always be an older one */
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL || pCache[i]->pName == NULL) {
+ if(iFirstFree == -1)
+ iFirstFree = i;
+ } else { /* got an element, let's see if it matches */
+ if(!ustrcmp(newFileName, pCache[i]->pName)) {
+ /* we found our element! */
+ pData->pStrm = pCache[i]->pStrm;
+ if(pData->useSigprov)
+ pData->sigprovFileData = pCache[i]->sigprovFileData;
+ pData->iCurrElt = i;
+ pCache[i]->clkTickAccessed = getClockFileAccess(); /* update "timestamp" for LRU */
+ FINALIZE;
+ }
+ /* did not find it - so lets keep track of the counters for LRU */
+ if(pCache[i]->clkTickAccessed < ctOldest) {
+ ctOldest = pCache[i]->clkTickAccessed;
+ iOldest = i;
+ }
+ }
+ }
+
+ /* we have not found an entry */
+ STATSCOUNTER_INC(pData->ctrMiss, pData->mutCtrMiss);
+
+ /* similarly, we need to set the current pStrm to NULL, because otherwise, if prepareFile() fails,
+ * we may end up using an old stream. This bug depends on how exactly prepareFile fails,
+ * but it could be triggered in the common case of a failed open() system call.
+ * rgerhards, 2010-03-22
+ */
+ pData->pStrm = NULL, pData->sigprovFileData = NULL;
+
+ if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) {
+ /* there is space left, so set it to that index */
+ iFirstFree = pData->iCurrCacheSize++;
+ STATSCOUNTER_SETMAX_NOMUT(pData->ctrMax, (unsigned) pData->iCurrCacheSize);
+ }
+
+ /* Note that the following code sequence does not work with the cache entry itself,
+ * but rather with pData->pStrm, the (sole) stream pointer in the non-dynafile case.
+ * The cache array is only updated after the open was successful. -- rgerhards, 2010-03-21
+ */
+ if(iFirstFree == -1) {
+ dynaFileDelCacheEntry(pData, iOldest, 0);
+ STATSCOUNTER_INC(pData->ctrEvict, pData->mutCtrEvict);
+ iFirstFree = iOldest; /* this one *is* now free ;) */
+ } else {
+ /* we need to allocate memory for the cache structure */
+ CHKmalloc(pCache[iFirstFree] = (dynaFileCacheEntry*) calloc(1, sizeof(dynaFileCacheEntry)));
+ }
+
+ /* Ok, we finally can open the file */
+ localRet = prepareFile(pData, newFileName); /* ignore exact error, we check fd below */
+
+ /* check if we had an error */
+ if(localRet != RS_RET_OK) {
+ /* We do no longer care about internal messages. The errmsg rate limiter
+ * will take care of too-frequent error messages.
+ */
+ parser_errmsg("Could not open dynamic file '%s' [state %d] - discarding "
+ "message", newFileName, localRet);
+ ABORT_FINALIZE(localRet);
+ }
+
+ if((pCache[iFirstFree]->pName = ustrdup(newFileName)) == NULL) {
+ closeFile(pData); /* need to free failed entry! */
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ pCache[iFirstFree]->pStrm = pData->pStrm;
+ if(pData->useSigprov)
+ pCache[iFirstFree]->sigprovFileData = pData->sigprovFileData;
+ pCache[iFirstFree]->clkTickAccessed = getClockFileAccess();
+ pData->iCurrElt = iFirstFree;
+ DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName);
+
+finalize_it:
+ if(iRet == RS_RET_OK)
+ pCache[pData->iCurrElt]->nInactive = 0;
+ RETiRet;
+}
+
+
+/* do the actual write process. This function is to be called once we are ready for writing.
+ * It will do buffered writes and persist data only when the buffer is full. Note that we must
+ * be careful to detect when the file handle changed.
+ * rgerhards, 2009-06-03
+ */
+static rsRetVal
+doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf)
+{
+ DEFiRet;
+ assert(pData != NULL);
+ assert(pszBuf != NULL);
+
+ DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, strt data %.128s\n",
+ pData->pStrm, lenBuf, pszBuf);
+ if(pData->pStrm != NULL){
+ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf));
+ if(pData->useSigprov) {
+ CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, pszBuf, lenBuf));
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* rgerhards 2004-11-11: write to a file output. */
+static rsRetVal
+writeFile(instanceData *__restrict__ const pData,
+ const actWrkrIParams_t *__restrict__ const pParam,
+ const int iMsg)
+{
+ DEFiRet;
+
+ STATSCOUNTER_INC(pData->ctrRequests, pData->mutCtrRequests);
+ /* first check if we have a dynamic file name and, if so,
+ * check if it still is ok or a new file needs to be created
+ */
+ if(pData->bDynamicName) {
+ DBGPRINTF("omfile: file to log to: %s\n",
+ actParam(pParam, pData->iNumTpls, iMsg, 1).param);
+ CHKiRet(prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param));
+ } else { /* "regular", non-dynafile */
+ if(pData->pStrm == NULL) {
+ CHKiRet(prepareFile(pData, pData->fname));
+ if(pData->pStrm == NULL) {
+ parser_errmsg(
+ "Could not open output file '%s'", pData->fname);
+ }
+ }
+ pData->nInactive = 0;
+ }
+
+ iRet = doWrite(pData, actParam(pParam, pData->iNumTpls, iMsg, 0).param,
+ actParam(pParam, pData->iNumTpls, iMsg, 0).lenStr);
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ pModConf->fCreateMode = 0644;
+ pModConf->fDirCreateMode = 0700;
+ pModConf->fileUID = -1;
+ pModConf->dirUID = -1;
+ pModConf->fileGID = -1;
+ pModConf->dirGID = -1;
+ pModConf->bDynafileDoNotSuspend = 1;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omfile:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed) {
+ continue;
+ }
+
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pszFileDfltTplName != NULL) {
+ parser_errmsg("omfile: warning: default template was already "
+ "set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "compression.driver")) {
+ if(!es_strcasebufcmp(pvals[i].val.d.estr, (const unsigned char*) "zlib", 4)) {
+ loadModConf->compressionDriver = STRM_COMPRESS_ZIP;
+ } else if(!es_strcasebufcmp(pvals[i].val.d.estr, (const unsigned char*) "zstd", 4)) {
+ loadModConf->compressionDriver = STRM_COMPRESS_ZSTD;
+ } else {
+ parser_errmsg("omfile: error: invalid compression.driver driver "
+ "name - noch applying setting. Valid drivers: 'zlib' and "
+ "'zstd'.");
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "compression.zstd.workers")) {
+ loadModConf->compressionDriver_workers = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dircreatemode")) {
+ loadModConf->fDirCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filecreatemode")) {
+ loadModConf->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirowner")) {
+ loadModConf->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirownernum")) {
+ loadModConf->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirgroup")) {
+ loadModConf->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dirgroupnum")) {
+ loadModConf->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "fileowner")) {
+ loadModConf->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "fileownernum")) {
+ loadModConf->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filegroup")) {
+ loadModConf->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "filegroupnum")) {
+ loadModConf->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "dynafile.donotsuspend")) {
+ loadModConf->bDynafileDoNotSuspend = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("omfile: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+/* This function checks dynafile cache for janitor action */
+static void
+janitorChkDynaFiles(instanceData *__restrict__ const pData)
+{
+ int i;
+ dynaFileCacheEntry **pCache = pData->dynCache;
+
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL)
+ continue;
+ DBGPRINTF("omfile janitor: checking dynafile %d:%s, inactive since %d\n", i,
+ pCache[i]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[i]->pName,
+ (int) pCache[i]->nInactive);
+ if(pCache[i]->nInactive >= pData->iCloseTimeout) {
+ STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ dynaFileDelCacheEntry(pData, i, 1);
+ if(pData->iCurrElt == i)
+ pData->iCurrElt = -1; /* no longer available! */
+ } else {
+ pCache[i]->nInactive += runModConf->pConf->globals.janitorInterval;
+ }
+ }
+}
+
+/* callback for the janitor. This cleans out files (if so configured) */
+static void
+janitorCB(void *pUsr)
+{
+ instanceData *__restrict__ const pData = (instanceData *) pUsr;
+ pthread_mutex_lock(&pData->mutWrite);
+ if(pData->bDynamicName) {
+ janitorChkDynaFiles(pData);
+ } else {
+ if(pData->pStrm != NULL) {
+ DBGPRINTF("omfile janitor: checking file %s, inactive since %d\n",
+ pData->fname, pData->nInactive);
+ if(pData->nInactive >= pData->iCloseTimeout) {
+ STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ closeFile(pData);
+ } else {
+ pData->nInactive += runModConf->pConf->globals.janitorInterval;
+ }
+ }
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+}
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->pStrm = NULL;
+ pthread_mutex_init(&pData->mutWrite, NULL);
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ free(pData->fname);
+ if(pData->iCloseTimeout > 0)
+ janitorDelEtry(pData->janitorID);
+ if(pData->bDynamicName) {
+ dynaFileFreeCache(pData);
+ } else if(pData->pStrm != NULL)
+ closeFile(pData);
+ if(pData->stats != NULL)
+ statsobj.Destruct(&(pData->stats));
+ if(pData->useSigprov) {
+ pData->sigprov.Destruct(&pData->sigprovData);
+ obj.ReleaseObj(__FILE__, pData->sigprovNameFull+2, pData->sigprovNameFull,
+ (void*) &pData->sigprov);
+ free(pData->sigprovName);
+ free(pData->sigprovNameFull);
+ }
+ if(pData->useCryprov) {
+ pData->cryprov.Destruct(&pData->cryprovData);
+ obj.ReleaseObj(__FILE__, pData->cryprovNameFull+2, pData->cryprovNameFull,
+ (void*) &pData->cryprov);
+ free(pData->cryprovName);
+ free(pData->cryprovNameFull);
+ }
+ pthread_mutex_destroy(&pData->mutWrite);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ /* we have nothing to do to begin a transaction */
+ENDbeginTransaction
+
+
+BEGINcommitTransaction
+ instanceData *__restrict__ const pData = pWrkrData->pData;
+ unsigned i;
+CODESTARTcommitTransaction
+
+ if(pData->isDevNull) {
+ goto terminate;
+ }
+
+ pthread_mutex_lock(&pData->mutWrite);
+
+ for(i = 0 ; i < nParams ; ++i) {
+ writeFile(pData, pParams, i);
+ }
+ /* Note: pStrm may be NULL if there was an error opening the stream */
+ /* if bFlushOnTXEnd is set, we need to flush on transaction end - in
+ * any case. It is not relevant if this is using background writes
+ * (which then become pretty slow) or not. And, similarly, no flush
+ * happens when it is not set. Please see
+ * https://github.com/rsyslog/rsyslog/issues/1297
+ * for a discussion of why we actually need this.
+ * rgerhards, 2017-01-13
+ */
+ if(pData->bFlushOnTXEnd && pData->pStrm != NULL) {
+ CHKiRet(strm.Flush(pData->pStrm));
+ }
+
+finalize_it:
+ pthread_mutex_unlock(&pData->mutWrite);
+ if(iRet == RS_RET_FILE_OPEN_ERROR || iRet == RS_RET_FILE_NOT_FOUND) {
+ iRet = (pData->bDynamicName && runModConf->bDynafileDoNotSuspend) ?
+ RS_RET_OK : RS_RET_SUSPENDED;
+ }
+
+terminate:
+ENDcommitTransaction
+
+
+static void
+setInstParamDefaults(instanceData *__restrict__ const pData)
+{
+ pData->fname = NULL;
+ pData->tplName = NULL;
+ pData->fileUID = loadModConf->fileUID;
+ pData->fileGID = loadModConf->fileGID;
+ pData->dirUID = loadModConf->dirUID;
+ pData->dirGID = loadModConf->dirGID;
+ pData->bFailOnChown = 1;
+ pData->iDynaFileCacheSize = 10;
+ pData->fCreateMode = loadModConf->fCreateMode;
+ pData->fDirCreateMode = loadModConf->fDirCreateMode;
+ pData->bCreateDirs = 1;
+ pData->bSyncFile = 0;
+ pData->iZipLevel = 0;
+ pData->bVeryRobustZip = 0;
+ pData->bFlushOnTXEnd = FLUSHONTX_DFLT;
+ pData->iIOBufSize = IOBUF_DFLT_SIZE;
+ pData->iFlushInterval = FLUSH_INTRVL_DFLT;
+ pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+ pData->sigprovName = NULL;
+ pData->cryprovName = NULL;
+ pData->useSigprov = 0;
+ pData->useCryprov = 0;
+ pData->iCloseTimeout = -1;
+ pData->iSizeLimit = 0;
+ pData->isDevNull = 0;
+ pData->pszSizeLimitCmd = NULL;
+}
+
+
+static rsRetVal
+setupInstStatsCtrs(instanceData *__restrict__ const pData)
+{
+ uchar ctrName[512];
+ DEFiRet;
+
+ if(!pData->bDynamicName) {
+ FINALIZE;
+ }
+
+ /* support statistics gathering */
+ snprintf((char*)ctrName, sizeof(ctrName), "dynafile cache %s", pData->fname);
+ ctrName[sizeof(ctrName)-1] = '\0'; /* be on the save side */
+ CHKiRet(statsobj.Construct(&(pData->stats)));
+ CHKiRet(statsobj.SetName(pData->stats, ctrName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar*)"omfile"));
+ STATSCOUNTER_INIT(pData->ctrRequests, pData->mutCtrRequests);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("requests"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrRequests)));
+ STATSCOUNTER_INIT(pData->ctrLevel0, pData->mutCtrLevel0);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("level0"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrLevel0)));
+ STATSCOUNTER_INIT(pData->ctrMiss, pData->mutCtrMiss);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("missed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMiss)));
+ STATSCOUNTER_INIT(pData->ctrEvict, pData->mutCtrEvict);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("evicted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrEvict)));
+ STATSCOUNTER_INIT(pData->ctrMax, pData->mutCtrMax);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("maxused"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMax)));
+ STATSCOUNTER_INIT(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("closetimeouts"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrCloseTimeouts)));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+
+finalize_it:
+ RETiRet;
+}
+
+static void
+initSigprov(instanceData *__restrict__ const pData, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmsig_%s", pData->sigprovName)
+ == sizeof(szDrvrName)) {
+ parser_errmsg("omfile: signature provider "
+ "name is too long: '%s' - signatures disabled",
+ pData->sigprovName);
+ goto done;
+ }
+ pData->sigprovNameFull = ustrdup(szDrvrName);
+
+ pData->sigprov.ifVersion = sigprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pData->sigprov)
+ != RS_RET_OK) {
+ parser_errmsg("omfile: could not load "
+ "signature provider '%s' - signatures disabled",
+ szDrvrName);
+ goto done;
+ }
+
+ if(pData->sigprov.Construct(&pData->sigprovData) != RS_RET_OK) {
+ parser_errmsg("omfile: error constructing "
+ "signature provider %s dataset - signatures disabled",
+ szDrvrName);
+ goto done;
+ }
+ pData->sigprov.SetCnfParam(pData->sigprovData, lst);
+
+ dbgprintf("loaded signature provider %s, data instance at %p\n",
+ szDrvrName, pData->sigprovData);
+ pData->useSigprov = 1;
+done: return;
+}
+
+static rsRetVal
+initCryprov(instanceData *__restrict__ const pData, struct nvlst *lst)
+{
+ uchar szDrvrName[1024];
+ DEFiRet;
+
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pData->cryprovName)
+ == sizeof(szDrvrName)) {
+ parser_errmsg("omfile: crypto provider "
+ "name is too long: '%s' - encryption disabled",
+ pData->cryprovName);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ pData->cryprovNameFull = ustrdup(szDrvrName);
+
+ pData->cryprov.ifVersion = cryprovCURR_IF_VERSION;
+ /* The pDrvrName+2 below is a hack to obtain the object name. It
+ * safes us to have yet another variable with the name without "lm" in
+ * front of it. If we change the module load interface, we may re-think
+ * about this hack, but for the time being it is efficient and clean enough.
+ */
+ if(obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void*) &pData->cryprov)
+ != RS_RET_OK) {
+ parser_errmsg("omfile: could not load "
+ "crypto provider '%s' - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+
+ if(pData->cryprov.Construct(&pData->cryprovData) != RS_RET_OK) {
+ parser_errmsg("omfile: error constructing "
+ "crypto provider %s dataset - encryption disabled",
+ szDrvrName);
+ ABORT_FINALIZE(RS_RET_CRYPROV_ERR);
+ }
+ CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst, CRYPROV_PARAMTYPE_REGULAR));
+
+ dbgprintf("loaded crypto provider %s, data instance at %p\n",
+ szDrvrName, pData->cryprovData);
+ pData->useCryprov = 1;
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplToUse;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omfile)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ parser_errmsg("omfile: either the \"file\" or "
+ "\"dynafile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omfile:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "dynafilecachesize")) {
+ pData->iDynaFileCacheSize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) {
+ pData->iZipLevel = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushinterval")) {
+ pData->iFlushInterval = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "veryrobustzip")) {
+ pData->bVeryRobustZip = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "asyncwriting")) {
+ pData->bUseAsyncWriter = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushontxend")) {
+ pData->bFlushOnTXEnd = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "iobuffersize")) {
+ pData->iIOBufSize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirowner")) {
+ pData->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirownernum")) {
+ pData->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirgroup")) {
+ pData->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirgroupnum")) {
+ pData->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "fileowner")) {
+ pData->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "fileownernum")) {
+ pData->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filegroup")) {
+ pData->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filegroupnum")) {
+ pData->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dircreatemode")) {
+ pData->fDirCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filecreatemode")) {
+ pData->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "failonchownfailure")) {
+ pData->bFailOnChown = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "sync")) {
+ pData->bSyncFile = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "createdirs")) {
+ pData->bCreateDirs = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "file")) {
+ pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ pData->bDynamicName = 0;
+ } else if(!strcmp(actpblk.descr[i].name, "dynafile")) {
+ if(pData->fname != NULL) {
+ parser_errmsg("omfile: both \"file\" and \"dynafile\" set, will use dynafile");
+ }
+ pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(2)
+ pData->bDynamicName = 1;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "sig.provider")) {
+ pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) {
+ pData->cryprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "closetimeout")) {
+ pData->iCloseTimeout = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "rotation.sizelimit")) {
+ pData->iSizeLimit = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "rotation.sizelimitcommand")) {
+ pData->pszSizeLimitCmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omfile: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->fname == NULL || *pData->fname == '\0') {
+ parser_errmsg("omfile: either the \"file\" or "
+ "\"dynafile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ int allWhiteSpace = 1;
+ for(const char *p = (const char*) pData->fname ; *p ; ++p) {
+ if(!isspace(*p)) {
+ allWhiteSpace = 0;
+ break;
+ }
+ }
+ if(allWhiteSpace) {
+ parser_errmsg("omfile: \"file\" or \"dynafile\" parameter "
+ "consist only of whitespace - this is not permitted");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(!strcmp((const char*) pData->fname, "/dev/null")) {
+ pData->isDevNull = 1;
+ }
+
+ if(pData->sigprovName != NULL) {
+ initSigprov(pData, lst);
+ }
+
+ if(pData->cryprovName != NULL) {
+ CHKiRet(initCryprov(pData, lst));
+ }
+
+ tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
+ pData->iNumTpls = 1;
+
+ if(pData->bDynamicName) {
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS));
+ pData->iNumTpls = 2;
+ // TODO: create unified code for this (legacy+v6 system)
+ /* we now allocate the cache table */
+ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+ calloc(pData->iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ pData->iCurrElt = -1; /* no current element */
+ }
+// TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
+ setupInstStatsCtrs(pData);
+
+ if(pData->iCloseTimeout == -1) { /* unset? */
+ pData->iCloseTimeout = (pData->bDynamicName) ? 10 : 0;
+ }
+
+ snprintf(pData->janitorID, sizeof(pData->janitorID), "omfile:%sfile:%s:%p",
+ (pData->bDynamicName) ? "dyna" : "", pData->fname, pData);
+ pData->janitorID[sizeof(pData->janitorID)-1] = '\0'; /* just in case... */
+
+ if(pData->iCloseTimeout > 0)
+ janitorAddEtry(janitorCB, pData->janitorID, pData);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ uchar fname[MAXFNAME];
+CODESTARTparseSelectorAct
+ /* Note: the indicator sequence permits us to use '$' to signify
+ * outchannel, what otherwise is not possible due to truely
+ * unresolvable grammar conflicts (*this time no way around*).
+ * rgerhards, 2011-07-09
+ */
+ if(!strncmp((char*) p, ":omfile:", sizeof(":omfile:") - 1)) {
+ p += sizeof(":omfile:") - 1;
+ }
+ if(!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-'))
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+
+ CHKiRet(createInstance(&pData));
+
+ if(*p == '-') {
+ pData->bSyncFile = 0;
+ p++;
+ } else {
+ pData->bSyncFile = cs.bEnableSync;
+ }
+ pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
+
+ switch(*p) {
+ case '$':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ pData->iNumTpls = 1;
+ /* rgerhards 2005-06-21: this is a special setting for output-channel
+ * definitions. In the long term, this setting will probably replace
+ * anything else, but for the time being we must co-exist with the
+ * traditional mode lines.
+ * rgerhards, 2007-07-24: output-channels will go away. We keep them
+ * for compatibility reasons, but seems to have been a bad idea.
+ */
+ CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+ pData->bDynamicName = 0;
+ break;
+
+ case '?': /* This is much like a regular file handle, but we need to obtain
+ * a template name. rgerhards, 2007-07-03
+ */
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ pData->iNumTpls = 2;
+ ++p; /* eat '?' */
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl()));
+ pData->fname = ustrdup(fname);
+ pData->bDynamicName = 1;
+ pData->iCurrElt = -1; /* no current element */
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS));
+ /* we now allocate the cache table */
+ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+ calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ break;
+
+ case '/':
+ case '.':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ pData->iNumTpls = 1;
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl()));
+ pData->fname = ustrdup(fname);
+ pData->bDynamicName = 0;
+ break;
+ default:
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* freeze current paremeters for this action */
+ pData->iDynaFileCacheSize = cs.iDynaFileCacheSize;
+ pData->fCreateMode = cs.fCreateMode;
+ pData->fDirCreateMode = cs.fDirCreateMode;
+ pData->bCreateDirs = cs.bCreateDirs;
+ pData->bFailOnChown = cs.bFailOnChown;
+ pData->fileUID = cs.fileUID;
+ pData->fileGID = cs.fileGID;
+ pData->dirUID = cs.dirUID;
+ pData->dirGID = cs.dirGID;
+ pData->iZipLevel = cs.iZipLevel;
+ pData->bFlushOnTXEnd = cs.bFlushOnTXEnd;
+ pData->iIOBufSize = (int) cs.iIOBufSize;
+ pData->iFlushInterval = cs.iFlushInterval;
+ pData->bUseAsyncWriter = cs.bUseAsyncWriter;
+ pData->bVeryRobustZip = 0; /* cannot be specified via legacy conf */
+ pData->iCloseTimeout = 0; /* cannot be specified via legacy conf */
+ setupInstStatsCtrs(pData);
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.fileUID = -1;
+ cs.fileGID = -1;
+ cs.dirUID = -1;
+ cs.dirGID = -1;
+ cs.bFailOnChown = 1;
+ cs.iDynaFileCacheSize = 10;
+ cs.fCreateMode = 0644;
+ cs.fDirCreateMode = 0700;
+ cs.bCreateDirs = 1;
+ cs.bEnableSync = 0;
+ cs.iZipLevel = 0;
+ cs.bFlushOnTXEnd = FLUSHONTX_DFLT;
+ cs.iIOBufSize = IOBUF_DFLT_SIZE;
+ cs.iFlushInterval = FLUSH_INTRVL_DFLT;
+ cs.bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ return RS_RET_OK;
+}
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutWrite);
+ if(pData->bDynamicName) {
+ dynaFileFreeCacheEntries(pData);
+ } else {
+ if(pData->pStrm != NULL) {
+ closeFile(pData);
+ }
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+ENDdoHUP
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(strm, CORE_COMPONENT);
+ objRelease(statsobj, CORE_COMPONENT);
+ DESTROY_ATOMIC_HELPER_MUT(mutClock);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_doHUP
+ENDqueryEtryPt
+
+
+BEGINmodInit(File)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+INITLegCnfVars
+ CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ INIT_ATOMIC_HELPER_MUT(mutClock);
+
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, setDynaFileCacheSize,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &cs.iZipLevel,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &cs.iFlushInterval,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileasyncwriting", 0, eCmdHdlrBinary, NULL, &cs.bUseAsyncWriter,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &cs.bFlushOnTXEnd,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &cs.iIOBufSize,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &cs.dirUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirownernum", 0, eCmdHdlrInt, NULL, &cs.dirUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &cs.dirGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroupnum", 0, eCmdHdlrInt, NULL, &cs.dirGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &cs.fileUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileownernum", 0, eCmdHdlrInt, NULL, &cs.fileUID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &cs.fileGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroupnum", 0, eCmdHdlrInt, NULL, &cs.fileGID,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL,
+ &cs.fDirCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL,
+ &cs.fCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &cs.bCreateDirs,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &cs.bFailOnChown,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrGoneAway, NULL, NULL,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &cs.bEnableSync,
+ STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl,
+ NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables,
+ NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/tools/omfile.h b/tools/omfile.h
new file mode 100644
index 0000000..dc7298d
--- /dev/null
+++ b/tools/omfile.h
@@ -0,0 +1,38 @@
+/* omfile.h
+ * These are the definitions for the build-in file output module.
+ *
+ * File begun on 2007-07-21 by RGerhards
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMFILE_H_INCLUDED
+#define OMFILE_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitFile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(),
+ rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+/* the define below is dirty, but we need it for ompipe integration. There is no
+ * other way to have the functionality (well, one way would be to go through the
+ * globals, but that seems not yet justified. -- rgerhards, 2010-03-01
+ */
+extern uchar *pszFileDfltTplName;
+#endif /* #ifndef OMFILE_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/omfwd.c b/tools/omfwd.c
new file mode 100644
index 0000000..d1eeeff
--- /dev/null
+++ b/tools/omfwd.c
@@ -0,0 +1,1778 @@
+/* omfwd.c
+ * This is the implementation of the build-in forwarding output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * Copyright 2007-2021 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <zlib.h>
+#include <pthread.h>
+#include "rsyslog.h"
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "netstrms.h"
+#include "netstrm.h"
+#include "omfwd.h"
+#include "template.h"
+#include "msg.h"
+#include "tcpclt.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+#include "parserif.h"
+#include "ratelimit.h"
+#include "statsobj.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omfwd")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrms)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(tcpclt)
+DEFobjCurrIf(statsobj)
+
+
+/* some local constants (just) for better readybility */
+#define IS_FLUSH 1
+#define NO_FLUSH 0
+
+typedef struct _instanceData {
+ uchar *tplName; /* name of assigned template */
+ uchar *pszStrmDrvr;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrPermitExpiredCerts;
+ permittedPeers_t *pPermPeers;
+ int iStrmDrvrMode;
+ int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */
+ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */
+ int iStrmTlsVerifyDepth; /**< Verify Depth for certificate chains */
+ const uchar *pszStrmDrvrCAFile;
+ const uchar *pszStrmDrvrCRLFile;
+ const uchar *pszStrmDrvrKeyFile;
+ const uchar *pszStrmDrvrCertFile;
+ char *target;
+ char *address;
+ char *device;
+ int compressionLevel; /* 0 - no compression, else level for zlib */
+ char *port;
+ int protocol;
+ char *networkNamespace;
+ int originalNamespace;
+ int iRebindInterval; /* rebind interval */
+ sbool bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int iConErrSkip; /* skipping excessive connection errors */
+ uchar *gnutlsPriorityString;
+ int ipfreebind;
+
+# define FORW_UDP 0
+# define FORW_TCP 1
+ /* following fields for UDP-based delivery */
+ int bSendToAll;
+ int iUDPSendDelay;
+ int UDPSendBuf;
+ /* following fields for TCP-based delivery */
+ TCPFRAMINGMODE tcp_framing;
+ uchar tcp_framingDelimiter;
+ int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */
+# define COMPRESS_NEVER 0
+# define COMPRESS_SINGLE_MSG 1 /* old, single-message compression */
+ /* all other settings are for stream-compression */
+# define COMPRESS_STREAM_ALWAYS 2
+ uint8_t compressionMode;
+ int errsToReport; /* max number of errors to report (per instance) */
+ sbool strmCompFlushOnTxEnd; /* flush stream compression on transaction end? */
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ ratelimit_t *ratelimiter;
+ statsobj_t *stats; /* dynafile, primarily cache stats */
+ intctr_t sentBytes;
+ DEF_ATOMIC_HELPER_MUT64(mut_sentBytes)
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+ netstrms_t *pNS; /* netstream subsystem */
+ netstrm_t *pNetstrm; /* our output netstream */
+ struct addrinfo *f_addr;
+ int *pSockArray; /* sockets to use for UDP */
+ int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */
+ int nXmit; /* number of transmissions since last (re-)bind */
+ tcpclt_t *pTCPClt; /* our tcpclt object */
+ sbool bzInitDone; /* did we do an init of zstrm already? */
+ z_stream zstrm; /* zip stream to use for tcp compression */
+ uchar sndBuf[16*1024]; /* this is intensionally fixed -- see no good reason to make configurable */
+ unsigned offsSndBuf; /* next free spot in send buffer */
+ int errsToReport; /* (remaining) number of errors to report */
+} wrkrInstanceData_t;
+
+/* config data */
+typedef struct configSettings_s {
+ uchar *pszTplName; /* name of the default template to use */
+ uchar *pszStrmDrvr; /* name of the stream driver to use */
+ int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */
+ uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
+ uchar *pszStrmDrvrPermitExpiredCerts; /* control how to handly expired certificates */
+ int iTCPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ int iUDPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ int bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int iConErrSkip;
+ uchar *gnutlsPriorityString;
+ permittedPeers_t *pPermPeers;
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 0 },
+ { "address", eCmdHdlrGetWord, 0 },
+ { "device", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "protocol", eCmdHdlrGetWord, 0 },
+ { "networknamespace", eCmdHdlrGetWord, 0 },
+ { "tcp_framing", eCmdHdlrGetWord, 0 },
+ { "tcp_framedelimiter", eCmdHdlrInt, 0 },
+ { "ziplevel", eCmdHdlrInt, 0 },
+ { "compression.mode", eCmdHdlrGetWord, 0 },
+ { "compression.stream.flushontxend", eCmdHdlrBinary, 0 },
+ { "ipfreebind", eCmdHdlrInt, 0 },
+ { "maxerrormessages", eCmdHdlrInt, CNFPARAM_DEPRECATED },
+ { "rebindinterval", eCmdHdlrInt, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.time", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.interval", eCmdHdlrNonNegInt, 0 },
+ { "conerrskip", eCmdHdlrNonNegInt, 0 },
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
+ { "streamdriver", eCmdHdlrGetWord, 0 },
+ { "streamdrivermode", eCmdHdlrInt, 0 },
+ { "streamdriverauthmode", eCmdHdlrGetWord, 0 },
+ { "streamdriverpermittedpeers", eCmdHdlrGetWord, 0 },
+ { "streamdriver.permitexpiredcerts", eCmdHdlrGetWord, 0 },
+ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
+ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
+ { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 },
+ { "streamdriver.cafile", eCmdHdlrString, 0 },
+ { "streamdriver.keyfile", eCmdHdlrString, 0 },
+ { "streamdriver.certfile", eCmdHdlrString, 0 },
+ { "resendlastmsgonreconnect", eCmdHdlrBinary, 0 },
+ { "udp.sendtoall", eCmdHdlrBinary, 0 },
+ { "udp.senddelay", eCmdHdlrInt, 0 },
+ { "udp.sendbuf", eCmdHdlrSize, 0 },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+static rsRetVal initTCP(wrkrInstanceData_t *pWrkrData);
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.pszTplName = NULL; /* name of the default template to use */
+ cs.pszStrmDrvr = NULL; /* name of the stream driver to use */
+ cs.iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ cs.bResendLastOnRecon = 0; /* should the last message be re-sent on a successful reconnect? */
+ cs.pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
+ cs.iUDPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ cs.iTCPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ cs.pPermPeers = NULL;
+ENDinitConfVars
+
+
+static rsRetVal doTryResume(wrkrInstanceData_t *);
+static rsRetVal doZipFinish(wrkrInstanceData_t *);
+
+/* this function gets the default template. It coordinates action between
+ * old-style and new-style configuration parts.
+ */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else if(cs.pszTplName == NULL)
+ return (uchar*)"RSYSLOG_TraditionalForwardFormat";
+ else
+ return cs.pszTplName;
+}
+
+
+/* set the default template to be used
+ * This is a module-global parameter, and as such needs special handling. It needs to
+ * be coordinated with values set via the v2 config system (rsyslog v6+). What we do
+ * is we do not permit this directive after the v2 config system has been used to set
+ * the parameter.
+ */
+static rsRetVal
+setLegacyDfltTpl(void __attribute__((unused)) *pVal, uchar* newVal)
+{
+ DEFiRet;
+
+ if(loadModConf != NULL && loadModConf->tplName != NULL) {
+ free(newVal);
+ LogError(0, RS_RET_ERR, "omfwd default template already set via module "
+ "global parameter - can no longer be changed");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ free(cs.pszTplName);
+ cs.pszTplName = newVal;
+finalize_it:
+ RETiRet;
+}
+
+/* Close the UDP sockets.
+ * rgerhards, 2009-05-29
+ */
+static rsRetVal
+closeUDPSockets(wrkrInstanceData_t *pWrkrData)
+{
+ DEFiRet;
+ if(pWrkrData->pSockArray != NULL) {
+ net.closeUDPListenSockets(pWrkrData->pSockArray);
+ pWrkrData->pSockArray = NULL;
+ freeaddrinfo(pWrkrData->f_addr);
+ pWrkrData->f_addr = NULL;
+ }
+pWrkrData->bIsConnected = 0; // TODO: remove this variable altogether
+ RETiRet;
+}
+
+
+/* destruct the TCP helper objects
+ * This, for example, is needed after something went wrong.
+ * This function is void because it "can not" fail.
+ * rgerhards, 2008-06-04
+ * Note that we DO NOT discard the current buffer contents
+ * (if any). This permits us to save data between sessions. In
+ * the worst case, some duplication occurs, but we do not
+ * loose data.
+ */
+static void
+DestructTCPInstanceData(wrkrInstanceData_t *pWrkrData)
+{
+ doZipFinish(pWrkrData);
+ if(pWrkrData->pNetstrm != NULL)
+ netstrm.Destruct(&pWrkrData->pNetstrm);
+ if(pWrkrData->pNS != NULL)
+ netstrms.Destruct(&pWrkrData->pNS);
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ int i;
+CODESTARTsetModCnf
+ const struct cnfparamvals *const __restrict__ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for omfwd:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(cs.pszTplName != NULL) {
+ LogError(0, RS_RET_DUP_PARAM, "omfwd: warning: default template "
+ "was already set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else {
+ dbgprintf("omfwd: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(cs.pszTplName);
+ cs.pszTplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ if(cs.pszStrmDrvr != NULL)
+ CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)cs.pszStrmDrvr));
+ if(cs.pszStrmDrvrAuthMode != NULL)
+ CHKmalloc(pData->pszStrmDrvrAuthMode =
+ (uchar*)strdup((char*)cs.pszStrmDrvrAuthMode));
+finalize_it:
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ dbgprintf("DDDD: createWrkrInstance: pWrkrData %p\n", pWrkrData);
+ pWrkrData->offsSndBuf = 0;
+ iRet = initTCP(pWrkrData);
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->stats != NULL)
+ statsobj.Destruct(&(pData->stats));
+ free(pData->pszStrmDrvr);
+ free(pData->pszStrmDrvrAuthMode);
+ free(pData->pszStrmDrvrPermitExpiredCerts);
+ free(pData->gnutlsPriorityString);
+ free(pData->port);
+ free(pData->networkNamespace);
+ free(pData->target);
+ free(pData->address);
+ free(pData->device);
+ free((void*)pData->pszStrmDrvrCAFile);
+ free((void*)pData->pszStrmDrvrCRLFile);
+ free((void*)pData->pszStrmDrvrKeyFile);
+ free((void*)pData->pszStrmDrvrCertFile);
+ net.DestructPermittedPeers(&pData->pPermPeers);
+ if (pData->ratelimiter != NULL){
+ ratelimitDestruct(pData->ratelimiter);
+ pData->ratelimiter = NULL;
+ }
+
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ DestructTCPInstanceData(pWrkrData);
+ closeUDPSockets(pWrkrData);
+
+ if(pWrkrData->pData->protocol == FORW_TCP) {
+ tcpclt.Destruct(&pWrkrData->pTCPClt);
+ }
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omfwd\n");
+ dbgprintf("\ttarget='%s'\n", pData->target);
+ dbgprintf("\tratelimit.interval='%u'\n", pData->ratelimitInterval);
+ dbgprintf("\tratelimit.burst='%u'\n", pData->ratelimitBurst);
+ENDdbgPrintInstInfo
+
+
+/* Send a message via UDP
+ * rgehards, 2007-12-20
+ */
+#define UDP_MAX_MSGSIZE 65507 /* limit per RFC definition */
+static rsRetVal UDPSend(wrkrInstanceData_t *__restrict__ const pWrkrData,
+ uchar *__restrict__ const msg,
+ size_t len)
+{
+ DEFiRet;
+ struct addrinfo *r;
+ int i;
+ ssize_t lsent = 0;
+ sbool bSendSuccess;
+ sbool reInit = RSFALSE;
+ int lasterrno = ENOENT;
+ int lasterr_sock = -1;
+
+ if(pWrkrData->pData->iRebindInterval && (pWrkrData->nXmit++ % pWrkrData->pData->iRebindInterval == 0)) {
+ dbgprintf("omfwd dropping UDP 'connection' (as configured)\n");
+ pWrkrData->nXmit = 1; /* else we have an addtl wrap at 2^31-1 */
+ CHKiRet(closeUDPSockets(pWrkrData));
+ }
+
+ if(pWrkrData->pSockArray == NULL) {
+ CHKiRet(doTryResume(pWrkrData));
+ }
+
+ if(pWrkrData->pSockArray == NULL) {
+ FINALIZE;
+ }
+
+
+ if(len > UDP_MAX_MSGSIZE) {
+ LogError(0, RS_RET_UDP_MSGSIZE_TOO_LARGE, "omfwd/udp: message is %u "
+ "bytes long, but UDP can send at most %d bytes (by RFC limit) "
+ "- truncating message", (unsigned) len, UDP_MAX_MSGSIZE);
+ len = UDP_MAX_MSGSIZE;
+ }
+
+ /* we need to track if we have success sending to the remote
+ * peer. Success is indicated by at least one sendto() call
+ * succeeding. We track this be bSendSuccess. We can not simply
+ * rely on lsent, as a call might initially work, but a later
+ * call fails. Then, lsent has the error status, even though
+ * the sendto() succeeded. -- rgerhards, 2007-06-22
+ */
+ bSendSuccess = RSFALSE;
+ for (r = pWrkrData->f_addr; r; r = r->ai_next) {
+ int runSockArrayLoop = 1;
+ for (i = 0; runSockArrayLoop && (i < *pWrkrData->pSockArray) ; i++) {
+ int try_send = 1;
+ size_t lenThisTry = len;
+ while(try_send) {
+ lsent = sendto(pWrkrData->pSockArray[i+1], msg, lenThisTry, 0,
+ r->ai_addr, r->ai_addrlen);
+ if (lsent == (ssize_t) lenThisTry) {
+ bSendSuccess = RSTRUE;
+ ATOMIC_ADD_uint64(&pWrkrData->pData->sentBytes,
+ &pWrkrData->pData->mut_sentBytes, lenThisTry);
+ try_send = 0;
+ runSockArrayLoop = 0;
+ } else if(errno == EMSGSIZE) {
+ const size_t newlen = (lenThisTry > 1024) ? lenThisTry - 1024 : 512;
+ LogError(0, RS_RET_UDP_MSGSIZE_TOO_LARGE,
+ "omfwd/udp: send failed due to message being too "
+ "large for this system. Message size was %u bytes. "
+ "Truncating to %u bytes and retrying.",
+ (unsigned) lenThisTry, (unsigned) newlen);
+ lenThisTry = newlen;
+ } else {
+ reInit = RSTRUE;
+ lasterrno = errno;
+ lasterr_sock = pWrkrData->pSockArray[i+1];
+ LogError(lasterrno, RS_RET_ERR_UDPSEND,
+ "omfwd/udp: socket %d: sendto() error",
+ lasterr_sock);
+ try_send = 0;
+ }
+ }
+ }
+ if (lsent == (ssize_t) len && !pWrkrData->pData->bSendToAll)
+ break;
+ }
+
+ /* one or more send failures; close sockets and re-init */
+ if (reInit == RSTRUE) {
+ CHKiRet(closeUDPSockets(pWrkrData));
+ }
+
+ /* finished looping */
+ if(bSendSuccess == RSTRUE) {
+ if(pWrkrData->pData->iUDPSendDelay > 0) {
+ srSleep(pWrkrData->pData->iUDPSendDelay / 1000000,
+ pWrkrData->pData->iUDPSendDelay % 1000000);
+ }
+ } else {
+ LogError(lasterrno, RS_RET_ERR_UDPSEND,
+ "omfwd: socket %d: error %d sending via udp", lasterr_sock, lasterrno);
+ iRet = RS_RET_SUSPENDED;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the permitted peers -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&cs.pPermPeers, pszID));
+ free(pszID); /* no longer needed, but we must free it as of interface def */
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* CODE FOR SENDING TCP MESSAGES */
+
+static rsRetVal
+TCPSendBufUncompressed(wrkrInstanceData_t *pWrkrData, uchar *const buf, const unsigned len)
+{
+ DEFiRet;
+ unsigned alreadySent;
+ ssize_t lenSend;
+
+ alreadySent = 0;
+ CHKiRet(netstrm.CheckConnection(pWrkrData->pNetstrm));
+ /* hack for plain tcp syslog - see ptcp driver for details */
+
+ while(alreadySent != len) {
+ lenSend = len - alreadySent;
+ CHKiRet(netstrm.Send(pWrkrData->pNetstrm, buf+alreadySent, &lenSend));
+ DBGPRINTF("omfwd: TCP sent %ld bytes, requested %u\n", (long) lenSend, len - alreadySent);
+ alreadySent += lenSend;
+ }
+
+ ATOMIC_ADD_uint64(&pWrkrData->pData->sentBytes, &pWrkrData->pData->mut_sentBytes, len);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(iRet == RS_RET_IO_ERROR) {
+ static unsigned int conErrCnt = 0;
+ const int skipFactor = pWrkrData->pData->iConErrSkip;
+ if (skipFactor <= 1) {
+ /* All the connection errors are printed. */
+ LogError(0, iRet, "omfwd: remote server at %s:%s seems to have closed connection. "
+ "This often happens when the remote peer (or an interim system like a load "
+ "balancer or firewall) shuts down or aborts a connection. Rsyslog will "
+ "re-open the connection if configured to do so (we saw a generic IO Error, "
+ "which usually goes along with that behaviour).",
+ pWrkrData->pData->target, pWrkrData->pData->port);
+ } else if ((conErrCnt++ % skipFactor) == 0) {
+ /* Every N'th error message is printed where N is a skipFactor. */
+ LogError(0, iRet, "omfwd: remote server at %s:%s seems to have closed connection. "
+ "This often happens when the remote peer (or an interim system like a load "
+ "balancer or firewall) shuts down or aborts a connection. Rsyslog will "
+ "re-open the connection if configured to do so (we saw a generic IO Error, "
+ "which usually goes along with that behaviour). Note that the next %d "
+ "connection error messages will be skipped.",
+ pWrkrData->pData->target, pWrkrData->pData->port, skipFactor-1);
+ }
+ } else {
+ LogError(0, iRet, "omfwd: TCPSendBuf error %d, destruct TCP Connection to %s:%s",
+ iRet, pWrkrData->pData->target, pWrkrData->pData->port);
+ }
+ DestructTCPInstanceData(pWrkrData);
+ iRet = RS_RET_SUSPENDED;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+TCPSendBufCompressed(wrkrInstanceData_t *pWrkrData, uchar *buf, unsigned len, sbool bIsFlush)
+{
+ int zRet; /* zlib return state */
+ unsigned outavail;
+ uchar zipBuf[32*1024];
+ int op;
+ DEFiRet;
+
+ if(!pWrkrData->bzInitDone) {
+ /* allocate deflate state */
+ pWrkrData->zstrm.zalloc = Z_NULL;
+ pWrkrData->zstrm.zfree = Z_NULL;
+ pWrkrData->zstrm.opaque = Z_NULL;
+ /* see note in file header for the params we use with deflateInit2() */
+ zRet = deflateInit(&pWrkrData->zstrm, pWrkrData->pData->compressionLevel);
+ if(zRet != Z_OK) {
+ DBGPRINTF("error %d returned from zlib/deflateInit()\n", zRet);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ pWrkrData->bzInitDone = RSTRUE;
+ }
+
+ /* now doing the compression */
+ pWrkrData->zstrm.next_in = (Bytef*) buf;
+ pWrkrData->zstrm.avail_in = len;
+ if(pWrkrData->pData->strmCompFlushOnTxEnd && bIsFlush)
+ op = Z_SYNC_FLUSH;
+ else
+ op = Z_NO_FLUSH;
+ /* run deflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("omfwd: in deflate() loop, avail_in %d, total_in %ld, isFlush %d\n",
+ pWrkrData->zstrm.avail_in, pWrkrData->zstrm.total_in, bIsFlush);
+ pWrkrData->zstrm.avail_out = sizeof(zipBuf);
+ pWrkrData->zstrm.next_out = zipBuf;
+ zRet = deflate(&pWrkrData->zstrm, op); /* no bad return value */
+ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pWrkrData->zstrm.avail_out);
+ outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out;
+ if(outavail != 0) {
+ CHKiRet(TCPSendBufUncompressed(pWrkrData, zipBuf, outavail));
+ }
+ } while (pWrkrData->zstrm.avail_out == 0);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+TCPSendBuf(wrkrInstanceData_t *pWrkrData, uchar *buf, unsigned len, sbool bIsFlush)
+{
+ DEFiRet;
+ if(pWrkrData->pData->compressionMode >= COMPRESS_STREAM_ALWAYS)
+ iRet = TCPSendBufCompressed(pWrkrData, buf, len, bIsFlush);
+ else
+ iRet = TCPSendBufUncompressed(pWrkrData, buf, len);
+ RETiRet;
+}
+
+/* finish zlib buffer, to be called before closing the ZIP file (if
+ * running in stream mode).
+ */
+static rsRetVal
+doZipFinish(wrkrInstanceData_t *pWrkrData)
+{
+ int zRet; /* zlib return state */
+ DEFiRet;
+ unsigned outavail;
+ uchar zipBuf[32*1024];
+
+ if(!pWrkrData->bzInitDone)
+ goto done;
+
+ // TODO: can we get this into a single common function?
+ pWrkrData->zstrm.avail_in = 0;
+ /* run deflate() on buffer until everything has been compressed */
+ do {
+ DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld\n", pWrkrData->zstrm.avail_in,
+ pWrkrData->zstrm.total_in);
+ pWrkrData->zstrm.avail_out = sizeof(zipBuf);
+ pWrkrData->zstrm.next_out = zipBuf;
+ zRet = deflate(&pWrkrData->zstrm, Z_FINISH); /* no bad return value */
+ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pWrkrData->zstrm.avail_out);
+ outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out;
+ if(outavail != 0) {
+ CHKiRet(TCPSendBufUncompressed(pWrkrData, zipBuf, outavail));
+ }
+ } while (pWrkrData->zstrm.avail_out == 0);
+
+finalize_it:
+ zRet = deflateEnd(&pWrkrData->zstrm);
+ if(zRet != Z_OK) {
+ DBGPRINTF("error %d returned from zlib/deflateEnd()\n", zRet);
+ }
+
+ pWrkrData->bzInitDone = 0;
+done: RETiRet;
+}
+
+
+/* Add frame to send buffer (or send, if requried)
+ */
+static rsRetVal TCPSendFrame(void *pvData, char *msg, size_t len)
+{
+ DEFiRet;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *) pvData;
+
+ DBGPRINTF("omfwd: add %u bytes to send buffer (curr offs %u)\n",
+ (unsigned) len, pWrkrData->offsSndBuf);
+ if(pWrkrData->offsSndBuf != 0 && pWrkrData->offsSndBuf + len >= sizeof(pWrkrData->sndBuf)) {
+ /* no buffer space left, need to commit previous records. With the
+ * current API, there unfortunately is no way to signal this
+ * state transition to the upper layer.
+ */
+ DBGPRINTF("omfwd: we need to do a tcp send due to buffer "
+ "out of space. If the transaction fails, this will "
+ "lead to duplication of messages");
+ CHKiRet(TCPSendBuf(pWrkrData, pWrkrData->sndBuf, pWrkrData->offsSndBuf, NO_FLUSH));
+ pWrkrData->offsSndBuf = 0;
+ }
+
+ /* check if the message is too large to fit into buffer */
+ if(len > sizeof(pWrkrData->sndBuf)) {
+ CHKiRet(TCPSendBuf(pWrkrData, (uchar*)msg, len, NO_FLUSH));
+ ABORT_FINALIZE(RS_RET_OK); /* committed everything so far */
+ }
+
+ /* we now know the buffer has enough free space */
+ memcpy(pWrkrData->sndBuf + pWrkrData->offsSndBuf, msg, len);
+ pWrkrData->offsSndBuf += len;
+ iRet = RS_RET_DEFER_COMMIT;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called immediately before a send retry is attempted.
+ * It shall clean up whatever makes sense.
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendPrepRetry(void *pvData)
+{
+ DEFiRet;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *) pvData;
+
+ assert(pWrkrData != NULL);
+ DestructTCPInstanceData(pWrkrData);
+ RETiRet;
+}
+
+
+/* initializes everything so that TCPSend can work.
+ * rgerhards, 2007-12-28
+ */
+static rsRetVal TCPSendInit(void *pvData)
+{
+ DEFiRet;
+ wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *) pvData;
+ instanceData *pData;
+
+ assert(pWrkrData != NULL);
+ pData = pWrkrData->pData;
+
+ if(pWrkrData->pNetstrm == NULL) {
+ dbgprintf("TCPSendInit CREATE\n");
+ CHKiRet(netstrms.Construct(&pWrkrData->pNS));
+ /* the stream driver must be set before the object is finalized! */
+ CHKiRet(netstrms.SetDrvrName(pWrkrData->pNS, pData->pszStrmDrvr));
+ CHKiRet(netstrms.ConstructFinalize(pWrkrData->pNS));
+
+ /* now create the actual stream and connect to the server */
+ CHKiRet(netstrms.CreateStrm(pWrkrData->pNS, &pWrkrData->pNetstrm));
+ CHKiRet(netstrm.ConstructFinalize(pWrkrData->pNetstrm));
+ CHKiRet(netstrm.SetDrvrMode(pWrkrData->pNetstrm, pData->iStrmDrvrMode));
+ CHKiRet(netstrm.SetDrvrCheckExtendedKeyUsage(pWrkrData->pNetstrm, pData->iStrmDrvrExtendedCertCheck));
+ CHKiRet(netstrm.SetDrvrPrioritizeSAN(pWrkrData->pNetstrm, pData->iStrmDrvrSANPreference));
+ CHKiRet(netstrm.SetDrvrTlsVerifyDepth(pWrkrData->pNetstrm, pData->iStrmTlsVerifyDepth));
+ /* now set optional params, but only if they were actually configured */
+ if(pData->pszStrmDrvrAuthMode != NULL) {
+ CHKiRet(netstrm.SetDrvrAuthMode(pWrkrData->pNetstrm, pData->pszStrmDrvrAuthMode));
+ }
+ /* Call SetDrvrPermitExpiredCerts required
+ * when param is NULL default handling for ExpiredCerts is set! */
+ CHKiRet(netstrm.SetDrvrPermitExpiredCerts(pWrkrData->pNetstrm,
+ pData->pszStrmDrvrPermitExpiredCerts));
+ CHKiRet(netstrm.SetDrvrTlsCAFile(pWrkrData->pNetstrm, pData->pszStrmDrvrCAFile));
+ CHKiRet(netstrm.SetDrvrTlsCRLFile(pWrkrData->pNetstrm, pData->pszStrmDrvrCRLFile));
+ CHKiRet(netstrm.SetDrvrTlsKeyFile(pWrkrData->pNetstrm, pData->pszStrmDrvrKeyFile));
+ CHKiRet(netstrm.SetDrvrTlsCertFile(pWrkrData->pNetstrm, pData->pszStrmDrvrCertFile));
+
+ if(pData->pPermPeers != NULL) {
+ CHKiRet(netstrm.SetDrvrPermPeers(pWrkrData->pNetstrm, pData->pPermPeers));
+ }
+ /* params set, now connect */
+ if(pData->gnutlsPriorityString != NULL) {
+ CHKiRet(netstrm.SetGnutlsPriorityString(pWrkrData->pNetstrm, pData->gnutlsPriorityString));
+ }
+ CHKiRet(netstrm.Connect(pWrkrData->pNetstrm, glbl.GetDefPFFamily(runModConf->pConf),
+ (uchar*)pData->port, (uchar*)pData->target, pData->device));
+
+ /* set keep-alive if enabled */
+ if(pData->bKeepAlive) {
+ CHKiRet(netstrm.SetKeepAliveProbes(pWrkrData->pNetstrm, pData->iKeepAliveProbes));
+ CHKiRet(netstrm.SetKeepAliveIntvl(pWrkrData->pNetstrm, pData->iKeepAliveIntvl));
+ CHKiRet(netstrm.SetKeepAliveTime(pWrkrData->pNetstrm, pData->iKeepAliveTime));
+ CHKiRet(netstrm.EnableKeepAlive(pWrkrData->pNetstrm));
+ }
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ dbgprintf("TCPSendInit FAILED with %d.\n", iRet);
+ DestructTCPInstanceData(pWrkrData);
+ }
+
+ RETiRet;
+}
+
+
+/* change to network namespace pData->networkNamespace and keep the file
+ * descriptor to the original namespace.
+ */
+static rsRetVal changeToNs(instanceData *const pData __attribute__((unused)))
+{
+ DEFiRet;
+#ifdef HAVE_SETNS
+ int iErr;
+ int destinationNs = -1;
+ char *nsPath = NULL;
+
+ if(pData->networkNamespace) {
+ /* keep file descriptor of original network namespace */
+ pData->originalNamespace = open("/proc/self/ns/net", O_RDONLY);
+ if (pData->originalNamespace < 0) {
+ LogError(0, RS_RET_IO_ERROR, "omfwd: could not read /proc/self/ns/net");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* build network namespace path */
+ if (asprintf(&nsPath, "/var/run/netns/%s", pData->networkNamespace) == -1) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "omfwd: asprintf failed");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* keep file descriptor of destination network namespace */
+ destinationNs = open(nsPath, 0);
+ if (destinationNs < 0) {
+ LogError(0, RS_RET_IO_ERROR, "omfwd: could not change to namespace '%s'",
+ pData->networkNamespace);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* actually change in the destination network namespace */
+ if((iErr = (setns(destinationNs, CLONE_NEWNET))) != 0) {
+ LogError(0, RS_RET_IO_ERROR, "could not change to namespace '%s': %s",
+ pData->networkNamespace, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ dbgprintf("omfwd: changed to network namespace '%s'\n", pData->networkNamespace);
+ }
+
+finalize_it:
+ free(nsPath);
+ if(destinationNs >= 0) {
+ close(destinationNs);
+ }
+#else /* #ifdef HAVE_SETNS */
+ dbgprintf("omfwd: OS does not support network namespaces\n");
+#endif /* #ifdef HAVE_SETNS */
+ RETiRet;
+}
+
+
+/* return to the original network namespace. This should be called after
+ * changeToNs().
+ */
+static rsRetVal returnToOriginalNs(instanceData *const pData __attribute__((unused)))
+{
+ DEFiRet;
+#ifdef HAVE_SETNS
+ int iErr;
+
+ /* only in case a network namespace is given and a file descriptor to
+ * the original namespace exists */
+ if(pData->networkNamespace && pData->originalNamespace >= 0) {
+ /* actually change to the original network namespace */
+ if((iErr = (setns(pData->originalNamespace, CLONE_NEWNET))) != 0) {
+ LogError(0, RS_RET_IO_ERROR, "could not return to original namespace: %s",
+ gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ close(pData->originalNamespace);
+ dbgprintf("omfwd: returned to original network namespace\n");
+ }
+
+finalize_it:
+#endif /* #ifdef HAVE_SETNS */
+ RETiRet;
+}
+
+
+/* try to resume connection if it is not ready
+ * rgerhards, 2007-08-02
+ */
+static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData)
+{
+ int iErr;
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+ instanceData *pData;
+ int bBindRequired = 0;
+ const char *address;
+ DEFiRet;
+
+ if(pWrkrData->bIsConnected)
+ FINALIZE;
+ pData = pWrkrData->pData;
+
+ /* The remote address is not yet known and needs to be obtained */
+ if(pData->protocol == FORW_UDP) {
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requires this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = glbl.GetDefPFFamily(runModConf->pConf);
+ hints.ai_socktype = SOCK_DGRAM;
+ if((iErr = (getaddrinfo(pData->target, pData->port, &hints, &res))) != 0) {
+ LogError(0, RS_RET_SUSPENDED,
+ "omfwd: could not get addrinfo for hostname '%s':'%s': %s",
+ pData->target, pData->port, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ address = pData->target;
+ if(pData->address) {
+ struct addrinfo *addr;
+ /* The AF of the bind addr must match that of target */
+ hints.ai_family = res->ai_family;
+ hints.ai_flags |= AI_PASSIVE;
+ iErr = getaddrinfo(pData->address, pData->port, &hints, &addr);
+ freeaddrinfo(addr);
+ if(iErr != 0) {
+ LogError(0, RS_RET_SUSPENDED,
+ "omfwd: cannot use bind address '%s' for host '%s': %s",
+ pData->address, pData->target, gai_strerror(iErr));
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ bBindRequired = 1;
+ address = pData->address;
+ }
+ DBGPRINTF("%s found, resuming.\n", pData->target);
+ pWrkrData->f_addr = res;
+ res = NULL;
+ if(pWrkrData->pSockArray == NULL) {
+ CHKiRet(changeToNs(pData));
+ pWrkrData->pSockArray = net.create_udp_socket((uchar*)address,
+ NULL, bBindRequired, 0, pData->UDPSendBuf, pData->ipfreebind, pData->device);
+ CHKiRet(returnToOriginalNs(pData));
+ }
+ if(pWrkrData->pSockArray != NULL) {
+ pWrkrData->bIsConnected = 1;
+ }
+ } else {
+ CHKiRet(changeToNs(pData));
+ CHKiRet(TCPSendInit((void*)pWrkrData));
+ CHKiRet(returnToOriginalNs(pData));
+ }
+
+finalize_it:
+ DBGPRINTF("omfwd: doTryResume %s iRet %d\n", pWrkrData->pData->target, iRet);
+ if(res != NULL) {
+ freeaddrinfo(res);
+ }
+ if(iRet != RS_RET_OK) {
+ returnToOriginalNs(pData);
+ if(pWrkrData->f_addr != NULL) {
+ freeaddrinfo(pWrkrData->f_addr);
+ pWrkrData->f_addr = NULL;
+ }
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ dbgprintf("omfwd: tryResume: pWrkrData %p\n", pWrkrData);
+ iRet = doTryResume(pWrkrData);
+ENDtryResume
+
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ dbgprintf("omfwd: beginTransaction\n");
+ iRet = doTryResume(pWrkrData);
+ENDbeginTransaction
+
+
+static rsRetVal
+processMsg(wrkrInstanceData_t *__restrict__ const pWrkrData,
+ actWrkrIParams_t *__restrict__ const iparam)
+{
+ uchar *psz; /* temporary buffering */
+ register unsigned l;
+ int iMaxLine;
+ Bytef *out = NULL; /* for compression */
+ instanceData *__restrict__ const pData = pWrkrData->pData;
+ DEFiRet;
+
+ iMaxLine = glbl.GetMaxLine(runModConf->pConf);
+
+ psz = iparam->param;
+ l = iparam->lenStr;
+ if((int) l > iMaxLine)
+ l = iMaxLine;
+
+ /* Check if we should compress and, if so, do it. We also
+ * check if the message is large enough to justify compression.
+ * The smaller the message, the less likely is a gain in compression.
+ * To save CPU cycles, we do not try to compress very small messages.
+ * What "very small" means needs to be configured. Currently, it is
+ * hard-coded but this may be changed to a config parameter.
+ * rgerhards, 2006-11-30
+ */
+ if(pData->compressionMode == COMPRESS_SINGLE_MSG && (l > CONF_MIN_SIZE_FOR_COMPRESS)) {
+ uLongf destLen = iMaxLine + iMaxLine/100 +12; /* recommended value from zlib doc */
+ uLong srcLen = l;
+ int ret;
+ CHKmalloc(out = (Bytef*) malloc(destLen));
+ out[0] = 'z';
+ out[1] = '\0';
+ ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz,
+ srcLen, pData->compressionLevel);
+ dbgprintf("Compressing message, length was %d now %d, return state %d.\n",
+ l, (int) destLen, ret);
+ if(ret != Z_OK) {
+ /* if we fail, we complain, but only in debug mode
+ * Otherwise, we are silent. In any case, we ignore the
+ * failed compression and just sent the uncompressed
+ * data, which is still valid. So this is probably the
+ * best course of action.
+ * rgerhards, 2006-11-30
+ */
+ dbgprintf("Compression failed, sending uncompressed message\n");
+ } else if(destLen+1 < l) {
+ /* only use compression if there is a gain in using it! */
+ dbgprintf("there is gain in compression, so we do it\n");
+ psz = out;
+ l = destLen + 1; /* take care for the "z" at message start! */
+ }
+ ++destLen;
+ }
+
+ if(pData->protocol == FORW_UDP) {
+ /* forward via UDP */
+ CHKiRet(UDPSend(pWrkrData, psz, l));
+ } else {
+ /* forward via TCP */
+ iRet = tcpclt.Send(pWrkrData->pTCPClt, pWrkrData, (char *)psz, l);
+ if(iRet != RS_RET_OK && iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED) {
+ /* error! */
+ LogError(0, iRet, "omfwd: error forwarding via tcp to %s:%s, suspending action",
+ pWrkrData->pData->target, pWrkrData->pData->port);
+ DestructTCPInstanceData(pWrkrData);
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+finalize_it:
+ free(out); /* is NULL if it was never used... */
+ RETiRet;
+}
+
+BEGINcommitTransaction
+ unsigned i;
+ char namebuf[264]; /* 256 for FGDN, 5 for port and 3 for transport => 264 */
+CODESTARTcommitTransaction
+ CHKiRet(doTryResume(pWrkrData));
+
+ DBGPRINTF(" %s:%s/%s\n", pWrkrData->pData->target, pWrkrData->pData->port,
+ pWrkrData->pData->protocol == FORW_UDP ? "udp" : "tcp");
+
+ if(pWrkrData->pData->ratelimiter) {
+ snprintf(namebuf, sizeof namebuf, "%s:[%s]:%s",
+ pWrkrData->pData->protocol == FORW_UDP ? "udp" : "tcp",
+ pWrkrData->pData->target,
+ pWrkrData->pData->port);
+ }
+
+ for(i = 0 ; i < nParams ; ++i) {
+ /* If rate limiting is enabled, check whether this message has to be discarded */
+ if(pWrkrData->pData->ratelimiter) {
+ iRet = ratelimitMsgCount(pWrkrData->pData->ratelimiter, 0, namebuf);
+ if (iRet == RS_RET_DISCARDMSG) {
+ iRet = RS_RET_OK;
+ continue;
+ } else if (iRet != RS_RET_OK) {
+ LogError(0, RS_RET_ERR, "omfwd: error during rate limit : %d.\n",iRet);
+ }
+ }
+ iRet = processMsg(pWrkrData, &actParam(pParams, 1, i, 0));
+ if(iRet != RS_RET_OK && iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED)
+ FINALIZE;
+ }
+
+ if(pWrkrData->offsSndBuf != 0) {
+ iRet = TCPSendBuf(pWrkrData, pWrkrData->sndBuf, pWrkrData->offsSndBuf, IS_FLUSH);
+ pWrkrData->offsSndBuf = 0;
+ }
+finalize_it:
+ENDcommitTransaction
+
+
+/* This function loads TCP support, if not already loaded. It will be called
+ * during config processing. To server ressources, TCP support will only
+ * be loaded if it actually is used. -- rgerhard, 2008-04-17
+ */
+static rsRetVal
+loadTCPSupport(void)
+{
+ DEFiRet;
+ CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* initialize TCP structures (if necessary) after the instance has been
+ * created.
+ */
+static rsRetVal
+initTCP(wrkrInstanceData_t *pWrkrData)
+{
+ instanceData *pData;
+ DEFiRet;
+
+ pData = pWrkrData->pData;
+ if(pData->protocol == FORW_TCP) {
+ /* create our tcpclt */
+ CHKiRet(tcpclt.Construct(&pWrkrData->pTCPClt));
+ CHKiRet(tcpclt.SetResendLastOnRecon(pWrkrData->pTCPClt, pData->bResendLastOnRecon));
+ /* and set callbacks */
+ CHKiRet(tcpclt.SetSendInit(pWrkrData->pTCPClt, TCPSendInit));
+ CHKiRet(tcpclt.SetSendFrame(pWrkrData->pTCPClt, TCPSendFrame));
+ CHKiRet(tcpclt.SetSendPrepRetry(pWrkrData->pTCPClt, TCPSendPrepRetry));
+ CHKiRet(tcpclt.SetFraming(pWrkrData->pTCPClt, pData->tcp_framing));
+ CHKiRet(tcpclt.SetFramingDelimiter(pWrkrData->pTCPClt, pData->tcp_framingDelimiter));
+ CHKiRet(tcpclt.SetRebindInterval(pWrkrData->pTCPClt, pData->iRebindInterval));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+static void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+ pData->protocol = FORW_UDP;
+ pData->networkNamespace = NULL;
+ pData->originalNamespace = -1;
+ pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+ pData->tcp_framingDelimiter = '\n';
+ pData->pszStrmDrvr = NULL;
+ pData->pszStrmDrvrAuthMode = NULL;
+ pData->pszStrmDrvrPermitExpiredCerts = NULL;
+ pData->iStrmDrvrMode = 0;
+ pData->iStrmDrvrExtendedCertCheck = 0;
+ pData->iStrmDrvrSANPreference = 0;
+ pData->iStrmTlsVerifyDepth = 0;
+ pData->pszStrmDrvrCAFile = NULL;
+ pData->pszStrmDrvrCRLFile = NULL;
+ pData->pszStrmDrvrKeyFile = NULL;
+ pData->pszStrmDrvrCertFile = NULL;
+ pData->iRebindInterval = 0;
+ pData->bKeepAlive = 0;
+ pData->iKeepAliveProbes = 0;
+ pData->iKeepAliveIntvl = 0;
+ pData->iKeepAliveTime = 0;
+ pData->iConErrSkip = 0;
+ pData->gnutlsPriorityString = NULL;
+ pData->bResendLastOnRecon = 0;
+ pData->bSendToAll = -1; /* unspecified */
+ pData->iUDPSendDelay = 0;
+ pData->UDPSendBuf = 0;
+ pData->pPermPeers = NULL;
+ pData->compressionLevel = 9;
+ pData->strmCompFlushOnTxEnd = 1;
+ pData->compressionMode = COMPRESS_NEVER;
+ pData->ipfreebind = IPFREEBIND_ENABLED_WITH_LOG;
+ pData->ratelimiter = NULL;
+ pData->ratelimitInterval = 0;
+ pData->ratelimitBurst = 200;
+}
+
+
+static rsRetVal
+setupInstStatsCtrs(instanceData *__restrict__ const pData)
+{
+ uchar ctrName[512];
+ DEFiRet;
+
+ /* support statistics gathering */
+ snprintf((char*)ctrName, sizeof(ctrName), "%s-%s-%s",
+ (pData->protocol == FORW_TCP) ? "TCP" : "UDP",
+ pData->target, pData->port);
+ ctrName[sizeof(ctrName)-1] = '\0'; /* be on the save side */
+ CHKiRet(statsobj.Construct(&(pData->stats)));
+ CHKiRet(statsobj.SetName(pData->stats, ctrName));
+ CHKiRet(statsobj.SetOrigin(pData->stats, (uchar*)"omfwd"));
+ pData->sentBytes = 0;
+ INIT_ATOMIC_HELPER_MUT64(pData->mut_sentBytes);
+ CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("bytes.sent"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->sentBytes)));
+ CHKiRet(statsobj.ConstructFinalize(pData->stats));
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ uchar *tplToUse;
+ char *cstr;
+ int i;
+ rsRetVal localRet;
+ int complevel = -1;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omfwd)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omfwd:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->target = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "address")) {
+ pData->address = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "device")) {
+ pData->device = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "protocol")) {
+ if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"udp", 3)) {
+ pData->protocol = FORW_UDP;
+ } else if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"tcp", 3)) {
+ localRet = loadTCPSupport();
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "could not activate network stream modules for TCP "
+ "(internal error %d) - are modules missing?", localRet);
+ ABORT_FINALIZE(localRet);
+ }
+ pData->protocol = FORW_TCP;
+ } else {
+ uchar *str;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_INVLD_PROTOCOL,
+ "omfwd: invalid protocol \"%s\"", str);
+ free(str);
+ ABORT_FINALIZE(RS_RET_INVLD_PROTOCOL);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "networknamespace")) {
+ pData->networkNamespace = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tcp_framing")) {
+ if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"traditional", 11)) {
+ pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+ } else if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"octet-counted", 13)) {
+ pData->tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else {
+ uchar *str;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ LogError(0, RS_RET_CNF_INVLD_FRAMING,
+ "omfwd: invalid framing \"%s\"", str);
+ free(str);
+ ABORT_FINALIZE(RS_RET_CNF_INVLD_FRAMING );
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "rebindinterval")) {
+ pData->iRebindInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "keepalive")) {
+ pData->bKeepAlive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "keepalive.probes")) {
+ pData->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "keepalive.interval")) {
+ pData->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "keepalive.time")) {
+ pData->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "conerrskip")) {
+ pData->iConErrSkip = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "gnutlsprioritystring")) {
+ pData->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver")) {
+ pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) {
+ pData->iStrmDrvrMode = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
+ pData->iStrmDrvrExtendedCertCheck = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
+ pData->iStrmDrvrSANPreference = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.TlsVerifyDepth")) {
+ if (pvals[i].val.d.n >= 2) {
+ pData->iStrmTlsVerifyDepth = pvals[i].val.d.n;
+ } else {
+ parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d",
+ (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriverauthmode")) {
+ pData->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.permitexpiredcerts")) {
+ uchar *val = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if( es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"off", 3)
+ && es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"on", 2)
+ && es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"warn", 4)
+ ) {
+ parser_errmsg("streamdriver.permitExpiredCerts must be 'warn', 'off' or 'on' "
+ "but is '%s' - ignoring parameter, using 'off' instead.", val);
+ free(val);
+ } else {
+ pData->pszStrmDrvrPermitExpiredCerts = val;
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.cafile")) {
+ pData->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.crlfile")) {
+ pData->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.keyfile")) {
+ pData->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver.certfile")) {
+ pData->pszStrmDrvrCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriverpermittedpeers")) {
+ uchar *start, *str;
+ uchar *p;
+ int lenStr;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ start = str;
+ lenStr = ustrlen(start); /* we need length after '\0' has been dropped... */
+ while(lenStr > 0) {
+ p = start;
+ while(*p && *p != ',' && lenStr--)
+ p++;
+ if(*p == ',') {
+ *p = '\0';
+ }
+ if(*start == '\0') {
+ DBGPRINTF("omfwd: ignoring empty permitted peer\n");
+ } else {
+ dbgprintf("omfwd: adding permitted peer: '%s'\n", start);
+ CHKiRet(net.AddPermittedPeer(&(pData->pPermPeers), start));
+ }
+ start = p+1;
+ if(lenStr)
+ --lenStr;
+ }
+ free(str);
+ } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) {
+ complevel = pvals[i].val.d.n;
+ if(complevel >= 0 && complevel <= 10) {
+ pData->compressionLevel = complevel;
+ pData->compressionMode = COMPRESS_SINGLE_MSG;
+ } else {
+ LogError(0, NO_ERRCODE, "Invalid ziplevel %d specified in "
+ "forwarding action - NOT turning on compression.",
+ complevel);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tcp_framedelimiter")) {
+ if(pvals[i].val.d.n > 255) {
+ parser_errmsg("tcp_frameDelimiter must be below 255 but is %d",
+ (int) pvals[i].val.d.n);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ pData->tcp_framingDelimiter = (uchar) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "resendlastmsgonreconnect")) {
+ pData->bResendLastOnRecon = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "udp.sendtoall")) {
+ pData->bSendToAll = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "udp.senddelay")) {
+ pData->iUDPSendDelay = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "udp.sendbuf")) {
+ pData->UDPSendBuf = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "compression.stream.flushontxend")) {
+ pData->strmCompFlushOnTxEnd = (sbool) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "compression.mode")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(!strcasecmp(cstr, "stream:always")) {
+ pData->compressionMode = COMPRESS_STREAM_ALWAYS;
+ } else if(!strcasecmp(cstr, "none")) {
+ pData->compressionMode = COMPRESS_NEVER;
+ } else if(!strcasecmp(cstr, "single")) {
+ pData->compressionMode = COMPRESS_SINGLE_MSG;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "omfwd: invalid value for 'compression.mode' "
+ "parameter (given is '%s')", cstr);
+ free(cstr);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ free(cstr);
+ } else if(!strcmp(actpblk.descr[i].name, "ipfreebind")) {
+ pData->ipfreebind = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.burst")) {
+ pData->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ratelimit.interval")) {
+ pData->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else {
+ LogError(0, RS_RET_INTERNAL_ERROR,
+ "omfwd: program error, non-handled parameter '%s'",
+ actpblk.descr[i].name);
+ }
+ }
+
+ /* check if no port is set. If so, we use the IANA-assigned port of 514 */
+ if(pData->port == NULL) {
+ CHKmalloc(pData->port = strdup("514"));
+ }
+
+ if(complevel != -1) {
+ pData->compressionLevel = complevel;
+ if(pData->compressionMode == COMPRESS_NEVER) {
+ /* to keep compatible with pre-7.3.11, only setting the
+ * compresion level means old-style single-message mode.
+ */
+ pData->compressionMode = COMPRESS_SINGLE_MSG;
+ }
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+
+ tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName);
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS));
+
+ if(pData->bSendToAll == -1) {
+ pData->bSendToAll = send_to_all;
+ } else {
+ if(pData->protocol == FORW_TCP) {
+ LogError(0, RS_RET_PARAM_ERROR, "omfwd: parameter udp.sendToAll "
+ "cannot be used with tcp transport -- ignored");
+ }
+ }
+
+ if(pData->address && (pData->protocol == FORW_TCP)) {
+ LogError(0, RS_RET_PARAM_ERROR,
+ "omfwd: parameter \"address\" not supported for tcp -- ignored");
+ }
+
+ if( pData->ratelimitInterval > 0) {
+ CHKiRet(ratelimitNew(&pData->ratelimiter, "omfwd", NULL));
+ ratelimitSetLinuxLike(pData->ratelimiter, pData->ratelimitInterval, pData->ratelimitBurst);
+ ratelimitSetNoTimeCache(pData->ratelimiter);
+ }
+
+ setupInstStatsCtrs(pData);
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+ rsRetVal localRet;
+ struct addrinfo;
+ TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(*p != '@')
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+
+ CHKiRet(createInstance(&pData));
+ pData->tcp_framingDelimiter = '\n';
+
+ ++p; /* eat '@' */
+ if(*p == '@') { /* indicator for TCP! */
+ localRet = loadTCPSupport();
+ if(localRet != RS_RET_OK) {
+ LogError(0, localRet, "could not activate network stream modules for TCP "
+ "(internal error %d) - are modules missing?", localRet);
+ ABORT_FINALIZE(localRet);
+ }
+ pData->protocol = FORW_TCP;
+ ++p; /* eat this '@', too */
+ } else {
+ pData->protocol = FORW_UDP;
+ }
+ /* we are now after the protocol indicator. Now check if we should
+ * use compression. We begin to use a new option format for this:
+ * @(option,option)host:port
+ * The first option defined is "z[0..9]" where the digit indicates
+ * the compression level. If it is not given, 9 (best compression) is
+ * assumed. An example action statement might be:
+ * @@(z5,o)127.0.0.1:1400
+ * Which means send via TCP with medium (5) compresion (z) to the local
+ * host on port 1400. The '0' option means that octet-couting (as in
+ * IETF I-D syslog-transport-tls) is to be used for framing (this option
+ * applies to TCP-based syslog only and is ignored when specified with UDP).
+ * That is not yet implemented.
+ * rgerhards, 2006-12-07
+ * In order to support IPv6 addresses, we must introduce an extension to
+ * the hostname. If it is in square brackets, whatever is in them is treated as
+ * the hostname - without any exceptions ;) -- rgerhards, 2008-08-05
+ */
+ if(*p == '(') {
+ /* at this position, it *must* be an option indicator */
+ do {
+ ++p; /* eat '(' or ',' (depending on when called) */
+ /* check options */
+ if(*p == 'z') { /* compression */
+ ++p; /* eat */
+ if(isdigit((int) *p)) {
+ int iLevel;
+ iLevel = *p - '0';
+ ++p; /* eat */
+ pData->compressionLevel = iLevel;
+ pData->compressionMode = COMPRESS_SINGLE_MSG;
+ } else {
+ LogError(0, NO_ERRCODE, "Invalid compression level '%c' specified in "
+ "forwarding action - NOT turning on compression.",
+ *p);
+ }
+ } else if(*p == 'o') { /* octet-couting based TCP framing? */
+ ++p; /* eat */
+ /* no further options settable */
+ tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else { /* invalid option! Just skip it... */
+ LogError(0, NO_ERRCODE, "Invalid option %c in forwarding action - ignoring.", *p);
+ ++p; /* eat invalid option */
+ }
+ /* the option processing is done. We now do a generic skip
+ * to either the next option or the end of the option
+ * block.
+ */
+ while(*p && *p != ')' && *p != ',')
+ ++p; /* just skip it */
+ } while(*p && *p == ','); /* Attention: do.. while() */
+ if(*p == ')')
+ ++p; /* eat terminator, on to next */
+ else
+ /* we probably have end of string - leave it for the rest
+ * of the code to handle it (but warn the user)
+ */
+ LogError(0, NO_ERRCODE, "Option block not terminated in forwarding action.");
+ }
+
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ if(*p == '[') { /* everything is hostname upto ']' */
+ ++p; /* skip '[' */
+ for(q = p ; *p && *p != ']' ; ++p)
+ /* JUST SKIP */;
+ if(*p == ']') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ ++p; /* eat it */
+ }
+ } else { /* traditional view of hostname */
+ for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p)
+ /* JUST SKIP */;
+ }
+
+ pData->tcp_framing = tcp_framing;
+ pData->port = NULL;
+ pData->networkNamespace = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ pData->port = malloc(i + 1);
+ if(pData->port == NULL) {
+ LogError(0, NO_ERRCODE, "Could not get memory to store syslog forwarding port, "
+ "using default port, results may not be what you intend");
+ /* we leave f_forw.port set to NULL, this is then handled below */
+ } else {
+ memcpy(pData->port, tmp, i);
+ *(pData->port + i) = '\0';
+ }
+ }
+ /* check if no port is set. If so, we use the IANA-assigned port of 514 */
+ if(pData->port == NULL) {
+ CHKmalloc(pData->port = strdup("514"));
+ }
+
+ /* now skip to template */
+ while(*p && *p != ';' && *p != '#' && !isspace((int) *p))
+ ++p; /*JUST SKIP*/
+
+ if(*p == ';' || *p == '#' || isspace(*p)) {
+ uchar cTmp = *p;
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ CHKmalloc(pData->target = strdup((char*) q));
+ *p = cTmp;
+ } else {
+ CHKmalloc(pData->target = strdup((char*) q));
+ }
+
+ /* copy over config data as needed */
+ pData->iRebindInterval = (pData->protocol == FORW_TCP) ?
+ cs.iTCPRebindInterval : cs.iUDPRebindInterval;
+
+ pData->bKeepAlive = cs.bKeepAlive;
+ pData->iKeepAliveProbes = cs.iKeepAliveProbes;
+ pData->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ pData->iKeepAliveTime = cs.iKeepAliveTime;
+ pData->iConErrSkip = cs.iConErrSkip;
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl()));
+
+ if(pData->protocol == FORW_TCP) {
+ pData->bResendLastOnRecon = cs.bResendLastOnRecon;
+ pData->iStrmDrvrMode = cs.iStrmDrvrMode;
+ if(cs.pPermPeers != NULL) {
+ pData->pPermPeers = cs.pPermPeers;
+ cs.pPermPeers = NULL;
+ }
+ }
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* a common function to free our configuration variables - used both on exit
+ * and on $ResetConfig processing. -- rgerhards, 2008-05-16
+ */
+static void
+freeConfigVars(void)
+{
+ free(cs.pszStrmDrvr);
+ cs.pszStrmDrvr = NULL;
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+ free(cs.pPermPeers);
+ cs.pPermPeers = NULL; /* TODO: fix in older builds! */
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(netstrms, LM_NETSTRMS_FILENAME);
+ objRelease(tcpclt, LM_TCPCLT_FILENAME);
+ objRelease(statsobj, CORE_COMPONENT);
+ freeConfigVars();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMODTX_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2008-03-28
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ freeConfigVars();
+
+ /* we now must reset all non-string values */
+ cs.iStrmDrvrMode = 0;
+ cs.bResendLastOnRecon = 0;
+ cs.iUDPRebindInterval = 0;
+ cs.iTCPRebindInterval = 0;
+ cs.bKeepAlive = 0;
+ cs.iKeepAliveProbes = 0;
+ cs.iKeepAliveIntvl = 0;
+ cs.iKeepAliveTime = 0;
+ cs.iConErrSkip = 0;
+
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit(Fwd)
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(net,LM_NET_FILENAME));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord,
+ setLegacyDfltTpl, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcprebindinterval", 0, eCmdHdlrInt,
+ NULL, &cs.iTCPRebindInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendudprebindinterval", 0, eCmdHdlrInt,
+ NULL, &cs.iUDPRebindInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive", 0, eCmdHdlrBinary,
+ NULL, &cs.bKeepAlive, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_probes", 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveProbes, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_intvl", 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveIntvl, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_time", 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveTime, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszStrmDrvr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt,
+ NULL, &cs.iStrmDrvrMode, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord,
+ NULL, &cs.pszStrmDrvrAuthMode, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverpermittedpeer", 0, eCmdHdlrGetWord,
+ setPermittedPeer, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendresendlastmsgonreconnect", 0, eCmdHdlrBinary,
+ NULL, &cs.bResendLastOnRecon, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
diff --git a/tools/omfwd.h b/tools/omfwd.h
new file mode 100644
index 0000000..c4f9074
--- /dev/null
+++ b/tools/omfwd.h
@@ -0,0 +1,34 @@
+/* omfwd.h
+ * These are the definitions for the build-in forwarding output module.
+ *
+ * File begun on 2007-07-13 by RGerhards
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMFWD_H_INCLUDED
+#define OMFWD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitFwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(),
+rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef OMFWD_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/tools/ompipe.c b/tools/ompipe.c
new file mode 100644
index 0000000..a3c460f
--- /dev/null
+++ b/tools/ompipe.c
@@ -0,0 +1,448 @@
+/* ompipe.c
+ * This is the implementation of the build-in pipe output module.
+ * Note that this module stems back to the "old" (4.4.2 and below)
+ * omfile. There were some issues with the new omfile code and pipes
+ * (namely in regard to xconsole), so we took out the pipe code and moved
+ * that to a separate module. That a) immediately solves the issue for a
+ * less common use case and probably makes it much easier to enhance
+ * file and pipe support (now independently) in the future (we always
+ * needed to think about pipes in omfile so far, what we now no longer
+ * need to, hopefully resulting in reduction of complexity).
+ *
+ * NOTE: read comments in module-template.h to understand how this pipe
+ * works!
+ *
+ * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/file.h>
+
+#include "rsyslog.h"
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "ompipe.h"
+#include "omfile.h" /* for dirty trick: access to $ActionFileDefaultTemplate value */
+#include "cfsysline.h"
+#include "module-template.h"
+#include "conf.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ompipe")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+
+typedef struct _instanceData {
+ uchar *pipe; /* pipe or template name (display only) */
+ uchar *tplName; /* format template to use */
+ short fd; /* pipe descriptor for (current) pipe */
+ pthread_mutex_t mutWrite; /* guard against multiple instances writing to same pipe */
+ sbool bHadError; /* did we already have/report an error on this pipe? */
+ sbool bTryResumeReopen; /* should we attempt to reopen the pipe on action resume? */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t __attribute__((unused)) cs;
+
+/* tables for interfacing with the v6 config system */
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "template", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "pipe", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "template", eCmdHdlrGetWord, 0 },
+ { "tryResumeReopen", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ uchar *tplName; /* default template */
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+/* this function gets the default template */
+static uchar*
+getDfltTpl(void)
+{
+ if(loadModConf != NULL && loadModConf->tplName != NULL)
+ return loadModConf->tplName;
+ else
+ return (uchar*)"RSYSLOG_FileFormat";
+}
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("pipe %s", pData->pipe);
+ if (pData->fd == -1)
+ dbgprintf(" (unused)");
+ENDdbgPrintInstInfo
+
+
+/* This is now shared code for all types of files. It simply prepares
+ * pipe access, which, among others, means the the pipe wil be opened
+ * and any directories in between will be created (based on config, of
+ * course). -- rgerhards, 2008-10-22
+ * changed to iRet interface - 2009-03-19
+ */
+static rsRetVal
+preparePipe(instanceData *pData)
+{
+ DEFiRet;
+ pData->fd = open((char*) pData->pipe, O_RDWR|O_NONBLOCK|O_CLOEXEC);
+ if(pData->fd < 0 ) {
+ pData->fd = -1;
+ if(!pData->bHadError) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS, "Could not open output pipe '%s':",
+ pData->pipe);
+ pData->bHadError = 1;
+ }
+ DBGPRINTF("Error opening log pipe: %s\n", pData->pipe);
+ }
+ RETiRet;
+}
+
+
+/* rgerhards 2004-11-11: write to a pipe output. This
+ * will be called for all outputs using pipe semantics,
+ * for example also for pipes.
+ */
+static rsRetVal writePipe(uchar **ppString, instanceData *pData)
+{
+ int iLenWritten;
+ DEFiRet;
+
+ assert(pData != NULL);
+
+ if(pData->fd == -1) {
+ rsRetVal iRetLocal;
+ iRetLocal = preparePipe(pData);
+ if((iRetLocal != RS_RET_OK) || (pData->fd == -1))
+ ABORT_FINALIZE(RS_RET_SUSPENDED); /* whatever the failure was, we need to retry */
+ }
+
+ /* create the message based on format specified */
+ iLenWritten = write(pData->fd, ppString[0], strlen((char*)ppString[0]));
+ if(iLenWritten < 0) {
+ const int e = errno;
+ /* If a named pipe is full, we suspend this action for a while */
+ if(e == EAGAIN)
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+
+ close(pData->fd);
+ pData->fd = -1; /* tell that fd is no longer open! */
+ iRet = RS_RET_SUSPENDED;
+ LogError(e, NO_ERRCODE, "write error on pipe %s", pData->pipe);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ pModConf->tplName = NULL;
+ENDbeginCnfLoad
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for ompipe:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "template")) {
+ loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ if(pszFileDfltTplName != NULL) {
+ LogError(0, RS_RET_DUP_PARAM, "ompipe: warning: default template "
+ "was already set via legacy directive - may lead to inconsistent "
+ "results.");
+ }
+ } else {
+ dbgprintf("ompipe: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ /* free legacy config vars */
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ free(pModConf->tplName);
+ENDfreeCnf
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->pipe = NULL;
+ pData->fd = -1;
+ pData->bHadError = 0;
+ pData->bTryResumeReopen = 0;
+ pthread_mutex_init(&pData->mutWrite, NULL);
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ pthread_mutex_destroy(&pData->mutWrite);
+ free(pData->pipe);
+ if(pData->fd != -1)
+ close(pData->fd);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINtryResume
+ instanceData *__restrict__ const pData = pWrkrData->pData;
+ fd_set wrds;
+ struct timeval tv;
+ int ready;
+CODESTARTtryResume
+ if(pData->fd == -1) {
+ rsRetVal iRetLocal;
+ iRetLocal = preparePipe(pData);
+ if((iRetLocal != RS_RET_OK) || (pData->fd == -1))
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ } else {
+ /* we can reach this if the pipe is full, so we need
+ * to check if we can write again. /dev/xconsole is the
+ * ugly example of why this is necessary.
+ */
+ FD_ZERO(&wrds);
+ FD_SET(pData->fd, &wrds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ ready = select(pData->fd+1, NULL, &wrds, NULL, &tv);
+ DBGPRINTF("ompipe: tryResume: ready to write fd %d: %d\n", pData->fd, ready);
+ if(ready != 1) {
+ if(pData->bTryResumeReopen && pData->fd != -1) {
+ close(pData->fd);
+ pData->fd = -1;
+ }
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+finalize_it:
+ENDtryResume
+
+BEGINdoAction
+ instanceData *pData;
+CODESTARTdoAction
+ pData = pWrkrData->pData;
+ DBGPRINTF("ompipe: writing to %s\n", pData->pipe);
+ /* this module is single-threaded by nature */
+ pthread_mutex_lock(&pData->mutWrite);
+ iRet = writePipe(ppString, pData);
+ pthread_mutex_unlock(&pData->mutWrite);
+ENDdoAction
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "pipe")) {
+ pData->pipe = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "tryResumeReopen")) {
+ pData->bTryResumeReopen = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("ompipe: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_FileFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+ /* yes, the if below is redundant, but I need it now. Will go away as
+ * the code further changes. -- rgerhards, 2007-07-25
+ */
+ if(*p == '|') {
+ if((iRet = createInstance(&pData)) != RS_RET_OK) {
+ return iRet; /* this can not use RET_iRet! */
+ }
+ } else {
+ /* this is not clean, but we need it for the time being
+ * TODO: remove when cleaning up modularization
+ */
+ return RS_RET_CONFLINE_UNPROCESSED;
+ }
+
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ CHKmalloc(pData->pipe = malloc(512));
+ ++p;
+ CHKiRet(cflineParseFileName(p, (uchar*) pData->pipe, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ getDfltTpl()));
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINdoHUP
+CODESTARTdoHUP
+ pthread_mutex_lock(&pData->mutWrite);
+ if(pData->fd != -1) {
+ close(pData->fd);
+ pData->fd = -1;
+ }
+ pthread_mutex_unlock(&pData->mutWrite);
+ENDdoHUP
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Pipe)
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+/* vi:set ai:
+ */
diff --git a/tools/ompipe.h b/tools/ompipe.h
new file mode 100644
index 0000000..49a5221
--- /dev/null
+++ b/tools/ompipe.h
@@ -0,0 +1,31 @@
+/* ompipe.h
+ * These are the definitions for the build-in pipe output module.
+ *
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This pipe is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMPIPE_H_INCLUDED
+#define OMPIPE_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitPipe(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(),
+ rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef OMPIPE_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/omshell.c b/tools/omshell.c
new file mode 100644
index 0000000..98f21f9
--- /dev/null
+++ b/tools/omshell.c
@@ -0,0 +1,163 @@
+/* omshell.c
+ * This is the implementation of the build-in shell output module.
+ *
+ * ************* DO NOT EXTEND THIS MODULE **************
+ * This is pure legacy, omprog has much better and more
+ * secure functionality than this module. It is NOT
+ * recommended to base new work on it!
+ * 2012-01-19 rgerhards
+ * ******************************************************
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * shell support was initially written by bkalkbrenner 2005-09-20
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007-2016 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "omshell.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ uchar progName[MAXFNAME]; /* program to execute */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("%s", pData->progName);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf("\n");
+ if(execProg((uchar*) pWrkrData->pData->progName, 1, ppString[0]) == 0)
+ LogError(0, NO_ERRCODE, "Executing program '%s' failed", (char*)pWrkrData->pData->progName);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* yes, the if below is redundant, but I need it now. Will go away as
+ * the code further changes. -- rgerhards, 2007-07-25
+ */
+ if(*p == '^') {
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ goto finalize_it;
+ }
+
+
+ switch (*p)
+ {
+ case '^': /* bkalkbrenner 2005-09-20: execute shell command */
+ dbgprintf("exec\n");
+ ++p;
+ iRet = cflineParseFileName(p, (uchar*) pData->progName, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ (uchar*)"RSYSLOG_TraditionalFileFormat");
+ break;
+ default:
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ break;
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Shell)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+/*
+ * vi:set ai:
+ */
diff --git a/tools/omshell.h b/tools/omshell.h
new file mode 100644
index 0000000..f0fd0b6
--- /dev/null
+++ b/tools/omshell.h
@@ -0,0 +1,34 @@
+/* omshell.c
+ * These are the definitions for the build-in shell output module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ACTSHELL_H_INCLUDED
+#define ACTSHELL_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitShell(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef ACTSHELL_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/tools/omusrmsg.c b/tools/omusrmsg.c
new file mode 100644
index 0000000..479db5b
--- /dev/null
+++ b/tools/omusrmsg.c
@@ -0,0 +1,551 @@
+/* omusrmsg.c
+ * This is the implementation of the build-in output module for sending
+ * user messages.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c, which at the
+ * time of the fork from sysklogd was under BSD license)
+ *
+ * Copyright 2007-2018 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/param.h>
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+# define STRUCTUTMP struct utmp
+# define UTNAME ut_name
+#else
+# include <utmpx.h>
+# define STRUCTUTMP struct utmpx
+# define UTNAME ut_user
+#endif
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <errno.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/msgbuf.h>
+#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_LIBSYSTEMD
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+#include <pwd.h>
+#endif
+#include "rsyslog.h"
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "conf.h"
+#include "omusrmsg.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+
+/* portability: */
+#ifndef _PATH_DEV
+# define _PATH_DEV "/dev/"
+#endif
+
+#ifdef UT_NAMESIZE
+# define UNAMESZ UT_NAMESIZE /* length of a login name */
+#else
+# define UNAMESZ 32 /* length of a login name, 32 seems current (2018) good bet */
+#endif
+#define MAXUNAMES 20 /* maximum number of user names */
+
+#ifdef OS_SOLARIS
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omusrmsg")
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ int bIsWall; /* 1- is wall, 0 - individual users */
+ char uname[MAXUNAMES][UNAMESZ+1];
+ uchar *tplName;
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t __attribute__((unused)) cs;
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "users", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->tplName);
+ENDfreeInstance
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINdbgPrintInstInfo
+ register int i;
+CODESTARTdbgPrintInstInfo
+ for (i = 0; i < MAXUNAMES && *pData->uname[i]; i++)
+ dbgprintf("%s, ", pData->uname[i]);
+ENDdbgPrintInstInfo
+
+
+/**
+ * BSD setutent/getutent() replacement routines
+ * The following routines emulate setutent() and getutent() under
+ * BSD because they are not available there. We only emulate what we actually
+ * need! rgerhards 2005-03-18
+ */
+#ifdef OS_BSD
+/* Since version 900007, FreeBSD has a POSIX compliant <utmpx.h> */
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 900007)
+# define setutent(void) setutxent(void)
+# define getutent(void) getutxent(void)
+# define endutent(void) endutxent(void)
+#else
+static FILE *BSD_uf = NULL;
+void setutent(void)
+{
+ assert(BSD_uf == NULL);
+ if ((BSD_uf = fopen(_PATH_UTMP, "r")) == NULL) {
+ LogError(errno, NO_ERRCODE, "error opening utmp %s", _PATH_UTMP);
+ return;
+ }
+}
+
+STRUCTUTMP* getutent(void)
+{
+ static STRUCTUTMP st_utmp;
+
+ if(fread((char *)&st_utmp, sizeof(st_utmp), 1, BSD_uf) != 1)
+ return NULL;
+
+ return(&st_utmp);
+}
+
+void endutent(void)
+{
+ fclose(BSD_uf);
+ BSD_uf = NULL;
+}
+#endif /* if defined(__FreeBSD__) */
+#endif /* #ifdef OS_BSD */
+
+
+static void sendwallmsg(const char *tty, uchar* pMsg)
+{
+ uchar szErr[512];
+ int errnoSave;
+ char p[sizeof(_PATH_DEV) + UNAMESZ];
+ int ttyf;
+ struct stat statb;
+ int wrRet;
+
+ /* compute the device name */
+ strcpy(p, _PATH_DEV);
+ strncat(p, tty, UNAMESZ);
+
+ /* we must be careful when writing to the terminal. A terminal may block
+ * (for example, a user has pressed <ctl>-s). In that case, we can not
+ * wait indefinitely. So we need to use non-blocking I/O. In case we would
+ * block, we simply do not send the message, because that's the best we can
+ * do. -- rgerhards, 2008-07-04
+ */
+
+ /* open the terminal */
+ if((ttyf = open(p, O_WRONLY|O_NOCTTY|O_NONBLOCK)) >= 0) {
+ if(fstat(ttyf, &statb) == 0 && (statb.st_mode & S_IWRITE)) {
+ wrRet = write(ttyf, pMsg, strlen((char*)pMsg));
+ if(Debug && wrRet == -1) {
+ /* we record the state to the debug log */
+ errnoSave = errno;
+ rs_strerror_r(errno, (char*)szErr, sizeof(szErr));
+ dbgprintf("write to terminal '%s' failed with [%d]:%s\n",
+ p, errnoSave, szErr);
+ }
+ }
+ close(ttyf);
+ }
+}
+
+/* WALLMSG -- Write a message to the world at large
+ *
+ * Write the specified message to either the entire
+ * world, or a list of approved users.
+ *
+ * rgerhards, 2005-10-19: applying the following sysklogd patch:
+ * Tue May 4 16:52:01 CEST 2004: Solar Designer <solar@openwall.com>
+ * Adjust the size of a variable to prevent a buffer overflow
+ * should _PATH_DEV ever contain something different than "/dev/".
+ * rgerhards, 2008-07-04: changing the function to no longer use fork() but
+ * continue run on its thread instead.
+ */
+static rsRetVal wallmsg(uchar* pMsg, instanceData *pData)
+{
+ register int i;
+ STRUCTUTMP ut;
+ STRUCTUTMP *uptr;
+ DEFiRet;
+
+ assert(pMsg != NULL);
+
+#ifdef HAVE_LIBSYSTEMD
+ if (sd_booted() > 0) {
+ register int j;
+ int sdRet;
+ char **sessions_list;
+ int sessions = sd_get_sessions(&sessions_list);
+
+ for (j = 0; j < sessions; j++) {
+ uchar szErr[512];
+ char *tty;
+ const char *user = NULL;
+ uid_t uid;
+ struct passwd *pws;
+
+ sdRet = sd_session_get_uid(sessions_list[j], &uid);
+ if (sdRet >= 0) {
+ pws = getpwuid(uid);
+ user = pws->pw_name; /* DO NOT FREE, OS/LIB internal memory! */
+
+ if (user == NULL) {
+ dbgprintf("failed to get username for userid '%d'\n", uid);
+ continue;
+ }
+ } else {
+ /* we record the state to the debug log */
+ rs_strerror_r(-sdRet, (char*)szErr, sizeof(szErr));
+ dbgprintf("get userid for session '%s' failed with [%d]:%s\n",
+ sessions_list[j], -sdRet, szErr);
+ continue; /* try next session */
+ }
+ /* should we send the message to this user? */
+ if(pData->bIsWall == 0) {
+ for(i = 0; i < MAXUNAMES; i++) {
+ if(!pData->uname[i][0]) {
+ i = MAXUNAMES;
+ break;
+ }
+ if(strncmp(pData->uname[i], user, UNAMESZ) == 0)
+ break;
+ }
+ if(i == MAXUNAMES) { /* user not found? */
+ free(sessions_list[j]);
+ continue; /* on to next user! */
+ }
+ }
+ if ((sdRet = sd_session_get_tty(sessions_list[j], &tty)) < 0) {
+ /* we record the state to the debug log */
+ rs_strerror_r(-sdRet, (char*)szErr, sizeof(szErr));
+ dbgprintf("get tty for session '%s' failed with [%d]:%s\n",
+ sessions_list[j], -sdRet, szErr);
+ free(sessions_list[j]);
+ continue; /* try next session */
+ }
+
+ sendwallmsg(tty, pMsg);
+
+ free(tty);
+ free(sessions_list[j]);
+ }
+ free(sessions_list);
+ } else {
+#endif
+
+ /* open the user login file */
+ setutent();
+
+ /* scan the user login file */
+ while((uptr = getutent())) {
+ memcpy(&ut, uptr, sizeof(ut));
+ /* is this slot used? */
+ if(ut.UTNAME[0] == '\0')
+ continue;
+#ifndef OS_BSD
+ if(ut.ut_type != USER_PROCESS)
+ continue;
+#endif
+ if(!(memcmp (ut.UTNAME,"LOGIN", 6))) /* paranoia */
+ continue;
+
+ /* should we send the message to this user? */
+ if(pData->bIsWall == 0) {
+ for(i = 0; i < MAXUNAMES; i++) {
+ if(!pData->uname[i][0]) {
+ i = MAXUNAMES;
+ break;
+ }
+ if(strncmp(pData->uname[i], ut.UTNAME, UNAMESZ) == 0)
+ break;
+ }
+ if(i == MAXUNAMES) /* user not found? */
+ continue; /* on to next user! */
+ }
+
+ sendwallmsg(ut.ut_line, pMsg);
+ }
+
+ /* close the user login file */
+ endutent();
+#ifdef HAVE_LIBSYSTEMD
+ }
+#endif
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf("\n");
+ iRet = wallmsg(ppString[0], pWrkrData->pData);
+ENDdoAction
+
+
+static void
+populateUsers(instanceData *pData, es_str_t *usrs)
+{
+ int i;
+ int iDst;
+ es_size_t iUsr;
+ es_size_t len;
+ uchar *c;
+
+ len = es_strlen(usrs);
+ c = es_getBufAddr(usrs);
+ pData->bIsWall = 0; /* write to individual users */
+ iUsr = 0;
+ for(i = 0 ; i < MAXUNAMES && iUsr < len ; ++i) {
+ for( iDst = 0
+ ; iDst < UNAMESZ && iUsr < len && c[iUsr] != ','
+ ; ++iDst, ++iUsr) {
+ pData->uname[i][iDst] = c[iUsr];
+ }
+ pData->uname[i][iDst] = '\0';
+ DBGPRINTF("omusrmsg: send to user '%s'\n", pData->uname[i]);
+ if(iUsr < len && c[iUsr] != ',') {
+ LogError(0, RS_RET_ERR, "user name '%s...' too long - "
+ "ignored", pData->uname[i]);
+ --i;
+ ++iUsr;
+ while(iUsr < len && c[iUsr] != ',')
+ ++iUsr; /* skip to next name */
+ } else if(iDst == 0) {
+ LogError(0, RS_RET_ERR, "no user name given - "
+ "ignored");
+ --i;
+ ++iUsr;
+ while(iUsr < len && c[iUsr] != ',')
+ ++iUsr; /* skip to next name */
+ }
+ if(iUsr < len) {
+ ++iUsr; /* skip "," */
+ while(iUsr < len && isspace(c[iUsr]))
+ ++iUsr; /* skip whitespace */
+ }
+ }
+ if(i == MAXUNAMES && iUsr != len) {
+ LogError(0, RS_RET_ERR, "omusrmsg supports only up to %d "
+ "user names in a single action - all others have been ignored",
+ MAXUNAMES);
+ }
+}
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->bIsWall = 0;
+ pData->tplName = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "users")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"*", 1)) {
+ pData->bIsWall = 1;
+ } else {
+ populateUsers(pData, pvals[i].val.d.estr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omusrmsg: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup(pData->bIsWall ? " WallFmt" : " StdUsrMsgFmt"),
+ OMSR_NO_RQD_TPL_OPTS));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup((char*) pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ es_str_t *usrs;
+ int bHadWarning;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ bHadWarning = 0;
+ if(!strncmp((char*) p, ":omusrmsg:", sizeof(":omusrmsg:") - 1)) {
+ p += sizeof(":omusrmsg:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ if(!*p || !((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
+ || (*p >= '0' && *p <= '9') || *p == '_' || *p == '.' || *p == '*')) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ } else {
+ LogMsg(0, RS_RET_OUTDATED_STMT, LOG_WARNING,
+ "action '%s' treated as ':omusrmsg:%s' - please "
+ "use ':omusrmsg:%s' syntax instead, '%s' will "
+ "not be supported in the future",
+ p, p, p, p);
+ bHadWarning = 1;
+ }
+ }
+
+ CHKiRet(createInstance(&pData));
+
+ if(*p == '*') { /* wall */
+ dbgprintf("write-all");
+ ++p; /* eat '*' */
+ pData->bIsWall = 1; /* write to all users */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) " WallFmt"));
+ } else {
+ /* everything else is currently treated as a user name */
+ usrs = es_newStr(128);
+ while(*p && *p != ';') {
+ es_addChar(&usrs, *p);
+ ++p;
+ }
+ populateUsers(pData, usrs);
+ es_deleteStr(usrs);
+ if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*)" StdUsrMsgFmt"))
+ != RS_RET_OK)
+ goto finalize_it;
+ }
+ if(iRet == RS_RET_OK && bHadWarning)
+ iRet = RS_RET_OK_WARN;
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(UsrMsg)
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/tools/omusrmsg.h b/tools/omusrmsg.h
new file mode 100644
index 0000000..0e50c03
--- /dev/null
+++ b/tools/omusrmsg.h
@@ -0,0 +1,33 @@
+/* omusrmsg.c
+ * These are the definitions for the build-in user message output module.
+ *
+ * File begun on 2007-07-13 by RGerhards
+ *
+ * Copyright 20072-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OMUSRMSG_H_INCLUDED
+#define OMUSRMSG_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitUsrMsg(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef OMUSRMSG_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/pmrfc3164.c b/tools/pmrfc3164.c
new file mode 100644
index 0000000..a1e136b
--- /dev/null
+++ b/tools/pmrfc3164.c
@@ -0,0 +1,419 @@
+/* pmrfc3164.c
+ * This is a parser module for RFC3164(legacy syslog)-formatted messages.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2009-11-04 by RGerhards
+ *
+ * Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+#include "rsconf.h"
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.rfc3164")
+MODULE_CNFNAME("pmrfc3164")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* static data */
+static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */
+
+
+/* parser instance parameters */
+static struct cnfparamdescr parserpdescr[] = {
+ { "detect.yearaftertimestamp", eCmdHdlrBinary, 0 },
+ { "permit.squarebracketsinhostname", eCmdHdlrBinary, 0 },
+ { "permit.slashesinhostname", eCmdHdlrBinary, 0 },
+ { "permit.atsignsinhostname", eCmdHdlrBinary, 0 },
+ { "force.tagendingbycolon", eCmdHdlrBinary, 0},
+ { "remove.msgfirstspace", eCmdHdlrBinary, 0},
+};
+static struct cnfparamblk parserpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(parserpdescr)/sizeof(struct cnfparamdescr),
+ parserpdescr
+ };
+
+struct instanceConf_s {
+ int bDetectYearAfterTimestamp;
+ int bPermitSquareBracketsInHostname;
+ int bPermitSlashesInHostname;
+ int bPermitAtSignsInHostname;
+ int bForceTagEndingByColon;
+ int bRemoveMsgFirstSpace;
+};
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
+ inst->bDetectYearAfterTimestamp = 0;
+ inst->bPermitSquareBracketsInHostname = 0;
+ inst->bPermitSlashesInHostname = 0;
+ inst->bPermitAtSignsInHostname = 0;
+ inst->bForceTagEndingByColon = 0;
+ inst->bRemoveMsgFirstSpace = 0;
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+BEGINnewParserInst
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTnewParserInst
+ DBGPRINTF("newParserInst (pmrfc3164)\n");
+
+ inst = NULL;
+ CHKiRet(createInstance(&inst));
+
+ if(lst == NULL)
+ FINALIZE; /* just set defaults, no param block! */
+
+ if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("parser param blk in pmrfc3164:\n");
+ cnfparamsPrint(&parserpblk, pvals);
+ }
+
+ for(i = 0 ; i < parserpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(parserpblk.descr[i].name, "detect.yearaftertimestamp")) {
+ inst->bDetectYearAfterTimestamp = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "permit.squarebracketsinhostname")) {
+ inst->bPermitSquareBracketsInHostname = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "permit.slashesinhostname")) {
+ inst->bPermitSlashesInHostname = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "permit.atsignsinhostname")) {
+ inst->bPermitAtSignsInHostname = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "force.tagendingbycolon")) {
+ inst->bForceTagEndingByColon = (int) pvals[i].val.d.n;
+ } else if(!strcmp(parserpblk.descr[i].name, "remove.msgfirstspace")) {
+ inst->bRemoveMsgFirstSpace = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("pmrfc3164: program error, non-handled "
+ "param '%s'\n", parserpblk.descr[i].name);
+ }
+ }
+finalize_it:
+CODE_STD_FINALIZERnewParserInst
+ if(lst != NULL)
+ cnfparamvalsDestruct(pvals, &parserpblk);
+ if(iRet != RS_RET_OK)
+ free(inst);
+ENDnewParserInst
+
+
+BEGINfreeParserInst
+CODESTARTfreeParserInst
+ dbgprintf("pmrfc3164: free parser instance %p\n", pInst);
+ENDfreeParserInst
+
+
+/* parse a legay-formatted syslog message.
+ */
+BEGINparse2
+ uchar *p2parse;
+ int lenMsg;
+ int i; /* general index for parsing */
+ uchar bufParseTAG[CONF_TAG_MAXSIZE];
+ uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE];
+CODESTARTparse
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+ DBGPRINTF("Message will now be parsed by the legacy syslog parser (offAfterPRI=%d, lenMsg=%d.\n",
+ pMsg->offAfterPRI, lenMsg);
+ /* note: offAfterPRI is already the number of PRI chars (do not add one!) */
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+ setProtocolVersion(pMsg, MSG_LEGACY_PROTOCOL);
+ if(pMsg->iFacility == (LOG_INVLD>>3)) {
+ DBGPRINTF("facility LOG_INVLD, do not parse\n");
+ FINALIZE;
+ }
+
+ /* now check if we have a completely headerless message. This is indicated
+ * by spaces or tabs followed '{' or '['.
+ */
+ i = 0;
+ while(i < lenMsg && (p2parse[i] == ' ' || p2parse[i] == '\t')) {
+ ++i;
+ }
+ if(i < lenMsg && (p2parse[i] == '{' || p2parse[i] == '[')) {
+ DBGPRINTF("msg seems to be headerless, treating it as such\n");
+ FINALIZE;
+ }
+
+
+ /* Check to see if msg contains a timestamp. We start by assuming
+ * that the message timestamp is the time of reception (which we
+ * generated ourselfs and then try to actually find one inside the
+ * message. There we go from high-to low precison and are done
+ * when we find a matching one. -- rgerhards, 2008-09-16
+ */
+ if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) {
+ /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */;
+ } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg,
+ NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
+ if(pMsg->dfltTZ[0] != '\0')
+ applyDfltTZ(&pMsg->tTIMESTAMP, pMsg->dfltTZ);
+ /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */;
+ } else if(*p2parse == ' ' && lenMsg > 1) {
+ /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */
+ ++p2parse; /* move over space */
+ --lenMsg;
+ if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg,
+ NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
+ /* indeed, we got it! */
+ /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */;
+ } else {/* parse pointer needs to be restored, as we moved it off-by-one
+ * for this try.
+ */
+ --p2parse;
+ ++lenMsg;
+ }
+ }
+
+ if(pMsg->msgFlags & IGNDATE) {
+ /* we need to ignore the msg data, so simply copy over reception date */
+ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime));
+ }
+
+ /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we
+ * do this only when the user has not forbidden this. I now introduce some
+ * code that allows a user to configure rsyslogd to treat the rest of the
+ * message as MSG part completely. In this case, the hostname will be the
+ * machine that we received the message from and the tag will be empty. This
+ * is meant to be an interim solution, but for now it is in the code.
+ */
+ if(bParseHOSTNAMEandTAG && !(pMsg->msgFlags & INTERNAL_MSG)) {
+ /* parse HOSTNAME - but only if this is network-received!
+ * rger, 2005-11-14: we still have a problem with BSD messages. These messages
+ * do NOT include a host name. In most cases, this leads to the TAG to be treated
+ * as hostname and the first word of the message as the TAG. Clearly, this is not
+ * of advantage ;) I think I have now found a way to handle this situation: there
+ * are certain characters which are frequently used in TAG (e.g. ':'), which are
+ * *invalid* in host names. So while parsing the hostname, I check for these characters.
+ * If I find them, I set a simple flag but continue. After parsing, I check the flag.
+ * If it was set, then we most probably do not have a hostname but a TAG. Thus, I change
+ * the fields. I think this logic shall work with any type of syslog message.
+ * rgerhards, 2009-06-23: and I now have extended this logic to every character
+ * that is not a valid hostname.
+ * A "hostname" can validly include "[]" at the beginning and end. This sometimes
+ * happens with IP address (e.g. "[192.168.0.1]"). This must be turned on via
+ * an option as it may interfere with non-hostnames in some message formats.
+ * rgerhards, 2015-04-20
+ */
+ if(lenMsg > 0 && pMsg->msgFlags & PARSE_HOSTNAME) {
+ i = 0;
+ int bHadSBracket = 0;
+ if(pInst->bPermitSquareBracketsInHostname) {
+ assert(i < lenMsg);
+ if(p2parse[i] == '[') {
+ bHadSBracket = 1;
+ bufParseHOSTNAME[0] = '[';
+ ++i;
+ }
+ }
+ while(i < lenMsg
+ && (isalnum(p2parse[i]) || p2parse[i] == '.'
+ || p2parse[i] == '_' || p2parse[i] == '-'
+ || (p2parse[i] == ']' && bHadSBracket)
+ || (p2parse[i] == '@' && pInst->bPermitAtSignsInHostname)
+ || (p2parse[i] == '/' && pInst->bPermitSlashesInHostname) )
+ && i < (CONF_HOSTNAME_MAXSIZE - 1)) {
+ bufParseHOSTNAME[i] = p2parse[i];
+ ++i;
+ if(p2parse[i] == ']')
+ break; /* must be closing bracket */
+ }
+
+ if(i == lenMsg) {
+ /* we have a message that is empty immediately after the hostname,
+ * but the hostname thus is valid! -- rgerhards, 2010-02-22
+ */
+ p2parse += i;
+ lenMsg -= i;
+ bufParseHOSTNAME[i] = '\0';
+ MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, i);
+ } else {
+ int isHostName = 0;
+ if(i > 0) {
+ if(bHadSBracket) {
+ if(p2parse[i] == ']') {
+ bufParseHOSTNAME[i] = ']';
+ ++i;
+ isHostName = 1;
+ }
+ } else {
+ if(isalnum(p2parse[i-1])) {
+ isHostName = 1;
+ }
+ }
+ if(p2parse[i] != ' ')
+ isHostName = 0;
+ }
+
+ if(isHostName) {
+ /* we got a hostname! */
+ p2parse += i + 1; /* "eat" it (including SP delimiter) */
+ lenMsg -= i + 1;
+ bufParseHOSTNAME[i] = '\0';
+ MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, i);
+ }
+ }
+ }
+
+ /* now parse TAG - that should be present in message from all sources.
+ * This code is somewhat not compliant with RFC 3164. As of 3164,
+ * the TAG field is ended by any non-alphanumeric character. In
+ * practice, however, the TAG often contains dashes and other things,
+ * which would end the TAG. So it is not desirable. As such, we only
+ * accept colon and SP to be terminators. Even there is a slight difference:
+ * a colon is PART of the TAG, while a SP is NOT part of the tag
+ * (it is CONTENT). Starting 2008-04-04, we have removed the 32 character
+ * size limit (from RFC3164) on the tag. This had bad effects on existing
+ * envrionments, as sysklogd didn't obey it either (probably another bug
+ * in RFC3164...). We now receive the full size, but will modify the
+ * outputs so that only 32 characters max are used by default.
+ */
+ i = 0;
+ while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE - 2) {
+ bufParseTAG[i++] = *p2parse++;
+ --lenMsg;
+ }
+ if(lenMsg > 0 && *p2parse == ':') {
+ ++p2parse;
+ --lenMsg;
+ bufParseTAG[i++] = ':';
+ }
+ else if (pInst->bForceTagEndingByColon) {
+ /* Tag need to be ended by a colon or it's not a tag but the
+ * begin of the message
+ */
+ p2parse -= ( i + 1 );
+ lenMsg += ( i + 1 );
+ i = 0;
+ /* Default TAG is dash (without ':')
+ */
+ bufParseTAG[i++] = '-';
+ }
+
+ /* no TAG can only be detected if the message immediatly ends, in which case an empty TAG
+ * is considered OK. So we do not need to check for empty TAG. -- rgerhards, 2009-06-23
+ */
+ bufParseTAG[i] = '\0'; /* terminate string */
+ MsgSetTAG(pMsg, bufParseTAG, i);
+ } else {/* we enter this code area when the user has instructed rsyslog NOT
+ * to parse HOSTNAME and TAG - rgerhards, 2006-03-13
+ */
+ if(!(pMsg->msgFlags & INTERNAL_MSG)) {
+ DBGPRINTF("HOSTNAME and TAG not parsed by user configuration.\n");
+ }
+ }
+
+finalize_it:
+ if (pInst->bRemoveMsgFirstSpace && *p2parse == ' ') {
+ /* Bypass first space found in MSG part */
+ p2parse++;
+ lenMsg--;
+ }
+ MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg);
+ENDparse2
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD2_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(pmrfc3164)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION;
+ /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ DBGPRINTF("rfc3164 parser init called\n");
+ bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf);
+ /* cache value, is set only during rsyslogd option processing */
+
+
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/tools/pmrfc3164.h b/tools/pmrfc3164.h
new file mode 100644
index 0000000..9ea3c81
--- /dev/null
+++ b/tools/pmrfc3164.h
@@ -0,0 +1,33 @@
+/* pmrfc3164.h
+ * These are the definitions for the RFC3164 parser module.
+ *
+ * File begun on 2009-11-04 by RGerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef PMRFC3164_H_INCLUDED
+#define PMRFC3164_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitpmrfc3164(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef PMRFC3164_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/pmrfc5424.c b/tools/pmrfc5424.c
new file mode 100644
index 0000000..f682b3e
--- /dev/null
+++ b/tools/pmrfc5424.c
@@ -0,0 +1,329 @@
+/* pmrfc5424.c
+ * This is a parser module for RFC5424-formatted messages.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2009-11-03 by RGerhards
+ *
+ * Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "parser.h"
+#include "datetime.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_PARSER
+MODULE_TYPE_NOKEEP
+PARSER_NAME("rsyslog.rfc5424")
+
+/* internal structures
+ */
+DEF_PMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
+
+
+/* config data */
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATUREAutomaticSanitazion)
+ iRet = RS_RET_OK;
+ if(eFeat == sFEATUREAutomaticPRIParsing)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* Helper to parseRFCSyslogMsg. This function parses a field up to
+ * (and including) the SP character after it. The field contents is
+ * returned in a caller-provided buffer. The parsepointer is advanced
+ * to after the terminating SP. The caller must ensure that the
+ * provided buffer is large enough to hold the to be extracted value.
+ * Returns 0 if everything is fine or 1 if either the field is not
+ * SP-terminated or any other error occurs. -- rger, 2005-11-24
+ * The function now receives the size of the string and makes sure
+ * that it does not process more than that. The *pLenStr counter is
+ * updated on exit. -- rgerhards, 2009-09-23
+ */
+static int parseRFCField(uchar **pp2parse, uchar *pResult, int *pLenStr)
+{
+ uchar *p2parse;
+ int iRet = 0;
+
+ assert(pp2parse != NULL);
+ assert(*pp2parse != NULL);
+ assert(pResult != NULL);
+
+ p2parse = *pp2parse;
+
+ /* this is the actual parsing loop */
+ while(*pLenStr > 0 && *p2parse != ' ') {
+ *pResult++ = *p2parse++;
+ --(*pLenStr);
+ }
+
+ if(*pLenStr > 0 && *p2parse == ' ') {
+ ++p2parse; /* eat SP, but only if not at end of string */
+ --(*pLenStr);
+ } else {
+ iRet = 1; /* there MUST be an SP! */
+ }
+ *pResult = '\0';
+
+ /* set the new parse pointer */
+ *pp2parse = p2parse;
+ return iRet;
+}
+
+
+/* Helper to parseRFCSyslogMsg. This function parses the structured
+ * data field of a message. It does NOT parse inside structured data,
+ * just gets the field as whole. Parsing the single entities is left
+ * to other functions. The parsepointer is advanced
+ * to after the terminating SP. The caller must ensure that the
+ * provided buffer is large enough to hold the to be extracted value.
+ * Returns 0 if everything is fine or 1 if either the field is not
+ * SP-terminated or any other error occurs. -- rger, 2005-11-24
+ * The function now receives the size of the string and makes sure
+ * that it does not process more than that. The *pLenStr counter is
+ * updated on exit. -- rgerhards, 2009-09-23
+ */
+static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr)
+{
+ uchar *p2parse;
+ int bCont = 1;
+ int iRet = 0;
+ int lenStr;
+
+ assert(pp2parse != NULL);
+ assert(*pp2parse != NULL);
+ assert(pResult != NULL);
+
+ p2parse = *pp2parse;
+ lenStr = *pLenStr;
+
+ /* this is the actual parsing loop
+ * Remeber: structured data starts with [ and includes any characters
+ * until the first ] followed by a SP. There may be spaces inside
+ * structured data. There may also be \] inside the structured data, which
+ * do NOT terminate an element.
+ */
+ if(lenStr == 0 || (*p2parse != '[' && *p2parse != '-'))
+ return 1; /* this is NOT structured data! */
+
+ if(*p2parse == '-') { /* empty structured data? */
+ *pResult++ = '-';
+ ++p2parse;
+ --lenStr;
+ } else {
+ while(bCont) {
+ if(lenStr < 2) {
+ /* we now need to check if we have only structured data */
+ if(lenStr > 0 && *p2parse == ']') {
+ *pResult++ = *p2parse;
+ p2parse++;
+ lenStr--;
+ bCont = 0;
+ } else {
+ iRet = 1; /* this is not valid! */
+ bCont = 0;
+ }
+ } else if(*p2parse == '\\' && *(p2parse+1) == ']') {
+ /* this is escaped, need to copy both */
+ *pResult++ = *p2parse++;
+ *pResult++ = *p2parse++;
+ lenStr -= 2;
+ } else if(*p2parse == ']' && *(p2parse+1) == ' ') {
+ /* found end, just need to copy the ] and eat the SP */
+ *pResult++ = *p2parse;
+ p2parse += 1;
+ lenStr -= 1;
+ bCont = 0;
+ } else {
+ *pResult++ = *p2parse++;
+ --lenStr;
+ }
+ }
+ }
+
+ if(lenStr > 0 && *p2parse == ' ') {
+ ++p2parse; /* eat SP, but only if not at end of string */
+ --lenStr;
+ } else {
+ iRet = 1; /* there MUST be an SP! */
+ }
+ *pResult = '\0';
+
+ /* set the new parse pointer */
+ *pp2parse = p2parse;
+ *pLenStr = lenStr;
+ return iRet;
+}
+
+/* parse a RFC5424-formatted syslog message. This function returns
+ * 0 if processing of the message shall continue and 1 if something
+ * went wrong and this messe should be ignored. This function has been
+ * implemented in the effort to support syslog-protocol. Please note that
+ * the name (parse *RFC*) stems from the hope that syslog-protocol will
+ * some time become an RFC. Do not confuse this with informational
+ * RFC 3164 (which is legacy syslog).
+ *
+ * currently supported format:
+ *
+ * <PRI>VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG
+ *
+ * <PRI> is already stripped when this function is entered. VERSION already
+ * has been confirmed to be "1", but has NOT been stripped from the message.
+ *
+ * rger, 2005-11-24
+ */
+BEGINparse
+ uchar *p2parse;
+ uchar *pBuf = NULL;
+ int lenMsg;
+ int bContParse = 1;
+CODESTARTparse
+ assert(pMsg != NULL);
+ assert(pMsg->pszRawMsg != NULL);
+ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
+ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
+
+ /* check if we are the right parser */
+ if(lenMsg < 2 || p2parse[0] != '1' || p2parse[1] != ' ') {
+ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE);
+ }
+ DBGPRINTF("Message has RFC5424/syslog-protocol format.\n");
+ setProtocolVersion(pMsg, MSG_RFC5424_PROTOCOL);
+ p2parse += 2;
+ lenMsg -= 2;
+
+ /* Now get us some memory we can use as a work buffer while parsing.
+ * We simply allocated a buffer sufficiently large to hold all of the
+ * message, so we can not run into any troubles. I think this is
+ * wiser than to use individual buffers.
+ */
+ CHKmalloc(pBuf = malloc(lenMsg + 1));
+
+ /* IMPORTANT NOTE:
+ * Validation is not actually done below nor are any errors handled. I have
+ * NOT included this for the current proof of concept. However, it is strongly
+ * advisable to add it when this code actually goes into production.
+ * rgerhards, 2005-11-24
+ */
+
+ /* TIMESTAMP */
+ if(lenMsg >= 2 && p2parse[0] == '-' && p2parse[1] == ' ') {
+ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime));
+ p2parse += 2;
+ lenMsg -= 2;
+ } else if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) {
+ if(pMsg->msgFlags & IGNDATE) {
+ /* we need to ignore the msg data, so simply copy over reception date */
+ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime));
+ }
+ } else {
+ DBGPRINTF("no TIMESTAMP detected!\n");
+ bContParse = 0;
+ }
+
+ /* HOSTNAME */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf, &lenMsg);
+ MsgSetHOSTNAME(pMsg, pBuf, ustrlen(pBuf));
+ }
+
+ /* APP-NAME */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf, &lenMsg);
+ MsgSetAPPNAME(pMsg, (char*)pBuf);
+ }
+
+ /* PROCID */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf, &lenMsg);
+ MsgSetPROCID(pMsg, (char*)pBuf);
+ }
+
+ /* MSGID */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf, &lenMsg);
+ MsgSetMSGID(pMsg, (char*)pBuf);
+ }
+
+ /* STRUCTURED-DATA */
+ if(bContParse) {
+ parseRFCStructuredData(&p2parse, pBuf, &lenMsg);
+ MsgSetStructuredData(pMsg, (char*)pBuf);
+ }
+
+ /* MSG */
+ MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg);
+
+finalize_it:
+ if(pBuf != NULL)
+ free(pBuf);
+ENDparse
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(parser, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_PMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(pmrfc5424)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ dbgprintf("rfc5424 parser init called\n");
+ dbgprintf("GetParserName addr %p\n", GetParserName);
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/tools/pmrfc5424.h b/tools/pmrfc5424.h
new file mode 100644
index 0000000..17f9306
--- /dev/null
+++ b/tools/pmrfc5424.h
@@ -0,0 +1,33 @@
+/* pmrfc5424.h
+ * These are the definitions for the RFCC5424 parser module.
+ *
+ * File begun on 2009-11-03 by RGerhards
+ *
+ * Copyright 2009-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef PMRFC54254_H_INCLUDED
+#define PMRFC54254_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitpmrfc5424(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef PMRFC54254_H_INCLUDED */
+/* vi:set ai:
+ */
diff --git a/tools/recover_qi.pl b/tools/recover_qi.pl
new file mode 100755
index 0000000..eb8de55
--- /dev/null
+++ b/tools/recover_qi.pl
@@ -0,0 +1,207 @@
+#!/usr/bin/perl -w
+# recover rsyslog disk queue index (.qi) from queue files (.nnnnnnnn).
+#
+# See:
+# runtime/queue.c: qqueuePersist()
+# runtime/queue.c: qqueueTryLoadPersistedInfo()
+#
+# kaiwang.chen@gmail.com 2012-03-14
+#
+use strict;
+use Getopt::Long;
+
+my %opt = ();
+GetOptions(\%opt,"spool|w=s","basename|f=s","digits|d=i","help!");
+if ($opt{help}) {
+ print "Usage:
+\t$0 -w WorkDirectory -f QueueFileName -d 8 > QueueFileName.qi
+";
+ exit;
+}
+
+# runtime/queue.c: qConstructDisk()
+my $iMaxFiles = 10000000; # 0+"1".( "0"x($opt{digits} - 1));
+
+# get the list of queue files, spool directory excluded
+my $re = qr/^\Q$opt{basename}\E\.\d{$opt{digits}}$/;
+opendir(DIR, $opt{spool}) or die "can’t open spool: $!";
+my @qf = grep { /$re/ && -f "$opt{spool}/$_" } readdir(DIR);
+closedir DIR;
+
+# ensure order and continuity
+@qf = sort @qf;
+my ($head) = ($qf[0] =~ /(\d+)$/);
+my ($tail) = ($qf[-1] =~ /(\d+)$/);
+$head += 0;
+$tail += 0;
+if ($tail-$head+1 != @qf || $tail > $iMaxFiles) {
+ die "broken queue: missing file(s) or wrong tail\n";
+}
+
+# collect some counters about the queue, assuming all are unprocessed entries.
+my $sizeOnDisk = 0;
+my $iQueueSize = 0;
+chdir($opt{spool}) or die "can't chdir to spool: $!";
+print STDERR "traversing ". @qf ." files, please wait...\n";
+for (@qf) {
+ open FH, "<", $_ or die "can't read queue file $_\n";
+ $sizeOnDisk += (stat FH)[7];
+ while (<FH>) {
+ $iQueueSize++ if /^<Obj/; # runtime/msg.c: MsgSerialize()
+ }
+ close FH;
+}
+# happen to reuse last stat
+my $iCurrOffs_Write = (stat(_))[7];
+
+# runtime/queue.c: qqueuePersist()
+my $qqueue = Rsyslog::OPB->new("qqueue",1);
+$qqueue->property("iQueueSize", "INT", $iQueueSize);
+$qqueue->property("tVars.disk.sizeOnDisk", "INT64", $sizeOnDisk);
+$qqueue->property("tVars.disk.bytesRead", "INT64", 0);
+
+# runtime/stream.h: strmType_t
+my $STREAMTYPE_FILE_CIRCULAR = 1;
+# runtime/stream.h: strmMode_t
+my $STREAMMODE_READ = 1;
+my $STREAMMODE_WRITE_APPEND = 4;
+
+# runtime/stream.c: strmSerialize()
+# write to end
+my $strm_Write = Rsyslog::Obj->new("strm",1);
+$strm_Write->property( "iCurrFNum", "INT", $tail);
+$strm_Write->property( "pszFName", "PSZ", $opt{basename});
+$strm_Write->property( "iMaxFiles", "INT", $iMaxFiles);
+$strm_Write->property( "bDeleteOnClose", "INT", 0);
+$strm_Write->property( "sType", "INT", $STREAMTYPE_FILE_CIRCULAR);
+$strm_Write->property("tOperationsMode", "INT", $STREAMMODE_WRITE_APPEND);
+$strm_Write->property( "tOpenMode", "INT", 0600);
+$strm_Write->property( "iCurrOffs","INT64", $iCurrOffs_Write);
+# read from head
+my $strm_ReadDel = Rsyslog::Obj->new("strm",1);
+$strm_ReadDel->property( "iCurrFNum", "INT", $head);
+$strm_ReadDel->property( "pszFName", "PSZ", $opt{basename});
+$strm_ReadDel->property( "iMaxFiles", "INT", $iMaxFiles);
+$strm_ReadDel->property( "bDeleteOnClose", "INT", 1);
+$strm_ReadDel->property( "sType", "INT", $STREAMTYPE_FILE_CIRCULAR);
+$strm_ReadDel->property("tOperationsMode", "INT", $STREAMMODE_READ);
+$strm_ReadDel->property( "tOpenMode", "INT", 0600);
+$strm_ReadDel->property( "iCurrOffs","INT64", 0);
+
+# .qi
+print $qqueue->serialize();
+print $strm_Write->serialize();
+print $strm_ReadDel->serialize();
+
+exit;
+#-----------------------------------------------------------------------------
+
+package Rsyslog::Serializable;
+# runtime/obj.c
+sub COOKIE_OBJLINE { '<' }
+sub COOKIE_PROPLINE { '+' }
+sub COOKIE_ENDLINE { '>' }
+sub COOKIE_BLANKLINE { '.' }
+# VARTYPE(short_ptype)
+sub VARTYPE {
+ my ($t) = @_;
+ # runtime/obj-types.h: propType_t
+ my $ptype = "PROPTYPE_".$t;
+ # runtime/var.h: varType_t
+ my %vm = (
+ VARTYPE_NONE => 0,
+ VARTYPE_STR => 1,
+ VARTYPE_NUMBER => 2,
+ VARTYPE_SYSLOGTIME => 3,
+ );
+ # runtime/obj.c: SerializeProp()
+ my %p2v = (
+ #PROPTYPE_NONE => "",
+ PROPTYPE_PSZ => "VARTYPE_STR",
+ PROPTYPE_SHORT => "VARTYPE_NUMBER",
+ PROPTYPE_INT => "VARTYPE_NUMBER",
+ PROPTYPE_LONG => "VARTYPE_NUMBER",
+ PROPTYPE_INT64 => "VARTYPE_NUMBER",
+ PROPTYPE_CSTR => "VARTYPE_STR",
+ #PROPTYPE_SYSLOGTIME => "VARTYPE_SYSLOGTIME",
+ );
+ my $vtype = $p2v{$ptype};
+ unless ($vtype) {
+ die "property type $t is not supported!\n";
+ }
+ return $vm{$vtype};
+}
+sub serialize {
+ my $self = shift;
+ # runtime/obj.c: objSerializeHeader()
+ my $x = COOKIE_OBJLINE();
+ $x .= join(":", $self->type(), $self->cver(), $self->id(), $self->version());
+ $x .= ":\n";
+ for ( values %{$self->{props}} ) {
+ # runtime/obj.c: SerializeProp()
+ $x .= COOKIE_PROPLINE();
+ $x .= join(":",
+ $_->{name},
+ VARTYPE($_->{type}),
+ length($_->{value}),
+ $_->{value});
+ $x .= ":\n";
+ }
+ # runtime/obj.c: EndSerialize()
+ $x .= COOKIE_ENDLINE() . "End\n";
+ $x .= COOKIE_BLANKLINE() . "\n";
+}
+# constructor: new(id,version)
+sub new {
+ my ($class, $id, $version) = @_;
+ $class = ref $class if ref $class;
+ bless {
+ id => $id,
+ version => $version,
+ props => {},
+ }, $class;
+}
+sub id {
+ my $self = shift;
+ if (@_) {
+ my $x = $self->{id};
+ $self->{id} = shift;
+ return $x;
+ }
+ return $self->{id};
+}
+sub version {
+ my $self = shift;
+ if (@_) {
+ my $x = $self->{version};
+ $self->{version} = shift;
+ return $x;
+ }
+ return $self->{version};
+}
+# property(name, type, value)
+sub property {
+ my $self = shift;
+ my $name = shift;
+ if (@_) {
+ my $x = $self->{props}{$name};
+ $self->{props}{$name}{name} = $name;
+ $self->{props}{$name}{type} = shift;
+ $self->{props}{$name}{value} = shift;
+ return $x;
+ }
+ return $self->{props}{$name};
+}
+1;
+package Rsyslog::OPB;
+use base qw(Rsyslog::Serializable);
+sub type { 'OPB' }
+sub cver { 1 }
+sub new { shift->SUPER::new(@_) }
+1;
+package Rsyslog::Obj;
+use base qw(Rsyslog::Serializable);
+sub type { 'Obj' }
+sub cver { 1 }
+sub new { shift->SUPER::new(@_) }
+1;
diff --git a/tools/rscryutil.c b/tools/rscryutil.c
new file mode 100644
index 0000000..6ff0724
--- /dev/null
+++ b/tools/rscryutil.c
@@ -0,0 +1,552 @@
+/* This is a tool for processing rsyslog encrypted log files.
+ *
+ * Copyright 2013-2019 Adiscon GmbH
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either exprs or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <gcrypt.h>
+
+#include "rsyslog.h"
+#include "libgcry.h"
+
+
+static enum { MD_DECRYPT, MD_WRITE_KEYFILE
+} mode = MD_DECRYPT;
+static int verbose = 0;
+static gcry_cipher_hd_t gcry_chd;
+static size_t blkLength;
+
+static char *keyfile = NULL;
+static char *keyprog = NULL;
+static int randomKeyLen = -1;
+static char *cry_key = NULL;
+static unsigned cry_keylen = 0;
+static int cry_algo = GCRY_CIPHER_AES128;
+static int cry_mode = GCRY_CIPHER_MODE_CBC;
+static int optionForce = 0;
+
+/* We use some common code which expects rsyslog runtime to be
+ * present, most importantly for debug output. As a stand-alone
+ * tool, we do not really have this. So we do some dummy defines
+ * in order to satisfy the needs of the common code.
+ */
+int Debug = 0;
+#ifndef DEBUGLESS
+void r_dbgprintf(const char *srcname __attribute__((unused)), const char *fmt __attribute__((unused)), ...) {};
+#endif
+void srSleep(int a __attribute__((unused)), int b __attribute__((unused)));
+/* prototype (avoid compiler warning) */
+void srSleep(int a __attribute__((unused)), int b __attribute__((unused))) {}
+/* this is not really needed by any of our code */
+long randomNumber(void);
+/* prototype (avoid compiler warning) */
+long randomNumber(void) {return 0l;}
+/* this is not really needed by any of our code */
+
+/* rectype/value must be EIF_MAX_*_LEN+1 long!
+ * returns 0 on success or something else on error/EOF
+ */
+static int
+eiGetRecord(FILE *eifp, char *rectype, char *value)
+{
+ int r;
+ unsigned short i, j;
+ char buf[EIF_MAX_RECTYPE_LEN+EIF_MAX_VALUE_LEN+128];
+ /* large enough for any valid record */
+
+ if(fgets(buf, sizeof(buf), eifp) == NULL) {
+ r = 1; goto done;
+ }
+
+ for(i = 0 ; i < EIF_MAX_RECTYPE_LEN && buf[i] != ':' ; ++i)
+ if(buf[i] == '\0') {
+ r = 2; goto done;
+ } else
+ rectype[i] = buf[i];
+ rectype[i] = '\0';
+ j = 0;
+ for(++i ; i < EIF_MAX_VALUE_LEN && buf[i] != '\n' ; ++i, ++j)
+ if(buf[i] == '\0') {
+ r = 3; goto done;
+ } else
+ value[j] = buf[i];
+ value[j] = '\0';
+ r = 0;
+done: return r;
+}
+
+static int
+eiCheckFiletype(FILE *eifp)
+{
+ char rectype[EIF_MAX_RECTYPE_LEN+1];
+ char value[EIF_MAX_VALUE_LEN+1];
+ int r;
+
+ if((r = eiGetRecord(eifp, rectype, value)) != 0) goto done;
+ if(strcmp(rectype, "FILETYPE") || strcmp(value, RSGCRY_FILETYPE_NAME)) {
+ fprintf(stderr, "invalid filetype \"cookie\" in encryption "
+ "info file\n");
+ fprintf(stderr, "\trectype: '%s', value: '%s'\n", rectype, value);
+ r = 1; goto done;
+ }
+ r = 0;
+done: return r;
+}
+
+static int
+eiGetIV(FILE *eifp, char *iv, size_t leniv)
+{
+ char rectype[EIF_MAX_RECTYPE_LEN+1];
+ char value[EIF_MAX_VALUE_LEN+1];
+ size_t valueLen;
+ unsigned short i, j;
+ int r;
+ unsigned char nibble;
+
+ if((r = eiGetRecord(eifp, rectype, value)) != 0) goto done;
+ if(strcmp(rectype, "IV")) {
+ fprintf(stderr, "no IV record found when expected, record type "
+ "seen is '%s'\n", rectype);
+ r = 1; goto done;
+ }
+ valueLen = strlen(value);
+ if(valueLen/2 != leniv) {
+ fprintf(stderr, "length of IV is %lld, expected %lld\n",
+ (long long) valueLen/2, (long long) leniv);
+ r = 1; goto done;
+ }
+
+ for(i = j = 0 ; i < valueLen ; ++i) {
+ if(value[i] >= '0' && value[i] <= '9')
+ nibble = value[i] - '0';
+ else if(value[i] >= 'a' && value[i] <= 'f')
+ nibble = value[i] - 'a' + 10;
+ else {
+ fprintf(stderr, "invalid IV '%s'\n", value);
+ r = 1; goto done;
+ }
+ if(i % 2 == 0)
+ iv[j] = nibble << 4;
+ else
+ iv[j++] |= nibble;
+ }
+ r = 0;
+done: return r;
+}
+
+static int
+eiGetEND(FILE *eifp, off64_t *offs)
+{
+ char rectype[EIF_MAX_RECTYPE_LEN+1] = "";
+ char value[EIF_MAX_VALUE_LEN+1];
+ int r;
+
+ if((r = eiGetRecord(eifp, rectype, value)) != 0) goto done;
+ if(strcmp(rectype, "END")) {
+ fprintf(stderr, "no END record found when expected, record type "
+ "seen is '%s'\n", rectype);
+ r = 1; goto done;
+ }
+ *offs = atoll(value);
+ r = 0;
+done: return r;
+}
+
+static int
+initCrypt(FILE *eifp)
+{
+ int r = 0;
+ gcry_error_t gcryError;
+ char iv[4096];
+
+ blkLength = gcry_cipher_get_algo_blklen(cry_algo);
+ if(blkLength > sizeof(iv)) {
+ fprintf(stderr, "internal error[%s:%d]: block length %lld too large for "
+ "iv buffer\n", __FILE__, __LINE__, (long long) blkLength);
+ r = 1; goto done;
+ }
+ if((r = eiGetIV(eifp, iv, blkLength)) != 0) goto done;
+
+ size_t keyLength = gcry_cipher_get_algo_keylen(cry_algo);
+ assert(cry_key != NULL); /* "fix" clang 10 static analyzer false positive */
+ if(strlen(cry_key) != keyLength) {
+ fprintf(stderr, "invalid key length; key is %u characters, but "
+ "exactly %llu characters are required\n", cry_keylen,
+ (long long unsigned) keyLength);
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_open(&gcry_chd, cry_algo, cry_mode, 0);
+ if (gcryError) {
+ printf("gcry_cipher_open failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_setkey(gcry_chd, cry_key, keyLength);
+ if (gcryError) {
+ printf("gcry_cipher_setkey failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+
+ gcryError = gcry_cipher_setiv(gcry_chd, iv, blkLength);
+ if (gcryError) {
+ printf("gcry_cipher_setiv failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ r = 1; goto done;
+ }
+done: return r;
+}
+
+static void
+removePadding(char *buf, size_t *plen)
+{
+ unsigned len = (unsigned) *plen;
+ unsigned iSrc, iDst;
+ char *frstNUL;
+
+ frstNUL = memchr(buf, 0x00, *plen);
+ if(frstNUL == NULL)
+ goto done;
+ iDst = iSrc = frstNUL - buf;
+
+ while(iSrc < len) {
+ if(buf[iSrc] != 0x00)
+ buf[iDst++] = buf[iSrc];
+ ++iSrc;
+ }
+
+ *plen = iDst;
+done: return;
+}
+
+static void
+decryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs)
+{
+ gcry_error_t gcryError;
+ size_t nRead, nWritten;
+ size_t toRead;
+ size_t leftTillBlkEnd;
+ char buf[64*1024];
+
+ leftTillBlkEnd = blkEnd - *pCurrOffs;
+ while(1) {
+ toRead = sizeof(buf) <= leftTillBlkEnd ? sizeof(buf) : leftTillBlkEnd;
+ toRead = toRead - toRead % blkLength;
+ nRead = fread(buf, 1, toRead, fpin);
+ if(nRead == 0)
+ break;
+ leftTillBlkEnd -= nRead, *pCurrOffs += nRead;
+ gcryError = gcry_cipher_decrypt(
+ gcry_chd, // gcry_cipher_hd_t
+ buf, // void *
+ nRead, // size_t
+ NULL, // const void *
+ 0); // size_t
+ if (gcryError) {
+ fprintf(stderr, "gcry_cipher_decrypt failed: %s/%s\n",
+ gcry_strsource(gcryError),
+ gcry_strerror(gcryError));
+ return;
+ }
+ removePadding(buf, &nRead);
+ nWritten = fwrite(buf, 1, nRead, fpout);
+ if(nWritten != nRead) {
+ perror("fpout");
+ return;
+ }
+ }
+}
+
+
+static int
+doDecrypt(FILE *logfp, FILE *eifp, FILE *outfp)
+{
+ off64_t blkEnd;
+ off64_t currOffs = 0;
+ int r = 1;
+ int fd;
+ struct stat buf;
+
+ while(1) {
+ /* process block */
+ if(initCrypt(eifp) != 0)
+ goto done;
+ /* set blkEnd to size of logfp and proceed. */
+ if((fd = fileno(logfp)) == -1) {
+ r = -1;
+ goto done;
+ }
+ if((r = fstat(fd, &buf)) != 0) goto done;
+ blkEnd = buf.st_size;
+ r = eiGetEND(eifp, &blkEnd);
+ if(r != 0 && r != 1) goto done;
+ decryptBlock(logfp, outfp, blkEnd, &currOffs);
+ gcry_cipher_close(gcry_chd);
+ }
+ r = 0;
+done: return r;
+}
+
+static void
+decrypt(const char *name)
+{
+ FILE *logfp = NULL, *eifp = NULL;
+ int r = 0;
+ char eifname[4096];
+
+ if(!strcmp(name, "-")) {
+ fprintf(stderr, "decrypt mode cannot work on stdin\n");
+ goto err;
+ } else {
+ if((logfp = fopen(name, "r")) == NULL) {
+ perror(name);
+ goto err;
+ }
+ snprintf(eifname, sizeof(eifname), "%s%s", name, ENCINFO_SUFFIX);
+ eifname[sizeof(eifname)-1] = '\0';
+ if((eifp = fopen(eifname, "r")) == NULL) {
+ perror(eifname);
+ goto err;
+ }
+ if(eiCheckFiletype(eifp) != 0)
+ goto err;
+ }
+
+ if((r = doDecrypt(logfp, eifp, stdout)) != 0)
+ goto err;
+
+ fclose(logfp); logfp = NULL;
+ fclose(eifp); eifp = NULL;
+ return;
+
+err:
+ fprintf(stderr, "error %d processing file %s\n", r, name);
+ if(eifp != NULL)
+ fclose(eifp);
+ if(logfp != NULL)
+ fclose(logfp);
+}
+
+static void
+write_keyfile(char *fn)
+{
+ int fd;
+ int r;
+ mode_t fmode;
+
+ fmode = O_WRONLY|O_CREAT;
+ if(!optionForce)
+ fmode |= O_EXCL;
+ if(fn == NULL) {
+ fprintf(stderr, "program error: keyfile is NULL");
+ exit(1);
+ }
+ if((fd = open(fn, fmode, S_IRUSR)) == -1) {
+ fprintf(stderr, "error opening keyfile ");
+ perror(fn);
+ exit(1);
+ }
+ if((r = write(fd, cry_key, cry_keylen)) != (ssize_t)cry_keylen) {
+ fprintf(stderr, "error writing keyfile (ret=%d) ", r);
+ perror(fn);
+ exit(1);
+ }
+ close(fd);
+}
+
+static void
+getKeyFromFile(const char *fn)
+{
+ const int r = gcryGetKeyFromFile(fn, &cry_key, &cry_keylen);
+ if(r != 0) {
+ perror(fn);
+ exit(1);
+ }
+}
+
+static void
+getRandomKey(void)
+{
+ int fd;
+ cry_keylen = randomKeyLen;
+ cry_key = malloc(randomKeyLen); /* do NOT zero-out! */
+ /* if we cannot obtain data from /dev/urandom, we use whatever
+ * is present at the current memory location as random data. Of
+ * course, this is very weak and we should consider a different
+ * option, especially when not running under Linux (for Linux,
+ * unavailability of /dev/urandom is just a theoretic thing, it
+ * will always work...). -- TODO -- rgerhards, 2013-03-06
+ */
+ if((fd = open("/dev/urandom", O_RDONLY)) >= 0) {
+ if(read(fd, cry_key, randomKeyLen) != randomKeyLen) {
+ fprintf(stderr, "warning: could not read sufficient data "
+ "from /dev/urandom - key may be weak\n");
+ };
+ close(fd);
+ }
+}
+
+
+static void
+setKey(void)
+{
+ if(randomKeyLen != -1)
+ getRandomKey();
+ else if(keyfile != NULL)
+ getKeyFromFile(keyfile);
+ else if(keyprog != NULL)
+ gcryGetKeyFromProg(keyprog, &cry_key, &cry_keylen);
+ if(cry_key == NULL) {
+ fprintf(stderr, "ERROR: key must be set via some method\n");
+ exit(1);
+ }
+}
+
+static struct option long_options[] =
+{
+ {"verbose", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ {"decrypt", no_argument, NULL, 'd'},
+ {"force", no_argument, NULL, 'f'},
+ {"write-keyfile", required_argument, NULL, 'W'},
+ {"key", required_argument, NULL, 'K'},
+ {"generate-random-key", required_argument, NULL, 'r'},
+ {"keyfile", required_argument, NULL, 'k'},
+ {"key-program", required_argument, NULL, 'p'},
+ {"algo", required_argument, NULL, 'a'},
+ {"mode", required_argument, NULL, 'm'},
+ {NULL, 0, NULL, 0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ int opt;
+ int temp;
+ char *newKeyFile = NULL;
+
+ while(1) {
+ opt = getopt_long(argc, argv, "a:dfk:K:m:p:r:vVW:", long_options, NULL);
+ if(opt == -1)
+ break;
+ switch(opt) {
+ case 'd':
+ mode = MD_DECRYPT;
+ break;
+ case 'W':
+ mode = MD_WRITE_KEYFILE;
+ newKeyFile = optarg;
+ break;
+ case 'k':
+ keyfile = optarg;
+ break;
+ case 'p':
+ keyprog = optarg;
+ break;
+ case 'f':
+ optionForce = 1;
+ break;
+ case 'r':
+ randomKeyLen = atoi(optarg);
+ if(randomKeyLen > 64*1024) {
+ fprintf(stderr, "ERROR: keys larger than 64KiB are "
+ "not supported\n");
+ exit(1);
+ }
+ break;
+ case 'K':
+ fprintf(stderr, "WARNING: specifying the actual key "
+ "via the command line is highly insecure\n"
+ "Do NOT use this for PRODUCTION use.\n");
+ cry_key = optarg;
+ cry_keylen = strlen(cry_key);
+ break;
+ case 'a':
+ temp = rsgcryAlgoname2Algo(optarg);
+ if(temp == GCRY_CIPHER_NONE) {
+ fprintf(stderr, "ERROR: algorithm \"%s\" is not "
+ "kown/supported\n", optarg);
+ exit(1);
+ }
+ cry_algo = temp;
+ break;
+ case 'm':
+ temp = rsgcryModename2Mode(optarg);
+ if(temp == GCRY_CIPHER_MODE_NONE) {
+ fprintf(stderr, "ERROR: cipher mode \"%s\" is not "
+ "kown/supported\n", optarg);
+ exit(1);
+ }
+ cry_mode = temp;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ fprintf(stderr, "rsgtutil " VERSION "\n");
+ exit(0);
+ break;
+ case '?':
+ break;
+ default:fprintf(stderr, "getopt_long() returns unknown value %d\n", opt);
+ return 1;
+ }
+ }
+
+ setKey();
+ assert(cry_key != NULL);
+
+ if(mode == MD_WRITE_KEYFILE) {
+ if(optind != argc) {
+ fprintf(stderr, "ERROR: no file parameters permitted in "
+ "--write-keyfile mode\n");
+ exit(1);
+ }
+ write_keyfile(newKeyFile);
+ } else {
+ if(optind == argc)
+ decrypt("-");
+ else {
+ for(i = optind ; i < argc ; ++i)
+ decrypt(argv[i]);
+ }
+ }
+
+ assert(cry_key != NULL);
+ memset(cry_key, 0, cry_keylen); /* zero-out key store */
+ cry_keylen = 0;
+ return 0;
+}
diff --git a/tools/rscryutil.rst b/tools/rscryutil.rst
new file mode 100644
index 0000000..dfd447d
--- /dev/null
+++ b/tools/rscryutil.rst
@@ -0,0 +1,199 @@
+=========
+rscryutil
+=========
+
+--------------------------
+Manage Encrypted Log Files
+--------------------------
+
+:Author: Rainer Gerhards <rgerhards@adiscon.com>
+:Date: 2013-04-15
+:Manual section: 1
+
+SYNOPSIS
+========
+
+::
+
+ rscryutil [OPTIONS] [FILE] ...
+
+
+DESCRIPTION
+===========
+
+This tool performs various operations on encrypted log files.
+Most importantly, it provides the ability to decrypt them.
+
+
+OPTIONS
+=======
+
+-d, --decrypt
+ Select decryption mode. This is the default mode.
+
+-W, --write-keyfile <file>
+ Utility function to write a key to a keyfile. The key can be obtained
+ via any method.
+
+-v, --verbose
+ Select verbose mode.
+
+-f, --force
+ Forces operations that otherwise would fail.
+
+-k, --keyfile <file>
+ Reads the key from <file>. File _must_ contain the key, only, no headers
+ or other meta information. Keyfiles can be generated via the
+ *--write-keyfile* option.
+
+-p, --key-program <path-to-program>
+ In this mode, the key is provided by a so-called "key program". This program
+ is executed and must return the key to (as well as some meta information)
+ via stdout. The core idea of key programs is that using this interface the
+ user can implement as complex (and secure) method to obtain keys as
+ desired, all without the need to make modifications to rsyslog.
+
+-K, --key <KEY>
+ TESTING AID, NOT FOR PRODUCTION USE. This uses the KEY specified
+ on the command line. This is the actual key, and as such this mode
+ is highly insecure. However, it can be useful for intial testing
+ steps. This option may be removed in the future.
+
+-a, --algo <algo>
+ Sets the encryption algorightm (cipher) to be used. See below
+ for supported algorithms. The default is "AES128".
+
+-m, --mode <mode>
+ Sets the ciphermode to be used. See below for supported modes.
+ The default is "CBC".
+
+-r, --generate-random-key <bytes>
+ Generates a random key of length <bytes>. This option is
+ meant to be used together with *--write-keyfile* (and it is hard
+ to envision any other valid use for it).
+
+OPERATION MODES
+===============
+
+The operation mode specifies what exactly the tool does with the provided
+files. The default operation mode is "dump", but this may change in the future.
+Thus, it is recommended to always set the operations mode explicitely. If
+multiple operations mode are set on the command line, results are
+unpredictable.
+
+decrypt
+-------
+
+The provided log files are decrypted. Note that the *.encinfo* side files
+must exist and be accessible in order for decryption to to work.
+
+write-keyfile
+-------------
+
+In this mode no log files are processed; thus it is an error to specify
+any on the command line. The specified keyfile is written. The key itself
+is obtained via the usual key commands. If *--keyfile* is used, that
+file is effectively copied.
+
+For security reasons, existing key files are _not_ overwritten. To permit
+this, specify the *--force* option. When doing so, keep in mind that lost
+keys cannot be recovered and data encrypted with them may also be considered
+lost.
+
+Keyfiles are always created with 0400 permission, that is read access for only
+the user. An exception is when an existing file is overwritten via the
+*--force* option, in which case the former permissions still apply.
+
+EXIT CODES
+==========
+
+The command returns an exit code of 0 if everything went fine, and some
+other code in case of failures.
+
+
+SUPPORTED ALGORITHMS
+====================
+
+We basically support what libgcrypt supports. This is:
+
+ 3DES
+ CAST5
+ BLOWFISH
+ AES128
+ AES192
+ AES256
+ TWOFISH
+ TWOFISH128
+ ARCFOUR
+ DES
+ SERPENT128
+ SERPENT192
+ SERPENT256
+ RFC2268_40
+ SEED
+ CAMELLIA128
+ CAMELLIA192
+ CAMELLIA256
+
+
+SUPPORTED CIPHER MODES
+======================
+
+We basically support what libgcrypt supports. This is:
+
+ ECB
+ CFB
+ CBC
+ STREAM
+ OFB
+ CTR
+ AESWRAP
+
+EXAMPLES
+========
+
+**rscryutil logfile**
+
+Decrypts "logfile" and sends data to stdout.
+
+
+**rscryutil --generate-random-key 16 --keyfile /some/secured/path/keyfile**
+
+Generates random key and stores it in the specified keyfile.
+
+LOG SIGNATURES
+==============
+
+Encrypted log files can be used together with signing. To verify such a file,
+it must be decrypted first, and the verification tool **rsgtutil(1)** must be
+run on the decrypted file.
+
+SECURITY CONSIDERATIONS
+=======================
+
+Specifying keys directly on the command line (*--key* option) is very
+insecure and should
+not be done, except for testing purposes with test keys. Even then it is
+recommended to use keyfiles, which are also easy to handle during testing.
+Keep in mind that command history is usally be kept by bash and can also
+easily be monitored.
+
+Local keyfiles are also a security risk. At a minimum, they should be
+used with very restrictive file permissions. For this reason,
+the *rscryutil* tool creates them with read permissions for the user,
+only, no matter what umask is set to.
+
+When selecting cipher algorithms and modes, care needs to be taken. The
+defaults should be reasonable safe to use, but this tends to change over
+time. Keep up with the most current crypto recommendations.
+
+
+SEE ALSO
+========
+**rsgtutil(1)**, **rsyslogd(8)**
+
+COPYRIGHT
+=========
+
+This page is part of the *rsyslog* project, and is available under
+LGPLv2.
diff --git a/tools/rsyslog.conf.5 b/tools/rsyslog.conf.5
new file mode 100644
index 0000000..ee0b3d0
--- /dev/null
+++ b/tools/rsyslog.conf.5
@@ -0,0 +1,815 @@
+.\" rsyslog.conf - rsyslogd(8) configuration file
+.\" Copyright 2003-2008 Rainer Gerhards and Adiscon GmbH.
+.\"
+.\" This file is part of the rsyslog package, an enhanced system log daemon.
+.\"
+.\" 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, USA.
+.\"
+.TH RSYSLOG.CONF 5 "22 October 2012" "Version 7.2.0" "Linux System Administration"
+.SH NAME
+rsyslog.conf \- rsyslogd(8) configuration file
+.SH DESCRIPTION
+The
+.I rsyslog.conf
+file is the main configuration file for the
+.BR rsyslogd (8)
+which logs system messages on *nix systems. This file specifies rules
+for logging. For special features see the
+.BR rsyslogd (8)
+manpage. Rsyslog.conf is backward-compatible with sysklogd's syslog.conf file. So if you migrate
+from sysklogd you can rename it and it should work.
+
+.B Note that this version of rsyslog ships with extensive documentation in HTML format.
+This is provided in the ./doc subdirectory and probably
+in a separate package if you installed rsyslog via a packaging system.
+To use rsyslog's advanced features, you
+.B need
+to look at the HTML documentation, because the man pages only cover
+basic aspects of operation.
+
+
+.SH MODULES
+
+Rsyslog has a modular design. Consequently, there is a growing number
+of modules. See the HTML documentation for their full description.
+
+.TP
+.I omsnmp
+SNMP trap output module
+.TP
+.I omgssapi
+Output module for GSS-enabled syslog
+.TP
+.I ommysql
+Output module for MySQL
+.TP
+.I omrelp
+Output module for the reliable RELP protocol (prevents message loss).
+For details, see below at imrelp and the HTML documentation.
+It can be used like this:
+.IP
+*.* :omrelp:server:port
+.IP
+*.* :omrelp:192.168.0.1:2514 # actual sample
+.TP
+.I ompgsql
+Output module for PostgreSQL
+.TP
+.I omlibdbi
+Generic database output module (Firebird/Interbase, MS SQL, Sybase,
+SQLite, Ingres, Oracle, mSQL)
+.TP
+.I imfile
+Input module for text files
+.TP
+.I imudp
+Input plugin for UDP syslog. Replaces the deprecated -r option. Can be
+used like this:
+.IP
+$ModLoad imudp
+.IP
+$UDPServerRun 514
+.TP
+.I imtcp
+Input plugin for plain TCP syslog. Replaces the deprecated -t
+option. Can be used like this:
+.IP
+$ModLoad imtcp
+.IP
+$InputTCPServerRun 514
+.TP
+.TP
+.I imrelp
+Input plugin for the RELP protocol. RELP can be used instead
+of UDP or plain TCP syslog to provide reliable delivery of
+syslog messages. Please note that plain TCP syslog does NOT
+provide truly reliable delivery, with it messages may be lost
+when there is a connection problem or the server shuts down.
+RELP prevents message loss in those cases.
+It can be used like this:
+.IP
+$ModLoad imrelp
+.IP
+$InputRELPServerRun 2514
+.TP
+.I imgssapi
+Input plugin for plain TCP and GSS-enable syslog
+.TP
+.I immark
+Support for mark messages
+.TP
+.I imklog
+Kernel logging. To include kernel log messages, you need to do
+.IP
+$ModLoad imklog
+
+Please note that the klogd daemon is no longer necessary and consequently
+no longer provided by the rsyslog package.
+.TP
+.I imuxsock
+Unix sockets, including the system log socket. You need to specify
+.IP
+$ModLoad imuxsock
+
+in order to receive log messages from local system processes. This
+config directive should only left out if you know exactly what you
+are doing.
+
+
+.SH BASIC STRUCTURE
+
+Lines starting with a hash mark ('#') and empty lines are ignored.
+Rsyslog.conf should contain following sections (sorted by recommended order in file):
+
+.TP
+Global directives
+Global directives set some global properties of whole rsyslog daemon, for example size of main
+message queue ($MainMessageQueueSize), loading external modules ($ModLoad) and so on.
+All global directives need to be specified on a line by their own and must start with
+a dollar-sign. The complete list of global directives can be found in HTML documentation in doc
+directory or online on web pages.
+
+.TP
+Templates
+Templates allow you to specify format of the logged message. They are also used for dynamic
+file name generation. They have to be defined before they are used in rules. For more info
+about templates see TEMPLATES section of this manpage.
+
+.TP
+Output channels
+Output channels provide an umbrella for any type of output that the user might want.
+They have to be defined before they are used in rules. For more info about output channels
+see OUTPUT CHANNELS section of this manpage.
+
+.TP
+Rules (selector + action)
+Every rule line consists of two fields, a selector field and an action field. These
+two fields are separated by one or more spaces or tabs. The selector field specifies
+a pattern of facilities and priorities belonging to the specified action.
+
+.SH SELECTORS
+
+The selector field itself again consists of two parts, a facility and a
+priority, separated by a period ('.'). Both parts are case insensitive and can
+also be specified as decimal numbers, but don't do that, you have been warned.
+Both facilities and priorities are described in syslog(3). The names mentioned
+below correspond to the similar LOG_-values in /usr/include/syslog.h.
+
+The facility is one of the following keywords: auth, authpriv, cron, daemon,
+kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and
+local0 through local7. The keyword security should not be used anymore and mark
+is only for internal use and therefore should not be used in applications.
+Anyway, you may want to specify and redirect these messages here. The facility
+specifies the subsystem that produced the message, i.e. all mail programs log
+with the mail facility (LOG_MAIL) if they log using syslog.
+
+The priority is one of the following keywords, in ascending order: debug, info,
+notice, warning, warn (same as warning), err, error (same as err), crit, alert,
+emerg, panic (same as emerg). The keywords error, warn and panic are deprecated
+and should not be used anymore. The priority defines the severity of the message.
+
+The behavior of the original BSD syslogd is that all messages of the specified
+priority and higher are logged according to the given action. Rsyslogd behaves
+the same, but has some extensions.
+
+In addition to the above mentioned names the rsyslogd(8) understands the
+following extensions: An asterisk ('*') stands for all facilities or all
+priorities, depending on where it is used (before or after the period). The
+keyword none stands for no priority of the given facility.
+
+You can specify multiple facilities with the same priority pattern in one
+statement using the comma (',') operator. You may specify as much facilities as
+you want. Remember that only the facility part from such a statement is taken, a
+priority part would be skipped.
+
+Multiple selectors may be specified for a single action using the semicolon
+(';') separator. Remember that each selector in the selector field is capable
+to overwrite the preceding ones. Using this behavior you can exclude some
+priorities from the pattern.
+
+Rsyslogd has a syntax extension to the original BSD source, that makes its use
+more intuitively. You may precede every priority with an equals sign ('=') to
+specify only this single priority and not any of the above. You may also (both
+is valid, too) precede the priority with an exclamation mark ('!') to ignore
+all that priorities, either exact this one or this and any higher priority. If
+you use both extensions then the exclamation mark must occur before the equals
+sign, just use it intuitively.
+
+However, please note that there are some restrictions over the traditional
+BSD syslog behaviour. These restrictions stem back to sysklogd, exist
+probably since at least the 1990's and as such have always been in
+rsyslog.
+
+Namely, in BSD syslogd you can craft a selector like this:
+
+*.debug;local6.err
+
+The intent is to log all facilities at debug or higher, except for local6,
+which should only log at err or higher.
+
+Unfortunately, local6.err will permit error severity and higher, but will
+not exclude lower severity messages from facility local6.
+
+As an alternative, you can explicitly exclude all severities that you do
+not want to match. For the above case, this selector is equivalent to the
+BSD syslog selector:
+
+*.debug;local6.!=info;local6.!=notice;local6.!=warn
+
+An easier approach is probably to do if ... then based matching in script.
+
+.SH ACTIONS
+The action field of a rule describes what to do with the message. In general, message content
+is written to a kind of "logfile". But also other actions might be done, like writing to a
+database table or forwarding to another host.
+
+.SS Regular file
+Typically messages are logged to real files. The file has to be specified with full pathname,
+beginning with a slash ('/').
+
+.B Example:
+.RS
+*.* /var/log/traditionalfile.log;RSYSLOG_TraditionalFileFormat # log to a file in the traditional format
+.RE
+
+Note: if you would like to use high-precision timestamps in your log files,
+just remove the ";RSYSLOG_TraditionalFormat". That will select the default
+template, which, if not changed, uses RFC 3339 timestamps.
+
+.B Example:
+.RS
+*.* /var/log/file.log # log to a file with RFC3339 timestamps
+.RE
+
+By default, files are not synced after each write. To enable syncing
+of log files globally, use either the "$ActionFileEnableSync"
+directive or the "sync" parameter to omfile. Enabling this option
+degrades performance and it is advised not to enable syncing unless
+you know what you are doing.
+To selectively disable syncing for certain files, you may prefix the
+file path with a minus sign ("-").
+
+.SS Named pipes
+This version of rsyslogd(8) has support for logging output to named pipes (fifos). A fifo or
+named pipe can be used as a destination for log messages by prepending a pipe symbol ('|')
+to the name of the file. This is handy for debugging. Note that the fifo must be created with
+the mkfifo(1) command before rsyslogd(8) is started.
+
+.SS Terminal and console
+If the file you specified is a tty, special tty-handling is done, same with /dev/console.
+
+.SS Remote machine
+There are three ways to forward message: the traditional UDP transport, which is extremely
+lossy but standard, the plain TCP based transport which loses messages only during certain
+situations but is widely available and the RELP transport which does not lose messages
+but is currently available only as part of rsyslogd 3.15.0 and above.
+
+To forward messages to another host via UDP, prepend the hostname with the at sign ("@").
+To forward it via plain tcp, prepend two at signs ("@@"). To forward via RELP, prepend the
+string ":omrelp:" in front of the hostname.
+
+.B Example:
+.RS
+*.* @192.168.0.1
+.RE
+.sp
+In the example above, messages are forwarded via UDP to the machine 192.168.0.1, the destination
+port defaults to 514. Due to the nature of UDP, you will probably lose some messages in transit.
+If you expect high traffic volume, you can expect to lose a quite noticeable number of messages
+(the higher the traffic, the more likely and severe is message loss).
+
+Sockets for forwarded messages can be bound to a specific device using the "device" option for
+the omfwd module.
+
+.B Example:
+.RS
+action(type="omfwd" Target="192.168.0.1" Device="eth0" Port=514 Protocol="udp")
+.RE
+.sp
+In the example above, messages are forwarded via UDP to the machine 192.168.0.1 at port 514 over
+the device eth0. TCP can be used by setting Protocol to "tcp" in the above example.
+
+For Linux with VRF support, the device option is used to specify the VRF to send messages.
+
+.B If you would like to prevent message loss, use RELP:
+.RS
+*.* :omrelp:192.168.0.1:2514
+.RE
+.sp
+Note that a port number was given as there is no standard port for relp.
+
+Keep in mind that you need to load the correct input and output plugins (see "Modules" above).
+
+Please note that rsyslogd offers a variety of options in regarding to remote
+forwarding. For full details, please see the HTML documentation.
+
+.SS List of users
+Usually critical messages are also directed to ``root'' on that machine. You
+can specify a list
+of users that shall get the message by simply writing ":omusrmsg:" followed
+by the login name. You may specify more than one
+user by separating them with commas (','). If they're logged in they
+get the message (for example: ":omusrmsg:root,user1,user2").
+
+.SS Everyone logged on
+Emergency messages often go to all users currently online to notify them that something strange
+is happening with the system. To specify this wall(1)-feature use an ":omusrmsg:*".
+
+.SS Database table
+This allows logging of the message to a database table.
+By default, a MonitorWare-compatible schema is required for this to work. You can
+create that schema with the createDB.SQL file that came with the rsyslog package. You can also
+use any other schema of your liking - you just need to define a proper template and assign this
+template to the action.
+
+See the HTML documentation for further details on database logging.
+
+.SS Discard
+If the discard action is carried out, the received message is immediately discarded. Discard
+can be highly effective if you want to filter out some annoying messages that otherwise would
+fill your log files. To do that, place the discard actions early in your log files.
+This often plays well with property-based filters, giving you great freedom in specifying
+what you do not want.
+
+Discard is just the single 'stop' command with no further parameters.
+.sp
+.B Example:
+.RS
+*.* stop # discards everything.
+.RE
+
+
+.SS Output channel
+Binds an output channel definition (see there for details) to this action. Output channel actions
+must start with a $-sign, e.g. if you would like to bind your output channel definition "mychannel"
+to the action, use "$mychannel". Output channels support template definitions like all all other
+actions.
+
+.SS Shell execute
+This executes a program in a subshell. The program is passed the template-generated message as the
+only command line parameter. Rsyslog waits until the program terminates and only then continues to run.
+
+.B Example:
+.RS
+^program-to-execute;template
+.RE
+
+The program-to-execute can be any valid executable. It receives the template string as a single parameter
+(argv[1]).
+
+.SH FILTER CONDITIONS
+Rsyslog offers three different types "filter conditions":
+.sp 0
+ * "traditional" severity and facility based selectors
+.sp 0
+ * property-based filters
+.sp 0
+ * expression-based filters
+.RE
+
+.SS Selectors
+.B Selectors are the traditional way of filtering syslog messages.
+They have been kept in rsyslog with their original syntax, because it is well-known, highly
+effective and also needed for compatibility with stock syslogd configuration files. If you just
+need to filter based on priority and facility, you should do this with selector lines. They are
+not second-class citizens in rsyslog and offer the best performance for this job.
+
+.SS Property-Based Filters
+Property-based filters are unique to rsyslogd. They allow one to filter on any property, like HOSTNAME,
+syslogtag and msg.
+
+A property-based filter must start with a colon in column 0. This tells rsyslogd that it is the new
+filter type. The colon must be followed by the property name, a comma, the name of the compare
+operation to carry out, another comma and then the value to compare against. This value must be quoted.
+There can be spaces and tabs between the commas. Property names and compare operations are
+case-sensitive, so "msg" works, while "MSG" is an invalid property name. In brief, the syntax is as follows:
+.sp
+.RS
+:property, [!]compare-operation, "value"
+.RE
+
+The following compare-operations are currently supported:
+.sp
+.RS
+.B contains
+.RS
+Checks if the string provided in value is contained in the property
+.RE
+.sp
+.B isequal
+.RS
+Compares the "value" string provided and the property contents. These two values must be exactly equal to match.
+.RE
+.sp
+.B startswith
+.RS
+Checks if the value is found exactly at the beginning of the property value
+.RE
+.sp
+.B regex
+.RS
+Compares the property against the provided regular expression.
+.RE
+
+.SS Expression-Based Filters
+See the HTML documentation for this feature.
+
+
+.SH TEMPLATES
+
+Every output in rsyslog uses templates - this holds true for files, user
+messages and so on. Templates compatible with the stock syslogd
+formats are hardcoded into rsyslogd. If no template is specified, we use
+one of these hardcoded templates. Search for "template_" in syslogd.c and
+you will find the hardcoded ones.
+
+A template consists of a template directive, a name, the actual template text
+and optional options. A sample is:
+
+.RS
+.B $template MyTemplateName,"\\\\7Text %property% some more text\\\\n",<options>
+.RE
+
+The "$template" is the template directive. It tells rsyslog that this line
+contains a template. The backslash is an escape character. For example, \\7 rings the
+bell (this is an ASCII value), \\n is a new line. The set in rsyslog is a bit restricted
+currently.
+
+All text in the template is used literally, except for things within percent
+signs. These are properties and allow you access to the contents of the syslog
+message. Properties are accessed via the property replacer and it can for example
+pick a substring or do date-specific formatting. More on this is the PROPERTY REPLACER
+section of this manpage.
+
+To escape:
+.sp 0
+ % = \\%
+.sp 0
+ \\ = \\\\ --> '\\' is used to escape (as in C)
+.sp 0
+$template TraditionalFormat,"%timegenerated% %HOSTNAME% %syslogtag%%msg%\\n"
+
+Properties can be accessed by the property replacer (see there for details).
+
+.B Please note that templates can also by used to generate selector lines with dynamic file names.
+For example, if you would like to split syslog messages from different hosts
+to different files (one per host), you can define the following template:
+
+.RS
+.B $template DynFile,"/var/log/system-%HOSTNAME%.log"
+.RE
+
+This template can then be used when defining an output selector line. It will
+result in something like "/var/log/system-localhost.log"
+
+.SS Template options
+The <options> part is optional. It carries options influencing the template as whole.
+See details below. Be sure NOT to mistake template options with property options - the
+later ones are processed by the property replacer and apply to a SINGLE property, only
+(and not the whole template).
+
+Template options are case-insensitive. Currently defined are:
+
+.RS
+.TP
+sql
+format the string suitable for a SQL statement in MySQL format. This will replace single
+quotes ("'") and the backslash character by their backslash-escaped counterpart
+("\'" and "\\") inside each field. Please note that in MySQL configuration, the NO_BACKSLASH_ESCAPES
+mode must be turned off for this format to work (this is the default).
+
+.TP
+stdsql
+format the string suitable for a SQL statement that is to be sent to a standards-compliant
+sql server. This will replace single quotes ("'") by two single quotes ("''") inside each field.
+You must use stdsql together with MySQL if in MySQL configuration the NO_BACKSLASH_ESCAPES
+is turned on.
+.RE
+
+Either the
+.B sql
+or
+.B stdsql
+option
+.B MUST
+be specified when a template is used for writing to a database,
+otherwise injection might occur. Please note that due to the unfortunate fact
+that several vendors have violated the sql standard and introduced their own
+escape methods, it is impossible to have a single option doing all the work.
+So you yourself must make sure you are using the right format.
+.B If you choose the wrong one, you are still vulnerable to sql injection.
+
+Please note that the database writer *checks* that the sql option is present
+in the template. If it is not present, the write database action is disabled.
+This is to guard you against accidental forgetting it and then becoming
+vulnerable to SQL injection. The sql option can also be useful with files -
+especially if you want to import them into a database on another machine for
+performance reasons. However, do NOT use it if you do not have a real need for
+it - among others, it takes some toll on the processing time. Not much, but on
+a really busy system you might notice it ;)
+
+The default template for the write to database action has the sql option set.
+
+.SS Template examples
+Please note that the samples are split across multiple lines. A template MUST
+NOT actually be split across multiple lines.
+
+A template that resembles traditional syslogd file output:
+.sp
+.RS
+$template TraditionalFormat,"%timegenerated% %HOSTNAME%
+.sp 0
+%syslogtag%%msg:::drop-last-lf%\\n"
+.RE
+
+A template that tells you a little more about the message:
+.sp
+.RS
+$template precise,"%syslogpriority%,%syslogfacility%,%timegenerated%,%HOSTNAME%,
+.sp 0
+%syslogtag%,%msg%\\n"
+.RE
+
+A template for RFC 3164 format:
+.sp
+.RS
+$template RFC3164fmt,"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%"
+.RE
+
+A template for the format traditionally used for user messages:
+.sp
+.RS
+$template usermsg," XXXX%syslogtag%%msg%\\n\\r"
+.RE
+
+And a template with the traditional wall-message format:
+.sp
+.RS
+$template wallmsg,"\\r\\n\\7Message from syslogd@%HOSTNAME% at %timegenerated%"
+.RE
+
+.B A template that can be used for writing to a database (please note the SQL template option)
+.sp
+.RS
+.ad l
+$template MySQLInsert,"insert iut, message, receivedat values
+('%iut%', '%msg:::UPPERCASE%', '%timegenerated:::date-mysql%')
+into systemevents\\r\\n", SQL
+
+NOTE 1: This template is embedded into core application under name
+.B StdDBFmt
+, so you don't need to define it.
+.sp
+NOTE 2: You have to have MySQL module installed to use this template.
+.ad
+.RE
+
+.SH OUTPUT CHANNELS
+
+Output Channels are a new concept first introduced in rsyslog 0.9.0. As of this writing,
+it is most likely that they will be replaced by something different in the future.
+So if you use them, be prepared to change you configuration file syntax when you upgrade
+to a later release.
+
+Output channels are defined via an $outchannel directive. It's syntax is as follows:
+.sp
+.RS
+.B $outchannel name,file-name,max-size,action-on-max-size
+.RE
+
+name is the name of the output channel (not the file), file-name is the file name to be
+written to, max-size the maximum allowed size and action-on-max-size a command to be issued
+when the max size is reached. This command always has exactly one parameter. The binary is
+that part of action-on-max-size before the first space, its parameter is everything behind
+that space.
+
+Keep in mind that $outchannel just defines a channel with "name". It does not activate it.
+To do so, you must use a selector line (see below). That selector line includes the channel
+name plus ":omfile:$" in front of it. A sample might be:
+.sp
+.RS
+*.* :omfile:$mychannel
+.RE
+
+.SH PROPERTY REPLACER
+The property replacer is a core component in rsyslogd's output system. A syslog message has
+a number of well-defined properties (see below). Each of this properties can be accessed and
+manipulated by the property replacer. With it, it is easy to use only part of a property value
+or manipulate the value, e.g. by converting all characters to lower case.
+
+.SS Accessing Properties
+Syslog message properties are used inside templates. They are accessed by putting them between
+percent signs. Properties can be modified by the property replacer. The full syntax is as follows:
+.sp
+.RS
+.B %propname:fromChar:toChar:options%
+.RE
+
+propname is the name of the property to access.
+.B It is case-sensitive.
+
+.SS Available Properties
+.TP
+.B msg
+the MSG part of the message (aka "the message" ;))
+.TP
+.B rawmsg
+the message exactly as it was received from the socket. Should be useful for debugging.
+.TP
+.B HOSTNAME
+hostname from the message
+.TP
+.B FROMHOST
+hostname of the system the message was received from (in a relay chain, this is the system immediately
+in front of us and not necessarily the original sender)
+.TP
+.B syslogtag
+TAG from the message
+.TP
+.B programname
+the "static" part of the tag, as defined by BSD syslogd. For example, when TAG is "named[12345]",
+programname is "named".
+.TP
+.B PRI
+PRI part of the message - undecoded (single value)
+.TP
+.B PRI-text
+the PRI part of the message in a textual form (e.g. "syslog.info")
+.TP
+.B IUT
+the monitorware InfoUnitType - used when talking to a MonitorWare backend (also for phpLogCon)
+.TP
+.B syslogfacility
+the facility from the message - in numerical form
+.TP
+.B syslogfacility-text
+the facility from the message - in text form
+.TP
+.B syslogseverity
+severity from the message - in numerical form
+.TP
+.B syslogseverity-text
+severity from the message - in text form
+.TP
+.B timegenerated
+timestamp when the message was RECEIVED. Always in high resolution
+.TP
+.B timereported
+timestamp from the message. Resolution depends on what was provided in the message (in most cases, only seconds)
+.TP
+.B TIMESTAMP
+alias for timereported
+.TP
+.B PROTOCOL-VERSION
+The contents of the PROTOCOL-VERSION field from IETF draft draft-ietf-syslog-protocol
+.TP
+.B STRUCTURED-DATA
+The contents of the STRUCTURED-DATA field from IETF draft draft-ietf-syslog-protocol
+.TP
+.B APP-NAME
+The contents of the APP-NAME field from IETF draft draft-ietf-syslog-protocol
+.TP
+.B PROCID
+The contents of the PROCID field from IETF draft draft-ietf-syslog-protocol
+.TP
+.B MSGID
+The contents of the MSGID field from IETF draft draft-ietf-syslog-protocol
+.TP
+.B $NOW
+The current date stamp in the format YYYY-MM-DD
+.TP
+.B $YEAR
+The current year (4-digit)
+.TP
+.B $MONTH
+The current month (2-digit)
+.TP
+.B $DAY
+The current day of the month (2-digit)
+.TP
+.B $HOUR
+The current hour in military (24 hour) time (2-digit)
+.TP
+.B $MINUTE
+The current minute (2-digit)
+
+.P
+Properties starting with a $-sign are so-called system properties. These do NOT stem from the
+message but are rather internally-generated.
+
+.SS Character Positions
+FromChar and toChar are used to build substrings. They specify the offset within the string that
+should be copied. Offset counting starts at 1, so if you need to obtain the first 2 characters of
+the message text, you can use this syntax: "%msg:1:2%". If you do not wish to specify from and to,
+but you want to specify options, you still need to include the colons. For example, if you would
+like to convert the full message text to lower case, use "%msg:::lowercase%". If you would like to
+extract from a position until the end of the string, you can place a dollar-sign ("$") in toChar
+(e.g. %msg:10:$%, which will extract from position 10 to the end of the string).
+
+There is also support for
+.B regular expressions.
+To use them, you need to place a "R" into FromChar.
+This tells rsyslog that a regular expression instead of position-based extraction is desired. The
+actual regular expression
+.B must
+then be provided in toChar. The regular expression must be followed
+by the string "--end". It denotes the end of the regular expression and will not become part of it.
+If you are using regular expressions, the property replacer will return the part of the property text
+that matches the regular expression. An example for a property replacer sequence with a regular
+expression is: "%msg:R:.*Sev:. \\(.*\\) \\[.*--end%"
+
+Also, extraction can be done based on so-called "fields". To do so, place a "F" into FromChar. A field
+in its current definition is anything that is delimited by a delimiter character. The delimiter by
+default is TAB (US-ASCII value 9). However, if can be changed to any other US-ASCII character by
+specifying a comma and the decimal US-ASCII value of the delimiter immediately after the "F". For example,
+to use comma (",") as a delimiter, use this field specifier: "F,44". If your syslog data is delimited,
+this is a quicker way to extract than via regular expressions (actually, a *much* quicker way). Field
+counting starts at 1. Field zero is accepted, but will always lead to a "field not found" error. The same
+happens if a field number higher than the number of fields in the property is requested. The field number
+must be placed in the "ToChar" parameter. An example where the 3rd field (delimited by TAB) from the msg
+property is extracted is as follows: "%msg:F:3%". The same example with semicolon as delimiter is
+"%msg:F,59:3%".
+
+Please note that the special characters "F" and "R" are case-sensitive. Only upper case works, lower case
+will return an error. There are no white spaces permitted inside the sequence (that will lead to error
+messages and will NOT provide the intended result).
+
+.SS Property Options
+Property options are case-insensitive. Currently, the following options are defined:
+.TP
+uppercase
+convert property to lowercase only
+.TP
+lowercase
+convert property text to uppercase only
+.TP
+drop-last-lf
+The last LF in the message (if any), is dropped. Especially useful for PIX.
+.TP
+date-mysql
+format as mysql date
+.TP
+date-rfc3164
+format as RFC 3164 date
+.TP
+date-rfc3339
+format as RFC 3339 date
+.TP
+escape-cc
+replace control characters (ASCII value 127 and values less then 32) with an escape sequence. The sequence is "#<charval>" where charval is the 3-digit decimal value of the control character. For example, a tabulator would be replaced by "#009".
+.TP
+space-cc
+replace control characters by spaces
+.TP
+drop-cc
+drop control characters - the resulting string will neither contain control characters, escape sequences nor any other replacement character like space.
+
+.SH QUEUED OPERATIONS
+Rsyslogd supports queued operations to handle offline outputs
+(like remote syslogd's or database servers being down). When running in
+queued mode, rsyslogd buffers messages to memory and optionally to disk
+(on an as-needed basis). Queues survive rsyslogd restarts.
+
+It is highly suggested to use remote forwarding and database writing
+in queued mode, only.
+
+To learn more about queued operations, see the HTML documentation.
+
+.SH FILES
+.PD 0
+.TP
+.I /etc/rsyslog.conf
+Configuration file for
+.B rsyslogd
+
+.SH SEE ALSO
+.BR rsyslogd (8),
+.BR logger (1),
+.BR syslog (3)
+
+The complete documentation can be found in the doc folder of the rsyslog distribution or online at
+
+.RS
+.B https://www.rsyslog.com/doc/
+
+.RE
+Please note that the man page reflects only a subset of the configuration options. Be sure to read
+the HTML documentation for all features and details. This is especially vital if you plan to set
+up a more-then-extremely-simple system.
+
+.SH AUTHORS
+.B rsyslogd
+is taken from sysklogd sources, which have been heavily modified
+by Rainer Gerhards (rgerhards@adiscon.com) and others.
diff --git a/tools/rsyslogd.8 b/tools/rsyslogd.8
new file mode 100644
index 0000000..ce69c36
--- /dev/null
+++ b/tools/rsyslogd.8
@@ -0,0 +1,320 @@
+.\" Copyright 2004-2014 Rainer Gerhards and Adiscon for the rsyslog modifications
+.\" May be distributed under the GNU General Public License
+.\"
+.TH RSYSLOGD 8 "28 May 2014" "Version 8.1905.0" "Linux System Administration"
+.SH NAME
+rsyslogd \- reliable and extended syslogd
+.SH SYNOPSIS
+.B rsyslogd
+.RB [ " \-d " ]
+.RB [ " \-D " ]
+.RB [ " \-f "
+.I config file
+]
+.RB [ " \-i "
+.I pid file
+]
+.RB [ " \-n " ]
+.RB [ " \-N "
+.I level
+]
+.RB [ " \-o "
+.I fullconf
+]
+.RB [ " \-C " ]
+.RB [ " \-v " ]
+.LP
+.SH DESCRIPTION
+.B Rsyslogd
+is a system utility providing support for message logging.
+Support of both internet and
+unix domain sockets enables this utility to support both local
+and remote logging.
+
+.B Note that this version of rsyslog ships with extensive documentation in HTML format.
+This is provided in the ./doc subdirectory and probably
+in a separate package if you installed rsyslog via a packaging system.
+To use rsyslog's advanced features, you
+.B need
+to look at the HTML documentation, because the man pages only covers
+basic aspects of operation.
+.B For details and configuration examples, see the rsyslog.conf (5)
+.B man page and the online documentation at https://www.rsyslog.com/doc/
+
+.BR Rsyslogd (8)
+is derived from the sysklogd package which in turn is derived from the
+stock BSD sources.
+
+.B Rsyslogd
+provides a kind of logging that many modern programs use. Every logged
+message contains at least a time and a hostname field, normally a
+program name field, too, but that depends on how trusty the logging
+program is. The rsyslog package supports free definition of output formats
+via templates. It also supports precise timestamps and writing directly
+to databases. If the database option is used, tools like phpLogCon can
+be used to view the log data.
+
+While the
+.B rsyslogd
+sources have been heavily modified a couple of notes
+are in order. First of all there has been a systematic attempt to
+ensure that rsyslogd follows its default, standard BSD behavior. Of course,
+some configuration file changes are necessary in order to support the
+template system. However, rsyslogd should be able to use a standard
+syslog.conf and act like the original syslogd. However, an original syslogd
+will not work correctly with a rsyslog-enhanced configuration file. At
+best, it will generate funny looking file names.
+The second important concept to note is that this version of rsyslogd
+interacts transparently with the version of syslog found in the
+standard libraries. If a binary linked to the standard shared
+libraries fails to function correctly we would like an example of the
+anomalous behavior.
+
+The main configuration file
+.I /etc/rsyslog.conf
+or an alternative file, given with the
+.B "\-f"
+option, is read at startup. Any lines that begin with the hash mark
+(``#'') and empty lines are ignored. If an error occurs during parsing
+the error element is ignored. It is tried to parse the rest of the line.
+
+.LP
+.SH OPTIONS
+.TP
+.B "\-D"
+Runs the Bison config parser in debug mode. This may help when hard to find
+syntax errors are reported. Please note that the output generated is deeply
+technical and originally targeted towards developers.
+.TP
+.B "\-d"
+Turns on debug mode. See the DEBUGGING section for more information.
+.TP
+.BI "\-f " "config file"
+Specify an alternative configuration file instead of
+.IR /etc/rsyslog.conf ","
+which is the default.
+.TP
+.BI "\-i " "pid file"
+Specify an alternative pid file instead of the default one.
+This option must be used if multiple instances of rsyslogd should
+run on a single machine. To disable writing a pid file, use
+the reserved name "NONE" (all upper case!), so "-iNONE".
+.TP
+.B "\-n"
+Avoid auto-backgrounding. This is needed especially if the
+.B rsyslogd
+is started and controlled by
+.BR init (8).
+.TP
+.B "\-N " "level"
+Do a config check. Do NOT run in regular mode, just check configuration
+file correctness.
+This option is meant to verify a config file. To do so, run rsyslogd
+interactively in foreground, specifying -f <config-file> and -N level.
+The level argument modifies behaviour. Currently, 0 is the same as
+not specifying the -N option at all (so this makes limited sense) and
+1 actually activates the code. Later, higher levels will mean more
+verbosity (this is a forward-compatibility option).
+.TP
+.B "\-o " "fullconf"
+Generates a consolidated config file
+.I fullconf
+that contains all of rsyslog's configuration in a single file. Include
+files are exploded into that file in exactly the way rsyslog sees them.
+This option is useful for troubleshooting, especially if problems with
+the order of action processing is suspected. It may also be used to
+check for "unexepectedly" included config content.
+.TP
+.BI "\-C"
+This prevents rsyslogd from changing to the root directory. This
+is almost never a good idea in production use. This option was introduced
+in support of the internal testbed.
+.TP
+.B "\-v"
+Print version and exit.
+.LP
+.SH SIGNALS
+.B Rsyslogd
+reacts to a set of signals. You may easily send a signal to
+.B rsyslogd
+using the following:
+.IP
+.nf
+kill -SIGNAL $(cat /var/run/rsyslogd.pid)
+.fi
+.PP
+Note that -SIGNAL must be replaced with the actual signal
+you are trying to send, e.g. with HUP. So it then becomes:
+.IP
+.nf
+kill -HUP $(cat /var/run/rsyslogd.pid)
+.fi
+.PP
+.TP
+.B HUP
+This lets
+.B rsyslogd
+perform close all open files.
+.TP
+.B TERM ", " INT ", " QUIT
+.B Rsyslogd
+will die.
+.TP
+.B USR1
+Switch debugging on/off. This option can only be used if
+.B rsyslogd
+is started with the
+.B "\-d"
+debug option.
+.TP
+.B CHLD
+Wait for children if some were born, because of wall'ing messages.
+.LP
+.SH SECURITY THREATS
+There is the potential for the rsyslogd daemon to be
+used as a conduit for a denial of service attack.
+A rogue program(mer) could very easily flood the rsyslogd daemon with
+syslog messages resulting in the log files consuming all the remaining
+space on the filesystem. Activating logging over the inet domain
+sockets will of course expose a system to risks outside of programs or
+individuals on the local machine.
+
+There are a number of methods of protecting a machine:
+.IP 1.
+Implement kernel firewalling to limit which hosts or networks have
+access to the 514/UDP socket.
+.IP 2.
+Logging can be directed to an isolated or non-root filesystem which,
+if filled, will not impair the machine.
+.IP 3.
+The ext2 filesystem can be used which can be configured to limit a
+certain percentage of a filesystem to usage by root only. \fBNOTE\fP
+that this will require rsyslogd to be run as a non-root process.
+\fBALSO NOTE\fP that this will prevent usage of remote logging on the default port since
+rsyslogd will be unable to bind to the 514/UDP socket.
+.IP 4.
+Disabling inet domain sockets will limit risk to the local machine.
+.SS Message replay and spoofing
+If remote logging is enabled, messages can easily be spoofed and replayed.
+As the messages are transmitted in clear-text, an attacker might use
+the information obtained from the packets for malicious things. Also, an
+attacker might replay recorded messages or spoof a sender's IP address,
+which could lead to a wrong perception of system activity. These can
+be prevented by using GSS-API authentication and encryption. Be sure
+to think about syslog network security before enabling it.
+.LP
+.SH DEBUGGING
+When debugging is turned on using the
+.B "\-d"
+option,
+.B rsyslogd
+produces debugging information according to the
+.B RSYSLOG_DEBUG
+environment variable and the signals received. When run in foreground,
+the information is written to stdout. An additional output file can be
+specified using the
+.B RSYSLOG_DEBUGLOG
+environment variable.
+.SH FILES
+.PD 0
+.TP
+.I /etc/rsyslog.conf
+Configuration file for
+.BR rsyslogd .
+See
+.BR rsyslog.conf (5)
+for exact information.
+.TP
+.I /dev/log
+The Unix domain socket to from where local syslog messages are read.
+.TP
+.I /var/run/rsyslogd.pid
+The file containing the process id of
+.BR rsyslogd .
+.TP
+.I prefix/lib/rsyslog
+Default directory for
+.B rsyslogd
+modules. The
+.I prefix
+is specified during compilation (e.g. /usr/local).
+.SH ENVIRONMENT
+.TP
+.B RSYSLOG_DEBUG
+Controls runtime debug support. It contains an option string with the
+following options possible (all are case insensitive):
+
+.RS
+.IP Debug
+Turns on debugging and prevents forking. This is processed earlier
+in the startup than command line options (i.e. -d) and as such
+enables earlier debugging output. Mutually exclusive with DebugOnDemand.
+.IP DebugOnDemand
+Enables debugging but turns off debug output. The output can be toggled
+by sending SIGUSR1. Mutually exclusive with Debug.
+.IP LogFuncFlow
+Print out the logical flow of functions (entering and exiting them)
+.IP FileTrace
+Specifies which files to trace LogFuncFlow. If not set (the
+default), a LogFuncFlow trace is provided for all files. Set to
+limit it to the files specified.FileTrace may be specified multiple
+times, one file each (e.g. export RSYSLOG_DEBUG="LogFuncFlow
+FileTrace=vm.c FileTrace=expr.c"
+.IP PrintFuncDB
+Print the content of the debug function database whenever debug
+information is printed (e.g. abort case)!
+.IP PrintAllDebugInfoOnExit
+Print all debug information immediately before rsyslogd exits
+(currently not implemented!)
+.IP PrintMutexAction
+Print mutex action as it happens. Useful for finding deadlocks and
+such.
+.IP NoLogTimeStamp
+Do not prefix log lines with a timestamp (default is to do that).
+.IP NoStdOut
+Do not emit debug messages to stdout. If RSYSLOG_DEBUGLOG is not
+set, this means no messages will be displayed at all.
+.IP Help
+Display a very short list of commands - hopefully a life saver if
+you can't access the documentation...
+.RE
+
+.TP
+.B RSYSLOG_DEBUGLOG
+If set, writes (almost) all debug message to the specified log file
+in addition to stdout.
+.TP
+.B RSYSLOG_MODDIR
+Provides the default directory in which loadable modules reside.
+.PD
+.SH BUGS
+Please review the file BUGS for up-to-date information on known
+bugs and annoyances.
+.SH Further Information
+Please visit
+.BR https://www.rsyslog.com/doc/
+for additional information, tutorials and a support forum.
+.SH SEE ALSO
+.BR rsyslog.conf (5),
+.BR logger (1),
+.BR syslog (2),
+.BR syslog (3),
+.BR services (5),
+.BR savelog (8)
+.LP
+.SH COLLABORATORS
+.B rsyslogd
+is derived from sysklogd sources, which in turn was taken from
+the BSD sources. Special thanks to Greg Wettstein (greg@wind.enjellic.com)
+and Martin Schulze (joey@linux.de) for the fine sysklogd package.
+
+.PD 0
+.TP
+Rainer Gerhards
+.TP
+Adiscon GmbH
+.TP
+Grossrinderfeld, Germany
+.TP
+rgerhards@adiscon.com
+.PD
diff --git a/tools/rsyslogd.c b/tools/rsyslogd.c
new file mode 100644
index 0000000..d27a2a7
--- /dev/null
+++ b/tools/rsyslogd.c
@@ -0,0 +1,2362 @@
+/* This is the main rsyslogd file.
+ * It contains code * that is known to be validly under ASL 2.0,
+ * because it was either written from scratch by me (rgerhards) or
+ * contributors who agreed to ASL 2.0.
+ *
+ * Copyright 2004-2023 Rainer Gerhards and Adiscon
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef ENABLE_LIBLOGGING_STDLOG
+# include <liblogging/stdlog.h>
+#else
+# include <syslog.h>
+#endif
+#ifdef HAVE_LIBSYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+#ifdef ENABLE_LIBCAPNG
+ #include <cap-ng.h>
+#endif
+#if defined(HAVE_LINUX_CLOSE_RANGE_H)
+# include <linux/close_range.h>
+#endif
+
+#include "rsyslog.h"
+#include "wti.h"
+#include "ratelimit.h"
+#include "parser.h"
+#include "linkedlist.h"
+#include "ruleset.h"
+#include "action.h"
+#include "iminternal.h"
+#include "errmsg.h"
+#include "threads.h"
+#include "dnscache.h"
+#include "prop.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "glbl.h"
+#include "debug.h"
+#include "srUtils.h"
+#include "rsconf.h"
+#include "cfsysline.h"
+#include "datetime.h"
+#include "operatingstate.h"
+#include "dirty.h"
+#include "janitor.h"
+#include "parserif.h"
+
+/* some global vars we need to differentiate between environments,
+ * for TZ-related things see
+ * https://github.com/rsyslog/rsyslog/issues/2994
+ */
+static int runningInContainer = 0;
+#ifdef OS_LINUX
+static int emitTZWarning = 0;
+#else
+static int emitTZWarning = 1;
+#endif
+static pthread_t mainthread = 0;
+
+#if defined(_AIX)
+/* AIXPORT : start
+ * The following includes and declarations are for support of the System
+ * Resource Controller (SRC) .
+ */
+#include <sys/select.h>
+/* AIXPORT : start*/
+#define SRC_FD 13
+#define SRCMSG (sizeof(srcpacket))
+
+static void deinitAll(void);
+#include <spc.h>
+static struct srcreq srcpacket;
+int cont;
+struct srchdr *srchdr;
+char progname[128];
+
+
+/* Normally defined as locals in main
+ * But here since the functionality is split
+ * across multiple functions, we make it global
+ */
+static int rc;
+static socklen_t addrsz;
+static struct sockaddr srcaddr;
+int src_exists = TRUE;
+/* src end */
+
+/*
+ * SRC packet processing - .
+ */
+#define SRCMIN(a, b) (a < b) ? a : b
+void
+dosrcpacket(msgno, txt, len)
+ int msgno;
+ char *txt;
+ int len;
+{
+ struct srcrep reply;
+
+ reply.svrreply.rtncode = msgno;
+/* AIXPORT : srv was corrected to syslogd */
+ strcpy(reply.svrreply.objname, "syslogd");
+ snprintf(reply.svrreply.rtnmsg,
+ SRCMIN(sizeof(reply.svrreply.rtnmsg)-1, strlen(txt)), "%s", txt);
+ srchdr = srcrrqs((char *)&srcpacket);
+ srcsrpy(srchdr, (char *)&reply, len, cont);
+}
+
+#define AIX_SRC_EXISTS_IF if(!src_exists) {
+#define AIX_SRC_EXISTS_FI }
+
+static void aix_close_it(int i)
+{
+ if(src_exists) {
+ if(i != SRC_FD)
+ (void)close(i);
+ } else
+ close(i);
+}
+
+
+#else
+
+#define AIX_SRC_EXISTS_IF
+#define AIX_SRC_EXISTS_FI
+#define aix_close_it(x) close(x)
+#endif
+
+/* AIXPORT : end */
+
+
+DEFobjCurrIf(obj)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(parser)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(net)
+DEFobjCurrIf(rsconf)
+DEFobjCurrIf(module)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(glbl)
+
+extern int yydebug; /* interface to flex */
+
+
+/* forward definitions */
+void rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg);
+void rsyslogdDoDie(int sig);
+
+
+#ifndef PATH_PIDFILE
+#if defined(_AIX) /* AIXPORT : Add _AIX */
+# define PATH_PIDFILE "/etc/rsyslogd.pid"
+#else
+# define PATH_PIDFILE "/var/run/rsyslogd.pid"
+#endif /*_AIX*/
+#endif
+
+#ifndef PATH_CONFFILE
+# define PATH_CONFFILE "/etc/rsyslog.conf"
+#endif
+
+/* global data items */
+static pthread_mutex_t mutChildDied;
+static int bChildDied = 0;
+static pthread_mutex_t mutHadHUP;
+static int bHadHUP;
+static int doFork = 1; /* fork - run in daemon mode - read-only after startup */
+int bFinished = 0; /* used by termination signal handler, read-only except there
+ * is either 0 or the number of the signal that requested the
+ * termination.
+ */
+const char *PidFile = NULL;
+#define NO_PIDFILE "NONE"
+int iConfigVerify = 0; /* is this just a config verify run? */
+rsconf_t *ourConf = NULL; /* our config object */
+int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
+ratelimit_t *dflt_ratelimiter = NULL; /* ratelimiter for submits without explicit one */
+uchar *ConfFile = (uchar*) PATH_CONFFILE;
+int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
+ * If the main queue is either not yet ready or not running in
+ * queueing mode (mode DIRECT!), then this is set to 0.
+ */
+prop_t *pInternalInputName = NULL; /* there is only one global inputName for all internally-generated messages */
+ratelimit_t *internalMsg_ratelimiter = NULL; /* ratelimiter for rsyslog-own messages */
+int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
+
+static struct queuefilenames_s {
+ struct queuefilenames_s *next;
+ uchar *name;
+} *queuefilenames = NULL;
+
+
+static __attribute__((noreturn)) void
+rsyslogd_usage(void)
+{
+ fprintf(stderr, "usage: rsyslogd [options]\n"
+ "use \"man rsyslogd\" for details. To run rsyslog "
+ "interactively, use \"rsyslogd -n\"\n"
+ "to run it in debug mode use \"rsyslogd -dn\"\n"
+ "For further information see https://www.rsyslog.com/doc/\n");
+ exit(1); /* "good" exit - done to terminate usage() */
+}
+
+#ifndef HAVE_SETSID
+extern void untty(void); /* in syslogd.c, GPLv3 */
+static int
+setsid(void)
+{
+ untty();
+ return 0;
+}
+#endif
+
+/* helper for imdiag. Returns if HUP processing has been requested or
+ * is not yet finished. We know this is racy, but imdiag handles this
+ * part by repeating operations. The mutex look is primarily to force
+ * a memory barrier, so that we have a change to see changes already
+ * written, but not present in the core's cache.
+ * 2023-07-26 Rainer Gerhards
+ */
+int
+get_bHadHUP(void)
+{
+ pthread_mutex_lock(&mutHadHUP);
+ const int ret = bHadHUP;
+ pthread_mutex_unlock(&mutHadHUP);
+ /* note: at this point ret can already be invalid */
+ return ret;
+}
+
+/* we need a pointer to the conf, because in early startup stage we
+ * need to use loadConf, later on runConf.
+ */
+rsRetVal
+queryLocalHostname(rsconf_t *const pConf)
+{
+ uchar *LocalHostName = NULL;
+ uchar *LocalDomain = NULL;
+ uchar *LocalFQDNName;
+ DEFiRet;
+
+ CHKiRet(net.getLocalHostname(pConf, &LocalFQDNName));
+ uchar *dot = (uchar*) strstr((char*)LocalFQDNName, ".");
+ if(dot == NULL) {
+ CHKmalloc(LocalHostName = (uchar*) strdup((char*)LocalFQDNName));
+ CHKmalloc(LocalDomain = (uchar*)strdup(""));
+ } else {
+ const size_t lenhn = dot - LocalFQDNName;
+ CHKmalloc(LocalHostName = (uchar*) strndup((char*) LocalFQDNName, lenhn));
+ CHKmalloc(LocalDomain = (uchar*) strdup((char*) dot+1));
+ }
+
+ glbl.SetLocalFQDNName(LocalFQDNName);
+ glbl.SetLocalHostName(LocalHostName);
+ glbl.SetLocalDomain(LocalDomain);
+ glbl.GenerateLocalHostNameProperty();
+ LocalHostName = NULL; /* handed over */
+ LocalDomain = NULL; /* handed over */
+
+finalize_it:
+ free(LocalHostName);
+ free(LocalDomain);
+ RETiRet;
+}
+
+static rsRetVal
+writePidFile(void)
+{
+ FILE *fp;
+ DEFiRet;
+
+ const char *tmpPidFile;
+
+ if(!strcmp(PidFile, NO_PIDFILE)) {
+ FINALIZE;
+ }
+ if(asprintf((char **)&tmpPidFile, "%s.tmp", PidFile) == -1) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ if(tmpPidFile == NULL)
+ tmpPidFile = PidFile;
+ DBGPRINTF("rsyslogd: writing pidfile '%s'.\n", tmpPidFile);
+ if((fp = fopen((char*) tmpPidFile, "w")) == NULL) {
+ perror("rsyslogd: error writing pid file (creation stage)\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if(fprintf(fp, "%d", (int) glblGetOurPid()) < 0) {
+ LogError(errno, iRet, "rsyslog: error writing pid file");
+ }
+ fclose(fp);
+ if(tmpPidFile != PidFile) {
+ if(rename(tmpPidFile, PidFile) != 0) {
+ perror("rsyslogd: error writing pid file (rename stage)");
+ }
+ free((void*)tmpPidFile);
+ }
+finalize_it:
+ RETiRet;
+}
+
+static void
+clearPidFile(void)
+{
+ if(PidFile != NULL) {
+ if(strcmp(PidFile, NO_PIDFILE)) {
+ unlink(PidFile);
+ }
+ }
+}
+
+/* duplicate startup protection: check, based on pid file, if our instance
+ * is already running. This MUST be called before we write our own pid file.
+ */
+static rsRetVal
+checkStartupOK(void)
+{
+ FILE *fp = NULL;
+ DEFiRet;
+
+ DBGPRINTF("rsyslogd: checking if startup is ok, pidfile '%s'.\n", PidFile);
+
+ if(!strcmp(PidFile, NO_PIDFILE)) {
+ dbgprintf("no pid file shall be written, skipping check\n");
+ FINALIZE;
+ }
+
+ if((fp = fopen((char*) PidFile, "r")) == NULL)
+ FINALIZE; /* all well, no pid file yet */
+
+ int pf_pid;
+ if(fscanf(fp, "%d", &pf_pid) != 1) {
+ fprintf(stderr, "rsyslogd: error reading pid file, cannot start up\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ /* ok, we got a pid, let's check if the process is running */
+ const pid_t pid = (pid_t) pf_pid;
+ if(kill(pid, 0) == 0 || errno != ESRCH) {
+ fprintf(stderr, "rsyslogd: pidfile '%s' and pid %d already exist.\n"
+ "If you want to run multiple instances of rsyslog, you need "
+ "to specify\n"
+ "different pid files for them (-i option).\n",
+ PidFile, (int) getpid());
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ if(fp != NULL)
+ fclose(fp);
+ RETiRet;
+}
+
+
+
+/* note: this function is specific to OS'es which provide
+ * the ability to read open file descriptors via /proc.
+ * returns 0 - success, something else otherwise
+ */
+static int
+close_unneeded_open_files(const char *const procdir,
+ const int beginClose, const int parentPipeFD)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir(procdir);
+ if (dir == NULL) {
+ dbgprintf("closes unneeded files: opendir failed for %s\n", procdir);
+ return 1;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ const int fd = atoi(entry->d_name);
+ if(fd >= beginClose && (((fd != dbgGetDbglogFd()) && (fd != parentPipeFD)))) {
+ close(fd);
+ }
+ }
+
+ closedir(dir);
+ return 0;
+}
+
+/* prepares the background processes (if auto-backbrounding) for
+ * operation.
+ */
+static void
+prepareBackground(const int parentPipeFD)
+{
+ DBGPRINTF("rsyslogd: in child, finalizing initialization\n");
+
+ dbgTimeoutToStderr = 0; /* we loose stderr when backgrounding! */
+ int r = setsid();
+ if(r == -1) {
+ char err[1024];
+ char em[2048];
+ rs_strerror_r(errno, err, sizeof(err));
+ snprintf(em, sizeof(em)-1, "rsyslog: error "
+ "auto-backgrounding: %s\n", err);
+ dbgprintf("%s\n", em);
+ fprintf(stderr, "%s", em);
+ }
+
+ int beginClose = 3;
+
+#ifdef HAVE_LIBSYSTEMD
+ /* running under systemd? Then we must make sure we "forward" any
+ * fds passed by it (adjust the pid).
+ */
+ if(sd_booted()) {
+ const char *lstnPid = getenv("LISTEN_PID");
+ if(lstnPid != NULL) {
+ char szBuf[64];
+ const int lstnPidI = atoi(lstnPid);
+ snprintf(szBuf, sizeof(szBuf), "%d", lstnPidI);
+ if(!strcmp(szBuf, lstnPid) && lstnPidI == getppid()) {
+ snprintf(szBuf, sizeof(szBuf), "%d", (int) getpid());
+ setenv("LISTEN_PID", szBuf, 1);
+ /* ensure we do not close what systemd provided */
+ const int nFds = sd_listen_fds(0);
+ if(nFds > 0) {
+ beginClose = SD_LISTEN_FDS_START + nFds;
+ }
+ }
+ }
+ }
+#endif
+
+ /* close unnecessary open files - first try to use /proc file system,
+ * if that is not possible iterate through all potentially open file
+ * descriptors. This can be lenghty, but in practice /proc should work
+ * for almost all current systems, and the fallback is primarily for
+ * Solaris and AIX, where we do expect a decent max numbers of fds.
+ */
+ close(0); /* always close stdin, we do not need it */
+
+ /* try Linux, Cygwin, NetBSD */
+ if(close_unneeded_open_files("/proc/self/fd", beginClose, parentPipeFD) != 0) {
+ /* try MacOS, FreeBSD */
+ if(close_unneeded_open_files("/proc/fd", beginClose, parentPipeFD) != 0) {
+ /* did not work out, so let's close everything... */
+ int endClose = (parentPipeFD > dbgGetDbglogFd()) ? parentPipeFD : dbgGetDbglogFd();
+ for(int i = beginClose ; i <= endClose ; ++i) {
+ if((i != dbgGetDbglogFd()) && (i != parentPipeFD)) {
+ aix_close_it(i); /* AIXPORT */
+ }
+ }
+ beginClose = endClose + 1;
+ endClose = getdtablesize();
+#if defined(HAVE_CLOSE_RANGE)
+ if(close_range(beginClose, endClose, 0) !=0) {
+ dbgprintf("errno %d after close_range(), fallback to loop\n", errno);
+#endif
+ for(int i = beginClose ; i <= endClose ; ++i) {
+ aix_close_it(i); /* AIXPORT */
+ }
+#if defined(HAVE_CLOSE_RANGE)
+ }
+#endif
+ }
+ }
+ seedRandomNumberForChild();
+}
+
+/* This is called when rsyslog is set to auto-background itself. If so, a child
+ * is forked and the parent waits until it is initialized.
+ * The parent never returns from this function, only this happens for the child.
+ * So if it returns, you know you are in the child.
+ * return: file descriptor to which the child needs to write an "OK" or error
+ * message.
+ */
+static int
+forkRsyslog(void)
+{
+ int pipefd[2];
+ pid_t cpid;
+ char err[1024];
+ char msgBuf[4096];
+
+ dbgprintf("rsyslogd: parent ready for forking\n");
+ if(pipe(pipefd) == -1) {
+ perror("error creating rsyslog \"fork pipe\" - terminating");
+ exit(1);
+ }
+ AIX_SRC_EXISTS_IF /* AIXPORT */
+ cpid = fork();
+ if(cpid == -1) {
+ perror("error forking rsyslogd process - terminating");
+ exit(1);
+ }
+ AIX_SRC_EXISTS_FI /* AIXPORT */
+
+ if(cpid == 0) {
+ prepareBackground(pipefd[1]);
+ close(pipefd[0]);
+ return pipefd[1];
+ }
+
+ /* we are now in the parent. All we need to do here is wait for the
+ * startup message, emit it (if necessary) and then terminate.
+ */
+ close(pipefd[1]);
+ dbgprintf("rsyslogd: parent waiting up to 60 seconds to read startup message\n");
+
+ fd_set rfds;
+ struct timeval tv;
+ int retval;
+
+ FD_ZERO(&rfds);
+ FD_SET(pipefd[0], &rfds);
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+
+ retval = select(pipefd[0]+1, &rfds, NULL, NULL, &tv);
+ if(retval == -1)
+ rs_strerror_r(errno, err, sizeof(err));
+ else
+ strcpy(err, "OK");
+ dbgprintf("rsyslogd: select() returns %d: %s\n", retval, err);
+ if(retval == -1) {
+ fprintf(stderr,"rsyslog startup failure, select() failed: %s\n", err);
+ exit(1);
+ } else if(retval == 0) {
+ fprintf(stderr,"rsyslog startup failure, child did not "
+ "respond within startup timeout (60 seconds)\n");
+ exit(1);
+ }
+
+ int nRead = read(pipefd[0], msgBuf, sizeof(msgBuf));
+ if(nRead > 0) {
+ msgBuf[nRead] = '\0';
+ } else {
+ rs_strerror_r(errno, err, sizeof(err));
+ snprintf(msgBuf, sizeof(msgBuf)-1, "error reading \"fork pipe\": %s",
+ err);
+ }
+ if(strcmp(msgBuf, "OK")) {
+ dbgprintf("rsyslog parent startup failure: %s\n", msgBuf);
+ fprintf(stderr,"rsyslog startup failure: %s\n", msgBuf);
+ exit(1);
+ }
+ close(pipefd[0]);
+ dbgprintf("rsyslogd: parent terminates after successful child startup\n");
+ exit(0);
+}
+
+/* startup processing: this signals the waiting parent that the child is ready
+ * and the parent may terminate.
+ */
+static void
+tellChildReady(const int pipefd, const char *const msg)
+{
+ dbgprintf("rsyslogd: child signaling OK\n");
+ const int nWritten = write(pipefd, msg, strlen(msg));
+ dbgprintf("rsyslogd: child signalled OK, nWritten %d\n", (int) nWritten);
+ close(pipefd);
+ sleep(1);
+}
+
+/* print version and compile-time setting information */
+static void
+printVersion(void)
+{
+ printf("rsyslogd " VERSION " (aka %4d.%2.2d) compiled with:\n",
+ 2000 + VERSION_YEAR, VERSION_MONTH);
+ printf("\tPLATFORM:\t\t\t\t%s\n", PLATFORM_ID);
+ printf("\tPLATFORM (lsb_release -d):\t\t%s\n", PLATFORM_ID_LSB);
+#ifdef FEATURE_REGEXP
+ printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
+#else
+ printf("\tFEATURE_REGEXP:\t\t\t\tNo\n");
+#endif
+#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
+ printf("\tGSSAPI Kerberos 5 support:\t\tYes\n");
+#else
+ printf("\tGSSAPI Kerberos 5 support:\t\tNo\n");
+#endif
+#ifndef NDEBUG
+ printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
+#else
+ printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
+#endif
+#ifdef HAVE_ATOMIC_BUILTINS
+ printf("\t32bit Atomic operations supported:\tYes\n");
+#else
+ printf("\t32bit Atomic operations supported:\tNo\n");
+#endif
+#ifdef HAVE_ATOMIC_BUILTINS64
+ printf("\t64bit Atomic operations supported:\tYes\n");
+#else
+ printf("\t64bit Atomic operations supported:\tNo\n");
+#endif
+#ifdef HAVE_JEMALLOC
+ printf("\tmemory allocator:\t\t\tjemalloc\n");
+#else
+ printf("\tmemory allocator:\t\t\tsystem default\n");
+#endif
+#ifdef RTINST
+ printf("\tRuntime Instrumentation (slow code):\tYes\n");
+#else
+ printf("\tRuntime Instrumentation (slow code):\tNo\n");
+#endif
+#ifdef USE_LIBUUID
+ printf("\tuuid support:\t\t\t\tYes\n");
+#else
+ printf("\tuuid support:\t\t\t\tNo\n");
+#endif
+#ifdef HAVE_LIBSYSTEMD
+ printf("\tsystemd support:\t\t\tYes\n");
+#else
+ printf("\tsystemd support:\t\t\tNo\n");
+#endif
+ /* we keep the following message to so that users don't need
+ * to wonder.
+ */
+ printf("\tConfig file:\t\t\t\t" PATH_CONFFILE "\n");
+ printf("\tPID file:\t\t\t\t" PATH_PIDFILE "%s\n", PATH_PIDFILE[0]!='/'?
+ "(relative to global workingdirectory)":"");
+ printf("\tNumber of Bits in RainerScript integers: 64\n");
+ printf("\nSee https://www.rsyslog.com for more information.\n");
+}
+
+static rsRetVal
+rsyslogd_InitStdRatelimiters(void)
+{
+ DEFiRet;
+ CHKiRet(ratelimitNew(&dflt_ratelimiter, "rsyslogd", "dflt"));
+ CHKiRet(ratelimitNew(&internalMsg_ratelimiter, "rsyslogd", "internal_messages"));
+ ratelimitSetThreadSafe(internalMsg_ratelimiter);
+ ratelimitSetLinuxLike(internalMsg_ratelimiter,
+ loadConf->globals.intMsgRateLimitItv, loadConf->globals.intMsgRateLimitBurst);
+ /* TODO: make internalMsg ratelimit settings configurable */
+finalize_it:
+ RETiRet;
+}
+
+
+/* Method to initialize all global classes and use the objects that we need.
+ * rgerhards, 2008-01-04
+ * rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime
+ */
+static rsRetVal
+rsyslogd_InitGlobalClasses(void)
+{
+ DEFiRet;
+ const char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */
+
+ /* Intialize the runtime system */
+ pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */
+ CHKiRet(rsrtInit(&pErrObj, &obj));
+ rsrtSetErrLogger(rsyslogd_submitErrMsg);
+
+ /* Now tell the system which classes we need ourselfs */
+ pErrObj = "glbl";
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ pErrObj = "module";
+ CHKiRet(objUse(module, CORE_COMPONENT));
+ pErrObj = "datetime";
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ pErrObj = "ruleset";
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ pErrObj = "prop";
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ pErrObj = "parser";
+ CHKiRet(objUse(parser, CORE_COMPONENT));
+ pErrObj = "rsconf";
+ CHKiRet(objUse(rsconf, CORE_COMPONENT));
+
+ /* intialize some dummy classes that are not part of the runtime */
+ pErrObj = "action";
+ CHKiRet(actionClassInit());
+ pErrObj = "template";
+ CHKiRet(templateInit());
+
+ /* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
+ pErrObj = "net";
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+
+ dnscacheInit();
+ initRainerscript();
+ ratelimitModInit();
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInternalInputName));
+ CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd") - 1));
+ CHKiRet(prop.ConstructFinalize(pInternalInputName));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* we know we are inside the init sequence, so we can safely emit
+ * messages to stderr. -- rgerhards, 2008-04-02
+ */
+ fprintf(stderr, "Error during class init for object '%s' - failing...\n", pErrObj);
+ fprintf(stderr, "rsyslogd initialization failed - global classes could not be initialized.\n"
+ "Did you do a \"make install\"?\n"
+ "Suggested action: run rsyslogd with -d -n options to see what exactly "
+ "fails.\n");
+ }
+
+ RETiRet;
+}
+
+/* preprocess a batch of messages, that is ready them for actual processing. This is done
+ * as a first stage and totally in parallel to any other worker active in the system. So
+ * it helps us keep up the overall concurrency level.
+ * rgerhards, 2010-06-09
+ */
+static rsRetVal
+preprocessBatch(batch_t *pBatch, int *pbShutdownImmediate) {
+ prop_t *ip;
+ prop_t *fqdn;
+ prop_t *localName;
+ int bIsPermitted;
+ smsg_t *pMsg;
+ int i;
+ rsRetVal localRet;
+ DEFiRet;
+
+ for(i = 0 ; i < pBatch->nElem && !*pbShutdownImmediate ; i++) {
+ pMsg = pBatch->pElem[i].pMsg;
+ if((pMsg->msgFlags & NEEDS_ACLCHK_U) != 0) {
+ DBGPRINTF("msgConsumer: UDP ACL must be checked for message (hostname-based)\n");
+ if(net.cvthname(pMsg->rcvFrom.pfrominet, &localName, &fqdn, &ip) != RS_RET_OK)
+ continue;
+ bIsPermitted = net.isAllowedSender2((uchar*)"UDP",
+ (struct sockaddr *)pMsg->rcvFrom.pfrominet, (char*)propGetSzStr(fqdn), 1);
+ if(!bIsPermitted) {
+ DBGPRINTF("Message from '%s' discarded, not a permitted sender host\n",
+ propGetSzStr(fqdn));
+ pBatch->eltState[i] = BATCH_STATE_DISC;
+ } else {
+ /* save some of the info we obtained */
+ MsgSetRcvFrom(pMsg, localName);
+ CHKiRet(MsgSetRcvFromIP(pMsg, ip));
+ pMsg->msgFlags &= ~NEEDS_ACLCHK_U;
+ }
+ }
+ if((pMsg->msgFlags & NEEDS_PARSING) != 0) {
+ if((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK) {
+ DBGPRINTF("Message discarded, parsing error %d\n", localRet);
+ pBatch->eltState[i] = BATCH_STATE_DISC;
+ }
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* The consumer of dequeued messages. This function is called by the
+ * queue engine on dequeueing of a message. It runs on a SEPARATE
+ * THREAD. It receives an array of pointers, which it must iterate
+ * over. We do not do any further batching, as this is of no benefit
+ * for the main queue.
+ */
+static rsRetVal
+msgConsumer(void __attribute__((unused)) *notNeeded, batch_t *pBatch, wti_t *pWti)
+{
+ DEFiRet;
+ assert(pBatch != NULL);
+ preprocessBatch(pBatch, pWti->pbShutdownImmediate);
+ ruleset.ProcessBatch(pBatch, pWti);
+//TODO: the BATCH_STATE_COMM must be set somewhere down the road, but we
+//do not have this yet and so we emulate -- 2010-06-10
+int i;
+ for(i = 0 ; i < pBatch->nElem && !*pWti->pbShutdownImmediate ; i++) {
+ pBatch->eltState[i] = BATCH_STATE_COMM;
+ }
+ RETiRet;
+}
+
+
+/* create a main message queue, now also used for ruleset queues. This function
+ * needs to be moved to some other module, but it is considered acceptable for
+ * the time being (remember that we want to restructure config processing at large!).
+ * rgerhards, 2009-10-27
+ */
+rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName, struct nvlst *lst)
+{
+ struct queuefilenames_s *qfn;
+ uchar *qfname = NULL;
+ static int qfn_renamenum = 0;
+ uchar qfrenamebuf[1024];
+ DEFiRet;
+
+ /* create message queue */
+ CHKiRet_Hdlr(qqueueConstruct(ppQueue, ourConf->globals.mainQ.MainMsgQueType,
+ ourConf->globals.mainQ.iMainMsgQueueNumWorkers, ourConf->globals.mainQ.iMainMsgQueueSize, msgConsumer)) {
+ /* no queue is fatal, we need to give up in that case... */
+ LogError(0, iRet, "could not create (ruleset) main message queue"); \
+ }
+ /* name our main queue object (it's not fatal if it fails...) */
+ obj.SetName((obj_t*) (*ppQueue), pszQueueName);
+
+ if(lst == NULL) { /* use legacy parameters? */
+ /* ... set some properties ... */
+ # define setQPROP(func, directive, data) \
+ CHKiRet_Hdlr(func(*ppQueue, data)) { \
+ LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, " \
+ "running with default setting", iRet); \
+ }
+ # define setQPROPstr(func, directive, data) \
+ CHKiRet_Hdlr(func(*ppQueue, data, (data == NULL)? 0 : strlen((char*) data))) { \
+ LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, " \
+ "running with default setting", iRet); \
+ }
+
+ if(ourConf->globals.mainQ.pszMainMsgQFName != NULL) {
+ /* check if the queue file name is unique, else emit an error */
+ for(qfn = queuefilenames ; qfn != NULL ; qfn = qfn->next) {
+ dbgprintf("check queue file name '%s' vs '%s'\n", qfn->name,
+ ourConf->globals.mainQ.pszMainMsgQFName );
+ if(!ustrcmp(qfn->name, ourConf->globals.mainQ.pszMainMsgQFName)) {
+ snprintf((char*)qfrenamebuf, sizeof(qfrenamebuf), "%d-%s-%s",
+ ++qfn_renamenum, ourConf->globals.mainQ.pszMainMsgQFName,
+ (pszQueueName == NULL) ? "NONAME" : (char*)pszQueueName);
+ qfname = ustrdup(qfrenamebuf);
+ LogError(0, NO_ERRCODE, "Error: queue file name '%s' already in use "
+ " - using '%s' instead", ourConf->globals.mainQ.pszMainMsgQFName,
+ qfname);
+ break;
+ }
+ }
+ if(qfname == NULL)
+ qfname = ustrdup(ourConf->globals.mainQ.pszMainMsgQFName);
+ qfn = malloc(sizeof(struct queuefilenames_s));
+ qfn->name = qfname;
+ qfn->next = queuefilenames;
+ queuefilenames = qfn;
+ }
+
+ setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize",
+ ourConf->globals.mainQ.iMainMsgQueMaxFileSize);
+ setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace",
+ ourConf->globals.mainQ.iMainMsgQueMaxDiskSpace);
+ setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize",
+ ourConf->globals.mainQ.iMainMsgQueDeqBatchSize);
+ setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", qfname);
+ setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval",
+ ourConf->globals.mainQ.iMainMsgQPersistUpdCnt);
+ setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles",
+ ourConf->globals.mainQ.bMainMsgQSyncQeueFiles);
+ setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown",
+ ourConf->globals.mainQ.iMainMsgQtoQShutdown );
+ setQPROP(qqueueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion",
+ ourConf->globals.mainQ.iMainMsgQtoActShutdown);
+ setQPROP(qqueueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown",
+ ourConf->globals.mainQ.iMainMsgQtoWrkShutdown);
+ setQPROP(qqueueSettoEnq, "$MainMsgQueueTimeoutEnqueue", ourConf->globals.mainQ.iMainMsgQtoEnq);
+ setQPROP(qqueueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark",
+ ourConf->globals.mainQ.iMainMsgQHighWtrMark);
+ setQPROP(qqueueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark",
+ ourConf->globals.mainQ.iMainMsgQLowWtrMark);
+ setQPROP(qqueueSetiDiscardMrk, "$MainMsgQueueDiscardMark",
+ ourConf->globals.mainQ.iMainMsgQDiscardMark);
+ setQPROP(qqueueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity",
+ ourConf->globals.mainQ.iMainMsgQDiscardSeverity);
+ setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages",
+ ourConf->globals.mainQ.iMainMsgQWrkMinMsgs);
+ setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown",
+ ourConf->globals.mainQ.bMainMsgQSaveOnShutdown);
+ setQPROP(qqueueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown",
+ ourConf->globals.mainQ.iMainMsgQDeqSlowdown);
+ setQPROP(qqueueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin",
+ ourConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr);
+ setQPROP(qqueueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd",
+ ourConf->globals.mainQ.iMainMsgQueueDeqtWinToHr);
+
+ # undef setQPROP
+ # undef setQPROPstr
+ } else { /* use new style config! */
+ qqueueSetDefaultsRulesetQueue(*ppQueue);
+ qqueueApplyCnfParam(*ppQueue, lst);
+ }
+ qqueueCorrectParams(*ppQueue);
+
+ RETiRet;
+}
+
+rsRetVal
+startMainQueue(rsconf_t *cnf, qqueue_t *const pQueue)
+{
+ DEFiRet;
+ CHKiRet_Hdlr(qqueueStart(cnf, pQueue)) {
+ /* no queue is fatal, we need to give up in that case... */
+ LogError(0, iRet, "could not start (ruleset) main message queue");
+ if(runConf->globals.bAbortOnFailedQueueStartup) {
+ fprintf(stderr, "rsyslogd: could not start (ruleset) main message queue, "
+ "abortOnFailedQueueStartup is set, so we abort rsyslog now.\n");
+ fflush(stderr);
+ clearPidFile();
+ exit(1); /* "good" exit, this is intended here */
+ }
+ pQueue->qType = QUEUETYPE_DIRECT;
+ CHKiRet_Hdlr(qqueueStart(cnf, pQueue)) {
+ /* no queue is fatal, we need to give up in that case... */
+ LogError(0, iRet, "fatal error: could not even start queue in direct mode");
+ }
+ }
+ RETiRet;
+}
+
+
+/* this is a special function used to submit an error message. This
+ * function is also passed to the runtime library as the generic error
+ * message handler. -- rgerhards, 2008-04-17
+ */
+void
+rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg)
+{
+ if (glbl.GetGlobalInputTermState() == 1) {
+ /* After fork the stderr is unusable (dfltErrLogger uses is internally) */
+ if(!doFork)
+ dfltErrLogger(severity, iErr, msg);
+ } else {
+ logmsgInternal(iErr, LOG_SYSLOG|(severity & 0x07), msg, 0);
+ }
+}
+
+static inline rsRetVal
+submitMsgWithDfltRatelimiter(smsg_t *pMsg)
+{
+ return ratelimitAddMsg(dflt_ratelimiter, NULL, pMsg);
+}
+
+
+static void
+logmsgInternal_doWrite(smsg_t *pMsg)
+{
+ const int pri = getPRIi(pMsg);
+ if(pri % 8 <= runConf->globals.intMsgsSeverityFilter) {
+ if(runConf->globals.bProcessInternalMessages) {
+ submitMsg2(pMsg);
+ pMsg = NULL; /* msg obj handed over; do not destruct */
+ } else {
+ uchar *const msg = getMSG(pMsg);
+ #ifdef ENABLE_LIBLOGGING_STDLOG
+ /* the "emit only once" rate limiter is quick and dirty and not
+ * thread safe. However, that's no problem for the current intend
+ * and it is not justified to create more robust code for the
+ * functionality. -- rgerhards, 2018-05-14
+ */
+ static warnmsg_emitted = 0;
+ if(warnmsg_emitted == 0) {
+ stdlog_log(runConf->globals.stdlog_hdl, LOG_WARNING, "%s",
+ "RSYSLOG WARNING: liblogging-stdlog "
+ "functionality will go away soon. For details see "
+ "https://github.com/rsyslog/rsyslog/issues/2706");
+ warnmsg_emitted = 1;
+ }
+ stdlog_log(runConf->globals.stdlog_hdl, pri2sev(pri), "%s", (char*)msg);
+ #else
+ syslog(pri, "%s", msg);
+ #endif
+ }
+ }
+ if(pMsg != NULL) {
+ msgDestruct(&pMsg);
+ }
+}
+
+/* This function creates a log message object out of the provided
+ * message text and forwards it for logging.
+ */
+static rsRetVal
+logmsgInternalSubmit(const int iErr, const syslog_pri_t pri, const size_t lenMsg,
+ const char *__restrict__ const msg, int flags)
+{
+ uchar pszTag[33];
+ smsg_t *pMsg;
+ DEFiRet;
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetInputName(pMsg, pInternalInputName);
+ MsgSetRawMsg(pMsg, (char*)msg, lenMsg);
+ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP());
+ MsgSetMSGoffs(pMsg, 0);
+ /* check if we have an error code associated and, if so,
+ * adjust the tag. -- rgerhards, 2008-06-27
+ */
+ if(iErr == NO_ERRCODE) {
+ MsgSetTAG(pMsg, UCHAR_CONSTANT("rsyslogd:"), sizeof("rsyslogd:") - 1);
+ } else {
+ size_t len = snprintf((char*)pszTag, sizeof(pszTag), "rsyslogd%d:", iErr);
+ pszTag[32] = '\0'; /* just to make sure... */
+ MsgSetTAG(pMsg, pszTag, len);
+ }
+ flags |= INTERNAL_MSG;
+ pMsg->msgFlags = flags;
+ msgSetPRI(pMsg, pri);
+
+ iminternalAddMsg(pMsg);
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* rgerhards 2004-11-09: the following is a function that can be used
+ * to log a message orginating from the syslogd itself.
+ */
+rsRetVal
+logmsgInternal(int iErr, const syslog_pri_t pri, const uchar *const msg, int flags)
+{
+ size_t lenMsg;
+ unsigned i;
+ char *bufModMsg = NULL; /* buffer for modified message, should we need to modify */
+ DEFiRet;
+
+ /* we first do a path the remove control characters that may have accidently
+ * introduced (program error!). This costs performance, but we do not expect
+ * to be called very frequently in any case ;) -- rgerhards, 2013-12-19.
+ */
+ lenMsg = ustrlen(msg);
+ for(i = 0 ; i < lenMsg ; ++i) {
+ if(msg[i] < 0x20 || msg[i] == 0x7f) {
+ if(bufModMsg == NULL) {
+ CHKmalloc(bufModMsg = strdup((char*) msg));
+ }
+ bufModMsg[i] = ' ';
+ }
+ }
+
+ CHKiRet(logmsgInternalSubmit(iErr, pri, lenMsg,
+ (bufModMsg == NULL) ? (char*)msg : bufModMsg,
+ flags));
+
+ /* we now check if we should print internal messages out to stderr. This was
+ * suggested by HKS as a way to help people troubleshoot rsyslog configuration
+ * (by running it interactively. This makes an awful lot of sense, so I add
+ * it here. -- rgerhards, 2008-07-28
+ * Note that error messages can not be disabled during a config verify. This
+ * permits us to process unmodified config files which otherwise contain a
+ * supressor statement.
+ */
+ int emit_to_stderr = (ourConf == NULL) ? 1 : ourConf->globals.bErrMsgToStderr;
+ int emit_supress_msg = 0;
+ if(Debug == DEBUG_FULL || !doFork) {
+ emit_to_stderr = 1;
+ }
+ if(ourConf != NULL && ourConf->globals.maxErrMsgToStderr != -1) {
+ if(emit_to_stderr && ourConf->globals.maxErrMsgToStderr != -1 && ourConf->globals.maxErrMsgToStderr) {
+ --ourConf->globals.maxErrMsgToStderr;
+ if(ourConf->globals.maxErrMsgToStderr == 0)
+ emit_supress_msg = 1;
+ } else {
+ emit_to_stderr = 0;
+ }
+ }
+ if(emit_to_stderr || iConfigVerify) {
+ if(pri2sev(pri) == LOG_ERR)
+ fprintf(stderr, "rsyslogd: %s\n",
+ (bufModMsg == NULL) ? (char*)msg : bufModMsg);
+ }
+ if(emit_supress_msg) {
+ fprintf(stderr, "rsyslogd: configured max number of error messages "
+ "to stderr reached, further messages will not be output\n"
+ "Consider adjusting\n"
+ " global(errorMessagesToStderr.maxNumber=\"xx\")\n"
+ "if you want more.\n");
+ }
+
+finalize_it:
+ free(bufModMsg);
+ RETiRet;
+}
+
+rsRetVal
+submitMsg(smsg_t *pMsg)
+{
+ return submitMsgWithDfltRatelimiter(pMsg);
+}
+
+
+static rsRetVal ATTR_NONNULL()
+splitOversizeMessage(smsg_t *const pMsg)
+{
+ DEFiRet;
+ const char *rawmsg;
+ int nsegments;
+ int len_rawmsg;
+ const int maxlen = glblGetMaxLine(runConf);
+ ISOBJ_TYPE_assert(pMsg, msg);
+
+ getRawMsg(pMsg, (uchar**) &rawmsg, &len_rawmsg);
+ nsegments = len_rawmsg / maxlen;
+ const int len_last_segment = len_rawmsg % maxlen;
+ DBGPRINTF("splitting oversize message, size %d, segment size %d, "
+ "nsegments %d, bytes in last fragment %d\n",
+ len_rawmsg, maxlen, nsegments, len_last_segment);
+
+ smsg_t *pMsg_seg;
+
+ /* process full segments */
+ for(int i = 0 ; i < nsegments ; ++i) {
+ CHKmalloc(pMsg_seg = MsgDup(pMsg));
+ MsgSetRawMsg(pMsg_seg, rawmsg + (i * maxlen), maxlen);
+ submitMsg2(pMsg_seg);
+ }
+
+ /* if necessary, write partial last segment */
+ if(len_last_segment != 0) {
+ CHKmalloc(pMsg_seg = MsgDup(pMsg));
+ MsgSetRawMsg(pMsg_seg, rawmsg + (nsegments * maxlen), len_last_segment);
+ submitMsg2(pMsg_seg);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* submit a message to the main message queue. This is primarily
+ * a hook to prevent the need for callers to know about the main message queue
+ * rgerhards, 2008-02-13
+ */
+rsRetVal
+submitMsg2(smsg_t *pMsg)
+{
+ qqueue_t *pQueue;
+ ruleset_t *pRuleset;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pMsg, msg);
+
+ if(getRawMsgLen(pMsg) > glblGetMaxLine(runConf)){
+ uchar *rawmsg;
+ int dummy;
+ getRawMsg(pMsg, &rawmsg, &dummy);
+ if(glblReportOversizeMessage(runConf)) {
+ LogMsg(0, RS_RET_OVERSIZE_MSG, LOG_WARNING,
+ "message too long (%d) with configured size %d, begin of "
+ "message is: %.80s",
+ getRawMsgLen(pMsg), glblGetMaxLine(runConf), rawmsg);
+ }
+ writeOversizeMessageLog(pMsg);
+ if(glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Split) {
+ splitOversizeMessage(pMsg);
+ /* we have submitted the message segments recursively, so we
+ * can just deleted the original msg object and terminate.
+ */
+ msgDestruct(&pMsg);
+ FINALIZE;
+ } else if(glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Truncate) {
+ MsgTruncateToMaxSize(pMsg);
+ } else {
+ /* in "accept" mode, we do nothing, simply because "accept" means
+ * to use as-is.
+ */
+ assert(glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Accept);
+ }
+ }
+
+ pRuleset = MsgGetRuleset(pMsg);
+ pQueue = (pRuleset == NULL) ? runConf->pMsgQueue : ruleset.GetRulesetQueue(pRuleset);
+
+ /* if a plugin logs a message during shutdown, the queue may no longer exist */
+ if(pQueue == NULL) {
+ DBGPRINTF("submitMsg2() could not submit message - "
+ "queue does (no longer?) exist - ignored\n");
+ FINALIZE;
+ }
+
+ qqueueEnqMsg(pQueue, pMsg->flowCtlType, pMsg);
+
+finalize_it:
+ RETiRet;
+}
+
+/* submit multiple messages at once, very similar to submitMsg, just
+ * for multi_submit_t. All messages need to go into the SAME queue!
+ * rgerhards, 2009-06-16
+ */
+rsRetVal ATTR_NONNULL()
+multiSubmitMsg2(multi_submit_t *const pMultiSub)
+{
+ qqueue_t *pQueue;
+ ruleset_t *pRuleset;
+ DEFiRet;
+
+ if(pMultiSub->nElem == 0)
+ FINALIZE;
+
+ pRuleset = MsgGetRuleset(pMultiSub->ppMsgs[0]);
+ pQueue = (pRuleset == NULL) ? runConf->pMsgQueue : ruleset.GetRulesetQueue(pRuleset);
+
+ /* if a plugin logs a message during shutdown, the queue may no longer exist */
+ if(pQueue == NULL) {
+ DBGPRINTF("multiSubmitMsg() could not submit message - "
+ "queue does (no longer?) exist - ignored\n");
+ FINALIZE;
+ }
+
+ iRet = pQueue->MultiEnq(pQueue, pMultiSub);
+ pMultiSub->nElem = 0;
+
+finalize_it:
+ RETiRet;
+}
+rsRetVal
+multiSubmitMsg(multi_submit_t *pMultiSub) /* backward compat. level */
+{
+ return multiSubmitMsg2(pMultiSub);
+}
+
+
+/* flush multiSubmit, e.g. at end of read records */
+rsRetVal
+multiSubmitFlush(multi_submit_t *pMultiSub)
+{
+ DEFiRet;
+ if(pMultiSub->nElem > 0) {
+ iRet = multiSubmitMsg2(pMultiSub);
+ }
+ RETiRet;
+}
+
+
+/* some support for command line option parsing. Any non-trivial options must be
+ * buffered until the complete command line has been parsed. This is necessary to
+ * prevent dependencies between the options. That, in turn, means we need to have
+ * something that is capable of buffering options and there values. The follwing
+ * functions handle that.
+ * rgerhards, 2008-04-04
+ */
+typedef struct bufOpt {
+ struct bufOpt *pNext;
+ char optchar;
+ char *arg;
+} bufOpt_t;
+static bufOpt_t *bufOptRoot = NULL;
+static bufOpt_t *bufOptLast = NULL;
+
+/* add option buffer */
+static rsRetVal
+bufOptAdd(char opt, char *arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if((pBuf = malloc(sizeof(bufOpt_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pBuf->optchar = opt;
+ pBuf->arg = arg;
+ pBuf->pNext = NULL;
+
+ if(bufOptLast == NULL) {
+ bufOptRoot = pBuf; /* then there is also no root! */
+ } else {
+ bufOptLast->pNext = pBuf;
+ }
+ bufOptLast = pBuf;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* remove option buffer from top of list, return values and destruct buffer itself.
+ * returns RS_RET_END_OF_LINKEDLIST when no more options are present.
+ * (we use int *opt instead of char *opt to keep consistent with getopt())
+ */
+static rsRetVal
+bufOptRemove(int *opt, char **arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if(bufOptRoot == NULL)
+ ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST);
+ pBuf = bufOptRoot;
+
+ *opt = pBuf->optchar;
+ *arg = pBuf->arg;
+
+ bufOptRoot = pBuf->pNext;
+ free(pBuf);
+
+finalize_it:
+ RETiRet;
+}
+
+
+static void
+hdlr_sigttin_ou(void)
+{
+ /* this is just a dummy to care for our sigttin input
+ * module cancel interface and sigttou internal message
+ * notificaton/mainloop wakeup mechanism. The important
+ * point is that it actually does *NOTHING*.
+ */
+}
+
+static void
+hdlr_enable(int sig, void (*hdlr)())
+{
+ struct sigaction sigAct;
+ memset(&sigAct, 0, sizeof (sigAct));
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_handler = hdlr;
+ sigaction(sig, &sigAct, NULL);
+}
+
+static void
+hdlr_sighup(void)
+{
+ pthread_mutex_lock(&mutHadHUP);
+ bHadHUP = 1;
+ pthread_mutex_unlock(&mutHadHUP);
+ /* at least on FreeBSD we seem not to necessarily awake the main thread.
+ * So let's do it explicitely.
+ */
+ dbgprintf("awaking mainthread on HUP\n");
+ pthread_kill(mainthread, SIGTTIN);
+}
+
+static void
+hdlr_sigchld(void)
+{
+ pthread_mutex_lock(&mutChildDied);
+ bChildDied = 1;
+ pthread_mutex_unlock(&mutChildDied);
+}
+
+static void
+rsyslogdDebugSwitch(void)
+{
+ time_t tTime;
+ struct tm tp;
+
+ datetime.GetTime(&tTime);
+ localtime_r(&tTime, &tp);
+ if(debugging_on == 0) {
+ debugging_on = 1;
+ dbgprintf("\n");
+ dbgprintf("\n");
+ dbgprintf("********************************************************************************\n");
+ dbgprintf("Switching debugging_on to true at %2.2d:%2.2d:%2.2d\n",
+ tp.tm_hour, tp.tm_min, tp.tm_sec);
+ dbgprintf("********************************************************************************\n");
+ } else {
+ dbgprintf("********************************************************************************\n");
+ dbgprintf("Switching debugging_on to false at %2.2d:%2.2d:%2.2d\n",
+ tp.tm_hour, tp.tm_min, tp.tm_sec);
+ dbgprintf("********************************************************************************\n");
+ dbgprintf("\n");
+ dbgprintf("\n");
+ debugging_on = 0;
+ }
+}
+
+
+/* This is the main entry point into rsyslogd. Over time, we should try to
+ * modularize it a bit more...
+ *
+ * NOTE on stderr and stdout: they are kept open during a fork. Note that this
+ * may introduce subtle security issues: if we are in a jail, one may break out of
+ * it via these descriptors. But if I close them earlier, error messages will (once
+ * again) not be emitted to the user that starts the daemon. Given that the risk
+ * of a break-in is very low in the startup phase, we decide it is more important
+ * to emit error messages.
+ */
+static void
+initAll(int argc, char **argv)
+{
+ rsRetVal localRet;
+ int ch;
+ int iHelperUOpt;
+ int bChDirRoot = 1; /* change the current working directory to "/"? */
+ char *arg; /* for command line option processing */
+ char cwdbuf[128]; /* buffer to obtain/display current working directory */
+ int parentPipeFD = 0; /* fd of pipe to parent, if auto-backgrounding */
+ DEFiRet;
+
+ /* prepare internal signaling */
+ hdlr_enable(SIGTTIN, hdlr_sigttin_ou);
+ hdlr_enable(SIGTTOU, hdlr_sigttin_ou);
+
+ /* first, parse the command line options. We do not carry out any actual work, just
+ * see what we should do. This relieves us from certain anomalies and we can process
+ * the parameters down below in the correct order. For example, we must know the
+ * value of -M before we can do the init, but at the same time we need to have
+ * the base classes init before we can process most of the options. Now, with the
+ * split of functionality, this is no longer a problem. Thanks to varmofekoj for
+ * suggesting this algo.
+ * Note: where we just need to set some flags and can do so without knowledge
+ * of other options, we do this during the inital option processing.
+ * rgerhards, 2008-04-04
+ */
+#if defined(_AIX)
+ while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) {
+#else
+ while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwx")) != EOF) {
+#endif
+ switch((char)ch) {
+ case '4':
+ case '6':
+ case 'A':
+ case 'f': /* configuration file */
+ case 'i': /* pid file name */
+ case 'n': /* don't fork */
+ case 'N': /* enable config verify mode */
+ case 'q': /* add hostname if DNS resolving has failed */
+ case 'Q': /* dont resolve hostnames in ACL to IPs */
+ case 'S': /* Source IP for local client to be used on multihomed host */
+ case 'T': /* chroot on startup (primarily for testing) */
+ case 'u': /* misc user settings */
+ case 'w': /* disable disallowed host warnings */
+ case 'C':
+ case 'o': /* write output config file */
+ case 'x': /* disable dns for remote messages */
+ CHKiRet(bufOptAdd(ch, optarg));
+ break;
+#if defined(_AIX)
+ case 'R': /* This option is a no-op for AIX */
+ break;
+#endif
+ case 'd': /* debug - must be handled now, so that debug is active during init! */
+ debugging_on = 1;
+ Debug = 1;
+ yydebug = 1;
+ break;
+ case 'D': /* BISON debug */
+ yydebug = 1;
+ break;
+ case 'M': /* default module load path -- this MUST be carried out immediately! */
+ glblModPath = (uchar*) optarg;
+ break;
+ case 'v': /* MUST be carried out immediately! */
+ printVersion();
+ exit(0); /* exit for -v option - so this is a "good one" */
+ case 'h':
+ case '?':
+ default:
+ rsyslogd_usage();
+ }
+ }
+
+ if(argc - optind)
+ rsyslogd_usage();
+
+ DBGPRINTF("rsyslogd %s startup, module path '%s', cwd:%s\n",
+ VERSION, glblModPath == NULL ? "" : (char*)glblModPath,
+ getcwd(cwdbuf, sizeof(cwdbuf)));
+
+ /* we are done with the initial option parsing and processing. Now we init the system. */
+
+ CHKiRet(rsyslogd_InitGlobalClasses());
+
+ /* doing some core initializations */
+
+ if((iRet = modInitIminternal()) != RS_RET_OK) {
+ fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
+ iRet);
+ exit(1); /* "good" exit, leaving at init for fatal error */
+ }
+
+ /* we now can emit error messages "the regular way" */
+
+ if(getenv("TZ") == NULL) {
+ const char *const tz =
+ (access("/etc/localtime", R_OK) == 0) ? "TZ=/etc/localtime" : "TZ=UTC";
+ putenv((char*)tz);
+ if(emitTZWarning) {
+ LogMsg(0, RS_RET_NO_TZ_SET, LOG_WARNING, "environment variable TZ is not "
+ "set, auto correcting this to %s", tz);
+ } else {
+ dbgprintf("environment variable TZ is not set, auto correcting this to %s\n", tz);
+ }
+ }
+
+ /* END core initializations - we now come back to carrying out command line options*/
+
+ while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) {
+ DBGPRINTF("deque option %c, optarg '%s'\n", ch, (arg == NULL) ? "" : arg);
+ switch((char)ch) {
+ case '4':
+ fprintf (stderr, "rsyslogd: the -4 command line option has gone away.\n"
+ "Please use the global(net.ipprotocol=\"ipv4-only\") "
+ "configuration parameter instead.\n");
+ break;
+ case '6':
+ fprintf (stderr, "rsyslogd: the -6 command line option will has gone away.\n"
+ "Please use the global(net.ipprotocol=\"ipv6-only\") "
+ "configuration parameter instead.\n");
+ break;
+ case 'A':
+ fprintf (stderr, "rsyslogd: the -A command line option will go away "
+ "soon.\n"
+ "Please use the omfwd parameter \"upd.sendToAll\" instead.\n");
+ send_to_all++;
+ break;
+ case 'S': /* Source IP for local client to be used on multihomed host */
+ fprintf (stderr, "rsyslogd: the -S command line option will go away "
+ "soon.\n"
+ "Please use the omrelp parameter \"localClientIP\" instead.\n");
+ if(glbl.GetSourceIPofLocalClient() != NULL) {
+ fprintf (stderr, "rsyslogd: Only one -S argument allowed, the first one is taken.\n");
+ } else {
+ glbl.SetSourceIPofLocalClient((uchar*)arg);
+ }
+ break;
+ case 'f': /* configuration file */
+ ConfFile = (uchar*) arg;
+ break;
+ case 'i': /* pid file name */
+ free((void*)PidFile);
+ PidFile = arg;
+ break;
+ case 'n': /* don't fork */
+ doFork = 0;
+ break;
+ case 'N': /* enable config verify mode */
+ iConfigVerify = (arg == NULL) ? 0 : atoi(arg);
+ break;
+ case 'o':
+ if(fp_rs_full_conf_output != NULL) {
+ fprintf(stderr, "warning: -o option given multiple times. Now "
+ "using value %s\n", (arg == NULL) ? "-" : arg);
+ fclose(fp_rs_full_conf_output);
+ fp_rs_full_conf_output = NULL;
+ }
+ if(arg == NULL || !strcmp(arg, "-")) {
+ fp_rs_full_conf_output = stdout;
+ } else {
+ fp_rs_full_conf_output = fopen(arg, "w");
+ }
+ if(fp_rs_full_conf_output == NULL) {
+ perror(arg);
+ fprintf (stderr, "rsyslogd: cannot open config output file %s - "
+ "-o option will be ignored\n", arg);
+ } else {
+ time_t tTime;
+ struct tm tp;
+ datetime.GetTime(&tTime);
+ localtime_r(&tTime, &tp);
+ fprintf(fp_rs_full_conf_output,
+ "## full conf created by rsyslog version %s at "
+ "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d ##\n",
+ VERSION, tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday,
+ tp.tm_hour, tp.tm_min, tp.tm_sec);
+ }
+ break;
+ case 'q': /* add hostname if DNS resolving has failed */
+ fprintf (stderr, "rsyslogd: the -q command line option has gone away.\n"
+ "Please use the global(net.aclAddHostnameOnFail=\"on\") "
+ "configuration parameter instead.\n");
+ break;
+ case 'Q': /* dont resolve hostnames in ACL to IPs */
+ fprintf (stderr, "rsyslogd: the -Q command line option has gone away.\n"
+ "Please use the global(net.aclResolveHostname=\"off\") "
+ "configuration parameter instead.\n");
+ break;
+ case 'T':/* chroot() immediately at program startup, but only for testing, NOT security yet */
+ if(arg == NULL) {
+ /* note this case should already be handled by getopt,
+ * but we want to keep the static analyzer happy.
+ */
+ fprintf(stderr, "-T options needs a parameter\n");
+ exit(1);
+ }
+ if(chroot(arg) != 0) {
+ perror("chroot");
+ exit(1);
+ }
+ if(chdir("/") != 0) {
+ perror("chdir");
+ exit(1);
+ }
+ break;
+ case 'u': /* misc user settings */
+ iHelperUOpt = (arg == NULL) ? 0 : atoi(arg);
+ if(iHelperUOpt & 0x01) {
+ fprintf (stderr, "rsyslogd: the -u command line option has gone away.\n"
+ "For the 0x01 bit, please use the "
+ "global(parser.parseHostnameAndTag=\"off\") "
+ "configuration parameter instead.\n");
+ }
+ if(iHelperUOpt & 0x02) {
+ fprintf (stderr, "rsyslogd: the -u command line option will go away "
+ "soon.\n"
+ "For the 0x02 bit, please use the -C option instead.");
+ bChDirRoot = 0;
+ }
+ break;
+ case 'C':
+ bChDirRoot = 0;
+ break;
+ case 'w': /* disable disallowed host warnigs */
+ fprintf (stderr, "rsyslogd: the -w command line option has gone away.\n"
+ "Please use the global(net.permitWarning=\"off\") "
+ "configuration parameter instead.\n");
+ break;
+ case 'x': /* disable dns for remote messages */
+ fprintf (stderr, "rsyslogd: the -x command line option has gone away.\n"
+ "Please use the global(net.enableDNS=\"off\") "
+ "configuration parameter instead.\n");
+ break;
+ case 'h':
+ case '?':
+ default:
+ rsyslogd_usage();
+ }
+ }
+
+ if(iRet != RS_RET_END_OF_LINKEDLIST)
+ FINALIZE;
+
+ if(iConfigVerify) {
+ doFork = 0;
+ fprintf(stderr, "rsyslogd: version %s, config validation run (level %d), master config %s\n",
+ VERSION, iConfigVerify, ConfFile);
+ }
+
+ resetErrMsgsFlag();
+ localRet = rsconf.Load(&ourConf, ConfFile);
+
+#ifdef ENABLE_LIBCAPNG
+ if (loadConf->globals.bCapabilityDropEnabled) {
+ /*
+ * Drop capabilities to the necessary set
+ */
+ int capng_rc, capng_failed = 0;
+ typedef struct capabilities_s {
+ int capability; /* capability code */
+ const char *name; /* name of the capability to be displayed */
+ /* is the capability present that is needed by rsyslog? if so we do not drop it */
+ sbool present;
+ capng_type_t type;
+ } capabilities_t;
+
+ capabilities_t capabilities[] = {
+ #define CAP_FIELD(code, type) { code, #code, 0 , type}
+ CAP_FIELD(CAP_BLOCK_SUSPEND, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_NET_RAW, CAPNG_EFFECTIVE | CAPNG_PERMITTED ),
+ CAP_FIELD(CAP_CHOWN, CAPNG_EFFECTIVE | CAPNG_PERMITTED ),
+ CAP_FIELD(CAP_IPC_LOCK, CAPNG_EFFECTIVE | CAPNG_PERMITTED ),
+ CAP_FIELD(CAP_LEASE, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_NET_ADMIN, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_NET_BIND_SERVICE, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_DAC_OVERRIDE, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_BOUNDING_SET),
+ CAP_FIELD(CAP_SETGID, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_SETUID, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_SYS_ADMIN, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_SYS_CHROOT, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_SYS_RESOURCE, CAPNG_EFFECTIVE | CAPNG_PERMITTED),
+ CAP_FIELD(CAP_SYSLOG, CAPNG_EFFECTIVE | CAPNG_PERMITTED)
+ #undef CAP_FIELD
+ };
+
+ if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE) {
+ /* Examine which capabilities are available to us, so we do not try to
+ drop something that is not present. We need to do this in two steps,
+ because capng_clear clears the capability set. In the second step,
+ we add back those caps, which were present before clearing the selected
+ posix capabilities set.
+ */
+ unsigned long caps_len = sizeof(capabilities) / sizeof(capabilities_t);
+ for (unsigned long i = 0; i < caps_len; i++) {
+ if (capng_have_capability(CAPNG_EFFECTIVE, capabilities[i].capability)) {
+ capabilities[i].present = 1;
+ }
+ }
+
+ capng_clear(CAPNG_SELECT_BOTH);
+
+ for (unsigned long i = 0; i < caps_len; i++) {
+ if (capabilities[i].present) {
+ DBGPRINTF("The %s capability is present, "
+ "will try to preserve it.\n", capabilities[i].name);
+ if ((capng_rc = capng_update(CAPNG_ADD, capabilities[i].type,
+ capabilities[i].capability)) != 0) {
+ LogError(0, RS_RET_LIBCAPNG_ERR,
+ "could not update the internal posix capabilities"
+ " settings based on the options passed to it,"
+ " capng_update=%d", capng_rc);
+ capng_failed = 1;
+ }
+ } else {
+ DBGPRINTF("The %s capability is not present, "
+ "will not try to preserve it.\n", capabilities[i].name);
+ }
+ }
+
+ if ((capng_rc = capng_apply(CAPNG_SELECT_BOTH)) != 0) {
+ LogError(0, RS_RET_LIBCAPNG_ERR,
+ "could not transfer the specified internal posix capabilities "
+ "settings to the kernel, capng_apply=%d", capng_rc);
+ capng_failed = 1;
+ }
+
+ if (capng_failed) {
+ DBGPRINTF("Capabilities were not dropped successfully.\n");
+ if (loadConf->globals.bAbortOnFailedLibcapngSetup) {
+ ABORT_FINALIZE(RS_RET_LIBCAPNG_ERR);
+ }
+ } else {
+ DBGPRINTF("Capabilities were dropped successfully\n");
+ }
+ } else {
+ DBGPRINTF("No capabilities to drop\n");
+ }
+ }
+#endif
+
+ if(fp_rs_full_conf_output != NULL) {
+ if(fp_rs_full_conf_output != stdout) {
+ fclose(fp_rs_full_conf_output);
+ }
+ fp_rs_full_conf_output = NULL;
+ }
+
+ /* check for "hard" errors that needs us to abort in any case */
+ if( (localRet == RS_RET_CONF_FILE_NOT_FOUND)
+ || (localRet == RS_RET_NO_ACTIONS) ) {
+ /* for extreme testing, we keep the ability to let rsyslog continue
+ * even on hard config errors. Note that this may lead to segfaults
+ * or other malfunction further down the road.
+ */
+ if((loadConf->globals.glblDevOptions & DEV_OPTION_KEEP_RUNNING_ON_HARD_CONF_ERROR) == 1) {
+ fprintf(stderr, "rsyslogd: NOTE: developer-only option set to keep rsyslog "
+ "running where it should abort - this can lead to "
+ "more problems later in the run.\n");
+ } else {
+ ABORT_FINALIZE(localRet);
+ }
+ }
+
+ glbl.GenerateLocalHostNameProperty();
+
+ if(hadErrMsgs()) {
+ if(loadConf->globals.bAbortOnUncleanConfig) {
+ fprintf(stderr, "rsyslogd: global(AbortOnUncleanConfig=\"on\") is set, and "
+ "config is not clean.\n"
+ "Check error log for details, fix errors and restart. As a last\n"
+ "resort, you may want to use global(AbortOnUncleanConfig=\"off\") \n"
+ "to permit a startup with a dirty config.\n");
+ exit(2);
+ }
+ if(iConfigVerify) {
+ /* a bit dirty, but useful... */
+ exit(1);
+ }
+ localRet = RS_RET_OK;
+ }
+ CHKiRet(localRet);
+
+ CHKiRet(rsyslogd_InitStdRatelimiters());
+
+ if(bChDirRoot) {
+ if(chdir("/") != 0)
+ fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
+ }
+
+ if(iConfigVerify)
+ FINALIZE;
+ /* after this point, we are in a "real" startup */
+
+ thrdInit();
+ CHKiRet(checkStartupOK());
+ if(doFork) {
+ parentPipeFD = forkRsyslog();
+ }
+ glblSetOurPid(getpid());
+
+ hdlr_enable(SIGPIPE, SIG_IGN);
+ hdlr_enable(SIGXFSZ, SIG_IGN);
+ if(Debug || loadConf->globals.permitCtlC) {
+ hdlr_enable(SIGUSR1, rsyslogdDebugSwitch);
+ hdlr_enable(SIGINT, rsyslogdDoDie);
+ hdlr_enable(SIGQUIT, rsyslogdDoDie);
+ } else {
+ hdlr_enable(SIGUSR1, SIG_IGN);
+ hdlr_enable(SIGINT, SIG_IGN);
+ hdlr_enable(SIGQUIT, SIG_IGN);
+ }
+ hdlr_enable(SIGTERM, rsyslogdDoDie);
+ hdlr_enable(SIGCHLD, hdlr_sigchld);
+ hdlr_enable(SIGHUP, hdlr_sighup);
+
+ if(rsconfNeedDropPriv(loadConf)) {
+ /* need to write pid file early as we may loose permissions */
+ CHKiRet(writePidFile());
+ }
+
+ CHKiRet(rsconf.Activate(ourConf));
+
+ if(runConf->globals.bLogStatusMsgs) {
+ char bufStartUpMsg[512];
+ snprintf(bufStartUpMsg, sizeof(bufStartUpMsg),
+ "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] start",
+ (int) glblGetOurPid());
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ }
+
+ if(!rsconfNeedDropPriv(runConf)) {
+ CHKiRet(writePidFile());
+ }
+
+ /* END OF INTIALIZATION */
+ DBGPRINTF("rsyslogd: initialization completed, transitioning to regular run mode\n");
+
+ if(doFork) {
+ tellChildReady(parentPipeFD, "OK");
+ stddbg = -1; /* turn off writing to fd 1 */
+ close(1);
+ close(2);
+ runConf->globals.bErrMsgToStderr = 0;
+ }
+
+finalize_it:
+ if(iRet == RS_RET_VALIDATION_RUN) {
+ fprintf(stderr, "rsyslogd: End of config validation run. Bye.\n");
+ exit(0);
+ } else if(iRet != RS_RET_OK) {
+ fprintf(stderr, "rsyslogd: run failed with error %d (see rsyslog.h "
+ "or try https://www.rsyslog.com/e/%d to learn what that number means)\n",
+ iRet, iRet*-1);
+ exit(1);
+ }
+
+}
+
+
+/* this function pulls all internal messages from the buffer
+ * and puts them into the processing engine.
+ * We can only do limited error handling, as this would not
+ * really help us. TODO: add error messages?
+ * rgerhards, 2007-08-03
+ */
+void
+processImInternal(void)
+{
+ smsg_t *pMsg;
+ smsg_t *repMsg;
+
+ while(iminternalRemoveMsg(&pMsg) == RS_RET_OK) {
+ rsRetVal localRet = ratelimitMsg(internalMsg_ratelimiter, pMsg, &repMsg);
+ if(repMsg != NULL) {
+ logmsgInternal_doWrite(repMsg);
+ }
+ if(localRet == RS_RET_OK) {
+ logmsgInternal_doWrite(pMsg);
+ }
+ }
+}
+
+
+/* This takes a received message that must be decoded and submits it to
+ * the main message queue. This is a legacy function which is being provided
+ * to aid older input plugins that do not support message creation via
+ * the new interfaces themselves. It is not recommended to use this
+ * function for new plugins. -- rgerhards, 2009-10-12
+ */
+rsRetVal
+parseAndSubmitMessage(const uchar *const hname, const uchar *const hnameIP, const uchar *const msg,
+ const int len, const int flags, const flowControl_t flowCtlType,
+ prop_t *const pInputName,
+ const struct syslogTime *const stTime,
+ const time_t ttGenTime,
+ ruleset_t *const pRuleset)
+{
+ prop_t *pProp = NULL;
+ smsg_t *pMsg = NULL;
+ DEFiRet;
+
+ /* we now create our own message object and submit it to the queue */
+ if(stTime == NULL) {
+ CHKiRet(msgConstruct(&pMsg));
+ } else {
+ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ }
+ if(pInputName != NULL)
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)msg, len);
+ MsgSetFlowControlType(pMsg, flowCtlType);
+ MsgSetRuleset(pMsg, pRuleset);
+ pMsg->msgFlags = flags | NEEDS_PARSING;
+
+ MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &pProp);
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hnameIP), &pProp));
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(submitMsg2(pMsg));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ DBGPRINTF("parseAndSubmitMessage() error, discarding msg: %s\n", msg);
+ if(pMsg != NULL) {
+ msgDestruct(&pMsg);
+ }
+ }
+ RETiRet;
+}
+
+
+/* helper to doHUP(), this "HUPs" each action. The necessary locking
+ * is done inside the action class and nothing we need to take care of.
+ * rgerhards, 2008-10-22
+ */
+DEFFUNC_llExecFunc(doHUPActions)
+{
+ actionCallHUPHdlr((action_t*) pData);
+ return RS_RET_OK; /* we ignore errors, we can not do anything either way */
+}
+
+
+/* This function processes a HUP after one has been detected. Note that this
+ * is *NOT* the sighup handler. The signal is recorded by the handler, that record
+ * detected inside the mainloop and then this function is called to do the
+ * real work. -- rgerhards, 2008-10-22
+ * Note: there is a VERY slim chance of a data race when the hostname is reset.
+ * We prefer to take this risk rather than sync all accesses, because to the best
+ * of my analysis it can not really hurt (the actual property is reference-counted)
+ * but the sync would require some extra CPU for *each* message processed.
+ * rgerhards, 2012-04-11
+ */
+static void
+doHUP(void)
+{
+ char buf[512];
+
+ DBGPRINTF("doHUP: doing modules\n");
+ if(ourConf->globals.bLogStatusMsgs) {
+ snprintf(buf, sizeof(buf),
+ "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION
+ "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] rsyslogd was HUPed",
+ (int) glblGetOurPid());
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ }
+
+ queryLocalHostname(runConf); /* re-read our name */
+ ruleset.IterateAllActions(ourConf, doHUPActions, NULL);
+ DBGPRINTF("doHUP: doing modules\n");
+ modDoHUP();
+ DBGPRINTF("doHUP: doing lookup tables\n");
+ lookupDoHUP();
+ DBGPRINTF("doHUP: doing errmsgs\n");
+ errmsgDoHUP();
+}
+
+/* rsyslogdDoDie() is a signal handler. If called, it sets the bFinished variable
+ * to indicate the program should terminate. However, it does not terminate
+ * it itself, because that causes issues with multi-threading. The actual
+ * termination is then done on the main thread. This solution might introduce
+ * a minimal delay, but it is much cleaner than the approach of doing everything
+ * inside the signal handler.
+ * rgerhards, 2005-10-26
+ * Note:
+ * - we do not call DBGPRINTF() as this may cause us to block in case something
+ * with the threading is wrong.
+ * - we do not really care about the return state of write(), but we need this
+ * strange check we do to silence compiler warnings (thanks, Ubuntu!)
+ */
+void
+rsyslogdDoDie(int sig)
+{
+# define MSG1 "DoDie called.\n"
+# define MSG2 "DoDie called 5 times - unconditional exit\n"
+ static int iRetries = 0; /* debug aid */
+ dbgprintf(MSG1);
+ if(Debug == DEBUG_FULL) {
+ if(write(1, MSG1, sizeof(MSG1) - 1) == -1) {
+ dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__);
+ }
+ }
+ if(iRetries++ == 4) {
+ if(Debug == DEBUG_FULL) {
+ if(write(1, MSG2, sizeof(MSG2) - 1) == -1) {
+ dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__);
+ }
+ }
+ abort();
+ }
+ bFinished = sig;
+ if(runConf->globals.debugOnShutdown) {
+ /* kind of hackish - set to 0, so that debug_swith will enable
+ * and AND emit the "start debug log" message.
+ */
+ debugging_on = 0;
+ rsyslogdDebugSwitch();
+ }
+# undef MSG1
+# undef MSG2
+ /* at least on FreeBSD we seem not to necessarily awake the main thread.
+ * So let's do it explicitely.
+ */
+ dbgprintf("awaking mainthread\n");
+ pthread_kill(mainthread, SIGTTIN);
+}
+
+
+static void
+wait_timeout(const sigset_t *sigmask)
+{
+ struct timespec tvSelectTimeout;
+
+ tvSelectTimeout.tv_sec = runConf->globals.janitorInterval * 60; /* interval is in minutes! */
+ tvSelectTimeout.tv_nsec = 0;
+
+#ifdef _AIX
+ if(!src_exists) {
+ /* it looks like select() is NOT interrupted by HUP, even though
+ * SA_RESTART is not given in the signal setup. As this code is
+ * not expected to be used in production (when running as a
+ * service under src control), we simply make a kind of
+ * "somewhat-busy-wait" algorithm. We compute our own
+ * timeout value, which we count down to zero. We do this
+ * in useful subsecond steps.
+ */
+ const long wait_period = 500000000; /* wait period in nanoseconds */
+ int timeout = runConf->globals.janitorInterval * 60 * (1000000000 / wait_period);
+
+ tvSelectTimeout.tv_sec = 0;
+ tvSelectTimeout.tv_nsec = wait_period;
+ do {
+ pthread_mutex_lock(&mutHadHUP);
+ if(bFinished || bHadHUP) {
+ pthread_mutex_unlock(&mutHadHUP);
+ break;
+ }
+ pthread_mutex_unlock(&mutHadHUP);
+ pselect(1, NULL, NULL, NULL, &tvSelectTimeout, sigmask);
+ } while(--timeout > 0);
+ } else {
+ char buf[256];
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(SRC_FD, &rfds);
+ if(pselect(SRC_FD + 1, (fd_set *)&rfds, NULL, NULL, &tvSelectTimeout, sigmask))
+ {
+ if(FD_ISSET(SRC_FD, &rfds))
+ {
+ rc = recvfrom(SRC_FD, &srcpacket, SRCMSG, 0, &srcaddr, &addrsz);
+ if(rc < 0) {
+ if (errno != EINTR)
+ {
+ fprintf(stderr,"%s: ERROR: '%d' recvfrom\n", progname,errno);
+ exit(1); //TODO: this needs to be handled gracefully
+ } else { /* punt on short read */
+ return;
+ }
+
+ switch(srcpacket.subreq.action)
+ {
+ case START:
+ dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support this "
+ "option.\n", sizeof(struct srcrep));
+ break;
+ case STOP:
+ if (srcpacket.subreq.object == SUBSYSTEM) {
+ dosrcpacket(SRC_OK,NULL,sizeof(struct srcrep));
+ (void) snprintf(buf, sizeof(buf) / sizeof(char), " [origin "
+ "software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]"
+ " exiting due to stopsrc.",
+ (int) glblGetOurPid());
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ return ;
+ } else
+ dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support "
+ "this option.\n",sizeof(struct srcrep));
+ break;
+ case REFRESH:
+ dosrcpacket(SRC_SUBMSG,"ERROR: rsyslogd does not support this "
+ "option.\n", sizeof(struct srcrep));
+ break;
+ default:
+ dosrcpacket(SRC_SUBICMD,NULL,sizeof(struct srcrep));
+ break;
+
+ }
+ }
+ }
+ }
+ }
+#else
+ pselect(0, NULL, NULL, NULL, &tvSelectTimeout, sigmask);
+#endif /* AIXPORT : SRC end */
+}
+
+
+static void
+reapChild(void)
+{
+ pid_t child;
+ do {
+ int status;
+ child = waitpid(-1, &status, WNOHANG);
+ if(child != -1 && child != 0) {
+ glblReportChildProcessExit(runConf, NULL, child, status);
+ }
+ } while(child > 0);
+}
+
+
+/* This is the main processing loop. It is called after successful initialization.
+ * When it returns, the syslogd terminates.
+ * Its sole function is to provide some housekeeping things. The real work is done
+ * by the other threads spawned.
+ */
+static void
+mainloop(void)
+{
+ time_t tTime;
+ sigset_t origmask;
+ sigset_t sigblockset;
+ int need_free_mutex;
+
+ sigemptyset(&sigblockset);
+ sigaddset(&sigblockset, SIGTERM);
+ sigaddset(&sigblockset, SIGCHLD);
+ sigaddset(&sigblockset, SIGHUP);
+
+ do {
+ pthread_sigmask(SIG_BLOCK, &sigblockset, &origmask);
+ pthread_mutex_lock(&mutChildDied);
+ need_free_mutex = 1;
+ if(bChildDied) {
+ bChildDied = 0;
+ pthread_mutex_unlock(&mutChildDied);
+ need_free_mutex = 0;
+ reapChild();
+ }
+ if(need_free_mutex) {
+ pthread_mutex_unlock(&mutChildDied);
+ }
+
+ pthread_mutex_lock(&mutHadHUP);
+ need_free_mutex = 1;
+ if(bHadHUP) {
+ need_free_mutex = 0;
+ pthread_mutex_unlock(&mutHadHUP);
+ doHUP();
+ pthread_mutex_lock(&mutHadHUP);
+ bHadHUP = 0;
+ pthread_mutex_unlock(&mutHadHUP);
+ }
+ if(need_free_mutex) {
+ pthread_mutex_unlock(&mutHadHUP);
+ }
+
+ processImInternal();
+
+ if(bFinished)
+ break; /* exit as quickly as possible */
+
+ wait_timeout(&origmask);
+ pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
+
+ janitorRun();
+
+ datetime.GetTime(&tTime);
+ checkGoneAwaySenders(tTime);
+
+ } while(!bFinished); /* end do ... while() */
+}
+
+/* Finalize and destruct all actions.
+ */
+static void
+rsyslogd_destructAllActions(void)
+{
+ ruleset.DestructAllActions(runConf);
+ PREFER_STORE_0_TO_INT(&bHaveMainQueue); /* flag that internal messages need to be temporarily stored */
+}
+
+
+/* de-initialize everything, make ready for termination */
+static void
+deinitAll(void)
+{
+ char buf[256];
+
+ DBGPRINTF("exiting on signal %d\n", bFinished);
+
+ /* IMPORTANT: we should close the inputs first, and THEN send our termination
+ * message. If we do it the other way around, logmsgInternal() may block on
+ * a full queue and the inputs still fill up that queue. Depending on the
+ * scheduling order, we may end up with logmsgInternal being held for a quite
+ * long time. When the inputs are terminated first, that should not happen
+ * because the queue is drained in parallel. The situation could only become
+ * an issue with extremely long running actions in a queue full environment.
+ * However, such actions are at least considered poorly written, if not
+ * outright wrong. So we do not care about this very remote problem.
+ * rgerhards, 2008-01-11
+ */
+
+ /* close the inputs */
+ DBGPRINTF("Terminating input threads...\n");
+ glbl.SetGlobalInputTermination();
+
+ thrdTerminateAll();
+
+ /* and THEN send the termination log message (see long comment above) */
+ if(bFinished && runConf->globals.bLogStatusMsgs) {
+ (void) snprintf(buf, sizeof(buf),
+ "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]" " exiting on signal %d.",
+ (int) glblGetOurPid(), bFinished);
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ }
+ processImInternal(); /* make sure not-yet written internal messages are processed */
+ /* we sleep a couple of ms to give the queue a chance to pick up the late messages
+ * (including exit message); otherwise we have seen cases where the message did
+ * not make it to log files, even on idle systems.
+ */
+ srSleep(0, 50);
+
+ /* drain queue (if configured so) and stop main queue worker thread pool */
+ DBGPRINTF("Terminating main queue...\n");
+ qqueueDestruct(&runConf->pMsgQueue);
+ runConf->pMsgQueue = NULL;
+
+ /* Free ressources and close connections. This includes flushing any remaining
+ * repeated msgs.
+ */
+ DBGPRINTF("Terminating outputs...\n");
+ rsyslogd_destructAllActions();
+
+ DBGPRINTF("all primary multi-thread sources have been terminated - now doing aux cleanup...\n");
+
+ DBGPRINTF("destructing current config...\n");
+ rsconf.Destruct(&runConf);
+
+ modExitIminternal();
+
+ if(pInternalInputName != NULL)
+ prop.Destruct(&pInternalInputName);
+
+ /* the following line cleans up CfSysLineHandlers that were not based on loadable
+ * modules. As such, they are not yet cleared. */
+ unregCfSysLineHdlrs();
+
+ /* this is the last spot where this can be done - below output modules are unloaded! */
+
+ parserClassExit();
+ rsconfClassExit();
+ strExit();
+ ratelimitModExit();
+ dnscacheDeinit();
+ thrdExit();
+ objRelease(net, LM_NET_FILENAME);
+
+ module.UnloadAndDestructAll(eMOD_LINK_ALL);
+
+ rsrtExit(); /* runtime MUST always be deinitialized LAST (except for debug system) */
+ DBGPRINTF("Clean shutdown completed, bye\n");
+
+ errmsgExit();
+ /* dbgClassExit MUST be the last one, because it de-inits the debug system */
+ dbgClassExit();
+
+ /* NO CODE HERE - dbgClassExit() must be the last thing before exit()! */
+ clearPidFile();
+}
+
+/* This is the main entry point into rsyslogd. This must be a function in its own
+ * right in order to intialize the debug system in a portable way (otherwise we would
+ * need to have a statement before variable definitions.
+ * rgerhards, 20080-01-28
+ */
+int
+main(int argc, char **argv)
+{
+#if defined(_AIX)
+ /* SRC support : fd 0 (stdin) must be the SRC socket
+ * startup. fd 0 is duped to a new descriptor so that stdin can be used
+ * internally by rsyslogd.
+ */
+
+ pthread_mutex_init(&mutHadHUP, NULL);
+ pthread_mutex_init(&mutChildDied, NULL);
+ strncpy(progname,argv[0], sizeof(progname)-1);
+ addrsz = sizeof(srcaddr);
+ if ((rc = getsockname(0, &srcaddr, &addrsz)) < 0) {
+ fprintf(stderr, "%s: continuing without SRC support\n", progname);
+ src_exists = FALSE;
+ }
+ if (src_exists)
+ if(dup2(0, SRC_FD) == -1) {
+ fprintf(stderr, "%s: dup2 failed exiting now...\n", progname);
+ /* In the unlikely event of dup2 failing we exit */
+ exit(-1);
+ }
+#endif
+
+ mainthread = pthread_self();
+ if((int) getpid() == 1) {
+ fprintf(stderr, "rsyslogd %s: running as pid 1, enabling "
+ "container-specific defaults, press ctl-c to "
+ "terminate rsyslog\n", VERSION);
+ PidFile = strdup("NONE"); /* disables pid file writing */
+ glblPermitCtlC = 1;
+ runningInContainer = 1;
+ emitTZWarning = 1;
+ } else {
+ /* "dynamic defaults" - non-container case */
+ PidFile = strdup(PATH_PIDFILE);
+ }
+ if(PidFile == NULL) {
+ fprintf(stderr, "rsyslogd: could not alloc memory for pid file "
+ "default name - aborting\n");
+ exit(1);
+ }
+
+ /* disable case-sensitive comparisons in variable subsystem: */
+ fjson_global_do_case_sensitive_comparison(0);
+
+ dbgClassInit();
+
+ initAll(argc, argv);
+#ifdef HAVE_LIBSYSTEMD
+ sd_notify(0, "READY=1");
+ dbgprintf("done signaling to systemd that we are ready!\n");
+#endif
+ DBGPRINTF("max message size: %d\n", glblGetMaxLine(runConf));
+ DBGPRINTF("----RSYSLOGD INITIALIZED\n");
+ LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd fully started up and initialized "
+ "- begin actual processing");
+
+ mainloop();
+ LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd shutting down");
+ deinitAll();
+ osf_close();
+ pthread_mutex_destroy(&mutChildDied);
+ pthread_mutex_destroy(&mutHadHUP);
+ return 0;
+}
diff --git a/tools/smfile.c b/tools/smfile.c
new file mode 100644
index 0000000..afd919b
--- /dev/null
+++ b/tools/smfile.c
@@ -0,0 +1,137 @@
+/* smfile.c
+ * This is a strgen module for the traditional file format.
+ *
+ * Format generated:
+ * "%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
+ * Note that this is the same as smtradfile.c, except that we do have a RFC3339 timestamp. However,
+ * we have copied over the code from there, it is too simple to go through all the hassle
+ * of having a single code base.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-06-01 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_STRGEN
+MODULE_TYPE_NOKEEP
+STRGEN_NAME("RSYSLOG_FileFormat")
+
+/* internal structures
+ */
+DEF_SMOD_STATIC_DATA
+
+
+/* config data */
+
+
+/* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings
+ * needed (including their length) and then calculating the actual space required. So when we
+ * finally copy, we know exactly what we need. So we do at most one alloc.
+ */
+BEGINstrgen
+ register int iBuf;
+ uchar *pTimeStamp;
+ size_t lenTimeStamp;
+ uchar *pHOSTNAME;
+ size_t lenHOSTNAME;
+ uchar *pTAG;
+ int lenTAG;
+ uchar *pMSG;
+ size_t lenMSG;
+ size_t lenTotal;
+CODESTARTstrgen
+ /* first obtain all strings and their length (if not fixed) */
+ pTimeStamp = (uchar*) getTimeReported(pMsg, tplFmtRFC3339Date);
+ lenTimeStamp = ustrlen(pTimeStamp);
+ pHOSTNAME = (uchar*) getHOSTNAME(pMsg);
+ lenHOSTNAME = getHOSTNAMELen(pMsg);
+ getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX);
+ pMSG = getMSG(pMsg);
+ lenMSG = getMSGLen(pMsg);
+
+ /* calculate len, constants for spaces and similar fixed strings */
+ lenTotal = lenTimeStamp + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 2;
+ if(pMSG[0] != ' ')
+ ++lenTotal; /* then we need to introduce one additional space */
+
+ /* now make sure buffer is large enough */
+ if(lenTotal >= iparam->lenBuf)
+ CHKiRet(ExtendBuf(iparam, lenTotal));
+
+ /* and concatenate the resulting string */
+ memcpy(iparam->param, pTimeStamp, lenTimeStamp);
+ iBuf = lenTimeStamp;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME);
+ iBuf += lenHOSTNAME;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pTAG, lenTAG);
+ iBuf += lenTAG;
+
+ if(pMSG[0] != ' ')
+ iparam->param[iBuf++] = ' ';
+ memcpy(iparam->param + iBuf, pMSG, lenMSG);
+ iBuf += lenMSG;
+
+ /* trailer */
+ iparam->param[iBuf++] = '\n';
+ iparam->param[iBuf] = '\0';
+
+ iparam->lenStr = lenTotal - 1; /* do not count \0! */
+
+finalize_it:
+ENDstrgen
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_SMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(smfile)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+
+ dbgprintf("rsyslog standard file format strgen init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/tools/smfile.h b/tools/smfile.h
new file mode 100644
index 0000000..d412554
--- /dev/null
+++ b/tools/smfile.h
@@ -0,0 +1,31 @@
+/* smfile.h
+ * These are the definitions for the traditional file format stringen module.
+ *
+ * File begun on 2010-06-04 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SMFILE_H_INCLUDED
+#define SMFILE_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitsmfile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef SMFILE_H_INCLUDED */
diff --git a/tools/smfwd.c b/tools/smfwd.c
new file mode 100644
index 0000000..95ea425
--- /dev/null
+++ b/tools/smfwd.c
@@ -0,0 +1,145 @@
+/* smfwd.c
+ * This is a strgen module for the traditional (network) forwarding format.
+ *
+ * Format generated:
+ * "<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-06-01 by RGerhards
+ *
+ * Copyright 2010-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_STRGEN
+MODULE_TYPE_NOKEEP
+STRGEN_NAME("RSYSLOG_ForwardFormat")
+
+/* internal structures
+ */
+DEF_SMOD_STATIC_DATA
+
+
+/* config data */
+
+
+/* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings
+ * needed (including their length) and then calculating the actual space required. So when we
+ * finally copy, we know exactly what we need. So we do at most one alloc.
+ */
+BEGINstrgen
+ register int iBuf;
+ const char *pPRI;
+ size_t lenPRI;
+ uchar *pTimeStamp;
+ size_t lenTimeStamp;
+ uchar *pHOSTNAME;
+ size_t lenHOSTNAME;
+ uchar *pTAG;
+ int lenTAG;
+ uchar *pMSG;
+ size_t lenMSG;
+ size_t lenTotal;
+CODESTARTstrgen
+ /* first obtain all strings and their length (if not fixed) */
+ pPRI = getPRI(pMsg);
+ lenPRI = strlen(pPRI);
+ pTimeStamp = (uchar*) getTimeReported(pMsg, tplFmtRFC3339Date);
+ lenTimeStamp = ustrlen(pTimeStamp);
+ pHOSTNAME = (uchar*) getHOSTNAME(pMsg);
+ lenHOSTNAME = getHOSTNAMELen(pMsg);
+ getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX);
+ if(lenTAG > 32)
+ lenTAG = 32; /* for forwarding, a max of 32 chars is permitted (RFC!) */
+ pMSG = getMSG(pMsg);
+ lenMSG = getMSGLen(pMsg);
+
+ /* calculate len, constants for spaces and similar fixed strings */
+ lenTotal = 1 + lenPRI + 1 + lenTimeStamp + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 1;
+ if(pMSG[0] != ' ')
+ ++lenTotal; /* then we need to introduce one additional space */
+
+ /* now make sure buffer is large enough */
+ if(lenTotal >= iparam->lenBuf)
+ CHKiRet(ExtendBuf(iparam, lenTotal));
+
+ /* and concatenate the resulting string */
+ iparam->param[0] = '<';
+ memcpy(iparam->param + 1, pPRI, lenPRI);
+ iBuf = lenPRI + 1;
+ iparam->param[iBuf++] = '>';
+
+ memcpy(iparam->param + iBuf, pTimeStamp, lenTimeStamp);
+ iBuf += lenTimeStamp;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME);
+ iBuf += lenHOSTNAME;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pTAG, lenTAG);
+ iBuf += lenTAG;
+
+ if(pMSG[0] != ' ')
+ iparam->param[iBuf++] = ' ';
+ memcpy(iparam->param + iBuf, pMSG, lenMSG);
+ iBuf += lenMSG;
+
+ /* string terminator */
+ iparam->param[iBuf] = '\0';
+
+ iparam->lenStr = lenTotal - 1; /* do not count \0! */
+
+finalize_it:
+ENDstrgen
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_SMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(smfwd)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+
+ dbgprintf("rsyslog standard (network) forward format strgen init called, compiled with version"
+ " %s\n", VERSION);
+ENDmodInit
diff --git a/tools/smfwd.h b/tools/smfwd.h
new file mode 100644
index 0000000..b695aea
--- /dev/null
+++ b/tools/smfwd.h
@@ -0,0 +1,30 @@
+/* smfwd.h
+ *
+ * File begun on 2010-06-04 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SMFWD_H_INCLUDED
+#define SMFWD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitsmfwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef SMFWD_H_INCLUDED */
diff --git a/tools/smtradfile.c b/tools/smtradfile.c
new file mode 100644
index 0000000..9a86ff4
--- /dev/null
+++ b/tools/smtradfile.c
@@ -0,0 +1,130 @@
+/* smtradfile.c
+ * This is a strgen module for the traditional file format.
+ *
+ * Format generated:
+ * "%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-06-01 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_STRGEN
+MODULE_TYPE_NOKEEP
+STRGEN_NAME("RSYSLOG_TraditionalFileFormat")
+
+/* internal structures
+ */
+DEF_SMOD_STATIC_DATA
+
+
+/* config data */
+
+
+/* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings
+ * needed (including their length) and then calculating the actual space required. So when we
+ * finally copy, we know exactly what we need. So we do at most one alloc.
+ */
+BEGINstrgen
+ register int iBuf;
+ uchar *pTimeStamp;
+ uchar *pHOSTNAME;
+ size_t lenHOSTNAME;
+ uchar *pTAG;
+ int lenTAG;
+ uchar *pMSG;
+ size_t lenMSG;
+ size_t lenTotal;
+CODESTARTstrgen
+ /* first obtain all strings and their length (if not fixed) */
+ pTimeStamp = (uchar*) getTimeReported(pMsg, tplFmtRFC3164Date);
+ pHOSTNAME = (uchar*) getHOSTNAME(pMsg);
+ lenHOSTNAME = getHOSTNAMELen(pMsg);
+ getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX);
+ pMSG = getMSG(pMsg);
+ lenMSG = getMSGLen(pMsg);
+
+ /* calculate len, constants for spaces and similar fixed strings */
+ lenTotal = CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 2;
+ if(pMSG[0] != ' ')
+ ++lenTotal; /* then we need to introduce one additional space */
+
+ /* now make sure buffer is large enough */
+ if(lenTotal >= iparam->lenBuf)
+ CHKiRet(ExtendBuf(iparam, lenTotal));
+
+ /* and concatenate the resulting string */
+ memcpy(iparam->param, pTimeStamp, CONST_LEN_TIMESTAMP_3164);
+ iparam->param[CONST_LEN_TIMESTAMP_3164] = ' ';
+
+ memcpy(iparam->param + CONST_LEN_TIMESTAMP_3164 + 1, pHOSTNAME, lenHOSTNAME);
+ iBuf = CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pTAG, lenTAG);
+ iBuf += lenTAG;
+
+ if(pMSG[0] != ' ')
+ iparam->param[iBuf++] = ' ';
+ memcpy(iparam->param + iBuf, pMSG, lenMSG);
+ iBuf += lenMSG;
+
+ /* trailer */
+ iparam->param[iBuf++] = '\n';
+ iparam->param[iBuf] = '\0';
+
+ iparam->lenStr = lenTotal - 1; /* do not count \0! */
+
+finalize_it:
+ENDstrgen
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_SMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(smtradfile)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("traditional file format strgen init called, compiled with version %s\n", VERSION);
+ENDmodInit
diff --git a/tools/smtradfile.h b/tools/smtradfile.h
new file mode 100644
index 0000000..dd5ee16
--- /dev/null
+++ b/tools/smtradfile.h
@@ -0,0 +1,31 @@
+/* smtradfile.h
+ * These are the definitions for the traditional file format stringen module.
+ *
+ * File begun on 2010-06-01 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SMTRADFILE_H_INCLUDED
+#define SMTRADFILE_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitsmtradfile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+ rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef SMTRADFILE_H_INCLUDED */
diff --git a/tools/smtradfwd.c b/tools/smtradfwd.c
new file mode 100644
index 0000000..163083f
--- /dev/null
+++ b/tools/smtradfwd.c
@@ -0,0 +1,142 @@
+/* smtradfwd.c
+ * This is a strgen module for the traditional forwarding format.
+ *
+ * Format generated:
+ * "<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-06-01 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "syslogd.h"
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_STRGEN
+MODULE_TYPE_NOKEEP
+STRGEN_NAME("RSYSLOG_TraditionalForwardFormat")
+
+/* internal structures
+ */
+DEF_SMOD_STATIC_DATA
+
+
+/* config data */
+
+
+/* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings
+ * needed (including their length) and then calculating the actual space required. So when we
+ * finally copy, we know exactly what we need. So we do at most one alloc.
+ */
+BEGINstrgen
+ register int iBuf;
+ const char *pPRI;
+ size_t lenPRI;
+ uchar *pTimeStamp;
+ uchar *pHOSTNAME;
+ size_t lenHOSTNAME;
+ uchar *pTAG;
+ int lenTAG;
+ uchar *pMSG;
+ size_t lenMSG;
+ size_t lenTotal;
+CODESTARTstrgen
+ /* first obtain all strings and their length (if not fixed) */
+ pPRI = getPRI(pMsg);
+ lenPRI = strlen(pPRI);
+ pTimeStamp = (uchar*) getTimeReported(pMsg, tplFmtRFC3164Date);
+ pHOSTNAME = (uchar*) getHOSTNAME(pMsg);
+ lenHOSTNAME = getHOSTNAMELen(pMsg);
+ getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX);
+ if(lenTAG > 32)
+ lenTAG = 32; /* for forwarding, a max of 32 chars is permitted (RFC!) */
+ pMSG = getMSG(pMsg);
+ lenMSG = getMSGLen(pMsg);
+
+ /* calculate len, constants for spaces and similar fixed strings */
+ lenTotal = 1 + lenPRI + 1 + CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 1;
+ if(pMSG[0] != ' ')
+ ++lenTotal; /* then we need to introduce one additional space */
+
+ /* now make sure buffer is large enough */
+ if(lenTotal >= iparam->lenBuf)
+ CHKiRet(ExtendBuf(iparam, lenTotal));
+
+ /* and concatenate the resulting string */
+ iparam->param[0] = '<';
+ memcpy(iparam->param + 1, pPRI, lenPRI);
+ iBuf = lenPRI + 1;
+ iparam->param[iBuf++] = '>';
+
+ memcpy(iparam->param + iBuf, pTimeStamp, CONST_LEN_TIMESTAMP_3164);
+ iBuf += CONST_LEN_TIMESTAMP_3164;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME);
+ iBuf += lenHOSTNAME;
+ iparam->param[iBuf++] = ' ';
+
+ memcpy(iparam->param + iBuf, pTAG, lenTAG);
+ iBuf += lenTAG;
+
+ if(pMSG[0] != ' ')
+ iparam->param[iBuf++] = ' ';
+ memcpy(iparam->param + iBuf, pMSG, lenMSG);
+ iBuf += lenMSG;
+
+ /* string terminator */
+ iparam->param[iBuf] = '\0';
+
+ iparam->lenStr = lenTotal - 1; /* do not count \0! */
+
+finalize_it:
+ENDstrgen
+
+
+BEGINmodExit
+CODESTARTmodExit
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_SMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(smtradfwd)
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ dbgprintf("rsyslog traditional (network) forward format strgen init called, compiled with "
+ "version %s\n", VERSION);
+ENDmodInit
diff --git a/tools/smtradfwd.h b/tools/smtradfwd.h
new file mode 100644
index 0000000..2bbaee3
--- /dev/null
+++ b/tools/smtradfwd.h
@@ -0,0 +1,30 @@
+/* smtradfwd.h
+ *
+ * File begun on 2010-06-04 by RGerhards
+ *
+ * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SMTRADFWD_H_INCLUDED
+#define SMTRADFWD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitsmtradfwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided,
+rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*);
+
+#endif /* #ifndef SMTRADFWD_H_INCLUDED */
diff --git a/tools/syslogd.c b/tools/syslogd.c
new file mode 100644
index 0000000..1229228
--- /dev/null
+++ b/tools/syslogd.c
@@ -0,0 +1,136 @@
+/**
+ * main rsyslog file with GPLv3 content.
+ *
+ * *********************** NOTE ************************
+ * * Do no longer patch this file. If there is hard *
+ * * need to, talk to Rainer as to how we can make any *
+ * * patch be licensed under ASL 2.0. *
+ * * THIS FILE WILL GO AWAY. The new main file is *
+ * * rsyslogd.c. *
+ * *****************************************************
+ *
+ * Please visit the rsyslog project at
+ * https://www.rsyslog.com
+ * to learn more about it and discuss any questions you may have.
+ *
+ * rsyslog had initially been forked from the sysklogd project.
+ * I would like to express my thanks to the developers of the sysklogd
+ * package - without it, I would have had a much harder start...
+ *
+ * Please note that while rsyslog started from the sysklogd code base,
+ * it nowadays has almost nothing left in common with it. Allmost all
+ * parts of the code have been rewritten.
+ *
+ * This Project was intiated and is maintained by
+ * Rainer Gerhards <rgerhards@hq.adiscon.com>.
+ *
+ * rsyslog - An Enhanced syslogd Replacement.
+ * Copyright 2003-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog 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.
+ *
+ * Rsyslog 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 Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef OS_SOLARIS
+# include <fcntl.h>
+# include <stropts.h>
+# include <sys/termios.h>
+# include <sys/types.h>
+#else
+# include <libgen.h>
+#endif
+
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#include <grp.h>
+
+#ifdef HAVE_SYS_TIMESPEC_H
+# include <sys/timespec.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#include <signal.h>
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "outchannel.h"
+#include "syslogd.h"
+
+#include "msg.h"
+#include "iminternal.h"
+#include "threads.h"
+#include "parser.h"
+#include "unicode-helper.h"
+#include "dnscache.h"
+#include "ratelimit.h"
+
+#ifndef HAVE_SETSID
+/* stems back to sysklogd in whole */
+void untty(void)
+{
+ int i;
+ pid_t pid;
+
+ if(!Debug) {
+ /* Peng Haitao <penght@cn.fujitsu.com> contribution */
+ pid = getpid();
+ if (setpgid(pid, pid) < 0) {
+ perror("setpgid");
+ exit(1);
+ }
+ /* end Peng Haitao <penght@cn.fujitsu.com> contribution */
+
+ i = open(_PATH_TTY, O_RDWR|O_CLOEXEC);
+ if (i >= 0) {
+# if !defined(__hpux)
+ (void) ioctl(i, (int) TIOCNOTTY, NULL);
+# else
+ /* TODO: we need to implement something for HP UX! -- rgerhards, 2008-03-04 */
+ /* actually, HP UX should have setsid, so the code directly above should
+ * trigger. So the actual question is why it doesn't do that...
+ */
+# endif
+ close(i);
+ }
+ }
+}
+#endif
diff --git a/tools/syslogd.h b/tools/syslogd.h
new file mode 100644
index 0000000..9bfe432
--- /dev/null
+++ b/tools/syslogd.h
@@ -0,0 +1,38 @@
+/* common header for syslogd
+ * Copyright 2007-2012 Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SYSLOGD_H_INCLUDED
+#define SYSLOGD_H_INCLUDED 1
+
+#include "syslogd-types.h"
+#include "objomsr.h"
+#include "modules.h"
+#include "template.h"
+#include "action.h"
+#include "linkedlist.h"
+
+/* the following prototypes should go away once we have an input
+ * module interface -- rgerhards, 2007-12-12
+ */
+extern int NoHops;
+extern int send_to_all;
+extern int Debug;
+#include "dirty.h"
+
+#endif /* #ifndef SYSLOGD_H_INCLUDED */
diff --git a/ylwrap b/ylwrap
new file mode 100755
index 0000000..5943168
--- /dev/null
+++ b/ylwrap
@@ -0,0 +1,247 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2018 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 <https://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>.
+
+get_dirname ()
+{
+ case $1 in
+ */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
+ # Otherwise, we want the empty string (not ".").
+ esac
+}
+
+# guard FILE
+# ----------
+# The CPP macro used to guard inclusion of FILE.
+guard ()
+{
+ printf '%s\n' "$1" \
+ | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
+ -e 's/__*/_/g'
+}
+
+# quote_for_sed [STRING]
+# ----------------------
+# Return STRING (or stdin) quoted to be used as a sed pattern.
+quote_for_sed ()
+{
+ case $# in
+ 0) cat;;
+ 1) printf '%s\n' "$1";;
+ esac \
+ | sed -e 's|[][\\.*]|\\&|g'
+}
+
+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
+# We'll later need for a correct munging of "#line" directives.
+input_sub_rx=`get_dirname "$input" | quote_for_sed`
+case $input in
+ [\\/]* | ?:[\\/]*)
+ # Absolute path; do nothing.
+ ;;
+ *)
+ # Relative path. Make it absolute.
+ input=`pwd`/$input
+ ;;
+esac
+input_rx=`get_dirname "$input" | quote_for_sed`
+
+# 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=false
+if test -f y_tab.c || test -f y_tab.h; then
+ y_tab_nodot=true
+fi
+
+# The parser itself, the first file, is the destination of the .y.c
+# rule in the Makefile.
+parser=$1
+
+# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
+# instance, we rename #include "y.tab.h" into #include "parse.h"
+# during the conversion from y.tab.c to parse.c.
+sed_fix_filenames=
+
+# Also rename header guards, as Bison 2.7 for instance uses its header
+# guard in its implementation file.
+sed_fix_header_guards=
+
+while test $# -ne 0; do
+ if test x"$1" = x"--"; then
+ shift
+ break
+ fi
+ from=$1
+ # Handle y_tab.c and y_tab.h output by DOS
+ if $y_tab_nodot; then
+ case $from in
+ "y.tab.c") from=y_tab.c;;
+ "y.tab.h") from=y_tab.h;;
+ esac
+ fi
+ shift
+ to=$1
+ shift
+ sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
+ sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
+done
+
+# The program to run.
+prog=$1
+shift
+# Make any relative path in $prog absolute.
+case $prog in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog=`pwd`/$prog ;;
+esac
+
+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
+ for from in *
+ do
+ to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
+ if test -f "$from"; then
+ # If $2 is an absolute path name, then just use that,
+ # otherwise prepend '../'.
+ case $to in
+ [\\/]* | ?:[\\/]*) target=$to;;
+ *) target=../$to;;
+ esac
+
+ # Do not overwrite unchanged header files to avoid useless
+ # recompilations. Always update the parser itself: 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 $from != $parser; then
+ realtarget=$target
+ target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
+ fi
+
+ # Munge "#line" or "#" directives. Don't let the resulting
+ # debug information point at an absolute srcdir. Use the real
+ # output file name, not yy.lex.c for instance. Adjust the
+ # include guards too.
+ sed -e "/^#/!b" \
+ -e "s|$input_rx|$input_sub_rx|" \
+ -e "$sed_fix_filenames" \
+ -e "$sed_fix_header_guards" \
+ "$from" >"$target" || ret=$?
+
+ # Check whether files must be updated.
+ if test "$from" != "$parser"; then
+ if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+ echo "$to is unchanged"
+ rm -f "$target"
+ else
+ echo "updating $to"
+ mv -f "$target" "$realtarget"
+ fi
+ fi
+ else
+ # A missing file is only an error for the parser. This is a
+ # blatant hack to let us support using "yacc -d". If -d is not
+ # specified, don't fail when the header file is "missing".
+ if test "$from" = "$parser"; then
+ ret=1
+ fi
+ fi
+ done
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End: